mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-16 09:16:31 +00:00
[clang] Track final substitution for Subst* AST nodes (#132748)
This commit is contained in:
parent
990a086d9d
commit
f302f35526
@ -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,
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}]>;
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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: {
|
||||
|
@ -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);
|
||||
|
@ -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(
|
||||
|
@ -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(
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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>) {}
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user