]> granicus.if.org Git - clang/commitdiff
Implement C++0x [expr.static.cast]p9, which permits explicitly casting
authorDouglas Gregor <dgregor@apple.com>
Fri, 18 Feb 2011 03:01:41 +0000 (03:01 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 18 Feb 2011 03:01:41 +0000 (03:01 +0000)
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/<rdar://problem/8937402>.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@125825 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaCXXCast.cpp
test/CXX/expr/expr.post/expr.static.cast/p9-0x.cpp [new file with mode: 0644]

index 35b7f51df1cfc21b6fd2303fefd68da52478c993..30bb5763f2116d2918fe702f5b6075d2e75b4b99 100644 (file)
@@ -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<EnumType>()->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<EnumType>()) {
+    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 (file)
index 0000000..4acafb8
--- /dev/null
@@ -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<bool>(ec);
+  (void)static_cast<bool>(EC::ec1);
+  (void)static_cast<char>(ec);
+  (void)static_cast<char>(EC::ec1);
+  (void)static_cast<int>(ec);
+  (void)static_cast<int>(EC::ec1);
+  (void)static_cast<unsigned long>(ec);
+  (void)static_cast<unsigned long>(EC::ec1);
+  (void)static_cast<float>(ec);
+  (void)static_cast<float>(EC::ec1);
+  (void)static_cast<double>(ec);
+  (void)static_cast<double>(EC::ec1);
+}
+
+namespace PR9107 {
+  enum E {};
+  template <class _Tp> inline _Tp* addressof(_Tp& __x) {
+    return (_Tp*)&(char&)__x;
+  }
+  void test() {
+    E a;
+    addressof(a);
+  }
+}