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 = 171 PLoc.isInvalid() ? SourceLocation() : PLoc.getIncludeLoc(); 172 173 // Skip redundant include stacks altogether. 174 if (LastIncludeLoc == IncludeLoc) 175 return; 176 177 LastIncludeLoc = IncludeLoc; 178 179 if (!DiagOpts->ShowNoteIncludeStack && Level == DiagnosticsEngine::Note) 180 return; 181 182 if (IncludeLoc.isValid()) 183 emitIncludeStackRecursively(IncludeLoc, SM); 184 else { 185 emitModuleBuildStack(SM); 186 emitImportStack(Loc, SM); 187 } 188 } 189 190 /// \brief Helper to recursivly walk up the include stack and print each layer 191 /// on the way back down. 192 void DiagnosticRenderer::emitIncludeStackRecursively(SourceLocation Loc, 193 const SourceManager &SM) { 194 if (Loc.isInvalid()) { 195 emitModuleBuildStack(SM); 196 return; 197 } 198 199 PresumedLoc PLoc = SM.getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc); 200 if (PLoc.isInvalid()) 201 return; 202 203 // If this source location was imported from a module, print the module 204 // import stack rather than the 205 // FIXME: We want submodule granularity here. 206 std::pair<SourceLocation, StringRef> Imported = SM.getModuleImportLoc(Loc); 207 if (!Imported.second.empty()) { 208 // This location was imported by a module. Emit the module import stack. 209 emitImportStackRecursively(Imported.first, Imported.second, SM); 210 return; 211 } 212 213 // Emit the other include frames first. 214 emitIncludeStackRecursively(PLoc.getIncludeLoc(), SM); 215 216 // Emit the inclusion text/note. 217 emitIncludeLocation(Loc, PLoc, SM); 218 } 219 220 /// \brief Emit the module import stack associated with the current location. 221 void DiagnosticRenderer::emitImportStack(SourceLocation Loc, 222 const SourceManager &SM) { 223 if (Loc.isInvalid()) { 224 emitModuleBuildStack(SM); 225 return; 226 } 227 228 std::pair<SourceLocation, StringRef> NextImportLoc 229 = SM.getModuleImportLoc(Loc); 230 emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second, SM); 231 } 232 233 /// \brief Helper to recursivly walk up the import stack and print each layer 234 /// on the way back down. 235 void DiagnosticRenderer::emitImportStackRecursively(SourceLocation Loc, 236 StringRef ModuleName, 237 const SourceManager &SM) { 238 if (ModuleName.empty()) { 239 return; 240 } 241 242 PresumedLoc PLoc = SM.getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc); 243 244 // Emit the other import frames first. 245 std::pair<SourceLocation, StringRef> NextImportLoc 246 = SM.getModuleImportLoc(Loc); 247 emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second, SM); 248 249 // Emit the inclusion text/note. 250 emitImportLocation(Loc, PLoc, ModuleName, SM); 251 } 252 253 /// \brief Emit the module build stack, for cases where a module is (re-)built 254 /// on demand. 255 void DiagnosticRenderer::emitModuleBuildStack(const SourceManager &SM) { 256 ModuleBuildStack Stack = SM.getModuleBuildStack(); 257 for (unsigned I = 0, N = Stack.size(); I != N; ++I) { 258 const SourceManager &CurSM = Stack[I].second.getManager(); 259 SourceLocation CurLoc = Stack[I].second; 260 emitBuildingModuleLocation(CurLoc, 261 CurSM.getPresumedLoc(CurLoc, 262 DiagOpts->ShowPresumedLoc), 263 Stack[I].first, 264 CurSM); 265 } 266 } 267 268 /// A recursive function to trace all possible backtrace locations 269 /// to match the \p CaretLocFileID. 270 static SourceLocation 271 retrieveMacroLocation(SourceLocation Loc, FileID MacroFileID, 272 FileID CaretFileID, 273 const SmallVectorImpl<FileID> &CommonArgExpansions, 274 bool IsBegin, const SourceManager *SM) { 275 assert(SM->getFileID(Loc) == MacroFileID); 276 if (MacroFileID == CaretFileID) 277 return Loc; 278 if (!Loc.isMacroID()) 279 return SourceLocation(); 280 281 SourceLocation MacroLocation, MacroArgLocation; 282 283 if (SM->isMacroArgExpansion(Loc)) { 284 // Only look at the immediate spelling location of this macro argument if 285 // the other location in the source range is also present in that expansion. 286 if (std::binary_search(CommonArgExpansions.begin(), 287 CommonArgExpansions.end(), MacroFileID)) 288 MacroLocation = SM->getImmediateSpellingLoc(Loc); 289 MacroArgLocation = IsBegin ? SM->getImmediateExpansionRange(Loc).first 290 : SM->getImmediateExpansionRange(Loc).second; 291 } else { 292 MacroLocation = IsBegin ? SM->getImmediateExpansionRange(Loc).first 293 : SM->getImmediateExpansionRange(Loc).second; 294 MacroArgLocation = SM->getImmediateSpellingLoc(Loc); 295 } 296 297 if (MacroLocation.isValid()) { 298 MacroFileID = SM->getFileID(MacroLocation); 299 MacroLocation = 300 retrieveMacroLocation(MacroLocation, MacroFileID, CaretFileID, 301 CommonArgExpansions, IsBegin, SM); 302 if (MacroLocation.isValid()) 303 return MacroLocation; 304 } 305 306 MacroFileID = SM->getFileID(MacroArgLocation); 307 return retrieveMacroLocation(MacroArgLocation, MacroFileID, CaretFileID, 308 CommonArgExpansions, IsBegin, SM); 309 } 310 311 /// Walk up the chain of macro expansions and collect the FileIDs identifying the 312 /// expansions. 313 static void getMacroArgExpansionFileIDs(SourceLocation Loc, 314 SmallVectorImpl<FileID> &IDs, 315 bool IsBegin, const SourceManager *SM) { 316 while (Loc.isMacroID()) { 317 if (SM->isMacroArgExpansion(Loc)) { 318 IDs.push_back(SM->getFileID(Loc)); 319 Loc = SM->getImmediateSpellingLoc(Loc); 320 } else { 321 auto ExpRange = SM->getImmediateExpansionRange(Loc); 322 Loc = IsBegin ? ExpRange.first : ExpRange.second; 323 } 324 } 325 } 326 327 /// Collect the expansions of the begin and end locations and compute the set 328 /// intersection. Produces a sorted vector of FileIDs in CommonArgExpansions. 329 static void computeCommonMacroArgExpansionFileIDs( 330 SourceLocation Begin, SourceLocation End, const SourceManager *SM, 331 SmallVectorImpl<FileID> &CommonArgExpansions) { 332 SmallVector<FileID, 4> BeginArgExpansions; 333 SmallVector<FileID, 4> EndArgExpansions; 334 getMacroArgExpansionFileIDs(Begin, BeginArgExpansions, /*IsBegin=*/true, SM); 335 getMacroArgExpansionFileIDs(End, EndArgExpansions, /*IsBegin=*/false, SM); 336 std::sort(BeginArgExpansions.begin(), BeginArgExpansions.end()); 337 std::sort(EndArgExpansions.begin(), EndArgExpansions.end()); 338 std::set_intersection(BeginArgExpansions.begin(), BeginArgExpansions.end(), 339 EndArgExpansions.begin(), EndArgExpansions.end(), 340 std::back_inserter(CommonArgExpansions)); 341 } 342 343 // Helper function to fix up source ranges. It takes in an array of ranges, 344 // and outputs an array of ranges where we want to draw the range highlighting 345 // around the location specified by CaretLoc. 346 // 347 // To find locations which correspond to the caret, we crawl the macro caller 348 // chain for the beginning and end of each range. If the caret location 349 // is in a macro expansion, we search each chain for a location 350 // in the same expansion as the caret; otherwise, we crawl to the top of 351 // each chain. Two locations are part of the same macro expansion 352 // iff the FileID is the same. 353 static void mapDiagnosticRanges( 354 SourceLocation CaretLoc, 355 ArrayRef<CharSourceRange> Ranges, 356 SmallVectorImpl<CharSourceRange> &SpellingRanges, 357 const SourceManager *SM) { 358 FileID CaretLocFileID = SM->getFileID(CaretLoc); 359 360 for (auto I = Ranges.begin(), E = Ranges.end(); I != E; ++I) { 361 if (I->isInvalid()) continue; 362 363 SourceLocation Begin = I->getBegin(), End = I->getEnd(); 364 bool IsTokenRange = I->isTokenRange(); 365 366 FileID BeginFileID = SM->getFileID(Begin); 367 FileID EndFileID = SM->getFileID(End); 368 369 // Find the common parent for the beginning and end of the range. 370 371 // First, crawl the expansion chain for the beginning of the range. 372 llvm::SmallDenseMap<FileID, SourceLocation> BeginLocsMap; 373 while (Begin.isMacroID() && BeginFileID != EndFileID) { 374 BeginLocsMap[BeginFileID] = Begin; 375 Begin = SM->getImmediateExpansionRange(Begin).first; 376 BeginFileID = SM->getFileID(Begin); 377 } 378 379 // Then, crawl the expansion chain for the end of the range. 380 if (BeginFileID != EndFileID) { 381 while (End.isMacroID() && !BeginLocsMap.count(EndFileID)) { 382 End = SM->getImmediateExpansionRange(End).second; 383 EndFileID = SM->getFileID(End); 384 } 385 if (End.isMacroID()) { 386 Begin = BeginLocsMap[EndFileID]; 387 BeginFileID = EndFileID; 388 } 389 } 390 391 // Do the backtracking. 392 SmallVector<FileID, 4> CommonArgExpansions; 393 computeCommonMacroArgExpansionFileIDs(Begin, End, SM, CommonArgExpansions); 394 Begin = retrieveMacroLocation(Begin, BeginFileID, CaretLocFileID, 395 CommonArgExpansions, /*IsBegin=*/true, SM); 396 End = retrieveMacroLocation(End, BeginFileID, CaretLocFileID, 397 CommonArgExpansions, /*IsBegin=*/false, SM); 398 if (Begin.isInvalid() || End.isInvalid()) continue; 399 400 // Return the spelling location of the beginning and end of the range. 401 Begin = SM->getSpellingLoc(Begin); 402 End = SM->getSpellingLoc(End); 403 404 SpellingRanges.push_back(CharSourceRange(SourceRange(Begin, End), 405 IsTokenRange)); 406 } 407 } 408 409 void DiagnosticRenderer::emitCaret(SourceLocation Loc, 410 DiagnosticsEngine::Level Level, 411 ArrayRef<CharSourceRange> Ranges, 412 ArrayRef<FixItHint> Hints, 413 const SourceManager &SM) { 414 SmallVector<CharSourceRange, 4> SpellingRanges; 415 mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM); 416 emitCodeContext(Loc, Level, SpellingRanges, Hints, SM); 417 } 418 419 /// \brief A helper function for emitMacroExpansion to print the 420 /// macro expansion message 421 void DiagnosticRenderer::emitSingleMacroExpansion( 422 SourceLocation Loc, 423 DiagnosticsEngine::Level Level, 424 ArrayRef<CharSourceRange> Ranges, 425 const SourceManager &SM) { 426 // Find the spelling location for the macro definition. We must use the 427 // spelling location here to avoid emitting a macro backtrace for the note. 428 SourceLocation SpellingLoc = SM.getSpellingLoc(Loc); 429 430 // Map the ranges into the FileID of the diagnostic location. 431 SmallVector<CharSourceRange, 4> SpellingRanges; 432 mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM); 433 434 SmallString<100> MessageStorage; 435 llvm::raw_svector_ostream Message(MessageStorage); 436 StringRef MacroName = 437 Lexer::getImmediateMacroNameForDiagnostics(Loc, SM, LangOpts); 438 if (MacroName.empty()) 439 Message << "expanded from here"; 440 else 441 Message << "expanded from macro '" << MacroName << "'"; 442 443 emitDiagnostic(SpellingLoc, DiagnosticsEngine::Note, Message.str(), 444 SpellingRanges, None, &SM); 445 } 446 447 /// Check that the macro argument location of Loc starts with ArgumentLoc. 448 /// The starting location of the macro expansions is used to differeniate 449 /// different macro expansions. 450 static bool checkLocForMacroArgExpansion(SourceLocation Loc, 451 const SourceManager &SM, 452 SourceLocation ArgumentLoc) { 453 SourceLocation MacroLoc; 454 if (SM.isMacroArgExpansion(Loc, &MacroLoc)) { 455 if (ArgumentLoc == MacroLoc) return true; 456 } 457 458 return false; 459 } 460 461 /// Check if all the locations in the range have the same macro argument 462 /// expansion, and that that expansion starts with ArgumentLoc. 463 static bool checkRangeForMacroArgExpansion(CharSourceRange Range, 464 const SourceManager &SM, 465 SourceLocation ArgumentLoc) { 466 SourceLocation BegLoc = Range.getBegin(), EndLoc = Range.getEnd(); 467 while (BegLoc != EndLoc) { 468 if (!checkLocForMacroArgExpansion(BegLoc, SM, ArgumentLoc)) 469 return false; 470 BegLoc.getLocWithOffset(1); 471 } 472 473 return checkLocForMacroArgExpansion(BegLoc, SM, ArgumentLoc); 474 } 475 476 /// A helper function to check if the current ranges are all inside the same 477 /// macro argument expansion as Loc. 478 static bool checkRangesForMacroArgExpansion(SourceLocation Loc, 479 ArrayRef<CharSourceRange> Ranges, 480 const SourceManager &SM) { 481 assert(Loc.isMacroID() && "Must be a macro expansion!"); 482 483 SmallVector<CharSourceRange, 4> SpellingRanges; 484 mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM); 485 486 /// Count all valid ranges. 487 unsigned ValidCount = 0; 488 for (auto I : Ranges) 489 if (I.isValid()) ValidCount++; 490 491 if (ValidCount > SpellingRanges.size()) 492 return false; 493 494 /// To store the source location of the argument location. 495 SourceLocation ArgumentLoc; 496 497 /// Set the ArgumentLoc to the beginning location of the expansion of Loc 498 /// so to check if the ranges expands to the same beginning location. 499 if (!SM.isMacroArgExpansion(Loc,&ArgumentLoc)) 500 return false; 501 502 for (auto I = SpellingRanges.begin(), E = SpellingRanges.end(); I != E; ++I) { 503 if (!checkRangeForMacroArgExpansion(*I, SM, ArgumentLoc)) 504 return false; 505 } 506 507 return true; 508 } 509 510 /// \brief Recursively emit notes for each macro expansion and caret 511 /// diagnostics where appropriate. 512 /// 513 /// Walks up the macro expansion stack printing expansion notes, the code 514 /// snippet, caret, underlines and FixItHint display as appropriate at each 515 /// level. 516 /// 517 /// \param Loc The location for this caret. 518 /// \param Level The diagnostic level currently being emitted. 519 /// \param Ranges The underlined ranges for this code snippet. 520 /// \param Hints The FixIt hints active for this diagnostic. 521 void DiagnosticRenderer::emitMacroExpansions(SourceLocation Loc, 522 DiagnosticsEngine::Level Level, 523 ArrayRef<CharSourceRange> Ranges, 524 ArrayRef<FixItHint> Hints, 525 const SourceManager &SM) { 526 assert(Loc.isValid() && "must have a valid source location here"); 527 528 // Produce a stack of macro backtraces. 529 SmallVector<SourceLocation, 8> LocationStack; 530 unsigned IgnoredEnd = 0; 531 while (Loc.isMacroID()) { 532 // If this is the expansion of a macro argument, point the caret at the 533 // use of the argument in the definition of the macro, not the expansion. 534 if (SM.isMacroArgExpansion(Loc)) 535 LocationStack.push_back(SM.getImmediateExpansionRange(Loc).first); 536 else 537 LocationStack.push_back(Loc); 538 539 if (checkRangesForMacroArgExpansion(Loc, Ranges, SM)) 540 IgnoredEnd = LocationStack.size(); 541 542 Loc = SM.getImmediateMacroCallerLoc(Loc); 543 544 // Once the location no longer points into a macro, try stepping through 545 // the last found location. This sometimes produces additional useful 546 // backtraces. 547 if (Loc.isFileID()) 548 Loc = SM.getImmediateMacroCallerLoc(LocationStack.back()); 549 assert(Loc.isValid() && "must have a valid source location here"); 550 } 551 552 LocationStack.erase(LocationStack.begin(), 553 LocationStack.begin() + IgnoredEnd); 554 555 unsigned MacroDepth = LocationStack.size(); 556 unsigned MacroLimit = DiagOpts->MacroBacktraceLimit; 557 if (MacroDepth <= MacroLimit || MacroLimit == 0) { 558 for (auto I = LocationStack.rbegin(), E = LocationStack.rend(); 559 I != E; ++I) 560 emitSingleMacroExpansion(*I, Level, Ranges, SM); 561 return; 562 } 563 564 unsigned MacroStartMessages = MacroLimit / 2; 565 unsigned MacroEndMessages = MacroLimit / 2 + MacroLimit % 2; 566 567 for (auto I = LocationStack.rbegin(), 568 E = LocationStack.rbegin() + MacroStartMessages; 569 I != E; ++I) 570 emitSingleMacroExpansion(*I, Level, Ranges, SM); 571 572 SmallString<200> MessageStorage; 573 llvm::raw_svector_ostream Message(MessageStorage); 574 Message << "(skipping " << (MacroDepth - MacroLimit) 575 << " expansions in backtrace; use -fmacro-backtrace-limit=0 to " 576 "see all)"; 577 emitBasicNote(Message.str()); 578 579 for (auto I = LocationStack.rend() - MacroEndMessages, 580 E = LocationStack.rend(); 581 I != E; ++I) 582 emitSingleMacroExpansion(*I, Level, Ranges, SM); 583 } 584 585 DiagnosticNoteRenderer::~DiagnosticNoteRenderer() {} 586 587 void DiagnosticNoteRenderer::emitIncludeLocation(SourceLocation Loc, 588 PresumedLoc PLoc, 589 const SourceManager &SM) { 590 // Generate a note indicating the include location. 591 SmallString<200> MessageStorage; 592 llvm::raw_svector_ostream Message(MessageStorage); 593 Message << "in file included from " << PLoc.getFilename() << ':' 594 << PLoc.getLine() << ":"; 595 emitNote(Loc, Message.str(), &SM); 596 } 597 598 void DiagnosticNoteRenderer::emitImportLocation(SourceLocation Loc, 599 PresumedLoc PLoc, 600 StringRef ModuleName, 601 const SourceManager &SM) { 602 // Generate a note indicating the include location. 603 SmallString<200> MessageStorage; 604 llvm::raw_svector_ostream Message(MessageStorage); 605 Message << "in module '" << ModuleName; 606 if (PLoc.isValid()) 607 Message << "' imported from " << PLoc.getFilename() << ':' 608 << PLoc.getLine(); 609 Message << ":"; 610 emitNote(Loc, Message.str(), &SM); 611 } 612 613 void 614 DiagnosticNoteRenderer::emitBuildingModuleLocation(SourceLocation Loc, 615 PresumedLoc PLoc, 616 StringRef ModuleName, 617 const SourceManager &SM) { 618 // Generate a note indicating the include location. 619 SmallString<200> MessageStorage; 620 llvm::raw_svector_ostream Message(MessageStorage); 621 if (PLoc.isValid()) 622 Message << "while building module '" << ModuleName << "' imported from " 623 << PLoc.getFilename() << ':' << PLoc.getLine() << ":"; 624 else 625 Message << "while building module '" << ModuleName << "':"; 626 emitNote(Loc, Message.str(), &SM); 627 } 628