diff options
Diffstat (limited to 'lib/Frontend/DiagnosticRenderer.cpp')
-rw-r--r-- | lib/Frontend/DiagnosticRenderer.cpp | 127 |
1 files changed, 36 insertions, 91 deletions
diff --git a/lib/Frontend/DiagnosticRenderer.cpp b/lib/Frontend/DiagnosticRenderer.cpp index 6c3bb1d..f052f90 100644 --- a/lib/Frontend/DiagnosticRenderer.cpp +++ b/lib/Frontend/DiagnosticRenderer.cpp @@ -22,56 +22,6 @@ #include <algorithm> using namespace clang; -/// Look through spelling locations for a macro argument expansion, and -/// if found skip to it so that we can trace the argument rather than the macros -/// in which that argument is used. If no macro argument expansion is found, -/// don't skip anything and return the starting location. -static SourceLocation skipToMacroArgExpansion(const SourceManager &SM, - SourceLocation StartLoc) { - for (SourceLocation L = StartLoc; L.isMacroID(); - L = SM.getImmediateSpellingLoc(L)) { - if (SM.isMacroArgExpansion(L)) - return L; - } - - // Otherwise just return initial location, there's nothing to skip. - return StartLoc; -} - -/// Gets the location of the immediate macro caller, one level up the stack -/// toward the initial macro typed into the source. -static SourceLocation getImmediateMacroCallerLoc(const SourceManager &SM, - SourceLocation Loc) { - if (!Loc.isMacroID()) return Loc; - - // When we have the location of (part of) an expanded parameter, its spelling - // location points to the argument as typed into the macro call, and - // therefore is used to locate the macro caller. - if (SM.isMacroArgExpansion(Loc)) - return SM.getImmediateSpellingLoc(Loc); - - // Otherwise, the caller of the macro is located where this macro is - // expanded (while the spelling is part of the macro definition). - return SM.getImmediateExpansionRange(Loc).first; -} - -/// Gets the location of the immediate macro callee, one level down the stack -/// toward the leaf macro. -static SourceLocation getImmediateMacroCalleeLoc(const SourceManager &SM, - SourceLocation Loc) { - if (!Loc.isMacroID()) return Loc; - - // When we have the location of (part of) an expanded parameter, its - // expansion location points to the unexpanded paramater reference within - // the macro definition (or callee). - if (SM.isMacroArgExpansion(Loc)) - return SM.getImmediateExpansionRange(Loc).first; - - // Otherwise, the callee of the macro is located where this location was - // spelled inside the macro definition. - return SM.getImmediateSpellingLoc(Loc); -} - /// \brief Retrieve the name of the immediate macro expansion. /// /// This routine starts from a source location, and finds the name of the macro @@ -109,24 +59,9 @@ static StringRef getImmediateMacroName(SourceLocation Loc, return ExpansionBuffer.substr(ExpansionInfo.second, MacroTokenLength); } -/// Get the presumed location of a diagnostic message. This computes the -/// presumed location for the top of any macro backtrace when present. -static PresumedLoc getDiagnosticPresumedLoc(const SourceManager &SM, - SourceLocation Loc) { - // This is a condensed form of the algorithm used by emitCaretDiagnostic to - // walk to the top of the macro call stack. - while (Loc.isMacroID()) { - Loc = skipToMacroArgExpansion(SM, Loc); - Loc = getImmediateMacroCallerLoc(SM, Loc); - } - - return SM.getPresumedLoc(Loc); -} - -DiagnosticRenderer::DiagnosticRenderer(const SourceManager &SM, - const LangOptions &LangOpts, +DiagnosticRenderer::DiagnosticRenderer(const LangOptions &LangOpts, const DiagnosticOptions &DiagOpts) -: SM(SM), LangOpts(LangOpts), DiagOpts(DiagOpts), LastLevel() {} +: LangOpts(LangOpts), DiagOpts(DiagOpts), LastLevel() {} DiagnosticRenderer::~DiagnosticRenderer() {} @@ -184,18 +119,23 @@ void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc, StringRef Message, ArrayRef<CharSourceRange> Ranges, ArrayRef<FixItHint> FixItHints, + const SourceManager *SM, DiagOrStoredDiag D) { + assert(SM || Loc.isInvalid()); beginDiagnostic(D, Level); - PresumedLoc PLoc = getDiagnosticPresumedLoc(SM, Loc); + PresumedLoc PLoc; + if (Loc.isValid()) { + PLoc = SM->getPresumedLocForDisplay(Loc); - // First, if this diagnostic is not in the main file, print out the - // "included from" lines. - emitIncludeStack(PLoc.getIncludeLoc(), Level); + // First, if this diagnostic is not in the main file, print out the + // "included from" lines. + emitIncludeStack(PLoc.getIncludeLoc(), Level, *SM); + } // Next, emit the actual diagnostic message. - emitDiagnosticMessage(Loc, PLoc, Level, Message, Ranges, D); + emitDiagnosticMessage(Loc, PLoc, Level, Message, Ranges, SM, D); // Only recurse if we have a valid location. if (Loc.isValid()) { @@ -205,7 +145,7 @@ void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc, llvm::SmallVector<FixItHint, 8> MergedFixits; if (!FixItHints.empty()) { - mergeFixits(FixItHints, SM, LangOpts, MergedFixits); + mergeFixits(FixItHints, *SM, LangOpts, MergedFixits); FixItHints = MergedFixits; } @@ -216,7 +156,7 @@ void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc, MutableRanges.push_back(I->RemoveRange); unsigned MacroDepth = 0; - emitMacroExpansionsAndCarets(Loc, Level, MutableRanges, FixItHints, + emitMacroExpansionsAndCarets(Loc, Level, MutableRanges, FixItHints, *SM, MacroDepth); } @@ -230,6 +170,8 @@ void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc, void DiagnosticRenderer::emitStoredDiagnostic(StoredDiagnostic &Diag) { emitDiagnostic(Diag.getLocation(), Diag.getLevel(), Diag.getMessage(), Diag.getRanges(), Diag.getFixIts(), + Diag.getLocation().isValid() ? &Diag.getLocation().getManager() + : 0, &Diag); } @@ -245,7 +187,8 @@ void DiagnosticRenderer::emitStoredDiagnostic(StoredDiagnostic &Diag) { /// \param Loc The include location of the current file (not the diagnostic /// location). void DiagnosticRenderer::emitIncludeStack(SourceLocation Loc, - DiagnosticsEngine::Level Level) { + DiagnosticsEngine::Level Level, + const SourceManager &SM) { // Skip redundant include stacks altogether. if (LastIncludeLoc == Loc) return; @@ -254,12 +197,13 @@ void DiagnosticRenderer::emitIncludeStack(SourceLocation Loc, if (!DiagOpts.ShowNoteIncludeStack && Level == DiagnosticsEngine::Note) return; - emitIncludeStackRecursively(Loc); + emitIncludeStackRecursively(Loc, SM); } /// \brief Helper to recursivly walk up the include stack and print each layer /// on the way back down. -void DiagnosticRenderer::emitIncludeStackRecursively(SourceLocation Loc) { +void DiagnosticRenderer::emitIncludeStackRecursively(SourceLocation Loc, + const SourceManager &SM) { if (Loc.isInvalid()) return; @@ -268,10 +212,10 @@ void DiagnosticRenderer::emitIncludeStackRecursively(SourceLocation Loc) { return; // Emit the other include frames first. - emitIncludeStackRecursively(PLoc.getIncludeLoc()); + emitIncludeStackRecursively(PLoc.getIncludeLoc(), SM); // Emit the inclusion text/note. - emitIncludeLocation(Loc, PLoc); + emitIncludeLocation(Loc, PLoc, SM); } /// \brief Recursively emit notes for each macro expansion and caret @@ -292,6 +236,7 @@ void DiagnosticRenderer::emitMacroExpansionsAndCarets( DiagnosticsEngine::Level Level, SmallVectorImpl<CharSourceRange>& Ranges, ArrayRef<FixItHint> Hints, + const SourceManager &SM, unsigned &MacroDepth, unsigned OnMacroInst) { @@ -302,26 +247,26 @@ void DiagnosticRenderer::emitMacroExpansionsAndCarets( if (Loc.isFileID()) { assert(MacroDepth == 0 && "We shouldn't hit a leaf node twice!"); MacroDepth = OnMacroInst; - emitCodeContext(Loc, Level, Ranges, Hints); + emitCodeContext(Loc, Level, Ranges, Hints, SM); return; } // Otherwise recurse through each macro expansion layer. // When processing macros, skip over the expansions leading up to // a macro argument, and trace the argument's expansion stack instead. - Loc = skipToMacroArgExpansion(SM, Loc); + Loc = SM.skipToMacroArgExpansion(Loc); - SourceLocation OneLevelUp = getImmediateMacroCallerLoc(SM, Loc); + SourceLocation OneLevelUp = SM.getImmediateMacroCallerLoc(Loc); // FIXME: Map ranges? - emitMacroExpansionsAndCarets(OneLevelUp, Level, Ranges, Hints, MacroDepth, + emitMacroExpansionsAndCarets(OneLevelUp, Level, Ranges, Hints, SM, MacroDepth, OnMacroInst + 1); // Save the original location so we can find the spelling of the macro call. SourceLocation MacroLoc = Loc; // Map the location. - Loc = getImmediateMacroCalleeLoc(SM, Loc); + Loc = SM.getImmediateMacroCalleeLoc(Loc); unsigned MacroSkipStart = 0, MacroSkipEnd = 0; if (MacroDepth > DiagOpts.MacroBacktraceLimit && @@ -341,9 +286,9 @@ void DiagnosticRenderer::emitMacroExpansionsAndCarets( I != E; ++I) { SourceLocation Start = I->getBegin(), End = I->getEnd(); if (Start.isMacroID()) - I->setBegin(getImmediateMacroCalleeLoc(SM, Start)); + I->setBegin(SM.getImmediateMacroCalleeLoc(Start)); if (End.isMacroID()) - I->setEnd(getImmediateMacroCalleeLoc(SM, End)); + I->setEnd(SM.getImmediateMacroCalleeLoc(End)); } if (Suppressed) { @@ -365,22 +310,22 @@ void DiagnosticRenderer::emitMacroExpansionsAndCarets( << getImmediateMacroName(MacroLoc, SM, LangOpts) << "'"; emitDiagnostic(SM.getSpellingLoc(Loc), DiagnosticsEngine::Note, Message.str(), - Ranges, ArrayRef<FixItHint>()); + Ranges, ArrayRef<FixItHint>(), &SM); } DiagnosticNoteRenderer::~DiagnosticNoteRenderer() {} void DiagnosticNoteRenderer::emitIncludeLocation(SourceLocation Loc, - PresumedLoc PLoc) { + PresumedLoc PLoc, + const SourceManager &SM) { // Generate a note indicating the include location. SmallString<200> MessageStorage; llvm::raw_svector_ostream Message(MessageStorage); Message << "in file included from " << PLoc.getFilename() << ':' << PLoc.getLine() << ":"; - emitNote(Loc, Message.str()); + emitNote(Loc, Message.str(), &SM); } void DiagnosticNoteRenderer::emitBasicNote(StringRef Message) { - emitNote(SourceLocation(), Message); + emitNote(SourceLocation(), Message, 0); } - |