DiagnosticRenderer.cpp revision 8be51eab5ad34515d2a40dcdc8558128ca1800ad
12898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek//===--- DiagnosticRenderer.cpp - Diagnostic Pretty-Printing --------------===// 22898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek// 32898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek// The LLVM Compiler Infrastructure 42898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek// 52898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek// This file is distributed under the University of Illinois Open Source 62898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek// License. See LICENSE.TXT for details. 72898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek// 82898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek//===----------------------------------------------------------------------===// 92898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 102898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek#include "clang/Frontend/DiagnosticRenderer.h" 112898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek#include "clang/Basic/FileManager.h" 122898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek#include "clang/Basic/SourceManager.h" 132898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek#include "clang/Frontend/DiagnosticOptions.h" 142898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek#include "clang/Lex/Lexer.h" 152898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek#include "llvm/Support/MemoryBuffer.h" 162898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek#include "llvm/Support/raw_ostream.h" 172898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek#include "llvm/Support/ErrorHandling.h" 182898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek#include "llvm/ADT/SmallString.h" 192898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek#include <algorithm> 202898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenekusing namespace clang; 212898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 222898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// Look through spelling locations for a macro argument expansion, and 232898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// if found skip to it so that we can trace the argument rather than the macros 242898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// in which that argument is used. If no macro argument expansion is found, 252898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// don't skip anything and return the starting location. 262898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenekstatic SourceLocation skipToMacroArgExpansion(const SourceManager &SM, 272898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek SourceLocation StartLoc) { 282898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek for (SourceLocation L = StartLoc; L.isMacroID(); 292898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek L = SM.getImmediateSpellingLoc(L)) { 302898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek if (SM.isMacroArgExpansion(L)) 312898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek return L; 322898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek } 332898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 342898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Otherwise just return initial location, there's nothing to skip. 352898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek return StartLoc; 362898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek} 372898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 382898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// Gets the location of the immediate macro caller, one level up the stack 392898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// toward the initial macro typed into the source. 402898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenekstatic SourceLocation getImmediateMacroCallerLoc(const SourceManager &SM, 412898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek SourceLocation Loc) { 422898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek if (!Loc.isMacroID()) return Loc; 432898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 442898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // When we have the location of (part of) an expanded parameter, its spelling 452898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // location points to the argument as typed into the macro call, and 462898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // therefore is used to locate the macro caller. 472898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek if (SM.isMacroArgExpansion(Loc)) 482898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek return SM.getImmediateSpellingLoc(Loc); 492898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 502898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Otherwise, the caller of the macro is located where this macro is 512898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // expanded (while the spelling is part of the macro definition). 522898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek return SM.getImmediateExpansionRange(Loc).first; 532898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek} 542898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 552898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// Gets the location of the immediate macro callee, one level down the stack 562898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// toward the leaf macro. 572898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenekstatic SourceLocation getImmediateMacroCalleeLoc(const SourceManager &SM, 582898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek SourceLocation Loc) { 592898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek if (!Loc.isMacroID()) return Loc; 602898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 612898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // When we have the location of (part of) an expanded parameter, its 622898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // expansion location points to the unexpanded paramater reference within 632898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // the macro definition (or callee). 642898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek if (SM.isMacroArgExpansion(Loc)) 652898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek return SM.getImmediateExpansionRange(Loc).first; 662898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 672898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Otherwise, the callee of the macro is located where this location was 682898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // spelled inside the macro definition. 692898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek return SM.getImmediateSpellingLoc(Loc); 702898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek} 712898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 727f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// \brief Retrieve the name of the immediate macro expansion. 737f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// 747f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// This routine starts from a source location, and finds the name of the macro 757f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// responsible for its immediate expansion. It looks through any intervening 767f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// macro argument expansions to compute this. It returns a StringRef which 777f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// refers to the SourceManager-owned buffer of the source where that macro 787f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// name is spelled. Thus, the result shouldn't out-live that SourceManager. 797f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// 807f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// This differs from Lexer::getImmediateMacroName in that any macro argument 817f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// location will result in the topmost function macro that accepted it. 827f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// e.g. 837f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// \code 847f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// MAC1( MAC2(foo) ) 857f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// \endcode 867f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// for location of 'foo' token, this function will return "MAC1" while 877f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// Lexer::getImmediateMacroName will return "MAC2". 887f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidisstatic StringRef getImmediateMacroName(SourceLocation Loc, 897f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis const SourceManager &SM, 907f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis const LangOptions &LangOpts) { 917f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis assert(Loc.isMacroID() && "Only reasonble to call this on macros"); 927f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis // Walk past macro argument expanions. 937f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis while (SM.isMacroArgExpansion(Loc)) 947f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis Loc = SM.getImmediateExpansionRange(Loc).first; 957f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis 967f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis // Find the spelling location of the start of the non-argument expansion 977f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis // range. This is where the macro name was spelled in order to begin 987f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis // expanding this macro. 997f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis Loc = SM.getSpellingLoc(SM.getImmediateExpansionRange(Loc).first); 1007f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis 1017f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis // Dig out the buffer where the macro name was spelled and the extents of the 1027f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis // name so that we can render it into the expansion note. 1037f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis std::pair<FileID, unsigned> ExpansionInfo = SM.getDecomposedLoc(Loc); 1047f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis unsigned MacroTokenLength = Lexer::MeasureTokenLength(Loc, SM, LangOpts); 1057f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis StringRef ExpansionBuffer = SM.getBufferData(ExpansionInfo.first); 1067f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis return ExpansionBuffer.substr(ExpansionInfo.second, MacroTokenLength); 1077f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis} 1087f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis 1092898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// Get the presumed location of a diagnostic message. This computes the 1102898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// presumed location for the top of any macro backtrace when present. 1112898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenekstatic PresumedLoc getDiagnosticPresumedLoc(const SourceManager &SM, 1122898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek SourceLocation Loc) { 1132898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // This is a condensed form of the algorithm used by emitCaretDiagnostic to 1142898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // walk to the top of the macro call stack. 1152898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek while (Loc.isMacroID()) { 1162898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek Loc = skipToMacroArgExpansion(SM, Loc); 1172898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek Loc = getImmediateMacroCallerLoc(SM, Loc); 1182898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek } 1192898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 1202898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek return SM.getPresumedLoc(Loc); 1212898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek} 1222898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 1232898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted KremenekDiagnosticRenderer::DiagnosticRenderer(const SourceManager &SM, 1242898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek const LangOptions &LangOpts, 1252898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek const DiagnosticOptions &DiagOpts) 1262898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek: SM(SM), LangOpts(LangOpts), DiagOpts(DiagOpts), LastLevel() {} 1272898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 1282898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted KremenekDiagnosticRenderer::~DiagnosticRenderer() {} 1292898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 1302898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 1312898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenekvoid DiagnosticRenderer::emitDiagnostic(SourceLocation Loc, 1322898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek DiagnosticsEngine::Level Level, 1332898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek StringRef Message, 1342898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek ArrayRef<CharSourceRange> Ranges, 1352898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek ArrayRef<FixItHint> FixItHints, 1368be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek DiagOrStoredDiag D) { 1372898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 1388be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek beginDiagnostic(D, Level); 1392898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 1402898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek PresumedLoc PLoc = getDiagnosticPresumedLoc(SM, Loc); 1412898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 1422898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // First, if this diagnostic is not in the main file, print out the 1432898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // "included from" lines. 1442898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek emitIncludeStack(PLoc.getIncludeLoc(), Level); 1452898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 1462898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Next, emit the actual diagnostic message. 1478be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek emitDiagnosticMessage(Loc, PLoc, Level, Message, Ranges, D); 1482898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 1492898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Only recurse if we have a valid location. 1502898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek if (Loc.isValid()) { 1512898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Get the ranges into a local array we can hack on. 1522898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek SmallVector<CharSourceRange, 20> MutableRanges(Ranges.begin(), 1532898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek Ranges.end()); 1542898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 1552898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek for (ArrayRef<FixItHint>::const_iterator I = FixItHints.begin(), 1562898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek E = FixItHints.end(); 1572898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek I != E; ++I) 1582898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek if (I->RemoveRange.isValid()) 1592898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek MutableRanges.push_back(I->RemoveRange); 1602898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 1612898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek unsigned MacroDepth = 0; 1622898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek emitMacroExpansionsAndCarets(Loc, Level, MutableRanges, FixItHints, 1632898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek MacroDepth); 1642898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek } 1652898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 1662898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek LastLoc = Loc; 1672898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek LastLevel = Level; 1682898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 1698be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek endDiagnostic(D, Level); 1708be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek} 1718be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek 1728be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek 1738be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenekvoid DiagnosticRenderer::emitStoredDiagnostic(StoredDiagnostic &Diag) { 1748be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek emitDiagnostic(Diag.getLocation(), Diag.getLevel(), Diag.getMessage(), 1758be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek Diag.getRanges(), Diag.getFixIts(), 1768be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek &Diag); 1772898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek} 1782898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 1792898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \brief Prints an include stack when appropriate for a particular 1802898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// diagnostic level and location. 1812898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// 1822898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// This routine handles all the logic of suppressing particular include 1832898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// stacks (such as those for notes) and duplicate include stacks when 1842898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// repeated warnings occur within the same file. It also handles the logic 1852898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// of customizing the formatting and display of the include stack. 1862898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// 1872898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \param Level The diagnostic level of the message this stack pertains to. 1882898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \param Loc The include location of the current file (not the diagnostic 1892898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// location). 1902898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenekvoid DiagnosticRenderer::emitIncludeStack(SourceLocation Loc, 1912898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek DiagnosticsEngine::Level Level) { 1922898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Skip redundant include stacks altogether. 1932898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek if (LastIncludeLoc == Loc) 1942898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek return; 1952898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek LastIncludeLoc = Loc; 1962898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 1972898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek if (!DiagOpts.ShowNoteIncludeStack && Level == DiagnosticsEngine::Note) 1982898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek return; 1992898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 2002898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek emitIncludeStackRecursively(Loc); 2012898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek} 2022898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 2032898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \brief Helper to recursivly walk up the include stack and print each layer 2042898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// on the way back down. 2052898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenekvoid DiagnosticRenderer::emitIncludeStackRecursively(SourceLocation Loc) { 2062898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek if (Loc.isInvalid()) 2072898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek return; 2082898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 2092898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek PresumedLoc PLoc = SM.getPresumedLoc(Loc); 2102898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek if (PLoc.isInvalid()) 2112898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek return; 2122898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 2132898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Emit the other include frames first. 2142898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek emitIncludeStackRecursively(PLoc.getIncludeLoc()); 2152898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 2162898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Emit the inclusion text/note. 2172898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek emitIncludeLocation(Loc, PLoc); 2182898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek} 2192898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 2202898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \brief Recursively emit notes for each macro expansion and caret 2212898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// diagnostics where appropriate. 2222898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// 2232898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// Walks up the macro expansion stack printing expansion notes, the code 2242898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// snippet, caret, underlines and FixItHint display as appropriate at each 2252898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// level. 2262898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// 2272898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \param Loc The location for this caret. 2282898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \param Level The diagnostic level currently being emitted. 2292898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \param Ranges The underlined ranges for this code snippet. 2302898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \param Hints The FixIt hints active for this diagnostic. 2312898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \param MacroSkipEnd The depth to stop skipping macro expansions. 2322898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \param OnMacroInst The current depth of the macro expansion stack. 2332898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenekvoid DiagnosticRenderer::emitMacroExpansionsAndCarets( 2342898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek SourceLocation Loc, 2352898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek DiagnosticsEngine::Level Level, 2362898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek SmallVectorImpl<CharSourceRange>& Ranges, 2372898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek ArrayRef<FixItHint> Hints, 2382898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek unsigned &MacroDepth, 2392898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek unsigned OnMacroInst) 2402898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek{ 2412898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek assert(!Loc.isInvalid() && "must have a valid source location here"); 2422898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 2432898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // If this is a file source location, directly emit the source snippet and 2442898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // caret line. Also record the macro depth reached. 2452898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek if (Loc.isFileID()) { 2462898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek assert(MacroDepth == 0 && "We shouldn't hit a leaf node twice!"); 2472898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek MacroDepth = OnMacroInst; 2482898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek emitCodeContext(Loc, Level, Ranges, Hints); 2492898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek return; 2502898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek } 2512898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Otherwise recurse through each macro expansion layer. 2522898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 2532898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // When processing macros, skip over the expansions leading up to 2542898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // a macro argument, and trace the argument's expansion stack instead. 2552898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek Loc = skipToMacroArgExpansion(SM, Loc); 2562898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 2572898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek SourceLocation OneLevelUp = getImmediateMacroCallerLoc(SM, Loc); 2582898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 2592898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // FIXME: Map ranges? 2602898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek emitMacroExpansionsAndCarets(OneLevelUp, Level, Ranges, Hints, MacroDepth, 2612898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek OnMacroInst + 1); 2622898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 2632898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Save the original location so we can find the spelling of the macro call. 2642898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek SourceLocation MacroLoc = Loc; 2652898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 2662898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Map the location. 2672898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek Loc = getImmediateMacroCalleeLoc(SM, Loc); 2682898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 2692898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek unsigned MacroSkipStart = 0, MacroSkipEnd = 0; 270cf2362b76b624b90e2649497ab8019bcce959bf4Ted Kremenek if (MacroDepth > DiagOpts.MacroBacktraceLimit && 271cf2362b76b624b90e2649497ab8019bcce959bf4Ted Kremenek DiagOpts.MacroBacktraceLimit != 0) { 2722898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek MacroSkipStart = DiagOpts.MacroBacktraceLimit / 2 + 2732898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek DiagOpts.MacroBacktraceLimit % 2; 2742898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek MacroSkipEnd = MacroDepth - DiagOpts.MacroBacktraceLimit / 2; 2752898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek } 2762898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 2772898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Whether to suppress printing this macro expansion. 2782898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek bool Suppressed = (OnMacroInst >= MacroSkipStart && 2792898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek OnMacroInst < MacroSkipEnd); 2802898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 2812898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Map the ranges. 2822898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek for (SmallVectorImpl<CharSourceRange>::iterator I = Ranges.begin(), 2832898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek E = Ranges.end(); 2842898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek I != E; ++I) { 2852898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek SourceLocation Start = I->getBegin(), End = I->getEnd(); 2862898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek if (Start.isMacroID()) 2872898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek I->setBegin(getImmediateMacroCalleeLoc(SM, Start)); 2882898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek if (End.isMacroID()) 2892898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek I->setEnd(getImmediateMacroCalleeLoc(SM, End)); 2902898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek } 2912898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 2922898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek if (Suppressed) { 2932898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Tell the user that we've skipped contexts. 2942898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek if (OnMacroInst == MacroSkipStart) { 295f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<200> MessageStorage; 2962898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek llvm::raw_svector_ostream Message(MessageStorage); 2972898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek Message << "(skipping " << (MacroSkipEnd - MacroSkipStart) 2982898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek << " expansions in backtrace; use -fmacro-backtrace-limit=0 to " 2992898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek "see all)"; 3002898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek emitBasicNote(Message.str()); 3012898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek } 3022898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek return; 3032898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek } 3042898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 305f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<100> MessageStorage; 3062898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek llvm::raw_svector_ostream Message(MessageStorage); 3072898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek Message << "expanded from macro '" 3087f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis << getImmediateMacroName(MacroLoc, SM, LangOpts) << "'"; 3092898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek emitDiagnostic(SM.getSpellingLoc(Loc), DiagnosticsEngine::Note, 3102898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek Message.str(), 3112898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek Ranges, ArrayRef<FixItHint>()); 3122898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek} 3132898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 3148be51eab5ad34515d2a40dcdc8558128ca1800adTed KremenekDiagnosticNoteRenderer::~DiagnosticNoteRenderer() {} 3158be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek 3168be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenekvoid DiagnosticNoteRenderer::emitIncludeLocation(SourceLocation Loc, 3178be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek PresumedLoc PLoc) { 3188be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek // Generate a note indicating the include location. 3198be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek SmallString<200> MessageStorage; 3208be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek llvm::raw_svector_ostream Message(MessageStorage); 3218be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek Message << "in file included from " << PLoc.getFilename() << ':' 3228be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek << PLoc.getLine() << ":"; 3238be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek emitNote(Loc, Message.str()); 3248be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek} 3258be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek 3268be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenekvoid DiagnosticNoteRenderer::emitBasicNote(StringRef Message) { 3278be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek emitNote(SourceLocation(), Message); 3288be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek} 3298be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek 330