Fixed a bug in signature creation.
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

Reply via email to