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