blob: 58f0729a70182d11f1a0820c4db0328e527f394b [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,
Ted Kremenekd55fe522008-02-15 00:35:38 +000023 Diagnostic& Diag, bool Visualize) {
Ted Kremeneke01c9872008-02-14 22:36:46 +000024
Ted Kremenek546bded2008-02-14 22:54:17 +000025 if (Diag.hasErrorOccurred())
26 return;
27
Ted Kremeneke01c9872008-02-14 22:36:46 +000028 GRCoreEngine<GRExprEngine> Engine(cfg, FD, Ctx);
29 GRExprEngine* CheckerState = &Engine.getCheckerState();
30 GRSimpleVals GRSV;
31 CheckerState->setTransferFunctions(GRSV);
32
33 // Execute the worklist algorithm.
Ted Kremenekf0c8ef02008-02-18 21:19:49 +000034 Engine.ExecuteWorkList(200);
Ted Kremeneke01c9872008-02-14 22:36:46 +000035
36 // Look for explicit-Null dereferences and warn about them.
37 for (GRExprEngine::null_iterator I=CheckerState->null_begin(),
38 E=CheckerState->null_end(); I!=E; ++I) {
39
40 const PostStmt& L = cast<PostStmt>((*I)->getLocation());
Eli Friedman7df3d712008-02-16 23:17:23 +000041 Expr* Exp = cast<Expr>(L.getStmt());
Ted Kremeneke01c9872008-02-14 22:36:46 +000042
Eli Friedman7df3d712008-02-16 23:17:23 +000043 Diag.Report(FullSourceLoc(Exp->getExprLoc(), Ctx.getSourceManager()),
Ted Kremeneke01c9872008-02-14 22:36:46 +000044 diag::chkr_null_deref_after_check);
45 }
46
47#ifndef NDEBUG
Ted Kremenekd55fe522008-02-15 00:35:38 +000048 if (Visualize) CheckerState->ViewGraph();
Ted Kremeneke01c9872008-02-14 22:36:46 +000049#endif
50 }
51} // end clang namespace
52
Ted Kremenekd59cccc2008-02-14 18:28:23 +000053//===----------------------------------------------------------------------===//
54// Transfer function for Casts.
55//===----------------------------------------------------------------------===//
56
57RValue GRSimpleVals::EvalCast(ValueManager& ValMgr, NonLValue X,
58 Expr* CastExpr) {
59
60 if (!isa<nonlval::ConcreteInt>(X))
61 return UnknownVal();
62
63 llvm::APSInt V = cast<nonlval::ConcreteInt>(X).getValue();
64 QualType T = CastExpr->getType();
65 V.setIsUnsigned(T->isUnsignedIntegerType() || T->isPointerType());
66 V.extOrTrunc(ValMgr.getContext().getTypeSize(T, CastExpr->getLocStart()));
67
68 if (CastExpr->getType()->isPointerType())
69 return lval::ConcreteInt(ValMgr.getValue(V));
70 else
71 return nonlval::ConcreteInt(ValMgr.getValue(V));
72}
73
74// Casts.
75
76RValue GRSimpleVals::EvalCast(ValueManager& ValMgr, LValue X, Expr* CastExpr) {
77
78 if (CastExpr->getType()->isPointerType())
79 return X;
80
81 assert (CastExpr->getType()->isIntegerType());
82
83 if (!isa<lval::ConcreteInt>(X))
84 return UnknownVal();
85
86 llvm::APSInt V = cast<lval::ConcreteInt>(X).getValue();
87 QualType T = CastExpr->getType();
88 V.setIsUnsigned(T->isUnsignedIntegerType() || T->isPointerType());
89 V.extOrTrunc(ValMgr.getContext().getTypeSize(T, CastExpr->getLocStart()));
90
91 return nonlval::ConcreteInt(ValMgr.getValue(V));
Ted Kremenekc3f261d2008-02-14 18:40:24 +000092}
93
94// Unary operators.
95
96NonLValue GRSimpleVals::EvalMinus(ValueManager& ValMgr, UnaryOperator* U,
97 NonLValue X) {
98
99 switch (X.getSubKind()) {
100 case nonlval::ConcreteIntKind:
101 return cast<nonlval::ConcreteInt>(X).EvalMinus(ValMgr, U);
102 default:
103 return cast<NonLValue>(UnknownVal());
104 }
105}
106
107NonLValue GRSimpleVals::EvalComplement(ValueManager& ValMgr, NonLValue X) {
108 switch (X.getSubKind()) {
109 case nonlval::ConcreteIntKind:
110 return cast<nonlval::ConcreteInt>(X).EvalComplement(ValMgr);
111 default:
112 return cast<NonLValue>(UnknownVal());
113 }
114}
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000115
116// Binary operators.
117
118NonLValue GRSimpleVals::EvalBinaryOp(ValueManager& ValMgr,
119 BinaryOperator::Opcode Op,
120 NonLValue LHS, NonLValue RHS) {
121
122 if (isa<UnknownVal>(LHS) || isa<UnknownVal>(RHS))
123 return cast<NonLValue>(UnknownVal());
124
125 if (isa<UninitializedVal>(LHS) || isa<UninitializedVal>(RHS))
126 return cast<NonLValue>(UninitializedVal());
127
128 while(1) {
129
130 switch (LHS.getSubKind()) {
131 default:
132 return cast<NonLValue>(UnknownVal());
133
134 case nonlval::ConcreteIntKind:
135
136 if (isa<nonlval::ConcreteInt>(RHS)) {
137 const nonlval::ConcreteInt& LHS_CI = cast<nonlval::ConcreteInt>(LHS);
138 const nonlval::ConcreteInt& RHS_CI = cast<nonlval::ConcreteInt>(RHS);
139 return LHS_CI.EvalBinaryOp(ValMgr, Op, RHS_CI);
140 }
141 else if(isa<UnknownVal>(RHS))
142 return cast<NonLValue>(UnknownVal());
143 else {
144 NonLValue tmp = RHS;
145 RHS = LHS;
146 LHS = tmp;
147 continue;
148 }
149
150 case nonlval::SymbolValKind: {
151 if (isa<nonlval::ConcreteInt>(RHS)) {
152 const SymIntConstraint& C =
153 ValMgr.getConstraint(cast<nonlval::SymbolVal>(LHS).getSymbol(), Op,
154 cast<nonlval::ConcreteInt>(RHS).getValue());
155
156 return nonlval::SymIntConstraintVal(C);
157 }
158 else
159 return cast<NonLValue>(UnknownVal());
160 }
161 }
162 }
163}
164
Ted Kremenekb640b3b2008-02-15 00:52:26 +0000165
Ted Kremenekc6fbdcd2008-02-15 23:15:23 +0000166// Binary Operators (except assignments and comma).
167
168RValue GRSimpleVals::EvalBinaryOp(ValueManager& ValMgr,
169 BinaryOperator::Opcode Op,
170 LValue LHS, LValue RHS) {
171
172 switch (Op) {
173 default:
174 return UnknownVal();
175
176 case BinaryOperator::EQ:
177 return EvalEQ(ValMgr, LHS, RHS);
178
179 case BinaryOperator::NE:
180 return EvalNE(ValMgr, LHS, RHS);
181 }
182}
183
Ted Kremenekb640b3b2008-02-15 00:52:26 +0000184// Pointer arithmetic.
185
186LValue GRSimpleVals::EvalBinaryOp(ValueManager& ValMgr,
187 BinaryOperator::Opcode Op,
188 LValue LHS, NonLValue RHS) {
189 return cast<LValue>(UnknownVal());
190}
191
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000192// Equality operators for LValues.
193
194
195NonLValue GRSimpleVals::EvalEQ(ValueManager& ValMgr, LValue LHS, LValue RHS) {
196
197 switch (LHS.getSubKind()) {
198 default:
199 assert(false && "EQ not implemented for this LValue.");
200 return cast<NonLValue>(UnknownVal());
201
202 case lval::ConcreteIntKind:
203 if (isa<lval::ConcreteInt>(RHS)) {
204 bool b = cast<lval::ConcreteInt>(LHS).getValue() ==
205 cast<lval::ConcreteInt>(RHS).getValue();
206
207 return NonLValue::GetIntTruthValue(ValMgr, b);
208 }
209 else if (isa<lval::SymbolVal>(RHS)) {
210
211 const SymIntConstraint& C =
212 ValMgr.getConstraint(cast<lval::SymbolVal>(RHS).getSymbol(),
213 BinaryOperator::EQ,
214 cast<lval::ConcreteInt>(LHS).getValue());
215
216 return nonlval::SymIntConstraintVal(C);
217 }
218
219 break;
220
221 case lval::SymbolValKind: {
222 if (isa<lval::ConcreteInt>(RHS)) {
223 const SymIntConstraint& C =
224 ValMgr.getConstraint(cast<lval::SymbolVal>(LHS).getSymbol(),
225 BinaryOperator::EQ,
226 cast<lval::ConcreteInt>(RHS).getValue());
227
228 return nonlval::SymIntConstraintVal(C);
229 }
230
Ted Kremenekf0c8ef02008-02-18 21:19:49 +0000231 // FIXME: Implement unification
232 return cast<NonLValue>(UnknownVal());
233 //assert (!isa<lval::SymbolVal>(RHS) && "FIXME: Implement unification.");
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000234
235 break;
236 }
237
238 case lval::DeclValKind:
239
240 if (isa<lval::DeclVal>(RHS)) {
241 bool b = cast<lval::DeclVal>(LHS) == cast<lval::DeclVal>(RHS);
242 return NonLValue::GetIntTruthValue(ValMgr, b);
243 }
244
245 break;
246 }
247
248 return NonLValue::GetIntTruthValue(ValMgr, false);
249}
250
251NonLValue GRSimpleVals::EvalNE(ValueManager& ValMgr, LValue LHS, LValue RHS) {
252
253 switch (LHS.getSubKind()) {
254 default:
255 assert(false && "NE not implemented for this LValue.");
256 return cast<NonLValue>(UnknownVal());
257
258 case lval::ConcreteIntKind:
259 if (isa<lval::ConcreteInt>(RHS)) {
260 bool b = cast<lval::ConcreteInt>(LHS).getValue() !=
261 cast<lval::ConcreteInt>(RHS).getValue();
262
263 return NonLValue::GetIntTruthValue(ValMgr, b);
264 }
265 else if (isa<lval::SymbolVal>(RHS)) {
266 const SymIntConstraint& C =
267 ValMgr.getConstraint(cast<lval::SymbolVal>(RHS).getSymbol(),
268 BinaryOperator::NE,
269 cast<lval::ConcreteInt>(LHS).getValue());
270
271 return nonlval::SymIntConstraintVal(C);
272 }
273
274 break;
275
276 case lval::SymbolValKind: {
277 if (isa<lval::ConcreteInt>(RHS)) {
278 const SymIntConstraint& C =
279 ValMgr.getConstraint(cast<lval::SymbolVal>(LHS).getSymbol(),
280 BinaryOperator::NE,
281 cast<lval::ConcreteInt>(RHS).getValue());
282
283 return nonlval::SymIntConstraintVal(C);
284 }
285
286 assert (!isa<lval::SymbolVal>(RHS) && "FIXME: Implement sym !=.");
287
288 break;
289 }
290
291 case lval::DeclValKind:
292 if (isa<lval::DeclVal>(RHS)) {
293 bool b = cast<lval::DeclVal>(LHS) == cast<lval::DeclVal>(RHS);
294 return NonLValue::GetIntTruthValue(ValMgr, b);
295 }
296
297 break;
298 }
299
300 return NonLValue::GetIntTruthValue(ValMgr, true);
301}