https://github.com/thebrandre updated https://github.com/llvm/llvm-project/pull/124407
From e535adb5e94f89350d2e64344857e001cc1e1ca5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Brand?= <andre.br...@mailbox.org> Date: Sat, 25 Jan 2025 14:25:32 +0100 Subject: [PATCH 1/3] [clang] Fix issues on template class enum member redeclaration --- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 6a2331e59477a2..fe412c2291fc3b 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1627,12 +1627,17 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { // specialization causes the implicit instantiation of the declarations, but // not the definitions of scoped member enumerations. // - // DR1484 clarifies that enumeration definitions inside of a template + // DR1484 clarifies that enumeration definitions inside a template // declaration aren't considered entities that can be separately instantiated - // from the rest of the entity they are declared inside of. + // from the rest of the entity they are declared inside. if (isDeclWithinFunction(D) ? D == Def : Def && !Enum->isScoped()) { - SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Enum); - InstantiateEnumDefinition(Enum, Def); + // Prevent redundant instantiation of the enumerator-definition if the + // definition has already been instantiated due to a prior + // opaque-enum-declaration. + if (PrevDecl == nullptr) { + SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Enum); + InstantiateEnumDefinition(Enum, Def); + } } return Enum; From 8c6dc63c310a04ada71ef52c12d586d73b060809 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Brand?= <andre.br...@mailbox.org> Date: Sat, 25 Jan 2025 14:25:32 +0100 Subject: [PATCH 2/3] [clang] Add tests with member enum redeclarations --- .../test/SemaCXX/member-enum-declarations.cpp | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 clang/test/SemaCXX/member-enum-declarations.cpp diff --git a/clang/test/SemaCXX/member-enum-declarations.cpp b/clang/test/SemaCXX/member-enum-declarations.cpp new file mode 100644 index 00000000000000..e08f6e7a3fcd6d --- /dev/null +++ b/clang/test/SemaCXX/member-enum-declarations.cpp @@ -0,0 +1,112 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only %s -verify +// RUN: %clang_cc1 -std=c++14 -fsyntax-only %s -verify +// RUN: %clang_cc1 -std=c++20 -fsyntax-only %s -verify + + +namespace ScopedEnumerations { + +template <typename T> +struct S1 { + enum class E : T; +}; + +template <typename T> +enum class S1<T>::E : T { + S1_X = 0x123 +}; + +static_assert(static_cast<int>(S1<int>::E::S1_X) == 0x123, ""); + +template <typename T> +struct S2 { + static constexpr T f(int) { return 0; }; + enum class E : T; + static constexpr T f(char) { return 1; }; + enum class E : T { X = f(T{}) }; +}; + +static_assert(static_cast<int>(S2<char>::E::X) == 1, ""); + +template <typename T> +struct S3 { + enum class E : T; + enum class E : T { X = 0x7FFFFF00 }; // expected-error {{cannot be narrowed to type 'char'}} expected-warning {{implicit conversion from 'int' to 'char'}} +}; +template struct S3<char>; // expected-note {{in instantiation}} + +template <typename T> +struct S4 { + enum class E : T; + enum class E : T { S4_X = 5 }; +}; + +auto x4 = S4<int>::E::S4_X; + +template <typename T> +T f1() { + enum class E : T { X_F1, Y_F1, Z_F1 }; + return X_F1; // expected-error {{use of undeclared identifier 'X_F1'}} +} + +const int resf1 = f1<int>(); + +} + + +namespace UnscopedEnumerations { + +template <typename T> +struct S1 { + enum E : T; +}; + +template <typename T> +enum S1<T>::E : T { + S1_X = 0x123 +}; + +static_assert(static_cast<int>(S1<int>::S1_X) == 0x123, ""); + +template <typename T> +struct S2 { + static constexpr T f(int) { return 0; }; + enum E : T; + static constexpr T f(char) { return 1; }; + enum E : T { S2_X = f(T{}) }; +}; + +static_assert(static_cast<int>(S2<char>::E::S2_X) == 1, ""); + +template <typename T> +struct S3 { + enum E : T; + enum E : T { S3_X = 0x7FFFFF00 }; // expected-error {{cannot be narrowed to type 'char'}} expected-warning {{implicit conversion from 'int' to 'char'}} +}; +template struct S3<char>; // expected-note {{in instantiation of template class}} + +template <typename T> +struct S4 { + enum E : T; + enum E : T { S4_X = 5 }; +}; + +auto x4 = S4<int>::S4_X; + +template <typename T> +struct S5 { + enum E : T; + T S5_X = 5; // expected-note {{previous definition is here}} + enum E : T { S5_X = 5 }; // expected-error {{redefinition of 'S5_X'}} +}; + + +template <typename T> +T f1() { + enum E : T { X_F2, Y_F2, Z_F2 }; + return X_F2; +} + +const int resf1 = f1<int>(); + +} + From 16fef8afdd4eae665062930caf43c5052beb2091 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Brand?= <andre.br...@mailbox.org> Date: Sat, 25 Jan 2025 15:02:02 +0100 Subject: [PATCH 3/3] [clang] Update release notes --- clang/docs/ReleaseNotes.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 031c5d84e49f97..af3632322b8453 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -1003,6 +1003,7 @@ Bug Fixes to C++ Support - Fixed assertions or false compiler diagnostics in the case of C++ modules for lambda functions or inline friend functions defined inside templates (#GH122493). - Clang now rejects declaring an alias template with the same name as its template parameter. (#GH123423) +- Fixed the rejection of valid code when referencing an enumerator of an unscoped enum member with a prior declaration. (#GH124405) - Fixed immediate escalation of non-dependent expressions. (#GH123405) - Fix type of expression when calling a template which returns an ``__array_rank`` querying a type depending on a template parameter. Now, such expression can be used with ``static_assert`` and ``constexpr``. (#GH123498) _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits