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

This commit is contained in:
Matheus Izvekov 2025-04-02 19:27:29 -03:00 committed by GitHub
parent 990a086d9d
commit f302f35526
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 146 additions and 119 deletions

View File

@ -1795,10 +1795,10 @@ public:
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 @@ public:
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,

View File

@ -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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
/// 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;

View File

@ -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 {

View File

@ -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 @@ public:
/// 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 @@ public:
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,

View File

@ -2158,12 +2158,15 @@ protected:
// 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 @@ public:
/// 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 @@ public:
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 @@ public:
/// 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 {

View File

@ -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);
}]>;
}

View File

@ -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.

View File

@ -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: {

View File

@ -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);

View File

@ -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(

View File

@ -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(

View File

@ -1294,9 +1294,9 @@ public:
== 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)

View File

@ -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 different
// 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);
}
}
}

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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>) {}

View File

@ -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