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
12int foo(void);
13int bar(int a);
14
15void test(void) {
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.
89void control_flow(void) {
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
108void with_nondependent_variable_type(void) {
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.
129void obscured_temp_failure_retry(void) {
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

source code of clang-tools-extra/test/clang-tidy/checkers/android/comparison-in-temp-failure-retry.c