Skip to content

Commit 72fc2fc

Browse files
committed
[clang] PackIndexingExpr
1 parent 91a28dc commit 72fc2fc

File tree

6 files changed

+77
-16
lines changed

6 files changed

+77
-16
lines changed

clang/include/clang/AST/ExprCXX.h

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4417,8 +4417,9 @@ class PackIndexingExpr final
44174417
public:
44184418
static PackIndexingExpr *Create(ASTContext &Context,
44194419
SourceLocation EllipsisLoc,
4420-
SourceLocation RSquareLoc, Expr *PackIdExpr,
4421-
Expr *IndexExpr, std::optional<int64_t> Index,
4420+
SourceLocation RSquareLoc, QualType Type,
4421+
Expr *PackIdExpr, Expr *IndexExpr,
4422+
std::optional<int64_t> Index,
44224423
ArrayRef<Expr *> SubstitutedExprs = {},
44234424
bool ExpandedToEmptyPack = false);
44244425
static PackIndexingExpr *CreateDeserialized(ASTContext &Context,
@@ -4465,6 +4466,28 @@ class PackIndexingExpr final
44654466
return {getTrailingObjects<Expr *>(), TransformedExpressions};
44664467
}
44674468

4469+
/// Returns the number of expansion, if known.
4470+
/// Note we have four states for pack expansion,
4471+
///
4472+
/// 1) The PackIndexingExpr has never been expanded. In this case,
4473+
/// \code expandsToEmptyPack() == false && getNumExpansions() == nullopt \endcode
4474+
///
4475+
/// 2) The PackIndexingExpr has been expanded, but it expands to empty.
4476+
/// \code expandsToEmptyPack() == true && getNumExpansions() == 0 \endcode
4477+
///
4478+
/// 3) The PackIndexingExpr has been expanded, but the expansion should be
4479+
/// held off because the expansion size is unknown.
4480+
/// \code
4481+
/// expandsToEmptyPack() == false && getNumExpansions() == nullopt
4482+
/// \endcode
4483+
///
4484+
/// 4) The PackIndexingExpr has been expanded to non-dependent expressions.
4485+
/// \code
4486+
/// expandsToEmptyPack() == false && getNumExpansions() ==
4487+
/// getExpressions().size()
4488+
/// \endcode
4489+
std::optional<unsigned> getNumExpansions() const;
4490+
44684491
static bool classof(const Stmt *T) {
44694492
return T->getStmtClass() == PackIndexingExprClass;
44704493
}

clang/lib/AST/ComputeDependence.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,7 @@ ExprDependence clang::computeDependence(PackIndexingExpr *E) {
385385
ExprDependence::Instantiation;
386386

387387
ArrayRef<Expr *> Exprs = E->getExpressions();
388-
if (Exprs.empty())
388+
if (!E->getNumExpansions())
389389
D |= PatternDep | ExprDependence::Instantiation;
390390

391391
else if (!E->getIndexExpr()->isInstantiationDependent()) {

clang/lib/AST/ExprCXX.cpp

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1714,13 +1714,9 @@ NonTypeTemplateParmDecl *SubstNonTypeTemplateParmExpr::getParameter() const {
17141714

17151715
PackIndexingExpr *PackIndexingExpr::Create(
17161716
ASTContext &Context, SourceLocation EllipsisLoc, SourceLocation RSquareLoc,
1717-
Expr *PackIdExpr, Expr *IndexExpr, std::optional<int64_t> Index,
1718-
ArrayRef<Expr *> SubstitutedExprs, bool ExpandedToEmptyPack) {
1719-
QualType Type;
1720-
if (Index && !SubstitutedExprs.empty())
1721-
Type = SubstitutedExprs[*Index]->getType();
1722-
else
1723-
Type = Context.DependentTy;
1717+
QualType Type, Expr *PackIdExpr, Expr *IndexExpr,
1718+
std::optional<int64_t> Index, ArrayRef<Expr *> SubstitutedExprs,
1719+
bool ExpandedToEmptyPack) {
17241720

17251721
void *Storage =
17261722
Context.Allocate(totalSizeToAlloc<Expr *>(SubstitutedExprs.size()));
@@ -1729,6 +1725,17 @@ PackIndexingExpr *PackIndexingExpr::Create(
17291725
SubstitutedExprs, ExpandedToEmptyPack);
17301726
}
17311727

1728+
std::optional<unsigned> PackIndexingExpr::getNumExpansions() const {
1729+
if (!TransformedExpressions && !expandsToEmptyPack())
1730+
return std::nullopt;
1731+
if (llvm::any_of(getExpressions(), [](Expr *E) {
1732+
return isa<PackExpansionExpr>(E) &&
1733+
!cast<PackExpansionExpr>(E)->getNumExpansions();
1734+
}))
1735+
return std::nullopt;
1736+
return TransformedExpressions;
1737+
}
1738+
17321739
NamedDecl *PackIndexingExpr::getPackDecl() const {
17331740
if (auto *D = dyn_cast<DeclRefExpr>(getPackIdExpression()); D) {
17341741
NamedDecl *ND = dyn_cast<NamedDecl>(D->getDecl());

clang/lib/Sema/SemaTemplateVariadic.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,16 +1121,29 @@ Sema::BuildPackIndexingExpr(Expr *PackExpression, SourceLocation EllipsisLoc,
11211121
IndexExpr = Res.get();
11221122
}
11231123

1124-
if (Index && (!ExpandedExprs.empty() || EmptyPack)) {
1124+
bool ContainsUnexpandedParameterPack =
1125+
llvm::any_of(ExpandedExprs, [](Expr *E) {
1126+
return isa<PackExpansionExpr>(E) &&
1127+
!cast<PackExpansionExpr>(E)->getNumExpansions();
1128+
});
1129+
1130+
if (!ContainsUnexpandedParameterPack && Index &&
1131+
(!ExpandedExprs.empty() || EmptyPack)) {
11251132
if (*Index < 0 || EmptyPack || *Index >= int64_t(ExpandedExprs.size())) {
11261133
Diag(PackExpression->getBeginLoc(), diag::err_pack_index_out_of_bound)
11271134
<< *Index << PackExpression << ExpandedExprs.size();
11281135
return ExprError();
11291136
}
11301137
}
11311138

1139+
QualType Type;
1140+
if (!ContainsUnexpandedParameterPack && Index && !ExpandedExprs.empty())
1141+
Type = ExpandedExprs[*Index]->getType();
1142+
else
1143+
Type = Context.DependentTy;
1144+
11321145
return PackIndexingExpr::Create(getASTContext(), EllipsisLoc, RSquareLoc,
1133-
PackExpression, IndexExpr, Index,
1146+
Type, PackExpression, IndexExpr, Index,
11341147
ExpandedExprs, EmptyPack);
11351148
}
11361149

clang/lib/Sema/TreeTransform.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15113,8 +15113,7 @@ TreeTransform<Derived>::TransformPackIndexingExpr(PackIndexingExpr *E) {
1511315113
// be expanded.
1511415114
bool ShouldExpand = true;
1511515115
bool RetainExpansion = false;
15116-
std::optional<unsigned> OrigNumExpansions;
15117-
std::optional<unsigned> NumExpansions = OrigNumExpansions;
15116+
std::optional<unsigned> NumExpansions;
1511815117
if (getDerived().TryExpandParameterPacks(
1511915118
E->getEllipsisLoc(), Pattern->getSourceRange(), Unexpanded,
1512015119
ShouldExpand, RetainExpansion, NumExpansions))
@@ -15135,7 +15134,7 @@ TreeTransform<Derived>::TransformPackIndexingExpr(PackIndexingExpr *E) {
1513515134
return true;
1513615135
if (Out.get()->containsUnexpandedParameterPack()) {
1513715136
Out = getDerived().RebuildPackExpansion(Out.get(), E->getEllipsisLoc(),
15138-
OrigNumExpansions);
15137+
/*NumExpansions=*/std::nullopt);
1513915138
if (Out.isInvalid())
1514015139
return true;
1514115140
}
@@ -15151,7 +15150,7 @@ TreeTransform<Derived>::TransformPackIndexingExpr(PackIndexingExpr *E) {
1515115150
return true;
1515215151

1515315152
Out = getDerived().RebuildPackExpansion(Out.get(), E->getEllipsisLoc(),
15154-
OrigNumExpansions);
15153+
/*NumExpansions=*/std::nullopt);
1515515154
if (Out.isInvalid())
1515615155
return true;
1515715156
ExpandedExprs.push_back(Out.get());

clang/test/SemaCXX/cxx2c-pack-indexing.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,3 +231,22 @@ struct type_info {
231231
namespace GH93650 {
232232
auto func(auto... inputArgs) { return typeid(inputArgs...[0]); }
233233
} // namespace GH93650
234+
235+
namespace init_capture_pack {
236+
237+
void init_capture() {
238+
auto L = [](auto... x) {
239+
return [x...](auto... y) {
240+
return [... w = y]() {
241+
return w...[3];
242+
};
243+
};
244+
};
245+
static_assert(L()(0, 1, 2, 3)() == 3);
246+
L()('a', 'b', 'c')();
247+
// expected-error@-6 {{invalid index 3 for pack w of size 3}}
248+
// expected-note@-8 {{while substituting}}
249+
// expected-note@-3 {{requested here}}
250+
}
251+
252+
}

0 commit comments

Comments
 (0)