diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -1243,7 +1243,13 @@ return TC_Failed; } if (SrcType->isIntegralOrEnumerationType()) { - Kind = CK_IntegralCast; + // [expr.static.cast]p10 If the enumeration type has a fixed underlying + // type, the value is first converted to that type by integral conversion + const EnumType *Enum = DestType->getAs(); + Kind = Enum->getDecl()->isFixed() && + Enum->getDecl()->getIntegerType()->isBooleanType() + ? CK_IntegralToBoolean + : CK_IntegralCast; return TC_Success; } else if (SrcType->isRealFloatingType()) { Kind = CK_FloatingToIntegral; diff --git a/clang/test/CXX/drs/dr23xx.cpp b/clang/test/CXX/drs/dr23xx.cpp --- a/clang/test/CXX/drs/dr23xx.cpp +++ b/clang/test/CXX/drs/dr23xx.cpp @@ -4,6 +4,19 @@ // RUN: %clang_cc1 -std=c++17 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s // RUN: %clang_cc1 -std=c++2a %s -verify -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s +#if __cplusplus >= 201103L +namespace dr2338 { // dr2338: 12 +namespace B { +enum E : bool { Zero, One }; +static_assert((int)(E)2 == 1, ""); +} // namespace B +namespace D { +enum class E : bool { Zero, One }; +static_assert((int)(E)2 == 1, ""); +} // namespace D +} // namespace dr2338 +#endif + namespace dr2346 { // dr2346: 11 void test() { const int i2 = 0; diff --git a/clang/test/CodeGen/enum-bool.cpp b/clang/test/CodeGen/enum-bool.cpp new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/enum-bool.cpp @@ -0,0 +1,49 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -S -emit-llvm -o - %s | FileCheck %s + +namespace dr2338 { +namespace A { +enum E { Zero, One }; +E a(int x) { return static_cast(x); } +// CHECK-LABEL: define i32 @_ZN6dr23381A1aEi +// CHECK: ret i32 %0 + +E b(int x) { return (E)x; } +// CHECK-LABEL: define i32 @_ZN6dr23381A1bEi +// CHECK: ret i32 %0 + +} // namespace A +namespace B { +enum E : bool { Zero, One }; +E a(int x) { return static_cast(x); } +// CHECK-LABEL: define zeroext i1 @_ZN6dr23381B1aEi +// CHECK: ret i1 %tobool + +E b(int x) { return (E)x; } +// CHECK-LABEL: define zeroext i1 @_ZN6dr23381B1bEi +// CHECK: ret i1 %tobool + +} // namespace B +namespace C { +enum class E { Zero, One }; +E a(int x) { return static_cast(x); } +// CHECK-LABEL: define i32 @_ZN6dr23381C1aEi +// CHECK: ret i32 %0 + +E b(int x) { return (E)x; } +// CHECK-LABEL: define i32 @_ZN6dr23381C1bEi +// CHECK: ret i32 %0 + +} // namespace C +namespace D { +enum class E : bool { Zero, One }; +E a(int x) { return static_cast(x); } +// CHECK-LABEL: define zeroext i1 @_ZN6dr23381D1aEi +// CHECK: ret i1 %tobool + +E b(int x) { return (E)x; } + +// CHECK-LABEL: define zeroext i1 @_ZN6dr23381D1bEi +// CHECK: ret i1 %tobool + +} // namespace D +} // namespace dr2338