blob: e7b456ff21cc432d496fc4723f17e018f26d84ee [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//
Gabor Greif843e9342008-03-06 10:40:09 +000010// This file defines GRSimpleVals, a sub-class of GRTransferFuncs that
Ted Kremenekd59cccc2008-02-14 18:28:23 +000011// provides transfer functions for performing simple value tracking with
12// limited support for symbolics.
13//
14//===----------------------------------------------------------------------===//
15
16#include "GRSimpleVals.h"
Ted Kremenek52755612008-03-27 17:17:22 +000017#include "BasicObjCFoundationChecks.h"
Ted Kremenek87abc032008-04-02 22:03:53 +000018#include "clang/Basic/SourceManager.h"
Ted Kremenek4dc41cc2008-03-31 18:26:32 +000019#include "clang/Analysis/PathDiagnostic.h"
Ted Kremenek61f3e052008-04-03 04:42:52 +000020#include "clang/Analysis/PathSensitive/ValueState.h"
21#include "clang/Analysis/PathSensitive/BugReporter.h"
22#include "llvm/Support/Compiler.h"
Ted Kremenek5c061212008-02-27 17:56:16 +000023#include <sstream>
Ted Kremenekd59cccc2008-02-14 18:28:23 +000024
25using namespace clang;
26
Ted Kremenekdd598112008-04-02 07:05:46 +000027//===----------------------------------------------------------------------===//
Ted Kremenekdd598112008-04-02 07:05:46 +000028// Utility functions.
29//===----------------------------------------------------------------------===//
Ted Kremenek50a6d0c2008-04-09 21:41:14 +000030
Chris Lattner3ae30f82008-04-06 04:22:39 +000031template <typename ITERATOR> inline
Ted Kremenek61f3e052008-04-03 04:42:52 +000032ExplodedNode<ValueState>* GetNode(ITERATOR I) {
Ted Kremenek503d6132008-04-02 05:15:22 +000033 return *I;
34}
35
Chris Lattner3ae30f82008-04-06 04:22:39 +000036template <> inline
Ted Kremenek61f3e052008-04-03 04:42:52 +000037ExplodedNode<ValueState>* GetNode(GRExprEngine::undef_arg_iterator I) {
Ted Kremenek503d6132008-04-02 05:15:22 +000038 return I->first;
39}
Ted Kremenekdd598112008-04-02 07:05:46 +000040
Ted Kremenek50a6d0c2008-04-09 21:41:14 +000041template <typename ITER>
42void GenericEmitWarnings(BugReporter& BR, const BugType& D,
43 ITER I, ITER E) {
44
45 for (; I != E; ++I) {
46 BugReport R(D);
47 BR.EmitPathWarning(R, GetNode(I));
48 }
49}
50
51//===----------------------------------------------------------------------===//
52// Bug Descriptions.
53//===----------------------------------------------------------------------===//
54
55namespace {
56
57class VISIBILITY_HIDDEN NullDeref : public BugType {
58public:
59 virtual const char* getName() const {
60 return "null dereference";
61 }
62
63 virtual const char* getDescription() const {
64 return "Dereference of null pointer.";
65 }
66
67 virtual void EmitWarnings(BugReporter& BR) {
68 GRExprEngine& Eng = BR.getEngine();
69 GenericEmitWarnings(BR, *this, Eng.null_derefs_begin(),
70 Eng.null_derefs_end());
71 }
72};
73
74class VISIBILITY_HIDDEN UndefDeref : public BugType {
75public:
76 virtual const char* getName() const {
77 return "bad dereference";
78 }
79
80 virtual const char* getDescription() const {
81 return "Dereference of undefined value.";
82 }
83
84 virtual void EmitWarnings(BugReporter& BR) {
85 GRExprEngine& Eng = BR.getEngine();
86 GenericEmitWarnings(BR, *this, Eng.undef_derefs_begin(),
87 Eng.undef_derefs_end());
88 }
89};
90
91class VISIBILITY_HIDDEN UndefBranch : public BugType {
92public:
93 virtual const char* getName() const {
94 return "uninitialized value";
95 }
96
97 virtual const char* getDescription() const {
98 return "Branch condition evaluates to an uninitialized value.";
99 }
100
101 virtual void EmitWarnings(BugReporter& BR) {
102 GRExprEngine& Eng = BR.getEngine();
103 GenericEmitWarnings(BR, *this, Eng.undef_branches_begin(),
104 Eng.undef_branches_end());
105 }
106};
107
108class VISIBILITY_HIDDEN DivZero : public BugType {
109public:
110 virtual const char* getName() const {
111 return "divide-by-zero";
112 }
113
114 virtual const char* getDescription() const {
115 return "Division by zero/undefined value.";
116 }
117
118 virtual void EmitWarnings(BugReporter& BR) {
119 GRExprEngine& Eng = BR.getEngine();
120 GenericEmitWarnings(BR, *this, Eng.explicit_bad_divides_begin(),
121 Eng.explicit_bad_divides_end());
122 }
123};
124
125class VISIBILITY_HIDDEN UndefResult : public BugType {
126public:
127 virtual const char* getName() const {
128 return "undefined result";
129 }
130
131 virtual const char* getDescription() const {
132 return "Result of operation is undefined.";
133 }
134
135 virtual void EmitWarnings(BugReporter& BR) {
136 GRExprEngine& Eng = BR.getEngine();
137 GenericEmitWarnings(BR, *this, Eng.undef_results_begin(),
138 Eng.undef_results_begin());
139 }
140};
141
142class VISIBILITY_HIDDEN BadCall : public BugType {
143public:
144 virtual const char* getName() const {
145 return "invalid function call";
146 }
147
148 virtual const char* getDescription() const {
149 return "Called function is a NULL or undefined function pointer value.";
150 }
151
152 virtual void EmitWarnings(BugReporter& BR) {
153 GRExprEngine& Eng = BR.getEngine();
154 GenericEmitWarnings(BR, *this, Eng.bad_calls_begin(),
155 Eng.bad_calls_begin());
156 }
157};
158
159
160class VISIBILITY_HIDDEN BadArg : public BugType {
161protected:
162
163 class Report : public BugReport {
164 const SourceRange R;
165 public:
166 Report(BugType& D, Expr* E) : BugReport(D), R(E->getSourceRange()) {}
167 virtual ~Report() {}
168
169 virtual void getRanges(const SourceRange*& B, const SourceRange*& E) const {
170 B = &R;
171 E = B+1;
172 }
173 };
174
175public:
176
177 virtual ~BadArg() {}
178
179 virtual const char* getName() const {
180 return "bad argument";
181 }
182
183 virtual const char* getDescription() const {
184 return "Pass-by-value argument in function is undefined.";
185 }
186
187 virtual void EmitWarnings(BugReporter& BR) {
188 GRExprEngine& Eng = BR.getEngine();
189
190 for (GRExprEngine::UndefArgsTy::iterator I = Eng.undef_arg_begin(),
191 E = Eng.undef_arg_end(); I!=E; ++I) {
192
193 // Generate a report for this bug.
194 Report report(*this, I->second);
195
196 // Emit the warning.
197 BR.EmitPathWarning(report, I->first);
198 }
199
200 }
201};
202
203class VISIBILITY_HIDDEN BadMsgExprArg : public BadArg {
204public:
205 virtual const char* getName() const {
206 return "bad argument";
207 }
208
209 virtual const char* getDescription() const {
210 return "Pass-by-value argument in message expression is undefined.";
211 }
212
213 virtual void EmitWarnings(BugReporter& BR) {
214 GRExprEngine& Eng = BR.getEngine();
215
216 for (GRExprEngine::UndefArgsTy::iterator I=Eng.msg_expr_undef_arg_begin(),
217 E = Eng.msg_expr_undef_arg_begin(); I!=E; ++I) {
218
219 // Generate a report for this bug.
220 Report report(*this, I->second);
221
222 // Emit the warning.
223 BR.EmitPathWarning(report, I->first);
224 }
225
226 }
227};
228
229class VISIBILITY_HIDDEN BadReceiver : public BugType {
230
231 class Report : public BugReport {
232 SourceRange R;
233 public:
234 Report(BugType& D, ExplodedNode<ValueState> *N) : BugReport(D) {
235 Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
236 Expr* E = cast<ObjCMessageExpr>(S)->getReceiver();
237 assert (E && "Receiver cannot be NULL");
238 R = E->getSourceRange();
239 }
240
241 virtual ~Report() {}
242
243 virtual void getRanges(const SourceRange*& B, const SourceRange*& E) const {
244 B = &R;
245 E = B+1;
246 }
247 };
248
249public:
250 virtual const char* getName() const {
251 return "bad receiver";
252 }
253
254 virtual const char* getDescription() const {
255 return "Receiver in message expression is an uninitialized value.";
256 }
257
258 virtual void EmitWarnings(BugReporter& BR) {
259 GRExprEngine& Eng = BR.getEngine();
260
261 for (GRExprEngine::UndefReceiversTy::iterator I=Eng.undef_receivers_begin(),
262 E = Eng.undef_receivers_end(); I!=E; ++I) {
263
264 // Generate a report for this bug.
265 Report report(*this, *I);
266
267 // Emit the warning.
268 BR.EmitPathWarning(report, *I);
269 }
270 }
271};
272
273class VISIBILITY_HIDDEN RetStack : public BugType {
274public:
275 virtual const char* getName() const {
276 return "return of stack address";
277 }
278
279 virtual const char* getDescription() const {
280 return "Address of stack-allocated variable returned.";
281 }
282
283 virtual void EmitWarnings(BugReporter& BR) {
284 GRExprEngine& Eng = BR.getEngine();
285 GenericEmitWarnings(BR, *this, Eng.ret_stackaddr_begin(),
286 Eng.ret_stackaddr_begin());
287 }
288};
289
290} // end anonymous namespace
291
292void GRSimpleVals::RegisterChecks(GRExprEngine& Eng) {
293 Eng.Register(new NullDeref());
294 Eng.Register(new UndefDeref());
295 Eng.Register(new UndefBranch());
296 Eng.Register(new DivZero());
297 Eng.Register(new UndefResult());
298 Eng.Register(new BadCall());
299 Eng.Register(new RetStack());
300 Eng.Register(new BadArg());
301 Eng.Register(new BadMsgExprArg());
302 Eng.Register(new BadReceiver());
303
304 // Add extra checkers.
305
306 GRSimpleAPICheck* FoundationCheck =
307 CreateBasicObjCFoundationChecks(Eng.getContext(), &Eng.getStateManager());
308
309 Eng.AddObjCMessageExprCheck(FoundationCheck);
310}
311
Ted Kremenekdd598112008-04-02 07:05:46 +0000312//===----------------------------------------------------------------------===//
Ted Kremenek503d6132008-04-02 05:15:22 +0000313// Analysis Driver.
314//===----------------------------------------------------------------------===//
Ted Kremenek61f3e052008-04-03 04:42:52 +0000315
Ted Kremenekdd598112008-04-02 07:05:46 +0000316namespace clang {
317
Ted Kremenek63bbe532008-03-14 17:31:00 +0000318unsigned RunGRSimpleVals(CFG& cfg, Decl& CD, ASTContext& Ctx,
Ted Kremenekf1ae7052008-04-03 17:57:38 +0000319 Diagnostic& Diag, PathDiagnosticClient* PD,
320 bool Visualize, bool TrimGraph) {
Ted Kremenek50a6d0c2008-04-09 21:41:14 +0000321
322 // Construct the analysis engine.
323 GRExprEngine Eng(cfg, CD, Ctx);
Ted Kremenek52755612008-03-27 17:17:22 +0000324
325 // Set base transfer functions.
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000326 GRSimpleVals GRSV;
Ted Kremenek50a6d0c2008-04-09 21:41:14 +0000327 Eng.setTransferFunctions(GRSV);
Ted Kremenek52755612008-03-27 17:17:22 +0000328
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000329 // Execute the worklist algorithm.
Ted Kremenek50a6d0c2008-04-09 21:41:14 +0000330 Eng.ExecuteWorkList();
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000331
Ted Kremenek50a6d0c2008-04-09 21:41:14 +0000332 // Display warnings.
333 Eng.EmitWarnings(Diag, PD);
Ted Kremenek61f3e052008-04-03 04:42:52 +0000334
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000335#ifndef NDEBUG
Ted Kremenek50a6d0c2008-04-09 21:41:14 +0000336 if (Visualize) Eng.ViewGraph(TrimGraph);
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000337#endif
338
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000339 return Eng.getGraph().size();
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000340}
341
Ted Kremeneke01c9872008-02-14 22:36:46 +0000342} // end clang namespace
343
Ted Kremenekd59cccc2008-02-14 18:28:23 +0000344//===----------------------------------------------------------------------===//
345// Transfer function for Casts.
346//===----------------------------------------------------------------------===//
347
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000348RVal GRSimpleVals::EvalCast(GRExprEngine& Eng, NonLVal X, QualType T) {
Ted Kremenek692416c2008-02-18 22:57:02 +0000349
Ted Kremenekd59cccc2008-02-14 18:28:23 +0000350 if (!isa<nonlval::ConcreteInt>(X))
351 return UnknownVal();
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000352
353 BasicValueFactory& BasicVals = Eng.getBasicVals();
Ted Kremenekd59cccc2008-02-14 18:28:23 +0000354
355 llvm::APSInt V = cast<nonlval::ConcreteInt>(X).getValue();
Ted Kremenek1b9df4c2008-03-14 18:14:50 +0000356 V.setIsUnsigned(T->isUnsignedIntegerType() || T->isPointerType()
357 || T->isObjCQualifiedIdType());
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000358 V.extOrTrunc(Eng.getContext().getTypeSize(T));
Ted Kremenekd59cccc2008-02-14 18:28:23 +0000359
Ted Kremenek9ef1ec92008-02-21 18:43:30 +0000360 if (T->isPointerType())
Ted Kremenek240f1f02008-03-07 20:13:31 +0000361 return lval::ConcreteInt(BasicVals.getValue(V));
Ted Kremenekd59cccc2008-02-14 18:28:23 +0000362 else
Ted Kremenek240f1f02008-03-07 20:13:31 +0000363 return nonlval::ConcreteInt(BasicVals.getValue(V));
Ted Kremenekd59cccc2008-02-14 18:28:23 +0000364}
365
366// Casts.
367
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000368RVal GRSimpleVals::EvalCast(GRExprEngine& Eng, LVal X, QualType T) {
Ted Kremenek692416c2008-02-18 22:57:02 +0000369
Chris Lattner423a3c92008-04-02 17:45:06 +0000370 if (T->isPointerLikeType() || T->isObjCQualifiedIdType())
Ted Kremenekd59cccc2008-02-14 18:28:23 +0000371 return X;
372
Ted Kremenek9ef1ec92008-02-21 18:43:30 +0000373 assert (T->isIntegerType());
Ted Kremenekd59cccc2008-02-14 18:28:23 +0000374
375 if (!isa<lval::ConcreteInt>(X))
376 return UnknownVal();
377
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000378 BasicValueFactory& BasicVals = Eng.getBasicVals();
379
Ted Kremenekd59cccc2008-02-14 18:28:23 +0000380 llvm::APSInt V = cast<lval::ConcreteInt>(X).getValue();
Ted Kremenekd59cccc2008-02-14 18:28:23 +0000381 V.setIsUnsigned(T->isUnsignedIntegerType() || T->isPointerType());
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000382 V.extOrTrunc(Eng.getContext().getTypeSize(T));
Ted Kremenekd59cccc2008-02-14 18:28:23 +0000383
Ted Kremenek240f1f02008-03-07 20:13:31 +0000384 return nonlval::ConcreteInt(BasicVals.getValue(V));
Ted Kremenekc3f261d2008-02-14 18:40:24 +0000385}
386
387// Unary operators.
388
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000389RVal GRSimpleVals::EvalMinus(GRExprEngine& Eng, UnaryOperator* U, NonLVal X){
Ted Kremenek692416c2008-02-18 22:57:02 +0000390
Ted Kremenekc3f261d2008-02-14 18:40:24 +0000391 switch (X.getSubKind()) {
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000392
Ted Kremenekc3f261d2008-02-14 18:40:24 +0000393 case nonlval::ConcreteIntKind:
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000394 return cast<nonlval::ConcreteInt>(X).EvalMinus(Eng.getBasicVals(), U);
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000395
Ted Kremenekc3f261d2008-02-14 18:40:24 +0000396 default:
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000397 return UnknownVal();
Ted Kremenekc3f261d2008-02-14 18:40:24 +0000398 }
399}
400
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000401RVal GRSimpleVals::EvalComplement(GRExprEngine& Eng, NonLVal X) {
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000402
Ted Kremenek90e42032008-02-20 04:12:31 +0000403 switch (X.getSubKind()) {
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000404
Ted Kremenekc3f261d2008-02-14 18:40:24 +0000405 case nonlval::ConcreteIntKind:
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000406 return cast<nonlval::ConcreteInt>(X).EvalComplement(Eng.getBasicVals());
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000407
Ted Kremenekc3f261d2008-02-14 18:40:24 +0000408 default:
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000409 return UnknownVal();
Ted Kremenekc3f261d2008-02-14 18:40:24 +0000410 }
411}
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000412
413// Binary operators.
414
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000415RVal GRSimpleVals::EvalBinOp(GRExprEngine& Eng, BinaryOperator::Opcode Op,
416 NonLVal L, NonLVal R) {
417
418 BasicValueFactory& BasicVals = Eng.getBasicVals();
419
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000420 while (1) {
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000421
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000422 switch (L.getSubKind()) {
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000423 default:
Ted Kremenek9258a642008-02-21 19:10:12 +0000424 return UnknownVal();
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000425
426 case nonlval::ConcreteIntKind:
427
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000428 if (isa<nonlval::ConcreteInt>(R)) {
429 const nonlval::ConcreteInt& L_CI = cast<nonlval::ConcreteInt>(L);
430 const nonlval::ConcreteInt& R_CI = cast<nonlval::ConcreteInt>(R);
Ted Kremenek240f1f02008-03-07 20:13:31 +0000431 return L_CI.EvalBinOp(BasicVals, Op, R_CI);
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000432 }
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000433 else {
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000434 NonLVal tmp = R;
435 R = L;
436 L = tmp;
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000437 continue;
438 }
439
440 case nonlval::SymbolValKind: {
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000441
442 if (isa<nonlval::ConcreteInt>(R)) {
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000443 const SymIntConstraint& C =
Ted Kremenek240f1f02008-03-07 20:13:31 +0000444 BasicVals.getConstraint(cast<nonlval::SymbolVal>(L).getSymbol(), Op,
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000445 cast<nonlval::ConcreteInt>(R).getValue());
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000446
447 return nonlval::SymIntConstraintVal(C);
448 }
449 else
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000450 return UnknownVal();
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000451 }
452 }
453 }
454}
455
Ted Kremenekb640b3b2008-02-15 00:52:26 +0000456
Ted Kremenekc6fbdcd2008-02-15 23:15:23 +0000457// Binary Operators (except assignments and comma).
458
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000459RVal GRSimpleVals::EvalBinOp(GRExprEngine& Eng, BinaryOperator::Opcode Op,
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000460 LVal L, LVal R) {
Ted Kremenek692416c2008-02-18 22:57:02 +0000461
Ted Kremenekc6fbdcd2008-02-15 23:15:23 +0000462 switch (Op) {
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000463
Ted Kremenekc6fbdcd2008-02-15 23:15:23 +0000464 default:
465 return UnknownVal();
466
467 case BinaryOperator::EQ:
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000468 return EvalEQ(Eng, L, R);
Ted Kremenekc6fbdcd2008-02-15 23:15:23 +0000469
470 case BinaryOperator::NE:
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000471 return EvalNE(Eng, L, R);
Ted Kremenekc6fbdcd2008-02-15 23:15:23 +0000472 }
473}
474
Ted Kremenekb640b3b2008-02-15 00:52:26 +0000475// Pointer arithmetic.
476
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000477RVal GRSimpleVals::EvalBinOp(GRExprEngine& Eng, BinaryOperator::Opcode Op,
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000478 LVal L, NonLVal R) {
479 return UnknownVal();
Ted Kremenekb640b3b2008-02-15 00:52:26 +0000480}
481
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000482// Equality operators for LVals.
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000483
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000484RVal GRSimpleVals::EvalEQ(GRExprEngine& Eng, LVal L, LVal R) {
485
486 BasicValueFactory& BasicVals = Eng.getBasicVals();
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000487
488 switch (L.getSubKind()) {
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000489
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000490 default:
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000491 assert(false && "EQ not implemented for this LVal.");
492 return UnknownVal();
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000493
494 case lval::ConcreteIntKind:
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000495
496 if (isa<lval::ConcreteInt>(R)) {
497 bool b = cast<lval::ConcreteInt>(L).getValue() ==
498 cast<lval::ConcreteInt>(R).getValue();
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000499
Ted Kremenek240f1f02008-03-07 20:13:31 +0000500 return NonLVal::MakeIntTruthVal(BasicVals, b);
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000501 }
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000502 else if (isa<lval::SymbolVal>(R)) {
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000503
504 const SymIntConstraint& C =
Ted Kremenek240f1f02008-03-07 20:13:31 +0000505 BasicVals.getConstraint(cast<lval::SymbolVal>(R).getSymbol(),
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000506 BinaryOperator::EQ,
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000507 cast<lval::ConcreteInt>(L).getValue());
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000508
509 return nonlval::SymIntConstraintVal(C);
510 }
511
512 break;
513
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000514 case lval::SymbolValKind: {
515
516 if (isa<lval::ConcreteInt>(R)) {
517 const SymIntConstraint& C =
Ted Kremenek240f1f02008-03-07 20:13:31 +0000518 BasicVals.getConstraint(cast<lval::SymbolVal>(L).getSymbol(),
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000519 BinaryOperator::EQ,
520 cast<lval::ConcreteInt>(R).getValue());
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000521
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000522 return nonlval::SymIntConstraintVal(C);
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000523 }
524
Ted Kremenekf700df22008-02-22 18:41:59 +0000525 // FIXME: Implement == for lval Symbols. This is mainly useful
526 // in iterator loops when traversing a buffer, e.g. while(z != zTerm).
527 // Since this is not useful for many checkers we'll punt on this for
528 // now.
529
530 return UnknownVal();
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000531 }
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000532
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000533 case lval::DeclValKind:
Ted Kremenekdc3936b2008-02-22 00:54:56 +0000534 case lval::FuncValKind:
535 case lval::GotoLabelKind:
Ted Kremenek240f1f02008-03-07 20:13:31 +0000536 return NonLVal::MakeIntTruthVal(BasicVals, L == R);
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000537 }
538
Ted Kremenek240f1f02008-03-07 20:13:31 +0000539 return NonLVal::MakeIntTruthVal(BasicVals, false);
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000540}
541
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000542RVal GRSimpleVals::EvalNE(GRExprEngine& Eng, LVal L, LVal R) {
Ted Kremenek692416c2008-02-18 22:57:02 +0000543
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000544 BasicValueFactory& BasicVals = Eng.getBasicVals();
545
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000546 switch (L.getSubKind()) {
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000547
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000548 default:
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000549 assert(false && "NE not implemented for this LVal.");
550 return UnknownVal();
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000551
552 case lval::ConcreteIntKind:
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000553
554 if (isa<lval::ConcreteInt>(R)) {
555 bool b = cast<lval::ConcreteInt>(L).getValue() !=
556 cast<lval::ConcreteInt>(R).getValue();
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000557
Ted Kremenek240f1f02008-03-07 20:13:31 +0000558 return NonLVal::MakeIntTruthVal(BasicVals, b);
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000559 }
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000560 else if (isa<lval::SymbolVal>(R)) {
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000561 const SymIntConstraint& C =
Ted Kremenek240f1f02008-03-07 20:13:31 +0000562 BasicVals.getConstraint(cast<lval::SymbolVal>(R).getSymbol(),
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000563 BinaryOperator::NE,
564 cast<lval::ConcreteInt>(L).getValue());
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000565
566 return nonlval::SymIntConstraintVal(C);
567 }
568
569 break;
570
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000571 case lval::SymbolValKind: {
572 if (isa<lval::ConcreteInt>(R)) {
573 const SymIntConstraint& C =
Ted Kremenek240f1f02008-03-07 20:13:31 +0000574 BasicVals.getConstraint(cast<lval::SymbolVal>(L).getSymbol(),
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000575 BinaryOperator::NE,
576 cast<lval::ConcreteInt>(R).getValue());
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000577
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000578 return nonlval::SymIntConstraintVal(C);
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000579 }
580
Ted Kremenekf700df22008-02-22 18:41:59 +0000581 // FIXME: Implement != for lval Symbols. This is mainly useful
582 // in iterator loops when traversing a buffer, e.g. while(z != zTerm).
583 // Since this is not useful for many checkers we'll punt on this for
584 // now.
585
586 return UnknownVal();
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000587
588 break;
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000589 }
590
591 case lval::DeclValKind:
Ted Kremenekdc3936b2008-02-22 00:54:56 +0000592 case lval::FuncValKind:
593 case lval::GotoLabelKind:
Ted Kremenek240f1f02008-03-07 20:13:31 +0000594 return NonLVal::MakeIntTruthVal(BasicVals, L != R);
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000595 }
596
Ted Kremenek240f1f02008-03-07 20:13:31 +0000597 return NonLVal::MakeIntTruthVal(BasicVals, true);
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000598}
Ted Kremenek06747692008-02-26 23:04:29 +0000599
600//===----------------------------------------------------------------------===//
601// Transfer function for Function Calls.
602//===----------------------------------------------------------------------===//
603
Ted Kremenek330dddd2008-03-05 00:33:14 +0000604void GRSimpleVals::EvalCall(ExplodedNodeSet<ValueState>& Dst,
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000605 GRExprEngine& Eng,
Ted Kremenek330dddd2008-03-05 00:33:14 +0000606 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek330dddd2008-03-05 00:33:14 +0000607 CallExpr* CE, LVal L,
608 ExplodedNode<ValueState>* Pred) {
609
Ted Kremenekf923a912008-03-12 21:04:07 +0000610 ValueStateManager& StateMgr = Eng.getStateManager();
611 ValueState* St = Builder.GetState(Pred);
Ted Kremenek06747692008-02-26 23:04:29 +0000612
613 // Invalidate all arguments passed in by reference (LVals).
614
615 for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end();
616 I != E; ++I) {
617
Ted Kremenekf923a912008-03-12 21:04:07 +0000618 RVal V = StateMgr.GetRVal(St, *I);
Ted Kremenek06747692008-02-26 23:04:29 +0000619
620 if (isa<LVal>(V))
Ted Kremenekf923a912008-03-12 21:04:07 +0000621 St = StateMgr.SetRVal(St, cast<LVal>(V), UnknownVal());
Ted Kremenek06747692008-02-26 23:04:29 +0000622 }
Ted Kremenekf923a912008-03-12 21:04:07 +0000623
624 // Make up a symbol for the return value of this function.
625
626 if (CE->getType() != Eng.getContext().VoidTy) {
627 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenek361fa8e2008-03-12 21:45:47 +0000628 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(CE, Count);
Ted Kremenekf923a912008-03-12 21:04:07 +0000629
630 RVal X = CE->getType()->isPointerType()
631 ? cast<RVal>(lval::SymbolVal(Sym))
632 : cast<RVal>(nonlval::SymbolVal(Sym));
633
634 St = StateMgr.SetRVal(St, CE, X, Eng.getCFG().isBlkExpr(CE), false);
635 }
Ted Kremenek330dddd2008-03-05 00:33:14 +0000636
Ted Kremenek0e561a32008-03-21 21:30:14 +0000637 Builder.MakeNode(Dst, CE, Pred, St);
Ted Kremenek06747692008-02-26 23:04:29 +0000638}