Home | History | Annotate | Line # | Download | only in lint1
c11_generic_expression.c revision 1.9
      1  1.9  rillig /*	$NetBSD: c11_generic_expression.c,v 1.9 2021/08/01 13:09:38 rillig Exp $	*/
      2  1.1  rillig # 3 "c11_generic_expression.c"
      3  1.1  rillig 
      4  1.1  rillig /*
      5  1.1  rillig  * C99 added support for type-generic macros, but these were limited to the
      6  1.1  rillig  * header <tgmath.h>.  C11 made this feature generally available.
      7  1.1  rillig  *
      8  1.1  rillig  * The generic selection is typically used with macros, but since lint1 works
      9  1.1  rillig  * on the preprocessed source, the test cases look a bit strange.
     10  1.1  rillig  *
     11  1.1  rillig  * C99 6.5.1.1 "Generic selection"
     12  1.1  rillig  */
     13  1.1  rillig 
     14  1.1  rillig /* lint1-extra-flags: -Ac11 */
     15  1.1  rillig 
     16  1.1  rillig /*
     17  1.1  rillig  * The type of 'var' is not compatible with any of the types from the
     18  1.1  rillig  * generic-association.  This is a compile-time error.
     19  1.1  rillig  */
     20  1.1  rillig const char *
     21  1.2  rillig classify_type_without_default(double var)
     22  1.1  rillig {
     23  1.3  rillig 	/* expect-2: argument 'var' unused */
     24  1.3  rillig 
     25  1.1  rillig 	return _Generic(var,
     26  1.1  rillig 	    long double: "long double",
     27  1.1  rillig 	    long long: "long long",
     28  1.1  rillig 	    unsigned: "unsigned"
     29  1.1  rillig 	);
     30  1.3  rillig 	/* expect-1: expects to return value [214] */
     31  1.1  rillig }
     32  1.1  rillig 
     33  1.1  rillig /*
     34  1.1  rillig  * In this case, the 'default' expression is selected.
     35  1.1  rillig  */
     36  1.1  rillig const char *
     37  1.2  rillig classify_type_with_default(double var)
     38  1.1  rillig {
     39  1.3  rillig 	/* expect-2: argument 'var' unused */
     40  1.3  rillig 
     41  1.1  rillig 	return _Generic(var,
     42  1.1  rillig 	    long double: "long double",
     43  1.1  rillig 	    long long: "long long",
     44  1.1  rillig 	    unsigned: "unsigned",
     45  1.1  rillig 	    default: "unknown"
     46  1.1  rillig 	);
     47  1.1  rillig }
     48  1.2  rillig 
     49  1.2  rillig /*
     50  1.2  rillig  * The type of a _Generic expression is the one from the selected association.
     51  1.2  rillig  */
     52  1.2  rillig const char *
     53  1.2  rillig classify_char(char c)
     54  1.2  rillig {
     55  1.3  rillig 	/* expect-2: argument 'c' unused */
     56  1.3  rillig 
     57  1.2  rillig 	return _Generic(c,
     58  1.2  rillig 	    char: "yes",
     59  1.2  rillig 	    default: 0.0
     60  1.2  rillig 	);
     61  1.2  rillig }
     62  1.4  rillig 
     63  1.4  rillig /*
     64  1.4  rillig  * Before cgram.y 1.238 from 2021-06-27, lint accepted a comma-expression,
     65  1.4  rillig  * which looked as if _Generic would accept multiple arguments before the
     66  1.4  rillig  * selection.
     67  1.4  rillig  */
     68  1.4  rillig /* ARGSUSED */
     69  1.4  rillig const int *
     70  1.4  rillig comma_expression(char first, double second)
     71  1.4  rillig {
     72  1.5  rillig 	return _Generic(first, second,	/* expect: syntax error 'second' */
     73  1.4  rillig 	    char: "first",
     74  1.4  rillig 	    double: 2.0
     75  1.4  rillig 	);
     76  1.5  rillig 	/* expect+1: without returning value [217] */
     77  1.4  rillig }
     78  1.6  rillig 
     79  1.6  rillig /*
     80  1.6  rillig  * Ensure that assignment-expressions are accepted by the grammar, as
     81  1.6  rillig  * opposed to comma-expressions.
     82  1.6  rillig  */
     83  1.6  rillig /* ARGSUSED */
     84  1.6  rillig int
     85  1.6  rillig assignment_expression(int first, int second)
     86  1.6  rillig {
     87  1.6  rillig 	return _Generic(first = second,
     88  1.6  rillig 	    int: second = first
     89  1.6  rillig 	);
     90  1.6  rillig }
     91  1.7  rillig 
     92  1.7  rillig int
     93  1.7  rillig primary_expression(void)
     94  1.7  rillig {
     95  1.7  rillig 	return _Generic(0, int: assignment_expression)(0, 0);
     96  1.7  rillig }
     97  1.9  rillig 
     98  1.9  rillig /*
     99  1.9  rillig  * The types don't match, therefore build_generic_selection returns NULL,
    100  1.9  rillig  * which is then silently ignored by init_expr.  This situation is already
    101  1.9  rillig  * covered by the compilers, so there is no need for lint to double-check it.
    102  1.9  rillig  */
    103  1.9  rillig const char *x = _Generic(
    104  1.9  rillig     (__uint128_t)1 + 1.0f,
    105  1.9  rillig     int: 1
    106  1.9  rillig );
    107