1 //===--- DiagnosticRenderer.cpp - Diagnostic Pretty-Printing --------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "clang/Frontend/DiagnosticRenderer.h" 11 #include "clang/Basic/DiagnosticOptions.h" 12 #include "clang/Basic/FileManager.h" 13 #include "clang/Basic/SourceManager.h" 14 #include "clang/Edit/Commit.h" 15 #include "clang/Edit/EditedSource.h" 16 #include "clang/Edit/EditsReceiver.h" 17 #include "clang/Lex/Lexer.h" 18 #include "llvm/ADT/SmallSet.h" 19 #include "llvm/ADT/SmallString.h" 20 #include "llvm/Support/ErrorHandling.h" 21 #include "llvm/Support/MemoryBuffer.h" 22 #include "llvm/Support/raw_ostream.h" 23 #include <algorithm> 24 using namespace clang; 25 26 /// \brief Retrieve the name of the immediate macro expansion. 27 /// 28 /// This routine starts from a source location, and finds the name of the macro 29 /// responsible for its immediate expansion. It looks through any intervening 30 /// macro argument expansions to compute this. It returns a StringRef which 31 /// refers to the SourceManager-owned buffer of the source where that macro 32 /// name is spelled. Thus, the result shouldn't out-live that SourceManager. 33 /// 34 /// This differs from Lexer::getImmediateMacroName in that any macro argument 35 /// location will result in the topmost function macro that accepted it. 36 /// e.g. 37 /// \code 38 /// MAC1( MAC2(foo) ) 39 /// \endcode 40 /// for location of 'foo' token, this function will return "MAC1" while 41 /// Lexer::getImmediateMacroName will return "MAC2". 42 static StringRef getImmediateMacroName(SourceLocation Loc, 43 const SourceManager &SM, 44 const LangOptions &LangOpts) { 45 assert(Loc.isMacroID() && "Only reasonble to call this on macros"); 46 // Walk past macro argument expanions. 47 while (SM.isMacroArgExpansion(Loc)) 48 Loc = SM.getImmediateExpansionRange(Loc).first; 49 50 // If the macro's spelling has no FileID, then it's actually a token paste 51 // or stringization (or similar) and not a macro at all. 52 if (!SM.getFileEntryForID(SM.getFileID(SM.getSpellingLoc(Loc)))) 53 return StringRef(); 54 55 // Find the spelling location of the start of the non-argument expansion 56 // range. This is where the macro name was spelled in order to begin 57 // expanding this macro. 58 Loc = SM.getSpellingLoc(SM.getImmediateExpansionRange(Loc).first); 59 60 // Dig out the buffer where the macro name was spelled and the extents of the 61 // name so that we can render it into the expansion note. 62 std::pair<FileID, unsigned> ExpansionInfo = SM.getDecomposedLoc(Loc); 63 unsigned MacroTokenLength = Lexer::MeasureTokenLength(Loc, SM, LangOpts); 64 StringRef ExpansionBuffer = SM.getBufferData(ExpansionInfo.first); 65 return ExpansionBuffer.substr(ExpansionInfo.second, MacroTokenLength); 66 } 67 68 DiagnosticRenderer::DiagnosticRenderer(const LangOptions &LangOpts, 69 DiagnosticOptions *DiagOpts) 70 : LangOpts(LangOpts), DiagOpts(DiagOpts), LastLevel() {} 71 72 DiagnosticRenderer::~DiagnosticRenderer() {} 73 74 namespace { 75 76 class FixitReceiver : public edit::EditsReceiver { 77 SmallVectorImpl<FixItHint> &MergedFixits; 78 79 public: 80 FixitReceiver(SmallVectorImpl<FixItHint> &MergedFixits) 81 : MergedFixits(MergedFixits) { } 82 void insert(SourceLocation loc, StringRef text) override { 83 MergedFixits.push_back(FixItHint::CreateInsertion(loc, text)); 84 } 85 void replace(CharSourceRange range, StringRef text) override { 86 MergedFixits.push_back(FixItHint::CreateReplacement(range, text)); 87 } 88 }; 89 90 } 91 92 static void mergeFixits(ArrayRef<FixItHint> FixItHints, 93 const SourceManager &SM, const LangOptions &LangOpts, 94 SmallVectorImpl<FixItHint> &MergedFixits) { 95 edit::Commit commit(SM, LangOpts); 96 for (ArrayRef<FixItHint>::const_iterator 97 I = FixItHints.begin(), E = FixItHints.end(); I != E; ++I) { 98 const FixItHint &Hint = *I; 99 if (Hint.CodeToInsert.empty()) { 100 if (Hint.InsertFromRange.isValid()) 101 commit.insertFromRange(Hint.RemoveRange.getBegin(), 102 Hint.InsertFromRange, /*afterToken=*/false, 103 Hint.BeforePreviousInsertions); 104 else 105 commit.remove(Hint.RemoveRange); 106 } else { 107 if (Hint.RemoveRange.isTokenRange() || 108 Hint.RemoveRange.getBegin() != Hint.RemoveRange.getEnd()) 109 commit.replace(Hint.RemoveRange, Hint.CodeToInsert); 110 else 111 commit.insert(Hint.RemoveRange.getBegin(), Hint.CodeToInsert, 112 /*afterToken=*/false, Hint.BeforePreviousInsertions); 113 } 114 } 115 116 edit::EditedSource Editor(SM, LangOpts); 117 if (Editor.commit(commit)) { 118 FixitReceiver Rec(MergedFixits); 119 Editor.applyRewrites(Rec); 120 } 121 } 122 123 void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc, 124 DiagnosticsEngine::Level Level, 125 StringRef Message, 126 ArrayRef<CharSourceRange> Ranges, 127 ArrayRef<FixItHint> FixItHints, 128 const SourceManager *SM, 129 DiagOrStoredDiag D) { 130 assert(SM || Loc.isInvalid()); 131 132 beginDiagnostic(D, Level); 133 134 if (!Loc.isValid()) 135 // If we have no source location, just emit the diagnostic message. 136 emitDiagnosticMessage(Loc, PresumedLoc(), Level, Message, Ranges, SM, D); 137 else { 138 // Get the ranges into a local array we can hack on. 139 SmallVector<CharSourceRange, 20> MutableRanges(Ranges.begin(), 140 Ranges.end()); 141 142 SmallVector<FixItHint, 8> MergedFixits; 143 if (!FixItHints.empty()) { 144 mergeFixits(FixItHints, *SM, LangOpts, MergedFixits); 145 FixItHints = MergedFixits; 146 } 147 148 for (ArrayRef<FixItHint>::const_iterator I = FixItHints.begin(), 149 E = FixItHints.end(); 150 I != E; ++I) 151 if (I->RemoveRange.isValid()) 152 MutableRanges.push_back(I->RemoveRange); 153 154 SourceLocation UnexpandedLoc = Loc; 155 156 // Find the ultimate expansion location for the diagnostic. 157 Loc = SM->getFileLoc(Loc); 158 159 PresumedLoc PLoc = SM->getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc); 160 161 // First, if this diagnostic is not in the main file, print out the 162 // "included from" lines. 163 emitIncludeStack(Loc, PLoc, Level, *SM); 164 165 // Next, emit the actual diagnostic message and caret. 166 emitDiagnosticMessage(Loc, PLoc, Level, Message, Ranges, SM, D); 167 emitCaret(Loc, Level, MutableRanges, FixItHints, *SM); 168 169 // If this location is within a macro, walk from UnexpandedLoc up to Loc 170 // and produce a macro backtrace. 171 if (UnexpandedLoc.isValid() && UnexpandedLoc.isMacroID()) { 172 emitMacroExpansions(UnexpandedLoc, Level, MutableRanges, FixItHints, *SM); 173 } 174 } 175 176 LastLoc = Loc; 177 LastLevel = Level; 178 179 endDiagnostic(D, Level); 180 } 181 182 183 void DiagnosticRenderer::emitStoredDiagnostic(StoredDiagnostic &Diag) { 184 emitDiagnostic(Diag.getLocation(), Diag.getLevel(), Diag.getMessage(), 185 Diag.getRanges(), Diag.getFixIts(), 186 Diag.getLocation().isValid() ? &Diag.getLocation().getManager() 187 : nullptr, 188 &Diag); 189 } 190 191 void DiagnosticRenderer::emitBasicNote(StringRef Message) { 192 emitDiagnosticMessage( 193 SourceLocation(), PresumedLoc(), DiagnosticsEngine::Note, Message, 194 None, nullptr, DiagOrStoredDiag()); 195 } 196 197 /// \brief Prints an include stack when appropriate for a particular 198 /// diagnostic level and location. 199 /// 200 /// This routine handles all the logic of suppressing particular include 201 /// stacks (such as those for notes) and duplicate include stacks when 202 /// repeated warnings occur within the same file. It also handles the logic 203 /// of customizing the formatting and display of the include stack. 204 /// 205 /// \param Loc The diagnostic location. 206 /// \param PLoc The presumed location of the diagnostic location. 207 /// \param Level The diagnostic level of the message this stack pertains to. 208 void DiagnosticRenderer::emitIncludeStack(SourceLocation Loc, 209 PresumedLoc PLoc, 210 DiagnosticsEngine::Level Level, 211 const SourceManager &SM) { 212 SourceLocation IncludeLoc = PLoc.getIncludeLoc(); 213 214 // Skip redundant include stacks altogether. 215 if (LastIncludeLoc == IncludeLoc) 216 return; 217 218 LastIncludeLoc = IncludeLoc; 219 220 if (!DiagOpts->ShowNoteIncludeStack && Level == DiagnosticsEngine::Note) 221 return; 222 223 if (IncludeLoc.isValid()) 224 emitIncludeStackRecursively(IncludeLoc, SM); 225 else { 226 emitModuleBuildStack(SM); 227 emitImportStack(Loc, SM); 228 } 229 } 230 231 /// \brief Helper to recursivly walk up the include stack and print each layer 232 /// on the way back down. 233 void DiagnosticRenderer::emitIncludeStackRecursively(SourceLocation Loc, 234 const SourceManager &SM) { 235 if (Loc.isInvalid()) { 236 emitModuleBuildStack(SM); 237 return; 238 } 239 240 PresumedLoc PLoc = SM.getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc); 241 if (PLoc.isInvalid()) 242 return; 243 244 // If this source location was imported from a module, print the module 245 // import stack rather than the 246 // FIXME: We want submodule granularity here. 247 std::pair<SourceLocation, StringRef> Imported = SM.getModuleImportLoc(Loc); 248 if (!Imported.second.empty()) { 249 // This location was imported by a module. Emit the module import stack. 250 emitImportStackRecursively(Imported.first, Imported.second, SM); 251 return; 252 } 253 254 // Emit the other include frames first. 255 emitIncludeStackRecursively(PLoc.getIncludeLoc(), SM); 256 257 // Emit the inclusion text/note. 258 emitIncludeLocation(Loc, PLoc, SM); 259 } 260 261 /// \brief Emit the module import stack associated with the current location. 262 void DiagnosticRenderer::emitImportStack(SourceLocation Loc, 263 const SourceManager &SM) { 264 if (Loc.isInvalid()) { 265 emitModuleBuildStack(SM); 266 return; 267 } 268 269 std::pair<SourceLocation, StringRef> NextImportLoc 270 = SM.getModuleImportLoc(Loc); 271 emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second, SM); 272 } 273 274 /// \brief Helper to recursivly walk up the import stack and print each layer 275 /// on the way back down. 276 void DiagnosticRenderer::emitImportStackRecursively(SourceLocation Loc, 277 StringRef ModuleName, 278 const SourceManager &SM) { 279 if (ModuleName.empty()) { 280 return; 281 } 282 283 PresumedLoc PLoc = SM.getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc); 284 285 // Emit the other import frames first. 286 std::pair<SourceLocation, StringRef> NextImportLoc 287 = SM.getModuleImportLoc(Loc); 288 emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second, SM); 289 290 // Emit the inclusion text/note. 291 emitImportLocation(Loc, PLoc, ModuleName, SM); 292 } 293 294 /// \brief Emit the module build stack, for cases where a module is (re-)built 295 /// on demand. 296 void DiagnosticRenderer::emitModuleBuildStack(const SourceManager &SM) { 297 ModuleBuildStack Stack = SM.getModuleBuildStack(); 298 for (unsigned I = 0, N = Stack.size(); I != N; ++I) { 299 const SourceManager &CurSM = Stack[I].second.getManager(); 300 SourceLocation CurLoc = Stack[I].second; 301 emitBuildingModuleLocation(CurLoc, 302 CurSM.getPresumedLoc(CurLoc, 303 DiagOpts->ShowPresumedLoc), 304 Stack[I].first, 305 CurSM); 306 } 307 } 308 309 /// A recursive function to trace all possible backtrace locations 310 /// to match the \p CaretLocFileID. 311 static SourceLocation 312 retrieveMacroLocation(SourceLocation Loc, FileID MacroFileID, 313 FileID CaretFileID, 314 const SmallVectorImpl<FileID> &CommonArgExpansions, 315 bool IsBegin, const SourceManager *SM) { 316 assert(SM->getFileID(Loc) == MacroFileID); 317 if (MacroFileID == CaretFileID) 318 return Loc; 319 if (!Loc.isMacroID()) 320 return SourceLocation(); 321 322 SourceLocation MacroLocation, MacroArgLocation; 323 324 if (SM->isMacroArgExpansion(Loc)) { 325 // Only look at the immediate spelling location of this macro argument if 326 // the other location in the source range is also present in that expansion. 327 if (std::binary_search(CommonArgExpansions.begin(), 328 CommonArgExpansions.end(), MacroFileID)) 329 MacroLocation = SM->getImmediateSpellingLoc(Loc); 330 MacroArgLocation = IsBegin ? SM->getImmediateExpansionRange(Loc).first 331 : SM->getImmediateExpansionRange(Loc).second; 332 } else { 333 MacroLocation = IsBegin ? SM->getImmediateExpansionRange(Loc).first 334 : SM->getImmediateExpansionRange(Loc).second; 335 MacroArgLocation = SM->getImmediateSpellingLoc(Loc); 336 } 337 338 if (MacroLocation.isValid()) { 339 MacroFileID = SM->getFileID(MacroLocation); 340 MacroLocation = 341 retrieveMacroLocation(MacroLocation, MacroFileID, CaretFileID, 342 CommonArgExpansions, IsBegin, SM); 343 if (MacroLocation.isValid()) 344 return MacroLocation; 345 } 346 347 MacroFileID = SM->getFileID(MacroArgLocation); 348 return retrieveMacroLocation(MacroArgLocation, MacroFileID, CaretFileID, 349 CommonArgExpansions, IsBegin, SM); 350 } 351 352 /// Walk up the chain of macro expansions and collect the FileIDs identifying the 353 /// expansions. 354 static void getMacroArgExpansionFileIDs(SourceLocation Loc, 355 SmallVectorImpl<FileID> &IDs, 356 bool IsBegin, const SourceManager *SM) { 357 while (Loc.isMacroID()) { 358 if (SM->isMacroArgExpansion(Loc)) { 359 IDs.push_back(SM->getFileID(Loc)); 360 Loc = SM->getImmediateSpellingLoc(Loc); 361 } else { 362 auto ExpRange = SM->getImmediateExpansionRange(Loc); 363 Loc = IsBegin ? ExpRange.first : ExpRange.second; 364 } 365 } 366 } 367 368 /// Collect the expansions of the begin and end locations and compute the set 369 /// intersection. Produces a sorted vector of FileIDs in CommonArgExpansions. 370 static void computeCommonMacroArgExpansionFileIDs( 371 SourceLocation Begin, SourceLocation End, const SourceManager *SM, 372 SmallVectorImpl<FileID> &CommonArgExpansions) { 373 SmallVector<FileID, 4> BeginArgExpansions; 374 SmallVector<FileID, 4> EndArgExpansions; 375 getMacroArgExpansionFileIDs(Begin, BeginArgExpansions, /*IsBegin=*/true, SM); 376 getMacroArgExpansionFileIDs(End, EndArgExpansions, /*IsBegin=*/false, SM); 377 std::sort(BeginArgExpansions.begin(), BeginArgExpansions.end()); 378 std::sort(EndArgExpansions.begin(), EndArgExpansions.end()); 379 std::set_intersection(BeginArgExpansions.begin(), BeginArgExpansions.end(), 380 EndArgExpansions.begin(), EndArgExpansions.end(), 381 std::back_inserter(CommonArgExpansions)); 382 } 383 384 // Helper function to fix up source ranges. It takes in an array of ranges, 385 // and outputs an array of ranges where we want to draw the range highlighting 386 // around the location specified by CaretLoc. 387 // 388 // To find locations which correspond to the caret, we crawl the macro caller 389 // chain for the beginning and end of each range. If the caret location 390 // is in a macro expansion, we search each chain for a location 391 // in the same expansion as the caret; otherwise, we crawl to the top of 392 // each chain. Two locations are part of the same macro expansion 393 // iff the FileID is the same. 394 static void mapDiagnosticRanges( 395 SourceLocation CaretLoc, 396 ArrayRef<CharSourceRange> Ranges, 397 SmallVectorImpl<CharSourceRange> &SpellingRanges, 398 const SourceManager *SM) { 399 FileID CaretLocFileID = SM->getFileID(CaretLoc); 400 401 for (auto I = Ranges.begin(), E = Ranges.end(); I != E; ++I) { 402 if (I->isInvalid()) continue; 403 404 SourceLocation Begin = I->getBegin(), End = I->getEnd(); 405 bool IsTokenRange = I->isTokenRange(); 406 407 FileID BeginFileID = SM->getFileID(Begin); 408 FileID EndFileID = SM->getFileID(End); 409 410 // Find the common parent for the beginning and end of the range. 411 412 // First, crawl the expansion chain for the beginning of the range. 413 llvm::SmallDenseMap<FileID, SourceLocation> BeginLocsMap; 414 while (Begin.isMacroID() && BeginFileID != EndFileID) { 415 BeginLocsMap[BeginFileID] = Begin; 416 Begin = SM->getImmediateExpansionRange(Begin).first; 417 BeginFileID = SM->getFileID(Begin); 418 } 419 420 // Then, crawl the expansion chain for the end of the range. 421 if (BeginFileID != EndFileID) { 422 while (End.isMacroID() && !BeginLocsMap.count(EndFileID)) { 423 End = SM->getImmediateExpansionRange(End).second; 424 EndFileID = SM->getFileID(End); 425 } 426 if (End.isMacroID()) { 427 Begin = BeginLocsMap[EndFileID]; 428 BeginFileID = EndFileID; 429 } 430 } 431 432 // Do the backtracking. 433 SmallVector<FileID, 4> CommonArgExpansions; 434 computeCommonMacroArgExpansionFileIDs(Begin, End, SM, CommonArgExpansions); 435 Begin = retrieveMacroLocation(Begin, BeginFileID, CaretLocFileID, 436 CommonArgExpansions, /*IsBegin=*/true, SM); 437 End = retrieveMacroLocation(End, BeginFileID, CaretLocFileID, 438 CommonArgExpansions, /*IsBegin=*/false, SM); 439 if (Begin.isInvalid() || End.isInvalid()) continue; 440 441 // Return the spelling location of the beginning and end of the range. 442 Begin = SM->getSpellingLoc(Begin); 443 End = SM->getSpellingLoc(End); 444 445 SpellingRanges.push_back(CharSourceRange(SourceRange(Begin, End), 446 IsTokenRange)); 447 } 448 } 449 450 void DiagnosticRenderer::emitCaret(SourceLocation Loc, 451 DiagnosticsEngine::Level Level, 452 ArrayRef<CharSourceRange> Ranges, 453 ArrayRef<FixItHint> Hints, 454 const SourceManager &SM) { 455 SmallVector<CharSourceRange, 4> SpellingRanges; 456 mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM); 457 emitCodeContext(Loc, Level, SpellingRanges, Hints, SM); 458 } 459 460 /// \brief A helper function for emitMacroExpansion to print the 461 /// macro expansion message 462 void DiagnosticRenderer::emitSingleMacroExpansion( 463 SourceLocation Loc, 464 DiagnosticsEngine::Level Level, 465 ArrayRef<CharSourceRange> Ranges, 466 const SourceManager &SM) { 467 // 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. 490 static 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. 503 static 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. 518 static 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. 561 void 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 625 DiagnosticNoteRenderer::~DiagnosticNoteRenderer() {} 626 627 void 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 638 void 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 653 void 654 DiagnosticNoteRenderer::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