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