From ba081617a9f116ca2d511d0bf96e45c53ecc2523 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Wed, 11 Sep 2013 02:53:02 +0000 Subject: [PATCH] Fix is_trivially_constructible preconditions. Fixes a crash in cases where the first argument was an incomplete type or an uninstantiated template type. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@190482 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaExprCXX.cpp | 24 ++++++++++++------------ test/SemaCXX/type-traits.cpp | 9 ++++++++- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 72bbfbc726..9b703ed098 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -3522,24 +3522,24 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc, << 1 << 1 << 1 << (int)Args.size(); 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) { - if (Args[I]->getType()->isVoidType()) { - SawVoid = true; + QualType ArgTy = Args[I]->getType(); + if (ArgTy->isVoidType() || ArgTy->isIncompleteArrayType()) continue; - } - - if (!Args[I]->getType()->isIncompleteType() && - S.RequireCompleteType(KWLoc, Args[I]->getType(), + + if (S.RequireCompleteType(KWLoc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr)) return false; } - - // If any argument was 'void', of course it won't type-check. - if (SawVoid) + + // Make sure the first argument is a complete type. + if (Args[0]->getType()->isIncompleteType()) return false; - + SmallVector OpaqueArgExprs; SmallVector ArgExprs; ArgExprs.reserve(Args.size() - 1); diff --git a/test/SemaCXX/type-traits.cpp b/test/SemaCXX/type-traits.cpp index aa18ff4e67..f9e679187d 100644 --- a/test/SemaCXX/type-traits.cpp +++ b/test/SemaCXX/type-traits.cpp @@ -1571,7 +1571,7 @@ template struct DerivedB : BaseA { }; template 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 void isBaseOfT() { @@ -1770,6 +1770,8 @@ void is_trivial() { int arr[F(__is_trivial(cvoid))]; } } +template struct TriviallyConstructibleTemplate {}; + void trivial_checks() { { int arr[T(__is_trivially_copyable(int))]; } @@ -1848,6 +1850,11 @@ void trivial_checks() { int arr[F((__is_trivially_constructible(ExtDefaulted, ExtDefaulted &&)))]; } + { int arr[T((__is_trivially_constructible(TriviallyConstructibleTemplate)))]; } + { 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&&)))]; } -- 2.40.0