SymbolManager.cpp 16 KB

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