Changed Delimiter to StringRef from std::string and fixed a typo in variable
name.
Updated to the latest trunk.
http://reviews.llvm.org/D10305
Files:
include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
lib/StaticAnalyzer/Core/BugReporter.cpp
lib/StaticAnalyzer/Core/PathDiagnostic.cpp
lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
EMAIL PREFERENCES
http://reviews.llvm.org/settings/panel/emailpreferences/
Index: include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
===================================================================
--- include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
+++ include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
@@ -75,6 +75,7 @@
const Decl *DeclWithIssue;
std::string ShortDescription;
std::string Description;
+ std::string HashField;
PathDiagnosticLocation Location;
PathDiagnosticLocation UniqueingLocation;
const Decl *UniqueingDecl;
@@ -143,19 +144,23 @@
void popInterestingSymbolsAndRegions();
public:
- BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode)
- : BT(bt), DeclWithIssue(nullptr), Description(desc), ErrorNode(errornode),
- ConfigurationChangeToken(0), DoNotPrunePath(false) {}
-
- BugReport(BugType& bt, StringRef shortDesc, StringRef desc,
- const ExplodedNode *errornode)
- : BT(bt), DeclWithIssue(nullptr), ShortDescription(shortDesc),
- Description(desc), ErrorNode(errornode), ConfigurationChangeToken(0),
- DoNotPrunePath(false) {}
-
- BugReport(BugType &bt, StringRef desc, PathDiagnosticLocation l)
- : BT(bt), DeclWithIssue(nullptr), Description(desc), Location(l),
- ErrorNode(nullptr), ConfigurationChangeToken(0), DoNotPrunePath(false) {}
+ BugReport(BugType &bt, StringRef desc, const ExplodedNode *errornode,
+ StringRef hashfield = "")
+ : BT(bt), DeclWithIssue(nullptr), Description(desc), HashField(hashfield),
+ ErrorNode(errornode), ConfigurationChangeToken(0),
+ DoNotPrunePath(false) {}
+
+ BugReport(BugType &bt, StringRef shortDesc, StringRef desc,
+ const ExplodedNode *errornode, StringRef hashfield = "")
+ : BT(bt), DeclWithIssue(nullptr), ShortDescription(shortDesc),
+ Description(desc), HashField(hashfield), ErrorNode(errornode),
+ ConfigurationChangeToken(0), DoNotPrunePath(false) {}
+
+ BugReport(BugType &bt, StringRef desc, PathDiagnosticLocation l,
+ StringRef hashfield = "")
+ : BT(bt), DeclWithIssue(nullptr), Description(desc), HashField(hashfield),
+ Location(l), ErrorNode(nullptr), ConfigurationChangeToken(0),
+ DoNotPrunePath(false) {}
/// \brief Create a BugReport with a custom uniqueing location.
///
@@ -165,8 +170,9 @@
/// for uniquing reports. For example, memory leaks checker, could set this to
/// the allocation site, rather then the location where the bug is reported.
BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode,
- PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique)
- : BT(bt), DeclWithIssue(nullptr), Description(desc),
+ PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique,
+ StringRef hashfield = "")
+ : BT(bt), DeclWithIssue(nullptr), Description(desc), HashField(hashfield),
UniqueingLocation(LocationToUnique),
UniqueingDecl(DeclToUnique),
ErrorNode(errornode), ConfigurationChangeToken(0),
@@ -181,6 +187,8 @@
StringRef getDescription() const { return Description; }
+ StringRef getHashField() const { return HashField; }
+
StringRef getShortDescription(bool UseFallback = true) const {
if (ShortDescription.empty() && UseFallback)
return Description;
Index: include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
===================================================================
--- include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
+++ include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
@@ -720,6 +720,7 @@
std::string BugType;
std::string VerboseDesc;
std::string ShortDesc;
+ std::string HashField;
std::string Category;
std::deque<std::string> OtherDesc;
@@ -739,7 +740,7 @@
PathDiagnostic(StringRef CheckName, const Decl *DeclWithIssue,
StringRef bugtype, StringRef verboseDesc, StringRef shortDesc,
StringRef category, PathDiagnosticLocation LocationToUnique,
- const Decl *DeclToUnique);
+ const Decl *DeclToUnique, StringRef hashfield);
~PathDiagnostic();
@@ -794,6 +795,7 @@
StringRef getShortDescription() const {
return ShortDesc.empty() ? VerboseDesc : ShortDesc;
}
+ StringRef getHashField() const { return HashField; }
StringRef getCheckName() const { return CheckName; }
StringRef getBugType() const { return BugType; }
StringRef getCategory() const { return Category; }
Index: lib/StaticAnalyzer/Core/BugReporter.cpp
===================================================================
--- lib/StaticAnalyzer/Core/BugReporter.cpp
+++ lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -3403,7 +3403,8 @@
exampleReport->getDescription(),
exampleReport->getShortDescription(/*Fallback=*/false), BT.getCategory(),
exampleReport->getUniqueingLocation(),
- exampleReport->getUniqueingDecl()));
+ exampleReport->getUniqueingDecl(),
+ exampleReport->getHashField()));
MaxBugClassSize = std::max(bugReports.size(),
static_cast<size_t>(MaxBugClassSize));
Index: lib/StaticAnalyzer/Core/PathDiagnostic.cpp
===================================================================
--- lib/StaticAnalyzer/Core/PathDiagnostic.cpp
+++ lib/StaticAnalyzer/Core/PathDiagnostic.cpp
@@ -111,12 +111,13 @@
StringRef bugtype, StringRef verboseDesc,
StringRef shortDesc, StringRef category,
PathDiagnosticLocation LocationToUnique,
- const Decl *DeclToUnique)
+ const Decl *DeclToUnique, StringRef hashfield)
: CheckName(CheckName),
DeclWithIssue(declWithIssue),
BugType(StripTrailingDots(bugtype)),
VerboseDesc(StripTrailingDots(verboseDesc)),
ShortDesc(StripTrailingDots(shortDesc)),
+ HashField(hashfield),
Category(StripTrailingDots(category)),
UniqueingLoc(LocationToUnique),
UniqueingDecl(DeclToUnique),
Index: lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
===================================================================
--- lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
+++ lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
@@ -11,17 +11,25 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/PlistSupport.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Version.h"
+#include "clang/Basic/Specifiers.h"
+#include "clang/Lex/Lexer.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/Support/Casting.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/LineIterator.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/MD5.h"
using namespace clang;
using namespace ento;
using namespace markup;
@@ -285,6 +293,151 @@
}
}
+static std::string GetSignature(const clang::FunctionDecl *Target) {
+ if (!Target)
+ return "";
+
+ std::string Signature;
+ const CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(Target);
+ const CXXDestructorDecl *DDecl = dyn_cast<CXXDestructorDecl>(Target);
+ const CXXConversionDecl *ConversionDecl = dyn_cast<CXXConversionDecl>(Target);
+
+ switch (Target->getStorageClass()) {
+ case SC_Extern:
+ Signature.append("extern ");
+ break;
+ case SC_Static:
+ Signature.append("static ");
+ break;
+ case SC_PrivateExtern:
+ Signature.append("__private_extern__ ");
+ break;
+ default:
+ break;
+ }
+
+ if (Target->isInlineSpecified())
+ Signature.append("inline ");
+ if (Target->isVirtualAsWritten())
+ Signature.append("virtual ");
+ if (Target->isModulePrivate())
+ Signature.append("__module_private__ ");
+ if (Target->isConstexpr() && !Target->isExplicitlyDefaulted())
+ Signature.append("constexpr ");
+ if ((CDecl && CDecl->isExplicitSpecified()) ||
+ (ConversionDecl && ConversionDecl->isExplicit()))
+ Signature.append("explicit ");
+
+ if (!CDecl && !ConversionDecl && !DDecl)
+ Signature.append(Target->getReturnType().getAsString()).append(" ");
+ Signature.append(Target->getQualifiedNameAsString()).append("(");
+
+ const FunctionProtoType *TargetPT =
+ llvm::dyn_cast_or_null<FunctionProtoType>(Target->getType().getTypePtr());
+
+ for (int i = 0, paramsCount = Target->getNumParams(); i < paramsCount; ++i) {
+ if (i)
+ Signature.append(", ");
+ Signature.append(Target->getParamDecl(i)->getType().getAsString());
+ }
+
+ if (TargetPT && TargetPT->isVariadic())
+ Signature.append(", ...");
+ Signature.append(")");
+
+ if (TargetPT) {
+ if (TargetPT->isConst())
+ Signature.append(" const");
+ if (TargetPT->isVolatile())
+ Signature.append(" volatile");
+ if (TargetPT->isRestrict())
+ Signature.append(" restrict");
+ }
+
+ switch (TargetPT->getRefQualifier()) {
+ case RQ_LValue:
+ Signature.append(" &");
+ break;
+ case RQ_RValue:
+ Signature.append(" &&");
+ break;
+ default:
+ break;
+ }
+
+ return Signature;
+}
+
+static std::string GetEnclosingDeclContextSignature(const Decl *D) {
+ if (!D)
+ return "";
+
+ if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
+ std::string DeclName;
+
+ switch (ND->getKind()) {
+ case Decl::Namespace:
+ case Decl::Record:
+ case Decl::CXXRecord:
+ case Decl::Enum:
+ DeclName = ND->getQualifiedNameAsString();
+ break;
+ case Decl::CXXConstructor:
+ case Decl::CXXDestructor:
+ case Decl::CXXConversion:
+ case Decl::CXXMethod:
+ case Decl::ObjCMethod:
+ case Decl::Function:
+ DeclName = GetSignature(dyn_cast_or_null<FunctionDecl>(ND));
+ break;
+ default:
+ break;
+ }
+
+ return DeclName;
+ }
+
+ return "";
+}
+
+static std::string GetNthLineOfFile(llvm::MemoryBuffer *Buffer, int Line) {
+ if (!Buffer)
+ return "";
+
+ llvm::line_iterator LI(*Buffer, false);
+ for (; !LI.is_at_eof() && LI.line_number() != Line; ++LI)
+ ;
+
+ return LI->str();
+}
+
+static llvm::SmallString<32> GetHashOfContent(StringRef Content) {
+ llvm::MD5 Hash;
+ llvm::MD5::MD5Result MD5Res;
+ llvm::SmallString<32> Res;
+
+ Hash.update(Content);
+ Hash.final(MD5Res);
+ llvm::MD5::stringifyResult(MD5Res, Res);
+
+ return Res;
+}
+
+static llvm::SmallString<32> GetIssueHash(const SourceManager *SM,
+ FullSourceLoc &L,
+ StringRef CheckerName,
+ StringRef HashField, const Decl *D) {
+ static llvm::StringRef Delimiter = "$";
+
+ return GetHashOfContent(
+ (llvm::Twine(llvm::sys::path::filename(SM->getFilename(L))) + Delimiter +
+ CheckerName + Delimiter + GetEnclosingDeclContextSignature(D) +
+ Delimiter + std::to_string(L.getExpansionColumnNumber()) + Delimiter +
+ GetNthLineOfFile(SM->getBuffer(L.getFileID(), L), L.getExpansionLineNumber()) +
+ Delimiter + HashField.str())
+ .str());
+}
+
void PlistDiagnostics::FlushDiagnosticsImpl(
std::vector<const PathDiagnostic *> &Diags,
FilesMade *filesMade) {
@@ -390,6 +543,12 @@
o << " <key>check_name</key>";
EmitString(o, D->getCheckName()) << '\n';
+ o << " <key>bug_id_1</key>";
+ FullSourceLoc L(SM->getExpansionLoc(D->getLocation().asLocation()), *SM);
+ const Decl *DeclWithIssue = D->getDeclWithIssue();
+ EmitString(o, GetIssueHash(SM, L, D->getCheckName(), D->getHashField(),
+ DeclWithIssue).str()) << '\n';
+
// Output information about the semantic context where
// the issue occurred.
if (const Decl *DeclWithIssue = D->getDeclWithIssue()) {
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits