mirror of
https://github.com/intel/llvm.git
synced 2026-01-24 17:01:00 +08:00
[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:
@@ -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
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}]>;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user