llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: None (thebrandre) <details> <summary>Changes</summary> This commit fixes implicit integer conversions for _opaque-enum-declarations_ inside a class template with a specified _enum-base_ (see [dcl.enum]). Previously, the promotion type of the instantiated enum was set only in `Sema::ActOnEnumBody`, which is not called if there are no curly braces are after the enum-base. This fixes GitHub issue #<!-- -->117960. --- Full diff: https://github.com/llvm/llvm-project/pull/121039.diff 2 Files Affected: - (modified) clang/lib/Sema/SemaTemplateInstantiateDecl.cpp (+3) - (added) clang/test/SemaCXX/enum-base-in-class-template.cpp (+66) ``````````diff diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index e058afe81da589..4d39fd409795b6 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1620,6 +1620,9 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { if (isDeclWithinFunction(D) ? D == Def : Def && !Enum->isScoped()) { SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Enum); InstantiateEnumDefinition(Enum, Def); + } else { + if (D->isFixed() && !Def) + Enum->setPromotionType(Enum->getIntegerType()); } return Enum; diff --git a/clang/test/SemaCXX/enum-base-in-class-template.cpp b/clang/test/SemaCXX/enum-base-in-class-template.cpp new file mode 100644 index 00000000000000..012bef9785cbaf --- /dev/null +++ b/clang/test/SemaCXX/enum-base-in-class-template.cpp @@ -0,0 +1,66 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only %s -verify +// RUN: %clang_cc1 -std=c++20 -fsyntax-only %s -verify + +// This program causes clang 19 and earlier to crash because +// EnumDecl::PromotionType has not been set on the instantiated enum. +// See GitHub Issue #117960. +namespace Issue117960 { +template <typename T> +struct A { + enum E : T; +}; + +int b = A<int>::E{} + 0; +} + + +namespace test { +template <typename T1, typename T2> +struct IsSame { + static constexpr bool check() { return false; } +}; + +template <typename T> +struct IsSame<T, T> { + static constexpr bool check() { return true; } +}; +} // namespace test + + +template <typename T> +struct S1 { + enum E : T; +}; +// checks if EnumDecl::PromotionType is set +int X1 = S1<int>::E{} + 0; +int Y1 = S1<unsigned>::E{} + 0; +static_assert(test::IsSame<decltype(S1<int>::E{}+0), int>::check(), ""); +static_assert(test::IsSame<decltype(S1<unsigned>::E{}+0), unsigned>::check(), ""); +char Z1 = S1<unsigned>::E(-1) + 0; // expected-warning{{implicit conversion from 'unsigned int' to 'char'}} + +template <typename Traits> +struct S2 { + enum E : typename Traits::IntegerType; +}; + +template <typename T> +struct Traits { + typedef T IntegerType; +}; + +int X2 = S2<Traits<int>>::E{} + 0; +int Y2 = S2<Traits<unsigned>>::E{} + 0; +static_assert(test::IsSame<decltype(S2<Traits<int>>::E{}+0), int>::check(), ""); +static_assert(test::IsSame<decltype(S2<Traits<unsigned>>::E{}+0), unsigned>::check(), ""); + + +template <typename T> +struct S3 { + enum E : unsigned; +}; + +int X3 = S3<float>::E{} + 0; + +// fails in clang 19 and earlier (see the discussion on GitHub Issue #117960): +static_assert(test::IsSame<decltype(S3<float>::E{}+0), unsigned>::check(), ""); + `````````` </details> https://github.com/llvm/llvm-project/pull/121039 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits