PathDiagnostic.cpp 42 KB

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