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/SourceManager.h" 13 #include "clang/Edit/Commit.h" 14 #include "clang/Edit/EditedSource.h" 15 #include "clang/Edit/EditsReceiver.h" 16 #include "clang/Lex/Lexer.h" 17 #include "llvm/ADT/SmallSet.h" 18 #include "llvm/ADT/SmallString.h" 19 #include "llvm/Support/ErrorHandling.h" 20 #include "llvm/Support/raw_ostream.h" 21 #include <algorithm> 22 using namespace clang; 23 24 DiagnosticRenderer::DiagnosticRenderer(const LangOptions &LangOpts, 25 DiagnosticOptions *DiagOpts) 26 : LangOpts(LangOpts), DiagOpts(DiagOpts), LastLevel() {} 27 28 DiagnosticRenderer::~DiagnosticRenderer() {} 29 30 namespace { 31 32 class FixitReceiver : public edit::EditsReceiver { 33 SmallVectorImpl<FixItHint> &MergedFixits; 34 35 public: 36 FixitReceiver(SmallVectorImpl<FixItHint> &MergedFixits) 37 : MergedFixits(MergedFixits) { } 38 void insert(SourceLocation loc, StringRef text) override { 39 MergedFixits.push_back(FixItHint::CreateInsertion(loc, text)); 40 } 41 void replace(CharSourceRange range, StringRef text) override { 42 MergedFixits.push_back(FixItHint::CreateReplacement(range, text)); 43 } 44 }; 45 46 } 47 48 static void mergeFixits(ArrayRef<FixItHint> FixItHints, 49 const SourceManager &SM, const LangOptions &LangOpts, 50 SmallVectorImpl<FixItHint> &MergedFixits) { 51 edit::Commit commit(SM, LangOpts); 52 for (ArrayRef<FixItHint>::const_iterator 53 I = FixItHints.begin(), E = FixItHints.end(); I != E; ++I) { 54 const FixItHint &Hint = *I; 55 if (Hint.CodeToInsert.empty()) { 56 if (Hint.InsertFromRange.isValid()) 57 commit.insertFromRange(Hint.RemoveRange.getBegin(), 58 Hint.InsertFromRange, /*afterToken=*/false, 59 Hint.BeforePreviousInsertions); 60 else 61 commit.remove(Hint.RemoveRange); 62 } else { 63 if (Hint.RemoveRange.isTokenRange() || 64 Hint.RemoveRange.getBegin() != Hint.RemoveRange.getEnd()) 65 commit.replace(Hint.RemoveRange, Hint.CodeToInsert); 66 else 67 commit.insert(Hint.RemoveRange.getBegin(), Hint.CodeToInsert, 68 /*afterToken=*/false, Hint.BeforePreviousInsertions); 69 } 70 } 71 72 edit::EditedSource Editor(SM, LangOpts); 73 if (Editor.commit(commit)) { 74 FixitReceiver Rec(MergedFixits); 75 Editor.applyRewrites(Rec); 76 } 77 } 78 79 void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc, 80 DiagnosticsEngine::Level Level, 81 StringRef Message, 82 ArrayRef<CharSourceRange> Ranges, 83 ArrayRef<FixItHint> FixItHints, 84 const SourceManager *SM, 85 DiagOrStoredDiag D) { 86 assert(SM || Loc.isInvalid()); 87 88 beginDiagnostic(D, Level); 89 90 if (!Loc.isValid()) 91 // If we have no source location, just emit the diagnostic message. 92 emitDiagnosticMessage(Loc, PresumedLoc(), Level, Message, Ranges, SM, D); 93 else { 94 // Get the ranges into a local array we can hack on. 95 SmallVector<CharSourceRange, 20> MutableRanges(Ranges.begin(), 96 Ranges.end()); 97 98 SmallVector<FixItHint, 8> MergedFixits; 99 if (!FixItHints.empty()) { 100 mergeFixits(FixItHints, *SM, LangOpts, MergedFixits); 101 FixItHints = MergedFixits; 102 } 103 104 for (ArrayRef<FixItHint>::const_iterator I = FixItHints.begin(), 105 E = FixItHints.end(); 106 I != E; ++I) 107 if (I->RemoveRange.isValid()) 108 MutableRanges.push_back(I->RemoveRange); 109 110 SourceLocation UnexpandedLoc = Loc; 111 112 // Find the ultimate expansion location for the diagnostic. 113 Loc = SM->getFileLoc(Loc); 114 115 PresumedLoc PLoc = SM->getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc); 116 117 // First, if this diagnostic is not in the main file, print out the 118 // "included from" lines. 119 emitIncludeStack(Loc, PLoc, Level, *SM); 120 121 // Next, emit the actual diagnostic message and caret. 122 emitDiagnosticMessage(Loc, PLoc, Level, Message, Ranges, SM, D); 123 emitCaret(Loc, Level, MutableRanges, FixItHints, *SM); 124 125 // If this location is within a macro, walk from UnexpandedLoc up to Loc 126 // and produce a macro backtrace. 127 if (UnexpandedLoc.isValid() && UnexpandedLoc.isMacroID()) { 128 emitMacroExpansions(UnexpandedLoc, Level, MutableRanges, FixItHints, *SM); 129 } 130 } 131 132 LastLoc = Loc; 133 LastLevel = Level; 134 135 endDiagnostic(D, Level); 136 } 137 138 139 void DiagnosticRenderer::emitStoredDiagnostic(StoredDiagnostic &Diag) { 140 emitDiagnostic(Diag.getLocation(), Diag.getLevel(), Diag.getMessage(), 141 Diag.getRanges(), Diag.getFixIts(), 142 Diag.getLocation().isValid() ? &Diag.getLocation().getManager() 143 : nullptr, 144 &Diag); 145 } 146 147 void DiagnosticRenderer::emitBasicNote(StringRef Message) { 148 emitDiagnosticMessage( 149 SourceLocation(), PresumedLoc(), DiagnosticsEngine::Note, Message, 150 None, nullptr, DiagOrStoredDiag()); 151 } 152 153 /// \brief Prints an include stack when appropriate for a particular 154 /// diagnostic level and location. 155 /// 156 /// This routine handles all the logic of suppressing particular include 157 /// stacks (such as those for notes) and duplicate include stacks when 158 /// repeated warnings occur within the same file. It also handles the logic 159 /// of customizing the formatting and display of the include stack. 160 /// 161 /// \param Loc The diagnostic location. 162 /// \param PLoc The presumed location of the diagnostic location. 163 /// \param Level The diagnostic level of the message this stack pertains to. 164 void DiagnosticRenderer::emitIncludeStack(SourceLocation Loc, 165 PresumedLoc PLoc, 166 DiagnosticsEngine::Level Level, 167 const SourceManager &SM) { 168 SourceLocation IncludeLoc = 169 PLoc.isInvalid() ? SourceLocation() : PLoc.getIncludeLoc(); 170 171 // Skip redundant include stacks altogether. 172 if (LastIncludeLoc == IncludeLoc) 173 return; 174 175 LastIncludeLoc = IncludeLoc; 176 177 if (!DiagOpts->ShowNoteIncludeStack && Level == DiagnosticsEngine::Note) 178 return; 179 180 if (IncludeLoc.isValid()) 181 emitIncludeStackRecursively(IncludeLoc, SM); 182 else { 183 emitModuleBuildStack(SM); 184 emitImportStack(Loc, SM); 185 } 186 } 187 188 /// \brief Helper to recursivly walk up the include stack and print each layer 189 /// on the way back down. 190 void DiagnosticRenderer::emitIncludeStackRecursively(SourceLocation Loc, 191 const SourceManager &SM) { 192 if (Loc.isInvalid()) { 193 emitModuleBuildStack(SM); 194 return; 195 } 196 197 PresumedLoc PLoc = SM.getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc); 198 if (PLoc.isInvalid()) 199 return; 200 201 // If this source location was imported from a module, print the module 202 // import stack rather than the 203 // FIXME: We want submodule granularity here. 204 std::pair<SourceLocation, StringRef> Imported = SM.getModuleImportLoc(Loc); 205 if (!Imported.second.empty()) { 206 // This location was imported by a module. Emit the module import stack. 207 emitImportStackRecursively(Imported.first, Imported.second, SM); 208 return; 209 } 210 211 // Emit the other include frames first. 212 emitIncludeStackRecursively(PLoc.getIncludeLoc(), SM); 213 214 // Emit the inclusion text/note. 215 emitIncludeLocation(Loc, PLoc, SM); 216 } 217 218 /// \brief Emit the module import stack associated with the current location. 219 void DiagnosticRenderer::emitImportStack(SourceLocation Loc, 220 const SourceManager &SM) { 221 if (Loc.isInvalid()) { 222 emitModuleBuildStack(SM); 223 return; 224 } 225 226 std::pair<SourceLocation, StringRef> NextImportLoc 227 = SM.getModuleImportLoc(Loc); 228 emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second, SM); 229 } 230 231 /// \brief Helper to recursivly walk up the import stack and print each layer 232 /// on the way back down. 233 void DiagnosticRenderer::emitImportStackRecursively(SourceLocation Loc, 234 StringRef ModuleName, 235 const SourceManager &SM) { 236 if (ModuleName.empty()) { 237 return; 238 } 239 240 PresumedLoc PLoc = SM.getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc); 241 242 // Emit the other import frames first. 243 std::pair<SourceLocation, StringRef> NextImportLoc 244 = SM.getModuleImportLoc(Loc); 245 emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second, SM); 246 247 // Emit the inclusion text/note. 248 emitImportLocation(Loc, PLoc, ModuleName, SM); 249 } 250 251 /// \brief Emit the module build stack, for cases where a module is (re-)built 252 /// on demand. 253 void DiagnosticRenderer::emitModuleBuildStack(const SourceManager &SM) { 254 ModuleBuildStack Stack = SM.getModuleBuildStack(); 255 for (unsigned I = 0, N = Stack.size(); I != N; ++I) { 256 const SourceManager &CurSM = Stack[I].second.getManager(); 257 SourceLocation CurLoc = Stack[I].second; 258 emitBuildingModuleLocation(CurLoc, 259 CurSM.getPresumedLoc(CurLoc, 260 DiagOpts->ShowPresumedLoc), 261 Stack[I].first, 262 CurSM); 263 } 264 } 265 266 /// A recursive function to trace all possible backtrace locations 267 /// to match the \p CaretLocFileID. 268 static SourceLocation 269 retrieveMacroLocation(SourceLocation Loc, FileID MacroFileID, 270 FileID CaretFileID, 271 const SmallVectorImpl<FileID> &CommonArgExpansions, 272 bool IsBegin, const SourceManager *SM) { 273 assert(SM->getFileID(Loc) == MacroFileID); 274 if (MacroFileID == CaretFileID) 275 return Loc; 276 if (!Loc.isMacroID()) 277 return SourceLocation(); 278 279 SourceLocation MacroLocation, MacroArgLocation; 280 281 if (SM->isMacroArgExpansion(Loc)) { 282 // Only look at the immediate spelling location of this macro argument if 283 // the other location in the source range is also present in that expansion. 284 if (std::binary_search(CommonArgExpansions.begin(), 285 CommonArgExpansions.end(), MacroFileID)) 286 MacroLocation = SM->getImmediateSpellingLoc(Loc); 287 MacroArgLocation = IsBegin ? SM->getImmediateExpansionRange(Loc).first 288 : SM->getImmediateExpansionRange(Loc).second; 289 } else { 290 MacroLocation = IsBegin ? SM->getImmediateExpansionRange(Loc).first 291 : SM->getImmediateExpansionRange(Loc).second; 292 MacroArgLocation = SM->getImmediateSpellingLoc(Loc); 293 } 294 295 if (MacroLocation.isValid()) { 296 MacroFileID = SM->getFileID(MacroLocation); 297 MacroLocation = 298 retrieveMacroLocation(MacroLocation, MacroFileID, CaretFileID, 299 CommonArgExpansions, IsBegin, SM); 300 if (MacroLocation.isValid()) 301 return MacroLocation; 302 } 303 304 MacroFileID = SM->getFileID(MacroArgLocation); 305 return retrieveMacroLocation(MacroArgLocation, MacroFileID, CaretFileID, 306 CommonArgExpansions, IsBegin, SM); 307 } 308 309 /// Walk up the chain of macro expansions and collect the FileIDs identifying the 310 /// expansions. 311 static void getMacroArgExpansionFileIDs(SourceLocation Loc, 312 SmallVectorImpl<FileID> &IDs, 313 bool IsBegin, const SourceManager *SM) { 314 while (Loc.isMacroID()) { 315 if (SM->isMacroArgExpansion(Loc)) { 316 IDs.push_back(SM->getFileID(Loc)); 317 Loc = SM->getImmediateSpellingLoc(Loc); 318 } else { 319 auto ExpRange = SM->getImmediateExpansionRange(Loc); 320 Loc = IsBegin ? ExpRange.first : ExpRange.second; 321 } 322 } 323 } 324 325 /// Collect the expansions of the begin and end locations and compute the set 326 /// intersection. Produces a sorted vector of FileIDs in CommonArgExpansions. 327 static void computeCommonMacroArgExpansionFileIDs( 328 SourceLocation Begin, SourceLocation End, const SourceManager *SM, 329 SmallVectorImpl<FileID> &CommonArgExpansions) { 330 SmallVector<FileID, 4> BeginArgExpansions; 331 SmallVector<FileID, 4> EndArgExpansions; 332 getMacroArgExpansionFileIDs(Begin, BeginArgExpansions, /*IsBegin=*/true, SM); 333 getMacroArgExpansionFileIDs(End, EndArgExpansions, /*IsBegin=*/false, SM); 334 std::sort(BeginArgExpansions.begin(), BeginArgExpansions.end()); 335 std::sort(EndArgExpansions.begin(), EndArgExpansions.end()); 336 std::set_intersection(BeginArgExpansions.begin(), BeginArgExpansions.end(), 337 EndArgExpansions.begin(), EndArgExpansions.end(), 338 std::back_inserter(CommonArgExpansions)); 339 } 340 341 // Helper function to fix up source ranges. It takes in an array of ranges, 342 // and outputs an array of ranges where we want to draw the range highlighting 343 // around the location specified by CaretLoc. 344 // 345 // To find locations which correspond to the caret, we crawl the macro caller 346 // chain for the beginning and end of each range. If the caret location 347 // is in a macro expansion, we search each chain for a location 348 // in the same expansion as the caret; otherwise, we crawl to the top of 349 // each chain. Two locations are part of the same macro expansion 350 // iff the FileID is the same. 351 static void mapDiagnosticRanges( 352 SourceLocation CaretLoc, 353 ArrayRef<CharSourceRange> Ranges, 354 SmallVectorImpl<CharSourceRange> &SpellingRanges, 355 const SourceManager *SM) { 356 FileID CaretLocFileID = SM->getFileID(CaretLoc); 357 358 for (auto I = Ranges.begin(), E = Ranges.end(); I != E; ++I) { 359 if (I->isInvalid()) continue; 360 361 SourceLocation Begin = I->getBegin(), End = I->getEnd(); 362 bool IsTokenRange = I->isTokenRange(); 363 364 FileID BeginFileID = SM->getFileID(Begin); 365 FileID EndFileID = SM->getFileID(End); 366 367 // Find the common parent for the beginning and end of the range. 368 369 // First, crawl the expansion chain for the beginning of the range. 370 llvm::SmallDenseMap<FileID, SourceLocation> BeginLocsMap; 371 while (Begin.isMacroID() && BeginFileID != EndFileID) { 372 BeginLocsMap[BeginFileID] = Begin; 373 Begin = SM->getImmediateExpansionRange(Begin).first; 374 BeginFileID = SM->getFileID(Begin); 375 } 376 377 // Then, crawl the expansion chain for the end of the range. 378 if (BeginFileID != EndFileID) { 379 while (End.isMacroID() && !BeginLocsMap.count(EndFileID)) { 380 End = SM->getImmediateExpansionRange(End).second; 381 EndFileID = SM->getFileID(End); 382 } 383 if (End.isMacroID()) { 384 Begin = BeginLocsMap[EndFileID]; 385 BeginFileID = EndFileID; 386 } 387 } 388 389 // Do the backtracking. 390 SmallVector<FileID, 4> CommonArgExpansions; 391 computeCommonMacroArgExpansionFileIDs(Begin, End, SM, CommonArgExpansions); 392 Begin = retrieveMacroLocation(Begin, BeginFileID, CaretLocFileID, 393 CommonArgExpansions, /*IsBegin=*/true, SM); 394 End = retrieveMacroLocation(End, BeginFileID, CaretLocFileID, 395 CommonArgExpansions, /*IsBegin=*/false, SM); 396 if (Begin.isInvalid() || End.isInvalid()) continue; 397 398 // Return the spelling location of the beginning and end of the range. 399 Begin = SM->getSpellingLoc(Begin); 400 End = SM->getSpellingLoc(End); 401 402 SpellingRanges.push_back(CharSourceRange(SourceRange(Begin, End), 403 IsTokenRange)); 404 } 405 } 406 407 void DiagnosticRenderer::emitCaret(SourceLocation Loc, 408 DiagnosticsEngine::Level Level, 409 ArrayRef<CharSourceRange> Ranges, 410 ArrayRef<FixItHint> Hints, 411 const SourceManager &SM) { 412 SmallVector<CharSourceRange, 4> SpellingRanges; 413 mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM); 414 emitCodeContext(Loc, Level, SpellingRanges, Hints, SM); 415 } 416 417 /// \brief A helper function for emitMacroExpansion to print the 418 /// macro expansion message 419 void DiagnosticRenderer::emitSingleMacroExpansion( 420 SourceLocation Loc, 421 DiagnosticsEngine::Level Level, 422 ArrayRef<CharSourceRange> Ranges, 423 const SourceManager &SM) { 424 // Find the spelling location for the macro definition. We must use the 425 // spelling location here to avoid emitting a macro backtrace for the note. 426 SourceLocation SpellingLoc = SM.getSpellingLoc(Loc); 427 428 // Map the ranges into the FileID of the diagnostic location. 429 SmallVector<CharSourceRange, 4> SpellingRanges; 430 mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM); 431 432 SmallString<100> MessageStorage; 433 llvm::raw_svector_ostream Message(MessageStorage); 434 StringRef MacroName = 435 Lexer::getImmediateMacroNameForDiagnostics(Loc, SM, LangOpts); 436 if (MacroName.empty()) 437 Message << "expanded from here"; 438 else 439 Message << "expanded from macro '" << MacroName << "'"; 440 441 emitDiagnostic(SpellingLoc, DiagnosticsEngine::Note, Message.str(), 442 SpellingRanges, None, &SM); 443 } 444 445 /// Check that the macro argument location of Loc starts with ArgumentLoc. 446 /// The starting location of the macro expansions is used to differeniate 447 /// different macro expansions. 448 static bool checkLocForMacroArgExpansion(SourceLocation Loc, 449 const SourceManager &SM, 450 SourceLocation ArgumentLoc) { 451 SourceLocation MacroLoc; 452 if (SM.isMacroArgExpansion(Loc, &MacroLoc)) { 453 if (ArgumentLoc == MacroLoc) return true; 454 } 455 456 return false; 457 } 458 459 /// Check if all the locations in the range have the same macro argument 460 /// expansion, and that that expansion starts with ArgumentLoc. 461 static bool checkRangeForMacroArgExpansion(CharSourceRange Range, 462 const SourceManager &SM, 463 SourceLocation ArgumentLoc) { 464 SourceLocation BegLoc = Range.getBegin(), EndLoc = Range.getEnd(); 465 while (BegLoc != EndLoc) { 466 if (!checkLocForMacroArgExpansion(BegLoc, SM, ArgumentLoc)) 467 return false; 468 BegLoc.getLocWithOffset(1); 469 } 470 471 return checkLocForMacroArgExpansion(BegLoc, SM, ArgumentLoc); 472 } 473 474 /// A helper function to check if the current ranges are all inside the same 475 /// macro argument expansion as Loc. 476 static bool checkRangesForMacroArgExpansion(SourceLocation Loc, 477 ArrayRef<CharSourceRange> Ranges, 478 const SourceManager &SM) { 479 assert(Loc.isMacroID() && "Must be a macro expansion!"); 480 481 SmallVector<CharSourceRange, 4> SpellingRanges; 482 mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM); 483 484 /// Count all valid ranges. 485 unsigned ValidCount = 0; 486 for (auto I : Ranges) 487 if (I.isValid()) ValidCount++; 488 489 if (ValidCount > SpellingRanges.size()) 490 return false; 491 492 /// To store the source location of the argument location. 493 SourceLocation ArgumentLoc; 494 495 /// Set the ArgumentLoc to the beginning location of the expansion of Loc 496 /// so to check if the ranges expands to the same beginning location. 497 if (!SM.isMacroArgExpansion(Loc,&ArgumentLoc)) 498 return false; 499 500 for (auto I = SpellingRanges.begin(), E = SpellingRanges.end(); I != E; ++I) { 501 if (!checkRangeForMacroArgExpansion(*I, SM, ArgumentLoc)) 502 return false; 503 } 504 505 return true; 506 } 507 508 /// \brief Recursively emit notes for each macro expansion and caret 509 /// diagnostics where appropriate. 510 /// 511 /// Walks up the macro expansion stack printing expansion notes, the code 512 /// snippet, caret, underlines and FixItHint display as appropriate at each 513 /// level. 514 /// 515 /// \param Loc The location for this caret. 516 /// \param Level The diagnostic level currently being emitted. 517 /// \param Ranges The underlined ranges for this code snippet. 518 /// \param Hints The FixIt hints active for this diagnostic. 519 void DiagnosticRenderer::emitMacroExpansions(SourceLocation Loc, 520 DiagnosticsEngine::Level Level, 521 ArrayRef<CharSourceRange> Ranges, 522 ArrayRef<FixItHint> Hints, 523 const SourceManager &SM) { 524 assert(Loc.isValid() && "must have a valid source location here"); 525 526 // Produce a stack of macro backtraces. 527 SmallVector<SourceLocation, 8> LocationStack; 528 unsigned IgnoredEnd = 0; 529 while (Loc.isMacroID()) { 530 // If this is the expansion of a macro argument, point the caret at the 531 // use of the argument in the definition of the macro, not the expansion. 532 if (SM.isMacroArgExpansion(Loc)) 533 LocationStack.push_back(SM.getImmediateExpansionRange(Loc).first); 534 else 535 LocationStack.push_back(Loc); 536 537 if (checkRangesForMacroArgExpansion(Loc, Ranges, SM)) 538 IgnoredEnd = LocationStack.size(); 539 540 Loc = SM.getImmediateMacroCallerLoc(Loc); 541 542 // Once the location no longer points into a macro, try stepping through 543 // the last found location. This sometimes produces additional useful 544 // backtraces. 545 if (Loc.isFileID()) 546 Loc = SM.getImmediateMacroCallerLoc(LocationStack.back()); 547 assert(Loc.isValid() && "must have a valid source location here"); 548 } 549 550 LocationStack.erase(LocationStack.begin(), 551 LocationStack.begin() + IgnoredEnd); 552 553 unsigned MacroDepth = LocationStack.size(); 554 unsigned MacroLimit = DiagOpts->MacroBacktraceLimit; 555 if (MacroDepth <= MacroLimit || MacroLimit == 0) { 556 for (auto I = LocationStack.rbegin(), E = LocationStack.rend(); 557 I != E; ++I) 558 emitSingleMacroExpansion(*I, Level, Ranges, SM); 559 return; 560 } 561 562 unsigned MacroStartMessages = MacroLimit / 2; 563 unsigned MacroEndMessages = MacroLimit / 2 + MacroLimit % 2; 564 565 for (auto I = LocationStack.rbegin(), 566 E = LocationStack.rbegin() + MacroStartMessages; 567 I != E; ++I) 568 emitSingleMacroExpansion(*I, Level, Ranges, SM); 569 570 SmallString<200> MessageStorage; 571 llvm::raw_svector_ostream Message(MessageStorage); 572 Message << "(skipping " << (MacroDepth - MacroLimit) 573 << " expansions in backtrace; use -fmacro-backtrace-limit=0 to " 574 "see all)"; 575 emitBasicNote(Message.str()); 576 577 for (auto I = LocationStack.rend() - MacroEndMessages, 578 E = LocationStack.rend(); 579 I != E; ++I) 580 emitSingleMacroExpansion(*I, Level, Ranges, SM); 581 } 582 583 DiagnosticNoteRenderer::~DiagnosticNoteRenderer() {} 584 585 void DiagnosticNoteRenderer::emitIncludeLocation(SourceLocation Loc, 586 PresumedLoc PLoc, 587 const SourceManager &SM) { 588 // Generate a note indicating the include location. 589 SmallString<200> MessageStorage; 590 llvm::raw_svector_ostream Message(MessageStorage); 591 Message << "in file included from " << PLoc.getFilename() << ':' 592 << PLoc.getLine() << ":"; 593 emitNote(Loc, Message.str(), &SM); 594 } 595 596 void DiagnosticNoteRenderer::emitImportLocation(SourceLocation Loc, 597 PresumedLoc PLoc, 598 StringRef ModuleName, 599 const SourceManager &SM) { 600 // Generate a note indicating the include location. 601 SmallString<200> MessageStorage; 602 llvm::raw_svector_ostream Message(MessageStorage); 603 Message << "in module '" << ModuleName; 604 if (PLoc.isValid()) 605 Message << "' imported from " << PLoc.getFilename() << ':' 606 << PLoc.getLine(); 607 Message << ":"; 608 emitNote(Loc, Message.str(), &SM); 609 } 610 611 void 612 DiagnosticNoteRenderer::emitBuildingModuleLocation(SourceLocation Loc, 613 PresumedLoc PLoc, 614 StringRef ModuleName, 615 const SourceManager &SM) { 616 // Generate a note indicating the include location. 617 SmallString<200> MessageStorage; 618 llvm::raw_svector_ostream Message(MessageStorage); 619 if (PLoc.isValid()) 620 Message << "while building module '" << ModuleName << "' imported from " 621 << PLoc.getFilename() << ':' << PLoc.getLine() << ":"; 622 else 623 Message << "while building module '" << ModuleName << "':"; 624 emitNote(Loc, Message.str(), &SM); 625 } 626