r304376 - PR33232: implement support for MSVC's __is_trivially_destructible trait.
Eric Fiselier via cfe-commits
cfe-commits at lists.llvm.org
Wed May 31 17:41:48 PDT 2017
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 at 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 at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170531/bc767caa/attachment-0001.html>
More information about the cfe-commits
mailing list