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