From: Douglas Gregor Date: Fri, 18 Feb 2011 03:01:41 +0000 (+0000) Subject: Implement C++0x [expr.static.cast]p9, which permits explicitly casting X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1e856d99c52d9e93eab48084c3aca4a59204b94b;p=clang Implement C++0x [expr.static.cast]p9, which permits explicitly casting a scoped enumeration type to an integral or floating type, properly. There was an over-eager assertion, and it was missing the floating-point case. Fixes PR9107/. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@125825 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp index 35b7f51df1..30bb5763f2 100644 --- a/lib/Sema/SemaCXXCast.cpp +++ b/lib/Sema/SemaCXXCast.cpp @@ -688,18 +688,23 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr, QualType SrcType = Self.Context.getCanonicalType(SrcExpr->getType()); // C++0x 5.2.9p9: A value of a scoped enumeration type can be explicitly - // converted to an integral type. - if (Self.getLangOptions().CPlusPlus0x && SrcType->isEnumeralType()) { - assert(SrcType->getAs()->getDecl()->isScoped()); - if (DestType->isBooleanType()) { - Kind = CK_IntegralToBoolean; - return TC_Success; - } else if (DestType->isIntegralType(Self.Context)) { - Kind = CK_IntegralCast; - return TC_Success; + // converted to an integral type. [...] A value of a scoped enumeration type + // can also be explicitly converted to a floating-point type [...]. + if (const EnumType *Enum = SrcType->getAs()) { + if (Enum->getDecl()->isScoped()) { + if (DestType->isBooleanType()) { + Kind = CK_IntegralToBoolean; + return TC_Success; + } else if (DestType->isIntegralType(Self.Context)) { + Kind = CK_IntegralCast; + return TC_Success; + } else if (DestType->isRealFloatingType()) { + Kind = CK_IntegralToFloating; + return TC_Success; + } } } - + // Reverse integral promotion/conversion. All such conversions are themselves // again integral promotions or conversions and are thus already handled by // p2 (TryDirectInitialization above). diff --git a/test/CXX/expr/expr.post/expr.static.cast/p9-0x.cpp b/test/CXX/expr/expr.post/expr.static.cast/p9-0x.cpp new file mode 100644 index 0000000000..4acafb89ac --- /dev/null +++ b/test/CXX/expr/expr.post/expr.static.cast/p9-0x.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +enum class EC { ec1 }; + +void test0(EC ec) { + (void)static_cast(ec); + (void)static_cast(EC::ec1); + (void)static_cast(ec); + (void)static_cast(EC::ec1); + (void)static_cast(ec); + (void)static_cast(EC::ec1); + (void)static_cast(ec); + (void)static_cast(EC::ec1); + (void)static_cast(ec); + (void)static_cast(EC::ec1); + (void)static_cast(ec); + (void)static_cast(EC::ec1); +} + +namespace PR9107 { + enum E {}; + template inline _Tp* addressof(_Tp& __x) { + return (_Tp*)&(char&)__x; + } + void test() { + E a; + addressof(a); + } +}