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