diff options
Diffstat (limited to 'clang/test')
-rw-r--r-- | clang/test/Analysis/copypaste/asm.cpp | 44 | ||||
-rw-r--r-- | clang/test/Analysis/copypaste/attributes.cpp | 28 | ||||
-rw-r--r-- | clang/test/Analysis/copypaste/call.cpp | 24 | ||||
-rw-r--r-- | clang/test/Analysis/copypaste/catch.cpp | 29 | ||||
-rw-r--r-- | clang/test/Analysis/copypaste/delete.cpp | 29 | ||||
-rw-r--r-- | clang/test/Analysis/copypaste/dependent-exist.cpp | 18 | ||||
-rw-r--r-- | clang/test/Analysis/copypaste/expr-types.cpp | 17 | ||||
-rw-r--r-- | clang/test/Analysis/copypaste/false-positives.cpp | 8 | ||||
-rw-r--r-- | clang/test/Analysis/copypaste/fold.cpp | 35 | ||||
-rw-r--r-- | clang/test/Analysis/copypaste/function-try-block.cpp | 9 | ||||
-rw-r--r-- | clang/test/Analysis/copypaste/functions.cpp | 25 | ||||
-rw-r--r-- | clang/test/Analysis/copypaste/generic.c | 31 | ||||
-rw-r--r-- | clang/test/Analysis/copypaste/labels.cpp | 51 | ||||
-rw-r--r-- | clang/test/Analysis/copypaste/lambda.cpp | 24 |
14 files changed, 364 insertions, 8 deletions
diff --git a/clang/test/Analysis/copypaste/asm.cpp b/clang/test/Analysis/copypaste/asm.cpp new file mode 100644 index 00000000000..61f0def594d --- /dev/null +++ b/clang/test/Analysis/copypaste/asm.cpp @@ -0,0 +1,44 @@ +// RUN: %clang_cc1 -analyze -std=c++11 -analyzer-checker=alpha.clone.CloneChecker -verify %s + +// expected-no-diagnostics + +int foo1(int src) { + int dst = src; + if (src < 100 && src > 0) { + + asm ("mov %1, %0\n\t" + "add $1, %0" + : "=r" (dst) + : "r" (src)); + + } + return dst; +} + +// Identical to foo1 except that it adds two instead of one, so it's no clone. +int foo2(int src) { + int dst = src; + if (src < 100 && src > 0) { + + asm ("mov %1, %0\n\t" + "add $2, %0" + : "=r" (dst) + : "r" (src)); + + } + return dst; +} + +// Identical to foo1 except that its a volatile asm statement, so it's no clone. +int foo3(int src) { + int dst = src; + if (src < 100 && src > 0) { + + asm volatile ("mov %1, %0\n\t" + "add $1, %0" + : "=r" (dst) + : "r" (src)); + + } + return dst; +} diff --git a/clang/test/Analysis/copypaste/attributes.cpp b/clang/test/Analysis/copypaste/attributes.cpp new file mode 100644 index 00000000000..72d654c6e06 --- /dev/null +++ b/clang/test/Analysis/copypaste/attributes.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -analyze -std=c++1z -analyzer-checker=alpha.clone.CloneChecker -verify %s + +// expected-no-diagnostics + +int foo1(int n) { + int result = 0; + switch (n) { + case 33: + result += 33; + [[clang::fallthrough]]; + case 44: + result += 44; + } + return result; +} + +// Identical to foo1 except the missing attribute. +int foo2(int n) { + int result = 0; + switch (n) { + case 33: + result += 33; + ; + case 44: + result += 44; + } + return result; +} diff --git a/clang/test/Analysis/copypaste/call.cpp b/clang/test/Analysis/copypaste/call.cpp new file mode 100644 index 00000000000..06aa633fe96 --- /dev/null +++ b/clang/test/Analysis/copypaste/call.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -analyze -std=c++1z -analyzer-checker=alpha.clone.CloneChecker -verify %s + +// expected-no-diagnostics + +bool a(); +bool b(); + +// Calls method a with some extra code to pass the minimum complexity +bool foo1(int x) { + if (x > 0) + return false; + else if (x < 0) + return a(); + return true; +} + +// Calls method b with some extra code to pass the minimum complexity +bool foo2(int x) { + if (x > 0) + return false; + else if (x < 0) + return b(); + return true; +} diff --git a/clang/test/Analysis/copypaste/catch.cpp b/clang/test/Analysis/copypaste/catch.cpp new file mode 100644 index 00000000000..590ce8f223f --- /dev/null +++ b/clang/test/Analysis/copypaste/catch.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -analyze -fcxx-exceptions -std=c++1z -analyzer-checker=alpha.clone.CloneChecker -verify %s + +// expected-no-diagnostics + +bool foo1(int x) { + if (x > 0) + return false; + else if (x < 0) + try { x--; } catch (int i) {} + return true; +} + +// Uses parenthesis instead of type +bool foo2(int x) { + if (x > 0) + return false; + else if (x < 0) + try { x--; } catch (...) {} + return true; +} + +// Catches a different type (long instead of int) +bool foo3(int x) { + if (x > 0) + return false; + else if (x < 0) + try { x--; } catch (long i) {} + return true; +} diff --git a/clang/test/Analysis/copypaste/delete.cpp b/clang/test/Analysis/copypaste/delete.cpp new file mode 100644 index 00000000000..dc42c9c0595 --- /dev/null +++ b/clang/test/Analysis/copypaste/delete.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -analyze -std=c++1z -analyzer-checker=alpha.clone.CloneChecker -verify %s + +// expected-no-diagnostics + +bool foo1(int x, int* a) { + if (x > 0) + return false; + else if (x < 0) + delete a; + return true; +} + +// Explicit global delete +bool foo2(int x, int* a) { + if (x > 0) + return false; + else if (x < 0) + ::delete a; + return true; +} + +// Array delete +bool foo3(int x, int* a) { + if (x > 0) + return false; + else if (x < 0) + delete[] a; + return true; +} diff --git a/clang/test/Analysis/copypaste/dependent-exist.cpp b/clang/test/Analysis/copypaste/dependent-exist.cpp new file mode 100644 index 00000000000..5182ba61c9d --- /dev/null +++ b/clang/test/Analysis/copypaste/dependent-exist.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -analyze -fms-extensions -std=c++1z -analyzer-checker=alpha.clone.CloneChecker -verify %s + +// expected-no-diagnostics + +bool foo1(int x) { + if (x < 0) { + __if_exists(x) { return false; } + } + return true; +} + +// Same as above, but __if_not_exists +bool foo2(int x) { + if (x < 0) { + __if_not_exists(x) { return false; } + } + return true; +} diff --git a/clang/test/Analysis/copypaste/expr-types.cpp b/clang/test/Analysis/copypaste/expr-types.cpp new file mode 100644 index 00000000000..14eef6eac63 --- /dev/null +++ b/clang/test/Analysis/copypaste/expr-types.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -analyze -std=c++11 -analyzer-checker=alpha.clone.CloneChecker -verify %s + +// expected-no-diagnostics + + +int foo1(int a, int b) { + if (a > b) + return a; + return b; +} + +// Different types, so not a clone +int foo2(long a, long b) { + 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 index 8d649c790b8..4c6275949da 100644 --- a/clang/test/Analysis/copypaste/false-positives.cpp +++ b/clang/test/Analysis/copypaste/false-positives.cpp @@ -12,14 +12,6 @@ int max(int a, int b) { // expected-warning{{Detected code clone.}} 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(); diff --git a/clang/test/Analysis/copypaste/fold.cpp b/clang/test/Analysis/copypaste/fold.cpp new file mode 100644 index 00000000000..548dfb19af5 --- /dev/null +++ b/clang/test/Analysis/copypaste/fold.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -analyze -std=c++1z -analyzer-checker=alpha.clone.CloneChecker -verify %s + +// expected-no-diagnostics + +int global = 0; + +template<typename ...Args> +int foo1(Args&&... args) { + if (global > 0) + return 0; + else if (global < 0) + return (args + ...); + return 1; +} + +// Different opeator in fold expression. +template<typename ...Args> +int foo2(Args&&... args) { + if (global > 0) + return 0; + else if (global < 0) + return (args - ...); + return 1; +} + +// Parameter pack on a different side +template<typename ...Args> +int foo3(Args&&... args) { + if (global > 0) + return 0; + else if (global < 0) + return -1; + return (... + args); +return 1; +} diff --git a/clang/test/Analysis/copypaste/function-try-block.cpp b/clang/test/Analysis/copypaste/function-try-block.cpp new file mode 100644 index 00000000000..b13096d949a --- /dev/null +++ b/clang/test/Analysis/copypaste/function-try-block.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -analyze -fcxx-exceptions -std=c++1z -analyzer-checker=alpha.clone.CloneChecker -verify %s + +// Tests if function try blocks are correctly handled. + +void nonCompoundStmt1(int& x) + try { x += 1; } catch(...) { x -= 1; } // expected-warning{{Detected code clone.}} + +void nonCompoundStmt2(int& x) + try { x += 1; } catch(...) { x -= 1; } // expected-note{{Related code clone is here.}} diff --git a/clang/test/Analysis/copypaste/functions.cpp b/clang/test/Analysis/copypaste/functions.cpp index 29f389a5eac..bedd374b79d 100644 --- a/clang/test/Analysis/copypaste/functions.cpp +++ b/clang/test/Analysis/copypaste/functions.cpp @@ -20,6 +20,31 @@ int maxClone(int x, int y) { // expected-note{{Related code clone is here.}} // Functions below are not clones and should not be reported. +// The next two functions test that statement classes are still respected when +// checking for clones in expressions. This will show that the statement +// specific data of all base classes is collected, and not just the data of the +// first base class. +int testBaseClass(int a, int b) { // no-warning + log(); + if (a > b) + return true ? a : b; + return b; +} +int testBaseClass2(int a, int b) { // no-warning + log(); + if (a > b) + return __builtin_choose_expr(true, a, b); + return b; +} + + +int min1(int a, int b) { // no-warning + log(); + if (a < b) + return a; + return b; +} + int foo(int a, int b) { // no-warning return a + b; } diff --git a/clang/test/Analysis/copypaste/generic.c b/clang/test/Analysis/copypaste/generic.c new file mode 100644 index 00000000000..9d8392139b3 --- /dev/null +++ b/clang/test/Analysis/copypaste/generic.c @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -analyze -std=c11 -analyzer-checker=alpha.clone.CloneChecker -verify %s + +// expected-no-diagnostics + +int global; + +int foo1() { + if (global > 0) + return 0; + else if (global < 0) + return _Generic(global, double: 1, float: 2, default: 3); + return 1; +} + +// Different associated type (int instead of float) +int foo2() { + if (global > 0) + return 0; + else if (global < 0) + return _Generic(global, double: 1, int: 2, default: 4); + return 1; +} + +// Different number of associated types. +int foo3() { + if (global > 0) + return 0; + else if (global < 0) + return _Generic(global, double: 1, default: 4); + return 1; +} diff --git a/clang/test/Analysis/copypaste/labels.cpp b/clang/test/Analysis/copypaste/labels.cpp new file mode 100644 index 00000000000..26318ac4051 --- /dev/null +++ b/clang/test/Analysis/copypaste/labels.cpp @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 -analyze -std=gnu++11 -analyzer-checker=alpha.clone.CloneChecker -verify %s + +// expected-no-diagnostics + + +bool foo1(int x) { + start: + if (x != 3) { + ++x; + void *ptr = &&start; + goto start; + } + end: + return false; +} + +// Targeting a different label with the address-of-label operator. +bool foo2(int x) { + start: + if (x != 3) { + ++x; + void *ptr = &&end; + goto start; + } + end: + return false; +} + +// Different target label in goto +bool foo3(int x) { + start: + if (x != 3) { + ++x; + void *ptr = &&start; + goto end; + } + end: + return false; +} + +// FIXME: Can't detect same algorithm as in foo1 but with different label names. +bool foo4(int x) { + foo: + if (x != 3) { + ++x; + void *ptr = &&foo; + goto foo; + } + end: + return false; +} diff --git a/clang/test/Analysis/copypaste/lambda.cpp b/clang/test/Analysis/copypaste/lambda.cpp new file mode 100644 index 00000000000..c13c56f6671 --- /dev/null +++ b/clang/test/Analysis/copypaste/lambda.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -analyze -std=c++11 -analyzer-checker=alpha.clone.CloneChecker -verify %s + +// expected-no-diagnostics + +void foo1(int a, long b) { + auto l = [a, b](){}; +} + +void foo2(int a, long b) { + auto l = [&a, b](){}; +} + +void foo3(int a, long b) { + auto l = [a](){}; +} + +void foo4(int a, long b) { + auto l = [=](){}; +} + +void foo5(int a, long b) { + auto l = [&](){}; +} + |