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) { } 8230660a898545416f0fea2d717f16f75640001e38Ted Kremenek virtual void insert(SourceLocation loc, StringRef text) { 8330660a898545416f0fea2d717f16f75640001e38Ted Kremenek MergedFixits.push_back(FixItHint::CreateInsertion(loc, text)); 8430660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 8530660a898545416f0fea2d717f16f75640001e38Ted Kremenek virtual void replace(CharSourceRange range, StringRef text) { 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() 18916afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis : 0, 1908be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek &Diag); 1912898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek} 1922898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 1932898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \brief Prints an include stack when appropriate for a particular 1942898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// diagnostic level and location. 1952898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// 1962898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// This routine handles all the logic of suppressing particular include 1972898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// stacks (such as those for notes) and duplicate include stacks when 1982898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// repeated warnings occur within the same file. It also handles the logic 1992898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// of customizing the formatting and display of the include stack. 2002898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// 2016c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor/// \param Loc The diagnostic location. 2026c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor/// \param PLoc The presumed location of the diagnostic location. 2032898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \param Level The diagnostic level of the message this stack pertains to. 2042898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenekvoid DiagnosticRenderer::emitIncludeStack(SourceLocation Loc, 2056c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor PresumedLoc PLoc, 20616afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis DiagnosticsEngine::Level Level, 20716afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis const SourceManager &SM) { 2086c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor SourceLocation IncludeLoc = PLoc.getIncludeLoc(); 2096c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor 2102898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Skip redundant include stacks altogether. 2116c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor if (LastIncludeLoc == IncludeLoc) 2122898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek return; 2136c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor 2146c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor LastIncludeLoc = IncludeLoc; 2152898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 21602c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor if (!DiagOpts->ShowNoteIncludeStack && Level == DiagnosticsEngine::Note) 2172898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek return; 2186c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor 2196c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor if (IncludeLoc.isValid()) 2206c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor emitIncludeStackRecursively(IncludeLoc, SM); 2216c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor else { 2224565e487531c7bf6d348dbe9f5529784966fc7aeDouglas Gregor emitModuleBuildStack(SM); 2236c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor emitImportStack(Loc, SM); 2246c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor } 2252898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek} 2262898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 2272898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \brief Helper to recursivly walk up the include stack and print each layer 2282898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// on the way back down. 22916afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidisvoid DiagnosticRenderer::emitIncludeStackRecursively(SourceLocation Loc, 23016afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis const SourceManager &SM) { 231830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor if (Loc.isInvalid()) { 2324565e487531c7bf6d348dbe9f5529784966fc7aeDouglas Gregor emitModuleBuildStack(SM); 2332898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek return; 234830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor } 2352898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 23662221b17c90457df9ca0ff20bb54d634e8951defRichard Smith PresumedLoc PLoc = SM.getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc); 2372898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek if (PLoc.isInvalid()) 2382898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek return; 2396c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor 2406c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor // If this source location was imported from a module, print the module 2416c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor // import stack rather than the 2426c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor // FIXME: We want submodule granularity here. 2436c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor std::pair<SourceLocation, StringRef> Imported = SM.getModuleImportLoc(Loc); 2446c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor if (Imported.first.isValid()) { 2456c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor // This location was imported by a module. Emit the module import stack. 2466c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor emitImportStackRecursively(Imported.first, Imported.second, SM); 2476c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor return; 2486c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor } 2496c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor 2502898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Emit the other include frames first. 25116afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis emitIncludeStackRecursively(PLoc.getIncludeLoc(), SM); 2522898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 2532898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Emit the inclusion text/note. 25416afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis emitIncludeLocation(Loc, PLoc, SM); 2552898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek} 2562898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 2576c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor/// \brief Emit the module import stack associated with the current location. 2586c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregorvoid DiagnosticRenderer::emitImportStack(SourceLocation Loc, 2596c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor const SourceManager &SM) { 2606c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor if (Loc.isInvalid()) { 2614565e487531c7bf6d348dbe9f5529784966fc7aeDouglas Gregor emitModuleBuildStack(SM); 2626c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor return; 2636c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor } 2646c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor 2656c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor std::pair<SourceLocation, StringRef> NextImportLoc 2666c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor = SM.getModuleImportLoc(Loc); 2676c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second, SM); 2686c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor} 2696c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor 2706c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor/// \brief Helper to recursivly walk up the import stack and print each layer 2716c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor/// on the way back down. 2726c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregorvoid DiagnosticRenderer::emitImportStackRecursively(SourceLocation Loc, 2736c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor StringRef ModuleName, 2746c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor const SourceManager &SM) { 2756c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor if (Loc.isInvalid()) { 2766c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor return; 2776c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor } 2786c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor 2796c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor PresumedLoc PLoc = SM.getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc); 2806c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor if (PLoc.isInvalid()) 2816c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor return; 2826c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor 2836c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor // Emit the other import frames first. 2846c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor std::pair<SourceLocation, StringRef> NextImportLoc 2856c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor = SM.getModuleImportLoc(Loc); 2866c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second, SM); 2876c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor 2886c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor // Emit the inclusion text/note. 2896c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor emitImportLocation(Loc, PLoc, ModuleName, SM); 2906c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor} 2916c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor 2924565e487531c7bf6d348dbe9f5529784966fc7aeDouglas Gregor/// \brief Emit the module build stack, for cases where a module is (re-)built 293830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor/// on demand. 2944565e487531c7bf6d348dbe9f5529784966fc7aeDouglas Gregorvoid DiagnosticRenderer::emitModuleBuildStack(const SourceManager &SM) { 2954565e487531c7bf6d348dbe9f5529784966fc7aeDouglas Gregor ModuleBuildStack Stack = SM.getModuleBuildStack(); 2964565e487531c7bf6d348dbe9f5529784966fc7aeDouglas Gregor for (unsigned I = 0, N = Stack.size(); I != N; ++I) { 2974565e487531c7bf6d348dbe9f5529784966fc7aeDouglas Gregor const SourceManager &CurSM = Stack[I].second.getManager(); 2984565e487531c7bf6d348dbe9f5529784966fc7aeDouglas Gregor SourceLocation CurLoc = Stack[I].second; 299830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor emitBuildingModuleLocation(CurLoc, 300830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor CurSM.getPresumedLoc(CurLoc, 301830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor DiagOpts->ShowPresumedLoc), 3024565e487531c7bf6d348dbe9f5529784966fc7aeDouglas Gregor Stack[I].first, 303830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor CurSM); 304830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor } 305830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor} 306830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor 3079cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman// Helper function to fix up source ranges. It takes in an array of ranges, 3089cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman// and outputs an array of ranges where we want to draw the range highlighting 3099cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman// around the location specified by CaretLoc. 3109cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman// 3119cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman// To find locations which correspond to the caret, we crawl the macro caller 3129cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman// chain for the beginning and end of each range. If the caret location 3139cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman// is in a macro expansion, we search each chain for a location 3149cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman// in the same expansion as the caret; otherwise, we crawl to the top of 3159cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman// each chain. Two locations are part of the same macro expansion 3169cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman// iff the FileID is the same. 3179cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedmanstatic void mapDiagnosticRanges( 3189cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman SourceLocation CaretLoc, 319ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith ArrayRef<CharSourceRange> Ranges, 32098cffc6b30dacd71434530fee368b1f7d03bd565Richard Smith SmallVectorImpl<CharSourceRange> &SpellingRanges, 3219cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman const SourceManager *SM) { 3229cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman FileID CaretLocFileID = SM->getFileID(CaretLoc); 3239cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman 324ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith for (ArrayRef<CharSourceRange>::const_iterator I = Ranges.begin(), 3259cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman E = Ranges.end(); 3269cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman I != E; ++I) { 3279cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman SourceLocation Begin = I->getBegin(), End = I->getEnd(); 3289cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman bool IsTokenRange = I->isTokenRange(); 3299cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman 3300fdcd1e81db7b8f5b3fd05154d966b215b20a2ebEli Friedman FileID BeginFileID = SM->getFileID(Begin); 3315bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem FileID EndFileID = SM->getFileID(End); 3325bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem 3335bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem // Find the common parent for the beginning and end of the range. 3345bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem 3355bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem // First, crawl the expansion chain for the beginning of the range. 3365bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem llvm::SmallDenseMap<FileID, SourceLocation> BeginLocsMap; 3375bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem while (Begin.isMacroID() && BeginFileID != EndFileID) { 3385bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem BeginLocsMap[BeginFileID] = Begin; 3395bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem Begin = SM->getImmediateExpansionRange(Begin).first; 3405bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem BeginFileID = SM->getFileID(Begin); 3415bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem } 3425bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem 3435bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem // Then, crawl the expansion chain for the end of the range. 3445bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem if (BeginFileID != EndFileID) { 3455bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem while (End.isMacroID() && !BeginLocsMap.count(EndFileID)) { 3465bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem End = SM->getImmediateExpansionRange(End).second; 3475bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem EndFileID = SM->getFileID(End); 3485bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem } 3495bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem if (End.isMacroID()) { 3505bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem Begin = BeginLocsMap[EndFileID]; 3515bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem BeginFileID = EndFileID; 3525bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem } 3535bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem } 354ecdc8d3e0fc65610746a4e074491ca0807fca7b2Eli Friedman 355ecdc8d3e0fc65610746a4e074491ca0807fca7b2Eli Friedman while (Begin.isMacroID() && BeginFileID != CaretLocFileID) { 356ecdc8d3e0fc65610746a4e074491ca0807fca7b2Eli Friedman if (SM->isMacroArgExpansion(Begin)) { 357ecdc8d3e0fc65610746a4e074491ca0807fca7b2Eli Friedman Begin = SM->getImmediateSpellingLoc(Begin); 3589cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman End = SM->getImmediateSpellingLoc(End); 3599cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman } else { 360ecdc8d3e0fc65610746a4e074491ca0807fca7b2Eli Friedman Begin = SM->getImmediateExpansionRange(Begin).first; 3619cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman End = SM->getImmediateExpansionRange(End).second; 3629cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman } 3635bdbc114da925304a774b726b0abb87d75bc3008Nadav Rotem BeginFileID = SM->getFileID(Begin); 364adff43ad96defb28bad20d8335ab30beadd72ee8Eli Friedman if (BeginFileID != SM->getFileID(End)) { 365adff43ad96defb28bad20d8335ab30beadd72ee8Eli Friedman // FIXME: Ugly hack to stop a crash; this code is making bad 366adff43ad96defb28bad20d8335ab30beadd72ee8Eli Friedman // assumptions and it's too complicated for me to reason 367adff43ad96defb28bad20d8335ab30beadd72ee8Eli Friedman // about. 368adff43ad96defb28bad20d8335ab30beadd72ee8Eli Friedman Begin = End = SourceLocation(); 369adff43ad96defb28bad20d8335ab30beadd72ee8Eli Friedman break; 370adff43ad96defb28bad20d8335ab30beadd72ee8Eli Friedman } 3719cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman } 3729cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman 3739cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman // Return the spelling location of the beginning and end of the range. 3749cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman Begin = SM->getSpellingLoc(Begin); 3759cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman End = SM->getSpellingLoc(End); 3769cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman SpellingRanges.push_back(CharSourceRange(SourceRange(Begin, End), 3779cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman IsTokenRange)); 3789cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman } 3799cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman} 3809cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman 381ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smithvoid DiagnosticRenderer::emitCaret(SourceLocation Loc, 382ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith DiagnosticsEngine::Level Level, 383ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith ArrayRef<CharSourceRange> Ranges, 384ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith ArrayRef<FixItHint> Hints, 385ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith const SourceManager &SM) { 386ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith SmallVector<CharSourceRange, 4> SpellingRanges; 387ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM); 388ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith emitCodeContext(Loc, Level, SpellingRanges, Hints, SM); 389ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith} 390ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith 3912898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \brief Recursively emit notes for each macro expansion and caret 3922898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// diagnostics where appropriate. 3932898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// 3942898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// Walks up the macro expansion stack printing expansion notes, the code 3952898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// snippet, caret, underlines and FixItHint display as appropriate at each 3962898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// level. 3972898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// 3982898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \param Loc The location for this caret. 3992898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \param Level The diagnostic level currently being emitted. 4002898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \param Ranges The underlined ranges for this code snippet. 4012898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \param Hints The FixIt hints active for this diagnostic. 4022898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \param OnMacroInst The current depth of the macro expansion stack. 403ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smithvoid DiagnosticRenderer::emitMacroExpansions(SourceLocation Loc, 404ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith DiagnosticsEngine::Level Level, 405ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith ArrayRef<CharSourceRange> Ranges, 406ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith ArrayRef<FixItHint> Hints, 407ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith const SourceManager &SM, 408ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith unsigned &MacroDepth, 409ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith unsigned OnMacroInst) { 4102898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek assert(!Loc.isInvalid() && "must have a valid source location here"); 411678839297204002df215e0be12bcd10b20a9a4a4Richard Smith 412678839297204002df215e0be12bcd10b20a9a4a4Richard Smith // Walk up to the caller of this macro, and produce a backtrace down to there. 413678839297204002df215e0be12bcd10b20a9a4a4Richard Smith SourceLocation OneLevelUp = SM.getImmediateMacroCallerLoc(Loc); 414ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith if (OneLevelUp.isMacroID()) 415ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith emitMacroExpansions(OneLevelUp, Level, Ranges, Hints, SM, 416ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith MacroDepth, OnMacroInst + 1); 417ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith else 418ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith MacroDepth = OnMacroInst + 1; 419678839297204002df215e0be12bcd10b20a9a4a4Richard Smith 4202898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek unsigned MacroSkipStart = 0, MacroSkipEnd = 0; 42102c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor if (MacroDepth > DiagOpts->MacroBacktraceLimit && 42202c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor DiagOpts->MacroBacktraceLimit != 0) { 42302c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor MacroSkipStart = DiagOpts->MacroBacktraceLimit / 2 + 42402c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor DiagOpts->MacroBacktraceLimit % 2; 42502c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor MacroSkipEnd = MacroDepth - DiagOpts->MacroBacktraceLimit / 2; 4262898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek } 427678839297204002df215e0be12bcd10b20a9a4a4Richard Smith 4282898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Whether to suppress printing this macro expansion. 4292898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek bool Suppressed = (OnMacroInst >= MacroSkipStart && 4302898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek OnMacroInst < MacroSkipEnd); 431678839297204002df215e0be12bcd10b20a9a4a4Richard Smith 4322898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek if (Suppressed) { 4332898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Tell the user that we've skipped contexts. 4342898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek if (OnMacroInst == MacroSkipStart) { 435f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<200> MessageStorage; 4362898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek llvm::raw_svector_ostream Message(MessageStorage); 4372898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek Message << "(skipping " << (MacroSkipEnd - MacroSkipStart) 4382898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek << " expansions in backtrace; use -fmacro-backtrace-limit=0 to " 4392898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek "see all)"; 4402898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek emitBasicNote(Message.str()); 4412898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek } 4422898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek return; 4432898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek } 4449cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman 445678839297204002df215e0be12bcd10b20a9a4a4Richard Smith // Find the spelling location for the macro definition. We must use the 446678839297204002df215e0be12bcd10b20a9a4a4Richard Smith // spelling location here to avoid emitting a macro bactrace for the note. 447678839297204002df215e0be12bcd10b20a9a4a4Richard Smith SourceLocation SpellingLoc = Loc; 448678839297204002df215e0be12bcd10b20a9a4a4Richard Smith // If this is the expansion of a macro argument, point the caret at the 449678839297204002df215e0be12bcd10b20a9a4a4Richard Smith // use of the argument in the definition of the macro, not the expansion. 450678839297204002df215e0be12bcd10b20a9a4a4Richard Smith if (SM.isMacroArgExpansion(Loc)) 451678839297204002df215e0be12bcd10b20a9a4a4Richard Smith SpellingLoc = SM.getImmediateExpansionRange(Loc).first; 452678839297204002df215e0be12bcd10b20a9a4a4Richard Smith SpellingLoc = SM.getSpellingLoc(SpellingLoc); 453678839297204002df215e0be12bcd10b20a9a4a4Richard Smith 454678839297204002df215e0be12bcd10b20a9a4a4Richard Smith // Map the ranges into the FileID of the diagnostic location. 4559cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman SmallVector<CharSourceRange, 4> SpellingRanges; 456678839297204002df215e0be12bcd10b20a9a4a4Richard Smith mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM); 4579cb1c3de9df7d944f0c5cccaf03fa414036487ebEli Friedman 458f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<100> MessageStorage; 4592898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek llvm::raw_svector_ostream Message(MessageStorage); 4605b10af7aa9e254a38d0a9f4d86caaccd61972124Richard Smith StringRef MacroName = getImmediateMacroName(Loc, SM, LangOpts); 4615b10af7aa9e254a38d0a9f4d86caaccd61972124Richard Smith if (MacroName.empty()) 4625b10af7aa9e254a38d0a9f4d86caaccd61972124Richard Smith Message << "expanded from here"; 4635b10af7aa9e254a38d0a9f4d86caaccd61972124Richard Smith else 4645b10af7aa9e254a38d0a9f4d86caaccd61972124Richard Smith Message << "expanded from macro '" << MacroName << "'"; 4655543169296beeb183b9c9392debc774fcf493eebDmitri Gribenko emitDiagnostic(SpellingLoc, DiagnosticsEngine::Note, Message.str(), 4665543169296beeb183b9c9392debc774fcf493eebDmitri Gribenko SpellingRanges, None, &SM); 4672898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek} 4682898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 4698be51eab5ad34515d2a40dcdc8558128ca1800adTed KremenekDiagnosticNoteRenderer::~DiagnosticNoteRenderer() {} 4708be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek 4718be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenekvoid DiagnosticNoteRenderer::emitIncludeLocation(SourceLocation Loc, 47216afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis PresumedLoc PLoc, 47316afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis const SourceManager &SM) { 4748be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek // Generate a note indicating the include location. 4758be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek SmallString<200> MessageStorage; 4768be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek llvm::raw_svector_ostream Message(MessageStorage); 4778be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek Message << "in file included from " << PLoc.getFilename() << ':' 4788be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek << PLoc.getLine() << ":"; 47916afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis emitNote(Loc, Message.str(), &SM); 4808be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek} 4818be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek 4826c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregorvoid DiagnosticNoteRenderer::emitImportLocation(SourceLocation Loc, 4836c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor PresumedLoc PLoc, 4846c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor StringRef ModuleName, 4856c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor const SourceManager &SM) { 4866c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor // Generate a note indicating the include location. 4876c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor SmallString<200> MessageStorage; 4886c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor llvm::raw_svector_ostream Message(MessageStorage); 4896c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor Message << "in module '" << ModuleName << "' imported from " 4906c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor << PLoc.getFilename() << ':' << PLoc.getLine() << ":"; 4916c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor emitNote(Loc, Message.str(), &SM); 4926c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor} 4936c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor 494830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregorvoid 495830ea5b7c75413526c19531f0180fa6e45b98919Douglas GregorDiagnosticNoteRenderer::emitBuildingModuleLocation(SourceLocation Loc, 496830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor PresumedLoc PLoc, 497830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor StringRef ModuleName, 498830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor const SourceManager &SM) { 499830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor // Generate a note indicating the include location. 500830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor SmallString<200> MessageStorage; 501830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor llvm::raw_svector_ostream Message(MessageStorage); 502830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor Message << "while building module '" << ModuleName << "' imported from " 503830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor << PLoc.getFilename() << ':' << PLoc.getLine() << ":"; 504830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor emitNote(Loc, Message.str(), &SM); 505830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor} 506830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor 507830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor 5088be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenekvoid DiagnosticNoteRenderer::emitBasicNote(StringRef Message) { 50916afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis emitNote(SourceLocation(), Message, 0); 5108be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek} 511