Author: majnemer Date: Mon Aug 10 22:03:28 2015 New Revision: 244564 URL: http://llvm.org/viewvc/llvm-project?rev=244564&view=rev Log: [MSVC Compat] Implement __is_destructible, __is_nothrow_destructible
Our implementations of these type trait intrinsics simply mapped them to __has_trivial_destructor. Instead, flesh these intrinsics out with a full implementation which matches the standard's description. Modified: cfe/trunk/lib/Sema/SemaExprCXX.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=244564&r1=244563&r2=244564&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original) +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Mon Aug 10 22:03:28 2015 @@ -3814,8 +3814,47 @@ static bool EvaluateUnaryTypeTrait(Sema return false; case UTT_IsDestructible: case UTT_IsNothrowDestructible: - // FIXME: Implement UTT_IsDestructible and UTT_IsNothrowDestructible. - // For now, let's fall through. + // C++14 [meta.unary.prop]: + // For reference types, is_destructible<T>::value is true. + if (T->isReferenceType()) + return true; + + // Objective-C++ ARC: autorelease types don't require destruction. + if (T->isObjCLifetimeType() && + T.getObjCLifetime() == Qualifiers::OCL_Autoreleasing) + return true; + + // C++14 [meta.unary.prop]: + // For incomplete types and function types, is_destructible<T>::value is + // false. + if (T->isIncompleteType() || T->isFunctionType()) + return false; + + // C++14 [meta.unary.prop]: + // For object types and given U equal to remove_all_extents_t<T>, if the + // expression std::declval<U&>().~U() is well-formed when treated as an + // unevaluated operand (Clause 5), then is_destructible<T>::value is true + if (auto *RD = C.getBaseElementType(T)->getAsCXXRecordDecl()) { + CXXDestructorDecl *Destructor = Self.LookupDestructor(RD); + if (!Destructor) + return false; + // C++14 [dcl.fct.def.delete]p2: + // A program that refers to a deleted function implicitly or + // explicitly, other than to declare it, is ill-formed. + if (Destructor->isDeleted()) + return false; + if (C.getLangOpts().AccessControl && Destructor->getAccess() != AS_public) + return false; + if (UTT == UTT_IsNothrowDestructible) { + const FunctionProtoType *CPT = + Destructor->getType()->getAs<FunctionProtoType>(); + CPT = Self.ResolveExceptionSpec(KeyLoc, CPT); + if (!CPT || !CPT->isNothrow(C)) + return false; + } + } + return true; + case UTT_HasTrivialDestructor: // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html // If __is_pod (type) is true or type is a reference type Modified: cfe/trunk/test/SemaCXX/type-traits.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/type-traits.cpp?rev=244564&r1=244563&r2=244564&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/type-traits.cpp (original) +++ cfe/trunk/test/SemaCXX/type-traits.cpp Mon Aug 10 22:03:28 2015 @@ -150,6 +150,18 @@ struct VariadicCtor { template<typename...T> VariadicCtor(T...); }; +struct ThrowingDtor { + ~ThrowingDtor() throw(int); +}; + +struct NoExceptDtor { + ~NoExceptDtor() noexcept(true); +}; + +struct NoThrowDtor { + ~NoThrowDtor() throw(); +}; + void is_pod() { { int arr[T(__is_pod(int))]; } @@ -2019,3 +2031,34 @@ void array_extent() { int t02[T(__array_extent(ConstIntArAr, 0) == 4)]; int t03[T(__array_extent(ConstIntArAr, 1) == 10)]; } + +void is_destructible_test() { + { int arr[T(__is_destructible(int))]; } + { int arr[T(__is_destructible(int[2]))]; } + { int arr[F(__is_destructible(int[]))]; } + { int arr[F(__is_destructible(void))]; } + { int arr[T(__is_destructible(int &))]; } + { int arr[T(__is_destructible(HasDest))]; } + { int arr[F(__is_destructible(AllPrivate))]; } + { int arr[T(__is_destructible(SuperNonTrivialStruct))]; } + { int arr[T(__is_destructible(AllDefaulted))]; } + { int arr[F(__is_destructible(AllDeleted))]; } + { int arr[T(__is_destructible(ThrowingDtor))]; } + { int arr[T(__is_destructible(NoThrowDtor))]; } +} + +void is_nothrow_destructible_test() { + { int arr[T(__is_nothrow_destructible(int))]; } + { int arr[T(__is_nothrow_destructible(int[2]))]; } + { int arr[F(__is_nothrow_destructible(int[]))]; } + { int arr[F(__is_nothrow_destructible(void))]; } + { int arr[T(__is_nothrow_destructible(int &))]; } + { int arr[T(__is_nothrow_destructible(HasDest))]; } + { int arr[F(__is_nothrow_destructible(AllPrivate))]; } + { int arr[T(__is_nothrow_destructible(SuperNonTrivialStruct))]; } + { int arr[T(__is_nothrow_destructible(AllDefaulted))]; } + { int arr[F(__is_nothrow_destructible(AllDeleted))]; } + { int arr[F(__is_nothrow_destructible(ThrowingDtor))]; } + { int arr[T(__is_nothrow_destructible(NoExceptDtor))]; } + { int arr[T(__is_nothrow_destructible(NoThrowDtor))]; } +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits