PathDiagnostic.cpp 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185
  1. //===--- PathDiagnostic.cpp - Path-Specific Diagnostic Handling -*- C++ -*-===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file defines the PathDiagnostic-related interfaces.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
  14. #include "clang/AST/Decl.h"
  15. #include "clang/AST/DeclCXX.h"
  16. #include "clang/AST/DeclObjC.h"
  17. #include "clang/AST/Expr.h"
  18. #include "clang/AST/ExprCXX.h"
  19. #include "clang/AST/ParentMap.h"
  20. #include "clang/AST/StmtCXX.h"
  21. #include "clang/Basic/SourceManager.h"
  22. #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
  23. #include "llvm/ADT/SmallString.h"
  24. #include "llvm/ADT/StringExtras.h"
  25. #include "llvm/Support/raw_ostream.h"
  26. using namespace clang;
  27. using namespace ento;
  28. bool PathDiagnosticMacroPiece::containsEvent() const {
  29. for (PathPieces::const_iterator I = subPieces.begin(), E = subPieces.end();
  30. I!=E; ++I) {
  31. if (isa<PathDiagnosticEventPiece>(*I))
  32. return true;
  33. if (PathDiagnosticMacroPiece *MP = dyn_cast<PathDiagnosticMacroPiece>(*I))
  34. if (MP->containsEvent())
  35. return true;
  36. }
  37. return false;
  38. }
  39. static StringRef StripTrailingDots(StringRef s) {
  40. for (StringRef::size_type i = s.size(); i != 0; --i)
  41. if (s[i - 1] != '.')
  42. return s.substr(0, i);
  43. return "";
  44. }
  45. PathDiagnosticPiece::PathDiagnosticPiece(StringRef s,
  46. Kind k, DisplayHint hint)
  47. : str(StripTrailingDots(s)), kind(k), Hint(hint),
  48. LastInMainSourceFile(false) {}
  49. PathDiagnosticPiece::PathDiagnosticPiece(Kind k, DisplayHint hint)
  50. : kind(k), Hint(hint), LastInMainSourceFile(false) {}
  51. PathDiagnosticPiece::~PathDiagnosticPiece() {}
  52. PathDiagnosticEventPiece::~PathDiagnosticEventPiece() {}
  53. PathDiagnosticCallPiece::~PathDiagnosticCallPiece() {}
  54. PathDiagnosticControlFlowPiece::~PathDiagnosticControlFlowPiece() {}
  55. PathDiagnosticMacroPiece::~PathDiagnosticMacroPiece() {}
  56. PathPieces::~PathPieces() {}
  57. void PathPieces::flattenTo(PathPieces &Primary, PathPieces &Current,
  58. bool ShouldFlattenMacros) const {
  59. for (PathPieces::const_iterator I = begin(), E = end(); I != E; ++I) {
  60. PathDiagnosticPiece *Piece = I->get();
  61. switch (Piece->getKind()) {
  62. case PathDiagnosticPiece::Call: {
  63. PathDiagnosticCallPiece *Call = cast<PathDiagnosticCallPiece>(Piece);
  64. IntrusiveRefCntPtr<PathDiagnosticEventPiece> CallEnter =
  65. Call->getCallEnterEvent();
  66. if (CallEnter)
  67. Current.push_back(CallEnter);
  68. Call->path.flattenTo(Primary, Primary, ShouldFlattenMacros);
  69. IntrusiveRefCntPtr<PathDiagnosticEventPiece> callExit =
  70. Call->getCallExitEvent();
  71. if (callExit)
  72. Current.push_back(callExit);
  73. break;
  74. }
  75. case PathDiagnosticPiece::Macro: {
  76. PathDiagnosticMacroPiece *Macro = cast<PathDiagnosticMacroPiece>(Piece);
  77. if (ShouldFlattenMacros) {
  78. Macro->subPieces.flattenTo(Primary, Primary, ShouldFlattenMacros);
  79. } else {
  80. Current.push_back(Piece);
  81. PathPieces NewPath;
  82. Macro->subPieces.flattenTo(Primary, NewPath, ShouldFlattenMacros);
  83. // FIXME: This probably shouldn't mutate the original path piece.
  84. Macro->subPieces = NewPath;
  85. }
  86. break;
  87. }
  88. case PathDiagnosticPiece::Event:
  89. case PathDiagnosticPiece::ControlFlow:
  90. Current.push_back(Piece);
  91. break;
  92. }
  93. }
  94. }
  95. PathDiagnostic::~PathDiagnostic() {}
  96. PathDiagnostic::PathDiagnostic(StringRef CheckName, const Decl *declWithIssue,
  97. StringRef bugtype, StringRef verboseDesc,
  98. StringRef shortDesc, StringRef category,
  99. PathDiagnosticLocation LocationToUnique,
  100. const Decl *DeclToUnique)
  101. : CheckName(CheckName),
  102. DeclWithIssue(declWithIssue),
  103. BugType(StripTrailingDots(bugtype)),
  104. VerboseDesc(StripTrailingDots(verboseDesc)),
  105. ShortDesc(StripTrailingDots(shortDesc)),
  106. Category(StripTrailingDots(category)),
  107. UniqueingLoc(LocationToUnique),
  108. UniqueingDecl(DeclToUnique),
  109. path(pathImpl) {}
  110. static PathDiagnosticCallPiece *
  111. getFirstStackedCallToHeaderFile(PathDiagnosticCallPiece *CP,
  112. const SourceManager &SMgr) {
  113. SourceLocation CallLoc = CP->callEnter.asLocation();
  114. // If the call is within a macro, don't do anything (for now).
  115. if (CallLoc.isMacroID())
  116. return nullptr;
  117. assert(SMgr.isInMainFile(CallLoc) &&
  118. "The call piece should be in the main file.");
  119. // Check if CP represents a path through a function outside of the main file.
  120. if (!SMgr.isInMainFile(CP->callEnterWithin.asLocation()))
  121. return CP;
  122. const PathPieces &Path = CP->path;
  123. if (Path.empty())
  124. return nullptr;
  125. // Check if the last piece in the callee path is a call to a function outside
  126. // of the main file.
  127. if (PathDiagnosticCallPiece *CPInner =
  128. dyn_cast<PathDiagnosticCallPiece>(Path.back())) {
  129. return getFirstStackedCallToHeaderFile(CPInner, SMgr);
  130. }
  131. // Otherwise, the last piece is in the main file.
  132. return nullptr;
  133. }
  134. void PathDiagnostic::resetDiagnosticLocationToMainFile() {
  135. if (path.empty())
  136. return;
  137. PathDiagnosticPiece *LastP = path.back().get();
  138. assert(LastP);
  139. const SourceManager &SMgr = LastP->getLocation().getManager();
  140. // We only need to check if the report ends inside headers, if the last piece
  141. // is a call piece.
  142. if (PathDiagnosticCallPiece *CP = dyn_cast<PathDiagnosticCallPiece>(LastP)) {
  143. CP = getFirstStackedCallToHeaderFile(CP, SMgr);
  144. if (CP) {
  145. // Mark the piece.
  146. CP->setAsLastInMainSourceFile();
  147. // Update the path diagnostic message.
  148. const NamedDecl *ND = dyn_cast<NamedDecl>(CP->getCallee());
  149. if (ND) {
  150. SmallString<200> buf;
  151. llvm::raw_svector_ostream os(buf);
  152. os << " (within a call to '" << ND->getDeclName() << "')";
  153. appendToDesc(os.str());
  154. }
  155. // Reset the report containing declaration and location.
  156. DeclWithIssue = CP->getCaller();
  157. Loc = CP->getLocation();
  158. return;
  159. }
  160. }
  161. }
  162. void PathDiagnosticConsumer::anchor() { }
  163. PathDiagnosticConsumer::~PathDiagnosticConsumer() {
  164. // Delete the contents of the FoldingSet if it isn't empty already.
  165. for (llvm::FoldingSet<PathDiagnostic>::iterator it =
  166. Diags.begin(), et = Diags.end() ; it != et ; ++it) {
  167. delete &*it;
  168. }
  169. }
  170. void PathDiagnosticConsumer::HandlePathDiagnostic(
  171. std::unique_ptr<PathDiagnostic> D) {
  172. if (!D || D->path.empty())
  173. return;
  174. // We need to flatten the locations (convert Stmt* to locations) because
  175. // the referenced statements may be freed by the time the diagnostics
  176. // are emitted.
  177. D->flattenLocations();
  178. // If the PathDiagnosticConsumer does not support diagnostics that
  179. // cross file boundaries, prune out such diagnostics now.
  180. if (!supportsCrossFileDiagnostics()) {
  181. // Verify that the entire path is from the same FileID.
  182. FileID FID;
  183. const SourceManager &SMgr = D->path.front()->getLocation().getManager();
  184. SmallVector<const PathPieces *, 5> WorkList;
  185. WorkList.push_back(&D->path);
  186. while (!WorkList.empty()) {
  187. const PathPieces &path = *WorkList.pop_back_val();
  188. for (PathPieces::const_iterator I = path.begin(), E = path.end(); I != E;
  189. ++I) {
  190. const PathDiagnosticPiece *piece = I->get();
  191. FullSourceLoc L = piece->getLocation().asLocation().getExpansionLoc();
  192. if (FID.isInvalid()) {
  193. FID = SMgr.getFileID(L);
  194. } else if (SMgr.getFileID(L) != FID)
  195. return; // FIXME: Emit a warning?
  196. // Check the source ranges.
  197. ArrayRef<SourceRange> Ranges = piece->getRanges();
  198. for (ArrayRef<SourceRange>::iterator I = Ranges.begin(),
  199. E = Ranges.end(); I != E; ++I) {
  200. SourceLocation L = SMgr.getExpansionLoc(I->getBegin());
  201. if (!L.isFileID() || SMgr.getFileID(L) != FID)
  202. return; // FIXME: Emit a warning?
  203. L = SMgr.getExpansionLoc(I->getEnd());
  204. if (!L.isFileID() || SMgr.getFileID(L) != FID)
  205. return; // FIXME: Emit a warning?
  206. }
  207. if (const PathDiagnosticCallPiece *call =
  208. dyn_cast<PathDiagnosticCallPiece>(piece)) {
  209. WorkList.push_back(&call->path);
  210. }
  211. else if (const PathDiagnosticMacroPiece *macro =
  212. dyn_cast<PathDiagnosticMacroPiece>(piece)) {
  213. WorkList.push_back(&macro->subPieces);
  214. }
  215. }
  216. }
  217. if (FID.isInvalid())
  218. return; // FIXME: Emit a warning?
  219. }
  220. // Profile the node to see if we already have something matching it
  221. llvm::FoldingSetNodeID profile;
  222. D->Profile(profile);
  223. void *InsertPos = nullptr;
  224. if (PathDiagnostic *orig = Diags.FindNodeOrInsertPos(profile, InsertPos)) {
  225. // Keep the PathDiagnostic with the shorter path.
  226. // Note, the enclosing routine is called in deterministic order, so the
  227. // results will be consistent between runs (no reason to break ties if the
  228. // size is the same).
  229. const unsigned orig_size = orig->full_size();
  230. const unsigned new_size = D->full_size();
  231. if (orig_size <= new_size)
  232. return;
  233. assert(orig != D.get());
  234. Diags.RemoveNode(orig);
  235. delete orig;
  236. }
  237. Diags.InsertNode(D.release());
  238. }
  239. static Optional<bool> comparePath(const PathPieces &X, const PathPieces &Y);
  240. static Optional<bool>
  241. compareControlFlow(const PathDiagnosticControlFlowPiece &X,
  242. const PathDiagnosticControlFlowPiece &Y) {
  243. FullSourceLoc XSL = X.getStartLocation().asLocation();
  244. FullSourceLoc YSL = Y.getStartLocation().asLocation();
  245. if (XSL != YSL)
  246. return XSL.isBeforeInTranslationUnitThan(YSL);
  247. FullSourceLoc XEL = X.getEndLocation().asLocation();
  248. FullSourceLoc YEL = Y.getEndLocation().asLocation();
  249. if (XEL != YEL)
  250. return XEL.isBeforeInTranslationUnitThan(YEL);
  251. return None;
  252. }
  253. static Optional<bool> compareMacro(const PathDiagnosticMacroPiece &X,
  254. const PathDiagnosticMacroPiece &Y) {
  255. return comparePath(X.subPieces, Y.subPieces);
  256. }
  257. static Optional<bool> compareCall(const PathDiagnosticCallPiece &X,
  258. const PathDiagnosticCallPiece &Y) {
  259. FullSourceLoc X_CEL = X.callEnter.asLocation();
  260. FullSourceLoc Y_CEL = Y.callEnter.asLocation();
  261. if (X_CEL != Y_CEL)
  262. return X_CEL.isBeforeInTranslationUnitThan(Y_CEL);
  263. FullSourceLoc X_CEWL = X.callEnterWithin.asLocation();
  264. FullSourceLoc Y_CEWL = Y.callEnterWithin.asLocation();
  265. if (X_CEWL != Y_CEWL)
  266. return X_CEWL.isBeforeInTranslationUnitThan(Y_CEWL);
  267. FullSourceLoc X_CRL = X.callReturn.asLocation();
  268. FullSourceLoc Y_CRL = Y.callReturn.asLocation();
  269. if (X_CRL != Y_CRL)
  270. return X_CRL.isBeforeInTranslationUnitThan(Y_CRL);
  271. return comparePath(X.path, Y.path);
  272. }
  273. static Optional<bool> comparePiece(const PathDiagnosticPiece &X,
  274. const PathDiagnosticPiece &Y) {
  275. if (X.getKind() != Y.getKind())
  276. return X.getKind() < Y.getKind();
  277. FullSourceLoc XL = X.getLocation().asLocation();
  278. FullSourceLoc YL = Y.getLocation().asLocation();
  279. if (XL != YL)
  280. return XL.isBeforeInTranslationUnitThan(YL);
  281. if (X.getString() != Y.getString())
  282. return X.getString() < Y.getString();
  283. if (X.getRanges().size() != Y.getRanges().size())
  284. return X.getRanges().size() < Y.getRanges().size();
  285. const SourceManager &SM = XL.getManager();
  286. for (unsigned i = 0, n = X.getRanges().size(); i < n; ++i) {
  287. SourceRange XR = X.getRanges()[i];
  288. SourceRange YR = Y.getRanges()[i];
  289. if (XR != YR) {
  290. if (XR.getBegin() != YR.getBegin())
  291. return SM.isBeforeInTranslationUnit(XR.getBegin(), YR.getBegin());
  292. return SM.isBeforeInTranslationUnit(XR.getEnd(), YR.getEnd());
  293. }
  294. }
  295. switch (X.getKind()) {
  296. case clang::ento::PathDiagnosticPiece::ControlFlow:
  297. return compareControlFlow(cast<PathDiagnosticControlFlowPiece>(X),
  298. cast<PathDiagnosticControlFlowPiece>(Y));
  299. case clang::ento::PathDiagnosticPiece::Event:
  300. return None;
  301. case clang::ento::PathDiagnosticPiece::Macro:
  302. return compareMacro(cast<PathDiagnosticMacroPiece>(X),
  303. cast<PathDiagnosticMacroPiece>(Y));
  304. case clang::ento::PathDiagnosticPiece::Call:
  305. return compareCall(cast<PathDiagnosticCallPiece>(X),
  306. cast<PathDiagnosticCallPiece>(Y));
  307. }
  308. llvm_unreachable("all cases handled");
  309. }
  310. static Optional<bool> comparePath(const PathPieces &X, const PathPieces &Y) {
  311. if (X.size() != Y.size())
  312. return X.size() < Y.size();
  313. PathPieces::const_iterator X_I = X.begin(), X_end = X.end();
  314. PathPieces::const_iterator Y_I = Y.begin(), Y_end = Y.end();
  315. for ( ; X_I != X_end && Y_I != Y_end; ++X_I, ++Y_I) {
  316. Optional<bool> b = comparePiece(**X_I, **Y_I);
  317. if (b.hasValue())
  318. return b.getValue();
  319. }
  320. return None;
  321. }
  322. static bool compare(const PathDiagnostic &X, const PathDiagnostic &Y) {
  323. FullSourceLoc XL = X.getLocation().asLocation();
  324. FullSourceLoc YL = Y.getLocation().asLocation();
  325. if (XL != YL)
  326. return XL.isBeforeInTranslationUnitThan(YL);
  327. if (X.getBugType() != Y.getBugType())
  328. return X.getBugType() < Y.getBugType();
  329. if (X.getCategory() != Y.getCategory())
  330. return X.getCategory() < Y.getCategory();
  331. if (X.getVerboseDescription() != Y.getVerboseDescription())
  332. return X.getVerboseDescription() < Y.getVerboseDescription();
  333. if (X.getShortDescription() != Y.getShortDescription())
  334. return X.getShortDescription() < Y.getShortDescription();
  335. if (X.getDeclWithIssue() != Y.getDeclWithIssue()) {
  336. const Decl *XD = X.getDeclWithIssue();
  337. if (!XD)
  338. return true;
  339. const Decl *YD = Y.getDeclWithIssue();
  340. if (!YD)
  341. return false;
  342. SourceLocation XDL = XD->getLocation();
  343. SourceLocation YDL = YD->getLocation();
  344. if (XDL != YDL) {
  345. const SourceManager &SM = XL.getManager();
  346. return SM.isBeforeInTranslationUnit(XDL, YDL);
  347. }
  348. }
  349. PathDiagnostic::meta_iterator XI = X.meta_begin(), XE = X.meta_end();
  350. PathDiagnostic::meta_iterator YI = Y.meta_begin(), YE = Y.meta_end();
  351. if (XE - XI != YE - YI)
  352. return (XE - XI) < (YE - YI);
  353. for ( ; XI != XE ; ++XI, ++YI) {
  354. if (*XI != *YI)
  355. return (*XI) < (*YI);
  356. }
  357. Optional<bool> b = comparePath(X.path, Y.path);
  358. assert(b.hasValue());
  359. return b.getValue();
  360. }
  361. void PathDiagnosticConsumer::FlushDiagnostics(
  362. PathDiagnosticConsumer::FilesMade *Files) {
  363. if (flushed)
  364. return;
  365. flushed = true;
  366. std::vector<const PathDiagnostic *> BatchDiags;
  367. for (llvm::FoldingSet<PathDiagnostic>::iterator it = Diags.begin(),
  368. et = Diags.end(); it != et; ++it) {
  369. const PathDiagnostic *D = &*it;
  370. BatchDiags.push_back(D);
  371. }
  372. // Sort the diagnostics so that they are always emitted in a deterministic
  373. // order.
  374. int (*Comp)(const PathDiagnostic *const *, const PathDiagnostic *const *) =
  375. [](const PathDiagnostic *const *X, const PathDiagnostic *const *Y) {
  376. assert(*X != *Y && "PathDiagnostics not uniqued!");
  377. if (compare(**X, **Y))
  378. return -1;
  379. assert(compare(**Y, **X) && "Not a total order!");
  380. return 1;
  381. };
  382. array_pod_sort(BatchDiags.begin(), BatchDiags.end(), Comp);
  383. FlushDiagnosticsImpl(BatchDiags, Files);
  384. // Delete the flushed diagnostics.
  385. for (std::vector<const PathDiagnostic *>::iterator it = BatchDiags.begin(),
  386. et = BatchDiags.end(); it != et; ++it) {
  387. const PathDiagnostic *D = *it;
  388. delete D;
  389. }
  390. // Clear out the FoldingSet.
  391. Diags.clear();
  392. }
  393. PathDiagnosticConsumer::FilesMade::~FilesMade() {
  394. for (PDFileEntry &Entry : Set)
  395. Entry.~PDFileEntry();
  396. }
  397. void PathDiagnosticConsumer::FilesMade::addDiagnostic(const PathDiagnostic &PD,
  398. StringRef ConsumerName,
  399. StringRef FileName) {
  400. llvm::FoldingSetNodeID NodeID;
  401. NodeID.Add(PD);
  402. void *InsertPos;
  403. PDFileEntry *Entry = Set.FindNodeOrInsertPos(NodeID, InsertPos);
  404. if (!Entry) {
  405. Entry = Alloc.Allocate<PDFileEntry>();
  406. Entry = new (Entry) PDFileEntry(NodeID);
  407. Set.InsertNode(Entry, InsertPos);
  408. }
  409. // Allocate persistent storage for the file name.
  410. char *FileName_cstr = (char*) Alloc.Allocate(FileName.size(), 1);
  411. memcpy(FileName_cstr, FileName.data(), FileName.size());
  412. Entry->files.push_back(std::make_pair(ConsumerName,
  413. StringRef(FileName_cstr,
  414. FileName.size())));
  415. }
  416. PathDiagnosticConsumer::PDFileEntry::ConsumerFiles *
  417. PathDiagnosticConsumer::FilesMade::getFiles(const PathDiagnostic &PD) {
  418. llvm::FoldingSetNodeID NodeID;
  419. NodeID.Add(PD);
  420. void *InsertPos;
  421. PDFileEntry *Entry = Set.FindNodeOrInsertPos(NodeID, InsertPos);
  422. if (!Entry)
  423. return nullptr;
  424. return &Entry->files;
  425. }
  426. //===----------------------------------------------------------------------===//
  427. // PathDiagnosticLocation methods.
  428. //===----------------------------------------------------------------------===//
  429. static SourceLocation getValidSourceLocation(const Stmt* S,
  430. LocationOrAnalysisDeclContext LAC,
  431. bool UseEnd = false) {
  432. SourceLocation L = UseEnd ? S->getLocEnd() : S->getLocStart();
  433. assert(!LAC.isNull() && "A valid LocationContext or AnalysisDeclContext should "
  434. "be passed to PathDiagnosticLocation upon creation.");
  435. // S might be a temporary statement that does not have a location in the
  436. // source code, so find an enclosing statement and use its location.
  437. if (!L.isValid()) {
  438. AnalysisDeclContext *ADC;
  439. if (LAC.is<const LocationContext*>())
  440. ADC = LAC.get<const LocationContext*>()->getAnalysisDeclContext();
  441. else
  442. ADC = LAC.get<AnalysisDeclContext*>();
  443. ParentMap &PM = ADC->getParentMap();
  444. const Stmt *Parent = S;
  445. do {
  446. Parent = PM.getParent(Parent);
  447. // In rare cases, we have implicit top-level expressions,
  448. // such as arguments for implicit member initializers.
  449. // In this case, fall back to the start of the body (even if we were
  450. // asked for the statement end location).
  451. if (!Parent) {
  452. const Stmt *Body = ADC->getBody();
  453. if (Body)
  454. L = Body->getLocStart();
  455. else
  456. L = ADC->getDecl()->getLocEnd();
  457. break;
  458. }
  459. L = UseEnd ? Parent->getLocEnd() : Parent->getLocStart();
  460. } while (!L.isValid());
  461. }
  462. return L;
  463. }
  464. static PathDiagnosticLocation
  465. getLocationForCaller(const StackFrameContext *SFC,
  466. const LocationContext *CallerCtx,
  467. const SourceManager &SM) {
  468. const CFGBlock &Block = *SFC->getCallSiteBlock();
  469. CFGElement Source = Block[SFC->getIndex()];
  470. switch (Source.getKind()) {
  471. case CFGElement::Statement:
  472. return PathDiagnosticLocation(Source.castAs<CFGStmt>().getStmt(),
  473. SM, CallerCtx);
  474. case CFGElement::Initializer: {
  475. const CFGInitializer &Init = Source.castAs<CFGInitializer>();
  476. return PathDiagnosticLocation(Init.getInitializer()->getInit(),
  477. SM, CallerCtx);
  478. }
  479. case CFGElement::AutomaticObjectDtor: {
  480. const CFGAutomaticObjDtor &Dtor = Source.castAs<CFGAutomaticObjDtor>();
  481. return PathDiagnosticLocation::createEnd(Dtor.getTriggerStmt(),
  482. SM, CallerCtx);
  483. }
  484. case CFGElement::DeleteDtor: {
  485. const CFGDeleteDtor &Dtor = Source.castAs<CFGDeleteDtor>();
  486. return PathDiagnosticLocation(Dtor.getDeleteExpr(), SM, CallerCtx);
  487. }
  488. case CFGElement::BaseDtor:
  489. case CFGElement::MemberDtor: {
  490. const AnalysisDeclContext *CallerInfo = CallerCtx->getAnalysisDeclContext();
  491. if (const Stmt *CallerBody = CallerInfo->getBody())
  492. return PathDiagnosticLocation::createEnd(CallerBody, SM, CallerCtx);
  493. return PathDiagnosticLocation::create(CallerInfo->getDecl(), SM);
  494. }
  495. case CFGElement::TemporaryDtor:
  496. case CFGElement::NewAllocator:
  497. llvm_unreachable("not yet implemented!");
  498. }
  499. llvm_unreachable("Unknown CFGElement kind");
  500. }
  501. PathDiagnosticLocation
  502. PathDiagnosticLocation::createBegin(const Decl *D,
  503. const SourceManager &SM) {
  504. return PathDiagnosticLocation(D->getLocStart(), SM, SingleLocK);
  505. }
  506. PathDiagnosticLocation
  507. PathDiagnosticLocation::createBegin(const Stmt *S,
  508. const SourceManager &SM,
  509. LocationOrAnalysisDeclContext LAC) {
  510. return PathDiagnosticLocation(getValidSourceLocation(S, LAC),
  511. SM, SingleLocK);
  512. }
  513. PathDiagnosticLocation
  514. PathDiagnosticLocation::createEnd(const Stmt *S,
  515. const SourceManager &SM,
  516. LocationOrAnalysisDeclContext LAC) {
  517. if (const CompoundStmt *CS = dyn_cast<CompoundStmt>(S))
  518. return createEndBrace(CS, SM);
  519. return PathDiagnosticLocation(getValidSourceLocation(S, LAC, /*End=*/true),
  520. SM, SingleLocK);
  521. }
  522. PathDiagnosticLocation
  523. PathDiagnosticLocation::createOperatorLoc(const BinaryOperator *BO,
  524. const SourceManager &SM) {
  525. return PathDiagnosticLocation(BO->getOperatorLoc(), SM, SingleLocK);
  526. }
  527. PathDiagnosticLocation
  528. PathDiagnosticLocation::createConditionalColonLoc(
  529. const ConditionalOperator *CO,
  530. const SourceManager &SM) {
  531. return PathDiagnosticLocation(CO->getColonLoc(), SM, SingleLocK);
  532. }
  533. PathDiagnosticLocation
  534. PathDiagnosticLocation::createMemberLoc(const MemberExpr *ME,
  535. const SourceManager &SM) {
  536. return PathDiagnosticLocation(ME->getMemberLoc(), SM, SingleLocK);
  537. }
  538. PathDiagnosticLocation
  539. PathDiagnosticLocation::createBeginBrace(const CompoundStmt *CS,
  540. const SourceManager &SM) {
  541. SourceLocation L = CS->getLBracLoc();
  542. return PathDiagnosticLocation(L, SM, SingleLocK);
  543. }
  544. PathDiagnosticLocation
  545. PathDiagnosticLocation::createEndBrace(const CompoundStmt *CS,
  546. const SourceManager &SM) {
  547. SourceLocation L = CS->getRBracLoc();
  548. return PathDiagnosticLocation(L, SM, SingleLocK);
  549. }
  550. PathDiagnosticLocation
  551. PathDiagnosticLocation::createDeclBegin(const LocationContext *LC,
  552. const SourceManager &SM) {
  553. // FIXME: Should handle CXXTryStmt if analyser starts supporting C++.
  554. if (const CompoundStmt *CS =
  555. dyn_cast_or_null<CompoundStmt>(LC->getDecl()->getBody()))
  556. if (!CS->body_empty()) {
  557. SourceLocation Loc = (*CS->body_begin())->getLocStart();
  558. return PathDiagnosticLocation(Loc, SM, SingleLocK);
  559. }
  560. return PathDiagnosticLocation();
  561. }
  562. PathDiagnosticLocation
  563. PathDiagnosticLocation::createDeclEnd(const LocationContext *LC,
  564. const SourceManager &SM) {
  565. SourceLocation L = LC->getDecl()->getBodyRBrace();
  566. return PathDiagnosticLocation(L, SM, SingleLocK);
  567. }
  568. PathDiagnosticLocation
  569. PathDiagnosticLocation::create(const ProgramPoint& P,
  570. const SourceManager &SMng) {
  571. const Stmt* S = nullptr;
  572. if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
  573. const CFGBlock *BSrc = BE->getSrc();
  574. S = BSrc->getTerminatorCondition();
  575. } else if (Optional<StmtPoint> SP = P.getAs<StmtPoint>()) {
  576. S = SP->getStmt();
  577. if (P.getAs<PostStmtPurgeDeadSymbols>())
  578. return PathDiagnosticLocation::createEnd(S, SMng, P.getLocationContext());
  579. } else if (Optional<PostInitializer> PIP = P.getAs<PostInitializer>()) {
  580. return PathDiagnosticLocation(PIP->getInitializer()->getSourceLocation(),
  581. SMng);
  582. } else if (Optional<PostImplicitCall> PIE = P.getAs<PostImplicitCall>()) {
  583. return PathDiagnosticLocation(PIE->getLocation(), SMng);
  584. } else if (Optional<CallEnter> CE = P.getAs<CallEnter>()) {
  585. return getLocationForCaller(CE->getCalleeContext(),
  586. CE->getLocationContext(),
  587. SMng);
  588. } else if (Optional<CallExitEnd> CEE = P.getAs<CallExitEnd>()) {
  589. return getLocationForCaller(CEE->getCalleeContext(),
  590. CEE->getLocationContext(),
  591. SMng);
  592. } else {
  593. llvm_unreachable("Unexpected ProgramPoint");
  594. }
  595. return PathDiagnosticLocation(S, SMng, P.getLocationContext());
  596. }
  597. const Stmt *PathDiagnosticLocation::getStmt(const ExplodedNode *N) {
  598. ProgramPoint P = N->getLocation();
  599. if (Optional<StmtPoint> SP = P.getAs<StmtPoint>())
  600. return SP->getStmt();
  601. if (Optional<BlockEdge> BE = P.getAs<BlockEdge>())
  602. return BE->getSrc()->getTerminator();
  603. if (Optional<CallEnter> CE = P.getAs<CallEnter>())
  604. return CE->getCallExpr();
  605. if (Optional<CallExitEnd> CEE = P.getAs<CallExitEnd>())
  606. return CEE->getCalleeContext()->getCallSite();
  607. if (Optional<PostInitializer> PIPP = P.getAs<PostInitializer>())
  608. return PIPP->getInitializer()->getInit();
  609. return nullptr;
  610. }
  611. const Stmt *PathDiagnosticLocation::getNextStmt(const ExplodedNode *N) {
  612. for (N = N->getFirstSucc(); N; N = N->getFirstSucc()) {
  613. if (const Stmt *S = getStmt(N)) {
  614. // Check if the statement is '?' or '&&'/'||'. These are "merges",
  615. // not actual statement points.
  616. switch (S->getStmtClass()) {
  617. case Stmt::ChooseExprClass:
  618. case Stmt::BinaryConditionalOperatorClass:
  619. case Stmt::ConditionalOperatorClass:
  620. continue;
  621. case Stmt::BinaryOperatorClass: {
  622. BinaryOperatorKind Op = cast<BinaryOperator>(S)->getOpcode();
  623. if (Op == BO_LAnd || Op == BO_LOr)
  624. continue;
  625. break;
  626. }
  627. default:
  628. break;
  629. }
  630. // We found the statement, so return it.
  631. return S;
  632. }
  633. }
  634. return nullptr;
  635. }
  636. PathDiagnosticLocation
  637. PathDiagnosticLocation::createEndOfPath(const ExplodedNode *N,
  638. const SourceManager &SM) {
  639. assert(N && "Cannot create a location with a null node.");
  640. const Stmt *S = getStmt(N);
  641. if (!S) {
  642. // If this is an implicit call, return the implicit call point location.
  643. if (Optional<PreImplicitCall> PIE = N->getLocationAs<PreImplicitCall>())
  644. return PathDiagnosticLocation(PIE->getLocation(), SM);
  645. S = getNextStmt(N);
  646. }
  647. if (S) {
  648. ProgramPoint P = N->getLocation();
  649. const LocationContext *LC = N->getLocationContext();
  650. // For member expressions, return the location of the '.' or '->'.
  651. if (const MemberExpr *ME = dyn_cast<MemberExpr>(S))
  652. return PathDiagnosticLocation::createMemberLoc(ME, SM);
  653. // For binary operators, return the location of the operator.
  654. if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S))
  655. return PathDiagnosticLocation::createOperatorLoc(B, SM);
  656. if (P.getAs<PostStmtPurgeDeadSymbols>())
  657. return PathDiagnosticLocation::createEnd(S, SM, LC);
  658. if (S->getLocStart().isValid())
  659. return PathDiagnosticLocation(S, SM, LC);
  660. return PathDiagnosticLocation(getValidSourceLocation(S, LC), SM);
  661. }
  662. return createDeclEnd(N->getLocationContext(), SM);
  663. }
  664. PathDiagnosticLocation PathDiagnosticLocation::createSingleLocation(
  665. const PathDiagnosticLocation &PDL) {
  666. FullSourceLoc L = PDL.asLocation();
  667. return PathDiagnosticLocation(L, L.getManager(), SingleLocK);
  668. }
  669. FullSourceLoc
  670. PathDiagnosticLocation::genLocation(SourceLocation L,
  671. LocationOrAnalysisDeclContext LAC) const {
  672. assert(isValid());
  673. // Note that we want a 'switch' here so that the compiler can warn us in
  674. // case we add more cases.
  675. switch (K) {
  676. case SingleLocK:
  677. case RangeK:
  678. break;
  679. case StmtK:
  680. // Defensive checking.
  681. if (!S)
  682. break;
  683. return FullSourceLoc(getValidSourceLocation(S, LAC),
  684. const_cast<SourceManager&>(*SM));
  685. case DeclK:
  686. // Defensive checking.
  687. if (!D)
  688. break;
  689. return FullSourceLoc(D->getLocation(), const_cast<SourceManager&>(*SM));
  690. }
  691. return FullSourceLoc(L, const_cast<SourceManager&>(*SM));
  692. }
  693. PathDiagnosticRange
  694. PathDiagnosticLocation::genRange(LocationOrAnalysisDeclContext LAC) const {
  695. assert(isValid());
  696. // Note that we want a 'switch' here so that the compiler can warn us in
  697. // case we add more cases.
  698. switch (K) {
  699. case SingleLocK:
  700. return PathDiagnosticRange(SourceRange(Loc,Loc), true);
  701. case RangeK:
  702. break;
  703. case StmtK: {
  704. const Stmt *S = asStmt();
  705. switch (S->getStmtClass()) {
  706. default:
  707. break;
  708. case Stmt::DeclStmtClass: {
  709. const DeclStmt *DS = cast<DeclStmt>(S);
  710. if (DS->isSingleDecl()) {
  711. // Should always be the case, but we'll be defensive.
  712. return SourceRange(DS->getLocStart(),
  713. DS->getSingleDecl()->getLocation());
  714. }
  715. break;
  716. }
  717. // FIXME: Provide better range information for different
  718. // terminators.
  719. case Stmt::IfStmtClass:
  720. case Stmt::WhileStmtClass:
  721. case Stmt::DoStmtClass:
  722. case Stmt::ForStmtClass:
  723. case Stmt::ChooseExprClass:
  724. case Stmt::IndirectGotoStmtClass:
  725. case Stmt::SwitchStmtClass:
  726. case Stmt::BinaryConditionalOperatorClass:
  727. case Stmt::ConditionalOperatorClass:
  728. case Stmt::ObjCForCollectionStmtClass: {
  729. SourceLocation L = getValidSourceLocation(S, LAC);
  730. return SourceRange(L, L);
  731. }
  732. }
  733. SourceRange R = S->getSourceRange();
  734. if (R.isValid())
  735. return R;
  736. break;
  737. }
  738. case DeclK:
  739. if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
  740. return MD->getSourceRange();
  741. if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
  742. if (Stmt *Body = FD->getBody())
  743. return Body->getSourceRange();
  744. }
  745. else {
  746. SourceLocation L = D->getLocation();
  747. return PathDiagnosticRange(SourceRange(L, L), true);
  748. }
  749. }
  750. return SourceRange(Loc,Loc);
  751. }
  752. void PathDiagnosticLocation::flatten() {
  753. if (K == StmtK) {
  754. K = RangeK;
  755. S = nullptr;
  756. D = nullptr;
  757. }
  758. else if (K == DeclK) {
  759. K = SingleLocK;
  760. S = nullptr;
  761. D = nullptr;
  762. }
  763. }
  764. //===----------------------------------------------------------------------===//
  765. // Manipulation of PathDiagnosticCallPieces.
  766. //===----------------------------------------------------------------------===//
  767. PathDiagnosticCallPiece *
  768. PathDiagnosticCallPiece::construct(const ExplodedNode *N,
  769. const CallExitEnd &CE,
  770. const SourceManager &SM) {
  771. const Decl *caller = CE.getLocationContext()->getDecl();
  772. PathDiagnosticLocation pos = getLocationForCaller(CE.getCalleeContext(),
  773. CE.getLocationContext(),
  774. SM);
  775. return new PathDiagnosticCallPiece(caller, pos);
  776. }
  777. PathDiagnosticCallPiece *
  778. PathDiagnosticCallPiece::construct(PathPieces &path,
  779. const Decl *caller) {
  780. PathDiagnosticCallPiece *C = new PathDiagnosticCallPiece(path, caller);
  781. path.clear();
  782. path.push_front(C);
  783. return C;
  784. }
  785. void PathDiagnosticCallPiece::setCallee(const CallEnter &CE,
  786. const SourceManager &SM) {
  787. const StackFrameContext *CalleeCtx = CE.getCalleeContext();
  788. Callee = CalleeCtx->getDecl();
  789. callEnterWithin = PathDiagnosticLocation::createBegin(Callee, SM);
  790. callEnter = getLocationForCaller(CalleeCtx, CE.getLocationContext(), SM);
  791. }
  792. static inline void describeClass(raw_ostream &Out, const CXXRecordDecl *D,
  793. StringRef Prefix = StringRef()) {
  794. if (!D->getIdentifier())
  795. return;
  796. Out << Prefix << '\'' << *D << '\'';
  797. }
  798. static bool describeCodeDecl(raw_ostream &Out, const Decl *D,
  799. bool ExtendedDescription,
  800. StringRef Prefix = StringRef()) {
  801. if (!D)
  802. return false;
  803. if (isa<BlockDecl>(D)) {
  804. if (ExtendedDescription)
  805. Out << Prefix << "anonymous block";
  806. return ExtendedDescription;
  807. }
  808. if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
  809. Out << Prefix;
  810. if (ExtendedDescription && !MD->isUserProvided()) {
  811. if (MD->isExplicitlyDefaulted())
  812. Out << "defaulted ";
  813. else
  814. Out << "implicit ";
  815. }
  816. if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(MD)) {
  817. if (CD->isDefaultConstructor())
  818. Out << "default ";
  819. else if (CD->isCopyConstructor())
  820. Out << "copy ";
  821. else if (CD->isMoveConstructor())
  822. Out << "move ";
  823. Out << "constructor";
  824. describeClass(Out, MD->getParent(), " for ");
  825. } else if (isa<CXXDestructorDecl>(MD)) {
  826. if (!MD->isUserProvided()) {
  827. Out << "destructor";
  828. describeClass(Out, MD->getParent(), " for ");
  829. } else {
  830. // Use ~Foo for explicitly-written destructors.
  831. Out << "'" << *MD << "'";
  832. }
  833. } else if (MD->isCopyAssignmentOperator()) {
  834. Out << "copy assignment operator";
  835. describeClass(Out, MD->getParent(), " for ");
  836. } else if (MD->isMoveAssignmentOperator()) {
  837. Out << "move assignment operator";
  838. describeClass(Out, MD->getParent(), " for ");
  839. } else {
  840. if (MD->getParent()->getIdentifier())
  841. Out << "'" << *MD->getParent() << "::" << *MD << "'";
  842. else
  843. Out << "'" << *MD << "'";
  844. }
  845. return true;
  846. }
  847. Out << Prefix << '\'' << cast<NamedDecl>(*D) << '\'';
  848. return true;
  849. }
  850. IntrusiveRefCntPtr<PathDiagnosticEventPiece>
  851. PathDiagnosticCallPiece::getCallEnterEvent() const {
  852. if (!Callee)
  853. return nullptr;
  854. SmallString<256> buf;
  855. llvm::raw_svector_ostream Out(buf);
  856. Out << "Calling ";
  857. describeCodeDecl(Out, Callee, /*ExtendedDescription=*/true);
  858. assert(callEnter.asLocation().isValid());
  859. return new PathDiagnosticEventPiece(callEnter, Out.str());
  860. }
  861. IntrusiveRefCntPtr<PathDiagnosticEventPiece>
  862. PathDiagnosticCallPiece::getCallEnterWithinCallerEvent() const {
  863. if (!callEnterWithin.asLocation().isValid())
  864. return nullptr;
  865. if (Callee->isImplicit() || !Callee->hasBody())
  866. return nullptr;
  867. if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Callee))
  868. if (MD->isDefaulted())
  869. return nullptr;
  870. SmallString<256> buf;
  871. llvm::raw_svector_ostream Out(buf);
  872. Out << "Entered call";
  873. describeCodeDecl(Out, Caller, /*ExtendedDescription=*/false, " from ");
  874. return new PathDiagnosticEventPiece(callEnterWithin, Out.str());
  875. }
  876. IntrusiveRefCntPtr<PathDiagnosticEventPiece>
  877. PathDiagnosticCallPiece::getCallExitEvent() const {
  878. if (NoExit)
  879. return nullptr;
  880. SmallString<256> buf;
  881. llvm::raw_svector_ostream Out(buf);
  882. if (!CallStackMessage.empty()) {
  883. Out << CallStackMessage;
  884. } else {
  885. bool DidDescribe = describeCodeDecl(Out, Callee,
  886. /*ExtendedDescription=*/false,
  887. "Returning from ");
  888. if (!DidDescribe)
  889. Out << "Returning to caller";
  890. }
  891. assert(callReturn.asLocation().isValid());
  892. return new PathDiagnosticEventPiece(callReturn, Out.str());
  893. }
  894. static void compute_path_size(const PathPieces &pieces, unsigned &size) {
  895. for (PathPieces::const_iterator it = pieces.begin(),
  896. et = pieces.end(); it != et; ++it) {
  897. const PathDiagnosticPiece *piece = it->get();
  898. if (const PathDiagnosticCallPiece *cp =
  899. dyn_cast<PathDiagnosticCallPiece>(piece)) {
  900. compute_path_size(cp->path, size);
  901. }
  902. else
  903. ++size;
  904. }
  905. }
  906. unsigned PathDiagnostic::full_size() {
  907. unsigned size = 0;
  908. compute_path_size(path, size);
  909. return size;
  910. }
  911. //===----------------------------------------------------------------------===//
  912. // FoldingSet profiling methods.
  913. //===----------------------------------------------------------------------===//
  914. void PathDiagnosticLocation::Profile(llvm::FoldingSetNodeID &ID) const {
  915. ID.AddInteger(Range.getBegin().getRawEncoding());
  916. ID.AddInteger(Range.getEnd().getRawEncoding());
  917. ID.AddInteger(Loc.getRawEncoding());
  918. return;
  919. }
  920. void PathDiagnosticPiece::Profile(llvm::FoldingSetNodeID &ID) const {
  921. ID.AddInteger((unsigned) getKind());
  922. ID.AddString(str);
  923. // FIXME: Add profiling support for code hints.
  924. ID.AddInteger((unsigned) getDisplayHint());
  925. ArrayRef<SourceRange> Ranges = getRanges();
  926. for (ArrayRef<SourceRange>::iterator I = Ranges.begin(), E = Ranges.end();
  927. I != E; ++I) {
  928. ID.AddInteger(I->getBegin().getRawEncoding());
  929. ID.AddInteger(I->getEnd().getRawEncoding());
  930. }
  931. }
  932. void PathDiagnosticCallPiece::Profile(llvm::FoldingSetNodeID &ID) const {
  933. PathDiagnosticPiece::Profile(ID);
  934. for (PathPieces::const_iterator it = path.begin(),
  935. et = path.end(); it != et; ++it) {
  936. ID.Add(**it);
  937. }
  938. }
  939. void PathDiagnosticSpotPiece::Profile(llvm::FoldingSetNodeID &ID) const {
  940. PathDiagnosticPiece::Profile(ID);
  941. ID.Add(Pos);
  942. }
  943. void PathDiagnosticControlFlowPiece::Profile(llvm::FoldingSetNodeID &ID) const {
  944. PathDiagnosticPiece::Profile(ID);
  945. for (const_iterator I = begin(), E = end(); I != E; ++I)
  946. ID.Add(*I);
  947. }
  948. void PathDiagnosticMacroPiece::Profile(llvm::FoldingSetNodeID &ID) const {
  949. PathDiagnosticSpotPiece::Profile(ID);
  950. for (PathPieces::const_iterator I = subPieces.begin(), E = subPieces.end();
  951. I != E; ++I)
  952. ID.Add(**I);
  953. }
  954. void PathDiagnostic::Profile(llvm::FoldingSetNodeID &ID) const {
  955. ID.Add(getLocation());
  956. ID.AddString(BugType);
  957. ID.AddString(VerboseDesc);
  958. ID.AddString(Category);
  959. }
  960. void PathDiagnostic::FullProfile(llvm::FoldingSetNodeID &ID) const {
  961. Profile(ID);
  962. for (PathPieces::const_iterator I = path.begin(), E = path.end(); I != E; ++I)
  963. ID.Add(**I);
  964. for (meta_iterator I = meta_begin(), E = meta_end(); I != E; ++I)
  965. ID.AddString(*I);
  966. }
  967. StackHintGenerator::~StackHintGenerator() {}
  968. std::string StackHintGeneratorForSymbol::getMessage(const ExplodedNode *N){
  969. ProgramPoint P = N->getLocation();
  970. CallExitEnd CExit = P.castAs<CallExitEnd>();
  971. // FIXME: Use CallEvent to abstract this over all calls.
  972. const Stmt *CallSite = CExit.getCalleeContext()->getCallSite();
  973. const CallExpr *CE = dyn_cast_or_null<CallExpr>(CallSite);
  974. if (!CE)
  975. return "";
  976. if (!N)
  977. return getMessageForSymbolNotFound();
  978. // Check if one of the parameters are set to the interesting symbol.
  979. ProgramStateRef State = N->getState();
  980. const LocationContext *LCtx = N->getLocationContext();
  981. unsigned ArgIndex = 0;
  982. for (CallExpr::const_arg_iterator I = CE->arg_begin(),
  983. E = CE->arg_end(); I != E; ++I, ++ArgIndex){
  984. SVal SV = State->getSVal(*I, LCtx);
  985. // Check if the variable corresponding to the symbol is passed by value.
  986. SymbolRef AS = SV.getAsLocSymbol();
  987. if (AS == Sym) {
  988. return getMessageForArg(*I, ArgIndex);
  989. }
  990. // Check if the parameter is a pointer to the symbol.
  991. if (Optional<loc::MemRegionVal> Reg = SV.getAs<loc::MemRegionVal>()) {
  992. SVal PSV = State->getSVal(Reg->getRegion());
  993. SymbolRef AS = PSV.getAsLocSymbol();
  994. if (AS == Sym) {
  995. return getMessageForArg(*I, ArgIndex);
  996. }
  997. }
  998. }
  999. // Check if we are returning the interesting symbol.
  1000. SVal SV = State->getSVal(CE, LCtx);
  1001. SymbolRef RetSym = SV.getAsLocSymbol();
  1002. if (RetSym == Sym) {
  1003. return getMessageForReturn(CE);
  1004. }
  1005. return getMessageForSymbolNotFound();
  1006. }
  1007. std::string StackHintGeneratorForSymbol::getMessageForArg(const Expr *ArgE,
  1008. unsigned ArgIndex) {
  1009. // Printed parameters start at 1, not 0.
  1010. ++ArgIndex;
  1011. SmallString<200> buf;
  1012. llvm::raw_svector_ostream os(buf);
  1013. os << Msg << " via " << ArgIndex << llvm::getOrdinalSuffix(ArgIndex)
  1014. << " parameter";
  1015. return os.str();
  1016. }