Index: lib/Sema/SemaExprCXX.cpp =================================================================== --- lib/Sema/SemaExprCXX.cpp +++ lib/Sema/SemaExprCXX.cpp @@ -4101,6 +4101,11 @@ case UTT_IsDestructible: case UTT_IsNothrowDestructible: case UTT_IsTriviallyDestructible: + if (ArgTy->isIncompleteArrayType() || ArgTy->isVoidType()) + return true; + + return !S.RequireCompleteType( + Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr); // Per the GCC type traits documentation, the same constraints apply to these. case UTT_HasNothrowAssign: case UTT_HasNothrowMoveAssign: @@ -4113,9 +4118,15 @@ case UTT_HasTrivialCopy: case UTT_HasTrivialDestructor: case UTT_HasVirtualDestructor: - if (ArgTy->isIncompleteArrayType() || ArgTy->isVoidType()) + if(ArgTy->isVoidType()) return true; + if (ArgTy->isIncompleteArrayType()) { + QualType ElTy = QualType(ArgTy->getBaseElementTypeUnsafe(), 0); + if (!ElTy->isIncompleteType()) + return true; + } + return !S.RequireCompleteType( Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr); } Index: test/SemaCXX/type-traits.cpp =================================================================== --- test/SemaCXX/type-traits.cpp +++ test/SemaCXX/type-traits.cpp @@ -1572,8 +1572,10 @@ { int arr[T(__has_trivial_destructor(AllDefaulted))]; } { int arr[T(__has_trivial_destructor(AllDeleted))]; } { int arr[T(__has_trivial_destructor(DerivesHasRef))]; } + { int arr[T(__has_trivial_destructor(ACompleteType[]))]; } { int arr[F(__has_trivial_destructor(HasDest))]; } + { int arr[F(__has_trivial_destructor(AnIncompleteType[]))]; } // expected-error {{incomplete type}} { int arr[F(__has_trivial_destructor(void))]; } { int arr[F(__has_trivial_destructor(cvoid))]; } { int arr[F(__has_trivial_destructor(AllPrivate))]; }