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 #include "llvm/Support/raw_ostream.h" 00020 00021 using namespace clang; 00022 using namespace ento; 00023 00024 static const Expr *ignoreTransparentExprs(const Expr *E) { 00025 E = E->IgnoreParens(); 00026 00027 switch (E->getStmtClass()) { 00028 case Stmt::OpaqueValueExprClass: 00029 E = cast<OpaqueValueExpr>(E)->getSourceExpr(); 00030 break; 00031 case Stmt::ExprWithCleanupsClass: 00032 E = cast<ExprWithCleanups>(E)->getSubExpr(); 00033 break; 00034 case Stmt::CXXBindTemporaryExprClass: 00035 E = cast<CXXBindTemporaryExpr>(E)->getSubExpr(); 00036 break; 00037 case Stmt::SubstNonTypeTemplateParmExprClass: 00038 E = cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement(); 00039 break; 00040 default: 00041 // This is the base case: we can't look through more than we already have. 00042 return E; 00043 } 00044 00045 return ignoreTransparentExprs(E); 00046 } 00047 00048 static const Stmt *ignoreTransparentExprs(const Stmt *S) { 00049 if (const Expr *E = dyn_cast<Expr>(S)) 00050 return ignoreTransparentExprs(E); 00051 return S; 00052 } 00053 00054 EnvironmentEntry::EnvironmentEntry(const Stmt *S, const LocationContext *L) 00055 : std::pair<const Stmt *, 00056 const StackFrameContext *>(ignoreTransparentExprs(S), 00057 L ? L->getCurrentStackFrame() 00058 : nullptr) {} 00059 00060 SVal Environment::lookupExpr(const EnvironmentEntry &E) const { 00061 const SVal* X = ExprBindings.lookup(E); 00062 if (X) { 00063 SVal V = *X; 00064 return V; 00065 } 00066 return UnknownVal(); 00067 } 00068 00069 SVal Environment::getSVal(const EnvironmentEntry &Entry, 00070 SValBuilder& svalBuilder) const { 00071 const Stmt *S = Entry.getStmt(); 00072 const LocationContext *LCtx = Entry.getLocationContext(); 00073 00074 switch (S->getStmtClass()) { 00075 case Stmt::CXXBindTemporaryExprClass: 00076 case Stmt::ExprWithCleanupsClass: 00077 case Stmt::GenericSelectionExprClass: 00078 case Stmt::OpaqueValueExprClass: 00079 case Stmt::ParenExprClass: 00080 case Stmt::SubstNonTypeTemplateParmExprClass: 00081 llvm_unreachable("Should have been handled by ignoreTransparentExprs"); 00082 00083 case Stmt::AddrLabelExprClass: 00084 case Stmt::CharacterLiteralClass: 00085 case Stmt::CXXBoolLiteralExprClass: 00086 case Stmt::CXXScalarValueInitExprClass: 00087 case Stmt::ImplicitValueInitExprClass: 00088 case Stmt::IntegerLiteralClass: 00089 case Stmt::ObjCBoolLiteralExprClass: 00090 case Stmt::CXXNullPtrLiteralExprClass: 00091 case Stmt::ObjCStringLiteralClass: 00092 case Stmt::StringLiteralClass: 00093 // Known constants; defer to SValBuilder. 00094 return svalBuilder.getConstantVal(cast<Expr>(S)).getValue(); 00095 00096 case Stmt::ReturnStmtClass: { 00097 const ReturnStmt *RS = cast<ReturnStmt>(S); 00098 if (const Expr *RE = RS->getRetValue()) 00099 return getSVal(EnvironmentEntry(RE, LCtx), svalBuilder); 00100 return UndefinedVal(); 00101 } 00102 00103 // Handle all other Stmt* using a lookup. 00104 default: 00105 return lookupExpr(EnvironmentEntry(S, LCtx)); 00106 } 00107 } 00108 00109 Environment EnvironmentManager::bindExpr(Environment Env, 00110 const EnvironmentEntry &E, 00111 SVal V, 00112 bool Invalidate) { 00113 if (V.isUnknown()) { 00114 if (Invalidate) 00115 return Environment(F.remove(Env.ExprBindings, E)); 00116 else 00117 return Env; 00118 } 00119 return Environment(F.add(Env.ExprBindings, E, V)); 00120 } 00121 00122 namespace { 00123 class MarkLiveCallback : public SymbolVisitor { 00124 SymbolReaper &SymReaper; 00125 public: 00126 MarkLiveCallback(SymbolReaper &symreaper) : SymReaper(symreaper) {} 00127 bool VisitSymbol(SymbolRef sym) override { 00128 SymReaper.markLive(sym); 00129 return true; 00130 } 00131 bool VisitMemRegion(const MemRegion *R) override { 00132 SymReaper.markLive(R); 00133 return true; 00134 } 00135 }; 00136 } // end anonymous namespace 00137 00138 // removeDeadBindings: 00139 // - Remove subexpression bindings. 00140 // - Remove dead block expression bindings. 00141 // - Keep live block expression bindings: 00142 // - Mark their reachable symbols live in SymbolReaper, 00143 // see ScanReachableSymbols. 00144 // - Mark the region in DRoots if the binding is a loc::MemRegionVal. 00145 Environment 00146 EnvironmentManager::removeDeadBindings(Environment Env, 00147 SymbolReaper &SymReaper, 00148 ProgramStateRef ST) { 00149 00150 // We construct a new Environment object entirely, as this is cheaper than 00151 // individually removing all the subexpression bindings (which will greatly 00152 // outnumber block-level expression bindings). 00153 Environment NewEnv = getInitialEnvironment(); 00154 00155 MarkLiveCallback CB(SymReaper); 00156 ScanReachableSymbols RSScaner(ST, CB); 00157 00158 llvm::ImmutableMapRef<EnvironmentEntry,SVal> 00159 EBMapRef(NewEnv.ExprBindings.getRootWithoutRetain(), 00160 F.getTreeFactory()); 00161 00162 // Iterate over the block-expr bindings. 00163 for (Environment::iterator I = Env.begin(), E = Env.end(); 00164 I != E; ++I) { 00165 00166 const EnvironmentEntry &BlkExpr = I.getKey(); 00167 const SVal &X = I.getData(); 00168 00169 if (SymReaper.isLive(BlkExpr.getStmt(), BlkExpr.getLocationContext())) { 00170 // Copy the binding to the new map. 00171 EBMapRef = EBMapRef.add(BlkExpr, X); 00172 00173 // If the block expr's value is a memory region, then mark that region. 00174 if (Optional<loc::MemRegionVal> R = X.getAs<loc::MemRegionVal>()) 00175 SymReaper.markLive(R->getRegion()); 00176 00177 // Mark all symbols in the block expr's value live. 00178 RSScaner.scan(X); 00179 continue; 00180 } else { 00181 SymExpr::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end(); 00182 for (; SI != SE; ++SI) 00183 SymReaper.maybeDead(*SI); 00184 } 00185 } 00186 00187 NewEnv.ExprBindings = EBMapRef.asImmutableMap(); 00188 return NewEnv; 00189 } 00190 00191 void Environment::print(raw_ostream &Out, const char *NL, 00192 const char *Sep) const { 00193 bool isFirst = true; 00194 00195 for (Environment::iterator I = begin(), E = end(); I != E; ++I) { 00196 const EnvironmentEntry &En = I.getKey(); 00197 00198 if (isFirst) { 00199 Out << NL << NL 00200 << "Expressions:" 00201 << NL; 00202 isFirst = false; 00203 } else { 00204 Out << NL; 00205 } 00206 00207 const Stmt *S = En.getStmt(); 00208 assert(S != nullptr && "Expected non-null Stmt"); 00209 00210 Out << " (" << (const void*) En.getLocationContext() << ',' 00211 << (const void*) S << ") "; 00212 LangOptions LO; // FIXME. 00213 S->printPretty(Out, nullptr, PrintingPolicy(LO)); 00214 Out << " : " << I.getData(); 00215 } 00216 }