1*7cdb3475Srillig /* $NetBSD: c11_generic_expression.c,v 1.11 2022/01/15 14:22:03 rillig Exp $ */ 21a74119aSrillig # 3 "c11_generic_expression.c" 31a74119aSrillig 41a74119aSrillig /* 51a74119aSrillig * C99 added support for type-generic macros, but these were limited to the 61a74119aSrillig * header <tgmath.h>. C11 made this feature generally available. 71a74119aSrillig * 81a74119aSrillig * The generic selection is typically used with macros, but since lint1 works 91a74119aSrillig * on the preprocessed source, the test cases look a bit strange. 101a74119aSrillig * 111a74119aSrillig * C99 6.5.1.1 "Generic selection" 121a74119aSrillig */ 131a74119aSrillig 141a74119aSrillig /* lint1-extra-flags: -Ac11 */ 151a74119aSrillig 161a74119aSrillig /* 171a74119aSrillig * The type of 'var' is not compatible with any of the types from the 181a74119aSrillig * generic-association. This is a compile-time error. 191a74119aSrillig */ 201a74119aSrillig const char * 21925438b6Srillig classify_type_without_default(double var) 221a74119aSrillig { 239db77d62Srillig /* expect-2: argument 'var' unused */ 249db77d62Srillig 251a74119aSrillig return _Generic(var, 261a74119aSrillig long double: "long double", 271a74119aSrillig long long: "long long", 281a74119aSrillig unsigned: "unsigned" 291a74119aSrillig ); 309db77d62Srillig /* expect-1: expects to return value [214] */ 311a74119aSrillig } 321a74119aSrillig 331a74119aSrillig /* 341a74119aSrillig * In this case, the 'default' expression is selected. 351a74119aSrillig */ 361a74119aSrillig const char * 37925438b6Srillig classify_type_with_default(double var) 381a74119aSrillig { 399db77d62Srillig /* expect-2: argument 'var' unused */ 409db77d62Srillig 411a74119aSrillig return _Generic(var, 421a74119aSrillig long double: "long double", 431a74119aSrillig long long: "long long", 441a74119aSrillig unsigned: "unsigned", 451a74119aSrillig default: "unknown" 461a74119aSrillig ); 471a74119aSrillig } 48925438b6Srillig 49925438b6Srillig /* 50925438b6Srillig * The type of a _Generic expression is the one from the selected association. 51925438b6Srillig */ 52925438b6Srillig const char * 53925438b6Srillig classify_char(char c) 54925438b6Srillig { 559db77d62Srillig /* expect-2: argument 'c' unused */ 569db77d62Srillig 57925438b6Srillig return _Generic(c, 58925438b6Srillig char: "yes", 59925438b6Srillig default: 0.0 60925438b6Srillig ); 61925438b6Srillig } 62518e17a2Srillig 63518e17a2Srillig /* 64518e17a2Srillig * Before cgram.y 1.238 from 2021-06-27, lint accepted a comma-expression, 65518e17a2Srillig * which looked as if _Generic would accept multiple arguments before the 66518e17a2Srillig * selection. 67518e17a2Srillig */ 68518e17a2Srillig /* ARGSUSED */ 69518e17a2Srillig const int * 70518e17a2Srillig comma_expression(char first, double second) 71518e17a2Srillig { 72*7cdb3475Srillig /* expect+1: error: syntax error 'second' [249] */ 73*7cdb3475Srillig return _Generic(first, second, 74518e17a2Srillig char: "first", 75518e17a2Srillig double: 2.0 76518e17a2Srillig ); 77c5e4f21dSrillig /* expect+1: without returning value [217] */ 78518e17a2Srillig } 796e36a2b9Srillig 806e36a2b9Srillig /* 816e36a2b9Srillig * Ensure that assignment-expressions are accepted by the grammar, as 826e36a2b9Srillig * opposed to comma-expressions. 836e36a2b9Srillig */ 846e36a2b9Srillig /* ARGSUSED */ 856e36a2b9Srillig int 866e36a2b9Srillig assignment_expression(int first, int second) 876e36a2b9Srillig { 886e36a2b9Srillig return _Generic(first = second, 896e36a2b9Srillig int: second = first 906e36a2b9Srillig ); 916e36a2b9Srillig } 920f733df6Srillig 930f733df6Srillig int 940f733df6Srillig primary_expression(void) 950f733df6Srillig { 960f733df6Srillig return _Generic(0, int: assignment_expression)(0, 0); 970f733df6Srillig } 988f1fb703Srillig 998f1fb703Srillig /* 1008f1fb703Srillig * The types don't match, therefore build_generic_selection returns NULL, 1018f1fb703Srillig * which is then silently ignored by init_expr. This situation is already 1028f1fb703Srillig * covered by the compilers, so there is no need for lint to double-check it. 1038f1fb703Srillig */ 1048f1fb703Srillig const char *x = _Generic( 105dd2691b0Srillig 1ULL + 1.0f, 1068f1fb703Srillig int: 1 1078f1fb703Srillig ); 108