/// This class provides an interface through which checkers can create
/// individual bug reports.
-class BugReport : public BugReporterVisitor {
+class BugReport {
public:
class NodeResolver {
public:
public:
BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode)
: BT(bt), Description(desc), ErrorNode(errornode),
- Callbacks(F.getEmptyList()) {
- addVisitor(this);
- }
+ Callbacks(F.getEmptyList()) {}
BugReport(BugType& bt, StringRef shortDesc, StringRef desc,
const ExplodedNode *errornode)
: BT(bt), ShortDescription(shortDesc), Description(desc),
- ErrorNode(errornode), Callbacks(F.getEmptyList()) {
- addVisitor(this);
- }
+ ErrorNode(errornode), Callbacks(F.getEmptyList()) {}
BugReport(BugType& bt, StringRef desc, FullSourceLoc l)
: BT(bt), Description(desc), Location(l), ErrorNode(0),
- Callbacks(F.getEmptyList()) {
- addVisitor(this);
- }
+ Callbacks(F.getEmptyList()) {}
virtual ~BugReport();
- virtual bool isOwnedByReporterContext() { return false; }
-
const BugType& getBugType() const { return BT; }
BugType& getBugType() { return BT; }
/// Iterators through the custom diagnostic visitors.
visitor_iterator visitor_begin() { return Callbacks.begin(); }
visitor_iterator visitor_end() { return Callbacks.end(); }
-
- virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
- BugReporterContext &BRC,
- BugReport &BR);
};
//===----------------------------------------------------------------------===//
BugReport::~BugReport() {
for (visitor_iterator I = visitor_begin(), E = visitor_end(); I != E; ++I) {
- if ((*I)->isOwnedByReporterContext()) {
- delete *I;
- }
+ delete *I;
}
}
return FullSourceLoc();
}
-PathDiagnosticPiece *BugReport::VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
- BugReporterContext &BRC,
- BugReport &BR) {
- return NULL;
-}
-
//===----------------------------------------------------------------------===//
// Methods for BugReporter and subclasses.
//===----------------------------------------------------------------------===//
// Bug Reports. //
//===---------===//
+ class CFRefReportVisitor : public BugReporterVisitor {
+ SymbolRef Sym;
+ const CFRefCount &TF;
+ public:
+
+ CFRefReportVisitor(SymbolRef sym, const CFRefCount &tf)
+ : Sym(sym), TF(tf) {}
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ static int x = 0;
+ ID.AddPointer(&x);
+ ID.AddPointer(Sym);
+ }
+
+ PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
+ const ExplodedNode *PrevN,
+ BugReporterContext &BRC,
+ BugReport &BR);
+ };
+
class CFRefReport : public BugReport {
protected:
SymbolRef Sym;
public:
CFRefReport(CFRefBug& D, const CFRefCount &tf,
ExplodedNode *n, SymbolRef sym)
- : BugReport(D, D.getDescription(), n), Sym(sym), TF(tf) {}
+ : BugReport(D, D.getDescription(), n), Sym(sym), TF(tf) {
+ addVisitor(new CFRefReportVisitor(sym, tf));
+ }
CFRefReport(CFRefBug& D, const CFRefCount &tf,
ExplodedNode *n, SymbolRef sym, StringRef endText)
- : BugReport(D, D.getDescription(), endText, n), Sym(sym), TF(tf) {}
+ : BugReport(D, D.getDescription(), endText, n), Sym(sym), TF(tf) {
+ addVisitor(new CFRefReportVisitor(sym, tf));
+ }
virtual ~CFRefReport() {}
const ExplodedNode *N);
std::pair<const char**,const char**> getExtraDescriptiveText();
-
- PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
- BugReporterContext &BRC,
- BugReport &BR);
};
class CFRefLeakReport : public CFRefReport {
return false;
}
-PathDiagnosticPiece *CFRefReport::VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
- BugReporterContext &BRC,
- BugReport &BR) {
+PathDiagnosticPiece *CFRefReportVisitor::VisitNode(const ExplodedNode *N,
+ const ExplodedNode *PrevN,
+ BugReporterContext &BRC,
+ BugReport &BR) {
if (!isa<PostStmt>(N->getLocation()))
return NULL;
if (CurrV.isOwned()) {
os << "+1 retain count";
- if (static_cast<CFRefBug&>(getBugType()).getTF().isGCEnabled()) {
+ if (TF.isGCEnabled()) {
assert(CurrV.getObjKind() == RetEffect::CF);
os << ". "
"Core Foundation objects are not automatically garbage collected.";
// FIXME: AllocBinding doesn't get populated for RegionStore yet.
if (AllocBinding)
os << " and stored into '" << AllocBinding->getString() << '\'';
+
+ addVisitor(new CFRefReportVisitor(sym, tf));
}
//===----------------------------------------------------------------------===//