DiagnosticRenderer.cpp revision 303975
1226584Sdim//===--- DiagnosticRenderer.cpp - Diagnostic Pretty-Printing --------------===// 2226584Sdim// 3226584Sdim// The LLVM Compiler Infrastructure 4226584Sdim// 5226584Sdim// This file is distributed under the University of Illinois Open Source 6226584Sdim// License. See LICENSE.TXT for details. 7226584Sdim// 8226584Sdim//===----------------------------------------------------------------------===// 9226584Sdim 10226584Sdim#include "clang/Frontend/DiagnosticRenderer.h" 11226584Sdim#include "clang/Basic/DiagnosticOptions.h" 12226584Sdim#include "clang/Basic/FileManager.h" 13226584Sdim#include "clang/Basic/SourceManager.h" 14226584Sdim#include "clang/Edit/Commit.h" 15226584Sdim#include "clang/Edit/EditedSource.h" 16249423Sdim#include "clang/Edit/EditsReceiver.h" 17263508Sdim#include "clang/Lex/Lexer.h" 18226584Sdim#include "llvm/ADT/SmallSet.h" 19226584Sdim#include "llvm/ADT/SmallString.h" 20226584Sdim#include "llvm/Support/ErrorHandling.h" 21226584Sdim#include "llvm/Support/MemoryBuffer.h" 22226584Sdim#include "llvm/Support/raw_ostream.h" 23226584Sdim#include <algorithm> 24226584Sdimusing namespace clang; 25226584Sdim 26226584Sdim/// \brief Retrieve the name of the immediate macro expansion. 27234353Sdim/// 28226584Sdim/// This routine starts from a source location, and finds the name of the macro 29249423Sdim/// responsible for its immediate expansion. It looks through any intervening 30251662Sdim/// macro argument expansions to compute this. It returns a StringRef which 31226584Sdim/// refers to the SourceManager-owned buffer of the source where that macro 32226584Sdim/// name is spelled. Thus, the result shouldn't out-live that SourceManager. 33226584Sdim/// 34226584Sdim/// This differs from Lexer::getImmediateMacroName in that any macro argument 35249423Sdim/// location will result in the topmost function macro that accepted it. 36226584Sdim/// e.g. 37226584Sdim/// \code 38226584Sdim/// MAC1( MAC2(foo) ) 39226584Sdim/// \endcode 40226584Sdim/// for location of 'foo' token, this function will return "MAC1" while 41226584Sdim/// Lexer::getImmediateMacroName will return "MAC2". 42226584Sdimstatic StringRef getImmediateMacroName(SourceLocation Loc, 43226584Sdim const SourceManager &SM, 44226584Sdim const LangOptions &LangOpts) { 45226584Sdim assert(Loc.isMacroID() && "Only reasonble to call this on macros"); 46226584Sdim // Walk past macro argument expanions. 47226584Sdim while (SM.isMacroArgExpansion(Loc)) 48226584Sdim Loc = SM.getImmediateExpansionRange(Loc).first; 49226584Sdim 50226584Sdim // If the macro's spelling has no FileID, then it's actually a token paste 51226584Sdim // or stringization (or similar) and not a macro at all. 52251662Sdim if (!SM.getFileEntryForID(SM.getFileID(SM.getSpellingLoc(Loc)))) 53226584Sdim return StringRef(); 54234353Sdim 55234353Sdim // Find the spelling location of the start of the non-argument expansion 56251662Sdim // range. This is where the macro name was spelled in order to begin 57234353Sdim // expanding this macro. 58226584Sdim Loc = SM.getSpellingLoc(SM.getImmediateExpansionRange(Loc).first); 59226584Sdim 60226584Sdim // Dig out the buffer where the macro name was spelled and the extents of the 61226584Sdim // name so that we can render it into the expansion note. 62226584Sdim std::pair<FileID, unsigned> ExpansionInfo = SM.getDecomposedLoc(Loc); 63226584Sdim unsigned MacroTokenLength = Lexer::MeasureTokenLength(Loc, SM, LangOpts); 64226584Sdim StringRef ExpansionBuffer = SM.getBufferData(ExpansionInfo.first); 65226584Sdim return ExpansionBuffer.substr(ExpansionInfo.second, MacroTokenLength); 66226584Sdim} 67226584Sdim 68226584SdimDiagnosticRenderer::DiagnosticRenderer(const LangOptions &LangOpts, 69226584Sdim DiagnosticOptions *DiagOpts) 70226584Sdim : LangOpts(LangOpts), DiagOpts(DiagOpts), LastLevel() {} 71234353Sdim 72234353SdimDiagnosticRenderer::~DiagnosticRenderer() {} 73234353Sdim 74234353Sdimnamespace { 75234353Sdim 76226584Sdimclass FixitReceiver : public edit::EditsReceiver { 77234353Sdim SmallVectorImpl<FixItHint> &MergedFixits; 78234353Sdim 79234353Sdimpublic: 80234353Sdim FixitReceiver(SmallVectorImpl<FixItHint> &MergedFixits) 81234353Sdim : MergedFixits(MergedFixits) { } 82234353Sdim void insert(SourceLocation loc, StringRef text) override { 83234353Sdim MergedFixits.push_back(FixItHint::CreateInsertion(loc, text)); 84234353Sdim } 85234353Sdim void replace(CharSourceRange range, StringRef text) override { 86234353Sdim MergedFixits.push_back(FixItHint::CreateReplacement(range, text)); 87234353Sdim } 88226584Sdim}; 89226584Sdim 90263508Sdim} 91263508Sdim 92263508Sdimstatic void mergeFixits(ArrayRef<FixItHint> FixItHints, 93263508Sdim const SourceManager &SM, const LangOptions &LangOpts, 94263508Sdim SmallVectorImpl<FixItHint> &MergedFixits) { 95226584Sdim edit::Commit commit(SM, LangOpts); 96263508Sdim for (ArrayRef<FixItHint>::const_iterator 97263508Sdim I = FixItHints.begin(), E = FixItHints.end(); I != E; ++I) { 98263508Sdim const FixItHint &Hint = *I; 99263508Sdim if (Hint.CodeToInsert.empty()) { 100226584Sdim if (Hint.InsertFromRange.isValid()) 101226584Sdim commit.insertFromRange(Hint.RemoveRange.getBegin(), 102263508Sdim Hint.InsertFromRange, /*afterToken=*/false, 103263508Sdim Hint.BeforePreviousInsertions); 104263508Sdim else 105226584Sdim commit.remove(Hint.RemoveRange); 106263508Sdim } else { 107263508Sdim if (Hint.RemoveRange.isTokenRange() || 108263508Sdim Hint.RemoveRange.getBegin() != Hint.RemoveRange.getEnd()) 109263508Sdim commit.replace(Hint.RemoveRange, Hint.CodeToInsert); 110263508Sdim else 111263508Sdim commit.insert(Hint.RemoveRange.getBegin(), Hint.CodeToInsert, 112263508Sdim /*afterToken=*/false, Hint.BeforePreviousInsertions); 113263508Sdim } 114263508Sdim } 115263508Sdim 116263508Sdim edit::EditedSource Editor(SM, LangOpts); 117263508Sdim if (Editor.commit(commit)) { 118263508Sdim FixitReceiver Rec(MergedFixits); 119263508Sdim Editor.applyRewrites(Rec); 120263508Sdim } 121263508Sdim} 122263508Sdim 123263508Sdimvoid DiagnosticRenderer::emitDiagnostic(SourceLocation Loc, 124263508Sdim DiagnosticsEngine::Level Level, 125226584Sdim StringRef Message, 126263508Sdim ArrayRef<CharSourceRange> Ranges, 127263508Sdim ArrayRef<FixItHint> FixItHints, 128263508Sdim const SourceManager *SM, 129263508Sdim DiagOrStoredDiag D) { 130263508Sdim assert(SM || Loc.isInvalid()); 131263508Sdim 132263508Sdim beginDiagnostic(D, Level); 133263508Sdim 134263508Sdim if (!Loc.isValid()) 135263508Sdim // If we have no source location, just emit the diagnostic message. 136263508Sdim emitDiagnosticMessage(Loc, PresumedLoc(), Level, Message, Ranges, SM, D); 137263508Sdim else { 138263508Sdim // Get the ranges into a local array we can hack on. 139263508Sdim SmallVector<CharSourceRange, 20> MutableRanges(Ranges.begin(), 140263508Sdim Ranges.end()); 141263508Sdim 142263508Sdim SmallVector<FixItHint, 8> MergedFixits; 143263508Sdim if (!FixItHints.empty()) { 144263508Sdim mergeFixits(FixItHints, *SM, LangOpts, MergedFixits); 145263508Sdim FixItHints = MergedFixits; 146263508Sdim } 147226584Sdim 148226584Sdim for (ArrayRef<FixItHint>::const_iterator I = FixItHints.begin(), 149226584Sdim E = FixItHints.end(); 150251662Sdim I != E; ++I) 151263508Sdim if (I->RemoveRange.isValid()) 152251662Sdim MutableRanges.push_back(I->RemoveRange); 153251662Sdim 154251662Sdim SourceLocation UnexpandedLoc = Loc; 155263508Sdim 156263508Sdim // Find the ultimate expansion location for the diagnostic. 157234353Sdim Loc = SM->getFileLoc(Loc); 158234353Sdim 159234353Sdim PresumedLoc PLoc = SM->getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc); 160234353Sdim 161226584Sdim // First, if this diagnostic is not in the main file, print out the 162234353Sdim // "included from" lines. 163234353Sdim emitIncludeStack(Loc, PLoc, Level, *SM); 164234353Sdim 165234353Sdim // Next, emit the actual diagnostic message and caret. 166234353Sdim emitDiagnosticMessage(Loc, PLoc, Level, Message, Ranges, SM, D); 167234353Sdim emitCaret(Loc, Level, MutableRanges, FixItHints, *SM); 168234353Sdim 169226584Sdim // If this location is within a macro, walk from UnexpandedLoc up to Loc 170251662Sdim // and produce a macro backtrace. 171251662Sdim if (UnexpandedLoc.isValid() && UnexpandedLoc.isMacroID()) { 172263508Sdim emitMacroExpansions(UnexpandedLoc, Level, MutableRanges, FixItHints, *SM); 173251662Sdim } 174263508Sdim } 175226584Sdim 176226584Sdim LastLoc = Loc; 177263508Sdim LastLevel = Level; 178251662Sdim 179226584Sdim endDiagnostic(D, Level); 180263508Sdim} 181226584Sdim 182263508Sdim 183263508Sdimvoid DiagnosticRenderer::emitStoredDiagnostic(StoredDiagnostic &Diag) { 184263508Sdim emitDiagnostic(Diag.getLocation(), Diag.getLevel(), Diag.getMessage(), 185263508Sdim Diag.getRanges(), Diag.getFixIts(), 186263508Sdim Diag.getLocation().isValid() ? &Diag.getLocation().getManager() 187263508Sdim : nullptr, 188263508Sdim &Diag); 189263508Sdim} 190263508Sdim 191251662Sdimvoid DiagnosticRenderer::emitBasicNote(StringRef Message) { 192263508Sdim emitDiagnosticMessage( 193251662Sdim SourceLocation(), PresumedLoc(), DiagnosticsEngine::Note, Message, 194251662Sdim None, nullptr, DiagOrStoredDiag()); 195251662Sdim} 196226584Sdim 197226584Sdim/// \brief Prints an include stack when appropriate for a particular 198226584Sdim/// diagnostic level and location. 199251662Sdim/// 200251662Sdim/// This routine handles all the logic of suppressing particular include 201251662Sdim/// stacks (such as those for notes) and duplicate include stacks when 202226584Sdim/// repeated warnings occur within the same file. It also handles the logic 203226584Sdim/// of customizing the formatting and display of the include stack. 204226584Sdim/// 205226584Sdim/// \param Loc The diagnostic location. 206226584Sdim/// \param PLoc The presumed location of the diagnostic location. 207226584Sdim/// \param Level The diagnostic level of the message this stack pertains to. 208226584Sdimvoid DiagnosticRenderer::emitIncludeStack(SourceLocation Loc, 209226584Sdim PresumedLoc PLoc, 210234353Sdim DiagnosticsEngine::Level Level, 211234353Sdim const SourceManager &SM) { 212226584Sdim SourceLocation IncludeLoc = PLoc.getIncludeLoc(); 213251662Sdim 214251662Sdim // Skip redundant include stacks altogether. 215251662Sdim if (LastIncludeLoc == IncludeLoc) 216251662Sdim return; 217251662Sdim 218251662Sdim LastIncludeLoc = IncludeLoc; 219226584Sdim 220226584Sdim if (!DiagOpts->ShowNoteIncludeStack && Level == DiagnosticsEngine::Note) 221226584Sdim return; 222226584Sdim 223226584Sdim if (IncludeLoc.isValid()) 224226584Sdim emitIncludeStackRecursively(IncludeLoc, SM); 225226584Sdim else { 226226584Sdim emitModuleBuildStack(SM); 227226584Sdim emitImportStack(Loc, SM); 228263508Sdim } 229263508Sdim} 230263508Sdim 231226584Sdim/// \brief Helper to recursivly walk up the include stack and print each layer 232226584Sdim/// on the way back down. 233226584Sdimvoid DiagnosticRenderer::emitIncludeStackRecursively(SourceLocation Loc, 234226584Sdim const SourceManager &SM) { 235234353Sdim if (Loc.isInvalid()) { 236234353Sdim emitModuleBuildStack(SM); 237234353Sdim return; 238226584Sdim } 239226584Sdim 240226584Sdim PresumedLoc PLoc = SM.getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc); 241226584Sdim if (PLoc.isInvalid()) 242226584Sdim return; 243226584Sdim 244226584Sdim // If this source location was imported from a module, print the module 245226584Sdim // import stack rather than the 246226584Sdim // FIXME: We want submodule granularity here. 247263508Sdim std::pair<SourceLocation, StringRef> Imported = SM.getModuleImportLoc(Loc); 248226584Sdim if (!Imported.second.empty()) { 249263508Sdim // This location was imported by a module. Emit the module import stack. 250263508Sdim emitImportStackRecursively(Imported.first, Imported.second, SM); 251263508Sdim return; 252263508Sdim } 253263508Sdim 254263508Sdim // Emit the other include frames first. 255234353Sdim emitIncludeStackRecursively(PLoc.getIncludeLoc(), SM); 256234353Sdim 257226584Sdim // Emit the inclusion text/note. 258263508Sdim emitIncludeLocation(Loc, PLoc, SM); 259226584Sdim} 260263508Sdim 261263508Sdim/// \brief Emit the module import stack associated with the current location. 262226584Sdimvoid DiagnosticRenderer::emitImportStack(SourceLocation Loc, 263226584Sdim const SourceManager &SM) { 264234353Sdim if (Loc.isInvalid()) { 265226584Sdim emitModuleBuildStack(SM); 266263508Sdim return; 267263508Sdim } 268263508Sdim 269263508Sdim std::pair<SourceLocation, StringRef> NextImportLoc 270263508Sdim = SM.getModuleImportLoc(Loc); 271263508Sdim emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second, SM); 272263508Sdim} 273263508Sdim 274263508Sdim/// \brief Helper to recursivly walk up the import stack and print each layer 275263508Sdim/// on the way back down. 276263508Sdimvoid DiagnosticRenderer::emitImportStackRecursively(SourceLocation Loc, 277263508Sdim StringRef ModuleName, 278263508Sdim const SourceManager &SM) { 279263508Sdim if (ModuleName.empty()) { 280263508Sdim return; 281263508Sdim } 282226584Sdim 283226584Sdim PresumedLoc PLoc = SM.getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc); 284226584Sdim 285226584Sdim // Emit the other import frames first. 286226584Sdim std::pair<SourceLocation, StringRef> NextImportLoc 287226584Sdim = SM.getModuleImportLoc(Loc); 288226584Sdim emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second, SM); 289251662Sdim 290226584Sdim // Emit the inclusion text/note. 291226584Sdim emitImportLocation(Loc, PLoc, ModuleName, SM); 292226584Sdim} 293226584Sdim 294226584Sdim/// \brief Emit the module build stack, for cases where a module is (re-)built 295226584Sdim/// on demand. 296263508Sdimvoid DiagnosticRenderer::emitModuleBuildStack(const SourceManager &SM) { 297226584Sdim ModuleBuildStack Stack = SM.getModuleBuildStack(); 298226584Sdim for (unsigned I = 0, N = Stack.size(); I != N; ++I) { 299226584Sdim const SourceManager &CurSM = Stack[I].second.getManager(); 300249423Sdim SourceLocation CurLoc = Stack[I].second; 301226584Sdim emitBuildingModuleLocation(CurLoc, 302226584Sdim CurSM.getPresumedLoc(CurLoc, 303249423Sdim DiagOpts->ShowPresumedLoc), 304249423Sdim Stack[I].first, 305226584Sdim CurSM); 306226584Sdim } 307263508Sdim} 308226584Sdim 309263508Sdim/// A recursive function to trace all possible backtrace locations 310263508Sdim/// to match the \p CaretLocFileID. 311263508Sdimstatic SourceLocation 312263508SdimretrieveMacroLocation(SourceLocation Loc, FileID MacroFileID, 313263508Sdim FileID CaretFileID, 314234353Sdim const SmallVectorImpl<FileID> &CommonArgExpansions, 315234353Sdim bool IsBegin, const SourceManager *SM) { 316249423Sdim assert(SM->getFileID(Loc) == MacroFileID); 317226584Sdim if (MacroFileID == CaretFileID) 318226584Sdim return Loc; 319249423Sdim if (!Loc.isMacroID()) 320263508Sdim return SourceLocation(); 321251662Sdim 322251662Sdim SourceLocation MacroLocation, MacroArgLocation; 323249423Sdim 324249423Sdim if (SM->isMacroArgExpansion(Loc)) { 325234353Sdim // Only look at the immediate spelling location of this macro argument if 326234353Sdim // the other location in the source range is also present in that expansion. 327226584Sdim if (std::binary_search(CommonArgExpansions.begin(), 328226584Sdim CommonArgExpansions.end(), MacroFileID)) 329226584Sdim MacroLocation = SM->getImmediateSpellingLoc(Loc); 330226584Sdim MacroArgLocation = IsBegin ? SM->getImmediateExpansionRange(Loc).first 331234353Sdim : SM->getImmediateExpansionRange(Loc).second; 332234353Sdim } else { 333234353Sdim MacroLocation = IsBegin ? SM->getImmediateExpansionRange(Loc).first 334234353Sdim : SM->getImmediateExpansionRange(Loc).second; 335234353Sdim MacroArgLocation = SM->getImmediateSpellingLoc(Loc); 336251662Sdim } 337234353Sdim 338234353Sdim if (MacroLocation.isValid()) { 339234353Sdim MacroFileID = SM->getFileID(MacroLocation); 340263508Sdim MacroLocation = 341234353Sdim retrieveMacroLocation(MacroLocation, MacroFileID, CaretFileID, 342263508Sdim CommonArgExpansions, IsBegin, SM); 343226584Sdim if (MacroLocation.isValid()) 344226584Sdim return MacroLocation; 345226584Sdim } 346226584Sdim 347226584Sdim MacroFileID = SM->getFileID(MacroArgLocation); 348234353Sdim return retrieveMacroLocation(MacroArgLocation, MacroFileID, CaretFileID, 349234353Sdim CommonArgExpansions, IsBegin, SM); 350234353Sdim} 351234353Sdim 352234353Sdim/// Walk up the chain of macro expansions and collect the FileIDs identifying the 353234353Sdim/// expansions. 354234353Sdimstatic void getMacroArgExpansionFileIDs(SourceLocation Loc, 355234353Sdim SmallVectorImpl<FileID> &IDs, 356226584Sdim bool IsBegin, const SourceManager *SM) { 357234353Sdim while (Loc.isMacroID()) { 358234353Sdim if (SM->isMacroArgExpansion(Loc)) { 359234353Sdim IDs.push_back(SM->getFileID(Loc)); 360226584Sdim Loc = SM->getImmediateSpellingLoc(Loc); 361226584Sdim } else { 362226584Sdim auto ExpRange = SM->getImmediateExpansionRange(Loc); 363234353Sdim Loc = IsBegin ? ExpRange.first : ExpRange.second; 364234353Sdim } 365234353Sdim } 366234353Sdim} 367234353Sdim 368234353Sdim/// Collect the expansions of the begin and end locations and compute the set 369226584Sdim/// intersection. Produces a sorted vector of FileIDs in CommonArgExpansions. 370226584Sdimstatic void computeCommonMacroArgExpansionFileIDs( 371239462Sdim SourceLocation Begin, SourceLocation End, const SourceManager *SM, 372234353Sdim SmallVectorImpl<FileID> &CommonArgExpansions) { 373234353Sdim SmallVector<FileID, 4> BeginArgExpansions; 374234353Sdim SmallVector<FileID, 4> EndArgExpansions; 375234353Sdim getMacroArgExpansionFileIDs(Begin, BeginArgExpansions, /*IsBegin=*/true, SM); 376234353Sdim getMacroArgExpansionFileIDs(End, EndArgExpansions, /*IsBegin=*/false, SM); 377234353Sdim std::sort(BeginArgExpansions.begin(), BeginArgExpansions.end()); 378234353Sdim std::sort(EndArgExpansions.begin(), EndArgExpansions.end()); 379234353Sdim std::set_intersection(BeginArgExpansions.begin(), BeginArgExpansions.end(), 380234353Sdim EndArgExpansions.begin(), EndArgExpansions.end(), 381234353Sdim std::back_inserter(CommonArgExpansions)); 382234353Sdim} 383234353Sdim 384234353Sdim// Helper function to fix up source ranges. It takes in an array of ranges, 385234353Sdim// and outputs an array of ranges where we want to draw the range highlighting 386234353Sdim// around the location specified by CaretLoc. 387234353Sdim// 388234353Sdim// To find locations which correspond to the caret, we crawl the macro caller 389234353Sdim// chain for the beginning and end of each range. If the caret location 390226584Sdim// is in a macro expansion, we search each chain for a location 391226584Sdim// in the same expansion as the caret; otherwise, we crawl to the top of 392226584Sdim// each chain. Two locations are part of the same macro expansion 393226584Sdim// iff the FileID is the same. 394263508Sdimstatic void mapDiagnosticRanges( 395263508Sdim SourceLocation CaretLoc, 396263508Sdim ArrayRef<CharSourceRange> Ranges, 397263508Sdim SmallVectorImpl<CharSourceRange> &SpellingRanges, 398234353Sdim const SourceManager *SM) { 399263508Sdim FileID CaretLocFileID = SM->getFileID(CaretLoc); 400263508Sdim 401263508Sdim for (auto I = Ranges.begin(), E = Ranges.end(); I != E; ++I) { 402226584Sdim if (I->isInvalid()) continue; 403263508Sdim 404263508Sdim SourceLocation Begin = I->getBegin(), End = I->getEnd(); 405263508Sdim bool IsTokenRange = I->isTokenRange(); 406263508Sdim 407263508Sdim FileID BeginFileID = SM->getFileID(Begin); 408263508Sdim FileID EndFileID = SM->getFileID(End); 409263508Sdim 410263508Sdim // Find the common parent for the beginning and end of the range. 411263508Sdim 412263508Sdim // First, crawl the expansion chain for the beginning of the range. 413263508Sdim llvm::SmallDenseMap<FileID, SourceLocation> BeginLocsMap; 414263508Sdim while (Begin.isMacroID() && BeginFileID != EndFileID) { 415263508Sdim BeginLocsMap[BeginFileID] = Begin; 416263508Sdim Begin = SM->getImmediateExpansionRange(Begin).first; 417263508Sdim BeginFileID = SM->getFileID(Begin); 418263508Sdim } 419234353Sdim 420263508Sdim // Then, crawl the expansion chain for the end of the range. 421263508Sdim if (BeginFileID != EndFileID) { 422263508Sdim while (End.isMacroID() && !BeginLocsMap.count(EndFileID)) { 423263508Sdim End = SM->getImmediateExpansionRange(End).second; 424226584Sdim EndFileID = SM->getFileID(End); 425263508Sdim } 426263508Sdim if (End.isMacroID()) { 427263508Sdim Begin = BeginLocsMap[EndFileID]; 428263508Sdim BeginFileID = EndFileID; 429263508Sdim } 430263508Sdim } 431263508Sdim 432263508Sdim // Do the backtracking. 433263508Sdim SmallVector<FileID, 4> CommonArgExpansions; 434226584Sdim computeCommonMacroArgExpansionFileIDs(Begin, End, SM, CommonArgExpansions); 435263508Sdim Begin = retrieveMacroLocation(Begin, BeginFileID, CaretLocFileID, 436263508Sdim CommonArgExpansions, /*IsBegin=*/true, SM); 437263508Sdim End = retrieveMacroLocation(End, BeginFileID, CaretLocFileID, 438263508Sdim CommonArgExpansions, /*IsBegin=*/false, SM); 439263508Sdim if (Begin.isInvalid() || End.isInvalid()) continue; 440226584Sdim 441226584Sdim // Return the spelling location of the beginning and end of the range. 442226584Sdim Begin = SM->getSpellingLoc(Begin); 443263508Sdim End = SM->getSpellingLoc(End); 444239462Sdim 445239462Sdim SpellingRanges.push_back(CharSourceRange(SourceRange(Begin, End), 446239462Sdim IsTokenRange)); 447239462Sdim } 448239462Sdim} 449239462Sdim 450239462Sdimvoid DiagnosticRenderer::emitCaret(SourceLocation Loc, 451239462Sdim DiagnosticsEngine::Level Level, 452226584Sdim ArrayRef<CharSourceRange> Ranges, 453239462Sdim ArrayRef<FixItHint> Hints, 454239462Sdim const SourceManager &SM) { 455239462Sdim SmallVector<CharSourceRange, 4> SpellingRanges; 456239462Sdim mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM); 457239462Sdim emitCodeContext(Loc, Level, SpellingRanges, Hints, SM); 458239462Sdim} 459239462Sdim 460239462Sdim/// \brief A helper function for emitMacroExpansion to print the 461239462Sdim/// macro expansion message 462239462Sdimvoid DiagnosticRenderer::emitSingleMacroExpansion( 463239462Sdim SourceLocation Loc, 464239462Sdim DiagnosticsEngine::Level Level, 465239462Sdim ArrayRef<CharSourceRange> Ranges, 466226584Sdim const SourceManager &SM) { 467226584Sdim // Find the spelling location for the macro definition. We must use the 468 // spelling location here to avoid emitting a macro backtrace for the note. 469 SourceLocation SpellingLoc = SM.getSpellingLoc(Loc); 470 471 // Map the ranges into the FileID of the diagnostic location. 472 SmallVector<CharSourceRange, 4> SpellingRanges; 473 mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM); 474 475 SmallString<100> MessageStorage; 476 llvm::raw_svector_ostream Message(MessageStorage); 477 StringRef MacroName = getImmediateMacroName(Loc, SM, LangOpts); 478 if (MacroName.empty()) 479 Message << "expanded from here"; 480 else 481 Message << "expanded from macro '" << MacroName << "'"; 482 483 emitDiagnostic(SpellingLoc, DiagnosticsEngine::Note, Message.str(), 484 SpellingRanges, None, &SM); 485} 486 487/// Check that the macro argument location of Loc starts with ArgumentLoc. 488/// The starting location of the macro expansions is used to differeniate 489/// different macro expansions. 490static bool checkLocForMacroArgExpansion(SourceLocation Loc, 491 const SourceManager &SM, 492 SourceLocation ArgumentLoc) { 493 SourceLocation MacroLoc; 494 if (SM.isMacroArgExpansion(Loc, &MacroLoc)) { 495 if (ArgumentLoc == MacroLoc) return true; 496 } 497 498 return false; 499} 500 501/// Check if all the locations in the range have the same macro argument 502/// expansion, and that that expansion starts with ArgumentLoc. 503static bool checkRangeForMacroArgExpansion(CharSourceRange Range, 504 const SourceManager &SM, 505 SourceLocation ArgumentLoc) { 506 SourceLocation BegLoc = Range.getBegin(), EndLoc = Range.getEnd(); 507 while (BegLoc != EndLoc) { 508 if (!checkLocForMacroArgExpansion(BegLoc, SM, ArgumentLoc)) 509 return false; 510 BegLoc.getLocWithOffset(1); 511 } 512 513 return checkLocForMacroArgExpansion(BegLoc, SM, ArgumentLoc); 514} 515 516/// A helper function to check if the current ranges are all inside the same 517/// macro argument expansion as Loc. 518static bool checkRangesForMacroArgExpansion(SourceLocation Loc, 519 ArrayRef<CharSourceRange> Ranges, 520 const SourceManager &SM) { 521 assert(Loc.isMacroID() && "Must be a macro expansion!"); 522 523 SmallVector<CharSourceRange, 4> SpellingRanges; 524 mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM); 525 526 /// Count all valid ranges. 527 unsigned ValidCount = 0; 528 for (auto I : Ranges) 529 if (I.isValid()) ValidCount++; 530 531 if (ValidCount > SpellingRanges.size()) 532 return false; 533 534 /// To store the source location of the argument location. 535 SourceLocation ArgumentLoc; 536 537 /// Set the ArgumentLoc to the beginning location of the expansion of Loc 538 /// so to check if the ranges expands to the same beginning location. 539 if (!SM.isMacroArgExpansion(Loc,&ArgumentLoc)) 540 return false; 541 542 for (auto I = SpellingRanges.begin(), E = SpellingRanges.end(); I != E; ++I) { 543 if (!checkRangeForMacroArgExpansion(*I, SM, ArgumentLoc)) 544 return false; 545 } 546 547 return true; 548} 549 550/// \brief Recursively emit notes for each macro expansion and caret 551/// diagnostics where appropriate. 552/// 553/// Walks up the macro expansion stack printing expansion notes, the code 554/// snippet, caret, underlines and FixItHint display as appropriate at each 555/// level. 556/// 557/// \param Loc The location for this caret. 558/// \param Level The diagnostic level currently being emitted. 559/// \param Ranges The underlined ranges for this code snippet. 560/// \param Hints The FixIt hints active for this diagnostic. 561void DiagnosticRenderer::emitMacroExpansions(SourceLocation Loc, 562 DiagnosticsEngine::Level Level, 563 ArrayRef<CharSourceRange> Ranges, 564 ArrayRef<FixItHint> Hints, 565 const SourceManager &SM) { 566 assert(Loc.isValid() && "must have a valid source location here"); 567 568 // Produce a stack of macro backtraces. 569 SmallVector<SourceLocation, 8> LocationStack; 570 unsigned IgnoredEnd = 0; 571 while (Loc.isMacroID()) { 572 // If this is the expansion of a macro argument, point the caret at the 573 // use of the argument in the definition of the macro, not the expansion. 574 if (SM.isMacroArgExpansion(Loc)) 575 LocationStack.push_back(SM.getImmediateExpansionRange(Loc).first); 576 else 577 LocationStack.push_back(Loc); 578 579 if (checkRangesForMacroArgExpansion(Loc, Ranges, SM)) 580 IgnoredEnd = LocationStack.size(); 581 582 Loc = SM.getImmediateMacroCallerLoc(Loc); 583 584 // Once the location no longer points into a macro, try stepping through 585 // the last found location. This sometimes produces additional useful 586 // backtraces. 587 if (Loc.isFileID()) 588 Loc = SM.getImmediateMacroCallerLoc(LocationStack.back()); 589 assert(Loc.isValid() && "must have a valid source location here"); 590 } 591 592 LocationStack.erase(LocationStack.begin(), 593 LocationStack.begin() + IgnoredEnd); 594 595 unsigned MacroDepth = LocationStack.size(); 596 unsigned MacroLimit = DiagOpts->MacroBacktraceLimit; 597 if (MacroDepth <= MacroLimit || MacroLimit == 0) { 598 for (auto I = LocationStack.rbegin(), E = LocationStack.rend(); 599 I != E; ++I) 600 emitSingleMacroExpansion(*I, Level, Ranges, SM); 601 return; 602 } 603 604 unsigned MacroStartMessages = MacroLimit / 2; 605 unsigned MacroEndMessages = MacroLimit / 2 + MacroLimit % 2; 606 607 for (auto I = LocationStack.rbegin(), 608 E = LocationStack.rbegin() + MacroStartMessages; 609 I != E; ++I) 610 emitSingleMacroExpansion(*I, Level, Ranges, SM); 611 612 SmallString<200> MessageStorage; 613 llvm::raw_svector_ostream Message(MessageStorage); 614 Message << "(skipping " << (MacroDepth - MacroLimit) 615 << " expansions in backtrace; use -fmacro-backtrace-limit=0 to " 616 "see all)"; 617 emitBasicNote(Message.str()); 618 619 for (auto I = LocationStack.rend() - MacroEndMessages, 620 E = LocationStack.rend(); 621 I != E; ++I) 622 emitSingleMacroExpansion(*I, Level, Ranges, SM); 623} 624 625DiagnosticNoteRenderer::~DiagnosticNoteRenderer() {} 626 627void DiagnosticNoteRenderer::emitIncludeLocation(SourceLocation Loc, 628 PresumedLoc PLoc, 629 const SourceManager &SM) { 630 // Generate a note indicating the include location. 631 SmallString<200> MessageStorage; 632 llvm::raw_svector_ostream Message(MessageStorage); 633 Message << "in file included from " << PLoc.getFilename() << ':' 634 << PLoc.getLine() << ":"; 635 emitNote(Loc, Message.str(), &SM); 636} 637 638void DiagnosticNoteRenderer::emitImportLocation(SourceLocation Loc, 639 PresumedLoc PLoc, 640 StringRef ModuleName, 641 const SourceManager &SM) { 642 // Generate a note indicating the include location. 643 SmallString<200> MessageStorage; 644 llvm::raw_svector_ostream Message(MessageStorage); 645 Message << "in module '" << ModuleName; 646 if (PLoc.isValid()) 647 Message << "' imported from " << PLoc.getFilename() << ':' 648 << PLoc.getLine(); 649 Message << ":"; 650 emitNote(Loc, Message.str(), &SM); 651} 652 653void 654DiagnosticNoteRenderer::emitBuildingModuleLocation(SourceLocation Loc, 655 PresumedLoc PLoc, 656 StringRef ModuleName, 657 const SourceManager &SM) { 658 // Generate a note indicating the include location. 659 SmallString<200> MessageStorage; 660 llvm::raw_svector_ostream Message(MessageStorage); 661 if (PLoc.getFilename()) 662 Message << "while building module '" << ModuleName << "' imported from " 663 << PLoc.getFilename() << ':' << PLoc.getLine() << ":"; 664 else 665 Message << "while building module '" << ModuleName << "':"; 666 emitNote(Loc, Message.str(), &SM); 667} 668