1*89a1d03eSRichard // RUN: %check_clang_tidy %s android-comparison-in-temp-failure-retry %t 2*89a1d03eSRichard 3*89a1d03eSRichard #define TEMP_FAILURE_RETRY(x) \ 4*89a1d03eSRichard ({ \ 5*89a1d03eSRichard typeof(x) __z; \ 6*89a1d03eSRichard do \ 7*89a1d03eSRichard __z = (x); \ 8*89a1d03eSRichard while (__z == -1); \ 9*89a1d03eSRichard __z; \ 10*89a1d03eSRichard }) 11*89a1d03eSRichard 12*89a1d03eSRichard int foo(void); 13*89a1d03eSRichard int bar(int a); 14*89a1d03eSRichard test(void)15*89a1d03eSRichardvoid test(void) { 16*89a1d03eSRichard int i; 17*89a1d03eSRichard TEMP_FAILURE_RETRY((i = foo())); 18*89a1d03eSRichard TEMP_FAILURE_RETRY(foo()); 19*89a1d03eSRichard TEMP_FAILURE_RETRY((foo())); 20*89a1d03eSRichard 21*89a1d03eSRichard TEMP_FAILURE_RETRY(foo() == 1); 22*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: top-level comparison in TEMP_FAILURE_RETRY [android-comparison-in-temp-failure-retry] 23*89a1d03eSRichard TEMP_FAILURE_RETRY((foo() == 1)); 24*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: top-level comparison in TEMP_FAILURE_RETRY 25*89a1d03eSRichard TEMP_FAILURE_RETRY((int)(foo() == 1)); 26*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: top-level comparison in TEMP_FAILURE_RETRY 27*89a1d03eSRichard 28*89a1d03eSRichard TEMP_FAILURE_RETRY(bar(foo() == 1)); 29*89a1d03eSRichard TEMP_FAILURE_RETRY((bar(foo() == 1))); 30*89a1d03eSRichard TEMP_FAILURE_RETRY((bar(foo() == 1)) == 1); 31*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:40: warning: top-level comparison in TEMP_FAILURE_RETRY 32*89a1d03eSRichard TEMP_FAILURE_RETRY(((bar(foo() == 1)) == 1)); 33*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:41: warning: top-level comparison in TEMP_FAILURE_RETRY 34*89a1d03eSRichard TEMP_FAILURE_RETRY((int)((bar(foo() == 1)) == 1)); 35*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:46: warning: top-level comparison in TEMP_FAILURE_RETRY 36*89a1d03eSRichard 37*89a1d03eSRichard #define INDIRECT TEMP_FAILURE_RETRY 38*89a1d03eSRichard INDIRECT(foo()); 39*89a1d03eSRichard INDIRECT((foo() == 1)); 40*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: top-level comparison in TEMP_FAILURE_RETRY 41*89a1d03eSRichard INDIRECT(bar(foo() == 1)); 42*89a1d03eSRichard INDIRECT((int)((bar(foo() == 1)) == 1)); 43*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: top-level comparison in TEMP_FAILURE_RETRY 44*89a1d03eSRichard 45*89a1d03eSRichard #define TFR(x) TEMP_FAILURE_RETRY(x) 46*89a1d03eSRichard TFR(foo()); 47*89a1d03eSRichard TFR((foo() == 1)); 48*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: top-level comparison in TEMP_FAILURE_RETRY 49*89a1d03eSRichard TFR(bar(foo() == 1)); 50*89a1d03eSRichard TFR((int)((bar(foo() == 1)) == 1)); 51*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: top-level comparison in TEMP_FAILURE_RETRY 52*89a1d03eSRichard 53*89a1d03eSRichard #define ADD_TFR(x) (1 + TEMP_FAILURE_RETRY(x) + 1) 54*89a1d03eSRichard ADD_TFR(foo()); 55*89a1d03eSRichard ADD_TFR(foo() == 1); 56*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: top-level comparison in TEMP_FAILURE_RETRY 57*89a1d03eSRichard 58*89a1d03eSRichard ADD_TFR(bar(foo() == 1)); 59*89a1d03eSRichard ADD_TFR((int)((bar(foo() == 1)) == 1)); 60*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: top-level comparison in TEMP_FAILURE_RETRY 61*89a1d03eSRichard 62*89a1d03eSRichard #define ADDP_TFR(x) (1 + TEMP_FAILURE_RETRY((x)) + 1) 63*89a1d03eSRichard ADDP_TFR(foo()); 64*89a1d03eSRichard ADDP_TFR((foo() == 1)); 65*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: top-level comparison in TEMP_FAILURE_RETRY 66*89a1d03eSRichard 67*89a1d03eSRichard ADDP_TFR(bar(foo() == 1)); 68*89a1d03eSRichard ADDP_TFR((int)((bar(foo() == 1)) == 1)); 69*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: top-level comparison in TEMP_FAILURE_RETRY 70*89a1d03eSRichard 71*89a1d03eSRichard #define MACRO TEMP_FAILURE_RETRY(foo() == 1) 72*89a1d03eSRichard MACRO; 73*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: top-level comparison in TEMP_FAILURE_RETRY 74*89a1d03eSRichard 75*89a1d03eSRichard // Be sure that being a macro arg doesn't mess with this. 76*89a1d03eSRichard #define ID(x) (x) 77*89a1d03eSRichard ID(ADDP_TFR(bar(foo() == 1))); 78*89a1d03eSRichard ID(ADDP_TFR(bar(foo() == 1) == 1)); 79*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: top-level comparison in TEMP_FAILURE_RETRY 80*89a1d03eSRichard ID(MACRO); 81*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: top-level comparison in TEMP_FAILURE_RETRY 82*89a1d03eSRichard 83*89a1d03eSRichard #define CMP(x) x == 1 84*89a1d03eSRichard TEMP_FAILURE_RETRY(CMP(foo())); 85*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: top-level comparison in TEMP_FAILURE_RETRY 86*89a1d03eSRichard } 87*89a1d03eSRichard 88*89a1d03eSRichard // Be sure that it works inside of things like loops, if statements, etc. control_flow(void)89*89a1d03eSRichardvoid control_flow(void) { 90*89a1d03eSRichard do { 91*89a1d03eSRichard if (TEMP_FAILURE_RETRY(foo())) { 92*89a1d03eSRichard } 93*89a1d03eSRichard 94*89a1d03eSRichard if (TEMP_FAILURE_RETRY(foo() == 1)) { 95*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: top-level comparison in TEMP_FAILURE_RETRY 96*89a1d03eSRichard } 97*89a1d03eSRichard 98*89a1d03eSRichard if (TEMP_FAILURE_RETRY(bar(foo() == 1))) { 99*89a1d03eSRichard } 100*89a1d03eSRichard 101*89a1d03eSRichard if (TEMP_FAILURE_RETRY(bar(foo() == 1) == 1)) { 102*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:44: warning: top-level comparison in TEMP_FAILURE_RETRY 103*89a1d03eSRichard } 104*89a1d03eSRichard } while (TEMP_FAILURE_RETRY(foo() == 1)); 105*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:37: warning: top-level comparison in TEMP_FAILURE_RETRY 106*89a1d03eSRichard } 107*89a1d03eSRichard with_nondependent_variable_type(void)108*89a1d03eSRichardvoid with_nondependent_variable_type(void) { 109*89a1d03eSRichard #undef TEMP_FAILURE_RETRY 110*89a1d03eSRichard #define TEMP_FAILURE_RETRY(x) \ 111*89a1d03eSRichard ({ \ 112*89a1d03eSRichard long int __z; \ 113*89a1d03eSRichard do \ 114*89a1d03eSRichard __z = (x); \ 115*89a1d03eSRichard while (__z == -1); \ 116*89a1d03eSRichard __z; \ 117*89a1d03eSRichard }) 118*89a1d03eSRichard 119*89a1d03eSRichard TEMP_FAILURE_RETRY((foo())); 120*89a1d03eSRichard TEMP_FAILURE_RETRY((int)(foo() == 1)); 121*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: top-level comparison in TEMP_FAILURE_RETRY 122*89a1d03eSRichard TEMP_FAILURE_RETRY((bar(foo() == 1))); 123*89a1d03eSRichard TEMP_FAILURE_RETRY((int)((bar(foo() == 1)) == 1)); 124*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:46: warning: top-level comparison in TEMP_FAILURE_RETRY 125*89a1d03eSRichard } 126*89a1d03eSRichard 127*89a1d03eSRichard // I can't find a case where TEMP_FAILURE_RETRY is implemented like this, but if 128*89a1d03eSRichard // we can cheaply support it, I don't see why not. obscured_temp_failure_retry(void)129*89a1d03eSRichardvoid obscured_temp_failure_retry(void) { 130*89a1d03eSRichard #undef TEMP_FAILURE_RETRY 131*89a1d03eSRichard #define IMPL(x) \ 132*89a1d03eSRichard ({ \ 133*89a1d03eSRichard typeof(x) __z; \ 134*89a1d03eSRichard do \ 135*89a1d03eSRichard __z = (x); \ 136*89a1d03eSRichard while (__z == -1); \ 137*89a1d03eSRichard __z; \ 138*89a1d03eSRichard }) 139*89a1d03eSRichard 140*89a1d03eSRichard #define IMPL2(x) IMPL(x) 141*89a1d03eSRichard #define TEMP_FAILURE_RETRY(x) IMPL2(x) 142*89a1d03eSRichard TEMP_FAILURE_RETRY((foo())); 143*89a1d03eSRichard TEMP_FAILURE_RETRY((int)(foo() == 1)); 144*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: top-level comparison in TEMP_FAILURE_RETRY 145*89a1d03eSRichard TEMP_FAILURE_RETRY((bar(foo() == 1))); 146*89a1d03eSRichard TEMP_FAILURE_RETRY((int)((bar(foo() == 1)) == 1)); 147*89a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:46: warning: top-level comparison in TEMP_FAILURE_RETRY 148*89a1d03eSRichard } 149