xiangzhai updated this revision to Diff 102777.
xiangzhai added a comment.
Herald added a subscriber: xazax.hun.

Dear Raphael,

Thanks for your suggestion!

> Would it solve your use case if allow specifying file patterns via the 
> command line like this -analyzer-config

Fixed!

  /home/zhaixiang/project/llvm/build/./bin/clang -cc1 -internal-isystem 
/home/zhaixiang/project/llvm/build/lib64/clang/5.0.0/include -nostdsysteminc 
-analyze -analyzer-constraints=range -std=c++11 
-analyzer-checker=alpha.clone.CloneChecker -analyzer-config 
alpha.clone.CloneChecker:IgnoredFilesPattern="moc_|ui_|dbus_|.*_automoc" 
-verify 
/home/zhaixiang/project/llvm/tools/clang/test/Analysis/copypaste/not-autogenerated.cpp

I ran `make check-clang-analysis` and tested it for checking the real K3B 
<https://github.com/KDE/k3b> project's Copy-paste issue to filter Meta Object 
Compiler <http://doc.qt.io/qt-5/moc.html>, User Interface Compiler 
<http://doc.qt.io/qt-5/uic.html>, D-Bus XML Compiler 
<http://doc.qt.io/qt-5/qdbusxml2cpp.html>, worked!

And it is able to specify the `IgnoredFilesPattern` to filter auto-generated 
files for different frameworks, please review my patch, if LGTU, may I commit 
it? thanks a lot!

Regards,
Leslie Zhai


Repository:
  rL LLVM

https://reviews.llvm.org/D31320

Files:
  include/clang/Analysis/CloneDetection.h
  lib/Analysis/CloneDetection.cpp
  lib/StaticAnalyzer/Checkers/CloneChecker.cpp
  test/Analysis/copypaste/autogenerated_automoc.cpp
  test/Analysis/copypaste/dbus_autogenerated.cpp
  test/Analysis/copypaste/moc_autogenerated.cpp
  test/Analysis/copypaste/not-autogenerated.cpp
  test/Analysis/copypaste/ui_autogenerated.cpp

Index: test/Analysis/copypaste/ui_autogenerated.cpp
===================================================================
--- test/Analysis/copypaste/ui_autogenerated.cpp
+++ test/Analysis/copypaste/ui_autogenerated.cpp
@@ -0,0 +1,19 @@
+// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=alpha.clone.CloneChecker -analyzer-config alpha.clone.CloneChecker:IgnoredFilesPattern="moc_|ui_|.*_automoc" -verify %s
+
+// Because files that have `ui_' in their names are most likely autogenerated,
+// we suppress copy-paste warnings here.
+
+// expected-no-diagnostics
+
+void f1() {
+  int *p1 = new int[1];
+  int *p2 = new int[1];
+  if (p1) {
+    delete [] p1;
+    p1 = nullptr;
+  }
+  if (p2) {
+    delete [] p1; // no-warning
+    p2 = nullptr;
+  }
+}
Index: test/Analysis/copypaste/not-autogenerated.cpp
===================================================================
--- test/Analysis/copypaste/not-autogenerated.cpp
+++ test/Analysis/copypaste/not-autogenerated.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=alpha.clone.CloneChecker -analyzer-config alpha.clone.CloneChecker:IgnoredFilesPattern="moc_|ui_|dbus_|.*_automoc" -verify %s
+
+void f1() {
+  int *p1 = new int[1];
+  int *p2 = new int[1];
+  if (p1) {
+    delete [] p1; // expected-note{{Similar code using 'p1' here}}
+    p1 = nullptr;
+  }
+  if (p2) {
+    delete [] p1; // expected-warning{{Potential copy-paste error; did you really mean to use 'p1' here?}}
+    p2 = nullptr;
+  }
+}
Index: test/Analysis/copypaste/moc_autogenerated.cpp
===================================================================
--- test/Analysis/copypaste/moc_autogenerated.cpp
+++ test/Analysis/copypaste/moc_autogenerated.cpp
@@ -0,0 +1,19 @@
+// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=alpha.clone.CloneChecker -analyzer-config alpha.clone.CloneChecker:IgnoredFilesPattern="moc_|.*_automoc" -verify %s
+
+// Because files that have `moc_' in their names are most likely autogenerated,
+// we suppress copy-paste warnings here.
+
+// expected-no-diagnostics
+
+void f1() {
+  int *p1 = new int[1];
+  int *p2 = new int[1];
+  if (p1) {
+    delete [] p1;
+    p1 = nullptr;
+  }
+  if (p2) {
+    delete [] p1; // no-warning
+    p2 = nullptr;
+  }
+}
Index: test/Analysis/copypaste/dbus_autogenerated.cpp
===================================================================
--- test/Analysis/copypaste/dbus_autogenerated.cpp
+++ test/Analysis/copypaste/dbus_autogenerated.cpp
@@ -0,0 +1,19 @@
+// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=alpha.clone.CloneChecker -analyzer-config alpha.clone.CloneChecker:IgnoredFilesPattern="moc_|dbus_|.*_automoc" -verify %s
+
+// Because files that have `dbus_' in their names are most likely autogenerated,
+// we suppress copy-paste warnings here.
+
+// expected-no-diagnostics
+
+void f1() {
+  int *p1 = new int[1];
+  int *p2 = new int[1];
+  if (p1) {
+    delete [] p1;
+    p1 = nullptr;
+  }
+  if (p2) {
+    delete [] p1; // no-warning
+    p2 = nullptr;
+  }
+}
Index: test/Analysis/copypaste/autogenerated_automoc.cpp
===================================================================
--- test/Analysis/copypaste/autogenerated_automoc.cpp
+++ test/Analysis/copypaste/autogenerated_automoc.cpp
@@ -0,0 +1,19 @@
+// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=alpha.clone.CloneChecker -analyzer-config alpha.clone.CloneChecker:IgnoredFilesPattern="moc_|.*_automoc" -verify %s
+
+// Because files that have `_automoc.' in their names are most likely autogenerated,
+// we suppress copy-paste warnings here.
+
+// expected-no-diagnostics
+
+void f1() {
+  int *p1 = new int[1];
+  int *p2 = new int[1];
+  if (p1) {
+    delete [] p1;
+    p1 = nullptr;
+  }
+  if (p2) {
+    delete [] p1; // no-warning
+    p2 = nullptr;
+  }
+}
Index: lib/StaticAnalyzer/Checkers/CloneChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/CloneChecker.cpp
+++ lib/StaticAnalyzer/Checkers/CloneChecker.cpp
@@ -73,12 +73,17 @@
   bool ReportNormalClones = Mgr.getAnalyzerOptions().getBooleanOption(
       "ReportNormalClones", true, this);
 
+  StringRef IgnoredFilesPattern = Mgr.getAnalyzerOptions().getOptionAsString(
+      "IgnoredFilesPattern", "", this);
+
   // Let the CloneDetector create a list of clones from all the analyzed
   // statements. We don't filter for matching variable patterns at this point
   // because reportSuspiciousClones() wants to search them for errors.
   std::vector<CloneDetector::CloneGroup> AllCloneGroups;
 
-  Detector.findClones(AllCloneGroups, RecursiveCloneTypeIIConstraint(),
+  Detector.findClones(AllCloneGroups,
+                      AutoGeneratedCloneConstraint(IgnoredFilesPattern),
+                      RecursiveCloneTypeIIConstraint(),
                       MinComplexityConstraint(MinComplexity),
                       MinGroupSizeConstraint(2), OnlyLargestCloneConstraint());
 
Index: lib/Analysis/CloneDetection.cpp
===================================================================
--- lib/Analysis/CloneDetection.cpp
+++ lib/Analysis/CloneDetection.cpp
@@ -18,9 +18,9 @@
 #include "clang/AST/Stmt.h"
 #include "clang/AST/StmtVisitor.h"
 #include "clang/Lex/Lexer.h"
-#include "llvm/ADT/StringRef.h"
 #include "llvm/Support/MD5.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Regex.h"
 
 using namespace clang;
 
@@ -366,6 +366,29 @@
   }
 }
 
+bool AutoGeneratedCloneConstraint::isAutoGenerated(const CloneDetector::CloneGroup &Group) {
+  if (IgnoredFilesPattern.empty() || Group.empty())
+    return false;
+
+  for (const StmtSequence &S : Group) {
+    const Decl *D = S.getContainingDecl();
+    const SourceManager &SM = D->getASTContext().getSourceManager();
+    std::string Filename = std::string(SM.getFilename(D->getLocation()));
+    // Get Basename
+    const size_t LastSlash = Filename.find_last_of("\\/");
+    if (LastSlash != std::string::npos)
+      Filename.erase(0, LastSlash + 1);
+    const size_t LastDot = Filename.rfind('.');
+    if (LastDot != std::string::npos)
+      Filename.erase(LastDot);
+    llvm::Regex R(StringRef("^(" + IgnoredFilesPattern.str() + "$)"));
+    if (R.match(StringRef(Filename)))
+      return true;
+  }
+
+  return false;
+}
+
 static size_t createHash(llvm::MD5 &Hash) {
   size_t HashCode;
 
Index: include/clang/Analysis/CloneDetection.h
===================================================================
--- include/clang/Analysis/CloneDetection.h
+++ include/clang/Analysis/CloneDetection.h
@@ -17,6 +17,7 @@
 
 #include "clang/Basic/SourceLocation.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
 #include <vector>
 
 namespace clang {
@@ -319,6 +320,22 @@
   void constrain(std::vector<CloneDetector::CloneGroup> &Result);
 };
 
+struct AutoGeneratedCloneConstraint {
+  StringRef IgnoredFilesPattern;
+
+  AutoGeneratedCloneConstraint(StringRef IgnoredFilesPattern) 
+      : IgnoredFilesPattern(IgnoredFilesPattern) {}
+
+  bool isAutoGenerated(const CloneDetector::CloneGroup &Group);
+
+  void constrain(std::vector<CloneDetector::CloneGroup> &CloneGroups) {
+    CloneConstraint::filterGroups(
+        CloneGroups, [this](const CloneDetector::CloneGroup &Group) {
+          return isAutoGenerated(Group);
+        });
+  }
+};
+
 /// Analyzes the pattern of the referenced variables in a statement.
 class VariablePattern {
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to