blob: 549aa0bb4ff3334f0420a1136f0584969ac30fef [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 Kremenekd87a3212008-02-26 21:31:18 +000022
23template <typename ITERATOR>
24static void EmitWarning(Diagnostic& Diag, SourceManager& SrcMgr,
25 ITERATOR I, ITERATOR E, const char* msg) {
26
27 bool isFirst;
28 unsigned ErrorDiag;
29
30 for (; I != E; ++I) {
31
32 if (isFirst) {
33 isFirst = false;
34 ErrorDiag = Diag.getCustomDiagID(Diagnostic::Warning, msg);
35 }
36
37 const PostStmt& L = cast<PostStmt>((*I)->getLocation());
38 Expr* Exp = cast<Expr>(L.getStmt());
39
40 Diag.Report(FullSourceLoc(Exp->getExprLoc(), SrcMgr), ErrorDiag);
41 }
42}
Ted Kremenekaa1c4e52008-02-21 18:02:17 +000043
44unsigned RunGRSimpleVals(CFG& cfg, FunctionDecl& FD, ASTContext& Ctx,
45 Diagnostic& Diag, bool Visualize) {
46
47 if (Diag.hasErrorOccurred())
48 return 0;
49
50 GRCoreEngine<GRExprEngine> Engine(cfg, FD, Ctx);
51 GRExprEngine* CheckerState = &Engine.getCheckerState();
52 GRSimpleVals GRSV;
53 CheckerState->setTransferFunctions(GRSV);
54
55 // Execute the worklist algorithm.
Ted Kremenekd87a3212008-02-26 21:31:18 +000056 Engine.ExecuteWorkList(20000);
Ted Kremenekaa1c4e52008-02-21 18:02:17 +000057
Ted Kremenekd87a3212008-02-26 21:31:18 +000058 SourceManager& SrcMgr = Ctx.getSourceManager();
59
60 EmitWarning(Diag, SrcMgr,
61 CheckerState->null_derefs_begin(),
62 CheckerState->null_derefs_end(),
63 "NULL pointer is dereferenced after it is checked for NULL.");
64
65 EmitWarning(Diag, SrcMgr,
66 CheckerState->uninit_derefs_begin(),
67 CheckerState->uninit_derefs_end(),
68 "Dereference of uninitialized value.");
69
70 EmitWarning(Diag, SrcMgr,
71 CheckerState->uninit_derefs_begin(),
72 CheckerState->uninit_derefs_end(),
73 "Dereference of uninitialized value.");
74
75 EmitWarning(Diag, SrcMgr,
76 CheckerState->bad_divides_begin(),
77 CheckerState->bad_divides_end(),
78 "Division by zero/uninitialized value.");
Ted Kremenekaa1c4e52008-02-21 18:02:17 +000079
80#ifndef NDEBUG
81 if (Visualize) CheckerState->ViewGraph();
82#endif
83
84 return Engine.getGraph().size();
85}
86
Ted Kremeneke01c9872008-02-14 22:36:46 +000087} // end clang namespace
88
Ted Kremenekd59cccc2008-02-14 18:28:23 +000089//===----------------------------------------------------------------------===//
90// Transfer function for Casts.
91//===----------------------------------------------------------------------===//
92
Ted Kremenek9ef1ec92008-02-21 18:43:30 +000093RVal GRSimpleVals::EvalCast(ValueManager& ValMgr, NonLVal X, QualType T) {
Ted Kremenek692416c2008-02-18 22:57:02 +000094
Ted Kremenekd59cccc2008-02-14 18:28:23 +000095 if (!isa<nonlval::ConcreteInt>(X))
96 return UnknownVal();
97
98 llvm::APSInt V = cast<nonlval::ConcreteInt>(X).getValue();
Ted Kremenekd59cccc2008-02-14 18:28:23 +000099 V.setIsUnsigned(T->isUnsignedIntegerType() || T->isPointerType());
Ted Kremenek9ef1ec92008-02-21 18:43:30 +0000100 V.extOrTrunc(ValMgr.getContext().getTypeSize(T, SourceLocation()));
Ted Kremenekd59cccc2008-02-14 18:28:23 +0000101
Ted Kremenek9ef1ec92008-02-21 18:43:30 +0000102 if (T->isPointerType())
Ted Kremenekd59cccc2008-02-14 18:28:23 +0000103 return lval::ConcreteInt(ValMgr.getValue(V));
104 else
105 return nonlval::ConcreteInt(ValMgr.getValue(V));
106}
107
108// Casts.
109
Ted Kremenek9ef1ec92008-02-21 18:43:30 +0000110RVal GRSimpleVals::EvalCast(ValueManager& ValMgr, LVal X, QualType T) {
Ted Kremenek692416c2008-02-18 22:57:02 +0000111
Ted Kremenek9ef1ec92008-02-21 18:43:30 +0000112 if (T->isPointerType())
Ted Kremenekd59cccc2008-02-14 18:28:23 +0000113 return X;
114
Ted Kremenek9ef1ec92008-02-21 18:43:30 +0000115 assert (T->isIntegerType());
Ted Kremenekd59cccc2008-02-14 18:28:23 +0000116
117 if (!isa<lval::ConcreteInt>(X))
118 return UnknownVal();
119
120 llvm::APSInt V = cast<lval::ConcreteInt>(X).getValue();
Ted Kremenekd59cccc2008-02-14 18:28:23 +0000121 V.setIsUnsigned(T->isUnsignedIntegerType() || T->isPointerType());
Ted Kremenek9ef1ec92008-02-21 18:43:30 +0000122 V.extOrTrunc(ValMgr.getContext().getTypeSize(T, SourceLocation()));
Ted Kremenekd59cccc2008-02-14 18:28:23 +0000123
124 return nonlval::ConcreteInt(ValMgr.getValue(V));
Ted Kremenekc3f261d2008-02-14 18:40:24 +0000125}
126
127// Unary operators.
128
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000129RVal GRSimpleVals::EvalMinus(ValueManager& ValMgr, UnaryOperator* U, NonLVal X){
Ted Kremenek692416c2008-02-18 22:57:02 +0000130
Ted Kremenekc3f261d2008-02-14 18:40:24 +0000131 switch (X.getSubKind()) {
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000132
Ted Kremenekc3f261d2008-02-14 18:40:24 +0000133 case nonlval::ConcreteIntKind:
134 return cast<nonlval::ConcreteInt>(X).EvalMinus(ValMgr, U);
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000135
Ted Kremenekc3f261d2008-02-14 18:40:24 +0000136 default:
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000137 return UnknownVal();
Ted Kremenekc3f261d2008-02-14 18:40:24 +0000138 }
139}
140
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000141RVal GRSimpleVals::EvalComplement(ValueManager& ValMgr, NonLVal X) {
142
Ted Kremenek90e42032008-02-20 04:12:31 +0000143 switch (X.getSubKind()) {
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000144
Ted Kremenekc3f261d2008-02-14 18:40:24 +0000145 case nonlval::ConcreteIntKind:
146 return cast<nonlval::ConcreteInt>(X).EvalComplement(ValMgr);
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000147
Ted Kremenekc3f261d2008-02-14 18:40:24 +0000148 default:
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000149 return UnknownVal();
Ted Kremenekc3f261d2008-02-14 18:40:24 +0000150 }
151}
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000152
153// Binary operators.
154
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000155RVal GRSimpleVals::EvalBinOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
156 NonLVal L, NonLVal R) {
157 while (1) {
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000158
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000159 switch (L.getSubKind()) {
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000160 default:
Ted Kremenek9258a642008-02-21 19:10:12 +0000161 return UnknownVal();
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000162
163 case nonlval::ConcreteIntKind:
164
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000165 if (isa<nonlval::ConcreteInt>(R)) {
166 const nonlval::ConcreteInt& L_CI = cast<nonlval::ConcreteInt>(L);
167 const nonlval::ConcreteInt& R_CI = cast<nonlval::ConcreteInt>(R);
168 return L_CI.EvalBinOp(ValMgr, Op, R_CI);
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000169 }
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000170 else {
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000171 NonLVal tmp = R;
172 R = L;
173 L = tmp;
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000174 continue;
175 }
176
177 case nonlval::SymbolValKind: {
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000178
179 if (isa<nonlval::ConcreteInt>(R)) {
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000180 const SymIntConstraint& C =
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000181 ValMgr.getConstraint(cast<nonlval::SymbolVal>(L).getSymbol(), Op,
182 cast<nonlval::ConcreteInt>(R).getValue());
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000183
184 return nonlval::SymIntConstraintVal(C);
185 }
186 else
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000187 return UnknownVal();
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000188 }
189 }
190 }
191}
192
Ted Kremenekb640b3b2008-02-15 00:52:26 +0000193
Ted Kremenekc6fbdcd2008-02-15 23:15:23 +0000194// Binary Operators (except assignments and comma).
195
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000196RVal GRSimpleVals::EvalBinOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
197 LVal L, LVal R) {
Ted Kremenek692416c2008-02-18 22:57:02 +0000198
Ted Kremenekc6fbdcd2008-02-15 23:15:23 +0000199 switch (Op) {
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000200
Ted Kremenekc6fbdcd2008-02-15 23:15:23 +0000201 default:
202 return UnknownVal();
203
204 case BinaryOperator::EQ:
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000205 return EvalEQ(ValMgr, L, R);
Ted Kremenekc6fbdcd2008-02-15 23:15:23 +0000206
207 case BinaryOperator::NE:
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000208 return EvalNE(ValMgr, L, R);
Ted Kremenekc6fbdcd2008-02-15 23:15:23 +0000209 }
210}
211
Ted Kremenekb640b3b2008-02-15 00:52:26 +0000212// Pointer arithmetic.
213
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000214RVal GRSimpleVals::EvalBinOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
215 LVal L, NonLVal R) {
216 return UnknownVal();
Ted Kremenekb640b3b2008-02-15 00:52:26 +0000217}
218
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000219// Equality operators for LVals.
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000220
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000221RVal GRSimpleVals::EvalEQ(ValueManager& ValMgr, LVal L, LVal R) {
222
223 switch (L.getSubKind()) {
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000224
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000225 default:
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000226 assert(false && "EQ not implemented for this LVal.");
227 return UnknownVal();
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000228
229 case lval::ConcreteIntKind:
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000230
231 if (isa<lval::ConcreteInt>(R)) {
232 bool b = cast<lval::ConcreteInt>(L).getValue() ==
233 cast<lval::ConcreteInt>(R).getValue();
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000234
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000235 return NonLVal::MakeIntTruthVal(ValMgr, b);
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000236 }
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000237 else if (isa<lval::SymbolVal>(R)) {
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000238
239 const SymIntConstraint& C =
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000240 ValMgr.getConstraint(cast<lval::SymbolVal>(R).getSymbol(),
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000241 BinaryOperator::EQ,
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000242 cast<lval::ConcreteInt>(L).getValue());
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000243
244 return nonlval::SymIntConstraintVal(C);
245 }
246
247 break;
248
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000249 case lval::SymbolValKind: {
250
251 if (isa<lval::ConcreteInt>(R)) {
252 const SymIntConstraint& C =
253 ValMgr.getConstraint(cast<lval::SymbolVal>(L).getSymbol(),
254 BinaryOperator::EQ,
255 cast<lval::ConcreteInt>(R).getValue());
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000256
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000257 return nonlval::SymIntConstraintVal(C);
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000258 }
259
Ted Kremenekf700df22008-02-22 18:41:59 +0000260 // FIXME: Implement == for lval Symbols. This is mainly useful
261 // in iterator loops when traversing a buffer, e.g. while(z != zTerm).
262 // Since this is not useful for many checkers we'll punt on this for
263 // now.
264
265 return UnknownVal();
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000266 }
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000267
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000268 case lval::DeclValKind:
Ted Kremenekdc3936b2008-02-22 00:54:56 +0000269 case lval::FuncValKind:
270 case lval::GotoLabelKind:
271 return NonLVal::MakeIntTruthVal(ValMgr, L == R);
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000272 }
273
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000274 return NonLVal::MakeIntTruthVal(ValMgr, false);
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000275}
276
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000277RVal GRSimpleVals::EvalNE(ValueManager& ValMgr, LVal L, LVal R) {
Ted Kremenek692416c2008-02-18 22:57:02 +0000278
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000279 switch (L.getSubKind()) {
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000280
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000281 default:
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000282 assert(false && "NE not implemented for this LVal.");
283 return UnknownVal();
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000284
285 case lval::ConcreteIntKind:
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000286
287 if (isa<lval::ConcreteInt>(R)) {
288 bool b = cast<lval::ConcreteInt>(L).getValue() !=
289 cast<lval::ConcreteInt>(R).getValue();
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000290
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000291 return NonLVal::MakeIntTruthVal(ValMgr, b);
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000292 }
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000293 else if (isa<lval::SymbolVal>(R)) {
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000294 const SymIntConstraint& C =
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000295 ValMgr.getConstraint(cast<lval::SymbolVal>(R).getSymbol(),
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000296 BinaryOperator::NE,
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000297 cast<lval::ConcreteInt>(L).getValue());
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000298
299 return nonlval::SymIntConstraintVal(C);
300 }
301
302 break;
303
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000304 case lval::SymbolValKind: {
305 if (isa<lval::ConcreteInt>(R)) {
306 const SymIntConstraint& C =
307 ValMgr.getConstraint(cast<lval::SymbolVal>(L).getSymbol(),
308 BinaryOperator::NE,
309 cast<lval::ConcreteInt>(R).getValue());
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000310
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000311 return nonlval::SymIntConstraintVal(C);
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000312 }
313
Ted Kremenekf700df22008-02-22 18:41:59 +0000314 // FIXME: Implement != for lval Symbols. This is mainly useful
315 // in iterator loops when traversing a buffer, e.g. while(z != zTerm).
316 // Since this is not useful for many checkers we'll punt on this for
317 // now.
318
319 return UnknownVal();
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000320
321 break;
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000322 }
323
324 case lval::DeclValKind:
Ted Kremenekdc3936b2008-02-22 00:54:56 +0000325 case lval::FuncValKind:
326 case lval::GotoLabelKind:
327 return NonLVal::MakeIntTruthVal(ValMgr, L != R);
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000328 }
329
Ted Kremenekaa1c4e52008-02-21 18:02:17 +0000330 return NonLVal::MakeIntTruthVal(ValMgr, true);
Ted Kremenek6cb0b542008-02-14 19:37:24 +0000331}