aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaTemplateVariadic.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaTemplateVariadic.cpp')
-rw-r--r--clang/lib/Sema/SemaTemplateVariadic.cpp72
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 {