SymbolManager.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  1. //== SymbolManager.h - Management of Symbolic Values ------------*- 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 SymbolManager, a class that manages symbolic values
  11. // created for use by ExprEngine and related classes.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
  15. #include "clang/Analysis/Analyses/LiveVariables.h"
  16. #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
  17. #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
  18. #include "llvm/Support/raw_ostream.h"
  19. using namespace clang;
  20. using namespace ento;
  21. void SymExpr::anchor() { }
  22. void SymExpr::dump() const {
  23. dumpToStream(llvm::errs());
  24. }
  25. void SymIntExpr::dumpToStream(raw_ostream &os) const {
  26. os << '(';
  27. getLHS()->dumpToStream(os);
  28. os << ") "
  29. << BinaryOperator::getOpcodeStr(getOpcode()) << ' '
  30. << getRHS().getZExtValue();
  31. if (getRHS().isUnsigned())
  32. os << 'U';
  33. }
  34. void IntSymExpr::dumpToStream(raw_ostream &os) const {
  35. os << getLHS().getZExtValue();
  36. if (getLHS().isUnsigned())
  37. os << 'U';
  38. os << ' '
  39. << BinaryOperator::getOpcodeStr(getOpcode())
  40. << " (";
  41. getRHS()->dumpToStream(os);
  42. os << ')';
  43. }
  44. void SymSymExpr::dumpToStream(raw_ostream &os) const {
  45. os << '(';
  46. getLHS()->dumpToStream(os);
  47. os << ") "
  48. << BinaryOperator::getOpcodeStr(getOpcode())
  49. << " (";
  50. getRHS()->dumpToStream(os);
  51. os << ')';
  52. }
  53. void SymbolCast::dumpToStream(raw_ostream &os) const {
  54. os << '(' << ToTy.getAsString() << ") (";
  55. Operand->dumpToStream(os);
  56. os << ')';
  57. }
  58. void SymbolConjured::dumpToStream(raw_ostream &os) const {
  59. os << "conj_$" << getSymbolID() << '{' << T.getAsString() << '}';
  60. }
  61. void SymbolDerived::dumpToStream(raw_ostream &os) const {
  62. os << "derived_$" << getSymbolID() << '{'
  63. << getParentSymbol() << ',' << getRegion() << '}';
  64. }
  65. void SymbolExtent::dumpToStream(raw_ostream &os) const {
  66. os << "extent_$" << getSymbolID() << '{' << getRegion() << '}';
  67. }
  68. void SymbolMetadata::dumpToStream(raw_ostream &os) const {
  69. os << "meta_$" << getSymbolID() << '{'
  70. << getRegion() << ',' << T.getAsString() << '}';
  71. }
  72. void SymbolData::anchor() { }
  73. void SymbolRegionValue::dumpToStream(raw_ostream &os) const {
  74. os << "reg_$" << getSymbolID() << "<" << R << ">";
  75. }
  76. bool SymExpr::symbol_iterator::operator==(const symbol_iterator &X) const {
  77. return itr == X.itr;
  78. }
  79. bool SymExpr::symbol_iterator::operator!=(const symbol_iterator &X) const {
  80. return itr != X.itr;
  81. }
  82. SymExpr::symbol_iterator::symbol_iterator(const SymExpr *SE) {
  83. itr.push_back(SE);
  84. }
  85. SymExpr::symbol_iterator &SymExpr::symbol_iterator::operator++() {
  86. assert(!itr.empty() && "attempting to iterate on an 'end' iterator");
  87. expand();
  88. return *this;
  89. }
  90. SymbolRef SymExpr::symbol_iterator::operator*() {
  91. assert(!itr.empty() && "attempting to dereference an 'end' iterator");
  92. return itr.back();
  93. }
  94. void SymExpr::symbol_iterator::expand() {
  95. const SymExpr *SE = itr.pop_back_val();
  96. switch (SE->getKind()) {
  97. case SymExpr::RegionValueKind:
  98. case SymExpr::ConjuredKind:
  99. case SymExpr::DerivedKind:
  100. case SymExpr::ExtentKind:
  101. case SymExpr::MetadataKind:
  102. return;
  103. case SymExpr::CastSymbolKind:
  104. itr.push_back(cast<SymbolCast>(SE)->getOperand());
  105. return;
  106. case SymExpr::SymIntKind:
  107. itr.push_back(cast<SymIntExpr>(SE)->getLHS());
  108. return;
  109. case SymExpr::IntSymKind:
  110. itr.push_back(cast<IntSymExpr>(SE)->getRHS());
  111. return;
  112. case SymExpr::SymSymKind: {
  113. const SymSymExpr *x = cast<SymSymExpr>(SE);
  114. itr.push_back(x->getLHS());
  115. itr.push_back(x->getRHS());
  116. return;
  117. }
  118. }
  119. llvm_unreachable("unhandled expansion case");
  120. }
  121. unsigned SymExpr::computeComplexity() const {
  122. unsigned R = 0;
  123. for (symbol_iterator I = symbol_begin(), E = symbol_end(); I != E; ++I)
  124. R++;
  125. return R;
  126. }
  127. const SymbolRegionValue*
  128. SymbolManager::getRegionValueSymbol(const TypedValueRegion* R) {
  129. llvm::FoldingSetNodeID profile;
  130. SymbolRegionValue::Profile(profile, R);
  131. void *InsertPos;
  132. SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
  133. if (!SD) {
  134. SD = (SymExpr*) BPAlloc.Allocate<SymbolRegionValue>();
  135. new (SD) SymbolRegionValue(SymbolCounter, R);
  136. DataSet.InsertNode(SD, InsertPos);
  137. ++SymbolCounter;
  138. }
  139. return cast<SymbolRegionValue>(SD);
  140. }
  141. const SymbolConjured* SymbolManager::conjureSymbol(const Stmt *E,
  142. const LocationContext *LCtx,
  143. QualType T,
  144. unsigned Count,
  145. const void *SymbolTag) {
  146. llvm::FoldingSetNodeID profile;
  147. SymbolConjured::Profile(profile, E, T, Count, LCtx, SymbolTag);
  148. void *InsertPos;
  149. SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
  150. if (!SD) {
  151. SD = (SymExpr*) BPAlloc.Allocate<SymbolConjured>();
  152. new (SD) SymbolConjured(SymbolCounter, E, LCtx, T, Count, SymbolTag);
  153. DataSet.InsertNode(SD, InsertPos);
  154. ++SymbolCounter;
  155. }
  156. return cast<SymbolConjured>(SD);
  157. }
  158. const SymbolDerived*
  159. SymbolManager::getDerivedSymbol(SymbolRef parentSymbol,
  160. const TypedValueRegion *R) {
  161. llvm::FoldingSetNodeID profile;
  162. SymbolDerived::Profile(profile, parentSymbol, R);
  163. void *InsertPos;
  164. SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
  165. if (!SD) {
  166. SD = (SymExpr*) BPAlloc.Allocate<SymbolDerived>();
  167. new (SD) SymbolDerived(SymbolCounter, parentSymbol, R);
  168. DataSet.InsertNode(SD, InsertPos);
  169. ++SymbolCounter;
  170. }
  171. return cast<SymbolDerived>(SD);
  172. }
  173. const SymbolExtent*
  174. SymbolManager::getExtentSymbol(const SubRegion *R) {
  175. llvm::FoldingSetNodeID profile;
  176. SymbolExtent::Profile(profile, R);
  177. void *InsertPos;
  178. SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
  179. if (!SD) {
  180. SD = (SymExpr*) BPAlloc.Allocate<SymbolExtent>();
  181. new (SD) SymbolExtent(SymbolCounter, R);
  182. DataSet.InsertNode(SD, InsertPos);
  183. ++SymbolCounter;
  184. }
  185. return cast<SymbolExtent>(SD);
  186. }
  187. const SymbolMetadata*
  188. SymbolManager::getMetadataSymbol(const MemRegion* R, const Stmt *S, QualType T,
  189. unsigned Count, const void *SymbolTag) {
  190. llvm::FoldingSetNodeID profile;
  191. SymbolMetadata::Profile(profile, R, S, T, Count, SymbolTag);
  192. void *InsertPos;
  193. SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
  194. if (!SD) {
  195. SD = (SymExpr*) BPAlloc.Allocate<SymbolMetadata>();
  196. new (SD) SymbolMetadata(SymbolCounter, R, S, T, Count, SymbolTag);
  197. DataSet.InsertNode(SD, InsertPos);
  198. ++SymbolCounter;
  199. }
  200. return cast<SymbolMetadata>(SD);
  201. }
  202. const SymbolCast*
  203. SymbolManager::getCastSymbol(const SymExpr *Op,
  204. QualType From, QualType To) {
  205. llvm::FoldingSetNodeID ID;
  206. SymbolCast::Profile(ID, Op, From, To);
  207. void *InsertPos;
  208. SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
  209. if (!data) {
  210. data = (SymbolCast*) BPAlloc.Allocate<SymbolCast>();
  211. new (data) SymbolCast(Op, From, To);
  212. DataSet.InsertNode(data, InsertPos);
  213. }
  214. return cast<SymbolCast>(data);
  215. }
  216. const SymIntExpr *SymbolManager::getSymIntExpr(const SymExpr *lhs,
  217. BinaryOperator::Opcode op,
  218. const llvm::APSInt& v,
  219. QualType t) {
  220. llvm::FoldingSetNodeID ID;
  221. SymIntExpr::Profile(ID, lhs, op, v, t);
  222. void *InsertPos;
  223. SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
  224. if (!data) {
  225. data = (SymIntExpr*) BPAlloc.Allocate<SymIntExpr>();
  226. new (data) SymIntExpr(lhs, op, v, t);
  227. DataSet.InsertNode(data, InsertPos);
  228. }
  229. return cast<SymIntExpr>(data);
  230. }
  231. const IntSymExpr *SymbolManager::getIntSymExpr(const llvm::APSInt& lhs,
  232. BinaryOperator::Opcode op,
  233. const SymExpr *rhs,
  234. QualType t) {
  235. llvm::FoldingSetNodeID ID;
  236. IntSymExpr::Profile(ID, lhs, op, rhs, t);
  237. void *InsertPos;
  238. SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
  239. if (!data) {
  240. data = (IntSymExpr*) BPAlloc.Allocate<IntSymExpr>();
  241. new (data) IntSymExpr(lhs, op, rhs, t);
  242. DataSet.InsertNode(data, InsertPos);
  243. }
  244. return cast<IntSymExpr>(data);
  245. }
  246. const SymSymExpr *SymbolManager::getSymSymExpr(const SymExpr *lhs,
  247. BinaryOperator::Opcode op,
  248. const SymExpr *rhs,
  249. QualType t) {
  250. llvm::FoldingSetNodeID ID;
  251. SymSymExpr::Profile(ID, lhs, op, rhs, t);
  252. void *InsertPos;
  253. SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
  254. if (!data) {
  255. data = (SymSymExpr*) BPAlloc.Allocate<SymSymExpr>();
  256. new (data) SymSymExpr(lhs, op, rhs, t);
  257. DataSet.InsertNode(data, InsertPos);
  258. }
  259. return cast<SymSymExpr>(data);
  260. }
  261. QualType SymbolConjured::getType() const {
  262. return T;
  263. }
  264. QualType SymbolDerived::getType() const {
  265. return R->getValueType();
  266. }
  267. QualType SymbolExtent::getType() const {
  268. ASTContext &Ctx = R->getMemRegionManager()->getContext();
  269. return Ctx.getSizeType();
  270. }
  271. QualType SymbolMetadata::getType() const {
  272. return T;
  273. }
  274. QualType SymbolRegionValue::getType() const {
  275. return R->getValueType();
  276. }
  277. SymbolManager::~SymbolManager() {
  278. llvm::DeleteContainerSeconds(SymbolDependencies);
  279. }
  280. bool SymbolManager::canSymbolicate(QualType T) {
  281. T = T.getCanonicalType();
  282. if (Loc::isLocType(T))
  283. return true;
  284. if (T->isIntegralOrEnumerationType())
  285. return true;
  286. if (T->isRecordType() && !T->isUnionType())
  287. return true;
  288. return false;
  289. }
  290. void SymbolManager::addSymbolDependency(const SymbolRef Primary,
  291. const SymbolRef Dependent) {
  292. SymbolDependTy::iterator I = SymbolDependencies.find(Primary);
  293. SymbolRefSmallVectorTy *dependencies = nullptr;
  294. if (I == SymbolDependencies.end()) {
  295. dependencies = new SymbolRefSmallVectorTy();
  296. SymbolDependencies[Primary] = dependencies;
  297. } else {
  298. dependencies = I->second;
  299. }
  300. dependencies->push_back(Dependent);
  301. }
  302. const SymbolRefSmallVectorTy *SymbolManager::getDependentSymbols(
  303. const SymbolRef Primary) {
  304. SymbolDependTy::const_iterator I = SymbolDependencies.find(Primary);
  305. if (I == SymbolDependencies.end())
  306. return nullptr;
  307. return I->second;
  308. }
  309. void SymbolReaper::markDependentsLive(SymbolRef sym) {
  310. // Do not mark dependents more then once.
  311. SymbolMapTy::iterator LI = TheLiving.find(sym);
  312. assert(LI != TheLiving.end() && "The primary symbol is not live.");
  313. if (LI->second == HaveMarkedDependents)
  314. return;
  315. LI->second = HaveMarkedDependents;
  316. if (const SymbolRefSmallVectorTy *Deps = SymMgr.getDependentSymbols(sym)) {
  317. for (SymbolRefSmallVectorTy::const_iterator I = Deps->begin(),
  318. E = Deps->end(); I != E; ++I) {
  319. if (TheLiving.find(*I) != TheLiving.end())
  320. continue;
  321. markLive(*I);
  322. }
  323. }
  324. }
  325. void SymbolReaper::markLive(SymbolRef sym) {
  326. TheLiving[sym] = NotProcessed;
  327. TheDead.erase(sym);
  328. markDependentsLive(sym);
  329. }
  330. void SymbolReaper::markLive(const MemRegion *region) {
  331. RegionRoots.insert(region);
  332. }
  333. void SymbolReaper::markInUse(SymbolRef sym) {
  334. if (isa<SymbolMetadata>(sym))
  335. MetadataInUse.insert(sym);
  336. }
  337. bool SymbolReaper::maybeDead(SymbolRef sym) {
  338. if (isLive(sym))
  339. return false;
  340. TheDead.insert(sym);
  341. return true;
  342. }
  343. bool SymbolReaper::isLiveRegion(const MemRegion *MR) {
  344. if (RegionRoots.count(MR))
  345. return true;
  346. MR = MR->getBaseRegion();
  347. if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(MR))
  348. return isLive(SR->getSymbol());
  349. if (const VarRegion *VR = dyn_cast<VarRegion>(MR))
  350. return isLive(VR, true);
  351. // FIXME: This is a gross over-approximation. What we really need is a way to
  352. // tell if anything still refers to this region. Unlike SymbolicRegions,
  353. // AllocaRegions don't have associated symbols, though, so we don't actually
  354. // have a way to track their liveness.
  355. if (isa<AllocaRegion>(MR))
  356. return true;
  357. if (isa<CXXThisRegion>(MR))
  358. return true;
  359. if (isa<MemSpaceRegion>(MR))
  360. return true;
  361. if (isa<CodeTextRegion>(MR))
  362. return true;
  363. return false;
  364. }
  365. bool SymbolReaper::isLive(SymbolRef sym) {
  366. if (TheLiving.count(sym)) {
  367. markDependentsLive(sym);
  368. return true;
  369. }
  370. bool KnownLive;
  371. switch (sym->getKind()) {
  372. case SymExpr::RegionValueKind:
  373. KnownLive = isLiveRegion(cast<SymbolRegionValue>(sym)->getRegion());
  374. break;
  375. case SymExpr::ConjuredKind:
  376. KnownLive = false;
  377. break;
  378. case SymExpr::DerivedKind:
  379. KnownLive = isLive(cast<SymbolDerived>(sym)->getParentSymbol());
  380. break;
  381. case SymExpr::ExtentKind:
  382. KnownLive = isLiveRegion(cast<SymbolExtent>(sym)->getRegion());
  383. break;
  384. case SymExpr::MetadataKind:
  385. KnownLive = MetadataInUse.count(sym) &&
  386. isLiveRegion(cast<SymbolMetadata>(sym)->getRegion());
  387. if (KnownLive)
  388. MetadataInUse.erase(sym);
  389. break;
  390. case SymExpr::SymIntKind:
  391. KnownLive = isLive(cast<SymIntExpr>(sym)->getLHS());
  392. break;
  393. case SymExpr::IntSymKind:
  394. KnownLive = isLive(cast<IntSymExpr>(sym)->getRHS());
  395. break;
  396. case SymExpr::SymSymKind:
  397. KnownLive = isLive(cast<SymSymExpr>(sym)->getLHS()) &&
  398. isLive(cast<SymSymExpr>(sym)->getRHS());
  399. break;
  400. case SymExpr::CastSymbolKind:
  401. KnownLive = isLive(cast<SymbolCast>(sym)->getOperand());
  402. break;
  403. }
  404. if (KnownLive)
  405. markLive(sym);
  406. return KnownLive;
  407. }
  408. bool
  409. SymbolReaper::isLive(const Stmt *ExprVal, const LocationContext *ELCtx) const {
  410. if (LCtx == nullptr)
  411. return false;
  412. if (LCtx != ELCtx) {
  413. // If the reaper's location context is a parent of the expression's
  414. // location context, then the expression value is now "out of scope".
  415. if (LCtx->isParentOf(ELCtx))
  416. return false;
  417. return true;
  418. }
  419. // If no statement is provided, everything is this and parent contexts is live.
  420. if (!Loc)
  421. return true;
  422. return LCtx->getAnalysis<RelaxedLiveVariables>()->isLive(Loc, ExprVal);
  423. }
  424. bool SymbolReaper::isLive(const VarRegion *VR, bool includeStoreBindings) const{
  425. const StackFrameContext *VarContext = VR->getStackFrame();
  426. if (!VarContext)
  427. return true;
  428. if (!LCtx)
  429. return false;
  430. const StackFrameContext *CurrentContext = LCtx->getCurrentStackFrame();
  431. if (VarContext == CurrentContext) {
  432. // If no statement is provided, everything is live.
  433. if (!Loc)
  434. return true;
  435. if (LCtx->getAnalysis<RelaxedLiveVariables>()->isLive(Loc, VR->getDecl()))
  436. return true;
  437. if (!includeStoreBindings)
  438. return false;
  439. unsigned &cachedQuery =
  440. const_cast<SymbolReaper*>(this)->includedRegionCache[VR];
  441. if (cachedQuery) {
  442. return cachedQuery == 1;
  443. }
  444. // Query the store to see if the region occurs in any live bindings.
  445. if (Store store = reapedStore.getStore()) {
  446. bool hasRegion =
  447. reapedStore.getStoreManager().includedInBindings(store, VR);
  448. cachedQuery = hasRegion ? 1 : 2;
  449. return hasRegion;
  450. }
  451. return false;
  452. }
  453. return VarContext->isParentOf(CurrentContext);
  454. }
  455. SymbolVisitor::~SymbolVisitor() {}