1*313458bcSrillig /* $NetBSD: expr_precedence.c,v 1.12 2024/05/01 07:40:11 rillig Exp $ */
260f9e3d3Srillig # 3 "expr_precedence.c"
360f9e3d3Srillig
460f9e3d3Srillig /*
560f9e3d3Srillig * Tests for the precedence among operators.
660f9e3d3Srillig */
760f9e3d3Srillig
8b2baa501Srillig /* lint1-extra-flags: -X 351 */
9b2baa501Srillig
1060f9e3d3Srillig int var;
1160f9e3d3Srillig
1260f9e3d3Srillig /*
1360f9e3d3Srillig * An initializer needs an assignment-expression; the comma must be
1460f9e3d3Srillig * interpreted as a separator, not an operator.
1560f9e3d3Srillig */
1660f9e3d3Srillig /* expect+1: error: syntax error '4' [249] */
1760f9e3d3Srillig int init_error = 3, 4;
1860f9e3d3Srillig
1960f9e3d3Srillig /* expect+1: error: non-constant initializer [177] */
2060f9e3d3Srillig int init_syntactically_ok = var = 1 ? 2 : 3;
2160f9e3d3Srillig
2260f9e3d3Srillig /*
23*313458bcSrillig * The arguments of __attribute__ must be constant-expression, but for
24*313458bcSrillig * simplicity of implementation, they are parsed just like function arguments,
25*313458bcSrillig * even though this allows assignment-expression.
2660f9e3d3Srillig */
2760f9e3d3Srillig void __attribute__((format(printf,
284c2e2660Srillig /*
294c2e2660Srillig * Inside of __attribute__((...)), symbol lookup works differently. For
304c2e2660Srillig * example, 'printf' is a keyword, and since all arguments to
314c2e2660Srillig * __attribute__ are constant expressions, looking up global variables
324c2e2660Srillig * would not make sense. Therefore, 'var' is undefined.
334c2e2660Srillig *
34512bf5dcSrillig * See lex.c, function 'search', keyword 'in_gcc_attribute'.
354c2e2660Srillig */
3660f9e3d3Srillig var = 1,
3760f9e3d3Srillig /* Syntactically ok, must be a constant expression though. */
3860f9e3d3Srillig var > 0 ? 2 : 1)))
3960f9e3d3Srillig my_printf(const char *, ...);
40036149f3Srillig
41036149f3Srillig void
assignment_associativity(int arg)42036149f3Srillig assignment_associativity(int arg)
43036149f3Srillig {
44036149f3Srillig int left, right;
45036149f3Srillig
4651b2be3cSrillig /*
4751b2be3cSrillig * Assignments are right-associative. If they were left-associative,
4851b2be3cSrillig * the result of (left = right) would be an rvalue, resulting in this
4951b2be3cSrillig * error message: 'left operand of '=' must be lvalue [114]'.
5051b2be3cSrillig */
51036149f3Srillig left = right = arg;
52036149f3Srillig
53036149f3Srillig left = arg;
54036149f3Srillig }
553120116eSrillig
563120116eSrillig void
conditional_associativity(_Bool cond1,_Bool cond2,int a,int b,int c)573120116eSrillig conditional_associativity(_Bool cond1, _Bool cond2, int a, int b, int c)
583120116eSrillig {
593120116eSrillig /* The then-expression can be an arbitrary expression. */
603120116eSrillig var = cond1 ? cond2 ? a : b : c;
613120116eSrillig var = cond1 ? (cond2 ? a : b) : c;
623120116eSrillig
633120116eSrillig /* The then-expression can even be a comma-expression. */
643120116eSrillig var = cond1 ? cond2 ? a, b : (b, a) : c;
653120116eSrillig
663120116eSrillig var = cond1 ? a : cond2 ? b : c;
673120116eSrillig /*
683120116eSrillig * In almost all programming languages, '?:' is right-associative,
693120116eSrillig * which allows for easy chaining.
703120116eSrillig */
713120116eSrillig var = cond1 ? a : (cond2 ? b : c);
723120116eSrillig /*
733120116eSrillig * In PHP, '?:' is left-associative, which is rather surprising and
743120116eSrillig * requires more parentheses to get the desired effect.
753120116eSrillig */
763120116eSrillig var = (cond1 ? a : cond2) ? b : c;
773120116eSrillig }
78