Fix is_trivially_constructible preconditions.

Fixes a crash in cases where the first argument was an incomplete type
or an uninstantiated template type.

<rdar://problem/14938471>

llvm-svn: 190482
This commit is contained in:
Eli Friedman 2013-09-11 02:53:02 +00:00
parent 8b4e379de3
commit 9ea1e16747
2 changed files with 20 additions and 13 deletions

View File

@ -3523,21 +3523,21 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
return false; return false;
} }
bool SawVoid = false; // Precondition: T and all types in the parameter pack Args shall be
// complete types, (possibly cv-qualified) void, or arrays of
// unknown bound.
for (unsigned I = 0, N = Args.size(); I != N; ++I) { for (unsigned I = 0, N = Args.size(); I != N; ++I) {
if (Args[I]->getType()->isVoidType()) { QualType ArgTy = Args[I]->getType();
SawVoid = true; if (ArgTy->isVoidType() || ArgTy->isIncompleteArrayType())
continue; continue;
}
if (!Args[I]->getType()->isIncompleteType() && if (S.RequireCompleteType(KWLoc, ArgTy,
S.RequireCompleteType(KWLoc, Args[I]->getType(),
diag::err_incomplete_type_used_in_type_trait_expr)) diag::err_incomplete_type_used_in_type_trait_expr))
return false; return false;
} }
// If any argument was 'void', of course it won't type-check. // Make sure the first argument is a complete type.
if (SawVoid) if (Args[0]->getType()->isIncompleteType())
return false; return false;
SmallVector<OpaqueValueExpr, 2> OpaqueArgExprs; SmallVector<OpaqueValueExpr, 2> OpaqueArgExprs;

View File

@ -1571,7 +1571,7 @@ template<typename T> struct DerivedB : BaseA<T> { };
template<typename T> struct CrazyDerived : T { }; template<typename T> struct CrazyDerived : T { };
class class_forward; // expected-note {{forward declaration of 'class_forward'}} class class_forward; // expected-note 2 {{forward declaration of 'class_forward'}}
template <typename Base, typename Derived> template <typename Base, typename Derived>
void isBaseOfT() { void isBaseOfT() {
@ -1770,6 +1770,8 @@ void is_trivial()
{ int arr[F(__is_trivial(cvoid))]; } { int arr[F(__is_trivial(cvoid))]; }
} }
template<typename T> struct TriviallyConstructibleTemplate {};
void trivial_checks() void trivial_checks()
{ {
{ int arr[T(__is_trivially_copyable(int))]; } { int arr[T(__is_trivially_copyable(int))]; }
@ -1848,6 +1850,11 @@ void trivial_checks()
{ int arr[F((__is_trivially_constructible(ExtDefaulted, { int arr[F((__is_trivially_constructible(ExtDefaulted,
ExtDefaulted &&)))]; } ExtDefaulted &&)))]; }
{ int arr[T((__is_trivially_constructible(TriviallyConstructibleTemplate<int>)))]; }
{ int arr[F((__is_trivially_constructible(class_forward)))]; } // expected-error {{incomplete type 'class_forward' used in type trait expression}}
{ int arr[F((__is_trivially_constructible(class_forward[])))]; }
{ int arr[F((__is_trivially_constructible(void)))]; }
{ int arr[T((__is_trivially_assignable(int&, int)))]; } { int arr[T((__is_trivially_assignable(int&, int)))]; }
{ int arr[T((__is_trivially_assignable(int&, int&)))]; } { int arr[T((__is_trivially_assignable(int&, int&)))]; }
{ int arr[T((__is_trivially_assignable(int&, int&&)))]; } { int arr[T((__is_trivially_assignable(int&, int&&)))]; }