From 08433d2af3310b1c98e9ffe9dd171b7322c05f42 Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Tue, 11 Aug 2015 03:03:28 +0000 Subject: [PATCH] [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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@244564 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaExprCXX.cpp | 43 ++++++++++++++++++++++++++++++++++-- test/SemaCXX/type-traits.cpp | 43 ++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 2 deletions(-) diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 9dce817600..f7103c885a 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -3814,8 +3814,47 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, 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::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::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, if the + // expression std::declval().~U() is well-formed when treated as an + // unevaluated operand (Clause 5), then is_destructible::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(); + 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 diff --git a/test/SemaCXX/type-traits.cpp b/test/SemaCXX/type-traits.cpp index 2265c28476..d8b40e3ae1 100644 --- a/test/SemaCXX/type-traits.cpp +++ b/test/SemaCXX/type-traits.cpp @@ -150,6 +150,18 @@ struct VariadicCtor { template 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))]; } +} -- 2.40.0