PathDiagnostic.cpp 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182
  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->getPtr();
  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().getPtr();
  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(PathDiagnostic *D) {
  171. std::unique_ptr<PathDiagnostic> OwningD(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.begin())->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->getPtr();
  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);
  234. Diags.RemoveNode(orig);
  235. delete orig;
  236. }
  237. Diags.InsertNode(OwningD.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. if (!BatchDiags.empty())
  375. std::sort(BatchDiags.begin(), BatchDiags.end(),
  376. [](const PathDiagnostic *X, const PathDiagnostic *Y) {
  377. return X != Y && compare(*X, *Y);
  378. });
  379. FlushDiagnosticsImpl(BatchDiags, Files);
  380. // Delete the flushed diagnostics.
  381. for (std::vector<const PathDiagnostic *>::iterator it = BatchDiags.begin(),
  382. et = BatchDiags.end(); it != et; ++it) {
  383. const PathDiagnostic *D = *it;
  384. delete D;
  385. }
  386. // Clear out the FoldingSet.
  387. Diags.clear();
  388. }
  389. PathDiagnosticConsumer::FilesMade::~FilesMade() {
  390. for (PDFileEntry &Entry : *this)
  391. Entry.~PDFileEntry();
  392. }
  393. void PathDiagnosticConsumer::FilesMade::addDiagnostic(const PathDiagnostic &PD,
  394. StringRef ConsumerName,
  395. StringRef FileName) {
  396. llvm::FoldingSetNodeID NodeID;
  397. NodeID.Add(PD);
  398. void *InsertPos;
  399. PDFileEntry *Entry = FindNodeOrInsertPos(NodeID, InsertPos);
  400. if (!Entry) {
  401. Entry = Alloc.Allocate<PDFileEntry>();
  402. Entry = new (Entry) PDFileEntry(NodeID);
  403. InsertNode(Entry, InsertPos);
  404. }
  405. // Allocate persistent storage for the file name.
  406. char *FileName_cstr = (char*) Alloc.Allocate(FileName.size(), 1);
  407. memcpy(FileName_cstr, FileName.data(), FileName.size());
  408. Entry->files.push_back(std::make_pair(ConsumerName,
  409. StringRef(FileName_cstr,
  410. FileName.size())));
  411. }
  412. PathDiagnosticConsumer::PDFileEntry::ConsumerFiles *
  413. PathDiagnosticConsumer::FilesMade::getFiles(const PathDiagnostic &PD) {
  414. llvm::FoldingSetNodeID NodeID;
  415. NodeID.Add(PD);
  416. void *InsertPos;
  417. PDFileEntry *Entry = FindNodeOrInsertPos(NodeID, InsertPos);
  418. if (!Entry)
  419. return nullptr;
  420. return &Entry->files;
  421. }
  422. //===----------------------------------------------------------------------===//
  423. // PathDiagnosticLocation methods.
  424. //===----------------------------------------------------------------------===//
  425. static SourceLocation getValidSourceLocation(const Stmt* S,
  426. LocationOrAnalysisDeclContext LAC,
  427. bool UseEnd = false) {
  428. SourceLocation L = UseEnd ? S->getLocEnd() : S->getLocStart();
  429. assert(!LAC.isNull() && "A valid LocationContext or AnalysisDeclContext should "
  430. "be passed to PathDiagnosticLocation upon creation.");
  431. // S might be a temporary statement that does not have a location in the
  432. // source code, so find an enclosing statement and use its location.
  433. if (!L.isValid()) {
  434. AnalysisDeclContext *ADC;
  435. if (LAC.is<const LocationContext*>())
  436. ADC = LAC.get<const LocationContext*>()->getAnalysisDeclContext();
  437. else
  438. ADC = LAC.get<AnalysisDeclContext*>();
  439. ParentMap &PM = ADC->getParentMap();
  440. const Stmt *Parent = S;
  441. do {
  442. Parent = PM.getParent(Parent);
  443. // In rare cases, we have implicit top-level expressions,
  444. // such as arguments for implicit member initializers.
  445. // In this case, fall back to the start of the body (even if we were
  446. // asked for the statement end location).
  447. if (!Parent) {
  448. const Stmt *Body = ADC->getBody();
  449. if (Body)
  450. L = Body->getLocStart();
  451. else
  452. L = ADC->getDecl()->getLocEnd();
  453. break;
  454. }
  455. L = UseEnd ? Parent->getLocEnd() : Parent->getLocStart();
  456. } while (!L.isValid());
  457. }
  458. return L;
  459. }
  460. static PathDiagnosticLocation
  461. getLocationForCaller(const StackFrameContext *SFC,
  462. const LocationContext *CallerCtx,
  463. const SourceManager &SM) {
  464. const CFGBlock &Block = *SFC->getCallSiteBlock();
  465. CFGElement Source = Block[SFC->getIndex()];
  466. switch (Source.getKind()) {
  467. case CFGElement::Statement:
  468. return PathDiagnosticLocation(Source.castAs<CFGStmt>().getStmt(),
  469. SM, CallerCtx);
  470. case CFGElement::Initializer: {
  471. const CFGInitializer &Init = Source.castAs<CFGInitializer>();
  472. return PathDiagnosticLocation(Init.getInitializer()->getInit(),
  473. SM, CallerCtx);
  474. }
  475. case CFGElement::AutomaticObjectDtor: {
  476. const CFGAutomaticObjDtor &Dtor = Source.castAs<CFGAutomaticObjDtor>();
  477. return PathDiagnosticLocation::createEnd(Dtor.getTriggerStmt(),
  478. SM, CallerCtx);
  479. }
  480. case CFGElement::DeleteDtor: {
  481. const CFGDeleteDtor &Dtor = Source.castAs<CFGDeleteDtor>();
  482. return PathDiagnosticLocation(Dtor.getDeleteExpr(), SM, CallerCtx);
  483. }
  484. case CFGElement::BaseDtor:
  485. case CFGElement::MemberDtor: {
  486. const AnalysisDeclContext *CallerInfo = CallerCtx->getAnalysisDeclContext();
  487. if (const Stmt *CallerBody = CallerInfo->getBody())
  488. return PathDiagnosticLocation::createEnd(CallerBody, SM, CallerCtx);
  489. return PathDiagnosticLocation::create(CallerInfo->getDecl(), SM);
  490. }
  491. case CFGElement::TemporaryDtor:
  492. case CFGElement::NewAllocator:
  493. llvm_unreachable("not yet implemented!");
  494. }
  495. llvm_unreachable("Unknown CFGElement kind");
  496. }
  497. PathDiagnosticLocation
  498. PathDiagnosticLocation::createBegin(const Decl *D,
  499. const SourceManager &SM) {
  500. return PathDiagnosticLocation(D->getLocStart(), SM, SingleLocK);
  501. }
  502. PathDiagnosticLocation
  503. PathDiagnosticLocation::createBegin(const Stmt *S,
  504. const SourceManager &SM,
  505. LocationOrAnalysisDeclContext LAC) {
  506. return PathDiagnosticLocation(getValidSourceLocation(S, LAC),
  507. SM, SingleLocK);
  508. }
  509. PathDiagnosticLocation
  510. PathDiagnosticLocation::createEnd(const Stmt *S,
  511. const SourceManager &SM,
  512. LocationOrAnalysisDeclContext LAC) {
  513. if (const CompoundStmt *CS = dyn_cast<CompoundStmt>(S))
  514. return createEndBrace(CS, SM);
  515. return PathDiagnosticLocation(getValidSourceLocation(S, LAC, /*End=*/true),
  516. SM, SingleLocK);
  517. }
  518. PathDiagnosticLocation
  519. PathDiagnosticLocation::createOperatorLoc(const BinaryOperator *BO,
  520. const SourceManager &SM) {
  521. return PathDiagnosticLocation(BO->getOperatorLoc(), SM, SingleLocK);
  522. }
  523. PathDiagnosticLocation
  524. PathDiagnosticLocation::createConditionalColonLoc(
  525. const ConditionalOperator *CO,
  526. const SourceManager &SM) {
  527. return PathDiagnosticLocation(CO->getColonLoc(), SM, SingleLocK);
  528. }
  529. PathDiagnosticLocation
  530. PathDiagnosticLocation::createMemberLoc(const MemberExpr *ME,
  531. const SourceManager &SM) {
  532. return PathDiagnosticLocation(ME->getMemberLoc(), SM, SingleLocK);
  533. }
  534. PathDiagnosticLocation
  535. PathDiagnosticLocation::createBeginBrace(const CompoundStmt *CS,
  536. const SourceManager &SM) {
  537. SourceLocation L = CS->getLBracLoc();
  538. return PathDiagnosticLocation(L, SM, SingleLocK);
  539. }
  540. PathDiagnosticLocation
  541. PathDiagnosticLocation::createEndBrace(const CompoundStmt *CS,
  542. const SourceManager &SM) {
  543. SourceLocation L = CS->getRBracLoc();
  544. return PathDiagnosticLocation(L, SM, SingleLocK);
  545. }
  546. PathDiagnosticLocation
  547. PathDiagnosticLocation::createDeclBegin(const LocationContext *LC,
  548. const SourceManager &SM) {
  549. // FIXME: Should handle CXXTryStmt if analyser starts supporting C++.
  550. if (const CompoundStmt *CS =
  551. dyn_cast_or_null<CompoundStmt>(LC->getDecl()->getBody()))
  552. if (!CS->body_empty()) {
  553. SourceLocation Loc = (*CS->body_begin())->getLocStart();
  554. return PathDiagnosticLocation(Loc, SM, SingleLocK);
  555. }
  556. return PathDiagnosticLocation();
  557. }
  558. PathDiagnosticLocation
  559. PathDiagnosticLocation::createDeclEnd(const LocationContext *LC,
  560. const SourceManager &SM) {
  561. SourceLocation L = LC->getDecl()->getBodyRBrace();
  562. return PathDiagnosticLocation(L, SM, SingleLocK);
  563. }
  564. PathDiagnosticLocation
  565. PathDiagnosticLocation::create(const ProgramPoint& P,
  566. const SourceManager &SMng) {
  567. const Stmt* S = nullptr;
  568. if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
  569. const CFGBlock *BSrc = BE->getSrc();
  570. S = BSrc->getTerminatorCondition();
  571. } else if (Optional<StmtPoint> SP = P.getAs<StmtPoint>()) {
  572. S = SP->getStmt();
  573. if (P.getAs<PostStmtPurgeDeadSymbols>())
  574. return PathDiagnosticLocation::createEnd(S, SMng, P.getLocationContext());
  575. } else if (Optional<PostInitializer> PIP = P.getAs<PostInitializer>()) {
  576. return PathDiagnosticLocation(PIP->getInitializer()->getSourceLocation(),
  577. SMng);
  578. } else if (Optional<PostImplicitCall> PIE = P.getAs<PostImplicitCall>()) {
  579. return PathDiagnosticLocation(PIE->getLocation(), SMng);
  580. } else if (Optional<CallEnter> CE = P.getAs<CallEnter>()) {
  581. return getLocationForCaller(CE->getCalleeContext(),
  582. CE->getLocationContext(),
  583. SMng);
  584. } else if (Optional<CallExitEnd> CEE = P.getAs<CallExitEnd>()) {
  585. return getLocationForCaller(CEE->getCalleeContext(),
  586. CEE->getLocationContext(),
  587. SMng);
  588. } else {
  589. llvm_unreachable("Unexpected ProgramPoint");
  590. }
  591. return PathDiagnosticLocation(S, SMng, P.getLocationContext());
  592. }
  593. const Stmt *PathDiagnosticLocation::getStmt(const ExplodedNode *N) {
  594. ProgramPoint P = N->getLocation();
  595. if (Optional<StmtPoint> SP = P.getAs<StmtPoint>())
  596. return SP->getStmt();
  597. if (Optional<BlockEdge> BE = P.getAs<BlockEdge>())
  598. return BE->getSrc()->getTerminator();
  599. if (Optional<CallEnter> CE = P.getAs<CallEnter>())
  600. return CE->getCallExpr();
  601. if (Optional<CallExitEnd> CEE = P.getAs<CallExitEnd>())
  602. return CEE->getCalleeContext()->getCallSite();
  603. if (Optional<PostInitializer> PIPP = P.getAs<PostInitializer>())
  604. return PIPP->getInitializer()->getInit();
  605. return nullptr;
  606. }
  607. const Stmt *PathDiagnosticLocation::getNextStmt(const ExplodedNode *N) {
  608. for (N = N->getFirstSucc(); N; N = N->getFirstSucc()) {
  609. if (const Stmt *S = getStmt(N)) {
  610. // Check if the statement is '?' or '&&'/'||'. These are "merges",
  611. // not actual statement points.
  612. switch (S->getStmtClass()) {
  613. case Stmt::ChooseExprClass:
  614. case Stmt::BinaryConditionalOperatorClass:
  615. case Stmt::ConditionalOperatorClass:
  616. continue;
  617. case Stmt::BinaryOperatorClass: {
  618. BinaryOperatorKind Op = cast<BinaryOperator>(S)->getOpcode();
  619. if (Op == BO_LAnd || Op == BO_LOr)
  620. continue;
  621. break;
  622. }
  623. default:
  624. break;
  625. }
  626. // We found the statement, so return it.
  627. return S;
  628. }
  629. }
  630. return nullptr;
  631. }
  632. PathDiagnosticLocation
  633. PathDiagnosticLocation::createEndOfPath(const ExplodedNode *N,
  634. const SourceManager &SM) {
  635. assert(N && "Cannot create a location with a null node.");
  636. const Stmt *S = getStmt(N);
  637. if (!S) {
  638. // If this is an implicit call, return the implicit call point location.
  639. if (Optional<PreImplicitCall> PIE = N->getLocationAs<PreImplicitCall>())
  640. return PathDiagnosticLocation(PIE->getLocation(), SM);
  641. S = getNextStmt(N);
  642. }
  643. if (S) {
  644. ProgramPoint P = N->getLocation();
  645. const LocationContext *LC = N->getLocationContext();
  646. // For member expressions, return the location of the '.' or '->'.
  647. if (const MemberExpr *ME = dyn_cast<MemberExpr>(S))
  648. return PathDiagnosticLocation::createMemberLoc(ME, SM);
  649. // For binary operators, return the location of the operator.
  650. if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S))
  651. return PathDiagnosticLocation::createOperatorLoc(B, SM);
  652. if (P.getAs<PostStmtPurgeDeadSymbols>())
  653. return PathDiagnosticLocation::createEnd(S, SM, LC);
  654. if (S->getLocStart().isValid())
  655. return PathDiagnosticLocation(S, SM, LC);
  656. return PathDiagnosticLocation(getValidSourceLocation(S, LC), SM);
  657. }
  658. return createDeclEnd(N->getLocationContext(), SM);
  659. }
  660. PathDiagnosticLocation PathDiagnosticLocation::createSingleLocation(
  661. const PathDiagnosticLocation &PDL) {
  662. FullSourceLoc L = PDL.asLocation();
  663. return PathDiagnosticLocation(L, L.getManager(), SingleLocK);
  664. }
  665. FullSourceLoc
  666. PathDiagnosticLocation::genLocation(SourceLocation L,
  667. LocationOrAnalysisDeclContext LAC) const {
  668. assert(isValid());
  669. // Note that we want a 'switch' here so that the compiler can warn us in
  670. // case we add more cases.
  671. switch (K) {
  672. case SingleLocK:
  673. case RangeK:
  674. break;
  675. case StmtK:
  676. // Defensive checking.
  677. if (!S)
  678. break;
  679. return FullSourceLoc(getValidSourceLocation(S, LAC),
  680. const_cast<SourceManager&>(*SM));
  681. case DeclK:
  682. // Defensive checking.
  683. if (!D)
  684. break;
  685. return FullSourceLoc(D->getLocation(), const_cast<SourceManager&>(*SM));
  686. }
  687. return FullSourceLoc(L, const_cast<SourceManager&>(*SM));
  688. }
  689. PathDiagnosticRange
  690. PathDiagnosticLocation::genRange(LocationOrAnalysisDeclContext LAC) const {
  691. assert(isValid());
  692. // Note that we want a 'switch' here so that the compiler can warn us in
  693. // case we add more cases.
  694. switch (K) {
  695. case SingleLocK:
  696. return PathDiagnosticRange(SourceRange(Loc,Loc), true);
  697. case RangeK:
  698. break;
  699. case StmtK: {
  700. const Stmt *S = asStmt();
  701. switch (S->getStmtClass()) {
  702. default:
  703. break;
  704. case Stmt::DeclStmtClass: {
  705. const DeclStmt *DS = cast<DeclStmt>(S);
  706. if (DS->isSingleDecl()) {
  707. // Should always be the case, but we'll be defensive.
  708. return SourceRange(DS->getLocStart(),
  709. DS->getSingleDecl()->getLocation());
  710. }
  711. break;
  712. }
  713. // FIXME: Provide better range information for different
  714. // terminators.
  715. case Stmt::IfStmtClass:
  716. case Stmt::WhileStmtClass:
  717. case Stmt::DoStmtClass:
  718. case Stmt::ForStmtClass:
  719. case Stmt::ChooseExprClass:
  720. case Stmt::IndirectGotoStmtClass:
  721. case Stmt::SwitchStmtClass:
  722. case Stmt::BinaryConditionalOperatorClass:
  723. case Stmt::ConditionalOperatorClass:
  724. case Stmt::ObjCForCollectionStmtClass: {
  725. SourceLocation L = getValidSourceLocation(S, LAC);
  726. return SourceRange(L, L);
  727. }
  728. }
  729. SourceRange R = S->getSourceRange();
  730. if (R.isValid())
  731. return R;
  732. break;
  733. }
  734. case DeclK:
  735. if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
  736. return MD->getSourceRange();
  737. if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
  738. if (Stmt *Body = FD->getBody())
  739. return Body->getSourceRange();
  740. }
  741. else {
  742. SourceLocation L = D->getLocation();
  743. return PathDiagnosticRange(SourceRange(L, L), true);
  744. }
  745. }
  746. return SourceRange(Loc,Loc);
  747. }
  748. void PathDiagnosticLocation::flatten() {
  749. if (K == StmtK) {
  750. K = RangeK;
  751. S = nullptr;
  752. D = nullptr;
  753. }
  754. else if (K == DeclK) {
  755. K = SingleLocK;
  756. S = nullptr;
  757. D = nullptr;
  758. }
  759. }
  760. //===----------------------------------------------------------------------===//
  761. // Manipulation of PathDiagnosticCallPieces.
  762. //===----------------------------------------------------------------------===//
  763. PathDiagnosticCallPiece *
  764. PathDiagnosticCallPiece::construct(const ExplodedNode *N,
  765. const CallExitEnd &CE,
  766. const SourceManager &SM) {
  767. const Decl *caller = CE.getLocationContext()->getDecl();
  768. PathDiagnosticLocation pos = getLocationForCaller(CE.getCalleeContext(),
  769. CE.getLocationContext(),
  770. SM);
  771. return new PathDiagnosticCallPiece(caller, pos);
  772. }
  773. PathDiagnosticCallPiece *
  774. PathDiagnosticCallPiece::construct(PathPieces &path,
  775. const Decl *caller) {
  776. PathDiagnosticCallPiece *C = new PathDiagnosticCallPiece(path, caller);
  777. path.clear();
  778. path.push_front(C);
  779. return C;
  780. }
  781. void PathDiagnosticCallPiece::setCallee(const CallEnter &CE,
  782. const SourceManager &SM) {
  783. const StackFrameContext *CalleeCtx = CE.getCalleeContext();
  784. Callee = CalleeCtx->getDecl();
  785. callEnterWithin = PathDiagnosticLocation::createBegin(Callee, SM);
  786. callEnter = getLocationForCaller(CalleeCtx, CE.getLocationContext(), SM);
  787. }
  788. static inline void describeClass(raw_ostream &Out, const CXXRecordDecl *D,
  789. StringRef Prefix = StringRef()) {
  790. if (!D->getIdentifier())
  791. return;
  792. Out << Prefix << '\'' << *D << '\'';
  793. }
  794. static bool describeCodeDecl(raw_ostream &Out, const Decl *D,
  795. bool ExtendedDescription,
  796. StringRef Prefix = StringRef()) {
  797. if (!D)
  798. return false;
  799. if (isa<BlockDecl>(D)) {
  800. if (ExtendedDescription)
  801. Out << Prefix << "anonymous block";
  802. return ExtendedDescription;
  803. }
  804. if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
  805. Out << Prefix;
  806. if (ExtendedDescription && !MD->isUserProvided()) {
  807. if (MD->isExplicitlyDefaulted())
  808. Out << "defaulted ";
  809. else
  810. Out << "implicit ";
  811. }
  812. if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(MD)) {
  813. if (CD->isDefaultConstructor())
  814. Out << "default ";
  815. else if (CD->isCopyConstructor())
  816. Out << "copy ";
  817. else if (CD->isMoveConstructor())
  818. Out << "move ";
  819. Out << "constructor";
  820. describeClass(Out, MD->getParent(), " for ");
  821. } else if (isa<CXXDestructorDecl>(MD)) {
  822. if (!MD->isUserProvided()) {
  823. Out << "destructor";
  824. describeClass(Out, MD->getParent(), " for ");
  825. } else {
  826. // Use ~Foo for explicitly-written destructors.
  827. Out << "'" << *MD << "'";
  828. }
  829. } else if (MD->isCopyAssignmentOperator()) {
  830. Out << "copy assignment operator";
  831. describeClass(Out, MD->getParent(), " for ");
  832. } else if (MD->isMoveAssignmentOperator()) {
  833. Out << "move assignment operator";
  834. describeClass(Out, MD->getParent(), " for ");
  835. } else {
  836. if (MD->getParent()->getIdentifier())
  837. Out << "'" << *MD->getParent() << "::" << *MD << "'";
  838. else
  839. Out << "'" << *MD << "'";
  840. }
  841. return true;
  842. }
  843. Out << Prefix << '\'' << cast<NamedDecl>(*D) << '\'';
  844. return true;
  845. }
  846. IntrusiveRefCntPtr<PathDiagnosticEventPiece>
  847. PathDiagnosticCallPiece::getCallEnterEvent() const {
  848. if (!Callee)
  849. return nullptr;
  850. SmallString<256> buf;
  851. llvm::raw_svector_ostream Out(buf);
  852. Out << "Calling ";
  853. describeCodeDecl(Out, Callee, /*ExtendedDescription=*/true);
  854. assert(callEnter.asLocation().isValid());
  855. return new PathDiagnosticEventPiece(callEnter, Out.str());
  856. }
  857. IntrusiveRefCntPtr<PathDiagnosticEventPiece>
  858. PathDiagnosticCallPiece::getCallEnterWithinCallerEvent() const {
  859. if (!callEnterWithin.asLocation().isValid())
  860. return nullptr;
  861. if (Callee->isImplicit() || !Callee->hasBody())
  862. return nullptr;
  863. if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Callee))
  864. if (MD->isDefaulted())
  865. return nullptr;
  866. SmallString<256> buf;
  867. llvm::raw_svector_ostream Out(buf);
  868. Out << "Entered call";
  869. describeCodeDecl(Out, Caller, /*ExtendedDescription=*/false, " from ");
  870. return new PathDiagnosticEventPiece(callEnterWithin, Out.str());
  871. }
  872. IntrusiveRefCntPtr<PathDiagnosticEventPiece>
  873. PathDiagnosticCallPiece::getCallExitEvent() const {
  874. if (NoExit)
  875. return nullptr;
  876. SmallString<256> buf;
  877. llvm::raw_svector_ostream Out(buf);
  878. if (!CallStackMessage.empty()) {
  879. Out << CallStackMessage;
  880. } else {
  881. bool DidDescribe = describeCodeDecl(Out, Callee,
  882. /*ExtendedDescription=*/false,
  883. "Returning from ");
  884. if (!DidDescribe)
  885. Out << "Returning to caller";
  886. }
  887. assert(callReturn.asLocation().isValid());
  888. return new PathDiagnosticEventPiece(callReturn, Out.str());
  889. }
  890. static void compute_path_size(const PathPieces &pieces, unsigned &size) {
  891. for (PathPieces::const_iterator it = pieces.begin(),
  892. et = pieces.end(); it != et; ++it) {
  893. const PathDiagnosticPiece *piece = it->getPtr();
  894. if (const PathDiagnosticCallPiece *cp =
  895. dyn_cast<PathDiagnosticCallPiece>(piece)) {
  896. compute_path_size(cp->path, size);
  897. }
  898. else
  899. ++size;
  900. }
  901. }
  902. unsigned PathDiagnostic::full_size() {
  903. unsigned size = 0;
  904. compute_path_size(path, size);
  905. return size;
  906. }
  907. //===----------------------------------------------------------------------===//
  908. // FoldingSet profiling methods.
  909. //===----------------------------------------------------------------------===//
  910. void PathDiagnosticLocation::Profile(llvm::FoldingSetNodeID &ID) const {
  911. ID.AddInteger(Range.getBegin().getRawEncoding());
  912. ID.AddInteger(Range.getEnd().getRawEncoding());
  913. ID.AddInteger(Loc.getRawEncoding());
  914. return;
  915. }
  916. void PathDiagnosticPiece::Profile(llvm::FoldingSetNodeID &ID) const {
  917. ID.AddInteger((unsigned) getKind());
  918. ID.AddString(str);
  919. // FIXME: Add profiling support for code hints.
  920. ID.AddInteger((unsigned) getDisplayHint());
  921. ArrayRef<SourceRange> Ranges = getRanges();
  922. for (ArrayRef<SourceRange>::iterator I = Ranges.begin(), E = Ranges.end();
  923. I != E; ++I) {
  924. ID.AddInteger(I->getBegin().getRawEncoding());
  925. ID.AddInteger(I->getEnd().getRawEncoding());
  926. }
  927. }
  928. void PathDiagnosticCallPiece::Profile(llvm::FoldingSetNodeID &ID) const {
  929. PathDiagnosticPiece::Profile(ID);
  930. for (PathPieces::const_iterator it = path.begin(),
  931. et = path.end(); it != et; ++it) {
  932. ID.Add(**it);
  933. }
  934. }
  935. void PathDiagnosticSpotPiece::Profile(llvm::FoldingSetNodeID &ID) const {
  936. PathDiagnosticPiece::Profile(ID);
  937. ID.Add(Pos);
  938. }
  939. void PathDiagnosticControlFlowPiece::Profile(llvm::FoldingSetNodeID &ID) const {
  940. PathDiagnosticPiece::Profile(ID);
  941. for (const_iterator I = begin(), E = end(); I != E; ++I)
  942. ID.Add(*I);
  943. }
  944. void PathDiagnosticMacroPiece::Profile(llvm::FoldingSetNodeID &ID) const {
  945. PathDiagnosticSpotPiece::Profile(ID);
  946. for (PathPieces::const_iterator I = subPieces.begin(), E = subPieces.end();
  947. I != E; ++I)
  948. ID.Add(**I);
  949. }
  950. void PathDiagnostic::Profile(llvm::FoldingSetNodeID &ID) const {
  951. ID.Add(getLocation());
  952. ID.AddString(BugType);
  953. ID.AddString(VerboseDesc);
  954. ID.AddString(Category);
  955. }
  956. void PathDiagnostic::FullProfile(llvm::FoldingSetNodeID &ID) const {
  957. Profile(ID);
  958. for (PathPieces::const_iterator I = path.begin(), E = path.end(); I != E; ++I)
  959. ID.Add(**I);
  960. for (meta_iterator I = meta_begin(), E = meta_end(); I != E; ++I)
  961. ID.AddString(*I);
  962. }
  963. StackHintGenerator::~StackHintGenerator() {}
  964. std::string StackHintGeneratorForSymbol::getMessage(const ExplodedNode *N){
  965. ProgramPoint P = N->getLocation();
  966. CallExitEnd CExit = P.castAs<CallExitEnd>();
  967. // FIXME: Use CallEvent to abstract this over all calls.
  968. const Stmt *CallSite = CExit.getCalleeContext()->getCallSite();
  969. const CallExpr *CE = dyn_cast_or_null<CallExpr>(CallSite);
  970. if (!CE)
  971. return "";
  972. if (!N)
  973. return getMessageForSymbolNotFound();
  974. // Check if one of the parameters are set to the interesting symbol.
  975. ProgramStateRef State = N->getState();
  976. const LocationContext *LCtx = N->getLocationContext();
  977. unsigned ArgIndex = 0;
  978. for (CallExpr::const_arg_iterator I = CE->arg_begin(),
  979. E = CE->arg_end(); I != E; ++I, ++ArgIndex){
  980. SVal SV = State->getSVal(*I, LCtx);
  981. // Check if the variable corresponding to the symbol is passed by value.
  982. SymbolRef AS = SV.getAsLocSymbol();
  983. if (AS == Sym) {
  984. return getMessageForArg(*I, ArgIndex);
  985. }
  986. // Check if the parameter is a pointer to the symbol.
  987. if (Optional<loc::MemRegionVal> Reg = SV.getAs<loc::MemRegionVal>()) {
  988. SVal PSV = State->getSVal(Reg->getRegion());
  989. SymbolRef AS = PSV.getAsLocSymbol();
  990. if (AS == Sym) {
  991. return getMessageForArg(*I, ArgIndex);
  992. }
  993. }
  994. }
  995. // Check if we are returning the interesting symbol.
  996. SVal SV = State->getSVal(CE, LCtx);
  997. SymbolRef RetSym = SV.getAsLocSymbol();
  998. if (RetSym == Sym) {
  999. return getMessageForReturn(CE);
  1000. }
  1001. return getMessageForSymbolNotFound();
  1002. }
  1003. std::string StackHintGeneratorForSymbol::getMessageForArg(const Expr *ArgE,
  1004. unsigned ArgIndex) {
  1005. // Printed parameters start at 1, not 0.
  1006. ++ArgIndex;
  1007. SmallString<200> buf;
  1008. llvm::raw_svector_ostream os(buf);
  1009. os << Msg << " via " << ArgIndex << llvm::getOrdinalSuffix(ArgIndex)
  1010. << " parameter";
  1011. return os.str();
  1012. }