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

Reply via email to