Author: Mark de Wever Date: 2020-08-16T18:40:08+02:00 New Revision: fef26071240711e8f7305715b5f22cfc7ad04bfe
URL: https://github.com/llvm/llvm-project/commit/fef26071240711e8f7305715b5f22cfc7ad04bfe DIFF: https://github.com/llvm/llvm-project/commit/fef26071240711e8f7305715b5f22cfc7ad04bfe.diff LOG: [Sema] Use the proper cast for a fixed bool enum. When casting an enumerate with a fixed bool type the casting should use an IntegralToBoolean instead of an IntegralCast as is required per Core Issue 2338. Fixes PR47055: Incorrect codegen for enum with bool underlying type Differential Revision: https://reviews.llvm.org/D85612 Added: clang/test/CodeGen/enum-bool.cpp Modified: clang/lib/Sema/SemaCast.cpp clang/test/CXX/drs/dr23xx.cpp Removed: ################################################################################ diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp index 93752766f4a2..726900c59f20 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -1243,7 +1243,13 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr, 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<EnumType>(); + 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 index c265ebbe359c..a7ff2a5813ed 100644 --- 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 index 000000000000..220baa3fd8b6 --- /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<E>(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<E>(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<E>(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<E>(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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits