xref: /netbsd-src/tests/usr.bin/xlint/lint1/c11_generic_expression.c (revision fe7ce87087f280c6ec3a05c8e6c372792bed4a2a)
1*fe7ce870Srillig /*	$NetBSD: c11_generic_expression.c,v 1.19 2023/08/06 19:44:50 rillig Exp $	*/
2f1f9bbffSrillig # 3 "c11_generic_expression.c"
3f1f9bbffSrillig 
4e6298b92Srillig /* lint1-extra-flags: -X 351 */
5e6298b92Srillig 
6f1f9bbffSrillig /*
7f1f9bbffSrillig  * C99 added support for type-generic macros, but these were limited to the
8f1f9bbffSrillig  * header <tgmath.h>.  C11 made this feature generally available.
9f1f9bbffSrillig  *
10f1f9bbffSrillig  * The generic selection is typically used with macros, but since lint1 works
11f1f9bbffSrillig  * on the preprocessed source, the test cases look a bit strange.
12f1f9bbffSrillig  *
13ce38ef24Srillig  * C11 6.5.1.1 "Generic selection"
14f1f9bbffSrillig  */
15f1f9bbffSrillig 
16a9b749ceSrillig /* lint1-extra-flags: -Ac11 */
17f1f9bbffSrillig 
18f1f9bbffSrillig /*
19f1f9bbffSrillig  * The type of 'var' is not compatible with any of the types from the
20*fe7ce870Srillig  * generic-association.  This is a constraint violation that the compiler must
21*fe7ce870Srillig  * detect, therefore lint doesn't repeat that diagnostic.
22f1f9bbffSrillig  */
23f1f9bbffSrillig const char *
classify_type_without_default(double var)24806e4bc5Srillig classify_type_without_default(double var)
25f1f9bbffSrillig {
26ea332265Srillig 	/* expect-2: warning: parameter 'var' unused in function 'classify_type_without_default' [231] */
27bd01cfcfSrillig 
28f1f9bbffSrillig 	return _Generic(var,
29f1f9bbffSrillig 	    long double: "long double",
30f1f9bbffSrillig 	    long long: "long long",
31f1f9bbffSrillig 	    unsigned: "unsigned"
32f1f9bbffSrillig 	);
33*fe7ce870Srillig 	/* expect-1: error: function 'classify_type_without_default' expects to return value [214] */
34f1f9bbffSrillig }
35f1f9bbffSrillig 
36f1f9bbffSrillig /*
37f1f9bbffSrillig  * In this case, the 'default' expression is selected.
38f1f9bbffSrillig  */
39f1f9bbffSrillig const char *
classify_type_with_default(double var)40806e4bc5Srillig classify_type_with_default(double var)
41f1f9bbffSrillig {
42ea332265Srillig 	/* expect-2: warning: parameter 'var' unused in function 'classify_type_with_default' [231] */
43bd01cfcfSrillig 
44f1f9bbffSrillig 	return _Generic(var,
45f1f9bbffSrillig 	    long double: "long double",
46f1f9bbffSrillig 	    long long: "long long",
47f1f9bbffSrillig 	    unsigned: "unsigned",
48f1f9bbffSrillig 	    default: "unknown"
49f1f9bbffSrillig 	);
50f1f9bbffSrillig }
51806e4bc5Srillig 
52806e4bc5Srillig /*
53806e4bc5Srillig  * The type of a _Generic expression is the one from the selected association.
54806e4bc5Srillig  */
55806e4bc5Srillig const char *
classify_char(char c)56806e4bc5Srillig classify_char(char c)
57806e4bc5Srillig {
58ea332265Srillig 	/* expect-2: warning: parameter 'c' unused in function 'classify_char' [231] */
59bd01cfcfSrillig 
60806e4bc5Srillig 	return _Generic(c,
61806e4bc5Srillig 	    char: "yes",
62806e4bc5Srillig 	    default: 0.0
63806e4bc5Srillig 	);
64806e4bc5Srillig }
65d4e4f03cSrillig 
66d4e4f03cSrillig /*
67d4e4f03cSrillig  * Before cgram.y 1.238 from 2021-06-27, lint accepted a comma-expression,
68d4e4f03cSrillig  * which looked as if _Generic would accept multiple arguments before the
69d4e4f03cSrillig  * selection.
70d4e4f03cSrillig  */
71d4e4f03cSrillig /* ARGSUSED */
72d4e4f03cSrillig const int *
comma_expression(char first,double second)73d4e4f03cSrillig comma_expression(char first, double second)
74d4e4f03cSrillig {
75a4a927acSrillig 	/* expect+1: error: syntax error 'second' [249] */
76a4a927acSrillig 	return _Generic(first, second,
77d4e4f03cSrillig 	    char: "first",
78d4e4f03cSrillig 	    double: 2.0
79d4e4f03cSrillig 	);
8040a9b8fdSrillig 	/* expect+1: warning: function 'comma_expression' falls off bottom without returning value [217] */
81d4e4f03cSrillig }
824610aed7Srillig 
834610aed7Srillig /*
844610aed7Srillig  * Ensure that assignment-expressions are accepted by the grammar, as
854610aed7Srillig  * opposed to comma-expressions.
864610aed7Srillig  */
874610aed7Srillig /* ARGSUSED */
884610aed7Srillig int
assignment_expression(int first,int second)894610aed7Srillig assignment_expression(int first, int second)
904610aed7Srillig {
914610aed7Srillig 	return _Generic(first = second,
924610aed7Srillig 	    int: second = first
934610aed7Srillig 	);
944610aed7Srillig }
95cf6cc874Srillig 
96cf6cc874Srillig int
primary_expression(void)97cf6cc874Srillig primary_expression(void)
98cf6cc874Srillig {
99cf6cc874Srillig 	return _Generic(0, int: assignment_expression)(0, 0);
100cf6cc874Srillig }
1017b590daaSrillig 
1027b590daaSrillig /*
1037b590daaSrillig  * The types don't match, therefore build_generic_selection returns NULL,
1047b590daaSrillig  * which is then silently ignored by init_expr.  This situation is already
1057b590daaSrillig  * covered by the compilers, so there is no need for lint to double-check it.
1067b590daaSrillig  */
1077b590daaSrillig const char *x = _Generic(
10801fc44edSrillig     1ULL + 1.0f,
1097b590daaSrillig     int: 1
1107b590daaSrillig );
111