xref: /netbsd-src/tests/usr.bin/xlint/lint1/gcc_attribute.c (revision 7d62b00eb9ad855ffcd7da46b41e23feb5476fac)
1 /*	$NetBSD: gcc_attribute.c,v 1.12 2022/08/25 19:03:48 rillig Exp $	*/
2 # 3 "gcc_attribute.c"
3 
4 /*
5  * Tests for the various attributes for functions, types, statements that are
6  * provided by GCC.
7  *
8  * https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html
9  */
10 
11 void __attribute__((noinline))
12 do_not_inline(void)
13 {
14 }
15 
16 /* All pointer arguments must be nonnull. */
17 void __attribute__((nonnull))
18 function_nonnull(void *, const void *, int);
19 
20 /*
21  * The documentation suggests that the argument list of nonnull be nonempty,
22  * but GCC 9.3.0 accepts an empty list as well, treating all parameters as
23  * nonnull.
24  */
25 void __attribute__((nonnull()))
26 function_nonnull_list(void *, const void *, int);
27 
28 /* Arguments 1 and 2 must be nonnull. */
29 void __attribute__((nonnull(1, 2)))
30 function_nonnull_list(void *, const void *, int);
31 
32 /*
33  * Unknown attributes are skipped, as lint does not have a list of all known
34  * GCC attributes.
35  */
36 void __attribute__((unknown_attribute))
37 function_with_unknown_attribute(void);
38 
39 /*
40  * There is an attribute called 'pcs', but that attribute must not prevent an
41  * ordinary variable from being named the same.  Starting with scan.l 1.77
42  * from 2017-01-07, that variable name generated a syntax error.  Fixed in
43  * lex.c 1.33 from 2021-05-03.
44  *
45  * Seen in yds.c, function yds_allocate_slots.
46  */
47 int
48 local_variable_pcs(void)
49 {
50 	int pcs = 3;
51 	return pcs;
52 }
53 
54 /*
55  * FIXME: The attributes are handled by different grammar rules even though
56  *  they occur in the same syntactical position.
57  *
58  * Grammar rule abstract_decl_param_list handles the first attribute.
59  *
60  * Grammar rule direct_abstract_declarator handles all remaining attributes.
61  *
62  * Since abstract_decl_param_list contains type_attribute_opt, this could be
63  * the source of the many shift/reduce conflicts in the grammar.
64  */
65 int
66 func(
67     int(int)
68     __attribute__((__noreturn__))
69     __attribute__((__noreturn__))
70 );
71 
72 /*
73  * https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html says that the
74  * attribute-list is a "possibly empty comma-separated sequence of
75  * attributes".
76  *
77  * No matter whether this particular example is interpreted as an empty list
78  * or a list containing a single empty attribute, the result is the same in
79  * both cases.
80  */
81 void one_empty_attribute(void)
82     __attribute__((/* none */));
83 
84 /*
85  * https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html further says that
86  * each individual attribute may be "Empty. Empty attributes are ignored".
87  */
88 void two_empty_attributes(void)
89     __attribute__((/* none */, /* still none */));
90 
91 /*
92  * Ensure that __attribute__ can be specified everywhere in a declaration.
93  * This is the simplest possible requirement that covers all valid code.
94  * It accepts invalid code as well, but these cases are covered by GCC and
95  * Clang already.
96  *
97  * Since lint only parses the attributes but doesn't really relate them to
98  * identifiers or other entities, ensuring that valid code can be parsed is
99  * enough for now.
100  *
101  * To really associate __attribute__ with the corresponding entity, the
102  * grammar needs to be rewritten, see the example with __noreturn__ above.
103  */
104 __attribute__((deprecated("d1")))
105 const
106 __attribute__((deprecated("d2")))
107 int
108 __attribute__((deprecated("d3")))
109 *
110 // The below line would produce a syntax error.
111 // __attribute__((deprecated("d3")))
112 const
113 __attribute__((deprecated("d4")))
114 identifier
115 __attribute__((deprecated("d5")))
116 (
117     __attribute__((deprecated("d6")))
118     void
119     __attribute__((deprecated("d7")))
120     )
121     __attribute__((deprecated("d8")))
122 ;
123 
124 /*
125  * The attribute 'const' provides stronger guarantees than 'pure', and
126  * 'volatile' is not defined.  To keep the grammar simple, any T_QUAL is
127  * allowed at this point, but only syntactically.
128  */
129 int const_function(int) __attribute__((const));
130 /* cover 'gcc_attribute_spec: T_QUAL' */
131 /* expect+1: error: syntax error 'volatile' [249] */
132 int volatile_function(int) __attribute__((volatile));
133