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