Skip to content

Commit aacdc65

Browse files
authored
[Clang] Preserve the ExpandsToEmpty flag in PackIndexingType (llvm#107181)
Similar to PackIndexingExpr, we should avoid another round of transformation of the pattern if the pattern has already turned out to be an empty pack. As an outcome, the empty SubstTemplateTypeParmPackType won't occur, and we don't need to collect any unexpanded packs. Fixes llvm#105903
1 parent e99eb89 commit aacdc65

File tree

7 files changed

+39
-16
lines changed

7 files changed

+39
-16
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ Bug Fixes to C++ Support
345345
- Fixed a constraint comparison bug for friend declarations. (#GH78101)
346346
- Fix handling of ``_`` as the name of a lambda's init capture variable. (#GH107024)
347347
- Fix an issue with dependent source location expressions (#GH106428), (#GH81155), (#GH80210), (#GH85373)
348-
348+
- Fixed a bug in the substitution of empty pack indexing types. (#GH105903)
349349

350350
Bug Fixes to AST Handling
351351
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/include/clang/AST/Type.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5828,12 +5828,15 @@ class PackIndexingType final
58285828
QualType Pattern;
58295829
Expr *IndexExpr;
58305830

5831-
unsigned Size;
5831+
unsigned Size : 31;
5832+
5833+
LLVM_PREFERRED_TYPE(bool)
5834+
unsigned ExpandsToEmptyPack : 1;
58325835

58335836
protected:
58345837
friend class ASTContext; // ASTContext creates these.
58355838
PackIndexingType(const ASTContext &Context, QualType Canonical,
5836-
QualType Pattern, Expr *IndexExpr,
5839+
QualType Pattern, Expr *IndexExpr, bool ExpandsToEmptyPack,
58375840
ArrayRef<QualType> Expansions = {});
58385841

58395842
public:
@@ -5857,6 +5860,8 @@ class PackIndexingType final
58575860

58585861
bool hasSelectedType() const { return getSelectedIndex() != std::nullopt; }
58595862

5863+
bool expandsToEmptyPack() const { return ExpandsToEmptyPack; }
5864+
58605865
ArrayRef<QualType> getExpansions() const {
58615866
return {getExpansionsPtr(), Size};
58625867
}
@@ -5869,10 +5874,10 @@ class PackIndexingType final
58695874
if (hasSelectedType())
58705875
getSelectedType().Profile(ID);
58715876
else
5872-
Profile(ID, Context, getPattern(), getIndexExpr());
5877+
Profile(ID, Context, getPattern(), getIndexExpr(), expandsToEmptyPack());
58735878
}
58745879
static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
5875-
QualType Pattern, Expr *E);
5880+
QualType Pattern, Expr *E, bool ExpandsToEmptyPack);
58765881

58775882
private:
58785883
const QualType *getExpansionsPtr() const {

clang/include/clang/AST/TypeProperties.td

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,9 +473,12 @@ let Class = PackIndexingType in {
473473
def : Property<"indexExpression", ExprRef> {
474474
let Read = [{ node->getIndexExpr() }];
475475
}
476+
def : Property<"expandsToEmptyPack", Bool> {
477+
let Read = [{ node->expandsToEmptyPack() }];
478+
}
476479

477480
def : Creator<[{
478-
return ctx.getPackIndexingType(pattern, indexExpression);
481+
return ctx.getPackIndexingType(pattern, indexExpression, expandsToEmptyPack);
479482
}]>;
480483
}
481484

clang/lib/AST/ASTContext.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6188,20 +6188,22 @@ QualType ASTContext::getPackIndexingType(QualType Pattern, Expr *IndexExpr,
61886188
ArrayRef<QualType> Expansions,
61896189
int Index) const {
61906190
QualType Canonical;
6191+
bool ExpandsToEmptyPack = FullySubstituted && Expansions.empty();
61916192
if (FullySubstituted && Index != -1) {
61926193
Canonical = getCanonicalType(Expansions[Index]);
61936194
} else {
61946195
llvm::FoldingSetNodeID ID;
6195-
PackIndexingType::Profile(ID, *this, Pattern, IndexExpr);
6196+
PackIndexingType::Profile(ID, *this, Pattern, IndexExpr,
6197+
ExpandsToEmptyPack);
61966198
void *InsertPos = nullptr;
61976199
PackIndexingType *Canon =
61986200
DependentPackIndexingTypes.FindNodeOrInsertPos(ID, InsertPos);
61996201
if (!Canon) {
62006202
void *Mem = Allocate(
62016203
PackIndexingType::totalSizeToAlloc<QualType>(Expansions.size()),
62026204
TypeAlignment);
6203-
Canon = new (Mem)
6204-
PackIndexingType(*this, QualType(), Pattern, IndexExpr, Expansions);
6205+
Canon = new (Mem) PackIndexingType(*this, QualType(), Pattern, IndexExpr,
6206+
ExpandsToEmptyPack, Expansions);
62056207
DependentPackIndexingTypes.InsertNode(Canon, InsertPos);
62066208
}
62076209
Canonical = QualType(Canon, 0);
@@ -6210,8 +6212,8 @@ QualType ASTContext::getPackIndexingType(QualType Pattern, Expr *IndexExpr,
62106212
void *Mem =
62116213
Allocate(PackIndexingType::totalSizeToAlloc<QualType>(Expansions.size()),
62126214
TypeAlignment);
6213-
auto *T = new (Mem)
6214-
PackIndexingType(*this, Canonical, Pattern, IndexExpr, Expansions);
6215+
auto *T = new (Mem) PackIndexingType(*this, Canonical, Pattern, IndexExpr,
6216+
ExpandsToEmptyPack, Expansions);
62156217
Types.push_back(T);
62166218
return QualType(T, 0);
62176219
}

clang/lib/AST/Type.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3992,12 +3992,12 @@ void DependentDecltypeType::Profile(llvm::FoldingSetNodeID &ID,
39923992

39933993
PackIndexingType::PackIndexingType(const ASTContext &Context,
39943994
QualType Canonical, QualType Pattern,
3995-
Expr *IndexExpr,
3995+
Expr *IndexExpr, bool ExpandsToEmptyPack,
39963996
ArrayRef<QualType> Expansions)
39973997
: Type(PackIndexing, Canonical,
39983998
computeDependence(Pattern, IndexExpr, Expansions)),
39993999
Context(Context), Pattern(Pattern), IndexExpr(IndexExpr),
4000-
Size(Expansions.size()) {
4000+
Size(Expansions.size()), ExpandsToEmptyPack(ExpandsToEmptyPack) {
40014001

40024002
std::uninitialized_copy(Expansions.begin(), Expansions.end(),
40034003
getTrailingObjects<QualType>());
@@ -4042,9 +4042,10 @@ PackIndexingType::computeDependence(QualType Pattern, Expr *IndexExpr,
40424042

40434043
void PackIndexingType::Profile(llvm::FoldingSetNodeID &ID,
40444044
const ASTContext &Context, QualType Pattern,
4045-
Expr *E) {
4045+
Expr *E, bool ExpandsToEmptyPack) {
40464046
Pattern.Profile(ID);
40474047
E->Profile(ID, Context, true);
4048+
ID.AddBoolean(ExpandsToEmptyPack);
40484049
}
40494050

40504051
UnaryTransformType::UnaryTransformType(QualType BaseType,

clang/lib/Sema/TreeTransform.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6687,10 +6687,10 @@ TreeTransform<Derived>::TransformPackIndexingType(TypeLocBuilder &TLB,
66876687
bool NotYetExpanded = Types.empty();
66886688
bool FullySubstituted = true;
66896689

6690-
if (Types.empty())
6690+
if (Types.empty() && !PIT->expandsToEmptyPack())
66916691
Types = llvm::ArrayRef<QualType>(&Pattern, 1);
66926692

6693-
for (const QualType &T : Types) {
6693+
for (QualType T : Types) {
66946694
if (!T->containsUnexpandedParameterPack()) {
66956695
QualType Transformed = getDerived().TransformType(T);
66966696
if (Transformed.isNull())

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,4 +258,16 @@ void f() {
258258
vars<0>::x<0>();
259259
}
260260

261+
} // namespace GH105900
262+
263+
namespace GH105903 {
264+
265+
template <typename... opts> struct temp {
266+
template <unsigned s> static auto x() -> opts... [s] {} // expected-note {{invalid index 0 for pack 'opts' of size 0}}
267+
};
268+
269+
void f() {
270+
temp<>::x<0>(); // expected-error {{no matching}}
261271
}
272+
273+
} // namespace GH105903

0 commit comments

Comments
 (0)