Environment.cpp revision d4ce811ae08398e357c8ce3e707ba5f2aa0041a5
1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//== Environment.cpp - Map from Stmt* to Locations/Values -------*- C++ -*--==// 2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// 3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// The LLVM Compiler Infrastructure 4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// This file is distributed under the University of Illinois Open Source 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// License. See LICENSE.TXT for details. 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//===----------------------------------------------------------------------===// 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// This file defined the Environment and EnvironmentManager classes. 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//===----------------------------------------------------------------------===// 13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "clang/AST/ExprCXX.h" 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "clang/AST/ExprObjC.h" 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "clang/Analysis/AnalysisContext.h" 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "clang/Analysis/CFG.h" 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using namespace clang; 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using namespace ento; 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static const Expr *ignoreTransparentExprs(const Expr *E) { 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) E = E->IgnoreParens(); 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) switch (E->getStmtClass()) { 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case Stmt::OpaqueValueExprClass: 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) E = cast<OpaqueValueExpr>(E)->getSourceExpr(); 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) break; 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case Stmt::ExprWithCleanupsClass: 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) E = cast<ExprWithCleanups>(E)->getSubExpr(); 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) break; 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case Stmt::CXXBindTemporaryExprClass: 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) E = cast<CXXBindTemporaryExpr>(E)->getSubExpr(); 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) break; 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case Stmt::SubstNonTypeTemplateParmExprClass: 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) E = cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement(); 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) break; 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case Stmt::CXXDefaultArgExprClass: 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) E = cast<CXXDefaultArgExpr>(E)->getExpr(); 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) break; 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) default: 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // This is the base case: we can't look through more than we already have. 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return E; 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return ignoreTransparentExprs(E); 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static const Stmt *ignoreTransparentExprs(const Stmt *S) { 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (const Expr *E = dyn_cast<Expr>(S)) 52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return ignoreTransparentExprs(E); 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return S; 54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)EnvironmentEntry::EnvironmentEntry(const Stmt *S, const LocationContext *L) 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : std::pair<const Stmt *, 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const StackFrameContext *>(ignoreTransparentExprs(S), 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) L ? L->getCurrentStackFrame() : 0) {} 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)SVal Environment::lookupExpr(const EnvironmentEntry &E) const { 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const SVal* X = ExprBindings.lookup(E); 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (X) { 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SVal V = *X; 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return V; 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return UnknownVal(); 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)SVal Environment::getSVal(const EnvironmentEntry &Entry, 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SValBuilder& svalBuilder) const { 72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const Stmt *S = Entry.getStmt(); 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const LocationContext *LCtx = Entry.getLocationContext(); 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) switch (S->getStmtClass()) { 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case Stmt::CXXBindTemporaryExprClass: 77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case Stmt::CXXDefaultArgExprClass: 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case Stmt::ExprWithCleanupsClass: 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case Stmt::GenericSelectionExprClass: 80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case Stmt::OpaqueValueExprClass: 81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case Stmt::ParenExprClass: 82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case Stmt::SubstNonTypeTemplateParmExprClass: 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) llvm_unreachable("Should have been handled by ignoreTransparentExprs"); 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case Stmt::AddrLabelExprClass: 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return svalBuilder.makeLoc(cast<AddrLabelExpr>(S)); 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case Stmt::CharacterLiteralClass: { 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const CharacterLiteral *C = cast<CharacterLiteral>(S); 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return svalBuilder.makeIntVal(C->getValue(), C->getType()); 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case Stmt::CXXBoolLiteralExprClass: 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return svalBuilder.makeBoolVal(cast<CXXBoolLiteralExpr>(S)); 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case Stmt::CXXScalarValueInitExprClass: 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case Stmt::ImplicitValueInitExprClass: { 98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) QualType Ty = cast<Expr>(S)->getType(); 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return svalBuilder.makeZeroVal(Ty); 100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case Stmt::IntegerLiteralClass: 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return svalBuilder.makeIntVal(cast<IntegerLiteral>(S)); 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case Stmt::ObjCBoolLiteralExprClass: 106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return svalBuilder.makeBoolVal(cast<ObjCBoolLiteralExpr>(S)); 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // For special C0xx nullptr case, make a null pointer SVal. 109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case Stmt::CXXNullPtrLiteralExprClass: 110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return svalBuilder.makeNull(); 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case Stmt::ObjCStringLiteralClass: { 113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MemRegionManager &MRMgr = svalBuilder.getRegionManager(); 114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const ObjCStringLiteral *SL = cast<ObjCStringLiteral>(S); 115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return svalBuilder.makeLoc(MRMgr.getObjCStringRegion(SL)); 116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case Stmt::StringLiteralClass: { 119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MemRegionManager &MRMgr = svalBuilder.getRegionManager(); 120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const StringLiteral *SL = cast<StringLiteral>(S); 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return svalBuilder.makeLoc(MRMgr.getStringRegion(SL)); 122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case Stmt::ReturnStmtClass: { 125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const ReturnStmt *RS = cast<ReturnStmt>(S); 126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (const Expr *RE = RS->getRetValue()) 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return getSVal(EnvironmentEntry(RE, LCtx), svalBuilder); 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return UndefinedVal(); 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Handle all other Stmt* using a lookup. 132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) default: 133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) break; 134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return lookupExpr(EnvironmentEntry(S, LCtx)); 137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Environment EnvironmentManager::bindExpr(Environment Env, 140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const EnvironmentEntry &E, 141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SVal V, 142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool Invalidate) { 143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (V.isUnknown()) { 144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (Invalidate) 145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return Environment(F.remove(Env.ExprBindings, E)); 146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) else 147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return Env; 148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return Environment(F.add(Env.ExprBindings, E, V)); 150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)EnvironmentEntry EnvironmentEntry::makeLocation() const { 153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EnvironmentEntry Result = *this; 154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) reinterpret_cast<uintptr_t &>(Result.first) |= 0x1; 155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return Result; 156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Environment EnvironmentManager::bindExprAndLocation(Environment Env, 159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const EnvironmentEntry &E, 160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SVal location, SVal V) { 161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return Environment(F.add(F.add(Env.ExprBindings, E.makeLocation(), location), 162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) E, V)); 163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace { 166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class MarkLiveCallback : public SymbolVisitor { 167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SymbolReaper &SymReaper; 168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)public: 169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MarkLiveCallback(SymbolReaper &symreaper) : SymReaper(symreaper) {} 170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool VisitSymbol(SymbolRef sym) { 171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SymReaper.markLive(sym); 172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return true; 173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool VisitMemRegion(const MemRegion *R) { 175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SymReaper.markLive(R); 176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return true; 177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // end anonymous namespace 180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// In addition to mapping from EnvironmentEntry - > SVals in the Environment, 182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// we also maintain a mapping from EnvironmentEntry -> SVals (locations) 183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// that were used during a load and store. 184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static inline bool IsLocation(const EnvironmentEntry &E) { 185 const Stmt *S = E.getStmt(); 186 return (bool) (((uintptr_t) S) & 0x1); 187} 188 189// removeDeadBindings: 190// - Remove subexpression bindings. 191// - Remove dead block expression bindings. 192// - Keep live block expression bindings: 193// - Mark their reachable symbols live in SymbolReaper, 194// see ScanReachableSymbols. 195// - Mark the region in DRoots if the binding is a loc::MemRegionVal. 196Environment 197EnvironmentManager::removeDeadBindings(Environment Env, 198 SymbolReaper &SymReaper, 199 ProgramStateRef ST) { 200 201 // We construct a new Environment object entirely, as this is cheaper than 202 // individually removing all the subexpression bindings (which will greatly 203 // outnumber block-level expression bindings). 204 Environment NewEnv = getInitialEnvironment(); 205 206 SmallVector<std::pair<EnvironmentEntry, SVal>, 10> deferredLocations; 207 208 MarkLiveCallback CB(SymReaper); 209 ScanReachableSymbols RSScaner(ST, CB); 210 211 llvm::ImmutableMapRef<EnvironmentEntry,SVal> 212 EBMapRef(NewEnv.ExprBindings.getRootWithoutRetain(), 213 F.getTreeFactory()); 214 215 // Iterate over the block-expr bindings. 216 for (Environment::iterator I = Env.begin(), E = Env.end(); 217 I != E; ++I) { 218 219 const EnvironmentEntry &BlkExpr = I.getKey(); 220 // For recorded locations (used when evaluating loads and stores), we 221 // consider them live only when their associated normal expression is 222 // also live. 223 // NOTE: This assumes that loads/stores that evaluated to UnknownVal 224 // still have an entry in the map. 225 if (IsLocation(BlkExpr)) { 226 deferredLocations.push_back(std::make_pair(BlkExpr, I.getData())); 227 continue; 228 } 229 const SVal &X = I.getData(); 230 231 if (SymReaper.isLive(BlkExpr.getStmt(), BlkExpr.getLocationContext())) { 232 // Copy the binding to the new map. 233 EBMapRef = EBMapRef.add(BlkExpr, X); 234 235 // If the block expr's value is a memory region, then mark that region. 236 if (isa<loc::MemRegionVal>(X)) { 237 const MemRegion *R = cast<loc::MemRegionVal>(X).getRegion(); 238 SymReaper.markLive(R); 239 } 240 241 // Mark all symbols in the block expr's value live. 242 RSScaner.scan(X); 243 continue; 244 } 245 } 246 247 // Go through he deferred locations and add them to the new environment if 248 // the correspond Stmt* is in the map as well. 249 for (SmallVectorImpl<std::pair<EnvironmentEntry, SVal> >::iterator 250 I = deferredLocations.begin(), E = deferredLocations.end(); I != E; ++I) { 251 const EnvironmentEntry &En = I->first; 252 const Stmt *S = (Stmt*) (((uintptr_t) En.getStmt()) & (uintptr_t) ~0x1); 253 if (EBMapRef.lookup(EnvironmentEntry(S, En.getLocationContext()))) 254 EBMapRef = EBMapRef.add(En, I->second); 255 } 256 257 NewEnv.ExprBindings = EBMapRef.asImmutableMap(); 258 return NewEnv; 259} 260 261void Environment::print(raw_ostream &Out, const char *NL, 262 const char *Sep) const { 263 printAux(Out, false, NL, Sep); 264 printAux(Out, true, NL, Sep); 265} 266 267void Environment::printAux(raw_ostream &Out, bool printLocations, 268 const char *NL, 269 const char *Sep) const{ 270 271 bool isFirst = true; 272 273 for (Environment::iterator I = begin(), E = end(); I != E; ++I) { 274 const EnvironmentEntry &En = I.getKey(); 275 if (IsLocation(En)) { 276 if (!printLocations) 277 continue; 278 } 279 else { 280 if (printLocations) 281 continue; 282 } 283 284 if (isFirst) { 285 Out << NL << NL 286 << (printLocations ? "Load/Store locations:" : "Expressions:") 287 << NL; 288 isFirst = false; 289 } else { 290 Out << NL; 291 } 292 293 const Stmt *S = En.getStmt(); 294 if (printLocations) { 295 S = (Stmt*) (((uintptr_t) S) & ((uintptr_t) ~0x1)); 296 } 297 298 Out << " (" << (const void*) En.getLocationContext() << ',' 299 << (const void*) S << ") "; 300 LangOptions LO; // FIXME. 301 S->printPretty(Out, 0, PrintingPolicy(LO)); 302 Out << " : " << I.getData(); 303 } 304} 305