[clang] [clang] Fix issue #117960 (PR #121039)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Dec 24 01:04:10 PST 2024
https://github.com/thebrandre created https://github.com/llvm/llvm-project/pull/121039
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.
>From 38eea8da39d50316061611dc0eefa471e282c7b2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9=20Brand?= <andre.j.brand at gmx.de>
Date: Tue, 24 Dec 2024 09:54:56 +0100
Subject: [PATCH] Fix implicit integer conversion for enum declared in class
template
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.
---
.../lib/Sema/SemaTemplateInstantiateDecl.cpp | 3 +
.../SemaCXX/enum-base-in-class-template.cpp | 66 +++++++++++++++++++
2 files changed, 69 insertions(+)
create mode 100644 clang/test/SemaCXX/enum-base-in-class-template.cpp
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(), "");
+
More information about the cfe-commits
mailing list