[analyzer] Add basic capabilities to detect source code clones.

This patch adds the CloneDetector class which allows searching source code
for clones.

For every statement or group of statements within a compound statement,
CloneDetector computes a hash value, and finds clones by detecting
identical hash values.

This initial patch only provides a simple hashing mechanism
that hashes the kind of each sub-statement.

This patch also adds CloneChecker - a simple static analyzer checker
that uses CloneDetector to report copy-pasted code.

Patch by Raphael Isemann!

Differential Revision: https://reviews.llvm.org/D20795

llvm-svn: 276782
diff --git a/clang/test/Analysis/copypaste/blocks.cpp b/clang/test/Analysis/copypaste/blocks.cpp
new file mode 100644
index 0000000..0bd9812
--- /dev/null
+++ b/clang/test/Analysis/copypaste/blocks.cpp
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -analyze -fblocks -std=c++11 -analyzer-checker=alpha.clone.CloneChecker -verify %s
+
+// This tests if we search for clones in blocks.
+
+void log();
+
+auto BlockA = ^(int a, int b){ // expected-warning{{Detected code clone.}}
+  log();
+  if (a > b)
+    return a;
+  return b;
+};
+
+auto BlockB = ^(int a, int b){ // expected-note{{Related code clone is here.}}
+  log();
+  if (a > b)
+    return a;
+  return b;
+};
diff --git a/clang/test/Analysis/copypaste/false-positives.cpp b/clang/test/Analysis/copypaste/false-positives.cpp
new file mode 100644
index 0000000..8d649c7
--- /dev/null
+++ b/clang/test/Analysis/copypaste/false-positives.cpp
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -analyze -std=c++11 -analyzer-checker=alpha.clone.CloneChecker -verify %s
+
+// This test contains false-positive reports from the CloneChecker that need to
+// be fixed.
+
+void log();
+
+int max(int a, int b) { // expected-warning{{Detected code clone.}}
+  log();
+  if (a > b)
+    return a;
+  return b;
+}
+
+// FIXME: Detect different binary operator kinds.
+int min1(int a, int b) { // expected-note{{Related code clone is here.}}
+  log();
+  if (a < b)
+    return a;
+  return b;
+}
+
+// FIXME: Detect different variable patterns.
+int min2(int a, int b) { // expected-note{{Related code clone is here.}}
+  log();
+  if (b > a)
+    return a;
+  return b;
+}
diff --git a/clang/test/Analysis/copypaste/functions.cpp b/clang/test/Analysis/copypaste/functions.cpp
new file mode 100644
index 0000000..29f389a
--- /dev/null
+++ b/clang/test/Analysis/copypaste/functions.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -analyze -std=c++11 -analyzer-checker=alpha.clone.CloneChecker -verify %s
+
+// This tests if we search for clones in functions.
+
+void log();
+
+int max(int a, int b) { // expected-warning{{Detected code clone.}}
+  log();
+  if (a > b)
+    return a;
+  return b;
+}
+
+int maxClone(int x, int y) { // expected-note{{Related code clone is here.}}
+  log();
+  if (x > y)
+    return x;
+  return y;
+}
+
+// Functions below are not clones and should not be reported.
+
+int foo(int a, int b) { // no-warning
+  return a + b;
+}
diff --git a/clang/test/Analysis/copypaste/objc-methods.m b/clang/test/Analysis/copypaste/objc-methods.m
new file mode 100644
index 0000000..0636447e
--- /dev/null
+++ b/clang/test/Analysis/copypaste/objc-methods.m
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -analyze -Wno-objc-root-class -analyzer-checker=alpha.clone.CloneChecker -verify %s
+
+// This tests if we search for clones in Objective-C methods.
+
+@interface A
+- (int) setOk : (int) a : (int) b;
+@end
+
+@implementation A
+- (int) setOk : (int) a : (int) b {  // expected-warning{{Detected code clone.}}
+  if (a > b)
+    return a;
+  return b;
+}
+@end
+
+@interface B
+- (int) setOk : (int) a : (int) b;
+@end
+
+@implementation B
+- (int) setOk : (int) a : (int) b { // expected-note{{Related code clone is here.}}
+  if (a > b)
+    return a;
+  return b;
+}
+@end
diff --git a/clang/test/Analysis/copypaste/sub-sequences.cpp b/clang/test/Analysis/copypaste/sub-sequences.cpp
new file mode 100644
index 0000000..59dc464
--- /dev/null
+++ b/clang/test/Analysis/copypaste/sub-sequences.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -analyze -std=c++11 -analyzer-checker=alpha.clone.CloneChecker -verify %s
+
+// This tests if sub-sequences can match with normal sequences.
+
+void log2(int a);
+void log();
+
+int max(int a, int b) {
+  log2(a);
+  log(); // expected-warning{{Detected code clone.}}
+  if (a > b)
+    return a;
+  return b;
+}
+
+int maxClone(int a, int b) {
+  log(); // expected-note{{Related code clone is here.}}
+  if (a > b)
+    return a;
+  return b;
+}
+
+// Functions below are not clones and should not be reported.
+
+int foo(int a, int b) { // no-warning
+  return a + b;
+}