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