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