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