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