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