blob: 0c62ae70c359f9dc7087d91fef39373cded57992 [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 Kremenek0f5f0592008-02-27 06:07:00 +000018#include "clang/Analysis/PathSensitive/ValueState.h"
Ted Kremenek4dc41cc2008-03-31 18:26:32 +000019#include "clang/Analysis/PathDiagnostic.h"
Ted Kremenek5c061212008-02-27 17:56:16 +000020#include <sstream>
Ted Kremenekd59cccc2008-02-14 18:28:23 +000021
22using namespace clang;
23
Ted Kremenekdd598112008-04-02 07:05:46 +000024//===----------------------------------------------------------------------===//
25// Bug Descriptions.
26//===----------------------------------------------------------------------===//
Ted Kremenekd87a3212008-02-26 21:31:18 +000027
Ted Kremenekdd598112008-04-02 07:05:46 +000028namespace bugdesc {
29
30struct NullDeref {
31 static const char* getName() { return "Null pointer dereference"; }
32
33 static PathDiagnosticPiece* getEndPath(SourceManager& SMgr,
34 ExplodedNode<ValueState> *N);
35};
36
37PathDiagnosticPiece* NullDeref::getEndPath(SourceManager& SMgr,
38 ExplodedNode<ValueState> *N) {
39
40 Expr* E = cast<Expr>(cast<PostStmt>(N->getLocation()).getStmt());
41
42 // FIXME: Do better ranges for different kinds of null dereferences.
43
44 FullSourceLoc L(E->getLocStart(), SMgr);
45
46 PathDiagnosticPiece* P = new PathDiagnosticPiece(L, getName());
47 P->addRange(E->getSourceRange());
48
49 return P;
50}
51
52} // end namespace: bugdesc
53
54//===----------------------------------------------------------------------===//
55// Utility functions.
56//===----------------------------------------------------------------------===//
57
Ted Kremenekd87a3212008-02-26 21:31:18 +000058template <typename ITERATOR>
Ted Kremenek503d6132008-04-02 05:15:22 +000059static inline ExplodedNode<ValueState>* GetNode(ITERATOR I) {
60 return *I;
61}
62
63template <>
64static inline ExplodedNode<ValueState>*
65GetNode(GRExprEngine::undef_arg_iterator I) {
66 return I->first;
67}
68
69template <typename ITERATOR>
Ted Kremenek1b9df4c2008-03-14 18:14:50 +000070static inline ProgramPoint GetLocation(ITERATOR I) {
71 return (*I)->getLocation();
Ted Kremenek1e80aa42008-03-04 00:42:54 +000072}
73
74template <>
Ted Kremenek503d6132008-04-02 05:15:22 +000075static inline ProgramPoint GetLocation(GRExprEngine::undef_arg_iterator I) {
Ted Kremenek1b9df4c2008-03-14 18:14:50 +000076 return I->first->getLocation();
77}
78
79static inline Stmt* GetStmt(const ProgramPoint& P) {
80 if (const PostStmt* PS = dyn_cast<PostStmt>(&P)) {
81 return PS->getStmt();
82 }
83 else if (const BlockEdge* BE = dyn_cast<BlockEdge>(&P)) {
84 return BE->getSrc()->getTerminator();
85 }
86
87 assert (false && "Unsupported ProgramPoint.");
88 return NULL;
Ted Kremenek1e80aa42008-03-04 00:42:54 +000089}
Ted Kremenek503d6132008-04-02 05:15:22 +000090
91//===----------------------------------------------------------------------===//
92// Pathless Warnings
93//===----------------------------------------------------------------------===//
94
Ted Kremenek1e80aa42008-03-04 00:42:54 +000095template <typename ITERATOR>
Ted Kremenek4dc41cc2008-03-31 18:26:32 +000096static void EmitDiag(Diagnostic& Diag, PathDiagnosticClient* PD,
97 SourceManager& SrcMgr,
98unsigned ErrorDiag, ITERATOR I) {
Ted Kremenek1e80aa42008-03-04 00:42:54 +000099
Ted Kremenek1b9df4c2008-03-14 18:14:50 +0000100 Stmt* S = GetStmt(GetLocation(I));
Ted Kremenek5297e5f2008-03-31 18:44:32 +0000101 SourceRange R = S->getSourceRange();
102 Diag.Report(PD, FullSourceLoc(S->getLocStart(), SrcMgr), ErrorDiag,
103 NULL, 0, &R, 1);
Ted Kremenek1e80aa42008-03-04 00:42:54 +0000104}
105
106
107template <>
Ted Kremenek4dc41cc2008-03-31 18:26:32 +0000108static void EmitDiag(Diagnostic& Diag, PathDiagnosticClient* PD,
109 SourceManager& SrcMgr, unsigned ErrorDiag,
110 GRExprEngine::undef_arg_iterator I) {
Ted Kremenek1e80aa42008-03-04 00:42:54 +0000111
Ted Kremenek1b9df4c2008-03-14 18:14:50 +0000112 Stmt* S1 = GetStmt(GetLocation(I));
Ted Kremenek1e80aa42008-03-04 00:42:54 +0000113 Expr* E2 = cast<Expr>(I->second);
114
Ted Kremenek1b9df4c2008-03-14 18:14:50 +0000115 SourceLocation Loc = S1->getLocStart();
Ted Kremenek1e80aa42008-03-04 00:42:54 +0000116 SourceRange R = E2->getSourceRange();
Ted Kremenek4dc41cc2008-03-31 18:26:32 +0000117 Diag.Report(PD, FullSourceLoc(Loc, SrcMgr), ErrorDiag, 0, 0, &R, 1);
Ted Kremenek1e80aa42008-03-04 00:42:54 +0000118}
119
120template <typename ITERATOR>
Ted Kremenekdd598112008-04-02 07:05:46 +0000121static void EmitWarning(Diagnostic& Diag, PathDiagnosticClient* PD,
122 SourceManager& SrcMgr,
123 ITERATOR I, ITERATOR E, const char* msg) {
Ted Kremenekd87a3212008-02-26 21:31:18 +0000124
Ted Kremenek5c061212008-02-27 17:56:16 +0000125 std::ostringstream Out;
Ted Kremenek503d6132008-04-02 05:15:22 +0000126 std::string Str(msg);
Ted Kremenek6bb205c2008-03-31 20:42:43 +0000127
128 if (!PD) {
129 Out << "[CHECKER] " << msg;
Ted Kremeneka6fb4e02008-04-01 22:35:58 +0000130 Str = Out.str();
131 msg = Str.c_str();
Ted Kremenek6bb205c2008-03-31 20:42:43 +0000132 }
Ted Kremenek5c061212008-02-27 17:56:16 +0000133
Ted Kremenek2bebc402008-02-27 20:47:56 +0000134 bool isFirst = true;
Ted Kremenekd9d1cbf2008-03-15 07:58:36 +0000135 unsigned ErrorDiag = 0;
Ted Kremenek1e80aa42008-03-04 00:42:54 +0000136 llvm::SmallPtrSet<void*,10> CachedErrors;
Ted Kremenekd87a3212008-02-26 21:31:18 +0000137
138 for (; I != E; ++I) {
139
140 if (isFirst) {
141 isFirst = false;
142 ErrorDiag = Diag.getCustomDiagID(Diagnostic::Warning, msg);
143 }
Ted Kremenek5c61e7a2008-02-28 20:38:16 +0000144 else {
145
146 // HACK: Cache the location of the error. Don't emit the same
147 // warning for the same error type that occurs at the same program
148 // location but along a different path.
Ted Kremenek1e80aa42008-03-04 00:42:54 +0000149 void* p = GetLocation(I).getRawData();
Ted Kremenek5c61e7a2008-02-28 20:38:16 +0000150
151 if (CachedErrors.count(p))
152 continue;
153
154 CachedErrors.insert(p);
155 }
Ted Kremenek1e80aa42008-03-04 00:42:54 +0000156
Ted Kremenekdd598112008-04-02 07:05:46 +0000157 EmitDiag(Diag, PD, SrcMgr, ErrorDiag, I);
Ted Kremenekd87a3212008-02-26 21:31:18 +0000158 }
159}
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000160
Ted Kremenek503d6132008-04-02 05:15:22 +0000161//===----------------------------------------------------------------------===//
Ted Kremenekdd598112008-04-02 07:05:46 +0000162// Path warnings.
163//===----------------------------------------------------------------------===//
164
165static void GeneratePathDiagnostic(PathDiagnostic& PD,
166 SourceManager& SMgr,
167 ExplodedNode<ValueState>* N) {
168
169 if (N->pred_empty())
170 return;
171
172 N = *(N->pred_begin());
173
174 ProgramPoint P = N->getLocation();
175
176 if (const BlockEdge* BE = dyn_cast<BlockEdge>(&P)) {
177
178 CFGBlock* Src = BE->getSrc();
179 CFGBlock* Dst = BE->getDst();
180
181 // FIXME: Better handling for switches.
182
183 if (Src->succ_size() == 2) {
184
185 Stmt* T = Src->getTerminator();
186
187 if (!Src)
188 return;
189
190 FullSourceLoc L(T->getLocStart(), SMgr);
191
192 if (*(Src->succ_begin()+1) == Dst)
193 PD.push_front(new PathDiagnosticPiece(L, "Taking false branch."));
194 else
195 PD.push_front(new PathDiagnosticPiece(L, "Taking true branch."));
196 }
197 }
198
199 GeneratePathDiagnostic(PD, SMgr, N);
200}
201
202template <typename ITERATOR, typename DESC>
203static void Report(PathDiagnosticClient& PDC, SourceManager& SMgr, DESC,
204 ITERATOR I, ITERATOR E) {
205
206
207 if (I == E)
208 return;
209
210 const char* BugName = DESC::getName();
211
212 llvm::SmallPtrSet<void*,10> CachedErrors;
213
214 for (; I != E; ++I) {
215
216 // HACK: Cache the location of the error. Don't emit the same
217 // warning for the same error type that occurs at the same program
218 // location but along a different path.
219 void* p = GetLocation(I).getRawData();
220
221 if (CachedErrors.count(p))
222 continue;
223
224 CachedErrors.insert(p);
225
226 // Create the PathDiagnostic.
227
228 PathDiagnostic D(BugName);
229
230 // Get the end-of-path diagnostic.
231 D.push_back(DESC::getEndPath(SMgr, GetNode(I)));
232
233 // Generate the rest of the diagnostic.
234 GeneratePathDiagnostic(D, SMgr, GetNode(I));
235
236 PDC.HandlePathDiagnostic(D);
237 }
238}
239
240
241//===----------------------------------------------------------------------===//
Ted Kremenek503d6132008-04-02 05:15:22 +0000242// Analysis Driver.
243//===----------------------------------------------------------------------===//
244
Ted Kremenekdd598112008-04-02 07:05:46 +0000245namespace clang {
246
Ted Kremenek63bbe532008-03-14 17:31:00 +0000247unsigned RunGRSimpleVals(CFG& cfg, Decl& CD, ASTContext& Ctx,
Ted Kremenekdd598112008-04-02 07:05:46 +0000248 Diagnostic& Diag, PathDiagnosticClient* PD,
249 bool Visualize, bool TrimGraph) {
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000250
Ted Kremenek63bbe532008-03-14 17:31:00 +0000251 GRCoreEngine<GRExprEngine> Eng(cfg, CD, Ctx);
Ted Kremenekdd598112008-04-02 07:05:46 +0000252 GRExprEngine* CS = &Eng.getCheckerState();
Ted Kremenek52755612008-03-27 17:17:22 +0000253
254 // Set base transfer functions.
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000255 GRSimpleVals GRSV;
Ted Kremenekdd598112008-04-02 07:05:46 +0000256 CS->setTransferFunctions(GRSV);
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000257
Ted Kremenek52755612008-03-27 17:17:22 +0000258 // Add extra checkers.
259 llvm::OwningPtr<GRSimpleAPICheck> FoundationCheck(
Ted Kremenekdd598112008-04-02 07:05:46 +0000260 CreateBasicObjCFoundationChecks(Ctx, &CS->getStateManager()));
Ted Kremenek52755612008-03-27 17:17:22 +0000261
Ted Kremenekdd598112008-04-02 07:05:46 +0000262 CS->AddObjCMessageExprCheck(FoundationCheck.get());
Ted Kremenek52755612008-03-27 17:17:22 +0000263
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000264 // Execute the worklist algorithm.
Ted Kremenek4dc41cc2008-03-31 18:26:32 +0000265 Eng.ExecuteWorkList(120000);
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000266
Ted Kremenekd87a3212008-02-26 21:31:18 +0000267 SourceManager& SrcMgr = Ctx.getSourceManager();
268
Ted Kremenekdd598112008-04-02 07:05:46 +0000269 if (!PD)
270 EmitWarning(Diag, PD, SrcMgr,
271 CS->null_derefs_begin(), CS->null_derefs_end(),
272 "Dereference of NULL pointer.");
273 else
274 Report(*PD, SrcMgr, bugdesc::NullDeref(),
275 CS->null_derefs_begin(), CS->null_derefs_end());
276
Ted Kremenekd87a3212008-02-26 21:31:18 +0000277
Ted Kremenek4dc41cc2008-03-31 18:26:32 +0000278 EmitWarning(Diag, PD, SrcMgr,
Ted Kremenekdd598112008-04-02 07:05:46 +0000279 CS->undef_derefs_begin(),
280 CS->undef_derefs_end(),
Ted Kremenek4a4e5242008-02-28 09:25:22 +0000281 "Dereference of undefined value.");
Ted Kremenekd87a3212008-02-26 21:31:18 +0000282
Ted Kremenek4dc41cc2008-03-31 18:26:32 +0000283 EmitWarning(Diag, PD, SrcMgr,
Ted Kremenekdd598112008-04-02 07:05:46 +0000284 CS->undef_branches_begin(),
285 CS->undef_branches_end(),
Ted Kremenekdbfe41a2008-03-25 16:40:05 +0000286 "Branch condition evaluates to an uninitialized value.");
Ted Kremenekd87a3212008-02-26 21:31:18 +0000287
Ted Kremenek4dc41cc2008-03-31 18:26:32 +0000288 EmitWarning(Diag, PD, SrcMgr,
Ted Kremenekdd598112008-04-02 07:05:46 +0000289 CS->explicit_bad_divides_begin(),
290 CS->explicit_bad_divides_end(),
Ted Kremenek4a4e5242008-02-28 09:25:22 +0000291 "Division by zero/undefined value.");
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000292
Ted Kremenek4dc41cc2008-03-31 18:26:32 +0000293 EmitWarning(Diag, PD, SrcMgr,
Ted Kremenekdd598112008-04-02 07:05:46 +0000294 CS->undef_results_begin(),
295 CS->undef_results_end(),
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000296 "Result of operation is undefined.");
Ted Kremenek5e03fcb2008-02-29 23:14:48 +0000297
Ted Kremenek4dc41cc2008-03-31 18:26:32 +0000298 EmitWarning(Diag, PD, SrcMgr,
Ted Kremenekdd598112008-04-02 07:05:46 +0000299 CS->bad_calls_begin(),
300 CS->bad_calls_end(),
Ted Kremenek5e03fcb2008-02-29 23:14:48 +0000301 "Call using a NULL or undefined function pointer value.");
Ted Kremenek2ded35a2008-02-29 23:53:11 +0000302
Ted Kremenek4dc41cc2008-03-31 18:26:32 +0000303 EmitWarning(Diag, PD, SrcMgr,
Ted Kremenekdd598112008-04-02 07:05:46 +0000304 CS->undef_arg_begin(),
305 CS->undef_arg_end(),
Ted Kremenekdbfe41a2008-03-25 16:40:05 +0000306 "Pass-by-value argument in function is undefined.");
Ted Kremenek1b9df4c2008-03-14 18:14:50 +0000307
Ted Kremenek4dc41cc2008-03-31 18:26:32 +0000308 EmitWarning(Diag, PD, SrcMgr,
Ted Kremenekdd598112008-04-02 07:05:46 +0000309 CS->msg_expr_undef_arg_begin(),
310 CS->msg_expr_undef_arg_end(),
Ted Kremenekdbfe41a2008-03-25 16:40:05 +0000311 "Pass-by-value argument in message expression is undefined.");
312
Ted Kremenek4dc41cc2008-03-31 18:26:32 +0000313 EmitWarning(Diag, PD, SrcMgr,
Ted Kremenekdd598112008-04-02 07:05:46 +0000314 CS->undef_receivers_begin(),
315 CS->undef_receivers_end(),
Ted Kremenekdbfe41a2008-03-25 16:40:05 +0000316 "Receiver in message expression is an uninitialized value.");
Ted Kremenek02737ed2008-03-31 15:02:58 +0000317
Ted Kremenek4dc41cc2008-03-31 18:26:32 +0000318 EmitWarning(Diag, PD, SrcMgr,
Ted Kremenekdd598112008-04-02 07:05:46 +0000319 CS->ret_stackaddr_begin(),
320 CS->ret_stackaddr_end(),
Ted Kremenek02737ed2008-03-31 15:02:58 +0000321 "Address of stack-allocated variable returned.");
Ted Kremenekdbfe41a2008-03-25 16:40:05 +0000322
Ted Kremeneke5d5c202008-03-27 21:15:17 +0000323 FoundationCheck.get()->ReportResults(Diag);
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000324#ifndef NDEBUG
Ted Kremenekdd598112008-04-02 07:05:46 +0000325 if (Visualize) CS->ViewGraph(TrimGraph);
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000326#endif
327
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000328 return Eng.getGraph().size();
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000329}
330
Ted Kremeneke01c9872008-02-14 22:36:46 +0000331} // end clang namespace
332
Ted Kremenekd59cccc2008-02-14 18:28:23 +0000333//===----------------------------------------------------------------------===//
334// Transfer function for Casts.
335//===----------------------------------------------------------------------===//
336
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000337RVal GRSimpleVals::EvalCast(GRExprEngine& Eng, NonLVal X, QualType T) {
Ted Kremenek692416c2008-02-18 22:57:02 +0000338
Ted Kremenekd59cccc2008-02-14 18:28:23 +0000339 if (!isa<nonlval::ConcreteInt>(X))
340 return UnknownVal();
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000341
342 BasicValueFactory& BasicVals = Eng.getBasicVals();
Ted Kremenekd59cccc2008-02-14 18:28:23 +0000343
344 llvm::APSInt V = cast<nonlval::ConcreteInt>(X).getValue();
Ted Kremenek1b9df4c2008-03-14 18:14:50 +0000345 V.setIsUnsigned(T->isUnsignedIntegerType() || T->isPointerType()
346 || T->isObjCQualifiedIdType());
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000347 V.extOrTrunc(Eng.getContext().getTypeSize(T));
Ted Kremenekd59cccc2008-02-14 18:28:23 +0000348
Ted Kremenek9ef1ec92008-02-21 18:43:30 +0000349 if (T->isPointerType())
Ted Kremenek240f1f02008-03-07 20:13:31 +0000350 return lval::ConcreteInt(BasicVals.getValue(V));
Ted Kremenekd59cccc2008-02-14 18:28:23 +0000351 else
Ted Kremenek240f1f02008-03-07 20:13:31 +0000352 return nonlval::ConcreteInt(BasicVals.getValue(V));
Ted Kremenekd59cccc2008-02-14 18:28:23 +0000353}
354
355// Casts.
356
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000357RVal GRSimpleVals::EvalCast(GRExprEngine& Eng, LVal X, QualType T) {
Ted Kremenek692416c2008-02-18 22:57:02 +0000358
Ted Kremenek1b9df4c2008-03-14 18:14:50 +0000359 if (T->isPointerType() || T->isReferenceType() || T->isObjCQualifiedIdType())
Ted Kremenekd59cccc2008-02-14 18:28:23 +0000360 return X;
361
Ted Kremenek9ef1ec92008-02-21 18:43:30 +0000362 assert (T->isIntegerType());
Ted Kremenekd59cccc2008-02-14 18:28:23 +0000363
364 if (!isa<lval::ConcreteInt>(X))
365 return UnknownVal();
366
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000367 BasicValueFactory& BasicVals = Eng.getBasicVals();
368
Ted Kremenekd59cccc2008-02-14 18:28:23 +0000369 llvm::APSInt V = cast<lval::ConcreteInt>(X).getValue();
Ted Kremenekd59cccc2008-02-14 18:28:23 +0000370 V.setIsUnsigned(T->isUnsignedIntegerType() || T->isPointerType());
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000371 V.extOrTrunc(Eng.getContext().getTypeSize(T));
Ted Kremenekd59cccc2008-02-14 18:28:23 +0000372
Ted Kremenek240f1f02008-03-07 20:13:31 +0000373 return nonlval::ConcreteInt(BasicVals.getValue(V));
Ted Kremenekc3f261d2008-02-14 18:40:24 +0000374}
375
376// Unary operators.
377
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000378RVal GRSimpleVals::EvalMinus(GRExprEngine& Eng, UnaryOperator* U, NonLVal X){
Ted Kremenek692416c2008-02-18 22:57:02 +0000379
Ted Kremenekc3f261d2008-02-14 18:40:24 +0000380 switch (X.getSubKind()) {
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000381
Ted Kremenekc3f261d2008-02-14 18:40:24 +0000382 case nonlval::ConcreteIntKind:
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000383 return cast<nonlval::ConcreteInt>(X).EvalMinus(Eng.getBasicVals(), U);
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000384
Ted Kremenekc3f261d2008-02-14 18:40:24 +0000385 default:
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000386 return UnknownVal();
Ted Kremenekc3f261d2008-02-14 18:40:24 +0000387 }
388}
389
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000390RVal GRSimpleVals::EvalComplement(GRExprEngine& Eng, NonLVal X) {
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000391
Ted Kremenek90e42032008-02-20 04:12:31 +0000392 switch (X.getSubKind()) {
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000393
Ted Kremenekc3f261d2008-02-14 18:40:24 +0000394 case nonlval::ConcreteIntKind:
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000395 return cast<nonlval::ConcreteInt>(X).EvalComplement(Eng.getBasicVals());
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000396
Ted Kremenekc3f261d2008-02-14 18:40:24 +0000397 default:
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000398 return UnknownVal();
Ted Kremenekc3f261d2008-02-14 18:40:24 +0000399 }
400}
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000401
402// Binary operators.
403
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000404RVal GRSimpleVals::EvalBinOp(GRExprEngine& Eng, BinaryOperator::Opcode Op,
405 NonLVal L, NonLVal R) {
406
407 BasicValueFactory& BasicVals = Eng.getBasicVals();
408
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000409 while (1) {
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000410
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000411 switch (L.getSubKind()) {
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000412 default:
Ted Kremenek9258a642008-02-21 19:10:12 +0000413 return UnknownVal();
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000414
415 case nonlval::ConcreteIntKind:
416
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000417 if (isa<nonlval::ConcreteInt>(R)) {
418 const nonlval::ConcreteInt& L_CI = cast<nonlval::ConcreteInt>(L);
419 const nonlval::ConcreteInt& R_CI = cast<nonlval::ConcreteInt>(R);
Ted Kremenek240f1f02008-03-07 20:13:31 +0000420 return L_CI.EvalBinOp(BasicVals, Op, R_CI);
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000421 }
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000422 else {
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000423 NonLVal tmp = R;
424 R = L;
425 L = tmp;
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000426 continue;
427 }
428
429 case nonlval::SymbolValKind: {
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000430
431 if (isa<nonlval::ConcreteInt>(R)) {
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000432 const SymIntConstraint& C =
Ted Kremenek240f1f02008-03-07 20:13:31 +0000433 BasicVals.getConstraint(cast<nonlval::SymbolVal>(L).getSymbol(), Op,
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000434 cast<nonlval::ConcreteInt>(R).getValue());
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000435
436 return nonlval::SymIntConstraintVal(C);
437 }
438 else
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000439 return UnknownVal();
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000440 }
441 }
442 }
443}
444
Ted Kremenekb640b3b2008-02-15 00:52:26 +0000445
Ted Kremenekc6fbdcd2008-02-15 23:15:23 +0000446// Binary Operators (except assignments and comma).
447
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000448RVal GRSimpleVals::EvalBinOp(GRExprEngine& Eng, BinaryOperator::Opcode Op,
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000449 LVal L, LVal R) {
Ted Kremenek692416c2008-02-18 22:57:02 +0000450
Ted Kremenekc6fbdcd2008-02-15 23:15:23 +0000451 switch (Op) {
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000452
Ted Kremenekc6fbdcd2008-02-15 23:15:23 +0000453 default:
454 return UnknownVal();
455
456 case BinaryOperator::EQ:
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000457 return EvalEQ(Eng, L, R);
Ted Kremenekc6fbdcd2008-02-15 23:15:23 +0000458
459 case BinaryOperator::NE:
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000460 return EvalNE(Eng, L, R);
Ted Kremenekc6fbdcd2008-02-15 23:15:23 +0000461 }
462}
463
Ted Kremenekb640b3b2008-02-15 00:52:26 +0000464// Pointer arithmetic.
465
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000466RVal GRSimpleVals::EvalBinOp(GRExprEngine& Eng, BinaryOperator::Opcode Op,
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000467 LVal L, NonLVal R) {
468 return UnknownVal();
Ted Kremenekb640b3b2008-02-15 00:52:26 +0000469}
470
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000471// Equality operators for LVals.
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000472
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000473RVal GRSimpleVals::EvalEQ(GRExprEngine& Eng, LVal L, LVal R) {
474
475 BasicValueFactory& BasicVals = Eng.getBasicVals();
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000476
477 switch (L.getSubKind()) {
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000478
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000479 default:
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000480 assert(false && "EQ not implemented for this LVal.");
481 return UnknownVal();
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000482
483 case lval::ConcreteIntKind:
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000484
485 if (isa<lval::ConcreteInt>(R)) {
486 bool b = cast<lval::ConcreteInt>(L).getValue() ==
487 cast<lval::ConcreteInt>(R).getValue();
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000488
Ted Kremenek240f1f02008-03-07 20:13:31 +0000489 return NonLVal::MakeIntTruthVal(BasicVals, b);
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000490 }
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000491 else if (isa<lval::SymbolVal>(R)) {
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000492
493 const SymIntConstraint& C =
Ted Kremenek240f1f02008-03-07 20:13:31 +0000494 BasicVals.getConstraint(cast<lval::SymbolVal>(R).getSymbol(),
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000495 BinaryOperator::EQ,
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000496 cast<lval::ConcreteInt>(L).getValue());
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000497
498 return nonlval::SymIntConstraintVal(C);
499 }
500
501 break;
502
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000503 case lval::SymbolValKind: {
504
505 if (isa<lval::ConcreteInt>(R)) {
506 const SymIntConstraint& C =
Ted Kremenek240f1f02008-03-07 20:13:31 +0000507 BasicVals.getConstraint(cast<lval::SymbolVal>(L).getSymbol(),
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000508 BinaryOperator::EQ,
509 cast<lval::ConcreteInt>(R).getValue());
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000510
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000511 return nonlval::SymIntConstraintVal(C);
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000512 }
513
Ted Kremenekf700df22008-02-22 18:41:59 +0000514 // FIXME: Implement == for lval Symbols. This is mainly useful
515 // in iterator loops when traversing a buffer, e.g. while(z != zTerm).
516 // Since this is not useful for many checkers we'll punt on this for
517 // now.
518
519 return UnknownVal();
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000520 }
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000521
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000522 case lval::DeclValKind:
Ted Kremenekdc3936b2008-02-22 00:54:56 +0000523 case lval::FuncValKind:
524 case lval::GotoLabelKind:
Ted Kremenek240f1f02008-03-07 20:13:31 +0000525 return NonLVal::MakeIntTruthVal(BasicVals, L == R);
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000526 }
527
Ted Kremenek240f1f02008-03-07 20:13:31 +0000528 return NonLVal::MakeIntTruthVal(BasicVals, false);
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000529}
530
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000531RVal GRSimpleVals::EvalNE(GRExprEngine& Eng, LVal L, LVal R) {
Ted Kremenek692416c2008-02-18 22:57:02 +0000532
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000533 BasicValueFactory& BasicVals = Eng.getBasicVals();
534
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000535 switch (L.getSubKind()) {
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000536
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000537 default:
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000538 assert(false && "NE not implemented for this LVal.");
539 return UnknownVal();
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000540
541 case lval::ConcreteIntKind:
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000542
543 if (isa<lval::ConcreteInt>(R)) {
544 bool b = cast<lval::ConcreteInt>(L).getValue() !=
545 cast<lval::ConcreteInt>(R).getValue();
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000546
Ted Kremenek240f1f02008-03-07 20:13:31 +0000547 return NonLVal::MakeIntTruthVal(BasicVals, b);
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000548 }
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000549 else if (isa<lval::SymbolVal>(R)) {
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000550 const SymIntConstraint& C =
Ted Kremenek240f1f02008-03-07 20:13:31 +0000551 BasicVals.getConstraint(cast<lval::SymbolVal>(R).getSymbol(),
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000552 BinaryOperator::NE,
553 cast<lval::ConcreteInt>(L).getValue());
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000554
555 return nonlval::SymIntConstraintVal(C);
556 }
557
558 break;
559
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000560 case lval::SymbolValKind: {
561 if (isa<lval::ConcreteInt>(R)) {
562 const SymIntConstraint& C =
Ted Kremenek240f1f02008-03-07 20:13:31 +0000563 BasicVals.getConstraint(cast<lval::SymbolVal>(L).getSymbol(),
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000564 BinaryOperator::NE,
565 cast<lval::ConcreteInt>(R).getValue());
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000566
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000567 return nonlval::SymIntConstraintVal(C);
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000568 }
569
Ted Kremenekf700df22008-02-22 18:41:59 +0000570 // FIXME: Implement != for lval Symbols. This is mainly useful
571 // in iterator loops when traversing a buffer, e.g. while(z != zTerm).
572 // Since this is not useful for many checkers we'll punt on this for
573 // now.
574
575 return UnknownVal();
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000576
577 break;
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000578 }
579
580 case lval::DeclValKind:
Ted Kremenekdc3936b2008-02-22 00:54:56 +0000581 case lval::FuncValKind:
582 case lval::GotoLabelKind:
Ted Kremenek240f1f02008-03-07 20:13:31 +0000583 return NonLVal::MakeIntTruthVal(BasicVals, L != R);
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000584 }
585
Ted Kremenek240f1f02008-03-07 20:13:31 +0000586 return NonLVal::MakeIntTruthVal(BasicVals, true);
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000587}
Ted Kremenek06747692008-02-26 23:04:29 +0000588
589//===----------------------------------------------------------------------===//
590// Transfer function for Function Calls.
591//===----------------------------------------------------------------------===//
592
Ted Kremenek330dddd2008-03-05 00:33:14 +0000593void GRSimpleVals::EvalCall(ExplodedNodeSet<ValueState>& Dst,
Ted Kremenek00a3a5f2008-03-12 01:21:45 +0000594 GRExprEngine& Eng,
Ted Kremenek330dddd2008-03-05 00:33:14 +0000595 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek330dddd2008-03-05 00:33:14 +0000596 CallExpr* CE, LVal L,
597 ExplodedNode<ValueState>* Pred) {
598
Ted Kremenekf923a912008-03-12 21:04:07 +0000599 ValueStateManager& StateMgr = Eng.getStateManager();
600 ValueState* St = Builder.GetState(Pred);
Ted Kremenek06747692008-02-26 23:04:29 +0000601
602 // Invalidate all arguments passed in by reference (LVals).
603
604 for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end();
605 I != E; ++I) {
606
Ted Kremenekf923a912008-03-12 21:04:07 +0000607 RVal V = StateMgr.GetRVal(St, *I);
Ted Kremenek06747692008-02-26 23:04:29 +0000608
609 if (isa<LVal>(V))
Ted Kremenekf923a912008-03-12 21:04:07 +0000610 St = StateMgr.SetRVal(St, cast<LVal>(V), UnknownVal());
Ted Kremenek06747692008-02-26 23:04:29 +0000611 }
Ted Kremenekf923a912008-03-12 21:04:07 +0000612
613 // Make up a symbol for the return value of this function.
614
615 if (CE->getType() != Eng.getContext().VoidTy) {
616 unsigned Count = Builder.getCurrentBlockCount();
Ted Kremenek361fa8e2008-03-12 21:45:47 +0000617 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(CE, Count);
Ted Kremenekf923a912008-03-12 21:04:07 +0000618
619 RVal X = CE->getType()->isPointerType()
620 ? cast<RVal>(lval::SymbolVal(Sym))
621 : cast<RVal>(nonlval::SymbolVal(Sym));
622
623 St = StateMgr.SetRVal(St, CE, X, Eng.getCFG().isBlkExpr(CE), false);
624 }
Ted Kremenek330dddd2008-03-05 00:33:14 +0000625
Ted Kremenek0e561a32008-03-21 21:30:14 +0000626 Builder.MakeNode(Dst, CE, Pred, St);
Ted Kremenek06747692008-02-26 23:04:29 +0000627}