1 /* $NetBSD: expr_precedence.c,v 1.12 2024/05/01 07:40:11 rillig Exp $ */
2 # 3 "expr_precedence.c"
3
4 /*
5 * Tests for the precedence among operators.
6 */
7
8 /* lint1-extra-flags: -X 351 */
9
10 int var;
11
12 /*
13 * An initializer needs an assignment-expression; the comma must be
14 * interpreted as a separator, not an operator.
15 */
16 /* expect+1: error: syntax error '4' [249] */
17 int init_error = 3, 4;
18
19 /* expect+1: error: non-constant initializer [177] */
20 int init_syntactically_ok = var = 1 ? 2 : 3;
21
22 /*
23 * The arguments of __attribute__ must be constant-expression, but for
24 * simplicity of implementation, they are parsed just like function arguments,
25 * even though this allows assignment-expression.
26 */
27 void __attribute__((format(printf,
28 /*
29 * Inside of __attribute__((...)), symbol lookup works differently. For
30 * example, 'printf' is a keyword, and since all arguments to
31 * __attribute__ are constant expressions, looking up global variables
32 * would not make sense. Therefore, 'var' is undefined.
33 *
34 * See lex.c, function 'search', keyword 'in_gcc_attribute'.
35 */
36 var = 1,
37 /* Syntactically ok, must be a constant expression though. */
38 var > 0 ? 2 : 1)))
39 my_printf(const char *, ...);
40
41 void
assignment_associativity(int arg)42 assignment_associativity(int arg)
43 {
44 int left, right;
45
46 /*
47 * Assignments are right-associative. If they were left-associative,
48 * the result of (left = right) would be an rvalue, resulting in this
49 * error message: 'left operand of '=' must be lvalue [114]'.
50 */
51 left = right = arg;
52
53 left = arg;
54 }
55
56 void
conditional_associativity(_Bool cond1,_Bool cond2,int a,int b,int c)57 conditional_associativity(_Bool cond1, _Bool cond2, int a, int b, int c)
58 {
59 /* The then-expression can be an arbitrary expression. */
60 var = cond1 ? cond2 ? a : b : c;
61 var = cond1 ? (cond2 ? a : b) : c;
62
63 /* The then-expression can even be a comma-expression. */
64 var = cond1 ? cond2 ? a, b : (b, a) : c;
65
66 var = cond1 ? a : cond2 ? b : c;
67 /*
68 * In almost all programming languages, '?:' is right-associative,
69 * which allows for easy chaining.
70 */
71 var = cond1 ? a : (cond2 ? b : c);
72 /*
73 * In PHP, '?:' is left-associative, which is rather surprising and
74 * requires more parentheses to get the desired effect.
75 */
76 var = (cond1 ? a : cond2) ? b : c;
77 }
78