@@ -140,7 +140,7 @@ struct quals_matter { // c17-note {{previous definition is here}}
140
140
};
141
141
142
142
struct 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}}
144
144
const int x ; // c23-note {{field 'x' has type 'const int' here}}
145
145
};
146
146
@@ -359,3 +359,45 @@ struct alignment { // c17-error {{redefinition of 'alignment'}} \
359
359
c23-error {{type 'struct alignment' has a member with an attribute which currently causes the types to be treated as though they are incompatible}}
360
360
int x ;
361
361
};
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