diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Checker/Environment.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Checker/Environment.cpp | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/contrib/llvm/tools/clang/lib/Checker/Environment.cpp b/contrib/llvm/tools/clang/lib/Checker/Environment.cpp new file mode 100644 index 0000000..addfc21 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Checker/Environment.cpp @@ -0,0 +1,191 @@ +//== Environment.cpp - Map from Stmt* to Locations/Values -------*- C++ -*--==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defined the Environment and EnvironmentManager classes. +// +//===----------------------------------------------------------------------===// + +#include "clang/Analysis/AnalysisContext.h" +#include "clang/Analysis/CFG.h" +#include "clang/Checker/PathSensitive/GRState.h" + +using namespace clang; + +SVal Environment::GetSVal(const Stmt *E, ValueManager& ValMgr) const { + + for (;;) { + + switch (E->getStmtClass()) { + + case Stmt::AddrLabelExprClass: + return ValMgr.makeLoc(cast<AddrLabelExpr>(E)); + + // ParenExprs are no-ops. + + case Stmt::ParenExprClass: + E = cast<ParenExpr>(E)->getSubExpr(); + continue; + + case Stmt::CharacterLiteralClass: { + const CharacterLiteral* C = cast<CharacterLiteral>(E); + return ValMgr.makeIntVal(C->getValue(), C->getType()); + } + + case Stmt::CXXBoolLiteralExprClass: { + const SVal *X = ExprBindings.lookup(E); + if (X) + return *X; + else + return ValMgr.makeIntVal(cast<CXXBoolLiteralExpr>(E)); + } + case Stmt::IntegerLiteralClass: { + // In C++, this expression may have been bound to a temporary object. + SVal const *X = ExprBindings.lookup(E); + if (X) + return *X; + else + return ValMgr.makeIntVal(cast<IntegerLiteral>(E)); + } + + // Casts where the source and target type are the same + // are no-ops. We blast through these to get the descendant + // subexpression that has a value. + + case Stmt::ImplicitCastExprClass: + case Stmt::CStyleCastExprClass: { + const CastExpr* C = cast<CastExpr>(E); + QualType CT = C->getType(); + + if (CT->isVoidType()) + return UnknownVal(); + + break; + } + + // Handle all other Stmt* using a lookup. + + default: + break; + }; + + break; + } + + return LookupExpr(E); +} + +Environment EnvironmentManager::BindExpr(Environment Env, const Stmt *S, + SVal V, bool Invalidate) { + assert(S); + + if (V.isUnknown()) { + if (Invalidate) + return Environment(F.Remove(Env.ExprBindings, S)); + else + return Env; + } + + return Environment(F.Add(Env.ExprBindings, S, V)); +} + +namespace { +class MarkLiveCallback : public SymbolVisitor { + SymbolReaper &SymReaper; +public: + MarkLiveCallback(SymbolReaper &symreaper) : SymReaper(symreaper) {} + bool VisitSymbol(SymbolRef sym) { SymReaper.markLive(sym); return true; } +}; +} // end anonymous namespace + +static bool isBlockExprInCallers(const Stmt *E, const LocationContext *LC) { + const LocationContext *ParentLC = LC->getParent(); + while (ParentLC) { + CFG &C = *ParentLC->getCFG(); + if (C.isBlkExpr(E)) + return true; + ParentLC = ParentLC->getParent(); + } + + return false; +} + + +// RemoveDeadBindings: +// - Remove subexpression bindings. +// - Remove dead block expression bindings. +// - Keep live block expression bindings: +// - Mark their reachable symbols live in SymbolReaper, +// see ScanReachableSymbols. +// - Mark the region in DRoots if the binding is a loc::MemRegionVal. + +Environment +EnvironmentManager::RemoveDeadBindings(Environment Env, const Stmt *S, + SymbolReaper &SymReaper, + const GRState *ST, + llvm::SmallVectorImpl<const MemRegion*> &DRoots) { + + CFG &C = *SymReaper.getLocationContext()->getCFG(); + + // We construct a new Environment object entirely, as this is cheaper than + // individually removing all the subexpression bindings (which will greatly + // outnumber block-level expression bindings). + Environment NewEnv = getInitialEnvironment(); + + // Iterate over the block-expr bindings. + for (Environment::iterator I = Env.begin(), E = Env.end(); + I != E; ++I) { + + const Stmt *BlkExpr = I.getKey(); + const SVal &X = I.getData(); + + // Block-level expressions in callers are assumed always live. + if (isBlockExprInCallers(BlkExpr, SymReaper.getLocationContext())) { + NewEnv.ExprBindings = F.Add(NewEnv.ExprBindings, BlkExpr, X); + + if (isa<loc::MemRegionVal>(X)) { + const MemRegion* R = cast<loc::MemRegionVal>(X).getRegion(); + DRoots.push_back(R); + } + + // Mark all symbols in the block expr's value live. + MarkLiveCallback cb(SymReaper); + ST->scanReachableSymbols(X, cb); + continue; + } + + // Not a block-level expression? + if (!C.isBlkExpr(BlkExpr)) + continue; + + if (SymReaper.isLive(S, BlkExpr)) { + // Copy the binding to the new map. + NewEnv.ExprBindings = F.Add(NewEnv.ExprBindings, BlkExpr, X); + + // If the block expr's value is a memory region, then mark that region. + if (isa<loc::MemRegionVal>(X)) { + const MemRegion* R = cast<loc::MemRegionVal>(X).getRegion(); + DRoots.push_back(R); + } + + // Mark all symbols in the block expr's value live. + MarkLiveCallback cb(SymReaper); + ST->scanReachableSymbols(X, cb); + continue; + } + + // Otherwise the expression is dead with a couple exceptions. + // Do not misclean LogicalExpr or ConditionalOperator. It is dead at the + // beginning of itself, but we need its UndefinedVal to determine its + // SVal. + if (X.isUndef() && cast<UndefinedVal>(X).getData()) + NewEnv.ExprBindings = F.Add(NewEnv.ExprBindings, BlkExpr, X); + } + + return NewEnv; +} |