xref: /llvm-project/clang-tools-extra/test/clang-tidy/checkers/misc/redundant-expression.cpp (revision 3f458cd9abbf99cddcded076b5e7b4049607b7b4)
1*3f458cd9SAmr Hesham // RUN: %check_clang_tidy %s misc-redundant-expression %t -- -- -fno-delayed-template-parsing -Wno-array-compare-cxx26
289a1d03eSRichard 
389a1d03eSRichard typedef __INT64_TYPE__ I64;
489a1d03eSRichard 
589a1d03eSRichard struct Point {
689a1d03eSRichard   int x;
789a1d03eSRichard   int y;
889a1d03eSRichard   int a[5];
989a1d03eSRichard } P;
1089a1d03eSRichard 
1189a1d03eSRichard extern Point P1;
1289a1d03eSRichard extern Point P2;
1389a1d03eSRichard 
1489a1d03eSRichard extern int foo(int x);
1589a1d03eSRichard extern int bar(int x);
1689a1d03eSRichard extern int bat(int x, int y);
1789a1d03eSRichard 
1889a1d03eSRichard int TestSimpleEquivalent(int X, int Y) {
1989a1d03eSRichard   if (X - X) return 1;
2089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent [misc-redundant-expression]
2189a1d03eSRichard   if (X / X) return 1;
2289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent
2389a1d03eSRichard   if (X % X) return 1;
2489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent
2589a1d03eSRichard 
2689a1d03eSRichard   if (X & X) return 1;
2789a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent
2889a1d03eSRichard   if (X | X) return 1;
2989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent
3089a1d03eSRichard   if (X ^ X) return 1;
3189a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent
3289a1d03eSRichard 
3389a1d03eSRichard   if (X < X) return 1;
3489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent
3589a1d03eSRichard   if (X <= X) return 1;
3689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent
3789a1d03eSRichard   if (X > X) return 1;
3889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent
3989a1d03eSRichard   if (X >= X) return 1;
4089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent
4189a1d03eSRichard 
4289a1d03eSRichard   if (X && X) return 1;
4389a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent
4489a1d03eSRichard   if (X || X) return 1;
4589a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent
4689a1d03eSRichard 
4789a1d03eSRichard   if (X != (((X)))) return 1;
4889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent
4989a1d03eSRichard 
5089a1d03eSRichard   if (X + 1 == X + 1) return 1;
5189a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent
5289a1d03eSRichard   if (X + 1 != X + 1) return 1;
5389a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent
5489a1d03eSRichard   if (X + 1 <= X + 1) return 1;
5589a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent
5689a1d03eSRichard   if (X + 1 >= X + 1) return 1;
5789a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent
5889a1d03eSRichard 
5989a1d03eSRichard   if ((X != 1 || Y != 1) && (X != 1 || Y != 1)) return 1;
6089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: both sides of operator are equivalent
6189a1d03eSRichard   if (P.a[X - P.x] != P.a[X - P.x]) return 1;
6289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: both sides of operator are equivalent
6389a1d03eSRichard 
6489a1d03eSRichard   if ((int)X < (int)X) return 1;
6589a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: both sides of operator are equivalent
6689a1d03eSRichard   if (int(X) < int(X)) return 1;
6789a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: both sides of operator are equivalent
6889a1d03eSRichard 
6989a1d03eSRichard   if ( + "dummy" == + "dummy") return 1;
7089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: both sides of operator are equivalent
7189a1d03eSRichard   if (L"abc" == L"abc") return 1;
7289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: both sides of operator are equivalent
7389a1d03eSRichard 
7489a1d03eSRichard   if (foo(0) - 2 < foo(0) - 2) return 1;
7589a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: both sides of operator are equivalent
7689a1d03eSRichard   if (foo(bar(0)) < (foo(bar((0))))) return 1;
7789a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: both sides of operator are equivalent
7889a1d03eSRichard 
7989a1d03eSRichard   if (P1.x < P2.x && P1.x < P2.x) return 1;
8089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: both sides of operator are equivalent
8189a1d03eSRichard   if (P2.a[P1.x + 2] < P2.x && P2.a[(P1.x) + (2)] < (P2.x)) return 1;
8289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: both sides of operator are equivalent
8389a1d03eSRichard 
8489a1d03eSRichard   if (X && Y && X) return 1;
8589a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: operator has equivalent nested operands
8689a1d03eSRichard   if (X || (Y || X)) return 1;
8789a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: operator has equivalent nested operands
8889a1d03eSRichard   if ((X ^ Y) ^ (Y ^ X)) return 1;
8989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: operator has equivalent nested operands
9089a1d03eSRichard 
9189a1d03eSRichard   return 0;
9289a1d03eSRichard }
9389a1d03eSRichard 
9489a1d03eSRichard template <int DX>
9589a1d03eSRichard int TestSimpleEquivalentDependent() {
9689a1d03eSRichard   if (DX > 0 && DX > 0) return 1;
9789a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: both sides of operator are equivalent
9889a1d03eSRichard 
9989a1d03eSRichard   return 0;
10089a1d03eSRichard }
10189a1d03eSRichard 
10289a1d03eSRichard int Valid(int X, int Y) {
10389a1d03eSRichard   if (X != Y) return 1;
10489a1d03eSRichard   if (X == Y + 0) return 1;
10589a1d03eSRichard   if (P.x == P.y) return 1;
10689a1d03eSRichard   if (P.a[P.x] < P.a[P.y]) return 1;
10789a1d03eSRichard   if (P.a[0] < P.a[1]) return 1;
10889a1d03eSRichard 
10989a1d03eSRichard   if (P.a[0] < P.a[0ULL]) return 1;
11089a1d03eSRichard   if (0 < 0ULL) return 1;
11189a1d03eSRichard   if ((int)0 < (int)0ULL) return 1;
11289a1d03eSRichard 
11389a1d03eSRichard   if (++X != ++X) return 1;
11489a1d03eSRichard   if (P.a[X]++ != P.a[X]++) return 1;
11589a1d03eSRichard   if (P.a[X++] != P.a[X++]) return 1;
11689a1d03eSRichard   if (X && X++ && X) return 1;
11789a1d03eSRichard 
11889a1d03eSRichard   if ("abc" == "ABC") return 1;
11989a1d03eSRichard   if (foo(bar(0)) < (foo(bat(0, 1)))) return 1;
12089a1d03eSRichard   return 0;
12189a1d03eSRichard }
12289a1d03eSRichard 
12389a1d03eSRichard #define COND_OP_MACRO 9
12489a1d03eSRichard #define COND_OP_OTHER_MACRO 9
12589a1d03eSRichard #define COND_OP_THIRD_MACRO COND_OP_MACRO
12689a1d03eSRichard int TestConditional(int x, int y) {
12789a1d03eSRichard   int k = 0;
12889a1d03eSRichard   k += (y < 0) ? x : x;
12989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: 'true' and 'false' expressions are equivalent
13089a1d03eSRichard   k += (y < 0) ? x + 1 : x + 1;
13189a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: 'true' and 'false' expressions are equivalent
13289a1d03eSRichard   k += (y < 0) ? COND_OP_MACRO : COND_OP_MACRO;
13389a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: 'true' and 'false' expressions are equivalent
13489a1d03eSRichard   k += (y < 0) ? COND_OP_MACRO + COND_OP_OTHER_MACRO : COND_OP_MACRO + COND_OP_OTHER_MACRO;
13589a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:54: warning: 'true' and 'false' expressions are equivalent
13689a1d03eSRichard 
13789a1d03eSRichard   // Do not match for conditional operators with a macro and a const.
13889a1d03eSRichard   k += (y < 0) ? COND_OP_MACRO : 9;
13989a1d03eSRichard   // Do not match for conditional operators with expressions from different macros.
14089a1d03eSRichard   k += (y < 0) ? COND_OP_MACRO : COND_OP_OTHER_MACRO;
14189a1d03eSRichard   // Do not match for conditional operators when a macro is defined to another macro
14289a1d03eSRichard   k += (y < 0) ? COND_OP_MACRO : COND_OP_THIRD_MACRO;
14389a1d03eSRichard #undef COND_OP_THIRD_MACRO
14489a1d03eSRichard #define   COND_OP_THIRD_MACRO 8
14589a1d03eSRichard   k += (y < 0) ? COND_OP_MACRO : COND_OP_THIRD_MACRO;
14689a1d03eSRichard #undef COND_OP_THIRD_MACRO
14789a1d03eSRichard 
14889a1d03eSRichard   k += (y < 0) ? sizeof(I64) : sizeof(I64);
14989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: 'true' and 'false' expressions are equivalent
15089a1d03eSRichard   k += (y < 0) ? sizeof(TestConditional(k,y)) : sizeof(TestConditional(k,y));
15189a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:47: warning: 'true' and 'false' expressions are equivalent
15289a1d03eSRichard   // No warning if the expression arguments are different.
15389a1d03eSRichard   k += (y < 0) ? sizeof(TestConditional(k,y)) : sizeof(Valid(k,y));
15489a1d03eSRichard 
15589a1d03eSRichard   return k;
15689a1d03eSRichard }
15789a1d03eSRichard #undef COND_OP_MACRO
15889a1d03eSRichard #undef COND_OP_OTHER_MACRO
15989a1d03eSRichard 
16089a1d03eSRichard // Overloaded operators that compare two instances of a struct.
16189a1d03eSRichard struct MyStruct {
16289a1d03eSRichard   int x;
16389a1d03eSRichard   bool operator==(const MyStruct& rhs) const {return this->x == rhs.x; } // not modifing
16489a1d03eSRichard   bool operator>=(const MyStruct& rhs) const { return this->x >= rhs.x; } // not modifing
16589a1d03eSRichard   bool operator<=(MyStruct& rhs) const { return this->x <= rhs.x; }
16689a1d03eSRichard   bool operator&&(const MyStruct& rhs){ this->x++; return this->x && rhs.x; }
16789a1d03eSRichard } Q;
16889a1d03eSRichard 
16989a1d03eSRichard bool operator!=(const MyStruct& lhs, const MyStruct& rhs) { return lhs.x == rhs.x; } // not modifing
17089a1d03eSRichard bool operator<(const MyStruct& lhs, const MyStruct& rhs) { return lhs.x < rhs.x; } // not modifing
17189a1d03eSRichard bool operator>(const MyStruct& lhs, MyStruct& rhs) { rhs.x--; return lhs.x > rhs.x; }
17289a1d03eSRichard bool operator||(MyStruct& lhs, const MyStruct& rhs) { lhs.x++; return lhs.x || rhs.x; }
17389a1d03eSRichard 
17489a1d03eSRichard struct MyStruct1 {
17589a1d03eSRichard   bool x;
17689a1d03eSRichard   MyStruct1(bool x) : x(x) {};
17789a1d03eSRichard   operator bool() { return x; }
17889a1d03eSRichard };
17989a1d03eSRichard 
18089a1d03eSRichard MyStruct1 operator&&(const MyStruct1& lhs, const MyStruct1& rhs) { return lhs.x && rhs.x; }
18189a1d03eSRichard MyStruct1 operator||(MyStruct1& lhs, MyStruct1& rhs) { return lhs.x && rhs.x; }
18289a1d03eSRichard 
18389a1d03eSRichard bool TestOverloadedOperator(MyStruct& S) {
18489a1d03eSRichard   if (S == Q) return false;
18589a1d03eSRichard 
18689a1d03eSRichard   if (S <= S) return false;
18789a1d03eSRichard   if (S && S) return false;
18889a1d03eSRichard   if (S > S) return false;
18989a1d03eSRichard   if (S || S) return false;
19089a1d03eSRichard 
19189a1d03eSRichard   if (S == S) return true;
19289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of overloaded operator are equivalent
19389a1d03eSRichard   if (S < S) return true;
19489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of overloaded operator are equivalent
19589a1d03eSRichard   if (S != S) return true;
19689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of overloaded operator are equivalent
19789a1d03eSRichard   if (S >= S) return true;
19889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of overloaded operator are equivalent
19989a1d03eSRichard 
20089a1d03eSRichard   MyStruct1 U(false);
20189a1d03eSRichard   MyStruct1 V(true);
20289a1d03eSRichard 
20389a1d03eSRichard   // valid because the operator is not const
20489a1d03eSRichard   if ((U || V) || U) return true;
20589a1d03eSRichard 
20689a1d03eSRichard   if (U && V && U && V) return true;
20789a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: overloaded operator has equivalent nested operands
20889a1d03eSRichard 
20989a1d03eSRichard   return true;
21089a1d03eSRichard }
21189a1d03eSRichard 
21289a1d03eSRichard #define LT(x, y) (void)((x) < (y))
21389a1d03eSRichard #define COND(x, y, z) ((x)?(y):(z))
21489a1d03eSRichard #define EQUALS(x, y) (x) == (y)
21589a1d03eSRichard 
21689a1d03eSRichard int TestMacro(int X, int Y) {
21789a1d03eSRichard   LT(0, 0);
21889a1d03eSRichard   LT(1, 0);
21989a1d03eSRichard   LT(X, X);
22089a1d03eSRichard   LT(X+1, X + 1);
22189a1d03eSRichard   COND(X < Y, X, X);
22289a1d03eSRichard   EQUALS(Q, Q);
22389a1d03eSRichard   return 0;
22489a1d03eSRichard }
22589a1d03eSRichard 
22689a1d03eSRichard int TestFalsePositive(int* A, int X, float F) {
22789a1d03eSRichard   // Produced by bison.
22889a1d03eSRichard   X = A[(2) - (2)];
22989a1d03eSRichard   X = A['a' - 'a'];
23089a1d03eSRichard 
23189a1d03eSRichard   // Testing NaN.
23289a1d03eSRichard   if (F != F && F == F) return 1;
23389a1d03eSRichard   return 0;
23489a1d03eSRichard }
23589a1d03eSRichard 
23689a1d03eSRichard int TestBannedMacros() {
23789a1d03eSRichard #define EAGAIN 3
23889a1d03eSRichard #define NOT_EAGAIN 3
23989a1d03eSRichard   if (EAGAIN == 0 | EAGAIN == 0) return 0;
24089a1d03eSRichard   if (NOT_EAGAIN == 0 | NOT_EAGAIN == 0) return 0;
24189a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: both sides of operator are equivalent
24289a1d03eSRichard   return 0;
24389a1d03eSRichard }
24489a1d03eSRichard 
24589a1d03eSRichard struct MyClass {
24689a1d03eSRichard static const int Value = 42;
24789a1d03eSRichard };
24889a1d03eSRichard template <typename T, typename U>
24989a1d03eSRichard void TemplateCheck() {
25089a1d03eSRichard   static_assert(T::Value == U::Value, "should be identical");
25189a1d03eSRichard   static_assert(T::Value == T::Value, "should be identical");
25289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: both sides of operator are equivalent
25389a1d03eSRichard }
25489a1d03eSRichard void TestTemplate() { TemplateCheck<MyClass, MyClass>(); }
25589a1d03eSRichard 
25689a1d03eSRichard int TestArithmetic(int X, int Y) {
25789a1d03eSRichard   if (X + 1 == X) return 1;
25889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always false
25989a1d03eSRichard   if (X + 1 != X) return 1;
26089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true
26189a1d03eSRichard   if (X - 1 == X) return 1;
26289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always false
26389a1d03eSRichard   if (X - 1 != X) return 1;
26489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true
26589a1d03eSRichard 
26689a1d03eSRichard   if (X + 1LL == X) return 1;
26789a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always false
26889a1d03eSRichard   if (X + 1ULL == X) return 1;
26989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: logical expression is always false
27089a1d03eSRichard 
27189a1d03eSRichard   if (X == X + 1) return 1;
27289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: logical expression is always false
27389a1d03eSRichard   if (X != X + 1) return 1;
27489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: logical expression is always true
27589a1d03eSRichard   if (X == X - 1) return 1;
27689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: logical expression is always false
27789a1d03eSRichard   if (X != X - 1) return 1;
27889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: logical expression is always true
27989a1d03eSRichard 
28089a1d03eSRichard   if (X != X - 1U) return 1;
28189a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: logical expression is always true
28289a1d03eSRichard   if (X != X - 1LL) return 1;
28389a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: logical expression is always true
28489a1d03eSRichard 
28589a1d03eSRichard   if ((X+X) != (X+X) - 1) return 1;
28689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true
28789a1d03eSRichard 
28889a1d03eSRichard   if (X + 1 == X + 2) return 1;
28989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always false
29089a1d03eSRichard   if (X + 1 != X + 2) return 1;
29189a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true
29289a1d03eSRichard 
29389a1d03eSRichard   if (X - 1 == X - 2) return 1;
29489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always false
29589a1d03eSRichard   if (X - 1 != X - 2) return 1;
29689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true
29789a1d03eSRichard 
29889a1d03eSRichard   if (X + 1 == X - -1) return 1;
29989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true
30089a1d03eSRichard   if (X + 1 != X - -1) return 1;
30189a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always false
30289a1d03eSRichard   if (X + 1 == X - -2) return 1;
30389a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always false
30489a1d03eSRichard   if (X + 1 != X - -2) return 1;
30589a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true
30689a1d03eSRichard 
30789a1d03eSRichard   if (X + 1 == X - (~0)) return 1;
30889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true
30989a1d03eSRichard   if (X + 1 == X - (~0U)) return 1;
31089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true
31189a1d03eSRichard 
31289a1d03eSRichard   if (X + 1 == X - (~0ULL)) return 1;
31389a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true
31489a1d03eSRichard 
31589a1d03eSRichard   // Should not match.
31689a1d03eSRichard   if (X + 0.5 == X) return 1;
31789a1d03eSRichard   if (X + 1 == Y) return 1;
31889a1d03eSRichard   if (X + 1 == Y + 1) return 1;
31989a1d03eSRichard   if (X + 1 == Y + 2) return 1;
32089a1d03eSRichard 
32189a1d03eSRichard   return 0;
32289a1d03eSRichard }
32389a1d03eSRichard 
32489a1d03eSRichard int TestBitwise(int X, int Y) {
32589a1d03eSRichard 
32689a1d03eSRichard   if ((X & 0xFF) == 0xF00) return 1;
32789a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always false
32889a1d03eSRichard   if ((X & 0xFF) != 0xF00) return 1;
32989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always true
33089a1d03eSRichard   if ((X | 0xFF) == 0xF00) return 1;
33189a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always false
33289a1d03eSRichard   if ((X | 0xFF) != 0xF00) return 1;
33389a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always true
33489a1d03eSRichard 
33589a1d03eSRichard   if ((X | 0xFFULL) != 0xF00) return 1;
33689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: logical expression is always true
33789a1d03eSRichard   if ((X | 0xFF) != 0xF00ULL) return 1;
33889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always true
33989a1d03eSRichard 
34089a1d03eSRichard   if ((0xFF & X) == 0xF00) return 1;
34189a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always false
34289a1d03eSRichard   if ((0xFF & X) != 0xF00) return 1;
34389a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always true
34489a1d03eSRichard   if ((0xFF & X) == 0xF00) return 1;
34589a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always false
34689a1d03eSRichard   if ((0xFF & X) != 0xF00) return 1;
34789a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always true
34889a1d03eSRichard 
34989a1d03eSRichard   if ((0xFFLL & X) == 0xF00) return 1;
35089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: logical expression is always false
35189a1d03eSRichard   if ((0xFF & X) == 0xF00ULL) return 1;
35289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always false
35389a1d03eSRichard 
35489a1d03eSRichard   return 0;
35589a1d03eSRichard }
35689a1d03eSRichard 
35789a1d03eSRichard // Overloaded operators that compare an instance of a struct and an integer
35889a1d03eSRichard // constant.
35989a1d03eSRichard struct S {
36089a1d03eSRichard   S() { x = 1; }
36189a1d03eSRichard   int x;
36289a1d03eSRichard   // Overloaded comparison operators without any possible side effect.
36389a1d03eSRichard   bool operator==(const int &i) const { return x == i; } // not modifying
36489a1d03eSRichard   bool operator!=(int i) const { return x != i; } // not modifying
36589a1d03eSRichard   bool operator>(const int &i) const { return x > i; } // not modifying
36689a1d03eSRichard   bool operator<(int i) const { return x < i; } // not modifying
36789a1d03eSRichard };
36889a1d03eSRichard 
36989a1d03eSRichard bool operator<=(const S &s, int i) { return s.x <= i; } // not modifying
37089a1d03eSRichard bool operator>=(const S &s, const int &i) { return s.x >= i; } // not modifying
37189a1d03eSRichard 
37289a1d03eSRichard bool operator==(int i, const S &s) { return s == i; } // not modifying
37389a1d03eSRichard bool operator<(const int &i, const S &s) { return s > i; } // not modifying
37489a1d03eSRichard bool operator<=(const int &i, const S &s) { return s >= i; } // not modifying
37589a1d03eSRichard bool operator>(const int &i, const S &s) { return s < i; } // not modifying
37689a1d03eSRichard 
37789a1d03eSRichard struct S2 {
37889a1d03eSRichard   S2() { x = 1; }
37989a1d03eSRichard   int x;
38089a1d03eSRichard   // Overloaded comparison operators that are able to modify their params.
38189a1d03eSRichard   bool operator==(const int &i) {
38289a1d03eSRichard     this->x++;
38389a1d03eSRichard     return x == i;
38489a1d03eSRichard   }
38589a1d03eSRichard   bool operator!=(int i) { return x != i; }
38689a1d03eSRichard   bool operator>(const int &i) { return x > i; }
38789a1d03eSRichard   bool operator<(int i) {
38889a1d03eSRichard     this->x--;
38989a1d03eSRichard     return x < i;
39089a1d03eSRichard   }
39189a1d03eSRichard };
39289a1d03eSRichard 
39389a1d03eSRichard bool operator>=(S2 &s, const int &i) { return s.x >= i; }
39489a1d03eSRichard bool operator<=(S2 &s, int i) {
39589a1d03eSRichard   s.x++;
39689a1d03eSRichard   return s.x <= i;
39789a1d03eSRichard }
39889a1d03eSRichard 
39989a1d03eSRichard int TestLogical(int X, int Y){
40089a1d03eSRichard #define CONFIG 0
40189a1d03eSRichard   if (CONFIG && X) return 1;
40289a1d03eSRichard #undef CONFIG
40389a1d03eSRichard #define CONFIG 1
40489a1d03eSRichard   if (CONFIG || X) return 1;
40589a1d03eSRichard #undef CONFIG
40689a1d03eSRichard 
40789a1d03eSRichard   if (X == 10 && X != 10) return 1;
40889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always false
40989a1d03eSRichard   if (X == 10 && (X != 10)) return 1;
41089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always false
41189a1d03eSRichard   if (X == 10 && !(X == 10)) return 1;
41289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always false
41389a1d03eSRichard   if (!(X != 10) && !(X == 10)) return 1;
41489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always false
41589a1d03eSRichard 
41689a1d03eSRichard   if (X == 10ULL && X != 10ULL) return 1;
41789a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always false
41889a1d03eSRichard   if (!(X != 10U) && !(X == 10)) return 1;
41989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: logical expression is always false
42089a1d03eSRichard   if (!(X != 10LL) && !(X == 10)) return 1;
42189a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: logical expression is always false
42289a1d03eSRichard   if (!(X != 10ULL) && !(X == 10)) return 1;
42389a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: logical expression is always false
42489a1d03eSRichard 
42589a1d03eSRichard   if (X == 0 && X) return 1;
42689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always false
42789a1d03eSRichard   if (X != 0 && !X) return 1;
42889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always false
42989a1d03eSRichard   if (X && !X) return 1;
43089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: logical expression is always false
43189a1d03eSRichard 
43289a1d03eSRichard   if (X && !!X) return 1;
43389a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: equivalent expression on both sides of logical operator
43489a1d03eSRichard   if (X != 0 && X) return 1;
43589a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: equivalent expression on both sides of logical operator
43689a1d03eSRichard   if (X != 0 && !!X) return 1;
43789a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: equivalent expression on both sides of logical operator
43889a1d03eSRichard   if (X == 0 && !X) return 1;
43989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: equivalent expression on both sides of logical operator
44089a1d03eSRichard 
44189a1d03eSRichard   // Should not match.
44289a1d03eSRichard   if (X == 10 && Y == 10) return 1;
44389a1d03eSRichard   if (X != 10 && X != 12) return 1;
44489a1d03eSRichard   if (X == 10 || X == 12) return 1;
44589a1d03eSRichard   if (!X && !Y) return 1;
44689a1d03eSRichard   if (!X && Y) return 1;
44789a1d03eSRichard   if (!X && Y == 0) return 1;
44889a1d03eSRichard   if (X == 10 && Y != 10) return 1;
44989a1d03eSRichard 
45089a1d03eSRichard   // Test for overloaded operators with constant params.
45189a1d03eSRichard   S s1;
45289a1d03eSRichard   if (s1 == 1 && s1 == 1) return true;
45389a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: equivalent expression on both sides of logical operator
45489a1d03eSRichard   if (s1 == 1 || s1 != 1) return true;
45589a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always true
45689a1d03eSRichard   if (s1 > 1 && s1 < 1) return true;
45789a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always false
45889a1d03eSRichard   if (s1 >= 1 || s1 <= 1) return true;
45989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always true
46089a1d03eSRichard   if (s1 >= 2 && s1 <= 0) return true;
46189a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always false
46289a1d03eSRichard 
46389a1d03eSRichard   // Same test as above but with swapped LHS/RHS on one side of the logical operator.
46489a1d03eSRichard   if (1 == s1 && s1 == 1) return true;
46589a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: equivalent expression on both sides of logical operator
46689a1d03eSRichard   if (1 == s1 || s1 != 1) return true;
46789a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always true
46889a1d03eSRichard   if (1 < s1 && s1 < 1) return true;
46989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always false
47089a1d03eSRichard   if (1 <= s1 || s1 <= 1) return true;
47189a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always true
47289a1d03eSRichard   if (2 < s1 && 0 > s1) return true;
47389a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always false
47489a1d03eSRichard 
47589a1d03eSRichard   // Test for absence of false positives (issue #54011).
47689a1d03eSRichard   if (s1 == 1 || s1 == 2) return true;
47789a1d03eSRichard   if (s1 > 1 && s1 < 3) return true;
47889a1d03eSRichard   if (s1 >= 2 || s1 <= 0) return true;
47989a1d03eSRichard 
48089a1d03eSRichard   // Test for overloaded operators that may modify their params.
48189a1d03eSRichard   S2 s2;
48289a1d03eSRichard   if (s2 == 1 || s2 != 1) return true;
48389a1d03eSRichard   if (s2 == 1 || s2 == 1) return true;
48489a1d03eSRichard   if (s2 > 1 && s2 < 1) return true;
48589a1d03eSRichard   if (s2 >= 1 || s2 <= 1) return true;
48689a1d03eSRichard }
48789a1d03eSRichard 
48889a1d03eSRichard int TestRelational(int X, int Y) {
48989a1d03eSRichard   if (X == 10 && X > 10) return 1;
49089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always false
49189a1d03eSRichard   if (X == 10 && X < 10) return 1;
49289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always false
49389a1d03eSRichard   if (X < 10 && X > 10) return 1;
49489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always false
49589a1d03eSRichard   if (X <= 10 && X > 10) return 1;
49689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always false
49789a1d03eSRichard   if (X < 10 && X >= 10) return 1;
49889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always false
49989a1d03eSRichard   if (X < 10 && X == 10) return 1;
50089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always false
50189a1d03eSRichard 
50289a1d03eSRichard   if (X > 5 && X <= 5) return 1;
50389a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always false
50489a1d03eSRichard   if (X > -5 && X <= -5) return 1;
50589a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always false
50689a1d03eSRichard 
50789a1d03eSRichard   if (X < 10 || X >= 10) return 1;
50889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always true
50989a1d03eSRichard   if (X <= 10 || X > 10) return 1;
51089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always true
51189a1d03eSRichard   if (X <= 10 || X >= 11) return 1;
51289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always true
51389a1d03eSRichard   if (X != 7 || X != 14) return 1;
51489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always true
51589a1d03eSRichard   if (X == 7 || X != 5) return 1;
51689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
51789a1d03eSRichard   if (X != 7 || X == 7) return 1;
51889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always true
51989a1d03eSRichard 
52089a1d03eSRichard   if (X < 7 && X < 6) return 1;
52189a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
52289a1d03eSRichard   if (X < 7 && X < 7) return 1;
52389a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent
52489a1d03eSRichard   if (X < 7 && X < 8) return 1;
52589a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: expression is redundant
52689a1d03eSRichard 
52789a1d03eSRichard   if (X < 7 && X <= 5) return 1;
52889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
52989a1d03eSRichard   if (X < 7 && X <= 6) return 1;
53089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: equivalent expression on both sides of logical operator
53189a1d03eSRichard   if (X < 7 && X <= 7) return 1;
53289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: expression is redundant
53389a1d03eSRichard   if (X < 7 && X <= 8) return 1;
53489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: expression is redundant
53589a1d03eSRichard 
53689a1d03eSRichard   if (X <= 7 && X < 6) return 1;
53789a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
53889a1d03eSRichard   if (X <= 7 && X < 7) return 1;
53989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
54089a1d03eSRichard   if (X <= 7 && X < 8) return 1;
54189a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: equivalent expression on both sides of logical operator
54289a1d03eSRichard 
54389a1d03eSRichard   if (X >= 7 && X > 6) return 1;
54489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: equivalent expression on both sides of logical operator
54589a1d03eSRichard   if (X >= 7 && X > 7) return 1;
54689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
54789a1d03eSRichard   if (X >= 7 && X > 8) return 1;
54889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
54989a1d03eSRichard 
55089a1d03eSRichard   if (X <= 7 && X <= 5) return 1;
55189a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
55289a1d03eSRichard   if (X <= 7 && X <= 6) return 1;
55389a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
55489a1d03eSRichard   if (X <= 7 && X <= 7) return 1;
55589a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: both sides of operator are equivalent
55689a1d03eSRichard   if (X <= 7 && X <= 8) return 1;
55789a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: expression is redundant
55889a1d03eSRichard 
55989a1d03eSRichard   if (X == 11 && X > 10) return 1;
56089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: expression is redundant
56189a1d03eSRichard   if (X == 11 && X < 12) return 1;
56289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: expression is redundant
56389a1d03eSRichard   if (X > 10 && X == 11) return 1;
56489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
56589a1d03eSRichard   if (X < 12 && X == 11) return 1;
56689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
56789a1d03eSRichard 
56889a1d03eSRichard   if (X != 11 && X == 42) return 1;
56989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
57089a1d03eSRichard   if (X != 11 && X > 11) return 1;
57189a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
57289a1d03eSRichard   if (X != 11 && X < 11) return 1;
57389a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
57489a1d03eSRichard   if (X != 11 && X < 8) return 1;
57589a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
57689a1d03eSRichard   if (X != 11 && X > 14) return 1;
57789a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
57889a1d03eSRichard 
57989a1d03eSRichard   if (X < 7 || X < 6) return 1;
58089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: expression is redundant
58189a1d03eSRichard   if (X < 7 || X < 7) return 1;
58289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent
58389a1d03eSRichard   if (X < 7 || X < 8) return 1;
58489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
58589a1d03eSRichard 
58689a1d03eSRichard   if (X > 7 || X > 6) return 1;
58789a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
58889a1d03eSRichard   if (X > 7 || X > 7) return 1;
58989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent
59089a1d03eSRichard   if (X > 7 || X > 8) return 1;
59189a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: expression is redundant
59289a1d03eSRichard 
59389a1d03eSRichard   // Should not match.
59489a1d03eSRichard   if (X < 10 || X > 12) return 1;
59589a1d03eSRichard   if (X > 10 && X < 12) return 1;
59689a1d03eSRichard   if (X < 10 || X >= 12) return 1;
59789a1d03eSRichard   if (X > 10 && X <= 12) return 1;
59889a1d03eSRichard   if (X <= 10 || X > 12) return 1;
59989a1d03eSRichard   if (X >= 10 && X < 12) return 1;
60089a1d03eSRichard   if (X <= 10 || X >= 12) return 1;
60189a1d03eSRichard   if (X >= 10 && X <= 12) return 1;
60289a1d03eSRichard   if (X >= 10 && X <= 11) return 1;
60389a1d03eSRichard   if (X >= 10 && X < 11) return 1;
60489a1d03eSRichard   if (X > 10 && X <= 11) return 1;
60589a1d03eSRichard   if (X > 10 && X != 11) return 1;
60689a1d03eSRichard   if (X >= 10 && X <= 10) return 1;
60789a1d03eSRichard   if (X <= 10 && X >= 10) return 1;
60889a1d03eSRichard   if (X < 0 || X > 0) return 1;
60989a1d03eSRichard }
61089a1d03eSRichard 
61189a1d03eSRichard int TestRelationalMacros(int X){
61289a1d03eSRichard #define SOME_MACRO 3
61389a1d03eSRichard #define SOME_MACRO_SAME_VALUE 3
61489a1d03eSRichard #define SOME_OTHER_MACRO 9
61589a1d03eSRichard   // Do not match for redundant relational macro expressions that can be
61689a1d03eSRichard   // considered intentional, and for some particular values, non redundant.
61789a1d03eSRichard 
61889a1d03eSRichard   // Test cases for expressions with the same macro on both sides.
61989a1d03eSRichard   if (X < SOME_MACRO && X > SOME_MACRO) return 1;
62089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: logical expression is always false
62189a1d03eSRichard   if (X < SOME_MACRO && X == SOME_MACRO) return 1;
62289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: logical expression is always false
62389a1d03eSRichard   if (X < SOME_MACRO || X >= SOME_MACRO) return 1;
62489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: logical expression is always true
62589a1d03eSRichard   if (X <= SOME_MACRO || X > SOME_MACRO) return 1;
62689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: logical expression is always true
62789a1d03eSRichard   if (X != SOME_MACRO && X > SOME_MACRO) return 1;
62889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
62989a1d03eSRichard   if (X != SOME_MACRO && X < SOME_MACRO) return 1;
63089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant
63189a1d03eSRichard 
63289a1d03eSRichard   // Test cases for two different macros.
63389a1d03eSRichard   if (X < SOME_MACRO && X > SOME_OTHER_MACRO) return 1;
63489a1d03eSRichard   if (X != SOME_MACRO && X >= SOME_OTHER_MACRO) return 1;
63589a1d03eSRichard   if (X != SOME_MACRO && X != SOME_OTHER_MACRO) return 1;
63689a1d03eSRichard   if (X == SOME_MACRO || X == SOME_MACRO_SAME_VALUE) return 1;
63789a1d03eSRichard   if (X == SOME_MACRO || X <= SOME_MACRO_SAME_VALUE) return 1;
63889a1d03eSRichard   if (X == SOME_MACRO || X > SOME_MACRO_SAME_VALUE) return 1;
63989a1d03eSRichard   if (X < SOME_MACRO && X <= SOME_OTHER_MACRO) return 1;
64089a1d03eSRichard   if (X == SOME_MACRO && X > SOME_OTHER_MACRO) return 1;
64189a1d03eSRichard   if (X == SOME_MACRO && X != SOME_OTHER_MACRO) return 1;
64289a1d03eSRichard   if (X == SOME_MACRO && X != SOME_MACRO_SAME_VALUE) return 1;
64389a1d03eSRichard   if (X == SOME_MACRO_SAME_VALUE && X == SOME_MACRO ) return 1;
64489a1d03eSRichard 
64589a1d03eSRichard   // Test cases for a macro and a const.
64689a1d03eSRichard   if (X < SOME_MACRO && X > 9) return 1;
64789a1d03eSRichard   if (X != SOME_MACRO && X >= 9) return 1;
64889a1d03eSRichard   if (X != SOME_MACRO && X != 9) return 1;
64989a1d03eSRichard   if (X == SOME_MACRO || X == 3) return 1;
65089a1d03eSRichard   if (X == SOME_MACRO || X <= 3) return 1;
65189a1d03eSRichard   if (X < SOME_MACRO && X <= 9) return 1;
65289a1d03eSRichard   if (X == SOME_MACRO && X != 9) return 1;
65389a1d03eSRichard   if (X == SOME_MACRO && X == 9) return 1;
65489a1d03eSRichard 
65589a1d03eSRichard #undef SOME_OTHER_MACRO
65689a1d03eSRichard #undef SOME_MACRO_SAME_VALUE
65789a1d03eSRichard #undef SOME_MACRO
65889a1d03eSRichard   return 0;
65989a1d03eSRichard }
66089a1d03eSRichard 
66189a1d03eSRichard int TestValidExpression(int X) {
66289a1d03eSRichard   if (X - 1 == 1 - X) return 1;
66389a1d03eSRichard   if (2 * X == X) return 1;
66489a1d03eSRichard   if ((X << 1) == X) return 1;
66589a1d03eSRichard 
66689a1d03eSRichard   return 0;
66789a1d03eSRichard }
66889a1d03eSRichard 
66989a1d03eSRichard enum Color { Red, Yellow, Green };
67089a1d03eSRichard int TestRelationalWithEnum(enum Color C) {
67189a1d03eSRichard   if (C == Red && C == Yellow) return 1;
67289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: logical expression is always false
67389a1d03eSRichard   if (C == Red && C != Red) return 1;
67489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: logical expression is always false
67589a1d03eSRichard   if (C != Red || C != Yellow) return 1;
67689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: logical expression is always true
67789a1d03eSRichard 
67889a1d03eSRichard   // Should not match.
67989a1d03eSRichard   if (C == Red || C == Yellow) return 1;
68089a1d03eSRichard   if (C != Red && C != Yellow) return 1;
68189a1d03eSRichard 
68289a1d03eSRichard   return 0;
68389a1d03eSRichard }
68489a1d03eSRichard 
68589a1d03eSRichard template<class T>
68689a1d03eSRichard int TestRelationalTemplated(int X) {
68789a1d03eSRichard   // This test causes a corner case with |isIntegerConstantExpr| where the type
68889a1d03eSRichard   // is dependent. There is an assert failing when evaluating
68989a1d03eSRichard   // sizeof(<incomplet-type>).
69089a1d03eSRichard   if (sizeof(T) == 4 || sizeof(T) == 8) return 1;
69189a1d03eSRichard 
69289a1d03eSRichard   if (X + 0 == -X) return 1;
69389a1d03eSRichard   if (X + 0 < X) return 1;
69489a1d03eSRichard 
69589a1d03eSRichard   return 0;
69689a1d03eSRichard }
69789a1d03eSRichard 
69889a1d03eSRichard int TestWithSignedUnsigned(int X) {
69989a1d03eSRichard   if (X + 1 == X + 1ULL) return 1;
70089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true
70189a1d03eSRichard 
70289a1d03eSRichard   if ((X & 0xFFU) == 0xF00) return 1;
70389a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: logical expression is always false
70489a1d03eSRichard 
70589a1d03eSRichard   if ((X & 0xFF) == 0xF00U) return 1;
70689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always false
70789a1d03eSRichard 
70889a1d03eSRichard   if ((X & 0xFFU) == 0xF00U) return 1;
70989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: logical expression is always false
71089a1d03eSRichard 
71189a1d03eSRichard   return 0;
71289a1d03eSRichard }
71389a1d03eSRichard 
71489a1d03eSRichard int TestWithLong(int X, I64 Y) {
71589a1d03eSRichard   if (X + 0ULL == -X) return 1;
71689a1d03eSRichard   if (Y + 0 == -Y) return 1;
71789a1d03eSRichard   if (Y <= 10 && X >= 10LL) return 1;
71889a1d03eSRichard   if (Y <= 10 && X >= 10ULL) return 1;
71989a1d03eSRichard   if (X <= 10 || X > 12LL) return 1;
72089a1d03eSRichard   if (X <= 10 || X > 12ULL) return 1;
72189a1d03eSRichard   if (Y <= 10 || Y > 12) return 1;
72289a1d03eSRichard 
72389a1d03eSRichard   return 0;
72489a1d03eSRichard }
72589a1d03eSRichard 
72689a1d03eSRichard int TestWithMinMaxInt(int X) {
72789a1d03eSRichard   if (X <= X + 0xFFFFFFFFU) return 1;
72889a1d03eSRichard   if (X <= X + 0x7FFFFFFF) return 1;
72989a1d03eSRichard   if (X <= X + 0x80000000) return 1;
73089a1d03eSRichard 
73189a1d03eSRichard   if (X <= 0xFFFFFFFFU && X > 0) return 1;
73289a1d03eSRichard   if (X <= 0xFFFFFFFFU && X > 0U) return 1;
73389a1d03eSRichard 
73489a1d03eSRichard   if (X + 0x80000000 == X - 0x80000000) return 1;
73589a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: logical expression is always true
73689a1d03eSRichard 
73789a1d03eSRichard   if (X > 0x7FFFFFFF || X < ((-0x7FFFFFFF)-1)) return 1;
73889a1d03eSRichard   if (X <= 0x7FFFFFFF && X >= ((-0x7FFFFFFF)-1)) return 1;
73989a1d03eSRichard 
74089a1d03eSRichard   return 0;
74189a1d03eSRichard }
74289a1d03eSRichard 
74389a1d03eSRichard #define FLAG1 1
74489a1d03eSRichard #define FLAG2 2
74589a1d03eSRichard #define FLAG3 4
74689a1d03eSRichard #define FLAGS (FLAG1 | FLAG2 | FLAG3)
74789a1d03eSRichard #define NOTFLAGS !(FLAG1 | FLAG2 | FLAG3)
74889a1d03eSRichard int TestOperatorConfusion(int X, int Y, long Z)
74989a1d03eSRichard {
75089a1d03eSRichard   // Ineffective & expressions.
75189a1d03eSRichard   Y = (Y << 8) & 0xff;
75289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: ineffective bitwise and operation
75389a1d03eSRichard   Y = (Y << 12) & 0xfff;
75489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: ineffective bitwise and
75589a1d03eSRichard   Y = (Y << 12) & 0xff;
75689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: ineffective bitwise and
75789a1d03eSRichard   Y = (Y << 8) & 0x77;
75889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: ineffective bitwise and
75989a1d03eSRichard   Y = (Y << 5) & 0x11;
76089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: ineffective bitwise and
76189a1d03eSRichard 
76289a1d03eSRichard   // Tests for unmatched types
76389a1d03eSRichard   Z = (Z << 8) & 0xff;
76489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: ineffective bitwise and operation
76589a1d03eSRichard   Y = (Y << 12) & 0xfffL;
76689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: ineffective bitwise and
76789a1d03eSRichard   Z = (Y << 12) & 0xffLL;
76889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: ineffective bitwise and
76989a1d03eSRichard   Y = (Z << 8L) & 0x77L;
77089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: ineffective bitwise and
77189a1d03eSRichard 
77289a1d03eSRichard   Y = (Y << 8) & 0;
77389a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: ineffective bitwise and
77489a1d03eSRichard 
77589a1d03eSRichard   Y = (Y << 8) & -1;
77689a1d03eSRichard 
77789a1d03eSRichard   // Effective expressions. Do not check.
77889a1d03eSRichard   Y = (Y << 4) & 0x15;
77989a1d03eSRichard   Y = (Y << 3) & 0x250;
78089a1d03eSRichard   Y = (Y << 9) & 0xF33;
78189a1d03eSRichard 
78289a1d03eSRichard   int K = !(1 | 2 | 4);
78389a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: ineffective logical negation operator used; did you mean '~'?
78489a1d03eSRichard   // CHECK-FIXES: {{^}}  int K = ~(1 | 2 | 4);{{$}}
78589a1d03eSRichard   K = !(FLAG1 & FLAG2 & FLAG3);
78689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: ineffective logical negation operator
78789a1d03eSRichard   // CHECK-FIXES: {{^}}  K = ~(FLAG1 & FLAG2 & FLAG3);{{$}}
78889a1d03eSRichard   K = !(3 | 4);
78989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: ineffective logical negation operator
79089a1d03eSRichard   // CHECK-FIXES: {{^}}  K = ~(3 | 4);{{$}}
79189a1d03eSRichard   int NotFlags = !FLAGS;
79289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: ineffective logical negation operator
79389a1d03eSRichard   // CHECK-FIXES: {{^}}  int NotFlags = ~FLAGS;{{$}}
79489a1d03eSRichard   NotFlags = NOTFLAGS;
79589a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: ineffective logical negation operator
79689a1d03eSRichard   return !(1 | 2 | 4);
79789a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: ineffective logical negation operator
79889a1d03eSRichard   // CHECK-FIXES: {{^}}  return ~(1 | 2 | 4);{{$}}
79989a1d03eSRichard }
80089a1d03eSRichard 
80189a1d03eSRichard template <int Shift, int Mask>
80289a1d03eSRichard int TestOperatorConfusionDependent(int Y) {
80389a1d03eSRichard   int r1 = (Y << Shift) & 0xff;
80489a1d03eSRichard   int r2 = (Y << 8) & Mask;
80589a1d03eSRichard }
80689a1d03eSRichard #undef FLAG1
80789a1d03eSRichard #undef FLAG2
80889a1d03eSRichard #undef FLAG3
80989a1d03eSRichard 
81089a1d03eSRichard namespace no_crash {
81189a1d03eSRichard struct Foo {};
81289a1d03eSRichard bool operator<(const Foo&, const Foo&);
81389a1d03eSRichard template <class T>
81489a1d03eSRichard struct Bar {
81589a1d03eSRichard   static const Foo &GetFoo();
81689a1d03eSRichard   static bool Test(const T & maybe_foo, const Foo& foo) {
81789a1d03eSRichard     return foo < GetFoo() && foo < maybe_foo;
81889a1d03eSRichard   }
81989a1d03eSRichard };
82089a1d03eSRichard 
82189a1d03eSRichard template <class... Values>
82289a1d03eSRichard struct Bar2 {
82389a1d03eSRichard   static_assert((... && (sizeof(Values) > 0)) == (... && (sizeof(Values) > 0)));
82489a1d03eSRichard   // FIXME: It's not clear that we should be diagnosing this. The `&&` operator
82589a1d03eSRichard   // here is unresolved and could resolve to an overloaded operator that might
82689a1d03eSRichard   // have side-effects on its operands. For other constructs with the same
82789a1d03eSRichard   // property (eg, the `S2` cases above) we suppress this diagnostic. This
82889a1d03eSRichard   // started failing when Clang started properly modeling the fold-expression as
82989a1d03eSRichard   // containing an unresolved operator name.
83089a1d03eSRichard   // FIXME-MESSAGES: :[[@LINE-1]]:47: warning: both sides of operator are equivalent [misc-redundant-expression]
83189a1d03eSRichard };
83289a1d03eSRichard 
83389a1d03eSRichard } // namespace no_crash
83489a1d03eSRichard 
83589a1d03eSRichard int TestAssignSideEffect(int i) {
83689a1d03eSRichard   int k = i;
83789a1d03eSRichard 
83889a1d03eSRichard   if ((k = k + 1) != 1 || (k = k + 1) != 2)
83989a1d03eSRichard     return 0;
84089a1d03eSRichard 
84189a1d03eSRichard   if ((k = foo(0)) != 1 || (k = foo(0)) != 2)
84289a1d03eSRichard     return 1;
84389a1d03eSRichard 
84489a1d03eSRichard   return 2;
84589a1d03eSRichard }
846c1dc914aSPiotr Zegar 
847c1dc914aSPiotr Zegar namespace PR63096 {
848c1dc914aSPiotr Zegar 
849c1dc914aSPiotr Zegar struct alignas(sizeof(int)) X {
850c1dc914aSPiotr Zegar   int x;
851c1dc914aSPiotr Zegar };
852c1dc914aSPiotr Zegar 
853c1dc914aSPiotr Zegar static_assert(alignof(X) == sizeof(X));
854c1dc914aSPiotr Zegar static_assert(sizeof(X) == sizeof(X));
855c1dc914aSPiotr Zegar // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: both sides of operator are equivalent
856c1dc914aSPiotr Zegar 
857c1dc914aSPiotr Zegar }
8580c7d28f7SPiotr Zegar 
8590c7d28f7SPiotr Zegar namespace PR35857 {
8600c7d28f7SPiotr Zegar   void test() {
8610c7d28f7SPiotr Zegar     int x = 0;
8620c7d28f7SPiotr Zegar     int y = 0;
8630c7d28f7SPiotr Zegar     decltype(x + y - (x + y)) z = 10;
8640c7d28f7SPiotr Zegar   }
8650c7d28f7SPiotr Zegar }
866