blob: 46aa9e2b9123b20595bbdec3ba76e85ee6197d74 [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 }
Jordan Rose68537992012-08-03 23:09:01 +0000200 else {
201 os << "initialized here";
202 }
Ted Kremenek53500662009-07-22 17:55:28 +0000203 }
Anna Zaks50bbc162011-08-19 22:33:38 +0000204 }
205
206 if (os.str().empty()) {
207 if (isa<loc::ConcreteInt>(V)) {
208 bool b = false;
209 if (R->isBoundable()) {
210 if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
211 if (TR->getValueType()->isObjCObjectPointerType()) {
212 os << "nil object reference stored to ";
213 b = true;
214 }
215 }
216 }
217
218 if (!b)
219 os << "Null pointer value stored to ";
220 }
221 else if (V.isUndef()) {
222 os << "Uninitialized value stored to ";
223 }
224 else if (isa<nonloc::ConcreteInt>(V)) {
225 os << "The value " << cast<nonloc::ConcreteInt>(V).getValue()
226 << " is assigned to ";
227 }
228 else
Jordan Rose68537992012-08-03 23:09:01 +0000229 os << "Value assigned to ";
Anna Zaks50bbc162011-08-19 22:33:38 +0000230
231 if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
Benjamin Kramerb8989f22011-10-14 18:45:37 +0000232 os << '\'' << *VR->getDecl() << '\'';
Anna Zaks50bbc162011-08-19 22:33:38 +0000233 }
234 else
235 return NULL;
236 }
237
Anna Zaks50bbc162011-08-19 22:33:38 +0000238 // Construct a new PathDiagnosticPiece.
Anna Zaks4fdf97b2011-09-15 18:56:07 +0000239 ProgramPoint P = N->getLocation();
Anna Zaks1531bb02011-09-20 01:38:47 +0000240 PathDiagnosticLocation L =
241 PathDiagnosticLocation::create(P, BRC.getSourceManager());
Anna Zaks4fdf97b2011-09-15 18:56:07 +0000242 if (!L.isValid())
243 return NULL;
Anna Zaks50bbc162011-08-19 22:33:38 +0000244 return new PathDiagnosticEventPiece(L, os.str());
245}
246
247void TrackConstraintBRVisitor::Profile(llvm::FoldingSetNodeID &ID) const {
248 static int tag = 0;
249 ID.AddPointer(&tag);
250 ID.AddBoolean(Assumption);
251 ID.Add(Constraint);
252}
253
254PathDiagnosticPiece *
255TrackConstraintBRVisitor::VisitNode(const ExplodedNode *N,
256 const ExplodedNode *PrevN,
257 BugReporterContext &BRC,
258 BugReport &BR) {
259 if (isSatisfied)
260 return NULL;
261
262 // Check if in the previous state it was feasible for this constraint
263 // to *not* be true.
264 if (PrevN->getState()->assume(Constraint, !Assumption)) {
265
266 isSatisfied = true;
267
268 // As a sanity check, make sure that the negation of the constraint
269 // was infeasible in the current state. If it is feasible, we somehow
270 // missed the transition point.
271 if (N->getState()->assume(Constraint, !Assumption))
272 return NULL;
273
274 // We found the transition point for the constraint. We now need to
275 // pretty-print the constraint. (work-in-progress)
276 std::string sbuf;
277 llvm::raw_string_ostream os(sbuf);
278
279 if (isa<Loc>(Constraint)) {
280 os << "Assuming pointer value is ";
281 os << (Assumption ? "non-null" : "null");
282 }
283
284 if (os.str().empty())
285 return NULL;
Mike Stump1eb44332009-09-09 15:08:12 +0000286
Ted Kremenek53500662009-07-22 17:55:28 +0000287 // Construct a new PathDiagnosticPiece.
Anna Zaks4fdf97b2011-09-15 18:56:07 +0000288 ProgramPoint P = N->getLocation();
Anna Zaks1531bb02011-09-20 01:38:47 +0000289 PathDiagnosticLocation L =
290 PathDiagnosticLocation::create(P, BRC.getSourceManager());
Anna Zaks4fdf97b2011-09-15 18:56:07 +0000291 if (!L.isValid())
292 return NULL;
Ted Kremenek53500662009-07-22 17:55:28 +0000293 return new PathDiagnosticEventPiece(L, os.str());
294 }
Ted Kremenek53500662009-07-22 17:55:28 +0000295
Anna Zaks50bbc162011-08-19 22:33:38 +0000296 return NULL;
Ted Kremenek53500662009-07-22 17:55:28 +0000297}
298
Jordan Rose68537992012-08-03 23:09:01 +0000299void bugreporter::addTrackNullOrUndefValueVisitor(const ExplodedNode *N,
300 const Stmt *S,
301 BugReport *report) {
Anna Zaks50bbc162011-08-19 22:33:38 +0000302 if (!S || !N)
Jordan Rose68537992012-08-03 23:09:01 +0000303 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000304
Anna Zaks8e6431a2011-08-18 22:37:56 +0000305 ProgramStateManager &StateMgr = N->getState()->getStateManager();
306
Ted Kremenek88299892011-07-28 23:07:59 +0000307 // Walk through nodes until we get one that matches the statement
308 // exactly.
309 while (N) {
310 const ProgramPoint &pp = N->getLocation();
311 if (const PostStmt *ps = dyn_cast<PostStmt>(&pp)) {
312 if (ps->getStmt() == S)
313 break;
314 }
Anna Zaksb459cf32011-10-01 06:35:19 +0000315 N = N->getFirstPred();
Ted Kremenek88299892011-07-28 23:07:59 +0000316 }
317
318 if (!N)
Jordan Rose68537992012-08-03 23:09:01 +0000319 return;
Ted Kremenek88299892011-07-28 23:07:59 +0000320
Ted Kremenek8bef8232012-01-26 21:29:00 +0000321 ProgramStateRef state = N->getState();
Mike Stump1eb44332009-09-09 15:08:12 +0000322
Ted Kremenek76aadc32012-03-09 01:13:14 +0000323 // Walk through lvalue-to-rvalue conversions.
324 const Expr *Ex = dyn_cast<Expr>(S);
325 if (Ex) {
326 Ex = Ex->IgnoreParenLValueCasts();
327 if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex)) {
328 if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
329 const VarRegion *R =
330 StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext());
Mike Stump1eb44332009-09-09 15:08:12 +0000331
Ted Kremenek76aadc32012-03-09 01:13:14 +0000332 // What did we load?
Ted Kremenek11abcec2012-05-02 00:31:29 +0000333 SVal V = state->getRawSVal(loc::MemRegionVal(R));
Ted Kremenek76aadc32012-03-09 01:13:14 +0000334 report->markInteresting(R);
335 report->markInteresting(V);
Jordan Rose68537992012-08-03 23:09:01 +0000336
337 if (V.getAsLocSymbol()) {
338 BugReporterVisitor *ConstraintTracker
339 = new TrackConstraintBRVisitor(cast<loc::MemRegionVal>(V), false);
340 report->addVisitor(ConstraintTracker);
341 }
342
343 report->addVisitor(new FindLastStoreBRVisitor(V, R));
344 return;
Ted Kremenek53500662009-07-22 17:55:28 +0000345 }
346 }
347 }
Mike Stump1eb44332009-09-09 15:08:12 +0000348
Ted Kremenek5eca4822012-01-06 22:09:28 +0000349 SVal V = state->getSValAsScalarOrLoc(S, N->getLocationContext());
Mike Stump1eb44332009-09-09 15:08:12 +0000350
Ted Kremenek53500662009-07-22 17:55:28 +0000351 // Uncomment this to find cases where we aren't properly getting the
352 // base value that was dereferenced.
353 // assert(!V.isUnknownOrUndef());
Mike Stump1eb44332009-09-09 15:08:12 +0000354
Ted Kremenek53500662009-07-22 17:55:28 +0000355 // Is it a symbolic value?
356 if (loc::MemRegionVal *L = dyn_cast<loc::MemRegionVal>(&V)) {
357 const SubRegion *R = cast<SubRegion>(L->getRegion());
358 while (R && !isa<SymbolicRegion>(R)) {
359 R = dyn_cast<SubRegion>(R->getSuperRegion());
360 }
Mike Stump1eb44332009-09-09 15:08:12 +0000361
Ted Kremenek53500662009-07-22 17:55:28 +0000362 if (R) {
Ted Kremenek76aadc32012-03-09 01:13:14 +0000363 report->markInteresting(R);
Jordan Rose68537992012-08-03 23:09:01 +0000364 report->addVisitor(new TrackConstraintBRVisitor(loc::MemRegionVal(R),
365 false));
Ted Kremenek53500662009-07-22 17:55:28 +0000366 }
367 }
368}
Ted Kremenek94fd0b82010-02-16 08:33:59 +0000369
Anna Zaks50bbc162011-08-19 22:33:38 +0000370BugReporterVisitor *
371FindLastStoreBRVisitor::createVisitorObject(const ExplodedNode *N,
372 const MemRegion *R) {
373 assert(R && "The memory region is null.");
Ted Kremenek94fd0b82010-02-16 08:33:59 +0000374
Ted Kremenek8bef8232012-01-26 21:29:00 +0000375 ProgramStateRef state = N->getState();
Ted Kremenek94fd0b82010-02-16 08:33:59 +0000376 SVal V = state->getSVal(R);
Ted Kremenek94fd0b82010-02-16 08:33:59 +0000377 if (V.isUnknown())
Anna Zaks50bbc162011-08-19 22:33:38 +0000378 return 0;
Ted Kremenek94fd0b82010-02-16 08:33:59 +0000379
Anna Zaks50bbc162011-08-19 22:33:38 +0000380 return new FindLastStoreBRVisitor(V, R);
Ted Kremenek94fd0b82010-02-16 08:33:59 +0000381}
Ted Kremenekff7f7362010-03-20 18:02:01 +0000382
383
Anna Zaks50bbc162011-08-19 22:33:38 +0000384PathDiagnosticPiece *NilReceiverBRVisitor::VisitNode(const ExplodedNode *N,
385 const ExplodedNode *PrevN,
386 BugReporterContext &BRC,
387 BugReport &BR) {
388 const PostStmt *P = N->getLocationAs<PostStmt>();
389 if (!P)
390 return 0;
391 const ObjCMessageExpr *ME = P->getStmtAs<ObjCMessageExpr>();
392 if (!ME)
393 return 0;
394 const Expr *Receiver = ME->getInstanceReceiver();
395 if (!Receiver)
396 return 0;
Ted Kremenek8bef8232012-01-26 21:29:00 +0000397 ProgramStateRef state = N->getState();
Ted Kremenek5eca4822012-01-06 22:09:28 +0000398 const SVal &V = state->getSVal(Receiver, N->getLocationContext());
Anna Zaks50bbc162011-08-19 22:33:38 +0000399 const DefinedOrUnknownSVal *DV = dyn_cast<DefinedOrUnknownSVal>(&V);
400 if (!DV)
401 return 0;
402 state = state->assume(*DV, true);
403 if (state)
404 return 0;
Ted Kremenekff7f7362010-03-20 18:02:01 +0000405
Anna Zaks50bbc162011-08-19 22:33:38 +0000406 // The receiver was nil, and hence the method was skipped.
407 // Register a BugReporterVisitor to issue a message telling us how
408 // the receiver was null.
Jordan Rose68537992012-08-03 23:09:01 +0000409 bugreporter::addTrackNullOrUndefValueVisitor(N, Receiver, &BR);
Anna Zaks50bbc162011-08-19 22:33:38 +0000410 // Issue a message saying that the method was skipped.
Anna Zaks220ac8c2011-09-15 01:08:34 +0000411 PathDiagnosticLocation L(Receiver, BRC.getSourceManager(),
412 N->getLocationContext());
Anna Zaks907344e2012-04-05 02:10:19 +0000413 return new PathDiagnosticEventPiece(L, "No method is called "
Anna Zaks50bbc162011-08-19 22:33:38 +0000414 "because the receiver is nil");
Ted Kremenekff7f7362010-03-20 18:02:01 +0000415}
Tom Care2bbbe502010-09-02 23:30:22 +0000416
Anna Zaks8e6431a2011-08-18 22:37:56 +0000417// Registers every VarDecl inside a Stmt with a last store visitor.
Anna Zaks50bbc162011-08-19 22:33:38 +0000418void FindLastStoreBRVisitor::registerStatementVarDecls(BugReport &BR,
419 const Stmt *S) {
Anna Zaks8e6431a2011-08-18 22:37:56 +0000420 const ExplodedNode *N = BR.getErrorNode();
Tom Care2bbbe502010-09-02 23:30:22 +0000421 std::deque<const Stmt *> WorkList;
Tom Care2bbbe502010-09-02 23:30:22 +0000422 WorkList.push_back(S);
423
424 while (!WorkList.empty()) {
425 const Stmt *Head = WorkList.front();
426 WorkList.pop_front();
427
Ted Kremenek8bef8232012-01-26 21:29:00 +0000428 ProgramStateRef state = N->getState();
Anna Zaks8e6431a2011-08-18 22:37:56 +0000429 ProgramStateManager &StateMgr = state->getStateManager();
Tom Care2bbbe502010-09-02 23:30:22 +0000430
431 if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Head)) {
432 if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
433 const VarRegion *R =
434 StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext());
435
436 // What did we load?
Ted Kremenek5eca4822012-01-06 22:09:28 +0000437 SVal V = state->getSVal(S, N->getLocationContext());
Tom Care2bbbe502010-09-02 23:30:22 +0000438
439 if (isa<loc::ConcreteInt>(V) || isa<nonloc::ConcreteInt>(V)) {
Anna Zaks50bbc162011-08-19 22:33:38 +0000440 // Register a new visitor with the BugReport.
441 BR.addVisitor(new FindLastStoreBRVisitor(V, R));
Tom Care2bbbe502010-09-02 23:30:22 +0000442 }
443 }
444 }
445
446 for (Stmt::const_child_iterator I = Head->child_begin();
447 I != Head->child_end(); ++I)
448 WorkList.push_back(*I);
449 }
450}
Ted Kremenek993124e2011-08-06 06:54:45 +0000451
452//===----------------------------------------------------------------------===//
453// Visitor that tries to report interesting diagnostics from conditions.
454//===----------------------------------------------------------------------===//
Anna Zaks50bbc162011-08-19 22:33:38 +0000455PathDiagnosticPiece *ConditionBRVisitor::VisitNode(const ExplodedNode *N,
456 const ExplodedNode *Prev,
457 BugReporterContext &BRC,
458 BugReport &BR) {
Ted Kremenekc89f4b02012-02-28 23:06:21 +0000459 PathDiagnosticPiece *piece = VisitNodeImpl(N, Prev, BRC, BR);
460 if (PathDiagnosticEventPiece *ev =
461 dyn_cast_or_null<PathDiagnosticEventPiece>(piece))
Ted Kremenek76aadc32012-03-09 01:13:14 +0000462 ev->setPrunable(true, /* override */ false);
Ted Kremenekc89f4b02012-02-28 23:06:21 +0000463 return piece;
464}
465
466PathDiagnosticPiece *ConditionBRVisitor::VisitNodeImpl(const ExplodedNode *N,
467 const ExplodedNode *Prev,
468 BugReporterContext &BRC,
469 BugReport &BR) {
Ted Kremenek993124e2011-08-06 06:54:45 +0000470
471 const ProgramPoint &progPoint = N->getLocation();
Ted Kremenek681bc112011-08-16 01:53:41 +0000472
Ted Kremenek8bef8232012-01-26 21:29:00 +0000473 ProgramStateRef CurrentState = N->getState();
474 ProgramStateRef PrevState = Prev->getState();
Ted Kremenek681bc112011-08-16 01:53:41 +0000475
476 // Compare the GDMs of the state, because that is where constraints
477 // are managed. Note that ensure that we only look at nodes that
478 // were generated by the analyzer engine proper, not checkers.
479 if (CurrentState->getGDM().getRoot() ==
480 PrevState->getGDM().getRoot())
481 return 0;
Ted Kremenek993124e2011-08-06 06:54:45 +0000482
483 // If an assumption was made on a branch, it should be caught
484 // here by looking at the state transition.
485 if (const BlockEdge *BE = dyn_cast<BlockEdge>(&progPoint)) {
Ted Kremenek681bc112011-08-16 01:53:41 +0000486 const CFGBlock *srcBlk = BE->getSrc();
487 if (const Stmt *term = srcBlk->getTerminator())
Ted Kremenek76aadc32012-03-09 01:13:14 +0000488 return VisitTerminator(term, N, srcBlk, BE->getDst(), BR, BRC);
Ted Kremenek681bc112011-08-16 01:53:41 +0000489 return 0;
490 }
491
492 if (const PostStmt *PS = dyn_cast<PostStmt>(&progPoint)) {
493 // FIXME: Assuming that BugReporter is a GRBugReporter is a layering
494 // violation.
495 const std::pair<const ProgramPointTag *, const ProgramPointTag *> &tags =
496 cast<GRBugReporter>(BRC.getBugReporter()).
497 getEngine().getEagerlyAssumeTags();
498
499 const ProgramPointTag *tag = PS->getTag();
500 if (tag == tags.first)
Anna Zaks220ac8c2011-09-15 01:08:34 +0000501 return VisitTrueTest(cast<Expr>(PS->getStmt()), true,
Ted Kremenek76aadc32012-03-09 01:13:14 +0000502 BRC, BR, N);
Ted Kremenek681bc112011-08-16 01:53:41 +0000503 if (tag == tags.second)
Anna Zaks220ac8c2011-09-15 01:08:34 +0000504 return VisitTrueTest(cast<Expr>(PS->getStmt()), false,
Ted Kremenek76aadc32012-03-09 01:13:14 +0000505 BRC, BR, N);
Ted Kremenek681bc112011-08-16 01:53:41 +0000506
Ted Kremenek993124e2011-08-06 06:54:45 +0000507 return 0;
508 }
509
510 return 0;
511}
512
513PathDiagnosticPiece *
Anna Zaks50bbc162011-08-19 22:33:38 +0000514ConditionBRVisitor::VisitTerminator(const Stmt *Term,
Anna Zaks220ac8c2011-09-15 01:08:34 +0000515 const ExplodedNode *N,
Anna Zaks50bbc162011-08-19 22:33:38 +0000516 const CFGBlock *srcBlk,
517 const CFGBlock *dstBlk,
Ted Kremenek76aadc32012-03-09 01:13:14 +0000518 BugReport &R,
Anna Zaks50bbc162011-08-19 22:33:38 +0000519 BugReporterContext &BRC) {
Ted Kremenek993124e2011-08-06 06:54:45 +0000520 const Expr *Cond = 0;
521
522 switch (Term->getStmtClass()) {
523 default:
524 return 0;
525 case Stmt::IfStmtClass:
526 Cond = cast<IfStmt>(Term)->getCond();
527 break;
528 case Stmt::ConditionalOperatorClass:
529 Cond = cast<ConditionalOperator>(Term)->getCond();
530 break;
531 }
532
533 assert(Cond);
534 assert(srcBlk->succ_size() == 2);
535 const bool tookTrue = *(srcBlk->succ_begin()) == dstBlk;
536 return VisitTrueTest(Cond->IgnoreParenNoopCasts(BRC.getASTContext()),
Ted Kremenek76aadc32012-03-09 01:13:14 +0000537 tookTrue, BRC, R, N);
Ted Kremenek993124e2011-08-06 06:54:45 +0000538}
539
540PathDiagnosticPiece *
Anna Zaks50bbc162011-08-19 22:33:38 +0000541ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
542 bool tookTrue,
Anna Zaks220ac8c2011-09-15 01:08:34 +0000543 BugReporterContext &BRC,
Ted Kremenek76aadc32012-03-09 01:13:14 +0000544 BugReport &R,
545 const ExplodedNode *N) {
Ted Kremenek993124e2011-08-06 06:54:45 +0000546
547 const Expr *Ex = Cond;
548
Ted Kremenek681bc112011-08-16 01:53:41 +0000549 while (true) {
550 Ex = Ex->IgnoreParens();
Ted Kremenek993124e2011-08-06 06:54:45 +0000551 switch (Ex->getStmtClass()) {
552 default:
553 return 0;
Ted Kremenek681bc112011-08-16 01:53:41 +0000554 case Stmt::BinaryOperatorClass:
Ted Kremenek76aadc32012-03-09 01:13:14 +0000555 return VisitTrueTest(Cond, cast<BinaryOperator>(Ex), tookTrue, BRC,
556 R, N);
Ted Kremenek993124e2011-08-06 06:54:45 +0000557 case Stmt::DeclRefExprClass:
Ted Kremenek76aadc32012-03-09 01:13:14 +0000558 return VisitTrueTest(Cond, cast<DeclRefExpr>(Ex), tookTrue, BRC,
559 R, N);
Ted Kremenek993124e2011-08-06 06:54:45 +0000560 case Stmt::UnaryOperatorClass: {
561 const UnaryOperator *UO = cast<UnaryOperator>(Ex);
562 if (UO->getOpcode() == UO_LNot) {
563 tookTrue = !tookTrue;
564 Ex = UO->getSubExpr()->IgnoreParenNoopCasts(BRC.getASTContext());
565 continue;
566 }
567 return 0;
568 }
569 }
Ted Kremenek681bc112011-08-16 01:53:41 +0000570 }
571}
572
Anna Zaks50bbc162011-08-19 22:33:38 +0000573bool ConditionBRVisitor::patternMatch(const Expr *Ex, llvm::raw_ostream &Out,
Ted Kremenek76aadc32012-03-09 01:13:14 +0000574 BugReporterContext &BRC,
575 BugReport &report,
576 const ExplodedNode *N,
577 llvm::Optional<bool> &prunable) {
Ted Kremenek681bc112011-08-16 01:53:41 +0000578 const Expr *OriginalExpr = Ex;
579 Ex = Ex->IgnoreParenCasts();
580
581 if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex)) {
Ted Kremenek3b9e8e42011-08-16 10:57:37 +0000582 const bool quotes = isa<VarDecl>(DR->getDecl());
Ted Kremenek76aadc32012-03-09 01:13:14 +0000583 if (quotes) {
Ted Kremenek3b9e8e42011-08-16 10:57:37 +0000584 Out << '\'';
Ted Kremenek76aadc32012-03-09 01:13:14 +0000585 const LocationContext *LCtx = N->getLocationContext();
586 const ProgramState *state = N->getState().getPtr();
587 if (const MemRegion *R = state->getLValue(cast<VarDecl>(DR->getDecl()),
588 LCtx).getAsRegion()) {
589 if (report.isInteresting(R))
590 prunable = false;
591 else {
592 const ProgramState *state = N->getState().getPtr();
593 SVal V = state->getSVal(R);
594 if (report.isInteresting(V))
595 prunable = false;
596 }
597 }
598 }
Ted Kremenek3b9e8e42011-08-16 10:57:37 +0000599 Out << DR->getDecl()->getDeclName().getAsString();
600 if (quotes)
601 Out << '\'';
602 return quotes;
Ted Kremenek681bc112011-08-16 01:53:41 +0000603 }
604
605 if (const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(Ex)) {
606 QualType OriginalTy = OriginalExpr->getType();
607 if (OriginalTy->isPointerType()) {
608 if (IL->getValue() == 0) {
609 Out << "null";
Ted Kremenek3b9e8e42011-08-16 10:57:37 +0000610 return false;
Ted Kremenek681bc112011-08-16 01:53:41 +0000611 }
612 }
613 else if (OriginalTy->isObjCObjectPointerType()) {
614 if (IL->getValue() == 0) {
615 Out << "nil";
Ted Kremenek3b9e8e42011-08-16 10:57:37 +0000616 return false;
Ted Kremenek681bc112011-08-16 01:53:41 +0000617 }
618 }
619
620 Out << IL->getValue();
Ted Kremenek3b9e8e42011-08-16 10:57:37 +0000621 return false;
Ted Kremenek681bc112011-08-16 01:53:41 +0000622 }
Ted Kremenek3b9e8e42011-08-16 10:57:37 +0000623
624 return false;
Ted Kremenek681bc112011-08-16 01:53:41 +0000625}
626
627PathDiagnosticPiece *
Anna Zaks50bbc162011-08-19 22:33:38 +0000628ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
629 const BinaryOperator *BExpr,
630 const bool tookTrue,
Anna Zaks220ac8c2011-09-15 01:08:34 +0000631 BugReporterContext &BRC,
Ted Kremenek76aadc32012-03-09 01:13:14 +0000632 BugReport &R,
633 const ExplodedNode *N) {
Ted Kremenek681bc112011-08-16 01:53:41 +0000634
Ted Kremenek3b9e8e42011-08-16 10:57:37 +0000635 bool shouldInvert = false;
Ted Kremenek76aadc32012-03-09 01:13:14 +0000636 llvm::Optional<bool> shouldPrune;
Ted Kremenek3b9e8e42011-08-16 10:57:37 +0000637
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +0000638 SmallString<128> LhsString, RhsString;
Ted Kremenek681bc112011-08-16 01:53:41 +0000639 {
Ted Kremenek76aadc32012-03-09 01:13:14 +0000640 llvm::raw_svector_ostream OutLHS(LhsString), OutRHS(RhsString);
641 const bool isVarLHS = patternMatch(BExpr->getLHS(), OutLHS, BRC, R, N,
642 shouldPrune);
643 const bool isVarRHS = patternMatch(BExpr->getRHS(), OutRHS, BRC, R, N,
644 shouldPrune);
Ted Kremenek3b9e8e42011-08-16 10:57:37 +0000645
646 shouldInvert = !isVarLHS && isVarRHS;
Ted Kremenek681bc112011-08-16 01:53:41 +0000647 }
648
Ted Kremenekd1247c52012-01-04 08:18:09 +0000649 BinaryOperator::Opcode Op = BExpr->getOpcode();
650
651 if (BinaryOperator::isAssignmentOp(Op)) {
652 // For assignment operators, all that we care about is that the LHS
653 // evaluates to "true" or "false".
654 return VisitConditionVariable(LhsString, BExpr->getLHS(), tookTrue,
Ted Kremenek76aadc32012-03-09 01:13:14 +0000655 BRC, R, N);
Ted Kremenekd1247c52012-01-04 08:18:09 +0000656 }
657
658 // For non-assignment operations, we require that we can understand
659 // both the LHS and RHS.
Ted Kremenek681bc112011-08-16 01:53:41 +0000660 if (LhsString.empty() || RhsString.empty())
661 return 0;
Ted Kremenek3b9e8e42011-08-16 10:57:37 +0000662
Ted Kremenekd1247c52012-01-04 08:18:09 +0000663 // Should we invert the strings if the LHS is not a variable name?
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +0000664 SmallString<256> buf;
Ted Kremenek681bc112011-08-16 01:53:41 +0000665 llvm::raw_svector_ostream Out(buf);
Ted Kremenek3b9e8e42011-08-16 10:57:37 +0000666 Out << "Assuming " << (shouldInvert ? RhsString : LhsString) << " is ";
Ted Kremenek681bc112011-08-16 01:53:41 +0000667
668 // Do we need to invert the opcode?
Ted Kremenek3b9e8e42011-08-16 10:57:37 +0000669 if (shouldInvert)
670 switch (Op) {
671 default: break;
672 case BO_LT: Op = BO_GT; break;
673 case BO_GT: Op = BO_LT; break;
674 case BO_LE: Op = BO_GE; break;
675 case BO_GE: Op = BO_LE; break;
676 }
677
Ted Kremenek681bc112011-08-16 01:53:41 +0000678 if (!tookTrue)
679 switch (Op) {
680 case BO_EQ: Op = BO_NE; break;
681 case BO_NE: Op = BO_EQ; break;
682 case BO_LT: Op = BO_GE; break;
683 case BO_GT: Op = BO_LE; break;
684 case BO_LE: Op = BO_GT; break;
Ted Kremenek4ee7c9c2011-08-16 03:44:38 +0000685 case BO_GE: Op = BO_LT; break;
Ted Kremenek681bc112011-08-16 01:53:41 +0000686 default:
687 return 0;
688 }
689
Ted Kremenek6ae32572011-12-20 22:00:25 +0000690 switch (Op) {
Ted Kremenek681bc112011-08-16 01:53:41 +0000691 case BO_EQ:
692 Out << "equal to ";
693 break;
694 case BO_NE:
695 Out << "not equal to ";
696 break;
697 default:
698 Out << BinaryOperator::getOpcodeStr(Op) << ' ';
699 break;
700 }
701
Ted Kremenek3b9e8e42011-08-16 10:57:37 +0000702 Out << (shouldInvert ? LhsString : RhsString);
Ted Kremenek76aadc32012-03-09 01:13:14 +0000703 const LocationContext *LCtx = N->getLocationContext();
704 PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
705 PathDiagnosticEventPiece *event =
706 new PathDiagnosticEventPiece(Loc, Out.str());
707 if (shouldPrune.hasValue())
708 event->setPrunable(shouldPrune.getValue());
709 return event;
Ted Kremenek993124e2011-08-06 06:54:45 +0000710}
Ted Kremenekd1247c52012-01-04 08:18:09 +0000711
712PathDiagnosticPiece *
713ConditionBRVisitor::VisitConditionVariable(StringRef LhsString,
714 const Expr *CondVarExpr,
715 const bool tookTrue,
716 BugReporterContext &BRC,
Ted Kremenek76aadc32012-03-09 01:13:14 +0000717 BugReport &report,
718 const ExplodedNode *N) {
Jordan Roseb0e1bad2012-08-03 23:08:54 +0000719 // FIXME: If there's already a constraint tracker for this variable,
720 // we shouldn't emit anything here (c.f. the double note in
721 // test/Analysis/inlining/path-notes.c)
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +0000722 SmallString<256> buf;
Ted Kremenekd1247c52012-01-04 08:18:09 +0000723 llvm::raw_svector_ostream Out(buf);
724 Out << "Assuming " << LhsString << " is ";
725
726 QualType Ty = CondVarExpr->getType();
727
728 if (Ty->isPointerType())
729 Out << (tookTrue ? "not null" : "null");
730 else if (Ty->isObjCObjectPointerType())
731 Out << (tookTrue ? "not nil" : "nil");
732 else if (Ty->isBooleanType())
733 Out << (tookTrue ? "true" : "false");
734 else if (Ty->isIntegerType())
735 Out << (tookTrue ? "non-zero" : "zero");
736 else
737 return 0;
738
Ted Kremenek76aadc32012-03-09 01:13:14 +0000739 const LocationContext *LCtx = N->getLocationContext();
740 PathDiagnosticLocation Loc(CondVarExpr, BRC.getSourceManager(), LCtx);
741 PathDiagnosticEventPiece *event =
742 new PathDiagnosticEventPiece(Loc, Out.str());
743
744 if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(CondVarExpr)) {
745 if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
746 const ProgramState *state = N->getState().getPtr();
747 if (const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) {
748 if (report.isInteresting(R))
749 event->setPrunable(false);
750 }
751 }
752 }
753
754 return event;
Ted Kremenekd1247c52012-01-04 08:18:09 +0000755}
Ted Kremenek993124e2011-08-06 06:54:45 +0000756
757PathDiagnosticPiece *
Anna Zaks50bbc162011-08-19 22:33:38 +0000758ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
759 const DeclRefExpr *DR,
760 const bool tookTrue,
Anna Zaks220ac8c2011-09-15 01:08:34 +0000761 BugReporterContext &BRC,
Ted Kremenek76aadc32012-03-09 01:13:14 +0000762 BugReport &report,
763 const ExplodedNode *N) {
Ted Kremenek993124e2011-08-06 06:54:45 +0000764
765 const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
766 if (!VD)
767 return 0;
768
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +0000769 SmallString<256> Buf;
Ted Kremenek993124e2011-08-06 06:54:45 +0000770 llvm::raw_svector_ostream Out(Buf);
771
772 Out << "Assuming '";
773 VD->getDeclName().printName(Out);
774 Out << "' is ";
775
776 QualType VDTy = VD->getType();
777
778 if (VDTy->isPointerType())
779 Out << (tookTrue ? "non-null" : "null");
780 else if (VDTy->isObjCObjectPointerType())
781 Out << (tookTrue ? "non-nil" : "nil");
782 else if (VDTy->isScalarType())
783 Out << (tookTrue ? "not equal to 0" : "0");
784 else
785 return 0;
786
Ted Kremenek76aadc32012-03-09 01:13:14 +0000787 const LocationContext *LCtx = N->getLocationContext();
788 PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
789 PathDiagnosticEventPiece *event =
790 new PathDiagnosticEventPiece(Loc, Out.str());
791
792 const ProgramState *state = N->getState().getPtr();
793 if (const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) {
794 if (report.isInteresting(R))
795 event->setPrunable(false);
796 else {
797 SVal V = state->getSVal(R);
798 if (report.isInteresting(V))
799 event->setPrunable(false);
800 }
801 }
802 return event;
Ted Kremenek993124e2011-08-06 06:54:45 +0000803}
Ted Kremenek0cf3d472012-02-07 00:24:33 +0000804