blob: 3dedcb3edf0378c5981c9036b1917fc6a8d2998c [file] [log] [blame]
Ted Kremenek53500662009-07-22 17:55:28 +00001// BugReporterVisitors.cpp - Helpers for reporting bugs -----------*- 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 a set of BugReporter "visitors" which can be used to
11// enhance the diagnostics reported for a bug.
12//
13//===----------------------------------------------------------------------===//
Anna Zaks50bbc162011-08-19 22:33:38 +000014#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h"
Ted Kremenek53500662009-07-22 17:55:28 +000015
16#include "clang/AST/Expr.h"
17#include "clang/AST/ExprObjC.h"
Ted Kremenek9b663712011-02-10 01:03:03 +000018#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
19#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
20#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
Ted Kremenek18c66fd2011-08-15 22:09:50 +000021#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
Ted Kremenek681bc112011-08-16 01:53:41 +000022#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
Benjamin Kramer8fe83e12012-02-04 13:45:25 +000023#include "llvm/ADT/SmallString.h"
Ted Kremenek53500662009-07-22 17:55:28 +000024
25using namespace clang;
Ted Kremenek9ef65372010-12-23 07:20:52 +000026using namespace ento;
Ted Kremenek53500662009-07-22 17:55:28 +000027
28//===----------------------------------------------------------------------===//
29// Utility functions.
30//===----------------------------------------------------------------------===//
31
Argyrios Kyrtzidis5a4f98f2010-12-22 18:53:20 +000032const Stmt *bugreporter::GetDerefExpr(const ExplodedNode *N) {
Ted Kremenek53500662009-07-22 17:55:28 +000033 // Pattern match for a few useful cases (do something smarter later):
34 // a[0], p->f, *p
35 const Stmt *S = N->getLocationAs<PostStmt>()->getStmt();
Mike Stump1eb44332009-09-09 15:08:12 +000036
Ted Kremenek11abcec2012-05-02 00:31:29 +000037 while (true) {
38 if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) {
39 assert(B->isAssignmentOp());
40 S = B->getLHS()->IgnoreParenCasts();
41 continue;
42 }
43 else if (const UnaryOperator *U = dyn_cast<UnaryOperator>(S)) {
44 if (U->getOpcode() == UO_Deref)
45 return U->getSubExpr()->IgnoreParenCasts();
46 }
47 else if (const MemberExpr *ME = dyn_cast<MemberExpr>(S)) {
48 return ME->getBase()->IgnoreParenCasts();
49 }
50 else if (const ArraySubscriptExpr *AE = dyn_cast<ArraySubscriptExpr>(S)) {
51 return AE->getBase();
52 }
53 break;
Ted Kremenek53500662009-07-22 17:55:28 +000054 }
Mike Stump1eb44332009-09-09 15:08:12 +000055
56 return NULL;
Ted Kremenek53500662009-07-22 17:55:28 +000057}
58
Argyrios Kyrtzidis5a4f98f2010-12-22 18:53:20 +000059const Stmt *bugreporter::GetDenomExpr(const ExplodedNode *N) {
Zhongxing Xu6403b572009-09-02 13:26:26 +000060 const Stmt *S = N->getLocationAs<PreStmt>()->getStmt();
Ted Kremenek53500662009-07-22 17:55:28 +000061 if (const BinaryOperator *BE = dyn_cast<BinaryOperator>(S))
62 return BE->getRHS();
63 return NULL;
64}
65
Argyrios Kyrtzidis5a4f98f2010-12-22 18:53:20 +000066const Stmt *bugreporter::GetRetValExpr(const ExplodedNode *N) {
Ted Kremenek53500662009-07-22 17:55:28 +000067 const Stmt *S = N->getLocationAs<PostStmt>()->getStmt();
68 if (const ReturnStmt *RS = dyn_cast<ReturnStmt>(S))
69 return RS->getRetValue();
70 return NULL;
71}
72
73//===----------------------------------------------------------------------===//
74// Definitions for bug reporter visitors.
75//===----------------------------------------------------------------------===//
Anna Zaks23f395e2011-08-20 01:27:22 +000076
77PathDiagnosticPiece*
78BugReporterVisitor::getEndPath(BugReporterContext &BRC,
79 const ExplodedNode *EndPathNode,
80 BugReport &BR) {
81 return 0;
82}
83
84PathDiagnosticPiece*
85BugReporterVisitor::getDefaultEndPath(BugReporterContext &BRC,
86 const ExplodedNode *EndPathNode,
87 BugReport &BR) {
Anna Zaks5a0917d2012-02-16 03:41:01 +000088 PathDiagnosticLocation L =
89 PathDiagnosticLocation::createEndOfPath(EndPathNode,BRC.getSourceManager());
Anna Zaks23f395e2011-08-20 01:27:22 +000090
91 BugReport::ranges_iterator Beg, End;
92 llvm::tie(Beg, End) = BR.getRanges();
93
94 // Only add the statement itself as a range if we didn't specify any
95 // special ranges for this report.
96 PathDiagnosticPiece *P = new PathDiagnosticEventPiece(L,
97 BR.getDescription(),
98 Beg == End);
99 for (; Beg != End; ++Beg)
100 P->addRange(*Beg);
101
102 return P;
103}
104
105
Anna Zaks50bbc162011-08-19 22:33:38 +0000106void FindLastStoreBRVisitor ::Profile(llvm::FoldingSetNodeID &ID) const {
107 static int tag = 0;
108 ID.AddPointer(&tag);
109 ID.AddPointer(R);
110 ID.Add(V);
111}
Ted Kremenek53500662009-07-22 17:55:28 +0000112
Anna Zaks50bbc162011-08-19 22:33:38 +0000113PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *N,
114 const ExplodedNode *PrevN,
115 BugReporterContext &BRC,
116 BugReport &BR) {
Mike Stump1eb44332009-09-09 15:08:12 +0000117
Anna Zaks50bbc162011-08-19 22:33:38 +0000118 if (satisfied)
119 return NULL;
120
121 if (!StoreSite) {
Jordan Rose20165e72012-08-03 23:08:42 +0000122 // Make sure the region is actually bound to value V here.
123 // This is necessary because the region may not actually be live at the
124 // report's error node.
125 if (N->getState()->getSVal(R) != V)
126 return NULL;
Anna Zaks50bbc162011-08-19 22:33:38 +0000127
Jordan Rose20165e72012-08-03 23:08:42 +0000128 const ExplodedNode *Node = N, *Last = N;
129
130 // Now look for the store of V.
Ted Kremenekd2e70902012-01-25 22:18:04 +0000131 for ( ; Node ; Node = Node->getFirstPred()) {
Anna Zaks50bbc162011-08-19 22:33:38 +0000132 if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
133 if (const PostStmt *P = Node->getLocationAs<PostStmt>())
134 if (const DeclStmt *DS = P->getStmtAs<DeclStmt>())
135 if (DS->getSingleDecl() == VR->getDecl()) {
Ted Kremenekd2e70902012-01-25 22:18:04 +0000136 // Record the last seen initialization point.
Anna Zaks50bbc162011-08-19 22:33:38 +0000137 Last = Node;
138 break;
139 }
140 }
141
Ted Kremenekd2e70902012-01-25 22:18:04 +0000142 // Does the region still bind to value V? If not, we are done
143 // looking for store sites.
Anna Zaks50bbc162011-08-19 22:33:38 +0000144 if (Node->getState()->getSVal(R) != V)
145 break;
Jordan Rose20165e72012-08-03 23:08:42 +0000146
147 Last = Node;
Anna Zaks50bbc162011-08-19 22:33:38 +0000148 }
149
Jordan Rose20165e72012-08-03 23:08:42 +0000150 if (!Node) {
Anna Zaks50bbc162011-08-19 22:33:38 +0000151 satisfied = true;
152 return NULL;
153 }
154
155 StoreSite = Last;
Ted Kremenek1b431022010-03-20 18:01:57 +0000156 }
157
Anna Zaks50bbc162011-08-19 22:33:38 +0000158 if (StoreSite != N)
159 return NULL;
Mike Stump1eb44332009-09-09 15:08:12 +0000160
Anna Zaks50bbc162011-08-19 22:33:38 +0000161 satisfied = true;
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +0000162 SmallString<256> sbuf;
Anna Zaks50bbc162011-08-19 22:33:38 +0000163 llvm::raw_svector_ostream os(sbuf);
Mike Stump1eb44332009-09-09 15:08:12 +0000164
Anna Zaks50bbc162011-08-19 22:33:38 +0000165 if (const PostStmt *PS = N->getLocationAs<PostStmt>()) {
166 if (const DeclStmt *DS = PS->getStmtAs<DeclStmt>()) {
Mike Stump1eb44332009-09-09 15:08:12 +0000167
Anna Zaks50bbc162011-08-19 22:33:38 +0000168 if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
Benjamin Kramerb8989f22011-10-14 18:45:37 +0000169 os << "Variable '" << *VR->getDecl() << "' ";
Ted Kremenek53500662009-07-22 17:55:28 +0000170 }
Anna Zaks50bbc162011-08-19 22:33:38 +0000171 else
Ted Kremenek53500662009-07-22 17:55:28 +0000172 return NULL;
Mike Stump1eb44332009-09-09 15:08:12 +0000173
Ted Kremenek53500662009-07-22 17:55:28 +0000174 if (isa<loc::ConcreteInt>(V)) {
175 bool b = false;
Ted Kremenek53500662009-07-22 17:55:28 +0000176 if (R->isBoundable()) {
Ted Kremenek96979342011-08-12 20:02:48 +0000177 if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
Zhongxing Xu018220c2010-08-11 06:10:55 +0000178 if (TR->getValueType()->isObjCObjectPointerType()) {
Anna Zaks50bbc162011-08-19 22:33:38 +0000179 os << "initialized to nil";
Ted Kremenek53500662009-07-22 17:55:28 +0000180 b = true;
181 }
182 }
183 }
Mike Stump1eb44332009-09-09 15:08:12 +0000184
Ted Kremenek53500662009-07-22 17:55:28 +0000185 if (!b)
Anna Zaks50bbc162011-08-19 22:33:38 +0000186 os << "initialized to a null pointer value";
Ted Kremenek53500662009-07-22 17:55:28 +0000187 }
Ted Kremenek592362b2009-08-18 01:05:30 +0000188 else if (isa<nonloc::ConcreteInt>(V)) {
Anna Zaks50bbc162011-08-19 22:33:38 +0000189 os << "initialized to " << cast<nonloc::ConcreteInt>(V).getValue();
Ted Kremenek592362b2009-08-18 01:05:30 +0000190 }
Anna Zaks50bbc162011-08-19 22:33:38 +0000191 else if (V.isUndef()) {
192 if (isa<VarRegion>(R)) {
193 const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl());
194 if (VD->getInit())
195 os << "initialized to a garbage value";
196 else
197 os << "declared without an initial value";
198 }
Ted Kremenek53500662009-07-22 17:55:28 +0000199 }
Ted Kremenek53500662009-07-22 17:55:28 +0000200 }
Anna Zaks50bbc162011-08-19 22:33:38 +0000201 }
202
203 if (os.str().empty()) {
204 if (isa<loc::ConcreteInt>(V)) {
205 bool b = false;
206 if (R->isBoundable()) {
207 if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
208 if (TR->getValueType()->isObjCObjectPointerType()) {
209 os << "nil object reference stored to ";
210 b = true;
211 }
212 }
213 }
214
215 if (!b)
216 os << "Null pointer value stored to ";
217 }
218 else if (V.isUndef()) {
219 os << "Uninitialized value stored to ";
220 }
221 else if (isa<nonloc::ConcreteInt>(V)) {
222 os << "The value " << cast<nonloc::ConcreteInt>(V).getValue()
223 << " is assigned to ";
224 }
225 else
226 return NULL;
227
228 if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
Benjamin Kramerb8989f22011-10-14 18:45:37 +0000229 os << '\'' << *VR->getDecl() << '\'';
Anna Zaks50bbc162011-08-19 22:33:38 +0000230 }
231 else
232 return NULL;
233 }
234
Anna Zaks50bbc162011-08-19 22:33:38 +0000235 // Construct a new PathDiagnosticPiece.
Anna Zaks4fdf97b2011-09-15 18:56:07 +0000236 ProgramPoint P = N->getLocation();
Anna Zaks1531bb02011-09-20 01:38:47 +0000237 PathDiagnosticLocation L =
238 PathDiagnosticLocation::create(P, BRC.getSourceManager());
Anna Zaks4fdf97b2011-09-15 18:56:07 +0000239 if (!L.isValid())
240 return NULL;
Anna Zaks50bbc162011-08-19 22:33:38 +0000241 return new PathDiagnosticEventPiece(L, os.str());
242}
243
244void TrackConstraintBRVisitor::Profile(llvm::FoldingSetNodeID &ID) const {
245 static int tag = 0;
246 ID.AddPointer(&tag);
247 ID.AddBoolean(Assumption);
248 ID.Add(Constraint);
249}
250
251PathDiagnosticPiece *
252TrackConstraintBRVisitor::VisitNode(const ExplodedNode *N,
253 const ExplodedNode *PrevN,
254 BugReporterContext &BRC,
255 BugReport &BR) {
256 if (isSatisfied)
257 return NULL;
258
259 // Check if in the previous state it was feasible for this constraint
260 // to *not* be true.
261 if (PrevN->getState()->assume(Constraint, !Assumption)) {
262
263 isSatisfied = true;
264
265 // As a sanity check, make sure that the negation of the constraint
266 // was infeasible in the current state. If it is feasible, we somehow
267 // missed the transition point.
268 if (N->getState()->assume(Constraint, !Assumption))
269 return NULL;
270
271 // We found the transition point for the constraint. We now need to
272 // pretty-print the constraint. (work-in-progress)
273 std::string sbuf;
274 llvm::raw_string_ostream os(sbuf);
275
276 if (isa<Loc>(Constraint)) {
277 os << "Assuming pointer value is ";
278 os << (Assumption ? "non-null" : "null");
279 }
280
281 if (os.str().empty())
282 return NULL;
Mike Stump1eb44332009-09-09 15:08:12 +0000283
Ted Kremenek53500662009-07-22 17:55:28 +0000284 // Construct a new PathDiagnosticPiece.
Anna Zaks4fdf97b2011-09-15 18:56:07 +0000285 ProgramPoint P = N->getLocation();
Anna Zaks1531bb02011-09-20 01:38:47 +0000286 PathDiagnosticLocation L =
287 PathDiagnosticLocation::create(P, BRC.getSourceManager());
Anna Zaks4fdf97b2011-09-15 18:56:07 +0000288 if (!L.isValid())
289 return NULL;
Ted Kremenek53500662009-07-22 17:55:28 +0000290 return new PathDiagnosticEventPiece(L, os.str());
291 }
Ted Kremenek53500662009-07-22 17:55:28 +0000292
Anna Zaks50bbc162011-08-19 22:33:38 +0000293 return NULL;
Ted Kremenek53500662009-07-22 17:55:28 +0000294}
295
Anna Zaks50bbc162011-08-19 22:33:38 +0000296BugReporterVisitor *
297bugreporter::getTrackNullOrUndefValueVisitor(const ExplodedNode *N,
Ted Kremenek76aadc32012-03-09 01:13:14 +0000298 const Stmt *S,
299 BugReport *report) {
Anna Zaks50bbc162011-08-19 22:33:38 +0000300 if (!S || !N)
301 return 0;
Mike Stump1eb44332009-09-09 15:08:12 +0000302
Anna Zaks8e6431a2011-08-18 22:37:56 +0000303 ProgramStateManager &StateMgr = N->getState()->getStateManager();
304
Ted Kremenek88299892011-07-28 23:07:59 +0000305 // Walk through nodes until we get one that matches the statement
306 // exactly.
307 while (N) {
308 const ProgramPoint &pp = N->getLocation();
309 if (const PostStmt *ps = dyn_cast<PostStmt>(&pp)) {
310 if (ps->getStmt() == S)
311 break;
312 }
Anna Zaksb459cf32011-10-01 06:35:19 +0000313 N = N->getFirstPred();
Ted Kremenek88299892011-07-28 23:07:59 +0000314 }
315
316 if (!N)
Anna Zaks50bbc162011-08-19 22:33:38 +0000317 return 0;
Ted Kremenek88299892011-07-28 23:07:59 +0000318
Ted Kremenek8bef8232012-01-26 21:29:00 +0000319 ProgramStateRef state = N->getState();
Mike Stump1eb44332009-09-09 15:08:12 +0000320
Ted Kremenek76aadc32012-03-09 01:13:14 +0000321 // Walk through lvalue-to-rvalue conversions.
322 const Expr *Ex = dyn_cast<Expr>(S);
323 if (Ex) {
324 Ex = Ex->IgnoreParenLValueCasts();
325 if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex)) {
326 if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
327 const VarRegion *R =
328 StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext());
Mike Stump1eb44332009-09-09 15:08:12 +0000329
Ted Kremenek76aadc32012-03-09 01:13:14 +0000330 // What did we load?
Ted Kremenek11abcec2012-05-02 00:31:29 +0000331 SVal V = state->getRawSVal(loc::MemRegionVal(R));
Ted Kremenek76aadc32012-03-09 01:13:14 +0000332 report->markInteresting(R);
333 report->markInteresting(V);
Anna Zaks50bbc162011-08-19 22:33:38 +0000334 return new FindLastStoreBRVisitor(V, R);
Ted Kremenek53500662009-07-22 17:55:28 +0000335 }
336 }
337 }
Mike Stump1eb44332009-09-09 15:08:12 +0000338
Ted Kremenek5eca4822012-01-06 22:09:28 +0000339 SVal V = state->getSValAsScalarOrLoc(S, N->getLocationContext());
Mike Stump1eb44332009-09-09 15:08:12 +0000340
Ted Kremenek53500662009-07-22 17:55:28 +0000341 // Uncomment this to find cases where we aren't properly getting the
342 // base value that was dereferenced.
343 // assert(!V.isUnknownOrUndef());
Mike Stump1eb44332009-09-09 15:08:12 +0000344
Ted Kremenek53500662009-07-22 17:55:28 +0000345 // Is it a symbolic value?
346 if (loc::MemRegionVal *L = dyn_cast<loc::MemRegionVal>(&V)) {
347 const SubRegion *R = cast<SubRegion>(L->getRegion());
348 while (R && !isa<SymbolicRegion>(R)) {
349 R = dyn_cast<SubRegion>(R->getSuperRegion());
350 }
Mike Stump1eb44332009-09-09 15:08:12 +0000351
Ted Kremenek53500662009-07-22 17:55:28 +0000352 if (R) {
Ted Kremenek76aadc32012-03-09 01:13:14 +0000353 report->markInteresting(R);
Anna Zaks50bbc162011-08-19 22:33:38 +0000354 return new TrackConstraintBRVisitor(loc::MemRegionVal(R), false);
Ted Kremenek53500662009-07-22 17:55:28 +0000355 }
356 }
Anna Zaks50bbc162011-08-19 22:33:38 +0000357
358 return 0;
Ted Kremenek53500662009-07-22 17:55:28 +0000359}
Ted Kremenek94fd0b82010-02-16 08:33:59 +0000360
Anna Zaks50bbc162011-08-19 22:33:38 +0000361BugReporterVisitor *
362FindLastStoreBRVisitor::createVisitorObject(const ExplodedNode *N,
363 const MemRegion *R) {
364 assert(R && "The memory region is null.");
Ted Kremenek94fd0b82010-02-16 08:33:59 +0000365
Ted Kremenek8bef8232012-01-26 21:29:00 +0000366 ProgramStateRef state = N->getState();
Ted Kremenek94fd0b82010-02-16 08:33:59 +0000367 SVal V = state->getSVal(R);
Ted Kremenek94fd0b82010-02-16 08:33:59 +0000368 if (V.isUnknown())
Anna Zaks50bbc162011-08-19 22:33:38 +0000369 return 0;
Ted Kremenek94fd0b82010-02-16 08:33:59 +0000370
Anna Zaks50bbc162011-08-19 22:33:38 +0000371 return new FindLastStoreBRVisitor(V, R);
Ted Kremenek94fd0b82010-02-16 08:33:59 +0000372}
Ted Kremenekff7f7362010-03-20 18:02:01 +0000373
374
Anna Zaks50bbc162011-08-19 22:33:38 +0000375PathDiagnosticPiece *NilReceiverBRVisitor::VisitNode(const ExplodedNode *N,
376 const ExplodedNode *PrevN,
377 BugReporterContext &BRC,
378 BugReport &BR) {
379 const PostStmt *P = N->getLocationAs<PostStmt>();
380 if (!P)
381 return 0;
382 const ObjCMessageExpr *ME = P->getStmtAs<ObjCMessageExpr>();
383 if (!ME)
384 return 0;
385 const Expr *Receiver = ME->getInstanceReceiver();
386 if (!Receiver)
387 return 0;
Ted Kremenek8bef8232012-01-26 21:29:00 +0000388 ProgramStateRef state = N->getState();
Ted Kremenek5eca4822012-01-06 22:09:28 +0000389 const SVal &V = state->getSVal(Receiver, N->getLocationContext());
Anna Zaks50bbc162011-08-19 22:33:38 +0000390 const DefinedOrUnknownSVal *DV = dyn_cast<DefinedOrUnknownSVal>(&V);
391 if (!DV)
392 return 0;
393 state = state->assume(*DV, true);
394 if (state)
395 return 0;
Ted Kremenekff7f7362010-03-20 18:02:01 +0000396
Anna Zaks50bbc162011-08-19 22:33:38 +0000397 // The receiver was nil, and hence the method was skipped.
398 // Register a BugReporterVisitor to issue a message telling us how
399 // the receiver was null.
Ted Kremenek76aadc32012-03-09 01:13:14 +0000400 BR.addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, Receiver, &BR));
Anna Zaks50bbc162011-08-19 22:33:38 +0000401 // Issue a message saying that the method was skipped.
Anna Zaks220ac8c2011-09-15 01:08:34 +0000402 PathDiagnosticLocation L(Receiver, BRC.getSourceManager(),
403 N->getLocationContext());
Anna Zaks907344e2012-04-05 02:10:19 +0000404 return new PathDiagnosticEventPiece(L, "No method is called "
Anna Zaks50bbc162011-08-19 22:33:38 +0000405 "because the receiver is nil");
Ted Kremenekff7f7362010-03-20 18:02:01 +0000406}
Tom Care2bbbe502010-09-02 23:30:22 +0000407
Anna Zaks8e6431a2011-08-18 22:37:56 +0000408// Registers every VarDecl inside a Stmt with a last store visitor.
Anna Zaks50bbc162011-08-19 22:33:38 +0000409void FindLastStoreBRVisitor::registerStatementVarDecls(BugReport &BR,
410 const Stmt *S) {
Anna Zaks8e6431a2011-08-18 22:37:56 +0000411 const ExplodedNode *N = BR.getErrorNode();
Tom Care2bbbe502010-09-02 23:30:22 +0000412 std::deque<const Stmt *> WorkList;
Tom Care2bbbe502010-09-02 23:30:22 +0000413 WorkList.push_back(S);
414
415 while (!WorkList.empty()) {
416 const Stmt *Head = WorkList.front();
417 WorkList.pop_front();
418
Ted Kremenek8bef8232012-01-26 21:29:00 +0000419 ProgramStateRef state = N->getState();
Anna Zaks8e6431a2011-08-18 22:37:56 +0000420 ProgramStateManager &StateMgr = state->getStateManager();
Tom Care2bbbe502010-09-02 23:30:22 +0000421
422 if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Head)) {
423 if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
424 const VarRegion *R =
425 StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext());
426
427 // What did we load?
Ted Kremenek5eca4822012-01-06 22:09:28 +0000428 SVal V = state->getSVal(S, N->getLocationContext());
Tom Care2bbbe502010-09-02 23:30:22 +0000429
430 if (isa<loc::ConcreteInt>(V) || isa<nonloc::ConcreteInt>(V)) {
Anna Zaks50bbc162011-08-19 22:33:38 +0000431 // Register a new visitor with the BugReport.
432 BR.addVisitor(new FindLastStoreBRVisitor(V, R));
Tom Care2bbbe502010-09-02 23:30:22 +0000433 }
434 }
435 }
436
437 for (Stmt::const_child_iterator I = Head->child_begin();
438 I != Head->child_end(); ++I)
439 WorkList.push_back(*I);
440 }
441}
Ted Kremenek993124e2011-08-06 06:54:45 +0000442
443//===----------------------------------------------------------------------===//
444// Visitor that tries to report interesting diagnostics from conditions.
445//===----------------------------------------------------------------------===//
Anna Zaks50bbc162011-08-19 22:33:38 +0000446PathDiagnosticPiece *ConditionBRVisitor::VisitNode(const ExplodedNode *N,
447 const ExplodedNode *Prev,
448 BugReporterContext &BRC,
449 BugReport &BR) {
Ted Kremenekc89f4b02012-02-28 23:06:21 +0000450 PathDiagnosticPiece *piece = VisitNodeImpl(N, Prev, BRC, BR);
451 if (PathDiagnosticEventPiece *ev =
452 dyn_cast_or_null<PathDiagnosticEventPiece>(piece))
Ted Kremenek76aadc32012-03-09 01:13:14 +0000453 ev->setPrunable(true, /* override */ false);
Ted Kremenekc89f4b02012-02-28 23:06:21 +0000454 return piece;
455}
456
457PathDiagnosticPiece *ConditionBRVisitor::VisitNodeImpl(const ExplodedNode *N,
458 const ExplodedNode *Prev,
459 BugReporterContext &BRC,
460 BugReport &BR) {
Ted Kremenek993124e2011-08-06 06:54:45 +0000461
462 const ProgramPoint &progPoint = N->getLocation();
Ted Kremenek681bc112011-08-16 01:53:41 +0000463
Ted Kremenek8bef8232012-01-26 21:29:00 +0000464 ProgramStateRef CurrentState = N->getState();
465 ProgramStateRef PrevState = Prev->getState();
Ted Kremenek681bc112011-08-16 01:53:41 +0000466
467 // Compare the GDMs of the state, because that is where constraints
468 // are managed. Note that ensure that we only look at nodes that
469 // were generated by the analyzer engine proper, not checkers.
470 if (CurrentState->getGDM().getRoot() ==
471 PrevState->getGDM().getRoot())
472 return 0;
Ted Kremenek993124e2011-08-06 06:54:45 +0000473
474 // If an assumption was made on a branch, it should be caught
475 // here by looking at the state transition.
476 if (const BlockEdge *BE = dyn_cast<BlockEdge>(&progPoint)) {
Ted Kremenek681bc112011-08-16 01:53:41 +0000477 const CFGBlock *srcBlk = BE->getSrc();
478 if (const Stmt *term = srcBlk->getTerminator())
Ted Kremenek76aadc32012-03-09 01:13:14 +0000479 return VisitTerminator(term, N, srcBlk, BE->getDst(), BR, BRC);
Ted Kremenek681bc112011-08-16 01:53:41 +0000480 return 0;
481 }
482
483 if (const PostStmt *PS = dyn_cast<PostStmt>(&progPoint)) {
484 // FIXME: Assuming that BugReporter is a GRBugReporter is a layering
485 // violation.
486 const std::pair<const ProgramPointTag *, const ProgramPointTag *> &tags =
487 cast<GRBugReporter>(BRC.getBugReporter()).
488 getEngine().getEagerlyAssumeTags();
489
490 const ProgramPointTag *tag = PS->getTag();
491 if (tag == tags.first)
Anna Zaks220ac8c2011-09-15 01:08:34 +0000492 return VisitTrueTest(cast<Expr>(PS->getStmt()), true,
Ted Kremenek76aadc32012-03-09 01:13:14 +0000493 BRC, BR, N);
Ted Kremenek681bc112011-08-16 01:53:41 +0000494 if (tag == tags.second)
Anna Zaks220ac8c2011-09-15 01:08:34 +0000495 return VisitTrueTest(cast<Expr>(PS->getStmt()), false,
Ted Kremenek76aadc32012-03-09 01:13:14 +0000496 BRC, BR, N);
Ted Kremenek681bc112011-08-16 01:53:41 +0000497
Ted Kremenek993124e2011-08-06 06:54:45 +0000498 return 0;
499 }
500
501 return 0;
502}
503
504PathDiagnosticPiece *
Anna Zaks50bbc162011-08-19 22:33:38 +0000505ConditionBRVisitor::VisitTerminator(const Stmt *Term,
Anna Zaks220ac8c2011-09-15 01:08:34 +0000506 const ExplodedNode *N,
Anna Zaks50bbc162011-08-19 22:33:38 +0000507 const CFGBlock *srcBlk,
508 const CFGBlock *dstBlk,
Ted Kremenek76aadc32012-03-09 01:13:14 +0000509 BugReport &R,
Anna Zaks50bbc162011-08-19 22:33:38 +0000510 BugReporterContext &BRC) {
Ted Kremenek993124e2011-08-06 06:54:45 +0000511 const Expr *Cond = 0;
512
513 switch (Term->getStmtClass()) {
514 default:
515 return 0;
516 case Stmt::IfStmtClass:
517 Cond = cast<IfStmt>(Term)->getCond();
518 break;
519 case Stmt::ConditionalOperatorClass:
520 Cond = cast<ConditionalOperator>(Term)->getCond();
521 break;
522 }
523
524 assert(Cond);
525 assert(srcBlk->succ_size() == 2);
526 const bool tookTrue = *(srcBlk->succ_begin()) == dstBlk;
527 return VisitTrueTest(Cond->IgnoreParenNoopCasts(BRC.getASTContext()),
Ted Kremenek76aadc32012-03-09 01:13:14 +0000528 tookTrue, BRC, R, N);
Ted Kremenek993124e2011-08-06 06:54:45 +0000529}
530
531PathDiagnosticPiece *
Anna Zaks50bbc162011-08-19 22:33:38 +0000532ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
533 bool tookTrue,
Anna Zaks220ac8c2011-09-15 01:08:34 +0000534 BugReporterContext &BRC,
Ted Kremenek76aadc32012-03-09 01:13:14 +0000535 BugReport &R,
536 const ExplodedNode *N) {
Ted Kremenek993124e2011-08-06 06:54:45 +0000537
538 const Expr *Ex = Cond;
539
Ted Kremenek681bc112011-08-16 01:53:41 +0000540 while (true) {
541 Ex = Ex->IgnoreParens();
Ted Kremenek993124e2011-08-06 06:54:45 +0000542 switch (Ex->getStmtClass()) {
543 default:
544 return 0;
Ted Kremenek681bc112011-08-16 01:53:41 +0000545 case Stmt::BinaryOperatorClass:
Ted Kremenek76aadc32012-03-09 01:13:14 +0000546 return VisitTrueTest(Cond, cast<BinaryOperator>(Ex), tookTrue, BRC,
547 R, N);
Ted Kremenek993124e2011-08-06 06:54:45 +0000548 case Stmt::DeclRefExprClass:
Ted Kremenek76aadc32012-03-09 01:13:14 +0000549 return VisitTrueTest(Cond, cast<DeclRefExpr>(Ex), tookTrue, BRC,
550 R, N);
Ted Kremenek993124e2011-08-06 06:54:45 +0000551 case Stmt::UnaryOperatorClass: {
552 const UnaryOperator *UO = cast<UnaryOperator>(Ex);
553 if (UO->getOpcode() == UO_LNot) {
554 tookTrue = !tookTrue;
555 Ex = UO->getSubExpr()->IgnoreParenNoopCasts(BRC.getASTContext());
556 continue;
557 }
558 return 0;
559 }
560 }
Ted Kremenek681bc112011-08-16 01:53:41 +0000561 }
562}
563
Anna Zaks50bbc162011-08-19 22:33:38 +0000564bool ConditionBRVisitor::patternMatch(const Expr *Ex, llvm::raw_ostream &Out,
Ted Kremenek76aadc32012-03-09 01:13:14 +0000565 BugReporterContext &BRC,
566 BugReport &report,
567 const ExplodedNode *N,
568 llvm::Optional<bool> &prunable) {
Ted Kremenek681bc112011-08-16 01:53:41 +0000569 const Expr *OriginalExpr = Ex;
570 Ex = Ex->IgnoreParenCasts();
571
572 if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex)) {
Ted Kremenek3b9e8e42011-08-16 10:57:37 +0000573 const bool quotes = isa<VarDecl>(DR->getDecl());
Ted Kremenek76aadc32012-03-09 01:13:14 +0000574 if (quotes) {
Ted Kremenek3b9e8e42011-08-16 10:57:37 +0000575 Out << '\'';
Ted Kremenek76aadc32012-03-09 01:13:14 +0000576 const LocationContext *LCtx = N->getLocationContext();
577 const ProgramState *state = N->getState().getPtr();
578 if (const MemRegion *R = state->getLValue(cast<VarDecl>(DR->getDecl()),
579 LCtx).getAsRegion()) {
580 if (report.isInteresting(R))
581 prunable = false;
582 else {
583 const ProgramState *state = N->getState().getPtr();
584 SVal V = state->getSVal(R);
585 if (report.isInteresting(V))
586 prunable = false;
587 }
588 }
589 }
Ted Kremenek3b9e8e42011-08-16 10:57:37 +0000590 Out << DR->getDecl()->getDeclName().getAsString();
591 if (quotes)
592 Out << '\'';
593 return quotes;
Ted Kremenek681bc112011-08-16 01:53:41 +0000594 }
595
596 if (const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(Ex)) {
597 QualType OriginalTy = OriginalExpr->getType();
598 if (OriginalTy->isPointerType()) {
599 if (IL->getValue() == 0) {
600 Out << "null";
Ted Kremenek3b9e8e42011-08-16 10:57:37 +0000601 return false;
Ted Kremenek681bc112011-08-16 01:53:41 +0000602 }
603 }
604 else if (OriginalTy->isObjCObjectPointerType()) {
605 if (IL->getValue() == 0) {
606 Out << "nil";
Ted Kremenek3b9e8e42011-08-16 10:57:37 +0000607 return false;
Ted Kremenek681bc112011-08-16 01:53:41 +0000608 }
609 }
610
611 Out << IL->getValue();
Ted Kremenek3b9e8e42011-08-16 10:57:37 +0000612 return false;
Ted Kremenek681bc112011-08-16 01:53:41 +0000613 }
Ted Kremenek3b9e8e42011-08-16 10:57:37 +0000614
615 return false;
Ted Kremenek681bc112011-08-16 01:53:41 +0000616}
617
618PathDiagnosticPiece *
Anna Zaks50bbc162011-08-19 22:33:38 +0000619ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
620 const BinaryOperator *BExpr,
621 const bool tookTrue,
Anna Zaks220ac8c2011-09-15 01:08:34 +0000622 BugReporterContext &BRC,
Ted Kremenek76aadc32012-03-09 01:13:14 +0000623 BugReport &R,
624 const ExplodedNode *N) {
Ted Kremenek681bc112011-08-16 01:53:41 +0000625
Ted Kremenek3b9e8e42011-08-16 10:57:37 +0000626 bool shouldInvert = false;
Ted Kremenek76aadc32012-03-09 01:13:14 +0000627 llvm::Optional<bool> shouldPrune;
Ted Kremenek3b9e8e42011-08-16 10:57:37 +0000628
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +0000629 SmallString<128> LhsString, RhsString;
Ted Kremenek681bc112011-08-16 01:53:41 +0000630 {
Ted Kremenek76aadc32012-03-09 01:13:14 +0000631 llvm::raw_svector_ostream OutLHS(LhsString), OutRHS(RhsString);
632 const bool isVarLHS = patternMatch(BExpr->getLHS(), OutLHS, BRC, R, N,
633 shouldPrune);
634 const bool isVarRHS = patternMatch(BExpr->getRHS(), OutRHS, BRC, R, N,
635 shouldPrune);
Ted Kremenek3b9e8e42011-08-16 10:57:37 +0000636
637 shouldInvert = !isVarLHS && isVarRHS;
Ted Kremenek681bc112011-08-16 01:53:41 +0000638 }
639
Ted Kremenekd1247c52012-01-04 08:18:09 +0000640 BinaryOperator::Opcode Op = BExpr->getOpcode();
641
642 if (BinaryOperator::isAssignmentOp(Op)) {
643 // For assignment operators, all that we care about is that the LHS
644 // evaluates to "true" or "false".
645 return VisitConditionVariable(LhsString, BExpr->getLHS(), tookTrue,
Ted Kremenek76aadc32012-03-09 01:13:14 +0000646 BRC, R, N);
Ted Kremenekd1247c52012-01-04 08:18:09 +0000647 }
648
649 // For non-assignment operations, we require that we can understand
650 // both the LHS and RHS.
Ted Kremenek681bc112011-08-16 01:53:41 +0000651 if (LhsString.empty() || RhsString.empty())
652 return 0;
Ted Kremenek3b9e8e42011-08-16 10:57:37 +0000653
Ted Kremenekd1247c52012-01-04 08:18:09 +0000654 // Should we invert the strings if the LHS is not a variable name?
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +0000655 SmallString<256> buf;
Ted Kremenek681bc112011-08-16 01:53:41 +0000656 llvm::raw_svector_ostream Out(buf);
Ted Kremenek3b9e8e42011-08-16 10:57:37 +0000657 Out << "Assuming " << (shouldInvert ? RhsString : LhsString) << " is ";
Ted Kremenek681bc112011-08-16 01:53:41 +0000658
659 // Do we need to invert the opcode?
Ted Kremenek3b9e8e42011-08-16 10:57:37 +0000660 if (shouldInvert)
661 switch (Op) {
662 default: break;
663 case BO_LT: Op = BO_GT; break;
664 case BO_GT: Op = BO_LT; break;
665 case BO_LE: Op = BO_GE; break;
666 case BO_GE: Op = BO_LE; break;
667 }
668
Ted Kremenek681bc112011-08-16 01:53:41 +0000669 if (!tookTrue)
670 switch (Op) {
671 case BO_EQ: Op = BO_NE; break;
672 case BO_NE: Op = BO_EQ; break;
673 case BO_LT: Op = BO_GE; break;
674 case BO_GT: Op = BO_LE; break;
675 case BO_LE: Op = BO_GT; break;
Ted Kremenek4ee7c9c2011-08-16 03:44:38 +0000676 case BO_GE: Op = BO_LT; break;
Ted Kremenek681bc112011-08-16 01:53:41 +0000677 default:
678 return 0;
679 }
680
Ted Kremenek6ae32572011-12-20 22:00:25 +0000681 switch (Op) {
Ted Kremenek681bc112011-08-16 01:53:41 +0000682 case BO_EQ:
683 Out << "equal to ";
684 break;
685 case BO_NE:
686 Out << "not equal to ";
687 break;
688 default:
689 Out << BinaryOperator::getOpcodeStr(Op) << ' ';
690 break;
691 }
692
Ted Kremenek3b9e8e42011-08-16 10:57:37 +0000693 Out << (shouldInvert ? LhsString : RhsString);
Ted Kremenek76aadc32012-03-09 01:13:14 +0000694 const LocationContext *LCtx = N->getLocationContext();
695 PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
696 PathDiagnosticEventPiece *event =
697 new PathDiagnosticEventPiece(Loc, Out.str());
698 if (shouldPrune.hasValue())
699 event->setPrunable(shouldPrune.getValue());
700 return event;
Ted Kremenek993124e2011-08-06 06:54:45 +0000701}
Ted Kremenekd1247c52012-01-04 08:18:09 +0000702
703PathDiagnosticPiece *
704ConditionBRVisitor::VisitConditionVariable(StringRef LhsString,
705 const Expr *CondVarExpr,
706 const bool tookTrue,
707 BugReporterContext &BRC,
Ted Kremenek76aadc32012-03-09 01:13:14 +0000708 BugReport &report,
709 const ExplodedNode *N) {
Jordan Roseb0e1bad2012-08-03 23:08:54 +0000710 // FIXME: If there's already a constraint tracker for this variable,
711 // we shouldn't emit anything here (c.f. the double note in
712 // test/Analysis/inlining/path-notes.c)
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +0000713 SmallString<256> buf;
Ted Kremenekd1247c52012-01-04 08:18:09 +0000714 llvm::raw_svector_ostream Out(buf);
715 Out << "Assuming " << LhsString << " is ";
716
717 QualType Ty = CondVarExpr->getType();
718
719 if (Ty->isPointerType())
720 Out << (tookTrue ? "not null" : "null");
721 else if (Ty->isObjCObjectPointerType())
722 Out << (tookTrue ? "not nil" : "nil");
723 else if (Ty->isBooleanType())
724 Out << (tookTrue ? "true" : "false");
725 else if (Ty->isIntegerType())
726 Out << (tookTrue ? "non-zero" : "zero");
727 else
728 return 0;
729
Ted Kremenek76aadc32012-03-09 01:13:14 +0000730 const LocationContext *LCtx = N->getLocationContext();
731 PathDiagnosticLocation Loc(CondVarExpr, BRC.getSourceManager(), LCtx);
732 PathDiagnosticEventPiece *event =
733 new PathDiagnosticEventPiece(Loc, Out.str());
734
735 if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(CondVarExpr)) {
736 if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
737 const ProgramState *state = N->getState().getPtr();
738 if (const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) {
739 if (report.isInteresting(R))
740 event->setPrunable(false);
741 }
742 }
743 }
744
745 return event;
Ted Kremenekd1247c52012-01-04 08:18:09 +0000746}
Ted Kremenek993124e2011-08-06 06:54:45 +0000747
748PathDiagnosticPiece *
Anna Zaks50bbc162011-08-19 22:33:38 +0000749ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
750 const DeclRefExpr *DR,
751 const bool tookTrue,
Anna Zaks220ac8c2011-09-15 01:08:34 +0000752 BugReporterContext &BRC,
Ted Kremenek76aadc32012-03-09 01:13:14 +0000753 BugReport &report,
754 const ExplodedNode *N) {
Ted Kremenek993124e2011-08-06 06:54:45 +0000755
756 const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
757 if (!VD)
758 return 0;
759
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +0000760 SmallString<256> Buf;
Ted Kremenek993124e2011-08-06 06:54:45 +0000761 llvm::raw_svector_ostream Out(Buf);
762
763 Out << "Assuming '";
764 VD->getDeclName().printName(Out);
765 Out << "' is ";
766
767 QualType VDTy = VD->getType();
768
769 if (VDTy->isPointerType())
770 Out << (tookTrue ? "non-null" : "null");
771 else if (VDTy->isObjCObjectPointerType())
772 Out << (tookTrue ? "non-nil" : "nil");
773 else if (VDTy->isScalarType())
774 Out << (tookTrue ? "not equal to 0" : "0");
775 else
776 return 0;
777
Ted Kremenek76aadc32012-03-09 01:13:14 +0000778 const LocationContext *LCtx = N->getLocationContext();
779 PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
780 PathDiagnosticEventPiece *event =
781 new PathDiagnosticEventPiece(Loc, Out.str());
782
783 const ProgramState *state = N->getState().getPtr();
784 if (const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) {
785 if (report.isInteresting(R))
786 event->setPrunable(false);
787 else {
788 SVal V = state->getSVal(R);
789 if (report.isInteresting(V))
790 event->setPrunable(false);
791 }
792 }
793 return event;
Ted Kremenek993124e2011-08-06 06:54:45 +0000794}
Ted Kremenek0cf3d472012-02-07 00:24:33 +0000795