Index: include/llvm/Support/SourceMgr.h =================================================================== --- include/llvm/Support/SourceMgr.h +++ include/llvm/Support/SourceMgr.h @@ -138,6 +138,9 @@ /// 0 is returned if the buffer is not found. unsigned FindBufferContainingLoc(SMLoc Loc) const; + /// Find the location for the Hash line in the buffer preceeding Loc + SMLoc FindCppHashLoc(SMLoc Loc, unsigned BufferID) const; + /// Find the line number for the specified location in the specified file. /// This is not a fast method. unsigned FindLineNumber(SMLoc Loc, unsigned BufferID = 0) const { Index: lib/MC/MCParser/AsmParser.cpp =================================================================== --- lib/MC/MCParser/AsmParser.cpp +++ lib/MC/MCParser/AsmParser.cpp @@ -207,6 +207,9 @@ /// \brief Are we parsing ms-style inline assembly? bool ParsingInlineAsm; + /// \brief have we finished parsing the file? + bool FinishedParsing; + public: AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out, const MCAsmInfo &MAI); @@ -576,7 +579,7 @@ : Lexer(MAI), Ctx(Ctx), Out(Out), MAI(MAI), SrcMgr(SM), PlatformParser(nullptr), CurBuffer(SM.getMainFileID()), MacrosEnabledFlag(true), CppHashInfo(), AssemblerDialect(~0U), - IsDarwin(false), ParsingInlineAsm(false) { + IsDarwin(false), ParsingInlineAsm(false), FinishedParsing(false) { HadError = false; // Save the old handler. SavedDiagHandler = SrcMgr.getDiagHandler(); @@ -822,6 +825,9 @@ } } + // Mark this run as finished + FinishedParsing = true; + // Finalize the output stream if there are no errors and if the client wants // us to. if (!HadError && !NoFinalize) @@ -2144,11 +2150,38 @@ const std::string &Filename = Parser->CppHashInfo.Filename; int DiagLocLineNo = DiagSrcMgr.FindLineNumber(DiagLoc, DiagBuf); + + // If we finished parsing CppHashLoc is invalid, so we need to recompute it + // from DiagBuf and DiagLoc. + SMLoc CppHashLoc; + int CppHashLineNumber; + if (Parser->FinishedParsing) { + CppHashLoc = Parser->SrcMgr.FindCppHashLoc(DiagLoc, DiagBuf); + + // From CppHashLoc, find line number (that's the number following the '#' + const char *Ptr = CppHashLoc.getPointer(); + const char *Start = ++Ptr; + for (Ptr = Start; *Start == ' '; Start++, Ptr++); + for (; *Ptr != ' '; Ptr++); + + // Start points to the beginning of the number and Ptr to the end + StringRef LineNoStr(Start, Ptr - Start); + bool failed = LineNoStr.getAsInteger(0, CppHashLineNumber); + assert (!failed); + } + else { + CppHashLoc = Parser->CppHashInfo.Loc; + CppHashLineNumber = Parser->CppHashInfo.LineNumber; + } + int CppHashLocLineNo = - Parser->SrcMgr.FindLineNumber(Parser->CppHashInfo.Loc, CppHashBuf); + Parser->SrcMgr.FindLineNumber(CppHashLoc, CppHashBuf); int LineNo = - Parser->CppHashInfo.LineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo); + CppHashLineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo); + // Better to crash than to be silly and report negative line number + assert (LineNo > 0); + SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), Filename, LineNo, Diag.getColumnNo(), Diag.getKind(), Diag.getMessage(), Diag.getLineContents(), Diag.getRanges()); Index: lib/Support/SourceMgr.cpp =================================================================== --- lib/Support/SourceMgr.cpp +++ lib/Support/SourceMgr.cpp @@ -74,6 +74,27 @@ return 0; } +SMLoc +SourceMgr::FindCppHashLoc(SMLoc Loc, unsigned BufferID) const { + unsigned CppHashBuf = FindBufferContainingLoc(Loc); + + // Initial implementation searches only for the previous '#' character + // after a newline: '\n[ ]*#' + const MemoryBuffer *Buff = getMemoryBuffer(BufferID); + const char *BufStart = Buff->getBufferStart(); + const char *Ptr = BufStart; + + SMLoc CppHashLoc; + + for (; SMLoc::getFromPointer(Ptr) != Loc; ++Ptr) + if (*Ptr == '#') + CppHashLoc = SMLoc::getFromPointer(Ptr); + + assert(CppHashLoc.isValid()); + + return CppHashLoc; +} + std::pair SourceMgr::getLineAndColumn(SMLoc Loc, unsigned BufferID) const { if (!BufferID)