@@ -140,7 +140,7 @@ struct quals_matter { // c17-note {{previous definition is here}}
140140};
141141
142142struct quals_matter { // c17-error {{redefinition of 'quals_matter'}} \
143- c23-error {{type 'struct quals_matter' has incompatible definitions}}
143+ c23-error {{type 'struct quals_matter' has incompatible definitions}}
144144 const int x ; // c23-note {{field 'x' has type 'const int' here}}
145145};
146146
@@ -359,3 +359,45 @@ struct alignment { // c17-error {{redefinition of 'alignment'}} \
359359 c23-error {{type 'struct alignment' has a member with an attribute which currently causes the types to be treated as though they are incompatible}}
360360 int x ;
361361};
362+
363+ // Both structures need to have a tag in order to be compatible within the same
364+ // translation unit.
365+ struct {int i ;} nontag ;
366+ struct tag {int i ;} tagged ; // c17-note 2 {{previous definition is here}}
367+
368+ _Static_assert (1 == _Generic(tagged , struct tag {int i ;}:1 , default :0 )); // c17-error {{redefinition of 'tag'}} \
369+ c17-error {{static assertion failed}}
370+ _Static_assert (0 == _Generic(tagged , struct {int i ;}:1 , default :0 ));
371+ _Static_assert (0 == _Generic(nontag , struct tag {int i ;}:1 , default :0 )); // c17-error {{redefinition of 'tag'}}
372+ // That means these two structures are not actually compatible; see GH141724.
373+ _Static_assert (0 == _Generic(nontag , struct {int i ;}:1 , default :0 ));
374+
375+ // Also test the behavior within a function (so the declaration context is not
376+ // at the translation unit level).
377+ void nontag_func_test (void ) {
378+ struct { int i ; } test ;
379+ _Static_assert (0 == _Generic(test , struct { int i ; } : 1 , default : 0 ));
380+ }
381+
382+ // Same kind of test, but this time for a declaration in the parameter list.
383+ void nontag_param_test (struct { int i ; } herp ) {
384+ _Static_assert (0 == _Generic(herp , struct { int i ; } : 1 , default : 0 ));
385+ }
386+
387+ // Same kind of test, but demonstrating that these still aren't compatible.
388+ void nontag_both_in_params (struct { int i ; } Arg1 , struct { int i ; } Arg2 ) {
389+ _Static_assert (0 == _Generic(__typeof__ (Arg1 ), __typeof__ (Arg2 ) : 1 , default : 0 )); // both-warning {{passing a type argument as the first operand to '_Generic' is a C2y extension}}
390+ }
391+
392+ struct InnerAnonStruct {
393+ struct {
394+ int i ;
395+ } untagged ;
396+ } inner_anon_tagged ;
397+
398+ _Static_assert (0 == _Generic(inner_anon_tagged .untagged , struct { int i ; } : 1 , default : 0 ));
399+
400+ // Test the same thing with enumerations (test for unions is omitted because
401+ // unions and structures are both RecordDecl objects, whereas EnumDecl is not).
402+ enum { E_Untagged1 } nontag_enum ; // both-note {{previous definition is here}}
403+ _Static_assert (0 == _Generic(nontag_enum , enum { E_Untagged1 } : 1 , default : 0 )); // both-error {{redefinition of enumerator 'E_Untagged1'}}
0 commit comments