Home | History | Annotate | Line # | Download | only in lint1
      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))
     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
     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