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 EnvironmentEntry &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 EnvironmentEntry &Entry, 32 SValBuilder& svalBuilder, 33 bool useOnlyDirectBindings) const { 34 35 if (useOnlyDirectBindings) { 36 // This branch is rarely taken, but can be exercised by 37 // checkers that explicitly bind values to arbitrary 38 // expressions. It is crucial that we do not ignore any 39 // expression here, and do a direct lookup. 40 return lookupExpr(Entry); 41 } 42 43 const Stmt *E = Entry.getStmt(); 44 const LocationContext *LCtx = Entry.getLocationContext(); 45 46 for (;;) { 47 if (const Expr *Ex = dyn_cast<Expr>(E)) 48 E = Ex->IgnoreParens(); 49 50 switch (E->getStmtClass()) { 51 case Stmt::AddrLabelExprClass: 52 return svalBuilder.makeLoc(cast<AddrLabelExpr>(E)); 53 case Stmt::OpaqueValueExprClass: { 54 const OpaqueValueExpr *ope = cast<OpaqueValueExpr>(E); 55 E = ope->getSourceExpr(); 56 continue; 57 } 58 case Stmt::ParenExprClass: 59 case Stmt::GenericSelectionExprClass: 60 llvm_unreachable("ParenExprs and GenericSelectionExprs should " 61 "have been handled by IgnoreParens()"); 62 case Stmt::CharacterLiteralClass: { 63 const CharacterLiteral* C = cast<CharacterLiteral>(E); 64 return svalBuilder.makeIntVal(C->getValue(), C->getType()); 65 } 66 case Stmt::CXXBoolLiteralExprClass: { 67 const SVal *X = ExprBindings.lookup(EnvironmentEntry(E, LCtx)); 68 if (X) 69 return *X; 70 else 71 return svalBuilder.makeBoolVal(cast<CXXBoolLiteralExpr>(E)); 72 } 73 case Stmt::IntegerLiteralClass: { 74 // In C++, this expression may have been bound to a temporary object. 75 SVal const *X = ExprBindings.lookup(EnvironmentEntry(E, LCtx)); 76 if (X) 77 return *X; 78 else 79 return svalBuilder.makeIntVal(cast<IntegerLiteral>(E)); 80 } 81 // For special C0xx nullptr case, make a null pointer SVal. 82 case Stmt::CXXNullPtrLiteralExprClass: 83 return svalBuilder.makeNull(); 84 case Stmt::ExprWithCleanupsClass: 85 E = cast<ExprWithCleanups>(E)->getSubExpr(); 86 continue; 87 case Stmt::CXXBindTemporaryExprClass: 88 E = cast<CXXBindTemporaryExpr>(E)->getSubExpr(); 89 continue; 90 case Stmt::ObjCPropertyRefExprClass: 91 return loc::ObjCPropRef(cast<ObjCPropertyRefExpr>(E)); 92 case Stmt::ReturnStmtClass: { 93 const ReturnStmt *RS = cast<ReturnStmt>(E); 94 if (const Expr *RE = RS->getRetValue()) { 95 E = RE; 96 continue; 97 } 98 return UndefinedVal(); 99 } 100 101 // Handle all other Stmt* using a lookup. 102 default: 103 break; 104 }; 105 break; 106 } 107 return lookupExpr(EnvironmentEntry(E, LCtx)); 108 } 109 110 Environment EnvironmentManager::bindExpr(Environment Env, 111 const EnvironmentEntry &E, 112 SVal V, 113 bool Invalidate) { 114 if (V.isUnknown()) { 115 if (Invalidate) 116 return Environment(F.remove(Env.ExprBindings, E)); 117 else 118 return Env; 119 } 120 return Environment(F.add(Env.ExprBindings, E, V)); 121 } 122 123 static inline EnvironmentEntry MakeLocation(const EnvironmentEntry &E) { 124 const Stmt *S = E.getStmt(); 125 S = (const Stmt*) (((uintptr_t) S) | 0x1); 126 return EnvironmentEntry(S, E.getLocationContext()); 127 } 128 129 Environment EnvironmentManager::bindExprAndLocation(Environment Env, 130 const EnvironmentEntry &E, 131 SVal location, SVal V) { 132 return Environment(F.add(F.add(Env.ExprBindings, MakeLocation(E), location), 133 E, V)); 134 } 135 136 namespace { 137 class MarkLiveCallback : public SymbolVisitor { 138 SymbolReaper &SymReaper; 139 public: 140 MarkLiveCallback(SymbolReaper &symreaper) : SymReaper(symreaper) {} 141 bool VisitSymbol(SymbolRef sym) { SymReaper.markLive(sym); return true; } 142 }; 143 } // end anonymous namespace 144 145 // In addition to mapping from EnvironmentEntry - > SVals in the Environment, 146 // we also maintain a mapping from EnvironmentEntry -> SVals (locations) 147 // that were used during a load and store. 148 static inline bool IsLocation(const EnvironmentEntry &E) { 149 const Stmt *S = E.getStmt(); 150 return (bool) (((uintptr_t) S) & 0x1); 151 } 152 153 // removeDeadBindings: 154 // - Remove subexpression bindings. 155 // - Remove dead block expression bindings. 156 // - Keep live block expression bindings: 157 // - Mark their reachable symbols live in SymbolReaper, 158 // see ScanReachableSymbols. 159 // - Mark the region in DRoots if the binding is a loc::MemRegionVal. 160 Environment 161 EnvironmentManager::removeDeadBindings(Environment Env, 162 SymbolReaper &SymReaper, 163 const ProgramState *ST) { 164 165 // We construct a new Environment object entirely, as this is cheaper than 166 // individually removing all the subexpression bindings (which will greatly 167 // outnumber block-level expression bindings). 168 Environment NewEnv = getInitialEnvironment(); 169 170 SmallVector<std::pair<EnvironmentEntry, SVal>, 10> deferredLocations; 171 172 MarkLiveCallback CB(SymReaper); 173 ScanReachableSymbols RSScaner(ST, CB); 174 175 llvm::ImmutableMapRef<EnvironmentEntry,SVal> 176 EBMapRef(NewEnv.ExprBindings.getRootWithoutRetain(), 177 F.getTreeFactory()); 178 179 // Iterate over the block-expr bindings. 180 for (Environment::iterator I = Env.begin(), E = Env.end(); 181 I != E; ++I) { 182 183 const EnvironmentEntry &BlkExpr = I.getKey(); 184 // For recorded locations (used when evaluating loads and stores), we 185 // consider them live only when their associated normal expression is 186 // also live. 187 // NOTE: This assumes that loads/stores that evaluated to UnknownVal 188 // still have an entry in the map. 189 if (IsLocation(BlkExpr)) { 190 deferredLocations.push_back(std::make_pair(BlkExpr, I.getData())); 191 continue; 192 } 193 const SVal &X = I.getData(); 194 195 if (SymReaper.isLive(BlkExpr.getStmt(), BlkExpr.getLocationContext())) { 196 // Copy the binding to the new map. 197 EBMapRef = EBMapRef.add(BlkExpr, X); 198 199 // If the block expr's value is a memory region, then mark that region. 200 if (isa<loc::MemRegionVal>(X)) { 201 const MemRegion *R = cast<loc::MemRegionVal>(X).getRegion(); 202 SymReaper.markLive(R); 203 } 204 205 // Mark all symbols in the block expr's value live. 206 RSScaner.scan(X); 207 continue; 208 } 209 210 // Otherwise the expression is dead with a couple exceptions. 211 // Do not misclean LogicalExpr or ConditionalOperator. It is dead at the 212 // beginning of itself, but we need its UndefinedVal to determine its 213 // SVal. 214 if (X.isUndef() && cast<UndefinedVal>(X).getData()) 215 EBMapRef = EBMapRef.add(BlkExpr, X); 216 } 217 218 // Go through he deferred locations and add them to the new environment if 219 // the correspond Stmt* is in the map as well. 220 for (SmallVectorImpl<std::pair<EnvironmentEntry, SVal> >::iterator 221 I = deferredLocations.begin(), E = deferredLocations.end(); I != E; ++I) { 222 const EnvironmentEntry &En = I->first; 223 const Stmt *S = (Stmt*) (((uintptr_t) En.getStmt()) & (uintptr_t) ~0x1); 224 if (EBMapRef.lookup(EnvironmentEntry(S, En.getLocationContext()))) 225 EBMapRef = EBMapRef.add(En, I->second); 226 } 227 228 NewEnv.ExprBindings = EBMapRef.asImmutableMap(); 229 return NewEnv; 230 } 231 232 void Environment::print(raw_ostream &Out, const char *NL, 233 const char *Sep) const { 234 printAux(Out, false, NL, Sep); 235 printAux(Out, true, NL, Sep); 236 } 237 238 void Environment::printAux(raw_ostream &Out, bool printLocations, 239 const char *NL, 240 const char *Sep) const{ 241 242 bool isFirst = true; 243 244 for (Environment::iterator I = begin(), E = end(); I != E; ++I) { 245 const EnvironmentEntry &En = I.getKey(); 246 if (IsLocation(En)) { 247 if (!printLocations) 248 continue; 249 } 250 else { 251 if (printLocations) 252 continue; 253 } 254 255 if (isFirst) { 256 Out << NL << NL 257 << (printLocations ? "Load/Store locations:" : "Expressions:") 258 << NL; 259 isFirst = false; 260 } else { 261 Out << NL; 262 } 263 264 const Stmt *S = En.getStmt(); 265 if (printLocations) { 266 S = (Stmt*) (((uintptr_t) S) & ((uintptr_t) ~0x1)); 267 } 268 269 Out << " (" << (void*) En.getLocationContext() << ',' << (void*) S << ") "; 270 LangOptions LO; // FIXME. 271 S->printPretty(Out, 0, PrintingPolicy(LO)); 272 Out << " : " << I.getData(); 273 } 274 } 275