diff options
Diffstat (limited to 'clang/test/C')
-rw-r--r-- | clang/test/C/C23/n3037.c | 74 | ||||
-rw-r--r-- | clang/test/C/C2y/n3353.c | 11 |
2 files changed, 80 insertions, 5 deletions
diff --git a/clang/test/C/C23/n3037.c b/clang/test/C/C23/n3037.c index ce6f4c4..3748375 100644 --- a/clang/test/C/C23/n3037.c +++ b/clang/test/C/C23/n3037.c @@ -401,3 +401,77 @@ _Static_assert(0 == _Generic(inner_anon_tagged.untagged, struct { int i; } : 1, // unions and structures are both RecordDecl objects, whereas EnumDecl is not). enum { E_Untagged1 } nontag_enum; // both-note {{previous definition is here}} _Static_assert(0 == _Generic(nontag_enum, enum { E_Untagged1 } : 1, default : 0)); // both-error {{redefinition of enumerator 'E_Untagged1'}} + +// Test that enumerations with mixed underlying types are properly handled. +enum GH150594_E1 : int { GH150594_Val1 }; +enum GH150594_E2 : int { GH150594_Val2 }; +enum GH150594_E3 { GH150594_Val3 }; +enum GH150594_E4 : int { GH150594_Val4 }; +void GH150594(void) { + extern enum GH150594_E1 Fn1(void); // both-note {{previous declaration is here}} + extern enum GH150594_E2 Fn2(void); // c17-note {{previous declaration is here}} + extern enum GH150594_E3 Fn3(void); // both-note {{previous declaration is here}} + extern enum GH150594_E4 Fn4(void); // both-note {{previous declaration is here}} + enum GH150594_E1 { GH150594_Val1 }; + enum GH150594_E2 : int { GH150594_Val2 }; + enum GH150594_E3 : int { GH150594_Val3 }; + enum GH150594_E4 : short { GH150594_Val4 }; + extern enum GH150594_E1 Fn1(void); // both-error {{conflicting types for 'Fn1'}} + extern enum GH150594_E2 Fn2(void); // c17-error {{conflicting types for 'Fn2'}} + extern enum GH150594_E3 Fn3(void); // both-error {{conflicting types for 'Fn3'}} + extern enum GH150594_E4 Fn4(void); // both-error {{conflicting types for 'Fn4'}} + + // Show that two declarations in the same scope give expected diagnostics. + enum E1 { e1 }; // both-note {{previous declaration is here}} + enum E1 : int { e1 }; // both-error {{enumeration previously declared with nonfixed underlying type}} + + enum E2 : int { e2 }; // both-note {{previous declaration is here}} + enum E2 { e2 }; // both-error {{enumeration previously declared with fixed underlying type}} + + enum E3 : int { e3 }; // both-note {{previous declaration is here}} + enum E3 : short { e3 }; // both-error {{enumeration redeclared with different underlying type 'short' (was 'int')}} + + typedef short foo; + enum E4 : foo { e4 }; // c17-note 2 {{previous definition is here}} + enum E4 : short { e4 }; // c17-error {{redefinition of 'E4'}} \ + c17-error {{redefinition of enumerator 'e4'}} + + enum E5 : foo { e5 }; // both-note {{previous declaration is here}} + enum E5 : int { e5 }; // both-error {{enumeration redeclared with different underlying type 'int' (was 'foo' (aka 'short'))}} +} + +// Test that enumerations are compatible with their underlying type, but still +// diagnose when "same type" is required rather than merely "compatible type". +enum E1 : int { e1 }; // Fixed underlying type +enum E2 { e2 }; // Unfixed underlying type, defaults to int or unsigned int + +struct GH149965_1 { int h; }; +// This typeof trick is used to get the underlying type of the enumeration in a +// platform agnostic way. +struct GH149965_2 { __typeof__(+(enum E2){}) h; }; +void gh149965(void) { + extern struct GH149965_1 x1; // c17-note {{previous declaration is here}} + extern struct GH149965_2 x2; // c17-note {{previous declaration is here}} + + // Both the structure and the variable declarations are fine because only a + // compatible type is required, not the same type, because the structures are + // declared in different scopes. + struct GH149965_1 { enum E1 h; }; + struct GH149965_2 { enum E2 h; }; + + extern struct GH149965_1 x1; // c17-error {{redeclaration of 'x1'}} + extern struct GH149965_2 x2; // c17-error {{redeclaration of 'x2'}} + + // However, in the same scope, the same type is required, not just compatible + // types. + // FIXME: this should be an error in both C17 and C23 mode. + struct GH149965_3 { int h; }; // c17-note {{previous definition is here}} + struct GH149965_3 { enum E1 h; }; // c17-error {{redefinition of 'GH149965_3'}} + + // For Clang, the composite type after declaration merging is the enumeration + // type rather than an integer type. + enum E1 *eptr; + [[maybe_unused]] __typeof__(x1.h) *ptr = eptr; + enum E2 *eptr2; + [[maybe_unused]] __typeof__(x2.h) *ptr2 = eptr2; +} diff --git a/clang/test/C/C2y/n3353.c b/clang/test/C/C2y/n3353.c index cd61cbf..a2e08cf 100644 --- a/clang/test/C/C2y/n3353.c +++ b/clang/test/C/C2y/n3353.c @@ -44,7 +44,12 @@ static const void *ptr = 0o0; /* ext-warning {{octal integer literals are a C2y #endif // 0 by itself is not deprecated, of course. -int k = 0; +int k1 = 0; +unsigned int k2 = 0u; +long k3 = 0l; +unsigned long k4 = 0ul; +long long k5 = 0ll; +unsigned long long k6 = 0ull; // Test a preprocessor use of 0 by itself, which is also not deprecated. #if 0 @@ -65,7 +70,6 @@ static_assert(__extension__ _Generic(typeof(l), const int : 1, default : 0)); // // Note that 0o by itself is an invalid literal. int m = 0o; /* expected-error {{invalid suffix 'o' on integer constant}} - c2y-warning {{octal literals without a '0o' prefix are deprecated}} */ // Ensure negation works as expected. @@ -83,13 +87,11 @@ int n = 0o18; /* expected-error {{invalid digit '8' in octal constant}} cpp-warning {{octal integer literals are a Clang extension}} */ int o1 = 0o8; /* expected-error {{invalid suffix 'o8' on integer constant}} - c2y-warning {{octal literals without a '0o' prefix are deprecated}} */ // FIXME: however, it matches the behavior for hex literals in terms of the // error reported. Unfortunately, we then go on to think 0 is an octal literal // without a prefix, which is again a bit confusing. int o2 = 0xG; /* expected-error {{invalid suffix 'xG' on integer constant}} - c2y-warning {{octal literals without a '0o' prefix are deprecated}} */ // Show that floating-point suffixes on octal literals are rejected. @@ -130,7 +132,6 @@ constexpr int p = 0o0'1'2'3'4'5'6'7; /* compat-warning {{octal integer literals */ static_assert(p == 01234567); // c2y-warning {{octal literals without a '0o' prefix are deprecated}} int q = 0o'0'1; /* expected-error {{invalid suffix 'o'0'1' on integer constant}} - c2y-warning {{octal literals without a '0o' prefix are deprecated}} */ #define M 0o123 |