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