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