[Clang] Preserve the ExpandsToEmpty flag in PackIndexingType (#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 https://github.com/llvm/llvm-project/issues/105903
This commit is contained in:
Younan Zhang
2024-09-04 16:34:27 +08:00
committed by GitHub
parent e99eb89d5d
commit aacdc657fc
7 changed files with 39 additions and 16 deletions

View File

@@ -345,7 +345,7 @@ Bug Fixes to C++ Support
- Fixed a constraint comparison bug for friend declarations. (#GH78101)
- Fix handling of ``_`` as the name of a lambda's init capture variable. (#GH107024)
- Fix an issue with dependent source location expressions (#GH106428), (#GH81155), (#GH80210), (#GH85373)
- Fixed a bug in the substitution of empty pack indexing types. (#GH105903)
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@@ -5828,12 +5828,15 @@ class PackIndexingType final
QualType Pattern;
Expr *IndexExpr;
unsigned Size;
unsigned Size : 31;
LLVM_PREFERRED_TYPE(bool)
unsigned ExpandsToEmptyPack : 1;
protected:
friend class ASTContext; // ASTContext creates these.
PackIndexingType(const ASTContext &Context, QualType Canonical,
QualType Pattern, Expr *IndexExpr,
QualType Pattern, Expr *IndexExpr, bool ExpandsToEmptyPack,
ArrayRef<QualType> Expansions = {});
public:
@@ -5857,6 +5860,8 @@ public:
bool hasSelectedType() const { return getSelectedIndex() != std::nullopt; }
bool expandsToEmptyPack() const { return ExpandsToEmptyPack; }
ArrayRef<QualType> getExpansions() const {
return {getExpansionsPtr(), Size};
}
@@ -5869,10 +5874,10 @@ public:
if (hasSelectedType())
getSelectedType().Profile(ID);
else
Profile(ID, Context, getPattern(), getIndexExpr());
Profile(ID, Context, getPattern(), getIndexExpr(), expandsToEmptyPack());
}
static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
QualType Pattern, Expr *E);
QualType Pattern, Expr *E, bool ExpandsToEmptyPack);
private:
const QualType *getExpansionsPtr() const {

View File

@@ -473,9 +473,12 @@ let Class = PackIndexingType in {
def : Property<"indexExpression", ExprRef> {
let Read = [{ node->getIndexExpr() }];
}
def : Property<"expandsToEmptyPack", Bool> {
let Read = [{ node->expandsToEmptyPack() }];
}
def : Creator<[{
return ctx.getPackIndexingType(pattern, indexExpression);
return ctx.getPackIndexingType(pattern, indexExpression, expandsToEmptyPack);
}]>;
}

View File

@@ -6188,11 +6188,13 @@ QualType ASTContext::getPackIndexingType(QualType Pattern, Expr *IndexExpr,
ArrayRef<QualType> Expansions,
int Index) const {
QualType Canonical;
bool ExpandsToEmptyPack = FullySubstituted && Expansions.empty();
if (FullySubstituted && Index != -1) {
Canonical = getCanonicalType(Expansions[Index]);
} else {
llvm::FoldingSetNodeID ID;
PackIndexingType::Profile(ID, *this, Pattern, IndexExpr);
PackIndexingType::Profile(ID, *this, Pattern, IndexExpr,
ExpandsToEmptyPack);
void *InsertPos = nullptr;
PackIndexingType *Canon =
DependentPackIndexingTypes.FindNodeOrInsertPos(ID, InsertPos);
@@ -6200,8 +6202,8 @@ QualType ASTContext::getPackIndexingType(QualType Pattern, Expr *IndexExpr,
void *Mem = Allocate(
PackIndexingType::totalSizeToAlloc<QualType>(Expansions.size()),
TypeAlignment);
Canon = new (Mem)
PackIndexingType(*this, QualType(), Pattern, IndexExpr, Expansions);
Canon = new (Mem) PackIndexingType(*this, QualType(), Pattern, IndexExpr,
ExpandsToEmptyPack, Expansions);
DependentPackIndexingTypes.InsertNode(Canon, InsertPos);
}
Canonical = QualType(Canon, 0);
@@ -6210,8 +6212,8 @@ QualType ASTContext::getPackIndexingType(QualType Pattern, Expr *IndexExpr,
void *Mem =
Allocate(PackIndexingType::totalSizeToAlloc<QualType>(Expansions.size()),
TypeAlignment);
auto *T = new (Mem)
PackIndexingType(*this, Canonical, Pattern, IndexExpr, Expansions);
auto *T = new (Mem) PackIndexingType(*this, Canonical, Pattern, IndexExpr,
ExpandsToEmptyPack, Expansions);
Types.push_back(T);
return QualType(T, 0);
}

View File

@@ -3992,12 +3992,12 @@ void DependentDecltypeType::Profile(llvm::FoldingSetNodeID &ID,
PackIndexingType::PackIndexingType(const ASTContext &Context,
QualType Canonical, QualType Pattern,
Expr *IndexExpr,
Expr *IndexExpr, bool ExpandsToEmptyPack,
ArrayRef<QualType> Expansions)
: Type(PackIndexing, Canonical,
computeDependence(Pattern, IndexExpr, Expansions)),
Context(Context), Pattern(Pattern), IndexExpr(IndexExpr),
Size(Expansions.size()) {
Size(Expansions.size()), ExpandsToEmptyPack(ExpandsToEmptyPack) {
std::uninitialized_copy(Expansions.begin(), Expansions.end(),
getTrailingObjects<QualType>());
@@ -4042,9 +4042,10 @@ PackIndexingType::computeDependence(QualType Pattern, Expr *IndexExpr,
void PackIndexingType::Profile(llvm::FoldingSetNodeID &ID,
const ASTContext &Context, QualType Pattern,
Expr *E) {
Expr *E, bool ExpandsToEmptyPack) {
Pattern.Profile(ID);
E->Profile(ID, Context, true);
ID.AddBoolean(ExpandsToEmptyPack);
}
UnaryTransformType::UnaryTransformType(QualType BaseType,

View File

@@ -6687,10 +6687,10 @@ TreeTransform<Derived>::TransformPackIndexingType(TypeLocBuilder &TLB,
bool NotYetExpanded = Types.empty();
bool FullySubstituted = true;
if (Types.empty())
if (Types.empty() && !PIT->expandsToEmptyPack())
Types = llvm::ArrayRef<QualType>(&Pattern, 1);
for (const QualType &T : Types) {
for (QualType T : Types) {
if (!T->containsUnexpandedParameterPack()) {
QualType Transformed = getDerived().TransformType(T);
if (Transformed.isNull())

View File

@@ -258,4 +258,16 @@ void f() {
vars<0>::x<0>();
}
} // namespace GH105900
namespace GH105903 {
template <typename... opts> struct temp {
template <unsigned s> static auto x() -> opts... [s] {} // expected-note {{invalid index 0 for pack 'opts' of size 0}}
};
void f() {
temp<>::x<0>(); // expected-error {{no matching}}
}
} // namespace GH105903