expr_binary.c revision 1.8.2.1 1 1.8.2.1 perseant /* $NetBSD: expr_binary.c,v 1.8.2.1 2025/08/02 05:58:14 perseant Exp $ */
2 1.1 rillig # 3 "expr_binary.c"
3 1.1 rillig
4 1.1 rillig /*
5 1.4 rillig * Test binary operators.
6 1.1 rillig */
7 1.1 rillig
8 1.1 rillig /* lint1-only-if: lp64 */
9 1.7 rillig /* lint1-extra-flags: -X 351 */
10 1.1 rillig
11 1.1 rillig struct incompatible { /* just to generate the error message */
12 1.1 rillig int member;
13 1.1 rillig };
14 1.1 rillig void sink(struct incompatible);
15 1.1 rillig
16 1.4 rillig /*
17 1.4 rillig * Test the usual arithmetic conversions.
18 1.4 rillig *
19 1.4 rillig * C99 6.3.1.8 "Usual arithmetic conversions"
20 1.4 rillig */
21 1.1 rillig void
22 1.1 rillig cover_balance(void)
23 1.1 rillig {
24 1.6 rillig /* expect+1: ... 'pointer to void' ... */
25 1.4 rillig sink((void *)0 + 0);
26 1.4 rillig
27 1.6 rillig /* expect+1: ... 'pointer to void' ... */
28 1.4 rillig sink(0 + (void *)0);
29 1.4 rillig
30 1.6 rillig /* expect+1: ... 'int' ... */
31 1.4 rillig sink(1 + 1);
32 1.1 rillig
33 1.6 rillig /* expect+1: ... 'const int' ... */
34 1.4 rillig sink((const int)1 + (volatile int)1);
35 1.4 rillig
36 1.6 rillig /* expect+1: ... 'volatile int' ... */
37 1.4 rillig sink((volatile int)1 + (const int)1);
38 1.1 rillig
39 1.4 rillig long double _Complex cldbl = 0.0;
40 1.4 rillig double _Complex cdbl = 0.0;
41 1.4 rillig float _Complex cflt = 0.0f;
42 1.4 rillig /* expect+1: error: invalid type for _Complex [308] */
43 1.4 rillig _Complex invalid = 0.0;
44 1.4 rillig
45 1.6 rillig /* expect+1: ... 'long double _Complex' ... */
46 1.4 rillig sink(cldbl + 0);
47 1.6 rillig /* expect+1: ... 'long double _Complex' ... */
48 1.4 rillig sink(0 + cldbl);
49 1.6 rillig /* expect+1: ... 'long double _Complex' ... */
50 1.4 rillig sink(cldbl + cdbl);
51 1.6 rillig /* expect+1: ... 'long double _Complex' ... */
52 1.4 rillig sink(cdbl + cldbl);
53 1.4 rillig
54 1.6 rillig /* expect+1: ... 'double _Complex' ... */
55 1.4 rillig sink(cdbl + 0);
56 1.6 rillig /* expect+1: ... 'double _Complex' ... */
57 1.4 rillig sink(0 + cdbl);
58 1.6 rillig /* expect+1: ... 'double _Complex' ... */
59 1.4 rillig sink(cdbl + cflt);
60 1.6 rillig /* expect+1: ... 'double _Complex' ... */
61 1.4 rillig sink(cflt + cdbl);
62 1.4 rillig
63 1.6 rillig /* expect+1: ... 'float _Complex' ... */
64 1.4 rillig sink(cflt + 0);
65 1.6 rillig /* expect+1: ... 'float _Complex' ... */
66 1.4 rillig sink(0 + cflt);
67 1.6 rillig /* expect+1: ... 'float _Complex' ... */
68 1.4 rillig sink(cflt + (__uint128_t)0);
69 1.6 rillig /* expect+1: ... 'float _Complex' ... */
70 1.4 rillig sink((__uint128_t)0 + cflt);
71 1.4 rillig
72 1.4 rillig /*
73 1.4 rillig * The type specifier '_Complex' is only used during parsing, it does
74 1.4 rillig * not make it to the expression.
75 1.4 rillig */
76 1.6 rillig /* expect+1: ... 'double _Complex' ... */
77 1.4 rillig sink(invalid + 0);
78 1.4 rillig
79 1.6 rillig /* expect+1: ... 'long double' ... */
80 1.4 rillig sink(0.0L + 0);
81 1.6 rillig /* expect+1: ... 'long double' ... */
82 1.4 rillig sink(0 + 0.0L);
83 1.6 rillig /* expect+1: ... 'long double' ... */
84 1.4 rillig sink(0.0L + 0.0);
85 1.6 rillig /* expect+1: ... 'long double' ... */
86 1.4 rillig sink(0.0 + 0.0L);
87 1.1 rillig
88 1.6 rillig /* expect+1: ... 'double' ... */
89 1.4 rillig sink(0.0 + 0);
90 1.6 rillig /* expect+1: ... 'double' ... */
91 1.4 rillig sink(0 + 0.0);
92 1.6 rillig /* expect+1: ... 'double' ... */
93 1.4 rillig sink(0.0 + 0.0f);
94 1.6 rillig /* expect+1: ... 'double' ... */
95 1.4 rillig sink(0.0f + 0.0);
96 1.1 rillig
97 1.6 rillig /* expect+1: ... 'float' ... */
98 1.4 rillig sink(0.0f + 0);
99 1.6 rillig /* expect+1: ... 'float' ... */
100 1.4 rillig sink(0 + 0.0f);
101 1.6 rillig /* expect+1: ... 'float' ... */
102 1.4 rillig sink(0.0f + (__uint128_t)0);
103 1.6 rillig /* expect+1: ... 'float' ... */
104 1.4 rillig sink((__uint128_t)0 + 0.0f);
105 1.2 rillig
106 1.6 rillig /* expect+1: ... 'unsigned long long' ... */
107 1.4 rillig sink(0ULL + 0);
108 1.6 rillig /* expect+1: ... 'unsigned long long' ... */
109 1.4 rillig sink(0 + 0ULL);
110 1.4 rillig
111 1.6 rillig /* expect+1: ... 'unsigned long long' ... */
112 1.4 rillig sink(0ULL + 0LL);
113 1.6 rillig /* expect+1: ... 'unsigned long long' ... */
114 1.4 rillig sink(0LL + 0ULL);
115 1.4 rillig
116 1.4 rillig /* If the bit-width is the same, prefer the unsigned variant. */
117 1.6 rillig /* expect+1: ... 'unsigned long long' ... */
118 1.4 rillig sink(0UL + 0LL);
119 1.6 rillig /* expect+1: ... 'unsigned long long' ... */
120 1.4 rillig sink(0LL + 0UL);
121 1.5 rillig
122 1.5 rillig /*
123 1.5 rillig * Ensure that __int128_t is listed in the integer ranks. This table
124 1.5 rillig * only becomes relevant when both operands have the same width.
125 1.5 rillig */
126 1.6 rillig /* expect+1: ... '__uint128_t' ... */
127 1.5 rillig sink((__uint128_t)1 + (__int128_t)1);
128 1.6 rillig /* expect+1: ... '__uint128_t' ... */
129 1.5 rillig sink((__int128_t)1 + (__uint128_t)1);
130 1.1 rillig }
131 1.8 rillig
132 1.8 rillig struct point {
133 1.8 rillig int x, y;
134 1.8 rillig };
135 1.8 rillig
136 1.8.2.1 perseant static void
137 1.8.2.1 perseant return_void(void)
138 1.8.2.1 perseant {
139 1.8.2.1 perseant }
140 1.8.2.1 perseant
141 1.8.2.1 perseant static _Bool
142 1.8.2.1 perseant return_bool(void)
143 1.8.2.1 perseant {
144 1.8.2.1 perseant return sizeof(char) == 1;
145 1.8.2.1 perseant }
146 1.8.2.1 perseant
147 1.8 rillig static struct point
148 1.8.2.1 perseant return_sou(void)
149 1.8 rillig {
150 1.8 rillig return (struct point){ 0, 0 };
151 1.8 rillig }
152 1.8 rillig
153 1.8.2.1 perseant static int
154 1.8.2.1 perseant return_integer(void)
155 1.8 rillig {
156 1.8.2.1 perseant return 4;
157 1.8.2.1 perseant }
158 1.8.2.1 perseant
159 1.8.2.1 perseant static double
160 1.8.2.1 perseant return_floating(void)
161 1.8.2.1 perseant {
162 1.8.2.1 perseant return 3.5;
163 1.8.2.1 perseant }
164 1.8.2.1 perseant
165 1.8.2.1 perseant static char *
166 1.8.2.1 perseant return_pointer(void)
167 1.8.2.1 perseant {
168 1.8.2.1 perseant return (void *)0;
169 1.8 rillig }
170 1.8 rillig
171 1.8 rillig static inline void
172 1.8 rillig op_colon(_Bool cond)
173 1.8 rillig {
174 1.8.2.1 perseant cond ? return_void() : return_void();
175 1.8.2.1 perseant /* expect+1: warning: incompatible types 'void' and '_Bool' in conditional [126] */
176 1.8.2.1 perseant cond ? return_void() : return_bool();
177 1.8.2.1 perseant /* expect+1: warning: incompatible types 'void' and 'struct point' in conditional [126] */
178 1.8.2.1 perseant cond ? return_void() : return_sou();
179 1.8.2.1 perseant /* expect+1: warning: incompatible types 'void' and 'int' in conditional [126] */
180 1.8.2.1 perseant cond ? return_void() : return_integer();
181 1.8.2.1 perseant /* expect+1: warning: incompatible types 'void' and 'double' in conditional [126] */
182 1.8.2.1 perseant cond ? return_void() : return_floating();
183 1.8.2.1 perseant /* expect+1: warning: incompatible types 'void' and 'pointer to char' in conditional [126] */
184 1.8.2.1 perseant cond ? return_void() : return_pointer();
185 1.8.2.1 perseant /* expect+1: warning: incompatible types '_Bool' and 'void' in conditional [126] */
186 1.8.2.1 perseant cond ? return_bool() : return_void();
187 1.8.2.1 perseant cond ? return_bool() : return_bool();
188 1.8.2.1 perseant /* expect+1: error: incompatible types '_Bool' and 'struct point' in conditional [126] */
189 1.8.2.1 perseant cond ? return_bool() : return_sou();
190 1.8.2.1 perseant cond ? return_bool() : return_integer();
191 1.8.2.1 perseant cond ? return_bool() : return_floating();
192 1.8.2.1 perseant /* expect+1: warning: invalid combination of integer '_Bool' and pointer 'pointer to char', op ':' [123] */
193 1.8.2.1 perseant cond ? return_bool() : return_pointer();
194 1.8 rillig // FIXME: GCC doesn't warn, as the 'type mismatch' is not wrong.
195 1.8 rillig /* expect+1: warning: incompatible types 'struct point' and 'void' in conditional [126] */
196 1.8.2.1 perseant cond ? return_sou() : return_void();
197 1.8.2.1 perseant /* expect+1: error: incompatible types 'struct point' and '_Bool' in conditional [126] */
198 1.8.2.1 perseant cond ? return_sou() : return_bool();
199 1.8.2.1 perseant cond ? return_sou() : return_sou();
200 1.8.2.1 perseant /* expect+1: error: incompatible types 'struct point' and 'int' in conditional [126] */
201 1.8.2.1 perseant cond ? return_sou() : return_integer();
202 1.8.2.1 perseant /* expect+1: error: incompatible types 'struct point' and 'double' in conditional [126] */
203 1.8.2.1 perseant cond ? return_sou() : return_floating();
204 1.8.2.1 perseant /* expect+1: error: incompatible types 'struct point' and 'pointer to char' in conditional [126] */
205 1.8.2.1 perseant cond ? return_sou() : return_pointer();
206 1.8.2.1 perseant /* expect+1: warning: incompatible types 'int' and 'void' in conditional [126] */
207 1.8.2.1 perseant cond ? return_integer() : return_void();
208 1.8.2.1 perseant cond ? return_integer() : return_bool();
209 1.8.2.1 perseant /* expect+1: error: incompatible types 'int' and 'struct point' in conditional [126] */
210 1.8.2.1 perseant cond ? return_integer() : return_sou();
211 1.8.2.1 perseant cond ? return_integer() : return_integer();
212 1.8.2.1 perseant cond ? return_integer() : return_floating();
213 1.8.2.1 perseant /* expect+1: warning: invalid combination of integer 'int' and pointer 'pointer to char', op ':' [123] */
214 1.8.2.1 perseant cond ? return_integer() : return_pointer();
215 1.8.2.1 perseant /* expect+1: warning: incompatible types 'double' and 'void' in conditional [126] */
216 1.8.2.1 perseant cond ? return_floating() : return_void();
217 1.8.2.1 perseant cond ? return_floating() : return_bool();
218 1.8.2.1 perseant /* expect+1: error: incompatible types 'double' and 'struct point' in conditional [126] */
219 1.8.2.1 perseant cond ? return_floating() : return_sou();
220 1.8.2.1 perseant cond ? return_floating() : return_integer();
221 1.8.2.1 perseant cond ? return_floating() : return_floating();
222 1.8.2.1 perseant /* expect+1: error: incompatible types 'double' and 'pointer to char' in conditional [126] */
223 1.8.2.1 perseant cond ? return_floating() : return_pointer();
224 1.8.2.1 perseant /* expect+1: warning: incompatible types 'pointer to char' and 'void' in conditional [126] */
225 1.8.2.1 perseant cond ? return_pointer() : return_void();
226 1.8.2.1 perseant /* expect+1: warning: invalid combination of pointer 'pointer to char' and integer '_Bool', op ':' [123] */
227 1.8.2.1 perseant cond ? return_pointer() : return_bool();
228 1.8.2.1 perseant /* expect+1: error: incompatible types 'pointer to char' and 'struct point' in conditional [126] */
229 1.8.2.1 perseant cond ? return_pointer() : return_sou();
230 1.8.2.1 perseant /* expect+1: warning: invalid combination of pointer 'pointer to char' and integer 'int', op ':' [123] */
231 1.8.2.1 perseant cond ? return_pointer() : return_integer();
232 1.8.2.1 perseant /* expect+1: error: incompatible types 'pointer to char' and 'double' in conditional [126] */
233 1.8.2.1 perseant cond ? return_pointer() : return_floating();
234 1.8.2.1 perseant cond ? return_pointer() : return_pointer();
235 1.8 rillig }
236