[clang] Track the templated entity in type substitution.

This is a change to how we represent type subsitution in the AST.
Instead of only storing the replaced type, we track the templated
entity we are substituting, plus an index.
We modify MLTAL to track the templated entity at each level.

Otherwise, it's much more expensive to go from the template parameter back
to the templated entity, and not possible to do in some cases, as when
we instantiate outer templates, parameters might still reference the
original entity.

This also allows us to very cheaply lookup the templated entity we saw in
the naming context and find the corresponding argument it was replaced
from, such as for implementing template specialization resugaring.

Signed-off-by: Matheus Izvekov <mizvekov@gmail.com>

Differential Revision: https://reviews.llvm.org/D131858
This commit is contained in:
Matheus Izvekov 2022-08-14 13:48:18 +02:00
parent 0784de20e2
commit bcd9ba2b7e
No known key found for this signature in database
GPG Key ID: 22C080C6DC4E70F8
46 changed files with 982 additions and 642 deletions

View File

@ -52,7 +52,7 @@ void ExceptionBaseclassCheck::check(const MatchFinder::MatchResult &Result) {
diag(BadThrow->getSubExpr()->getBeginLoc(), diag(BadThrow->getSubExpr()->getBeginLoc(),
"type %0 is a template instantiation of %1", DiagnosticIDs::Note) "type %0 is a template instantiation of %1", DiagnosticIDs::Note)
<< BadThrow->getSubExpr()->getType() << BadThrow->getSubExpr()->getType()
<< Template->getReplacedParameter()->getDecl(); << Template->getReplacedParameter();
if (const auto *TypeDecl = Result.Nodes.getNodeAs<NamedDecl>("decl")) if (const auto *TypeDecl = Result.Nodes.getNodeAs<NamedDecl>("decl"))
diag(TypeDecl->getBeginLoc(), "type defined here", DiagnosticIDs::Note); diag(TypeDecl->getBeginLoc(), "type defined here", DiagnosticIDs::Note);

View File

@ -191,12 +191,12 @@ bool differentReplacedTemplateParams(const QualType &VarType,
getSubstitutedType(VarType, Context)) { getSubstitutedType(VarType, Context)) {
if (const SubstTemplateTypeParmType *InitializerTmplType = if (const SubstTemplateTypeParmType *InitializerTmplType =
getSubstitutedType(InitializerType, Context)) { getSubstitutedType(InitializerType, Context)) {
return VarTmplType->getReplacedParameter() const TemplateTypeParmDecl *VarTTP = VarTmplType->getReplacedParameter();
->desugar() const TemplateTypeParmDecl *InitTTP =
.getCanonicalType() != InitializerTmplType->getReplacedParameter();
InitializerTmplType->getReplacedParameter() return (VarTTP->getDepth() != InitTTP->getDepth() ||
->desugar() VarTTP->getIndex() != InitTTP->getIndex() ||
.getCanonicalType(); VarTTP->isParameterPack() != InitTTP->isParameterPack());
} }
} }
return false; return false;

View File

@ -730,8 +730,8 @@ const TemplateTypeParmType *getUnderylingPackType(const ParmVarDecl *Param) {
if (const auto *SubstType = dyn_cast<SubstTemplateTypeParmType>(PlainType)) { if (const auto *SubstType = dyn_cast<SubstTemplateTypeParmType>(PlainType)) {
const auto *ReplacedParameter = SubstType->getReplacedParameter(); const auto *ReplacedParameter = SubstType->getReplacedParameter();
if (ReplacedParameter->isParameterPack()) { if (ReplacedParameter->isParameterPack()) {
return dyn_cast<TemplateTypeParmType>( return ReplacedParameter->getTypeForDecl()
ReplacedParameter->getCanonicalTypeUnqualified()->getTypePtr()); ->castAs<TemplateTypeParmType>();
} }
} }
return nullptr; return nullptr;

View File

@ -1617,12 +1617,12 @@ public:
QualType getBTFTagAttributedType(const BTFTypeTagAttr *BTFAttr, QualType getBTFTagAttributedType(const BTFTypeTagAttr *BTFAttr,
QualType Wrapped); QualType Wrapped);
QualType getSubstTemplateTypeParmType(const TemplateTypeParmType *Replaced, QualType getSubstTemplateTypeParmType(QualType Replacement,
QualType Replacement, Decl *AssociatedDecl, unsigned Index,
Optional<unsigned> PackIndex) const; Optional<unsigned> PackIndex) const;
QualType QualType getSubstTemplateTypeParmPackType(Decl *AssociatedDecl,
getSubstTemplateTypeParmPackType(const TemplateTypeParmType *Replaced, unsigned Index,
const TemplateArgument &ArgPack); const TemplateArgument &ArgPack);
QualType QualType
getTemplateTypeParmType(unsigned Depth, unsigned Index, getTemplateTypeParmType(unsigned Depth, unsigned Index,
@ -2202,10 +2202,13 @@ public:
const IdentifierInfo *Name) const; const IdentifierInfo *Name) const;
TemplateName getDependentTemplateName(NestedNameSpecifier *NNS, TemplateName getDependentTemplateName(NestedNameSpecifier *NNS,
OverloadedOperatorKind Operator) const; OverloadedOperatorKind Operator) const;
TemplateName getSubstTemplateTemplateParm(TemplateTemplateParmDecl *param, TemplateName getSubstTemplateTemplateParm(TemplateName replacement,
TemplateName replacement) const; Decl *AssociatedDecl,
TemplateName getSubstTemplateTemplateParmPack(TemplateTemplateParmDecl *Param, unsigned Index,
const TemplateArgument &ArgPack) const; Optional<unsigned> PackIndex) const;
TemplateName getSubstTemplateTemplateParmPack(const TemplateArgument &ArgPack,
Decl *AssociatedDecl,
unsigned Index) const;
enum GetBuiltinTypeError { enum GetBuiltinTypeError {
/// No error /// No error

View File

@ -389,12 +389,9 @@ public:
void VisitBTFTagAttributedType(const BTFTagAttributedType *T) { void VisitBTFTagAttributedType(const BTFTagAttributedType *T) {
Visit(T->getWrappedType()); Visit(T->getWrappedType());
} }
void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) { void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *) {}
Visit(T->getReplacedParameter());
}
void void
VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T) { VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T) {
Visit(T->getReplacedParameter());
Visit(T->getArgumentPack()); Visit(T->getArgumentPack());
} }
void VisitTemplateSpecializationType(const TemplateSpecializationType *T) { void VisitTemplateSpecializationType(const TemplateSpecializationType *T) {

View File

@ -459,18 +459,17 @@ protected:
NamedDecl *TemplatedDecl; NamedDecl *TemplatedDecl;
TemplateParameterList *TemplateParams; TemplateParameterList *TemplateParams;
public:
void setTemplateParameters(TemplateParameterList *TParams) { void setTemplateParameters(TemplateParameterList *TParams) {
TemplateParams = TParams; TemplateParams = TParams;
} }
public: /// Initialize the underlying templated declaration.
/// Initialize the underlying templated declaration and void init(NamedDecl *NewTemplatedDecl) {
/// template parameters. if (TemplatedDecl)
void init(NamedDecl *templatedDecl, TemplateParameterList* templateParams) { assert(TemplatedDecl == NewTemplatedDecl && "Inconsistent TemplatedDecl");
assert(!TemplatedDecl && "TemplatedDecl already set!"); else
assert(!TemplateParams && "TemplateParams already set!"); TemplatedDecl = NewTemplatedDecl;
TemplatedDecl = templatedDecl;
TemplateParams = templateParams;
} }
}; };
@ -3425,6 +3424,10 @@ inline Optional<unsigned> getExpandedPackSize(const NamedDecl *Param) {
return None; return None;
} }
/// Internal helper used by Subst* nodes to retrieve the parameter list
/// for their AssociatedDecl.
TemplateParameterList *getReplacedTemplateParameterList(Decl *D);
} // namespace clang } // namespace clang
#endif // LLVM_CLANG_AST_DECLTEMPLATE_H #endif // LLVM_CLANG_AST_DECLTEMPLATE_H

View File

@ -941,7 +941,7 @@ class AssumedTemplateStorage : public UncommonTemplateNameStorage {
friend class ASTContext; friend class ASTContext;
AssumedTemplateStorage(DeclarationName Name) AssumedTemplateStorage(DeclarationName Name)
: UncommonTemplateNameStorage(Assumed, 0), Name(Name) {} : UncommonTemplateNameStorage(Assumed, 0, 0), Name(Name) {}
DeclarationName Name; DeclarationName Name;
public: public:

View File

@ -4270,24 +4270,30 @@ class SubstNonTypeTemplateParmExpr : public Expr {
friend class ASTReader; friend class ASTReader;
friend class ASTStmtReader; friend class ASTStmtReader;
/// The replaced parameter and a flag indicating if it was a reference
/// parameter. For class NTTPs, we can't determine that based on the value
/// category alone.
llvm::PointerIntPair<NonTypeTemplateParmDecl*, 1, bool> ParamAndRef;
/// The replacement expression. /// The replacement expression.
Stmt *Replacement; Stmt *Replacement;
/// The associated declaration and a flag indicating if it was a reference
/// parameter. For class NTTPs, we can't determine that based on the value
/// category alone.
llvm::PointerIntPair<Decl *, 1, bool> AssociatedDeclAndRef;
unsigned Index : 15;
unsigned PackIndex : 16;
explicit SubstNonTypeTemplateParmExpr(EmptyShell Empty) explicit SubstNonTypeTemplateParmExpr(EmptyShell Empty)
: Expr(SubstNonTypeTemplateParmExprClass, Empty) {} : Expr(SubstNonTypeTemplateParmExprClass, Empty) {}
public: public:
SubstNonTypeTemplateParmExpr(QualType Ty, ExprValueKind ValueKind, SubstNonTypeTemplateParmExpr(QualType Ty, ExprValueKind ValueKind,
SourceLocation Loc, SourceLocation Loc, Expr *Replacement,
NonTypeTemplateParmDecl *Param, bool RefParam, Decl *AssociatedDecl, unsigned Index,
Expr *Replacement) Optional<unsigned> PackIndex, bool RefParam)
: Expr(SubstNonTypeTemplateParmExprClass, Ty, ValueKind, OK_Ordinary), : Expr(SubstNonTypeTemplateParmExprClass, Ty, ValueKind, OK_Ordinary),
ParamAndRef(Param, RefParam), Replacement(Replacement) { Replacement(Replacement),
AssociatedDeclAndRef(AssociatedDecl, RefParam), Index(Index),
PackIndex(PackIndex ? *PackIndex + 1 : 0) {
assert(AssociatedDecl != nullptr);
SubstNonTypeTemplateParmExprBits.NameLoc = Loc; SubstNonTypeTemplateParmExprBits.NameLoc = Loc;
setDependence(computeDependence(this)); setDependence(computeDependence(this));
} }
@ -4300,11 +4306,23 @@ public:
Expr *getReplacement() const { return cast<Expr>(Replacement); } Expr *getReplacement() const { return cast<Expr>(Replacement); }
NonTypeTemplateParmDecl *getParameter() const { /// A template-like entity which owns the whole pattern being substituted.
return ParamAndRef.getPointer(); /// This will own a set of template parameters.
Decl *getAssociatedDecl() const { return AssociatedDeclAndRef.getPointer(); }
/// Returns the index of the replaced parameter in the associated declaration.
/// This should match the result of `getParameter()->getIndex()`.
unsigned getIndex() const { return Index; }
Optional<unsigned> getPackIndex() const {
if (PackIndex == 0)
return None;
return PackIndex - 1;
} }
bool isReferenceParameter() const { return ParamAndRef.getInt(); } NonTypeTemplateParmDecl *getParameter() const;
bool isReferenceParameter() const { return AssociatedDeclAndRef.getInt(); }
/// Determine the substituted type of the template parameter. /// Determine the substituted type of the template parameter.
QualType getParameterType(const ASTContext &Ctx) const; QualType getParameterType(const ASTContext &Ctx) const;
@ -4338,14 +4356,16 @@ class SubstNonTypeTemplateParmPackExpr : public Expr {
friend class ASTStmtReader; friend class ASTStmtReader;
/// The non-type template parameter pack itself. /// The non-type template parameter pack itself.
NonTypeTemplateParmDecl *Param; Decl *AssociatedDecl;
/// A pointer to the set of template arguments that this /// A pointer to the set of template arguments that this
/// parameter pack is instantiated with. /// parameter pack is instantiated with.
const TemplateArgument *Arguments; const TemplateArgument *Arguments;
/// The number of template arguments in \c Arguments. /// The number of template arguments in \c Arguments.
unsigned NumArguments; unsigned NumArguments : 16;
unsigned Index : 16;
/// The location of the non-type template parameter pack reference. /// The location of the non-type template parameter pack reference.
SourceLocation NameLoc; SourceLocation NameLoc;
@ -4354,14 +4374,21 @@ class SubstNonTypeTemplateParmPackExpr : public Expr {
: Expr(SubstNonTypeTemplateParmPackExprClass, Empty) {} : Expr(SubstNonTypeTemplateParmPackExprClass, Empty) {}
public: public:
SubstNonTypeTemplateParmPackExpr(QualType T, SubstNonTypeTemplateParmPackExpr(QualType T, ExprValueKind ValueKind,
ExprValueKind ValueKind,
NonTypeTemplateParmDecl *Param,
SourceLocation NameLoc, SourceLocation NameLoc,
const TemplateArgument &ArgPack); const TemplateArgument &ArgPack,
Decl *AssociatedDecl, unsigned Index);
/// A template-like entity which owns the whole pattern being substituted.
/// This will own a set of template parameters.
Decl *getAssociatedDecl() const { return AssociatedDecl; }
/// Returns the index of the replaced parameter in the associated declaration.
/// This should match the result of `getParameterPack()->getIndex()`.
unsigned getIndex() const { return Index; }
/// Retrieve the non-type template parameter pack being substituted. /// Retrieve the non-type template parameter pack being substituted.
NonTypeTemplateParmDecl *getParameterPack() const { return Param; } NonTypeTemplateParmDecl *getParameterPack() const;
/// Retrieve the location of the parameter pack name. /// Retrieve the location of the parameter pack name.
SourceLocation getParameterPackLocation() const { return NameLoc; } SourceLocation getParameterPackLocation() const { return NameLoc; }

View File

@ -222,6 +222,8 @@ public:
void VisitTagType(const TagType *TT); void VisitTagType(const TagType *TT);
void VisitTemplateTypeParmType(const TemplateTypeParmType *TTPT); void VisitTemplateTypeParmType(const TemplateTypeParmType *TTPT);
void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *STTPT); void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *STTPT);
void
VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T);
void VisitAutoType(const AutoType *AT); void VisitAutoType(const AutoType *AT);
void VisitTemplateSpecializationType(const TemplateSpecializationType *TST); void VisitTemplateSpecializationType(const TemplateSpecializationType *TST);
void VisitInjectedClassNameType(const InjectedClassNameType *ICNT); void VisitInjectedClassNameType(const InjectedClassNameType *ICNT);

View File

@ -701,28 +701,37 @@ let Class = PropertyTypeCase<TemplateName, "SubstTemplateTemplateParm"> in {
def : ReadHelper<[{ def : ReadHelper<[{
auto parm = node.getAsSubstTemplateTemplateParm(); auto parm = node.getAsSubstTemplateTemplateParm();
}]>; }]>;
def : Property<"parameter", TemplateTemplateParmDeclRef> {
let Read = [{ parm->getParameter() }];
}
def : Property<"replacement", TemplateName> { def : Property<"replacement", TemplateName> {
let Read = [{ parm->getReplacement() }]; let Read = [{ parm->getReplacement() }];
} }
def : Property<"associatedDecl", DeclRef> {
let Read = [{ parm->getAssociatedDecl() }];
}
def : Property<"index", UInt32> {
let Read = [{ parm->getIndex() }];
}
def : Property<"packIndex", Optional<UInt32>> {
let Read = [{ parm->getPackIndex() }];
}
def : Creator<[{ def : Creator<[{
return ctx.getSubstTemplateTemplateParm(parameter, replacement); return ctx.getSubstTemplateTemplateParm(replacement, associatedDecl, index, packIndex);
}]>; }]>;
} }
let Class = PropertyTypeCase<TemplateName, "SubstTemplateTemplateParmPack"> in { let Class = PropertyTypeCase<TemplateName, "SubstTemplateTemplateParmPack"> in {
def : ReadHelper<[{ def : ReadHelper<[{
auto parm = node.getAsSubstTemplateTemplateParmPack(); auto parm = node.getAsSubstTemplateTemplateParmPack();
}]>; }]>;
def : Property<"parameterPack", TemplateTemplateParmDeclRef> {
let Read = [{ parm->getParameterPack() }];
}
def : Property<"argumentPack", TemplateArgument> { def : Property<"argumentPack", TemplateArgument> {
let Read = [{ parm->getArgumentPack() }]; let Read = [{ parm->getArgumentPack() }];
} }
def : Property<"associatedDecl", DeclRef> {
let Read = [{ parm->getAssociatedDecl() }];
}
def : Property<"index", UInt32> {
let Read = [{ parm->getIndex() }];
}
def : Creator<[{ def : Creator<[{
return ctx.getSubstTemplateTemplateParmPack(parameterPack, argumentPack); return ctx.getSubstTemplateTemplateParmPack(argumentPack, associatedDecl, index);
}]>; }]>;
} }

View File

@ -57,9 +57,12 @@ protected:
/// A Kind. /// A Kind.
unsigned Kind : 2; unsigned Kind : 2;
/// The number of stored templates or template arguments, // The template parameter index.
/// depending on which subclass we have. unsigned Index : 15;
unsigned Size : 30;
/// The pack index, or the number of stored templates
/// or template arguments, depending on which subclass we have.
unsigned Data : 15;
}; };
union { union {
@ -67,14 +70,13 @@ protected:
void *PointerAlignment; void *PointerAlignment;
}; };
UncommonTemplateNameStorage(Kind kind, unsigned size) { UncommonTemplateNameStorage(Kind Kind, unsigned Index, unsigned Data) {
Bits.Kind = kind; Bits.Kind = Kind;
Bits.Size = size; Bits.Index = Index;
Bits.Data = Data;
} }
public: public:
unsigned size() const { return Bits.Size; }
OverloadedTemplateStorage *getAsOverloadedStorage() { OverloadedTemplateStorage *getAsOverloadedStorage() {
return Bits.Kind == Overloaded return Bits.Kind == Overloaded
? reinterpret_cast<OverloadedTemplateStorage *>(this) ? reinterpret_cast<OverloadedTemplateStorage *>(this)
@ -106,7 +108,7 @@ class OverloadedTemplateStorage : public UncommonTemplateNameStorage {
friend class ASTContext; friend class ASTContext;
OverloadedTemplateStorage(unsigned size) OverloadedTemplateStorage(unsigned size)
: UncommonTemplateNameStorage(Overloaded, size) {} : UncommonTemplateNameStorage(Overloaded, 0, size) {}
NamedDecl **getStorage() { NamedDecl **getStorage() {
return reinterpret_cast<NamedDecl **>(this + 1); return reinterpret_cast<NamedDecl **>(this + 1);
@ -116,10 +118,12 @@ class OverloadedTemplateStorage : public UncommonTemplateNameStorage {
} }
public: public:
unsigned size() const { return Bits.Data; }
using iterator = NamedDecl *const *; using iterator = NamedDecl *const *;
iterator begin() const { return getStorage(); } iterator begin() const { return getStorage(); }
iterator end() const { return getStorage() + size(); } iterator end() const { return getStorage() + Bits.Data; }
llvm::ArrayRef<NamedDecl*> decls() const { llvm::ArrayRef<NamedDecl*> decls() const {
return llvm::makeArrayRef(begin(), end()); return llvm::makeArrayRef(begin(), end());
@ -132,23 +136,30 @@ public:
/// This kind of template names occurs when the parameter pack has been /// This kind of template names occurs when the parameter pack has been
/// provided with a template template argument pack in a context where its /// provided with a template template argument pack in a context where its
/// enclosing pack expansion could not be fully expanded. /// enclosing pack expansion could not be fully expanded.
class SubstTemplateTemplateParmPackStorage class SubstTemplateTemplateParmPackStorage : public UncommonTemplateNameStorage,
: public UncommonTemplateNameStorage, public llvm::FoldingSetNode public llvm::FoldingSetNode {
{
TemplateTemplateParmDecl *Parameter;
const TemplateArgument *Arguments; const TemplateArgument *Arguments;
Decl *AssociatedDecl;
public: public:
SubstTemplateTemplateParmPackStorage(TemplateTemplateParmDecl *Parameter, SubstTemplateTemplateParmPackStorage(ArrayRef<TemplateArgument> ArgPack,
unsigned Size, Decl *AssociatedDecl, unsigned Index)
const TemplateArgument *Arguments) : UncommonTemplateNameStorage(SubstTemplateTemplateParmPack, Index,
: UncommonTemplateNameStorage(SubstTemplateTemplateParmPack, Size), ArgPack.size()),
Parameter(Parameter), Arguments(Arguments) {} Arguments(ArgPack.data()), AssociatedDecl(AssociatedDecl) {
assert(AssociatedDecl != nullptr);
}
/// A template-like entity which owns the whole pattern being substituted.
/// This will own a set of template parameters.
Decl *getAssociatedDecl() const { return AssociatedDecl; }
/// Returns the index of the replaced parameter in the associated declaration.
/// This should match the result of `getParameterPack()->getIndex()`.
unsigned getIndex() const { return Bits.Index; }
/// Retrieve the template template parameter pack being substituted. /// Retrieve the template template parameter pack being substituted.
TemplateTemplateParmDecl *getParameterPack() const { TemplateTemplateParmDecl *getParameterPack() const;
return Parameter;
}
/// Retrieve the template template argument pack with which this /// Retrieve the template template argument pack with which this
/// parameter was substituted. /// parameter was substituted.
@ -156,10 +167,9 @@ public:
void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context); void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context);
static void Profile(llvm::FoldingSetNodeID &ID, static void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context,
ASTContext &Context, const TemplateArgument &ArgPack, Decl *AssociatedDecl,
TemplateTemplateParmDecl *Parameter, unsigned Index);
const TemplateArgument &ArgPack);
}; };
/// Represents a C++ template name within the type system. /// Represents a C++ template name within the type system.
@ -365,23 +375,41 @@ class SubstTemplateTemplateParmStorage
: public UncommonTemplateNameStorage, public llvm::FoldingSetNode { : public UncommonTemplateNameStorage, public llvm::FoldingSetNode {
friend class ASTContext; friend class ASTContext;
TemplateTemplateParmDecl *Parameter;
TemplateName Replacement; TemplateName Replacement;
Decl *AssociatedDecl;
SubstTemplateTemplateParmStorage(TemplateTemplateParmDecl *parameter, SubstTemplateTemplateParmStorage(TemplateName Replacement,
TemplateName replacement) Decl *AssociatedDecl, unsigned Index,
: UncommonTemplateNameStorage(SubstTemplateTemplateParm, 0), Optional<unsigned> PackIndex)
Parameter(parameter), Replacement(replacement) {} : UncommonTemplateNameStorage(SubstTemplateTemplateParm, Index,
PackIndex ? *PackIndex + 1 : 0),
Replacement(Replacement), AssociatedDecl(AssociatedDecl) {
assert(AssociatedDecl != nullptr);
}
public: public:
TemplateTemplateParmDecl *getParameter() const { return Parameter; } /// A template-like entity which owns the whole pattern being substituted.
/// This will own a set of template parameters.
Decl *getAssociatedDecl() const { return AssociatedDecl; }
/// Returns the index of the replaced parameter in the associated declaration.
/// This should match the result of `getParameter()->getIndex()`.
unsigned getIndex() const { return Bits.Index; }
Optional<unsigned> getPackIndex() const {
if (Bits.Data == 0)
return None;
return Bits.Data - 1;
}
TemplateTemplateParmDecl *getParameter() const;
TemplateName getReplacement() const { return Replacement; } TemplateName getReplacement() const { return Replacement; }
void Profile(llvm::FoldingSetNodeID &ID); void Profile(llvm::FoldingSetNodeID &ID);
static void Profile(llvm::FoldingSetNodeID &ID, static void Profile(llvm::FoldingSetNodeID &ID, TemplateName Replacement,
TemplateTemplateParmDecl *parameter, Decl *AssociatedDecl, unsigned Index,
TemplateName replacement); Optional<unsigned> PackIndex);
}; };
inline TemplateName TemplateName::getUnderlying() const { inline TemplateName TemplateName::getUnderlying() const {

View File

@ -318,6 +318,8 @@ public:
void VisitTagType(const TagType *T); void VisitTagType(const TagType *T);
void VisitTemplateTypeParmType(const TemplateTypeParmType *T); void VisitTemplateTypeParmType(const TemplateTypeParmType *T);
void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T); void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T);
void
VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T);
void VisitAutoType(const AutoType *T); void VisitAutoType(const AutoType *T);
void VisitDeducedTemplateSpecializationType( void VisitDeducedTemplateSpecializationType(
const DeducedTemplateSpecializationType *T); const DeducedTemplateSpecializationType *T);

View File

@ -1832,6 +1832,9 @@ protected:
unsigned HasNonCanonicalUnderlyingType : 1; unsigned HasNonCanonicalUnderlyingType : 1;
// The index of the template parameter this substitution represents.
unsigned Index : 15;
/// Represents the index within a pack if this represents a substitution /// 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 /// from a pack expansion. This index starts at the end of the pack and
/// increments towards the beginning. /// increments towards the beginning.
@ -1845,14 +1848,14 @@ protected:
unsigned : NumTypeBits; unsigned : NumTypeBits;
// The index of the template parameter this substitution represents.
unsigned Index : 16;
/// The number of template arguments in \c Arguments, which is /// The number of template arguments in \c Arguments, which is
/// expected to be able to hold at least 1024 according to [implimits]. /// expected to be able to hold at least 1024 according to [implimits].
/// However as this limit is somewhat easy to hit with template /// However as this limit is somewhat easy to hit with template
/// metaprogramming we'd prefer to keep it as large as possible. /// metaprogramming we'd prefer to keep it as large as possible.
/// At the moment it has been left as a non-bitfield since this type unsigned NumArgs : 16;
/// safely fits in 64 bits as an unsigned, so there is no reason to
/// introduce the performance impact of a bitfield.
unsigned NumArgs;
}; };
class TemplateSpecializationTypeBitfields { class TemplateSpecializationTypeBitfields {
@ -5083,18 +5086,12 @@ class SubstTemplateTypeParmType final
friend class ASTContext; friend class ASTContext;
friend class llvm::TrailingObjects<SubstTemplateTypeParmType, QualType>; friend class llvm::TrailingObjects<SubstTemplateTypeParmType, QualType>;
// The original type parameter. Decl *AssociatedDecl;
const TemplateTypeParmType *Replaced;
SubstTemplateTypeParmType(const TemplateTypeParmType *Param, QualType Canon, SubstTemplateTypeParmType(QualType Replacement, Decl *AssociatedDecl,
Optional<unsigned> PackIndex); unsigned Index, Optional<unsigned> PackIndex);
public: public:
/// Gets the template parameter that was substituted for.
const TemplateTypeParmType *getReplacedParameter() const {
return Replaced;
}
/// Gets the type that was substituted for the template /// Gets the type that was substituted for the template
/// parameter. /// parameter.
QualType getReplacementType() const { QualType getReplacementType() const {
@ -5103,6 +5100,18 @@ public:
: getCanonicalTypeInternal(); : getCanonicalTypeInternal();
} }
/// A template-like entity which owns the whole pattern being substituted.
/// This will usually own a set of template parameters, or in some
/// cases might even be a template parameter itself.
Decl *getAssociatedDecl() const { return AssociatedDecl; }
/// Gets the template parameter declaration that was substituted for.
const TemplateTypeParmDecl *getReplacedParameter() const;
/// Returns the index of the replaced parameter in the associated declaration.
/// This should match the result of `getReplacedParameter()->getIndex()`.
unsigned getIndex() const { return SubstTemplateTypeParmTypeBits.Index; }
Optional<unsigned> getPackIndex() const { Optional<unsigned> getPackIndex() const {
if (SubstTemplateTypeParmTypeBits.PackIndex == 0) if (SubstTemplateTypeParmTypeBits.PackIndex == 0)
return None; return None;
@ -5113,14 +5122,16 @@ public:
QualType desugar() const { return getReplacementType(); } QualType desugar() const { return getReplacementType(); }
void Profile(llvm::FoldingSetNodeID &ID) { void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getReplacedParameter(), getReplacementType(), getPackIndex()); Profile(ID, getReplacementType(), getAssociatedDecl(), getIndex(),
getPackIndex());
} }
static void Profile(llvm::FoldingSetNodeID &ID, static void Profile(llvm::FoldingSetNodeID &ID, QualType Replacement,
const TemplateTypeParmType *Replaced, const Decl *AssociatedDecl, unsigned Index,
QualType Replacement, Optional<unsigned> PackIndex) { Optional<unsigned> PackIndex) {
ID.AddPointer(Replaced);
Replacement.Profile(ID); Replacement.Profile(ID);
ID.AddPointer(AssociatedDecl);
ID.AddInteger(Index);
ID.AddInteger(PackIndex ? *PackIndex - 1 : 0); ID.AddInteger(PackIndex ? *PackIndex - 1 : 0);
} }
@ -5144,24 +5155,30 @@ public:
class SubstTemplateTypeParmPackType : public Type, public llvm::FoldingSetNode { class SubstTemplateTypeParmPackType : public Type, public llvm::FoldingSetNode {
friend class ASTContext; friend class ASTContext;
/// The original type parameter.
const TemplateTypeParmType *Replaced;
/// A pointer to the set of template arguments that this /// A pointer to the set of template arguments that this
/// parameter pack is instantiated with. /// parameter pack is instantiated with.
const TemplateArgument *Arguments; const TemplateArgument *Arguments;
SubstTemplateTypeParmPackType(const TemplateTypeParmType *Param, Decl *AssociatedDecl;
QualType Canon,
SubstTemplateTypeParmPackType(QualType Canon, Decl *AssociatedDecl,
unsigned Index,
const TemplateArgument &ArgPack); const TemplateArgument &ArgPack);
public: public:
IdentifierInfo *getIdentifier() const { return Replaced->getIdentifier(); } IdentifierInfo *getIdentifier() const;
/// Gets the template parameter that was substituted for. /// A template-like entity which owns the whole pattern being substituted.
const TemplateTypeParmType *getReplacedParameter() const { /// This will usually own a set of template parameters, or in some
return Replaced; /// cases might even be a template parameter itself.
} Decl *getAssociatedDecl() const { return AssociatedDecl; }
/// Gets the template parameter declaration that was substituted for.
const TemplateTypeParmDecl *getReplacedParameter() const;
/// Returns the index of the replaced parameter in the associated declaration.
/// This should match the result of `getReplacedParameter()->getIndex()`.
unsigned getIndex() const { return SubstTemplateTypeParmPackTypeBits.Index; }
unsigned getNumArgs() const { unsigned getNumArgs() const {
return SubstTemplateTypeParmPackTypeBits.NumArgs; return SubstTemplateTypeParmPackTypeBits.NumArgs;
@ -5173,9 +5190,8 @@ public:
TemplateArgument getArgumentPack() const; TemplateArgument getArgumentPack() const;
void Profile(llvm::FoldingSetNodeID &ID); void Profile(llvm::FoldingSetNodeID &ID);
static void Profile(llvm::FoldingSetNodeID &ID, static void Profile(llvm::FoldingSetNodeID &ID, const Decl *AssociatedDecl,
const TemplateTypeParmType *Replaced, unsigned Index, const TemplateArgument &ArgPack);
const TemplateArgument &ArgPack);
static bool classof(const Type *T) { static bool classof(const Type *T) {
return T->getTypeClass() == SubstTemplateTypeParmPack; return T->getTypeClass() == SubstTemplateTypeParmPack;

View File

@ -732,20 +732,23 @@ let Class = TemplateTypeParmType in {
} }
let Class = SubstTemplateTypeParmType in { let Class = SubstTemplateTypeParmType in {
def : Property<"replacedParameter", QualType> {
let Read = [{ QualType(node->getReplacedParameter(), 0) }];
}
def : Property<"replacementType", QualType> { def : Property<"replacementType", QualType> {
let Read = [{ node->getReplacementType() }]; let Read = [{ node->getReplacementType() }];
} }
def : Property<"associatedDecl", DeclRef> {
let Read = [{ node->getAssociatedDecl() }];
}
def : Property<"Index", UInt32> {
let Read = [{ node->getIndex() }];
}
def : Property<"PackIndex", Optional<UInt32>> { def : Property<"PackIndex", Optional<UInt32>> {
let Read = [{ node->getPackIndex() }]; let Read = [{ node->getPackIndex() }];
} }
// The call to getCanonicalType here existed in ASTReader.cpp, too.
def : Creator<[{ def : Creator<[{
return ctx.getSubstTemplateTypeParmType( return ctx.getSubstTemplateTypeParmType(
cast<TemplateTypeParmType>(replacedParameter), replacementType, associatedDecl, Index, PackIndex);
replacementType, PackIndex);
}]>; }]>;
} }
@ -764,8 +767,11 @@ let Class = PackExpansionType in {
} }
let Class = SubstTemplateTypeParmPackType in { let Class = SubstTemplateTypeParmPackType in {
def : Property<"replacedParameter", QualType> { def : Property<"associatedDecl", DeclRef> {
let Read = [{ QualType(node->getReplacedParameter(), 0) }]; let Read = [{ node->getAssociatedDecl() }];
}
def : Property<"Index", UInt32> {
let Read = [{ node->getIndex() }];
} }
def : Property<"replacementPack", TemplateArgument> { def : Property<"replacementPack", TemplateArgument> {
let Read = [{ node->getArgumentPack() }]; let Read = [{ node->getArgumentPack() }];
@ -773,8 +779,7 @@ let Class = SubstTemplateTypeParmPackType in {
def : Creator<[{ def : Creator<[{
return ctx.getSubstTemplateTypeParmPackType( return ctx.getSubstTemplateTypeParmPackType(
cast<TemplateTypeParmType>(replacedParameter), associatedDecl, Index, replacementPack);
replacementPack);
}]>; }]>;
} }

View File

@ -74,13 +74,20 @@ enum class TemplateSubstitutionKind : char {
/// template argument list (17) at depth 1. /// template argument list (17) at depth 1.
class MultiLevelTemplateArgumentList { class MultiLevelTemplateArgumentList {
/// The template argument list at a certain template depth /// The template argument list at a certain template depth
using ArgList = ArrayRef<TemplateArgument>; using ArgList = ArrayRef<TemplateArgument>;
using ArgListsIterator = SmallVector<ArgList, 4>::iterator; struct ArgumentListLevel {
using ConstArgListsIterator = SmallVector<ArgList, 4>::const_iterator; Decl *AssociatedDecl;
ArgList Args;
};
using ContainerType = SmallVector<ArgumentListLevel, 4>;
using ArgListsIterator = ContainerType::iterator;
using ConstArgListsIterator = ContainerType::const_iterator;
/// The template argument lists, stored from the innermost template /// The template argument lists, stored from the innermost template
/// argument list (first) to the outermost template argument list (last). /// argument list (first) to the outermost template argument list (last).
SmallVector<ArgList, 4> TemplateArgumentLists; ContainerType TemplateArgumentLists;
/// The number of outer levels of template arguments that are not /// The number of outer levels of template arguments that are not
/// being substituted. /// being substituted.
@ -94,9 +101,8 @@ enum class TemplateSubstitutionKind : char {
MultiLevelTemplateArgumentList() = default; MultiLevelTemplateArgumentList() = default;
/// Construct a single-level template argument list. /// Construct a single-level template argument list.
explicit MultiLevelTemplateArgumentList(Decl *D, ArgList Args) {
MultiLevelTemplateArgumentList(const TemplateArgumentList &TemplateArgs) { addOuterTemplateArguments(D, Args);
addOuterTemplateArguments(&TemplateArgs);
} }
void setKind(TemplateSubstitutionKind K) { Kind = K; } void setKind(TemplateSubstitutionKind K) { Kind = K; }
@ -126,7 +132,7 @@ enum class TemplateSubstitutionKind : char {
// Determine the number of substituted args at 'Depth'. // Determine the number of substituted args at 'Depth'.
unsigned getNumSubsitutedArgs(unsigned Depth) const { unsigned getNumSubsitutedArgs(unsigned Depth) const {
assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels()); assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
return TemplateArgumentLists[getNumLevels() - Depth - 1].size(); return TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size();
} }
unsigned getNumRetainedOuterLevels() const { unsigned getNumRetainedOuterLevels() const {
@ -146,8 +152,17 @@ enum class TemplateSubstitutionKind : char {
/// Retrieve the template argument at a given depth and index. /// Retrieve the template argument at a given depth and index.
const TemplateArgument &operator()(unsigned Depth, unsigned Index) const { const TemplateArgument &operator()(unsigned Depth, unsigned Index) const {
assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels()); assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1].size()); assert(Index <
return TemplateArgumentLists[getNumLevels() - Depth - 1][Index]; TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size());
return TemplateArgumentLists[getNumLevels() - Depth - 1].Args[Index];
}
/// A template-like entity which owns the whole pattern being substituted.
/// This will usually own a set of template parameters, or in some
/// cases might even be a template parameter itself.
Decl *getAssociatedDecl(unsigned Depth) const {
assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
return TemplateArgumentLists[getNumLevels() - Depth - 1].AssociatedDecl;
} }
/// Determine whether there is a non-NULL template argument at the /// Determine whether there is a non-NULL template argument at the
@ -160,15 +175,16 @@ enum class TemplateSubstitutionKind : char {
if (Depth < NumRetainedOuterLevels) if (Depth < NumRetainedOuterLevels)
return false; return false;
if (Index >= TemplateArgumentLists[getNumLevels() - Depth - 1].size()) if (Index >=
TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size())
return false; return false;
return !(*this)(Depth, Index).isNull(); return !(*this)(Depth, Index).isNull();
} }
bool isAnyArgInstantiationDependent() const { bool isAnyArgInstantiationDependent() const {
for (ArgList List : TemplateArgumentLists) for (ArgumentListLevel ListLevel : TemplateArgumentLists)
for (const TemplateArgument &TA : List) for (const TemplateArgument &TA : ListLevel.Args)
if (TA.isInstantiationDependent()) if (TA.isInstantiationDependent())
return true; return true;
return false; return false;
@ -178,25 +194,35 @@ enum class TemplateSubstitutionKind : char {
void setArgument(unsigned Depth, unsigned Index, void setArgument(unsigned Depth, unsigned Index,
TemplateArgument Arg) { TemplateArgument Arg) {
assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels()); assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1].size()); assert(Index <
const_cast<TemplateArgument&>( TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size());
TemplateArgumentLists[getNumLevels() - Depth - 1][Index]) const_cast<TemplateArgument &>(
= Arg; TemplateArgumentLists[getNumLevels() - Depth - 1].Args[Index]) = Arg;
}
/// Add a new outermost level to the multi-level template argument
/// list.
void addOuterTemplateArguments(const TemplateArgumentList *TemplateArgs) {
addOuterTemplateArguments(ArgList(TemplateArgs->data(),
TemplateArgs->size()));
} }
/// Add a new outmost level to the multi-level template argument /// Add a new outmost level to the multi-level template argument
/// list. /// list.
void addOuterTemplateArguments(Decl *AssociatedDecl, ArgList Args) {
assert(!NumRetainedOuterLevels &&
"substituted args outside retained args?");
assert(getKind() == TemplateSubstitutionKind::Specialization);
assert(AssociatedDecl != nullptr || Args.size() == 0);
TemplateArgumentLists.push_back(
{AssociatedDecl ? AssociatedDecl->getCanonicalDecl() : nullptr,
Args});
}
void addOuterTemplateArguments(ArgList Args) { void addOuterTemplateArguments(ArgList Args) {
assert(!NumRetainedOuterLevels && assert(!NumRetainedOuterLevels &&
"substituted args outside retained args?"); "substituted args outside retained args?");
TemplateArgumentLists.push_back(Args); assert(getKind() == TemplateSubstitutionKind::Rewrite);
TemplateArgumentLists.push_back({nullptr, Args});
}
void addOuterTemplateArguments(llvm::NoneType) {
assert(!NumRetainedOuterLevels &&
"substituted args outside retained args?");
TemplateArgumentLists.push_back({});
} }
/// Replaces the current 'innermost' level with the provided argument list. /// Replaces the current 'innermost' level with the provided argument list.
@ -204,7 +230,7 @@ enum class TemplateSubstitutionKind : char {
/// list from the AST, but then add the deduced innermost list. /// list from the AST, but then add the deduced innermost list.
void replaceInnermostTemplateArguments(ArgList Args) { void replaceInnermostTemplateArguments(ArgList Args) {
assert(TemplateArgumentLists.size() > 0 && "Replacing in an empty list?"); assert(TemplateArgumentLists.size() > 0 && "Replacing in an empty list?");
TemplateArgumentLists[0] = Args; TemplateArgumentLists[0].Args = Args;
} }
/// Add an outermost level that we are not substituting. We have no /// Add an outermost level that we are not substituting. We have no
@ -219,11 +245,11 @@ enum class TemplateSubstitutionKind : char {
/// Retrieve the innermost template argument list. /// Retrieve the innermost template argument list.
const ArgList &getInnermost() const { const ArgList &getInnermost() const {
return TemplateArgumentLists.front(); return TemplateArgumentLists.front().Args;
} }
/// Retrieve the outermost template argument list. /// Retrieve the outermost template argument list.
const ArgList &getOutermost() const { const ArgList &getOutermost() const {
return TemplateArgumentLists.back(); return TemplateArgumentLists.back().Args;
} }
ArgListsIterator begin() { return TemplateArgumentLists.begin(); } ArgListsIterator begin() { return TemplateArgumentLists.begin(); }
ConstArgListsIterator begin() const { ConstArgListsIterator begin() const {

View File

@ -4785,21 +4785,22 @@ QualType ASTContext::getBTFTagAttributedType(const BTFTypeTagAttr *BTFAttr,
/// Retrieve a substitution-result type. /// Retrieve a substitution-result type.
QualType QualType
ASTContext::getSubstTemplateTypeParmType(const TemplateTypeParmType *Parm, ASTContext::getSubstTemplateTypeParmType(QualType Replacement,
QualType Replacement, Decl *AssociatedDecl, unsigned Index,
Optional<unsigned> PackIndex) const { Optional<unsigned> PackIndex) const {
llvm::FoldingSetNodeID ID; llvm::FoldingSetNodeID ID;
SubstTemplateTypeParmType::Profile(ID, Parm, Replacement, PackIndex); SubstTemplateTypeParmType::Profile(ID, Replacement, AssociatedDecl, Index,
PackIndex);
void *InsertPos = nullptr; void *InsertPos = nullptr;
SubstTemplateTypeParmType *SubstParm SubstTemplateTypeParmType *SubstParm =
= SubstTemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos); SubstTemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos);
if (!SubstParm) { if (!SubstParm) {
void *Mem = Allocate(SubstTemplateTypeParmType::totalSizeToAlloc<QualType>( void *Mem = Allocate(SubstTemplateTypeParmType::totalSizeToAlloc<QualType>(
!Replacement.isCanonical()), !Replacement.isCanonical()),
TypeAlignment); TypeAlignment);
SubstParm = SubstParm = new (Mem) SubstTemplateTypeParmType(Replacement, AssociatedDecl,
new (Mem) SubstTemplateTypeParmType(Parm, Replacement, PackIndex); Index, PackIndex);
Types.push_back(SubstParm); Types.push_back(SubstParm);
SubstTemplateTypeParmTypes.InsertNode(SubstParm, InsertPos); SubstTemplateTypeParmTypes.InsertNode(SubstParm, InsertPos);
} }
@ -4809,33 +4810,30 @@ ASTContext::getSubstTemplateTypeParmType(const TemplateTypeParmType *Parm,
/// Retrieve a /// Retrieve a
QualType ASTContext::getSubstTemplateTypeParmPackType( QualType ASTContext::getSubstTemplateTypeParmPackType(
const TemplateTypeParmType *Parm, Decl *AssociatedDecl, unsigned Index, const TemplateArgument &ArgPack) {
const TemplateArgument &ArgPack) {
#ifndef NDEBUG #ifndef NDEBUG
for (const auto &P : ArgPack.pack_elements()) { for (const auto &P : ArgPack.pack_elements()) {
assert(P.getKind() == TemplateArgument::Type &&"Pack contains a non-type"); assert(P.getKind() == TemplateArgument::Type && "Pack contains a non-type");
assert(P.getAsType().isCanonical() && "Pack contains non-canonical type"); assert(P.getAsType().isCanonical() && "Pack contains non-canonical type");
} }
#endif #endif
llvm::FoldingSetNodeID ID; llvm::FoldingSetNodeID ID;
SubstTemplateTypeParmPackType::Profile(ID, Parm, ArgPack); SubstTemplateTypeParmPackType::Profile(ID, AssociatedDecl, Index, ArgPack);
void *InsertPos = nullptr; void *InsertPos = nullptr;
if (SubstTemplateTypeParmPackType *SubstParm if (SubstTemplateTypeParmPackType *SubstParm =
= SubstTemplateTypeParmPackTypes.FindNodeOrInsertPos(ID, InsertPos)) SubstTemplateTypeParmPackTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(SubstParm, 0); return QualType(SubstParm, 0);
QualType Canon; QualType Canon;
if (!Parm->isCanonicalUnqualified()) { if (!AssociatedDecl->isCanonicalDecl()) {
Canon = getCanonicalType(QualType(Parm, 0)); Canon = getSubstTemplateTypeParmPackType(AssociatedDecl->getCanonicalDecl(),
Canon = getSubstTemplateTypeParmPackType(cast<TemplateTypeParmType>(Canon), Index, ArgPack);
ArgPack);
SubstTemplateTypeParmPackTypes.FindNodeOrInsertPos(ID, InsertPos); SubstTemplateTypeParmPackTypes.FindNodeOrInsertPos(ID, InsertPos);
} }
auto *SubstParm auto *SubstParm = new (*this, TypeAlignment)
= new (*this, TypeAlignment) SubstTemplateTypeParmPackType(Parm, Canon, SubstTemplateTypeParmPackType(Canon, AssociatedDecl, Index, ArgPack);
ArgPack);
Types.push_back(SubstParm); Types.push_back(SubstParm);
SubstTemplateTypeParmPackTypes.InsertNode(SubstParm, InsertPos); SubstTemplateTypeParmPackTypes.InsertNode(SubstParm, InsertPos);
return QualType(SubstParm, 0); return QualType(SubstParm, 0);
@ -6241,13 +6239,13 @@ ASTContext::getCanonicalTemplateName(const TemplateName &Name) const {
} }
case TemplateName::SubstTemplateTemplateParmPack: { case TemplateName::SubstTemplateTemplateParmPack: {
SubstTemplateTemplateParmPackStorage *subst SubstTemplateTemplateParmPackStorage *subst =
= Name.getAsSubstTemplateTemplateParmPack(); Name.getAsSubstTemplateTemplateParmPack();
TemplateTemplateParmDecl *canonParameter TemplateArgument canonArgPack =
= getCanonicalTemplateTemplateParmDecl(subst->getParameterPack()); getCanonicalTemplateArgument(subst->getArgumentPack());
TemplateArgument canonArgPack return getSubstTemplateTemplateParmPack(
= getCanonicalTemplateArgument(subst->getArgumentPack()); canonArgPack, subst->getAssociatedDecl()->getCanonicalDecl(),
return getSubstTemplateTemplateParmPack(canonParameter, canonArgPack); subst->getIndex());
} }
} }
@ -9250,17 +9248,20 @@ ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS,
} }
TemplateName TemplateName
ASTContext::getSubstTemplateTemplateParm(TemplateTemplateParmDecl *param, ASTContext::getSubstTemplateTemplateParm(TemplateName Replacement,
TemplateName replacement) const { Decl *AssociatedDecl, unsigned Index,
Optional<unsigned> PackIndex) const {
llvm::FoldingSetNodeID ID; llvm::FoldingSetNodeID ID;
SubstTemplateTemplateParmStorage::Profile(ID, param, replacement); SubstTemplateTemplateParmStorage::Profile(ID, Replacement, AssociatedDecl,
Index, PackIndex);
void *insertPos = nullptr; void *insertPos = nullptr;
SubstTemplateTemplateParmStorage *subst SubstTemplateTemplateParmStorage *subst
= SubstTemplateTemplateParms.FindNodeOrInsertPos(ID, insertPos); = SubstTemplateTemplateParms.FindNodeOrInsertPos(ID, insertPos);
if (!subst) { if (!subst) {
subst = new (*this) SubstTemplateTemplateParmStorage(param, replacement); subst = new (*this) SubstTemplateTemplateParmStorage(
Replacement, AssociatedDecl, Index, PackIndex);
SubstTemplateTemplateParms.InsertNode(subst, insertPos); SubstTemplateTemplateParms.InsertNode(subst, insertPos);
} }
@ -9268,20 +9269,21 @@ ASTContext::getSubstTemplateTemplateParm(TemplateTemplateParmDecl *param,
} }
TemplateName TemplateName
ASTContext::getSubstTemplateTemplateParmPack(TemplateTemplateParmDecl *Param, ASTContext::getSubstTemplateTemplateParmPack(const TemplateArgument &ArgPack,
const TemplateArgument &ArgPack) const { Decl *AssociatedDecl,
unsigned Index) const {
auto &Self = const_cast<ASTContext &>(*this); auto &Self = const_cast<ASTContext &>(*this);
llvm::FoldingSetNodeID ID; llvm::FoldingSetNodeID ID;
SubstTemplateTemplateParmPackStorage::Profile(ID, Self, Param, ArgPack); SubstTemplateTemplateParmPackStorage::Profile(ID, Self, ArgPack,
AssociatedDecl, Index);
void *InsertPos = nullptr; void *InsertPos = nullptr;
SubstTemplateTemplateParmPackStorage *Subst SubstTemplateTemplateParmPackStorage *Subst
= SubstTemplateTemplateParmPacks.FindNodeOrInsertPos(ID, InsertPos); = SubstTemplateTemplateParmPacks.FindNodeOrInsertPos(ID, InsertPos);
if (!Subst) { if (!Subst) {
Subst = new (*this) SubstTemplateTemplateParmPackStorage(Param, Subst = new (*this) SubstTemplateTemplateParmPackStorage(
ArgPack.pack_size(), ArgPack.pack_elements(), AssociatedDecl, Index);
ArgPack.pack_begin());
SubstTemplateTemplateParmPacks.InsertNode(Subst, InsertPos); SubstTemplateTemplateParmPacks.InsertNode(Subst, InsertPos);
} }
@ -12931,14 +12933,18 @@ static QualType getCommonSugarTypeNode(ASTContext &Ctx, const Type *X,
case Type::SubstTemplateTypeParm: { case Type::SubstTemplateTypeParm: {
const auto *SX = cast<SubstTemplateTypeParmType>(X), const auto *SX = cast<SubstTemplateTypeParmType>(X),
*SY = cast<SubstTemplateTypeParmType>(Y); *SY = cast<SubstTemplateTypeParmType>(Y);
const TemplateTypeParmType *PX = SX->getReplacedParameter(); Decl *CD =
if (PX != SY->getReplacedParameter()) ::getCommonDecl(SX->getAssociatedDecl(), SY->getAssociatedDecl());
if (!CD)
return QualType();
unsigned Index = SX->getIndex();
if (Index != SY->getIndex())
return QualType(); return QualType();
auto PackIndex = SX->getPackIndex(); auto PackIndex = SX->getPackIndex();
if (PackIndex != SY->getPackIndex()) if (PackIndex != SY->getPackIndex())
return QualType(); return QualType();
return Ctx.getSubstTemplateTypeParmType( return Ctx.getSubstTemplateTypeParmType(Ctx.getQualifiedType(Underlying),
PX, Ctx.getQualifiedType(Underlying), PackIndex); CD, Index, PackIndex);
} }
case Type::ObjCTypeParam: case Type::ObjCTypeParam:
// FIXME: Try to merge these. // FIXME: Try to merge these.

View File

@ -1523,8 +1523,7 @@ ExpectedType ASTNodeImporter::VisitTemplateTypeParmType(
ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmType( ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmType(
const SubstTemplateTypeParmType *T) { const SubstTemplateTypeParmType *T) {
Expected<const TemplateTypeParmType *> ReplacedOrErr = Expected<Decl *> ReplacedOrErr = import(T->getAssociatedDecl());
import(T->getReplacedParameter());
if (!ReplacedOrErr) if (!ReplacedOrErr)
return ReplacedOrErr.takeError(); return ReplacedOrErr.takeError();
@ -1533,13 +1532,13 @@ ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmType(
return ToReplacementTypeOrErr.takeError(); return ToReplacementTypeOrErr.takeError();
return Importer.getToContext().getSubstTemplateTypeParmType( return Importer.getToContext().getSubstTemplateTypeParmType(
*ReplacedOrErr, *ToReplacementTypeOrErr, T->getPackIndex()); *ToReplacementTypeOrErr, *ReplacedOrErr, T->getIndex(),
T->getPackIndex());
} }
ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmPackType( ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmPackType(
const SubstTemplateTypeParmPackType *T) { const SubstTemplateTypeParmPackType *T) {
Expected<const TemplateTypeParmType *> ReplacedOrErr = Expected<Decl *> ReplacedOrErr = import(T->getAssociatedDecl());
import(T->getReplacedParameter());
if (!ReplacedOrErr) if (!ReplacedOrErr)
return ReplacedOrErr.takeError(); return ReplacedOrErr.takeError();
@ -1548,7 +1547,7 @@ ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmPackType(
return ToArgumentPack.takeError(); return ToArgumentPack.takeError();
return Importer.getToContext().getSubstTemplateTypeParmPackType( return Importer.getToContext().getSubstTemplateTypeParmPackType(
*ReplacedOrErr, *ToArgumentPack); *ReplacedOrErr, T->getIndex(), *ToArgumentPack);
} }
ExpectedType ASTNodeImporter::VisitTemplateSpecializationType( ExpectedType ASTNodeImporter::VisitTemplateSpecializationType(
@ -3753,6 +3752,10 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
} }
} }
// If it is a template, import all related things.
if (Error Err = ImportTemplateInformation(D, ToFunction))
return std::move(Err);
if (D->doesThisDeclarationHaveABody()) { if (D->doesThisDeclarationHaveABody()) {
Error Err = ImportFunctionDeclBody(D, ToFunction); Error Err = ImportFunctionDeclBody(D, ToFunction);
@ -3774,10 +3777,6 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
// FIXME: Other bits to merge? // FIXME: Other bits to merge?
// If it is a template, import all related things.
if (Error Err = ImportTemplateInformation(D, ToFunction))
return std::move(Err);
addDeclToContexts(D, ToFunction); addDeclToContexts(D, ToFunction);
if (auto *FromCXXMethod = dyn_cast<CXXMethodDecl>(D)) if (auto *FromCXXMethod = dyn_cast<CXXMethodDecl>(D))
@ -5998,6 +5997,30 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl(
D2->setTemplateSpecializationKind(D->getTemplateSpecializationKind()); D2->setTemplateSpecializationKind(D->getTemplateSpecializationKind());
if (auto P = D->getInstantiatedFrom()) {
if (auto *CTD = P.dyn_cast<ClassTemplateDecl *>()) {
if (auto CTDorErr = import(CTD))
D2->setInstantiationOf(*CTDorErr);
} else {
auto *CTPSD = cast<ClassTemplatePartialSpecializationDecl *>(P);
auto CTPSDOrErr = import(CTPSD);
if (!CTPSDOrErr)
return CTPSDOrErr.takeError();
const TemplateArgumentList &DArgs = D->getTemplateInstantiationArgs();
SmallVector<TemplateArgument, 2> D2ArgsVec(DArgs.size());
for (unsigned I = 0; I < DArgs.size(); ++I) {
const TemplateArgument &DArg = DArgs[I];
if (auto ArgOrErr = import(DArg))
D2ArgsVec[I] = *ArgOrErr;
else
return ArgOrErr.takeError();
}
D2->setInstantiationOf(
*CTPSDOrErr,
TemplateArgumentList::CreateCopy(Importer.getToContext(), D2ArgsVec));
}
}
if (D->isCompleteDefinition()) if (D->isCompleteDefinition())
if (Error Err = ImportDefinition(D, D2)) if (Error Err = ImportDefinition(D, D2))
return std::move(Err); return std::move(Err);
@ -6161,15 +6184,6 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl(
} }
} }
} else { } else {
// Import the type.
QualType T;
if (Error Err = importInto(T, D->getType()))
return std::move(Err);
auto TInfoOrErr = import(D->getTypeSourceInfo());
if (!TInfoOrErr)
return TInfoOrErr.takeError();
TemplateArgumentListInfo ToTAInfo; TemplateArgumentListInfo ToTAInfo;
if (const ASTTemplateArgumentListInfo *Args = D->getTemplateArgsInfo()) { if (const ASTTemplateArgumentListInfo *Args = D->getTemplateArgsInfo()) {
if (Error Err = ImportTemplateArgumentListInfo(*Args, ToTAInfo)) if (Error Err = ImportTemplateArgumentListInfo(*Args, ToTAInfo))
@ -6194,7 +6208,7 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl(
PartVarSpecDecl *ToPartial; PartVarSpecDecl *ToPartial;
if (GetImportedOrCreateDecl(ToPartial, D, Importer.getToContext(), DC, if (GetImportedOrCreateDecl(ToPartial, D, Importer.getToContext(), DC,
*BeginLocOrErr, *IdLocOrErr, *ToTPListOrErr, *BeginLocOrErr, *IdLocOrErr, *ToTPListOrErr,
VarTemplate, T, *TInfoOrErr, VarTemplate, QualType(), nullptr,
D->getStorageClass(), TemplateArgs, ArgInfos)) D->getStorageClass(), TemplateArgs, ArgInfos))
return ToPartial; return ToPartial;
@ -6215,11 +6229,21 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl(
} else { // Full specialization } else { // Full specialization
if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), DC, if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), DC,
*BeginLocOrErr, *IdLocOrErr, VarTemplate, *BeginLocOrErr, *IdLocOrErr, VarTemplate,
T, *TInfoOrErr, QualType(), nullptr, D->getStorageClass(),
D->getStorageClass(), TemplateArgs)) TemplateArgs))
return D2; return D2;
} }
QualType T;
if (Error Err = importInto(T, D->getType()))
return std::move(Err);
D2->setType(T);
auto TInfoOrErr = import(D->getTypeSourceInfo());
if (!TInfoOrErr)
return TInfoOrErr.takeError();
D2->setTypeSourceInfo(*TInfoOrErr);
if (D->getPointOfInstantiation().isValid()) { if (D->getPointOfInstantiation().isValid()) {
if (ExpectedSLoc POIOrErr = import(D->getPointOfInstantiation())) if (ExpectedSLoc POIOrErr = import(D->getPointOfInstantiation()))
D2->setPointOfInstantiation(*POIOrErr); D2->setPointOfInstantiation(*POIOrErr);
@ -8412,14 +8436,14 @@ ExpectedStmt ASTNodeImporter::VisitSubstNonTypeTemplateParmExpr(
Error Err = Error::success(); Error Err = Error::success();
auto ToType = importChecked(Err, E->getType()); auto ToType = importChecked(Err, E->getType());
auto ToExprLoc = importChecked(Err, E->getExprLoc()); auto ToExprLoc = importChecked(Err, E->getExprLoc());
auto ToParameter = importChecked(Err, E->getParameter()); auto ToAssociatedDecl = importChecked(Err, E->getAssociatedDecl());
auto ToReplacement = importChecked(Err, E->getReplacement()); auto ToReplacement = importChecked(Err, E->getReplacement());
if (Err) if (Err)
return std::move(Err); return std::move(Err);
return new (Importer.getToContext()) SubstNonTypeTemplateParmExpr( return new (Importer.getToContext()) SubstNonTypeTemplateParmExpr(
ToType, E->getValueKind(), ToExprLoc, ToParameter, ToType, E->getValueKind(), ToExprLoc, ToReplacement, ToAssociatedDecl,
E->isReferenceParameter(), ToReplacement); E->getIndex(), E->getPackIndex(), E->isReferenceParameter());
} }
ExpectedStmt ASTNodeImporter::VisitTypeTraitExpr(TypeTraitExpr *E) { ExpectedStmt ASTNodeImporter::VisitTypeTraitExpr(TypeTraitExpr *E) {
@ -9396,33 +9420,34 @@ Expected<TemplateName> ASTImporter::Import(TemplateName From) {
case TemplateName::SubstTemplateTemplateParm: { case TemplateName::SubstTemplateTemplateParm: {
SubstTemplateTemplateParmStorage *Subst = SubstTemplateTemplateParmStorage *Subst =
From.getAsSubstTemplateTemplateParm(); From.getAsSubstTemplateTemplateParm();
ExpectedDecl ParamOrErr = Import(Subst->getParameter());
if (!ParamOrErr)
return ParamOrErr.takeError();
auto ReplacementOrErr = Import(Subst->getReplacement()); auto ReplacementOrErr = Import(Subst->getReplacement());
if (!ReplacementOrErr) if (!ReplacementOrErr)
return ReplacementOrErr.takeError(); return ReplacementOrErr.takeError();
auto AssociatedDeclOrErr = Import(Subst->getAssociatedDecl());
if (!AssociatedDeclOrErr)
return AssociatedDeclOrErr.takeError();
return ToContext.getSubstTemplateTemplateParm( return ToContext.getSubstTemplateTemplateParm(
cast<TemplateTemplateParmDecl>(*ParamOrErr), *ReplacementOrErr); *ReplacementOrErr, *AssociatedDeclOrErr, Subst->getIndex(),
Subst->getPackIndex());
} }
case TemplateName::SubstTemplateTemplateParmPack: { case TemplateName::SubstTemplateTemplateParmPack: {
SubstTemplateTemplateParmPackStorage *SubstPack SubstTemplateTemplateParmPackStorage *SubstPack =
= From.getAsSubstTemplateTemplateParmPack(); From.getAsSubstTemplateTemplateParmPack();
ExpectedDecl ParamOrErr = Import(SubstPack->getParameterPack());
if (!ParamOrErr)
return ParamOrErr.takeError();
ASTNodeImporter Importer(*this); ASTNodeImporter Importer(*this);
auto ArgPackOrErr = auto ArgPackOrErr =
Importer.ImportTemplateArgument(SubstPack->getArgumentPack()); Importer.ImportTemplateArgument(SubstPack->getArgumentPack());
if (!ArgPackOrErr) if (!ArgPackOrErr)
return ArgPackOrErr.takeError(); return ArgPackOrErr.takeError();
auto AssociatedDeclOrErr = Import(SubstPack->getAssociatedDecl());
if (!AssociatedDeclOrErr)
return AssociatedDeclOrErr.takeError();
return ToContext.getSubstTemplateTemplateParmPack( return ToContext.getSubstTemplateTemplateParmPack(
cast<TemplateTemplateParmDecl>(*ParamOrErr), *ArgPackOrErr); *ArgPackOrErr, *AssociatedDeclOrErr, SubstPack->getIndex());
} }
case TemplateName::UsingTemplate: { case TemplateName::UsingTemplate: {
auto UsingOrError = Import(From.getAsUsingShadowDecl()); auto UsingOrError = Import(From.getAsUsingShadowDecl());

View File

@ -289,8 +289,14 @@ class StmtComparer {
bool IsStmtEquivalent(const SubstNonTypeTemplateParmExpr *E1, bool IsStmtEquivalent(const SubstNonTypeTemplateParmExpr *E1,
const SubstNonTypeTemplateParmExpr *E2) { const SubstNonTypeTemplateParmExpr *E2) {
return IsStructurallyEquivalent(Context, E1->getParameter(), if (!IsStructurallyEquivalent(Context, E1->getAssociatedDecl(),
E2->getParameter()); E2->getAssociatedDecl()))
return false;
if (E1->getIndex() != E2->getIndex())
return false;
if (E1->getPackIndex() != E2->getPackIndex())
return false;
return true;
} }
bool IsStmtEquivalent(const SubstNonTypeTemplateParmPackExpr *E1, bool IsStmtEquivalent(const SubstNonTypeTemplateParmPackExpr *E1,
@ -510,8 +516,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
*P2 = N2.getAsSubstTemplateTemplateParmPack(); *P2 = N2.getAsSubstTemplateTemplateParmPack();
return IsStructurallyEquivalent(Context, P1->getArgumentPack(), return IsStructurallyEquivalent(Context, P1->getArgumentPack(),
P2->getArgumentPack()) && P2->getArgumentPack()) &&
IsStructurallyEquivalent(Context, P1->getParameterPack(), IsStructurallyEquivalent(Context, P1->getAssociatedDecl(),
P2->getParameterPack()); P2->getAssociatedDecl()) &&
P1->getIndex() == P2->getIndex();
} }
case TemplateName::Template: case TemplateName::Template:
@ -1061,13 +1068,14 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
case Type::SubstTemplateTypeParm: { case Type::SubstTemplateTypeParm: {
const auto *Subst1 = cast<SubstTemplateTypeParmType>(T1); const auto *Subst1 = cast<SubstTemplateTypeParmType>(T1);
const auto *Subst2 = cast<SubstTemplateTypeParmType>(T2); const auto *Subst2 = cast<SubstTemplateTypeParmType>(T2);
if (!IsStructurallyEquivalent(Context,
QualType(Subst1->getReplacedParameter(), 0),
QualType(Subst2->getReplacedParameter(), 0)))
return false;
if (!IsStructurallyEquivalent(Context, Subst1->getReplacementType(), if (!IsStructurallyEquivalent(Context, Subst1->getReplacementType(),
Subst2->getReplacementType())) Subst2->getReplacementType()))
return false; return false;
if (!IsStructurallyEquivalent(Context, Subst1->getAssociatedDecl(),
Subst2->getAssociatedDecl()))
return false;
if (Subst1->getIndex() != Subst2->getIndex())
return false;
if (Subst1->getPackIndex() != Subst2->getPackIndex()) if (Subst1->getPackIndex() != Subst2->getPackIndex())
return false; return false;
break; break;
@ -1076,9 +1084,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
case Type::SubstTemplateTypeParmPack: { case Type::SubstTemplateTypeParmPack: {
const auto *Subst1 = cast<SubstTemplateTypeParmPackType>(T1); const auto *Subst1 = cast<SubstTemplateTypeParmPackType>(T1);
const auto *Subst2 = cast<SubstTemplateTypeParmPackType>(T2); const auto *Subst2 = cast<SubstTemplateTypeParmPackType>(T2);
if (!IsStructurallyEquivalent(Context, if (!IsStructurallyEquivalent(Context, Subst1->getAssociatedDecl(),
QualType(Subst1->getReplacedParameter(), 0), Subst2->getAssociatedDecl()))
QualType(Subst2->getReplacedParameter(), 0))) return false;
if (Subst1->getIndex() != Subst2->getIndex())
return false; return false;
if (!IsStructurallyEquivalent(Context, Subst1->getArgumentPack(), if (!IsStructurallyEquivalent(Context, Subst1->getArgumentPack(),
Subst2->getArgumentPack())) Subst2->getArgumentPack()))

View File

@ -1557,3 +1557,56 @@ void TemplateParamObjectDecl::printAsInit(llvm::raw_ostream &OS,
const PrintingPolicy &Policy) const { const PrintingPolicy &Policy) const {
getValue().printPretty(OS, Policy, getType(), &getASTContext()); getValue().printPretty(OS, Policy, getType(), &getASTContext());
} }
TemplateParameterList *clang::getReplacedTemplateParameterList(Decl *D) {
switch (D->getKind()) {
case Decl::Kind::ClassTemplate:
return cast<ClassTemplateDecl>(D)->getTemplateParameters();
case Decl::Kind::ClassTemplateSpecialization: {
const auto *CTSD = cast<ClassTemplateSpecializationDecl>(D);
auto P = CTSD->getSpecializedTemplateOrPartial();
if (const auto *CTPSD =
P.dyn_cast<ClassTemplatePartialSpecializationDecl *>())
return CTPSD->getTemplateParameters();
return cast<ClassTemplateDecl *>(P)->getTemplateParameters();
}
case Decl::Kind::ClassTemplatePartialSpecialization:
return cast<ClassTemplatePartialSpecializationDecl>(D)
->getTemplateParameters();
case Decl::Kind::TypeAliasTemplate:
return cast<TypeAliasTemplateDecl>(D)->getTemplateParameters();
case Decl::Kind::BuiltinTemplate:
return cast<BuiltinTemplateDecl>(D)->getTemplateParameters();
case Decl::Kind::CXXDeductionGuide:
case Decl::Kind::CXXConversion:
case Decl::Kind::CXXConstructor:
case Decl::Kind::CXXDestructor:
case Decl::Kind::CXXMethod:
case Decl::Kind::Function:
return cast<FunctionDecl>(D)
->getTemplateSpecializationInfo()
->getTemplate()
->getTemplateParameters();
case Decl::Kind::FunctionTemplate:
return cast<FunctionTemplateDecl>(D)->getTemplateParameters();
case Decl::Kind::VarTemplate:
return cast<VarTemplateDecl>(D)->getTemplateParameters();
case Decl::Kind::VarTemplateSpecialization: {
const auto *VTSD = cast<VarTemplateSpecializationDecl>(D);
auto P = VTSD->getSpecializedTemplateOrPartial();
if (const auto *VTPSD =
P.dyn_cast<VarTemplatePartialSpecializationDecl *>())
return VTPSD->getTemplateParameters();
return cast<VarTemplateDecl *>(P)->getTemplateParameters();
}
case Decl::Kind::VarTemplatePartialSpecialization:
return cast<VarTemplatePartialSpecializationDecl>(D)
->getTemplateParameters();
case Decl::Kind::TemplateTemplateParm:
return cast<TemplateTemplateParmDecl>(D)->getTemplateParameters();
case Decl::Kind::Concept:
return cast<ConceptDecl>(D)->getTemplateParameters();
default:
llvm_unreachable("Unhandled templated declaration kind");
}
}

View File

@ -1574,6 +1574,11 @@ SizeOfPackExpr *SizeOfPackExpr::CreateDeserialized(ASTContext &Context,
return new (Storage) SizeOfPackExpr(EmptyShell(), NumPartialArgs); return new (Storage) SizeOfPackExpr(EmptyShell(), NumPartialArgs);
} }
NonTypeTemplateParmDecl *SubstNonTypeTemplateParmExpr::getParameter() const {
return cast<NonTypeTemplateParmDecl>(
getReplacedTemplateParameterList(getAssociatedDecl())->asArray()[Index]);
}
QualType SubstNonTypeTemplateParmExpr::getParameterType( QualType SubstNonTypeTemplateParmExpr::getParameterType(
const ASTContext &Context) const { const ASTContext &Context) const {
// Note that, for a class type NTTP, we will have an lvalue of type 'const // Note that, for a class type NTTP, we will have an lvalue of type 'const
@ -1584,15 +1589,22 @@ QualType SubstNonTypeTemplateParmExpr::getParameterType(
} }
SubstNonTypeTemplateParmPackExpr::SubstNonTypeTemplateParmPackExpr( SubstNonTypeTemplateParmPackExpr::SubstNonTypeTemplateParmPackExpr(
QualType T, ExprValueKind ValueKind, NonTypeTemplateParmDecl *Param, QualType T, ExprValueKind ValueKind, SourceLocation NameLoc,
SourceLocation NameLoc, const TemplateArgument &ArgPack) const TemplateArgument &ArgPack, Decl *AssociatedDecl, unsigned Index)
: Expr(SubstNonTypeTemplateParmPackExprClass, T, ValueKind, OK_Ordinary), : Expr(SubstNonTypeTemplateParmPackExprClass, T, ValueKind, OK_Ordinary),
Param(Param), Arguments(ArgPack.pack_begin()), AssociatedDecl(AssociatedDecl), Arguments(ArgPack.pack_begin()),
NumArguments(ArgPack.pack_size()), NameLoc(NameLoc) { NumArguments(ArgPack.pack_size()), Index(Index), NameLoc(NameLoc) {
assert(AssociatedDecl != nullptr);
setDependence(ExprDependence::TypeValueInstantiation | setDependence(ExprDependence::TypeValueInstantiation |
ExprDependence::UnexpandedPack); ExprDependence::UnexpandedPack);
} }
NonTypeTemplateParmDecl *
SubstNonTypeTemplateParmPackExpr::getParameterPack() const {
return cast<NonTypeTemplateParmDecl>(
getReplacedTemplateParameterList(getAssociatedDecl())->asArray()[Index]);
}
TemplateArgument SubstNonTypeTemplateParmPackExpr::getArgumentPack() const { TemplateArgument SubstNonTypeTemplateParmPackExpr::getArgumentPack() const {
return TemplateArgument(llvm::makeArrayRef(Arguments, NumArguments)); return TemplateArgument(llvm::makeArrayRef(Arguments, NumArguments));
} }

View File

@ -692,10 +692,16 @@ void JSONNodeDumper::VisitTemplateTypeParmType(
void JSONNodeDumper::VisitSubstTemplateTypeParmType( void JSONNodeDumper::VisitSubstTemplateTypeParmType(
const SubstTemplateTypeParmType *STTPT) { const SubstTemplateTypeParmType *STTPT) {
JOS.attribute("index", STTPT->getIndex());
if (auto PackIndex = STTPT->getPackIndex()) if (auto PackIndex = STTPT->getPackIndex())
JOS.attribute("pack_index", *PackIndex); JOS.attribute("pack_index", *PackIndex);
} }
void JSONNodeDumper::VisitSubstTemplateTypeParmPackType(
const SubstTemplateTypeParmPackType *T) {
JOS.attribute("index", T->getIndex());
}
void JSONNodeDumper::VisitAutoType(const AutoType *AT) { void JSONNodeDumper::VisitAutoType(const AutoType *AT) {
JOS.attribute("undeduced", !AT->isDeduced()); JOS.attribute("undeduced", !AT->isDeduced());
switch (AT->getKeyword()) { switch (AT->getKeyword()) {

View File

@ -671,7 +671,7 @@ public:
} }
} }
void AddDecl(Decl *D) { void AddDecl(const Decl *D) {
Hash.AddBoolean(D); Hash.AddBoolean(D);
if (D) { if (D) {
Hash.AddDecl(D); Hash.AddDecl(D);
@ -995,13 +995,13 @@ public:
void void
VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T) { VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T) {
AddType(T->getReplacedParameter()); AddDecl(T->getAssociatedDecl());
Hash.AddTemplateArgument(T->getArgumentPack()); Hash.AddTemplateArgument(T->getArgumentPack());
VisitType(T); VisitType(T);
} }
void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) { void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) {
AddType(T->getReplacedParameter()); AddDecl(T->getAssociatedDecl());
AddQualType(T->getReplacementType()); AddQualType(T->getReplacementType());
VisitType(T); VisitType(T);
} }

View File

@ -35,31 +35,49 @@ using namespace clang;
TemplateArgument TemplateArgument
SubstTemplateTemplateParmPackStorage::getArgumentPack() const { SubstTemplateTemplateParmPackStorage::getArgumentPack() const {
return TemplateArgument(llvm::makeArrayRef(Arguments, size())); return TemplateArgument(llvm::makeArrayRef(Arguments, Bits.Data));
}
TemplateTemplateParmDecl *
SubstTemplateTemplateParmPackStorage::getParameterPack() const {
return cast<TemplateTemplateParmDecl>(
getReplacedTemplateParameterList(getAssociatedDecl())
->asArray()[Bits.Index]);
}
TemplateTemplateParmDecl *
SubstTemplateTemplateParmStorage::getParameter() const {
return cast<TemplateTemplateParmDecl>(
getReplacedTemplateParameterList(getAssociatedDecl())
->asArray()[Bits.Index]);
} }
void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) { void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, Parameter, Replacement); Profile(ID, Replacement, getAssociatedDecl(), getIndex(), getPackIndex());
} }
void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID, void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID,
TemplateTemplateParmDecl *parameter, TemplateName Replacement,
TemplateName replacement) { Decl *AssociatedDecl,
ID.AddPointer(parameter); unsigned Index,
ID.AddPointer(replacement.getAsVoidPointer()); Optional<unsigned> PackIndex) {
Replacement.Profile(ID);
ID.AddPointer(AssociatedDecl);
ID.AddInteger(Index);
ID.AddInteger(PackIndex ? *PackIndex + 1 : 0);
} }
void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID, void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
ASTContext &Context) { ASTContext &Context) {
Profile(ID, Context, Parameter, getArgumentPack()); Profile(ID, Context, getArgumentPack(), getAssociatedDecl(), getIndex());
} }
void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID, void SubstTemplateTemplateParmPackStorage::Profile(
ASTContext &Context, llvm::FoldingSetNodeID &ID, ASTContext &Context,
TemplateTemplateParmDecl *Parameter, const TemplateArgument &ArgPack, Decl *AssociatedDecl, unsigned Index) {
const TemplateArgument &ArgPack) {
ID.AddPointer(Parameter);
ArgPack.Profile(ID, Context); ArgPack.Profile(ID, Context);
ID.AddPointer(AssociatedDecl);
ID.AddInteger(Index);
} }
TemplateName::TemplateName(void *Ptr) { TemplateName::TemplateName(void *Ptr) {

View File

@ -1576,10 +1576,18 @@ void TextNodeDumper::VisitTemplateTypeParmType(const TemplateTypeParmType *T) {
void TextNodeDumper::VisitSubstTemplateTypeParmType( void TextNodeDumper::VisitSubstTemplateTypeParmType(
const SubstTemplateTypeParmType *T) { const SubstTemplateTypeParmType *T) {
dumpDeclRef(T->getAssociatedDecl());
VisitTemplateTypeParmDecl(T->getReplacedParameter());
if (auto PackIndex = T->getPackIndex()) if (auto PackIndex = T->getPackIndex())
OS << " pack_index " << *PackIndex; OS << " pack_index " << *PackIndex;
} }
void TextNodeDumper::VisitSubstTemplateTypeParmPackType(
const SubstTemplateTypeParmPackType *T) {
dumpDeclRef(T->getAssociatedDecl());
VisitTemplateTypeParmDecl(T->getReplacedParameter());
}
void TextNodeDumper::VisitAutoType(const AutoType *T) { void TextNodeDumper::VisitAutoType(const AutoType *T) {
if (T->isDecltypeAuto()) if (T->isDecltypeAuto())
OS << " decltype(auto)"; OS << " decltype(auto)";

View File

@ -1166,8 +1166,9 @@ public:
== T->getReplacementType().getAsOpaquePtr()) == T->getReplacementType().getAsOpaquePtr())
return QualType(T, 0); return QualType(T, 0);
return Ctx.getSubstTemplateTypeParmType(T->getReplacedParameter(), return Ctx.getSubstTemplateTypeParmType(replacementType,
replacementType, T->getPackIndex()); T->getAssociatedDecl(),
T->getIndex(), T->getPackIndex());
} }
// FIXME: Non-trivial to implement, but important for C++ // FIXME: Non-trivial to implement, but important for C++
@ -3668,28 +3669,54 @@ IdentifierInfo *TemplateTypeParmType::getIdentifier() const {
return isCanonicalUnqualified() ? nullptr : getDecl()->getIdentifier(); return isCanonicalUnqualified() ? nullptr : getDecl()->getIdentifier();
} }
static const TemplateTypeParmDecl *getReplacedParameter(Decl *D,
unsigned Index) {
if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(D))
return TTP;
return cast<TemplateTypeParmDecl>(
getReplacedTemplateParameterList(D)->getParam(Index));
}
SubstTemplateTypeParmType::SubstTemplateTypeParmType( SubstTemplateTypeParmType::SubstTemplateTypeParmType(
const TemplateTypeParmType *Param, QualType Replacement, QualType Replacement, Decl *AssociatedDecl, unsigned Index,
Optional<unsigned> PackIndex) Optional<unsigned> PackIndex)
: Type(SubstTemplateTypeParm, Replacement.getCanonicalType(), : Type(SubstTemplateTypeParm, Replacement.getCanonicalType(),
Replacement->getDependence()), Replacement->getDependence()),
Replaced(Param) { AssociatedDecl(AssociatedDecl) {
SubstTemplateTypeParmTypeBits.HasNonCanonicalUnderlyingType = SubstTemplateTypeParmTypeBits.HasNonCanonicalUnderlyingType =
Replacement != getCanonicalTypeInternal(); Replacement != getCanonicalTypeInternal();
if (SubstTemplateTypeParmTypeBits.HasNonCanonicalUnderlyingType) if (SubstTemplateTypeParmTypeBits.HasNonCanonicalUnderlyingType)
*getTrailingObjects<QualType>() = Replacement; *getTrailingObjects<QualType>() = Replacement;
SubstTemplateTypeParmTypeBits.Index = Index;
SubstTemplateTypeParmTypeBits.PackIndex = PackIndex ? *PackIndex + 1 : 0; SubstTemplateTypeParmTypeBits.PackIndex = PackIndex ? *PackIndex + 1 : 0;
assert(AssociatedDecl != nullptr);
}
const TemplateTypeParmDecl *
SubstTemplateTypeParmType::getReplacedParameter() const {
return ::getReplacedParameter(getAssociatedDecl(), getIndex());
} }
SubstTemplateTypeParmPackType::SubstTemplateTypeParmPackType( SubstTemplateTypeParmPackType::SubstTemplateTypeParmPackType(
const TemplateTypeParmType *Param, QualType Canon, QualType Canon, Decl *AssociatedDecl, unsigned Index,
const TemplateArgument &ArgPack) const TemplateArgument &ArgPack)
: Type(SubstTemplateTypeParmPack, Canon, : Type(SubstTemplateTypeParmPack, Canon,
TypeDependence::DependentInstantiation | TypeDependence::DependentInstantiation |
TypeDependence::UnexpandedPack), TypeDependence::UnexpandedPack),
Replaced(Param), Arguments(ArgPack.pack_begin()) { Arguments(ArgPack.pack_begin()), AssociatedDecl(AssociatedDecl) {
SubstTemplateTypeParmPackTypeBits.Index = Index;
SubstTemplateTypeParmPackTypeBits.NumArgs = ArgPack.pack_size(); SubstTemplateTypeParmPackTypeBits.NumArgs = ArgPack.pack_size();
assert(AssociatedDecl != nullptr);
}
const TemplateTypeParmDecl *
SubstTemplateTypeParmPackType::getReplacedParameter() const {
return ::getReplacedParameter(getAssociatedDecl(), getIndex());
}
IdentifierInfo *SubstTemplateTypeParmPackType::getIdentifier() const {
return getReplacedParameter()->getIdentifier();
} }
TemplateArgument SubstTemplateTypeParmPackType::getArgumentPack() const { TemplateArgument SubstTemplateTypeParmPackType::getArgumentPack() const {
@ -3697,13 +3724,15 @@ TemplateArgument SubstTemplateTypeParmPackType::getArgumentPack() const {
} }
void SubstTemplateTypeParmPackType::Profile(llvm::FoldingSetNodeID &ID) { void SubstTemplateTypeParmPackType::Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getReplacedParameter(), getArgumentPack()); Profile(ID, getAssociatedDecl(), getIndex(), getArgumentPack());
} }
void SubstTemplateTypeParmPackType::Profile(llvm::FoldingSetNodeID &ID, void SubstTemplateTypeParmPackType::Profile(llvm::FoldingSetNodeID &ID,
const TemplateTypeParmType *Replaced, const Decl *AssociatedDecl,
unsigned Index,
const TemplateArgument &ArgPack) { const TemplateArgument &ArgPack) {
ID.AddPointer(Replaced); ID.AddPointer(AssociatedDecl);
ID.AddInteger(Index);
ID.AddInteger(ArgPack.pack_size()); ID.AddInteger(ArgPack.pack_size());
for (const auto &P : ArgPack.pack_elements()) for (const auto &P : ArgPack.pack_elements())
ID.AddPointer(P.getAsType().getAsOpaquePtr()); ID.AddPointer(P.getAsType().getAsOpaquePtr());

View File

@ -1464,14 +1464,27 @@ void TypePrinter::printSubstTemplateTypeParmPackBefore(
const SubstTemplateTypeParmPackType *T, const SubstTemplateTypeParmPackType *T,
raw_ostream &OS) { raw_ostream &OS) {
IncludeStrongLifetimeRAII Strong(Policy); IncludeStrongLifetimeRAII Strong(Policy);
printTemplateTypeParmBefore(T->getReplacedParameter(), OS); if (const TemplateTypeParmDecl *D = T->getReplacedParameter()) {
if (D && D->isImplicit()) {
if (auto *TC = D->getTypeConstraint()) {
TC->print(OS, Policy);
OS << ' ';
}
OS << "auto";
} else if (IdentifierInfo *Id = D->getIdentifier())
OS << (Policy.CleanUglifiedParameters ? Id->deuglifiedName()
: Id->getName());
else
OS << "type-parameter-" << D->getDepth() << '-' << D->getIndex();
spaceBeforePlaceHolder(OS);
}
} }
void TypePrinter::printSubstTemplateTypeParmPackAfter( void TypePrinter::printSubstTemplateTypeParmPackAfter(
const SubstTemplateTypeParmPackType *T, const SubstTemplateTypeParmPackType *T,
raw_ostream &OS) { raw_ostream &OS) {
IncludeStrongLifetimeRAII Strong(Policy); IncludeStrongLifetimeRAII Strong(Policy);
printTemplateTypeParmAfter(T->getReplacedParameter(), OS);
} }
void TypePrinter::printTemplateId(const TemplateSpecializationType *T, void TypePrinter::printTemplateId(const TemplateSpecializationType *T,

View File

@ -396,8 +396,9 @@ bool Sema::CheckConstraintSatisfaction(
// has no access to the MultiLevelTemplateArgumentList, so this has to happen // has no access to the MultiLevelTemplateArgumentList, so this has to happen
// here. // here.
llvm::SmallVector<TemplateArgument, 4> FlattenedArgs; llvm::SmallVector<TemplateArgument, 4> FlattenedArgs;
for (ArrayRef<TemplateArgument> List : TemplateArgsLists) for (auto List : TemplateArgsLists)
FlattenedArgs.insert(FlattenedArgs.end(), List.begin(), List.end()); FlattenedArgs.insert(FlattenedArgs.end(), List.Args.begin(),
List.Args.end());
llvm::FoldingSetNodeID ID; llvm::FoldingSetNodeID ID;
ConstraintSatisfaction::Profile(ID, Context, Template, FlattenedArgs); ConstraintSatisfaction::Profile(ID, Context, Template, FlattenedArgs);
@ -452,7 +453,7 @@ bool Sema::SetupConstraintScope(
// the list of current template arguments to the list so that they also can // the list of current template arguments to the list so that they also can
// be picked out of the map. // be picked out of the map.
if (auto *SpecArgs = FD->getTemplateSpecializationArgs()) { if (auto *SpecArgs = FD->getTemplateSpecializationArgs()) {
MultiLevelTemplateArgumentList JustTemplArgs(*SpecArgs); MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray());
if (addInstantiatedParametersToScope( if (addInstantiatedParametersToScope(
FD, PrimaryTemplate->getTemplatedDecl(), Scope, JustTemplArgs)) FD, PrimaryTemplate->getTemplatedDecl(), Scope, JustTemplArgs))
return true; return true;

View File

@ -8960,13 +8960,13 @@ Sema::BuildExprRequirement(
Context.getReferenceQualifiedType(E).getCanonicalType(); Context.getReferenceQualifiedType(E).getCanonicalType();
llvm::SmallVector<TemplateArgument, 1> Args; llvm::SmallVector<TemplateArgument, 1> Args;
Args.push_back(TemplateArgument(MatchedType)); Args.push_back(TemplateArgument(MatchedType));
auto *Param = cast<TemplateTypeParmDecl>(TPL->getParam(0));
TemplateArgumentList TAL(TemplateArgumentList::OnStack, Args); TemplateArgumentList TAL(TemplateArgumentList::OnStack, Args);
MultiLevelTemplateArgumentList MLTAL(TAL); MultiLevelTemplateArgumentList MLTAL(Param, TAL.asArray());
for (unsigned I = 0; I < TPL->getDepth(); ++I) MLTAL.addOuterRetainedLevels(TPL->getDepth());
MLTAL.addOuterRetainedLevel(); Expr *IDC = Param->getTypeConstraint()->getImmediatelyDeclaredConstraint();
Expr *IDC =
cast<TemplateTypeParmDecl>(TPL->getParam(0))->getTypeConstraint()
->getImmediatelyDeclaredConstraint();
ExprResult Constraint = SubstExpr(IDC, MLTAL); ExprResult Constraint = SubstExpr(IDC, MLTAL);
if (Constraint.isInvalid()) { if (Constraint.isInvalid()) {
Status = concepts::ExprRequirement::SS_ExprSubstitutionFailure; Status = concepts::ExprRequirement::SS_ExprSubstitutionFailure;

View File

@ -3581,16 +3581,11 @@ checkBuiltinTemplateIdType(Sema &SemaRef, BuiltinTemplateDecl *BTD,
TemplateArgumentListInfo &TemplateArgs) { TemplateArgumentListInfo &TemplateArgs) {
ASTContext &Context = SemaRef.getASTContext(); ASTContext &Context = SemaRef.getASTContext();
TemplateParameterList *TPL = BTD->getTemplateParameters();
// Wrap the type in substitution sugar. // Wrap the type in substitution sugar.
auto getSubstType = [&](QualType Replacement, unsigned IndexReplaced, auto getSubstType = [&](QualType Replacement, unsigned IndexReplaced,
Optional<unsigned> PackIndexReplaced) { Optional<unsigned> PackIndexReplaced) {
QualType TTP = SemaRef.Context.getTemplateTypeParmType(
0, IndexReplaced, false,
cast<TemplateTypeParmDecl>(TPL->getParam(IndexReplaced)));
return SemaRef.Context.getSubstTemplateTypeParmType( return SemaRef.Context.getSubstTemplateTypeParmType(
cast<TemplateTypeParmType>(TTP), Replacement, PackIndexReplaced); Replacement, BTD, IndexReplaced, PackIndexReplaced);
}; };
switch (BTD->getBuiltinTemplateKind()) { switch (BTD->getBuiltinTemplateKind()) {
@ -3639,8 +3634,7 @@ checkBuiltinTemplateIdType(Sema &SemaRef, BuiltinTemplateDecl *BTD,
// Wrap the template in substitution sugar. // Wrap the template in substitution sugar.
TemplateName TN = SemaRef.Context.getSubstTemplateTemplateParm( TemplateName TN = SemaRef.Context.getSubstTemplateTemplateParm(
cast<TemplateTemplateParmDecl>(TPL->getParam(0)), Converted[0].getAsTemplate(), BTD, 0, None);
Converted[0].getAsTemplate());
// The first template argument will be reused as the template decl that // The first template argument will be reused as the template decl that
// our synthetic template arguments will be applied to. // our synthetic template arguments will be applied to.
@ -3872,7 +3866,8 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
// Only substitute for the innermost template argument list. // Only substitute for the innermost template argument list.
MultiLevelTemplateArgumentList TemplateArgLists; MultiLevelTemplateArgumentList TemplateArgLists;
TemplateArgLists.addOuterTemplateArguments(&StackTemplateArgs); TemplateArgLists.addOuterTemplateArguments(Template,
StackTemplateArgs.asArray());
TemplateArgLists.addOuterRetainedLevels( TemplateArgLists.addOuterRetainedLevels(
AliasTemplate->getTemplateParameters()->getDepth()); AliasTemplate->getTemplateParameters()->getDepth());
@ -3997,7 +3992,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
InstantiatingTemplate Inst(*this, TemplateLoc, Decl); InstantiatingTemplate Inst(*this, TemplateLoc, Decl);
if (!Inst.isInvalid()) { if (!Inst.isInvalid()) {
MultiLevelTemplateArgumentList TemplateArgLists; MultiLevelTemplateArgumentList TemplateArgLists;
TemplateArgLists.addOuterTemplateArguments(Converted); TemplateArgLists.addOuterTemplateArguments(Template, Converted);
InstantiateAttrsForDecl(TemplateArgLists, InstantiateAttrsForDecl(TemplateArgLists,
ClassTemplate->getTemplatedDecl(), Decl); ClassTemplate->getTemplatedDecl(), Decl);
} }
@ -4876,7 +4871,7 @@ Sema::CheckConceptTemplateId(const CXXScopeSpec &SS,
TemplateSpecializationType::anyDependentTemplateArguments(*TemplateArgs, TemplateSpecializationType::anyDependentTemplateArguments(*TemplateArgs,
Converted); Converted);
MultiLevelTemplateArgumentList MLTAL; MultiLevelTemplateArgumentList MLTAL;
MLTAL.addOuterTemplateArguments(Converted); MLTAL.addOuterTemplateArguments(NamedConcept, Converted);
LocalInstantiationScope Scope(*this); LocalInstantiationScope Scope(*this);
if (!AreArgsDependent && if (!AreArgsDependent &&
CheckConstraintSatisfaction( CheckConstraintSatisfaction(
@ -5286,8 +5281,8 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted); TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted);
// Only substitute for the innermost template argument list. // Only substitute for the innermost template argument list.
MultiLevelTemplateArgumentList TemplateArgLists; MultiLevelTemplateArgumentList TemplateArgLists(Template,
TemplateArgLists.addOuterTemplateArguments(&TemplateArgs); TemplateArgs.asArray());
for (unsigned i = 0, e = Param->getDepth(); i != e; ++i) for (unsigned i = 0, e = Param->getDepth(); i != e; ++i)
TemplateArgLists.addOuterTemplateArguments(None); TemplateArgLists.addOuterTemplateArguments(None);
@ -5342,8 +5337,8 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted); TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted);
// Only substitute for the innermost template argument list. // Only substitute for the innermost template argument list.
MultiLevelTemplateArgumentList TemplateArgLists; MultiLevelTemplateArgumentList TemplateArgLists(Template,
TemplateArgLists.addOuterTemplateArguments(&TemplateArgs); TemplateArgs.asArray());
for (unsigned i = 0, e = Param->getDepth(); i != e; ++i) for (unsigned i = 0, e = Param->getDepth(); i != e; ++i)
TemplateArgLists.addOuterTemplateArguments(None); TemplateArgLists.addOuterTemplateArguments(None);
@ -5395,8 +5390,8 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted); TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted);
// Only substitute for the innermost template argument list. // Only substitute for the innermost template argument list.
MultiLevelTemplateArgumentList TemplateArgLists; MultiLevelTemplateArgumentList TemplateArgLists(Template,
TemplateArgLists.addOuterTemplateArguments(&TemplateArgs); TemplateArgs.asArray());
for (unsigned i = 0, e = Param->getDepth(); i != e; ++i) for (unsigned i = 0, e = Param->getDepth(); i != e; ++i)
TemplateArgLists.addOuterTemplateArguments(None); TemplateArgLists.addOuterTemplateArguments(None);
@ -5580,18 +5575,15 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
Converted); Converted);
MultiLevelTemplateArgumentList MLTAL(Template, TemplateArgs.asArray());
// If the parameter is a pack expansion, expand this slice of the pack. // If the parameter is a pack expansion, expand this slice of the pack.
if (auto *PET = NTTPType->getAs<PackExpansionType>()) { if (auto *PET = NTTPType->getAs<PackExpansionType>()) {
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this,
ArgumentPackIndex); ArgumentPackIndex);
NTTPType = SubstType(PET->getPattern(), NTTPType = SubstType(PET->getPattern(), MLTAL, NTTP->getLocation(),
MultiLevelTemplateArgumentList(TemplateArgs),
NTTP->getLocation(),
NTTP->getDeclName()); NTTP->getDeclName());
} else { } else {
NTTPType = SubstType(NTTPType, NTTPType = SubstType(NTTPType, MLTAL, NTTP->getLocation(),
MultiLevelTemplateArgumentList(TemplateArgs),
NTTP->getLocation(),
NTTP->getDeclName()); NTTP->getDeclName());
} }
@ -5734,15 +5726,15 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
{ {
// Set up a template instantiation context. // Set up a template instantiation context.
LocalInstantiationScope Scope(*this); LocalInstantiationScope Scope(*this);
InstantiatingTemplate Inst(*this, TemplateLoc, Template, InstantiatingTemplate Inst(*this, TemplateLoc, Template, TempParm,
TempParm, Converted, Converted, SourceRange(TemplateLoc, RAngleLoc));
SourceRange(TemplateLoc, RAngleLoc));
if (Inst.isInvalid()) if (Inst.isInvalid())
return true; return true;
TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted); TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted);
Params = SubstTemplateParams(Params, CurContext, Params = SubstTemplateParams(
MultiLevelTemplateArgumentList(TemplateArgs)); Params, CurContext,
MultiLevelTemplateArgumentList(Template, TemplateArgs.asArray()));
if (!Params) if (!Params)
return true; return true;
} }

View File

@ -2687,7 +2687,7 @@ ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
if (PackedArgsBuilder.empty()) { if (PackedArgsBuilder.empty()) {
LocalInstantiationScope Scope(S); LocalInstantiationScope Scope(S);
TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Output); TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Output);
MultiLevelTemplateArgumentList Args(TemplateArgs); MultiLevelTemplateArgumentList Args(Template, TemplateArgs.asArray());
if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) { if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
Sema::InstantiatingTemplate Inst(S, Template->getLocation(), Template, Sema::InstantiatingTemplate Inst(S, Template->getLocation(), Template,
@ -2870,12 +2870,11 @@ CheckDeducedArgumentConstraints(Sema& S, TemplateDeclT *Template,
TemplateDeductionInfo& Info) { TemplateDeductionInfo& Info) {
llvm::SmallVector<const Expr *, 3> AssociatedConstraints; llvm::SmallVector<const Expr *, 3> AssociatedConstraints;
Template->getAssociatedConstraints(AssociatedConstraints); Template->getAssociatedConstraints(AssociatedConstraints);
MultiLevelTemplateArgumentList MLTAL;
bool NeedsReplacement = DeducedArgsNeedReplacement(Template); bool NeedsReplacement = DeducedArgsNeedReplacement(Template);
TemplateArgumentList DeducedTAL{TemplateArgumentList::OnStack, DeducedArgs}; TemplateArgumentList DeducedTAL{TemplateArgumentList::OnStack, DeducedArgs};
MLTAL = S.getTemplateInstantiationArgs( MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
Template, /*InnerMost=*/NeedsReplacement ? nullptr : &DeducedTAL, Template, /*InnerMost=*/NeedsReplacement ? nullptr : &DeducedTAL,
/*RelativeToPrimary=*/true, /*Pattern=*/ /*RelativeToPrimary=*/true, /*Pattern=*/
nullptr, /*ForConstraintInstantiation=*/true); nullptr, /*ForConstraintInstantiation=*/true);
@ -2940,9 +2939,10 @@ FinishTemplateArgumentDeduction(
TemplateArgumentListInfo InstArgs(PartialTemplArgInfo->LAngleLoc, TemplateArgumentListInfo InstArgs(PartialTemplArgInfo->LAngleLoc,
PartialTemplArgInfo->RAngleLoc); PartialTemplArgInfo->RAngleLoc);
if (S.SubstTemplateArguments( if (S.SubstTemplateArguments(PartialTemplArgInfo->arguments(),
PartialTemplArgInfo->arguments(), MultiLevelTemplateArgumentList(
MultiLevelTemplateArgumentList(*DeducedArgumentList), InstArgs)) { Partial, DeducedArgumentList->asArray()),
InstArgs)) {
unsigned ArgIdx = InstArgs.size(), ParamIdx = ArgIdx; unsigned ArgIdx = InstArgs.size(), ParamIdx = ArgIdx;
if (ParamIdx >= Partial->getTemplateParameters()->size()) if (ParamIdx >= Partial->getTemplateParameters()->size())
ParamIdx = Partial->getTemplateParameters()->size() - 1; ParamIdx = Partial->getTemplateParameters()->size() - 1;
@ -3279,7 +3279,8 @@ Sema::SubstituteExplicitTemplateArguments(
if (Proto->hasTrailingReturn()) { if (Proto->hasTrailingReturn()) {
if (SubstParmTypes(Function->getLocation(), Function->parameters(), if (SubstParmTypes(Function->getLocation(), Function->parameters(),
Proto->getExtParameterInfosOrNull(), Proto->getExtParameterInfosOrNull(),
MultiLevelTemplateArgumentList(*ExplicitArgumentList), MultiLevelTemplateArgumentList(
FunctionTemplate, ExplicitArgumentList->asArray()),
ParamTypes, /*params*/ nullptr, ExtParamInfos)) ParamTypes, /*params*/ nullptr, ExtParamInfos))
return TDK_SubstitutionFailure; return TDK_SubstitutionFailure;
} }
@ -3305,7 +3306,8 @@ Sema::SubstituteExplicitTemplateArguments(
ResultType = ResultType =
SubstType(Proto->getReturnType(), SubstType(Proto->getReturnType(),
MultiLevelTemplateArgumentList(*ExplicitArgumentList), MultiLevelTemplateArgumentList(
FunctionTemplate, ExplicitArgumentList->asArray()),
Function->getTypeSpecStartLoc(), Function->getDeclName()); Function->getTypeSpecStartLoc(), Function->getDeclName());
if (ResultType.isNull() || Trap.hasErrorOccurred()) if (ResultType.isNull() || Trap.hasErrorOccurred())
return TDK_SubstitutionFailure; return TDK_SubstitutionFailure;
@ -3323,7 +3325,8 @@ Sema::SubstituteExplicitTemplateArguments(
if (!Proto->hasTrailingReturn() && if (!Proto->hasTrailingReturn() &&
SubstParmTypes(Function->getLocation(), Function->parameters(), SubstParmTypes(Function->getLocation(), Function->parameters(),
Proto->getExtParameterInfosOrNull(), Proto->getExtParameterInfosOrNull(),
MultiLevelTemplateArgumentList(*ExplicitArgumentList), MultiLevelTemplateArgumentList(
FunctionTemplate, ExplicitArgumentList->asArray()),
ParamTypes, /*params*/ nullptr, ExtParamInfos)) ParamTypes, /*params*/ nullptr, ExtParamInfos))
return TDK_SubstitutionFailure; return TDK_SubstitutionFailure;
@ -3338,7 +3341,8 @@ Sema::SubstituteExplicitTemplateArguments(
if (getLangOpts().CPlusPlus17 && if (getLangOpts().CPlusPlus17 &&
SubstExceptionSpec( SubstExceptionSpec(
Function->getLocation(), EPI.ExceptionSpec, ExceptionStorage, Function->getLocation(), EPI.ExceptionSpec, ExceptionStorage,
MultiLevelTemplateArgumentList(*ExplicitArgumentList))) MultiLevelTemplateArgumentList(FunctionTemplate,
ExplicitArgumentList->asArray())))
return TDK_SubstitutionFailure; return TDK_SubstitutionFailure;
*FunctionType = BuildFunctionType(ResultType, ParamTypes, *FunctionType = BuildFunctionType(ResultType, ParamTypes,
@ -3578,7 +3582,8 @@ Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
DeclContext *Owner = FunctionTemplate->getDeclContext(); DeclContext *Owner = FunctionTemplate->getDeclContext();
if (FunctionTemplate->getFriendObjectKind()) if (FunctionTemplate->getFriendObjectKind())
Owner = FunctionTemplate->getLexicalDeclContext(); Owner = FunctionTemplate->getLexicalDeclContext();
MultiLevelTemplateArgumentList SubstArgs(*DeducedArgumentList); MultiLevelTemplateArgumentList SubstArgs(FunctionTemplate,
DeducedArgumentList->asArray());
Specialization = cast_or_null<FunctionDecl>( Specialization = cast_or_null<FunctionDecl>(
SubstDecl(FunctionTemplate->getTemplatedDecl(), Owner, SubstArgs)); SubstDecl(FunctionTemplate->getTemplatedDecl(), Owner, SubstArgs));
if (!Specialization || Specialization->isInvalidDecl()) if (!Specialization || Specialization->isInvalidDecl())
@ -4635,7 +4640,7 @@ static bool CheckDeducedPlaceholderConstraints(Sema &S, const AutoType &Type,
/*PartialTemplateArgs=*/false, Converted)) /*PartialTemplateArgs=*/false, Converted))
return true; return true;
MultiLevelTemplateArgumentList MLTAL; MultiLevelTemplateArgumentList MLTAL;
MLTAL.addOuterTemplateArguments(Converted); MLTAL.addOuterTemplateArguments(Concept, Converted);
if (S.CheckConstraintSatisfaction(Concept, {Concept->getConstraintExpr()}, if (S.CheckConstraintSatisfaction(Concept, {Concept->getConstraintExpr()},
MLTAL, TypeLoc.getLocalSourceRange(), MLTAL, TypeLoc.getLocalSourceRange(),
Satisfaction)) Satisfaction))
@ -5939,9 +5944,8 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
case Type::SubstTemplateTypeParmPack: { case Type::SubstTemplateTypeParmPack: {
const SubstTemplateTypeParmPackType *Subst const SubstTemplateTypeParmPackType *Subst
= cast<SubstTemplateTypeParmPackType>(T); = cast<SubstTemplateTypeParmPackType>(T);
MarkUsedTemplateParameters(Ctx, if (Subst->getReplacedParameter()->getDepth() == Depth)
QualType(Subst->getReplacedParameter(), 0), Used[Subst->getIndex()] = true;
OnlyDeduced, Depth, Used);
MarkUsedTemplateParameters(Ctx, Subst->getArgumentPack(), MarkUsedTemplateParameters(Ctx, Subst->getArgumentPack(),
OnlyDeduced, Depth, Used); OnlyDeduced, Depth, Used);
break; break;

View File

@ -86,9 +86,6 @@ HandleVarTemplateSpec(const VarTemplateSpecializationDecl *VarTemplSpec,
!isa<VarTemplatePartialSpecializationDecl>(VarTemplSpec)) !isa<VarTemplatePartialSpecializationDecl>(VarTemplSpec))
return Response::Done(); return Response::Done();
Result.addOuterTemplateArguments(
&VarTemplSpec->getTemplateInstantiationArgs());
// If this variable template specialization was instantiated from a // If this variable template specialization was instantiated from a
// specialized member that is a variable template, we're done. // specialized member that is a variable template, we're done.
assert(VarTemplSpec->getSpecializedTemplate() && "No variable template?"); assert(VarTemplSpec->getSpecializedTemplate() && "No variable template?");
@ -96,10 +93,14 @@ HandleVarTemplateSpec(const VarTemplateSpecializationDecl *VarTemplSpec,
Specialized = VarTemplSpec->getSpecializedTemplateOrPartial(); Specialized = VarTemplSpec->getSpecializedTemplateOrPartial();
if (VarTemplatePartialSpecializationDecl *Partial = if (VarTemplatePartialSpecializationDecl *Partial =
Specialized.dyn_cast<VarTemplatePartialSpecializationDecl *>()) { Specialized.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
Result.addOuterTemplateArguments(
Partial, VarTemplSpec->getTemplateInstantiationArgs().asArray());
if (Partial->isMemberSpecialization()) if (Partial->isMemberSpecialization())
return Response::Done(); return Response::Done();
} else { } else {
VarTemplateDecl *Tmpl = Specialized.get<VarTemplateDecl *>(); VarTemplateDecl *Tmpl = Specialized.get<VarTemplateDecl *>();
Result.addOuterTemplateArguments(
Tmpl, VarTemplSpec->getTemplateInstantiationArgs().asArray());
if (Tmpl->isMemberSpecialization()) if (Tmpl->isMemberSpecialization())
return Response::Done(); return Response::Done();
} }
@ -131,7 +132,8 @@ HandleClassTemplateSpec(const ClassTemplateSpecializationDecl *ClassTemplSpec,
return Response::Done(); return Response::Done();
Result.addOuterTemplateArguments( Result.addOuterTemplateArguments(
&ClassTemplSpec->getTemplateInstantiationArgs()); const_cast<ClassTemplateSpecializationDecl *>(ClassTemplSpec),
ClassTemplSpec->getTemplateInstantiationArgs().asArray());
// If this class template specialization was instantiated from a // If this class template specialization was instantiated from a
// specialized member that is a class template, we're done. // specialized member that is a class template, we're done.
@ -161,7 +163,8 @@ Response HandleFunction(const FunctionDecl *Function,
} else if (const TemplateArgumentList *TemplateArgs = } else if (const TemplateArgumentList *TemplateArgs =
Function->getTemplateSpecializationArgs()) { Function->getTemplateSpecializationArgs()) {
// Add the template arguments for this specialization. // Add the template arguments for this specialization.
Result.addOuterTemplateArguments(TemplateArgs); Result.addOuterTemplateArguments(const_cast<FunctionDecl *>(Function),
TemplateArgs->asArray());
// If this function was instantiated from a specialized member that is // If this function was instantiated from a specialized member that is
// a function template, we're done. // a function template, we're done.
@ -206,7 +209,8 @@ Response HandleRecordDecl(const CXXRecordDecl *Rec,
QualType Injected = cast<InjectedClassNameType>(RecordType) QualType Injected = cast<InjectedClassNameType>(RecordType)
->getInjectedSpecializationType(); ->getInjectedSpecializationType();
const auto *InjectedType = cast<TemplateSpecializationType>(Injected); const auto *InjectedType = cast<TemplateSpecializationType>(Injected);
Result.addOuterTemplateArguments(InjectedType->template_arguments()); Result.addOuterTemplateArguments(const_cast<CXXRecordDecl *>(Rec),
InjectedType->template_arguments());
} }
} }
@ -266,7 +270,8 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
MultiLevelTemplateArgumentList Result; MultiLevelTemplateArgumentList Result;
if (Innermost) if (Innermost)
Result.addOuterTemplateArguments(Innermost); Result.addOuterTemplateArguments(const_cast<NamedDecl *>(ND),
Innermost->asArray());
const Decl *CurDecl = ND; const Decl *CurDecl = ND;
@ -1371,9 +1376,9 @@ namespace {
Sema::ExtParameterInfoBuilder &PInfos); Sema::ExtParameterInfoBuilder &PInfos);
private: private:
ExprResult transformNonTypeTemplateParmRef(NonTypeTemplateParmDecl *parm, ExprResult transformNonTypeTemplateParmRef(
SourceLocation loc, Decl *AssociatedDecl, const NonTypeTemplateParmDecl *parm,
TemplateArgument arg); SourceLocation loc, TemplateArgument arg, Optional<unsigned> PackIndex);
}; };
} }
@ -1563,6 +1568,8 @@ TemplateName TemplateInstantiator::TransformTemplateName(
return Arg.getAsTemplate(); return Arg.getAsTemplate();
} }
Decl *AssociatedDecl = TemplateArgs.getAssociatedDecl(TTP->getDepth());
Optional<unsigned> PackIndex;
if (TTP->isParameterPack()) { if (TTP->isParameterPack()) {
assert(Arg.getKind() == TemplateArgument::Pack && assert(Arg.getKind() == TemplateArgument::Pack &&
"Missing argument pack"); "Missing argument pack");
@ -1571,10 +1578,12 @@ TemplateName TemplateInstantiator::TransformTemplateName(
// We have the template argument pack to substitute, but we're not // We have the template argument pack to substitute, but we're not
// actually expanding the enclosing pack expansion yet. So, just // actually expanding the enclosing pack expansion yet. So, just
// keep the entire argument pack. // keep the entire argument pack.
return getSema().Context.getSubstTemplateTemplateParmPack(TTP, Arg); return getSema().Context.getSubstTemplateTemplateParmPack(
Arg, AssociatedDecl, TTP->getIndex());
} }
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg); Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
PackIndex = getSema().ArgumentPackSubstitutionIndex;
} }
TemplateName Template = Arg.getAsTemplate().getNameToSubstitute(); TemplateName Template = Arg.getAsTemplate().getNameToSubstitute();
@ -1582,7 +1591,8 @@ TemplateName TemplateInstantiator::TransformTemplateName(
assert(!Template.getAsQualifiedTemplateName() && assert(!Template.getAsQualifiedTemplateName() &&
"template decl to substitute is qualified?"); "template decl to substitute is qualified?");
Template = getSema().Context.getSubstTemplateTemplateParm(TTP, Template); Template = getSema().Context.getSubstTemplateTemplateParm(
Template, AssociatedDecl, TTP->getIndex(), PackIndex);
return Template; return Template;
} }
} }
@ -1638,6 +1648,8 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
return Arg.getAsExpr(); return Arg.getAsExpr();
} }
Decl *AssociatedDecl = TemplateArgs.getAssociatedDecl(NTTP->getDepth());
Optional<unsigned> PackIndex;
if (NTTP->isParameterPack()) { if (NTTP->isParameterPack()) {
assert(Arg.getKind() == TemplateArgument::Pack && assert(Arg.getKind() == TemplateArgument::Pack &&
"Missing argument pack"); "Missing argument pack");
@ -1658,13 +1670,14 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
return new (SemaRef.Context) SubstNonTypeTemplateParmPackExpr( return new (SemaRef.Context) SubstNonTypeTemplateParmPackExpr(
ExprType, TargetType->isReferenceType() ? VK_LValue : VK_PRValue, ExprType, TargetType->isReferenceType() ? VK_LValue : VK_PRValue,
NTTP, E->getLocation(), Arg); E->getLocation(), Arg, AssociatedDecl, NTTP->getPosition());
} }
PackIndex = getSema().ArgumentPackSubstitutionIndex;
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg); Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
} }
return transformNonTypeTemplateParmRef(NTTP, E->getLocation(), Arg); return transformNonTypeTemplateParmRef(AssociatedDecl, NTTP, E->getLocation(),
Arg, PackIndex);
} }
const LoopHintAttr * const LoopHintAttr *
@ -1685,9 +1698,8 @@ TemplateInstantiator::TransformLoopHintAttr(const LoopHintAttr *LH) {
} }
ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef( ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef(
NonTypeTemplateParmDecl *parm, Decl *AssociatedDecl, const NonTypeTemplateParmDecl *parm,
SourceLocation loc, SourceLocation loc, TemplateArgument arg, Optional<unsigned> PackIndex) {
TemplateArgument arg) {
ExprResult result; ExprResult result;
// Determine the substituted parameter type. We can usually infer this from // Determine the substituted parameter type. We can usually infer this from
@ -1756,23 +1768,24 @@ ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef(
Expr *resultExpr = result.get(); Expr *resultExpr = result.get();
return new (SemaRef.Context) SubstNonTypeTemplateParmExpr( return new (SemaRef.Context) SubstNonTypeTemplateParmExpr(
resultExpr->getType(), resultExpr->getValueKind(), loc, parm, refParam, resultExpr->getType(), resultExpr->getValueKind(), loc, resultExpr,
resultExpr); AssociatedDecl, parm->getIndex(), PackIndex, refParam);
} }
ExprResult ExprResult
TemplateInstantiator::TransformSubstNonTypeTemplateParmPackExpr( TemplateInstantiator::TransformSubstNonTypeTemplateParmPackExpr(
SubstNonTypeTemplateParmPackExpr *E) { SubstNonTypeTemplateParmPackExpr *E) {
if (getSema().ArgumentPackSubstitutionIndex == -1) { int PackIndex = getSema().ArgumentPackSubstitutionIndex;
if (PackIndex == -1) {
// We aren't expanding the parameter pack, so just return ourselves. // We aren't expanding the parameter pack, so just return ourselves.
return E; return E;
} }
TemplateArgument Arg = E->getArgumentPack(); TemplateArgument Arg = E->getArgumentPack();
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg); Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
return transformNonTypeTemplateParmRef(E->getParameterPack(), return transformNonTypeTemplateParmRef(
E->getParameterPackLocation(), E->getAssociatedDecl(), E->getParameterPack(),
Arg); E->getParameterPackLocation(), Arg, PackIndex);
} }
ExprResult ExprResult
@ -1811,8 +1824,9 @@ TemplateInstantiator::TransformSubstNonTypeTemplateParmExpr(
SubstReplacement.get(), SubstReplacement.get(),
Converted).isInvalid()) Converted).isInvalid())
return true; return true;
return transformNonTypeTemplateParmRef(E->getParameter(), return transformNonTypeTemplateParmRef(E->getAssociatedDecl(),
E->getExprLoc(), Converted); E->getParameter(), E->getExprLoc(),
Converted, E->getPackIndex());
} }
ExprResult TemplateInstantiator::RebuildVarDeclRefExpr(VarDecl *PD, ExprResult TemplateInstantiator::RebuildVarDeclRefExpr(VarDecl *PD,
@ -1982,6 +1996,8 @@ TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
return NewT; return NewT;
} }
Decl *AssociatedDecl =
const_cast<Decl *>(TemplateArgs.getAssociatedDecl(T->getDepth()));
Optional<unsigned> PackIndex; Optional<unsigned> PackIndex;
if (T->isParameterPack()) { if (T->isParameterPack()) {
assert(Arg.getKind() == TemplateArgument::Pack && assert(Arg.getKind() == TemplateArgument::Pack &&
@ -1991,8 +2007,8 @@ TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
// We have the template argument pack, but we're not expanding the // We have the template argument pack, but we're not expanding the
// enclosing pack expansion yet. Just save the template argument // enclosing pack expansion yet. Just save the template argument
// pack for later substitution. // pack for later substitution.
QualType Result QualType Result = getSema().Context.getSubstTemplateTypeParmPackType(
= getSema().Context.getSubstTemplateTypeParmPackType(T, Arg); AssociatedDecl, T->getIndex(), Arg);
SubstTemplateTypeParmPackTypeLoc NewTL SubstTemplateTypeParmPackTypeLoc NewTL
= TLB.push<SubstTemplateTypeParmPackTypeLoc>(Result); = TLB.push<SubstTemplateTypeParmPackTypeLoc>(Result);
NewTL.setNameLoc(TL.getNameLoc()); NewTL.setNameLoc(TL.getNameLoc());
@ -2011,7 +2027,7 @@ TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
// TODO: only do this uniquing once, at the start of instantiation. // TODO: only do this uniquing once, at the start of instantiation.
QualType Result = getSema().Context.getSubstTemplateTypeParmType( QualType Result = getSema().Context.getSubstTemplateTypeParmType(
T, Replacement, PackIndex); Replacement, AssociatedDecl, T->getIndex(), PackIndex);
SubstTemplateTypeParmTypeLoc NewTL SubstTemplateTypeParmTypeLoc NewTL
= TLB.push<SubstTemplateTypeParmTypeLoc>(Result); = TLB.push<SubstTemplateTypeParmTypeLoc>(Result);
NewTL.setNameLoc(TL.getNameLoc()); NewTL.setNameLoc(TL.getNameLoc());
@ -2025,8 +2041,7 @@ TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
TemplateTypeParmDecl *NewTTPDecl = nullptr; TemplateTypeParmDecl *NewTTPDecl = nullptr;
if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl()) if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl())
NewTTPDecl = cast_or_null<TemplateTypeParmDecl>( NewTTPDecl = cast_or_null<TemplateTypeParmDecl>(
TransformDecl(TL.getNameLoc(), OldTTPDecl)); TransformDecl(TL.getNameLoc(), OldTTPDecl));
QualType Result = getSema().Context.getTemplateTypeParmType( QualType Result = getSema().Context.getTemplateTypeParmType(
T->getDepth() - TemplateArgs.getNumSubstitutedLevels(), T->getIndex(), T->getDepth() - TemplateArgs.getNumSubstitutedLevels(), T->getIndex(),
T->isParameterPack(), NewTTPDecl); T->isParameterPack(), NewTTPDecl);
@ -2035,27 +2050,32 @@ TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
return Result; return Result;
} }
QualType QualType TemplateInstantiator::TransformSubstTemplateTypeParmPackType(
TemplateInstantiator::TransformSubstTemplateTypeParmPackType( TypeLocBuilder &TLB, SubstTemplateTypeParmPackTypeLoc TL) {
TypeLocBuilder &TLB, const SubstTemplateTypeParmPackType *T = TL.getTypePtr();
SubstTemplateTypeParmPackTypeLoc TL) {
Decl *NewReplaced = TransformDecl(TL.getNameLoc(), T->getAssociatedDecl());
if (getSema().ArgumentPackSubstitutionIndex == -1) { if (getSema().ArgumentPackSubstitutionIndex == -1) {
// We aren't expanding the parameter pack, so just return ourselves. // We aren't expanding the parameter pack, so just return ourselves.
SubstTemplateTypeParmPackTypeLoc NewTL QualType Result = TL.getType();
= TLB.push<SubstTemplateTypeParmPackTypeLoc>(TL.getType()); if (NewReplaced != T->getAssociatedDecl())
Result = getSema().Context.getSubstTemplateTypeParmPackType(
NewReplaced, T->getIndex(), T->getArgumentPack());
SubstTemplateTypeParmPackTypeLoc NewTL =
TLB.push<SubstTemplateTypeParmPackTypeLoc>(Result);
NewTL.setNameLoc(TL.getNameLoc()); NewTL.setNameLoc(TL.getNameLoc());
return TL.getType(); return Result;
} }
const SubstTemplateTypeParmPackType *T = TL.getTypePtr();
TemplateArgument Pack = T->getArgumentPack(); TemplateArgument Pack = T->getArgumentPack();
TemplateArgument Arg = getPackSubstitutedTemplateArgument(getSema(), Pack); TemplateArgument Arg = getPackSubstitutedTemplateArgument(getSema(), Pack);
// PackIndex starts from last element. // PackIndex starts from last element.
QualType Result = getSema().Context.getSubstTemplateTypeParmType( QualType Result = getSema().Context.getSubstTemplateTypeParmType(
T->getReplacedParameter(), Arg.getAsType(), Arg.getAsType(), NewReplaced, T->getIndex(),
Pack.pack_size() - 1 - getSema().ArgumentPackSubstitutionIndex); Pack.pack_size() - 1 - getSema().ArgumentPackSubstitutionIndex);
SubstTemplateTypeParmTypeLoc NewTL SubstTemplateTypeParmTypeLoc NewTL =
= TLB.push<SubstTemplateTypeParmTypeLoc>(Result); TLB.push<SubstTemplateTypeParmTypeLoc>(Result);
NewTL.setNameLoc(TL.getNameLoc()); NewTL.setNameLoc(TL.getNameLoc());
return Result; return Result;
} }

View File

@ -4761,7 +4761,7 @@ Sema::InstantiateFunctionDeclaration(FunctionTemplateDecl *FTD,
return nullptr; return nullptr;
ContextRAII SavedContext(*this, FD); ContextRAII SavedContext(*this, FD);
MultiLevelTemplateArgumentList MArgs(*Args); MultiLevelTemplateArgumentList MArgs(FTD, Args->asArray());
return cast_or_null<FunctionDecl>(SubstDecl(FD, FD->getParent(), MArgs)); return cast_or_null<FunctionDecl>(SubstDecl(FD, FD->getParent(), MArgs));
} }
@ -5097,8 +5097,7 @@ VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation(
const TemplateArgumentList &TemplateArgList, const TemplateArgumentList &TemplateArgList,
const TemplateArgumentListInfo &TemplateArgsInfo, const TemplateArgumentListInfo &TemplateArgsInfo,
SmallVectorImpl<TemplateArgument> &Converted, SmallVectorImpl<TemplateArgument> &Converted,
SourceLocation PointOfInstantiation, SourceLocation PointOfInstantiation, LateInstantiatedAttrVec *LateAttrs,
LateInstantiatedAttrVec *LateAttrs,
LocalInstantiationScope *StartingScope) { LocalInstantiationScope *StartingScope) {
if (FromVar->isInvalidDecl()) if (FromVar->isInvalidDecl())
return nullptr; return nullptr;
@ -5107,9 +5106,6 @@ VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation(
if (Inst.isInvalid()) if (Inst.isInvalid())
return nullptr; return nullptr;
MultiLevelTemplateArgumentList TemplateArgLists;
TemplateArgLists.addOuterTemplateArguments(&TemplateArgList);
// Instantiate the first declaration of the variable template: for a partial // Instantiate the first declaration of the variable template: for a partial
// specialization of a static data member template, the first declaration may // specialization of a static data member template, the first declaration may
// or may not be the declaration in the class; if it's in the class, we want // or may not be the declaration in the class; if it's in the class, we want
@ -5120,15 +5116,21 @@ VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation(
// partial specialization, don't do this. The member specialization completely // partial specialization, don't do this. The member specialization completely
// replaces the original declaration in this case. // replaces the original declaration in this case.
bool IsMemberSpec = false; bool IsMemberSpec = false;
if (VarTemplatePartialSpecializationDecl *PartialSpec = MultiLevelTemplateArgumentList MultiLevelList;
dyn_cast<VarTemplatePartialSpecializationDecl>(FromVar)) if (auto *PartialSpec =
dyn_cast<VarTemplatePartialSpecializationDecl>(FromVar)) {
IsMemberSpec = PartialSpec->isMemberSpecialization(); IsMemberSpec = PartialSpec->isMemberSpecialization();
else if (VarTemplateDecl *FromTemplate = FromVar->getDescribedVarTemplate()) MultiLevelList.addOuterTemplateArguments(PartialSpec,
IsMemberSpec = FromTemplate->isMemberSpecialization(); TemplateArgList.asArray());
} else {
assert(VarTemplate == FromVar->getDescribedVarTemplate());
IsMemberSpec = VarTemplate->isMemberSpecialization();
MultiLevelList.addOuterTemplateArguments(VarTemplate,
TemplateArgList.asArray());
}
if (!IsMemberSpec) if (!IsMemberSpec)
FromVar = FromVar->getFirstDecl(); FromVar = FromVar->getFirstDecl();
MultiLevelTemplateArgumentList MultiLevelList(TemplateArgList);
TemplateDeclInstantiator Instantiator(*this, FromVar->getDeclContext(), TemplateDeclInstantiator Instantiator(*this, FromVar->getDeclContext(),
MultiLevelList); MultiLevelList);

View File

@ -720,7 +720,7 @@ bool Sema::CheckParameterPacksForExpansion(
} else if (const auto *STP = } else if (const auto *STP =
P.dyn_cast<const SubstTemplateTypeParmPackType *>()) { P.dyn_cast<const SubstTemplateTypeParmPackType *>()) {
NewPackSize = STP->getNumArgs(); NewPackSize = STP->getNumArgs();
ND = STP->getReplacedParameter()->getDecl(); ND = STP->getReplacedParameter();
} else { } else {
const auto *SEP = P.get<const SubstNonTypeTemplateParmPackExpr *>(); const auto *SEP = P.get<const SubstNonTypeTemplateParmPackExpr *>();
NewPackSize = SEP->getArgumentPack().pack_size(); NewPackSize = SEP->getArgumentPack().pack_size();

View File

@ -1285,9 +1285,10 @@ public:
/// be resolved to a specific template, then builds the appropriate kind of /// be resolved to a specific template, then builds the appropriate kind of
/// template name. Subclasses may override this routine to provide different /// template name. Subclasses may override this routine to provide different
/// behavior. /// behavior.
TemplateName RebuildTemplateName(TemplateTemplateParmDecl *Param, TemplateName RebuildTemplateName(const TemplateArgument &ArgPack,
const TemplateArgument &ArgPack) { Decl *AssociatedDecl, unsigned Index) {
return getSema().Context.getSubstTemplateTemplateParmPack(Param, ArgPack); return getSema().Context.getSubstTemplateTemplateParmPack(
ArgPack, AssociatedDecl, Index);
} }
/// Build a new compound statement. /// Build a new compound statement.
@ -4391,18 +4392,9 @@ TreeTransform<Derived>::TransformTemplateName(CXXScopeSpec &SS,
if (SubstTemplateTemplateParmPackStorage *SubstPack if (SubstTemplateTemplateParmPackStorage *SubstPack
= Name.getAsSubstTemplateTemplateParmPack()) { = Name.getAsSubstTemplateTemplateParmPack()) {
TemplateTemplateParmDecl *TransParam return getDerived().RebuildTemplateName(SubstPack->getArgumentPack(),
= cast_or_null<TemplateTemplateParmDecl>( SubstPack->getAssociatedDecl(),
getDerived().TransformDecl(NameLoc, SubstPack->getParameterPack())); SubstPack->getIndex());
if (!TransParam)
return TemplateName();
if (!getDerived().AlwaysRebuild() &&
TransParam == SubstPack->getParameterPack())
return Name;
return getDerived().RebuildTemplateName(TransParam,
SubstPack->getArgumentPack());
} }
// These should be getting filtered out before they reach the AST. // These should be getting filtered out before they reach the AST.
@ -4887,8 +4879,8 @@ QualType TreeTransform<Derived>::RebuildQualifiedType(QualType T,
Replacement = SemaRef.Context.getQualifiedType( Replacement = SemaRef.Context.getQualifiedType(
Replacement.getUnqualifiedType(), Qs); Replacement.getUnqualifiedType(), Qs);
T = SemaRef.Context.getSubstTemplateTypeParmType( T = SemaRef.Context.getSubstTemplateTypeParmType(
SubstTypeParam->getReplacedParameter(), Replacement, Replacement, SubstTypeParam->getAssociatedDecl(),
SubstTypeParam->getPackIndex()); SubstTypeParam->getIndex(), SubstTypeParam->getPackIndex());
} else if ((AutoTy = dyn_cast<AutoType>(T)) && AutoTy->isDeduced()) { } else if ((AutoTy = dyn_cast<AutoType>(T)) && AutoTy->isDeduced()) {
// 'auto' types behave the same way as template parameters. // 'auto' types behave the same way as template parameters.
QualType Deduced = AutoTy->getDeducedType(); QualType Deduced = AutoTy->getDeducedType();
@ -6440,6 +6432,9 @@ QualType TreeTransform<Derived>::TransformSubstTemplateTypeParmType(
SubstTemplateTypeParmTypeLoc TL) { SubstTemplateTypeParmTypeLoc TL) {
const SubstTemplateTypeParmType *T = TL.getTypePtr(); const SubstTemplateTypeParmType *T = TL.getTypePtr();
Decl *NewReplaced =
getDerived().TransformDecl(TL.getNameLoc(), T->getAssociatedDecl());
// Substitute into the replacement type, which itself might involve something // Substitute into the replacement type, which itself might involve something
// that needs to be transformed. This only tends to occur with default // that needs to be transformed. This only tends to occur with default
// template arguments of template template parameters. // template arguments of template template parameters.
@ -6449,7 +6444,7 @@ QualType TreeTransform<Derived>::TransformSubstTemplateTypeParmType(
return QualType(); return QualType();
QualType Result = SemaRef.Context.getSubstTemplateTypeParmType( QualType Result = SemaRef.Context.getSubstTemplateTypeParmType(
T->getReplacedParameter(), Replacement, T->getPackIndex()); Replacement, NewReplaced, T->getIndex(), T->getPackIndex());
// Propagate type-source information. // Propagate type-source information.
SubstTemplateTypeParmTypeLoc NewTL SubstTemplateTypeParmTypeLoc NewTL

View File

@ -382,7 +382,7 @@ namespace clang {
void VisitDecompositionDecl(DecompositionDecl *DD); void VisitDecompositionDecl(DecompositionDecl *DD);
void VisitBindingDecl(BindingDecl *BD); void VisitBindingDecl(BindingDecl *BD);
void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D); void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
DeclID VisitTemplateDecl(TemplateDecl *D); void VisitTemplateDecl(TemplateDecl *D);
void VisitConceptDecl(ConceptDecl *D); void VisitConceptDecl(ConceptDecl *D);
void VisitRequiresExprBodyDecl(RequiresExprBodyDecl *D); void VisitRequiresExprBodyDecl(RequiresExprBodyDecl *D);
RedeclarableResult VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D); RedeclarableResult VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D);
@ -415,14 +415,15 @@ namespace clang {
template<typename T> template<typename T>
RedeclarableResult VisitRedeclarable(Redeclarable<T> *D); RedeclarableResult VisitRedeclarable(Redeclarable<T> *D);
template<typename T> template <typename T>
void mergeRedeclarable(Redeclarable<T> *D, RedeclarableResult &Redecl, void mergeRedeclarable(Redeclarable<T> *D, RedeclarableResult &Redecl);
DeclID TemplatePatternID = 0);
template<typename T> void mergeRedeclarableTemplate(RedeclarableTemplateDecl *D,
RedeclarableResult &Redecl);
template <typename T>
void mergeRedeclarable(Redeclarable<T> *D, T *Existing, void mergeRedeclarable(Redeclarable<T> *D, T *Existing,
RedeclarableResult &Redecl, RedeclarableResult &Redecl);
DeclID TemplatePatternID = 0);
template<typename T> template<typename T>
void mergeMergeable(Mergeable<T> *D); void mergeMergeable(Mergeable<T> *D);
@ -431,7 +432,7 @@ namespace clang {
void mergeTemplatePattern(RedeclarableTemplateDecl *D, void mergeTemplatePattern(RedeclarableTemplateDecl *D,
RedeclarableTemplateDecl *Existing, RedeclarableTemplateDecl *Existing,
DeclID DsID, bool IsKeyDecl); bool IsKeyDecl);
ObjCTypeParamList *ReadObjCTypeParamList(); ObjCTypeParamList *ReadObjCTypeParamList();
@ -887,90 +888,27 @@ void ASTDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) {
void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
RedeclarableResult Redecl = VisitRedeclarable(FD); RedeclarableResult Redecl = VisitRedeclarable(FD);
VisitDeclaratorDecl(FD);
// Attach a type to this function. Use the real type if possible, but fall FunctionDecl *Existing = nullptr;
// back to the type as written if it involves a deduced return type.
if (FD->getTypeSourceInfo() &&
FD->getTypeSourceInfo()->getType()->castAs<FunctionType>()
->getReturnType()->getContainedAutoType()) {
// We'll set up the real type in Visit, once we've finished loading the
// function.
FD->setType(FD->getTypeSourceInfo()->getType());
Reader.PendingFunctionTypes.push_back({FD, DeferredTypeID});
} else {
FD->setType(Reader.GetType(DeferredTypeID));
}
DeferredTypeID = 0;
FD->DNLoc = Record.readDeclarationNameLoc(FD->getDeclName());
FD->IdentifierNamespace = Record.readInt();
// FunctionDecl's body is handled last at ASTDeclReader::Visit,
// after everything else is read.
FD->setStorageClass(static_cast<StorageClass>(Record.readInt()));
FD->setInlineSpecified(Record.readInt());
FD->setImplicitlyInline(Record.readInt());
FD->setVirtualAsWritten(Record.readInt());
// We defer calling `FunctionDecl::setPure()` here as for methods of
// `CXXTemplateSpecializationDecl`s, we may not have connected up the
// definition (which is required for `setPure`).
const bool Pure = Record.readInt();
FD->setHasInheritedPrototype(Record.readInt());
FD->setHasWrittenPrototype(Record.readInt());
FD->setDeletedAsWritten(Record.readInt());
FD->setTrivial(Record.readInt());
FD->setTrivialForCall(Record.readInt());
FD->setDefaulted(Record.readInt());
FD->setExplicitlyDefaulted(Record.readInt());
FD->setHasImplicitReturnZero(Record.readInt());
FD->setConstexprKind(static_cast<ConstexprSpecKind>(Record.readInt()));
FD->setUsesSEHTry(Record.readInt());
FD->setHasSkippedBody(Record.readInt());
FD->setIsMultiVersion(Record.readInt());
FD->setLateTemplateParsed(Record.readInt());
FD->setFriendConstraintRefersToEnclosingTemplate(Record.readInt());
FD->setCachedLinkage(static_cast<Linkage>(Record.readInt()));
FD->EndRangeLoc = readSourceLocation();
FD->setDefaultLoc(readSourceLocation());
FD->ODRHash = Record.readInt();
FD->setHasODRHash(true);
if (FD->isDefaulted()) {
if (unsigned NumLookups = Record.readInt()) {
SmallVector<DeclAccessPair, 8> Lookups;
for (unsigned I = 0; I != NumLookups; ++I) {
NamedDecl *ND = Record.readDeclAs<NamedDecl>();
AccessSpecifier AS = (AccessSpecifier)Record.readInt();
Lookups.push_back(DeclAccessPair::make(ND, AS));
}
FD->setDefaultedFunctionInfo(FunctionDecl::DefaultedFunctionInfo::Create(
Reader.getContext(), Lookups));
}
}
switch ((FunctionDecl::TemplatedKind)Record.readInt()) { switch ((FunctionDecl::TemplatedKind)Record.readInt()) {
case FunctionDecl::TK_NonTemplate: case FunctionDecl::TK_NonTemplate:
mergeRedeclarable(FD, Redecl);
break; break;
case FunctionDecl::TK_DependentNonTemplate: case FunctionDecl::TK_DependentNonTemplate:
mergeRedeclarable(FD, Redecl);
FD->setInstantiatedFromDecl(readDeclAs<FunctionDecl>()); FD->setInstantiatedFromDecl(readDeclAs<FunctionDecl>());
break; break;
case FunctionDecl::TK_FunctionTemplate: case FunctionDecl::TK_FunctionTemplate: {
// Merged when we merge the template. auto *Template = readDeclAs<FunctionTemplateDecl>();
FD->setDescribedFunctionTemplate(readDeclAs<FunctionTemplateDecl>()); Template->init(FD);
FD->setDescribedFunctionTemplate(Template);
break; break;
}
case FunctionDecl::TK_MemberSpecialization: { case FunctionDecl::TK_MemberSpecialization: {
auto *InstFD = readDeclAs<FunctionDecl>(); auto *InstFD = readDeclAs<FunctionDecl>();
auto TSK = (TemplateSpecializationKind)Record.readInt(); auto TSK = (TemplateSpecializationKind)Record.readInt();
SourceLocation POI = readSourceLocation(); SourceLocation POI = readSourceLocation();
FD->setInstantiationOfMemberFunction(Reader.getContext(), InstFD, TSK); FD->setInstantiationOfMemberFunction(Reader.getContext(), InstFD, TSK);
FD->getMemberSpecializationInfo()->setPointOfInstantiation(POI); FD->getMemberSpecializationInfo()->setPointOfInstantiation(POI);
mergeRedeclarable(FD, Redecl);
break; break;
} }
case FunctionDecl::TK_FunctionTemplateSpecialization: { case FunctionDecl::TK_FunctionTemplateSpecialization: {
@ -1041,7 +979,7 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
else { else {
assert(Reader.getContext().getLangOpts().Modules && assert(Reader.getContext().getLangOpts().Modules &&
"already deserialized this template specialization"); "already deserialized this template specialization");
mergeRedeclarable(FD, ExistingInfo->getFunction(), Redecl); Existing = ExistingInfo->getFunction();
} }
} }
break; break;
@ -1069,6 +1007,96 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
} }
} }
VisitDeclaratorDecl(FD);
// Attach a type to this function. Use the real type if possible, but fall
// back to the type as written if it involves a deduced return type.
if (FD->getTypeSourceInfo() && FD->getTypeSourceInfo()
->getType()
->castAs<FunctionType>()
->getReturnType()
->getContainedAutoType()) {
// We'll set up the real type in Visit, once we've finished loading the
// function.
FD->setType(FD->getTypeSourceInfo()->getType());
Reader.PendingFunctionTypes.push_back({FD, DeferredTypeID});
} else {
FD->setType(Reader.GetType(DeferredTypeID));
}
DeferredTypeID = 0;
FD->DNLoc = Record.readDeclarationNameLoc(FD->getDeclName());
FD->IdentifierNamespace = Record.readInt();
// FunctionDecl's body is handled last at ASTDeclReader::Visit,
// after everything else is read.
FD->setStorageClass(static_cast<StorageClass>(Record.readInt()));
FD->setInlineSpecified(Record.readInt());
FD->setImplicitlyInline(Record.readInt());
FD->setVirtualAsWritten(Record.readInt());
// We defer calling `FunctionDecl::setPure()` here as for methods of
// `CXXTemplateSpecializationDecl`s, we may not have connected up the
// definition (which is required for `setPure`).
const bool Pure = Record.readInt();
FD->setHasInheritedPrototype(Record.readInt());
FD->setHasWrittenPrototype(Record.readInt());
FD->setDeletedAsWritten(Record.readInt());
FD->setTrivial(Record.readInt());
FD->setTrivialForCall(Record.readInt());
FD->setDefaulted(Record.readInt());
FD->setExplicitlyDefaulted(Record.readInt());
FD->setHasImplicitReturnZero(Record.readInt());
FD->setConstexprKind(static_cast<ConstexprSpecKind>(Record.readInt()));
FD->setUsesSEHTry(Record.readInt());
FD->setHasSkippedBody(Record.readInt());
FD->setIsMultiVersion(Record.readInt());
FD->setLateTemplateParsed(Record.readInt());
FD->setFriendConstraintRefersToEnclosingTemplate(Record.readInt());
FD->setCachedLinkage(static_cast<Linkage>(Record.readInt()));
FD->EndRangeLoc = readSourceLocation();
FD->setDefaultLoc(readSourceLocation());
FD->ODRHash = Record.readInt();
FD->setHasODRHash(true);
if (FD->isDefaulted()) {
if (unsigned NumLookups = Record.readInt()) {
SmallVector<DeclAccessPair, 8> Lookups;
for (unsigned I = 0; I != NumLookups; ++I) {
NamedDecl *ND = Record.readDeclAs<NamedDecl>();
AccessSpecifier AS = (AccessSpecifier)Record.readInt();
Lookups.push_back(DeclAccessPair::make(ND, AS));
}
FD->setDefaultedFunctionInfo(FunctionDecl::DefaultedFunctionInfo::Create(
Reader.getContext(), Lookups));
}
}
if (Existing)
mergeRedeclarable(FD, Existing, Redecl);
else if (auto Kind = FD->getTemplatedKind();
Kind == FunctionDecl::TK_FunctionTemplate ||
Kind == FunctionDecl::TK_FunctionTemplateSpecialization) {
// Function Templates have their FunctionTemplateDecls merged instead of
// their FunctionDecls.
auto merge = [this, &Redecl, FD](auto &&F) {
auto *Existing = cast_or_null<FunctionDecl>(Redecl.getKnownMergeTarget());
RedeclarableResult NewRedecl(Existing ? F(Existing) : nullptr,
Redecl.getFirstID(), Redecl.isKeyDecl());
mergeRedeclarableTemplate(F(FD), NewRedecl);
};
if (Kind == FunctionDecl::TK_FunctionTemplate)
merge(
[](FunctionDecl *FD) { return FD->getDescribedFunctionTemplate(); });
else
merge([](FunctionDecl *FD) {
return FD->getTemplateSpecializationInfo()->getTemplate();
});
} else
mergeRedeclarable(FD, Redecl);
// Defer calling `setPure` until merging above has guaranteed we've set // Defer calling `setPure` until merging above has guaranteed we've set
// `DefinitionData` (as this will need to access it). // `DefinitionData` (as this will need to access it).
FD->setPure(Pure); FD->setPure(Pure);
@ -2187,15 +2215,12 @@ void ASTDeclReader::VisitFriendTemplateDecl(FriendTemplateDecl *D) {
D->FriendLoc = readSourceLocation(); D->FriendLoc = readSourceLocation();
} }
DeclID ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) { void ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) {
VisitNamedDecl(D); VisitNamedDecl(D);
DeclID PatternID = readDeclID(); assert(!D->TemplateParams && "TemplateParams already set!");
auto *TemplatedDecl = cast_or_null<NamedDecl>(Reader.GetDecl(PatternID)); D->TemplateParams = Record.readTemplateParameterList();
TemplateParameterList *TemplateParams = Record.readTemplateParameterList(); D->init(readDeclAs<NamedDecl>());
D->init(TemplatedDecl, TemplateParams);
return PatternID;
} }
void ASTDeclReader::VisitConceptDecl(ConceptDecl *D) { void ASTDeclReader::VisitConceptDecl(ConceptDecl *D) {
@ -2232,21 +2257,15 @@ ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
} }
} }
DeclID PatternID = VisitTemplateDecl(D); VisitTemplateDecl(D);
D->IdentifierNamespace = Record.readInt(); D->IdentifierNamespace = Record.readInt();
mergeRedeclarable(D, Redecl, PatternID);
// If we merged the template with a prior declaration chain, merge the common
// pointer.
// FIXME: Actually merge here, don't just overwrite.
D->Common = D->getCanonicalDecl()->Common;
return Redecl; return Redecl;
} }
void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) { void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D); RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D);
mergeRedeclarableTemplate(D, Redecl);
if (ThisDeclID == Redecl.getFirstID()) { if (ThisDeclID == Redecl.getFirstID()) {
// This ClassTemplateDecl owns a CommonPtr; read it to keep track of all of // This ClassTemplateDecl owns a CommonPtr; read it to keep track of all of
@ -2274,6 +2293,7 @@ void ASTDeclReader::VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D) {
/// VarTemplateDecl beyond TemplateDecl... /// VarTemplateDecl beyond TemplateDecl...
void ASTDeclReader::VisitVarTemplateDecl(VarTemplateDecl *D) { void ASTDeclReader::VisitVarTemplateDecl(VarTemplateDecl *D) {
RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D); RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D);
mergeRedeclarableTemplate(D, Redecl);
if (ThisDeclID == Redecl.getFirstID()) { if (ThisDeclID == Redecl.getFirstID()) {
// This VarTemplateDecl owns a CommonPtr; read it to keep track of all of // This VarTemplateDecl owns a CommonPtr; read it to keep track of all of
@ -2402,8 +2422,6 @@ void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
ASTDeclReader::RedeclarableResult ASTDeclReader::RedeclarableResult
ASTDeclReader::VisitVarTemplateSpecializationDeclImpl( ASTDeclReader::VisitVarTemplateSpecializationDeclImpl(
VarTemplateSpecializationDecl *D) { VarTemplateSpecializationDecl *D) {
RedeclarableResult Redecl = VisitVarDeclImpl(D);
ASTContext &C = Reader.getContext(); ASTContext &C = Reader.getContext();
if (Decl *InstD = readDecl()) { if (Decl *InstD = readDecl()) {
if (auto *VTD = dyn_cast<VarTemplateDecl>(InstD)) { if (auto *VTD = dyn_cast<VarTemplateDecl>(InstD)) {
@ -2440,6 +2458,8 @@ ASTDeclReader::VisitVarTemplateSpecializationDeclImpl(
D->SpecializationKind = (TemplateSpecializationKind)Record.readInt(); D->SpecializationKind = (TemplateSpecializationKind)Record.readInt();
D->IsCompleteDefinition = Record.readInt(); D->IsCompleteDefinition = Record.readInt();
RedeclarableResult Redecl = VisitVarDeclImpl(D);
bool writtenAsCanonicalDecl = Record.readInt(); bool writtenAsCanonicalDecl = Record.readInt();
if (writtenAsCanonicalDecl) { if (writtenAsCanonicalDecl) {
auto *CanonPattern = readDeclAs<VarTemplateDecl>(); auto *CanonPattern = readDeclAs<VarTemplateDecl>();
@ -2547,7 +2567,8 @@ void ASTDeclReader::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
} }
void ASTDeclReader::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { void ASTDeclReader::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
VisitRedeclarableTemplateDecl(D); RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D);
mergeRedeclarableTemplate(D, Redecl);
} }
void ASTDeclReader::VisitStaticAssertDecl(StaticAssertDecl *D) { void ASTDeclReader::VisitStaticAssertDecl(StaticAssertDecl *D) {
@ -2644,10 +2665,9 @@ ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
/// Attempts to merge the given declaration (D) with another declaration /// Attempts to merge the given declaration (D) with another declaration
/// of the same entity. /// of the same entity.
template<typename T> template <typename T>
void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase,
RedeclarableResult &Redecl, RedeclarableResult &Redecl) {
DeclID TemplatePatternID) {
// If modules are not available, there is no reason to perform this merge. // If modules are not available, there is no reason to perform this merge.
if (!Reader.getContext().getLangOpts().Modules) if (!Reader.getContext().getLangOpts().Modules)
return; return;
@ -2660,10 +2680,19 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase,
if (auto *Existing = Redecl.getKnownMergeTarget()) if (auto *Existing = Redecl.getKnownMergeTarget())
// We already know of an existing declaration we should merge with. // We already know of an existing declaration we should merge with.
mergeRedeclarable(D, cast<T>(Existing), Redecl, TemplatePatternID); mergeRedeclarable(D, cast<T>(Existing), Redecl);
else if (FindExistingResult ExistingRes = findExisting(D)) else if (FindExistingResult ExistingRes = findExisting(D))
if (T *Existing = ExistingRes) if (T *Existing = ExistingRes)
mergeRedeclarable(D, Existing, Redecl, TemplatePatternID); mergeRedeclarable(D, Existing, Redecl);
}
void ASTDeclReader::mergeRedeclarableTemplate(RedeclarableTemplateDecl *D,
RedeclarableResult &Redecl) {
mergeRedeclarable(D, Redecl);
// If we merged the template with a prior declaration chain, merge the
// common pointer.
// FIXME: Actually merge here, don't just overwrite.
D->Common = D->getCanonicalDecl()->Common;
} }
/// "Cast" to type T, asserting if we don't have an implicit conversion. /// "Cast" to type T, asserting if we don't have an implicit conversion.
@ -2678,7 +2707,7 @@ template<typename T> static T assert_cast(...) {
/// declarations. /// declarations.
void ASTDeclReader::mergeTemplatePattern(RedeclarableTemplateDecl *D, void ASTDeclReader::mergeTemplatePattern(RedeclarableTemplateDecl *D,
RedeclarableTemplateDecl *Existing, RedeclarableTemplateDecl *Existing,
DeclID DsID, bool IsKeyDecl) { bool IsKeyDecl) {
auto *DPattern = D->getTemplatedDecl(); auto *DPattern = D->getTemplatedDecl();
auto *ExistingPattern = Existing->getTemplatedDecl(); auto *ExistingPattern = Existing->getTemplatedDecl();
RedeclarableResult Result(/*MergeWith*/ ExistingPattern, RedeclarableResult Result(/*MergeWith*/ ExistingPattern,
@ -2718,17 +2747,13 @@ void ASTDeclReader::mergeTemplatePattern(RedeclarableTemplateDecl *D,
/// Attempts to merge the given declaration (D) with another declaration /// Attempts to merge the given declaration (D) with another declaration
/// of the same entity. /// of the same entity.
template<typename T> template <typename T>
void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, T *Existing, void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, T *Existing,
RedeclarableResult &Redecl, RedeclarableResult &Redecl) {
DeclID TemplatePatternID) {
auto *D = static_cast<T *>(DBase); auto *D = static_cast<T *>(DBase);
T *ExistingCanon = Existing->getCanonicalDecl(); T *ExistingCanon = Existing->getCanonicalDecl();
T *DCanon = D->getCanonicalDecl(); T *DCanon = D->getCanonicalDecl();
if (ExistingCanon != DCanon) { if (ExistingCanon != DCanon) {
assert(DCanon->getGlobalID() == Redecl.getFirstID() &&
"already merged this declaration");
// Have our redeclaration link point back at the canonical declaration // Have our redeclaration link point back at the canonical declaration
// of the existing declaration, so that this declaration has the // of the existing declaration, so that this declaration has the
// appropriate canonical declaration. // appropriate canonical declaration.
@ -2747,8 +2772,8 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, T *Existing,
// When we merge a template, merge its pattern. // When we merge a template, merge its pattern.
if (auto *DTemplate = dyn_cast<RedeclarableTemplateDecl>(D)) if (auto *DTemplate = dyn_cast<RedeclarableTemplateDecl>(D))
mergeTemplatePattern( mergeTemplatePattern(
DTemplate, assert_cast<RedeclarableTemplateDecl*>(ExistingCanon), DTemplate, assert_cast<RedeclarableTemplateDecl *>(ExistingCanon),
TemplatePatternID, Redecl.isKeyDecl()); Redecl.isKeyDecl());
// If this declaration is a key declaration, make a note of that. // If this declaration is a key declaration, make a note of that.
if (Redecl.isKeyDecl()) if (Redecl.isKeyDecl())

View File

@ -2118,8 +2118,10 @@ void ASTStmtReader::VisitSizeOfPackExpr(SizeOfPackExpr *E) {
void ASTStmtReader::VisitSubstNonTypeTemplateParmExpr( void ASTStmtReader::VisitSubstNonTypeTemplateParmExpr(
SubstNonTypeTemplateParmExpr *E) { SubstNonTypeTemplateParmExpr *E) {
VisitExpr(E); VisitExpr(E);
E->ParamAndRef.setPointer(readDeclAs<NonTypeTemplateParmDecl>()); E->AssociatedDeclAndRef.setPointer(readDeclAs<Decl>());
E->ParamAndRef.setInt(Record.readInt()); E->AssociatedDeclAndRef.setInt(Record.readInt());
E->Index = Record.readInt();
E->PackIndex = Record.readInt();
E->SubstNonTypeTemplateParmExprBits.NameLoc = readSourceLocation(); E->SubstNonTypeTemplateParmExprBits.NameLoc = readSourceLocation();
E->Replacement = Record.readSubExpr(); E->Replacement = Record.readSubExpr();
} }
@ -2127,7 +2129,8 @@ void ASTStmtReader::VisitSubstNonTypeTemplateParmExpr(
void ASTStmtReader::VisitSubstNonTypeTemplateParmPackExpr( void ASTStmtReader::VisitSubstNonTypeTemplateParmPackExpr(
SubstNonTypeTemplateParmPackExpr *E) { SubstNonTypeTemplateParmPackExpr *E) {
VisitExpr(E); VisitExpr(E);
E->Param = readDeclAs<NonTypeTemplateParmDecl>(); E->AssociatedDecl = readDeclAs<Decl>();
E->Index = Record.readInt();
TemplateArgument ArgPack = Record.readTemplateArgument(); TemplateArgument ArgPack = Record.readTemplateArgument();
if (ArgPack.getKind() != TemplateArgument::Pack) if (ArgPack.getKind() != TemplateArgument::Pack)
return; return;

View File

@ -539,48 +539,6 @@ void ASTDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) {
void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
VisitRedeclarable(D); VisitRedeclarable(D);
VisitDeclaratorDecl(D);
Record.AddDeclarationNameLoc(D->DNLoc, D->getDeclName());
Record.push_back(D->getIdentifierNamespace());
// FunctionDecl's body is handled last at ASTWriterDecl::Visit,
// after everything else is written.
Record.push_back(static_cast<int>(D->getStorageClass())); // FIXME: stable encoding
Record.push_back(D->isInlineSpecified());
Record.push_back(D->isInlined());
Record.push_back(D->isVirtualAsWritten());
Record.push_back(D->isPure());
Record.push_back(D->hasInheritedPrototype());
Record.push_back(D->hasWrittenPrototype());
Record.push_back(D->isDeletedBit());
Record.push_back(D->isTrivial());
Record.push_back(D->isTrivialForCall());
Record.push_back(D->isDefaulted());
Record.push_back(D->isExplicitlyDefaulted());
Record.push_back(D->hasImplicitReturnZero());
Record.push_back(static_cast<uint64_t>(D->getConstexprKind()));
Record.push_back(D->usesSEHTry());
Record.push_back(D->hasSkippedBody());
Record.push_back(D->isMultiVersion());
Record.push_back(D->isLateTemplateParsed());
Record.push_back(D->FriendConstraintRefersToEnclosingTemplate());
Record.push_back(D->getLinkageInternal());
Record.AddSourceLocation(D->getEndLoc());
Record.AddSourceLocation(D->getDefaultLoc());
Record.push_back(D->getODRHash());
if (D->isDefaulted()) {
if (auto *FDI = D->getDefaultedFunctionInfo()) {
Record.push_back(FDI->getUnqualifiedLookups().size());
for (DeclAccessPair P : FDI->getUnqualifiedLookups()) {
Record.AddDeclRef(P.getDecl());
Record.push_back(P.getAccess());
}
} else {
Record.push_back(0);
}
}
Record.push_back(D->getTemplatedKind()); Record.push_back(D->getTemplatedKind());
switch (D->getTemplatedKind()) { switch (D->getTemplatedKind()) {
@ -661,6 +619,50 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
} }
} }
VisitDeclaratorDecl(D);
Record.AddDeclarationNameLoc(D->DNLoc, D->getDeclName());
Record.push_back(D->getIdentifierNamespace());
// FunctionDecl's body is handled last at ASTWriterDecl::Visit,
// after everything else is written.
Record.push_back(
static_cast<int>(D->getStorageClass())); // FIXME: stable encoding
Record.push_back(D->isInlineSpecified());
Record.push_back(D->isInlined());
Record.push_back(D->isVirtualAsWritten());
Record.push_back(D->isPure());
Record.push_back(D->hasInheritedPrototype());
Record.push_back(D->hasWrittenPrototype());
Record.push_back(D->isDeletedBit());
Record.push_back(D->isTrivial());
Record.push_back(D->isTrivialForCall());
Record.push_back(D->isDefaulted());
Record.push_back(D->isExplicitlyDefaulted());
Record.push_back(D->hasImplicitReturnZero());
Record.push_back(static_cast<uint64_t>(D->getConstexprKind()));
Record.push_back(D->usesSEHTry());
Record.push_back(D->hasSkippedBody());
Record.push_back(D->isMultiVersion());
Record.push_back(D->isLateTemplateParsed());
Record.push_back(D->FriendConstraintRefersToEnclosingTemplate());
Record.push_back(D->getLinkageInternal());
Record.AddSourceLocation(D->getEndLoc());
Record.AddSourceLocation(D->getDefaultLoc());
Record.push_back(D->getODRHash());
if (D->isDefaulted()) {
if (auto *FDI = D->getDefaultedFunctionInfo()) {
Record.push_back(FDI->getUnqualifiedLookups().size());
for (DeclAccessPair P : FDI->getUnqualifiedLookups()) {
Record.AddDeclRef(P.getDecl());
Record.push_back(P.getAccess());
}
} else {
Record.push_back(0);
}
}
Record.push_back(D->param_size()); Record.push_back(D->param_size());
for (auto *P : D->parameters()) for (auto *P : D->parameters())
Record.AddDeclRef(P); Record.AddDeclRef(P);
@ -1405,14 +1407,12 @@ void ASTDeclWriter::VisitCXXMethodDecl(CXXMethodDecl *D) {
} }
if (D->getDeclContext() == D->getLexicalDeclContext() && if (D->getDeclContext() == D->getLexicalDeclContext() &&
D->getFirstDecl() == D->getMostRecentDecl() && D->getFirstDecl() == D->getMostRecentDecl() && !D->isInvalidDecl() &&
!D->isInvalidDecl() && !D->hasAttrs() && !D->isTopLevelDeclInObjCContainer() &&
!D->hasAttrs() &&
!D->isTopLevelDeclInObjCContainer() &&
D->getDeclName().getNameKind() == DeclarationName::Identifier && D->getDeclName().getNameKind() == DeclarationName::Identifier &&
!D->hasExtInfo() && !D->hasExtInfo() && !D->hasInheritedPrototype() &&
!D->hasInheritedPrototype() && D->hasWrittenPrototype() &&
D->hasWrittenPrototype()) D->getTemplatedKind() == FunctionDecl::TK_NonTemplate)
AbbrevToUse = Writer.getDeclCXXMethodAbbrev(); AbbrevToUse = Writer.getDeclCXXMethodAbbrev();
Code = serialization::DECL_CXX_METHOD; Code = serialization::DECL_CXX_METHOD;
@ -1506,8 +1506,8 @@ void ASTDeclWriter::VisitFriendTemplateDecl(FriendTemplateDecl *D) {
void ASTDeclWriter::VisitTemplateDecl(TemplateDecl *D) { void ASTDeclWriter::VisitTemplateDecl(TemplateDecl *D) {
VisitNamedDecl(D); VisitNamedDecl(D);
Record.AddDeclRef(D->getTemplatedDecl());
Record.AddTemplateParameterList(D->getTemplateParameters()); Record.AddTemplateParameterList(D->getTemplateParameters());
Record.AddDeclRef(D->getTemplatedDecl());
} }
void ASTDeclWriter::VisitConceptDecl(ConceptDecl *D) { void ASTDeclWriter::VisitConceptDecl(ConceptDecl *D) {
@ -1608,8 +1608,6 @@ void ASTDeclWriter::VisitVarTemplateSpecializationDecl(
VarTemplateSpecializationDecl *D) { VarTemplateSpecializationDecl *D) {
RegisterTemplateSpecialization(D->getSpecializedTemplate(), D); RegisterTemplateSpecialization(D->getSpecializedTemplate(), D);
VisitVarDecl(D);
llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *> llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>
InstFrom = D->getSpecializedTemplateOrPartial(); InstFrom = D->getSpecializedTemplateOrPartial();
if (Decl *InstFromD = InstFrom.dyn_cast<VarTemplateDecl *>()) { if (Decl *InstFromD = InstFrom.dyn_cast<VarTemplateDecl *>()) {
@ -1630,6 +1628,9 @@ void ASTDeclWriter::VisitVarTemplateSpecializationDecl(
Record.AddSourceLocation(D->getPointOfInstantiation()); Record.AddSourceLocation(D->getPointOfInstantiation());
Record.push_back(D->getSpecializationKind()); Record.push_back(D->getSpecializationKind());
Record.push_back(D->IsCompleteDefinition); Record.push_back(D->IsCompleteDefinition);
VisitVarDecl(D);
Record.push_back(D->isCanonicalDecl()); Record.push_back(D->isCanonicalDecl());
if (D->isCanonicalDecl()) { if (D->isCanonicalDecl()) {
@ -2245,6 +2246,8 @@ void ASTWriter::WriteDeclAbbrevs() {
Abv->Add(BitCodeAbbrevOp(serialization::DECL_CXX_METHOD)); Abv->Add(BitCodeAbbrevOp(serialization::DECL_CXX_METHOD));
// RedeclarableDecl // RedeclarableDecl
Abv->Add(BitCodeAbbrevOp(0)); // CanonicalDecl Abv->Add(BitCodeAbbrevOp(0)); // CanonicalDecl
// FIXME: Implement abbreviation for other template kinds.
Abv->Add(BitCodeAbbrevOp(FunctionDecl::TK_NonTemplate)); // TemplateKind
// Decl // Decl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext
@ -2292,11 +2295,10 @@ void ASTWriter::WriteDeclAbbrevs() {
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LocEnd Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LocEnd
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Default Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Default
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // ODRHash Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // ODRHash
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // TemplateKind
// This Array slurps the rest of the record. Fortunately we want to encode // This Array slurps the rest of the record. Fortunately we want to encode
// (nearly) all the remaining (variable number of) fields in the same way. // (nearly) all the remaining (variable number of) fields in the same way.
// //
// This is the function template information if any, then // This is:
// NumParams and Params[] from FunctionDecl, and // NumParams and Params[] from FunctionDecl, and
// NumOverriddenMethods, OverriddenMethods[] from CXXMethodDecl. // NumOverriddenMethods, OverriddenMethods[] from CXXMethodDecl.
// //

View File

@ -2028,8 +2028,13 @@ void ASTStmtWriter::VisitSizeOfPackExpr(SizeOfPackExpr *E) {
void ASTStmtWriter::VisitSubstNonTypeTemplateParmExpr( void ASTStmtWriter::VisitSubstNonTypeTemplateParmExpr(
SubstNonTypeTemplateParmExpr *E) { SubstNonTypeTemplateParmExpr *E) {
VisitExpr(E); VisitExpr(E);
Record.AddDeclRef(E->getParameter()); Record.AddDeclRef(E->getAssociatedDecl());
Record.push_back(E->isReferenceParameter()); Record.push_back(E->isReferenceParameter());
Record.push_back(E->getIndex());
if (auto PackIndex = E->getPackIndex())
Record.push_back(*PackIndex + 1);
else
Record.push_back(0);
Record.AddSourceLocation(E->getNameLoc()); Record.AddSourceLocation(E->getNameLoc());
Record.AddStmt(E->getReplacement()); Record.AddStmt(E->getReplacement());
Code = serialization::EXPR_SUBST_NON_TYPE_TEMPLATE_PARM; Code = serialization::EXPR_SUBST_NON_TYPE_TEMPLATE_PARM;
@ -2038,7 +2043,8 @@ void ASTStmtWriter::VisitSubstNonTypeTemplateParmExpr(
void ASTStmtWriter::VisitSubstNonTypeTemplateParmPackExpr( void ASTStmtWriter::VisitSubstNonTypeTemplateParmPackExpr(
SubstNonTypeTemplateParmPackExpr *E) { SubstNonTypeTemplateParmPackExpr *E) {
VisitExpr(E); VisitExpr(E);
Record.AddDeclRef(E->getParameterPack()); Record.AddDeclRef(E->getAssociatedDecl());
Record.push_back(E->getIndex());
Record.AddTemplateArgument(E->getArgumentPack()); Record.AddTemplateArgument(E->getArgumentPack());
Record.AddSourceLocation(E->getParameterPackLocation()); Record.AddSourceLocation(E->getParameterPackLocation());
Code = serialization::EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK; Code = serialization::EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK;

View File

@ -176,8 +176,10 @@ void MismatchedIteratorChecker::checkPreCall(const CallEvent &Call,
const auto *Param = Func->getParamDecl(J); const auto *Param = Func->getParamDecl(J);
const auto *ParamType = const auto *ParamType =
Param->getType()->getAs<SubstTemplateTypeParmType>(); Param->getType()->getAs<SubstTemplateTypeParmType>();
if (!ParamType || if (!ParamType)
ParamType->getReplacedParameter()->getDecl() != TPDecl) continue;
const TemplateTypeParmDecl *D = ParamType->getReplacedParameter();
if (D != TPDecl)
continue; continue;
if (LHS.isUndef()) { if (LHS.isUndef()) {
LHS = Call.getArgSVal(J); LHS = Call.getArgSVal(J);

View File

@ -122,9 +122,8 @@ int test(float &&f, short &&s) {
// CHECK-NEXT: | | | `-BuiltinType [[ADDR_8:0x[a-z0-9]*]] 'float' // CHECK-NEXT: | | | `-BuiltinType [[ADDR_8:0x[a-z0-9]*]] 'float'
// CHECK-NEXT: | | |-CXXRecordDecl [[ADDR_9:0x[a-z0-9]*]] <col:22, col:29> col:29 implicit struct remove_reference // CHECK-NEXT: | | |-CXXRecordDecl [[ADDR_9:0x[a-z0-9]*]] <col:22, col:29> col:29 implicit struct remove_reference
// CHECK-NEXT: | | `-TypedefDecl [[ADDR_10:0x[a-z0-9]*]] <col:55, col:67> col:67 referenced type 'float':'float' // CHECK-NEXT: | | `-TypedefDecl [[ADDR_10:0x[a-z0-9]*]] <col:55, col:67> col:67 referenced type 'float':'float'
// CHECK-NEXT: | | `-SubstTemplateTypeParmType [[ADDR_11:0x[a-z0-9]*]] 'float' sugar // CHECK-NEXT: | | `-SubstTemplateTypeParmType [[ADDR_11:0x[a-z0-9]*]] 'float' sugar class depth 0 index 0 _Tp
// CHECK-NEXT: | | |-TemplateTypeParmType [[ADDR_12:0x[a-z0-9]*]] '_Tp' dependent depth 0 index 0 // CHECK-NEXT: | | |-ClassTemplateSpecialization [[ADDR_6]] 'remove_reference'
// CHECK-NEXT: | | | `-TemplateTypeParm [[ADDR_13:0x[a-z0-9]*]] '_Tp'
// CHECK-NEXT: | | `-BuiltinType [[ADDR_8]] 'float' // CHECK-NEXT: | | `-BuiltinType [[ADDR_8]] 'float'
// CHECK-NEXT: | `-ClassTemplateSpecializationDecl [[ADDR_14:0x[a-z0-9]*]] <col:1, col:73> col:29 struct remove_reference definition // CHECK-NEXT: | `-ClassTemplateSpecializationDecl [[ADDR_14:0x[a-z0-9]*]] <col:1, col:73> col:29 struct remove_reference definition
// CHECK-NEXT: | |-DefinitionData pass_in_registers empty aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor can_const_default_init // CHECK-NEXT: | |-DefinitionData pass_in_registers empty aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor can_const_default_init
@ -139,9 +138,8 @@ int test(float &&f, short &&s) {
// CHECK-NEXT: | | `-BuiltinType [[ADDR_16:0x[a-z0-9]*]] 'short' // CHECK-NEXT: | | `-BuiltinType [[ADDR_16:0x[a-z0-9]*]] 'short'
// CHECK-NEXT: | |-CXXRecordDecl [[ADDR_17:0x[a-z0-9]*]] <col:22, col:29> col:29 implicit struct remove_reference // CHECK-NEXT: | |-CXXRecordDecl [[ADDR_17:0x[a-z0-9]*]] <col:22, col:29> col:29 implicit struct remove_reference
// CHECK-NEXT: | `-TypedefDecl [[ADDR_18:0x[a-z0-9]*]] <col:55, col:67> col:67 referenced type 'short':'short' // CHECK-NEXT: | `-TypedefDecl [[ADDR_18:0x[a-z0-9]*]] <col:55, col:67> col:67 referenced type 'short':'short'
// CHECK-NEXT: | `-SubstTemplateTypeParmType [[ADDR_19:0x[a-z0-9]*]] 'short' sugar // CHECK-NEXT: | `-SubstTemplateTypeParmType [[ADDR_19:0x[a-z0-9]*]] 'short' sugar class depth 0 index 0 _Tp
// CHECK-NEXT: | |-TemplateTypeParmType [[ADDR_12]] '_Tp' dependent depth 0 index 0 // CHECK-NEXT: | |-ClassTemplateSpecialization [[ADDR_14]] 'remove_reference'
// CHECK-NEXT: | | `-TemplateTypeParm [[ADDR_13]] '_Tp'
// CHECK-NEXT: | `-BuiltinType [[ADDR_16]] 'short' // CHECK-NEXT: | `-BuiltinType [[ADDR_16]] 'short'
// CHECK-NEXT: |-ClassTemplatePartialSpecializationDecl [[ADDR_20:0x[a-z0-9]*]] <col:1, col:73> col:29 struct remove_reference definition // CHECK-NEXT: |-ClassTemplatePartialSpecializationDecl [[ADDR_20:0x[a-z0-9]*]] <col:1, col:73> col:29 struct remove_reference definition
// CHECK-NEXT: | |-DefinitionData empty aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor can_const_default_init // CHECK-NEXT: | |-DefinitionData empty aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor can_const_default_init
@ -154,10 +152,10 @@ int test(float &&f, short &&s) {
// CHECK-NEXT: | |-TemplateArgument type 'type-parameter-0-0 &' // CHECK-NEXT: | |-TemplateArgument type 'type-parameter-0-0 &'
// CHECK-NEXT: | | `-LValueReferenceType [[ADDR_21:0x[a-z0-9]*]] 'type-parameter-0-0 &' dependent // CHECK-NEXT: | | `-LValueReferenceType [[ADDR_21:0x[a-z0-9]*]] 'type-parameter-0-0 &' dependent
// CHECK-NEXT: | | `-TemplateTypeParmType [[ADDR_22:0x[a-z0-9]*]] 'type-parameter-0-0' dependent depth 0 index 0 // CHECK-NEXT: | | `-TemplateTypeParmType [[ADDR_22:0x[a-z0-9]*]] 'type-parameter-0-0' dependent depth 0 index 0
// CHECK-NEXT: | |-TemplateTypeParmDecl [[ADDR_13]] <col:11, col:17> col:17 referenced class depth 0 index 0 _Tp // CHECK-NEXT: | |-TemplateTypeParmDecl [[ADDR_13:0x[a-z0-9]*]] <col:11, col:17> col:17 referenced class depth 0 index 0 _Tp
// CHECK-NEXT: | |-CXXRecordDecl [[ADDR_23:0x[a-z0-9]*]] <col:22, col:29> col:29 implicit struct remove_reference // CHECK-NEXT: | |-CXXRecordDecl [[ADDR_23:0x[a-z0-9]*]] <col:22, col:29> col:29 implicit struct remove_reference
// CHECK-NEXT: | `-TypedefDecl [[ADDR_24:0x[a-z0-9]*]] <col:55, col:67> col:67 type '_Tp' // CHECK-NEXT: | `-TypedefDecl [[ADDR_24:0x[a-z0-9]*]] <col:55, col:67> col:67 type '_Tp'
// CHECK-NEXT: | `-TemplateTypeParmType [[ADDR_12]] '_Tp' dependent depth 0 index 0 // CHECK-NEXT: | `-TemplateTypeParmType [[ADDR_12:0x[a-z0-9]*]] '_Tp' dependent depth 0 index 0
// CHECK-NEXT: | `-TemplateTypeParm [[ADDR_13]] '_Tp' // CHECK-NEXT: | `-TemplateTypeParm [[ADDR_13]] '_Tp'
// CHECK-NEXT: |-ClassTemplatePartialSpecializationDecl [[ADDR_25:0x[a-z0-9]*]] <line:7:1, col:74> col:29 struct remove_reference definition // CHECK-NEXT: |-ClassTemplatePartialSpecializationDecl [[ADDR_25:0x[a-z0-9]*]] <line:7:1, col:74> col:29 struct remove_reference definition
// CHECK-NEXT: | |-DefinitionData empty aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor can_const_default_init // CHECK-NEXT: | |-DefinitionData empty aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor can_const_default_init
@ -197,9 +195,8 @@ int test(float &&f, short &&s) {
// CHECK-NEXT: | | | `-ElaboratedType [[ADDR_47:0x[a-z0-9]*]] 'typename remove_reference<float &>::type' sugar // CHECK-NEXT: | | | `-ElaboratedType [[ADDR_47:0x[a-z0-9]*]] 'typename remove_reference<float &>::type' sugar
// CHECK-NEXT: | | | `-TypedefType [[ADDR_48:0x[a-z0-9]*]] 'remove_reference<float &>::type' sugar // CHECK-NEXT: | | | `-TypedefType [[ADDR_48:0x[a-z0-9]*]] 'remove_reference<float &>::type' sugar
// CHECK-NEXT: | | | |-Typedef [[ADDR_10]] 'type' // CHECK-NEXT: | | | |-Typedef [[ADDR_10]] 'type'
// CHECK-NEXT: | | | `-SubstTemplateTypeParmType [[ADDR_11]] 'float' sugar // CHECK-NEXT: | | | `-SubstTemplateTypeParmType [[ADDR_11]] 'float' sugar class depth 0 index 0 _Tp
// CHECK-NEXT: | | | |-TemplateTypeParmType [[ADDR_12]] '_Tp' dependent depth 0 index 0 // CHECK-NEXT: | | | |-ClassTemplateSpecialization [[ADDR_6]] 'remove_reference'
// CHECK-NEXT: | | | | `-TemplateTypeParm [[ADDR_13]] '_Tp'
// CHECK-NEXT: | | | `-BuiltinType [[ADDR_8]] 'float' // CHECK-NEXT: | | | `-BuiltinType [[ADDR_8]] 'float'
// CHECK-NEXT: | | `-ReturnStmt [[ADDR_49:0x[a-z0-9]*]] <line:13:3, col:33> // CHECK-NEXT: | | `-ReturnStmt [[ADDR_49:0x[a-z0-9]*]] <line:13:3, col:33>
// CHECK-NEXT: | | `-CXXStaticCastExpr [[ADDR_50:0x[a-z0-9]*]] <col:10, col:33> '_Up':'float' xvalue static_cast<_Up &&> <NoOp> // CHECK-NEXT: | | `-CXXStaticCastExpr [[ADDR_50:0x[a-z0-9]*]] <col:10, col:33> '_Up':'float' xvalue static_cast<_Up &&> <NoOp>
@ -215,9 +212,8 @@ int test(float &&f, short &&s) {
// CHECK-NEXT: | | `-ElaboratedType [[ADDR_57:0x[a-z0-9]*]] 'typename remove_reference<short &>::type' sugar // CHECK-NEXT: | | `-ElaboratedType [[ADDR_57:0x[a-z0-9]*]] 'typename remove_reference<short &>::type' sugar
// CHECK-NEXT: | | `-TypedefType [[ADDR_58:0x[a-z0-9]*]] 'remove_reference<short &>::type' sugar // CHECK-NEXT: | | `-TypedefType [[ADDR_58:0x[a-z0-9]*]] 'remove_reference<short &>::type' sugar
// CHECK-NEXT: | | |-Typedef [[ADDR_18]] 'type' // CHECK-NEXT: | | |-Typedef [[ADDR_18]] 'type'
// CHECK-NEXT: | | `-SubstTemplateTypeParmType [[ADDR_19]] 'short' sugar // CHECK-NEXT: | | `-SubstTemplateTypeParmType [[ADDR_19]] 'short' sugar class depth 0 index 0 _Tp
// CHECK-NEXT: | | |-TemplateTypeParmType [[ADDR_12]] '_Tp' dependent depth 0 index 0 // CHECK-NEXT: | | |-ClassTemplateSpecialization [[ADDR_14]] 'remove_reference'
// CHECK-NEXT: | | | `-TemplateTypeParm [[ADDR_13]] '_Tp'
// CHECK-NEXT: | | `-BuiltinType [[ADDR_16]] 'short' // CHECK-NEXT: | | `-BuiltinType [[ADDR_16]] 'short'
// CHECK-NEXT: | `-ReturnStmt [[ADDR_59:0x[a-z0-9]*]] <line:13:3, col:33> // CHECK-NEXT: | `-ReturnStmt [[ADDR_59:0x[a-z0-9]*]] <line:13:3, col:33>
// CHECK-NEXT: | `-CXXStaticCastExpr [[ADDR_60:0x[a-z0-9]*]] <col:10, col:33> '_Up':'short' xvalue static_cast<_Up &&> <NoOp> // CHECK-NEXT: | `-CXXStaticCastExpr [[ADDR_60:0x[a-z0-9]*]] <col:10, col:33> '_Up':'short' xvalue static_cast<_Up &&> <NoOp>

View File

@ -120,12 +120,12 @@ using type2 = typename C<int>::type1<void>;
// CHECK-NEXT: TemplateArgument type 'void' // CHECK-NEXT: TemplateArgument type 'void'
// CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'void' // CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'void'
// CHECK-NEXT: FunctionProtoType 0x{{[^ ]*}} 'void (int)' cdecl // CHECK-NEXT: FunctionProtoType 0x{{[^ ]*}} 'void (int)' cdecl
// CHECK-NEXT: SubstTemplateTypeParmType 0x{{[^ ]*}} 'void' sugar // CHECK-NEXT: SubstTemplateTypeParmType 0x{{[^ ]*}} 'void' sugar class depth 0 index 0 U
// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'U' dependent depth 0 index 0 // CHECK-NEXT: TypeAliasTemplate 0x{{[^ ]*}} 'type1'
// CHECK-NEXT: TemplateTypeParm 0x{{[^ ]*}} 'U'
// CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'void' // CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'void'
// CHECK-NEXT: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar // CHECK-NEXT: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar class depth 0 index 0 T
// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'T' dependent depth 0 index 0 // CHECK-NEXT: ClassTemplateSpecialization 0x{{[^ ]*}} 'C'
// CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'int'
} // namespace PR55886 } // namespace PR55886
namespace PR56099 { namespace PR56099 {
@ -136,14 +136,14 @@ template <typename... Cs> struct foo {
}; };
using t1 = foo<int, short>::bind<char, float>; using t1 = foo<int, short>::bind<char, float>;
// CHECK: TemplateSpecializationType 0x{{[^ ]*}} 'Y<char, float, int, short>' sugar Y // CHECK: TemplateSpecializationType 0x{{[^ ]*}} 'Y<char, float, int, short>' sugar Y
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'char' sugar pack_index 3 // CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'char' sugar typename depth 0 index 0 ... Bs pack_index 3
// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'Bs' dependent contains_unexpanded_pack depth 0 index 0 pack // CHECK-NEXT: TypeAliasTemplate 0x{{[^ ]*}} 'Z'
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'float' sugar pack_index 2 // CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'float' sugar typename depth 0 index 0 ... Bs pack_index 2
// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'Bs' dependent contains_unexpanded_pack depth 0 index 0 pack // CHECK-NEXT: TypeAliasTemplate 0x{{[^ ]*}} 'Z'
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar pack_index 1 // CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar typename depth 0 index 0 ... Bs pack_index 1
// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'Bs' dependent contains_unexpanded_pack depth 0 index 0 pack // CHECK-NEXT: TypeAliasTemplate 0x{{[^ ]*}} 'Z'
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'short' sugar pack_index 0 // CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'short' sugar typename depth 0 index 0 ... Bs pack_index 0
// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'Bs' dependent contains_unexpanded_pack depth 0 index 0 pack // CHECK-NEXT: TypeAliasTemplate 0x{{[^ ]*}} 'Z'
template <typename... T> struct D { template <typename... T> struct D {
template <typename... U> using B = int(int (*...p)(T, U)); template <typename... U> using B = int(int (*...p)(T, U));
@ -152,15 +152,15 @@ using t2 = D<float, char>::B<int, short>;
// CHECK: TemplateSpecializationType 0x{{[^ ]*}} 'B<int, short>' sugar alias B // CHECK: TemplateSpecializationType 0x{{[^ ]*}} 'B<int, short>' sugar alias B
// CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (int (*)(float, int), int (*)(char, short))' cdecl // CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (int (*)(float, int), int (*)(char, short))' cdecl
// CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (float, int)' cdecl // CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (float, int)' cdecl
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'float' sugar pack_index 1 // CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'float' sugar typename depth 0 index 0 ... T pack_index 1
// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'T' dependent contains_unexpanded_pack depth 0 index 0 pack // CHECK-NEXT: ClassTemplateSpecialization 0x{{[^ ]*}} 'D'
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar pack_index 1 // CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar typename depth 0 index 0 ... U pack_index 1
// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'U' dependent contains_unexpanded_pack depth 0 index 0 pack // CHECK-NEXT: TypeAliasTemplate 0x{{[^ ]*}} 'B'
// CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (char, short)' cdecl // CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (char, short)' cdecl
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'char' sugar pack_index 0 // CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'char' sugar typename depth 0 index 0 ... T pack_index 0
// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'T' dependent contains_unexpanded_pack depth 0 index 0 pack // CHECK-NEXT: ClassTemplateSpecialization 0x{{[^ ]*}} 'D'
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'short' sugar pack_index 0 // CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'short' sugar typename depth 0 index 0 ... U pack_index 0
// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'U' dependent contains_unexpanded_pack depth 0 index 0 pack // CHECK-NEXT: TypeAliasTemplate 0x{{[^ ]*}} 'B'
} // namespace PR56099 } // namespace PR56099
namespace subst_default_argument { namespace subst_default_argument {
@ -172,11 +172,10 @@ using test1 = D<E, int>;
// CHECK: TypeAliasDecl 0x{{[^ ]*}} <line:{{[1-9]+}}:1, col:23> col:7 test1 'D<subst_default_argument::E, int>':'subst_default_argument::E<int, subst_default_argument::A<int>>' // CHECK: TypeAliasDecl 0x{{[^ ]*}} <line:{{[1-9]+}}:1, col:23> col:7 test1 'D<subst_default_argument::E, int>':'subst_default_argument::E<int, subst_default_argument::A<int>>'
// CHECK: TemplateSpecializationType 0x{{[^ ]*}} 'A<int>' sugar A // CHECK: TemplateSpecializationType 0x{{[^ ]*}} 'A<int>' sugar A
// CHECK-NEXT: |-TemplateArgument type 'int':'int' // CHECK-NEXT: |-TemplateArgument type 'int':'int'
// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar // CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar class depth 0 index 0 E1
// CHECK-NEXT: | |-TemplateTypeParmType 0x{{[^ ]*}} 'C1' dependent depth 1 index 0 // CHECK-NEXT: | |-ClassTemplate 0x{{[^ ]*}} 'E'
// CHECK-NEXT: | | `-TemplateTypeParm 0x{{[^ ]*}} 'C1' // CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar class depth 0 index 1 D2
// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar // CHECK-NEXT: | |-TypeAliasTemplate 0x{{[^ ]*}} 'D'
// CHECK-NEXT: | |-TemplateTypeParmType 0x{{[^ ]*}} 'type-parameter-0-1' dependent depth 0 index 1
// CHECK-NEXT: | `-BuiltinType 0x{{[^ ]*}} 'int' // CHECK-NEXT: | `-BuiltinType 0x{{[^ ]*}} 'int'
// CHECK-NEXT: `-RecordType 0x{{[^ ]*}} 'subst_default_argument::A<int>' // CHECK-NEXT: `-RecordType 0x{{[^ ]*}} 'subst_default_argument::A<int>'
// CHECK-NEXT: `-ClassTemplateSpecialization 0x{{[^ ]*}} 'A' // CHECK-NEXT: `-ClassTemplateSpecialization 0x{{[^ ]*}} 'A'

View File

@ -67,9 +67,8 @@ namespace PR48177 {
// CHECK-NEXT: ElaboratedType {{.*}} 'typename Derived<int, 1, int>::type_alias' sugar // CHECK-NEXT: ElaboratedType {{.*}} 'typename Derived<int, 1, int>::type_alias' sugar
// CHECK-NEXT: TypedefType {{.*}} 'PR48177::Base<int>::type_alias' sugar // CHECK-NEXT: TypedefType {{.*}} 'PR48177::Base<int>::type_alias' sugar
// CHECK-NEXT: TypeAlias {{.*}} 'type_alias' // CHECK-NEXT: TypeAlias {{.*}} 'type_alias'
// CHECK-NEXT: SubstTemplateTypeParmType {{.*}} 'int' sugar // CHECK-NEXT: SubstTemplateTypeParmType {{.*}} 'int' sugar class depth 0 index 0 A
// CHECK-NEXT: TemplateTypeParmType {{.*}} 'A' // CHECK-NEXT: ClassTemplateSpecialization {{.*}} 'Base'
// CHECK-NEXT: TemplateTypeParm {{.*}} 'A'
// CHECK-NEXT: BuiltinType {{.*}} 'int' // CHECK-NEXT: BuiltinType {{.*}} 'int'
// CHECK: CXXDeductionGuideDecl {{.*}} implicit <deduction guide for Derived> 'auto (Derived<T, S, A> &&, const typename Derived<T, S, A>::type_alias &) -> Derived<T, S, A>' // CHECK: CXXDeductionGuideDecl {{.*}} implicit <deduction guide for Derived> 'auto (Derived<T, S, A> &&, const typename Derived<T, S, A>::type_alias &) -> Derived<T, S, A>'

View File

@ -156,9 +156,8 @@ using DT = D<int, int>;
// CHECK: |-BuiltinType {{.*}} 'int' // CHECK: |-BuiltinType {{.*}} 'int'
// CHECK: |-TemplateTypeParmType {{.*}} 'T' dependent contains_unexpanded_pack depth 0 index 0 pack // CHECK: |-TemplateTypeParmType {{.*}} 'T' dependent contains_unexpanded_pack depth 0 index 0 pack
// CHECK: | `-TemplateTypeParm {{.*}} 'T' // CHECK: | `-TemplateTypeParm {{.*}} 'T'
// CHECK: `-SubstTemplateTypeParmPackType {{.*}} 'U' dependent contains_unexpanded_pack // CHECK: `-SubstTemplateTypeParmPackType {{.*}} 'U' dependent contains_unexpanded_pack typename depth 1 index 0 ... U
// CHECK: |-TemplateTypeParmType {{.*}} 'U' dependent contains_unexpanded_pack depth 1 index 0 pack // CHECK: |-TypeAliasTemplate {{.*}} 'B'
// CHECK: | `-TemplateTypeParm {{.*}} 'U'
// CHECK: `-TemplateArgument pack // CHECK: `-TemplateArgument pack
// CHECK: |-TemplateArgument type 'type-parameter-0-1' // CHECK: |-TemplateArgument type 'type-parameter-0-1'
// CHECK-NOT: Subst // CHECK-NOT: Subst

View File

@ -15,9 +15,8 @@ using test1 = __make_integer_seq<A, int, 1>;
// CHECK-NEXT: | `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:42> 'int' 1 // CHECK-NEXT: | `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:42> 'int' 1
// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} 'A<int, 0>' sugar A // CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} 'A<int, 0>' sugar A
// CHECK-NEXT: |-TemplateArgument type 'int':'int' // CHECK-NEXT: |-TemplateArgument type 'int':'int'
// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'int' sugar // CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'int' sugar typename depth 0 index 1
// CHECK-NEXT: | |-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'auto' dependent depth 0 index 1 // CHECK-NEXT: | |-BuiltinTemplate 0x{{[0-9A-Fa-f]+}} '__make_integer_seq'
// CHECK-NEXT: | | `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} ''
// CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int' // CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
// CHECK-NEXT: |-TemplateArgument expr // CHECK-NEXT: |-TemplateArgument expr
// CHECK-NEXT: | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'int' // CHECK-NEXT: | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'int'
@ -28,7 +27,7 @@ using test1 = __make_integer_seq<A, int, 1>;
template <class B1, B1 B2> using B = __make_integer_seq<A, B1, B2>; template <class B1, B1 B2> using B = __make_integer_seq<A, B1, B2>;
using test2 = B<int, 1>; using test2 = B<int, 1>;
// CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:30:1, col:23> col:7 test2 'B<int, 1>':'A<int, 0>' // CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:29:1, col:23> col:7 test2 'B<int, 1>':'A<int, 0>'
// CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} 'B<int, 1>' sugar // CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} 'B<int, 1>' sugar
// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} 'B<int, 1>' sugar alias B // CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} 'B<int, 1>' sugar alias B
// CHECK-NEXT: |-TemplateArgument type 'int' // CHECK-NEXT: |-TemplateArgument type 'int'
@ -41,21 +40,19 @@ using test2 = B<int, 1>;
// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, int, 1>' sugar alias __make_integer_seq // CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, int, 1>' sugar alias __make_integer_seq
// CHECK-NEXT: |-TemplateArgument template A // CHECK-NEXT: |-TemplateArgument template A
// CHECK-NEXT: |-TemplateArgument type 'int':'int' // CHECK-NEXT: |-TemplateArgument type 'int':'int'
// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'int' sugar // CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'int' sugar class depth 0 index 0 B1
// CHECK-NEXT: | |-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'B1' dependent depth 0 index 0 // CHECK-NEXT: | |-TypeAliasTemplate 0x{{[0-9A-Fa-f]+}} 'B'
// CHECK-NEXT: | | `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} 'B1'
// CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int' // CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
// CHECK-NEXT: |-TemplateArgument expr // CHECK-NEXT: |-TemplateArgument expr
// CHECK-NEXT: | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} <line:29:64> 'int' // CHECK-NEXT: | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} <line:28:64> 'int'
// CHECK-NEXT: | |-value: Int 1 // CHECK-NEXT: | |-value: Int 1
// CHECK-NEXT: | `-SubstNonTypeTemplateParmExpr 0x{{[0-9A-Fa-f]+}} <col:64> 'int' // CHECK-NEXT: | `-SubstNonTypeTemplateParmExpr 0x{{[0-9A-Fa-f]+}} <col:64> 'int'
// CHECK-NEXT: | |-NonTypeTemplateParmDecl 0x{{[0-9A-Fa-f]+}} <col:21, col:24> col:24 referenced 'B1' depth 0 index 1 B2 // CHECK-NEXT: | |-NonTypeTemplateParmDecl 0x{{[0-9A-Fa-f]+}} <col:21, col:24> col:24 referenced 'B1' depth 0 index 1 B2
// CHECK-NEXT: | `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:64> 'int' 1 // CHECK-NEXT: | `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:64> 'int' 1
// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} 'A<int, 0>' sugar A // CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} 'A<int, 0>' sugar A
// CHECK-NEXT: |-TemplateArgument type 'int':'int' // CHECK-NEXT: |-TemplateArgument type 'int':'int'
// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'int' sugar // CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'int' sugar typename depth 0 index 1
// CHECK-NEXT: | |-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'auto' dependent depth 0 index 1 // CHECK-NEXT: | |-BuiltinTemplate 0x{{[0-9A-Fa-f]+}} '__make_integer_seq'
// CHECK-NEXT: | | `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} ''
// CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int' // CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
// CHECK-NEXT: |-TemplateArgument expr // CHECK-NEXT: |-TemplateArgument expr
// CHECK-NEXT: | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} <col:64> 'int' // CHECK-NEXT: | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} <col:64> 'int'
@ -66,7 +63,7 @@ using test2 = B<int, 1>;
template <template <class T, T...> class S, class T, int N> struct C { template <template <class T, T...> class S, class T, int N> struct C {
using test3 = __make_integer_seq<S, T, N>; using test3 = __make_integer_seq<S, T, N>;
// CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:68:3, col:43> col:9 test3 '__make_integer_seq<S, T, N>':'__make_integer_seq<type-parameter-0-1, N>' // CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:65:3, col:43> col:9 test3 '__make_integer_seq<S, T, N>':'__make_integer_seq<type-parameter-0-1, N>'
// CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<S, T, N>' sugar dependent // CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<S, T, N>' sugar dependent
// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<S, T, N>' sugar dependent alias __make_integer_seq // CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<S, T, N>' sugar dependent alias __make_integer_seq
// CHECK-NEXT: |-TemplateArgument template S // CHECK-NEXT: |-TemplateArgument template S
@ -85,7 +82,7 @@ template <template <class T, T...> class S, class T, int N> struct C {
// CHECK-NEXT: `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int' // CHECK-NEXT: `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int'
using test4 = __make_integer_seq<A, T, 1>; using test4 = __make_integer_seq<A, T, 1>;
// CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:87:3, col:43> col:9 test4 '__make_integer_seq<A, T, 1>':'__make_integer_seq<A, type-parameter-0-1, 1>' // CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:84:3, col:43> col:9 test4 '__make_integer_seq<A, T, 1>':'__make_integer_seq<A, type-parameter-0-1, 1>'
// CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, T, 1>' sugar dependent // CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, T, 1>' sugar dependent
// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, T, 1>' sugar dependent alias __make_integer_seq // CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, T, 1>' sugar dependent alias __make_integer_seq
// CHECK-NEXT: |-TemplateArgument template A // CHECK-NEXT: |-TemplateArgument template A
@ -104,7 +101,7 @@ template <template <class T, T...> class S, class T, int N> struct C {
// CHECK-NEXT: `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:42> 'int' 1 // CHECK-NEXT: `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:42> 'int' 1
using test5 = __make_integer_seq<A, int, N>; using test5 = __make_integer_seq<A, int, N>;
// CHECK: `-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:106:3, col:45> col:9 test5 '__make_integer_seq<A, int, N>':'__make_integer_seq<A, int, N>' // CHECK: `-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:103:3, col:45> col:9 test5 '__make_integer_seq<A, int, N>':'__make_integer_seq<A, int, N>'
// CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, int, N>' sugar dependent // CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, int, N>' sugar dependent
// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, int, N>' sugar dependent alias __make_integer_seq // CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, int, N>' sugar dependent alias __make_integer_seq
// CHECK-NEXT: |-TemplateArgument template A // CHECK-NEXT: |-TemplateArgument template A

View File

@ -11,14 +11,13 @@ using test1 = __type_pack_element<0, int>;
// CHECK-NEXT: | `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:35> 'int' 0 // CHECK-NEXT: | `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:35> 'int' 0
// CHECK-NEXT: |-TemplateArgument type 'int' // CHECK-NEXT: |-TemplateArgument type 'int'
// CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int' // CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
// CHECK-NEXT: `-SubstTemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'int' sugar pack_index 0 // CHECK-NEXT: `-SubstTemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'int' sugar typename depth 0 index 1 ... pack_index 0
// CHECK-NEXT: |-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'auto' dependent depth 0 index 1 // CHECK-NEXT: |-BuiltinTemplate 0x{{[0-9A-Fa-f]+}} '__type_pack_element'
// CHECK-NEXT: | `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} ''
// CHECK-NEXT: `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int' // CHECK-NEXT: `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
template<int N, class ...Ts> struct A { template<int N, class ...Ts> struct A {
using test2 = __type_pack_element<N, Ts...>; using test2 = __type_pack_element<N, Ts...>;
// CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:20:3, col:45> col:9 test2 '__type_pack_element<N, Ts...>':'__type_pack_element<N, type-parameter-0-1...>' // CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:19:3, col:45> col:9 test2 '__type_pack_element<N, Ts...>':'__type_pack_element<N, type-parameter-0-1...>'
// CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, Ts...>' sugar dependent // CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, Ts...>' sugar dependent
// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, Ts...>' sugar dependent alias __type_pack_element // CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, Ts...>' sugar dependent alias __type_pack_element
// CHECK-NEXT: |-TemplateArgument expr // CHECK-NEXT: |-TemplateArgument expr
@ -38,7 +37,7 @@ template<int N, class ...Ts> struct A {
// CHECK-NEXT: `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'type-parameter-0-1' dependent contains_unexpanded_pack depth 0 index 1 pack // CHECK-NEXT: `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'type-parameter-0-1' dependent contains_unexpanded_pack depth 0 index 1 pack
using test3 = __type_pack_element<0, Ts...>; using test3 = __type_pack_element<0, Ts...>;
// CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:40:3, col:45> col:9 test3 '__type_pack_element<0, Ts...>':'__type_pack_element<0, type-parameter-0-1...>' // CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:39:3, col:45> col:9 test3 '__type_pack_element<0, Ts...>':'__type_pack_element<0, type-parameter-0-1...>'
// CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<0, Ts...>' sugar dependent // CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<0, Ts...>' sugar dependent
// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<0, Ts...>' sugar dependent alias __type_pack_element // CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<0, Ts...>' sugar dependent alias __type_pack_element
// CHECK-NEXT: |-TemplateArgument expr // CHECK-NEXT: |-TemplateArgument expr
@ -58,7 +57,7 @@ template<int N, class ...Ts> struct A {
// CHECK-NEXT: `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'type-parameter-0-1' dependent contains_unexpanded_pack depth 0 index 1 pack // CHECK-NEXT: `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'type-parameter-0-1' dependent contains_unexpanded_pack depth 0 index 1 pack
using test4 = __type_pack_element<N, int>; using test4 = __type_pack_element<N, int>;
// CHECK: `-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:60:3, col:43> col:9 test4 '__type_pack_element<N, int>':'__type_pack_element<N, int>' // CHECK: `-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:59:3, col:43> col:9 test4 '__type_pack_element<N, int>':'__type_pack_element<N, int>'
// CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, int>' sugar dependent // CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, int>' sugar dependent
// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, int>' sugar dependent alias __type_pack_element // CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, int>' sugar dependent alias __type_pack_element
// CHECK-NEXT: |-TemplateArgument expr // CHECK-NEXT: |-TemplateArgument expr

View File

@ -1445,7 +1445,8 @@ clang::FunctionTemplateDecl *TypeSystemClang::CreateFunctionTemplateDecl(
func_tmpl_decl->setDeclContext(decl_ctx); func_tmpl_decl->setDeclContext(decl_ctx);
func_tmpl_decl->setLocation(func_decl->getLocation()); func_tmpl_decl->setLocation(func_decl->getLocation());
func_tmpl_decl->setDeclName(func_decl->getDeclName()); func_tmpl_decl->setDeclName(func_decl->getDeclName());
func_tmpl_decl->init(func_decl, template_param_list); func_tmpl_decl->setTemplateParameters(template_param_list);
func_tmpl_decl->init(func_decl);
SetOwningModule(func_tmpl_decl, owning_module); SetOwningModule(func_tmpl_decl, owning_module);
for (size_t i = 0, template_param_decl_count = template_param_decls.size(); for (size_t i = 0, template_param_decl_count = template_param_decls.size();
@ -1622,7 +1623,8 @@ ClassTemplateDecl *TypeSystemClang::CreateClassTemplateDecl(
// What decl context do we use here? TU? The actual decl context? // What decl context do we use here? TU? The actual decl context?
class_template_decl->setDeclContext(decl_ctx); class_template_decl->setDeclContext(decl_ctx);
class_template_decl->setDeclName(decl_name); class_template_decl->setDeclName(decl_name);
class_template_decl->init(template_cxx_decl, template_param_list); class_template_decl->setTemplateParameters(template_param_list);
class_template_decl->init(template_cxx_decl);
template_cxx_decl->setDescribedClassTemplate(class_template_decl); template_cxx_decl->setDescribedClassTemplate(class_template_decl);
SetOwningModule(class_template_decl, owning_module); SetOwningModule(class_template_decl, owning_module);