CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
217 lines
6.1 KiB
C++
217 lines
6.1 KiB
C++
// RUN: %clang_cc1 -std=c++11 -Wredeclared-class-member -Wconstant-conversion -Wdeprecated-declarations -Wc++11-narrowing -fsyntax-only %s -verify
|
|
// RUN: %clang_cc1 -std=c++14 -Wredeclared-class-member -Wconstant-conversion -Wdeprecated-declarations -Wc++11-narrowing -fsyntax-only %s -verify
|
|
// RUN: %clang_cc1 -std=c++20 -Wredeclared-class-member -Wconstant-conversion -Wdeprecated-declarations -Wc++11-narrowing -fsyntax-only %s -verify
|
|
|
|
// Test that opaque-enum-declarations are handled correctly w.r.t integral promotions.
|
|
// The key sections in the C++11 standard are:
|
|
// C++11 [dcl.enum]p3: An enumeration declared by an opaque-enum-declaration
|
|
// has a fixed underlying type and is a complete type.
|
|
// C++11 [conv.prom]: A prvalue of an unscoped enumeration type whose underlying type
|
|
// is fixed ([dcl.enum]) can be converted to a prvalue of its underlying type.
|
|
|
|
// 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(), "");
|
|
// C++11 [conv.prom]p4:
|
|
// A prvalue of an unscoped enumeration type whose underlying type is fixed can be converted to a
|
|
// prvalue of its underlying type. Moreover, if integral promotion can be applied to its underlying type, a
|
|
// prvalue of an unscoped enumeration type whose underlying type is fixed can also be converted to a prvalue
|
|
// of the promoted underlying type.
|
|
static_assert(test::IsSame<decltype(S2<Traits<char>>::E{}+char(0)), int>::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(), "");
|
|
|
|
template <typename T>
|
|
struct S4 {
|
|
enum E1 : char;
|
|
enum E2 : T;
|
|
};
|
|
|
|
int X4 = S4<char>::E1{} + '\0';
|
|
int Y4 = S4<char>::E2{} + '\0';
|
|
|
|
template <typename T>
|
|
struct S5 {
|
|
enum class E1 : char;
|
|
enum class E2 : T;
|
|
};
|
|
|
|
int X5 = S5<char>::E1{} + '\0'; // expected-error{{invalid operands to binary expression}}
|
|
// expected-note@-1{{no implicit conversion for scoped enum; consider casting to underlying type}}
|
|
int Y5 = S5<char>::E2{} + '\0'; // expected-error{{invalid operands to binary expression}}
|
|
// expected-note@-1{{no implicit conversion for scoped enum; consider casting to underlying type}}
|
|
|
|
|
|
template <typename T>
|
|
struct S6 {
|
|
enum E1 : T;
|
|
enum E2 : E1; // expected-error{{invalid underlying type}}
|
|
};
|
|
|
|
template struct S6<int>; // expected-note{{in instantiation of template class 'S6<int>' requested here}}
|
|
|
|
|
|
template <typename T>
|
|
struct S7 {
|
|
enum E : T;
|
|
enum E : T { X, Y, Z }; // expected-note{{previous declaration is here}}
|
|
enum E : T; // expected-warning{{class member cannot be redeclared}}
|
|
};
|
|
|
|
template struct S7<int>;
|
|
|
|
template <typename T>
|
|
struct S8 {
|
|
enum E : char;
|
|
enum E : char { X, Y, Z }; // expected-note{{previous declaration is here}}
|
|
enum E : char; // expected-warning{{class member cannot be redeclared}}
|
|
};
|
|
|
|
template struct S8<float>;
|
|
|
|
template <typename T>
|
|
struct S9 {
|
|
enum class E1 : T;
|
|
enum class E1 : T { X, Y, Z }; // expected-note{{previous declaration is here}}
|
|
enum class E1 : T; // expected-warning{{class member cannot be redeclared}}
|
|
enum class E2 : char;
|
|
enum class E2 : char { X, Y, Z }; // expected-note{{previous declaration is here}}
|
|
enum class E2 : char; // expected-warning{{class member cannot be redeclared}}
|
|
};
|
|
|
|
template struct S9<int>;
|
|
|
|
#if defined(__cplusplus) && __cplusplus >= 201402L
|
|
template <typename T>
|
|
struct S10 {
|
|
enum [[deprecated("for reasons")]] E : T; // expected-note{{explicitly marked deprecated here}}
|
|
};
|
|
|
|
int X10 = S10<int>::E{} + 0; // expected-warning{{deprecated: for reasons}}
|
|
#endif
|
|
|
|
template <typename T>
|
|
struct S11 {};
|
|
|
|
template <>
|
|
struct S11<unsigned> {
|
|
enum E : unsigned;
|
|
};
|
|
|
|
unsigned X11 = S11<unsigned>::E{} + 0u;
|
|
|
|
#if defined(__cplusplus) && __cplusplus >= 201402L
|
|
template <typename T>
|
|
struct S12 {
|
|
enum [[deprecated("for reasons")]] E1 : T; // expected-note{{explicitly marked deprecated here}}
|
|
enum [[deprecated("for reasons")]] E2 : T;
|
|
};
|
|
|
|
template <>
|
|
struct S12<float> {
|
|
enum E1 : unsigned;
|
|
enum E2 : unsigned;
|
|
};
|
|
|
|
unsigned X12 = S12<float>::E1{} + 0u;
|
|
unsigned Y12 = S12<float>::E2{} + 0u;
|
|
int Z12 = S12<int>::E1{} + 0; // expected-warning{{deprecated: for reasons}}
|
|
#endif
|
|
|
|
template <typename T>
|
|
struct S13 {
|
|
enum __attribute__((packed)) E { X, Y };
|
|
};
|
|
|
|
static_assert(sizeof(S13<int>::E) == 1, "");
|
|
|
|
template<typename T>
|
|
struct S14 {
|
|
enum E : float; // expected-error {{invalid underlying type}}
|
|
};
|
|
|
|
template<typename T>
|
|
struct S15 {
|
|
enum E : T; // expected-error {{invalid underlying type}}
|
|
};
|
|
|
|
template struct S15<float>; // expected-note {{in instantiation of template class 'S15<float>' requested here}}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
int f1() {
|
|
enum E : T;
|
|
return E{} + 0;
|
|
}
|
|
|
|
int F1 = f1<int>();
|
|
|
|
template <typename T>
|
|
int f2() {
|
|
struct LocalClass {
|
|
enum E : T;
|
|
};
|
|
return typename LocalClass::E{} + 0;
|
|
}
|
|
|
|
int F2 = f2<int>();
|