1084 lines · cpp
1// RUN: %check_clang_tidy %s misc-redundant-expression %t -- -- -fno-delayed-template-parsing -Wno-array-compare-cxx262// RUN: %check_clang_tidy %s misc-redundant-expression %t -- -- -fno-delayed-template-parsing -Wno-array-compare-cxx26 -DTEST_MACRO3 4typedef __INT64_TYPE__ I64;5 6struct Point {7 int x;8 int y;9 int a[5];10} P;11 12extern Point P1;13extern Point P2;14 15extern int foo(int x);16extern int bar(int x);17extern int bat(int x, int y);18 19int TestSimpleEquivalent(int X, int Y) {20 if (X - X) return 1;21 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent [misc-redundant-expression]22 if (X / X) return 1;23 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent24 if (X % X) return 1;25 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent26 27 if (X & X) return 1;28 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent29 if (X | X) return 1;30 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent31 if (X ^ X) return 1;32 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent33 34 if (X < X) return 1;35 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent36 if (X <= X) return 1;37 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent38 if (X > X) return 1;39 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent40 if (X >= X) return 1;41 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent42 43 if (X && X) return 1;44 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent45 if (X || X) return 1;46 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent47 48 if (X != (((X)))) return 1;49 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent50 51 if (X + 1 == X + 1) return 1;52 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent53 if (X + 1 != X + 1) return 1;54 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent55 if (X + 1 <= X + 1) return 1;56 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent57 if (X + 1 >= X + 1) return 1;58 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent59 60 if ((X != 1 || Y != 1) && (X != 1 || Y != 1)) return 1;61 // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: both sides of operator are equivalent62 if (P.a[X - P.x] != P.a[X - P.x]) return 1;63 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: both sides of operator are equivalent64 65 if ((int)X < (int)X) return 1;66 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: both sides of operator are equivalent67 if (int(X) < int(X)) return 1;68 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: both sides of operator are equivalent69 70 if ( + "dummy" == + "dummy") return 1;71 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: both sides of operator are equivalent72 if (L"abc" == L"abc") return 1;73 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: both sides of operator are equivalent74 75 if (foo(0) - 2 < foo(0) - 2) return 1;76 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: both sides of operator are equivalent77 if (foo(bar(0)) < (foo(bar((0))))) return 1;78 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: both sides of operator are equivalent79 80 if (P1.x < P2.x && P1.x < P2.x) return 1;81 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: both sides of operator are equivalent82 if (P2.a[P1.x + 2] < P2.x && P2.a[(P1.x) + (2)] < (P2.x)) return 1;83 // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: both sides of operator are equivalent84 85 if (X && Y && X) return 1;86 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: operator has equivalent nested operands87 if (X || (Y || X)) return 1;88 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: operator has equivalent nested operands89 if ((X ^ Y) ^ (Y ^ X)) return 1;90 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: operator has equivalent nested operands91 92 return 0;93}94 95#ifndef TEST_MACRO96#define VAL_1 297#define VAL_3 398#else99#define VAL_1 3100#define VAL_3 2101#endif102 103#define VAL_2 2104 105#ifndef TEST_MACRO106#define VAL_4 2 + 1107#define VAL_6 3 + 1108#else109#define VAL_4 3 + 1110#define VAL_6 2 + 1111#endif112 113#define VAL_5 2 + 1114 115struct TestStruct116{117 int mA;118 int mB;119 int mC[10];120};121 122int TestDefineEquivalent() {123 124 int int_val1 = 3;125 int int_val2 = 4;126 int int_val = 0;127 const int cint_val2 = 4;128 129 // Cases which should not be reported130 if (VAL_1 != VAL_2) return 0;131 if (VAL_3 != VAL_2) return 0;132 if (VAL_1 == VAL_2) return 0;133 if (VAL_3 == VAL_2) return 0;134 if (VAL_1 >= VAL_2) return 0;135 if (VAL_3 >= VAL_2) return 0;136 if (VAL_1 <= VAL_2) return 0;137 if (VAL_3 <= VAL_2) return 0;138 if (VAL_1 < VAL_2) return 0;139 if (VAL_3 < VAL_2) return 0;140 if (VAL_1 > VAL_2) return 0;141 if (VAL_3 > VAL_2) return 0;142 143 if (VAL_4 != VAL_5) return 0;144 if (VAL_6 != VAL_5) return 0;145 if (VAL_6 == VAL_5) return 0;146 if (VAL_4 >= VAL_5) return 0;147 if (VAL_6 >= VAL_5) return 0;148 if (VAL_4 <= VAL_5) return 0;149 if (VAL_6 <= VAL_5) return 0;150 if (VAL_4 > VAL_5) return 0;151 if (VAL_6 > VAL_5) return 0;152 if (VAL_4 < VAL_5) return 0;153 if (VAL_6 < VAL_5) return 0;154 155 if (VAL_1 != 2) return 0;156 if (VAL_3 == 3) return 0;157 158 if (VAL_1 >= VAL_1) return 0;159 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent160 if (VAL_2 <= VAL_2) return 0;161 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent162 if (VAL_3 > VAL_3) return 0;163 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent164 if (VAL_4 < VAL_4) return 0;165 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent166 if (VAL_6 == VAL_6) return 2;167 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent168 if (VAL_5 != VAL_5) return 2;169 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent170 171 // Test prefixes172 if (+VAL_6 == +VAL_6) return 2;173 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: both sides of operator are equivalent174 if (-VAL_6 == -VAL_6) return 2;175 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: both sides of operator are equivalent176 if ((+VAL_6) == (+VAL_6)) return 2;177 // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: both sides of operator are equivalent178 if ((-VAL_6) == (-VAL_6)) return 2;179 // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: both sides of operator are equivalent180 181 if (1 >= 1) return 0;182 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent183 if (0xFF <= 0xFF) return 0;184 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: both sides of operator are equivalent185 if (042 > 042) return 0;186 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: both sides of operator are equivalent187 188 int_val = (VAL_6 == VAL_6)?int_val1: int_val2;189 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: both sides of operator are equivalent190 int_val = (042 > 042)?int_val1: int_val2;191 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: both sides of operator are equivalent192 193 194 // Ternary operator cases which should not be reported195 int_val = (VAL_4 == VAL_5)? int_val1: int_val2;196 int_val = (VAL_3 != VAL_2)? int_val1: int_val2;197 int_val = (VAL_6 != 10)? int_val1: int_val2;198 int_val = (VAL_6 != 3)? int_val1: int_val2;199 int_val = (VAL_6 != 4)? int_val1: int_val2;200 int_val = (VAL_6 == 3)? int_val1: int_val2;201 int_val = (VAL_6 == 4)? int_val1: int_val2;202 203 TestStruct tsVar1 = {204 .mA = 3,205 .mB = int_val,206 .mC[0 ... VAL_2 - 2] = int_val + 1,207 };208 209 TestStruct tsVar2 = {210 .mA = 3,211 .mB = int_val,212 .mC[0 ... cint_val2 - 2] = int_val + 1,213 };214 215 TestStruct tsVar3 = {216 .mA = 3,217 .mB = int_val,218 .mC[0 ... VAL_3 - VAL_3] = int_val + 1,219 // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: both sides of operator are equivalent220 };221 222 TestStruct tsVar4 = {223 .mA = 3,224 .mB = int_val,225 .mC[0 ... 5 - 5] = int_val + 1,226 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: both sides of operator are equivalent227 };228 229 return 1 + int_val + sizeof(tsVar1) + sizeof(tsVar2) +230 sizeof(tsVar3) + sizeof(tsVar4);231}232 233#define LOOP_DEFINE 1234 235unsigned int testLoops(const unsigned int arr1[LOOP_DEFINE])236{237 unsigned int localIndex;238 for (localIndex = LOOP_DEFINE - 1; localIndex > 0; localIndex--)239 {240 }241 for (localIndex = LOOP_DEFINE - 1; 10 > 10; localIndex--)242 // CHECK-MESSAGES: :[[@LINE-1]]:41: warning: both sides of operator are equivalent243 {244 }245 246 for (localIndex = LOOP_DEFINE - 1; LOOP_DEFINE > LOOP_DEFINE; localIndex--)247 // CHECK-MESSAGES: :[[@LINE-1]]:50: warning: both sides of operator are equivalent248 {249 }250 251 return localIndex;252}253 254#define getValue(a) a255#define getValueM(a) a256 257int TestParamDefine() {258 int ret = 0;259 260 // Negative cases261 ret += getValue(VAL_6) == getValue(2);262 ret += getValue(VAL_6) == getValue(3);263 ret += getValue(VAL_5) == getValue(2);264 ret += getValue(VAL_5) == getValue(3);265 ret += getValue(1) > getValue( 2);266 ret += getValue(VAL_1) == getValue(VAL_2);267 ret += getValue(VAL_1) != getValue(VAL_2);268 ret += getValue(VAL_1) == getValueM(VAL_1);269 ret += getValue(VAL_1 + VAL_2) == getValueM(VAL_1 + VAL_2);270 ret += getValue(1) == getValueM(1);271 ret += getValue(false) == getValueM(false);272 ret += -getValue(1) > +getValue( 1);273 274 // Positive cases275 ret += (+getValue(1)) > (+getValue( 1));276 // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: both sides of operator are equivalent277 ret += (-getValue(1)) > (-getValue( 1));278 // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: both sides of operator are equivalent279 280 ret += +getValue(1) > +getValue( 1);281 // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: both sides of operator are equivalent282 ret += -getValue(1) > -getValue( 1);283 // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: both sides of operator are equivalent284 285 ret += getValue(1) > getValue( 1);286 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: both sides of operator are equivalent287 ret += getValue(1) > getValue( 1 );288 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: both sides of operator are equivalent289 ret += getValue(1) > getValue( 1);290 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: both sides of operator are equivalent291 ret += getValue( 1) > getValue( 1);292 // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: both sides of operator are equivalent293 ret += getValue( 1 ) > getValue( 1);294 // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: both sides of operator are equivalent295 ret += getValue( VAL_5 ) > getValue(VAL_5);296 // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: both sides of operator are equivalent297 ret += getValue( VAL_5 ) > getValue( VAL_5);298 // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: both sides of operator are equivalent299 ret += getValue( VAL_5 ) > getValue( VAL_5 ) ;300 // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: both sides of operator are equivalent301 ret += getValue(VAL_5) > getValue( VAL_5 ) ;302 // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: both sides of operator are equivalent303 ret += getValue(VAL_1+VAL_2) > getValue(VAL_1 + VAL_2) ;304 // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: both sides of operator are equivalent305 ret += getValue(VAL_1)+getValue(VAL_2) > getValue(VAL_1) + getValue( VAL_2) ;306 // CHECK-MESSAGES: :[[@LINE-1]]:42: warning: both sides of operator are equivalent307 ret += (getValue(VAL_1)+getValue(VAL_2)) > (getValue(VAL_1) + getValue( VAL_2) ) ;308 // CHECK-MESSAGES: :[[@LINE-1]]:44: warning: both sides of operator are equivalent309 return ret;310}311 312template <int DX>313int TestSimpleEquivalentDependent() {314 if (DX > 0 && DX > 0) return 1;315 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: both sides of operator are equivalent316 317 return 0;318}319 320int Valid(int X, int Y) {321 if (X != Y) return 1;322 if (X == Y + 0) return 1;323 if (P.x == P.y) return 1;324 if (P.a[P.x] < P.a[P.y]) return 1;325 if (P.a[0] < P.a[1]) return 1;326 327 if (P.a[0] < P.a[0ULL]) return 1;328 if (0 < 0ULL) return 1;329 if ((int)0 < (int)0ULL) return 1;330 331 if (++X != ++X) return 1;332 if (P.a[X]++ != P.a[X]++) return 1;333 if (P.a[X++] != P.a[X++]) return 1;334 if (X && X++ && X) return 1;335 336 if ("abc" == "ABC") return 1;337 if (foo(bar(0)) < (foo(bat(0, 1)))) return 1;338 return 0;339}340 341#define COND_OP_MACRO 9342#define COND_OP_OTHER_MACRO 9343#define COND_OP_THIRD_MACRO COND_OP_MACRO344int TestConditional(int x, int y) {345 int k = 0;346 k += (y < 0) ? x : x;347 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: 'true' and 'false' expressions are equivalent348 k += (y < 0) ? x + 1 : x + 1;349 // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: 'true' and 'false' expressions are equivalent350 k += (y < 0) ? COND_OP_MACRO : COND_OP_MACRO;351 // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: 'true' and 'false' expressions are equivalent352 k += (y < 0) ? COND_OP_MACRO + COND_OP_OTHER_MACRO : COND_OP_MACRO + COND_OP_OTHER_MACRO;353 // CHECK-MESSAGES: :[[@LINE-1]]:54: warning: 'true' and 'false' expressions are equivalent354 355 // Do not match for conditional operators with a macro and a const.356 k += (y < 0) ? COND_OP_MACRO : 9;357 // Do not match for conditional operators with expressions from different macros.358 k += (y < 0) ? COND_OP_MACRO : COND_OP_OTHER_MACRO;359 // Do not match for conditional operators when a macro is defined to another macro360 k += (y < 0) ? COND_OP_MACRO : COND_OP_THIRD_MACRO;361#undef COND_OP_THIRD_MACRO362#define COND_OP_THIRD_MACRO 8363 k += (y < 0) ? COND_OP_MACRO : COND_OP_THIRD_MACRO;364#undef COND_OP_THIRD_MACRO365 366 k += (y < 0) ? sizeof(I64) : sizeof(I64);367 // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: 'true' and 'false' expressions are equivalent368 k += (y < 0) ? sizeof(TestConditional(k,y)) : sizeof(TestConditional(k,y));369 // CHECK-MESSAGES: :[[@LINE-1]]:47: warning: 'true' and 'false' expressions are equivalent370 // No warning if the expression arguments are different.371 k += (y < 0) ? sizeof(TestConditional(k,y)) : sizeof(Valid(k,y));372 373 return k;374}375#undef COND_OP_MACRO376#undef COND_OP_OTHER_MACRO377 378// Overloaded operators that compare two instances of a struct.379struct MyStruct {380 int x;381 bool operator==(const MyStruct& rhs) const {return this->x == rhs.x; } // not modifing382 bool operator>=(const MyStruct& rhs) const { return this->x >= rhs.x; } // not modifing383 bool operator<=(MyStruct& rhs) const { return this->x <= rhs.x; }384 bool operator&&(const MyStruct& rhs){ this->x++; return this->x && rhs.x; }385} Q;386 387bool operator!=(const MyStruct& lhs, const MyStruct& rhs) { return lhs.x == rhs.x; } // not modifing388bool operator<(const MyStruct& lhs, const MyStruct& rhs) { return lhs.x < rhs.x; } // not modifing389bool operator>(const MyStruct& lhs, MyStruct& rhs) { rhs.x--; return lhs.x > rhs.x; }390bool operator||(MyStruct& lhs, const MyStruct& rhs) { lhs.x++; return lhs.x || rhs.x; }391 392struct MyStruct1 {393 bool x;394 MyStruct1(bool x) : x(x) {};395 operator bool() { return x; }396};397 398MyStruct1 operator&&(const MyStruct1& lhs, const MyStruct1& rhs) { return lhs.x && rhs.x; }399MyStruct1 operator||(MyStruct1& lhs, MyStruct1& rhs) { return lhs.x && rhs.x; }400 401bool TestOverloadedOperator(MyStruct& S) {402 if (S == Q) return false;403 404 if (S <= S) return false;405 if (S && S) return false;406 if (S > S) return false;407 if (S || S) return false;408 409 if (S == S) return true;410 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of overloaded operator are equivalent411 if (S < S) return true;412 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of overloaded operator are equivalent413 if (S != S) return true;414 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of overloaded operator are equivalent415 if (S >= S) return true;416 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of overloaded operator are equivalent417 418 MyStruct1 U(false);419 MyStruct1 V(true);420 421 // valid because the operator is not const422 if ((U || V) || U) return true;423 424 if (U && V && U && V) return true;425 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: overloaded operator has equivalent nested operands426 427 return true;428}429 430#define LT(x, y) (void)((x) < (y))431#define COND(x, y, z) ((x)?(y):(z))432#define EQUALS(x, y) (x) == (y)433 434int TestMacro(int X, int Y) {435 LT(0, 0);436 LT(1, 0);437 LT(X, X);438 LT(X+1, X + 1);439 COND(X < Y, X, X);440 EQUALS(Q, Q);441 return 0;442}443 444int TestFalsePositive(int* A, int X, float F) {445 // Produced by bison.446 X = A[(2) - (2)];447 X = A['a' - 'a'];448 449 // Testing NaN.450 if (F != F && F == F) return 1;451 return 0;452}453 454int TestBannedMacros() {455#define EAGAIN 3456#define NOT_EAGAIN 3457 if (EAGAIN == 0 | EAGAIN == 0) return 0;458 if (NOT_EAGAIN == 0 | NOT_EAGAIN == 0) return 0;459 // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: both sides of operator are equivalent460 return 0;461}462 463struct MyClass {464static const int Value = 42;465};466template <typename T, typename U>467void TemplateCheck() {468 static_assert(T::Value == U::Value, "should be identical");469 static_assert(T::Value == T::Value, "should be identical");470 // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: both sides of operator are equivalent471}472void TestTemplate() { TemplateCheck<MyClass, MyClass>(); }473 474int TestArithmetic(int X, int Y) {475 if (X + 1 == X) return 1;476 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always false477 if (X + 1 != X) return 1;478 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true479 if (X - 1 == X) return 1;480 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always false481 if (X - 1 != X) return 1;482 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true483 484 if (X + 1LL == X) return 1;485 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always false486 if (X + 1ULL == X) return 1;487 // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: logical expression is always false488 489 if (X == X + 1) return 1;490 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: logical expression is always false491 if (X != X + 1) return 1;492 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: logical expression is always true493 if (X == X - 1) return 1;494 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: logical expression is always false495 if (X != X - 1) return 1;496 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: logical expression is always true497 498 if (X != X - 1U) return 1;499 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: logical expression is always true500 if (X != X - 1LL) return 1;501 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: logical expression is always true502 503 if ((X+X) != (X+X) - 1) return 1;504 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true505 506 if (X + 1 == X + 2) return 1;507 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always false508 if (X + 1 != X + 2) return 1;509 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true510 511 if (X - 1 == X - 2) return 1;512 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always false513 if (X - 1 != X - 2) return 1;514 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true515 516 if (X + 1 == X - -1) return 1;517 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true518 if (X + 1 != X - -1) return 1;519 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always false520 if (X + 1 == X - -2) return 1;521 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always false522 if (X + 1 != X - -2) return 1;523 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true524 525 if (X + 1 == X - (~0)) return 1;526 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true527 if (X + 1 == X - (~0U)) return 1;528 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true529 530 if (X + 1 == X - (~0ULL)) return 1;531 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true532 533 // Should not match.534 if (X + 0.5 == X) return 1;535 if (X + 1 == Y) return 1;536 if (X + 1 == Y + 1) return 1;537 if (X + 1 == Y + 2) return 1;538 539 return 0;540}541 542int TestBitwise(int X, int Y) {543 544 if ((X & 0xFF) == 0xF00) return 1;545 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always false546 if ((X & 0xFF) != 0xF00) return 1;547 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always true548 if ((X | 0xFF) == 0xF00) return 1;549 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always false550 if ((X | 0xFF) != 0xF00) return 1;551 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always true552 553 if ((X | 0xFFULL) != 0xF00) return 1;554 // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: logical expression is always true555 if ((X | 0xFF) != 0xF00ULL) return 1;556 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always true557 558 if ((0xFF & X) == 0xF00) return 1;559 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always false560 if ((0xFF & X) != 0xF00) return 1;561 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always true562 if ((0xFF & X) == 0xF00) return 1;563 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always false564 if ((0xFF & X) != 0xF00) return 1;565 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always true566 567 if ((0xFFLL & X) == 0xF00) return 1;568 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: logical expression is always false569 if ((0xFF & X) == 0xF00ULL) return 1;570 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always false571 572 return 0;573}574 575// Overloaded operators that compare an instance of a struct and an integer576// constant.577struct S {578 S() { x = 1; }579 int x;580 // Overloaded comparison operators without any possible side effect.581 bool operator==(const int &i) const { return x == i; } // not modifying582 bool operator!=(int i) const { return x != i; } // not modifying583 bool operator>(const int &i) const { return x > i; } // not modifying584 bool operator<(int i) const { return x < i; } // not modifying585};586 587bool operator<=(const S &s, int i) { return s.x <= i; } // not modifying588bool operator>=(const S &s, const int &i) { return s.x >= i; } // not modifying589 590bool operator==(int i, const S &s) { return s == i; } // not modifying591bool operator<(const int &i, const S &s) { return s > i; } // not modifying592bool operator<=(const int &i, const S &s) { return s >= i; } // not modifying593bool operator>(const int &i, const S &s) { return s < i; } // not modifying594 595struct S2 {596 S2() { x = 1; }597 int x;598 // Overloaded comparison operators that are able to modify their params.599 bool operator==(const int &i) {600 this->x++;601 return x == i;602 }603 bool operator!=(int i) { return x != i; }604 bool operator>(const int &i) { return x > i; }605 bool operator<(int i) {606 this->x--;607 return x < i;608 }609};610 611bool operator>=(S2 &s, const int &i) { return s.x >= i; }612bool operator<=(S2 &s, int i) {613 s.x++;614 return s.x <= i;615}616 617int TestLogical(int X, int Y){618#define CONFIG 0619 if (CONFIG && X) return 1;620#undef CONFIG621#define CONFIG 1622 if (CONFIG || X) return 1;623#undef CONFIG624 625 if (X == 10 && X != 10) return 1;626 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always false627 if (X == 10 && (X != 10)) return 1;628 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always false629 if (X == 10 && !(X == 10)) return 1;630 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always false631 if (!(X != 10) && !(X == 10)) return 1;632 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always false633 634 if (X == 10ULL && X != 10ULL) return 1;635 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always false636 if (!(X != 10U) && !(X == 10)) return 1;637 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: logical expression is always false638 if (!(X != 10LL) && !(X == 10)) return 1;639 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: logical expression is always false640 if (!(X != 10ULL) && !(X == 10)) return 1;641 // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: logical expression is always false642 643 if (X == 0 && X) return 1;644 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always false645 if (X != 0 && !X) return 1;646 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always false647 if (X && !X) return 1;648 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: logical expression is always false649 650 if (X && !!X) return 1;651 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: equivalent expression on both sides of logical operator652 if (X != 0 && X) return 1;653 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: equivalent expression on both sides of logical operator654 if (X != 0 && !!X) return 1;655 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: equivalent expression on both sides of logical operator656 if (X == 0 && !X) return 1;657 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: equivalent expression on both sides of logical operator658 659 // Should not match.660 if (X == 10 && Y == 10) return 1;661 if (X != 10 && X != 12) return 1;662 if (X == 10 || X == 12) return 1;663 if (!X && !Y) return 1;664 if (!X && Y) return 1;665 if (!X && Y == 0) return 1;666 if (X == 10 && Y != 10) return 1;667 668 // Test for overloaded operators with constant params.669 S s1;670 if (s1 == 1 && s1 == 1) return true;671 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: equivalent expression on both sides of logical operator672 if (s1 == 1 || s1 != 1) return true;673 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always true674 if (s1 > 1 && s1 < 1) return true;675 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always false676 if (s1 >= 1 || s1 <= 1) return true;677 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always true678 if (s1 >= 2 && s1 <= 0) return true;679 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always false680 681 // Same test as above but with swapped LHS/RHS on one side of the logical operator.682 if (1 == s1 && s1 == 1) return true;683 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: equivalent expression on both sides of logical operator684 if (1 == s1 || s1 != 1) return true;685 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always true686 if (1 < s1 && s1 < 1) return true;687 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always false688 if (1 <= s1 || s1 <= 1) return true;689 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always true690 if (2 < s1 && 0 > s1) return true;691 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always false692 693 // Test for absence of false positives (issue #54011).694 if (s1 == 1 || s1 == 2) return true;695 if (s1 > 1 && s1 < 3) return true;696 if (s1 >= 2 || s1 <= 0) return true;697 698 // Test for overloaded operators that may modify their params.699 S2 s2;700 if (s2 == 1 || s2 != 1) return true;701 if (s2 == 1 || s2 == 1) return true;702 if (s2 > 1 && s2 < 1) return true;703 if (s2 >= 1 || s2 <= 1) return true;704}705 706int TestRelational(int X, int Y) {707 if (X == 10 && X > 10) return 1;708 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always false709 if (X == 10 && X < 10) return 1;710 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always false711 if (X < 10 && X > 10) return 1;712 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always false713 if (X <= 10 && X > 10) return 1;714 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always false715 if (X < 10 && X >= 10) return 1;716 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always false717 if (X < 10 && X == 10) return 1;718 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always false719 720 if (X > 5 && X <= 5) return 1;721 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always false722 if (X > -5 && X <= -5) return 1;723 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always false724 725 if (X < 10 || X >= 10) return 1;726 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always true727 if (X <= 10 || X > 10) return 1;728 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always true729 if (X <= 10 || X >= 11) return 1;730 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: logical expression is always true731 if (X != 7 || X != 14) return 1;732 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always true733 if (X == 7 || X != 5) return 1;734 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant735 if (X != 7 || X == 7) return 1;736 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: logical expression is always true737 738 if (X < 7 && X < 6) return 1;739 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant740 if (X < 7 && X < 7) return 1;741 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent742 if (X < 7 && X < 8) return 1;743 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: expression is redundant744 745 if (X < 7 && X <= 5) return 1;746 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant747 if (X < 7 && X <= 6) return 1;748 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: equivalent expression on both sides of logical operator749 if (X < 7 && X <= 7) return 1;750 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: expression is redundant751 if (X < 7 && X <= 8) return 1;752 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: expression is redundant753 754 if (X <= 7 && X < 6) return 1;755 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant756 if (X <= 7 && X < 7) return 1;757 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant758 if (X <= 7 && X < 8) return 1;759 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: equivalent expression on both sides of logical operator760 761 if (X >= 7 && X > 6) return 1;762 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: equivalent expression on both sides of logical operator763 if (X >= 7 && X > 7) return 1;764 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant765 if (X >= 7 && X > 8) return 1;766 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant767 768 if (X <= 7 && X <= 5) return 1;769 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant770 if (X <= 7 && X <= 6) return 1;771 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant772 if (X <= 7 && X <= 7) return 1;773 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: both sides of operator are equivalent774 if (X <= 7 && X <= 8) return 1;775 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: expression is redundant776 777 if (X == 11 && X > 10) return 1;778 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: expression is redundant779 if (X == 11 && X < 12) return 1;780 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: expression is redundant781 if (X > 10 && X == 11) return 1;782 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant783 if (X < 12 && X == 11) return 1;784 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant785 786 if (X != 11 && X == 42) return 1;787 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant788 if (X != 11 && X > 11) return 1;789 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant790 if (X != 11 && X < 11) return 1;791 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant792 if (X != 11 && X < 8) return 1;793 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant794 if (X != 11 && X > 14) return 1;795 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant796 797 if (X < 7 || X < 6) return 1;798 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: expression is redundant799 if (X < 7 || X < 7) return 1;800 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent801 if (X < 7 || X < 8) return 1;802 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant803 804 if (X > 7 || X > 6) return 1;805 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant806 if (X > 7 || X > 7) return 1;807 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent808 if (X > 7 || X > 8) return 1;809 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: expression is redundant810 811 // Should not match.812 if (X < 10 || X > 12) return 1;813 if (X > 10 && X < 12) return 1;814 if (X < 10 || X >= 12) return 1;815 if (X > 10 && X <= 12) return 1;816 if (X <= 10 || X > 12) return 1;817 if (X >= 10 && X < 12) return 1;818 if (X <= 10 || X >= 12) return 1;819 if (X >= 10 && X <= 12) return 1;820 if (X >= 10 && X <= 11) return 1;821 if (X >= 10 && X < 11) return 1;822 if (X > 10 && X <= 11) return 1;823 if (X > 10 && X != 11) return 1;824 if (X >= 10 && X <= 10) return 1;825 if (X <= 10 && X >= 10) return 1;826 if (X < 0 || X > 0) return 1;827}828 829int TestRelationalMacros(int X){830#define SOME_MACRO 3831#define SOME_MACRO_SAME_VALUE 3832#define SOME_OTHER_MACRO 9833 // Do not match for redundant relational macro expressions that can be834 // considered intentional, and for some particular values, non redundant.835 836 // Test cases for expressions with the same macro on both sides.837 if (X < SOME_MACRO && X > SOME_MACRO) return 1;838 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: logical expression is always false839 if (X < SOME_MACRO && X == SOME_MACRO) return 1;840 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: logical expression is always false841 if (X < SOME_MACRO || X >= SOME_MACRO) return 1;842 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: logical expression is always true843 if (X <= SOME_MACRO || X > SOME_MACRO) return 1;844 // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: logical expression is always true845 if (X != SOME_MACRO && X > SOME_MACRO) return 1;846 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant847 if (X != SOME_MACRO && X < SOME_MACRO) return 1;848 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: expression is redundant849 850 // Test cases for two different macros.851 if (X < SOME_MACRO && X > SOME_OTHER_MACRO) return 1;852 if (X != SOME_MACRO && X >= SOME_OTHER_MACRO) return 1;853 if (X != SOME_MACRO && X != SOME_OTHER_MACRO) return 1;854 if (X == SOME_MACRO || X == SOME_MACRO_SAME_VALUE) return 1;855 if (X == SOME_MACRO || X <= SOME_MACRO_SAME_VALUE) return 1;856 if (X == SOME_MACRO || X > SOME_MACRO_SAME_VALUE) return 1;857 if (X < SOME_MACRO && X <= SOME_OTHER_MACRO) return 1;858 if (X == SOME_MACRO && X > SOME_OTHER_MACRO) return 1;859 if (X == SOME_MACRO && X != SOME_OTHER_MACRO) return 1;860 if (X == SOME_MACRO && X != SOME_MACRO_SAME_VALUE) return 1;861 if (X == SOME_MACRO_SAME_VALUE && X == SOME_MACRO ) return 1;862 863 // Test cases for a macro and a const.864 if (X < SOME_MACRO && X > 9) return 1;865 if (X != SOME_MACRO && X >= 9) return 1;866 if (X != SOME_MACRO && X != 9) return 1;867 if (X == SOME_MACRO || X == 3) return 1;868 if (X == SOME_MACRO || X <= 3) return 1;869 if (X < SOME_MACRO && X <= 9) return 1;870 if (X == SOME_MACRO && X != 9) return 1;871 if (X == SOME_MACRO && X == 9) return 1;872 873#undef SOME_OTHER_MACRO874#undef SOME_MACRO_SAME_VALUE875#undef SOME_MACRO876 return 0;877}878 879int TestValidExpression(int X) {880 if (X - 1 == 1 - X) return 1;881 if (2 * X == X) return 1;882 if ((X << 1) == X) return 1;883 884 return 0;885}886 887enum Color { Red, Yellow, Green };888int TestRelationalWithEnum(enum Color C) {889 if (C == Red && C == Yellow) return 1;890 // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: logical expression is always false891 if (C == Red && C != Red) return 1;892 // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: logical expression is always false893 if (C != Red || C != Yellow) return 1;894 // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: logical expression is always true895 896 // Should not match.897 if (C == Red || C == Yellow) return 1;898 if (C != Red && C != Yellow) return 1;899 900 return 0;901}902 903template<class T>904int TestRelationalTemplated(int X) {905 // This test causes a corner case with |isIntegerConstantExpr| where the type906 // is dependent. There is an assert failing when evaluating907 // sizeof(<incomplet-type>).908 if (sizeof(T) == 4 || sizeof(T) == 8) return 1;909 910 if (X + 0 == -X) return 1;911 if (X + 0 < X) return 1;912 913 return 0;914}915 916int TestWithSignedUnsigned(int X) {917 if (X + 1 == X + 1ULL) return 1;918 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: logical expression is always true919 920 if ((X & 0xFFU) == 0xF00) return 1;921 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: logical expression is always false922 923 if ((X & 0xFF) == 0xF00U) return 1;924 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: logical expression is always false925 926 if ((X & 0xFFU) == 0xF00U) return 1;927 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: logical expression is always false928 929 return 0;930}931 932int TestWithLong(int X, I64 Y) {933 if (X + 0ULL == -X) return 1;934 if (Y + 0 == -Y) return 1;935 if (Y <= 10 && X >= 10LL) return 1;936 if (Y <= 10 && X >= 10ULL) return 1;937 if (X <= 10 || X > 12LL) return 1;938 if (X <= 10 || X > 12ULL) return 1;939 if (Y <= 10 || Y > 12) return 1;940 941 return 0;942}943 944int TestWithMinMaxInt(int X) {945 if (X <= X + 0xFFFFFFFFU) return 1;946 if (X <= X + 0x7FFFFFFF) return 1;947 if (X <= X + 0x80000000) return 1;948 949 if (X <= 0xFFFFFFFFU && X > 0) return 1;950 if (X <= 0xFFFFFFFFU && X > 0U) return 1;951 952 if (X + 0x80000000 == X - 0x80000000) return 1;953 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: logical expression is always true954 955 if (X > 0x7FFFFFFF || X < ((-0x7FFFFFFF)-1)) return 1;956 if (X <= 0x7FFFFFFF && X >= ((-0x7FFFFFFF)-1)) return 1;957 958 return 0;959}960 961#define FLAG1 1962#define FLAG2 2963#define FLAG3 4964#define FLAGS (FLAG1 | FLAG2 | FLAG3)965#define NOTFLAGS !(FLAG1 | FLAG2 | FLAG3)966int TestOperatorConfusion(int X, int Y, long Z)967{968 // Ineffective & expressions.969 Y = (Y << 8) & 0xff;970 // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: ineffective bitwise and operation971 Y = (Y << 12) & 0xfff;972 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: ineffective bitwise and973 Y = (Y << 12) & 0xff;974 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: ineffective bitwise and975 Y = (Y << 8) & 0x77;976 // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: ineffective bitwise and977 Y = (Y << 5) & 0x11;978 // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: ineffective bitwise and979 980 // Tests for unmatched types981 Z = (Z << 8) & 0xff;982 // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: ineffective bitwise and operation983 Y = (Y << 12) & 0xfffL;984 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: ineffective bitwise and985 Z = (Y << 12) & 0xffLL;986 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: ineffective bitwise and987 Y = (Z << 8L) & 0x77L;988 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: ineffective bitwise and989 990 Y = (Y << 8) & 0;991 // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: ineffective bitwise and992 993 Y = (Y << 8) & -1;994 995 // Effective expressions. Do not check.996 Y = (Y << 4) & 0x15;997 Y = (Y << 3) & 0x250;998 Y = (Y << 9) & 0xF33;999 1000 int K = !(1 | 2 | 4);1001 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: ineffective logical negation operator used; did you mean '~'?1002 // CHECK-FIXES: int K = ~(1 | 2 | 4);1003 K = !(FLAG1 & FLAG2 & FLAG3);1004 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: ineffective logical negation operator1005 // CHECK-FIXES: K = ~(FLAG1 & FLAG2 & FLAG3);1006 K = !(3 | 4);1007 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: ineffective logical negation operator1008 // CHECK-FIXES: K = ~(3 | 4);1009 int NotFlags = !FLAGS;1010 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: ineffective logical negation operator1011 // CHECK-FIXES: int NotFlags = ~FLAGS;1012 NotFlags = NOTFLAGS;1013 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: ineffective logical negation operator1014 return !(1 | 2 | 4);1015 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: ineffective logical negation operator1016 // CHECK-FIXES: return ~(1 | 2 | 4);1017}1018 1019template <int Shift, int Mask>1020int TestOperatorConfusionDependent(int Y) {1021 int r1 = (Y << Shift) & 0xff;1022 int r2 = (Y << 8) & Mask;1023}1024#undef FLAG11025#undef FLAG21026#undef FLAG31027 1028namespace no_crash {1029struct Foo {};1030bool operator<(const Foo&, const Foo&);1031template <class T>1032struct Bar {1033 static const Foo &GetFoo();1034 static bool Test(const T & maybe_foo, const Foo& foo) {1035 return foo < GetFoo() && foo < maybe_foo;1036 }1037};1038 1039template <class... Values>1040struct Bar2 {1041 static_assert((... && (sizeof(Values) > 0)) == (... && (sizeof(Values) > 0)));1042 // FIXME: It's not clear that we should be diagnosing this. The `&&` operator1043 // here is unresolved and could resolve to an overloaded operator that might1044 // have side-effects on its operands. For other constructs with the same1045 // property (eg, the `S2` cases above) we suppress this diagnostic. This1046 // started failing when Clang started properly modeling the fold-expression as1047 // containing an unresolved operator name.1048 // FIXME-MESSAGES: :[[@LINE-1]]:47: warning: both sides of operator are equivalent [misc-redundant-expression]1049};1050 1051} // namespace no_crash1052 1053int TestAssignSideEffect(int i) {1054 int k = i;1055 1056 if ((k = k + 1) != 1 || (k = k + 1) != 2)1057 return 0;1058 1059 if ((k = foo(0)) != 1 || (k = foo(0)) != 2)1060 return 1;1061 1062 return 2;1063}1064 1065namespace PR63096 {1066 1067struct alignas(sizeof(int)) X {1068 int x;1069};1070 1071static_assert(alignof(X) == sizeof(X));1072static_assert(sizeof(X) == sizeof(X));1073// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: both sides of operator are equivalent1074 1075}1076 1077namespace PR35857 {1078 void test() {1079 int x = 0;1080 int y = 0;1081 decltype(x + y - (x + y)) z = 10;1082 }1083}1084