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@55 {{interface type cannot inherit from 'struct S'}} // expected-note@+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))]; } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits