class GRExprEngine;
class ValueState;
class Stmt;
+class BugReport;
class BugType {
public:
virtual void EmitWarnings(BugReporter& BR) {}
virtual void GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes) {}
+
+ virtual bool isCached(BugReport& R) = 0;
+};
+
+class BugTypeCacheLocation : public BugType {
+ llvm::SmallPtrSet<void*,10> CachedErrors;
+public:
+ BugTypeCacheLocation() {}
+ virtual ~BugTypeCacheLocation() {}
+ virtual bool isCached(BugReport& R);
};
+
class BugReport {
- const BugType& Desc;
+ BugType& Desc;
ExplodedNode<ValueState> *N;
public:
- BugReport(const BugType& D, ExplodedNode<ValueState> *n) : Desc(D), N(n) {}
+ BugReport(BugType& D, ExplodedNode<ValueState> *n) : Desc(D), N(n) {}
virtual ~BugReport();
const BugType& getBugType() const { return Desc; }
+ BugType& getBugType() { return Desc; }
ExplodedNode<ValueState>* getEndNode() const { return N; }
class RangedBugReport : public BugReport {
std::vector<SourceRange> Ranges;
public:
- RangedBugReport(const BugType& D, ExplodedNode<ValueState> *n)
+ RangedBugReport(BugType& D, ExplodedNode<ValueState> *n)
: BugReport(D, n) {}
virtual ~RangedBugReport();
};
class BugReporter {
- llvm::SmallPtrSet<void*,10> CachedErrors;
Diagnostic& Diag;
PathDiagnosticClient* PD;
ASTContext& Ctx;
CFG& getCFG() { return getGraph().getCFG(); }
void EmitWarning(BugReport& R);
-
- void clearCache() { CachedErrors.clear(); }
-
- bool IsCached(ExplodedNode<ValueState>* N);
void GeneratePathDiagnostic(PathDiagnostic& PD, BugReport& R);
};
namespace {
-class VISIBILITY_HIDDEN NilArg : public BugType {
+class VISIBILITY_HIDDEN NilArg : public BugTypeCacheLocation {
public:
virtual ~NilArg() {}
}
}
-bool BugReporter::IsCached(ExplodedNode<ValueState>* N) {
+bool BugTypeCacheLocation::isCached(BugReport& R) {
+
+ ExplodedNode<ValueState>* N = R.getEndNode();
if (!N)
return false;
-
- // HACK: Cache the location of the error. Don't emit the same
+
+ // Cache the location of the error. Don't emit the same
// warning for the same error type that occurs at the same program
// location but along a different path.
if (CachedErrors.count(p))
return true;
- CachedErrors.insert(p);
-
+ CachedErrors.insert(p);
return false;
}
void BugReporter::EmitWarning(BugReport& R) {
- if (IsCached(R.getEndNode()))
+ if (R.getBugType().isCached(R))
return;
PathDiagnostic D(R.getName());
// Bug Descriptions. //
//===-------------===//
- class VISIBILITY_HIDDEN CFRefBug : public BugType {
+ class VISIBILITY_HIDDEN CFRefBug : public BugTypeCacheLocation {
protected:
CFRefCount& TF;
class VISIBILITY_HIDDEN CFRefReport : public RangedBugReport {
SymbolID Sym;
public:
- CFRefReport(const BugType& D, ExplodedNode<ValueState> *n, SymbolID sym)
+ CFRefReport(BugType& D, ExplodedNode<ValueState> *n, SymbolID sym)
: RangedBugReport(D, n), Sym(sym) {}
virtual ~CFRefReport() {}
std::list<std::string> Strs;
FullSourceLoc L;
public:
- DiagBugReport(const BugType& D, FullSourceLoc l) :
+ DiagBugReport(BugType& D, FullSourceLoc l) :
RangedBugReport(D, NULL), L(l) {}
virtual ~DiagBugReport() {}
class VISIBILITY_HIDDEN DiagCollector : public DiagnosticClient {
std::list<DiagBugReport> Reports;
- const BugType& D;
+ BugType& D;
public:
DiagCollector(BugType& d) : D(d) {}
iterator end() { return Reports.end(); }
};
-class VISIBILITY_HIDDEN DeadStoresChecker : public BugType {
+class VISIBILITY_HIDDEN DeadStoresChecker : public BugTypeCacheLocation {
public:
virtual const char* getName() const {
return "dead store";
}
template <typename ITER>
-void GenericEmitWarnings(BugReporter& BR, const BugType& D,
- ITER I, ITER E) {
+void GenericEmitWarnings(BugReporter& BR, BugType& D, ITER I, ITER E) {
for (; I != E; ++I) {
BugReport R(D, GetNode(I));
namespace {
-class VISIBILITY_HIDDEN NullDeref : public BugType {
+class VISIBILITY_HIDDEN NullDeref : public BugTypeCacheLocation {
public:
virtual const char* getName() const {
return "null dereference";
}
};
-class VISIBILITY_HIDDEN UndefDeref : public BugType {
+class VISIBILITY_HIDDEN UndefDeref : public BugTypeCacheLocation {
public:
virtual const char* getName() const {
return "bad dereference";
}
};
-class VISIBILITY_HIDDEN UndefBranch : public BugType {
+class VISIBILITY_HIDDEN UndefBranch : public BugTypeCacheLocation {
public:
virtual const char* getName() const {
return "uninitialized value";
}
};
-class VISIBILITY_HIDDEN DivZero : public BugType {
+class VISIBILITY_HIDDEN DivZero : public BugTypeCacheLocation {
public:
virtual const char* getName() const {
return "divide-by-zero";
}
};
-class VISIBILITY_HIDDEN UndefResult : public BugType {
+class VISIBILITY_HIDDEN UndefResult : public BugTypeCacheLocation {
public:
virtual const char* getName() const {
return "undefined result";
}
};
-class VISIBILITY_HIDDEN BadCall : public BugType {
+class VISIBILITY_HIDDEN BadCall : public BugTypeCacheLocation {
public:
virtual const char* getName() const {
return "invalid function call";
};
-class VISIBILITY_HIDDEN BadArg : public BugType {
+class VISIBILITY_HIDDEN BadArg : public BugTypeCacheLocation {
public:
virtual ~BadArg() {}
}
};
-class VISIBILITY_HIDDEN BadReceiver : public BugType {
+class VISIBILITY_HIDDEN BadReceiver : public BugTypeCacheLocation {
public:
virtual const char* getName() const {
return "bad receiver";
}
};
-class VISIBILITY_HIDDEN RetStack : public BugType {
+class VISIBILITY_HIDDEN RetStack : public BugTypeCacheLocation {
public:
virtual const char* getName() const {
return "return of stack address";