PathDiagnostic.cpp 40 KB

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