From: Eli Friedman Date: Tue, 23 Oct 2012 02:43:30 +0000 (+0000) Subject: [ms-inline-asm] Add handling for errors coming out of the backend. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5f1385b81b0a6c6878ff1e35118a5b0bf52ca930;p=clang [ms-inline-asm] Add handling for errors coming out of the backend. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@166463 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 1e93f1bc0d..efa974839a 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/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/lib/Sema/SemaStmtAsm.cpp b/lib/Sema/SemaStmtAsm.cpp index 616dcfcd83..f33b87cebc 100644 --- a/lib/Sema/SemaStmtAsm.cpp +++ b/lib/Sema/SemaStmtAsm.cpp @@ -328,6 +328,7 @@ static StringRef getSpelling(Sema &SemaRef, Token AsmTok) { static bool buildMSAsmString(Sema &SemaRef, SourceLocation AsmLoc, ArrayRef AsmToks, + llvm::SmallVectorImpl &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 AsmToks; + ArrayRef TokOffsets; public: - MCAsmParserSemaCallbackImpl(class Sema *Ref) { SemaRef = Ref; } + MCAsmParserSemaCallbackImpl(Sema &Ref, SourceLocation Loc, + ArrayRef Toks, + ArrayRef 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(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 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/test/Sema/ms-inline-asm.c b/test/Sema/ms-inline-asm.c index 4c9dfd0b59..169c27f535 100644 --- a/test/Sema/ms-inline-asm.c +++ b/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}} + } }