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