[clang] f302f35 - [clang] Track final substitution for Subst* AST nodes (#132748)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Apr 2 15:27:33 PDT 2025
Author: Matheus Izvekov
Date: 2025-04-02T19:27:29-03:00
New Revision: f302f35526553abcb46dab278c4494c3d01deb45
URL: https://github.com/llvm/llvm-project/commit/f302f35526553abcb46dab278c4494c3d01deb45
DIFF: https://github.com/llvm/llvm-project/commit/f302f35526553abcb46dab278c4494c3d01deb45.diff
LOG: [clang] Track final substitution for Subst* AST nodes (#132748)
Added:
Modified:
clang/include/clang/AST/ASTContext.h
clang/include/clang/AST/ExprCXX.h
clang/include/clang/AST/PropertiesBase.td
clang/include/clang/AST/TemplateName.h
clang/include/clang/AST/Type.h
clang/include/clang/AST/TypeProperties.td
clang/lib/AST/ASTContext.cpp
clang/lib/AST/ASTImporter.cpp
clang/lib/AST/ExprCXX.cpp
clang/lib/AST/TemplateName.cpp
clang/lib/AST/TextNodeDumper.cpp
clang/lib/AST/Type.cpp
clang/lib/Sema/SemaTemplate.cpp
clang/lib/Sema/SemaTemplateInstantiate.cpp
clang/lib/Sema/TreeTransform.h
clang/test/AST/ast-dump-template-decls.cpp
clang/test/Misc/diag-template-diffing-cxx11.cpp
clang/test/SemaTemplate/make_integer_seq.cpp
Removed:
clang/test/AST/ast-dump-retain-subst-template-type-parm-type-ast-nodes.cpp
################################################################################
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index a24f30815e6b9..b3010fa888fa4 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -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);
@@ -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,
diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h
index 223d74993e9e6..028ee82718d50 100644
--- a/clang/include/clang/AST/ExprCXX.h
+++ b/clang/include/clang/AST/ExprCXX.h
@@ -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) {}
@@ -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));
@@ -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(); }
@@ -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;
@@ -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.
@@ -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;
diff --git a/clang/include/clang/AST/PropertiesBase.td b/clang/include/clang/AST/PropertiesBase.td
index 5171555008ac9..0e360de16fdd6 100644
--- a/clang/include/clang/AST/PropertiesBase.td
+++ b/clang/include/clang/AST/PropertiesBase.td
@@ -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 {
diff --git a/clang/include/clang/AST/TemplateName.h b/clang/include/clang/AST/TemplateName.h
index 1a56133b72d6e..ece2afcfa72ab 100644
--- a/clang/include/clang/AST/TemplateName.h
+++ b/clang/include/clang/AST/TemplateName.h
@@ -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);
}
@@ -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;
@@ -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,
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index cfd417068abb7..86ae335452980 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -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 {
@@ -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
@@ -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;
@@ -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;
@@ -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 {
diff --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td
index 391fd26a086f7..477106a152188 100644
--- a/clang/include/clang/AST/TypeProperties.td
+++ b/clang/include/clang/AST/TypeProperties.td
@@ -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);
}]>;
}
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 552b5823add36..0270a8e012849 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -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);
@@ -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);
}
@@ -10090,10 +10090,10 @@ 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
@@ -10101,7 +10101,7 @@ TemplateName ASTContext::getSubstTemplateTemplateParm(
if (!subst) {
subst = new (*this) SubstTemplateTemplateParmStorage(
- Replacement, AssociatedDecl, Index, PackIndex);
+ Replacement, AssociatedDecl, Index, PackIndex, Final);
SubstTemplateTemplateParms.InsertNode(subst, insertPos);
}
@@ -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.
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 81acb013b0f7d..893160e8f5ba9 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -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(
@@ -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) {
@@ -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: {
diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp
index a000e988e6834..a0bc50c449d82 100644
--- a/clang/lib/AST/ExprCXX.cpp
+++ b/clang/lib/AST/ExprCXX.cpp
@@ -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);
diff --git a/clang/lib/AST/TemplateName.cpp b/clang/lib/AST/TemplateName.cpp
index 031b58123fc99..f8ba5a24c7519 100644
--- a/clang/lib/AST/TemplateName.cpp
+++ b/clang/lib/AST/TemplateName.cpp
@@ -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(
diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp
index 1fe6f2c722acf..d35b2f5d9ab6d 100644
--- a/clang/lib/AST/TextNodeDumper.cpp
+++ b/clang/lib/AST/TextNodeDumper.cpp
@@ -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";
if (const TemplateTemplateParmDecl *P = STS->getParameter())
AddChild("parameter", [=] { Visit(P); });
dumpDeclRef(STS->getAssociatedDecl(), "associated");
@@ -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(
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 667ffc0e599a6..4669bf5541493 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -1294,9 +1294,9 @@ struct SimpleTransformVisitor : public TypeVisitor<Derived, QualType> {
== T->getReplacementType().getAsOpaquePtr())
return QualType(T, 0);
- return Ctx.getSubstTemplateTypeParmType(replacementType,
- T->getAssociatedDecl(),
- T->getIndex(), T->getPackIndex());
+ return Ctx.getSubstTemplateTypeParmType(
+ replacementType, T->getAssociatedDecl(), T->getIndex(),
+ T->getPackIndex(), T->getFinal());
}
// FIXME: Non-trivial to implement, but important for C++
@@ -4263,7 +4263,7 @@ static const TemplateTypeParmDecl *getReplacedParameter(Decl *D,
SubstTemplateTypeParmType::SubstTemplateTypeParmType(
QualType Replacement, Decl *AssociatedDecl, unsigned Index,
- std::optional<unsigned> PackIndex)
+ std::optional<unsigned> PackIndex, bool Final)
: Type(SubstTemplateTypeParm, Replacement.getCanonicalType(),
Replacement->getDependence()),
AssociatedDecl(AssociatedDecl) {
@@ -4273,6 +4273,7 @@ SubstTemplateTypeParmType::SubstTemplateTypeParmType(
*getTrailingObjects<QualType>() = Replacement;
SubstTemplateTypeParmTypeBits.Index = Index;
+ SubstTemplateTypeParmTypeBits.Final = Final;
SubstTemplateTypeParmTypeBits.PackIndex = PackIndex ? *PackIndex + 1 : 0;
assert(AssociatedDecl != nullptr);
}
@@ -4282,6 +4283,19 @@ SubstTemplateTypeParmType::getReplacedParameter() const {
return ::getReplacedParameter(getAssociatedDecl(), getIndex());
}
+void SubstTemplateTypeParmType::Profile(llvm::FoldingSetNodeID &ID,
+ QualType Replacement,
+ const Decl *AssociatedDecl,
+ 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);
+}
+
SubstTemplateTypeParmPackType::SubstTemplateTypeParmPackType(
QualType Canon, Decl *AssociatedDecl, unsigned Index, bool Final,
const TemplateArgument &ArgPack)
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 1f87ef4b27bab..8cf65ebe03c07 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -3528,16 +3528,10 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
if (Pattern->isInvalidDecl())
return QualType();
- // Only substitute for the innermost template argument list. NOTE: Some
- // external resugarers rely on leaving a Subst* node here. Make the
- // substitution non-final in that case. Note that these external resugarers
- // will still miss some information in this representation, because we don't
- // provide enough context in the Subst* nodes in order to tell
diff erent
- // template type alias specializations apart.
+ // Only substitute for the innermost template argument list.
MultiLevelTemplateArgumentList TemplateArgLists;
- TemplateArgLists.addOuterTemplateArguments(
- Template, CTAI.SugaredConverted,
- /*Final=*/!getLangOpts().RetainSubstTemplateTypeParmTypeAstNodes);
+ TemplateArgLists.addOuterTemplateArguments(Template, CTAI.SugaredConverted,
+ /*Final=*/true);
TemplateArgLists.addOuterRetainedLevels(
AliasTemplate->getTemplateParameters()->getDepth());
@@ -7558,7 +7552,7 @@ ExprResult Sema::BuildExpressionFromDeclTemplateArgument(
ParamType->getPointeeType(), RefExpr.get()->getValueKind(),
RefExpr.get()->getExprLoc(), RefExpr.get(), VD, NTTP->getIndex(),
/*PackIndex=*/std::nullopt,
- /*RefParam=*/true);
+ /*RefParam=*/true, /*Final=*/true);
}
}
}
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 9f5ca9dca8e89..d835b3b06893d 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1865,11 +1865,10 @@ namespace {
Sema::ExtParameterInfoBuilder &PInfos);
private:
- ExprResult
- transformNonTypeTemplateParmRef(Decl *AssociatedDecl,
- const NonTypeTemplateParmDecl *parm,
- SourceLocation loc, TemplateArgument arg,
- std::optional<unsigned> PackIndex);
+ ExprResult transformNonTypeTemplateParmRef(
+ Decl *AssociatedDecl, const NonTypeTemplateParmDecl *parm,
+ SourceLocation loc, TemplateArgument arg,
+ std::optional<unsigned> PackIndex, bool Final);
};
}
@@ -2083,10 +2082,8 @@ TemplateName TemplateInstantiator::TransformTemplateName(
TemplateName Template = Arg.getAsTemplate();
assert(!Template.isNull() && "Null template template argument");
- if (Final)
- return Template;
return getSema().Context.getSubstTemplateTemplateParm(
- Template, AssociatedDecl, TTP->getIndex(), PackIndex);
+ Template, AssociatedDecl, TTP->getIndex(), PackIndex, Final);
}
}
@@ -2098,11 +2095,9 @@ TemplateName TemplateInstantiator::TransformTemplateName(
TemplateArgument Pack = SubstPack->getArgumentPack();
TemplateName Template =
getPackSubstitutedTemplateArgument(getSema(), Pack).getAsTemplate();
- if (SubstPack->getFinal())
- return Template;
return getSema().Context.getSubstTemplateTemplateParm(
Template, SubstPack->getAssociatedDecl(), SubstPack->getIndex(),
- getPackIndex(Pack));
+ getPackIndex(Pack), SubstPack->getFinal());
}
return inherited::TransformTemplateName(SS, Name, NameLoc, ObjectType,
@@ -2144,7 +2139,8 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
return Arg.getAsExpr();
}
- auto [AssociatedDecl, _] = TemplateArgs.getAssociatedDecl(NTTP->getDepth());
+ auto [AssociatedDecl, Final] =
+ TemplateArgs.getAssociatedDecl(NTTP->getDepth());
std::optional<unsigned> PackIndex;
if (NTTP->isParameterPack()) {
assert(Arg.getKind() == TemplateArgument::Pack &&
@@ -2163,17 +2159,15 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
QualType ExprType = TargetType.getNonLValueExprType(SemaRef.Context);
if (TargetType->isRecordType())
ExprType.addConst();
- // FIXME: Pass in Final.
return new (SemaRef.Context) SubstNonTypeTemplateParmPackExpr(
ExprType, TargetType->isReferenceType() ? VK_LValue : VK_PRValue,
- E->getLocation(), Arg, AssociatedDecl, NTTP->getPosition());
+ E->getLocation(), Arg, AssociatedDecl, NTTP->getPosition(), Final);
}
PackIndex = getPackIndex(Arg);
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
}
- // FIXME: Don't put subst node on Final replacement.
return transformNonTypeTemplateParmRef(AssociatedDecl, NTTP, E->getLocation(),
- Arg, PackIndex);
+ Arg, PackIndex, Final);
}
const AnnotateAttr *
@@ -2268,8 +2262,8 @@ TemplateInstantiator::TransformOpenACCRoutineDeclAttr(
ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef(
Decl *AssociatedDecl, const NonTypeTemplateParmDecl *parm,
- SourceLocation loc, TemplateArgument arg,
- std::optional<unsigned> PackIndex) {
+ SourceLocation loc, TemplateArgument arg, std::optional<unsigned> PackIndex,
+ bool Final) {
ExprResult result;
// Determine the substituted parameter type. We can usually infer this from
@@ -2335,10 +2329,9 @@ ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef(
return ExprError();
Expr *resultExpr = result.get();
- // FIXME: Don't put subst node on final replacement.
return new (SemaRef.Context) SubstNonTypeTemplateParmExpr(
resultExpr->getType(), resultExpr->getValueKind(), loc, resultExpr,
- AssociatedDecl, parm->getIndex(), PackIndex, refParam);
+ AssociatedDecl, parm->getIndex(), PackIndex, refParam, Final);
}
ExprResult
@@ -2351,10 +2344,9 @@ TemplateInstantiator::TransformSubstNonTypeTemplateParmPackExpr(
TemplateArgument Pack = E->getArgumentPack();
TemplateArgument Arg = getPackSubstitutedTemplateArgument(getSema(), Pack);
- // FIXME: Don't put subst node on final replacement.
return transformNonTypeTemplateParmRef(
E->getAssociatedDecl(), E->getParameterPack(),
- E->getParameterPackLocation(), Arg, getPackIndex(Pack));
+ E->getParameterPackLocation(), Arg, getPackIndex(Pack), E->getFinal());
}
ExprResult
@@ -2396,9 +2388,9 @@ TemplateInstantiator::TransformSubstNonTypeTemplateParmExpr(
/*PartialOrderingTTP=*/false, Sema::CTAK_Specified)
.isInvalid())
return true;
- return transformNonTypeTemplateParmRef(E->getAssociatedDecl(),
- E->getParameter(), E->getExprLoc(),
- SugaredConverted, E->getPackIndex());
+ return transformNonTypeTemplateParmRef(
+ E->getAssociatedDecl(), E->getParameter(), E->getExprLoc(),
+ SugaredConverted, E->getPackIndex(), E->getFinal());
}
ExprResult TemplateInstantiator::RebuildVarDeclRefExpr(ValueDecl *PD,
@@ -2554,13 +2546,9 @@ QualType TemplateInstantiator::BuildSubstTemplateTypeParmType(
SemaRef.Context.getQualifiedType(Replacement.getUnqualifiedType(), RQs);
}
- if (Final) {
- TLB.pushTrivial(SemaRef.Context, Replacement, NameLoc);
- return Replacement;
- }
// TODO: only do this uniquing once, at the start of instantiation.
QualType Result = getSema().Context.getSubstTemplateTypeParmType(
- Replacement, AssociatedDecl, Index, PackIndex);
+ Replacement, AssociatedDecl, Index, PackIndex, Final);
SubstTemplateTypeParmTypeLoc NewTL =
TLB.push<SubstTemplateTypeParmTypeLoc>(Result);
NewTL.setNameLoc(NameLoc);
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 524e73242a2da..3689d323cf25b 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -7077,7 +7077,8 @@ QualType TreeTransform<Derived>::TransformSubstTemplateTypeParmType(
return QualType();
QualType Result = SemaRef.Context.getSubstTemplateTypeParmType(
- Replacement, NewReplaced, T->getIndex(), T->getPackIndex());
+ Replacement, NewReplaced, T->getIndex(), T->getPackIndex(),
+ T->getFinal());
// Propagate type-source information.
SubstTemplateTypeParmTypeLoc NewTL
diff --git a/clang/test/AST/ast-dump-retain-subst-template-type-parm-type-ast-nodes.cpp b/clang/test/AST/ast-dump-retain-subst-template-type-parm-type-ast-nodes.cpp
deleted file mode 100644
index 97dc983e2436c..0000000000000
--- a/clang/test/AST/ast-dump-retain-subst-template-type-parm-type-ast-nodes.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-// RUN: %clang_cc1 -fsyntax-only -fretain-subst-template-type-parm-type-ast-nodes -ast-dump -ast-dump-filter=dump %s | FileCheck -strict-whitespace %s
-
-namespace t1 {
-template<class T> using X = T;
-using dump = X<int>;
-
-// CHECK-LABEL: Dumping t1::dump:
-// CHECK-NEXT: TypeAliasDecl
-// CHECK-NEXT: `-ElaboratedType
-// CHECK-NEXT: `-TemplateSpecializationType
-// CHECK-NEXT: |-name: 'X':'t1::X' qualified
-// CHECK-NEXT: | `-TypeAliasTemplateDecl
-// CHECK-NEXT: |-TemplateArgument
-// CHECK-NEXT: | `-BuiltinType {{.+}} 'int'
-// CHECK-NEXT: `-SubstTemplateTypeParmType 0x{{[0-9a-f]+}} 'int' sugar class depth 0 index 0 T
-// CHECK-NEXT: |-TypeAliasTemplate {{.+}} 'X'
-// CHECK-NEXT: `-BuiltinType {{.+}} 'int'
-} // namespace t1
diff --git a/clang/test/AST/ast-dump-template-decls.cpp b/clang/test/AST/ast-dump-template-decls.cpp
index 9f578e5afe561..d5228d4667304 100644
--- a/clang/test/AST/ast-dump-template-decls.cpp
+++ b/clang/test/AST/ast-dump-template-decls.cpp
@@ -123,6 +123,8 @@ using type2 = typename C<int>::type1<void>;
// CHECK-NEXT: TemplateArgument type 'void'
// CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'void'
// CHECK-NEXT: FunctionProtoType 0x{{[^ ]*}} 'void (int)' cdecl
+// CHECK-NEXT: SubstTemplateTypeParmType 0x{{[^ ]*}} 'void' sugar class depth 0 index 0 U final
+// CHECK-NEXT: TypeAliasTemplate 0x{{[^ ]*}} 'type1'
// CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'void'
// CHECK-NEXT: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar class depth 0 index 0 T
// CHECK-NEXT: ClassTemplateSpecialization 0x{{[^ ]*}} 'C'
@@ -139,14 +141,14 @@ template struct D<float, char>::bind<int, short>;
// CHECK: TypeAliasDecl 0x{{[^ ]*}} <line:{{[1-9]+}}:5, col:45> col:11 bound_type 'int (int (*)(float, int), int (*)(char, short))'
// CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (int (*)(float, int), int (*)(char, short))' cdecl
// CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (float, int)' cdecl
-// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'float' sugar typename depth 0 index 0 ... T pack_index 1
+// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'float' sugar typename depth 0 index 0 ... T pack_index 1{{$}}
// CHECK-NEXT: ClassTemplateSpecialization 0x{{[^ ]*}} 'D'
-// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar typename depth 0 index 0 ... U pack_index 1
+// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar typename depth 0 index 0 ... U pack_index 1{{$}}
// CHECK-NEXT: ClassTemplateSpecialization 0x{{[^ ]*}} 'bind'
// CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (char, short)' cdecl
-// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'char' sugar typename depth 0 index 0 ... T pack_index 0
+// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'char' sugar typename depth 0 index 0 ... T pack_index 0{{$}}
// CHECK-NEXT: ClassTemplateSpecialization 0x{{[^ ]*}} 'D'
-// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'short' sugar typename depth 0 index 0 ... U pack_index 0
+// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'short' sugar typename depth 0 index 0 ... U pack_index 0{{$}}
// CHECK-NEXT: ClassTemplateSpecialization 0x{{[^ ]*}} 'bind'
} // namespace PR56099
@@ -156,12 +158,16 @@ template<template<class C1, class C2 = A<C1>> class D1, class D2> using D = D1<D
template<class E1, class E2> class E {};
using test1 = D<E, int>;
-// CHECK: TypeAliasDecl 0x{{[^ ]*}} <line:{{[1-9]+}}:1, col:23> col:7 test1 'D<E, int>':'subst_default_argument::E<int, subst_default_argument::A<int>>'
+// CHECK: TypeAliasDecl 0x{{[^ ]*}} <line:{{[0-9]+}}:1, col:23> col:7 test1 'D<E, int>':'subst_default_argument::E<int, subst_default_argument::A<int>>'
// CHECK: TemplateSpecializationType 0x{{[^ ]*}} 'A<int>' sugar
// CHECK-NEXT: |-name: 'A':'subst_default_argument::A' qualified
// CHECK-NEXT: | `-ClassTemplateDecl {{.+}} A
// CHECK-NEXT: |-TemplateArgument type 'int'
-// CHECK-NEXT: | `-BuiltinType 0x{{[^ ]*}} 'int'
+// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar class depth 0 index 0 E1 final
+// CHECK-NEXT: | |-ClassTemplate 0x{{[^ ]*}} 'E'
+// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar class depth 0 index 1 D2 final
+// CHECK-NEXT: | |-TypeAliasTemplate 0x{{[^ ]*}} 'D'
+// CHECK-NEXT: | `-BuiltinType 0x{{[^ ]*}} 'int'
// CHECK-NEXT: `-RecordType 0x{{[^ ]*}} 'subst_default_argument::A<int>'
// CHECK-NEXT: `-ClassTemplateSpecialization 0x{{[^ ]*}} 'A'
} // namespace subst_default_argument
diff --git a/clang/test/Misc/diag-template-
diff ing-cxx11.cpp b/clang/test/Misc/diag-template-
diff ing-cxx11.cpp
index ae4fa524e4e44..c62bffe2b458d 100644
--- a/clang/test/Misc/diag-template-
diff ing-cxx11.cpp
+++ b/clang/test/Misc/diag-template-
diff ing-cxx11.cpp
@@ -265,14 +265,14 @@ int k9 = f9(V9<double>());
// CHECK-ELIDE-TREE: S9<
// CHECK-ELIDE-TREE: [2 * ...],
// CHECK-ELIDE-TREE: U9<
-// CHECK-ELIDE-TREE: [(no qualifiers) != const] double>>
+// CHECK-ELIDE-TREE: [double != const double]>>
// CHECK-NOELIDE-TREE: no matching function for call to 'f9'
// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument
// CHECK-NOELIDE-TREE: S9<
// CHECK-NOELIDE-TREE: int,
// CHECK-NOELIDE-TREE: char,
// CHECK-NOELIDE-TREE: U9<
-// CHECK-NOELIDE-TREE: [(no qualifiers) != const] double>>
+// CHECK-NOELIDE-TREE: [double != const double]>>
template<typename ...A> class class_types {};
void set10(class_types<int, int>) {}
diff --git a/clang/test/SemaTemplate/make_integer_seq.cpp b/clang/test/SemaTemplate/make_integer_seq.cpp
index 71e34c5e0e7df..7ca7b55b49964 100644
--- a/clang/test/SemaTemplate/make_integer_seq.cpp
+++ b/clang/test/SemaTemplate/make_integer_seq.cpp
@@ -48,7 +48,9 @@ using test2 = B<int, 1>;
// CHECK-NEXT: |-TemplateArgument template 'A'
// CHECK-NEXT: | `-ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <line:{{.+}}:1, col:41> col:38 A
// CHECK-NEXT: |-TemplateArgument type 'int'
-// CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
+// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'int' sugar class depth 0 index 0 B1 final
+// CHECK-NEXT: | |-TypeAliasTemplate 0x{{[0-9A-Fa-f]+}} 'B'
+// CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
// CHECK-NEXT: |-TemplateArgument expr '1'
// CHECK-NEXT: | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} <line:{{.+}}:64> 'int'
// CHECK-NEXT: | |-value: Int 1
@@ -59,7 +61,9 @@ using test2 = B<int, 1>;
// CHECK-NEXT: |-name: 'A' qualified
// CHECK-NEXT: | `-ClassTemplateDecl {{.+}} A
// CHECK-NEXT: |-TemplateArgument type 'int'
-// CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
+// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'int' sugar class depth 0 index 0 B1 final
+// CHECK-NEXT: | |-TypeAliasTemplate 0x{{[0-9A-Fa-f]+}} 'B'
+// CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
// CHECK-NEXT: |-TemplateArgument expr '0'
// CHECK-NEXT: | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} <line:{{.+}}:64> 'int'
// CHECK-NEXT: | |-value: Int 0
More information about the cfe-commits
mailing list