[analyzer] Re-apply r283094 "Improve CloneChecker diagnostics"

The parent commit (r283092) was reverted before and now finally landed.

llvm-svn: 283661
diff --git a/clang/test/Analysis/copypaste/blocks.cpp b/clang/test/Analysis/copypaste/blocks.cpp
index 0bd9812..133b5cb 100644
--- a/clang/test/Analysis/copypaste/blocks.cpp
+++ b/clang/test/Analysis/copypaste/blocks.cpp
@@ -4,14 +4,14 @@
 
 void log();
 
-auto BlockA = ^(int a, int b){ // expected-warning{{Detected code clone.}}
+auto BlockA = ^(int a, int b){ // expected-warning{{Duplicate code detected}}
   log();
   if (a > b)
     return a;
   return b;
 };
 
-auto BlockB = ^(int a, int b){ // expected-note{{Related code clone is here.}}
+auto BlockB = ^(int a, int b){ // expected-note{{Similar code here}}
   log();
   if (a > b)
     return a;
diff --git a/clang/test/Analysis/copypaste/function-try-block.cpp b/clang/test/Analysis/copypaste/function-try-block.cpp
index b13096d..7a69097 100644
--- a/clang/test/Analysis/copypaste/function-try-block.cpp
+++ b/clang/test/Analysis/copypaste/function-try-block.cpp
@@ -3,7 +3,7 @@
 // Tests if function try blocks are correctly handled.
 
 void nonCompoundStmt1(int& x)
-  try { x += 1; } catch(...) { x -= 1; } // expected-warning{{Detected code clone.}}
+  try { x += 1; } catch(...) { x -= 1; } // expected-warning{{Duplicate code detected}}
 
 void nonCompoundStmt2(int& x)
-  try { x += 1; } catch(...) { x -= 1; } // expected-note{{Related code clone is here.}}
+  try { x += 1; } catch(...) { x -= 1; } // expected-note{{Similar code here}}
diff --git a/clang/test/Analysis/copypaste/functions.cpp b/clang/test/Analysis/copypaste/functions.cpp
index 2a871f7..c95443d 100644
--- a/clang/test/Analysis/copypaste/functions.cpp
+++ b/clang/test/Analysis/copypaste/functions.cpp
@@ -4,14 +4,14 @@
 
 void log();
 
-int max(int a, int b) { // expected-warning{{Detected code clone.}}
+int max(int a, int b) { // expected-warning{{Duplicate code detected}}
   log();
   if (a > b)
     return a;
   return b;
 }
 
-int maxClone(int x, int y) { // expected-note{{Related code clone is here.}}
+int maxClone(int x, int y) { // expected-note{{Similar code here}}
   log();
   if (x > y)
     return x;
diff --git a/clang/test/Analysis/copypaste/macro-complexity.cpp b/clang/test/Analysis/copypaste/macro-complexity.cpp
index 58b884a..aca4df1 100644
--- a/clang/test/Analysis/copypaste/macro-complexity.cpp
+++ b/clang/test/Analysis/copypaste/macro-complexity.cpp
@@ -11,11 +11,11 @@
 // This confirms that with the current configuration the macro body would be
 // considered large enough to pass the MinimumCloneComplexity constraint.
 
-int manualMacro(int a, int b) { // expected-warning{{Detected code clone.}}
+int manualMacro(int a, int b) { // expected-warning{{Duplicate code detected}}
   return a > b ? -a * a : -b * b;
 }
 
-int manualMacroClone(int a, int b) { // expected-note{{Related code clone is here.}}
+int manualMacroClone(int a, int b) { // expected-note{{Similar code here}}
   return a > b ? -a * a : -b * b;
 }
 
@@ -41,10 +41,10 @@
 
 #define NEG(A) -(A)
 
-int nestedMacros() { // expected-warning{{Detected code clone.}}
+int nestedMacros() { // expected-warning{{Duplicate code detected}}
   return NEG(NEG(NEG(NEG(NEG(NEG(NEG(NEG(NEG(NEG(1))))))))));
 }
 
-int nestedMacrosClone() { // expected-note{{Related code clone is here.}}
+int nestedMacrosClone() { // expected-note{{Similar code here}}
   return NEG(NEG(NEG(NEG(NEG(NEG(NEG(NEG(NEG(NEG(1))))))))));
 }
diff --git a/clang/test/Analysis/copypaste/macros.cpp b/clang/test/Analysis/copypaste/macros.cpp
index 170e034..db9b4c6 100644
--- a/clang/test/Analysis/copypaste/macros.cpp
+++ b/clang/test/Analysis/copypaste/macros.cpp
@@ -5,7 +5,7 @@
 // to have the same complexity value. Macros have smaller complexity values
 // and need to be in their own hash group.
 
-int foo(int a) { // expected-warning{{Detected code clone.}}
+int foo(int a) { // expected-warning{{Duplicate code detected}}
   a = a + 1;
   a = a + 1 / 1;
   a = a + 1 + 1 + 1;
@@ -15,7 +15,7 @@
   return a;
 }
 
-int fooClone(int a) { // expected-note{{Related code clone is here.}}
+int fooClone(int a) { // expected-note{{Similar code here}}
   a = a + 1;
   a = a + 1 / 1;
   a = a + 1 + 1 + 1;
@@ -30,7 +30,7 @@
 
 #define ASSIGN(T, V) T = T + V
 
-int macro(int a) { // expected-warning{{Detected code clone.}}
+int macro(int a) { // expected-warning{{Duplicate code detected}}
   ASSIGN(a, 1);
   ASSIGN(a, 1 / 1);
   ASSIGN(a, 1 + 1 + 1);
@@ -40,7 +40,7 @@
   return a;
 }
 
-int macroClone(int a) { // expected-note{{Related code clone is here.}}
+int macroClone(int a) { // expected-note{{Similar code here}}
   ASSIGN(a, 1);
   ASSIGN(a, 1 / 1);
   ASSIGN(a, 1 + 1 + 1);
@@ -54,7 +54,7 @@
 
 #define EMPTY
 
-int fooFalsePositiveClone(int a) { // expected-note{{Related code clone is here.}}
+int fooFalsePositiveClone(int a) { // expected-note{{Similar code here}}
   a = EMPTY a + 1;
   a = a + 1 / 1;
   a = a + 1 + 1 + 1;
diff --git a/clang/test/Analysis/copypaste/objc-methods.m b/clang/test/Analysis/copypaste/objc-methods.m
index 0636447e..9b8002c 100644
--- a/clang/test/Analysis/copypaste/objc-methods.m
+++ b/clang/test/Analysis/copypaste/objc-methods.m
@@ -7,7 +7,7 @@
 @end
 
 @implementation A
-- (int) setOk : (int) a : (int) b {  // expected-warning{{Detected code clone.}}
+- (int) setOk : (int) a : (int) b {  // expected-warning{{Duplicate code detected}}
   if (a > b)
     return a;
   return b;
@@ -19,7 +19,7 @@
 @end
 
 @implementation B
-- (int) setOk : (int) a : (int) b { // expected-note{{Related code clone is here.}}
+- (int) setOk : (int) a : (int) b { // expected-note{{Similar code here}}
   if (a > b)
     return a;
   return b;
diff --git a/clang/test/Analysis/copypaste/plist-diagnostics-notes-as-events.cpp b/clang/test/Analysis/copypaste/plist-diagnostics-notes-as-events.cpp
new file mode 100644
index 0000000..1180d44
--- /dev/null
+++ b/clang/test/Analysis/copypaste/plist-diagnostics-notes-as-events.cpp
@@ -0,0 +1,97 @@
+// RUN: %clang_cc1 -analyze -analyzer-output=plist -analyzer-config notes-as-events=true -o %t.plist -std=c++11 -analyzer-checker=alpha.clone.CloneChecker -verify %s
+// RUN: FileCheck --input-file=%t.plist %s
+
+void log();
+
+int max(int a, int b) { // expected-warning{{Duplicate code detected}}
+  log();
+  if (a > b)
+    return a;
+  return b;
+}
+
+int maxClone(int a, int b) { // no-note (converted into event)
+  log();
+  if (a > b)
+    return a;
+  return b;
+}
+
+// CHECK:  <key>diagnostics</key>
+// CHECK-NEXT:  <array>
+// CHECK-NEXT:   <dict>
+// CHECK-NEXT:    <key>path</key>
+// CHECK-NEXT:    <array>
+// CHECK-NEXT:     <dict>
+// CHECK-NEXT:      <key>kind</key><string>event</string>
+// CHECK-NEXT:      <key>location</key>
+// CHECK-NEXT:      <dict>
+// CHECK-NEXT:       <key>line</key><integer>13</integer>
+// CHECK-NEXT:       <key>col</key><integer>28</integer>
+// CHECK-NEXT:       <key>file</key><integer>0</integer>
+// CHECK-NEXT:      </dict>
+// CHECK-NEXT:      <key>ranges</key>
+// CHECK-NEXT:      <array>
+// CHECK-NEXT:        <array>
+// CHECK-NEXT:         <dict>
+// CHECK-NEXT:          <key>line</key><integer>13</integer>
+// CHECK-NEXT:          <key>col</key><integer>28</integer>
+// CHECK-NEXT:          <key>file</key><integer>0</integer>
+// CHECK-NEXT:         </dict>
+// CHECK-NEXT:         <dict>
+// CHECK-NEXT:          <key>line</key><integer>18</integer>
+// CHECK-NEXT:          <key>col</key><integer>1</integer>
+// CHECK-NEXT:          <key>file</key><integer>0</integer>
+// CHECK-NEXT:         </dict>
+// CHECK-NEXT:        </array>
+// CHECK-NEXT:      </array>
+// CHECK-NEXT:      <key>depth</key><integer>0</integer>
+// CHECK-NEXT:      <key>extended_message</key>
+// CHECK-NEXT:      <string>Similar code here</string>
+// CHECK-NEXT:      <key>message</key>
+// CHECK-NEXT:      <string>Similar code here</string>
+// CHECK-NEXT:     </dict>
+// CHECK-NEXT:     <dict>
+// CHECK-NEXT:      <key>kind</key><string>event</string>
+// CHECK-NEXT:      <key>location</key>
+// CHECK-NEXT:      <dict>
+// CHECK-NEXT:       <key>line</key><integer>6</integer>
+// CHECK-NEXT:       <key>col</key><integer>23</integer>
+// CHECK-NEXT:       <key>file</key><integer>0</integer>
+// CHECK-NEXT:      </dict>
+// CHECK-NEXT:      <key>ranges</key>
+// CHECK-NEXT:      <array>
+// CHECK-NEXT:        <array>
+// CHECK-NEXT:         <dict>
+// CHECK-NEXT:          <key>line</key><integer>6</integer>
+// CHECK-NEXT:          <key>col</key><integer>23</integer>
+// CHECK-NEXT:          <key>file</key><integer>0</integer>
+// CHECK-NEXT:         </dict>
+// CHECK-NEXT:         <dict>
+// CHECK-NEXT:          <key>line</key><integer>11</integer>
+// CHECK-NEXT:          <key>col</key><integer>1</integer>
+// CHECK-NEXT:          <key>file</key><integer>0</integer>
+// CHECK-NEXT:         </dict>
+// CHECK-NEXT:        </array>
+// CHECK-NEXT:      </array>
+// CHECK-NEXT:      <key>depth</key><integer>0</integer>
+// CHECK-NEXT:      <key>extended_message</key>
+// CHECK-NEXT:      <string>Duplicate code detected</string>
+// CHECK-NEXT:      <key>message</key>
+// CHECK-NEXT:      <string>Duplicate code detected</string>
+// CHECK-NEXT:     </dict>
+// CHECK-NEXT:    </array>
+// CHECK-NEXT:    <key>description</key><string>Duplicate code detected</string>
+// CHECK-NEXT:    <key>category</key><string>Code clone</string>
+// CHECK-NEXT:    <key>type</key><string>Exact code clone</string>
+// CHECK-NEXT:    <key>check_name</key><string>alpha.clone.CloneChecker</string>
+// CHECK-NEXT:    <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT:    <key>issue_hash_content_of_line_in_context</key><string>3d15184f38c5fa57e479b744fe3f5035</string>
+// CHECK-NEXT:   <key>location</key>
+// CHECK-NEXT:   <dict>
+// CHECK-NEXT:    <key>line</key><integer>6</integer>
+// CHECK-NEXT:    <key>col</key><integer>23</integer>
+// CHECK-NEXT:    <key>file</key><integer>0</integer>
+// CHECK-NEXT:   </dict>
+// CHECK-NEXT:   </dict>
+// CHECK-NEXT:  </array>
diff --git a/clang/test/Analysis/copypaste/plist-diagnostics.cpp b/clang/test/Analysis/copypaste/plist-diagnostics.cpp
new file mode 100644
index 0000000..109d8e4
--- /dev/null
+++ b/clang/test/Analysis/copypaste/plist-diagnostics.cpp
@@ -0,0 +1,71 @@
+// RUN: %clang_cc1 -analyze -analyzer-output=plist -o %t.plist -std=c++11 -analyzer-checker=alpha.clone.CloneChecker -verify %s
+// RUN: FileCheck --input-file=%t.plist %s
+
+void log();
+
+int max(int a, int b) { // expected-warning{{Duplicate code detected}}
+  log();
+  if (a > b)
+    return a;
+  return b;
+}
+
+int maxClone(int a, int b) { // expected-note{{Similar code here}}
+  log();
+  if (a > b)
+    return a;
+  return b;
+}
+
+// FIXME: This plist output doesn't include the extra note on line 13.
+// It should be updated once the format for extra notes in plists is defined.
+
+// CHECK:  <key>diagnostics</key>
+// CHECK-NEXT:  <array>
+// CHECK-NEXT:   <dict>
+// CHECK-NEXT:    <key>path</key>
+// CHECK-NEXT:    <array>
+// CHECK-NEXT:     <dict>
+// CHECK-NEXT:      <key>kind</key><string>event</string>
+// CHECK-NEXT:      <key>location</key>
+// CHECK-NEXT:      <dict>
+// CHECK-NEXT:       <key>line</key><integer>6</integer>
+// CHECK-NEXT:       <key>col</key><integer>23</integer>
+// CHECK-NEXT:       <key>file</key><integer>0</integer>
+// CHECK-NEXT:      </dict>
+// CHECK-NEXT:      <key>ranges</key>
+// CHECK-NEXT:      <array>
+// CHECK-NEXT:        <array>
+// CHECK-NEXT:         <dict>
+// CHECK-NEXT:          <key>line</key><integer>6</integer>
+// CHECK-NEXT:          <key>col</key><integer>23</integer>
+// CHECK-NEXT:          <key>file</key><integer>0</integer>
+// CHECK-NEXT:         </dict>
+// CHECK-NEXT:         <dict>
+// CHECK-NEXT:          <key>line</key><integer>11</integer>
+// CHECK-NEXT:          <key>col</key><integer>1</integer>
+// CHECK-NEXT:          <key>file</key><integer>0</integer>
+// CHECK-NEXT:         </dict>
+// CHECK-NEXT:        </array>
+// CHECK-NEXT:      </array>
+// CHECK-NEXT:      <key>depth</key><integer>0</integer>
+// CHECK-NEXT:      <key>extended_message</key>
+// CHECK-NEXT:      <string>Duplicate code detected</string>
+// CHECK-NEXT:      <key>message</key>
+// CHECK-NEXT:      <string>Duplicate code detected</string>
+// CHECK-NEXT:     </dict>
+// CHECK-NEXT:    </array>
+// CHECK-NEXT:    <key>description</key><string>Duplicate code detected</string>
+// CHECK-NEXT:    <key>category</key><string>Code clone</string>
+// CHECK-NEXT:    <key>type</key><string>Exact code clone</string>
+// CHECK-NEXT:    <key>check_name</key><string>alpha.clone.CloneChecker</string>
+// CHECK-NEXT:    <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT:    <key>issue_hash_content_of_line_in_context</key><string>3d15184f38c5fa57e479b744fe3f5035</string>
+// CHECK-NEXT:   <key>location</key>
+// CHECK-NEXT:   <dict>
+// CHECK-NEXT:    <key>line</key><integer>6</integer>
+// CHECK-NEXT:    <key>col</key><integer>23</integer>
+// CHECK-NEXT:    <key>file</key><integer>0</integer>
+// CHECK-NEXT:   </dict>
+// CHECK-NEXT:   </dict>
+// CHECK-NEXT:  </array>
diff --git a/clang/test/Analysis/copypaste/sub-sequences.cpp b/clang/test/Analysis/copypaste/sub-sequences.cpp
index 59dc464..ff73632 100644
--- a/clang/test/Analysis/copypaste/sub-sequences.cpp
+++ b/clang/test/Analysis/copypaste/sub-sequences.cpp
@@ -7,14 +7,14 @@
 
 int max(int a, int b) {
   log2(a);
-  log(); // expected-warning{{Detected code clone.}}
+  log(); // expected-warning{{Duplicate code detected}}
   if (a > b)
     return a;
   return b;
 }
 
 int maxClone(int a, int b) {
-  log(); // expected-note{{Related code clone is here.}}
+  log(); // expected-note{{Similar code here}}
   if (a > b)
     return a;
   return b;
diff --git a/clang/test/Analysis/copypaste/suspicious-clones.cpp b/clang/test/Analysis/copypaste/suspicious-clones.cpp
index fb22d38c8..c64a1dc 100644
--- a/clang/test/Analysis/copypaste/suspicious-clones.cpp
+++ b/clang/test/Analysis/copypaste/suspicious-clones.cpp
@@ -8,14 +8,14 @@
   log();
   if (a > b)
     return a;
-  return b; // expected-note{{suggestion is based on the usage of this variable in a similar piece of code}}
+  return b; // expected-note{{Similar code using 'b' here}}
 }
 
 int maxClone(int x, int y, int z) {
   log();
   if (x > y)
     return x;
-  return z; // expected-warning{{suspicious code clone detected; did you mean to use 'y'?}}
+  return z; // expected-warning{{Potential copy-paste error; did you really mean to use 'z' here?}}
 }
 
 // Tests finding a suspicious clone that references global variables.
@@ -33,7 +33,7 @@
   while (true) {
     if (m1.try_lock()) {
       ++i;
-      m1.unlock(); // expected-note{{suggestion is based on the usage of this variable in a similar piece of code}}
+      m1.unlock(); // expected-note{{Similar code using 'm1' here}}
       if (i > 1000) {
         return;
       }
@@ -45,7 +45,7 @@
   while (true) {
     if (m1.try_lock()) {
       ++i;
-      m2.unlock();  // expected-warning{{suspicious code clone detected; did you mean to use 'm1'?}}
+      m2.unlock();  // expected-warning{{Potential copy-paste error; did you really mean to use 'm2' here?}}
       if (i > 1000) {
         return;
       }
@@ -58,14 +58,14 @@
 int foo(int a, int b, int c) {
   a += b + c;
   b /= a + b;
-  c -= b * a; // expected-warning{{suspicious code clone detected; did you mean to use 'a'?}}
+  c -= b * a; // expected-warning{{Potential copy-paste error; did you really mean to use 'b' here?}}
   return c;
 }
 
 int fooClone(int a, int b, int c) {
   a += b + c;
   b /= a + b;
-  c -= a * a; // expected-note{{suggestion is based on the usage of this variable in a similar piece of code; did you mean to use 'b'?}}
+  c -= a * a; // expected-note{{Similar code using 'a' here}}
   return c;
 }
 
@@ -77,21 +77,21 @@
 long bar1(long a, long b, long c, long d) {
   c = a - b;
   c = c / d * a;
-  d = b * b - c; // expected-warning{{suspicious code clone detected; did you mean to use 'c'?}}
+  d = b * b - c; // expected-warning{{Potential copy-paste error; did you really mean to use 'b' here?}}
   return d;
 }
 
 long bar2(long a, long b, long c, long d) {
   c = a - b;
   c = c / d * a;
-  d = c * b - c; // expected-note{{suggestion is based on the usage of this variable in a similar piece of code; did you mean to use 'b'?}} \
-                 // expected-warning{{suspicious code clone detected; did you mean to use 'a'?}}
+  d = c * b - c; // expected-note{{Similar code using 'c' here}} \
+                 // expected-warning{{Potential copy-paste error; did you really mean to use 'c' here?}}
   return d;
 }
 
 long bar3(long a, long b, long c, long d) {
   c = a - b;
   c = c / d * a;
-  d = a * b - c; // expected-note{{suggestion is based on the usage of this variable in a similar piece of code; did you mean to use 'c'?}}
+  d = a * b - c; // expected-note{{Similar code using 'a' here}}
   return d;
 }
diff --git a/clang/test/Analysis/copypaste/text-diagnostics.cpp b/clang/test/Analysis/copypaste/text-diagnostics.cpp
new file mode 100644
index 0000000..a80afdb
--- /dev/null
+++ b/clang/test/Analysis/copypaste/text-diagnostics.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -analyze -analyzer-output=text -std=c++11 -analyzer-checker=alpha.clone.CloneChecker -verify %s
+
+void log();
+
+int max(int a, int b) { // expected-warning{{Duplicate code detected}} // expected-note{{Duplicate code detected}}
+  log();
+  if (a > b)
+    return a;
+  return b;
+}
+
+int maxClone(int a, int b) { // expected-note{{Similar code here}}
+  log();
+  if (a > b)
+    return a;
+  return b;
+}