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