DiagnosticRenderer.cpp revision 02c23ebf41ae2f70da0ba7337e05c51fbfe35f7f
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" 1102c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor#include "clang/Basic/DiagnosticOptions.h" 122898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek#include "clang/Basic/FileManager.h" 132898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek#include "clang/Basic/SourceManager.h" 142898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek#include "clang/Lex/Lexer.h" 1530660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/Edit/EditedSource.h" 1630660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/Edit/Commit.h" 1730660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/Edit/EditsReceiver.h" 182898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek#include "llvm/Support/MemoryBuffer.h" 192898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek#include "llvm/Support/raw_ostream.h" 202898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek#include "llvm/Support/ErrorHandling.h" 212898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek#include "llvm/ADT/SmallString.h" 222898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek#include <algorithm> 232898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenekusing namespace clang; 242898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 257f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// \brief Retrieve the name of the immediate macro expansion. 267f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// 277f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// This routine starts from a source location, and finds the name of the macro 287f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// responsible for its immediate expansion. It looks through any intervening 297f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// macro argument expansions to compute this. It returns a StringRef which 307f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// refers to the SourceManager-owned buffer of the source where that macro 317f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// name is spelled. Thus, the result shouldn't out-live that SourceManager. 327f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// 337f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// This differs from Lexer::getImmediateMacroName in that any macro argument 347f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// location will result in the topmost function macro that accepted it. 357f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// e.g. 367f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// \code 377f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// MAC1( MAC2(foo) ) 387f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// \endcode 397f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// for location of 'foo' token, this function will return "MAC1" while 407f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// Lexer::getImmediateMacroName will return "MAC2". 417f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidisstatic StringRef getImmediateMacroName(SourceLocation Loc, 427f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis const SourceManager &SM, 437f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis const LangOptions &LangOpts) { 447f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis assert(Loc.isMacroID() && "Only reasonble to call this on macros"); 457f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis // Walk past macro argument expanions. 467f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis while (SM.isMacroArgExpansion(Loc)) 477f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis Loc = SM.getImmediateExpansionRange(Loc).first; 487f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis 497f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis // Find the spelling location of the start of the non-argument expansion 507f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis // range. This is where the macro name was spelled in order to begin 517f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis // expanding this macro. 527f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis Loc = SM.getSpellingLoc(SM.getImmediateExpansionRange(Loc).first); 537f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis 547f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis // Dig out the buffer where the macro name was spelled and the extents of the 557f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis // name so that we can render it into the expansion note. 567f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis std::pair<FileID, unsigned> ExpansionInfo = SM.getDecomposedLoc(Loc); 577f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis unsigned MacroTokenLength = Lexer::MeasureTokenLength(Loc, SM, LangOpts); 587f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis StringRef ExpansionBuffer = SM.getBufferData(ExpansionInfo.first); 597f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis return ExpansionBuffer.substr(ExpansionInfo.second, MacroTokenLength); 607f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis} 617f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis 6216afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios KyrtzidisDiagnosticRenderer::DiagnosticRenderer(const LangOptions &LangOpts, 6302c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor DiagnosticOptions *DiagOpts) 6402c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor : LangOpts(LangOpts), DiagOpts(DiagOpts), LastLevel() {} 652898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 662898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted KremenekDiagnosticRenderer::~DiagnosticRenderer() {} 672898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 6830660a898545416f0fea2d717f16f75640001e38Ted Kremeneknamespace { 6930660a898545416f0fea2d717f16f75640001e38Ted Kremenek 7030660a898545416f0fea2d717f16f75640001e38Ted Kremenekclass FixitReceiver : public edit::EditsReceiver { 7130660a898545416f0fea2d717f16f75640001e38Ted Kremenek SmallVectorImpl<FixItHint> &MergedFixits; 7230660a898545416f0fea2d717f16f75640001e38Ted Kremenek 7330660a898545416f0fea2d717f16f75640001e38Ted Kremenekpublic: 7430660a898545416f0fea2d717f16f75640001e38Ted Kremenek FixitReceiver(SmallVectorImpl<FixItHint> &MergedFixits) 7530660a898545416f0fea2d717f16f75640001e38Ted Kremenek : MergedFixits(MergedFixits) { } 7630660a898545416f0fea2d717f16f75640001e38Ted Kremenek virtual void insert(SourceLocation loc, StringRef text) { 7730660a898545416f0fea2d717f16f75640001e38Ted Kremenek MergedFixits.push_back(FixItHint::CreateInsertion(loc, text)); 7830660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 7930660a898545416f0fea2d717f16f75640001e38Ted Kremenek virtual void replace(CharSourceRange range, StringRef text) { 8030660a898545416f0fea2d717f16f75640001e38Ted Kremenek MergedFixits.push_back(FixItHint::CreateReplacement(range, text)); 8130660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 8230660a898545416f0fea2d717f16f75640001e38Ted Kremenek}; 8330660a898545416f0fea2d717f16f75640001e38Ted Kremenek 8430660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 8530660a898545416f0fea2d717f16f75640001e38Ted Kremenek 8630660a898545416f0fea2d717f16f75640001e38Ted Kremenekstatic void mergeFixits(ArrayRef<FixItHint> FixItHints, 8730660a898545416f0fea2d717f16f75640001e38Ted Kremenek const SourceManager &SM, const LangOptions &LangOpts, 8830660a898545416f0fea2d717f16f75640001e38Ted Kremenek SmallVectorImpl<FixItHint> &MergedFixits) { 8930660a898545416f0fea2d717f16f75640001e38Ted Kremenek edit::Commit commit(SM, LangOpts); 9030660a898545416f0fea2d717f16f75640001e38Ted Kremenek for (ArrayRef<FixItHint>::const_iterator 9130660a898545416f0fea2d717f16f75640001e38Ted Kremenek I = FixItHints.begin(), E = FixItHints.end(); I != E; ++I) { 9230660a898545416f0fea2d717f16f75640001e38Ted Kremenek const FixItHint &Hint = *I; 9330660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (Hint.CodeToInsert.empty()) { 9430660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (Hint.InsertFromRange.isValid()) 9530660a898545416f0fea2d717f16f75640001e38Ted Kremenek commit.insertFromRange(Hint.RemoveRange.getBegin(), 9630660a898545416f0fea2d717f16f75640001e38Ted Kremenek Hint.InsertFromRange, /*afterToken=*/false, 9730660a898545416f0fea2d717f16f75640001e38Ted Kremenek Hint.BeforePreviousInsertions); 9830660a898545416f0fea2d717f16f75640001e38Ted Kremenek else 9930660a898545416f0fea2d717f16f75640001e38Ted Kremenek commit.remove(Hint.RemoveRange); 10030660a898545416f0fea2d717f16f75640001e38Ted Kremenek } else { 10130660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (Hint.RemoveRange.isTokenRange() || 10230660a898545416f0fea2d717f16f75640001e38Ted Kremenek Hint.RemoveRange.getBegin() != Hint.RemoveRange.getEnd()) 10330660a898545416f0fea2d717f16f75640001e38Ted Kremenek commit.replace(Hint.RemoveRange, Hint.CodeToInsert); 10430660a898545416f0fea2d717f16f75640001e38Ted Kremenek else 10530660a898545416f0fea2d717f16f75640001e38Ted Kremenek commit.insert(Hint.RemoveRange.getBegin(), Hint.CodeToInsert, 10630660a898545416f0fea2d717f16f75640001e38Ted Kremenek /*afterToken=*/false, Hint.BeforePreviousInsertions); 10730660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 10830660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 10930660a898545416f0fea2d717f16f75640001e38Ted Kremenek 11030660a898545416f0fea2d717f16f75640001e38Ted Kremenek edit::EditedSource Editor(SM, LangOpts); 11130660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (Editor.commit(commit)) { 11230660a898545416f0fea2d717f16f75640001e38Ted Kremenek FixitReceiver Rec(MergedFixits); 11330660a898545416f0fea2d717f16f75640001e38Ted Kremenek Editor.applyRewrites(Rec); 11430660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 11530660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 1162898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 1172898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenekvoid DiagnosticRenderer::emitDiagnostic(SourceLocation Loc, 1182898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek DiagnosticsEngine::Level Level, 1192898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek StringRef Message, 1202898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek ArrayRef<CharSourceRange> Ranges, 1212898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek ArrayRef<FixItHint> FixItHints, 12216afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis const SourceManager *SM, 1238be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek DiagOrStoredDiag D) { 12416afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis assert(SM || Loc.isInvalid()); 1252898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 1268be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek beginDiagnostic(D, Level); 1272898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 12816afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis PresumedLoc PLoc; 12916afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis if (Loc.isValid()) { 13029271fbcef645117df05d5b60e593acb6562422cMatt Beaumont-Gay PLoc = SM->getPresumedLocForDisplay(Loc); 1312898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 13216afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis // First, if this diagnostic is not in the main file, print out the 13316afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis // "included from" lines. 13416afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis emitIncludeStack(PLoc.getIncludeLoc(), Level, *SM); 13516afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis } 1362898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 1372898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Next, emit the actual diagnostic message. 13816afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis emitDiagnosticMessage(Loc, PLoc, Level, Message, Ranges, SM, D); 1392898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 1402898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Only recurse if we have a valid location. 1412898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek if (Loc.isValid()) { 1422898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Get the ranges into a local array we can hack on. 1432898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek SmallVector<CharSourceRange, 20> MutableRanges(Ranges.begin(), 1442898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek Ranges.end()); 1452898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 14630660a898545416f0fea2d717f16f75640001e38Ted Kremenek llvm::SmallVector<FixItHint, 8> MergedFixits; 14730660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (!FixItHints.empty()) { 14816afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis mergeFixits(FixItHints, *SM, LangOpts, MergedFixits); 14930660a898545416f0fea2d717f16f75640001e38Ted Kremenek FixItHints = MergedFixits; 15030660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 15130660a898545416f0fea2d717f16f75640001e38Ted Kremenek 1522898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek for (ArrayRef<FixItHint>::const_iterator I = FixItHints.begin(), 1532898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek E = FixItHints.end(); 1542898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek I != E; ++I) 1552898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek if (I->RemoveRange.isValid()) 1562898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek MutableRanges.push_back(I->RemoveRange); 1572898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 1582898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek unsigned MacroDepth = 0; 15916afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis emitMacroExpansionsAndCarets(Loc, Level, MutableRanges, FixItHints, *SM, 1602898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek MacroDepth); 1612898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek } 1622898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 1632898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek LastLoc = Loc; 1642898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek LastLevel = Level; 1652898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 1668be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek endDiagnostic(D, Level); 1678be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek} 1688be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek 1698be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek 1708be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenekvoid DiagnosticRenderer::emitStoredDiagnostic(StoredDiagnostic &Diag) { 1718be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek emitDiagnostic(Diag.getLocation(), Diag.getLevel(), Diag.getMessage(), 1728be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek Diag.getRanges(), Diag.getFixIts(), 17316afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis Diag.getLocation().isValid() ? &Diag.getLocation().getManager() 17416afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis : 0, 1758be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek &Diag); 1762898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek} 1772898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 1782898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \brief Prints an include stack when appropriate for a particular 1792898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// diagnostic level and location. 1802898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// 1812898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// This routine handles all the logic of suppressing particular include 1822898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// stacks (such as those for notes) and duplicate include stacks when 1832898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// repeated warnings occur within the same file. It also handles the logic 1842898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// of customizing the formatting and display of the include stack. 1852898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// 1862898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \param Level The diagnostic level of the message this stack pertains to. 1872898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \param Loc The include location of the current file (not the diagnostic 1882898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// location). 1892898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenekvoid DiagnosticRenderer::emitIncludeStack(SourceLocation Loc, 19016afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis DiagnosticsEngine::Level Level, 19116afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis const SourceManager &SM) { 1922898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Skip redundant include stacks altogether. 1932898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek if (LastIncludeLoc == Loc) 1942898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek return; 1952898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek LastIncludeLoc = Loc; 1962898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 19702c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor if (!DiagOpts->ShowNoteIncludeStack && Level == DiagnosticsEngine::Note) 1982898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek return; 1992898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 20016afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis emitIncludeStackRecursively(Loc, SM); 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. 20516afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidisvoid DiagnosticRenderer::emitIncludeStackRecursively(SourceLocation Loc, 20616afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis const SourceManager &SM) { 2072898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek if (Loc.isInvalid()) 2082898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek return; 2092898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 2102898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek PresumedLoc PLoc = SM.getPresumedLoc(Loc); 2112898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek if (PLoc.isInvalid()) 2122898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek return; 2132898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 2142898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Emit the other include frames first. 21516afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis emitIncludeStackRecursively(PLoc.getIncludeLoc(), SM); 2162898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 2172898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Emit the inclusion text/note. 21816afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis emitIncludeLocation(Loc, PLoc, SM); 2192898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek} 2202898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 2212898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \brief Recursively emit notes for each macro expansion and caret 2222898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// diagnostics where appropriate. 2232898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// 2242898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// Walks up the macro expansion stack printing expansion notes, the code 2252898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// snippet, caret, underlines and FixItHint display as appropriate at each 2262898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// level. 2272898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// 2282898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \param Loc The location for this caret. 2292898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \param Level The diagnostic level currently being emitted. 2302898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \param Ranges The underlined ranges for this code snippet. 2312898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \param Hints The FixIt hints active for this diagnostic. 2322898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \param MacroSkipEnd The depth to stop skipping macro expansions. 2332898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \param OnMacroInst The current depth of the macro expansion stack. 2342898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenekvoid DiagnosticRenderer::emitMacroExpansionsAndCarets( 2352898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek SourceLocation Loc, 2362898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek DiagnosticsEngine::Level Level, 2372898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek SmallVectorImpl<CharSourceRange>& Ranges, 2382898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek ArrayRef<FixItHint> Hints, 23916afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis const SourceManager &SM, 2402898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek unsigned &MacroDepth, 2412898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek unsigned OnMacroInst) 2422898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek{ 2432898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek assert(!Loc.isInvalid() && "must have a valid source location here"); 2442898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 2452898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // If this is a file source location, directly emit the source snippet and 2462898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // caret line. Also record the macro depth reached. 2472898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek if (Loc.isFileID()) { 2482898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek assert(MacroDepth == 0 && "We shouldn't hit a leaf node twice!"); 2492898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek MacroDepth = OnMacroInst; 25016afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis emitCodeContext(Loc, Level, Ranges, Hints, SM); 2512898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek return; 2522898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek } 2532898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Otherwise recurse through each macro expansion layer. 2542898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 2552898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // When processing macros, skip over the expansions leading up to 2562898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // a macro argument, and trace the argument's expansion stack instead. 25729271fbcef645117df05d5b60e593acb6562422cMatt Beaumont-Gay Loc = SM.skipToMacroArgExpansion(Loc); 2582898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 25929271fbcef645117df05d5b60e593acb6562422cMatt Beaumont-Gay SourceLocation OneLevelUp = SM.getImmediateMacroCallerLoc(Loc); 2602898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 2612898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // FIXME: Map ranges? 26216afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis emitMacroExpansionsAndCarets(OneLevelUp, Level, Ranges, Hints, SM, MacroDepth, 2632898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek OnMacroInst + 1); 2642898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 2652898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Save the original location so we can find the spelling of the macro call. 2662898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek SourceLocation MacroLoc = Loc; 2672898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 2682898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Map the location. 26929271fbcef645117df05d5b60e593acb6562422cMatt Beaumont-Gay Loc = SM.getImmediateMacroCalleeLoc(Loc); 2702898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 2712898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek unsigned MacroSkipStart = 0, MacroSkipEnd = 0; 27202c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor if (MacroDepth > DiagOpts->MacroBacktraceLimit && 27302c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor DiagOpts->MacroBacktraceLimit != 0) { 27402c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor MacroSkipStart = DiagOpts->MacroBacktraceLimit / 2 + 27502c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor DiagOpts->MacroBacktraceLimit % 2; 27602c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor MacroSkipEnd = MacroDepth - DiagOpts->MacroBacktraceLimit / 2; 2772898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek } 2782898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 2792898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Whether to suppress printing this macro expansion. 2802898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek bool Suppressed = (OnMacroInst >= MacroSkipStart && 2812898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek OnMacroInst < MacroSkipEnd); 2822898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 2832898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Map the ranges. 2842898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek for (SmallVectorImpl<CharSourceRange>::iterator I = Ranges.begin(), 2852898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek E = Ranges.end(); 2862898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek I != E; ++I) { 2872898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek SourceLocation Start = I->getBegin(), End = I->getEnd(); 2882898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek if (Start.isMacroID()) 28929271fbcef645117df05d5b60e593acb6562422cMatt Beaumont-Gay I->setBegin(SM.getImmediateMacroCalleeLoc(Start)); 2902898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek if (End.isMacroID()) 29129271fbcef645117df05d5b60e593acb6562422cMatt Beaumont-Gay I->setEnd(SM.getImmediateMacroCalleeLoc(End)); 2922898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek } 2932898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 2942898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek if (Suppressed) { 2952898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Tell the user that we've skipped contexts. 2962898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek if (OnMacroInst == MacroSkipStart) { 297f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<200> MessageStorage; 2982898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek llvm::raw_svector_ostream Message(MessageStorage); 2992898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek Message << "(skipping " << (MacroSkipEnd - MacroSkipStart) 3002898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek << " expansions in backtrace; use -fmacro-backtrace-limit=0 to " 3012898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek "see all)"; 3022898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek emitBasicNote(Message.str()); 3032898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek } 3042898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek return; 3052898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek } 3062898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 307f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<100> MessageStorage; 3082898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek llvm::raw_svector_ostream Message(MessageStorage); 3092898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek Message << "expanded from macro '" 3107f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis << getImmediateMacroName(MacroLoc, SM, LangOpts) << "'"; 3112898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek emitDiagnostic(SM.getSpellingLoc(Loc), DiagnosticsEngine::Note, 3122898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek Message.str(), 31316afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis Ranges, ArrayRef<FixItHint>(), &SM); 3142898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek} 3152898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 3168be51eab5ad34515d2a40dcdc8558128ca1800adTed KremenekDiagnosticNoteRenderer::~DiagnosticNoteRenderer() {} 3178be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek 3188be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenekvoid DiagnosticNoteRenderer::emitIncludeLocation(SourceLocation Loc, 31916afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis PresumedLoc PLoc, 32016afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis const SourceManager &SM) { 3218be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek // Generate a note indicating the include location. 3228be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek SmallString<200> MessageStorage; 3238be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek llvm::raw_svector_ostream Message(MessageStorage); 3248be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek Message << "in file included from " << PLoc.getFilename() << ':' 3258be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek << PLoc.getLine() << ":"; 32616afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis emitNote(Loc, Message.str(), &SM); 3278be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek} 3288be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek 3298be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenekvoid DiagnosticNoteRenderer::emitBasicNote(StringRef Message) { 33016afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis emitNote(SourceLocation(), Message, 0); 3318be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek} 332