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