clang API Documentation
00001 //== Environment.cpp - Map from Stmt* to Locations/Values -------*- C++ -*--==// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defined the Environment and EnvironmentManager classes. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "clang/AST/ExprCXX.h" 00015 #include "clang/AST/ExprObjC.h" 00016 #include "clang/Analysis/AnalysisContext.h" 00017 #include "clang/Analysis/CFG.h" 00018 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" 00019 00020 using namespace clang; 00021 using namespace ento; 00022 00023 SVal Environment::lookupExpr(const EnvironmentEntry &E) const { 00024 const SVal* X = ExprBindings.lookup(E); 00025 if (X) { 00026 SVal V = *X; 00027 return V; 00028 } 00029 return UnknownVal(); 00030 } 00031 00032 SVal Environment::getSVal(const EnvironmentEntry &Entry, 00033 SValBuilder& svalBuilder, 00034 bool useOnlyDirectBindings) const { 00035 00036 if (useOnlyDirectBindings) { 00037 // This branch is rarely taken, but can be exercised by 00038 // checkers that explicitly bind values to arbitrary 00039 // expressions. It is crucial that we do not ignore any 00040 // expression here, and do a direct lookup. 00041 return lookupExpr(Entry); 00042 } 00043 00044 const Stmt *E = Entry.getStmt(); 00045 const LocationContext *LCtx = Entry.getLocationContext(); 00046 00047 for (;;) { 00048 if (const Expr *Ex = dyn_cast<Expr>(E)) 00049 E = Ex->IgnoreParens(); 00050 00051 switch (E->getStmtClass()) { 00052 case Stmt::AddrLabelExprClass: 00053 return svalBuilder.makeLoc(cast<AddrLabelExpr>(E)); 00054 case Stmt::OpaqueValueExprClass: { 00055 const OpaqueValueExpr *ope = cast<OpaqueValueExpr>(E); 00056 E = ope->getSourceExpr(); 00057 continue; 00058 } 00059 case Stmt::ParenExprClass: 00060 case Stmt::GenericSelectionExprClass: 00061 llvm_unreachable("ParenExprs and GenericSelectionExprs should " 00062 "have been handled by IgnoreParens()"); 00063 case Stmt::CharacterLiteralClass: { 00064 const CharacterLiteral* C = cast<CharacterLiteral>(E); 00065 return svalBuilder.makeIntVal(C->getValue(), C->getType()); 00066 } 00067 case Stmt::CXXBoolLiteralExprClass: { 00068 const SVal *X = ExprBindings.lookup(EnvironmentEntry(E, LCtx)); 00069 if (X) 00070 return *X; 00071 else 00072 return svalBuilder.makeBoolVal(cast<CXXBoolLiteralExpr>(E)); 00073 } 00074 case Stmt::CXXScalarValueInitExprClass: 00075 case Stmt::ImplicitValueInitExprClass: { 00076 QualType Ty = cast<Expr>(E)->getType(); 00077 return svalBuilder.makeZeroVal(Ty); 00078 } 00079 case Stmt::IntegerLiteralClass: { 00080 // In C++, this expression may have been bound to a temporary object. 00081 SVal const *X = ExprBindings.lookup(EnvironmentEntry(E, LCtx)); 00082 if (X) 00083 return *X; 00084 else 00085 return svalBuilder.makeIntVal(cast<IntegerLiteral>(E)); 00086 } 00087 case Stmt::ObjCBoolLiteralExprClass: 00088 return svalBuilder.makeBoolVal(cast<ObjCBoolLiteralExpr>(E)); 00089 00090 // For special C0xx nullptr case, make a null pointer SVal. 00091 case Stmt::CXXNullPtrLiteralExprClass: 00092 return svalBuilder.makeNull(); 00093 case Stmt::ExprWithCleanupsClass: 00094 E = cast<ExprWithCleanups>(E)->getSubExpr(); 00095 continue; 00096 case Stmt::CXXBindTemporaryExprClass: 00097 E = cast<CXXBindTemporaryExpr>(E)->getSubExpr(); 00098 continue; 00099 case Stmt::ObjCPropertyRefExprClass: 00100 return loc::ObjCPropRef(cast<ObjCPropertyRefExpr>(E)); 00101 case Stmt::ObjCStringLiteralClass: { 00102 MemRegionManager &MRMgr = svalBuilder.getRegionManager(); 00103 const ObjCStringLiteral *SL = cast<ObjCStringLiteral>(E); 00104 return svalBuilder.makeLoc(MRMgr.getObjCStringRegion(SL)); 00105 } 00106 case Stmt::StringLiteralClass: { 00107 MemRegionManager &MRMgr = svalBuilder.getRegionManager(); 00108 const StringLiteral *SL = cast<StringLiteral>(E); 00109 return svalBuilder.makeLoc(MRMgr.getStringRegion(SL)); 00110 } 00111 case Stmt::ReturnStmtClass: { 00112 const ReturnStmt *RS = cast<ReturnStmt>(E); 00113 if (const Expr *RE = RS->getRetValue()) { 00114 E = RE; 00115 continue; 00116 } 00117 return UndefinedVal(); 00118 } 00119 00120 // Handle all other Stmt* using a lookup. 00121 default: 00122 break; 00123 }; 00124 break; 00125 } 00126 return lookupExpr(EnvironmentEntry(E, LCtx)); 00127 } 00128 00129 Environment EnvironmentManager::bindExpr(Environment Env, 00130 const EnvironmentEntry &E, 00131 SVal V, 00132 bool Invalidate) { 00133 if (V.isUnknown()) { 00134 if (Invalidate) 00135 return Environment(F.remove(Env.ExprBindings, E)); 00136 else 00137 return Env; 00138 } 00139 return Environment(F.add(Env.ExprBindings, E, V)); 00140 } 00141 00142 static inline EnvironmentEntry MakeLocation(const EnvironmentEntry &E) { 00143 const Stmt *S = E.getStmt(); 00144 S = (const Stmt*) (((uintptr_t) S) | 0x1); 00145 return EnvironmentEntry(S, E.getLocationContext()); 00146 } 00147 00148 Environment EnvironmentManager::bindExprAndLocation(Environment Env, 00149 const EnvironmentEntry &E, 00150 SVal location, SVal V) { 00151 return Environment(F.add(F.add(Env.ExprBindings, MakeLocation(E), location), 00152 E, V)); 00153 } 00154 00155 namespace { 00156 class MarkLiveCallback : public SymbolVisitor { 00157 SymbolReaper &SymReaper; 00158 public: 00159 MarkLiveCallback(SymbolReaper &symreaper) : SymReaper(symreaper) {} 00160 bool VisitSymbol(SymbolRef sym) { 00161 SymReaper.markLive(sym); 00162 return true; 00163 } 00164 bool VisitMemRegion(const MemRegion *R) { 00165 SymReaper.markLive(R); 00166 return true; 00167 } 00168 }; 00169 } // end anonymous namespace 00170 00171 // In addition to mapping from EnvironmentEntry - > SVals in the Environment, 00172 // we also maintain a mapping from EnvironmentEntry -> SVals (locations) 00173 // that were used during a load and store. 00174 static inline bool IsLocation(const EnvironmentEntry &E) { 00175 const Stmt *S = E.getStmt(); 00176 return (bool) (((uintptr_t) S) & 0x1); 00177 } 00178 00179 // removeDeadBindings: 00180 // - Remove subexpression bindings. 00181 // - Remove dead block expression bindings. 00182 // - Keep live block expression bindings: 00183 // - Mark their reachable symbols live in SymbolReaper, 00184 // see ScanReachableSymbols. 00185 // - Mark the region in DRoots if the binding is a loc::MemRegionVal. 00186 Environment 00187 EnvironmentManager::removeDeadBindings(Environment Env, 00188 SymbolReaper &SymReaper, 00189 ProgramStateRef ST) { 00190 00191 // We construct a new Environment object entirely, as this is cheaper than 00192 // individually removing all the subexpression bindings (which will greatly 00193 // outnumber block-level expression bindings). 00194 Environment NewEnv = getInitialEnvironment(); 00195 00196 SmallVector<std::pair<EnvironmentEntry, SVal>, 10> deferredLocations; 00197 00198 MarkLiveCallback CB(SymReaper); 00199 ScanReachableSymbols RSScaner(ST, CB); 00200 00201 llvm::ImmutableMapRef<EnvironmentEntry,SVal> 00202 EBMapRef(NewEnv.ExprBindings.getRootWithoutRetain(), 00203 F.getTreeFactory()); 00204 00205 // Iterate over the block-expr bindings. 00206 for (Environment::iterator I = Env.begin(), E = Env.end(); 00207 I != E; ++I) { 00208 00209 const EnvironmentEntry &BlkExpr = I.getKey(); 00210 // For recorded locations (used when evaluating loads and stores), we 00211 // consider them live only when their associated normal expression is 00212 // also live. 00213 // NOTE: This assumes that loads/stores that evaluated to UnknownVal 00214 // still have an entry in the map. 00215 if (IsLocation(BlkExpr)) { 00216 deferredLocations.push_back(std::make_pair(BlkExpr, I.getData())); 00217 continue; 00218 } 00219 const SVal &X = I.getData(); 00220 00221 if (SymReaper.isLive(BlkExpr.getStmt(), BlkExpr.getLocationContext())) { 00222 // Copy the binding to the new map. 00223 EBMapRef = EBMapRef.add(BlkExpr, X); 00224 00225 // If the block expr's value is a memory region, then mark that region. 00226 if (isa<loc::MemRegionVal>(X)) { 00227 const MemRegion *R = cast<loc::MemRegionVal>(X).getRegion(); 00228 SymReaper.markLive(R); 00229 } 00230 00231 // Mark all symbols in the block expr's value live. 00232 RSScaner.scan(X); 00233 continue; 00234 } 00235 00236 // Otherwise the expression is dead with a couple exceptions. 00237 // Do not misclean LogicalExpr or ConditionalOperator. It is dead at the 00238 // beginning of itself, but we need its UndefinedVal to determine its 00239 // SVal. 00240 if (X.isUndef() && cast<UndefinedVal>(X).getData()) 00241 EBMapRef = EBMapRef.add(BlkExpr, X); 00242 } 00243 00244 // Go through he deferred locations and add them to the new environment if 00245 // the correspond Stmt* is in the map as well. 00246 for (SmallVectorImpl<std::pair<EnvironmentEntry, SVal> >::iterator 00247 I = deferredLocations.begin(), E = deferredLocations.end(); I != E; ++I) { 00248 const EnvironmentEntry &En = I->first; 00249 const Stmt *S = (Stmt*) (((uintptr_t) En.getStmt()) & (uintptr_t) ~0x1); 00250 if (EBMapRef.lookup(EnvironmentEntry(S, En.getLocationContext()))) 00251 EBMapRef = EBMapRef.add(En, I->second); 00252 } 00253 00254 NewEnv.ExprBindings = EBMapRef.asImmutableMap(); 00255 return NewEnv; 00256 } 00257 00258 void Environment::print(raw_ostream &Out, const char *NL, 00259 const char *Sep) const { 00260 printAux(Out, false, NL, Sep); 00261 printAux(Out, true, NL, Sep); 00262 } 00263 00264 void Environment::printAux(raw_ostream &Out, bool printLocations, 00265 const char *NL, 00266 const char *Sep) const{ 00267 00268 bool isFirst = true; 00269 00270 for (Environment::iterator I = begin(), E = end(); I != E; ++I) { 00271 const EnvironmentEntry &En = I.getKey(); 00272 if (IsLocation(En)) { 00273 if (!printLocations) 00274 continue; 00275 } 00276 else { 00277 if (printLocations) 00278 continue; 00279 } 00280 00281 if (isFirst) { 00282 Out << NL << NL 00283 << (printLocations ? "Load/Store locations:" : "Expressions:") 00284 << NL; 00285 isFirst = false; 00286 } else { 00287 Out << NL; 00288 } 00289 00290 const Stmt *S = En.getStmt(); 00291 if (printLocations) { 00292 S = (Stmt*) (((uintptr_t) S) & ((uintptr_t) ~0x1)); 00293 } 00294 00295 Out << " (" << (void*) En.getLocationContext() << ',' << (void*) S << ") "; 00296 LangOptions LO; // FIXME. 00297 S->printPretty(Out, 0, PrintingPolicy(LO)); 00298 Out << " : " << I.getData(); 00299 } 00300 }