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