diff options
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaStmtAsm.cpp | 51 | ||||
-rw-r--r-- | clang/test/Sema/ms-inline-asm.c | 19 |
3 files changed, 65 insertions, 7 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 1e93f1bc0d0..efa974839ac 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -5143,6 +5143,8 @@ let CategoryName = "Inline Assembly Issue" in { "invalid use of a cast in a inline asm context requiring an l-value: " "accepted due to -fheinous-gnu-extensions, but clang may remove support " "for this in the future">; + + def err_inline_ms_asm_parsing : Error<"%0">; } let CategoryName = "Semantic Issue" in { diff --git a/clang/lib/Sema/SemaStmtAsm.cpp b/clang/lib/Sema/SemaStmtAsm.cpp index 616dcfcd83a..f33b87cebcc 100644 --- a/clang/lib/Sema/SemaStmtAsm.cpp +++ b/clang/lib/Sema/SemaStmtAsm.cpp @@ -328,6 +328,7 @@ static StringRef getSpelling(Sema &SemaRef, Token AsmTok) { static bool buildMSAsmString(Sema &SemaRef, SourceLocation AsmLoc, ArrayRef<Token> AsmToks, + llvm::SmallVectorImpl<unsigned> &TokOffsets, std::string &AsmString) { assert (!AsmToks.empty() && "Didn't expect an empty AsmToks!"); @@ -355,6 +356,7 @@ static bool buildMSAsmString(Sema &SemaRef, StringRef Spelling = getSpelling(SemaRef, AsmToks[i]); Asm += Spelling; + TokOffsets.push_back(Asm.size()); } AsmString = Asm.str(); return false; @@ -363,17 +365,53 @@ static bool buildMSAsmString(Sema &SemaRef, namespace { class MCAsmParserSemaCallbackImpl : public llvm::MCAsmParserSemaCallback { - Sema *SemaRef; + Sema &SemaRef; + SourceLocation AsmLoc; + ArrayRef<Token> AsmToks; + ArrayRef<unsigned> TokOffsets; public: - MCAsmParserSemaCallbackImpl(class Sema *Ref) { SemaRef = Ref; } + MCAsmParserSemaCallbackImpl(Sema &Ref, SourceLocation Loc, + ArrayRef<Token> Toks, + ArrayRef<unsigned> Offsets) + : SemaRef(Ref), AsmLoc(Loc), AsmToks(Toks), TokOffsets(Offsets) { } ~MCAsmParserSemaCallbackImpl() {} void *LookupInlineAsmIdentifier(StringRef Name, void *SrcLoc, unsigned &Size){ SourceLocation Loc = SourceLocation::getFromPtrEncoding(SrcLoc); - NamedDecl *OpDecl = SemaRef->LookupInlineAsmIdentifier(Name, Loc, Size); + NamedDecl *OpDecl = SemaRef.LookupInlineAsmIdentifier(Name, Loc, Size); return static_cast<void *>(OpDecl); } + + static void MSAsmDiagHandlerCallback(const llvm::SMDiagnostic &D, + void *Context) { + ((MCAsmParserSemaCallbackImpl*)Context)->MSAsmDiagHandler(D); + } + void MSAsmDiagHandler(const llvm::SMDiagnostic &D) { + // Compute an offset into the inline asm buffer. + // FIXME: This isn't right if .macro is involved (but hopefully, no + // real-world code does that). + const llvm::SourceMgr &LSM = *D.getSourceMgr(); + const llvm::MemoryBuffer *LBuf = + LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc())); + unsigned Offset = D.getLoc().getPointer() - LBuf->getBufferStart(); + + // Figure out which token that offset points into. + const unsigned *OffsetPtr = + std::lower_bound(TokOffsets.begin(), TokOffsets.end(), Offset); + unsigned TokIndex = OffsetPtr - TokOffsets.begin(); + + // If we come up with an answer which seems sane, use it; otherwise, + // just point at the __asm keyword. + // FIXME: Assert the answer is sane once we handle .macro correctly. + SourceLocation Loc = AsmLoc; + if (TokIndex < AsmToks.size()) { + const Token *Tok = &AsmToks[TokIndex]; + Loc = Tok->getLocation(); + Loc = Loc.getLocWithOffset(Offset - (*OffsetPtr - Tok->getLength())); + } + SemaRef.Diag(Loc, diag::err_inline_ms_asm_parsing) << D.getMessage(); + } }; } @@ -427,7 +465,8 @@ StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc, } std::string AsmString; - if (buildMSAsmString(*this, AsmLoc, AsmToks, AsmString)) + llvm::SmallVector<unsigned, 8> TokOffsets; + if (buildMSAsmString(*this, AsmLoc, AsmToks, TokOffsets, AsmString)) return StmtError(); // Get the target specific parser. @@ -466,8 +505,10 @@ StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc, Parser->setParsingInlineAsm(true); TargetParser->setParsingInlineAsm(true); - MCAsmParserSemaCallbackImpl MCAPSI(this); + MCAsmParserSemaCallbackImpl MCAPSI(*this, AsmLoc, AsmToks, TokOffsets); TargetParser->setSemaCallback(&MCAPSI); + SrcMgr.setDiagHandler(MCAsmParserSemaCallbackImpl::MSAsmDiagHandlerCallback, + &MCAPSI); unsigned NumOutputs; unsigned NumInputs; diff --git a/clang/test/Sema/ms-inline-asm.c b/clang/test/Sema/ms-inline-asm.c index 4c9dfd0b599..169c27f535d 100644 --- a/clang/test/Sema/ms-inline-asm.c +++ b/clang/test/Sema/ms-inline-asm.c @@ -1,5 +1,20 @@ -// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -fms-extensions -fenable-experimental-ms-inline-asm -verify -fsyntax-only +// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -fms-extensions -fenable-experimental-ms-inline-asm -Wno-microsoft -verify -fsyntax-only void t1(void) { - __asm __asm // expected-warning {{MS-style inline assembly is not supported}} expected-error {{__asm used with no assembly instructions}} + __asm __asm // expected-error {{__asm used with no assembly instructions}} +} + +void f() { + __asm { + mov eax, eax + .unknowndirective // expected-error {{unknown directive}} + } + f(); + __asm { + mov eax, 1+=2 // expected-error 2 {{unknown token in expression}} + } + f(); + __asm { + mov eax, 1+++ // expected-error 2 {{unknown token in expression}} + } } |