I'm assuming libc++ should move to this trait instead? /Eric
On Wed, May 31, 2017 at 6:28 PM, Richard Smith via cfe-commits < cfe-commits@lists.llvm.org> wrote: > Author: rsmith > Date: Wed May 31 19:28:16 2017 > New Revision: 304376 > > URL: http://llvm.org/viewvc/llvm-project?rev=304376&view=rev > Log: > PR33232: implement support for MSVC's __is_trivially_destructible trait. > > Unlike the GCC-compatible __has_trivial_destructor trait, this one > computes the > right answer rather than performing the quirky set of checks described in > GCC's > documentation (https://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html). > > MSVC also has a __has_trivial_destructor trait which is the same as its > (and > now Clang's) __is_trivially_destructible trait; we might want to consider > changing the behavior of __has_trivial_destructor if we're targeting an > MSVC > platform, but I'm not doing so for now. > > While implementing this I found that we were incorrectly rejecting > __is_destructible queries on arrays of unknown bound of incomplete types; > that > too is fixed, and I've added similar tests for other traits for good > measure. > > Modified: > cfe/trunk/include/clang/Basic/TokenKinds.def > cfe/trunk/include/clang/Basic/TypeTraits.h > cfe/trunk/lib/Sema/SemaExprCXX.cpp > cfe/trunk/test/SemaCXX/type-traits.cpp > > Modified: cfe/trunk/include/clang/Basic/TokenKinds.def > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/ > clang/Basic/TokenKinds.def?rev=304376&r1=304375&r2=304376&view=diff > ============================================================ > ================== > --- cfe/trunk/include/clang/Basic/TokenKinds.def (original) > +++ cfe/trunk/include/clang/Basic/TokenKinds.def Wed May 31 19:28:16 2017 > @@ -411,6 +411,7 @@ TYPE_TRAIT_1(__is_sealed, IsSealed, KEYM > > // MSVC12.0 / VS2013 Type Traits > TYPE_TRAIT_1(__is_destructible, IsDestructible, KEYMS) > +TYPE_TRAIT_1(__is_trivially_destructible, IsTriviallyDestructible, > KEYCXX) > TYPE_TRAIT_1(__is_nothrow_destructible, IsNothrowDestructible, KEYMS) > TYPE_TRAIT_2(__is_nothrow_assignable, IsNothrowAssignable, KEYCXX) > TYPE_TRAIT_N(__is_constructible, IsConstructible, KEYCXX) > @@ -439,7 +440,6 @@ TYPE_TRAIT_2(__is_convertible_to, IsConv > TYPE_TRAIT_1(__is_empty, IsEmpty, KEYCXX) > TYPE_TRAIT_1(__is_enum, IsEnum, KEYCXX) > TYPE_TRAIT_1(__is_final, IsFinal, KEYCXX) > -// Tentative name - there's no implementation of std::is_literal_type yet. > TYPE_TRAIT_1(__is_literal, IsLiteral, KEYCXX) > // Name for GCC 4.6 compatibility - people have already written libraries > using > // this name unfortunately. > > Modified: cfe/trunk/include/clang/Basic/TypeTraits.h > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/ > clang/Basic/TypeTraits.h?rev=304376&r1=304375&r2=304376&view=diff > ============================================================ > ================== > --- cfe/trunk/include/clang/Basic/TypeTraits.h (original) > +++ cfe/trunk/include/clang/Basic/TypeTraits.h Wed May 31 19:28:16 2017 > @@ -65,6 +65,7 @@ namespace clang { > UTT_IsStandardLayout, > UTT_IsTrivial, > UTT_IsTriviallyCopyable, > + UTT_IsTriviallyDestructible, > UTT_IsUnion, > UTT_IsUnsigned, > UTT_IsVoid, > > Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/ > SemaExprCXX.cpp?rev=304376&r1=304375&r2=304376&view=diff > ============================================================ > ================== > --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original) > +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Wed May 31 19:28:16 2017 > @@ -4080,24 +4080,23 @@ static bool CheckUnaryTypeTraitTypeCompl > 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++1z [meta.unary.prop]: > + // remove_all_extents_t<T> shall be a complete type or cv void. > case UTT_IsAggregate: > case UTT_IsTrivial: > case UTT_IsTriviallyCopyable: > case UTT_IsStandardLayout: > case UTT_IsPOD: > case UTT_IsLiteral: > + ArgTy = QualType(ArgTy->getBaseElementTypeUnsafe(), 0); > + LLVM_FALLTHROUGH; > > + // C++1z [meta.unary.prop]: > + // T shall be a complete type, cv void, or an array of unknown bound. > case UTT_IsDestructible: > case UTT_IsNothrowDestructible: > - // Fall-through > - > - // 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 > - // type due to the overarching C++0x type predicates being implemented > - // requiring the complete type. > + case UTT_IsTriviallyDestructible: > + // Per the GCC type traits documentation, the same constraints apply to > these. > case UTT_HasNothrowAssign: > case UTT_HasNothrowMoveAssign: > case UTT_HasNothrowConstructor: > @@ -4109,17 +4108,11 @@ static bool CheckUnaryTypeTraitTypeCompl > case UTT_HasTrivialCopy: > case UTT_HasTrivialDestructor: > case UTT_HasVirtualDestructor: > - // Arrays of unknown bound are expressly allowed. > - QualType ElTy = ArgTy; > - if (ArgTy->isIncompleteArrayType()) > - ElTy = S.Context.getAsArrayType(ArgTy)->getElementType(); > - > - // The void type is expressly allowed. > - if (ElTy->isVoidType()) > + if (ArgTy->isIncompleteArrayType() || ArgTy->isVoidType()) > return true; > > return !S.RequireCompleteType( > - Loc, ElTy, diag::err_incomplete_type_used_in_type_trait_expr); > + Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr); > } > } > > @@ -4356,6 +4349,7 @@ static bool EvaluateUnaryTypeTrait(Sema > !RD->hasNonTrivialCopyAssignment(); > return false; > case UTT_IsDestructible: > + case UTT_IsTriviallyDestructible: > case UTT_IsNothrowDestructible: > // C++14 [meta.unary.prop]: > // For reference types, is_destructible<T>::value is true. > @@ -4373,6 +4367,11 @@ static bool EvaluateUnaryTypeTrait(Sema > if (T->isIncompleteType() || T->isFunctionType()) > return false; > > + // A type that requires destruction (via a non-trivial destructor or > ARC > + // lifetime semantics) is not trivially-destructible. > + if (UTT == UTT_IsTriviallyDestructible && T.isDestructedType()) > + 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 > > Modified: cfe/trunk/test/SemaCXX/type-traits.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ > SemaCXX/type-traits.cpp?rev=304376&r1=304375&r2=304376&view=diff > ============================================================ > ================== > --- cfe/trunk/test/SemaCXX/type-traits.cpp (original) > +++ cfe/trunk/test/SemaCXX/type-traits.cpp Wed May 31 19:28:16 2017 > @@ -252,6 +252,11 @@ void is_pod() > { int arr[F(__is_pod(void))]; } > { int arr[F(__is_pod(cvoid))]; } > // { int arr[F(__is_pod(NonPODUnion))]; } > + > + { int arr[T(__is_pod(ACompleteType))]; } > + { int arr[F(__is_pod(AnIncompleteType))]; } // expected-error > {{incomplete type}} > + { int arr[F(__is_pod(AnIncompleteType[]))]; } // expected-error > {{incomplete type}} > + { int arr[F(__is_pod(AnIncompleteType[1]))]; } // expected-error > {{incomplete type}} > } > > typedef Empty EmptyAr[10]; > @@ -287,6 +292,11 @@ void is_empty() > { int arr[F(__is_empty(IntArNB))]; } > { int arr[F(__is_empty(HasAnonymousUnion))]; } > // { int arr[F(__is_empty(DerivesVirt))]; } > + > + { int arr[T(__is_empty(ACompleteType))]; } > + { int arr[F(__is_empty(AnIncompleteType))]; } // expected-error > {{incomplete type}} > + { int arr[F(__is_empty(AnIncompleteType[]))]; } > + { int arr[F(__is_empty(AnIncompleteType[1]))]; } > } > > typedef Derives ClassType; > @@ -511,6 +521,8 @@ void is_aggregate() > constexpr bool TrueAfterCpp14 = __cplusplus > 201402L; > > __is_aggregate(AnIncompleteType); // expected-error {{incomplete type}} > + __is_aggregate(AnIncompleteType[]); // expected-error {{incomplete > type}} > + __is_aggregate(AnIncompleteType[1]); // expected-error {{incomplete > type}} > __is_aggregate(AnIncompleteTypeAr); // expected-error {{incomplete > type}} > __is_aggregate(AnIncompleteTypeArNB); // expected-error {{incomplete > type}} > __is_aggregate(AnIncompleteTypeArMB); // expected-error {{incomplete > type}} > @@ -1220,6 +1232,13 @@ void is_trivial2() > int t32[F(__is_trivial(SuperNonTrivialStruct))]; > int t33[F(__is_trivial(NonTCStruct))]; > int t34[F(__is_trivial(ExtDefaulted))]; > + > + int t40[T(__is_trivial(ACompleteType))]; > + int t41[F(__is_trivial(AnIncompleteType))]; // expected-error > {{incomplete type}} > + int t42[F(__is_trivial(AnIncompleteType[]))]; // expected-error > {{incomplete type}} > + int t43[F(__is_trivial(AnIncompleteType[1]))]; // expected-error > {{incomplete type}} > + int t44[F(__is_trivial(void))]; > + int t45[F(__is_trivial(const volatile void))]; > } > > void is_trivially_copyable2() > @@ -1257,6 +1276,13 @@ void is_trivially_copyable2() > > int t34[T(__is_trivially_copyable(const int))]; > int t35[T(__is_trivially_copyable(volatile int))]; > + > + int t40[T(__is_trivially_copyable(ACompleteType))]; > + int t41[F(__is_trivially_copyable(AnIncompleteType))]; // > expected-error {{incomplete type}} > + int t42[F(__is_trivially_copyable(AnIncompleteType[]))]; // > expected-error {{incomplete type}} > + int t43[F(__is_trivially_copyable(AnIncompleteType[1]))]; // > expected-error {{incomplete type}} > + int t44[F(__is_trivially_copyable(void))]; > + int t45[F(__is_trivially_copyable(const volatile void))]; > } > > struct CStruct { > @@ -1320,6 +1346,13 @@ void is_standard_layout() > int t15[F(__is_standard_layout(CppStructNonStandardByBaseAr))]; > int t16[F(__is_standard_layout(CppStructNonStandardBySameBase))]; > int t17[F(__is_standard_layout(CppStructNonStandardBy2ndVirtBase))]; > + > + int t40[T(__is_standard_layout(ACompleteType))]; > + int t41[F(__is_standard_layout(AnIncompleteType))]; // expected-error > {{incomplete type}} > + int t42[F(__is_standard_layout(AnIncompleteType[]))]; // > expected-error {{incomplete type}} > + int t43[F(__is_standard_layout(AnIncompleteType[1]))]; // > expected-error {{incomplete type}} > + int t44[F(__is_standard_layout(void))]; > + int t45[F(__is_standard_layout(const volatile void))]; > } > > void is_signed() > @@ -2133,6 +2166,13 @@ void trivial_checks() > TrivialMoveButNotCopy)))]; } > { int arr[T((__is_assignable(TrivialMoveButNotCopy &, > TrivialMoveButNotCopy &&)))]; } > + > + { int arr[T(__is_assignable(ACompleteType, ACompleteType))]; } > + { int arr[F(__is_assignable(AnIncompleteType, AnIncompleteType))]; } > // expected-error {{incomplete type}} > + { int arr[F(__is_assignable(AnIncompleteType[], AnIncompleteType[]))]; > } > + { int arr[F(__is_assignable(AnIncompleteType[1], > AnIncompleteType[1]))]; } // expected-error {{incomplete type}} > + { int arr[F(__is_assignable(void, void))]; } > + { int arr[F(__is_assignable(const volatile void, const volatile > void))]; } > } > > void constructible_checks() { > @@ -2164,6 +2204,19 @@ void constructible_checks() { > > // PR25513 > { int arr[F(__is_constructible(int(int)))]; } > + > + { int arr[T(__is_constructible(ACompleteType))]; } > + { int arr[T(__is_nothrow_constructible(ACompleteType))]; } > + { int arr[F(__is_constructible(AnIncompleteType))]; } // > expected-error {{incomplete type}} > + { int arr[F(__is_nothrow_constructible(AnIncompleteType))]; } // > expected-error {{incomplete type}} > + { int arr[F(__is_constructible(AnIncompleteType[]))]; } > + { int arr[F(__is_nothrow_constructible(AnIncompleteType[]))]; } > + { int arr[F(__is_constructible(AnIncompleteType[1]))]; } // > expected-error {{incomplete type}} > + { int arr[F(__is_nothrow_constructible(AnIncompleteType[1]))]; } // > expected-error {{incomplete type}} > + { int arr[F(__is_constructible(void))]; } > + { int arr[F(__is_nothrow_constructible(void))]; } > + { int arr[F(__is_constructible(const volatile void))]; } > + { int arr[F(__is_nothrow_constructible(const volatile void))]; } > } > > // Instantiation of __is_trivially_constructible > @@ -2192,6 +2245,13 @@ void is_trivially_constructible_test() { > { int arr[F((is_trivially_constructible<NonTrivialDefault>::value))]; } > { int arr[F((is_trivially_constructible<ThreeArgCtor, int*, char*, > int&>::value))]; } > { int arr[F((is_trivially_constructible<Abstract>::value))]; } // > PR19178 > + > + { int arr[T(__is_trivially_constructible(ACompleteType))]; } > + { int arr[F(__is_trivially_constructible(AnIncompleteType))]; } // > expected-error {{incomplete type}} > + { int arr[F(__is_trivially_constructible(AnIncompleteType[]))]; } > + { int arr[F(__is_trivially_constructible(AnIncompleteType[1]))]; } // > expected-error {{incomplete type}} > + { int arr[F(__is_trivially_constructible(void))]; } > + { int arr[F(__is_trivially_constructible(const volatile void))]; } > } > > void array_rank() { > @@ -2218,6 +2278,13 @@ void is_destructible_test() { > { int arr[F(__is_destructible(AllDeleted))]; } > { int arr[T(__is_destructible(ThrowingDtor))]; } > { int arr[T(__is_destructible(NoThrowDtor))]; } > + > + { int arr[T(__is_destructible(ACompleteType))]; } > + { int arr[F(__is_destructible(AnIncompleteType))]; } // expected-error > {{incomplete type}} > + { int arr[F(__is_destructible(AnIncompleteType[]))]; } > + { int arr[F(__is_destructible(AnIncompleteType[1]))]; } // > expected-error {{incomplete type}} > + { int arr[F(__is_destructible(void))]; } > + { int arr[F(__is_destructible(const volatile void))]; } > } > > void is_nothrow_destructible_test() { > @@ -2234,4 +2301,33 @@ void is_nothrow_destructible_test() { > { int arr[F(__is_nothrow_destructible(ThrowingDtor))]; } > { int arr[T(__is_nothrow_destructible(NoExceptDtor))]; } > { int arr[T(__is_nothrow_destructible(NoThrowDtor))]; } > + > + { int arr[T(__is_nothrow_destructible(ACompleteType))]; } > + { int arr[F(__is_nothrow_destructible(AnIncompleteType))]; } // > expected-error {{incomplete type}} > + { int arr[F(__is_nothrow_destructible(AnIncompleteType[]))]; } > + { int arr[F(__is_nothrow_destructible(AnIncompleteType[1]))]; } // > expected-error {{incomplete type}} > + { int arr[F(__is_nothrow_destructible(void))]; } > + { int arr[F(__is_nothrow_destructible(const volatile void))]; } > +} > + > +void is_trivially_destructible_test() { > + { int arr[T(__is_trivially_destructible(int))]; } > + { int arr[T(__is_trivially_destructible(int[2]))]; } > + { int arr[F(__is_trivially_destructible(int[]))]; } > + { int arr[F(__is_trivially_destructible(void))]; } > + { int arr[T(__is_trivially_destructible(int &))]; } > + { int arr[F(__is_trivially_destructible(HasDest))]; } > + { int arr[F(__is_trivially_destructible(AllPrivate))]; } > + { int arr[F(__is_trivially_destructible(SuperNonTrivialStruct))]; } > + { int arr[T(__is_trivially_destructible(AllDefaulted))]; } > + { int arr[F(__is_trivially_destructible(AllDeleted))]; } > + { int arr[F(__is_trivially_destructible(ThrowingDtor))]; } > + { int arr[F(__is_trivially_destructible(NoThrowDtor))]; } > + > + { int arr[T(__is_trivially_destructible(ACompleteType))]; } > + { int arr[F(__is_trivially_destructible(AnIncompleteType))]; } // > expected-error {{incomplete type}} > + { int arr[F(__is_trivially_destructible(AnIncompleteType[]))]; } > + { int arr[F(__is_trivially_destructible(AnIncompleteType[1]))]; } // > expected-error {{incomplete type}} > + { int arr[F(__is_trivially_destructible(void))]; } > + { int arr[F(__is_trivially_destructible(const volatile void))]; } > } > > > _______________________________________________ > cfe-commits mailing list > cfe-commits@lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits