blob: c2c9190fc9ff4384bd4347dfc62381c644f322d1 [file] [log] [blame]
Shih-wei Liaof8fd82b2010-02-10 11:10:31 -08001//== 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#include "clang/Checker/PathSensitive/GRState.h"
14#include "clang/Analysis/Analyses/LiveVariables.h"
15#include "llvm/ADT/ImmutableMap.h"
16
17using namespace clang;
18
19SVal Environment::GetSVal(const Stmt *E, ValueManager& ValMgr) const {
20
21 for (;;) {
22
23 switch (E->getStmtClass()) {
24
25 case Stmt::AddrLabelExprClass:
26 return ValMgr.makeLoc(cast<AddrLabelExpr>(E));
27
28 // ParenExprs are no-ops.
29
30 case Stmt::ParenExprClass:
31 E = cast<ParenExpr>(E)->getSubExpr();
32 continue;
33
34 case Stmt::CharacterLiteralClass: {
35 const CharacterLiteral* C = cast<CharacterLiteral>(E);
36 return ValMgr.makeIntVal(C->getValue(), C->getType());
37 }
38
39 case Stmt::IntegerLiteralClass: {
40 // In C++, this expression may have been bound to a temporary object.
41 SVal const *X = ExprBindings.lookup(E);
42 if (X)
43 return *X;
44 else
45 return ValMgr.makeIntVal(cast<IntegerLiteral>(E));
46 }
47
48 // Casts where the source and target type are the same
49 // are no-ops. We blast through these to get the descendant
50 // subexpression that has a value.
51
52 case Stmt::ImplicitCastExprClass:
53 case Stmt::CStyleCastExprClass: {
54 const CastExpr* C = cast<CastExpr>(E);
55 QualType CT = C->getType();
56
57 if (CT->isVoidType())
58 return UnknownVal();
59
60 break;
61 }
62
63 // Handle all other Stmt* using a lookup.
64
65 default:
66 break;
67 };
68
69 break;
70 }
71
72 return LookupExpr(E);
73}
74
75Environment EnvironmentManager::BindExpr(Environment Env, const Stmt *S,
76 SVal V, bool Invalidate) {
77 assert(S);
78
79 if (V.isUnknown()) {
80 if (Invalidate)
81 return Environment(F.Remove(Env.ExprBindings, S), Env.ACtx);
82 else
83 return Env;
84 }
85
86 return Environment(F.Add(Env.ExprBindings, S, V), Env.ACtx);
87}
88
89namespace {
90class MarkLiveCallback : public SymbolVisitor {
91 SymbolReaper &SymReaper;
92public:
93 MarkLiveCallback(SymbolReaper &symreaper) : SymReaper(symreaper) {}
94 bool VisitSymbol(SymbolRef sym) { SymReaper.markLive(sym); return true; }
95};
96} // end anonymous namespace
97
98// RemoveDeadBindings:
99// - Remove subexpression bindings.
100// - Remove dead block expression bindings.
101// - Keep live block expression bindings:
102// - Mark their reachable symbols live in SymbolReaper,
103// see ScanReachableSymbols.
104// - Mark the region in DRoots if the binding is a loc::MemRegionVal.
105
106Environment
107EnvironmentManager::RemoveDeadBindings(Environment Env, const Stmt *S,
108 SymbolReaper &SymReaper,
109 const GRState *ST,
110 llvm::SmallVectorImpl<const MemRegion*> &DRoots) {
111
112 CFG &C = *Env.getAnalysisContext().getCFG();
113
114 // We construct a new Environment object entirely, as this is cheaper than
115 // individually removing all the subexpression bindings (which will greatly
116 // outnumber block-level expression bindings).
117 Environment NewEnv = getInitialEnvironment(&Env.getAnalysisContext());
118
119 // Iterate over the block-expr bindings.
120 for (Environment::iterator I = Env.begin(), E = Env.end();
121 I != E; ++I) {
122
123 const Stmt *BlkExpr = I.getKey();
124
125 // Not a block-level expression?
126 if (!C.isBlkExpr(BlkExpr))
127 continue;
128
129 const SVal &X = I.getData();
130
131 if (SymReaper.isLive(S, BlkExpr)) {
132 // Copy the binding to the new map.
133 NewEnv.ExprBindings = F.Add(NewEnv.ExprBindings, BlkExpr, X);
134
135 // If the block expr's value is a memory region, then mark that region.
136 if (isa<loc::MemRegionVal>(X)) {
137 const MemRegion* R = cast<loc::MemRegionVal>(X).getRegion();
138 DRoots.push_back(R);
139 // Mark the super region of the RX as live.
140 // e.g.: int x; char *y = (char*) &x; if (*y) ...
141 // 'y' => element region. 'x' is its super region.
142 // We only add one level super region for now.
143
144 // FIXME: maybe multiple level of super regions should be added.
145 if (const SubRegion *SR = dyn_cast<SubRegion>(R))
146 DRoots.push_back(SR->getSuperRegion());
147 }
148
149 // Mark all symbols in the block expr's value live.
150 MarkLiveCallback cb(SymReaper);
151 ST->scanReachableSymbols(X, cb);
152 continue;
153 }
154
155 // Otherwise the expression is dead with a couple exceptions.
156 // Do not misclean LogicalExpr or ConditionalOperator. It is dead at the
157 // beginning of itself, but we need its UndefinedVal to determine its
158 // SVal.
159 if (X.isUndef() && cast<UndefinedVal>(X).getData())
160 NewEnv.ExprBindings = F.Add(NewEnv.ExprBindings, BlkExpr, X);
161 }
162
163 return NewEnv;
164}