xref: /netbsd-src/tests/usr.bin/xlint/lint1/c11_generic_expression.c (revision 122b5006ee1bd67145794b4cde92f4fe4781a5ec)
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