1/* $NetBSD: lsym_lparen_or_lbracket.c,v 1.19 2023/06/17 22:09:24 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//indent input
148int zero = (((((((((((((((((((0)))))))))))))))))));
149int many = ((((((((((((((((((((((((((((((((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){0, 0};
198
199	/* GCC statement expression */
200	/* expr = ({if(expr)debug();expr;}); */
201}
202//indent end
203
204
205/*
206 * Test a few variants of C99 compound expressions, as the '{' and '}' must not
207 * be treated as block delimiters.
208 */
209//indent input
210{
211	return (struct point){0, 0};
212	return (struct point){
213		0, 0
214	};
215	return (struct point){.x = 0, .y = 0};
216	return (struct point){
217		.x = 0,
218		.y = 0,
219	};
220}
221//indent end
222
223//indent run-equals-input
224
225
226/*
227 * C99 designator initializers are the rare situation where there is a space
228 * before a '['.
229 */
230//indent input
231int array[] = {
232	1, 2, [2] = 3, [3] = 4,
233};
234//indent end
235
236//indent run-equals-input -di0
237
238
239/*
240 * Test want_blank_before_lparen for all possible token types.
241 */
242//indent input
243void cover_want_blank_before_lparen(void)
244{
245	/* ps.prev_lsym can never be 'newline'. */
246	int newline =
247	(3);
248
249	int lparen_or_lbracket = a[(3)];
250	int rparen_or_rbracket = a[3](5);
251	+(unary_op);
252	3 + (binary_op);
253	a++(postfix_op);	/* unlikely to be seen in practice */
254	cond ? (question) : (5);
255	switch (expr) {
256	case (case_label):;
257	}
258	a ? 3 : (colon);
259	(semicolon) = 3;
260	int lbrace[] = {(3)};
261	int rbrace_in_decl = {{3}(4)};	/* syntax error */
262	{}
263	(rbrace_in_stmt)();
264	ident(3);
265	int(decl);
266	a++, (comma)();
267	int comment = /* comment */ (3);	/* comment is skipped */
268	switch (expr) {}
269#define preprocessing
270	(preprocessing)();
271	(lsym_form_feed)();
272	for(;;);
273	do(lsym_do)=3;while(0);
274	if(cond);else(lsym_else)();
275	do(lsym_do);while(0);
276	str.(member);		/* syntax error */
277	L("string_prefix");		/* impossible */
278	static (int)storage_class;	/* syntax error */
279	funcname(3);
280	typedef (type_def) new_type;
281	// $ TODO: is keyword_struct_union_enum possible?
282	struct (keyword_struct_union_enum);	/* syntax error */
283}
284//indent end
285
286//indent run -ldi0
287void
288cover_want_blank_before_lparen(void)
289{
290	/* ps.prev_lsym can never be 'newline'. */
291	int newline =
292		(3);
293
294	int lparen_or_lbracket = a[(3)];
295	int rparen_or_rbracket = a[3](5);
296	+(unary_op);
297	3 + (binary_op);
298	a++(postfix_op);	/* unlikely to be seen in practice */
299	cond ? (question) : (5);
300	switch (expr) {
301	case (case_label): ;
302	}
303	a ? 3 : (colon);
304	(semicolon) = 3;
305	int lbrace[] = {(3)};
306	int rbrace_in_decl = {{3} (4)};	/* syntax error */
307	{
308	}
309	(rbrace_in_stmt)();
310	ident(3);
311	int (decl);
312	a++, (comma)();
313	int comment = /* comment */ (3);	/* comment is skipped */
314	switch (expr) {
315	}
316#define preprocessing
317	(preprocessing)();
318	(lsym_form_feed)();
319	for (;;);
320	do
321		(lsym_do) = 3;
322	while (0);
323	if (cond);
324	else
325		(lsym_else)();
326	do
327		(lsym_do);
328	while (0);
329	str.(member);		/* syntax error */
330	L("string_prefix");	/* impossible */
331	static (int)storage_class;	/* syntax error */
332	funcname(3);
333	typedef (type_def) new_type;
334	struct (keyword_struct_union_enum);	/* syntax error */
335}
336//indent end
337
338/* See t_errors.sh, test case 'compound_literal'. */
339
340
341/*
342 * Ensure that a designated initializer after a comma is not indented further
343 * than necessary, as in most other contexts, there is no space before a '['.
344 */
345//indent input
346int arr[] = {
347['0'] = 1,
348['1'] = 2,
349};
350//indent end
351
352//indent run -di0
353int arr[] = {
354	['0'] = 1,
355	['1'] = 2,
356};
357//indent end
358
359
360/* In an initializer, a '(' does not start a function definition. */
361//indent input
362{
363type var = {
364.CONCAT(a, b)
365= init,
366};
367}
368
369//indent end
370
371//indent run
372{
373	type		var = {
374		.CONCAT(a, b)
375		= init,
376	};
377}
378//indent end
379