@@ -401,3 +401,77 @@ _Static_assert(0 == _Generic(inner_anon_tagged.untagged, struct { int i; } : 1,
401
401
// unions and structures are both RecordDecl objects, whereas EnumDecl is not).
402
402
enum { E_Untagged1 } nontag_enum ; // both-note {{previous definition is here}}
403
403
_Static_assert (0 == _Generic(nontag_enum , enum { E_Untagged1 } : 1 , default : 0 )); // both-error {{redefinition of enumerator 'E_Untagged1'}}
404
+
405
+ // Test that enumerations with mixed underlying types are properly handled.
406
+ enum GH150594_E1 : int { GH150594_Val1 };
407
+ enum GH150594_E2 : int { GH150594_Val2 };
408
+ enum GH150594_E3 { GH150594_Val3 };
409
+ enum GH150594_E4 : int { GH150594_Val4 };
410
+ void GH150594 (void ) {
411
+ extern enum GH150594_E1 Fn1 (void ); // both-note {{previous declaration is here}}
412
+ extern enum GH150594_E2 Fn2 (void ); // c17-note {{previous declaration is here}}
413
+ extern enum GH150594_E3 Fn3 (void ); // both-note {{previous declaration is here}}
414
+ extern enum GH150594_E4 Fn4 (void ); // both-note {{previous declaration is here}}
415
+ enum GH150594_E1 { GH150594_Val1 };
416
+ enum GH150594_E2 : int { GH150594_Val2 };
417
+ enum GH150594_E3 : int { GH150594_Val3 };
418
+ enum GH150594_E4 : short { GH150594_Val4 };
419
+ extern enum GH150594_E1 Fn1 (void ); // both-error {{conflicting types for 'Fn1'}}
420
+ extern enum GH150594_E2 Fn2 (void ); // c17-error {{conflicting types for 'Fn2'}}
421
+ extern enum GH150594_E3 Fn3 (void ); // both-error {{conflicting types for 'Fn3'}}
422
+ extern enum GH150594_E4 Fn4 (void ); // both-error {{conflicting types for 'Fn4'}}
423
+
424
+ // Show that two declarations in the same scope give expected diagnostics.
425
+ enum E1 { e1 }; // both-note {{previous declaration is here}}
426
+ enum E1 : int { e1 }; // both-error {{enumeration previously declared with nonfixed underlying type}}
427
+
428
+ enum E2 : int { e2 }; // both-note {{previous declaration is here}}
429
+ enum E2 { e2 }; // both-error {{enumeration previously declared with fixed underlying type}}
430
+
431
+ enum E3 : int { e3 }; // both-note {{previous declaration is here}}
432
+ enum E3 : short { e3 }; // both-error {{enumeration redeclared with different underlying type 'short' (was 'int')}}
433
+
434
+ typedef short foo ;
435
+ enum E4 : foo { e4 }; // c17-note 2 {{previous definition is here}}
436
+ enum E4 : short { e4 }; // c17-error {{redefinition of 'E4'}} \
437
+ c17-error {{redefinition of enumerator 'e4'}}
438
+
439
+ enum E5 : foo { e5 }; // both-note {{previous declaration is here}}
440
+ enum E5 : int { e5 }; // both-error {{enumeration redeclared with different underlying type 'int' (was 'foo' (aka 'short'))}}
441
+ }
442
+
443
+ // Test that enumerations are compatible with their underlying type, but still
444
+ // diagnose when "same type" is required rather than merely "compatible type".
445
+ enum E1 : int { e1 }; // Fixed underlying type
446
+ enum E2 { e2 }; // Unfixed underlying type, defaults to int or unsigned int
447
+
448
+ struct GH149965_1 { int h ; };
449
+ // This typeof trick is used to get the underlying type of the enumeration in a
450
+ // platform agnostic way.
451
+ struct GH149965_2 { __typeof__ (+ (enum E2 ){}) h ; };
452
+ void gh149965 (void ) {
453
+ extern struct GH149965_1 x1 ; // c17-note {{previous declaration is here}}
454
+ extern struct GH149965_2 x2 ; // c17-note {{previous declaration is here}}
455
+
456
+ // Both the structure and the variable declarations are fine because only a
457
+ // compatible type is required, not the same type, because the structures are
458
+ // declared in different scopes.
459
+ struct GH149965_1 { enum E1 h ; };
460
+ struct GH149965_2 { enum E2 h ; };
461
+
462
+ extern struct GH149965_1 x1 ; // c17-error {{redeclaration of 'x1'}}
463
+ extern struct GH149965_2 x2 ; // c17-error {{redeclaration of 'x2'}}
464
+
465
+ // However, in the same scope, the same type is required, not just compatible
466
+ // types.
467
+ // FIXME: this should be an error in both C17 and C23 mode.
468
+ struct GH149965_3 { int h ; }; // c17-note {{previous definition is here}}
469
+ struct GH149965_3 { enum E1 h ; }; // c17-error {{redefinition of 'GH149965_3'}}
470
+
471
+ // For Clang, the composite type after declaration merging is the enumeration
472
+ // type rather than an integer type.
473
+ enum E1 * eptr ;
474
+ [[maybe_unused ]] __typeof__ (x1 .h ) * ptr = eptr ;
475
+ enum E2 * eptr2 ;
476
+ [[maybe_unused ]] __typeof__ (x2 .h ) * ptr2 = eptr2 ;
477
+ }
0 commit comments