Skip to content

[clang] Track final substitution for Subst* AST nodes #132748

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions clang/include/clang/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -1795,10 +1795,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
QualType Wrapped, QualType Contained,
const HLSLAttributedResourceType::Attributes &Attrs);

QualType
getSubstTemplateTypeParmType(QualType Replacement, Decl *AssociatedDecl,
unsigned Index,
std::optional<unsigned> PackIndex) const;
QualType getSubstTemplateTypeParmType(QualType Replacement,
Decl *AssociatedDecl, unsigned Index,
std::optional<unsigned> PackIndex,
bool Final) const;
QualType getSubstTemplateTypeParmPackType(Decl *AssociatedDecl,
unsigned Index, bool Final,
const TemplateArgument &ArgPack);
Expand Down Expand Up @@ -2393,10 +2393,11 @@ class ASTContext : public RefCountedBase<ASTContext> {
TemplateName
getDependentTemplateName(const DependentTemplateStorage &Name) const;

TemplateName
getSubstTemplateTemplateParm(TemplateName replacement, Decl *AssociatedDecl,
unsigned Index,
std::optional<unsigned> PackIndex) const;
TemplateName getSubstTemplateTemplateParm(TemplateName replacement,
Decl *AssociatedDecl,
unsigned Index,
std::optional<unsigned> PackIndex,
bool Final) const;
TemplateName getSubstTemplateTemplateParmPack(const TemplateArgument &ArgPack,
Decl *AssociatedDecl,
unsigned Index,
Expand Down
25 changes: 20 additions & 5 deletions clang/include/clang/AST/ExprCXX.h
Original file line number Diff line number Diff line change
Expand Up @@ -4514,7 +4514,9 @@ class SubstNonTypeTemplateParmExpr : public Expr {
llvm::PointerIntPair<Decl *, 1, bool> AssociatedDeclAndRef;

unsigned Index : 15;
unsigned PackIndex : 16;
unsigned PackIndex : 15;
LLVM_PREFERRED_TYPE(bool)
unsigned Final : 1;

explicit SubstNonTypeTemplateParmExpr(EmptyShell Empty)
: Expr(SubstNonTypeTemplateParmExprClass, Empty) {}
Expand All @@ -4523,11 +4525,12 @@ class SubstNonTypeTemplateParmExpr : public Expr {
SubstNonTypeTemplateParmExpr(QualType Ty, ExprValueKind ValueKind,
SourceLocation Loc, Expr *Replacement,
Decl *AssociatedDecl, unsigned Index,
std::optional<unsigned> PackIndex, bool RefParam)
std::optional<unsigned> PackIndex, bool RefParam,
bool Final)
: Expr(SubstNonTypeTemplateParmExprClass, Ty, ValueKind, OK_Ordinary),
Replacement(Replacement),
AssociatedDeclAndRef(AssociatedDecl, RefParam), Index(Index),
PackIndex(PackIndex ? *PackIndex + 1 : 0) {
PackIndex(PackIndex ? *PackIndex + 1 : 0), Final(Final) {
assert(AssociatedDecl != nullptr);
SubstNonTypeTemplateParmExprBits.NameLoc = Loc;
setDependence(computeDependence(this));
Expand Down Expand Up @@ -4555,6 +4558,10 @@ class SubstNonTypeTemplateParmExpr : public Expr {
return PackIndex - 1;
}

// This substitution is Final, which means the substitution is fully
// sugared: it doesn't need to be resugared later.
bool getFinal() const { return Final; }

NonTypeTemplateParmDecl *getParameter() const;

bool isReferenceParameter() const { return AssociatedDeclAndRef.getInt(); }
Expand Down Expand Up @@ -4598,7 +4605,10 @@ class SubstNonTypeTemplateParmPackExpr : public Expr {
const TemplateArgument *Arguments;

/// The number of template arguments in \c Arguments.
unsigned NumArguments : 16;
unsigned NumArguments : 15;

LLVM_PREFERRED_TYPE(bool)
unsigned Final : 1;

unsigned Index : 16;

Expand All @@ -4612,7 +4622,8 @@ class SubstNonTypeTemplateParmPackExpr : public Expr {
SubstNonTypeTemplateParmPackExpr(QualType T, ExprValueKind ValueKind,
SourceLocation NameLoc,
const TemplateArgument &ArgPack,
Decl *AssociatedDecl, unsigned Index);
Decl *AssociatedDecl, unsigned Index,
bool Final);

/// A template-like entity which owns the whole pattern being substituted.
/// This will own a set of template parameters.
Expand All @@ -4622,6 +4633,10 @@ class SubstNonTypeTemplateParmPackExpr : public Expr {
/// This should match the result of `getParameterPack()->getIndex()`.
unsigned getIndex() const { return Index; }

// This substitution will be Final, which means the substitution will be fully
// sugared: it doesn't need to be resugared later.
bool getFinal() const { return Final; }

/// Retrieve the non-type template parameter pack being substituted.
NonTypeTemplateParmDecl *getParameterPack() const;

Expand Down
3 changes: 2 additions & 1 deletion clang/include/clang/AST/PropertiesBase.td
Original file line number Diff line number Diff line change
Expand Up @@ -730,8 +730,9 @@ let Class = PropertyTypeCase<TemplateName, "SubstTemplateTemplateParm"> in {
def : Property<"packIndex", Optional<UInt32>> {
let Read = [{ parm->getPackIndex() }];
}
def : Property<"final", Bool> { let Read = [{ parm->getFinal() }]; }
def : Creator<[{
return ctx.getSubstTemplateTemplateParm(replacement, associatedDecl, index, packIndex);
return ctx.getSubstTemplateTemplateParm(replacement, associatedDecl, index, packIndex, final);
}]>;
}
let Class = PropertyTypeCase<TemplateName, "SubstTemplateTemplateParmPack"> in {
Expand Down
17 changes: 12 additions & 5 deletions clang/include/clang/AST/TemplateName.h
Original file line number Diff line number Diff line change
Expand Up @@ -414,9 +414,11 @@ class SubstTemplateTemplateParmStorage

SubstTemplateTemplateParmStorage(TemplateName Replacement,
Decl *AssociatedDecl, unsigned Index,
std::optional<unsigned> PackIndex)
std::optional<unsigned> PackIndex,
bool Final)
: UncommonTemplateNameStorage(SubstTemplateTemplateParm, Index,
PackIndex ? *PackIndex + 1 : 0),
((PackIndex ? *PackIndex + 1 : 0) << 1) |
Final),
Replacement(Replacement), AssociatedDecl(AssociatedDecl) {
assert(AssociatedDecl != nullptr);
}
Expand All @@ -430,10 +432,15 @@ class SubstTemplateTemplateParmStorage
/// This should match the result of `getParameter()->getIndex()`.
unsigned getIndex() const { return Bits.Index; }

// This substitution is Final, which means the substitution is fully
// sugared: it doesn't need to be resugared later.
bool getFinal() const { return Bits.Data & 1; }

std::optional<unsigned> getPackIndex() const {
if (Bits.Data == 0)
auto Data = Bits.Data >> 1;
if (Data == 0)
return std::nullopt;
return Bits.Data - 1;
return Data - 1;
}

TemplateTemplateParmDecl *getParameter() const;
Expand All @@ -443,7 +450,7 @@ class SubstTemplateTemplateParmStorage

static void Profile(llvm::FoldingSetNodeID &ID, TemplateName Replacement,
Decl *AssociatedDecl, unsigned Index,
std::optional<unsigned> PackIndex);
std::optional<unsigned> PackIndex, bool Final);
};

class DeducedTemplateStorage : public UncommonTemplateNameStorage,
Expand Down
24 changes: 14 additions & 10 deletions clang/include/clang/AST/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -2158,12 +2158,15 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
// The index of the template parameter this substitution represents.
unsigned Index : 15;

LLVM_PREFERRED_TYPE(bool)
unsigned Final : 1;

/// Represents the index within a pack if this represents a substitution
/// from a pack expansion. This index starts at the end of the pack and
/// increments towards the beginning.
/// Positive non-zero number represents the index + 1.
/// Zero means this is not substituted from an expansion.
unsigned PackIndex : 16;
unsigned PackIndex : 15;
};

class SubstTemplateTypeParmPackTypeBitfields {
Expand Down Expand Up @@ -6397,7 +6400,8 @@ class SubstTemplateTypeParmType final
Decl *AssociatedDecl;

SubstTemplateTypeParmType(QualType Replacement, Decl *AssociatedDecl,
unsigned Index, std::optional<unsigned> PackIndex);
unsigned Index, std::optional<unsigned> PackIndex,
bool Final);

public:
/// Gets the type that was substituted for the template
Expand All @@ -6420,6 +6424,10 @@ class SubstTemplateTypeParmType final
/// This should match the result of `getReplacedParameter()->getIndex()`.
unsigned getIndex() const { return SubstTemplateTypeParmTypeBits.Index; }

// This substitution is Final, which means the substitution is fully
// sugared: it doesn't need to be resugared later.
unsigned getFinal() const { return SubstTemplateTypeParmTypeBits.Final; }

std::optional<unsigned> getPackIndex() const {
if (SubstTemplateTypeParmTypeBits.PackIndex == 0)
return std::nullopt;
Expand All @@ -6431,17 +6439,12 @@ class SubstTemplateTypeParmType final

void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getReplacementType(), getAssociatedDecl(), getIndex(),
getPackIndex());
getPackIndex(), getFinal());
}

static void Profile(llvm::FoldingSetNodeID &ID, QualType Replacement,
const Decl *AssociatedDecl, unsigned Index,
std::optional<unsigned> PackIndex) {
Replacement.Profile(ID);
ID.AddPointer(AssociatedDecl);
ID.AddInteger(Index);
ID.AddInteger(PackIndex ? *PackIndex - 1 : 0);
}
std::optional<unsigned> PackIndex, bool Final);

static bool classof(const Type *T) {
return T->getTypeClass() == SubstTemplateTypeParm;
Expand Down Expand Up @@ -6488,7 +6491,8 @@ class SubstTemplateTypeParmPackType : public Type, public llvm::FoldingSetNode {
/// This should match the result of `getReplacedParameter()->getIndex()`.
unsigned getIndex() const { return SubstTemplateTypeParmPackTypeBits.Index; }

// When true the substitution will be 'Final' (subst node won't be placed).
// This substitution will be Final, which means the substitution will be fully
// sugared: it doesn't need to be resugared later.
bool getFinal() const;

unsigned getNumArgs() const {
Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/AST/TypeProperties.td
Original file line number Diff line number Diff line change
Expand Up @@ -842,11 +842,11 @@ let Class = SubstTemplateTypeParmType in {
def : Property<"PackIndex", Optional<UInt32>> {
let Read = [{ node->getPackIndex() }];
}
def : Property<"Final", Bool> { let Read = [{ node->getFinal() }]; }

// The call to getCanonicalType here existed in ASTReader.cpp, too.
def : Creator<[{
return ctx.getSubstTemplateTypeParmType(
replacementType, associatedDecl, Index, PackIndex);
replacementType, associatedDecl, Index, PackIndex, Final);
}]>;
}

Expand Down
15 changes: 8 additions & 7 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5447,10 +5447,10 @@ QualType ASTContext::getHLSLAttributedResourceType(
/// Retrieve a substitution-result type.
QualType ASTContext::getSubstTemplateTypeParmType(
QualType Replacement, Decl *AssociatedDecl, unsigned Index,
std::optional<unsigned> PackIndex) const {
std::optional<unsigned> PackIndex, bool Final) const {
llvm::FoldingSetNodeID ID;
SubstTemplateTypeParmType::Profile(ID, Replacement, AssociatedDecl, Index,
PackIndex);
PackIndex, Final);
void *InsertPos = nullptr;
SubstTemplateTypeParmType *SubstParm =
SubstTemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos);
Expand All @@ -5460,7 +5460,7 @@ QualType ASTContext::getSubstTemplateTypeParmType(
!Replacement.isCanonical()),
alignof(SubstTemplateTypeParmType));
SubstParm = new (Mem) SubstTemplateTypeParmType(Replacement, AssociatedDecl,
Index, PackIndex);
Index, PackIndex, Final);
Types.push_back(SubstParm);
SubstTemplateTypeParmTypes.InsertNode(SubstParm, InsertPos);
}
Expand Down Expand Up @@ -10090,18 +10090,18 @@ ASTContext::getDependentTemplateName(const DependentTemplateStorage &S) const {

TemplateName ASTContext::getSubstTemplateTemplateParm(
TemplateName Replacement, Decl *AssociatedDecl, unsigned Index,
std::optional<unsigned> PackIndex) const {
std::optional<unsigned> PackIndex, bool Final) const {
llvm::FoldingSetNodeID ID;
SubstTemplateTemplateParmStorage::Profile(ID, Replacement, AssociatedDecl,
Index, PackIndex);
Index, PackIndex, Final);

void *insertPos = nullptr;
SubstTemplateTemplateParmStorage *subst
= SubstTemplateTemplateParms.FindNodeOrInsertPos(ID, insertPos);

if (!subst) {
subst = new (*this) SubstTemplateTemplateParmStorage(
Replacement, AssociatedDecl, Index, PackIndex);
Replacement, AssociatedDecl, Index, PackIndex, Final);
SubstTemplateTemplateParms.InsertNode(subst, insertPos);
}

Expand Down Expand Up @@ -14202,7 +14202,8 @@ static QualType getCommonSugarTypeNode(ASTContext &Ctx, const Type *X,
if (PackIndex != SY->getPackIndex())
return QualType();
return Ctx.getSubstTemplateTypeParmType(Ctx.getQualifiedType(Underlying),
CD, Index, PackIndex);
CD, Index, PackIndex,
SX->getFinal() && SY->getFinal());
}
case Type::ObjCTypeParam:
// FIXME: Try to merge these.
Expand Down
9 changes: 5 additions & 4 deletions clang/lib/AST/ASTImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1631,8 +1631,8 @@ ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmType(
return ToReplacementTypeOrErr.takeError();

return Importer.getToContext().getSubstTemplateTypeParmType(
*ToReplacementTypeOrErr, *ReplacedOrErr, T->getIndex(),
T->getPackIndex());
*ToReplacementTypeOrErr, *ReplacedOrErr, T->getIndex(), T->getPackIndex(),
T->getFinal());
}

ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmPackType(
Expand Down Expand Up @@ -8937,7 +8937,8 @@ ExpectedStmt ASTNodeImporter::VisitSubstNonTypeTemplateParmExpr(

return new (Importer.getToContext()) SubstNonTypeTemplateParmExpr(
ToType, E->getValueKind(), ToExprLoc, ToReplacement, ToAssociatedDecl,
E->getIndex(), E->getPackIndex(), E->isReferenceParameter());
E->getIndex(), E->getPackIndex(), E->isReferenceParameter(),
E->getFinal());
}

ExpectedStmt ASTNodeImporter::VisitTypeTraitExpr(TypeTraitExpr *E) {
Expand Down Expand Up @@ -9932,7 +9933,7 @@ Expected<TemplateName> ASTImporter::Import(TemplateName From) {

return ToContext.getSubstTemplateTemplateParm(
*ReplacementOrErr, *AssociatedDeclOrErr, Subst->getIndex(),
Subst->getPackIndex());
Subst->getPackIndex(), Subst->getFinal());
}

case TemplateName::SubstTemplateTemplateParmPack: {
Expand Down
6 changes: 4 additions & 2 deletions clang/lib/AST/ExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1760,10 +1760,12 @@ QualType SubstNonTypeTemplateParmExpr::getParameterType(

SubstNonTypeTemplateParmPackExpr::SubstNonTypeTemplateParmPackExpr(
QualType T, ExprValueKind ValueKind, SourceLocation NameLoc,
const TemplateArgument &ArgPack, Decl *AssociatedDecl, unsigned Index)
const TemplateArgument &ArgPack, Decl *AssociatedDecl, unsigned Index,
bool Final)
: Expr(SubstNonTypeTemplateParmPackExprClass, T, ValueKind, OK_Ordinary),
AssociatedDecl(AssociatedDecl), Arguments(ArgPack.pack_begin()),
NumArguments(ArgPack.pack_size()), Index(Index), NameLoc(NameLoc) {
NumArguments(ArgPack.pack_size()), Final(Final), Index(Index),
NameLoc(NameLoc) {
assert(AssociatedDecl != nullptr);
setDependence(ExprDependence::TypeValueInstantiation |
ExprDependence::UnexpandedPack);
Expand Down
6 changes: 4 additions & 2 deletions clang/lib/AST/TemplateName.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,16 +77,18 @@ SubstTemplateTemplateParmStorage::getParameter() const {
}

void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, Replacement, getAssociatedDecl(), getIndex(), getPackIndex());
Profile(ID, Replacement, getAssociatedDecl(), getIndex(), getPackIndex(),
getFinal());
}

void SubstTemplateTemplateParmStorage::Profile(
llvm::FoldingSetNodeID &ID, TemplateName Replacement, Decl *AssociatedDecl,
unsigned Index, std::optional<unsigned> PackIndex) {
unsigned Index, std::optional<unsigned> PackIndex, bool Final) {
Replacement.Profile(ID);
ID.AddPointer(AssociatedDecl);
ID.AddInteger(Index);
ID.AddInteger(PackIndex ? *PackIndex + 1 : 0);
ID.AddBoolean(Final);
}

SubstTemplateTemplateParmPackStorage::SubstTemplateTemplateParmPackStorage(
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/AST/TextNodeDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1298,6 +1298,8 @@ void TextNodeDumper::dumpBareTemplateName(TemplateName TN) {
OS << " index " << STS->getIndex();
if (std::optional<unsigned int> PackIndex = STS->getPackIndex())
OS << " pack_index " << *PackIndex;
if (STS->getFinal())
OS << " final";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as final is a keyword in C++ I wonder if we can find a better name for this. I certainly wouldn't see this in an AST and know what it means. I wonder if we should find a better name than final throughout this patch. Something like, FullySugared or something? Though open to other/better names.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am open for suggestions, but I'd prefer to change this in a follow up, since the term is existing and this would make the patch much larger.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FullySugared seems fine to me, unless you have a better idea. I would be ok with changing the name in a followup, which wouldn't really require review once we agree on a name.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FullySugared seems fine to me, unless you have a better idea. I would be ok with changing the name in a followup, which wouldn't really require review once we agree on a name.

+1

if (const TemplateTemplateParmDecl *P = STS->getParameter())
AddChild("parameter", [=] { Visit(P); });
dumpDeclRef(STS->getAssociatedDecl(), "associated");
Expand Down Expand Up @@ -2124,6 +2126,8 @@ void TextNodeDumper::VisitSubstTemplateTypeParmType(
VisitTemplateTypeParmDecl(T->getReplacedParameter());
if (auto PackIndex = T->getPackIndex())
OS << " pack_index " << *PackIndex;
if (T->getFinal())
OS << " final";
}

void TextNodeDumper::VisitSubstTemplateTypeParmPackType(
Expand Down
Loading