1 //===- PathDiagnostic.cpp - Path-Specific Diagnostic Handling -------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file defines the PathDiagnostic-related interfaces. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "clang/Analysis/PathDiagnostic.h" 14 #include "clang/AST/Decl.h" 15 #include "clang/AST/DeclBase.h" 16 #include "clang/AST/DeclCXX.h" 17 #include "clang/AST/DeclObjC.h" 18 #include "clang/AST/DeclTemplate.h" 19 #include "clang/AST/Expr.h" 20 #include "clang/AST/ExprCXX.h" 21 #include "clang/AST/OperationKinds.h" 22 #include "clang/AST/ParentMap.h" 23 #include "clang/AST/Stmt.h" 24 #include "clang/AST/Type.h" 25 #include "clang/Analysis/AnalysisDeclContext.h" 26 #include "clang/Analysis/CFG.h" 27 #include "clang/Analysis/ProgramPoint.h" 28 #include "clang/Basic/FileManager.h" 29 #include "clang/Basic/LLVM.h" 30 #include "clang/Basic/SourceLocation.h" 31 #include "clang/Basic/SourceManager.h" 32 #include "llvm/ADT/ArrayRef.h" 33 #include "llvm/ADT/FoldingSet.h" 34 #include "llvm/ADT/None.h" 35 #include "llvm/ADT/Optional.h" 36 #include "llvm/ADT/STLExtras.h" 37 #include "llvm/ADT/SmallString.h" 38 #include "llvm/ADT/SmallVector.h" 39 #include "llvm/ADT/StringExtras.h" 40 #include "llvm/ADT/StringRef.h" 41 #include "llvm/Support/Casting.h" 42 #include "llvm/Support/ErrorHandling.h" 43 #include "llvm/Support/raw_ostream.h" 44 #include <cassert> 45 #include <cstring> 46 #include <memory> 47 #include <utility> 48 #include <vector> 49 50 using namespace clang; 51 using namespace ento; 52 53 static StringRef StripTrailingDots(StringRef s) { 54 for (StringRef::size_type i = s.size(); i != 0; --i) 55 if (s[i - 1] != '.') 56 return s.substr(0, i); 57 return {}; 58 } 59 60 PathDiagnosticPiece::PathDiagnosticPiece(StringRef s, 61 Kind k, DisplayHint hint) 62 : str(StripTrailingDots(s)), kind(k), Hint(hint) {} 63 64 PathDiagnosticPiece::PathDiagnosticPiece(Kind k, DisplayHint hint) 65 : kind(k), Hint(hint) {} 66 67 PathDiagnosticPiece::~PathDiagnosticPiece() = default; 68 69 PathDiagnosticEventPiece::~PathDiagnosticEventPiece() = default; 70 71 PathDiagnosticCallPiece::~PathDiagnosticCallPiece() = default; 72 73 PathDiagnosticControlFlowPiece::~PathDiagnosticControlFlowPiece() = default; 74 75 PathDiagnosticMacroPiece::~PathDiagnosticMacroPiece() = default; 76 77 PathDiagnosticNotePiece::~PathDiagnosticNotePiece() = default; 78 79 PathDiagnosticPopUpPiece::~PathDiagnosticPopUpPiece() = default; 80 81 void PathPieces::flattenTo(PathPieces &Primary, PathPieces &Current, 82 bool ShouldFlattenMacros) const { 83 for (auto &Piece : *this) { 84 switch (Piece->getKind()) { 85 case PathDiagnosticPiece::Call: { 86 auto &Call = cast<PathDiagnosticCallPiece>(*Piece); 87 if (auto CallEnter = Call.getCallEnterEvent()) 88 Current.push_back(std::move(CallEnter)); 89 Call.path.flattenTo(Primary, Primary, ShouldFlattenMacros); 90 if (auto callExit = Call.getCallExitEvent()) 91 Current.push_back(std::move(callExit)); 92 break; 93 } 94 case PathDiagnosticPiece::Macro: { 95 auto &Macro = cast<PathDiagnosticMacroPiece>(*Piece); 96 if (ShouldFlattenMacros) { 97 Macro.subPieces.flattenTo(Primary, Primary, ShouldFlattenMacros); 98 } else { 99 Current.push_back(Piece); 100 PathPieces NewPath; 101 Macro.subPieces.flattenTo(Primary, NewPath, ShouldFlattenMacros); 102 // FIXME: This probably shouldn't mutate the original path piece. 103 Macro.subPieces = NewPath; 104 } 105 break; 106 } 107 case PathDiagnosticPiece::Event: 108 case PathDiagnosticPiece::ControlFlow: 109 case PathDiagnosticPiece::Note: 110 case PathDiagnosticPiece::PopUp: 111 Current.push_back(Piece); 112 break; 113 } 114 } 115 } 116 117 PathDiagnostic::~PathDiagnostic() = default; 118 119 PathDiagnostic::PathDiagnostic( 120 StringRef CheckerName, const Decl *declWithIssue, StringRef bugtype, 121 StringRef verboseDesc, StringRef shortDesc, StringRef category, 122 PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique, 123 std::unique_ptr<FilesToLineNumsMap> ExecutedLines) 124 : CheckerName(CheckerName), DeclWithIssue(declWithIssue), 125 BugType(StripTrailingDots(bugtype)), 126 VerboseDesc(StripTrailingDots(verboseDesc)), 127 ShortDesc(StripTrailingDots(shortDesc)), 128 Category(StripTrailingDots(category)), UniqueingLoc(LocationToUnique), 129 UniqueingDecl(DeclToUnique), ExecutedLines(std::move(ExecutedLines)), 130 path(pathImpl) {} 131 132 void PathDiagnosticConsumer::anchor() {} 133 134 PathDiagnosticConsumer::~PathDiagnosticConsumer() { 135 // Delete the contents of the FoldingSet if it isn't empty already. 136 for (auto &Diag : Diags) 137 delete &Diag; 138 } 139 140 void PathDiagnosticConsumer::HandlePathDiagnostic( 141 std::unique_ptr<PathDiagnostic> D) { 142 if (!D || D->path.empty()) 143 return; 144 145 // We need to flatten the locations (convert Stmt* to locations) because 146 // the referenced statements may be freed by the time the diagnostics 147 // are emitted. 148 D->flattenLocations(); 149 150 // If the PathDiagnosticConsumer does not support diagnostics that 151 // cross file boundaries, prune out such diagnostics now. 152 if (!supportsCrossFileDiagnostics()) { 153 // Verify that the entire path is from the same FileID. 154 FileID FID; 155 const SourceManager &SMgr = D->path.front()->getLocation().getManager(); 156 SmallVector<const PathPieces *, 5> WorkList; 157 WorkList.push_back(&D->path); 158 SmallString<128> buf; 159 llvm::raw_svector_ostream warning(buf); 160 warning << "warning: Path diagnostic report is not generated. Current " 161 << "output format does not support diagnostics that cross file " 162 << "boundaries. Refer to --analyzer-output for valid output " 163 << "formats\n"; 164 165 while (!WorkList.empty()) { 166 const PathPieces &path = *WorkList.pop_back_val(); 167 168 for (const auto &I : path) { 169 const PathDiagnosticPiece *piece = I.get(); 170 FullSourceLoc L = piece->getLocation().asLocation().getExpansionLoc(); 171 172 if (FID.isInvalid()) { 173 FID = SMgr.getFileID(L); 174 } else if (SMgr.getFileID(L) != FID) { 175 llvm::errs() << warning.str(); 176 return; 177 } 178 179 // Check the source ranges. 180 ArrayRef<SourceRange> Ranges = piece->getRanges(); 181 for (const auto &I : Ranges) { 182 SourceLocation L = SMgr.getExpansionLoc(I.getBegin()); 183 if (!L.isFileID() || SMgr.getFileID(L) != FID) { 184 llvm::errs() << warning.str(); 185 return; 186 } 187 L = SMgr.getExpansionLoc(I.getEnd()); 188 if (!L.isFileID() || SMgr.getFileID(L) != FID) { 189 llvm::errs() << warning.str(); 190 return; 191 } 192 } 193 194 if (const auto *call = dyn_cast<PathDiagnosticCallPiece>(piece)) 195 WorkList.push_back(&call->path); 196 else if (const auto *macro = dyn_cast<PathDiagnosticMacroPiece>(piece)) 197 WorkList.push_back(¯o->subPieces); 198 } 199 } 200 201 if (FID.isInvalid()) 202 return; // FIXME: Emit a warning? 203 } 204 205 // Profile the node to see if we already have something matching it 206 llvm::FoldingSetNodeID profile; 207 D->Profile(profile); 208 void *InsertPos = nullptr; 209 210 if (PathDiagnostic *orig = Diags.FindNodeOrInsertPos(profile, InsertPos)) { 211 // Keep the PathDiagnostic with the shorter path. 212 // Note, the enclosing routine is called in deterministic order, so the 213 // results will be consistent between runs (no reason to break ties if the 214 // size is the same). 215 const unsigned orig_size = orig->full_size(); 216 const unsigned new_size = D->full_size(); 217 if (orig_size <= new_size) 218 return; 219 220 assert(orig != D.get()); 221 Diags.RemoveNode(orig); 222 delete orig; 223 } 224 225 Diags.InsertNode(D.release()); 226 } 227 228 static Optional<bool> comparePath(const PathPieces &X, const PathPieces &Y); 229 230 static Optional<bool> 231 compareControlFlow(const PathDiagnosticControlFlowPiece &X, 232 const PathDiagnosticControlFlowPiece &Y) { 233 FullSourceLoc XSL = X.getStartLocation().asLocation(); 234 FullSourceLoc YSL = Y.getStartLocation().asLocation(); 235 if (XSL != YSL) 236 return XSL.isBeforeInTranslationUnitThan(YSL); 237 FullSourceLoc XEL = X.getEndLocation().asLocation(); 238 FullSourceLoc YEL = Y.getEndLocation().asLocation(); 239 if (XEL != YEL) 240 return XEL.isBeforeInTranslationUnitThan(YEL); 241 return None; 242 } 243 244 static Optional<bool> compareMacro(const PathDiagnosticMacroPiece &X, 245 const PathDiagnosticMacroPiece &Y) { 246 return comparePath(X.subPieces, Y.subPieces); 247 } 248 249 static Optional<bool> compareCall(const PathDiagnosticCallPiece &X, 250 const PathDiagnosticCallPiece &Y) { 251 FullSourceLoc X_CEL = X.callEnter.asLocation(); 252 FullSourceLoc Y_CEL = Y.callEnter.asLocation(); 253 if (X_CEL != Y_CEL) 254 return X_CEL.isBeforeInTranslationUnitThan(Y_CEL); 255 FullSourceLoc X_CEWL = X.callEnterWithin.asLocation(); 256 FullSourceLoc Y_CEWL = Y.callEnterWithin.asLocation(); 257 if (X_CEWL != Y_CEWL) 258 return X_CEWL.isBeforeInTranslationUnitThan(Y_CEWL); 259 FullSourceLoc X_CRL = X.callReturn.asLocation(); 260 FullSourceLoc Y_CRL = Y.callReturn.asLocation(); 261 if (X_CRL != Y_CRL) 262 return X_CRL.isBeforeInTranslationUnitThan(Y_CRL); 263 return comparePath(X.path, Y.path); 264 } 265 266 static Optional<bool> comparePiece(const PathDiagnosticPiece &X, 267 const PathDiagnosticPiece &Y) { 268 if (X.getKind() != Y.getKind()) 269 return X.getKind() < Y.getKind(); 270 271 FullSourceLoc XL = X.getLocation().asLocation(); 272 FullSourceLoc YL = Y.getLocation().asLocation(); 273 if (XL != YL) 274 return XL.isBeforeInTranslationUnitThan(YL); 275 276 if (X.getString() != Y.getString()) 277 return X.getString() < Y.getString(); 278 279 if (X.getRanges().size() != Y.getRanges().size()) 280 return X.getRanges().size() < Y.getRanges().size(); 281 282 const SourceManager &SM = XL.getManager(); 283 284 for (unsigned i = 0, n = X.getRanges().size(); i < n; ++i) { 285 SourceRange XR = X.getRanges()[i]; 286 SourceRange YR = Y.getRanges()[i]; 287 if (XR != YR) { 288 if (XR.getBegin() != YR.getBegin()) 289 return SM.isBeforeInTranslationUnit(XR.getBegin(), YR.getBegin()); 290 return SM.isBeforeInTranslationUnit(XR.getEnd(), YR.getEnd()); 291 } 292 } 293 294 switch (X.getKind()) { 295 case PathDiagnosticPiece::ControlFlow: 296 return compareControlFlow(cast<PathDiagnosticControlFlowPiece>(X), 297 cast<PathDiagnosticControlFlowPiece>(Y)); 298 case PathDiagnosticPiece::Macro: 299 return compareMacro(cast<PathDiagnosticMacroPiece>(X), 300 cast<PathDiagnosticMacroPiece>(Y)); 301 case PathDiagnosticPiece::Call: 302 return compareCall(cast<PathDiagnosticCallPiece>(X), 303 cast<PathDiagnosticCallPiece>(Y)); 304 case PathDiagnosticPiece::Event: 305 case PathDiagnosticPiece::Note: 306 case PathDiagnosticPiece::PopUp: 307 return None; 308 } 309 llvm_unreachable("all cases handled"); 310 } 311 312 static Optional<bool> comparePath(const PathPieces &X, const PathPieces &Y) { 313 if (X.size() != Y.size()) 314 return X.size() < Y.size(); 315 316 PathPieces::const_iterator X_I = X.begin(), X_end = X.end(); 317 PathPieces::const_iterator Y_I = Y.begin(), Y_end = Y.end(); 318 319 for ( ; X_I != X_end && Y_I != Y_end; ++X_I, ++Y_I) { 320 Optional<bool> b = comparePiece(**X_I, **Y_I); 321 if (b.hasValue()) 322 return b.getValue(); 323 } 324 325 return None; 326 } 327 328 static bool compareCrossTUSourceLocs(FullSourceLoc XL, FullSourceLoc YL) { 329 std::pair<FileID, unsigned> XOffs = XL.getDecomposedLoc(); 330 std::pair<FileID, unsigned> YOffs = YL.getDecomposedLoc(); 331 const SourceManager &SM = XL.getManager(); 332 std::pair<bool, bool> InSameTU = SM.isInTheSameTranslationUnit(XOffs, YOffs); 333 if (InSameTU.first) 334 return XL.isBeforeInTranslationUnitThan(YL); 335 const FileEntry *XFE = SM.getFileEntryForID(XL.getSpellingLoc().getFileID()); 336 const FileEntry *YFE = SM.getFileEntryForID(YL.getSpellingLoc().getFileID()); 337 if (!XFE || !YFE) 338 return XFE && !YFE; 339 int NameCmp = XFE->getName().compare(YFE->getName()); 340 if (NameCmp != 0) 341 return NameCmp == -1; 342 // Last resort: Compare raw file IDs that are possibly expansions. 343 return XL.getFileID() < YL.getFileID(); 344 } 345 346 static bool compare(const PathDiagnostic &X, const PathDiagnostic &Y) { 347 FullSourceLoc XL = X.getLocation().asLocation(); 348 FullSourceLoc YL = Y.getLocation().asLocation(); 349 if (XL != YL) 350 return compareCrossTUSourceLocs(XL, YL); 351 if (X.getBugType() != Y.getBugType()) 352 return X.getBugType() < Y.getBugType(); 353 if (X.getCategory() != Y.getCategory()) 354 return X.getCategory() < Y.getCategory(); 355 if (X.getVerboseDescription() != Y.getVerboseDescription()) 356 return X.getVerboseDescription() < Y.getVerboseDescription(); 357 if (X.getShortDescription() != Y.getShortDescription()) 358 return X.getShortDescription() < Y.getShortDescription(); 359 if (X.getDeclWithIssue() != Y.getDeclWithIssue()) { 360 const Decl *XD = X.getDeclWithIssue(); 361 if (!XD) 362 return true; 363 const Decl *YD = Y.getDeclWithIssue(); 364 if (!YD) 365 return false; 366 SourceLocation XDL = XD->getLocation(); 367 SourceLocation YDL = YD->getLocation(); 368 if (XDL != YDL) { 369 const SourceManager &SM = XL.getManager(); 370 return compareCrossTUSourceLocs(FullSourceLoc(XDL, SM), 371 FullSourceLoc(YDL, SM)); 372 } 373 } 374 PathDiagnostic::meta_iterator XI = X.meta_begin(), XE = X.meta_end(); 375 PathDiagnostic::meta_iterator YI = Y.meta_begin(), YE = Y.meta_end(); 376 if (XE - XI != YE - YI) 377 return (XE - XI) < (YE - YI); 378 for ( ; XI != XE ; ++XI, ++YI) { 379 if (*XI != *YI) 380 return (*XI) < (*YI); 381 } 382 Optional<bool> b = comparePath(X.path, Y.path); 383 assert(b.hasValue()); 384 return b.getValue(); 385 } 386 387 void PathDiagnosticConsumer::FlushDiagnostics( 388 PathDiagnosticConsumer::FilesMade *Files) { 389 if (flushed) 390 return; 391 392 flushed = true; 393 394 std::vector<const PathDiagnostic *> BatchDiags; 395 for (const auto &D : Diags) 396 BatchDiags.push_back(&D); 397 398 // Sort the diagnostics so that they are always emitted in a deterministic 399 // order. 400 int (*Comp)(const PathDiagnostic *const *, const PathDiagnostic *const *) = 401 [](const PathDiagnostic *const *X, const PathDiagnostic *const *Y) { 402 assert(*X != *Y && "PathDiagnostics not uniqued!"); 403 if (compare(**X, **Y)) 404 return -1; 405 assert(compare(**Y, **X) && "Not a total order!"); 406 return 1; 407 }; 408 array_pod_sort(BatchDiags.begin(), BatchDiags.end(), Comp); 409 410 FlushDiagnosticsImpl(BatchDiags, Files); 411 412 // Delete the flushed diagnostics. 413 for (const auto D : BatchDiags) 414 delete D; 415 416 // Clear out the FoldingSet. 417 Diags.clear(); 418 } 419 420 PathDiagnosticConsumer::FilesMade::~FilesMade() { 421 for (PDFileEntry &Entry : Set) 422 Entry.~PDFileEntry(); 423 } 424 425 void PathDiagnosticConsumer::FilesMade::addDiagnostic(const PathDiagnostic &PD, 426 StringRef ConsumerName, 427 StringRef FileName) { 428 llvm::FoldingSetNodeID NodeID; 429 NodeID.Add(PD); 430 void *InsertPos; 431 PDFileEntry *Entry = Set.FindNodeOrInsertPos(NodeID, InsertPos); 432 if (!Entry) { 433 Entry = Alloc.Allocate<PDFileEntry>(); 434 Entry = new (Entry) PDFileEntry(NodeID); 435 Set.InsertNode(Entry, InsertPos); 436 } 437 438 // Allocate persistent storage for the file name. 439 char *FileName_cstr = (char*) Alloc.Allocate(FileName.size(), 1); 440 memcpy(FileName_cstr, FileName.data(), FileName.size()); 441 442 Entry->files.push_back(std::make_pair(ConsumerName, 443 StringRef(FileName_cstr, 444 FileName.size()))); 445 } 446 447 PathDiagnosticConsumer::PDFileEntry::ConsumerFiles * 448 PathDiagnosticConsumer::FilesMade::getFiles(const PathDiagnostic &PD) { 449 llvm::FoldingSetNodeID NodeID; 450 NodeID.Add(PD); 451 void *InsertPos; 452 PDFileEntry *Entry = Set.FindNodeOrInsertPos(NodeID, InsertPos); 453 if (!Entry) 454 return nullptr; 455 return &Entry->files; 456 } 457 458 //===----------------------------------------------------------------------===// 459 // PathDiagnosticLocation methods. 460 //===----------------------------------------------------------------------===// 461 462 SourceLocation PathDiagnosticLocation::getValidSourceLocation( 463 const Stmt *S, LocationOrAnalysisDeclContext LAC, bool UseEndOfStatement) { 464 SourceLocation L = UseEndOfStatement ? S->getEndLoc() : S->getBeginLoc(); 465 assert(!LAC.isNull() && 466 "A valid LocationContext or AnalysisDeclContext should be passed to " 467 "PathDiagnosticLocation upon creation."); 468 469 // S might be a temporary statement that does not have a location in the 470 // source code, so find an enclosing statement and use its location. 471 if (!L.isValid()) { 472 AnalysisDeclContext *ADC; 473 if (LAC.is<const LocationContext*>()) 474 ADC = LAC.get<const LocationContext*>()->getAnalysisDeclContext(); 475 else 476 ADC = LAC.get<AnalysisDeclContext*>(); 477 478 ParentMap &PM = ADC->getParentMap(); 479 480 const Stmt *Parent = S; 481 do { 482 Parent = PM.getParent(Parent); 483 484 // In rare cases, we have implicit top-level expressions, 485 // such as arguments for implicit member initializers. 486 // In this case, fall back to the start of the body (even if we were 487 // asked for the statement end location). 488 if (!Parent) { 489 const Stmt *Body = ADC->getBody(); 490 if (Body) 491 L = Body->getBeginLoc(); 492 else 493 L = ADC->getDecl()->getEndLoc(); 494 break; 495 } 496 497 L = UseEndOfStatement ? Parent->getEndLoc() : Parent->getBeginLoc(); 498 } while (!L.isValid()); 499 } 500 501 // FIXME: Ironically, this assert actually fails in some cases. 502 //assert(L.isValid()); 503 return L; 504 } 505 506 static PathDiagnosticLocation 507 getLocationForCaller(const StackFrameContext *SFC, 508 const LocationContext *CallerCtx, 509 const SourceManager &SM) { 510 const CFGBlock &Block = *SFC->getCallSiteBlock(); 511 CFGElement Source = Block[SFC->getIndex()]; 512 513 switch (Source.getKind()) { 514 case CFGElement::Statement: 515 case CFGElement::Constructor: 516 case CFGElement::CXXRecordTypedCall: 517 return PathDiagnosticLocation(Source.castAs<CFGStmt>().getStmt(), 518 SM, CallerCtx); 519 case CFGElement::Initializer: { 520 const CFGInitializer &Init = Source.castAs<CFGInitializer>(); 521 return PathDiagnosticLocation(Init.getInitializer()->getInit(), 522 SM, CallerCtx); 523 } 524 case CFGElement::AutomaticObjectDtor: { 525 const CFGAutomaticObjDtor &Dtor = Source.castAs<CFGAutomaticObjDtor>(); 526 return PathDiagnosticLocation::createEnd(Dtor.getTriggerStmt(), 527 SM, CallerCtx); 528 } 529 case CFGElement::DeleteDtor: { 530 const CFGDeleteDtor &Dtor = Source.castAs<CFGDeleteDtor>(); 531 return PathDiagnosticLocation(Dtor.getDeleteExpr(), SM, CallerCtx); 532 } 533 case CFGElement::BaseDtor: 534 case CFGElement::MemberDtor: { 535 const AnalysisDeclContext *CallerInfo = CallerCtx->getAnalysisDeclContext(); 536 if (const Stmt *CallerBody = CallerInfo->getBody()) 537 return PathDiagnosticLocation::createEnd(CallerBody, SM, CallerCtx); 538 return PathDiagnosticLocation::create(CallerInfo->getDecl(), SM); 539 } 540 case CFGElement::NewAllocator: { 541 const CFGNewAllocator &Alloc = Source.castAs<CFGNewAllocator>(); 542 return PathDiagnosticLocation(Alloc.getAllocatorExpr(), SM, CallerCtx); 543 } 544 case CFGElement::TemporaryDtor: { 545 // Temporary destructors are for temporaries. They die immediately at around 546 // the location of CXXBindTemporaryExpr. If they are lifetime-extended, 547 // they'd be dealt with via an AutomaticObjectDtor instead. 548 const auto &Dtor = Source.castAs<CFGTemporaryDtor>(); 549 return PathDiagnosticLocation::createEnd(Dtor.getBindTemporaryExpr(), SM, 550 CallerCtx); 551 } 552 case CFGElement::ScopeBegin: 553 case CFGElement::ScopeEnd: 554 llvm_unreachable("not yet implemented!"); 555 case CFGElement::LifetimeEnds: 556 case CFGElement::LoopExit: 557 llvm_unreachable("CFGElement kind should not be on callsite!"); 558 } 559 560 llvm_unreachable("Unknown CFGElement kind"); 561 } 562 563 PathDiagnosticLocation 564 PathDiagnosticLocation::createBegin(const Decl *D, 565 const SourceManager &SM) { 566 return PathDiagnosticLocation(D->getBeginLoc(), SM, SingleLocK); 567 } 568 569 PathDiagnosticLocation 570 PathDiagnosticLocation::createBegin(const Stmt *S, 571 const SourceManager &SM, 572 LocationOrAnalysisDeclContext LAC) { 573 return PathDiagnosticLocation(getValidSourceLocation(S, LAC), 574 SM, SingleLocK); 575 } 576 577 PathDiagnosticLocation 578 PathDiagnosticLocation::createEnd(const Stmt *S, 579 const SourceManager &SM, 580 LocationOrAnalysisDeclContext LAC) { 581 if (const auto *CS = dyn_cast<CompoundStmt>(S)) 582 return createEndBrace(CS, SM); 583 return PathDiagnosticLocation(getValidSourceLocation(S, LAC, /*End=*/true), 584 SM, SingleLocK); 585 } 586 587 PathDiagnosticLocation 588 PathDiagnosticLocation::createOperatorLoc(const BinaryOperator *BO, 589 const SourceManager &SM) { 590 return PathDiagnosticLocation(BO->getOperatorLoc(), SM, SingleLocK); 591 } 592 593 PathDiagnosticLocation 594 PathDiagnosticLocation::createConditionalColonLoc( 595 const ConditionalOperator *CO, 596 const SourceManager &SM) { 597 return PathDiagnosticLocation(CO->getColonLoc(), SM, SingleLocK); 598 } 599 600 PathDiagnosticLocation 601 PathDiagnosticLocation::createMemberLoc(const MemberExpr *ME, 602 const SourceManager &SM) { 603 604 assert(ME->getMemberLoc().isValid() || ME->getBeginLoc().isValid()); 605 606 // In some cases, getMemberLoc isn't valid -- in this case we'll return with 607 // some other related valid SourceLocation. 608 if (ME->getMemberLoc().isValid()) 609 return PathDiagnosticLocation(ME->getMemberLoc(), SM, SingleLocK); 610 611 return PathDiagnosticLocation(ME->getBeginLoc(), SM, SingleLocK); 612 } 613 614 PathDiagnosticLocation 615 PathDiagnosticLocation::createBeginBrace(const CompoundStmt *CS, 616 const SourceManager &SM) { 617 SourceLocation L = CS->getLBracLoc(); 618 return PathDiagnosticLocation(L, SM, SingleLocK); 619 } 620 621 PathDiagnosticLocation 622 PathDiagnosticLocation::createEndBrace(const CompoundStmt *CS, 623 const SourceManager &SM) { 624 SourceLocation L = CS->getRBracLoc(); 625 return PathDiagnosticLocation(L, SM, SingleLocK); 626 } 627 628 PathDiagnosticLocation 629 PathDiagnosticLocation::createDeclBegin(const LocationContext *LC, 630 const SourceManager &SM) { 631 // FIXME: Should handle CXXTryStmt if analyser starts supporting C++. 632 if (const auto *CS = dyn_cast_or_null<CompoundStmt>(LC->getDecl()->getBody())) 633 if (!CS->body_empty()) { 634 SourceLocation Loc = (*CS->body_begin())->getBeginLoc(); 635 return PathDiagnosticLocation(Loc, SM, SingleLocK); 636 } 637 638 return PathDiagnosticLocation(); 639 } 640 641 PathDiagnosticLocation 642 PathDiagnosticLocation::createDeclEnd(const LocationContext *LC, 643 const SourceManager &SM) { 644 SourceLocation L = LC->getDecl()->getBodyRBrace(); 645 return PathDiagnosticLocation(L, SM, SingleLocK); 646 } 647 648 PathDiagnosticLocation 649 PathDiagnosticLocation::create(const ProgramPoint& P, 650 const SourceManager &SMng) { 651 const Stmt* S = nullptr; 652 if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) { 653 const CFGBlock *BSrc = BE->getSrc(); 654 if (BSrc->getTerminator().isVirtualBaseBranch()) { 655 // TODO: VirtualBaseBranches should also appear for destructors. 656 // In this case we should put the diagnostic at the end of decl. 657 return PathDiagnosticLocation::createBegin( 658 P.getLocationContext()->getDecl(), SMng); 659 660 } else { 661 S = BSrc->getTerminatorCondition(); 662 if (!S) { 663 // If the BlockEdge has no terminator condition statement but its 664 // source is the entry of the CFG (e.g. a checker crated the branch at 665 // the beginning of a function), use the function's declaration instead. 666 assert(BSrc == &BSrc->getParent()->getEntry() && "CFGBlock has no " 667 "TerminatorCondition and is not the enrty block of the CFG"); 668 return PathDiagnosticLocation::createBegin( 669 P.getLocationContext()->getDecl(), SMng); 670 } 671 } 672 } else if (Optional<StmtPoint> SP = P.getAs<StmtPoint>()) { 673 S = SP->getStmt(); 674 if (P.getAs<PostStmtPurgeDeadSymbols>()) 675 return PathDiagnosticLocation::createEnd(S, SMng, P.getLocationContext()); 676 } else if (Optional<PostInitializer> PIP = P.getAs<PostInitializer>()) { 677 return PathDiagnosticLocation(PIP->getInitializer()->getSourceLocation(), 678 SMng); 679 } else if (Optional<PreImplicitCall> PIC = P.getAs<PreImplicitCall>()) { 680 return PathDiagnosticLocation(PIC->getLocation(), SMng); 681 } else if (Optional<PostImplicitCall> PIE = P.getAs<PostImplicitCall>()) { 682 return PathDiagnosticLocation(PIE->getLocation(), SMng); 683 } else if (Optional<CallEnter> CE = P.getAs<CallEnter>()) { 684 return getLocationForCaller(CE->getCalleeContext(), 685 CE->getLocationContext(), 686 SMng); 687 } else if (Optional<CallExitEnd> CEE = P.getAs<CallExitEnd>()) { 688 return getLocationForCaller(CEE->getCalleeContext(), 689 CEE->getLocationContext(), 690 SMng); 691 } else if (auto CEB = P.getAs<CallExitBegin>()) { 692 if (const ReturnStmt *RS = CEB->getReturnStmt()) 693 return PathDiagnosticLocation::createBegin(RS, SMng, 694 CEB->getLocationContext()); 695 return PathDiagnosticLocation( 696 CEB->getLocationContext()->getDecl()->getSourceRange().getEnd(), SMng); 697 } else if (Optional<BlockEntrance> BE = P.getAs<BlockEntrance>()) { 698 if (Optional<CFGElement> BlockFront = BE->getFirstElement()) { 699 if (auto StmtElt = BlockFront->getAs<CFGStmt>()) { 700 return PathDiagnosticLocation(StmtElt->getStmt()->getBeginLoc(), SMng); 701 } else if (auto NewAllocElt = BlockFront->getAs<CFGNewAllocator>()) { 702 return PathDiagnosticLocation( 703 NewAllocElt->getAllocatorExpr()->getBeginLoc(), SMng); 704 } 705 llvm_unreachable("Unexpected CFG element at front of block"); 706 } 707 708 return PathDiagnosticLocation( 709 BE->getBlock()->getTerminatorStmt()->getBeginLoc(), SMng); 710 } else if (Optional<FunctionExitPoint> FE = P.getAs<FunctionExitPoint>()) { 711 return PathDiagnosticLocation(FE->getStmt(), SMng, 712 FE->getLocationContext()); 713 } else { 714 llvm_unreachable("Unexpected ProgramPoint"); 715 } 716 717 return PathDiagnosticLocation(S, SMng, P.getLocationContext()); 718 } 719 720 PathDiagnosticLocation PathDiagnosticLocation::createSingleLocation( 721 const PathDiagnosticLocation &PDL) { 722 FullSourceLoc L = PDL.asLocation(); 723 return PathDiagnosticLocation(L, L.getManager(), SingleLocK); 724 } 725 726 FullSourceLoc 727 PathDiagnosticLocation::genLocation(SourceLocation L, 728 LocationOrAnalysisDeclContext LAC) const { 729 assert(isValid()); 730 // Note that we want a 'switch' here so that the compiler can warn us in 731 // case we add more cases. 732 switch (K) { 733 case SingleLocK: 734 case RangeK: 735 break; 736 case StmtK: 737 // Defensive checking. 738 if (!S) 739 break; 740 return FullSourceLoc(getValidSourceLocation(S, LAC), 741 const_cast<SourceManager&>(*SM)); 742 case DeclK: 743 // Defensive checking. 744 if (!D) 745 break; 746 return FullSourceLoc(D->getLocation(), const_cast<SourceManager&>(*SM)); 747 } 748 749 return FullSourceLoc(L, const_cast<SourceManager&>(*SM)); 750 } 751 752 PathDiagnosticRange 753 PathDiagnosticLocation::genRange(LocationOrAnalysisDeclContext LAC) const { 754 assert(isValid()); 755 // Note that we want a 'switch' here so that the compiler can warn us in 756 // case we add more cases. 757 switch (K) { 758 case SingleLocK: 759 return PathDiagnosticRange(SourceRange(Loc,Loc), true); 760 case RangeK: 761 break; 762 case StmtK: { 763 const Stmt *S = asStmt(); 764 switch (S->getStmtClass()) { 765 default: 766 break; 767 case Stmt::DeclStmtClass: { 768 const auto *DS = cast<DeclStmt>(S); 769 if (DS->isSingleDecl()) { 770 // Should always be the case, but we'll be defensive. 771 return SourceRange(DS->getBeginLoc(), 772 DS->getSingleDecl()->getLocation()); 773 } 774 break; 775 } 776 // FIXME: Provide better range information for different 777 // terminators. 778 case Stmt::IfStmtClass: 779 case Stmt::WhileStmtClass: 780 case Stmt::DoStmtClass: 781 case Stmt::ForStmtClass: 782 case Stmt::ChooseExprClass: 783 case Stmt::IndirectGotoStmtClass: 784 case Stmt::SwitchStmtClass: 785 case Stmt::BinaryConditionalOperatorClass: 786 case Stmt::ConditionalOperatorClass: 787 case Stmt::ObjCForCollectionStmtClass: { 788 SourceLocation L = getValidSourceLocation(S, LAC); 789 return SourceRange(L, L); 790 } 791 } 792 SourceRange R = S->getSourceRange(); 793 if (R.isValid()) 794 return R; 795 break; 796 } 797 case DeclK: 798 if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) 799 return MD->getSourceRange(); 800 if (const auto *FD = dyn_cast<FunctionDecl>(D)) { 801 if (Stmt *Body = FD->getBody()) 802 return Body->getSourceRange(); 803 } 804 else { 805 SourceLocation L = D->getLocation(); 806 return PathDiagnosticRange(SourceRange(L, L), true); 807 } 808 } 809 810 return SourceRange(Loc, Loc); 811 } 812 813 void PathDiagnosticLocation::flatten() { 814 if (K == StmtK) { 815 K = RangeK; 816 S = nullptr; 817 D = nullptr; 818 } 819 else if (K == DeclK) { 820 K = SingleLocK; 821 S = nullptr; 822 D = nullptr; 823 } 824 } 825 826 //===----------------------------------------------------------------------===// 827 // Manipulation of PathDiagnosticCallPieces. 828 //===----------------------------------------------------------------------===// 829 830 std::shared_ptr<PathDiagnosticCallPiece> 831 PathDiagnosticCallPiece::construct(const CallExitEnd &CE, 832 const SourceManager &SM) { 833 const Decl *caller = CE.getLocationContext()->getDecl(); 834 PathDiagnosticLocation pos = getLocationForCaller(CE.getCalleeContext(), 835 CE.getLocationContext(), 836 SM); 837 return std::shared_ptr<PathDiagnosticCallPiece>( 838 new PathDiagnosticCallPiece(caller, pos)); 839 } 840 841 PathDiagnosticCallPiece * 842 PathDiagnosticCallPiece::construct(PathPieces &path, 843 const Decl *caller) { 844 std::shared_ptr<PathDiagnosticCallPiece> C( 845 new PathDiagnosticCallPiece(path, caller)); 846 path.clear(); 847 auto *R = C.get(); 848 path.push_front(std::move(C)); 849 return R; 850 } 851 852 void PathDiagnosticCallPiece::setCallee(const CallEnter &CE, 853 const SourceManager &SM) { 854 const StackFrameContext *CalleeCtx = CE.getCalleeContext(); 855 Callee = CalleeCtx->getDecl(); 856 857 callEnterWithin = PathDiagnosticLocation::createBegin(Callee, SM); 858 callEnter = getLocationForCaller(CalleeCtx, CE.getLocationContext(), SM); 859 860 // Autosynthesized property accessors are special because we'd never 861 // pop back up to non-autosynthesized code until we leave them. 862 // This is not generally true for autosynthesized callees, which may call 863 // non-autosynthesized callbacks. 864 // Unless set here, the IsCalleeAnAutosynthesizedPropertyAccessor flag 865 // defaults to false. 866 if (const auto *MD = dyn_cast<ObjCMethodDecl>(Callee)) 867 IsCalleeAnAutosynthesizedPropertyAccessor = ( 868 MD->isPropertyAccessor() && 869 CalleeCtx->getAnalysisDeclContext()->isBodyAutosynthesized()); 870 } 871 872 static void describeTemplateParameters(raw_ostream &Out, 873 const ArrayRef<TemplateArgument> TAList, 874 const LangOptions &LO, 875 StringRef Prefix = StringRef(), 876 StringRef Postfix = StringRef()); 877 878 static void describeTemplateParameter(raw_ostream &Out, 879 const TemplateArgument &TArg, 880 const LangOptions &LO) { 881 882 if (TArg.getKind() == TemplateArgument::ArgKind::Pack) { 883 describeTemplateParameters(Out, TArg.getPackAsArray(), LO); 884 } else { 885 TArg.print(PrintingPolicy(LO), Out); 886 } 887 } 888 889 static void describeTemplateParameters(raw_ostream &Out, 890 const ArrayRef<TemplateArgument> TAList, 891 const LangOptions &LO, 892 StringRef Prefix, StringRef Postfix) { 893 if (TAList.empty()) 894 return; 895 896 Out << Prefix; 897 for (int I = 0, Last = TAList.size() - 1; I != Last; ++I) { 898 describeTemplateParameter(Out, TAList[I], LO); 899 Out << ", "; 900 } 901 describeTemplateParameter(Out, TAList[TAList.size() - 1], LO); 902 Out << Postfix; 903 } 904 905 static void describeClass(raw_ostream &Out, const CXXRecordDecl *D, 906 StringRef Prefix = StringRef()) { 907 if (!D->getIdentifier()) 908 return; 909 Out << Prefix << '\'' << *D; 910 if (const auto T = dyn_cast<ClassTemplateSpecializationDecl>(D)) 911 describeTemplateParameters(Out, T->getTemplateArgs().asArray(), 912 D->getASTContext().getLangOpts(), "<", ">"); 913 914 Out << '\''; 915 } 916 917 static bool describeCodeDecl(raw_ostream &Out, const Decl *D, 918 bool ExtendedDescription, 919 StringRef Prefix = StringRef()) { 920 if (!D) 921 return false; 922 923 if (isa<BlockDecl>(D)) { 924 if (ExtendedDescription) 925 Out << Prefix << "anonymous block"; 926 return ExtendedDescription; 927 } 928 929 if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) { 930 Out << Prefix; 931 if (ExtendedDescription && !MD->isUserProvided()) { 932 if (MD->isExplicitlyDefaulted()) 933 Out << "defaulted "; 934 else 935 Out << "implicit "; 936 } 937 938 if (const auto *CD = dyn_cast<CXXConstructorDecl>(MD)) { 939 if (CD->isDefaultConstructor()) 940 Out << "default "; 941 else if (CD->isCopyConstructor()) 942 Out << "copy "; 943 else if (CD->isMoveConstructor()) 944 Out << "move "; 945 946 Out << "constructor"; 947 describeClass(Out, MD->getParent(), " for "); 948 } else if (isa<CXXDestructorDecl>(MD)) { 949 if (!MD->isUserProvided()) { 950 Out << "destructor"; 951 describeClass(Out, MD->getParent(), " for "); 952 } else { 953 // Use ~Foo for explicitly-written destructors. 954 Out << "'" << *MD << "'"; 955 } 956 } else if (MD->isCopyAssignmentOperator()) { 957 Out << "copy assignment operator"; 958 describeClass(Out, MD->getParent(), " for "); 959 } else if (MD->isMoveAssignmentOperator()) { 960 Out << "move assignment operator"; 961 describeClass(Out, MD->getParent(), " for "); 962 } else { 963 if (MD->getParent()->getIdentifier()) 964 Out << "'" << *MD->getParent() << "::" << *MD << "'"; 965 else 966 Out << "'" << *MD << "'"; 967 } 968 969 return true; 970 } 971 972 Out << Prefix << '\'' << cast<NamedDecl>(*D); 973 974 // Adding template parameters. 975 if (const auto FD = dyn_cast<FunctionDecl>(D)) 976 if (const TemplateArgumentList *TAList = 977 FD->getTemplateSpecializationArgs()) 978 describeTemplateParameters(Out, TAList->asArray(), 979 FD->getASTContext().getLangOpts(), "<", ">"); 980 981 Out << '\''; 982 return true; 983 } 984 985 std::shared_ptr<PathDiagnosticEventPiece> 986 PathDiagnosticCallPiece::getCallEnterEvent() const { 987 // We do not produce call enters and call exits for autosynthesized property 988 // accessors. We do generally produce them for other functions coming from 989 // the body farm because they may call callbacks that bring us back into 990 // visible code. 991 if (!Callee || IsCalleeAnAutosynthesizedPropertyAccessor) 992 return nullptr; 993 994 SmallString<256> buf; 995 llvm::raw_svector_ostream Out(buf); 996 997 Out << "Calling "; 998 describeCodeDecl(Out, Callee, /*ExtendedDescription=*/true); 999 1000 assert(callEnter.asLocation().isValid()); 1001 return std::make_shared<PathDiagnosticEventPiece>(callEnter, Out.str()); 1002 } 1003 1004 std::shared_ptr<PathDiagnosticEventPiece> 1005 PathDiagnosticCallPiece::getCallEnterWithinCallerEvent() const { 1006 if (!callEnterWithin.asLocation().isValid()) 1007 return nullptr; 1008 if (Callee->isImplicit() || !Callee->hasBody()) 1009 return nullptr; 1010 if (const auto *MD = dyn_cast<CXXMethodDecl>(Callee)) 1011 if (MD->isDefaulted()) 1012 return nullptr; 1013 1014 SmallString<256> buf; 1015 llvm::raw_svector_ostream Out(buf); 1016 1017 Out << "Entered call"; 1018 describeCodeDecl(Out, Caller, /*ExtendedDescription=*/false, " from "); 1019 1020 return std::make_shared<PathDiagnosticEventPiece>(callEnterWithin, Out.str()); 1021 } 1022 1023 std::shared_ptr<PathDiagnosticEventPiece> 1024 PathDiagnosticCallPiece::getCallExitEvent() const { 1025 // We do not produce call enters and call exits for autosynthesized property 1026 // accessors. We do generally produce them for other functions coming from 1027 // the body farm because they may call callbacks that bring us back into 1028 // visible code. 1029 if (NoExit || IsCalleeAnAutosynthesizedPropertyAccessor) 1030 return nullptr; 1031 1032 SmallString<256> buf; 1033 llvm::raw_svector_ostream Out(buf); 1034 1035 if (!CallStackMessage.empty()) { 1036 Out << CallStackMessage; 1037 } else { 1038 bool DidDescribe = describeCodeDecl(Out, Callee, 1039 /*ExtendedDescription=*/false, 1040 "Returning from "); 1041 if (!DidDescribe) 1042 Out << "Returning to caller"; 1043 } 1044 1045 assert(callReturn.asLocation().isValid()); 1046 return std::make_shared<PathDiagnosticEventPiece>(callReturn, Out.str()); 1047 } 1048 1049 static void compute_path_size(const PathPieces &pieces, unsigned &size) { 1050 for (const auto &I : pieces) { 1051 const PathDiagnosticPiece *piece = I.get(); 1052 if (const auto *cp = dyn_cast<PathDiagnosticCallPiece>(piece)) 1053 compute_path_size(cp->path, size); 1054 else 1055 ++size; 1056 } 1057 } 1058 1059 unsigned PathDiagnostic::full_size() { 1060 unsigned size = 0; 1061 compute_path_size(path, size); 1062 return size; 1063 } 1064 1065 //===----------------------------------------------------------------------===// 1066 // FoldingSet profiling methods. 1067 //===----------------------------------------------------------------------===// 1068 1069 void PathDiagnosticLocation::Profile(llvm::FoldingSetNodeID &ID) const { 1070 ID.AddInteger(Range.getBegin().getRawEncoding()); 1071 ID.AddInteger(Range.getEnd().getRawEncoding()); 1072 ID.AddInteger(Loc.getRawEncoding()); 1073 } 1074 1075 void PathDiagnosticPiece::Profile(llvm::FoldingSetNodeID &ID) const { 1076 ID.AddInteger((unsigned) getKind()); 1077 ID.AddString(str); 1078 // FIXME: Add profiling support for code hints. 1079 ID.AddInteger((unsigned) getDisplayHint()); 1080 ArrayRef<SourceRange> Ranges = getRanges(); 1081 for (const auto &I : Ranges) { 1082 ID.AddInteger(I.getBegin().getRawEncoding()); 1083 ID.AddInteger(I.getEnd().getRawEncoding()); 1084 } 1085 } 1086 1087 void PathDiagnosticCallPiece::Profile(llvm::FoldingSetNodeID &ID) const { 1088 PathDiagnosticPiece::Profile(ID); 1089 for (const auto &I : path) 1090 ID.Add(*I); 1091 } 1092 1093 void PathDiagnosticSpotPiece::Profile(llvm::FoldingSetNodeID &ID) const { 1094 PathDiagnosticPiece::Profile(ID); 1095 ID.Add(Pos); 1096 } 1097 1098 void PathDiagnosticControlFlowPiece::Profile(llvm::FoldingSetNodeID &ID) const { 1099 PathDiagnosticPiece::Profile(ID); 1100 for (const auto &I : *this) 1101 ID.Add(I); 1102 } 1103 1104 void PathDiagnosticMacroPiece::Profile(llvm::FoldingSetNodeID &ID) const { 1105 PathDiagnosticSpotPiece::Profile(ID); 1106 for (const auto &I : subPieces) 1107 ID.Add(*I); 1108 } 1109 1110 void PathDiagnosticNotePiece::Profile(llvm::FoldingSetNodeID &ID) const { 1111 PathDiagnosticSpotPiece::Profile(ID); 1112 } 1113 1114 void PathDiagnosticPopUpPiece::Profile(llvm::FoldingSetNodeID &ID) const { 1115 PathDiagnosticSpotPiece::Profile(ID); 1116 } 1117 1118 void PathDiagnostic::Profile(llvm::FoldingSetNodeID &ID) const { 1119 ID.Add(getLocation()); 1120 ID.AddString(BugType); 1121 ID.AddString(VerboseDesc); 1122 ID.AddString(Category); 1123 } 1124 1125 void PathDiagnostic::FullProfile(llvm::FoldingSetNodeID &ID) const { 1126 Profile(ID); 1127 for (const auto &I : path) 1128 ID.Add(*I); 1129 for (meta_iterator I = meta_begin(), E = meta_end(); I != E; ++I) 1130 ID.AddString(*I); 1131 } 1132 1133 LLVM_DUMP_METHOD void PathPieces::dump() const { 1134 unsigned index = 0; 1135 for (PathPieces::const_iterator I = begin(), E = end(); I != E; ++I) { 1136 llvm::errs() << "[" << index++ << "] "; 1137 (*I)->dump(); 1138 llvm::errs() << "\n"; 1139 } 1140 } 1141 1142 LLVM_DUMP_METHOD void PathDiagnosticCallPiece::dump() const { 1143 llvm::errs() << "CALL\n--------------\n"; 1144 1145 if (const Stmt *SLoc = getLocation().getStmtOrNull()) 1146 SLoc->dump(); 1147 else if (const auto *ND = dyn_cast_or_null<NamedDecl>(getCallee())) 1148 llvm::errs() << *ND << "\n"; 1149 else 1150 getLocation().dump(); 1151 } 1152 1153 LLVM_DUMP_METHOD void PathDiagnosticEventPiece::dump() const { 1154 llvm::errs() << "EVENT\n--------------\n"; 1155 llvm::errs() << getString() << "\n"; 1156 llvm::errs() << " ---- at ----\n"; 1157 getLocation().dump(); 1158 } 1159 1160 LLVM_DUMP_METHOD void PathDiagnosticControlFlowPiece::dump() const { 1161 llvm::errs() << "CONTROL\n--------------\n"; 1162 getStartLocation().dump(); 1163 llvm::errs() << " ---- to ----\n"; 1164 getEndLocation().dump(); 1165 } 1166 1167 LLVM_DUMP_METHOD void PathDiagnosticMacroPiece::dump() const { 1168 llvm::errs() << "MACRO\n--------------\n"; 1169 // FIXME: Print which macro is being invoked. 1170 } 1171 1172 LLVM_DUMP_METHOD void PathDiagnosticNotePiece::dump() const { 1173 llvm::errs() << "NOTE\n--------------\n"; 1174 llvm::errs() << getString() << "\n"; 1175 llvm::errs() << " ---- at ----\n"; 1176 getLocation().dump(); 1177 } 1178 1179 LLVM_DUMP_METHOD void PathDiagnosticPopUpPiece::dump() const { 1180 llvm::errs() << "POP-UP\n--------------\n"; 1181 llvm::errs() << getString() << "\n"; 1182 llvm::errs() << " ---- at ----\n"; 1183 getLocation().dump(); 1184 } 1185 1186 LLVM_DUMP_METHOD void PathDiagnosticLocation::dump() const { 1187 if (!isValid()) { 1188 llvm::errs() << "<INVALID>\n"; 1189 return; 1190 } 1191 1192 switch (K) { 1193 case RangeK: 1194 // FIXME: actually print the range. 1195 llvm::errs() << "<range>\n"; 1196 break; 1197 case SingleLocK: 1198 asLocation().dump(); 1199 llvm::errs() << "\n"; 1200 break; 1201 case StmtK: 1202 if (S) 1203 S->dump(); 1204 else 1205 llvm::errs() << "<NULL STMT>\n"; 1206 break; 1207 case DeclK: 1208 if (const auto *ND = dyn_cast_or_null<NamedDecl>(D)) 1209 llvm::errs() << *ND << "\n"; 1210 else if (isa<BlockDecl>(D)) 1211 // FIXME: Make this nicer. 1212 llvm::errs() << "<block>\n"; 1213 else if (D) 1214 llvm::errs() << "<unknown decl>\n"; 1215 else 1216 llvm::errs() << "<NULL DECL>\n"; 1217 break; 1218 } 1219 } 1220