lsym_lparen_or_lbracket.c revision 1.6
1/* $NetBSD: lsym_lparen_or_lbracket.c,v 1.6 2022/04/24 08:48:17 rillig Exp $ */
2
3/*
4 * Tests for the token lsym_lparen_or_lbracket, which represents a '(' or '['
5 * in these contexts:
6 *
7 * In a type name, '(' constructs a function type.
8 *
9 * In an expression, '(' starts an inner expression to override the usual
10 * operator precedence.
11 *
12 * In a function call expression, '(' marks the beginning of the function
13 * arguments.
14 *
15 * In a 'sizeof' expression, '(' is required if the argument is a type name.
16 *
17 * In an expression, '(' followed by a type name starts a cast expression or
18 * a compound literal.
19 *
20 * In a type declaration, '(' marks the beginning of the function parameters.
21 *
22 * After one of the keywords 'for', 'if', 'switch' or 'while', the controlling
23 * expression must be enclosed in '(' and ')'; see lsym_for.c, lsym_if.c,
24 * lsym_switch.c, lsym_while.c.
25 *
26 * In a declaration, '[' derives an array type.
27 *
28 * In an expression, '[' starts an array subscript.
29 */
30
31/* The '(' in a type name derives a function type. */
32#indent input
33typedef void signal_handler(int);
34void (*signal(void (*)(int)))(int);
35#indent end
36
37#indent run
38typedef void signal_handler(int);
39void		(*signal(void (*)(int)))(int);
40#indent end
41
42
43#indent input
44#define macro(arg) ((arg) + 1)
45#indent end
46
47#indent run-equals-input -di0
48
49
50/*
51 * The '(' in an expression overrides operator precedence.  In multi-line
52 * expressions, the continuation lines are aligned on the parentheses.
53 */
54#indent input
55int nested = (
56	(
57		(
58			(
59				1 + 4
60			)
61		)
62	)
63);
64#indent end
65
66#indent run
67int		nested = (
68			  (
69			   (
70			    (
71			     1 + 4
72			     )
73			    )
74			   )
75);
76#indent end
77
78
79/* The '(' in a function call expression starts the argument list. */
80#indent input
81int var = macro_call ( arg1,  arg2  ,arg3);
82#indent end
83
84#indent run
85int		var = macro_call(arg1, arg2, arg3);
86#indent end
87
88
89/*
90 * The '(' in a sizeof expression is required for type names and optional for
91 * expressions.
92 */
93#indent input
94size_t sizeof_typename = sizeof ( int );
95size_t sizeof_expr = sizeof ( 12345 ) ;
96#indent end
97
98#indent run
99size_t		sizeof_typename = sizeof(int);
100size_t		sizeof_expr = sizeof(12345);
101#indent end
102
103
104/* The '[' in a type name derives an array type. */
105#indent input
106int array_of_numbers[100];
107#indent end
108
109#indent run
110int		array_of_numbers[100];
111#indent end
112
113
114/* The '[' in an expression accesses an array element. */
115#indent input
116int second_prime = &primes[1];
117#indent end
118
119#indent run
120int		second_prime = &primes[1];
121#indent end
122
123
124#indent input
125void
126function(void)
127{
128	/* Type casts */
129	a = (int)b;
130	a = (struct tag)b;
131	/* TODO: The '(int)' is not a type cast, it is a prototype list. */
132	a = (int (*)(int))fn;
133
134	/* Not type casts */
135	a = sizeof(int) * 2;
136	a = sizeof(5) * 2;
137	a = offsetof(struct stat, st_mtime);
138
139	/* Grouping subexpressions */
140	a = ((((b + c)))) * d;
141}
142#indent end
143
144#indent run-equals-input
145
146
147/* This is the maximum supported number of parentheses. */
148#indent input
149int zero = (((((((((((((((((((0)))))))))))))))))));
150#indent end
151
152#indent run-equals-input -di0
153
154
155#indent input
156void (*action)(void);
157#indent end
158
159#indent run-equals-input -di0
160
161
162#indent input
163void
164function(void)
165{
166    other_function();
167    other_function("first", 2, "last argument"[4]);
168
169    if (false)(void)x;
170    if (false)(func)(arg);
171    if (false)(cond)?123:456;
172
173    /* C99 compound literal */
174    origin = (struct point){0,0};
175
176    /* GCC statement expression */
177    /* expr = ({if(expr)debug();expr;}); */
178/* $ XXX: Generates 'error: Standard Input:36: Unbalanced parentheses'. */
179}
180#indent end
181
182#indent run
183void
184function(void)
185{
186	other_function();
187	other_function("first", 2, "last argument"[4]);
188
189	if (false)
190		(void)x;
191	if (false)
192		(func)(arg);
193	if (false)
194		(cond) ? 123 : 456;
195
196	/* C99 compound literal */
197	origin = (struct point){
198		0, 0
199	};
200
201	/* GCC statement expression */
202	/* expr = ({if(expr)debug();expr;}); */
203}
204#indent end
205
206
207/*
208 * C99 designator initializers are the rare situation where there is a space
209 * before a '['.
210 */
211#indent input
212int array[] = {
213	1, 2, [2] = 3, [3] = 4,
214};
215#indent end
216
217#indent run-equals-input -di0
218
219
220/*
221 * Test want_blank_before_lparen for all possible token types.
222 */
223#indent input
224void cover_want_blank_before_lparen(void)
225{
226	/* ps.prev_token can never be 'newline'. */
227	int newline =
228	(3);
229
230	int lparen_or_lbracket = a[(3)];
231	int rparen_or_rbracket = a[3](5);
232	+(unary_op);
233	3 + (binary_op);
234	a++(postfix_op);	/* unlikely to be seen in practice */
235	cond ? (question) : (5);
236	switch (expr) {
237	case (case_label):;
238	}
239	a ? 3 : (colon);
240	(semicolon) = 3;
241	int lbrace[] = {(3)};
242	int rbrace_in_decl = {{3}(4)};	/* syntax error */
243	{}
244	(rbrace_in_stmt)();
245	ident(3);
246	int(decl);
247	a++, (comma)();
248	int comment = /* comment */ (3);	/* comment is skipped */
249	switch (expr) {}
250#define preprocessing
251	(preprocessing)();
252	/* $ XXX: lsym_form_feed should be skipped, just as newline. */
253	(lsym_form_feed)();	/* XXX: should be skipped */
254	for(;;);
255	do(lsym_do)=3;while(0);
256	if(cond);else(lsym_else)();
257	do(lsym_do);while(0);
258	str.(member);		/* syntax error */
259	L("string_prefix");		/* impossible */
260	static (int)storage_class;	/* syntax error */
261	funcname(3);
262	typedef (type_def) new_type;
263	// $ TODO: is keyword_struct_union_enum possible?
264	struct (keyword_struct_union_enum);	/* syntax error */
265}
266#indent end
267
268#indent run -ldi0
269void
270cover_want_blank_before_lparen(void)
271{
272	/* ps.prev_token can never be 'newline'. */
273	int newline =
274	(3);
275
276	int lparen_or_lbracket = a[(3)];
277	int rparen_or_rbracket = a[3](5);
278	+(unary_op);
279	3 + (binary_op);
280	a++ (postfix_op);	/* unlikely to be seen in practice */
281	cond ? (question) : (5);
282	switch (expr) {
283	case (case_label):;
284	}
285	a ? 3 : (colon);
286	(semicolon) = 3;
287	int lbrace[] = {(3)};
288	int rbrace_in_decl = {{3} (4)};	/* syntax error */
289	{
290	}
291	(rbrace_in_stmt)();
292	ident(3);
293	int (decl);
294	a++, (comma)();
295	int comment = /* comment */ (3);	/* comment is skipped */
296	switch (expr) {
297	}
298#define preprocessing
299	(preprocessing)();
300
301/* $ XXX: Where has the '\f' gone? It should have been preserved. */
302	(lsym_form_feed)();	/* XXX: should be skipped */
303	for (;;);
304	do
305		(lsym_do) = 3;
306	while (0);
307	if (cond);
308	else
309		(lsym_else)();
310	do
311		(lsym_do);
312	while (0);
313	str.(member);		/* syntax error */
314	L("string_prefix");	/* impossible */
315	static (int)storage_class;	/* syntax error */
316	funcname(3);
317	typedef (type_def) new_type;
318	struct (keyword_struct_union_enum);	/* syntax error */
319}
320#indent end
321
322/* See t_errors.sh, test case 'compound_literal'. */
323