r253184 - [Sema] Implement several unary type traits more accurately

David Majnemer via cfe-commits cfe-commits at lists.llvm.org
Sun Nov 15 22:58:52 PST 2015


Author: majnemer
Date: Mon Nov 16 00:58:51 2015
New Revision: 253184

URL: http://llvm.org/viewvc/llvm-project?rev=253184&view=rev
Log:
[Sema] Implement several unary type traits more accurately

is_empty, is_polymorphic, and is_abstract didn't handle incomplete types
correctly.  Only non-union class types must be complete for these
traits.

is_final and is_sealed don't care about the particular spelling of the
FinalAttr.

is_interface_class should always return false regardless of its input.
The type trait can only be satisfied in a mode we do not support (/CLR).

Modified:
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/test/SemaCXX/abstract.cpp
    cfe/trunk/test/SemaCXX/ms-interface.cpp
    cfe/trunk/test/SemaCXX/type-traits.cpp

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=253184&r1=253183&r2=253184&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Mon Nov 16 00:58:51 2015
@@ -3550,27 +3550,43 @@ static bool CheckUnaryTypeTraitTypeCompl
   case UTT_IsVolatile:
   case UTT_IsSigned:
   case UTT_IsUnsigned:
+
+  // This type trait always returns false, checking the type is moot.
+  case UTT_IsInterfaceClass:
+    return true;
+
+  // C++14 [meta.unary.prop]:
+  //   If T is a non-union class type, T shall be a complete type.
+  case UTT_IsEmpty:
+  case UTT_IsPolymorphic:
+  case UTT_IsAbstract:
+    if (const auto *RD = ArgTy->getAsCXXRecordDecl())
+      if (!RD->isUnion())
+        return !S.RequireCompleteType(
+            Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);
+    return true;
+
+  // C++14 [meta.unary.prop]:
+  //   If T is a class type, T shall be a complete type.
+  case UTT_IsFinal:
+  case UTT_IsSealed:
+    if (ArgTy->getAsCXXRecordDecl())
+      return !S.RequireCompleteType(
+          Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);
     return true;
 
-    // C++0x [meta.unary.prop] Table 49 requires the following traits to be
-    // applied to a complete type.
+  // C++0x [meta.unary.prop] Table 49 requires the following traits to be
+  // applied to a complete type.
   case UTT_IsTrivial:
   case UTT_IsTriviallyCopyable:
   case UTT_IsStandardLayout:
   case UTT_IsPOD:
   case UTT_IsLiteral:
-  case UTT_IsEmpty:
-  case UTT_IsPolymorphic:
-  case UTT_IsAbstract:
-  case UTT_IsInterfaceClass:
+
   case UTT_IsDestructible:
   case UTT_IsNothrowDestructible:
     // Fall-through
 
-  // These traits require a complete type.
-  case UTT_IsFinal:
-  case UTT_IsSealed:
-
     // These trait expressions are designed to help implement predicates in
     // [meta.unary.prop] despite not being named the same. They are specified
     // by both GCC and the Embarcadero C++ compiler, and require the complete
@@ -3729,24 +3745,21 @@ static bool EvaluateUnaryTypeTrait(Sema
     return false;
   case UTT_IsPolymorphic:
     if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
-      return RD->isPolymorphic();
+      return !RD->isUnion() && RD->isPolymorphic();
     return false;
   case UTT_IsAbstract:
     if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
-      return RD->isAbstract();
+      return !RD->isUnion() && RD->isAbstract();
     return false;
+  // __is_interface_class only returns true when CL is invoked in /CLR mode and
+  // even then only when it is used with the 'interface struct ...' syntax
+  // Clang doesn't support /CLR which makes this type trait moot.
   case UTT_IsInterfaceClass:
-    if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
-      return RD->isInterface();
     return false;
   case UTT_IsFinal:
-    if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
-      return RD->hasAttr<FinalAttr>();
-    return false;
   case UTT_IsSealed:
     if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
-      if (FinalAttr *FA = RD->getAttr<FinalAttr>())
-        return FA->isSpelledAsSealed();
+      return RD->hasAttr<FinalAttr>();
     return false;
   case UTT_IsSigned:
     return T->isSignedIntegerType();

Modified: cfe/trunk/test/SemaCXX/abstract.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/abstract.cpp?rev=253184&r1=253183&r2=253184&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/abstract.cpp (original)
+++ cfe/trunk/test/SemaCXX/abstract.cpp Mon Nov 16 00:58:51 2015
@@ -8,6 +8,10 @@
   typedef int __CONCAT(__sa, __LINE__)[__b ? 1 : -1]
 #endif
 
+union IncompleteUnion;
+
+static_assert(!__is_abstract(IncompleteUnion), "unions are never abstract");
+
 class C {
   virtual void f() = 0; // expected-note {{unimplemented pure virtual method 'f'}}
 };

Modified: cfe/trunk/test/SemaCXX/ms-interface.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/ms-interface.cpp?rev=253184&r1=253183&r2=253184&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/ms-interface.cpp (original)
+++ cfe/trunk/test/SemaCXX/ms-interface.cpp Mon Nov 16 00:58:51 2015
@@ -58,10 +58,12 @@ __interface I6 : X {
 struct S { };
 class C { };
 __interface I { };
+union U;
 
 static_assert(!__is_interface_class(S), "oops");
 static_assert(!__is_interface_class(C), "oops");
-static_assert(__is_interface_class(I), "oops");
+static_assert(!__is_interface_class(I), "oops");
+static_assert(!__is_interface_class(U), "oops");
 
 // expected-error at 55 {{interface type cannot inherit from 'struct S'}}
 // expected-note at +1 {{in instantiation of template class 'I6<S>' requested here}}

Modified: cfe/trunk/test/SemaCXX/type-traits.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/type-traits.cpp?rev=253184&r1=253183&r2=253184&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/type-traits.cpp (original)
+++ cfe/trunk/test/SemaCXX/type-traits.cpp Mon Nov 16 00:58:51 2015
@@ -14,6 +14,7 @@ typedef Int IntAr[10];
 typedef Int IntArNB[];
 class Statics { static int priv; static NonPOD np; };
 union EmptyUnion {};
+union IncompleteUnion;
 union Union { int i; float f; };
 struct HasFunc { void f (); };
 struct HasOp { void operator *(); };
@@ -235,6 +236,7 @@ void is_empty()
   { int arr[F(__is_empty(Int))]; }
   { int arr[F(__is_empty(POD))]; }
   { int arr[F(__is_empty(EmptyUnion))]; }
+  { int arr[F(__is_empty(IncompleteUnion))]; }
   { int arr[F(__is_empty(EmptyAr))]; }
   { int arr[F(__is_empty(HasRef))]; }
   { int arr[F(__is_empty(HasVirt))]; }
@@ -313,8 +315,23 @@ struct PotentiallyFinal<T*> final { };
 template<>
 struct PotentiallyFinal<int> final { };
 
+struct SealedClass sealed {
+};
+
+template<typename T>
+struct PotentiallySealed { };
+
+template<typename T>
+struct PotentiallySealed<T*> sealed { };
+
+template<>
+struct PotentiallySealed<int> sealed { };
+
 void is_final()
 {
+	{ int arr[T(__is_final(SealedClass))]; }
+	{ int arr[T(__is_final(PotentiallySealed<float*>))]; }
+	{ int arr[T(__is_final(PotentiallySealed<int>))]; }
 	{ int arr[T(__is_final(FinalClass))]; }
 	{ int arr[T(__is_final(PotentiallyFinal<float*>))]; }
 	{ int arr[T(__is_final(PotentiallyFinal<int>))]; }
@@ -330,25 +347,17 @@ void is_final()
 	{ int arr[F(__is_final(IntArNB))]; }
 	{ int arr[F(__is_final(HasAnonymousUnion))]; }
 	{ int arr[F(__is_final(PotentiallyFinal<float>))]; }
+	{ int arr[F(__is_final(PotentiallySealed<float>))]; }
 }
 
-struct SealedClass sealed {
-};
-
-template<typename T>
-struct PotentiallySealed { };
-
-template<typename T>
-struct PotentiallySealed<T*> sealed { };
-
-template<>
-struct PotentiallySealed<int> sealed { };
-
 void is_sealed()
 {
 	{ int arr[T(__is_sealed(SealedClass))]; }
 	{ int arr[T(__is_sealed(PotentiallySealed<float*>))]; }
 	{ int arr[T(__is_sealed(PotentiallySealed<int>))]; }
+	{ int arr[T(__is_sealed(FinalClass))]; }
+	{ int arr[T(__is_sealed(PotentiallyFinal<float*>))]; }
+	{ int arr[T(__is_sealed(PotentiallyFinal<int>))]; }
 
 	{ int arr[F(__is_sealed(int))]; }
 	{ int arr[F(__is_sealed(Union))]; }
@@ -361,6 +370,7 @@ void is_sealed()
 	{ int arr[F(__is_sealed(IntArNB))]; }
 	{ int arr[F(__is_sealed(HasAnonymousUnion))]; }
 	{ int arr[F(__is_sealed(PotentiallyFinal<float>))]; }
+	{ int arr[F(__is_sealed(PotentiallySealed<float>))]; }
 }
 
 typedef HasVirt Polymorph;
@@ -373,6 +383,7 @@ void is_polymorphic()
 
   { int arr[F(__is_polymorphic(int))]; }
   { int arr[F(__is_polymorphic(Union))]; }
+  { int arr[F(__is_polymorphic(IncompleteUnion))]; }
   { int arr[F(__is_polymorphic(Int))]; }
   { int arr[F(__is_polymorphic(IntAr))]; }
   { int arr[F(__is_polymorphic(UnionAr))]; }




More information about the cfe-commits mailing list