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" 1430660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/Edit/Commit.h" 1555fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Edit/EditedSource.h" 1630660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/Edit/EditsReceiver.h" 1755fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Lex/Lexer.h" 189cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman#include "llvm/ADT/SmallSet.h" 192898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek#include "llvm/ADT/SmallString.h" 2055fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/Support/ErrorHandling.h" 2155fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/Support/MemoryBuffer.h" 2255fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/Support/raw_ostream.h" 232898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek#include <algorithm> 242898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenekusing namespace clang; 252898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 267f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// \brief Retrieve the name of the immediate macro expansion. 277f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// 287f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// This routine starts from a source location, and finds the name of the macro 297f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// responsible for its immediate expansion. It looks through any intervening 307f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// macro argument expansions to compute this. It returns a StringRef which 317f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// refers to the SourceManager-owned buffer of the source where that macro 327f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// name is spelled. Thus, the result shouldn't out-live that SourceManager. 337f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// 347f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// This differs from Lexer::getImmediateMacroName in that any macro argument 357f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// location will result in the topmost function macro that accepted it. 367f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// e.g. 377f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// \code 387f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// MAC1( MAC2(foo) ) 397f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// \endcode 407f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// for location of 'foo' token, this function will return "MAC1" while 417f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis/// Lexer::getImmediateMacroName will return "MAC2". 427f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidisstatic StringRef getImmediateMacroName(SourceLocation Loc, 437f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis const SourceManager &SM, 447f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis const LangOptions &LangOpts) { 457f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis assert(Loc.isMacroID() && "Only reasonble to call this on macros"); 467f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis // Walk past macro argument expanions. 477f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis while (SM.isMacroArgExpansion(Loc)) 487f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis Loc = SM.getImmediateExpansionRange(Loc).first; 497f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis 505b10af7aa9e254a38d0a9f4d86caaccd61972124Richard Smith // If the macro's spelling has no FileID, then it's actually a token paste 515b10af7aa9e254a38d0a9f4d86caaccd61972124Richard Smith // or stringization (or similar) and not a macro at all. 525b10af7aa9e254a38d0a9f4d86caaccd61972124Richard Smith if (!SM.getFileEntryForID(SM.getFileID(SM.getSpellingLoc(Loc)))) 535b10af7aa9e254a38d0a9f4d86caaccd61972124Richard Smith return StringRef(); 545b10af7aa9e254a38d0a9f4d86caaccd61972124Richard Smith 557f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis // Find the spelling location of the start of the non-argument expansion 567f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis // range. This is where the macro name was spelled in order to begin 577f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis // expanding this macro. 587f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis Loc = SM.getSpellingLoc(SM.getImmediateExpansionRange(Loc).first); 597f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis 607f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis // Dig out the buffer where the macro name was spelled and the extents of the 617f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis // name so that we can render it into the expansion note. 627f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis std::pair<FileID, unsigned> ExpansionInfo = SM.getDecomposedLoc(Loc); 637f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis unsigned MacroTokenLength = Lexer::MeasureTokenLength(Loc, SM, LangOpts); 647f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis StringRef ExpansionBuffer = SM.getBufferData(ExpansionInfo.first); 657f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis return ExpansionBuffer.substr(ExpansionInfo.second, MacroTokenLength); 667f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis} 677f6cf9764b33381e03fcf7c44f7985a333212b06Argyrios Kyrtzidis 6816afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios KyrtzidisDiagnosticRenderer::DiagnosticRenderer(const LangOptions &LangOpts, 6902c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor DiagnosticOptions *DiagOpts) 7002c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor : LangOpts(LangOpts), DiagOpts(DiagOpts), LastLevel() {} 712898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 722898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted KremenekDiagnosticRenderer::~DiagnosticRenderer() {} 732898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 7430660a898545416f0fea2d717f16f75640001e38Ted Kremeneknamespace { 7530660a898545416f0fea2d717f16f75640001e38Ted Kremenek 7630660a898545416f0fea2d717f16f75640001e38Ted Kremenekclass FixitReceiver : public edit::EditsReceiver { 7730660a898545416f0fea2d717f16f75640001e38Ted Kremenek SmallVectorImpl<FixItHint> &MergedFixits; 7830660a898545416f0fea2d717f16f75640001e38Ted Kremenek 7930660a898545416f0fea2d717f16f75640001e38Ted Kremenekpublic: 8030660a898545416f0fea2d717f16f75640001e38Ted Kremenek FixitReceiver(SmallVectorImpl<FixItHint> &MergedFixits) 8130660a898545416f0fea2d717f16f75640001e38Ted Kremenek : MergedFixits(MergedFixits) { } 82651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void insert(SourceLocation loc, StringRef text) override { 8330660a898545416f0fea2d717f16f75640001e38Ted Kremenek MergedFixits.push_back(FixItHint::CreateInsertion(loc, text)); 8430660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 85651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void replace(CharSourceRange range, StringRef text) override { 8630660a898545416f0fea2d717f16f75640001e38Ted Kremenek MergedFixits.push_back(FixItHint::CreateReplacement(range, text)); 8730660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 8830660a898545416f0fea2d717f16f75640001e38Ted Kremenek}; 8930660a898545416f0fea2d717f16f75640001e38Ted Kremenek 9030660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 9130660a898545416f0fea2d717f16f75640001e38Ted Kremenek 9230660a898545416f0fea2d717f16f75640001e38Ted Kremenekstatic void mergeFixits(ArrayRef<FixItHint> FixItHints, 9330660a898545416f0fea2d717f16f75640001e38Ted Kremenek const SourceManager &SM, const LangOptions &LangOpts, 9430660a898545416f0fea2d717f16f75640001e38Ted Kremenek SmallVectorImpl<FixItHint> &MergedFixits) { 9530660a898545416f0fea2d717f16f75640001e38Ted Kremenek edit::Commit commit(SM, LangOpts); 9630660a898545416f0fea2d717f16f75640001e38Ted Kremenek for (ArrayRef<FixItHint>::const_iterator 9730660a898545416f0fea2d717f16f75640001e38Ted Kremenek I = FixItHints.begin(), E = FixItHints.end(); I != E; ++I) { 9830660a898545416f0fea2d717f16f75640001e38Ted Kremenek const FixItHint &Hint = *I; 9930660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (Hint.CodeToInsert.empty()) { 10030660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (Hint.InsertFromRange.isValid()) 10130660a898545416f0fea2d717f16f75640001e38Ted Kremenek commit.insertFromRange(Hint.RemoveRange.getBegin(), 10230660a898545416f0fea2d717f16f75640001e38Ted Kremenek Hint.InsertFromRange, /*afterToken=*/false, 10330660a898545416f0fea2d717f16f75640001e38Ted Kremenek Hint.BeforePreviousInsertions); 10430660a898545416f0fea2d717f16f75640001e38Ted Kremenek else 10530660a898545416f0fea2d717f16f75640001e38Ted Kremenek commit.remove(Hint.RemoveRange); 10630660a898545416f0fea2d717f16f75640001e38Ted Kremenek } else { 10730660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (Hint.RemoveRange.isTokenRange() || 10830660a898545416f0fea2d717f16f75640001e38Ted Kremenek Hint.RemoveRange.getBegin() != Hint.RemoveRange.getEnd()) 10930660a898545416f0fea2d717f16f75640001e38Ted Kremenek commit.replace(Hint.RemoveRange, Hint.CodeToInsert); 11030660a898545416f0fea2d717f16f75640001e38Ted Kremenek else 11130660a898545416f0fea2d717f16f75640001e38Ted Kremenek commit.insert(Hint.RemoveRange.getBegin(), Hint.CodeToInsert, 11230660a898545416f0fea2d717f16f75640001e38Ted Kremenek /*afterToken=*/false, Hint.BeforePreviousInsertions); 11330660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 11430660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 11530660a898545416f0fea2d717f16f75640001e38Ted Kremenek 11630660a898545416f0fea2d717f16f75640001e38Ted Kremenek edit::EditedSource Editor(SM, LangOpts); 11730660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (Editor.commit(commit)) { 11830660a898545416f0fea2d717f16f75640001e38Ted Kremenek FixitReceiver Rec(MergedFixits); 11930660a898545416f0fea2d717f16f75640001e38Ted Kremenek Editor.applyRewrites(Rec); 12030660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 12130660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 1222898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 1232898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenekvoid DiagnosticRenderer::emitDiagnostic(SourceLocation Loc, 1242898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek DiagnosticsEngine::Level Level, 1252898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek StringRef Message, 1262898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek ArrayRef<CharSourceRange> Ranges, 1272898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek ArrayRef<FixItHint> FixItHints, 12816afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis const SourceManager *SM, 1298be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek DiagOrStoredDiag D) { 13016afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis assert(SM || Loc.isInvalid()); 13198cffc6b30dacd71434530fee368b1f7d03bd565Richard Smith 1328be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek beginDiagnostic(D, Level); 13398cffc6b30dacd71434530fee368b1f7d03bd565Richard Smith 13498cffc6b30dacd71434530fee368b1f7d03bd565Richard Smith if (!Loc.isValid()) 13598cffc6b30dacd71434530fee368b1f7d03bd565Richard Smith // If we have no source location, just emit the diagnostic message. 13698cffc6b30dacd71434530fee368b1f7d03bd565Richard Smith emitDiagnosticMessage(Loc, PresumedLoc(), Level, Message, Ranges, SM, D); 13798cffc6b30dacd71434530fee368b1f7d03bd565Richard Smith else { 1382898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Get the ranges into a local array we can hack on. 1392898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek SmallVector<CharSourceRange, 20> MutableRanges(Ranges.begin(), 1402898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek Ranges.end()); 14198cffc6b30dacd71434530fee368b1f7d03bd565Richard Smith 142cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko SmallVector<FixItHint, 8> MergedFixits; 14330660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (!FixItHints.empty()) { 14416afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis mergeFixits(FixItHints, *SM, LangOpts, MergedFixits); 14530660a898545416f0fea2d717f16f75640001e38Ted Kremenek FixItHints = MergedFixits; 14630660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 14730660a898545416f0fea2d717f16f75640001e38Ted Kremenek 1482898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek for (ArrayRef<FixItHint>::const_iterator I = FixItHints.begin(), 1492898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek E = FixItHints.end(); 1502898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek I != E; ++I) 1512898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek if (I->RemoveRange.isValid()) 1522898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek MutableRanges.push_back(I->RemoveRange); 153ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith 15498cffc6b30dacd71434530fee368b1f7d03bd565Richard Smith SourceLocation UnexpandedLoc = Loc; 15598cffc6b30dacd71434530fee368b1f7d03bd565Richard Smith 1566ee225c8d4381e728c73252ed589f13e9f546defTed Kremenek // Find the ultimate expansion location for the diagnostic. 1576ee225c8d4381e728c73252ed589f13e9f546defTed Kremenek Loc = SM->getFileLoc(Loc); 158ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith 15998cffc6b30dacd71434530fee368b1f7d03bd565Richard Smith PresumedLoc PLoc = SM->getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc); 16098cffc6b30dacd71434530fee368b1f7d03bd565Richard Smith 16198cffc6b30dacd71434530fee368b1f7d03bd565Richard Smith // First, if this diagnostic is not in the main file, print out the 16298cffc6b30dacd71434530fee368b1f7d03bd565Richard Smith // "included from" lines. 16398cffc6b30dacd71434530fee368b1f7d03bd565Richard Smith emitIncludeStack(Loc, PLoc, Level, *SM); 16498cffc6b30dacd71434530fee368b1f7d03bd565Richard Smith 16598cffc6b30dacd71434530fee368b1f7d03bd565Richard Smith // Next, emit the actual diagnostic message and caret. 16698cffc6b30dacd71434530fee368b1f7d03bd565Richard Smith emitDiagnosticMessage(Loc, PLoc, Level, Message, Ranges, SM, D); 16798cffc6b30dacd71434530fee368b1f7d03bd565Richard Smith emitCaret(Loc, Level, MutableRanges, FixItHints, *SM); 16898cffc6b30dacd71434530fee368b1f7d03bd565Richard Smith 16998cffc6b30dacd71434530fee368b1f7d03bd565Richard Smith // If this location is within a macro, walk from UnexpandedLoc up to Loc 17098cffc6b30dacd71434530fee368b1f7d03bd565Richard Smith // and produce a macro backtrace. 17198cffc6b30dacd71434530fee368b1f7d03bd565Richard Smith if (UnexpandedLoc.isValid() && UnexpandedLoc.isMacroID()) { 172ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith unsigned MacroDepth = 0; 17398cffc6b30dacd71434530fee368b1f7d03bd565Richard Smith emitMacroExpansions(UnexpandedLoc, Level, MutableRanges, FixItHints, *SM, 174ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith MacroDepth); 175ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith } 1762898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek } 17798cffc6b30dacd71434530fee368b1f7d03bd565Richard Smith 1782898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek LastLoc = Loc; 1792898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek LastLevel = Level; 18098cffc6b30dacd71434530fee368b1f7d03bd565Richard Smith 1818be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek endDiagnostic(D, Level); 1828be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek} 1838be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek 1848be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek 1858be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenekvoid DiagnosticRenderer::emitStoredDiagnostic(StoredDiagnostic &Diag) { 1868be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek emitDiagnostic(Diag.getLocation(), Diag.getLevel(), Diag.getMessage(), 1878be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek Diag.getRanges(), Diag.getFixIts(), 18816afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis Diag.getLocation().isValid() ? &Diag.getLocation().getManager() 1896bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines : nullptr, 1908be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek &Diag); 1912898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek} 1922898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 193ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesvoid DiagnosticRenderer::emitBasicNote(StringRef Message) { 194ef8225444452a1486bd721f3285301fe84643b00Stephen Hines emitDiagnosticMessage( 195ef8225444452a1486bd721f3285301fe84643b00Stephen Hines SourceLocation(), PresumedLoc(), DiagnosticsEngine::Note, Message, 196ef8225444452a1486bd721f3285301fe84643b00Stephen Hines ArrayRef<CharSourceRange>(), nullptr, DiagOrStoredDiag()); 197ef8225444452a1486bd721f3285301fe84643b00Stephen Hines} 198ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 1992898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \brief Prints an include stack when appropriate for a particular 2002898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// diagnostic level and location. 2012898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// 2022898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// This routine handles all the logic of suppressing particular include 2032898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// stacks (such as those for notes) and duplicate include stacks when 2042898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// repeated warnings occur within the same file. It also handles the logic 2052898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// of customizing the formatting and display of the include stack. 2062898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// 2076c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor/// \param Loc The diagnostic location. 2086c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor/// \param PLoc The presumed location of the diagnostic location. 2092898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \param Level The diagnostic level of the message this stack pertains to. 2102898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenekvoid DiagnosticRenderer::emitIncludeStack(SourceLocation Loc, 2116c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor PresumedLoc PLoc, 21216afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis DiagnosticsEngine::Level Level, 21316afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis const SourceManager &SM) { 2146c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor SourceLocation IncludeLoc = PLoc.getIncludeLoc(); 2156c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor 2162898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Skip redundant include stacks altogether. 2176c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor if (LastIncludeLoc == IncludeLoc) 2182898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek return; 2196c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor 2206c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor LastIncludeLoc = IncludeLoc; 2212898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 22202c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor if (!DiagOpts->ShowNoteIncludeStack && Level == DiagnosticsEngine::Note) 2232898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek return; 2246c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor 2256c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor if (IncludeLoc.isValid()) 2266c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor emitIncludeStackRecursively(IncludeLoc, SM); 2276c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor else { 2284565e487531c7bf6d348dbe9f5529784966fc7aeDouglas Gregor emitModuleBuildStack(SM); 2296c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor emitImportStack(Loc, SM); 2306c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor } 2312898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek} 2322898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 2332898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \brief Helper to recursivly walk up the include stack and print each layer 2342898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// on the way back down. 23516afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidisvoid DiagnosticRenderer::emitIncludeStackRecursively(SourceLocation Loc, 23616afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis const SourceManager &SM) { 237830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor if (Loc.isInvalid()) { 2384565e487531c7bf6d348dbe9f5529784966fc7aeDouglas Gregor emitModuleBuildStack(SM); 2392898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek return; 240830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor } 2412898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 24262221b17c90457df9ca0ff20bb54d634e8951defRichard Smith PresumedLoc PLoc = SM.getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc); 2432898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek if (PLoc.isInvalid()) 2442898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek return; 2456c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor 2466c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor // If this source location was imported from a module, print the module 2476c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor // import stack rather than the 2486c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor // FIXME: We want submodule granularity here. 2496c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor std::pair<SourceLocation, StringRef> Imported = SM.getModuleImportLoc(Loc); 2506c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor if (Imported.first.isValid()) { 2516c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor // This location was imported by a module. Emit the module import stack. 2526c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor emitImportStackRecursively(Imported.first, Imported.second, SM); 2536c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor return; 2546c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor } 2556c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor 2562898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Emit the other include frames first. 25716afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis emitIncludeStackRecursively(PLoc.getIncludeLoc(), SM); 2582898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 2592898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Emit the inclusion text/note. 26016afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis emitIncludeLocation(Loc, PLoc, SM); 2612898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek} 2622898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 2636c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor/// \brief Emit the module import stack associated with the current location. 2646c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregorvoid DiagnosticRenderer::emitImportStack(SourceLocation Loc, 2656c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor const SourceManager &SM) { 2666c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor if (Loc.isInvalid()) { 2674565e487531c7bf6d348dbe9f5529784966fc7aeDouglas Gregor emitModuleBuildStack(SM); 2686c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor return; 2696c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor } 2706c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor 2716c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor std::pair<SourceLocation, StringRef> NextImportLoc 2726c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor = SM.getModuleImportLoc(Loc); 2736c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second, SM); 2746c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor} 2756c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor 2766c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor/// \brief Helper to recursivly walk up the import stack and print each layer 2776c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor/// on the way back down. 2786c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregorvoid DiagnosticRenderer::emitImportStackRecursively(SourceLocation Loc, 2796c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor StringRef ModuleName, 2806c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor const SourceManager &SM) { 2816c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor if (Loc.isInvalid()) { 2826c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor return; 2836c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor } 2846c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor 2856c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor PresumedLoc PLoc = SM.getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc); 2866c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor if (PLoc.isInvalid()) 2876c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor return; 2886c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor 2896c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor // Emit the other import frames first. 2906c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor std::pair<SourceLocation, StringRef> NextImportLoc 2916c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor = SM.getModuleImportLoc(Loc); 2926c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second, SM); 2936c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor 2946c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor // Emit the inclusion text/note. 2956c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor emitImportLocation(Loc, PLoc, ModuleName, SM); 2966c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor} 2976c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor 2984565e487531c7bf6d348dbe9f5529784966fc7aeDouglas Gregor/// \brief Emit the module build stack, for cases where a module is (re-)built 299830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor/// on demand. 3004565e487531c7bf6d348dbe9f5529784966fc7aeDouglas Gregorvoid DiagnosticRenderer::emitModuleBuildStack(const SourceManager &SM) { 3014565e487531c7bf6d348dbe9f5529784966fc7aeDouglas Gregor ModuleBuildStack Stack = SM.getModuleBuildStack(); 3024565e487531c7bf6d348dbe9f5529784966fc7aeDouglas Gregor for (unsigned I = 0, N = Stack.size(); I != N; ++I) { 3034565e487531c7bf6d348dbe9f5529784966fc7aeDouglas Gregor const SourceManager &CurSM = Stack[I].second.getManager(); 3044565e487531c7bf6d348dbe9f5529784966fc7aeDouglas Gregor SourceLocation CurLoc = Stack[I].second; 305830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor emitBuildingModuleLocation(CurLoc, 306830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor CurSM.getPresumedLoc(CurLoc, 307830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor DiagOpts->ShowPresumedLoc), 3084565e487531c7bf6d348dbe9f5529784966fc7aeDouglas Gregor Stack[I].first, 309830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor CurSM); 310830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor } 311830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor} 312830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor 3139cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman// Helper function to fix up source ranges. It takes in an array of ranges, 3149cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman// and outputs an array of ranges where we want to draw the range highlighting 3159cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman// around the location specified by CaretLoc. 3169cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman// 3179cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman// To find locations which correspond to the caret, we crawl the macro caller 3189cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman// chain for the beginning and end of each range. If the caret location 3199cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman// is in a macro expansion, we search each chain for a location 3209cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman// in the same expansion as the caret; otherwise, we crawl to the top of 3219cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman// each chain. Two locations are part of the same macro expansion 3229cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman// iff the FileID is the same. 3239cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedmanstatic void mapDiagnosticRanges( 3249cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman SourceLocation CaretLoc, 325ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith ArrayRef<CharSourceRange> Ranges, 32698cffc6b30dacd71434530fee368b1f7d03bd565Richard Smith SmallVectorImpl<CharSourceRange> &SpellingRanges, 3279cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman const SourceManager *SM) { 3289cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman FileID CaretLocFileID = SM->getFileID(CaretLoc); 3299cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman 330ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith for (ArrayRef<CharSourceRange>::const_iterator I = Ranges.begin(), 3319cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman E = Ranges.end(); 3329cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman I != E; ++I) { 3339cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman SourceLocation Begin = I->getBegin(), End = I->getEnd(); 3349cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman bool IsTokenRange = I->isTokenRange(); 3359cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman 3360fdcd1e81db7b8f5b3fd05154d966b215b20a2ebEli Friedman FileID BeginFileID = SM->getFileID(Begin); 3375bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem FileID EndFileID = SM->getFileID(End); 3385bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem 3395bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem // Find the common parent for the beginning and end of the range. 3405bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem 3415bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem // First, crawl the expansion chain for the beginning of the range. 3425bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem llvm::SmallDenseMap<FileID, SourceLocation> BeginLocsMap; 3435bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem while (Begin.isMacroID() && BeginFileID != EndFileID) { 3445bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem BeginLocsMap[BeginFileID] = Begin; 3455bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem Begin = SM->getImmediateExpansionRange(Begin).first; 3465bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem BeginFileID = SM->getFileID(Begin); 3475bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem } 3485bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem 3495bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem // Then, crawl the expansion chain for the end of the range. 3505bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem if (BeginFileID != EndFileID) { 3515bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem while (End.isMacroID() && !BeginLocsMap.count(EndFileID)) { 3525bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem End = SM->getImmediateExpansionRange(End).second; 3535bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem EndFileID = SM->getFileID(End); 3545bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem } 3555bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem if (End.isMacroID()) { 3565bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem Begin = BeginLocsMap[EndFileID]; 3575bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem BeginFileID = EndFileID; 3585bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem } 3595bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem } 360ecdc8d3e0fc65610746a4e074491ca0807fca7b2Eli Friedman 361ecdc8d3e0fc65610746a4e074491ca0807fca7b2Eli Friedman while (Begin.isMacroID() && BeginFileID != CaretLocFileID) { 362ecdc8d3e0fc65610746a4e074491ca0807fca7b2Eli Friedman if (SM->isMacroArgExpansion(Begin)) { 363ecdc8d3e0fc65610746a4e074491ca0807fca7b2Eli Friedman Begin = SM->getImmediateSpellingLoc(Begin); 3649cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman End = SM->getImmediateSpellingLoc(End); 3659cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman } else { 366ecdc8d3e0fc65610746a4e074491ca0807fca7b2Eli Friedman Begin = SM->getImmediateExpansionRange(Begin).first; 3679cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman End = SM->getImmediateExpansionRange(End).second; 3689cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman } 3695bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem BeginFileID = SM->getFileID(Begin); 370adff43ad96defb28bad20d8335ab30beadd72ee8Eli Friedman if (BeginFileID != SM->getFileID(End)) { 371adff43ad96defb28bad20d8335ab30beadd72ee8Eli Friedman // FIXME: Ugly hack to stop a crash; this code is making bad 372adff43ad96defb28bad20d8335ab30beadd72ee8Eli Friedman // assumptions and it's too complicated for me to reason 373adff43ad96defb28bad20d8335ab30beadd72ee8Eli Friedman // about. 374adff43ad96defb28bad20d8335ab30beadd72ee8Eli Friedman Begin = End = SourceLocation(); 375adff43ad96defb28bad20d8335ab30beadd72ee8Eli Friedman break; 376adff43ad96defb28bad20d8335ab30beadd72ee8Eli Friedman } 3779cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman } 3789cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman 3799cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman // Return the spelling location of the beginning and end of the range. 3809cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman Begin = SM->getSpellingLoc(Begin); 3819cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman End = SM->getSpellingLoc(End); 3829cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman SpellingRanges.push_back(CharSourceRange(SourceRange(Begin, End), 3839cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman IsTokenRange)); 3849cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman } 3859cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman} 3869cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman 387ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smithvoid DiagnosticRenderer::emitCaret(SourceLocation Loc, 388ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith DiagnosticsEngine::Level Level, 389ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith ArrayRef<CharSourceRange> Ranges, 390ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith ArrayRef<FixItHint> Hints, 391ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith const SourceManager &SM) { 392ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith SmallVector<CharSourceRange, 4> SpellingRanges; 393ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM); 394ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith emitCodeContext(Loc, Level, SpellingRanges, Hints, SM); 395ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith} 396ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith 3972898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \brief Recursively emit notes for each macro expansion and caret 3982898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// diagnostics where appropriate. 3992898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// 4002898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// Walks up the macro expansion stack printing expansion notes, the code 4012898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// snippet, caret, underlines and FixItHint display as appropriate at each 4022898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// level. 4032898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// 4042898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \param Loc The location for this caret. 4052898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \param Level The diagnostic level currently being emitted. 4062898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \param Ranges The underlined ranges for this code snippet. 4072898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \param Hints The FixIt hints active for this diagnostic. 4082898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \param OnMacroInst The current depth of the macro expansion stack. 409ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smithvoid DiagnosticRenderer::emitMacroExpansions(SourceLocation Loc, 410ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith DiagnosticsEngine::Level Level, 411ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith ArrayRef<CharSourceRange> Ranges, 412ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith ArrayRef<FixItHint> Hints, 413ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith const SourceManager &SM, 414ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith unsigned &MacroDepth, 415ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith unsigned OnMacroInst) { 4162898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek assert(!Loc.isInvalid() && "must have a valid source location here"); 417678839297204002df215e0be12bcd10b20a9a4a4Richard Smith 418678839297204002df215e0be12bcd10b20a9a4a4Richard Smith // Walk up to the caller of this macro, and produce a backtrace down to there. 419678839297204002df215e0be12bcd10b20a9a4a4Richard Smith SourceLocation OneLevelUp = SM.getImmediateMacroCallerLoc(Loc); 420ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith if (OneLevelUp.isMacroID()) 421ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith emitMacroExpansions(OneLevelUp, Level, Ranges, Hints, SM, 422ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith MacroDepth, OnMacroInst + 1); 423ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith else 424ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith MacroDepth = OnMacroInst + 1; 425678839297204002df215e0be12bcd10b20a9a4a4Richard Smith 4262898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek unsigned MacroSkipStart = 0, MacroSkipEnd = 0; 42702c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor if (MacroDepth > DiagOpts->MacroBacktraceLimit && 42802c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor DiagOpts->MacroBacktraceLimit != 0) { 42902c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor MacroSkipStart = DiagOpts->MacroBacktraceLimit / 2 + 43002c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor DiagOpts->MacroBacktraceLimit % 2; 43102c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor MacroSkipEnd = MacroDepth - DiagOpts->MacroBacktraceLimit / 2; 4322898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek } 433678839297204002df215e0be12bcd10b20a9a4a4Richard Smith 4342898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Whether to suppress printing this macro expansion. 4352898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek bool Suppressed = (OnMacroInst >= MacroSkipStart && 4362898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek OnMacroInst < MacroSkipEnd); 437678839297204002df215e0be12bcd10b20a9a4a4Richard Smith 4382898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek if (Suppressed) { 4392898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Tell the user that we've skipped contexts. 4402898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek if (OnMacroInst == MacroSkipStart) { 441f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<200> MessageStorage; 4422898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek llvm::raw_svector_ostream Message(MessageStorage); 4432898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek Message << "(skipping " << (MacroSkipEnd - MacroSkipStart) 4442898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek << " expansions in backtrace; use -fmacro-backtrace-limit=0 to " 4452898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek "see all)"; 4462898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek emitBasicNote(Message.str()); 4472898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek } 4482898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek return; 4492898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek } 4509cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman 451678839297204002df215e0be12bcd10b20a9a4a4Richard Smith // Find the spelling location for the macro definition. We must use the 452678839297204002df215e0be12bcd10b20a9a4a4Richard Smith // spelling location here to avoid emitting a macro bactrace for the note. 453678839297204002df215e0be12bcd10b20a9a4a4Richard Smith SourceLocation SpellingLoc = Loc; 454678839297204002df215e0be12bcd10b20a9a4a4Richard Smith // If this is the expansion of a macro argument, point the caret at the 455678839297204002df215e0be12bcd10b20a9a4a4Richard Smith // use of the argument in the definition of the macro, not the expansion. 456678839297204002df215e0be12bcd10b20a9a4a4Richard Smith if (SM.isMacroArgExpansion(Loc)) 457678839297204002df215e0be12bcd10b20a9a4a4Richard Smith SpellingLoc = SM.getImmediateExpansionRange(Loc).first; 458678839297204002df215e0be12bcd10b20a9a4a4Richard Smith SpellingLoc = SM.getSpellingLoc(SpellingLoc); 459678839297204002df215e0be12bcd10b20a9a4a4Richard Smith 460678839297204002df215e0be12bcd10b20a9a4a4Richard Smith // Map the ranges into the FileID of the diagnostic location. 4619cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman SmallVector<CharSourceRange, 4> SpellingRanges; 462678839297204002df215e0be12bcd10b20a9a4a4Richard Smith mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM); 4639cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman 464f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<100> MessageStorage; 4652898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek llvm::raw_svector_ostream Message(MessageStorage); 4665b10af7aa9e254a38d0a9f4d86caaccd61972124Richard Smith StringRef MacroName = getImmediateMacroName(Loc, SM, LangOpts); 4675b10af7aa9e254a38d0a9f4d86caaccd61972124Richard Smith if (MacroName.empty()) 4685b10af7aa9e254a38d0a9f4d86caaccd61972124Richard Smith Message << "expanded from here"; 4695b10af7aa9e254a38d0a9f4d86caaccd61972124Richard Smith else 4705b10af7aa9e254a38d0a9f4d86caaccd61972124Richard Smith Message << "expanded from macro '" << MacroName << "'"; 4715543169296beeb183b9c9392debc774fcf493eebDmitri Gribenko emitDiagnostic(SpellingLoc, DiagnosticsEngine::Note, Message.str(), 4725543169296beeb183b9c9392debc774fcf493eebDmitri Gribenko SpellingRanges, None, &SM); 4732898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek} 4742898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 4758be51eab5ad34515d2a40dcdc8558128ca1800adTed KremenekDiagnosticNoteRenderer::~DiagnosticNoteRenderer() {} 4768be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek 4778be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenekvoid DiagnosticNoteRenderer::emitIncludeLocation(SourceLocation Loc, 47816afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis PresumedLoc PLoc, 47916afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis const SourceManager &SM) { 4808be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek // Generate a note indicating the include location. 4818be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek SmallString<200> MessageStorage; 4828be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek llvm::raw_svector_ostream Message(MessageStorage); 4838be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek Message << "in file included from " << PLoc.getFilename() << ':' 4848be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek << PLoc.getLine() << ":"; 48516afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis emitNote(Loc, Message.str(), &SM); 4868be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek} 4878be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek 4886c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregorvoid DiagnosticNoteRenderer::emitImportLocation(SourceLocation Loc, 4896c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor PresumedLoc PLoc, 4906c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor StringRef ModuleName, 4916c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor const SourceManager &SM) { 4926c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor // Generate a note indicating the include location. 4936c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor SmallString<200> MessageStorage; 4946c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor llvm::raw_svector_ostream Message(MessageStorage); 4956c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor Message << "in module '" << ModuleName << "' imported from " 4966c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor << PLoc.getFilename() << ':' << PLoc.getLine() << ":"; 4976c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor emitNote(Loc, Message.str(), &SM); 4986c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor} 4996c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor 500830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregorvoid 501830ea5b7c75413526c19531f0180fa6e45b98919Douglas GregorDiagnosticNoteRenderer::emitBuildingModuleLocation(SourceLocation Loc, 502830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor PresumedLoc PLoc, 503830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor StringRef ModuleName, 504830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor const SourceManager &SM) { 505830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor // Generate a note indicating the include location. 506830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor SmallString<200> MessageStorage; 507830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor llvm::raw_svector_ostream Message(MessageStorage); 508651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (PLoc.getFilename()) 509651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Message << "while building module '" << ModuleName << "' imported from " 510651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << PLoc.getFilename() << ':' << PLoc.getLine() << ":"; 511651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines else 512651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Message << "while building module '" << ModuleName << ":"; 513830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor emitNote(Loc, Message.str(), &SM); 514830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor} 515