xref: /netbsd/tests/usr.bin/xlint/lint1/expr_binary.c (revision 5b5d646f)
1 /*	$NetBSD: expr_binary.c,v 1.8 2023/07/14 08:53:52 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
cover_balance(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 struct point
returning_struct(void)137 returning_struct(void)
138 {
139 	return (struct point){ 0, 0 };
140 }
141 
142 static void
returning_void(void)143 returning_void(void)
144 {
145 }
146 
147 static inline void
op_colon(_Bool cond)148 op_colon(_Bool cond)
149 {
150 	// FIXME: GCC doesn't warn, as the 'type mismatch' is not wrong.
151 	/* expect+1: warning: incompatible types 'struct point' and 'void' in conditional [126] */
152 	cond ? returning_struct() : returning_void();
153 
154 	// TODO: Test the other combinations as well.
155 	// |         | void | bool | arith | sou | int | flt | ptr | nullptr |
156 	// |---------|------|------|-------|-----|-----|-----|-----|---------|
157 	// | void    | ok   |      |       |     |     |     |     |         |
158 	// | bool    |      | ok   |       |     |     |     |     |         |
159 	// | arith   |      |      | ok    |     |     |     |     |         |
160 	// | sou     |      |      |       | ok  |     |     |     |         |
161 	// | int     |      |      |       |     |     |     | ok  |         |
162 	// | flt     |      |      |       |     |     |     |     |         |
163 	// | ptr     |      |      |       |     | ok  |     |     | ok      |
164 	// | nullptr |      |      |       |     |     |     | ok  |         |
165 }
166