diff options
author | cor3ntin <corentinjabot@gmail.com> | 2024-01-27 10:23:38 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-01-27 10:23:38 +0100 |
commit | ad1a65fcacda8794e2f1fa3e1dec1c1b7813422c (patch) | |
tree | ee68f0f3f24c7dfaa09a2b75dc5427d7f11b6a15 /clang/lib/Sema/SemaTemplateVariadic.cpp | |
parent | 1f13203029333ac99cc9844b8b6915aae3fc0902 (diff) | |
download | llvm-ad1a65fcacda8794e2f1fa3e1dec1c1b7813422c.zip llvm-ad1a65fcacda8794e2f1fa3e1dec1c1b7813422c.tar.gz llvm-ad1a65fcacda8794e2f1fa3e1dec1c1b7813422c.tar.bz2 |
[Clang][C++26] Implement Pack Indexing (P2662R3). (#72644)
Implements https://isocpp.org/files/papers/P2662R3.pdf
The feature is exposed as an extension in older language modes.
Mangling is not yet supported and that is something we will have to do before release.
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 { |