std::list<PathDiagnosticPiece*> path;
unsigned Size;
std::string Desc;
+ std::string Category;
std::vector<std::string> OtherDesc;
public:
PathDiagnostic() : Size(0) {}
- PathDiagnostic(const char* desc) : Size(0), Desc(desc) {}
+ PathDiagnostic(const char* desc, const char* category)
+ : Size(0), Desc(desc), Category(category) {}
- PathDiagnostic(const std::string& desc) : Size(0), Desc(desc) {}
+ PathDiagnostic(const std::string& desc, const std::string& category)
+ : Size(0), Desc(desc), Category(category) {}
~PathDiagnostic();
const std::string& getDescription() const { return Desc; }
+ const std::string& getCategory() const { return Category; }
typedef std::vector<std::string>::const_iterator meta_iterator;
meta_iterator meta_begin() const { return OtherDesc.begin(); }
virtual const char* getName() const = 0;
virtual const char* getDescription() const { return getName(); }
+ virtual const char* getCategory() const { return ""; }
virtual std::pair<const char**,const char**> getExtraDescriptiveText() {
return std::pair<const char**, const char**>(0, 0);
return getBugType().getDescription();
}
+ virtual const char* getCategory() const {
+ return getBugType().getCategory();
+ }
+
virtual std::pair<const char**,const char**> getExtraDescriptiveText() {
return getBugType().getExtraDescriptiveText();
}
SourceLocation Loc,
SourceRange* RangeBeg, unsigned NumRanges);
+ void EmitBasicReport(const char* BugName, const char* BugCategory,
+ const char* BugStr, SourceLocation Loc,
+ SourceRange* RangeBeg, unsigned NumRanges);
+
+
void EmitBasicReport(const char* BugName, const char* BugStr,
SourceLocation Loc) {
EmitBasicReport(BugName, BugStr, Loc, 0, 0);
EmitBasicReport(BugName, BugStr, Loc, &R, 1);
}
+ void EmitBasicReport(const char* BugName, const char* Category,
+ const char* BugStr, SourceLocation Loc, SourceRange R) {
+ EmitBasicReport(BugName, Category, BugStr, Loc, &R, 1);
+ }
+
static bool classof(const BugReporter* R) { return true; }
};
class SimpleBugType : public BugTypeCacheLocation {
const char* name;
+ const char* category;
const char* desc;
public:
- SimpleBugType(const char* n) : name(n), desc(n) {}
- SimpleBugType(const char* n, const char* d) : name(n), desc(d) {}
+ SimpleBugType(const char* n) : name(n), category(""), desc(0) {}
+ SimpleBugType(const char* n, const char* c, const char* d)
+ : name(n), category(c), desc(d) {}
virtual const char* getName() const { return name; }
- virtual const char* getDescription() const { return desc; }
+ virtual const char* getDescription() const { return desc ? desc : name; }
+ virtual const char* getCategory() const { return category; }
};
} // end clang namespace
if (R.getBugType().isCached(R))
return;
- llvm::OwningPtr<PathDiagnostic> D(new PathDiagnostic(R.getName()));
+ llvm::OwningPtr<PathDiagnostic> D(new PathDiagnostic(R.getName(),
+ R.getCategory()));
GeneratePathDiagnostic(*D.get(), R);
// Get the meta data.
}
}
-void
-BugReporter::EmitBasicReport(const char* name, const char* str,
- SourceLocation Loc,
- SourceRange* RBeg, unsigned NumRanges) {
+void BugReporter::EmitBasicReport(const char* name, const char* str,
+ SourceLocation Loc,
+ SourceRange* RBeg, unsigned NumRanges) {
+ EmitBasicReport(name, "", str, Loc, RBeg, NumRanges);
+}
+
+void BugReporter::EmitBasicReport(const char* name, const char* category,
+ const char* str, SourceLocation Loc,
+ SourceRange* RBeg, unsigned NumRanges) {
- SimpleBugType BT(name);
+ SimpleBugType BT(name, category, 0);
DiagCollector C(BT);
Diagnostic& Diag = getDiagnostic();
Diag.Report(&C, getContext().getFullLoc(Loc),
const CFRefCount& getTF() const { return TF; }
virtual bool isLeak() const { return false; }
+
+ const char* getCategory() const {
+ return "Memory (Core Foundation/Objective-C)";
+ }
};
class VISIBILITY_HIDDEN UseAfterRelease : public CFRefBug {
UseAfterRelease(CFRefCount& tf) : CFRefBug(tf) {}
virtual const char* getName() const {
- return "Use-After-Release";
+ return "use-after-release";
}
virtual const char* getDescription() const {
return "Reference-counted object is used after it is released.";
BadRelease(CFRefCount& tf) : CFRefBug(tf) {}
virtual const char* getName() const {
- return "Bad Release";
+ return "bad release";
}
virtual const char* getDescription() const {
return "Incorrect decrement of the reference count of a "
virtual const char* getName() const {
if (getTF().isGCEnabled())
- return "Memory Leak (GC)";
+ return "Leak (GC)";
if (getTF().getLangOptions().getGCMode() == LangOptions::HybridGC)
- return "Memory Leak (Hybrid MM, non-GC)";
+ return "leak (hybrid MM, non-GC)";
assert (getTF().getLangOptions().getGCMode() == LangOptions::NonGC);
- return "Memory Leak";
+ return "leak";
}
virtual const char* getDescription() const {
case DeadIncrement:
BugType = "dead increment";
case Standard:
- if (!BugType) BugType = "dead store";
+ if (!BugType) BugType = "dead assignment";
msg = "Value stored to '" + name + "' is never read";
break;
case Enclosing:
- BugType = "dead store";
+ BugType = "dead nested assignment";
msg = "Although the value stored to '" + name +
"' is used in the enclosing expression, the value is never actually"
" read from '" + name + "'";
break;
}
- BR.EmitBasicReport(BugType, msg.c_str(), L, R);
+ BR.EmitBasicReport(BugType, "Dead Store", msg.c_str(), L, R);
}
void CheckVarDecl(VarDecl* VD, Expr* Ex, Expr* Val,
public:
CheckAttrNonNull() :
- BT("'nonnull' argument passed null",
+ BT("'nonnull' argument passed null", "API",
"Null pointer passed as an argument to a 'nonnull' parameter") {}
virtual bool Audit(ExplodedNode<GRState>* N, GRStateManager& VMgr) {
R.InsertStrBefore(SourceLocation::getFileLoc(FileID, 0), os.str());
}
+ const std::string& BugCategory = D.getCategory();
+
+ if (!BugCategory.empty()) {
+ std::string s;
+ llvm::raw_string_ostream os(s);
+ os << "\n<!-- BUGCATEGORY " << BugCategory << " -->\n";
+ R.InsertStrBefore(SourceLocation::getFileLoc(FileID, 0), os.str());
+ }
+
{
std::string s;
llvm::raw_string_ostream os(s);