gcc_attribute_var.c revision 1.12
11.12Srillig/*	$NetBSD: gcc_attribute_var.c,v 1.12 2024/09/28 11:20:29 rillig Exp $	*/
21.1Srillig# 3 "gcc_attribute_var.c"
31.1Srillig
41.1Srillig/*
51.1Srillig * Tests for the GCC __attribute__ for variables.
61.1Srillig *
71.1Srillig * https://gcc.gnu.org/onlinedocs/gcc/Variable-Attributes.html
81.1Srillig */
91.1Srillig
101.8Srillig/* lint1-extra-flags: -X 351 */
111.8Srillig
121.1Srilligvoid
131.1Srilligwrite_to_page(unsigned index, char ch)
141.1Srillig{
151.1Srillig	static char page[4096]
161.1Srillig	    __attribute__((__aligned__(4096)));
171.1Srillig
181.1Srillig	page[index] = ch;
191.1Srillig}
201.1Srillig
211.1Srilligvoid
221.1Srilligplacement(
231.1Srillig    __attribute__((__deprecated__)) int before,
241.1Srillig    int __attribute__((__deprecated__)) between,
251.1Srillig    int after __attribute__((__deprecated__))
261.1Srillig);
271.1Srillig
281.2Srilligvoid println(void);
291.2Srillig
301.2Srillig/*
311.2Srillig * Since cgram.y 1.294 from 2021-07-10, lint did not accept declarations that
321.2Srillig * started with __attribute__, due to a newly and accidentally introduced
331.2Srillig * shift/reduce conflict in the grammar.
341.2Srillig *
351.2Srillig * A GCC extension allows statement of the form __attribute__((fallthrough)),
361.2Srillig * thus starting with __attribute__.  This is the 'shift' in the conflict.
371.2Srillig * The 'reduce' in the conflict was begin_type.
381.2Srillig *
391.2Srillig * Before cgram 1.294, the gcc_attribute was placed outside the pair of
401.2Srillig * begin_type/end_type, exactly to resolve this conflict.
411.2Srillig *
421.2Srillig * Conceptually, it made sense to put the __attribute__((unused)) between
431.2Srillig * begin_type and end_type, to make it part of the declaration-specifiers.
441.2Srillig * This change introduced the hidden conflict though.
451.2Srillig *
461.2Srillig * Interestingly, the number of shift/reduce conflicts did not change in
471.2Srillig * cgram 1.294, the conflicts were just resolved differently than before.
481.2Srillig *
491.2Srillig * To prevent this from happening again, make sure that declarations as well
501.2Srillig * as statements can start with gcc_attribute.
511.2Srillig */
521.2Srilligvoid
531.2Srilligambiguity_for_attribute(void)
541.2Srillig{
551.9Srillig	/* expect+1: warning: 'var1' unused in function 'ambiguity_for_attribute' [192] */
561.2Srillig	__attribute__((unused)) _Bool var1;
571.2Srillig
581.2Srillig	switch (1) {
591.2Srillig	case 1:
601.2Srillig		println();
611.3Srillig		/* expect+1: warning: 'var2' unused in function 'ambiguity_for_attribute' [192] */
621.2Srillig		__attribute__((unused)) _Bool var2;
631.2Srillig		__attribute__((fallthrough));
641.2Srillig		case 2:
651.2Srillig			println();
661.2Srillig	}
671.2Srillig}
681.2Srillig
691.4Srilligvoid
701.4Srilligattribute_after_array_brackets(
711.4Srillig    const char *argv[] __attribute__((__unused__))
721.4Srillig)
731.4Srillig{
741.4Srillig}
751.10Srillig
761.10Srilligstruct attribute_in_member_declaration {
771.10Srillig	int __attribute__(())
781.10Srillig	    x __attribute__(()),
791.10Srillig	    y __attribute__(());
801.10Srillig
811.10Srillig	unsigned int __attribute__(())
821.10Srillig	    bit1:1 __attribute__(()),
831.10Srillig	    bit2:2 __attribute__(()),
841.10Srillig	    bit3:3 __attribute__(());
851.10Srillig};
861.12Srillig
871.12Srillig
881.12Srilligvoid
891.12Srilliganonymous_members(void)
901.12Srillig{
911.12Srillig	struct single_attribute_outer {
921.12Srillig		struct single_attribute_inner {
931.12Srillig			int member;
941.12Srillig		} __attribute__(());
951.12Srillig	} __attribute__(());
961.12Srillig
971.12Srillig	struct multiple_attributes_outer {
981.12Srillig		struct multiple_attributes_inner {
991.12Srillig			int member;
1001.12Srillig		} __attribute__(()) __attribute__(());
1011.12Srillig	} __attribute__(()) __attribute__(());
1021.12Srillig}
103