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