blob: 87b39b70c53da37d0ec1b029d00cfe0bf415883b [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 Kremenek692416c2008-02-18 22:57:02 +000034 Engine.ExecuteWorkList(10000);
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
Ted Kremenek692416c2008-02-18 22:57:02 +000060 assert (!isa<UnknownVal>(X) && !isa<UninitializedVal>(X));
61
Ted Kremenekd59cccc2008-02-14 18:28:23 +000062 if (!isa<nonlval::ConcreteInt>(X))
63 return UnknownVal();
64
65 llvm::APSInt V = cast<nonlval::ConcreteInt>(X).getValue();
66 QualType T = CastExpr->getType();
67 V.setIsUnsigned(T->isUnsignedIntegerType() || T->isPointerType());
68 V.extOrTrunc(ValMgr.getContext().getTypeSize(T, CastExpr->getLocStart()));
69
70 if (CastExpr->getType()->isPointerType())
71 return lval::ConcreteInt(ValMgr.getValue(V));
72 else
73 return nonlval::ConcreteInt(ValMgr.getValue(V));
74}
75
76// Casts.
77
78RValue GRSimpleVals::EvalCast(ValueManager& ValMgr, LValue X, Expr* CastExpr) {
Ted Kremenek692416c2008-02-18 22:57:02 +000079
80 assert (!isa<UnknownVal>(X) && !isa<UninitializedVal>(X));
Ted Kremenekd59cccc2008-02-14 18:28:23 +000081
82 if (CastExpr->getType()->isPointerType())
83 return X;
84
85 assert (CastExpr->getType()->isIntegerType());
86
87 if (!isa<lval::ConcreteInt>(X))
88 return UnknownVal();
89
90 llvm::APSInt V = cast<lval::ConcreteInt>(X).getValue();
91 QualType T = CastExpr->getType();
92 V.setIsUnsigned(T->isUnsignedIntegerType() || T->isPointerType());
93 V.extOrTrunc(ValMgr.getContext().getTypeSize(T, CastExpr->getLocStart()));
94
95 return nonlval::ConcreteInt(ValMgr.getValue(V));
Ted Kremenekc3f261d2008-02-14 18:40:24 +000096}
97
98// Unary operators.
99
100NonLValue GRSimpleVals::EvalMinus(ValueManager& ValMgr, UnaryOperator* U,
101 NonLValue X) {
102
Ted Kremenek692416c2008-02-18 22:57:02 +0000103 assert (!isa<UnknownVal>(X) && !isa<UninitializedVal>(X));
104
Ted Kremenekc3f261d2008-02-14 18:40:24 +0000105 switch (X.getSubKind()) {
106 case nonlval::ConcreteIntKind:
107 return cast<nonlval::ConcreteInt>(X).EvalMinus(ValMgr, U);
108 default:
109 return cast<NonLValue>(UnknownVal());
110 }
111}
112
113NonLValue GRSimpleVals::EvalComplement(ValueManager& ValMgr, NonLValue X) {
Ted Kremenek692416c2008-02-18 22:57:02 +0000114
115 assert (!isa<UnknownVal>(X) && !isa<UninitializedVal>(X));
116
Ted Kremenekc3f261d2008-02-14 18:40:24 +0000117 switch (X.getSubKind()) {
118 case nonlval::ConcreteIntKind:
119 return cast<nonlval::ConcreteInt>(X).EvalComplement(ValMgr);
120 default:
121 return cast<NonLValue>(UnknownVal());
122 }
123}
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000124
125// Binary operators.
126
127NonLValue GRSimpleVals::EvalBinaryOp(ValueManager& ValMgr,
128 BinaryOperator::Opcode Op,
129 NonLValue LHS, NonLValue RHS) {
130
Ted Kremenek692416c2008-02-18 22:57:02 +0000131 assert (!isa<UnknownVal>(LHS) && !isa<UninitializedVal>(LHS));
132 assert (!isa<UnknownVal>(RHS) && !isa<UninitializedVal>(RHS));
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000133
134 while(1) {
135
136 switch (LHS.getSubKind()) {
137 default:
138 return cast<NonLValue>(UnknownVal());
139
140 case nonlval::ConcreteIntKind:
141
142 if (isa<nonlval::ConcreteInt>(RHS)) {
143 const nonlval::ConcreteInt& LHS_CI = cast<nonlval::ConcreteInt>(LHS);
144 const nonlval::ConcreteInt& RHS_CI = cast<nonlval::ConcreteInt>(RHS);
145 return LHS_CI.EvalBinaryOp(ValMgr, Op, RHS_CI);
146 }
147 else if(isa<UnknownVal>(RHS))
148 return cast<NonLValue>(UnknownVal());
149 else {
150 NonLValue tmp = RHS;
151 RHS = LHS;
152 LHS = tmp;
153 continue;
154 }
155
156 case nonlval::SymbolValKind: {
157 if (isa<nonlval::ConcreteInt>(RHS)) {
158 const SymIntConstraint& C =
159 ValMgr.getConstraint(cast<nonlval::SymbolVal>(LHS).getSymbol(), Op,
160 cast<nonlval::ConcreteInt>(RHS).getValue());
161
162 return nonlval::SymIntConstraintVal(C);
163 }
164 else
165 return cast<NonLValue>(UnknownVal());
166 }
167 }
168 }
169}
170
Ted Kremenekb640b3b2008-02-15 00:52:26 +0000171
Ted Kremenekc6fbdcd2008-02-15 23:15:23 +0000172// Binary Operators (except assignments and comma).
173
174RValue GRSimpleVals::EvalBinaryOp(ValueManager& ValMgr,
175 BinaryOperator::Opcode Op,
176 LValue LHS, LValue RHS) {
177
Ted Kremenek692416c2008-02-18 22:57:02 +0000178 assert (!isa<UnknownVal>(LHS) && !isa<UninitializedVal>(LHS));
179 assert (!isa<UnknownVal>(RHS) && !isa<UninitializedVal>(RHS));
180
Ted Kremenekc6fbdcd2008-02-15 23:15:23 +0000181 switch (Op) {
182 default:
183 return UnknownVal();
184
185 case BinaryOperator::EQ:
186 return EvalEQ(ValMgr, LHS, RHS);
187
188 case BinaryOperator::NE:
189 return EvalNE(ValMgr, LHS, RHS);
190 }
191}
192
Ted Kremenekb640b3b2008-02-15 00:52:26 +0000193// Pointer arithmetic.
194
195LValue GRSimpleVals::EvalBinaryOp(ValueManager& ValMgr,
196 BinaryOperator::Opcode Op,
197 LValue LHS, NonLValue RHS) {
Ted Kremenek692416c2008-02-18 22:57:02 +0000198
199 assert (!isa<UnknownVal>(LHS) && !isa<UninitializedVal>(LHS));
200 assert (!isa<UnknownVal>(RHS) && !isa<UninitializedVal>(RHS));
201
Ted Kremenekb640b3b2008-02-15 00:52:26 +0000202 return cast<LValue>(UnknownVal());
203}
204
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000205// Equality operators for LValues.
206
207
208NonLValue GRSimpleVals::EvalEQ(ValueManager& ValMgr, LValue LHS, LValue RHS) {
209
Ted Kremenek692416c2008-02-18 22:57:02 +0000210 assert (!isa<UnknownVal>(LHS) && !isa<UninitializedVal>(LHS));
211 assert (!isa<UnknownVal>(RHS) && !isa<UninitializedVal>(RHS));
212
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000213 switch (LHS.getSubKind()) {
214 default:
215 assert(false && "EQ not implemented for this LValue.");
216 return cast<NonLValue>(UnknownVal());
217
218 case lval::ConcreteIntKind:
219 if (isa<lval::ConcreteInt>(RHS)) {
220 bool b = cast<lval::ConcreteInt>(LHS).getValue() ==
221 cast<lval::ConcreteInt>(RHS).getValue();
222
223 return NonLValue::GetIntTruthValue(ValMgr, b);
224 }
225 else if (isa<lval::SymbolVal>(RHS)) {
226
227 const SymIntConstraint& C =
228 ValMgr.getConstraint(cast<lval::SymbolVal>(RHS).getSymbol(),
229 BinaryOperator::EQ,
230 cast<lval::ConcreteInt>(LHS).getValue());
231
232 return nonlval::SymIntConstraintVal(C);
233 }
234
235 break;
236
237 case lval::SymbolValKind: {
238 if (isa<lval::ConcreteInt>(RHS)) {
239 const SymIntConstraint& C =
240 ValMgr.getConstraint(cast<lval::SymbolVal>(LHS).getSymbol(),
241 BinaryOperator::EQ,
242 cast<lval::ConcreteInt>(RHS).getValue());
243
244 return nonlval::SymIntConstraintVal(C);
245 }
246
Ted Kremenekf0c8ef02008-02-18 21:19:49 +0000247 // FIXME: Implement unification
248 return cast<NonLValue>(UnknownVal());
249 //assert (!isa<lval::SymbolVal>(RHS) && "FIXME: Implement unification.");
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000250
251 break;
252 }
253
254 case lval::DeclValKind:
255
256 if (isa<lval::DeclVal>(RHS)) {
257 bool b = cast<lval::DeclVal>(LHS) == cast<lval::DeclVal>(RHS);
258 return NonLValue::GetIntTruthValue(ValMgr, b);
259 }
260
261 break;
262 }
263
264 return NonLValue::GetIntTruthValue(ValMgr, false);
265}
266
267NonLValue GRSimpleVals::EvalNE(ValueManager& ValMgr, LValue LHS, LValue RHS) {
Ted Kremenek692416c2008-02-18 22:57:02 +0000268
269 assert (!isa<UnknownVal>(LHS) && !isa<UninitializedVal>(LHS));
270 assert (!isa<UnknownVal>(RHS) && !isa<UninitializedVal>(RHS));
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000271
272 switch (LHS.getSubKind()) {
273 default:
274 assert(false && "NE not implemented for this LValue.");
275 return cast<NonLValue>(UnknownVal());
276
277 case lval::ConcreteIntKind:
278 if (isa<lval::ConcreteInt>(RHS)) {
279 bool b = cast<lval::ConcreteInt>(LHS).getValue() !=
280 cast<lval::ConcreteInt>(RHS).getValue();
281
282 return NonLValue::GetIntTruthValue(ValMgr, b);
283 }
284 else if (isa<lval::SymbolVal>(RHS)) {
285 const SymIntConstraint& C =
286 ValMgr.getConstraint(cast<lval::SymbolVal>(RHS).getSymbol(),
287 BinaryOperator::NE,
288 cast<lval::ConcreteInt>(LHS).getValue());
289
290 return nonlval::SymIntConstraintVal(C);
291 }
292
293 break;
294
295 case lval::SymbolValKind: {
296 if (isa<lval::ConcreteInt>(RHS)) {
297 const SymIntConstraint& C =
298 ValMgr.getConstraint(cast<lval::SymbolVal>(LHS).getSymbol(),
299 BinaryOperator::NE,
300 cast<lval::ConcreteInt>(RHS).getValue());
301
302 return nonlval::SymIntConstraintVal(C);
303 }
304
305 assert (!isa<lval::SymbolVal>(RHS) && "FIXME: Implement sym !=.");
306
307 break;
308 }
309
310 case lval::DeclValKind:
311 if (isa<lval::DeclVal>(RHS)) {
312 bool b = cast<lval::DeclVal>(LHS) == cast<lval::DeclVal>(RHS);
313 return NonLValue::GetIntTruthValue(ValMgr, b);
314 }
315
316 break;
317 }
318
319 return NonLValue::GetIntTruthValue(ValMgr, true);
320}