xref: /llvm-project/clang/test/Analysis/copypaste/suspicious-clones.cpp (revision 56e241a07ff7f839d39775dbf05de5153a8e7d9f)
1 // RUN: %clang_analyze_cc1 -verify %s \
2 // RUN:   -analyzer-checker=alpha.clone.CloneChecker \
3 // RUN:   -analyzer-config alpha.clone.CloneChecker:ReportNormalClones=false \
4 // RUN:   -analyzer-config alpha.clone.CloneChecker:MinimumCloneComplexity=10
5 
6 // Tests finding a suspicious clone that references local variables.
7 
8 void log();
9 
max(int a,int b)10 int max(int a, int b) {
11   log();
12   if (a > b)
13     return a;
14   return b; // expected-note{{Similar code using 'b' here}}
15 }
16 
maxClone(int x,int y,int z)17 int maxClone(int x, int y, int z) {
18   log();
19   if (x > y)
20     return x;
21   return z; // expected-warning{{Potential copy-paste error; did you really mean to use 'z' here?}}
22 }
23 
24 // Test that the checker works with [[clang::suppress]].
max_suppressed(int a,int b)25 int max_suppressed(int a, int b) {
26   log();
27   if (a > b)
28     return a;
29 
30   // This [[clang::suppress]] doesn't suppress anything but we need it here
31   // because otherwise the other function won't count as a perfect clone.
32   // FIXME: The checker should probably skip the attribute entirely
33   // when detecting clones. Otherwise warnings will still get suppressed,
34   // but for a completely wrong reason.
35   [[clang::suppress]]
36   return b; // no-note
37 }
38 
maxClone_suppressed(int x,int y,int z)39 int maxClone_suppressed(int x, int y, int z) {
40   log();
41   if (x > y)
42     return x;
43   [[clang::suppress]]
44   return z; // no-warning
45 }
46 
47 
48 // Tests finding a suspicious clone that references global variables.
49 
50 struct mutex {
51   bool try_lock();
52   void unlock();
53 };
54 
55 mutex m1;
56 mutex m2;
57 int i;
58 
busyIncrement()59 void busyIncrement() {
60   while (true) {
61     if (m1.try_lock()) {
62       ++i;
63       m1.unlock(); // expected-note{{Similar code using 'm1' here}}
64       if (i > 1000) {
65         return;
66       }
67     }
68   }
69 }
70 
faultyBusyIncrement()71 void faultyBusyIncrement() {
72   while (true) {
73     if (m1.try_lock()) {
74       ++i;
75       m2.unlock();  // expected-warning{{Potential copy-paste error; did you really mean to use 'm2' here?}}
76       if (i > 1000) {
77         return;
78       }
79     }
80   }
81 }
82 
83 // Tests that we provide two suggestions in cases where two fixes are possible.
84 
foo(int a,int b,int c)85 int foo(int a, int b, int c) {
86   a += b + c;
87   b /= a + b;
88   c -= b * a; // expected-warning{{Potential copy-paste error; did you really mean to use 'b' here?}}
89   return c;
90 }
91 
fooClone(int a,int b,int c)92 int fooClone(int a, int b, int c) {
93   a += b + c;
94   b /= a + b;
95   c -= a * a; // expected-note{{Similar code using 'a' here}}
96   return c;
97 }
98 
99 
100 // Tests that for clone groups with a many possible suspicious clone pairs, at
101 // most one warning per clone group is generated and every relevant clone is
102 // reported through either a warning or a note.
103 
bar1(long a,long b,long c,long d)104 long bar1(long a, long b, long c, long d) {
105   c = a - b;
106   c = c / d * a;
107   d = b * b - c; // expected-warning{{Potential copy-paste error; did you really mean to use 'b' here?}}
108   return d;
109 }
110 
bar2(long a,long b,long c,long d)111 long bar2(long a, long b, long c, long d) {
112   c = a - b;
113   c = c / d * a;
114   d = c * b - c; // expected-note{{Similar code using 'c' here}} \
115                  // expected-warning{{Potential copy-paste error; did you really mean to use 'c' here?}}
116   return d;
117 }
118 
bar3(long a,long b,long c,long d)119 long bar3(long a, long b, long c, long d) {
120   c = a - b;
121   c = c / d * a;
122   d = a * b - c; // expected-note{{Similar code using 'a' here}}
123   return d;
124 }
125