PathDiagnostic.cpp 43 KB

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