blob: a76acb3d1f366030281c602eed2fac135221434c [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 {
Ted Kremenek9dca0622008-02-19 00:22:37 +000022 unsigned RunGRSimpleVals(CFG& cfg, FunctionDecl& FD, ASTContext& Ctx,
23 Diagnostic& Diag, bool Visualize) {
Ted Kremeneke01c9872008-02-14 22:36:46 +000024
Ted Kremenek546bded2008-02-14 22:54:17 +000025 if (Diag.hasErrorOccurred())
Ted Kremenek9dca0622008-02-19 00:22:37 +000026 return 0;
Ted Kremenek546bded2008-02-14 22:54:17 +000027
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 Kremeneke6ea2d52008-02-19 02:34:18 +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 Kremenek9dca0622008-02-19 00:22:37 +000049#endif
50
51 return Engine.getGraph().size();
Ted Kremeneke01c9872008-02-14 22:36:46 +000052 }
53} // end clang namespace
54
Ted Kremenekd59cccc2008-02-14 18:28:23 +000055//===----------------------------------------------------------------------===//
56// Transfer function for Casts.
57//===----------------------------------------------------------------------===//
58
59RValue GRSimpleVals::EvalCast(ValueManager& ValMgr, NonLValue X,
60 Expr* CastExpr) {
61
Ted Kremenek692416c2008-02-18 22:57:02 +000062 assert (!isa<UnknownVal>(X) && !isa<UninitializedVal>(X));
63
Ted Kremenekd59cccc2008-02-14 18:28:23 +000064 if (!isa<nonlval::ConcreteInt>(X))
65 return UnknownVal();
66
67 llvm::APSInt V = cast<nonlval::ConcreteInt>(X).getValue();
68 QualType T = CastExpr->getType();
69 V.setIsUnsigned(T->isUnsignedIntegerType() || T->isPointerType());
70 V.extOrTrunc(ValMgr.getContext().getTypeSize(T, CastExpr->getLocStart()));
71
72 if (CastExpr->getType()->isPointerType())
73 return lval::ConcreteInt(ValMgr.getValue(V));
74 else
75 return nonlval::ConcreteInt(ValMgr.getValue(V));
76}
77
78// Casts.
79
80RValue GRSimpleVals::EvalCast(ValueManager& ValMgr, LValue X, Expr* CastExpr) {
Ted Kremenek692416c2008-02-18 22:57:02 +000081
82 assert (!isa<UnknownVal>(X) && !isa<UninitializedVal>(X));
Ted Kremenekd59cccc2008-02-14 18:28:23 +000083
84 if (CastExpr->getType()->isPointerType())
85 return X;
86
87 assert (CastExpr->getType()->isIntegerType());
88
89 if (!isa<lval::ConcreteInt>(X))
90 return UnknownVal();
91
92 llvm::APSInt V = cast<lval::ConcreteInt>(X).getValue();
93 QualType T = CastExpr->getType();
94 V.setIsUnsigned(T->isUnsignedIntegerType() || T->isPointerType());
95 V.extOrTrunc(ValMgr.getContext().getTypeSize(T, CastExpr->getLocStart()));
96
97 return nonlval::ConcreteInt(ValMgr.getValue(V));
Ted Kremenekc3f261d2008-02-14 18:40:24 +000098}
99
100// Unary operators.
101
102NonLValue GRSimpleVals::EvalMinus(ValueManager& ValMgr, UnaryOperator* U,
103 NonLValue X) {
104
Ted Kremenek692416c2008-02-18 22:57:02 +0000105 assert (!isa<UnknownVal>(X) && !isa<UninitializedVal>(X));
106
Ted Kremenekc3f261d2008-02-14 18:40:24 +0000107 switch (X.getSubKind()) {
108 case nonlval::ConcreteIntKind:
109 return cast<nonlval::ConcreteInt>(X).EvalMinus(ValMgr, U);
110 default:
111 return cast<NonLValue>(UnknownVal());
112 }
113}
114
Ted Kremenek90e42032008-02-20 04:12:31 +0000115NonLValue GRSimpleVals::EvalPlus(ValueManager& ValMgr, UnaryOperator* U,
116 NonLValue X) {
117
118 assert (!isa<UnknownVal>(X) && !isa<UninitializedVal>(X));
119
120 switch (X.getSubKind()) {
121 case nonlval::ConcreteIntKind:
122 return cast<nonlval::ConcreteInt>(X).EvalPlus(ValMgr, U);
123 default:
124 return cast<NonLValue>(UnknownVal());
125 }
126}
127
128
Ted Kremenekc3f261d2008-02-14 18:40:24 +0000129NonLValue GRSimpleVals::EvalComplement(ValueManager& ValMgr, NonLValue X) {
Ted Kremenek692416c2008-02-18 22:57:02 +0000130
131 assert (!isa<UnknownVal>(X) && !isa<UninitializedVal>(X));
132
Ted Kremenekc3f261d2008-02-14 18:40:24 +0000133 switch (X.getSubKind()) {
134 case nonlval::ConcreteIntKind:
135 return cast<nonlval::ConcreteInt>(X).EvalComplement(ValMgr);
136 default:
137 return cast<NonLValue>(UnknownVal());
138 }
139}
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000140
141// Binary operators.
142
143NonLValue GRSimpleVals::EvalBinaryOp(ValueManager& ValMgr,
144 BinaryOperator::Opcode Op,
145 NonLValue LHS, NonLValue RHS) {
146
Ted Kremenek692416c2008-02-18 22:57:02 +0000147 assert (!isa<UnknownVal>(LHS) && !isa<UninitializedVal>(LHS));
148 assert (!isa<UnknownVal>(RHS) && !isa<UninitializedVal>(RHS));
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000149
150 while(1) {
151
152 switch (LHS.getSubKind()) {
153 default:
154 return cast<NonLValue>(UnknownVal());
155
156 case nonlval::ConcreteIntKind:
157
158 if (isa<nonlval::ConcreteInt>(RHS)) {
159 const nonlval::ConcreteInt& LHS_CI = cast<nonlval::ConcreteInt>(LHS);
160 const nonlval::ConcreteInt& RHS_CI = cast<nonlval::ConcreteInt>(RHS);
161 return LHS_CI.EvalBinaryOp(ValMgr, Op, RHS_CI);
162 }
163 else if(isa<UnknownVal>(RHS))
164 return cast<NonLValue>(UnknownVal());
165 else {
166 NonLValue tmp = RHS;
167 RHS = LHS;
168 LHS = tmp;
169 continue;
170 }
171
172 case nonlval::SymbolValKind: {
173 if (isa<nonlval::ConcreteInt>(RHS)) {
174 const SymIntConstraint& C =
175 ValMgr.getConstraint(cast<nonlval::SymbolVal>(LHS).getSymbol(), Op,
176 cast<nonlval::ConcreteInt>(RHS).getValue());
177
178 return nonlval::SymIntConstraintVal(C);
179 }
180 else
181 return cast<NonLValue>(UnknownVal());
182 }
183 }
184 }
185}
186
Ted Kremenekb640b3b2008-02-15 00:52:26 +0000187
Ted Kremenekc6fbdcd2008-02-15 23:15:23 +0000188// Binary Operators (except assignments and comma).
189
190RValue GRSimpleVals::EvalBinaryOp(ValueManager& ValMgr,
191 BinaryOperator::Opcode Op,
192 LValue LHS, LValue RHS) {
193
Ted Kremenek692416c2008-02-18 22:57:02 +0000194 assert (!isa<UnknownVal>(LHS) && !isa<UninitializedVal>(LHS));
195 assert (!isa<UnknownVal>(RHS) && !isa<UninitializedVal>(RHS));
196
Ted Kremenekc6fbdcd2008-02-15 23:15:23 +0000197 switch (Op) {
198 default:
199 return UnknownVal();
200
201 case BinaryOperator::EQ:
202 return EvalEQ(ValMgr, LHS, RHS);
203
204 case BinaryOperator::NE:
205 return EvalNE(ValMgr, LHS, RHS);
206 }
207}
208
Ted Kremenekb640b3b2008-02-15 00:52:26 +0000209// Pointer arithmetic.
210
211LValue GRSimpleVals::EvalBinaryOp(ValueManager& ValMgr,
212 BinaryOperator::Opcode Op,
213 LValue LHS, NonLValue RHS) {
Ted Kremenek692416c2008-02-18 22:57:02 +0000214
215 assert (!isa<UnknownVal>(LHS) && !isa<UninitializedVal>(LHS));
216 assert (!isa<UnknownVal>(RHS) && !isa<UninitializedVal>(RHS));
217
Ted Kremenekb640b3b2008-02-15 00:52:26 +0000218 return cast<LValue>(UnknownVal());
219}
220
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000221// Equality operators for LValues.
222
223
224NonLValue GRSimpleVals::EvalEQ(ValueManager& ValMgr, LValue LHS, LValue RHS) {
225
Ted Kremenek692416c2008-02-18 22:57:02 +0000226 assert (!isa<UnknownVal>(LHS) && !isa<UninitializedVal>(LHS));
227 assert (!isa<UnknownVal>(RHS) && !isa<UninitializedVal>(RHS));
228
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000229 switch (LHS.getSubKind()) {
230 default:
231 assert(false && "EQ not implemented for this LValue.");
232 return cast<NonLValue>(UnknownVal());
233
234 case lval::ConcreteIntKind:
235 if (isa<lval::ConcreteInt>(RHS)) {
236 bool b = cast<lval::ConcreteInt>(LHS).getValue() ==
237 cast<lval::ConcreteInt>(RHS).getValue();
238
239 return NonLValue::GetIntTruthValue(ValMgr, b);
240 }
241 else if (isa<lval::SymbolVal>(RHS)) {
242
243 const SymIntConstraint& C =
244 ValMgr.getConstraint(cast<lval::SymbolVal>(RHS).getSymbol(),
245 BinaryOperator::EQ,
246 cast<lval::ConcreteInt>(LHS).getValue());
247
248 return nonlval::SymIntConstraintVal(C);
249 }
250
251 break;
252
253 case lval::SymbolValKind: {
254 if (isa<lval::ConcreteInt>(RHS)) {
255 const SymIntConstraint& C =
256 ValMgr.getConstraint(cast<lval::SymbolVal>(LHS).getSymbol(),
257 BinaryOperator::EQ,
258 cast<lval::ConcreteInt>(RHS).getValue());
259
260 return nonlval::SymIntConstraintVal(C);
261 }
262
Ted Kremenekf0c8ef02008-02-18 21:19:49 +0000263 // FIXME: Implement unification
264 return cast<NonLValue>(UnknownVal());
265 //assert (!isa<lval::SymbolVal>(RHS) && "FIXME: Implement unification.");
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000266
267 break;
268 }
269
270 case lval::DeclValKind:
271
272 if (isa<lval::DeclVal>(RHS)) {
273 bool b = cast<lval::DeclVal>(LHS) == cast<lval::DeclVal>(RHS);
274 return NonLValue::GetIntTruthValue(ValMgr, b);
275 }
276
277 break;
278 }
279
280 return NonLValue::GetIntTruthValue(ValMgr, false);
281}
282
283NonLValue GRSimpleVals::EvalNE(ValueManager& ValMgr, LValue LHS, LValue RHS) {
Ted Kremenek692416c2008-02-18 22:57:02 +0000284
285 assert (!isa<UnknownVal>(LHS) && !isa<UninitializedVal>(LHS));
286 assert (!isa<UnknownVal>(RHS) && !isa<UninitializedVal>(RHS));
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000287
288 switch (LHS.getSubKind()) {
289 default:
290 assert(false && "NE not implemented for this LValue.");
291 return cast<NonLValue>(UnknownVal());
292
293 case lval::ConcreteIntKind:
294 if (isa<lval::ConcreteInt>(RHS)) {
295 bool b = cast<lval::ConcreteInt>(LHS).getValue() !=
296 cast<lval::ConcreteInt>(RHS).getValue();
297
298 return NonLValue::GetIntTruthValue(ValMgr, b);
299 }
300 else if (isa<lval::SymbolVal>(RHS)) {
301 const SymIntConstraint& C =
302 ValMgr.getConstraint(cast<lval::SymbolVal>(RHS).getSymbol(),
303 BinaryOperator::NE,
304 cast<lval::ConcreteInt>(LHS).getValue());
305
306 return nonlval::SymIntConstraintVal(C);
307 }
308
309 break;
310
311 case lval::SymbolValKind: {
312 if (isa<lval::ConcreteInt>(RHS)) {
313 const SymIntConstraint& C =
314 ValMgr.getConstraint(cast<lval::SymbolVal>(LHS).getSymbol(),
315 BinaryOperator::NE,
316 cast<lval::ConcreteInt>(RHS).getValue());
317
318 return nonlval::SymIntConstraintVal(C);
319 }
320
321 assert (!isa<lval::SymbolVal>(RHS) && "FIXME: Implement sym !=.");
322
323 break;
324 }
325
326 case lval::DeclValKind:
327 if (isa<lval::DeclVal>(RHS)) {
328 bool b = cast<lval::DeclVal>(LHS) == cast<lval::DeclVal>(RHS);
329 return NonLValue::GetIntTruthValue(ValMgr, b);
330 }
331
332 break;
333 }
334
335 return NonLValue::GetIntTruthValue(ValMgr, true);
336}