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 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 19 using namespace clang; 20 using namespace ento; 21 22 SVal Environment::lookupExpr(const Stmt *E) const { 23 const SVal* X = ExprBindings.lookup(E); 24 if (X) { 25 SVal V = *X; 26 return V; 27 } 28 return UnknownVal(); 29 } 30 31 SVal Environment::getSVal(const Stmt *E, SValBuilder& svalBuilder, 32 bool useOnlyDirectBindings) const { 33 34 if (useOnlyDirectBindings) { 35 // This branch is rarely taken, but can be exercised by 36 // checkers that explicitly bind values to arbitrary 37 // expressions. It is crucial that we do not ignore any 38 // expression here, and do a direct lookup. 39 return lookupExpr(E); 40 } 41 42 for (;;) { 43 if (const Expr *Ex = dyn_cast<Expr>(E)) 44 E = Ex->IgnoreParens(); 45 46 switch (E->getStmtClass()) { 47 case Stmt::AddrLabelExprClass: 48 return svalBuilder.makeLoc(cast<AddrLabelExpr>(E)); 49 case Stmt::OpaqueValueExprClass: { 50 const OpaqueValueExpr *ope = cast<OpaqueValueExpr>(E); 51 E = ope->getSourceExpr(); 52 continue; 53 } 54 case Stmt::ParenExprClass: 55 case Stmt::GenericSelectionExprClass: 56 llvm_unreachable("ParenExprs and GenericSelectionExprs should " 57 "have been handled by IgnoreParens()"); 58 return UnknownVal(); 59 case Stmt::CharacterLiteralClass: { 60 const CharacterLiteral* C = cast<CharacterLiteral>(E); 61 return svalBuilder.makeIntVal(C->getValue(), C->getType()); 62 } 63 case Stmt::CXXBoolLiteralExprClass: { 64 const SVal *X = ExprBindings.lookup(E); 65 if (X) 66 return *X; 67 else 68 return svalBuilder.makeBoolVal(cast<CXXBoolLiteralExpr>(E)); 69 } 70 case Stmt::IntegerLiteralClass: { 71 // In C++, this expression may have been bound to a temporary object. 72 SVal const *X = ExprBindings.lookup(E); 73 if (X) 74 return *X; 75 else 76 return svalBuilder.makeIntVal(cast<IntegerLiteral>(E)); 77 } 78 // For special C0xx nullptr case, make a null pointer SVal. 79 case Stmt::CXXNullPtrLiteralExprClass: 80 return svalBuilder.makeNull(); 81 case Stmt::ExprWithCleanupsClass: 82 E = cast<ExprWithCleanups>(E)->getSubExpr(); 83 continue; 84 case Stmt::CXXBindTemporaryExprClass: 85 E = cast<CXXBindTemporaryExpr>(E)->getSubExpr(); 86 continue; 87 case Stmt::ObjCPropertyRefExprClass: 88 return loc::ObjCPropRef(cast<ObjCPropertyRefExpr>(E)); 89 90 // Handle all other Stmt* using a lookup. 91 default: 92 break; 93 }; 94 break; 95 } 96 return lookupExpr(E); 97 } 98 99 Environment EnvironmentManager::bindExpr(Environment Env, const Stmt *S, 100 SVal V, bool Invalidate) { 101 assert(S); 102 103 if (V.isUnknown()) { 104 if (Invalidate) 105 return Environment(F.remove(Env.ExprBindings, S)); 106 else 107 return Env; 108 } 109 110 return Environment(F.add(Env.ExprBindings, S, V)); 111 } 112 113 static inline const Stmt *MakeLocation(const Stmt *S) { 114 return (const Stmt*) (((uintptr_t) S) | 0x1); 115 } 116 117 Environment EnvironmentManager::bindExprAndLocation(Environment Env, 118 const Stmt *S, 119 SVal location, SVal V) { 120 return Environment(F.add(F.add(Env.ExprBindings, MakeLocation(S), location), 121 S, V)); 122 } 123 124 namespace { 125 class MarkLiveCallback : public SymbolVisitor { 126 SymbolReaper &SymReaper; 127 public: 128 MarkLiveCallback(SymbolReaper &symreaper) : SymReaper(symreaper) {} 129 bool VisitSymbol(SymbolRef sym) { SymReaper.markLive(sym); return true; } 130 }; 131 } // end anonymous namespace 132 133 // In addition to mapping from Stmt * - > SVals in the Environment, we also 134 // maintain a mapping from Stmt * -> SVals (locations) that were used during 135 // a load and store. 136 static inline bool IsLocation(const Stmt *S) { 137 return (bool) (((uintptr_t) S) & 0x1); 138 } 139 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 const ProgramState *ST) { 151 152 // We construct a new Environment object entirely, as this is cheaper than 153 // individually removing all the subexpression bindings (which will greatly 154 // outnumber block-level expression bindings). 155 Environment NewEnv = getInitialEnvironment(); 156 157 SmallVector<std::pair<const Stmt*, SVal>, 10> deferredLocations; 158 159 MarkLiveCallback CB(SymReaper); 160 ScanReachableSymbols RSScaner(ST, CB); 161 162 llvm::ImmutableMapRef<const Stmt*,SVal> 163 EBMapRef(NewEnv.ExprBindings.getRootWithoutRetain(), 164 F.getTreeFactory()); 165 166 // Iterate over the block-expr bindings. 167 for (Environment::iterator I = Env.begin(), E = Env.end(); 168 I != E; ++I) { 169 170 const Stmt *BlkExpr = I.getKey(); 171 // For recorded locations (used when evaluating loads and stores), we 172 // consider them live only when their associated normal expression is 173 // also live. 174 // NOTE: This assumes that loads/stores that evaluated to UnknownVal 175 // still have an entry in the map. 176 if (IsLocation(BlkExpr)) { 177 deferredLocations.push_back(std::make_pair(BlkExpr, I.getData())); 178 continue; 179 } 180 const SVal &X = I.getData(); 181 182 if (SymReaper.isLive(BlkExpr)) { 183 // Copy the binding to the new map. 184 EBMapRef = EBMapRef.add(BlkExpr, X); 185 186 // If the block expr's value is a memory region, then mark that region. 187 if (isa<loc::MemRegionVal>(X)) { 188 const MemRegion *R = cast<loc::MemRegionVal>(X).getRegion(); 189 SymReaper.markLive(R); 190 } 191 192 // Mark all symbols in the block expr's value live. 193 RSScaner.scan(X); 194 continue; 195 } 196 197 // Otherwise the expression is dead with a couple exceptions. 198 // Do not misclean LogicalExpr or ConditionalOperator. It is dead at the 199 // beginning of itself, but we need its UndefinedVal to determine its 200 // SVal. 201 if (X.isUndef() && cast<UndefinedVal>(X).getData()) 202 EBMapRef = EBMapRef.add(BlkExpr, X); 203 } 204 205 // Go through he deferred locations and add them to the new environment if 206 // the correspond Stmt* is in the map as well. 207 for (SmallVectorImpl<std::pair<const Stmt*, SVal> >::iterator 208 I = deferredLocations.begin(), E = deferredLocations.end(); I != E; ++I) { 209 const Stmt *S = (Stmt*) (((uintptr_t) I->first) & (uintptr_t) ~0x1); 210 if (EBMapRef.lookup(S)) 211 EBMapRef = EBMapRef.add(I->first, I->second); 212 } 213 214 NewEnv.ExprBindings = EBMapRef.asImmutableMap(); 215 return NewEnv; 216 } 217