diff options
Diffstat (limited to 'clang/lib/Sema/SemaTemplateVariadic.cpp')
-rw-r--r-- | clang/lib/Sema/SemaTemplateVariadic.cpp | 72 |
1 files changed, 70 insertions, 2 deletions
diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp index 4a7872b..903fbfd 100644 --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -184,6 +184,15 @@ namespace { bool TraversePackExpansionTypeLoc(PackExpansionTypeLoc TL) { return true; } bool TraversePackExpansionExpr(PackExpansionExpr *E) { return true; } bool TraverseCXXFoldExpr(CXXFoldExpr *E) { return true; } + bool TraversePackIndexingExpr(PackIndexingExpr *E) { + return inherited::TraverseStmt(E->getIndexExpr()); + } + bool TraversePackIndexingType(PackIndexingType *E) { + return inherited::TraverseStmt(E->getIndexExpr()); + } + bool TraversePackIndexingTypeLoc(PackIndexingTypeLoc TL) { + return inherited::TraverseStmt(TL.getIndexExpr()); + } ///@} @@ -865,6 +874,7 @@ std::optional<unsigned> Sema::getNumArgumentsInExpansion( bool Sema::containsUnexpandedParameterPacks(Declarator &D) { const DeclSpec &DS = D.getDeclSpec(); switch (DS.getTypeSpecType()) { + case TST_typename_pack_indexing: case TST_typename: case TST_typeof_unqualType: case TST_typeofType: @@ -1050,8 +1060,7 @@ ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S, } if (!ParameterPack || !ParameterPack->isParameterPack()) { - Diag(NameLoc, diag::err_sizeof_pack_no_pack_name) - << &Name; + Diag(NameLoc, diag::err_expected_name_of_pack) << &Name; return ExprError(); } @@ -1061,6 +1070,65 @@ ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S, RParenLoc); } +static bool isParameterPack(Expr *PackExpression) { + if (auto *D = dyn_cast<DeclRefExpr>(PackExpression); D) { + ValueDecl *VD = D->getDecl(); + return VD->isParameterPack(); + } + return false; +} + +ExprResult Sema::ActOnPackIndexingExpr(Scope *S, Expr *PackExpression, + SourceLocation EllipsisLoc, + SourceLocation LSquareLoc, + Expr *IndexExpr, + SourceLocation RSquareLoc) { + bool isParameterPack = ::isParameterPack(PackExpression); + if (!isParameterPack) { + CorrectDelayedTyposInExpr(IndexExpr); + Diag(PackExpression->getBeginLoc(), diag::err_expected_name_of_pack) + << PackExpression; + return ExprError(); + } + ExprResult Res = + BuildPackIndexingExpr(PackExpression, EllipsisLoc, IndexExpr, RSquareLoc); + if (!Res.isInvalid()) + Diag(Res.get()->getBeginLoc(), getLangOpts().CPlusPlus26 + ? diag::warn_cxx23_pack_indexing + : diag::ext_pack_indexing); + return Res; +} + +ExprResult +Sema::BuildPackIndexingExpr(Expr *PackExpression, SourceLocation EllipsisLoc, + Expr *IndexExpr, SourceLocation RSquareLoc, + ArrayRef<Expr *> ExpandedExprs, bool EmptyPack) { + + std::optional<int64_t> Index; + if (!IndexExpr->isInstantiationDependent()) { + llvm::APSInt Value(Context.getIntWidth(Context.getSizeType())); + + ExprResult Res = CheckConvertedConstantExpression( + IndexExpr, Context.getSizeType(), Value, CCEK_ArrayBound); + if (!Res.isUsable()) + return ExprError(); + Index = Value.getExtValue(); + IndexExpr = Res.get(); + } + + if (Index && (!ExpandedExprs.empty() || EmptyPack)) { + if (*Index < 0 || EmptyPack || *Index >= int64_t(ExpandedExprs.size())) { + Diag(PackExpression->getBeginLoc(), diag::err_pack_index_out_of_bound) + << *Index << PackExpression << ExpandedExprs.size(); + return ExprError(); + } + } + + return PackIndexingExpr::Create(getASTContext(), EllipsisLoc, RSquareLoc, + PackExpression, IndexExpr, Index, + ExpandedExprs); +} + TemplateArgumentLoc Sema::getTemplateArgumentPackExpansionPattern( TemplateArgumentLoc OrigLoc, SourceLocation &Ellipsis, std::optional<unsigned> &NumExpansions) const { |