blob: 490ed7f31eed6abe39ae9545a86c57920059a1ad [file] [log] [blame]
Ted Kremenekd59cccc2008-02-14 18:28:23 +00001// GRSimpleVals.cpp - Transfer functions for tracking simple 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 files defines GRSimpleVals, a sub-class of GRTransferFuncs that
11// provides transfer functions for performing simple value tracking with
12// limited support for symbolics.
13//
14//===----------------------------------------------------------------------===//
15
16#include "GRSimpleVals.h"
Ted Kremeneke01c9872008-02-14 22:36:46 +000017#include "clang/Basic/Diagnostic.h"
Ted Kremenekd59cccc2008-02-14 18:28:23 +000018
19using namespace clang;
20
Ted Kremeneke01c9872008-02-14 22:36:46 +000021namespace clang {
22 void RunGRSimpleVals(CFG& cfg, FunctionDecl& FD, ASTContext& Ctx,
23 Diagnostic& Diag) {
24
25 GRCoreEngine<GRExprEngine> Engine(cfg, FD, Ctx);
26 GRExprEngine* CheckerState = &Engine.getCheckerState();
27 GRSimpleVals GRSV;
28 CheckerState->setTransferFunctions(GRSV);
29
30 // Execute the worklist algorithm.
31 Engine.ExecuteWorkList();
32
33 // Look for explicit-Null dereferences and warn about them.
34 for (GRExprEngine::null_iterator I=CheckerState->null_begin(),
35 E=CheckerState->null_end(); I!=E; ++I) {
36
37 const PostStmt& L = cast<PostStmt>((*I)->getLocation());
38 Expr* E = cast<Expr>(L.getStmt());
39
40 Diag.Report(FullSourceLoc(E->getExprLoc(), Ctx.getSourceManager()),
41 diag::chkr_null_deref_after_check);
42 }
43
44#ifndef NDEBUG
45 CheckerState->ViewGraph();
46#endif
47 }
48} // end clang namespace
49
Ted Kremenekd59cccc2008-02-14 18:28:23 +000050//===----------------------------------------------------------------------===//
51// Transfer function for Casts.
52//===----------------------------------------------------------------------===//
53
54RValue GRSimpleVals::EvalCast(ValueManager& ValMgr, NonLValue X,
55 Expr* CastExpr) {
56
57 if (!isa<nonlval::ConcreteInt>(X))
58 return UnknownVal();
59
60 llvm::APSInt V = cast<nonlval::ConcreteInt>(X).getValue();
61 QualType T = CastExpr->getType();
62 V.setIsUnsigned(T->isUnsignedIntegerType() || T->isPointerType());
63 V.extOrTrunc(ValMgr.getContext().getTypeSize(T, CastExpr->getLocStart()));
64
65 if (CastExpr->getType()->isPointerType())
66 return lval::ConcreteInt(ValMgr.getValue(V));
67 else
68 return nonlval::ConcreteInt(ValMgr.getValue(V));
69}
70
71// Casts.
72
73RValue GRSimpleVals::EvalCast(ValueManager& ValMgr, LValue X, Expr* CastExpr) {
74
75 if (CastExpr->getType()->isPointerType())
76 return X;
77
78 assert (CastExpr->getType()->isIntegerType());
79
80 if (!isa<lval::ConcreteInt>(X))
81 return UnknownVal();
82
83 llvm::APSInt V = cast<lval::ConcreteInt>(X).getValue();
84 QualType T = CastExpr->getType();
85 V.setIsUnsigned(T->isUnsignedIntegerType() || T->isPointerType());
86 V.extOrTrunc(ValMgr.getContext().getTypeSize(T, CastExpr->getLocStart()));
87
88 return nonlval::ConcreteInt(ValMgr.getValue(V));
Ted Kremenekc3f261d2008-02-14 18:40:24 +000089}
90
91// Unary operators.
92
93NonLValue GRSimpleVals::EvalMinus(ValueManager& ValMgr, UnaryOperator* U,
94 NonLValue X) {
95
96 switch (X.getSubKind()) {
97 case nonlval::ConcreteIntKind:
98 return cast<nonlval::ConcreteInt>(X).EvalMinus(ValMgr, U);
99 default:
100 return cast<NonLValue>(UnknownVal());
101 }
102}
103
104NonLValue GRSimpleVals::EvalComplement(ValueManager& ValMgr, NonLValue X) {
105 switch (X.getSubKind()) {
106 case nonlval::ConcreteIntKind:
107 return cast<nonlval::ConcreteInt>(X).EvalComplement(ValMgr);
108 default:
109 return cast<NonLValue>(UnknownVal());
110 }
111}
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000112
113// Binary operators.
114
115NonLValue GRSimpleVals::EvalBinaryOp(ValueManager& ValMgr,
116 BinaryOperator::Opcode Op,
117 NonLValue LHS, NonLValue RHS) {
118
119 if (isa<UnknownVal>(LHS) || isa<UnknownVal>(RHS))
120 return cast<NonLValue>(UnknownVal());
121
122 if (isa<UninitializedVal>(LHS) || isa<UninitializedVal>(RHS))
123 return cast<NonLValue>(UninitializedVal());
124
125 while(1) {
126
127 switch (LHS.getSubKind()) {
128 default:
129 return cast<NonLValue>(UnknownVal());
130
131 case nonlval::ConcreteIntKind:
132
133 if (isa<nonlval::ConcreteInt>(RHS)) {
134 const nonlval::ConcreteInt& LHS_CI = cast<nonlval::ConcreteInt>(LHS);
135 const nonlval::ConcreteInt& RHS_CI = cast<nonlval::ConcreteInt>(RHS);
136 return LHS_CI.EvalBinaryOp(ValMgr, Op, RHS_CI);
137 }
138 else if(isa<UnknownVal>(RHS))
139 return cast<NonLValue>(UnknownVal());
140 else {
141 NonLValue tmp = RHS;
142 RHS = LHS;
143 LHS = tmp;
144 continue;
145 }
146
147 case nonlval::SymbolValKind: {
148 if (isa<nonlval::ConcreteInt>(RHS)) {
149 const SymIntConstraint& C =
150 ValMgr.getConstraint(cast<nonlval::SymbolVal>(LHS).getSymbol(), Op,
151 cast<nonlval::ConcreteInt>(RHS).getValue());
152
153 return nonlval::SymIntConstraintVal(C);
154 }
155 else
156 return cast<NonLValue>(UnknownVal());
157 }
158 }
159 }
160}
161
162// Equality operators for LValues.
163
164
165NonLValue GRSimpleVals::EvalEQ(ValueManager& ValMgr, LValue LHS, LValue RHS) {
166
167 switch (LHS.getSubKind()) {
168 default:
169 assert(false && "EQ not implemented for this LValue.");
170 return cast<NonLValue>(UnknownVal());
171
172 case lval::ConcreteIntKind:
173 if (isa<lval::ConcreteInt>(RHS)) {
174 bool b = cast<lval::ConcreteInt>(LHS).getValue() ==
175 cast<lval::ConcreteInt>(RHS).getValue();
176
177 return NonLValue::GetIntTruthValue(ValMgr, b);
178 }
179 else if (isa<lval::SymbolVal>(RHS)) {
180
181 const SymIntConstraint& C =
182 ValMgr.getConstraint(cast<lval::SymbolVal>(RHS).getSymbol(),
183 BinaryOperator::EQ,
184 cast<lval::ConcreteInt>(LHS).getValue());
185
186 return nonlval::SymIntConstraintVal(C);
187 }
188
189 break;
190
191 case lval::SymbolValKind: {
192 if (isa<lval::ConcreteInt>(RHS)) {
193 const SymIntConstraint& C =
194 ValMgr.getConstraint(cast<lval::SymbolVal>(LHS).getSymbol(),
195 BinaryOperator::EQ,
196 cast<lval::ConcreteInt>(RHS).getValue());
197
198 return nonlval::SymIntConstraintVal(C);
199 }
200
201 assert (!isa<lval::SymbolVal>(RHS) && "FIXME: Implement unification.");
202
203 break;
204 }
205
206 case lval::DeclValKind:
207
208 if (isa<lval::DeclVal>(RHS)) {
209 bool b = cast<lval::DeclVal>(LHS) == cast<lval::DeclVal>(RHS);
210 return NonLValue::GetIntTruthValue(ValMgr, b);
211 }
212
213 break;
214 }
215
216 return NonLValue::GetIntTruthValue(ValMgr, false);
217}
218
219NonLValue GRSimpleVals::EvalNE(ValueManager& ValMgr, LValue LHS, LValue RHS) {
220
221 switch (LHS.getSubKind()) {
222 default:
223 assert(false && "NE not implemented for this LValue.");
224 return cast<NonLValue>(UnknownVal());
225
226 case lval::ConcreteIntKind:
227 if (isa<lval::ConcreteInt>(RHS)) {
228 bool b = cast<lval::ConcreteInt>(LHS).getValue() !=
229 cast<lval::ConcreteInt>(RHS).getValue();
230
231 return NonLValue::GetIntTruthValue(ValMgr, b);
232 }
233 else if (isa<lval::SymbolVal>(RHS)) {
234 const SymIntConstraint& C =
235 ValMgr.getConstraint(cast<lval::SymbolVal>(RHS).getSymbol(),
236 BinaryOperator::NE,
237 cast<lval::ConcreteInt>(LHS).getValue());
238
239 return nonlval::SymIntConstraintVal(C);
240 }
241
242 break;
243
244 case lval::SymbolValKind: {
245 if (isa<lval::ConcreteInt>(RHS)) {
246 const SymIntConstraint& C =
247 ValMgr.getConstraint(cast<lval::SymbolVal>(LHS).getSymbol(),
248 BinaryOperator::NE,
249 cast<lval::ConcreteInt>(RHS).getValue());
250
251 return nonlval::SymIntConstraintVal(C);
252 }
253
254 assert (!isa<lval::SymbolVal>(RHS) && "FIXME: Implement sym !=.");
255
256 break;
257 }
258
259 case lval::DeclValKind:
260 if (isa<lval::DeclVal>(RHS)) {
261 bool b = cast<lval::DeclVal>(LHS) == cast<lval::DeclVal>(RHS);
262 return NonLValue::GetIntTruthValue(ValMgr, b);
263 }
264
265 break;
266 }
267
268 return NonLValue::GetIntTruthValue(ValMgr, true);
269}