r244564 - [MSVC Compat] Implement __is_destructible, __is_nothrow_destructible

David Majnemer via cfe-commits cfe-commits at lists.llvm.org
Mon Aug 10 20:03:28 PDT 2015


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))]; }
+}




More information about the cfe-commits mailing list