blob: 9a0d63e808b99c4851162da65d8132a864641fc8 [file] [log] [blame]
Ted Kremenek25a484d2008-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 Greif2224fcb2008-03-06 10:40:09 +000010// This file defines GRSimpleVals, a sub-class of GRTransferFuncs that
Ted Kremenek25a484d2008-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 Kremenek7a681942008-03-27 17:17:22 +000017#include "BasicObjCFoundationChecks.h"
Ted Kremenek9f6b1612008-02-27 06:07:00 +000018#include "clang/Analysis/PathSensitive/ValueState.h"
Ted Kremenekdd0126b2008-03-31 18:26:32 +000019#include "clang/Analysis/PathDiagnostic.h"
Ted Kremenek9cac66e2008-02-27 17:56:16 +000020#include <sstream>
Ted Kremenek25a484d2008-02-14 18:28:23 +000021
22using namespace clang;
23
Ted Kremenekd1d4d752008-04-02 07:05:46 +000024//===----------------------------------------------------------------------===//
25// Bug Descriptions.
26//===----------------------------------------------------------------------===//
Ted Kremenekf567a822008-02-26 21:31:18 +000027
Ted Kremenekd1d4d752008-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 Kremenekf567a822008-02-26 21:31:18 +000058template <typename ITERATOR>
Ted Kremenek139bf402008-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 Kremenek2f0c0e12008-03-14 18:14:50 +000070static inline ProgramPoint GetLocation(ITERATOR I) {
71 return (*I)->getLocation();
Ted Kremenek4aa57592008-03-04 00:42:54 +000072}
73
74template <>
Ted Kremenek139bf402008-04-02 05:15:22 +000075static inline ProgramPoint GetLocation(GRExprEngine::undef_arg_iterator I) {
Ted Kremenek2f0c0e12008-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 Kremenek4aa57592008-03-04 00:42:54 +000089}
Ted Kremenek139bf402008-04-02 05:15:22 +000090
91//===----------------------------------------------------------------------===//
92// Pathless Warnings
93//===----------------------------------------------------------------------===//
94
Ted Kremenek4aa57592008-03-04 00:42:54 +000095template <typename ITERATOR>
Ted Kremenekdd0126b2008-03-31 18:26:32 +000096static void EmitDiag(Diagnostic& Diag, PathDiagnosticClient* PD,
97 SourceManager& SrcMgr,
98unsigned ErrorDiag, ITERATOR I) {
Ted Kremenek4aa57592008-03-04 00:42:54 +000099
Ted Kremenek2f0c0e12008-03-14 18:14:50 +0000100 Stmt* S = GetStmt(GetLocation(I));
Ted Kremenek8088f2c2008-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 Kremenek4aa57592008-03-04 00:42:54 +0000104}
105
106
107template <>
Ted Kremenekdd0126b2008-03-31 18:26:32 +0000108static void EmitDiag(Diagnostic& Diag, PathDiagnosticClient* PD,
109 SourceManager& SrcMgr, unsigned ErrorDiag,
110 GRExprEngine::undef_arg_iterator I) {
Ted Kremenek4aa57592008-03-04 00:42:54 +0000111
Ted Kremenek2f0c0e12008-03-14 18:14:50 +0000112 Stmt* S1 = GetStmt(GetLocation(I));
Ted Kremenek4aa57592008-03-04 00:42:54 +0000113 Expr* E2 = cast<Expr>(I->second);
114
Ted Kremenek2f0c0e12008-03-14 18:14:50 +0000115 SourceLocation Loc = S1->getLocStart();
Ted Kremenek4aa57592008-03-04 00:42:54 +0000116 SourceRange R = E2->getSourceRange();
Ted Kremenekdd0126b2008-03-31 18:26:32 +0000117 Diag.Report(PD, FullSourceLoc(Loc, SrcMgr), ErrorDiag, 0, 0, &R, 1);
Ted Kremenek4aa57592008-03-04 00:42:54 +0000118}
119
120template <typename ITERATOR>
Ted Kremenekd1d4d752008-04-02 07:05:46 +0000121static void EmitWarning(Diagnostic& Diag, PathDiagnosticClient* PD,
122 SourceManager& SrcMgr,
123 ITERATOR I, ITERATOR E, const char* msg) {
Ted Kremenekf567a822008-02-26 21:31:18 +0000124
Ted Kremenek9cac66e2008-02-27 17:56:16 +0000125 std::ostringstream Out;
Ted Kremenek139bf402008-04-02 05:15:22 +0000126 std::string Str(msg);
Ted Kremenek0102b5b2008-03-31 20:42:43 +0000127
128 if (!PD) {
129 Out << "[CHECKER] " << msg;
Ted Kremenek138d8852008-04-01 22:35:58 +0000130 Str = Out.str();
131 msg = Str.c_str();
Ted Kremenek0102b5b2008-03-31 20:42:43 +0000132 }
Ted Kremenek9cac66e2008-02-27 17:56:16 +0000133
Ted Kremenek717bd7d2008-02-27 20:47:56 +0000134 bool isFirst = true;
Ted Kremenek38ad0202008-03-15 07:58:36 +0000135 unsigned ErrorDiag = 0;
Ted Kremenek4aa57592008-03-04 00:42:54 +0000136 llvm::SmallPtrSet<void*,10> CachedErrors;
Ted Kremenekf567a822008-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 Kremenek3f3a30b2008-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 Kremenek4aa57592008-03-04 00:42:54 +0000149 void* p = GetLocation(I).getRawData();
Ted Kremenek3f3a30b2008-02-28 20:38:16 +0000150
151 if (CachedErrors.count(p))
152 continue;
153
154 CachedErrors.insert(p);
155 }
Ted Kremenek4aa57592008-03-04 00:42:54 +0000156
Ted Kremenekd1d4d752008-04-02 07:05:46 +0000157 EmitDiag(Diag, PD, SrcMgr, ErrorDiag, I);
Ted Kremenekf567a822008-02-26 21:31:18 +0000158 }
159}
Ted Kremenek07baa252008-02-21 18:02:17 +0000160
Ted Kremenek139bf402008-04-02 05:15:22 +0000161//===----------------------------------------------------------------------===//
Ted Kremenekd1d4d752008-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 Kremenek139bf402008-04-02 05:15:22 +0000242// Analysis Driver.
243//===----------------------------------------------------------------------===//
244
Ted Kremenekd1d4d752008-04-02 07:05:46 +0000245namespace clang {
246
Ted Kremenek5d257d42008-03-14 17:31:00 +0000247unsigned RunGRSimpleVals(CFG& cfg, Decl& CD, ASTContext& Ctx,
Ted Kremenekd1d4d752008-04-02 07:05:46 +0000248 Diagnostic& Diag, PathDiagnosticClient* PD,
249 bool Visualize, bool TrimGraph) {
Ted Kremenek07baa252008-02-21 18:02:17 +0000250
Ted Kremenek5d257d42008-03-14 17:31:00 +0000251 GRCoreEngine<GRExprEngine> Eng(cfg, CD, Ctx);
Ted Kremenekd1d4d752008-04-02 07:05:46 +0000252 GRExprEngine* CS = &Eng.getCheckerState();
Ted Kremenek7a681942008-03-27 17:17:22 +0000253
254 // Set base transfer functions.
Ted Kremenek07baa252008-02-21 18:02:17 +0000255 GRSimpleVals GRSV;
Ted Kremenekd1d4d752008-04-02 07:05:46 +0000256 CS->setTransferFunctions(GRSV);
Ted Kremenek07baa252008-02-21 18:02:17 +0000257
Ted Kremenek7a681942008-03-27 17:17:22 +0000258 // Add extra checkers.
259 llvm::OwningPtr<GRSimpleAPICheck> FoundationCheck(
Ted Kremenekd1d4d752008-04-02 07:05:46 +0000260 CreateBasicObjCFoundationChecks(Ctx, &CS->getStateManager()));
Ted Kremenek7a681942008-03-27 17:17:22 +0000261
Ted Kremenekd1d4d752008-04-02 07:05:46 +0000262 CS->AddObjCMessageExprCheck(FoundationCheck.get());
Ted Kremenek7a681942008-03-27 17:17:22 +0000263
Ted Kremenek07baa252008-02-21 18:02:17 +0000264 // Execute the worklist algorithm.
Ted Kremenekdd0126b2008-03-31 18:26:32 +0000265 Eng.ExecuteWorkList(120000);
Ted Kremenek07baa252008-02-21 18:02:17 +0000266
Ted Kremenekf567a822008-02-26 21:31:18 +0000267 SourceManager& SrcMgr = Ctx.getSourceManager();
268
Ted Kremenekd1d4d752008-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 Kremenekf567a822008-02-26 21:31:18 +0000277
Ted Kremenekdd0126b2008-03-31 18:26:32 +0000278 EmitWarning(Diag, PD, SrcMgr,
Ted Kremenekd1d4d752008-04-02 07:05:46 +0000279 CS->undef_derefs_begin(),
280 CS->undef_derefs_end(),
Ted Kremenekb31af242008-02-28 09:25:22 +0000281 "Dereference of undefined value.");
Ted Kremenekf567a822008-02-26 21:31:18 +0000282
Ted Kremenekdd0126b2008-03-31 18:26:32 +0000283 EmitWarning(Diag, PD, SrcMgr,
Ted Kremenekd1d4d752008-04-02 07:05:46 +0000284 CS->undef_branches_begin(),
285 CS->undef_branches_end(),
Ted Kremenekd58da2b2008-03-25 16:40:05 +0000286 "Branch condition evaluates to an uninitialized value.");
Ted Kremenekf567a822008-02-26 21:31:18 +0000287
Ted Kremenekdd0126b2008-03-31 18:26:32 +0000288 EmitWarning(Diag, PD, SrcMgr,
Ted Kremenekd1d4d752008-04-02 07:05:46 +0000289 CS->explicit_bad_divides_begin(),
290 CS->explicit_bad_divides_end(),
Ted Kremenekb31af242008-02-28 09:25:22 +0000291 "Division by zero/undefined value.");
Ted Kremenekc2d07202008-02-28 20:32:03 +0000292
Ted Kremenekdd0126b2008-03-31 18:26:32 +0000293 EmitWarning(Diag, PD, SrcMgr,
Ted Kremenekd1d4d752008-04-02 07:05:46 +0000294 CS->undef_results_begin(),
295 CS->undef_results_end(),
Ted Kremenekc2d07202008-02-28 20:32:03 +0000296 "Result of operation is undefined.");
Ted Kremenek43863eb2008-02-29 23:14:48 +0000297
Ted Kremenekdd0126b2008-03-31 18:26:32 +0000298 EmitWarning(Diag, PD, SrcMgr,
Ted Kremenekd1d4d752008-04-02 07:05:46 +0000299 CS->bad_calls_begin(),
300 CS->bad_calls_end(),
Ted Kremenek43863eb2008-02-29 23:14:48 +0000301 "Call using a NULL or undefined function pointer value.");
Ted Kremenek9b31f5b2008-02-29 23:53:11 +0000302
Ted Kremenekdd0126b2008-03-31 18:26:32 +0000303 EmitWarning(Diag, PD, SrcMgr,
Ted Kremenekd1d4d752008-04-02 07:05:46 +0000304 CS->undef_arg_begin(),
305 CS->undef_arg_end(),
Ted Kremenekd58da2b2008-03-25 16:40:05 +0000306 "Pass-by-value argument in function is undefined.");
Ted Kremenek2f0c0e12008-03-14 18:14:50 +0000307
Ted Kremenekdd0126b2008-03-31 18:26:32 +0000308 EmitWarning(Diag, PD, SrcMgr,
Ted Kremenekd1d4d752008-04-02 07:05:46 +0000309 CS->msg_expr_undef_arg_begin(),
310 CS->msg_expr_undef_arg_end(),
Ted Kremenekd58da2b2008-03-25 16:40:05 +0000311 "Pass-by-value argument in message expression is undefined.");
312
Ted Kremenekdd0126b2008-03-31 18:26:32 +0000313 EmitWarning(Diag, PD, SrcMgr,
Ted Kremenekd1d4d752008-04-02 07:05:46 +0000314 CS->undef_receivers_begin(),
315 CS->undef_receivers_end(),
Ted Kremenekd58da2b2008-03-25 16:40:05 +0000316 "Receiver in message expression is an uninitialized value.");
Ted Kremenek108048c2008-03-31 15:02:58 +0000317
Ted Kremenekdd0126b2008-03-31 18:26:32 +0000318 EmitWarning(Diag, PD, SrcMgr,
Ted Kremenekd1d4d752008-04-02 07:05:46 +0000319 CS->ret_stackaddr_begin(),
320 CS->ret_stackaddr_end(),
Ted Kremenek108048c2008-03-31 15:02:58 +0000321 "Address of stack-allocated variable returned.");
Ted Kremenekd58da2b2008-03-25 16:40:05 +0000322
Ted Kremenek583c4382008-03-27 21:15:17 +0000323 FoundationCheck.get()->ReportResults(Diag);
Ted Kremenek07baa252008-02-21 18:02:17 +0000324#ifndef NDEBUG
Ted Kremenekd1d4d752008-04-02 07:05:46 +0000325 if (Visualize) CS->ViewGraph(TrimGraph);
Ted Kremenek07baa252008-02-21 18:02:17 +0000326#endif
327
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000328 return Eng.getGraph().size();
Ted Kremenek07baa252008-02-21 18:02:17 +0000329}
330
Ted Kremenek3862eb12008-02-14 22:36:46 +0000331} // end clang namespace
332
Ted Kremenek25a484d2008-02-14 18:28:23 +0000333//===----------------------------------------------------------------------===//
334// Transfer function for Casts.
335//===----------------------------------------------------------------------===//
336
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000337RVal GRSimpleVals::EvalCast(GRExprEngine& Eng, NonLVal X, QualType T) {
Ted Kremenekbc965a62008-02-18 22:57:02 +0000338
Ted Kremenek25a484d2008-02-14 18:28:23 +0000339 if (!isa<nonlval::ConcreteInt>(X))
340 return UnknownVal();
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000341
342 BasicValueFactory& BasicVals = Eng.getBasicVals();
Ted Kremenek25a484d2008-02-14 18:28:23 +0000343
344 llvm::APSInt V = cast<nonlval::ConcreteInt>(X).getValue();
Ted Kremenek2f0c0e12008-03-14 18:14:50 +0000345 V.setIsUnsigned(T->isUnsignedIntegerType() || T->isPointerType()
346 || T->isObjCQualifiedIdType());
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000347 V.extOrTrunc(Eng.getContext().getTypeSize(T));
Ted Kremenek25a484d2008-02-14 18:28:23 +0000348
Ted Kremenek9cfda3f2008-02-21 18:43:30 +0000349 if (T->isPointerType())
Ted Kremenek8ad19872008-03-07 20:13:31 +0000350 return lval::ConcreteInt(BasicVals.getValue(V));
Ted Kremenek25a484d2008-02-14 18:28:23 +0000351 else
Ted Kremenek8ad19872008-03-07 20:13:31 +0000352 return nonlval::ConcreteInt(BasicVals.getValue(V));
Ted Kremenek25a484d2008-02-14 18:28:23 +0000353}
354
355// Casts.
356
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000357RVal GRSimpleVals::EvalCast(GRExprEngine& Eng, LVal X, QualType T) {
Ted Kremenekbc965a62008-02-18 22:57:02 +0000358
Chris Lattnera05f7d22008-04-02 17:45:06 +0000359 if (T->isPointerLikeType() || T->isObjCQualifiedIdType())
Ted Kremenek25a484d2008-02-14 18:28:23 +0000360 return X;
361
Ted Kremenek9cfda3f2008-02-21 18:43:30 +0000362 assert (T->isIntegerType());
Ted Kremenek25a484d2008-02-14 18:28:23 +0000363
364 if (!isa<lval::ConcreteInt>(X))
365 return UnknownVal();
366
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000367 BasicValueFactory& BasicVals = Eng.getBasicVals();
368
Ted Kremenek25a484d2008-02-14 18:28:23 +0000369 llvm::APSInt V = cast<lval::ConcreteInt>(X).getValue();
Ted Kremenek25a484d2008-02-14 18:28:23 +0000370 V.setIsUnsigned(T->isUnsignedIntegerType() || T->isPointerType());
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000371 V.extOrTrunc(Eng.getContext().getTypeSize(T));
Ted Kremenek25a484d2008-02-14 18:28:23 +0000372
Ted Kremenek8ad19872008-03-07 20:13:31 +0000373 return nonlval::ConcreteInt(BasicVals.getValue(V));
Ted Kremenekc9922fd2008-02-14 18:40:24 +0000374}
375
376// Unary operators.
377
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000378RVal GRSimpleVals::EvalMinus(GRExprEngine& Eng, UnaryOperator* U, NonLVal X){
Ted Kremenekbc965a62008-02-18 22:57:02 +0000379
Ted Kremenekc9922fd2008-02-14 18:40:24 +0000380 switch (X.getSubKind()) {
Ted Kremenek07baa252008-02-21 18:02:17 +0000381
Ted Kremenekc9922fd2008-02-14 18:40:24 +0000382 case nonlval::ConcreteIntKind:
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000383 return cast<nonlval::ConcreteInt>(X).EvalMinus(Eng.getBasicVals(), U);
Ted Kremenek07baa252008-02-21 18:02:17 +0000384
Ted Kremenekc9922fd2008-02-14 18:40:24 +0000385 default:
Ted Kremenek07baa252008-02-21 18:02:17 +0000386 return UnknownVal();
Ted Kremenekc9922fd2008-02-14 18:40:24 +0000387 }
388}
389
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000390RVal GRSimpleVals::EvalComplement(GRExprEngine& Eng, NonLVal X) {
Ted Kremenek07baa252008-02-21 18:02:17 +0000391
Ted Kremenek0cd96352008-02-20 04:12:31 +0000392 switch (X.getSubKind()) {
Ted Kremenek07baa252008-02-21 18:02:17 +0000393
Ted Kremenekc9922fd2008-02-14 18:40:24 +0000394 case nonlval::ConcreteIntKind:
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000395 return cast<nonlval::ConcreteInt>(X).EvalComplement(Eng.getBasicVals());
Ted Kremenek07baa252008-02-21 18:02:17 +0000396
Ted Kremenekc9922fd2008-02-14 18:40:24 +0000397 default:
Ted Kremenek07baa252008-02-21 18:02:17 +0000398 return UnknownVal();
Ted Kremenekc9922fd2008-02-14 18:40:24 +0000399 }
400}
Ted Kremenekb1934132008-02-14 19:37:24 +0000401
402// Binary operators.
403
Ted Kremenekce3ed1e2008-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 Kremenek07baa252008-02-21 18:02:17 +0000409 while (1) {
Ted Kremenekb1934132008-02-14 19:37:24 +0000410
Ted Kremenek07baa252008-02-21 18:02:17 +0000411 switch (L.getSubKind()) {
Ted Kremenekb1934132008-02-14 19:37:24 +0000412 default:
Ted Kremenekde89ec02008-02-21 19:10:12 +0000413 return UnknownVal();
Ted Kremenekb1934132008-02-14 19:37:24 +0000414
415 case nonlval::ConcreteIntKind:
416
Ted Kremenek07baa252008-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 Kremenek8ad19872008-03-07 20:13:31 +0000420 return L_CI.EvalBinOp(BasicVals, Op, R_CI);
Ted Kremenekb1934132008-02-14 19:37:24 +0000421 }
Ted Kremenekb1934132008-02-14 19:37:24 +0000422 else {
Ted Kremenek07baa252008-02-21 18:02:17 +0000423 NonLVal tmp = R;
424 R = L;
425 L = tmp;
Ted Kremenekb1934132008-02-14 19:37:24 +0000426 continue;
427 }
428
429 case nonlval::SymbolValKind: {
Ted Kremenek07baa252008-02-21 18:02:17 +0000430
431 if (isa<nonlval::ConcreteInt>(R)) {
Ted Kremenekb1934132008-02-14 19:37:24 +0000432 const SymIntConstraint& C =
Ted Kremenek8ad19872008-03-07 20:13:31 +0000433 BasicVals.getConstraint(cast<nonlval::SymbolVal>(L).getSymbol(), Op,
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000434 cast<nonlval::ConcreteInt>(R).getValue());
Ted Kremenekb1934132008-02-14 19:37:24 +0000435
436 return nonlval::SymIntConstraintVal(C);
437 }
438 else
Ted Kremenek07baa252008-02-21 18:02:17 +0000439 return UnknownVal();
Ted Kremenekb1934132008-02-14 19:37:24 +0000440 }
441 }
442 }
443}
444
Ted Kremenek775e0d82008-02-15 00:52:26 +0000445
Ted Kremenek521d9722008-02-15 23:15:23 +0000446// Binary Operators (except assignments and comma).
447
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000448RVal GRSimpleVals::EvalBinOp(GRExprEngine& Eng, BinaryOperator::Opcode Op,
Ted Kremenek07baa252008-02-21 18:02:17 +0000449 LVal L, LVal R) {
Ted Kremenekbc965a62008-02-18 22:57:02 +0000450
Ted Kremenek521d9722008-02-15 23:15:23 +0000451 switch (Op) {
Ted Kremenek07baa252008-02-21 18:02:17 +0000452
Ted Kremenek521d9722008-02-15 23:15:23 +0000453 default:
454 return UnknownVal();
455
456 case BinaryOperator::EQ:
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000457 return EvalEQ(Eng, L, R);
Ted Kremenek521d9722008-02-15 23:15:23 +0000458
459 case BinaryOperator::NE:
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000460 return EvalNE(Eng, L, R);
Ted Kremenek521d9722008-02-15 23:15:23 +0000461 }
462}
463
Ted Kremenek775e0d82008-02-15 00:52:26 +0000464// Pointer arithmetic.
465
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000466RVal GRSimpleVals::EvalBinOp(GRExprEngine& Eng, BinaryOperator::Opcode Op,
Ted Kremenek07baa252008-02-21 18:02:17 +0000467 LVal L, NonLVal R) {
468 return UnknownVal();
Ted Kremenek775e0d82008-02-15 00:52:26 +0000469}
470
Ted Kremenek07baa252008-02-21 18:02:17 +0000471// Equality operators for LVals.
Ted Kremenekb1934132008-02-14 19:37:24 +0000472
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000473RVal GRSimpleVals::EvalEQ(GRExprEngine& Eng, LVal L, LVal R) {
474
475 BasicValueFactory& BasicVals = Eng.getBasicVals();
Ted Kremenek07baa252008-02-21 18:02:17 +0000476
477 switch (L.getSubKind()) {
Ted Kremenekb1934132008-02-14 19:37:24 +0000478
Ted Kremenekb1934132008-02-14 19:37:24 +0000479 default:
Ted Kremenek07baa252008-02-21 18:02:17 +0000480 assert(false && "EQ not implemented for this LVal.");
481 return UnknownVal();
Ted Kremenekb1934132008-02-14 19:37:24 +0000482
483 case lval::ConcreteIntKind:
Ted Kremenek07baa252008-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 Kremenekb1934132008-02-14 19:37:24 +0000488
Ted Kremenek8ad19872008-03-07 20:13:31 +0000489 return NonLVal::MakeIntTruthVal(BasicVals, b);
Ted Kremenekb1934132008-02-14 19:37:24 +0000490 }
Ted Kremenek07baa252008-02-21 18:02:17 +0000491 else if (isa<lval::SymbolVal>(R)) {
Ted Kremenekb1934132008-02-14 19:37:24 +0000492
493 const SymIntConstraint& C =
Ted Kremenek8ad19872008-03-07 20:13:31 +0000494 BasicVals.getConstraint(cast<lval::SymbolVal>(R).getSymbol(),
Ted Kremenekb1934132008-02-14 19:37:24 +0000495 BinaryOperator::EQ,
Ted Kremenek07baa252008-02-21 18:02:17 +0000496 cast<lval::ConcreteInt>(L).getValue());
Ted Kremenekb1934132008-02-14 19:37:24 +0000497
498 return nonlval::SymIntConstraintVal(C);
499 }
500
501 break;
502
Ted Kremenek07baa252008-02-21 18:02:17 +0000503 case lval::SymbolValKind: {
504
505 if (isa<lval::ConcreteInt>(R)) {
506 const SymIntConstraint& C =
Ted Kremenek8ad19872008-03-07 20:13:31 +0000507 BasicVals.getConstraint(cast<lval::SymbolVal>(L).getSymbol(),
Ted Kremenek07baa252008-02-21 18:02:17 +0000508 BinaryOperator::EQ,
509 cast<lval::ConcreteInt>(R).getValue());
Ted Kremenekb1934132008-02-14 19:37:24 +0000510
Ted Kremenek07baa252008-02-21 18:02:17 +0000511 return nonlval::SymIntConstraintVal(C);
Ted Kremenekb1934132008-02-14 19:37:24 +0000512 }
513
Ted Kremenekfe944c42008-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 Kremenek07baa252008-02-21 18:02:17 +0000520 }
Ted Kremenekb1934132008-02-14 19:37:24 +0000521
Ted Kremenek07baa252008-02-21 18:02:17 +0000522 case lval::DeclValKind:
Ted Kremenek38706192008-02-22 00:54:56 +0000523 case lval::FuncValKind:
524 case lval::GotoLabelKind:
Ted Kremenek8ad19872008-03-07 20:13:31 +0000525 return NonLVal::MakeIntTruthVal(BasicVals, L == R);
Ted Kremenekb1934132008-02-14 19:37:24 +0000526 }
527
Ted Kremenek8ad19872008-03-07 20:13:31 +0000528 return NonLVal::MakeIntTruthVal(BasicVals, false);
Ted Kremenekb1934132008-02-14 19:37:24 +0000529}
530
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000531RVal GRSimpleVals::EvalNE(GRExprEngine& Eng, LVal L, LVal R) {
Ted Kremenekbc965a62008-02-18 22:57:02 +0000532
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000533 BasicValueFactory& BasicVals = Eng.getBasicVals();
534
Ted Kremenek07baa252008-02-21 18:02:17 +0000535 switch (L.getSubKind()) {
Ted Kremenekb1934132008-02-14 19:37:24 +0000536
Ted Kremenekb1934132008-02-14 19:37:24 +0000537 default:
Ted Kremenek07baa252008-02-21 18:02:17 +0000538 assert(false && "NE not implemented for this LVal.");
539 return UnknownVal();
Ted Kremenekb1934132008-02-14 19:37:24 +0000540
541 case lval::ConcreteIntKind:
Ted Kremenek07baa252008-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 Kremenekb1934132008-02-14 19:37:24 +0000546
Ted Kremenek8ad19872008-03-07 20:13:31 +0000547 return NonLVal::MakeIntTruthVal(BasicVals, b);
Ted Kremenekb1934132008-02-14 19:37:24 +0000548 }
Ted Kremenek07baa252008-02-21 18:02:17 +0000549 else if (isa<lval::SymbolVal>(R)) {
Ted Kremenekb1934132008-02-14 19:37:24 +0000550 const SymIntConstraint& C =
Ted Kremenek8ad19872008-03-07 20:13:31 +0000551 BasicVals.getConstraint(cast<lval::SymbolVal>(R).getSymbol(),
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000552 BinaryOperator::NE,
553 cast<lval::ConcreteInt>(L).getValue());
Ted Kremenekb1934132008-02-14 19:37:24 +0000554
555 return nonlval::SymIntConstraintVal(C);
556 }
557
558 break;
559
Ted Kremenek07baa252008-02-21 18:02:17 +0000560 case lval::SymbolValKind: {
561 if (isa<lval::ConcreteInt>(R)) {
562 const SymIntConstraint& C =
Ted Kremenek8ad19872008-03-07 20:13:31 +0000563 BasicVals.getConstraint(cast<lval::SymbolVal>(L).getSymbol(),
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000564 BinaryOperator::NE,
565 cast<lval::ConcreteInt>(R).getValue());
Ted Kremenekb1934132008-02-14 19:37:24 +0000566
Ted Kremenek07baa252008-02-21 18:02:17 +0000567 return nonlval::SymIntConstraintVal(C);
Ted Kremenekb1934132008-02-14 19:37:24 +0000568 }
569
Ted Kremenekfe944c42008-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 Kremenekb1934132008-02-14 19:37:24 +0000576
577 break;
Ted Kremenek07baa252008-02-21 18:02:17 +0000578 }
579
580 case lval::DeclValKind:
Ted Kremenek38706192008-02-22 00:54:56 +0000581 case lval::FuncValKind:
582 case lval::GotoLabelKind:
Ted Kremenek8ad19872008-03-07 20:13:31 +0000583 return NonLVal::MakeIntTruthVal(BasicVals, L != R);
Ted Kremenekb1934132008-02-14 19:37:24 +0000584 }
585
Ted Kremenek8ad19872008-03-07 20:13:31 +0000586 return NonLVal::MakeIntTruthVal(BasicVals, true);
Ted Kremenekb1934132008-02-14 19:37:24 +0000587}
Ted Kremenek348d7852008-02-26 23:04:29 +0000588
589//===----------------------------------------------------------------------===//
590// Transfer function for Function Calls.
591//===----------------------------------------------------------------------===//
592
Ted Kremenek3eea8dd2008-03-05 00:33:14 +0000593void GRSimpleVals::EvalCall(ExplodedNodeSet<ValueState>& Dst,
Ted Kremenekce3ed1e2008-03-12 01:21:45 +0000594 GRExprEngine& Eng,
Ted Kremenek3eea8dd2008-03-05 00:33:14 +0000595 GRStmtNodeBuilder<ValueState>& Builder,
Ted Kremenek3eea8dd2008-03-05 00:33:14 +0000596 CallExpr* CE, LVal L,
597 ExplodedNode<ValueState>* Pred) {
598
Ted Kremenek1a531942008-03-12 21:04:07 +0000599 ValueStateManager& StateMgr = Eng.getStateManager();
600 ValueState* St = Builder.GetState(Pred);
Ted Kremenek348d7852008-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 Kremenek1a531942008-03-12 21:04:07 +0000607 RVal V = StateMgr.GetRVal(St, *I);
Ted Kremenek348d7852008-02-26 23:04:29 +0000608
609 if (isa<LVal>(V))
Ted Kremenek1a531942008-03-12 21:04:07 +0000610 St = StateMgr.SetRVal(St, cast<LVal>(V), UnknownVal());
Ted Kremenek348d7852008-02-26 23:04:29 +0000611 }
Ted Kremenek1a531942008-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 Kremenekd4676512008-03-12 21:45:47 +0000617 SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(CE, Count);
Ted Kremenek1a531942008-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 Kremenek3eea8dd2008-03-05 00:33:14 +0000625
Ted Kremenekf10f2882008-03-21 21:30:14 +0000626 Builder.MakeNode(Dst, CE, Pred, St);
Ted Kremenek348d7852008-02-26 23:04:29 +0000627}