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. llvm-svn: 304376
This commit is contained in:
parent
32c5e809be
commit
f03e9084c1
|
@ -411,6 +411,7 @@ TYPE_TRAIT_1(__is_sealed, IsSealed, KEYMS)
|
|||
|
||||
// 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, IsConvertibleTo, KEYCXX)
|
|||
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.
|
||||
|
|
|
@ -65,6 +65,7 @@ namespace clang {
|
|||
UTT_IsStandardLayout,
|
||||
UTT_IsTrivial,
|
||||
UTT_IsTriviallyCopyable,
|
||||
UTT_IsTriviallyDestructible,
|
||||
UTT_IsUnion,
|
||||
UTT_IsUnsigned,
|
||||
UTT_IsVoid,
|
||||
|
|
|
@ -4080,24 +4080,23 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT,
|
|||
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 CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT,
|
|||
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 &Self, TypeTrait UTT,
|
|||
!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 &Self, TypeTrait UTT,
|
|||
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
|
||||
|
|
|
@ -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))]; }
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue