blob: 443a7ddb7599dd4c5bfda4e928dd3076bc3f897e [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
115NonLValue GRSimpleVals::EvalComplement(ValueManager& ValMgr, NonLValue X) {
Ted Kremenek692416c2008-02-18 22:57:02 +0000116
117 assert (!isa<UnknownVal>(X) && !isa<UninitializedVal>(X));
118
Ted Kremenekc3f261d2008-02-14 18:40:24 +0000119 switch (X.getSubKind()) {
120 case nonlval::ConcreteIntKind:
121 return cast<nonlval::ConcreteInt>(X).EvalComplement(ValMgr);
122 default:
123 return cast<NonLValue>(UnknownVal());
124 }
125}
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000126
127// Binary operators.
128
129NonLValue GRSimpleVals::EvalBinaryOp(ValueManager& ValMgr,
130 BinaryOperator::Opcode Op,
131 NonLValue LHS, NonLValue RHS) {
132
Ted Kremenek692416c2008-02-18 22:57:02 +0000133 assert (!isa<UnknownVal>(LHS) && !isa<UninitializedVal>(LHS));
134 assert (!isa<UnknownVal>(RHS) && !isa<UninitializedVal>(RHS));
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000135
136 while(1) {
137
138 switch (LHS.getSubKind()) {
139 default:
140 return cast<NonLValue>(UnknownVal());
141
142 case nonlval::ConcreteIntKind:
143
144 if (isa<nonlval::ConcreteInt>(RHS)) {
145 const nonlval::ConcreteInt& LHS_CI = cast<nonlval::ConcreteInt>(LHS);
146 const nonlval::ConcreteInt& RHS_CI = cast<nonlval::ConcreteInt>(RHS);
147 return LHS_CI.EvalBinaryOp(ValMgr, Op, RHS_CI);
148 }
149 else if(isa<UnknownVal>(RHS))
150 return cast<NonLValue>(UnknownVal());
151 else {
152 NonLValue tmp = RHS;
153 RHS = LHS;
154 LHS = tmp;
155 continue;
156 }
157
158 case nonlval::SymbolValKind: {
159 if (isa<nonlval::ConcreteInt>(RHS)) {
160 const SymIntConstraint& C =
161 ValMgr.getConstraint(cast<nonlval::SymbolVal>(LHS).getSymbol(), Op,
162 cast<nonlval::ConcreteInt>(RHS).getValue());
163
164 return nonlval::SymIntConstraintVal(C);
165 }
166 else
167 return cast<NonLValue>(UnknownVal());
168 }
169 }
170 }
171}
172
Ted Kremenekb640b3b2008-02-15 00:52:26 +0000173
Ted Kremenekc6fbdcd2008-02-15 23:15:23 +0000174// Binary Operators (except assignments and comma).
175
176RValue GRSimpleVals::EvalBinaryOp(ValueManager& ValMgr,
177 BinaryOperator::Opcode Op,
178 LValue LHS, LValue RHS) {
179
Ted Kremenek692416c2008-02-18 22:57:02 +0000180 assert (!isa<UnknownVal>(LHS) && !isa<UninitializedVal>(LHS));
181 assert (!isa<UnknownVal>(RHS) && !isa<UninitializedVal>(RHS));
182
Ted Kremenekc6fbdcd2008-02-15 23:15:23 +0000183 switch (Op) {
184 default:
185 return UnknownVal();
186
187 case BinaryOperator::EQ:
188 return EvalEQ(ValMgr, LHS, RHS);
189
190 case BinaryOperator::NE:
191 return EvalNE(ValMgr, LHS, RHS);
192 }
193}
194
Ted Kremenekb640b3b2008-02-15 00:52:26 +0000195// Pointer arithmetic.
196
197LValue GRSimpleVals::EvalBinaryOp(ValueManager& ValMgr,
198 BinaryOperator::Opcode Op,
199 LValue LHS, NonLValue RHS) {
Ted Kremenek692416c2008-02-18 22:57:02 +0000200
201 assert (!isa<UnknownVal>(LHS) && !isa<UninitializedVal>(LHS));
202 assert (!isa<UnknownVal>(RHS) && !isa<UninitializedVal>(RHS));
203
Ted Kremenekb640b3b2008-02-15 00:52:26 +0000204 return cast<LValue>(UnknownVal());
205}
206
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000207// Equality operators for LValues.
208
209
210NonLValue GRSimpleVals::EvalEQ(ValueManager& ValMgr, LValue LHS, LValue RHS) {
211
Ted Kremenek692416c2008-02-18 22:57:02 +0000212 assert (!isa<UnknownVal>(LHS) && !isa<UninitializedVal>(LHS));
213 assert (!isa<UnknownVal>(RHS) && !isa<UninitializedVal>(RHS));
214
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000215 switch (LHS.getSubKind()) {
216 default:
217 assert(false && "EQ not implemented for this LValue.");
218 return cast<NonLValue>(UnknownVal());
219
220 case lval::ConcreteIntKind:
221 if (isa<lval::ConcreteInt>(RHS)) {
222 bool b = cast<lval::ConcreteInt>(LHS).getValue() ==
223 cast<lval::ConcreteInt>(RHS).getValue();
224
225 return NonLValue::GetIntTruthValue(ValMgr, b);
226 }
227 else if (isa<lval::SymbolVal>(RHS)) {
228
229 const SymIntConstraint& C =
230 ValMgr.getConstraint(cast<lval::SymbolVal>(RHS).getSymbol(),
231 BinaryOperator::EQ,
232 cast<lval::ConcreteInt>(LHS).getValue());
233
234 return nonlval::SymIntConstraintVal(C);
235 }
236
237 break;
238
239 case lval::SymbolValKind: {
240 if (isa<lval::ConcreteInt>(RHS)) {
241 const SymIntConstraint& C =
242 ValMgr.getConstraint(cast<lval::SymbolVal>(LHS).getSymbol(),
243 BinaryOperator::EQ,
244 cast<lval::ConcreteInt>(RHS).getValue());
245
246 return nonlval::SymIntConstraintVal(C);
247 }
248
Ted Kremenekf0c8ef02008-02-18 21:19:49 +0000249 // FIXME: Implement unification
250 return cast<NonLValue>(UnknownVal());
251 //assert (!isa<lval::SymbolVal>(RHS) && "FIXME: Implement unification.");
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000252
253 break;
254 }
255
256 case lval::DeclValKind:
257
258 if (isa<lval::DeclVal>(RHS)) {
259 bool b = cast<lval::DeclVal>(LHS) == cast<lval::DeclVal>(RHS);
260 return NonLValue::GetIntTruthValue(ValMgr, b);
261 }
262
263 break;
264 }
265
266 return NonLValue::GetIntTruthValue(ValMgr, false);
267}
268
269NonLValue GRSimpleVals::EvalNE(ValueManager& ValMgr, LValue LHS, LValue RHS) {
Ted Kremenek692416c2008-02-18 22:57:02 +0000270
271 assert (!isa<UnknownVal>(LHS) && !isa<UninitializedVal>(LHS));
272 assert (!isa<UnknownVal>(RHS) && !isa<UninitializedVal>(RHS));
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000273
274 switch (LHS.getSubKind()) {
275 default:
276 assert(false && "NE not implemented for this LValue.");
277 return cast<NonLValue>(UnknownVal());
278
279 case lval::ConcreteIntKind:
280 if (isa<lval::ConcreteInt>(RHS)) {
281 bool b = cast<lval::ConcreteInt>(LHS).getValue() !=
282 cast<lval::ConcreteInt>(RHS).getValue();
283
284 return NonLValue::GetIntTruthValue(ValMgr, b);
285 }
286 else if (isa<lval::SymbolVal>(RHS)) {
287 const SymIntConstraint& C =
288 ValMgr.getConstraint(cast<lval::SymbolVal>(RHS).getSymbol(),
289 BinaryOperator::NE,
290 cast<lval::ConcreteInt>(LHS).getValue());
291
292 return nonlval::SymIntConstraintVal(C);
293 }
294
295 break;
296
297 case lval::SymbolValKind: {
298 if (isa<lval::ConcreteInt>(RHS)) {
299 const SymIntConstraint& C =
300 ValMgr.getConstraint(cast<lval::SymbolVal>(LHS).getSymbol(),
301 BinaryOperator::NE,
302 cast<lval::ConcreteInt>(RHS).getValue());
303
304 return nonlval::SymIntConstraintVal(C);
305 }
306
307 assert (!isa<lval::SymbolVal>(RHS) && "FIXME: Implement sym !=.");
308
309 break;
310 }
311
312 case lval::DeclValKind:
313 if (isa<lval::DeclVal>(RHS)) {
314 bool b = cast<lval::DeclVal>(LHS) == cast<lval::DeclVal>(RHS);
315 return NonLValue::GetIntTruthValue(ValMgr, b);
316 }
317
318 break;
319 }
320
321 return NonLValue::GetIntTruthValue(ValMgr, true);
322}