diff options
author | Richard Trieu <rtrieu@google.com> | 2019-09-21 03:02:26 +0000 |
---|---|---|
committer | Richard Trieu <rtrieu@google.com> | 2019-09-21 03:02:26 +0000 |
commit | dbb59f794229857ec4acc86f12f3f9172ec253f6 (patch) | |
tree | 25a8129b9adbbe158f87e6d84c477f5c5fae9f51 /test | |
parent | ca66650e21db892f1acb156d9f1d082591c0eaac (diff) | |
download | clang-dbb59f794229857ec4acc86f12f3f9172ec253f6.tar.gz |
Merge and improve code that detects same value in comparisons.
-Wtautological-overlap-compare and self-comparison from -Wtautological-compare
relay on detecting the same operand in different locations. Previously, each
warning had it's own operand checker. Now, both are merged together into
one function that each can call. The function also now looks through member
access and array accesses.
Differential Revision: https://reviews.llvm.org/D66045
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@372453 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test')
-rw-r--r-- | test/Analysis/array-struct-region.cpp | 6 | ||||
-rw-r--r-- | test/Sema/warn-overlap.c | 14 | ||||
-rw-r--r-- | test/SemaCXX/compare-cxx2a.cpp | 6 | ||||
-rw-r--r-- | test/SemaCXX/self-comparison.cpp | 81 |
4 files changed, 107 insertions, 0 deletions
diff --git a/test/Analysis/array-struct-region.cpp b/test/Analysis/array-struct-region.cpp index cfb57d3924..1b9fa3e8db 100644 --- a/test/Analysis/array-struct-region.cpp +++ b/test/Analysis/array-struct-region.cpp @@ -1,20 +1,26 @@ // RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core\ // RUN: -analyzer-checker=debug.ExprInspection -verify\ +// RUN: -Wno-tautological-compare\ // RUN: -x c %s // RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core\ // RUN: -analyzer-checker=debug.ExprInspection -verify\ +// RUN: -Wno-tautological-compare\ // RUN: -x c++ -std=c++14 %s // RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core\ // RUN: -analyzer-checker=debug.ExprInspection -verify\ +// RUN: -Wno-tautological-compare\ // RUN: -x c++ -std=c++17 %s // RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core\ // RUN: -analyzer-checker=debug.ExprInspection -verify\ +// RUN: -Wno-tautological-compare\ // RUN: -DINLINE -x c %s // RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core\ // RUN: -analyzer-checker=debug.ExprInspection -verify\ +// RUN: -Wno-tautological-compare\ // RUN: -DINLINE -x c++ -std=c++14 %s // RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core\ // RUN: -analyzer-checker=debug.ExprInspection -verify\ +// RUN: -Wno-tautological-compare\ // RUN: -DINLINE -x c++ -std=c++17 %s void clang_analyzer_eval(int); diff --git a/test/Sema/warn-overlap.c b/test/Sema/warn-overlap.c index d72e60755d..066312591c 100644 --- a/test/Sema/warn-overlap.c +++ b/test/Sema/warn-overlap.c @@ -158,3 +158,17 @@ int no_warning(unsigned x) { return x >= 0 || x == 1; // no warning since "x >= 0" is caught by a different tautological warning. } + +struct A { + int x; + int y; +}; + +int struct_test(struct A a) { + return a.x > 5 && a.y < 1; // no warning, different variables + + return a.x > 5 && a.x < 1; + // expected-warning@-1{{overlapping comparisons always evaluate to false}} + return a.y == 1 || a.y != 1; + // expected-warning@-1{{overlapping comparisons always evaluate to true}} +} diff --git a/test/SemaCXX/compare-cxx2a.cpp b/test/SemaCXX/compare-cxx2a.cpp index c68a0ae913..b6e7fc8061 100644 --- a/test/SemaCXX/compare-cxx2a.cpp +++ b/test/SemaCXX/compare-cxx2a.cpp @@ -8,12 +8,18 @@ #define ASSERT_TYPE(...) static_assert(__is_same(__VA_ARGS__)) #define ASSERT_EXPR_TYPE(Expr, Expect) static_assert(__is_same(decltype(Expr), Expect)); +struct S { + static int x[5]; +}; + void self_compare() { int a; int *b = nullptr; + S s; (void)(a <=> a); // expected-warning {{self-comparison always evaluates to 'std::strong_ordering::equal'}} (void)(b <=> b); // expected-warning {{self-comparison always evaluates to 'std::strong_ordering::equal'}} + (void)(s.x[a] <=> S::x[a]); // expected-warning {{self-comparison always evaluates to 'std::strong_ordering::equal'}} } void test0(long a, unsigned long b) { diff --git a/test/SemaCXX/self-comparison.cpp b/test/SemaCXX/self-comparison.cpp index ac129b68a6..4ea16665f1 100644 --- a/test/SemaCXX/self-comparison.cpp +++ b/test/SemaCXX/self-comparison.cpp @@ -40,3 +40,84 @@ bool g() { Y<T>::n == Y<U>::n; } template bool g<int, int>(); // should not produce any warnings + +namespace member_tests { +struct B { + int field; + static int static_field; + int test(B b) { + return field == field; // expected-warning {{self-comparison always evaluates to true}} + return static_field == static_field; // expected-warning {{self-comparison always evaluates to true}} + return static_field == b.static_field; // expected-warning {{self-comparison always evaluates to true}} + return B::static_field == this->static_field; // expected-warning {{self-comparison always evaluates to true}} + return this == this; // expected-warning {{self-comparison always evaluates to true}} + + return field == b.field; + return this->field == b.field; + } +}; + +enum { + I0, + I1, + I2, +}; + +struct S { + int field; + static int static_field; + int array[4]; +}; + +struct T { + int field; + static int static_field; + int array[4]; + S s; +}; + +int struct_test(S s1, S s2, S *s3, T t) { + return s1.field == s1.field; // expected-warning {{self-comparison always evaluates to true}} + return s2.field == s2.field; // expected-warning {{self-comparison always evaluates to true}} + return s1.static_field == s2.static_field; // expected-warning {{self-comparison always evaluates to true}} + return S::static_field == s1.static_field; // expected-warning {{self-comparison always evaluates to true}} + return s1.array == s1.array; // expected-warning {{self-comparison always evaluates to true}} + return t.s.static_field == S::static_field; // expected-warning {{self-comparison always evaluates to true}} + return s3->field == s3->field; // expected-warning {{self-comparison always evaluates to true}} + return s3->static_field == S::static_field; // expected-warning {{self-comparison always evaluates to true}} + return s1.array[0] == s1.array[0]; // expected-warning {{self-comparison always evaluates to true}} + return s1.array[I1] == s1.array[I1]; // expected-warning {{self-comparison always evaluates to true}} + return s1.array[s2.array[0]] == s1.array[s2.array[0]]; // expected-warning {{self-comparison always evaluates to true}} + return s3->array[t.field] == s3->array[t.field]; // expected-warning {{self-comparison always evaluates to true}} + + // Try all operators + return t.field == t.field; // expected-warning {{self-comparison always evaluates to true}} + return t.field <= t.field; // expected-warning {{self-comparison always evaluates to true}} + return t.field >= t.field; // expected-warning {{self-comparison always evaluates to true}} + + return t.field != t.field; // expected-warning {{self-comparison always evaluates to false}} + return t.field < t.field; // expected-warning {{self-comparison always evaluates to false}} + return t.field > t.field; // expected-warning {{self-comparison always evaluates to false}} + + // no warning + return s1.field == s2.field; + return s2.array == s1.array; + return s2.array[0] == s1.array[0]; + return s1.array[I1] == s1.array[I2]; + + return s1.static_field == t.static_field; +}; + +struct U { + bool operator!=(const U&); +}; + +bool operator==(const U&, const U&); + +// May want to warn on this in the future. +int user_defined(U u) { + return u == u; + return u != u; +} + +} // namespace member_tests |