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