135 lines
3.9 KiB
C
135 lines
3.9 KiB
C
/* $NetBSD: gcc_attribute.c,v 1.13 2023/03/28 14:44:34 rillig Exp $ */
|
|
# 3 "gcc_attribute.c"
|
|
|
|
/*
|
|
* Tests for the various attributes for functions, types, statements that are
|
|
* provided by GCC.
|
|
*
|
|
* https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html
|
|
*/
|
|
|
|
/* lint1-extra-flags: -X 351 */
|
|
|
|
void __attribute__((noinline))
|
|
do_not_inline(void)
|
|
{
|
|
}
|
|
|
|
/* All pointer arguments must be nonnull. */
|
|
void __attribute__((nonnull))
|
|
function_nonnull(void *, const void *, int);
|
|
|
|
/*
|
|
* The documentation suggests that the argument list of nonnull be nonempty,
|
|
* but GCC 9.3.0 accepts an empty list as well, treating all parameters as
|
|
* nonnull.
|
|
*/
|
|
void __attribute__((nonnull()))
|
|
function_nonnull_list(void *, const void *, int);
|
|
|
|
/* Arguments 1 and 2 must be nonnull. */
|
|
void __attribute__((nonnull(1, 2)))
|
|
function_nonnull_list(void *, const void *, int);
|
|
|
|
/*
|
|
* Unknown attributes are skipped, as lint does not have a list of all known
|
|
* GCC attributes.
|
|
*/
|
|
void __attribute__((unknown_attribute))
|
|
function_with_unknown_attribute(void);
|
|
|
|
/*
|
|
* There is an attribute called 'pcs', but that attribute must not prevent an
|
|
* ordinary variable from being named the same. Starting with scan.l 1.77
|
|
* from 2017-01-07, that variable name generated a syntax error. Fixed in
|
|
* lex.c 1.33 from 2021-05-03.
|
|
*
|
|
* Seen in yds.c, function yds_allocate_slots.
|
|
*/
|
|
int
|
|
local_variable_pcs(void)
|
|
{
|
|
int pcs = 3;
|
|
return pcs;
|
|
}
|
|
|
|
/*
|
|
* FIXME: The attributes are handled by different grammar rules even though
|
|
* they occur in the same syntactical position.
|
|
*
|
|
* Grammar rule abstract_decl_param_list handles the first attribute.
|
|
*
|
|
* Grammar rule direct_abstract_declarator handles all remaining attributes.
|
|
*
|
|
* Since abstract_decl_param_list contains type_attribute_opt, this could be
|
|
* the source of the many shift/reduce conflicts in the grammar.
|
|
*/
|
|
int
|
|
func(
|
|
int(int)
|
|
__attribute__((__noreturn__))
|
|
__attribute__((__noreturn__))
|
|
);
|
|
|
|
/*
|
|
* https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html says that the
|
|
* attribute-list is a "possibly empty comma-separated sequence of
|
|
* attributes".
|
|
*
|
|
* No matter whether this particular example is interpreted as an empty list
|
|
* or a list containing a single empty attribute, the result is the same in
|
|
* both cases.
|
|
*/
|
|
void one_empty_attribute(void)
|
|
__attribute__((/* none */));
|
|
|
|
/*
|
|
* https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html further says that
|
|
* each individual attribute may be "Empty. Empty attributes are ignored".
|
|
*/
|
|
void two_empty_attributes(void)
|
|
__attribute__((/* none */, /* still none */));
|
|
|
|
/*
|
|
* Ensure that __attribute__ can be specified everywhere in a declaration.
|
|
* This is the simplest possible requirement that covers all valid code.
|
|
* It accepts invalid code as well, but these cases are covered by GCC and
|
|
* Clang already.
|
|
*
|
|
* Since lint only parses the attributes but doesn't really relate them to
|
|
* identifiers or other entities, ensuring that valid code can be parsed is
|
|
* enough for now.
|
|
*
|
|
* To really associate __attribute__ with the corresponding entity, the
|
|
* grammar needs to be rewritten, see the example with __noreturn__ above.
|
|
*/
|
|
__attribute__((deprecated("d1")))
|
|
const
|
|
__attribute__((deprecated("d2")))
|
|
int
|
|
__attribute__((deprecated("d3")))
|
|
*
|
|
// The below line would produce a syntax error.
|
|
// __attribute__((deprecated("d3")))
|
|
const
|
|
__attribute__((deprecated("d4")))
|
|
identifier
|
|
__attribute__((deprecated("d5")))
|
|
(
|
|
__attribute__((deprecated("d6")))
|
|
void
|
|
__attribute__((deprecated("d7")))
|
|
)
|
|
__attribute__((deprecated("d8")))
|
|
;
|
|
|
|
/*
|
|
* The attribute 'const' provides stronger guarantees than 'pure', and
|
|
* 'volatile' is not defined. To keep the grammar simple, any T_QUAL is
|
|
* allowed at this point, but only syntactically.
|
|
*/
|
|
int const_function(int) __attribute__((const));
|
|
/* cover 'gcc_attribute_spec: T_QUAL' */
|
|
/* expect+1: error: syntax error 'volatile' [249] */
|
|
int volatile_function(int) __attribute__((volatile));
|