diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 1cfd3e56a583e..d2f18d4aa9b98 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -5012,6 +5012,20 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, return From; } +/// Checks that type T is not a VLA. +/// +/// @returns @c true if @p T is VLA and a diagnostic was emitted, +/// @c false otherwise. +static bool DiagnoseVLAInCXXTypeTrait(Sema &S, const TypeSourceInfo *T, + clang::tok::TokenKind TypeTraitID) { + if (!T->getType()->isVariableArrayType()) + return false; + + S.Diag(T->getTypeLoc().getBeginLoc(), diag::err_vla_unsupported) + << 1 << TypeTraitID; + return true; +} + /// Check the completeness of a type in a unary type trait. /// /// If the particular type trait requires a complete type, tries to complete @@ -5188,7 +5202,9 @@ static bool HasNoThrowOperator(const RecordType *RT, OverloadedOperatorKind Op, } static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, - SourceLocation KeyLoc, QualType T) { + SourceLocation KeyLoc, + TypeSourceInfo *TInfo) { + QualType T = TInfo->getType(); assert(!T->isDependentType() && "Cannot evaluate traits of dependent type"); ASTContext &C = Self.Context; @@ -5205,21 +5221,13 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, case UTT_IsArray: return T->isArrayType(); case UTT_IsBoundedArray: - if (!T->isVariableArrayType()) { - return T->isArrayType() && !T->isIncompleteArrayType(); - } - - Self.Diag(KeyLoc, diag::err_vla_unsupported) - << 1 << tok::kw___is_bounded_array; - return false; + if (DiagnoseVLAInCXXTypeTrait(Self, TInfo, tok::kw___is_bounded_array)) + return false; + return T->isArrayType() && !T->isIncompleteArrayType(); case UTT_IsUnboundedArray: - if (!T->isVariableArrayType()) { - return T->isIncompleteArrayType(); - } - - Self.Diag(KeyLoc, diag::err_vla_unsupported) - << 1 << tok::kw___is_unbounded_array; - return false; + if (DiagnoseVLAInCXXTypeTrait(Self, TInfo, tok::kw___is_unbounded_array)) + return false; + return T->isIncompleteArrayType(); case UTT_IsPointer: return T->isAnyPointerType(); case UTT_IsNullPointer: @@ -5631,7 +5639,7 @@ static bool EvaluateBooleanTypeTrait(Sema &S, TypeTrait Kind, return false; if (Kind <= UTT_Last) - return EvaluateUnaryTypeTrait(S, Kind, KWLoc, Args[0]->getType()); + return EvaluateUnaryTypeTrait(S, Kind, KWLoc, Args[0]); // Evaluate ReferenceBindsToTemporary and ReferenceConstructsFromTemporary // alongside the IsConstructible traits to avoid duplication. @@ -6093,12 +6101,9 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, const TypeSourceI Self.RequireCompleteType(Rhs->getTypeLoc().getBeginLoc(), RhsT, diag::err_incomplete_type); - if (LhsT->isVariableArrayType()) - Self.Diag(Lhs->getTypeLoc().getBeginLoc(), diag::err_vla_unsupported) - << 1 << tok::kw___is_layout_compatible; - if (RhsT->isVariableArrayType()) - Self.Diag(Rhs->getTypeLoc().getBeginLoc(), diag::err_vla_unsupported) - << 1 << tok::kw___is_layout_compatible; + DiagnoseVLAInCXXTypeTrait(Self, Lhs, tok::kw___is_layout_compatible); + DiagnoseVLAInCXXTypeTrait(Self, Rhs, tok::kw___is_layout_compatible); + return Self.IsLayoutCompatible(LhsT, RhsT); } case BTT_IsPointerInterconvertibleBaseOf: { @@ -6108,12 +6113,10 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, const TypeSourceI diag::err_incomplete_type); } - if (LhsT->isVariableArrayType()) - Self.Diag(Lhs->getTypeLoc().getBeginLoc(), diag::err_vla_unsupported) - << 1 << tok::kw___is_pointer_interconvertible_base_of; - if (RhsT->isVariableArrayType()) - Self.Diag(Rhs->getTypeLoc().getBeginLoc(), diag::err_vla_unsupported) - << 1 << tok::kw___is_pointer_interconvertible_base_of; + DiagnoseVLAInCXXTypeTrait(Self, Lhs, + tok::kw___is_pointer_interconvertible_base_of); + DiagnoseVLAInCXXTypeTrait(Self, Rhs, + tok::kw___is_pointer_interconvertible_base_of); return Self.IsPointerInterconvertibleBaseOf(Lhs, Rhs); }