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/Analysis/AnalysisContext.h" 15 #include "clang/Analysis/CFG.h" 16 #include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h" 17 18 using namespace clang; 19 using namespace ento; 20 21 SVal Environment::lookupExpr(const Stmt* E) const { 22 const SVal* X = ExprBindings.lookup(E); 23 if (X) { 24 SVal V = *X; 25 return V; 26 } 27 return UnknownVal(); 28 } 29 30 SVal Environment::getSVal(const Stmt *E, SValBuilder& svalBuilder, 31 bool useOnlyDirectBindings) const { 32 33 if (useOnlyDirectBindings) { 34 // This branch is rarely taken, but can be exercised by 35 // checkers that explicitly bind values to arbitrary 36 // expressions. It is crucial that we do not ignore any 37 // expression here, and do a direct lookup. 38 return lookupExpr(E); 39 } 40 41 for (;;) { 42 switch (E->getStmtClass()) { 43 case Stmt::AddrLabelExprClass: 44 return svalBuilder.makeLoc(cast<AddrLabelExpr>(E)); 45 case Stmt::OpaqueValueExprClass: { 46 const OpaqueValueExpr *ope = cast<OpaqueValueExpr>(E); 47 E = ope->getSourceExpr(); 48 continue; 49 } 50 case Stmt::ParenExprClass: 51 // ParenExprs are no-ops. 52 E = cast<ParenExpr>(E)->getSubExpr(); 53 continue; 54 case Stmt::GenericSelectionExprClass: 55 // GenericSelectionExprs are no-ops. 56 E = cast<GenericSelectionExpr>(E)->getResultExpr(); 57 continue; 58 case Stmt::CharacterLiteralClass: { 59 const CharacterLiteral* C = cast<CharacterLiteral>(E); 60 return svalBuilder.makeIntVal(C->getValue(), C->getType()); 61 } 62 case Stmt::CXXBoolLiteralExprClass: { 63 const SVal *X = ExprBindings.lookup(E); 64 if (X) 65 return *X; 66 else 67 return svalBuilder.makeBoolVal(cast<CXXBoolLiteralExpr>(E)); 68 } 69 case Stmt::IntegerLiteralClass: { 70 // In C++, this expression may have been bound to a temporary object. 71 SVal const *X = ExprBindings.lookup(E); 72 if (X) 73 return *X; 74 else 75 return svalBuilder.makeIntVal(cast<IntegerLiteral>(E)); 76 } 77 // For special C0xx nullptr case, make a null pointer SVal. 78 case Stmt::CXXNullPtrLiteralExprClass: 79 return svalBuilder.makeNull(); 80 case Stmt::ImplicitCastExprClass: 81 case Stmt::CXXFunctionalCastExprClass: 82 case Stmt::CStyleCastExprClass: { 83 // We blast through no-op casts to get the descendant 84 // subexpression that has a value. 85 const CastExpr* C = cast<CastExpr>(E); 86 QualType CT = C->getType(); 87 if (CT->isVoidType()) 88 return UnknownVal(); 89 if (C->getCastKind() == CK_NoOp) { 90 E = C->getSubExpr(); 91 continue; 92 } 93 break; 94 } 95 case Stmt::ExprWithCleanupsClass: 96 E = cast<ExprWithCleanups>(E)->getSubExpr(); 97 continue; 98 case Stmt::CXXBindTemporaryExprClass: 99 E = cast<CXXBindTemporaryExpr>(E)->getSubExpr(); 100 continue; 101 // Handle all other Stmt* using a lookup. 102 default: 103 break; 104 }; 105 break; 106 } 107 return lookupExpr(E); 108 } 109 110 Environment EnvironmentManager::bindExpr(Environment Env, const Stmt *S, 111 SVal V, bool Invalidate) { 112 assert(S); 113 114 if (V.isUnknown()) { 115 if (Invalidate) 116 return Environment(F.remove(Env.ExprBindings, S)); 117 else 118 return Env; 119 } 120 121 return Environment(F.add(Env.ExprBindings, S, V)); 122 } 123 124 static inline const Stmt *MakeLocation(const Stmt *S) { 125 return (const Stmt*) (((uintptr_t) S) | 0x1); 126 } 127 128 Environment EnvironmentManager::bindExprAndLocation(Environment Env, 129 const Stmt *S, 130 SVal location, SVal V) { 131 return Environment(F.add(F.add(Env.ExprBindings, MakeLocation(S), location), 132 S, V)); 133 } 134 135 namespace { 136 class MarkLiveCallback : public SymbolVisitor { 137 SymbolReaper &SymReaper; 138 public: 139 MarkLiveCallback(SymbolReaper &symreaper) : SymReaper(symreaper) {} 140 bool VisitSymbol(SymbolRef sym) { SymReaper.markLive(sym); return true; } 141 }; 142 } // end anonymous namespace 143 144 static bool isBlockExprInCallers(const Stmt *E, const LocationContext *LC) { 145 const LocationContext *ParentLC = LC->getParent(); 146 while (ParentLC) { 147 CFG &C = *ParentLC->getCFG(); 148 if (C.isBlkExpr(E)) 149 return true; 150 ParentLC = ParentLC->getParent(); 151 } 152 153 return false; 154 } 155 156 // In addition to mapping from Stmt * - > SVals in the Environment, we also 157 // maintain a mapping from Stmt * -> SVals (locations) that were used during 158 // a load and store. 159 static inline bool IsLocation(const Stmt *S) { 160 return (bool) (((uintptr_t) S) & 0x1); 161 } 162 163 // removeDeadBindings: 164 // - Remove subexpression bindings. 165 // - Remove dead block expression bindings. 166 // - Keep live block expression bindings: 167 // - Mark their reachable symbols live in SymbolReaper, 168 // see ScanReachableSymbols. 169 // - Mark the region in DRoots if the binding is a loc::MemRegionVal. 170 Environment 171 EnvironmentManager::removeDeadBindings(Environment Env, 172 SymbolReaper &SymReaper, 173 const GRState *ST, 174 llvm::SmallVectorImpl<const MemRegion*> &DRoots) { 175 176 CFG &C = *SymReaper.getLocationContext()->getCFG(); 177 178 // We construct a new Environment object entirely, as this is cheaper than 179 // individually removing all the subexpression bindings (which will greatly 180 // outnumber block-level expression bindings). 181 Environment NewEnv = getInitialEnvironment(); 182 183 llvm::SmallVector<std::pair<const Stmt*, SVal>, 10> deferredLocations; 184 185 // Iterate over the block-expr bindings. 186 for (Environment::iterator I = Env.begin(), E = Env.end(); 187 I != E; ++I) { 188 189 const Stmt *BlkExpr = I.getKey(); 190 191 // For recorded locations (used when evaluating loads and stores), we 192 // consider them live only when their associated normal expression is 193 // also live. 194 // NOTE: This assumes that loads/stores that evaluated to UnknownVal 195 // still have an entry in the map. 196 if (IsLocation(BlkExpr)) { 197 deferredLocations.push_back(std::make_pair(BlkExpr, I.getData())); 198 continue; 199 } 200 201 const SVal &X = I.getData(); 202 203 // Block-level expressions in callers are assumed always live. 204 if (isBlockExprInCallers(BlkExpr, SymReaper.getLocationContext())) { 205 NewEnv.ExprBindings = F.add(NewEnv.ExprBindings, BlkExpr, X); 206 207 if (isa<loc::MemRegionVal>(X)) { 208 const MemRegion* R = cast<loc::MemRegionVal>(X).getRegion(); 209 DRoots.push_back(R); 210 } 211 212 // Mark all symbols in the block expr's value live. 213 MarkLiveCallback cb(SymReaper); 214 ST->scanReachableSymbols(X, cb); 215 continue; 216 } 217 218 // Not a block-level expression? 219 if (!C.isBlkExpr(BlkExpr)) 220 continue; 221 222 if (SymReaper.isLive(BlkExpr)) { 223 // Copy the binding to the new map. 224 NewEnv.ExprBindings = F.add(NewEnv.ExprBindings, BlkExpr, X); 225 226 // If the block expr's value is a memory region, then mark that region. 227 if (isa<loc::MemRegionVal>(X)) { 228 const MemRegion* R = cast<loc::MemRegionVal>(X).getRegion(); 229 DRoots.push_back(R); 230 } 231 232 // Mark all symbols in the block expr's value live. 233 MarkLiveCallback cb(SymReaper); 234 ST->scanReachableSymbols(X, cb); 235 continue; 236 } 237 238 // Otherwise the expression is dead with a couple exceptions. 239 // Do not misclean LogicalExpr or ConditionalOperator. It is dead at the 240 // beginning of itself, but we need its UndefinedVal to determine its 241 // SVal. 242 if (X.isUndef() && cast<UndefinedVal>(X).getData()) 243 NewEnv.ExprBindings = F.add(NewEnv.ExprBindings, BlkExpr, X); 244 } 245 246 // Go through he deferred locations and add them to the new environment if 247 // the correspond Stmt* is in the map as well. 248 for (llvm::SmallVectorImpl<std::pair<const Stmt*, SVal> >::iterator 249 I = deferredLocations.begin(), E = deferredLocations.end(); I != E; ++I) { 250 const Stmt *S = (Stmt*) (((uintptr_t) I->first) & (uintptr_t) ~0x1); 251 if (NewEnv.ExprBindings.lookup(S)) 252 NewEnv.ExprBindings = F.add(NewEnv.ExprBindings, I->first, I->second); 253 } 254 255 return NewEnv; 256 } 257