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