Environment.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. //== Environment.cpp - Map from Stmt* to Locations/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 defined the Environment and EnvironmentManager classes.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "clang/AST/ExprCXX.h"
  14. #include "clang/AST/ExprObjC.h"
  15. #include "clang/Analysis/AnalysisContext.h"
  16. #include "clang/Analysis/CFG.h"
  17. #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
  18. #include "llvm/Support/raw_ostream.h"
  19. using namespace clang;
  20. using namespace ento;
  21. static const Expr *ignoreTransparentExprs(const Expr *E) {
  22. E = E->IgnoreParens();
  23. switch (E->getStmtClass()) {
  24. case Stmt::OpaqueValueExprClass:
  25. E = cast<OpaqueValueExpr>(E)->getSourceExpr();
  26. break;
  27. case Stmt::ExprWithCleanupsClass:
  28. E = cast<ExprWithCleanups>(E)->getSubExpr();
  29. break;
  30. case Stmt::CXXBindTemporaryExprClass:
  31. E = cast<CXXBindTemporaryExpr>(E)->getSubExpr();
  32. break;
  33. case Stmt::SubstNonTypeTemplateParmExprClass:
  34. E = cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement();
  35. break;
  36. default:
  37. // This is the base case: we can't look through more than we already have.
  38. return E;
  39. }
  40. return ignoreTransparentExprs(E);
  41. }
  42. static const Stmt *ignoreTransparentExprs(const Stmt *S) {
  43. if (const Expr *E = dyn_cast<Expr>(S))
  44. return ignoreTransparentExprs(E);
  45. return S;
  46. }
  47. EnvironmentEntry::EnvironmentEntry(const Stmt *S, const LocationContext *L)
  48. : std::pair<const Stmt *,
  49. const StackFrameContext *>(ignoreTransparentExprs(S),
  50. L ? L->getCurrentStackFrame() : 0) {}
  51. SVal Environment::lookupExpr(const EnvironmentEntry &E) const {
  52. const SVal* X = ExprBindings.lookup(E);
  53. if (X) {
  54. SVal V = *X;
  55. return V;
  56. }
  57. return UnknownVal();
  58. }
  59. SVal Environment::getSVal(const EnvironmentEntry &Entry,
  60. SValBuilder& svalBuilder) const {
  61. const Stmt *S = Entry.getStmt();
  62. const LocationContext *LCtx = Entry.getLocationContext();
  63. switch (S->getStmtClass()) {
  64. case Stmt::CXXBindTemporaryExprClass:
  65. case Stmt::ExprWithCleanupsClass:
  66. case Stmt::GenericSelectionExprClass:
  67. case Stmt::OpaqueValueExprClass:
  68. case Stmt::ParenExprClass:
  69. case Stmt::SubstNonTypeTemplateParmExprClass:
  70. llvm_unreachable("Should have been handled by ignoreTransparentExprs");
  71. case Stmt::AddrLabelExprClass:
  72. return svalBuilder.makeLoc(cast<AddrLabelExpr>(S));
  73. case Stmt::CharacterLiteralClass: {
  74. const CharacterLiteral *C = cast<CharacterLiteral>(S);
  75. return svalBuilder.makeIntVal(C->getValue(), C->getType());
  76. }
  77. case Stmt::CXXBoolLiteralExprClass:
  78. return svalBuilder.makeBoolVal(cast<CXXBoolLiteralExpr>(S));
  79. case Stmt::CXXScalarValueInitExprClass:
  80. case Stmt::ImplicitValueInitExprClass: {
  81. QualType Ty = cast<Expr>(S)->getType();
  82. return svalBuilder.makeZeroVal(Ty);
  83. }
  84. case Stmt::IntegerLiteralClass:
  85. return svalBuilder.makeIntVal(cast<IntegerLiteral>(S));
  86. case Stmt::ObjCBoolLiteralExprClass:
  87. return svalBuilder.makeBoolVal(cast<ObjCBoolLiteralExpr>(S));
  88. // For special C0xx nullptr case, make a null pointer SVal.
  89. case Stmt::CXXNullPtrLiteralExprClass:
  90. return svalBuilder.makeNull();
  91. case Stmt::ObjCStringLiteralClass: {
  92. MemRegionManager &MRMgr = svalBuilder.getRegionManager();
  93. const ObjCStringLiteral *SL = cast<ObjCStringLiteral>(S);
  94. return svalBuilder.makeLoc(MRMgr.getObjCStringRegion(SL));
  95. }
  96. case Stmt::StringLiteralClass: {
  97. MemRegionManager &MRMgr = svalBuilder.getRegionManager();
  98. const StringLiteral *SL = cast<StringLiteral>(S);
  99. return svalBuilder.makeLoc(MRMgr.getStringRegion(SL));
  100. }
  101. case Stmt::ReturnStmtClass: {
  102. const ReturnStmt *RS = cast<ReturnStmt>(S);
  103. if (const Expr *RE = RS->getRetValue())
  104. return getSVal(EnvironmentEntry(RE, LCtx), svalBuilder);
  105. return UndefinedVal();
  106. }
  107. // Handle all other Stmt* using a lookup.
  108. default:
  109. break;
  110. }
  111. return lookupExpr(EnvironmentEntry(S, LCtx));
  112. }
  113. Environment EnvironmentManager::bindExpr(Environment Env,
  114. const EnvironmentEntry &E,
  115. SVal V,
  116. bool Invalidate) {
  117. if (V.isUnknown()) {
  118. if (Invalidate)
  119. return Environment(F.remove(Env.ExprBindings, E));
  120. else
  121. return Env;
  122. }
  123. return Environment(F.add(Env.ExprBindings, E, V));
  124. }
  125. namespace {
  126. class MarkLiveCallback : public SymbolVisitor {
  127. SymbolReaper &SymReaper;
  128. public:
  129. MarkLiveCallback(SymbolReaper &symreaper) : SymReaper(symreaper) {}
  130. bool VisitSymbol(SymbolRef sym) {
  131. SymReaper.markLive(sym);
  132. return true;
  133. }
  134. bool VisitMemRegion(const MemRegion *R) {
  135. SymReaper.markLive(R);
  136. return true;
  137. }
  138. };
  139. } // end anonymous namespace
  140. // removeDeadBindings:
  141. // - Remove subexpression bindings.
  142. // - Remove dead block expression bindings.
  143. // - Keep live block expression bindings:
  144. // - Mark their reachable symbols live in SymbolReaper,
  145. // see ScanReachableSymbols.
  146. // - Mark the region in DRoots if the binding is a loc::MemRegionVal.
  147. Environment
  148. EnvironmentManager::removeDeadBindings(Environment Env,
  149. SymbolReaper &SymReaper,
  150. ProgramStateRef ST) {
  151. // We construct a new Environment object entirely, as this is cheaper than
  152. // individually removing all the subexpression bindings (which will greatly
  153. // outnumber block-level expression bindings).
  154. Environment NewEnv = getInitialEnvironment();
  155. MarkLiveCallback CB(SymReaper);
  156. ScanReachableSymbols RSScaner(ST, CB);
  157. llvm::ImmutableMapRef<EnvironmentEntry,SVal>
  158. EBMapRef(NewEnv.ExprBindings.getRootWithoutRetain(),
  159. F.getTreeFactory());
  160. // Iterate over the block-expr bindings.
  161. for (Environment::iterator I = Env.begin(), E = Env.end();
  162. I != E; ++I) {
  163. const EnvironmentEntry &BlkExpr = I.getKey();
  164. const SVal &X = I.getData();
  165. if (SymReaper.isLive(BlkExpr.getStmt(), BlkExpr.getLocationContext())) {
  166. // Copy the binding to the new map.
  167. EBMapRef = EBMapRef.add(BlkExpr, X);
  168. // If the block expr's value is a memory region, then mark that region.
  169. if (isa<loc::MemRegionVal>(X)) {
  170. const MemRegion *R = cast<loc::MemRegionVal>(X).getRegion();
  171. SymReaper.markLive(R);
  172. }
  173. // Mark all symbols in the block expr's value live.
  174. RSScaner.scan(X);
  175. continue;
  176. } else {
  177. SymExpr::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end();
  178. for (; SI != SE; ++SI)
  179. SymReaper.maybeDead(*SI);
  180. }
  181. }
  182. NewEnv.ExprBindings = EBMapRef.asImmutableMap();
  183. return NewEnv;
  184. }
  185. void Environment::print(raw_ostream &Out, const char *NL,
  186. const char *Sep) const {
  187. bool isFirst = true;
  188. for (Environment::iterator I = begin(), E = end(); I != E; ++I) {
  189. const EnvironmentEntry &En = I.getKey();
  190. if (isFirst) {
  191. Out << NL << NL
  192. << "Expressions:"
  193. << NL;
  194. isFirst = false;
  195. } else {
  196. Out << NL;
  197. }
  198. const Stmt *S = En.getStmt();
  199. Out << " (" << (const void*) En.getLocationContext() << ','
  200. << (const void*) S << ") ";
  201. LangOptions LO; // FIXME.
  202. S->printPretty(Out, 0, PrintingPolicy(LO));
  203. Out << " : " << I.getData();
  204. }
  205. }