summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h51
-rw-r--r--clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h166
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp9
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp2
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp2
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp14
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp8
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp4
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp4
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp5
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp2
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp4
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp5
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp4
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp4
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp2
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp4
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp4
-rw-r--r--clang/lib/StaticAnalyzer/Core/BugReporter.cpp4
-rw-r--r--clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp534
20 files changed, 423 insertions, 409 deletions
diff --git a/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
index 421e305508a..a8923be63f6 100644
--- a/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
+++ b/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
@@ -16,6 +16,7 @@
#define LLVM_CLANG_GR_BUGREPORTER
#include "clang/Basic/SourceLocation.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/ImmutableList.h"
@@ -48,24 +49,6 @@ class BugType;
// Interface for individual bug reports.
//===----------------------------------------------------------------------===//
-class BugReporterVisitor : public llvm::FoldingSetNode {
-public:
- virtual ~BugReporterVisitor();
-
- /// \brief Return a diagnostic piece which should be associated with the
- /// given node.
- ///
- /// The last parameter can be used to register a new visitor with the given
- /// BugReport while processing a node.
- virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
- BugReporterContext &BRC,
- BugReport &BR) = 0;
-
- virtual bool isOwnedByReporterContext() { return true; }
- virtual void Profile(llvm::FoldingSetNodeID &ID) const = 0;
-};
-
/// This class provides an interface through which checkers can create
/// individual bug reports.
class BugReport : public BugReporterVisitor {
@@ -77,14 +60,12 @@ public:
getOriginalNode(const ExplodedNode *N) = 0;
};
- typedef void (*VisitorCreator)(BugReport &BR, const void *data);
typedef const SourceRange *ranges_iterator;
typedef llvm::ImmutableList<BugReporterVisitor*>::iterator visitor_iterator;
protected:
friend class BugReporter;
friend class BugReportEquivClass;
- typedef SmallVector<std::pair<VisitorCreator, const void*>, 2> Creators;
BugType& BT;
std::string ShortDescription;
@@ -178,11 +159,7 @@ public:
/// \sa registerConditionVisitor(), registerTrackNullOrUndefValue(),
/// registerFindLastStore(), registerNilReceiverVisitor(), and
/// registerVarDeclsLastStore().
- void addVisitorCreator(VisitorCreator creator, const void *data) {
- creator(*this, data);
- }
-
- void addVisitor(BugReporterVisitor* visitor);
+ void addVisitor(BugReporterVisitor *visitor);
/// Iterators through the custom diagnostic visitors.
visitor_iterator visitor_begin() { return Callbacks.begin(); }
@@ -445,30 +422,6 @@ public:
virtual BugReport::NodeResolver& getNodeResolver() = 0;
};
-//===----------------------------------------------------------------------===//
-//===----------------------------------------------------------------------===//
-
-namespace bugreporter {
-
-const Stmt *GetDerefExpr(const ExplodedNode *N);
-const Stmt *GetDenomExpr(const ExplodedNode *N);
-const Stmt *GetCalleeExpr(const ExplodedNode *N);
-const Stmt *GetRetValExpr(const ExplodedNode *N);
-
-void registerConditionVisitor(BugReport &BR);
-
-void registerTrackNullOrUndefValue(BugReport &BR, const void *stmt);
-
-void registerFindLastStore(BugReport &BR, const void *memregion);
-
-void registerNilReceiverVisitor(BugReport &BR);
-
-void registerVarDeclsLastStore(BugReport &BR, const void *stmt);
-
-} // end namespace clang::bugreporter
-
-//===----------------------------------------------------------------------===//
-
} // end GR namespace
} // end clang namespace
diff --git a/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h b/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h
new file mode 100644
index 00000000000..4533616d99a
--- /dev/null
+++ b/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h
@@ -0,0 +1,166 @@
+//===--- BugReporterVisitor.h - Generate PathDiagnostics -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares BugReporterVisitors, which are used to generate enhanced
+// diagnostic traces.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GR_BUGREPORTERVISITOR
+#define LLVM_CLANG_GR_BUGREPORTERVISITOR
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "llvm/ADT/FoldingSet.h"
+
+namespace clang {
+
+namespace ento {
+
+class BugReport;
+class BugReporterContext;
+class ExplodedNode;
+class MemRegion;
+class PathDiagnosticPiece;
+
+class BugReporterVisitor : public llvm::FoldingSetNode {
+public:
+ virtual ~BugReporterVisitor();
+
+ /// \brief Return a diagnostic piece which should be associated with the
+ /// given node.
+ ///
+ /// The last parameter can be used to register a new visitor with the given
+ /// BugReport while processing a node.
+ virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
+ const ExplodedNode *PrevN,
+ BugReporterContext &BRC,
+ BugReport &BR) = 0;
+
+ virtual bool isOwnedByReporterContext() { return true; }
+ virtual void Profile(llvm::FoldingSetNodeID &ID) const = 0;
+};
+
+class FindLastStoreBRVisitor : public BugReporterVisitor {
+ const MemRegion *R;
+ SVal V;
+ bool satisfied;
+ const ExplodedNode *StoreSite;
+
+public:
+ /// \brief Convenience method to create a visitor given only the MemRegion.
+ /// Returns NULL if the visitor cannot be created. For example, when the
+ /// corresponding value is unknown.
+ static BugReporterVisitor *createVisitorObject(const ExplodedNode *N,
+ const MemRegion *R);
+
+ /// Creates a visitor for every VarDecl inside a Stmt and registers it with
+ /// the BugReport.
+ static void registerStatementVarDecls(BugReport &BR, const Stmt *S);
+
+ FindLastStoreBRVisitor(SVal v, const MemRegion *r)
+ : R(r), V(v), satisfied(false), StoreSite(0) {
+ assert (!V.isUnknown() && "Cannot track unknown value.");
+
+ // TODO: Does it make sense to allow undef values here?
+ // (If not, also see UndefCapturedBlockVarChecker)?
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const;
+
+ PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
+ const ExplodedNode *PrevN,
+ BugReporterContext &BRC,
+ BugReport &BR);
+};
+
+class TrackConstraintBRVisitor : public BugReporterVisitor {
+ DefinedSVal Constraint;
+ const bool Assumption;
+ bool isSatisfied;
+
+public:
+ TrackConstraintBRVisitor(DefinedSVal constraint, bool assumption)
+ : Constraint(constraint), Assumption(assumption), isSatisfied(false) {}
+
+ void Profile(llvm::FoldingSetNodeID &ID) const;
+
+ PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
+ const ExplodedNode *PrevN,
+ BugReporterContext &BRC,
+ BugReport &BR);
+};
+
+class NilReceiverBRVisitor : public BugReporterVisitor {
+public:
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ static int x = 0;
+ ID.AddPointer(&x);
+ }
+
+ PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
+ const ExplodedNode *PrevN,
+ BugReporterContext &BRC,
+ BugReport &BR);
+};
+
+/// Visitor that tries to report interesting diagnostics from conditions.
+class ConditionBRVisitor : public BugReporterVisitor {
+public:
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ static int x = 0;
+ ID.AddPointer(&x);
+ }
+
+ virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
+ const ExplodedNode *Prev,
+ BugReporterContext &BRC,
+ BugReport &BR);
+
+ PathDiagnosticPiece *VisitTerminator(const Stmt *Term,
+ const ProgramState *CurrentState,
+ const ProgramState *PrevState,
+ const CFGBlock *srcBlk,
+ const CFGBlock *dstBlk,
+ BugReporterContext &BRC);
+
+ PathDiagnosticPiece *VisitTrueTest(const Expr *Cond,
+ bool tookTrue,
+ BugReporterContext &BRC);
+
+ PathDiagnosticPiece *VisitTrueTest(const Expr *Cond,
+ const DeclRefExpr *DR,
+ const bool tookTrue,
+ BugReporterContext &BRC);
+
+ PathDiagnosticPiece *VisitTrueTest(const Expr *Cond,
+ const BinaryOperator *BExpr,
+ const bool tookTrue,
+ BugReporterContext &BRC);
+
+ bool patternMatch(const Expr *Ex,
+ llvm::raw_ostream &Out,
+ BugReporterContext &BRC);
+};
+
+namespace bugreporter {
+
+BugReporterVisitor *getTrackNullOrUndefValueVisitor(const ExplodedNode *N,
+ const Stmt *S);
+
+const Stmt *GetDerefExpr(const ExplodedNode *N);
+const Stmt *GetDenomExpr(const ExplodedNode *N);
+const Stmt *GetCalleeExpr(const ExplodedNode *N);
+const Stmt *GetRetValExpr(const ExplodedNode *N);
+
+} // end namespace clang
+} // end namespace ento
+} // end namespace bugreporter
+
+
+#endif //LLVM_CLANG_GR__BUGREPORTERVISITOR
diff --git a/clang/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp
index 285b3920fa4..8296eb93c5a 100644
--- a/clang/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp
@@ -101,15 +101,14 @@ void AttrNonNullChecker::checkPreStmt(const CallExpr *CE,
"API"));
BugReport *R =
- new BugReport(*BT,
- "Null pointer passed as an argument to a "
- "'nonnull' parameter", errorNode);
+ new BugReport(*BT, "Null pointer passed as an argument to a "
+ "'nonnull' parameter", errorNode);
// Highlight the range of the argument that was null.
const Expr *arg = *I;
R->addRange(arg->getSourceRange());
- R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, arg);
-
+ R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(errorNode,
+ arg));
// Emit the bug report.
C.EmitReport(R);
}
diff --git a/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp b/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
index da592050ebc..1631df8af98 100644
--- a/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
@@ -414,7 +414,7 @@ void CFRetainReleaseChecker::checkPreStmt(const CallExpr *CE,
BugReport *report = new BugReport(*BT, description, N);
report->addRange(Arg->getSourceRange());
- report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, Arg);
+ report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, Arg));
C.EmitReport(report);
return;
}
diff --git a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
index c5d4379fcbb..d043e2d8aef 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -231,7 +231,7 @@ const ProgramState *CStringChecker::checkNonNull(CheckerContext &C,
BugReport *report = new BugReport(*BT, os.str(), N);
report->addRange(S->getSourceRange());
- report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, S);
+ report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, S));
C.EmitReport(report);
return NULL;
}
diff --git a/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
index 191d4bba02a..ba1dae87387 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
@@ -65,8 +65,8 @@ void CallAndMessageChecker::EmitBadCall(BugType *BT, CheckerContext &C,
return;
BugReport *R = new BugReport(*BT, BT->getName(), N);
- R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
- bugreporter::GetCalleeExpr(N));
+ R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N,
+ bugreporter::GetCalleeExpr(N)));
C.EmitReport(R);
}
@@ -95,7 +95,7 @@ bool CallAndMessageChecker::PreVisitProcessArg(CheckerContext &C,
BugReport *R = new BugReport(*BT, BT->getName(), N);
R->addRange(argRange);
if (argEx)
- R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, argEx);
+ R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, argEx));
C.EmitReport(R);
}
return true;
@@ -230,8 +230,8 @@ void CallAndMessageChecker::checkPreObjCMessage(ObjCMessage msg,
BugReport *R =
new BugReport(*BT_msg_undef, BT_msg_undef->getName(), N);
R->addRange(receiver->getSourceRange());
- R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
- receiver);
+ R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N,
+ receiver));
C.EmitReport(R);
}
return;
@@ -275,8 +275,8 @@ void CallAndMessageChecker::emitNilReceiverBug(CheckerContext &C,
BugReport *report = new BugReport(*BT_msg_ret, os.str(), N);
if (const Expr *receiver = msg.getInstanceReceiver()) {
report->addRange(receiver->getSourceRange());
- report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
- receiver);
+ report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N,
+ receiver));
}
C.EmitReport(report);
}
diff --git a/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
index 22af688547c..c416dd8e8ed 100644
--- a/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
@@ -75,8 +75,8 @@ void DereferenceChecker::checkLocation(SVal l, bool isLoad,
BugReport *report =
new BugReport(*BT_undef, BT_undef->getDescription(), N);
- report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
- bugreporter::GetDerefExpr(N));
+ report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N,
+ bugreporter::GetDerefExpr(N)));
C.EmitReport(report);
}
return;
@@ -162,8 +162,8 @@ void DereferenceChecker::checkLocation(SVal l, bool isLoad,
buf.empty() ? BT_null->getDescription():buf.str(),
N);
- report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
- bugreporter::GetDerefExpr(N));
+ report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N,
+ bugreporter::GetDerefExpr(N)));
for (SmallVectorImpl<SourceRange>::iterator
I = Ranges.begin(), E = Ranges.end(); I!=E; ++I)
diff --git a/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp
index d87c773d6e7..75b7cc47aa7 100644
--- a/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp
@@ -63,8 +63,8 @@ void DivZeroChecker::checkPreStmt(const BinaryOperator *B,
BugReport *R =
new BugReport(*BT, BT->getDescription(), N);
- R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
- bugreporter::GetDenomExpr(N));
+ R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N,
+ bugreporter::GetDenomExpr(N)));
C.EmitReport(R);
}
diff --git a/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp
index af819ecf30e..46f06a0a848 100644
--- a/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp
@@ -413,12 +413,12 @@ void IdempotentOperationChecker::checkEndAnalysis(ExplodedGraph &G,
if (LHSRelevant) {
const Expr *LHS = i->first->getLHS();
report->addRange(LHS->getSourceRange());
- report->addVisitorCreator(bugreporter::registerVarDeclsLastStore, LHS);
+ FindLastStoreBRVisitor::registerStatementVarDecls(*report, LHS);
}
if (RHSRelevant) {
const Expr *RHS = i->first->getRHS();
report->addRange(i->first->getRHS()->getSourceRange());
- report->addVisitorCreator(bugreporter::registerVarDeclsLastStore, RHS);
+ FindLastStoreBRVisitor::registerStatementVarDecls(*report, RHS);
}
BR.EmitReport(report);
diff --git a/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
index 7b964a44ba8..3e4e07b6505 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
@@ -49,7 +49,7 @@ void ObjCAtSyncChecker::checkPreStmt(const ObjCAtSynchronizedStmt *S,
"for @synchronized"));
BugReport *report =
new BugReport(*BT_undef, BT_undef->getDescription(), N);
- report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, Ex);
+ report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, Ex));
C.EmitReport(report);
}
return;
@@ -72,8 +72,7 @@ void ObjCAtSyncChecker::checkPreStmt(const ObjCAtSynchronizedStmt *S,
"(no synchronization will occur)"));
BugReport *report =
new BugReport(*BT_null, BT_null->getDescription(), N);
- report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
- Ex);
+ report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, Ex));
C.EmitReport(report);
return;
diff --git a/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp
index 979c1077925..e8c8d902a5e 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp
@@ -54,7 +54,7 @@ void ReturnUndefChecker::checkPreStmt(const ReturnStmt *RS,
new BugReport(*BT, BT->getDescription(), N);
report->addRange(RetE->getSourceRange());
- report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, RetE);
+ report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, RetE));
C.EmitReport(report);
}
diff --git a/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
index f29cac60282..de20e89dff7 100644
--- a/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
@@ -99,8 +99,8 @@ void UndefBranchChecker::checkBranchCondition(const Stmt *Condition,
Ex = FindIt.FindExpr(Ex);
// Emit the bug report.
- BugReport *R = new BugReport(*BT, BT->getDescription(),N);
- R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, Ex);
+ BugReport *R = new BugReport(*BT, BT->getDescription(), N);
+ R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, Ex));
R->addRange(Ex->getSourceRange());
Eng.getBugReporter().EmitReport(R);
diff --git a/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
index 486ddbb1355..2aebed9346d 100644
--- a/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
@@ -74,8 +74,9 @@ UndefCapturedBlockVarChecker::checkPostStmt(const BlockExpr *BE,
// Get the VarRegion associated with VD in the local stack frame.
const LocationContext *LC = C.getPredecessor()->getLocationContext();
VR = C.getSValBuilder().getRegionManager().getVarRegion(VD, LC);
+ SVal VRVal = state->getSVal(VR);
- if (state->getSVal(VR).isUndef())
+ if (VRVal.isUndef())
if (ExplodedNode *N = C.generateSink()) {
if (!BT)
BT.reset(new BuiltinBug("uninitialized variable captured by block"));
@@ -90,7 +91,7 @@ UndefCapturedBlockVarChecker::checkPostStmt(const BlockExpr *BE,
BugReport *R = new BugReport(*BT, os.str(), N);
if (const Expr *Ex = FindBlockDeclRefExpr(BE->getBody(), VD))
R->addRange(Ex->getSourceRange());
- R->addVisitorCreator(bugreporter::registerFindLastStore, VR);
+ R->addVisitor(new FindLastStoreBRVisitor(VRVal, VR));
// need location of block
C.EmitReport(R);
}
diff --git a/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
index 1074688562d..7ae966865c8 100644
--- a/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
@@ -74,10 +74,10 @@ void UndefResultChecker::checkPostStmt(const BinaryOperator *B,
BugReport *report = new BugReport(*BT, OS.str(), N);
if (Ex) {
report->addRange(Ex->getSourceRange());
- report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, Ex);
+ report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, Ex));
}
else
- report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, B);
+ report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, B));
C.EmitReport(report);
}
}
diff --git a/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp
index 92e656109ff..bb6831b7830 100644
--- a/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp
@@ -42,8 +42,8 @@ UndefinedArraySubscriptChecker::checkPreStmt(const ArraySubscriptExpr *A,
// Generate a report for this bug.
BugReport *R = new BugReport(*BT, BT->getName(), N);
R->addRange(A->getIdx()->getSourceRange());
- R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
- A->getIdx());
+ R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N,
+ A->getIdx()));
C.EmitReport(R);
}
}
diff --git a/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
index 6f937c6816a..b0c4bee424f 100644
--- a/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
@@ -77,7 +77,7 @@ void UndefinedAssignmentChecker::checkBind(SVal location, SVal val,
BugReport *R = new BugReport(*BT, str, N);
if (ex) {
R->addRange(ex->getSourceRange());
- R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, ex);
+ R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, ex));
}
C.EmitReport(R);
}
diff --git a/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
index f6931fc09f0..336df59bd8d 100644
--- a/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
@@ -206,8 +206,8 @@ void UnixAPIChecker::CheckMallocZero(CheckerContext &C,
new BugReport(*BT_mallocZero, "Call to 'malloc' has an allocation"
" size of 0 bytes", N);
report->addRange(CE->getArg(0)->getSourceRange());
- report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
- CE->getArg(0));
+ report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N,
+ CE->getArg(0)));
C.EmitReport(report);
return;
}
diff --git a/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
index 61590b296a2..b34b97c5b30 100644
--- a/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
@@ -65,7 +65,7 @@ void VLASizeChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
BugReport *report =
new BugReport(*BT_undef, BT_undef->getName(), N);
report->addRange(SE->getSourceRange());
- report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, SE);
+ report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, SE));
C.EmitReport(report);
return;
}
@@ -90,7 +90,7 @@ void VLASizeChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
BugReport *report =
new BugReport(*BT_zero, BT_zero->getName(), N);
report->addRange(SE->getSourceRange());
- report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, SE);
+ report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, SE));
C.EmitReport(report);
return;
}
diff --git a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
index 6821806c846..fb0331c2745 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -1672,8 +1672,8 @@ void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
return;
// Register additional node visitors.
- bugreporter::registerNilReceiverVisitor(*R);
- bugreporter::registerConditionVisitor(*R);
+ R->addVisitor(new NilReceiverBRVisitor());
+ R->addVisitor(new ConditionBRVisitor());
switch (PDB.getGenerationScheme()) {
case PathDiagnosticClient::Extensive:
diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index b6e726fd0be..9fbccf8f813 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -11,6 +11,7 @@
// enhance the diagnostics reported for a bug.
//
//===----------------------------------------------------------------------===//
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprObjC.h"
@@ -71,249 +72,213 @@ const Stmt *bugreporter::GetRetValExpr(const ExplodedNode *N) {
//===----------------------------------------------------------------------===//
// Definitions for bug reporter visitors.
//===----------------------------------------------------------------------===//
+void FindLastStoreBRVisitor ::Profile(llvm::FoldingSetNodeID &ID) const {
+ static int tag = 0;
+ ID.AddPointer(&tag);
+ ID.AddPointer(R);
+ ID.Add(V);
+}
-namespace {
-class FindLastStoreBRVisitor : public BugReporterVisitor {
- const MemRegion *R;
- SVal V;
- bool satisfied;
- const ExplodedNode *StoreSite;
-public:
- FindLastStoreBRVisitor(SVal v, const MemRegion *r)
- : R(r), V(v), satisfied(false), StoreSite(0) {}
-
- virtual void Profile(llvm::FoldingSetNodeID &ID) const {
- static int tag = 0;
- ID.AddPointer(&tag);
- ID.AddPointer(R);
- ID.Add(V);
- }
-
- PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
- BugReporterContext &BRC,
- BugReport &BR) {
-
- if (satisfied)
- return NULL;
-
- if (!StoreSite) {
- const ExplodedNode *Node = N, *Last = NULL;
+PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *N,
+ const ExplodedNode *PrevN,
+ BugReporterContext &BRC,
+ BugReport &BR) {
- for ( ; Node ; Last = Node, Node = Node->getFirstPred()) {
+ if (satisfied)
+ return NULL;
- if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
- if (const PostStmt *P = Node->getLocationAs<PostStmt>())
- if (const DeclStmt *DS = P->getStmtAs<DeclStmt>())
- if (DS->getSingleDecl() == VR->getDecl()) {
- Last = Node;
- break;
- }
- }
+ if (!StoreSite) {
+ const ExplodedNode *Node = N, *Last = NULL;
- if (Node->getState()->getSVal(R) != V)
- break;
- }
+ for ( ; Node ; Last = Node, Node = Node->getFirstPred()) {
- if (!Node || !Last) {
- satisfied = true;
- return NULL;
+ if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
+ if (const PostStmt *P = Node->getLocationAs<PostStmt>())
+ if (const DeclStmt *DS = P->getStmtAs<DeclStmt>())
+ if (DS->getSingleDecl() == VR->getDecl()) {
+ Last = Node;
+ break;
+ }
}
- StoreSite = Last;
+ if (Node->getState()->getSVal(R) != V)
+ break;
}
- if (StoreSite != N)
+ if (!Node || !Last) {
+ satisfied = true;
return NULL;
+ }
- satisfied = true;
- llvm::SmallString<256> sbuf;
- llvm::raw_svector_ostream os(sbuf);
+ StoreSite = Last;
+ }
- if (const PostStmt *PS = N->getLocationAs<PostStmt>()) {
- if (const DeclStmt *DS = PS->getStmtAs<DeclStmt>()) {
+ if (StoreSite != N)
+ return NULL;
- if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
- os << "Variable '" << VR->getDecl() << "' ";
- }
- else
- return NULL;
-
- if (isa<loc::ConcreteInt>(V)) {
- bool b = false;
- if (R->isBoundable()) {
- if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
- if (TR->getValueType()->isObjCObjectPointerType()) {
- os << "initialized to nil";
- b = true;
- }
- }
- }
+ satisfied = true;
+ llvm::SmallString<256> sbuf;
+ llvm::raw_svector_ostream os(sbuf);
- if (!b)
- os << "initialized to a null pointer value";
- }
- else if (isa<nonloc::ConcreteInt>(V)) {
- os << "initialized to " << cast<nonloc::ConcreteInt>(V).getValue();
- }
- else if (V.isUndef()) {
- if (isa<VarRegion>(R)) {
- const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl());
- if (VD->getInit())
- os << "initialized to a garbage value";
- else
- os << "declared without an initial value";
- }
- }
+ if (const PostStmt *PS = N->getLocationAs<PostStmt>()) {
+ if (const DeclStmt *DS = PS->getStmtAs<DeclStmt>()) {
+
+ if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
+ os << "Variable '" << VR->getDecl() << "' ";
}
- }
+ else
+ return NULL;
- if (os.str().empty()) {
if (isa<loc::ConcreteInt>(V)) {
bool b = false;
if (R->isBoundable()) {
if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
if (TR->getValueType()->isObjCObjectPointerType()) {
- os << "nil object reference stored to ";
+ os << "initialized to nil";
b = true;
}
}
}
if (!b)
- os << "Null pointer value stored to ";
- }
- else if (V.isUndef()) {
- os << "Uninitialized value stored to ";
+ os << "initialized to a null pointer value";
}
else if (isa<nonloc::ConcreteInt>(V)) {
- os << "The value " << cast<nonloc::ConcreteInt>(V).getValue()
- << " is assigned to ";
+ os << "initialized to " << cast<nonloc::ConcreteInt>(V).getValue();
}
- else
- return NULL;
-
- if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
- os << '\'' << VR->getDecl() << '\'';
+ else if (V.isUndef()) {
+ if (isa<VarRegion>(R)) {
+ const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl());
+ if (VD->getInit())
+ os << "initialized to a garbage value";
+ else
+ os << "declared without an initial value";
+ }
}
- else
- return NULL;
}
+ }
- // FIXME: Refactor this into BugReporterContext.
- const Stmt *S = 0;
- ProgramPoint P = N->getLocation();
+ if (os.str().empty()) {
+ if (isa<loc::ConcreteInt>(V)) {
+ bool b = false;
+ if (R->isBoundable()) {
+ if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
+ if (TR->getValueType()->isObjCObjectPointerType()) {
+ os << "nil object reference stored to ";
+ b = true;
+ }
+ }
+ }
- if (BlockEdge *BE = dyn_cast<BlockEdge>(&P)) {
- const CFGBlock *BSrc = BE->getSrc();
- S = BSrc->getTerminatorCondition();
+ if (!b)
+ os << "Null pointer value stored to ";
}
- else if (PostStmt *PS = dyn_cast<PostStmt>(&P)) {
- S = PS->getStmt();
+ else if (V.isUndef()) {
+ os << "Uninitialized value stored to ";
}
-
- if (!S)
+ else if (isa<nonloc::ConcreteInt>(V)) {
+ os << "The value " << cast<nonloc::ConcreteInt>(V).getValue()
+ << " is assigned to ";
+ }
+ else
return NULL;
- // Construct a new PathDiagnosticPiece.
- PathDiagnosticLocation L(S, BRC.getSourceManager());
- return new PathDiagnosticEventPiece(L, os.str());
+ if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
+ os << '\'' << VR->getDecl() << '\'';
+ }
+ else
+ return NULL;
}
-};
+ // FIXME: Refactor this into BugReporterContext.
+ const Stmt *S = 0;
+ ProgramPoint P = N->getLocation();
-static void registerFindLastStore(BugReport &BR, const MemRegion *R,
- SVal V) {
- BR.addVisitor(new FindLastStoreBRVisitor(V, R));
-}
-
-class TrackConstraintBRVisitor : public BugReporterVisitor {
- DefinedSVal Constraint;
- const bool Assumption;
- bool isSatisfied;
-public:
- TrackConstraintBRVisitor(DefinedSVal constraint, bool assumption)
- : Constraint(constraint), Assumption(assumption), isSatisfied(false) {}
-
- void Profile(llvm::FoldingSetNodeID &ID) const {
- static int tag = 0;
- ID.AddPointer(&tag);
- ID.AddBoolean(Assumption);
- ID.Add(Constraint);
+ if (BlockEdge *BE = dyn_cast<BlockEdge>(&P)) {
+ const CFGBlock *BSrc = BE->getSrc();
+ S = BSrc->getTerminatorCondition();
+ }
+ else if (PostStmt *PS = dyn_cast<PostStmt>(&P)) {
+ S = PS->getStmt();
}
- PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
- BugReporterContext &BRC,
- BugReport &BR) {
- if (isSatisfied)
- return NULL;
+ if (!S)
+ return NULL;
- // Check if in the previous state it was feasible for this constraint
- // to *not* be true.
- if (PrevN->getState()->assume(Constraint, !Assumption)) {
+ // Construct a new PathDiagnosticPiece.
+ PathDiagnosticLocation L(S, BRC.getSourceManager());
+ return new PathDiagnosticEventPiece(L, os.str());
+}
- isSatisfied = true;
+void TrackConstraintBRVisitor::Profile(llvm::FoldingSetNodeID &ID) const {
+ static int tag = 0;
+ ID.AddPointer(&tag);
+ ID.AddBoolean(Assumption);
+ ID.Add(Constraint);
+}
- // As a sanity check, make sure that the negation of the constraint
- // was infeasible in the current state. If it is feasible, we somehow
- // missed the transition point.
- if (N->getState()->assume(Constraint, !Assumption))
- return NULL;
+PathDiagnosticPiece *
+TrackConstraintBRVisitor::VisitNode(const ExplodedNode *N,
+ const ExplodedNode *PrevN,
+ BugReporterContext &BRC,
+ BugReport &BR) {
+ if (isSatisfied)
+ return NULL;
- // We found the transition point for the constraint. We now need to
- // pretty-print the constraint. (work-in-progress)
- std::string sbuf;
- llvm::raw_string_ostream os(sbuf);
+ // Check if in the previous state it was feasible for this constraint
+ // to *not* be true.
+ if (PrevN->getState()->assume(Constraint, !Assumption)) {
- if (isa<Loc>(Constraint)) {
- os << "Assuming pointer value is ";
- os << (Assumption ? "non-null" : "null");
- }
+ isSatisfied = true;
- if (os.str().empty())
- return NULL;
+ // As a sanity check, make sure that the negation of the constraint
+ // was infeasible in the current state. If it is feasible, we somehow
+ // missed the transition point.
+ if (N->getState()->assume(Constraint, !Assumption))
+ return NULL;
- // FIXME: Refactor this into BugReporterContext.
- const Stmt *S = 0;
- ProgramPoint P = N->getLocation();
+ // We found the transition point for the constraint. We now need to
+ // pretty-print the constraint. (work-in-progress)
+ std::string sbuf;
+ llvm::raw_string_ostream os(sbuf);
- if (BlockEdge *BE = dyn_cast<BlockEdge>(&P)) {
- const CFGBlock *BSrc = BE->getSrc();
- S = BSrc->getTerminatorCondition();
- }
- else if (PostStmt *PS = dyn_cast<PostStmt>(&P)) {
- S = PS->getStmt();
- }
+ if (isa<Loc>(Constraint)) {
+ os << "Assuming pointer value is ";
+ os << (Assumption ? "non-null" : "null");
+ }
- if (!S)
- return NULL;
+ if (os.str().empty())
+ return NULL;
+
+ // FIXME: Refactor this into BugReporterContext.
+ const Stmt *S = 0;
+ ProgramPoint P = N->getLocation();
- // Construct a new PathDiagnosticPiece.
- PathDiagnosticLocation L(S, BRC.getSourceManager());
- return new PathDiagnosticEventPiece(L, os.str());
+ if (BlockEdge *BE = dyn_cast<BlockEdge>(&P)) {
+ const CFGBlock *BSrc = BE->getSrc();
+ S = BSrc->getTerminatorCondition();
+ }
+ else if (PostStmt *PS = dyn_cast<PostStmt>(&P)) {
+ S = PS->getStmt();
}
- return NULL;
+ if (!S)
+ return NULL;
+
+ // Construct a new PathDiagnosticPiece.
+ PathDiagnosticLocation L(S, BRC.getSourceManager());
+ return new PathDiagnosticEventPiece(L, os.str());
}
-};
-} // end anonymous namespace
-static void registerTrackConstraint(BugReport &BR,
- DefinedSVal Constraint,
- bool Assumption) {
- BR.addVisitor(new TrackConstraintBRVisitor(Constraint, Assumption));
+ return NULL;
}
-void bugreporter::registerTrackNullOrUndefValue(BugReport &BR,
- const void *data) {
-
- const Stmt *S = static_cast<const Stmt*>(data);
- const ExplodedNode *N = BR.getErrorNode();
+BugReporterVisitor *
+bugreporter::getTrackNullOrUndefValueVisitor(const ExplodedNode *N,
+ const Stmt *S) {
+ if (!S || !N)
+ return 0;
- if (!S)
- return;
-
ProgramStateManager &StateMgr = N->getState()->getStateManager();
// Walk through nodes until we get one that matches the statement
@@ -328,7 +293,7 @@ void bugreporter::registerTrackNullOrUndefValue(BugReport &BR,
}
if (!N)
- return;
+ return 0;
const ProgramState *state = N->getState();
@@ -343,7 +308,7 @@ void bugreporter::registerTrackNullOrUndefValue(BugReport &BR,
if (isa<loc::ConcreteInt>(V) || isa<nonloc::ConcreteInt>(V)
|| V.isUndef()) {
- ::registerFindLastStore(BR, R, V);
+ return new FindLastStoreBRVisitor(V, R);
}
}
}
@@ -363,87 +328,64 @@ void bugreporter::registerTrackNullOrUndefValue(BugReport &BR,
if (R) {
assert(isa<SymbolicRegion>(R));
- registerTrackConstraint(BR, loc::MemRegionVal(R), false);
+ return new TrackConstraintBRVisitor(loc::MemRegionVal(R), false);
}
}
-}
-
-void bugreporter::registerFindLastStore(BugReport &BR,
- const void *data) {
- const MemRegion *R = static_cast<const MemRegion*>(data);
- const ExplodedNode *N = BR.getErrorNode();
+ return 0;
+}
- if (!R)
- return;
+BugReporterVisitor *
+FindLastStoreBRVisitor::createVisitorObject(const ExplodedNode *N,
+ const MemRegion *R) {
+ assert(R && "The memory region is null.");
const ProgramState *state = N->getState();
SVal V = state->getSVal(R);
-
if (V.isUnknown())
- return;
+ return 0;
- BR.addVisitor(new FindLastStoreBRVisitor(V, R));
+ return new FindLastStoreBRVisitor(V, R);
}
-namespace {
-class NilReceiverVisitor : public BugReporterVisitor {
-public:
- NilReceiverVisitor() {}
-
- void Profile(llvm::FoldingSetNodeID &ID) const {
- static int x = 0;
- ID.AddPointer(&x);
- }
-
- PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
- BugReporterContext &BRC,
- BugReport &BR) {
-
- const PostStmt *P = N->getLocationAs<PostStmt>();
- if (!P)
- return 0;
- const ObjCMessageExpr *ME = P->getStmtAs<ObjCMessageExpr>();
- if (!ME)
- return 0;
- const Expr *Receiver = ME->getInstanceReceiver();
- if (!Receiver)
- return 0;
- const ProgramState *state = N->getState();
- const SVal &V = state->getSVal(Receiver);
- const DefinedOrUnknownSVal *DV = dyn_cast<DefinedOrUnknownSVal>(&V);
- if (!DV)
- return 0;
- state = state->assume(*DV, true);
- if (state)
- return 0;
-
- // The receiver was nil, and hence the method was skipped.
- // Register a BugReporterVisitor to issue a message telling us how
- // the receiver was null.
- bugreporter::registerTrackNullOrUndefValue(BR, Receiver);
- // Issue a message saying that the method was skipped.
- PathDiagnosticLocation L(Receiver, BRC.getSourceManager());
- return new PathDiagnosticEventPiece(L, "No method actually called "
- "because the receiver is nil");
- }
-};
-} // end anonymous namespace
+PathDiagnosticPiece *NilReceiverBRVisitor::VisitNode(const ExplodedNode *N,
+ const ExplodedNode *PrevN,
+ BugReporterContext &BRC,
+ BugReport &BR) {
+ const PostStmt *P = N->getLocationAs<PostStmt>();
+ if (!P)
+ return 0;
+ const ObjCMessageExpr *ME = P->getStmtAs<ObjCMessageExpr>();
+ if (!ME)
+ return 0;
+ const Expr *Receiver = ME->getInstanceReceiver();
+ if (!Receiver)
+ return 0;
+ const ProgramState *state = N->getState();
+ const SVal &V = state->getSVal(Receiver);
+ const DefinedOrUnknownSVal *DV = dyn_cast<DefinedOrUnknownSVal>(&V);
+ if (!DV)
+ return 0;
+ state = state->assume(*DV, true);
+ if (state)
+ return 0;
-void bugreporter::registerNilReceiverVisitor(BugReport &BR) {
- BR.addVisitor(new NilReceiverVisitor());
+ // The receiver was nil, and hence the method was skipped.
+ // Register a BugReporterVisitor to issue a message telling us how
+ // the receiver was null.
+ BR.addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, Receiver));
+ // Issue a message saying that the method was skipped.
+ PathDiagnosticLocation L(Receiver, BRC.getSourceManager());
+ return new PathDiagnosticEventPiece(L, "No method actually called "
+ "because the receiver is nil");
}
// Registers every VarDecl inside a Stmt with a last store visitor.
-void bugreporter::registerVarDeclsLastStore(BugReport &BR,
- const void *stmt) {
- const Stmt *S = static_cast<const Stmt *>(stmt);
+void FindLastStoreBRVisitor::registerStatementVarDecls(BugReport &BR,
+ const Stmt *S) {
const ExplodedNode *N = BR.getErrorNode();
-
std::deque<const Stmt *> WorkList;
-
WorkList.push_back(S);
while (!WorkList.empty()) {
@@ -462,7 +404,8 @@ void bugreporter::registerVarDeclsLastStore(BugReport &BR,
SVal V = state->getSVal(S);
if (isa<loc::ConcreteInt>(V) || isa<nonloc::ConcreteInt>(V)) {
- ::registerFindLastStore(BR, R, V);
+ // Register a new visitor with the BugReport.
+ BR.addVisitor(new FindLastStoreBRVisitor(V, R));
}
}
}
@@ -476,51 +419,10 @@ void bugreporter::registerVarDeclsLastStore(BugReport &BR,
//===----------------------------------------------------------------------===//
// Visitor that tries to report interesting diagnostics from conditions.
//===----------------------------------------------------------------------===//
-
-namespace {
-class ConditionVisitor : public BugReporterVisitor {
-public:
- void Profile(llvm::FoldingSetNodeID &ID) const {
- static int x = 0;
- ID.AddPointer(&x);
- }
-
- virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
- const ExplodedNode *Prev,
- BugReporterContext &BRC,
- BugReport &BR);
-
- PathDiagnosticPiece *VisitTerminator(const Stmt *Term,
- const ProgramState *CurrentState,
- const ProgramState *PrevState,
- const CFGBlock *srcBlk,
- const CFGBlock *dstBlk,
- BugReporterContext &BRC);
-
- PathDiagnosticPiece *VisitTrueTest(const Expr *Cond,
- bool tookTrue,
- BugReporterContext &BRC);
-
- PathDiagnosticPiece *VisitTrueTest(const Expr *Cond,
- const DeclRefExpr *DR,
- const bool tookTrue,
- BugReporterContext &BRC);
-
- PathDiagnosticPiece *VisitTrueTest(const Expr *Cond,
- const BinaryOperator *BExpr,
- const bool tookTrue,
- BugReporterContext &BRC);
-
- bool patternMatch(const Expr *Ex,
- llvm::raw_ostream &Out,
- BugReporterContext &BRC);
-};
-}
-
-PathDiagnosticPiece *ConditionVisitor::VisitNode(const ExplodedNode *N,
- const ExplodedNode *Prev,
- BugReporterContext &BRC,
- BugReport &BR) {
+PathDiagnosticPiece *ConditionBRVisitor::VisitNode(const ExplodedNode *N,
+ const ExplodedNode *Prev,
+ BugReporterContext &BRC,
+ BugReport &BR) {
const ProgramPoint &progPoint = N->getLocation();
@@ -564,13 +466,12 @@ PathDiagnosticPiece *ConditionVisitor::VisitNode(const ExplodedNode *N,
}
PathDiagnosticPiece *
-ConditionVisitor::VisitTerminator(const Stmt *Term,
- const ProgramState *CurrentState,
- const ProgramState *PrevState,
- const CFGBlock *srcBlk,
- const CFGBlock *dstBlk,
- BugReporterContext &BRC) {
-
+ConditionBRVisitor::VisitTerminator(const Stmt *Term,
+ const ProgramState *CurrentState,
+ const ProgramState *PrevState,
+ const CFGBlock *srcBlk,
+ const CFGBlock *dstBlk,
+ BugReporterContext &BRC) {
const Expr *Cond = 0;
switch (Term->getStmtClass()) {
@@ -592,9 +493,9 @@ ConditionVisitor::VisitTerminator(const Stmt *Term,
}
PathDiagnosticPiece *
-ConditionVisitor::VisitTrueTest(const Expr *Cond,
- bool tookTrue,
- BugReporterContext &BRC) {
+ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
+ bool tookTrue,
+ BugReporterContext &BRC) {
const Expr *Ex = Cond;
@@ -620,8 +521,8 @@ ConditionVisitor::VisitTrueTest(const Expr *Cond,
}
}
-bool ConditionVisitor::patternMatch(const Expr *Ex, llvm::raw_ostream &Out,
- BugReporterContext &BRC) {
+bool ConditionBRVisitor::patternMatch(const Expr *Ex, llvm::raw_ostream &Out,
+ BugReporterContext &BRC) {
const Expr *OriginalExpr = Ex;
Ex = Ex->IgnoreParenCasts();
@@ -658,10 +559,10 @@ bool ConditionVisitor::patternMatch(const Expr *Ex, llvm::raw_ostream &Out,
}
PathDiagnosticPiece *
-ConditionVisitor::VisitTrueTest(const Expr *Cond,
- const BinaryOperator *BExpr,
- const bool tookTrue,
- BugReporterContext &BRC) {
+ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
+ const BinaryOperator *BExpr,
+ const bool tookTrue,
+ BugReporterContext &BRC) {
bool shouldInvert = false;
@@ -726,10 +627,10 @@ ConditionVisitor::VisitTrueTest(const Expr *Cond,
}
PathDiagnosticPiece *
-ConditionVisitor::VisitTrueTest(const Expr *Cond,
- const DeclRefExpr *DR,
- const bool tookTrue,
- BugReporterContext &BRC) {
+ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
+ const DeclRefExpr *DR,
+ const bool tookTrue,
+ BugReporterContext &BRC) {
const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
if (!VD)
@@ -756,8 +657,3 @@ ConditionVisitor::VisitTrueTest(const Expr *Cond,
PathDiagnosticLocation Loc(Cond, BRC.getSourceManager());
return new PathDiagnosticEventPiece(Loc, Out.str());
}
-
-void bugreporter::registerConditionVisitor(BugReport &BR) {
- BR.addVisitor(new ConditionVisitor());
-}
-
OpenPOWER on IntegriCloud