blob: dc01b96d92cd8e91b967af546df13a0e280a22a3 [file] [log] [blame]
Ted Kremenek1f352db2008-07-22 16:21:24 +00001//=-- GRExprEngineInternalChecks.cpp - Builtin GRExprEngine Checks---*- 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 file defines the BugType classes used by GRExprEngine to report
11// bugs derived from builtin checks in the path-sensitive engine.
12//
13//===----------------------------------------------------------------------===//
14
Ted Kremenekbee01e52009-11-06 02:24:13 +000015#include "GRExprEngineInternalChecks.h"
Ted Kremenek1f352db2008-07-22 16:21:24 +000016#include "clang/Analysis/PathSensitive/BugReporter.h"
17#include "clang/Analysis/PathSensitive/GRExprEngine.h"
Ted Kremenek915c3512009-07-22 21:46:56 +000018#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
Ted Kremenekef910042009-11-04 04:24:16 +000019#include "clang/Analysis/PathSensitive/Checkers/UndefinedAssignmentChecker.h"
Ted Kremenek9abe4742009-05-07 00:45:33 +000020#include "clang/Analysis/PathDiagnostic.h"
Ted Kremenek83214f92008-10-31 00:13:20 +000021#include "clang/Basic/SourceManager.h"
Ted Kremenek1f352db2008-07-22 16:21:24 +000022#include "llvm/Support/Compiler.h"
Ted Kremenek289c37a2008-10-31 00:18:30 +000023#include "llvm/Support/raw_ostream.h"
Ted Kremenek1f352db2008-07-22 16:21:24 +000024
25using namespace clang;
Ted Kremenekf1282072009-07-22 17:55:28 +000026using namespace clang::bugreporter;
Ted Kremenek1f352db2008-07-22 16:21:24 +000027
28//===----------------------------------------------------------------------===//
29// Utility functions.
30//===----------------------------------------------------------------------===//
31
32template <typename ITERATOR> inline
Zhongxing Xu20227f72009-08-06 01:32:16 +000033ExplodedNode* GetNode(ITERATOR I) {
Ted Kremenek1f352db2008-07-22 16:21:24 +000034 return *I;
35}
36
37template <> inline
Zhongxing Xu20227f72009-08-06 01:32:16 +000038ExplodedNode* GetNode(GRExprEngine::undef_arg_iterator I) {
Ted Kremenek1f352db2008-07-22 16:21:24 +000039 return I->first;
40}
41
42//===----------------------------------------------------------------------===//
43// Bug Descriptions.
44//===----------------------------------------------------------------------===//
Zhongxing Xu6b8bfb32009-10-29 02:09:30 +000045namespace clang {
46class BuiltinBugReport : public RangedBugReport {
Ted Kremenek9abe4742009-05-07 00:45:33 +000047public:
48 BuiltinBugReport(BugType& bt, const char* desc,
Zhongxing Xu20227f72009-08-06 01:32:16 +000049 ExplodedNode *n)
Ted Kremenekbae77722009-05-13 19:16:35 +000050 : RangedBugReport(bt, desc, n) {}
Mike Stump11289f42009-09-09 15:08:12 +000051
Ted Kremenek608a6172009-05-15 05:25:09 +000052 BuiltinBugReport(BugType& bt, const char *shortDesc, const char *desc,
Zhongxing Xu20227f72009-08-06 01:32:16 +000053 ExplodedNode *n)
Mike Stump11289f42009-09-09 15:08:12 +000054 : RangedBugReport(bt, shortDesc, desc, n) {}
55
Ted Kremenek9abe4742009-05-07 00:45:33 +000056 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xu20227f72009-08-06 01:32:16 +000057 const ExplodedNode* N);
Mike Stump11289f42009-09-09 15:08:12 +000058};
59
Zhongxing Xu6b8bfb32009-10-29 02:09:30 +000060void BuiltinBugReport::registerInitialVisitors(BugReporterContext& BRC,
61 const ExplodedNode* N) {
62 static_cast<BuiltinBug&>(getBugType()).registerInitialVisitors(BRC, N, this);
63}
Mike Stump11289f42009-09-09 15:08:12 +000064
Ted Kremenek9abe4742009-05-07 00:45:33 +000065template <typename ITER>
66void BuiltinBug::Emit(BugReporter& BR, ITER I, ITER E) {
67 for (; I != E; ++I) BR.EmitReport(new BuiltinBugReport(*this, desc.c_str(),
68 GetNode(I)));
Mike Stump11289f42009-09-09 15:08:12 +000069}
Mike Stump11289f42009-09-09 15:08:12 +000070
Ted Kremenekbae77722009-05-13 19:16:35 +000071class VISIBILITY_HIDDEN NilReceiverStructRet : public BuiltinBug {
Ted Kremenek66d9edc2009-02-19 04:06:22 +000072public:
73 NilReceiverStructRet(GRExprEngine* eng) :
Ted Kremenekbae77722009-05-13 19:16:35 +000074 BuiltinBug(eng, "'nil' receiver with struct return type") {}
Ted Kremenek66d9edc2009-02-19 04:06:22 +000075
Ted Kremenekbae77722009-05-13 19:16:35 +000076 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek66d9edc2009-02-19 04:06:22 +000077 for (GRExprEngine::nil_receiver_struct_ret_iterator
78 I=Eng.nil_receiver_struct_ret_begin(),
79 E=Eng.nil_receiver_struct_ret_end(); I!=E; ++I) {
80
81 std::string sbuf;
82 llvm::raw_string_ostream os(sbuf);
83 PostStmt P = cast<PostStmt>((*I)->getLocation());
Ted Kremenekbfd28fd2009-07-22 22:35:28 +000084 const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(P.getStmt());
Ted Kremenek66d9edc2009-02-19 04:06:22 +000085 os << "The receiver in the message expression is 'nil' and results in the"
86 " returned value (of type '"
87 << ME->getType().getAsString()
Ted Kremenek7020eae2009-09-11 22:07:28 +000088 << "') to be garbage or otherwise undefined";
Ted Kremenek66d9edc2009-02-19 04:06:22 +000089
Ted Kremenekbae77722009-05-13 19:16:35 +000090 BuiltinBugReport *R = new BuiltinBugReport(*this, os.str().c_str(), *I);
Ted Kremenek66d9edc2009-02-19 04:06:22 +000091 R->addRange(ME->getReceiver()->getSourceRange());
92 BR.EmitReport(R);
93 }
94 }
Mike Stump11289f42009-09-09 15:08:12 +000095
Ted Kremenekbae77722009-05-13 19:16:35 +000096 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xu20227f72009-08-06 01:32:16 +000097 const ExplodedNode* N,
Ted Kremenekbae77722009-05-13 19:16:35 +000098 BuiltinBugReport *R) {
Ted Kremenek608a6172009-05-15 05:25:09 +000099 registerTrackNullOrUndefValue(BRC, GetReceiverExpr(N), N);
Ted Kremenekbae77722009-05-13 19:16:35 +0000100 }
Ted Kremenek66d9edc2009-02-19 04:06:22 +0000101};
Ted Kremenek605fee82009-04-08 03:07:17 +0000102
Ted Kremenekbae77722009-05-13 19:16:35 +0000103class VISIBILITY_HIDDEN NilReceiverLargerThanVoidPtrRet : public BuiltinBug {
Ted Kremenek605fee82009-04-08 03:07:17 +0000104public:
105 NilReceiverLargerThanVoidPtrRet(GRExprEngine* eng) :
Ted Kremenekbae77722009-05-13 19:16:35 +0000106 BuiltinBug(eng,
107 "'nil' receiver with return type larger than sizeof(void *)") {}
Mike Stump11289f42009-09-09 15:08:12 +0000108
Ted Kremenekbae77722009-05-13 19:16:35 +0000109 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek605fee82009-04-08 03:07:17 +0000110 for (GRExprEngine::nil_receiver_larger_than_voidptr_ret_iterator
111 I=Eng.nil_receiver_larger_than_voidptr_ret_begin(),
112 E=Eng.nil_receiver_larger_than_voidptr_ret_end(); I!=E; ++I) {
Mike Stump11289f42009-09-09 15:08:12 +0000113
Ted Kremenek605fee82009-04-08 03:07:17 +0000114 std::string sbuf;
115 llvm::raw_string_ostream os(sbuf);
116 PostStmt P = cast<PostStmt>((*I)->getLocation());
Ted Kremenekbfd28fd2009-07-22 22:35:28 +0000117 const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(P.getStmt());
Ted Kremenek605fee82009-04-08 03:07:17 +0000118 os << "The receiver in the message expression is 'nil' and results in the"
119 " returned value (of type '"
120 << ME->getType().getAsString()
121 << "' and of size "
122 << Eng.getContext().getTypeSize(ME->getType()) / 8
Ted Kremenek7020eae2009-09-11 22:07:28 +0000123 << " bytes) to be garbage or otherwise undefined";
Mike Stump11289f42009-09-09 15:08:12 +0000124
Ted Kremenekbae77722009-05-13 19:16:35 +0000125 BuiltinBugReport *R = new BuiltinBugReport(*this, os.str().c_str(), *I);
Ted Kremenek605fee82009-04-08 03:07:17 +0000126 R->addRange(ME->getReceiver()->getSourceRange());
127 BR.EmitReport(R);
128 }
Mike Stump11289f42009-09-09 15:08:12 +0000129 }
Ted Kremenekbae77722009-05-13 19:16:35 +0000130 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xu20227f72009-08-06 01:32:16 +0000131 const ExplodedNode* N,
Ted Kremenekbae77722009-05-13 19:16:35 +0000132 BuiltinBugReport *R) {
Ted Kremenek608a6172009-05-15 05:25:09 +0000133 registerTrackNullOrUndefValue(BRC, GetReceiverExpr(N), N);
Ted Kremenek605fee82009-04-08 03:07:17 +0000134 }
135};
Mike Stump11289f42009-09-09 15:08:12 +0000136
Ted Kremenek1f352db2008-07-22 16:21:24 +0000137class VISIBILITY_HIDDEN UndefResult : public BuiltinBug {
138public:
Ted Kremenek7020eae2009-09-11 22:07:28 +0000139 UndefResult(GRExprEngine* eng)
140 : BuiltinBug(eng,"Undefined or garbage result",
141 "Result of operation is garbage or undefined") {}
Mike Stump11289f42009-09-09 15:08:12 +0000142
Ted Kremenekfc5d0672009-02-04 23:49:09 +0000143 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek7020eae2009-09-11 22:07:28 +0000144 for (GRExprEngine::undef_result_iterator I=Eng.undef_results_begin(),
145 E = Eng.undef_results_end(); I!=E; ++I) {
146
147 ExplodedNode *N = *I;
148 const Stmt *S = N->getLocationAs<PostStmt>()->getStmt();
149 BuiltinBugReport *report = NULL;
150
151 if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) {
152 llvm::SmallString<256> sbuf;
153 llvm::raw_svector_ostream OS(sbuf);
154 const GRState *ST = N->getState();
Ted Kremenek4f335c32009-09-16 06:04:26 +0000155 const Expr *Ex = NULL;
156 bool isLeft = true;
Ted Kremenek7020eae2009-09-11 22:07:28 +0000157
158 if (ST->getSVal(B->getLHS()).isUndef()) {
159 Ex = B->getLHS()->IgnoreParenCasts();
Ted Kremenek4f335c32009-09-16 06:04:26 +0000160 isLeft = true;
Ted Kremenek7020eae2009-09-11 22:07:28 +0000161 }
Ted Kremenek188f62f2009-09-15 17:43:54 +0000162 else if (ST->getSVal(B->getRHS()).isUndef()) {
Ted Kremenek7020eae2009-09-11 22:07:28 +0000163 Ex = B->getRHS()->IgnoreParenCasts();
Ted Kremenek4f335c32009-09-16 06:04:26 +0000164 isLeft = false;
Ted Kremenek7020eae2009-09-11 22:07:28 +0000165 }
Ted Kremenek4f335c32009-09-16 06:04:26 +0000166
167 if (Ex) {
168 OS << "The " << (isLeft ? "left" : "right")
Ted Kremenekd9120d32009-09-24 00:44:26 +0000169 << " operand of '"
Ted Kremenek4f335c32009-09-16 06:04:26 +0000170 << BinaryOperator::getOpcodeStr(B->getOpcode())
Ted Kremenekd9120d32009-09-24 00:44:26 +0000171 << "' is a garbage value";
Ted Kremenek188f62f2009-09-15 17:43:54 +0000172 }
173 else {
Ted Kremenek4f335c32009-09-16 06:04:26 +0000174 // Neither operand was undefined, but the result is undefined.
Ted Kremenek188f62f2009-09-15 17:43:54 +0000175 OS << "The result of the '"
176 << BinaryOperator::getOpcodeStr(B->getOpcode())
177 << "' expression is undefined";
178 }
179
Ted Kremenek7020eae2009-09-11 22:07:28 +0000180 // FIXME: Use StringRefs to pass string information.
181 report = new BuiltinBugReport(*this, OS.str().str().c_str(), N);
Ted Kremenek188f62f2009-09-15 17:43:54 +0000182 if (Ex) report->addRange(Ex->getSourceRange());
Ted Kremenek7020eae2009-09-11 22:07:28 +0000183 }
184 else {
185 report = new BuiltinBugReport(*this,
186 "Expression evaluates to an uninitialized"
187 " or undefined value", N);
188 }
189
190 BR.EmitReport(report);
191 }
192 }
193
194 void registerInitialVisitors(BugReporterContext& BRC,
195 const ExplodedNode* N,
196 BuiltinBugReport *R) {
197
198 const Stmt *S = N->getLocationAs<StmtPoint>()->getStmt();
199 const Stmt *X = S;
200
201 if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) {
202 const GRState *ST = N->getState();
Ted Kremenek4f335c32009-09-16 06:04:26 +0000203 if (ST->getSVal(B->getLHS()).isUndef())
204 X = B->getLHS();
205 else if (ST->getSVal(B->getRHS()).isUndef())
206 X = B->getRHS();
Ted Kremenek7020eae2009-09-11 22:07:28 +0000207 }
208
209 registerTrackNullOrUndefValue(BRC, X, N);
Ted Kremenek1f352db2008-07-22 16:21:24 +0000210 }
211};
Mike Stump11289f42009-09-09 15:08:12 +0000212
Ted Kremenek608a6172009-05-15 05:25:09 +0000213class VISIBILITY_HIDDEN ArgReport : public BuiltinBugReport {
214 const Stmt *Arg;
215public:
Zhongxing Xu20227f72009-08-06 01:32:16 +0000216 ArgReport(BugType& bt, const char* desc, ExplodedNode *n,
Ted Kremenek608a6172009-05-15 05:25:09 +0000217 const Stmt *arg)
218 : BuiltinBugReport(bt, desc, n), Arg(arg) {}
Mike Stump11289f42009-09-09 15:08:12 +0000219
Ted Kremenek608a6172009-05-15 05:25:09 +0000220 ArgReport(BugType& bt, const char *shortDesc, const char *desc,
Zhongxing Xu20227f72009-08-06 01:32:16 +0000221 ExplodedNode *n, const Stmt *arg)
Mike Stump11289f42009-09-09 15:08:12 +0000222 : BuiltinBugReport(bt, shortDesc, desc, n), Arg(arg) {}
223
224 const Stmt *getArg() const { return Arg; }
Ted Kremenek1f352db2008-07-22 16:21:24 +0000225};
226
227class VISIBILITY_HIDDEN BadArg : public BuiltinBug {
Mike Stump11289f42009-09-09 15:08:12 +0000228public:
229 BadArg(GRExprEngine* eng=0) : BuiltinBug(eng,"Uninitialized argument",
Ted Kremenek7020eae2009-09-11 22:07:28 +0000230 "Pass-by-value argument in function call is undefined") {}
Ted Kremenek1f352db2008-07-22 16:21:24 +0000231
Ted Kremenekfc5d0672009-02-04 23:49:09 +0000232 BadArg(GRExprEngine* eng, const char* d)
Ted Kremenekb82dd532009-04-02 02:40:26 +0000233 : BuiltinBug(eng,"Uninitialized argument", d) {}
Mike Stump11289f42009-09-09 15:08:12 +0000234
Ted Kremenek608a6172009-05-15 05:25:09 +0000235 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xu20227f72009-08-06 01:32:16 +0000236 const ExplodedNode* N,
Ted Kremenek608a6172009-05-15 05:25:09 +0000237 BuiltinBugReport *R) {
238 registerTrackNullOrUndefValue(BRC, static_cast<ArgReport*>(R)->getArg(),
239 N);
Mike Stump11289f42009-09-09 15:08:12 +0000240 }
Ted Kremenek1f352db2008-07-22 16:21:24 +0000241};
Mike Stump11289f42009-09-09 15:08:12 +0000242
Ted Kremenek1f352db2008-07-22 16:21:24 +0000243class VISIBILITY_HIDDEN BadMsgExprArg : public BadArg {
244public:
Mike Stump11289f42009-09-09 15:08:12 +0000245 BadMsgExprArg(GRExprEngine* eng)
Ted Kremenekb82dd532009-04-02 02:40:26 +0000246 : BadArg(eng,"Pass-by-value argument in message expression is undefined"){}
Mike Stump11289f42009-09-09 15:08:12 +0000247
Ted Kremenekfc5d0672009-02-04 23:49:09 +0000248 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek1f352db2008-07-22 16:21:24 +0000249 for (GRExprEngine::UndefArgsTy::iterator I=Eng.msg_expr_undef_arg_begin(),
Mike Stump11289f42009-09-09 15:08:12 +0000250 E = Eng.msg_expr_undef_arg_end(); I!=E; ++I) {
Ted Kremenek1f352db2008-07-22 16:21:24 +0000251 // Generate a report for this bug.
Ted Kremenek608a6172009-05-15 05:25:09 +0000252 ArgReport *report = new ArgReport(*this, desc.c_str(), I->first,
253 I->second);
Ted Kremenekfc5d0672009-02-04 23:49:09 +0000254 report->addRange(I->second->getSourceRange());
255 BR.EmitReport(report);
Mike Stump11289f42009-09-09 15:08:12 +0000256 }
257 }
Ted Kremenek1f352db2008-07-22 16:21:24 +0000258};
Mike Stump11289f42009-09-09 15:08:12 +0000259
Ted Kremenek1f352db2008-07-22 16:21:24 +0000260class VISIBILITY_HIDDEN BadReceiver : public BuiltinBug {
Mike Stump11289f42009-09-09 15:08:12 +0000261public:
Ted Kremenekfc5d0672009-02-04 23:49:09 +0000262 BadReceiver(GRExprEngine* eng)
Ted Kremenekb82dd532009-04-02 02:40:26 +0000263 : BuiltinBug(eng,"Uninitialized receiver",
264 "Receiver in message expression is an uninitialized value") {}
Mike Stump11289f42009-09-09 15:08:12 +0000265
Ted Kremenekfc5d0672009-02-04 23:49:09 +0000266 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek8f7afdd2008-12-08 22:47:34 +0000267 for (GRExprEngine::ErrorNodes::iterator I=Eng.undef_receivers_begin(),
Ted Kremenek1f352db2008-07-22 16:21:24 +0000268 End = Eng.undef_receivers_end(); I!=End; ++I) {
Mike Stump11289f42009-09-09 15:08:12 +0000269
Ted Kremenek1f352db2008-07-22 16:21:24 +0000270 // Generate a report for this bug.
Ted Kremenekbae77722009-05-13 19:16:35 +0000271 BuiltinBugReport *report = new BuiltinBugReport(*this, desc.c_str(), *I);
Zhongxing Xu20227f72009-08-06 01:32:16 +0000272 ExplodedNode* N = *I;
Ted Kremenekbfd28fd2009-07-22 22:35:28 +0000273 const Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
274 const Expr* E = cast<ObjCMessageExpr>(S)->getReceiver();
Ted Kremenek1f352db2008-07-22 16:21:24 +0000275 assert (E && "Receiver cannot be NULL");
Ted Kremenekfc5d0672009-02-04 23:49:09 +0000276 report->addRange(E->getSourceRange());
277 BR.EmitReport(report);
Ted Kremenekbae77722009-05-13 19:16:35 +0000278 }
279 }
Ted Kremenek608a6172009-05-15 05:25:09 +0000280
Ted Kremenekbae77722009-05-13 19:16:35 +0000281 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xu20227f72009-08-06 01:32:16 +0000282 const ExplodedNode* N,
Ted Kremenekbae77722009-05-13 19:16:35 +0000283 BuiltinBugReport *R) {
Ted Kremenek608a6172009-05-15 05:25:09 +0000284 registerTrackNullOrUndefValue(BRC, GetReceiverExpr(N), N);
Mike Stump11289f42009-09-09 15:08:12 +0000285 }
Ted Kremenek1f352db2008-07-22 16:21:24 +0000286};
Ted Kremenek0b63f962008-11-21 00:27:44 +0000287
Ted Kremenek1f352db2008-07-22 16:21:24 +0000288class VISIBILITY_HIDDEN UndefBranch : public BuiltinBug {
289 struct VISIBILITY_HIDDEN FindUndefExpr {
Ted Kremenek5ab5a1b2008-08-13 04:27:00 +0000290 GRStateManager& VM;
291 const GRState* St;
Mike Stump11289f42009-09-09 15:08:12 +0000292
Ted Kremenek5ab5a1b2008-08-13 04:27:00 +0000293 FindUndefExpr(GRStateManager& V, const GRState* S) : VM(V), St(S) {}
Mike Stump11289f42009-09-09 15:08:12 +0000294
295 Expr* FindExpr(Expr* Ex) {
Ted Kremenek1f352db2008-07-22 16:21:24 +0000296 if (!MatchesCriteria(Ex))
Ted Kremeneka8b8ce42008-07-30 17:49:12 +0000297 return 0;
Mike Stump11289f42009-09-09 15:08:12 +0000298
Ted Kremeneka8b8ce42008-07-30 17:49:12 +0000299 for (Stmt::child_iterator I=Ex->child_begin(), E=Ex->child_end();I!=E;++I)
Ted Kremenek1f352db2008-07-22 16:21:24 +0000300 if (Expr* ExI = dyn_cast_or_null<Expr>(*I)) {
301 Expr* E2 = FindExpr(ExI);
302 if (E2) return E2;
303 }
Mike Stump11289f42009-09-09 15:08:12 +0000304
Ted Kremenek1f352db2008-07-22 16:21:24 +0000305 return Ex;
306 }
Mike Stump11289f42009-09-09 15:08:12 +0000307
Ted Kremenek095f1a92009-06-18 23:58:37 +0000308 bool MatchesCriteria(Expr* Ex) { return St->getSVal(Ex).isUndef(); }
Ted Kremenek1f352db2008-07-22 16:21:24 +0000309 };
Mike Stump11289f42009-09-09 15:08:12 +0000310
Ted Kremenek1f352db2008-07-22 16:21:24 +0000311public:
Ted Kremenekfc5d0672009-02-04 23:49:09 +0000312 UndefBranch(GRExprEngine *eng)
Ted Kremenek7020eae2009-09-11 22:07:28 +0000313 : BuiltinBug(eng,"Use of garbage value",
314 "Branch condition evaluates to an undefined or garbage value")
315 {}
Mike Stump11289f42009-09-09 15:08:12 +0000316
Ted Kremenekfc5d0672009-02-04 23:49:09 +0000317 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek1f352db2008-07-22 16:21:24 +0000318 for (GRExprEngine::undef_branch_iterator I=Eng.undef_branches_begin(),
319 E=Eng.undef_branches_end(); I!=E; ++I) {
320
321 // What's going on here: we want to highlight the subexpression of the
322 // condition that is the most likely source of the "uninitialized
323 // branch condition." We do a recursive walk of the condition's
324 // subexpressions and roughly look for the most nested subexpression
325 // that binds to Undefined. We then highlight that expression's range.
Ted Kremenek1f352db2008-07-22 16:21:24 +0000326 BlockEdge B = cast<BlockEdge>((*I)->getLocation());
327 Expr* Ex = cast<Expr>(B.getSrc()->getTerminatorCondition());
328 assert (Ex && "Block must have a terminator.");
329
330 // Get the predecessor node and check if is a PostStmt with the Stmt
331 // being the terminator condition. We want to inspect the state
332 // of that node instead because it will contain main information about
333 // the subexpressions.
Ted Kremenek1f352db2008-07-22 16:21:24 +0000334 assert (!(*I)->pred_empty());
335
336 // Note: any predecessor will do. They should have identical state,
337 // since all the BlockEdge did was act as an error sink since the value
338 // had to already be undefined.
Zhongxing Xu20227f72009-08-06 01:32:16 +0000339 ExplodedNode *N = *(*I)->pred_begin();
Ted Kremenek1f352db2008-07-22 16:21:24 +0000340 ProgramPoint P = N->getLocation();
Ted Kremenek5ab5a1b2008-08-13 04:27:00 +0000341 const GRState* St = (*I)->getState();
Ted Kremenek1f352db2008-07-22 16:21:24 +0000342
343 if (PostStmt* PS = dyn_cast<PostStmt>(&P))
344 if (PS->getStmt() == Ex)
345 St = N->getState();
346
347 FindUndefExpr FindIt(Eng.getStateManager(), St);
348 Ex = FindIt.FindExpr(Ex);
349
Ted Kremenek608a6172009-05-15 05:25:09 +0000350 ArgReport *R = new ArgReport(*this, desc.c_str(), *I, Ex);
Ted Kremenekfc5d0672009-02-04 23:49:09 +0000351 R->addRange(Ex->getSourceRange());
352 BR.EmitReport(R);
Ted Kremenek1f352db2008-07-22 16:21:24 +0000353 }
354 }
Mike Stump11289f42009-09-09 15:08:12 +0000355
Ted Kremenek608a6172009-05-15 05:25:09 +0000356 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xu20227f72009-08-06 01:32:16 +0000357 const ExplodedNode* N,
Ted Kremenek608a6172009-05-15 05:25:09 +0000358 BuiltinBugReport *R) {
359 registerTrackNullOrUndefValue(BRC, static_cast<ArgReport*>(R)->getArg(),
360 N);
361 }
Ted Kremenek1f352db2008-07-22 16:21:24 +0000362};
363
Zhongxing Xu6b8bfb32009-10-29 02:09:30 +0000364} // end clang namespace
Ted Kremenekf613e892009-10-30 17:24:47 +0000365
Ted Kremenek1f352db2008-07-22 16:21:24 +0000366//===----------------------------------------------------------------------===//
367// Check registration.
Ted Kremenekfc5d0672009-02-04 23:49:09 +0000368//===----------------------------------------------------------------------===//
Ted Kremenek1f352db2008-07-22 16:21:24 +0000369
370void GRExprEngine::RegisterInternalChecks() {
Ted Kremenekfc5d0672009-02-04 23:49:09 +0000371 // Register internal "built-in" BugTypes with the BugReporter. These BugTypes
372 // are different than what probably many checks will do since they don't
373 // create BugReports on-the-fly but instead wait until GRExprEngine finishes
374 // analyzing a function. Generation of BugReport objects is done via a call
375 // to 'FlushReports' from BugReporter.
Ted Kremenekfc5d0672009-02-04 23:49:09 +0000376 BR.Register(new UndefBranch(this));
Ted Kremenekfc5d0672009-02-04 23:49:09 +0000377 BR.Register(new UndefResult(this));
Ted Kremenekfc5d0672009-02-04 23:49:09 +0000378 BR.Register(new BadMsgExprArg(this));
379 BR.Register(new BadReceiver(this));
Ted Kremenek66d9edc2009-02-19 04:06:22 +0000380 BR.Register(new NilReceiverStructRet(this));
Ted Kremenek605fee82009-04-08 03:07:17 +0000381 BR.Register(new NilReceiverLargerThanVoidPtrRet(this));
Mike Stump11289f42009-09-09 15:08:12 +0000382
Ted Kremenekfc5d0672009-02-04 23:49:09 +0000383 // The following checks do not need to have their associated BugTypes
384 // explicitly registered with the BugReporter. If they issue any BugReports,
385 // their associated BugType will get registered with the BugReporter
386 // automatically. Note that the check itself is owned by the GRExprEngine
Ted Kremenek53a70c02009-11-06 20:47:51 +0000387 // object.
Ted Kremenekef910042009-11-04 04:24:16 +0000388 registerCheck(new UndefinedAssignmentChecker());
Ted Kremenek795c6112009-11-06 21:51:50 +0000389
Ted Kremenek43253152009-11-11 05:50:44 +0000390 RegisterAttrNonNullChecker(*this);
391 RegisterUndefinedArgChecker(*this);
392 RegisterBadCallChecker(*this);
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000393 RegisterDereferenceChecker(*this);
Ted Kremenek795c6112009-11-06 21:51:50 +0000394 RegisterVLASizeChecker(*this);
395 RegisterDivZeroChecker(*this);
396 RegisterReturnStackAddressChecker(*this);
397 RegisterReturnUndefChecker(*this);
Zhongxing Xu86b1e012009-11-09 05:34:10 +0000398 RegisterPointerSubChecker(*this);
Zhongxing Xuab0e27f2009-11-09 13:23:31 +0000399 RegisterPointerArithChecker(*this);
Zhongxing Xu6c306c82009-11-09 06:52:44 +0000400 RegisterFixedAddressChecker(*this);
Ted Kremenek795c6112009-11-06 21:51:50 +0000401 // Note that this must be registered after ReturnStackAddressChecker.
402 RegisterReturnPointerRangeChecker(*this);
Zhongxing Xuf06c6842009-11-09 08:07:38 +0000403
404 RegisterCastToStructChecker(*this);
Zhongxing Xu4f7759a2009-11-11 12:33:27 +0000405 RegisterArrayBoundChecker(*this);
Zhongxing Xub1667122009-11-11 13:42:54 +0000406 RegisterUndefinedArraySubscriptChecker(*this);
Ted Kremenek1f352db2008-07-22 16:21:24 +0000407}