SymbolManager.cpp 14 KB

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