forked from OSchip/llvm-project
[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:
parent
0784de20e2
commit
bcd9ba2b7e
|
@ -52,7 +52,7 @@ void ExceptionBaseclassCheck::check(const MatchFinder::MatchResult &Result) {
|
|||
diag(BadThrow->getSubExpr()->getBeginLoc(),
|
||||
"type %0 is a template instantiation of %1", DiagnosticIDs::Note)
|
||||
<< BadThrow->getSubExpr()->getType()
|
||||
<< Template->getReplacedParameter()->getDecl();
|
||||
<< Template->getReplacedParameter();
|
||||
|
||||
if (const auto *TypeDecl = Result.Nodes.getNodeAs<NamedDecl>("decl"))
|
||||
diag(TypeDecl->getBeginLoc(), "type defined here", DiagnosticIDs::Note);
|
||||
|
|
|
@ -191,12 +191,12 @@ bool differentReplacedTemplateParams(const QualType &VarType,
|
|||
getSubstitutedType(VarType, Context)) {
|
||||
if (const SubstTemplateTypeParmType *InitializerTmplType =
|
||||
getSubstitutedType(InitializerType, Context)) {
|
||||
return VarTmplType->getReplacedParameter()
|
||||
->desugar()
|
||||
.getCanonicalType() !=
|
||||
InitializerTmplType->getReplacedParameter()
|
||||
->desugar()
|
||||
.getCanonicalType();
|
||||
const TemplateTypeParmDecl *VarTTP = VarTmplType->getReplacedParameter();
|
||||
const TemplateTypeParmDecl *InitTTP =
|
||||
InitializerTmplType->getReplacedParameter();
|
||||
return (VarTTP->getDepth() != InitTTP->getDepth() ||
|
||||
VarTTP->getIndex() != InitTTP->getIndex() ||
|
||||
VarTTP->isParameterPack() != InitTTP->isParameterPack());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -730,8 +730,8 @@ const TemplateTypeParmType *getUnderylingPackType(const ParmVarDecl *Param) {
|
|||
if (const auto *SubstType = dyn_cast<SubstTemplateTypeParmType>(PlainType)) {
|
||||
const auto *ReplacedParameter = SubstType->getReplacedParameter();
|
||||
if (ReplacedParameter->isParameterPack()) {
|
||||
return dyn_cast<TemplateTypeParmType>(
|
||||
ReplacedParameter->getCanonicalTypeUnqualified()->getTypePtr());
|
||||
return ReplacedParameter->getTypeForDecl()
|
||||
->castAs<TemplateTypeParmType>();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
|
|
|
@ -1617,11 +1617,11 @@ public:
|
|||
QualType getBTFTagAttributedType(const BTFTypeTagAttr *BTFAttr,
|
||||
QualType Wrapped);
|
||||
|
||||
QualType getSubstTemplateTypeParmType(const TemplateTypeParmType *Replaced,
|
||||
QualType Replacement,
|
||||
QualType getSubstTemplateTypeParmType(QualType Replacement,
|
||||
Decl *AssociatedDecl, unsigned Index,
|
||||
Optional<unsigned> PackIndex) const;
|
||||
QualType
|
||||
getSubstTemplateTypeParmPackType(const TemplateTypeParmType *Replaced,
|
||||
QualType getSubstTemplateTypeParmPackType(Decl *AssociatedDecl,
|
||||
unsigned Index,
|
||||
const TemplateArgument &ArgPack);
|
||||
|
||||
QualType
|
||||
|
@ -2202,10 +2202,13 @@ public:
|
|||
const IdentifierInfo *Name) const;
|
||||
TemplateName getDependentTemplateName(NestedNameSpecifier *NNS,
|
||||
OverloadedOperatorKind Operator) const;
|
||||
TemplateName getSubstTemplateTemplateParm(TemplateTemplateParmDecl *param,
|
||||
TemplateName replacement) const;
|
||||
TemplateName getSubstTemplateTemplateParmPack(TemplateTemplateParmDecl *Param,
|
||||
const TemplateArgument &ArgPack) const;
|
||||
TemplateName getSubstTemplateTemplateParm(TemplateName replacement,
|
||||
Decl *AssociatedDecl,
|
||||
unsigned Index,
|
||||
Optional<unsigned> PackIndex) const;
|
||||
TemplateName getSubstTemplateTemplateParmPack(const TemplateArgument &ArgPack,
|
||||
Decl *AssociatedDecl,
|
||||
unsigned Index) const;
|
||||
|
||||
enum GetBuiltinTypeError {
|
||||
/// No error
|
||||
|
|
|
@ -389,12 +389,9 @@ public:
|
|||
void VisitBTFTagAttributedType(const BTFTagAttributedType *T) {
|
||||
Visit(T->getWrappedType());
|
||||
}
|
||||
void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) {
|
||||
Visit(T->getReplacedParameter());
|
||||
}
|
||||
void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *) {}
|
||||
void
|
||||
VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T) {
|
||||
Visit(T->getReplacedParameter());
|
||||
Visit(T->getArgumentPack());
|
||||
}
|
||||
void VisitTemplateSpecializationType(const TemplateSpecializationType *T) {
|
||||
|
|
|
@ -459,18 +459,17 @@ protected:
|
|||
NamedDecl *TemplatedDecl;
|
||||
TemplateParameterList *TemplateParams;
|
||||
|
||||
public:
|
||||
void setTemplateParameters(TemplateParameterList *TParams) {
|
||||
TemplateParams = TParams;
|
||||
}
|
||||
|
||||
public:
|
||||
/// Initialize the underlying templated declaration and
|
||||
/// template parameters.
|
||||
void init(NamedDecl *templatedDecl, TemplateParameterList* templateParams) {
|
||||
assert(!TemplatedDecl && "TemplatedDecl already set!");
|
||||
assert(!TemplateParams && "TemplateParams already set!");
|
||||
TemplatedDecl = templatedDecl;
|
||||
TemplateParams = templateParams;
|
||||
/// Initialize the underlying templated declaration.
|
||||
void init(NamedDecl *NewTemplatedDecl) {
|
||||
if (TemplatedDecl)
|
||||
assert(TemplatedDecl == NewTemplatedDecl && "Inconsistent TemplatedDecl");
|
||||
else
|
||||
TemplatedDecl = NewTemplatedDecl;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -3425,6 +3424,10 @@ inline Optional<unsigned> getExpandedPackSize(const NamedDecl *Param) {
|
|||
return None;
|
||||
}
|
||||
|
||||
/// Internal helper used by Subst* nodes to retrieve the parameter list
|
||||
/// for their AssociatedDecl.
|
||||
TemplateParameterList *getReplacedTemplateParameterList(Decl *D);
|
||||
|
||||
} // namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_AST_DECLTEMPLATE_H
|
||||
|
|
|
@ -941,7 +941,7 @@ class AssumedTemplateStorage : public UncommonTemplateNameStorage {
|
|||
friend class ASTContext;
|
||||
|
||||
AssumedTemplateStorage(DeclarationName Name)
|
||||
: UncommonTemplateNameStorage(Assumed, 0), Name(Name) {}
|
||||
: UncommonTemplateNameStorage(Assumed, 0, 0), Name(Name) {}
|
||||
DeclarationName Name;
|
||||
|
||||
public:
|
||||
|
|
|
@ -4270,24 +4270,30 @@ class SubstNonTypeTemplateParmExpr : public Expr {
|
|||
friend class ASTReader;
|
||||
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.
|
||||
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)
|
||||
: Expr(SubstNonTypeTemplateParmExprClass, Empty) {}
|
||||
|
||||
public:
|
||||
SubstNonTypeTemplateParmExpr(QualType Ty, ExprValueKind ValueKind,
|
||||
SourceLocation Loc,
|
||||
NonTypeTemplateParmDecl *Param, bool RefParam,
|
||||
Expr *Replacement)
|
||||
SourceLocation Loc, Expr *Replacement,
|
||||
Decl *AssociatedDecl, unsigned Index,
|
||||
Optional<unsigned> PackIndex, bool RefParam)
|
||||
: 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;
|
||||
setDependence(computeDependence(this));
|
||||
}
|
||||
|
@ -4300,11 +4306,23 @@ public:
|
|||
|
||||
Expr *getReplacement() const { return cast<Expr>(Replacement); }
|
||||
|
||||
NonTypeTemplateParmDecl *getParameter() const {
|
||||
return ParamAndRef.getPointer();
|
||||
/// A template-like entity which owns the whole pattern being substituted.
|
||||
/// 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.
|
||||
QualType getParameterType(const ASTContext &Ctx) const;
|
||||
|
@ -4338,14 +4356,16 @@ class SubstNonTypeTemplateParmPackExpr : public Expr {
|
|||
friend class ASTStmtReader;
|
||||
|
||||
/// The non-type template parameter pack itself.
|
||||
NonTypeTemplateParmDecl *Param;
|
||||
Decl *AssociatedDecl;
|
||||
|
||||
/// A pointer to the set of template arguments that this
|
||||
/// parameter pack is instantiated with.
|
||||
const TemplateArgument *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.
|
||||
SourceLocation NameLoc;
|
||||
|
@ -4354,14 +4374,21 @@ class SubstNonTypeTemplateParmPackExpr : public Expr {
|
|||
: Expr(SubstNonTypeTemplateParmPackExprClass, Empty) {}
|
||||
|
||||
public:
|
||||
SubstNonTypeTemplateParmPackExpr(QualType T,
|
||||
ExprValueKind ValueKind,
|
||||
NonTypeTemplateParmDecl *Param,
|
||||
SubstNonTypeTemplateParmPackExpr(QualType T, ExprValueKind ValueKind,
|
||||
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.
|
||||
NonTypeTemplateParmDecl *getParameterPack() const { return Param; }
|
||||
NonTypeTemplateParmDecl *getParameterPack() const;
|
||||
|
||||
/// Retrieve the location of the parameter pack name.
|
||||
SourceLocation getParameterPackLocation() const { return NameLoc; }
|
||||
|
|
|
@ -222,6 +222,8 @@ public:
|
|||
void VisitTagType(const TagType *TT);
|
||||
void VisitTemplateTypeParmType(const TemplateTypeParmType *TTPT);
|
||||
void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *STTPT);
|
||||
void
|
||||
VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T);
|
||||
void VisitAutoType(const AutoType *AT);
|
||||
void VisitTemplateSpecializationType(const TemplateSpecializationType *TST);
|
||||
void VisitInjectedClassNameType(const InjectedClassNameType *ICNT);
|
||||
|
|
|
@ -701,28 +701,37 @@ let Class = PropertyTypeCase<TemplateName, "SubstTemplateTemplateParm"> in {
|
|||
def : ReadHelper<[{
|
||||
auto parm = node.getAsSubstTemplateTemplateParm();
|
||||
}]>;
|
||||
def : Property<"parameter", TemplateTemplateParmDeclRef> {
|
||||
let Read = [{ parm->getParameter() }];
|
||||
}
|
||||
def : Property<"replacement", TemplateName> {
|
||||
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<[{
|
||||
return ctx.getSubstTemplateTemplateParm(parameter, replacement);
|
||||
return ctx.getSubstTemplateTemplateParm(replacement, associatedDecl, index, packIndex);
|
||||
}]>;
|
||||
}
|
||||
let Class = PropertyTypeCase<TemplateName, "SubstTemplateTemplateParmPack"> in {
|
||||
def : ReadHelper<[{
|
||||
auto parm = node.getAsSubstTemplateTemplateParmPack();
|
||||
}]>;
|
||||
def : Property<"parameterPack", TemplateTemplateParmDeclRef> {
|
||||
let Read = [{ parm->getParameterPack() }];
|
||||
}
|
||||
def : Property<"argumentPack", TemplateArgument> {
|
||||
let Read = [{ parm->getArgumentPack() }];
|
||||
}
|
||||
def : Property<"associatedDecl", DeclRef> {
|
||||
let Read = [{ parm->getAssociatedDecl() }];
|
||||
}
|
||||
def : Property<"index", UInt32> {
|
||||
let Read = [{ parm->getIndex() }];
|
||||
}
|
||||
def : Creator<[{
|
||||
return ctx.getSubstTemplateTemplateParmPack(parameterPack, argumentPack);
|
||||
return ctx.getSubstTemplateTemplateParmPack(argumentPack, associatedDecl, index);
|
||||
}]>;
|
||||
}
|
||||
|
||||
|
|
|
@ -57,9 +57,12 @@ protected:
|
|||
/// A Kind.
|
||||
unsigned Kind : 2;
|
||||
|
||||
/// The number of stored templates or template arguments,
|
||||
/// depending on which subclass we have.
|
||||
unsigned Size : 30;
|
||||
// The template parameter index.
|
||||
unsigned Index : 15;
|
||||
|
||||
/// The pack index, or the number of stored templates
|
||||
/// or template arguments, depending on which subclass we have.
|
||||
unsigned Data : 15;
|
||||
};
|
||||
|
||||
union {
|
||||
|
@ -67,14 +70,13 @@ protected:
|
|||
void *PointerAlignment;
|
||||
};
|
||||
|
||||
UncommonTemplateNameStorage(Kind kind, unsigned size) {
|
||||
Bits.Kind = kind;
|
||||
Bits.Size = size;
|
||||
UncommonTemplateNameStorage(Kind Kind, unsigned Index, unsigned Data) {
|
||||
Bits.Kind = Kind;
|
||||
Bits.Index = Index;
|
||||
Bits.Data = Data;
|
||||
}
|
||||
|
||||
public:
|
||||
unsigned size() const { return Bits.Size; }
|
||||
|
||||
OverloadedTemplateStorage *getAsOverloadedStorage() {
|
||||
return Bits.Kind == Overloaded
|
||||
? reinterpret_cast<OverloadedTemplateStorage *>(this)
|
||||
|
@ -106,7 +108,7 @@ class OverloadedTemplateStorage : public UncommonTemplateNameStorage {
|
|||
friend class ASTContext;
|
||||
|
||||
OverloadedTemplateStorage(unsigned size)
|
||||
: UncommonTemplateNameStorage(Overloaded, size) {}
|
||||
: UncommonTemplateNameStorage(Overloaded, 0, size) {}
|
||||
|
||||
NamedDecl **getStorage() {
|
||||
return reinterpret_cast<NamedDecl **>(this + 1);
|
||||
|
@ -116,10 +118,12 @@ class OverloadedTemplateStorage : public UncommonTemplateNameStorage {
|
|||
}
|
||||
|
||||
public:
|
||||
unsigned size() const { return Bits.Data; }
|
||||
|
||||
using iterator = NamedDecl *const *;
|
||||
|
||||
iterator begin() const { return getStorage(); }
|
||||
iterator end() const { return getStorage() + size(); }
|
||||
iterator end() const { return getStorage() + Bits.Data; }
|
||||
|
||||
llvm::ArrayRef<NamedDecl*> decls() const {
|
||||
return llvm::makeArrayRef(begin(), end());
|
||||
|
@ -132,23 +136,30 @@ public:
|
|||
/// This kind of template names occurs when the parameter pack has been
|
||||
/// provided with a template template argument pack in a context where its
|
||||
/// enclosing pack expansion could not be fully expanded.
|
||||
class SubstTemplateTemplateParmPackStorage
|
||||
: public UncommonTemplateNameStorage, public llvm::FoldingSetNode
|
||||
{
|
||||
TemplateTemplateParmDecl *Parameter;
|
||||
class SubstTemplateTemplateParmPackStorage : public UncommonTemplateNameStorage,
|
||||
public llvm::FoldingSetNode {
|
||||
const TemplateArgument *Arguments;
|
||||
Decl *AssociatedDecl;
|
||||
|
||||
public:
|
||||
SubstTemplateTemplateParmPackStorage(TemplateTemplateParmDecl *Parameter,
|
||||
unsigned Size,
|
||||
const TemplateArgument *Arguments)
|
||||
: UncommonTemplateNameStorage(SubstTemplateTemplateParmPack, Size),
|
||||
Parameter(Parameter), Arguments(Arguments) {}
|
||||
SubstTemplateTemplateParmPackStorage(ArrayRef<TemplateArgument> ArgPack,
|
||||
Decl *AssociatedDecl, unsigned Index)
|
||||
: UncommonTemplateNameStorage(SubstTemplateTemplateParmPack, Index,
|
||||
ArgPack.size()),
|
||||
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.
|
||||
TemplateTemplateParmDecl *getParameterPack() const {
|
||||
return Parameter;
|
||||
}
|
||||
TemplateTemplateParmDecl *getParameterPack() const;
|
||||
|
||||
/// Retrieve the template template argument pack with which this
|
||||
/// parameter was substituted.
|
||||
|
@ -156,10 +167,9 @@ public:
|
|||
|
||||
void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context);
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID &ID,
|
||||
ASTContext &Context,
|
||||
TemplateTemplateParmDecl *Parameter,
|
||||
const TemplateArgument &ArgPack);
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context,
|
||||
const TemplateArgument &ArgPack, Decl *AssociatedDecl,
|
||||
unsigned Index);
|
||||
};
|
||||
|
||||
/// Represents a C++ template name within the type system.
|
||||
|
@ -365,23 +375,41 @@ class SubstTemplateTemplateParmStorage
|
|||
: public UncommonTemplateNameStorage, public llvm::FoldingSetNode {
|
||||
friend class ASTContext;
|
||||
|
||||
TemplateTemplateParmDecl *Parameter;
|
||||
TemplateName Replacement;
|
||||
Decl *AssociatedDecl;
|
||||
|
||||
SubstTemplateTemplateParmStorage(TemplateTemplateParmDecl *parameter,
|
||||
TemplateName replacement)
|
||||
: UncommonTemplateNameStorage(SubstTemplateTemplateParm, 0),
|
||||
Parameter(parameter), Replacement(replacement) {}
|
||||
SubstTemplateTemplateParmStorage(TemplateName Replacement,
|
||||
Decl *AssociatedDecl, unsigned Index,
|
||||
Optional<unsigned> PackIndex)
|
||||
: UncommonTemplateNameStorage(SubstTemplateTemplateParm, Index,
|
||||
PackIndex ? *PackIndex + 1 : 0),
|
||||
Replacement(Replacement), AssociatedDecl(AssociatedDecl) {
|
||||
assert(AssociatedDecl != nullptr);
|
||||
}
|
||||
|
||||
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; }
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID);
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID &ID,
|
||||
TemplateTemplateParmDecl *parameter,
|
||||
TemplateName replacement);
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, TemplateName Replacement,
|
||||
Decl *AssociatedDecl, unsigned Index,
|
||||
Optional<unsigned> PackIndex);
|
||||
};
|
||||
|
||||
inline TemplateName TemplateName::getUnderlying() const {
|
||||
|
|
|
@ -318,6 +318,8 @@ public:
|
|||
void VisitTagType(const TagType *T);
|
||||
void VisitTemplateTypeParmType(const TemplateTypeParmType *T);
|
||||
void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T);
|
||||
void
|
||||
VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T);
|
||||
void VisitAutoType(const AutoType *T);
|
||||
void VisitDeducedTemplateSpecializationType(
|
||||
const DeducedTemplateSpecializationType *T);
|
||||
|
|
|
@ -1832,6 +1832,9 @@ protected:
|
|||
|
||||
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
|
||||
/// from a pack expansion. This index starts at the end of the pack and
|
||||
/// increments towards the beginning.
|
||||
|
@ -1845,14 +1848,14 @@ protected:
|
|||
|
||||
unsigned : NumTypeBits;
|
||||
|
||||
// The index of the template parameter this substitution represents.
|
||||
unsigned Index : 16;
|
||||
|
||||
/// The number of template arguments in \c Arguments, which is
|
||||
/// expected to be able to hold at least 1024 according to [implimits].
|
||||
/// However as this limit is somewhat easy to hit with template
|
||||
/// 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
|
||||
/// safely fits in 64 bits as an unsigned, so there is no reason to
|
||||
/// introduce the performance impact of a bitfield.
|
||||
unsigned NumArgs;
|
||||
unsigned NumArgs : 16;
|
||||
};
|
||||
|
||||
class TemplateSpecializationTypeBitfields {
|
||||
|
@ -5083,18 +5086,12 @@ class SubstTemplateTypeParmType final
|
|||
friend class ASTContext;
|
||||
friend class llvm::TrailingObjects<SubstTemplateTypeParmType, QualType>;
|
||||
|
||||
// The original type parameter.
|
||||
const TemplateTypeParmType *Replaced;
|
||||
Decl *AssociatedDecl;
|
||||
|
||||
SubstTemplateTypeParmType(const TemplateTypeParmType *Param, QualType Canon,
|
||||
Optional<unsigned> PackIndex);
|
||||
SubstTemplateTypeParmType(QualType Replacement, Decl *AssociatedDecl,
|
||||
unsigned Index, Optional<unsigned> PackIndex);
|
||||
|
||||
public:
|
||||
/// Gets the template parameter that was substituted for.
|
||||
const TemplateTypeParmType *getReplacedParameter() const {
|
||||
return Replaced;
|
||||
}
|
||||
|
||||
/// Gets the type that was substituted for the template
|
||||
/// parameter.
|
||||
QualType getReplacementType() const {
|
||||
|
@ -5103,6 +5100,18 @@ public:
|
|||
: 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 {
|
||||
if (SubstTemplateTypeParmTypeBits.PackIndex == 0)
|
||||
return None;
|
||||
|
@ -5113,14 +5122,16 @@ public:
|
|||
QualType desugar() const { return getReplacementType(); }
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
Profile(ID, getReplacedParameter(), getReplacementType(), getPackIndex());
|
||||
Profile(ID, getReplacementType(), getAssociatedDecl(), getIndex(),
|
||||
getPackIndex());
|
||||
}
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID &ID,
|
||||
const TemplateTypeParmType *Replaced,
|
||||
QualType Replacement, Optional<unsigned> PackIndex) {
|
||||
ID.AddPointer(Replaced);
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, QualType Replacement,
|
||||
const Decl *AssociatedDecl, unsigned Index,
|
||||
Optional<unsigned> PackIndex) {
|
||||
Replacement.Profile(ID);
|
||||
ID.AddPointer(AssociatedDecl);
|
||||
ID.AddInteger(Index);
|
||||
ID.AddInteger(PackIndex ? *PackIndex - 1 : 0);
|
||||
}
|
||||
|
||||
|
@ -5144,24 +5155,30 @@ public:
|
|||
class SubstTemplateTypeParmPackType : public Type, public llvm::FoldingSetNode {
|
||||
friend class ASTContext;
|
||||
|
||||
/// The original type parameter.
|
||||
const TemplateTypeParmType *Replaced;
|
||||
|
||||
/// A pointer to the set of template arguments that this
|
||||
/// parameter pack is instantiated with.
|
||||
const TemplateArgument *Arguments;
|
||||
|
||||
SubstTemplateTypeParmPackType(const TemplateTypeParmType *Param,
|
||||
QualType Canon,
|
||||
Decl *AssociatedDecl;
|
||||
|
||||
SubstTemplateTypeParmPackType(QualType Canon, Decl *AssociatedDecl,
|
||||
unsigned Index,
|
||||
const TemplateArgument &ArgPack);
|
||||
|
||||
public:
|
||||
IdentifierInfo *getIdentifier() const { return Replaced->getIdentifier(); }
|
||||
IdentifierInfo *getIdentifier() const;
|
||||
|
||||
/// Gets the template parameter that was substituted for.
|
||||
const TemplateTypeParmType *getReplacedParameter() const {
|
||||
return Replaced;
|
||||
}
|
||||
/// 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 SubstTemplateTypeParmPackTypeBits.Index; }
|
||||
|
||||
unsigned getNumArgs() const {
|
||||
return SubstTemplateTypeParmPackTypeBits.NumArgs;
|
||||
|
@ -5173,9 +5190,8 @@ public:
|
|||
TemplateArgument getArgumentPack() const;
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID);
|
||||
static void Profile(llvm::FoldingSetNodeID &ID,
|
||||
const TemplateTypeParmType *Replaced,
|
||||
const TemplateArgument &ArgPack);
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, const Decl *AssociatedDecl,
|
||||
unsigned Index, const TemplateArgument &ArgPack);
|
||||
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() == SubstTemplateTypeParmPack;
|
||||
|
|
|
@ -732,20 +732,23 @@ let Class = TemplateTypeParmType in {
|
|||
}
|
||||
|
||||
let Class = SubstTemplateTypeParmType in {
|
||||
def : Property<"replacedParameter", QualType> {
|
||||
let Read = [{ QualType(node->getReplacedParameter(), 0) }];
|
||||
}
|
||||
def : Property<"replacementType", QualType> {
|
||||
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>> {
|
||||
let Read = [{ node->getPackIndex() }];
|
||||
}
|
||||
|
||||
// The call to getCanonicalType here existed in ASTReader.cpp, too.
|
||||
def : Creator<[{
|
||||
return ctx.getSubstTemplateTypeParmType(
|
||||
cast<TemplateTypeParmType>(replacedParameter),
|
||||
replacementType, PackIndex);
|
||||
replacementType, associatedDecl, Index, PackIndex);
|
||||
}]>;
|
||||
}
|
||||
|
||||
|
@ -764,8 +767,11 @@ let Class = PackExpansionType in {
|
|||
}
|
||||
|
||||
let Class = SubstTemplateTypeParmPackType in {
|
||||
def : Property<"replacedParameter", QualType> {
|
||||
let Read = [{ QualType(node->getReplacedParameter(), 0) }];
|
||||
def : Property<"associatedDecl", DeclRef> {
|
||||
let Read = [{ node->getAssociatedDecl() }];
|
||||
}
|
||||
def : Property<"Index", UInt32> {
|
||||
let Read = [{ node->getIndex() }];
|
||||
}
|
||||
def : Property<"replacementPack", TemplateArgument> {
|
||||
let Read = [{ node->getArgumentPack() }];
|
||||
|
@ -773,8 +779,7 @@ let Class = SubstTemplateTypeParmPackType in {
|
|||
|
||||
def : Creator<[{
|
||||
return ctx.getSubstTemplateTypeParmPackType(
|
||||
cast<TemplateTypeParmType>(replacedParameter),
|
||||
replacementPack);
|
||||
associatedDecl, Index, replacementPack);
|
||||
}]>;
|
||||
}
|
||||
|
||||
|
|
|
@ -74,13 +74,20 @@ enum class TemplateSubstitutionKind : char {
|
|||
/// template argument list (17) at depth 1.
|
||||
class MultiLevelTemplateArgumentList {
|
||||
/// The template argument list at a certain template depth
|
||||
|
||||
using ArgList = ArrayRef<TemplateArgument>;
|
||||
using ArgListsIterator = SmallVector<ArgList, 4>::iterator;
|
||||
using ConstArgListsIterator = SmallVector<ArgList, 4>::const_iterator;
|
||||
struct ArgumentListLevel {
|
||||
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
|
||||
/// 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
|
||||
/// being substituted.
|
||||
|
@ -94,9 +101,8 @@ enum class TemplateSubstitutionKind : char {
|
|||
MultiLevelTemplateArgumentList() = default;
|
||||
|
||||
/// Construct a single-level template argument list.
|
||||
explicit
|
||||
MultiLevelTemplateArgumentList(const TemplateArgumentList &TemplateArgs) {
|
||||
addOuterTemplateArguments(&TemplateArgs);
|
||||
MultiLevelTemplateArgumentList(Decl *D, ArgList Args) {
|
||||
addOuterTemplateArguments(D, Args);
|
||||
}
|
||||
|
||||
void setKind(TemplateSubstitutionKind K) { Kind = K; }
|
||||
|
@ -126,7 +132,7 @@ enum class TemplateSubstitutionKind : char {
|
|||
// Determine the number of substituted args at 'Depth'.
|
||||
unsigned getNumSubsitutedArgs(unsigned Depth) const {
|
||||
assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
|
||||
return TemplateArgumentLists[getNumLevels() - Depth - 1].size();
|
||||
return TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size();
|
||||
}
|
||||
|
||||
unsigned getNumRetainedOuterLevels() const {
|
||||
|
@ -146,8 +152,17 @@ enum class TemplateSubstitutionKind : char {
|
|||
/// Retrieve the template argument at a given depth and index.
|
||||
const TemplateArgument &operator()(unsigned Depth, unsigned Index) const {
|
||||
assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
|
||||
assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1].size());
|
||||
return TemplateArgumentLists[getNumLevels() - Depth - 1][Index];
|
||||
assert(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
|
||||
|
@ -160,15 +175,16 @@ enum class TemplateSubstitutionKind : char {
|
|||
if (Depth < NumRetainedOuterLevels)
|
||||
return false;
|
||||
|
||||
if (Index >= TemplateArgumentLists[getNumLevels() - Depth - 1].size())
|
||||
if (Index >=
|
||||
TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size())
|
||||
return false;
|
||||
|
||||
return !(*this)(Depth, Index).isNull();
|
||||
}
|
||||
|
||||
bool isAnyArgInstantiationDependent() const {
|
||||
for (ArgList List : TemplateArgumentLists)
|
||||
for (const TemplateArgument &TA : List)
|
||||
for (ArgumentListLevel ListLevel : TemplateArgumentLists)
|
||||
for (const TemplateArgument &TA : ListLevel.Args)
|
||||
if (TA.isInstantiationDependent())
|
||||
return true;
|
||||
return false;
|
||||
|
@ -178,25 +194,35 @@ enum class TemplateSubstitutionKind : char {
|
|||
void setArgument(unsigned Depth, unsigned Index,
|
||||
TemplateArgument Arg) {
|
||||
assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
|
||||
assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1].size());
|
||||
const_cast<TemplateArgument&>(
|
||||
TemplateArgumentLists[getNumLevels() - Depth - 1][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()));
|
||||
assert(Index <
|
||||
TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size());
|
||||
const_cast<TemplateArgument &>(
|
||||
TemplateArgumentLists[getNumLevels() - Depth - 1].Args[Index]) = Arg;
|
||||
}
|
||||
|
||||
/// Add a new outmost level to the multi-level template argument
|
||||
/// 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) {
|
||||
assert(!NumRetainedOuterLevels &&
|
||||
"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.
|
||||
|
@ -204,7 +230,7 @@ enum class TemplateSubstitutionKind : char {
|
|||
/// list from the AST, but then add the deduced innermost list.
|
||||
void replaceInnermostTemplateArguments(ArgList Args) {
|
||||
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
|
||||
|
@ -219,11 +245,11 @@ enum class TemplateSubstitutionKind : char {
|
|||
|
||||
/// Retrieve the innermost template argument list.
|
||||
const ArgList &getInnermost() const {
|
||||
return TemplateArgumentLists.front();
|
||||
return TemplateArgumentLists.front().Args;
|
||||
}
|
||||
/// Retrieve the outermost template argument list.
|
||||
const ArgList &getOutermost() const {
|
||||
return TemplateArgumentLists.back();
|
||||
return TemplateArgumentLists.back().Args;
|
||||
}
|
||||
ArgListsIterator begin() { return TemplateArgumentLists.begin(); }
|
||||
ConstArgListsIterator begin() const {
|
||||
|
|
|
@ -4785,21 +4785,22 @@ QualType ASTContext::getBTFTagAttributedType(const BTFTypeTagAttr *BTFAttr,
|
|||
|
||||
/// Retrieve a substitution-result type.
|
||||
QualType
|
||||
ASTContext::getSubstTemplateTypeParmType(const TemplateTypeParmType *Parm,
|
||||
QualType Replacement,
|
||||
ASTContext::getSubstTemplateTypeParmType(QualType Replacement,
|
||||
Decl *AssociatedDecl, unsigned Index,
|
||||
Optional<unsigned> PackIndex) const {
|
||||
llvm::FoldingSetNodeID ID;
|
||||
SubstTemplateTypeParmType::Profile(ID, Parm, Replacement, PackIndex);
|
||||
SubstTemplateTypeParmType::Profile(ID, Replacement, AssociatedDecl, Index,
|
||||
PackIndex);
|
||||
void *InsertPos = nullptr;
|
||||
SubstTemplateTypeParmType *SubstParm
|
||||
= SubstTemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos);
|
||||
SubstTemplateTypeParmType *SubstParm =
|
||||
SubstTemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos);
|
||||
|
||||
if (!SubstParm) {
|
||||
void *Mem = Allocate(SubstTemplateTypeParmType::totalSizeToAlloc<QualType>(
|
||||
!Replacement.isCanonical()),
|
||||
TypeAlignment);
|
||||
SubstParm =
|
||||
new (Mem) SubstTemplateTypeParmType(Parm, Replacement, PackIndex);
|
||||
SubstParm = new (Mem) SubstTemplateTypeParmType(Replacement, AssociatedDecl,
|
||||
Index, PackIndex);
|
||||
Types.push_back(SubstParm);
|
||||
SubstTemplateTypeParmTypes.InsertNode(SubstParm, InsertPos);
|
||||
}
|
||||
|
@ -4809,33 +4810,30 @@ ASTContext::getSubstTemplateTypeParmType(const TemplateTypeParmType *Parm,
|
|||
|
||||
/// Retrieve a
|
||||
QualType ASTContext::getSubstTemplateTypeParmPackType(
|
||||
const TemplateTypeParmType *Parm,
|
||||
const TemplateArgument &ArgPack) {
|
||||
Decl *AssociatedDecl, unsigned Index, const TemplateArgument &ArgPack) {
|
||||
#ifndef NDEBUG
|
||||
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");
|
||||
}
|
||||
#endif
|
||||
|
||||
llvm::FoldingSetNodeID ID;
|
||||
SubstTemplateTypeParmPackType::Profile(ID, Parm, ArgPack);
|
||||
SubstTemplateTypeParmPackType::Profile(ID, AssociatedDecl, Index, ArgPack);
|
||||
void *InsertPos = nullptr;
|
||||
if (SubstTemplateTypeParmPackType *SubstParm
|
||||
= SubstTemplateTypeParmPackTypes.FindNodeOrInsertPos(ID, InsertPos))
|
||||
if (SubstTemplateTypeParmPackType *SubstParm =
|
||||
SubstTemplateTypeParmPackTypes.FindNodeOrInsertPos(ID, InsertPos))
|
||||
return QualType(SubstParm, 0);
|
||||
|
||||
QualType Canon;
|
||||
if (!Parm->isCanonicalUnqualified()) {
|
||||
Canon = getCanonicalType(QualType(Parm, 0));
|
||||
Canon = getSubstTemplateTypeParmPackType(cast<TemplateTypeParmType>(Canon),
|
||||
ArgPack);
|
||||
if (!AssociatedDecl->isCanonicalDecl()) {
|
||||
Canon = getSubstTemplateTypeParmPackType(AssociatedDecl->getCanonicalDecl(),
|
||||
Index, ArgPack);
|
||||
SubstTemplateTypeParmPackTypes.FindNodeOrInsertPos(ID, InsertPos);
|
||||
}
|
||||
|
||||
auto *SubstParm
|
||||
= new (*this, TypeAlignment) SubstTemplateTypeParmPackType(Parm, Canon,
|
||||
ArgPack);
|
||||
auto *SubstParm = new (*this, TypeAlignment)
|
||||
SubstTemplateTypeParmPackType(Canon, AssociatedDecl, Index, ArgPack);
|
||||
Types.push_back(SubstParm);
|
||||
SubstTemplateTypeParmPackTypes.InsertNode(SubstParm, InsertPos);
|
||||
return QualType(SubstParm, 0);
|
||||
|
@ -6241,13 +6239,13 @@ ASTContext::getCanonicalTemplateName(const TemplateName &Name) const {
|
|||
}
|
||||
|
||||
case TemplateName::SubstTemplateTemplateParmPack: {
|
||||
SubstTemplateTemplateParmPackStorage *subst
|
||||
= Name.getAsSubstTemplateTemplateParmPack();
|
||||
TemplateTemplateParmDecl *canonParameter
|
||||
= getCanonicalTemplateTemplateParmDecl(subst->getParameterPack());
|
||||
TemplateArgument canonArgPack
|
||||
= getCanonicalTemplateArgument(subst->getArgumentPack());
|
||||
return getSubstTemplateTemplateParmPack(canonParameter, canonArgPack);
|
||||
SubstTemplateTemplateParmPackStorage *subst =
|
||||
Name.getAsSubstTemplateTemplateParmPack();
|
||||
TemplateArgument canonArgPack =
|
||||
getCanonicalTemplateArgument(subst->getArgumentPack());
|
||||
return getSubstTemplateTemplateParmPack(
|
||||
canonArgPack, subst->getAssociatedDecl()->getCanonicalDecl(),
|
||||
subst->getIndex());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9250,17 +9248,20 @@ ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS,
|
|||
}
|
||||
|
||||
TemplateName
|
||||
ASTContext::getSubstTemplateTemplateParm(TemplateTemplateParmDecl *param,
|
||||
TemplateName replacement) const {
|
||||
ASTContext::getSubstTemplateTemplateParm(TemplateName Replacement,
|
||||
Decl *AssociatedDecl, unsigned Index,
|
||||
Optional<unsigned> PackIndex) const {
|
||||
llvm::FoldingSetNodeID ID;
|
||||
SubstTemplateTemplateParmStorage::Profile(ID, param, replacement);
|
||||
SubstTemplateTemplateParmStorage::Profile(ID, Replacement, AssociatedDecl,
|
||||
Index, PackIndex);
|
||||
|
||||
void *insertPos = nullptr;
|
||||
SubstTemplateTemplateParmStorage *subst
|
||||
= SubstTemplateTemplateParms.FindNodeOrInsertPos(ID, insertPos);
|
||||
|
||||
if (!subst) {
|
||||
subst = new (*this) SubstTemplateTemplateParmStorage(param, replacement);
|
||||
subst = new (*this) SubstTemplateTemplateParmStorage(
|
||||
Replacement, AssociatedDecl, Index, PackIndex);
|
||||
SubstTemplateTemplateParms.InsertNode(subst, insertPos);
|
||||
}
|
||||
|
||||
|
@ -9268,20 +9269,21 @@ ASTContext::getSubstTemplateTemplateParm(TemplateTemplateParmDecl *param,
|
|||
}
|
||||
|
||||
TemplateName
|
||||
ASTContext::getSubstTemplateTemplateParmPack(TemplateTemplateParmDecl *Param,
|
||||
const TemplateArgument &ArgPack) const {
|
||||
ASTContext::getSubstTemplateTemplateParmPack(const TemplateArgument &ArgPack,
|
||||
Decl *AssociatedDecl,
|
||||
unsigned Index) const {
|
||||
auto &Self = const_cast<ASTContext &>(*this);
|
||||
llvm::FoldingSetNodeID ID;
|
||||
SubstTemplateTemplateParmPackStorage::Profile(ID, Self, Param, ArgPack);
|
||||
SubstTemplateTemplateParmPackStorage::Profile(ID, Self, ArgPack,
|
||||
AssociatedDecl, Index);
|
||||
|
||||
void *InsertPos = nullptr;
|
||||
SubstTemplateTemplateParmPackStorage *Subst
|
||||
= SubstTemplateTemplateParmPacks.FindNodeOrInsertPos(ID, InsertPos);
|
||||
|
||||
if (!Subst) {
|
||||
Subst = new (*this) SubstTemplateTemplateParmPackStorage(Param,
|
||||
ArgPack.pack_size(),
|
||||
ArgPack.pack_begin());
|
||||
Subst = new (*this) SubstTemplateTemplateParmPackStorage(
|
||||
ArgPack.pack_elements(), AssociatedDecl, Index);
|
||||
SubstTemplateTemplateParmPacks.InsertNode(Subst, InsertPos);
|
||||
}
|
||||
|
||||
|
@ -12931,14 +12933,18 @@ static QualType getCommonSugarTypeNode(ASTContext &Ctx, const Type *X,
|
|||
case Type::SubstTemplateTypeParm: {
|
||||
const auto *SX = cast<SubstTemplateTypeParmType>(X),
|
||||
*SY = cast<SubstTemplateTypeParmType>(Y);
|
||||
const TemplateTypeParmType *PX = SX->getReplacedParameter();
|
||||
if (PX != SY->getReplacedParameter())
|
||||
Decl *CD =
|
||||
::getCommonDecl(SX->getAssociatedDecl(), SY->getAssociatedDecl());
|
||||
if (!CD)
|
||||
return QualType();
|
||||
unsigned Index = SX->getIndex();
|
||||
if (Index != SY->getIndex())
|
||||
return QualType();
|
||||
auto PackIndex = SX->getPackIndex();
|
||||
if (PackIndex != SY->getPackIndex())
|
||||
return QualType();
|
||||
return Ctx.getSubstTemplateTypeParmType(
|
||||
PX, Ctx.getQualifiedType(Underlying), PackIndex);
|
||||
return Ctx.getSubstTemplateTypeParmType(Ctx.getQualifiedType(Underlying),
|
||||
CD, Index, PackIndex);
|
||||
}
|
||||
case Type::ObjCTypeParam:
|
||||
// FIXME: Try to merge these.
|
||||
|
|
|
@ -1523,8 +1523,7 @@ ExpectedType ASTNodeImporter::VisitTemplateTypeParmType(
|
|||
|
||||
ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmType(
|
||||
const SubstTemplateTypeParmType *T) {
|
||||
Expected<const TemplateTypeParmType *> ReplacedOrErr =
|
||||
import(T->getReplacedParameter());
|
||||
Expected<Decl *> ReplacedOrErr = import(T->getAssociatedDecl());
|
||||
if (!ReplacedOrErr)
|
||||
return ReplacedOrErr.takeError();
|
||||
|
||||
|
@ -1533,13 +1532,13 @@ ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmType(
|
|||
return ToReplacementTypeOrErr.takeError();
|
||||
|
||||
return Importer.getToContext().getSubstTemplateTypeParmType(
|
||||
*ReplacedOrErr, *ToReplacementTypeOrErr, T->getPackIndex());
|
||||
*ToReplacementTypeOrErr, *ReplacedOrErr, T->getIndex(),
|
||||
T->getPackIndex());
|
||||
}
|
||||
|
||||
ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmPackType(
|
||||
const SubstTemplateTypeParmPackType *T) {
|
||||
Expected<const TemplateTypeParmType *> ReplacedOrErr =
|
||||
import(T->getReplacedParameter());
|
||||
Expected<Decl *> ReplacedOrErr = import(T->getAssociatedDecl());
|
||||
if (!ReplacedOrErr)
|
||||
return ReplacedOrErr.takeError();
|
||||
|
||||
|
@ -1548,7 +1547,7 @@ ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmPackType(
|
|||
return ToArgumentPack.takeError();
|
||||
|
||||
return Importer.getToContext().getSubstTemplateTypeParmPackType(
|
||||
*ReplacedOrErr, *ToArgumentPack);
|
||||
*ReplacedOrErr, T->getIndex(), *ToArgumentPack);
|
||||
}
|
||||
|
||||
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()) {
|
||||
Error Err = ImportFunctionDeclBody(D, ToFunction);
|
||||
|
||||
|
@ -3774,10 +3777,6 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
|
|||
|
||||
// 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);
|
||||
|
||||
if (auto *FromCXXMethod = dyn_cast<CXXMethodDecl>(D))
|
||||
|
@ -5998,6 +5997,30 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl(
|
|||
|
||||
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 (Error Err = ImportDefinition(D, D2))
|
||||
return std::move(Err);
|
||||
|
@ -6161,15 +6184,6 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl(
|
|||
}
|
||||
}
|
||||
} 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;
|
||||
if (const ASTTemplateArgumentListInfo *Args = D->getTemplateArgsInfo()) {
|
||||
if (Error Err = ImportTemplateArgumentListInfo(*Args, ToTAInfo))
|
||||
|
@ -6194,7 +6208,7 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl(
|
|||
PartVarSpecDecl *ToPartial;
|
||||
if (GetImportedOrCreateDecl(ToPartial, D, Importer.getToContext(), DC,
|
||||
*BeginLocOrErr, *IdLocOrErr, *ToTPListOrErr,
|
||||
VarTemplate, T, *TInfoOrErr,
|
||||
VarTemplate, QualType(), nullptr,
|
||||
D->getStorageClass(), TemplateArgs, ArgInfos))
|
||||
return ToPartial;
|
||||
|
||||
|
@ -6215,11 +6229,21 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl(
|
|||
} else { // Full specialization
|
||||
if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), DC,
|
||||
*BeginLocOrErr, *IdLocOrErr, VarTemplate,
|
||||
T, *TInfoOrErr,
|
||||
D->getStorageClass(), TemplateArgs))
|
||||
QualType(), nullptr, D->getStorageClass(),
|
||||
TemplateArgs))
|
||||
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 (ExpectedSLoc POIOrErr = import(D->getPointOfInstantiation()))
|
||||
D2->setPointOfInstantiation(*POIOrErr);
|
||||
|
@ -8412,14 +8436,14 @@ ExpectedStmt ASTNodeImporter::VisitSubstNonTypeTemplateParmExpr(
|
|||
Error Err = Error::success();
|
||||
auto ToType = importChecked(Err, E->getType());
|
||||
auto ToExprLoc = importChecked(Err, E->getExprLoc());
|
||||
auto ToParameter = importChecked(Err, E->getParameter());
|
||||
auto ToAssociatedDecl = importChecked(Err, E->getAssociatedDecl());
|
||||
auto ToReplacement = importChecked(Err, E->getReplacement());
|
||||
if (Err)
|
||||
return std::move(Err);
|
||||
|
||||
return new (Importer.getToContext()) SubstNonTypeTemplateParmExpr(
|
||||
ToType, E->getValueKind(), ToExprLoc, ToParameter,
|
||||
E->isReferenceParameter(), ToReplacement);
|
||||
ToType, E->getValueKind(), ToExprLoc, ToReplacement, ToAssociatedDecl,
|
||||
E->getIndex(), E->getPackIndex(), E->isReferenceParameter());
|
||||
}
|
||||
|
||||
ExpectedStmt ASTNodeImporter::VisitTypeTraitExpr(TypeTraitExpr *E) {
|
||||
|
@ -9396,33 +9420,34 @@ Expected<TemplateName> ASTImporter::Import(TemplateName From) {
|
|||
case TemplateName::SubstTemplateTemplateParm: {
|
||||
SubstTemplateTemplateParmStorage *Subst =
|
||||
From.getAsSubstTemplateTemplateParm();
|
||||
ExpectedDecl ParamOrErr = Import(Subst->getParameter());
|
||||
if (!ParamOrErr)
|
||||
return ParamOrErr.takeError();
|
||||
|
||||
auto ReplacementOrErr = Import(Subst->getReplacement());
|
||||
if (!ReplacementOrErr)
|
||||
return ReplacementOrErr.takeError();
|
||||
|
||||
auto AssociatedDeclOrErr = Import(Subst->getAssociatedDecl());
|
||||
if (!AssociatedDeclOrErr)
|
||||
return AssociatedDeclOrErr.takeError();
|
||||
|
||||
return ToContext.getSubstTemplateTemplateParm(
|
||||
cast<TemplateTemplateParmDecl>(*ParamOrErr), *ReplacementOrErr);
|
||||
*ReplacementOrErr, *AssociatedDeclOrErr, Subst->getIndex(),
|
||||
Subst->getPackIndex());
|
||||
}
|
||||
|
||||
case TemplateName::SubstTemplateTemplateParmPack: {
|
||||
SubstTemplateTemplateParmPackStorage *SubstPack
|
||||
= From.getAsSubstTemplateTemplateParmPack();
|
||||
ExpectedDecl ParamOrErr = Import(SubstPack->getParameterPack());
|
||||
if (!ParamOrErr)
|
||||
return ParamOrErr.takeError();
|
||||
|
||||
SubstTemplateTemplateParmPackStorage *SubstPack =
|
||||
From.getAsSubstTemplateTemplateParmPack();
|
||||
ASTNodeImporter Importer(*this);
|
||||
auto ArgPackOrErr =
|
||||
Importer.ImportTemplateArgument(SubstPack->getArgumentPack());
|
||||
if (!ArgPackOrErr)
|
||||
return ArgPackOrErr.takeError();
|
||||
|
||||
auto AssociatedDeclOrErr = Import(SubstPack->getAssociatedDecl());
|
||||
if (!AssociatedDeclOrErr)
|
||||
return AssociatedDeclOrErr.takeError();
|
||||
|
||||
return ToContext.getSubstTemplateTemplateParmPack(
|
||||
cast<TemplateTemplateParmDecl>(*ParamOrErr), *ArgPackOrErr);
|
||||
*ArgPackOrErr, *AssociatedDeclOrErr, SubstPack->getIndex());
|
||||
}
|
||||
case TemplateName::UsingTemplate: {
|
||||
auto UsingOrError = Import(From.getAsUsingShadowDecl());
|
||||
|
|
|
@ -289,8 +289,14 @@ class StmtComparer {
|
|||
|
||||
bool IsStmtEquivalent(const SubstNonTypeTemplateParmExpr *E1,
|
||||
const SubstNonTypeTemplateParmExpr *E2) {
|
||||
return IsStructurallyEquivalent(Context, E1->getParameter(),
|
||||
E2->getParameter());
|
||||
if (!IsStructurallyEquivalent(Context, E1->getAssociatedDecl(),
|
||||
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,
|
||||
|
@ -510,8 +516,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
|
|||
*P2 = N2.getAsSubstTemplateTemplateParmPack();
|
||||
return IsStructurallyEquivalent(Context, P1->getArgumentPack(),
|
||||
P2->getArgumentPack()) &&
|
||||
IsStructurallyEquivalent(Context, P1->getParameterPack(),
|
||||
P2->getParameterPack());
|
||||
IsStructurallyEquivalent(Context, P1->getAssociatedDecl(),
|
||||
P2->getAssociatedDecl()) &&
|
||||
P1->getIndex() == P2->getIndex();
|
||||
}
|
||||
|
||||
case TemplateName::Template:
|
||||
|
@ -1061,13 +1068,14 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
|
|||
case Type::SubstTemplateTypeParm: {
|
||||
const auto *Subst1 = cast<SubstTemplateTypeParmType>(T1);
|
||||
const auto *Subst2 = cast<SubstTemplateTypeParmType>(T2);
|
||||
if (!IsStructurallyEquivalent(Context,
|
||||
QualType(Subst1->getReplacedParameter(), 0),
|
||||
QualType(Subst2->getReplacedParameter(), 0)))
|
||||
return false;
|
||||
if (!IsStructurallyEquivalent(Context, Subst1->getReplacementType(),
|
||||
Subst2->getReplacementType()))
|
||||
return false;
|
||||
if (!IsStructurallyEquivalent(Context, Subst1->getAssociatedDecl(),
|
||||
Subst2->getAssociatedDecl()))
|
||||
return false;
|
||||
if (Subst1->getIndex() != Subst2->getIndex())
|
||||
return false;
|
||||
if (Subst1->getPackIndex() != Subst2->getPackIndex())
|
||||
return false;
|
||||
break;
|
||||
|
@ -1076,9 +1084,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
|
|||
case Type::SubstTemplateTypeParmPack: {
|
||||
const auto *Subst1 = cast<SubstTemplateTypeParmPackType>(T1);
|
||||
const auto *Subst2 = cast<SubstTemplateTypeParmPackType>(T2);
|
||||
if (!IsStructurallyEquivalent(Context,
|
||||
QualType(Subst1->getReplacedParameter(), 0),
|
||||
QualType(Subst2->getReplacedParameter(), 0)))
|
||||
if (!IsStructurallyEquivalent(Context, Subst1->getAssociatedDecl(),
|
||||
Subst2->getAssociatedDecl()))
|
||||
return false;
|
||||
if (Subst1->getIndex() != Subst2->getIndex())
|
||||
return false;
|
||||
if (!IsStructurallyEquivalent(Context, Subst1->getArgumentPack(),
|
||||
Subst2->getArgumentPack()))
|
||||
|
|
|
@ -1557,3 +1557,56 @@ void TemplateParamObjectDecl::printAsInit(llvm::raw_ostream &OS,
|
|||
const PrintingPolicy &Policy) const {
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1574,6 +1574,11 @@ SizeOfPackExpr *SizeOfPackExpr::CreateDeserialized(ASTContext &Context,
|
|||
return new (Storage) SizeOfPackExpr(EmptyShell(), NumPartialArgs);
|
||||
}
|
||||
|
||||
NonTypeTemplateParmDecl *SubstNonTypeTemplateParmExpr::getParameter() const {
|
||||
return cast<NonTypeTemplateParmDecl>(
|
||||
getReplacedTemplateParameterList(getAssociatedDecl())->asArray()[Index]);
|
||||
}
|
||||
|
||||
QualType SubstNonTypeTemplateParmExpr::getParameterType(
|
||||
const ASTContext &Context) 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(
|
||||
QualType T, ExprValueKind ValueKind, NonTypeTemplateParmDecl *Param,
|
||||
SourceLocation NameLoc, const TemplateArgument &ArgPack)
|
||||
QualType T, ExprValueKind ValueKind, SourceLocation NameLoc,
|
||||
const TemplateArgument &ArgPack, Decl *AssociatedDecl, unsigned Index)
|
||||
: Expr(SubstNonTypeTemplateParmPackExprClass, T, ValueKind, OK_Ordinary),
|
||||
Param(Param), Arguments(ArgPack.pack_begin()),
|
||||
NumArguments(ArgPack.pack_size()), NameLoc(NameLoc) {
|
||||
AssociatedDecl(AssociatedDecl), Arguments(ArgPack.pack_begin()),
|
||||
NumArguments(ArgPack.pack_size()), Index(Index), NameLoc(NameLoc) {
|
||||
assert(AssociatedDecl != nullptr);
|
||||
setDependence(ExprDependence::TypeValueInstantiation |
|
||||
ExprDependence::UnexpandedPack);
|
||||
}
|
||||
|
||||
NonTypeTemplateParmDecl *
|
||||
SubstNonTypeTemplateParmPackExpr::getParameterPack() const {
|
||||
return cast<NonTypeTemplateParmDecl>(
|
||||
getReplacedTemplateParameterList(getAssociatedDecl())->asArray()[Index]);
|
||||
}
|
||||
|
||||
TemplateArgument SubstNonTypeTemplateParmPackExpr::getArgumentPack() const {
|
||||
return TemplateArgument(llvm::makeArrayRef(Arguments, NumArguments));
|
||||
}
|
||||
|
|
|
@ -692,10 +692,16 @@ void JSONNodeDumper::VisitTemplateTypeParmType(
|
|||
|
||||
void JSONNodeDumper::VisitSubstTemplateTypeParmType(
|
||||
const SubstTemplateTypeParmType *STTPT) {
|
||||
JOS.attribute("index", STTPT->getIndex());
|
||||
if (auto PackIndex = STTPT->getPackIndex())
|
||||
JOS.attribute("pack_index", *PackIndex);
|
||||
}
|
||||
|
||||
void JSONNodeDumper::VisitSubstTemplateTypeParmPackType(
|
||||
const SubstTemplateTypeParmPackType *T) {
|
||||
JOS.attribute("index", T->getIndex());
|
||||
}
|
||||
|
||||
void JSONNodeDumper::VisitAutoType(const AutoType *AT) {
|
||||
JOS.attribute("undeduced", !AT->isDeduced());
|
||||
switch (AT->getKeyword()) {
|
||||
|
|
|
@ -671,7 +671,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void AddDecl(Decl *D) {
|
||||
void AddDecl(const Decl *D) {
|
||||
Hash.AddBoolean(D);
|
||||
if (D) {
|
||||
Hash.AddDecl(D);
|
||||
|
@ -995,13 +995,13 @@ public:
|
|||
|
||||
void
|
||||
VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T) {
|
||||
AddType(T->getReplacedParameter());
|
||||
AddDecl(T->getAssociatedDecl());
|
||||
Hash.AddTemplateArgument(T->getArgumentPack());
|
||||
VisitType(T);
|
||||
}
|
||||
|
||||
void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) {
|
||||
AddType(T->getReplacedParameter());
|
||||
AddDecl(T->getAssociatedDecl());
|
||||
AddQualType(T->getReplacementType());
|
||||
VisitType(T);
|
||||
}
|
||||
|
|
|
@ -35,31 +35,49 @@ using namespace clang;
|
|||
|
||||
TemplateArgument
|
||||
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) {
|
||||
Profile(ID, Parameter, Replacement);
|
||||
Profile(ID, Replacement, getAssociatedDecl(), getIndex(), getPackIndex());
|
||||
}
|
||||
|
||||
void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID,
|
||||
TemplateTemplateParmDecl *parameter,
|
||||
TemplateName replacement) {
|
||||
ID.AddPointer(parameter);
|
||||
ID.AddPointer(replacement.getAsVoidPointer());
|
||||
TemplateName Replacement,
|
||||
Decl *AssociatedDecl,
|
||||
unsigned Index,
|
||||
Optional<unsigned> PackIndex) {
|
||||
Replacement.Profile(ID);
|
||||
ID.AddPointer(AssociatedDecl);
|
||||
ID.AddInteger(Index);
|
||||
ID.AddInteger(PackIndex ? *PackIndex + 1 : 0);
|
||||
}
|
||||
|
||||
void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
|
||||
ASTContext &Context) {
|
||||
Profile(ID, Context, Parameter, getArgumentPack());
|
||||
Profile(ID, Context, getArgumentPack(), getAssociatedDecl(), getIndex());
|
||||
}
|
||||
|
||||
void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
|
||||
ASTContext &Context,
|
||||
TemplateTemplateParmDecl *Parameter,
|
||||
const TemplateArgument &ArgPack) {
|
||||
ID.AddPointer(Parameter);
|
||||
void SubstTemplateTemplateParmPackStorage::Profile(
|
||||
llvm::FoldingSetNodeID &ID, ASTContext &Context,
|
||||
const TemplateArgument &ArgPack, Decl *AssociatedDecl, unsigned Index) {
|
||||
ArgPack.Profile(ID, Context);
|
||||
ID.AddPointer(AssociatedDecl);
|
||||
ID.AddInteger(Index);
|
||||
}
|
||||
|
||||
TemplateName::TemplateName(void *Ptr) {
|
||||
|
|
|
@ -1576,10 +1576,18 @@ void TextNodeDumper::VisitTemplateTypeParmType(const TemplateTypeParmType *T) {
|
|||
|
||||
void TextNodeDumper::VisitSubstTemplateTypeParmType(
|
||||
const SubstTemplateTypeParmType *T) {
|
||||
dumpDeclRef(T->getAssociatedDecl());
|
||||
VisitTemplateTypeParmDecl(T->getReplacedParameter());
|
||||
if (auto PackIndex = T->getPackIndex())
|
||||
OS << " pack_index " << *PackIndex;
|
||||
}
|
||||
|
||||
void TextNodeDumper::VisitSubstTemplateTypeParmPackType(
|
||||
const SubstTemplateTypeParmPackType *T) {
|
||||
dumpDeclRef(T->getAssociatedDecl());
|
||||
VisitTemplateTypeParmDecl(T->getReplacedParameter());
|
||||
}
|
||||
|
||||
void TextNodeDumper::VisitAutoType(const AutoType *T) {
|
||||
if (T->isDecltypeAuto())
|
||||
OS << " decltype(auto)";
|
||||
|
|
|
@ -1166,8 +1166,9 @@ public:
|
|||
== T->getReplacementType().getAsOpaquePtr())
|
||||
return QualType(T, 0);
|
||||
|
||||
return Ctx.getSubstTemplateTypeParmType(T->getReplacedParameter(),
|
||||
replacementType, T->getPackIndex());
|
||||
return Ctx.getSubstTemplateTypeParmType(replacementType,
|
||||
T->getAssociatedDecl(),
|
||||
T->getIndex(), T->getPackIndex());
|
||||
}
|
||||
|
||||
// FIXME: Non-trivial to implement, but important for C++
|
||||
|
@ -3668,28 +3669,54 @@ IdentifierInfo *TemplateTypeParmType::getIdentifier() const {
|
|||
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(
|
||||
const TemplateTypeParmType *Param, QualType Replacement,
|
||||
QualType Replacement, Decl *AssociatedDecl, unsigned Index,
|
||||
Optional<unsigned> PackIndex)
|
||||
: Type(SubstTemplateTypeParm, Replacement.getCanonicalType(),
|
||||
Replacement->getDependence()),
|
||||
Replaced(Param) {
|
||||
AssociatedDecl(AssociatedDecl) {
|
||||
SubstTemplateTypeParmTypeBits.HasNonCanonicalUnderlyingType =
|
||||
Replacement != getCanonicalTypeInternal();
|
||||
if (SubstTemplateTypeParmTypeBits.HasNonCanonicalUnderlyingType)
|
||||
*getTrailingObjects<QualType>() = Replacement;
|
||||
|
||||
SubstTemplateTypeParmTypeBits.Index = Index;
|
||||
SubstTemplateTypeParmTypeBits.PackIndex = PackIndex ? *PackIndex + 1 : 0;
|
||||
assert(AssociatedDecl != nullptr);
|
||||
}
|
||||
|
||||
const TemplateTypeParmDecl *
|
||||
SubstTemplateTypeParmType::getReplacedParameter() const {
|
||||
return ::getReplacedParameter(getAssociatedDecl(), getIndex());
|
||||
}
|
||||
|
||||
SubstTemplateTypeParmPackType::SubstTemplateTypeParmPackType(
|
||||
const TemplateTypeParmType *Param, QualType Canon,
|
||||
QualType Canon, Decl *AssociatedDecl, unsigned Index,
|
||||
const TemplateArgument &ArgPack)
|
||||
: Type(SubstTemplateTypeParmPack, Canon,
|
||||
TypeDependence::DependentInstantiation |
|
||||
TypeDependence::UnexpandedPack),
|
||||
Replaced(Param), Arguments(ArgPack.pack_begin()) {
|
||||
Arguments(ArgPack.pack_begin()), AssociatedDecl(AssociatedDecl) {
|
||||
SubstTemplateTypeParmPackTypeBits.Index = Index;
|
||||
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 {
|
||||
|
@ -3697,13 +3724,15 @@ TemplateArgument SubstTemplateTypeParmPackType::getArgumentPack() const {
|
|||
}
|
||||
|
||||
void SubstTemplateTypeParmPackType::Profile(llvm::FoldingSetNodeID &ID) {
|
||||
Profile(ID, getReplacedParameter(), getArgumentPack());
|
||||
Profile(ID, getAssociatedDecl(), getIndex(), getArgumentPack());
|
||||
}
|
||||
|
||||
void SubstTemplateTypeParmPackType::Profile(llvm::FoldingSetNodeID &ID,
|
||||
const TemplateTypeParmType *Replaced,
|
||||
const Decl *AssociatedDecl,
|
||||
unsigned Index,
|
||||
const TemplateArgument &ArgPack) {
|
||||
ID.AddPointer(Replaced);
|
||||
ID.AddPointer(AssociatedDecl);
|
||||
ID.AddInteger(Index);
|
||||
ID.AddInteger(ArgPack.pack_size());
|
||||
for (const auto &P : ArgPack.pack_elements())
|
||||
ID.AddPointer(P.getAsType().getAsOpaquePtr());
|
||||
|
|
|
@ -1464,14 +1464,27 @@ void TypePrinter::printSubstTemplateTypeParmPackBefore(
|
|||
const SubstTemplateTypeParmPackType *T,
|
||||
raw_ostream &OS) {
|
||||
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(
|
||||
const SubstTemplateTypeParmPackType *T,
|
||||
raw_ostream &OS) {
|
||||
IncludeStrongLifetimeRAII Strong(Policy);
|
||||
printTemplateTypeParmAfter(T->getReplacedParameter(), OS);
|
||||
}
|
||||
|
||||
void TypePrinter::printTemplateId(const TemplateSpecializationType *T,
|
||||
|
|
|
@ -396,8 +396,9 @@ bool Sema::CheckConstraintSatisfaction(
|
|||
// has no access to the MultiLevelTemplateArgumentList, so this has to happen
|
||||
// here.
|
||||
llvm::SmallVector<TemplateArgument, 4> FlattenedArgs;
|
||||
for (ArrayRef<TemplateArgument> List : TemplateArgsLists)
|
||||
FlattenedArgs.insert(FlattenedArgs.end(), List.begin(), List.end());
|
||||
for (auto List : TemplateArgsLists)
|
||||
FlattenedArgs.insert(FlattenedArgs.end(), List.Args.begin(),
|
||||
List.Args.end());
|
||||
|
||||
llvm::FoldingSetNodeID ID;
|
||||
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
|
||||
// be picked out of the map.
|
||||
if (auto *SpecArgs = FD->getTemplateSpecializationArgs()) {
|
||||
MultiLevelTemplateArgumentList JustTemplArgs(*SpecArgs);
|
||||
MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray());
|
||||
if (addInstantiatedParametersToScope(
|
||||
FD, PrimaryTemplate->getTemplatedDecl(), Scope, JustTemplArgs))
|
||||
return true;
|
||||
|
|
|
@ -8960,13 +8960,13 @@ Sema::BuildExprRequirement(
|
|||
Context.getReferenceQualifiedType(E).getCanonicalType();
|
||||
llvm::SmallVector<TemplateArgument, 1> Args;
|
||||
Args.push_back(TemplateArgument(MatchedType));
|
||||
|
||||
auto *Param = cast<TemplateTypeParmDecl>(TPL->getParam(0));
|
||||
|
||||
TemplateArgumentList TAL(TemplateArgumentList::OnStack, Args);
|
||||
MultiLevelTemplateArgumentList MLTAL(TAL);
|
||||
for (unsigned I = 0; I < TPL->getDepth(); ++I)
|
||||
MLTAL.addOuterRetainedLevel();
|
||||
Expr *IDC =
|
||||
cast<TemplateTypeParmDecl>(TPL->getParam(0))->getTypeConstraint()
|
||||
->getImmediatelyDeclaredConstraint();
|
||||
MultiLevelTemplateArgumentList MLTAL(Param, TAL.asArray());
|
||||
MLTAL.addOuterRetainedLevels(TPL->getDepth());
|
||||
Expr *IDC = Param->getTypeConstraint()->getImmediatelyDeclaredConstraint();
|
||||
ExprResult Constraint = SubstExpr(IDC, MLTAL);
|
||||
if (Constraint.isInvalid()) {
|
||||
Status = concepts::ExprRequirement::SS_ExprSubstitutionFailure;
|
||||
|
|
|
@ -3581,16 +3581,11 @@ checkBuiltinTemplateIdType(Sema &SemaRef, BuiltinTemplateDecl *BTD,
|
|||
TemplateArgumentListInfo &TemplateArgs) {
|
||||
ASTContext &Context = SemaRef.getASTContext();
|
||||
|
||||
TemplateParameterList *TPL = BTD->getTemplateParameters();
|
||||
|
||||
// Wrap the type in substitution sugar.
|
||||
auto getSubstType = [&](QualType Replacement, unsigned IndexReplaced,
|
||||
Optional<unsigned> PackIndexReplaced) {
|
||||
QualType TTP = SemaRef.Context.getTemplateTypeParmType(
|
||||
0, IndexReplaced, false,
|
||||
cast<TemplateTypeParmDecl>(TPL->getParam(IndexReplaced)));
|
||||
return SemaRef.Context.getSubstTemplateTypeParmType(
|
||||
cast<TemplateTypeParmType>(TTP), Replacement, PackIndexReplaced);
|
||||
Replacement, BTD, IndexReplaced, PackIndexReplaced);
|
||||
};
|
||||
|
||||
switch (BTD->getBuiltinTemplateKind()) {
|
||||
|
@ -3639,8 +3634,7 @@ checkBuiltinTemplateIdType(Sema &SemaRef, BuiltinTemplateDecl *BTD,
|
|||
|
||||
// Wrap the template in substitution sugar.
|
||||
TemplateName TN = SemaRef.Context.getSubstTemplateTemplateParm(
|
||||
cast<TemplateTemplateParmDecl>(TPL->getParam(0)),
|
||||
Converted[0].getAsTemplate());
|
||||
Converted[0].getAsTemplate(), BTD, 0, None);
|
||||
|
||||
// The first template argument will be reused as the template decl that
|
||||
// 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.
|
||||
MultiLevelTemplateArgumentList TemplateArgLists;
|
||||
TemplateArgLists.addOuterTemplateArguments(&StackTemplateArgs);
|
||||
TemplateArgLists.addOuterTemplateArguments(Template,
|
||||
StackTemplateArgs.asArray());
|
||||
TemplateArgLists.addOuterRetainedLevels(
|
||||
AliasTemplate->getTemplateParameters()->getDepth());
|
||||
|
||||
|
@ -3997,7 +3992,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
|
|||
InstantiatingTemplate Inst(*this, TemplateLoc, Decl);
|
||||
if (!Inst.isInvalid()) {
|
||||
MultiLevelTemplateArgumentList TemplateArgLists;
|
||||
TemplateArgLists.addOuterTemplateArguments(Converted);
|
||||
TemplateArgLists.addOuterTemplateArguments(Template, Converted);
|
||||
InstantiateAttrsForDecl(TemplateArgLists,
|
||||
ClassTemplate->getTemplatedDecl(), Decl);
|
||||
}
|
||||
|
@ -4876,7 +4871,7 @@ Sema::CheckConceptTemplateId(const CXXScopeSpec &SS,
|
|||
TemplateSpecializationType::anyDependentTemplateArguments(*TemplateArgs,
|
||||
Converted);
|
||||
MultiLevelTemplateArgumentList MLTAL;
|
||||
MLTAL.addOuterTemplateArguments(Converted);
|
||||
MLTAL.addOuterTemplateArguments(NamedConcept, Converted);
|
||||
LocalInstantiationScope Scope(*this);
|
||||
if (!AreArgsDependent &&
|
||||
CheckConstraintSatisfaction(
|
||||
|
@ -5286,8 +5281,8 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
|
|||
TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted);
|
||||
|
||||
// Only substitute for the innermost template argument list.
|
||||
MultiLevelTemplateArgumentList TemplateArgLists;
|
||||
TemplateArgLists.addOuterTemplateArguments(&TemplateArgs);
|
||||
MultiLevelTemplateArgumentList TemplateArgLists(Template,
|
||||
TemplateArgs.asArray());
|
||||
for (unsigned i = 0, e = Param->getDepth(); i != e; ++i)
|
||||
TemplateArgLists.addOuterTemplateArguments(None);
|
||||
|
||||
|
@ -5342,8 +5337,8 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
|
|||
TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted);
|
||||
|
||||
// Only substitute for the innermost template argument list.
|
||||
MultiLevelTemplateArgumentList TemplateArgLists;
|
||||
TemplateArgLists.addOuterTemplateArguments(&TemplateArgs);
|
||||
MultiLevelTemplateArgumentList TemplateArgLists(Template,
|
||||
TemplateArgs.asArray());
|
||||
for (unsigned i = 0, e = Param->getDepth(); i != e; ++i)
|
||||
TemplateArgLists.addOuterTemplateArguments(None);
|
||||
|
||||
|
@ -5395,8 +5390,8 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
|
|||
TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted);
|
||||
|
||||
// Only substitute for the innermost template argument list.
|
||||
MultiLevelTemplateArgumentList TemplateArgLists;
|
||||
TemplateArgLists.addOuterTemplateArguments(&TemplateArgs);
|
||||
MultiLevelTemplateArgumentList TemplateArgLists(Template,
|
||||
TemplateArgs.asArray());
|
||||
for (unsigned i = 0, e = Param->getDepth(); i != e; ++i)
|
||||
TemplateArgLists.addOuterTemplateArguments(None);
|
||||
|
||||
|
@ -5580,18 +5575,15 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
|
|||
TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
|
||||
Converted);
|
||||
|
||||
MultiLevelTemplateArgumentList MLTAL(Template, TemplateArgs.asArray());
|
||||
// If the parameter is a pack expansion, expand this slice of the pack.
|
||||
if (auto *PET = NTTPType->getAs<PackExpansionType>()) {
|
||||
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this,
|
||||
ArgumentPackIndex);
|
||||
NTTPType = SubstType(PET->getPattern(),
|
||||
MultiLevelTemplateArgumentList(TemplateArgs),
|
||||
NTTP->getLocation(),
|
||||
NTTPType = SubstType(PET->getPattern(), MLTAL, NTTP->getLocation(),
|
||||
NTTP->getDeclName());
|
||||
} else {
|
||||
NTTPType = SubstType(NTTPType,
|
||||
MultiLevelTemplateArgumentList(TemplateArgs),
|
||||
NTTP->getLocation(),
|
||||
NTTPType = SubstType(NTTPType, MLTAL, NTTP->getLocation(),
|
||||
NTTP->getDeclName());
|
||||
}
|
||||
|
||||
|
@ -5734,15 +5726,15 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
|
|||
{
|
||||
// Set up a template instantiation context.
|
||||
LocalInstantiationScope Scope(*this);
|
||||
InstantiatingTemplate Inst(*this, TemplateLoc, Template,
|
||||
TempParm, Converted,
|
||||
SourceRange(TemplateLoc, RAngleLoc));
|
||||
InstantiatingTemplate Inst(*this, TemplateLoc, Template, TempParm,
|
||||
Converted, SourceRange(TemplateLoc, RAngleLoc));
|
||||
if (Inst.isInvalid())
|
||||
return true;
|
||||
|
||||
TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted);
|
||||
Params = SubstTemplateParams(Params, CurContext,
|
||||
MultiLevelTemplateArgumentList(TemplateArgs));
|
||||
Params = SubstTemplateParams(
|
||||
Params, CurContext,
|
||||
MultiLevelTemplateArgumentList(Template, TemplateArgs.asArray()));
|
||||
if (!Params)
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -2687,7 +2687,7 @@ ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
|
|||
if (PackedArgsBuilder.empty()) {
|
||||
LocalInstantiationScope Scope(S);
|
||||
TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Output);
|
||||
MultiLevelTemplateArgumentList Args(TemplateArgs);
|
||||
MultiLevelTemplateArgumentList Args(Template, TemplateArgs.asArray());
|
||||
|
||||
if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
|
||||
Sema::InstantiatingTemplate Inst(S, Template->getLocation(), Template,
|
||||
|
@ -2870,12 +2870,11 @@ CheckDeducedArgumentConstraints(Sema& S, TemplateDeclT *Template,
|
|||
TemplateDeductionInfo& Info) {
|
||||
llvm::SmallVector<const Expr *, 3> AssociatedConstraints;
|
||||
Template->getAssociatedConstraints(AssociatedConstraints);
|
||||
MultiLevelTemplateArgumentList MLTAL;
|
||||
|
||||
bool NeedsReplacement = DeducedArgsNeedReplacement(Template);
|
||||
TemplateArgumentList DeducedTAL{TemplateArgumentList::OnStack, DeducedArgs};
|
||||
|
||||
MLTAL = S.getTemplateInstantiationArgs(
|
||||
MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
|
||||
Template, /*InnerMost=*/NeedsReplacement ? nullptr : &DeducedTAL,
|
||||
/*RelativeToPrimary=*/true, /*Pattern=*/
|
||||
nullptr, /*ForConstraintInstantiation=*/true);
|
||||
|
@ -2940,9 +2939,10 @@ FinishTemplateArgumentDeduction(
|
|||
TemplateArgumentListInfo InstArgs(PartialTemplArgInfo->LAngleLoc,
|
||||
PartialTemplArgInfo->RAngleLoc);
|
||||
|
||||
if (S.SubstTemplateArguments(
|
||||
PartialTemplArgInfo->arguments(),
|
||||
MultiLevelTemplateArgumentList(*DeducedArgumentList), InstArgs)) {
|
||||
if (S.SubstTemplateArguments(PartialTemplArgInfo->arguments(),
|
||||
MultiLevelTemplateArgumentList(
|
||||
Partial, DeducedArgumentList->asArray()),
|
||||
InstArgs)) {
|
||||
unsigned ArgIdx = InstArgs.size(), ParamIdx = ArgIdx;
|
||||
if (ParamIdx >= Partial->getTemplateParameters()->size())
|
||||
ParamIdx = Partial->getTemplateParameters()->size() - 1;
|
||||
|
@ -3279,7 +3279,8 @@ Sema::SubstituteExplicitTemplateArguments(
|
|||
if (Proto->hasTrailingReturn()) {
|
||||
if (SubstParmTypes(Function->getLocation(), Function->parameters(),
|
||||
Proto->getExtParameterInfosOrNull(),
|
||||
MultiLevelTemplateArgumentList(*ExplicitArgumentList),
|
||||
MultiLevelTemplateArgumentList(
|
||||
FunctionTemplate, ExplicitArgumentList->asArray()),
|
||||
ParamTypes, /*params*/ nullptr, ExtParamInfos))
|
||||
return TDK_SubstitutionFailure;
|
||||
}
|
||||
|
@ -3305,7 +3306,8 @@ Sema::SubstituteExplicitTemplateArguments(
|
|||
|
||||
ResultType =
|
||||
SubstType(Proto->getReturnType(),
|
||||
MultiLevelTemplateArgumentList(*ExplicitArgumentList),
|
||||
MultiLevelTemplateArgumentList(
|
||||
FunctionTemplate, ExplicitArgumentList->asArray()),
|
||||
Function->getTypeSpecStartLoc(), Function->getDeclName());
|
||||
if (ResultType.isNull() || Trap.hasErrorOccurred())
|
||||
return TDK_SubstitutionFailure;
|
||||
|
@ -3323,7 +3325,8 @@ Sema::SubstituteExplicitTemplateArguments(
|
|||
if (!Proto->hasTrailingReturn() &&
|
||||
SubstParmTypes(Function->getLocation(), Function->parameters(),
|
||||
Proto->getExtParameterInfosOrNull(),
|
||||
MultiLevelTemplateArgumentList(*ExplicitArgumentList),
|
||||
MultiLevelTemplateArgumentList(
|
||||
FunctionTemplate, ExplicitArgumentList->asArray()),
|
||||
ParamTypes, /*params*/ nullptr, ExtParamInfos))
|
||||
return TDK_SubstitutionFailure;
|
||||
|
||||
|
@ -3338,7 +3341,8 @@ Sema::SubstituteExplicitTemplateArguments(
|
|||
if (getLangOpts().CPlusPlus17 &&
|
||||
SubstExceptionSpec(
|
||||
Function->getLocation(), EPI.ExceptionSpec, ExceptionStorage,
|
||||
MultiLevelTemplateArgumentList(*ExplicitArgumentList)))
|
||||
MultiLevelTemplateArgumentList(FunctionTemplate,
|
||||
ExplicitArgumentList->asArray())))
|
||||
return TDK_SubstitutionFailure;
|
||||
|
||||
*FunctionType = BuildFunctionType(ResultType, ParamTypes,
|
||||
|
@ -3578,7 +3582,8 @@ Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
|
|||
DeclContext *Owner = FunctionTemplate->getDeclContext();
|
||||
if (FunctionTemplate->getFriendObjectKind())
|
||||
Owner = FunctionTemplate->getLexicalDeclContext();
|
||||
MultiLevelTemplateArgumentList SubstArgs(*DeducedArgumentList);
|
||||
MultiLevelTemplateArgumentList SubstArgs(FunctionTemplate,
|
||||
DeducedArgumentList->asArray());
|
||||
Specialization = cast_or_null<FunctionDecl>(
|
||||
SubstDecl(FunctionTemplate->getTemplatedDecl(), Owner, SubstArgs));
|
||||
if (!Specialization || Specialization->isInvalidDecl())
|
||||
|
@ -4635,7 +4640,7 @@ static bool CheckDeducedPlaceholderConstraints(Sema &S, const AutoType &Type,
|
|||
/*PartialTemplateArgs=*/false, Converted))
|
||||
return true;
|
||||
MultiLevelTemplateArgumentList MLTAL;
|
||||
MLTAL.addOuterTemplateArguments(Converted);
|
||||
MLTAL.addOuterTemplateArguments(Concept, Converted);
|
||||
if (S.CheckConstraintSatisfaction(Concept, {Concept->getConstraintExpr()},
|
||||
MLTAL, TypeLoc.getLocalSourceRange(),
|
||||
Satisfaction))
|
||||
|
@ -5939,9 +5944,8 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
|
|||
case Type::SubstTemplateTypeParmPack: {
|
||||
const SubstTemplateTypeParmPackType *Subst
|
||||
= cast<SubstTemplateTypeParmPackType>(T);
|
||||
MarkUsedTemplateParameters(Ctx,
|
||||
QualType(Subst->getReplacedParameter(), 0),
|
||||
OnlyDeduced, Depth, Used);
|
||||
if (Subst->getReplacedParameter()->getDepth() == Depth)
|
||||
Used[Subst->getIndex()] = true;
|
||||
MarkUsedTemplateParameters(Ctx, Subst->getArgumentPack(),
|
||||
OnlyDeduced, Depth, Used);
|
||||
break;
|
||||
|
|
|
@ -86,9 +86,6 @@ HandleVarTemplateSpec(const VarTemplateSpecializationDecl *VarTemplSpec,
|
|||
!isa<VarTemplatePartialSpecializationDecl>(VarTemplSpec))
|
||||
return Response::Done();
|
||||
|
||||
Result.addOuterTemplateArguments(
|
||||
&VarTemplSpec->getTemplateInstantiationArgs());
|
||||
|
||||
// If this variable template specialization was instantiated from a
|
||||
// specialized member that is a variable template, we're done.
|
||||
assert(VarTemplSpec->getSpecializedTemplate() && "No variable template?");
|
||||
|
@ -96,10 +93,14 @@ HandleVarTemplateSpec(const VarTemplateSpecializationDecl *VarTemplSpec,
|
|||
Specialized = VarTemplSpec->getSpecializedTemplateOrPartial();
|
||||
if (VarTemplatePartialSpecializationDecl *Partial =
|
||||
Specialized.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
|
||||
Result.addOuterTemplateArguments(
|
||||
Partial, VarTemplSpec->getTemplateInstantiationArgs().asArray());
|
||||
if (Partial->isMemberSpecialization())
|
||||
return Response::Done();
|
||||
} else {
|
||||
VarTemplateDecl *Tmpl = Specialized.get<VarTemplateDecl *>();
|
||||
Result.addOuterTemplateArguments(
|
||||
Tmpl, VarTemplSpec->getTemplateInstantiationArgs().asArray());
|
||||
if (Tmpl->isMemberSpecialization())
|
||||
return Response::Done();
|
||||
}
|
||||
|
@ -131,7 +132,8 @@ HandleClassTemplateSpec(const ClassTemplateSpecializationDecl *ClassTemplSpec,
|
|||
return Response::Done();
|
||||
|
||||
Result.addOuterTemplateArguments(
|
||||
&ClassTemplSpec->getTemplateInstantiationArgs());
|
||||
const_cast<ClassTemplateSpecializationDecl *>(ClassTemplSpec),
|
||||
ClassTemplSpec->getTemplateInstantiationArgs().asArray());
|
||||
|
||||
// If this class template specialization was instantiated from a
|
||||
// specialized member that is a class template, we're done.
|
||||
|
@ -161,7 +163,8 @@ Response HandleFunction(const FunctionDecl *Function,
|
|||
} else if (const TemplateArgumentList *TemplateArgs =
|
||||
Function->getTemplateSpecializationArgs()) {
|
||||
// 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
|
||||
// a function template, we're done.
|
||||
|
@ -206,7 +209,8 @@ Response HandleRecordDecl(const CXXRecordDecl *Rec,
|
|||
QualType Injected = cast<InjectedClassNameType>(RecordType)
|
||||
->getInjectedSpecializationType();
|
||||
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;
|
||||
|
||||
if (Innermost)
|
||||
Result.addOuterTemplateArguments(Innermost);
|
||||
Result.addOuterTemplateArguments(const_cast<NamedDecl *>(ND),
|
||||
Innermost->asArray());
|
||||
|
||||
const Decl *CurDecl = ND;
|
||||
|
||||
|
@ -1371,9 +1376,9 @@ namespace {
|
|||
Sema::ExtParameterInfoBuilder &PInfos);
|
||||
|
||||
private:
|
||||
ExprResult transformNonTypeTemplateParmRef(NonTypeTemplateParmDecl *parm,
|
||||
SourceLocation loc,
|
||||
TemplateArgument arg);
|
||||
ExprResult transformNonTypeTemplateParmRef(
|
||||
Decl *AssociatedDecl, const NonTypeTemplateParmDecl *parm,
|
||||
SourceLocation loc, TemplateArgument arg, Optional<unsigned> PackIndex);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1563,6 +1568,8 @@ TemplateName TemplateInstantiator::TransformTemplateName(
|
|||
return Arg.getAsTemplate();
|
||||
}
|
||||
|
||||
Decl *AssociatedDecl = TemplateArgs.getAssociatedDecl(TTP->getDepth());
|
||||
Optional<unsigned> PackIndex;
|
||||
if (TTP->isParameterPack()) {
|
||||
assert(Arg.getKind() == TemplateArgument::Pack &&
|
||||
"Missing argument pack");
|
||||
|
@ -1571,10 +1578,12 @@ TemplateName TemplateInstantiator::TransformTemplateName(
|
|||
// We have the template argument pack to substitute, but we're not
|
||||
// actually expanding the enclosing pack expansion yet. So, just
|
||||
// keep the entire argument pack.
|
||||
return getSema().Context.getSubstTemplateTemplateParmPack(TTP, Arg);
|
||||
return getSema().Context.getSubstTemplateTemplateParmPack(
|
||||
Arg, AssociatedDecl, TTP->getIndex());
|
||||
}
|
||||
|
||||
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
|
||||
PackIndex = getSema().ArgumentPackSubstitutionIndex;
|
||||
}
|
||||
|
||||
TemplateName Template = Arg.getAsTemplate().getNameToSubstitute();
|
||||
|
@ -1582,7 +1591,8 @@ TemplateName TemplateInstantiator::TransformTemplateName(
|
|||
assert(!Template.getAsQualifiedTemplateName() &&
|
||||
"template decl to substitute is qualified?");
|
||||
|
||||
Template = getSema().Context.getSubstTemplateTemplateParm(TTP, Template);
|
||||
Template = getSema().Context.getSubstTemplateTemplateParm(
|
||||
Template, AssociatedDecl, TTP->getIndex(), PackIndex);
|
||||
return Template;
|
||||
}
|
||||
}
|
||||
|
@ -1638,6 +1648,8 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
|
|||
return Arg.getAsExpr();
|
||||
}
|
||||
|
||||
Decl *AssociatedDecl = TemplateArgs.getAssociatedDecl(NTTP->getDepth());
|
||||
Optional<unsigned> PackIndex;
|
||||
if (NTTP->isParameterPack()) {
|
||||
assert(Arg.getKind() == TemplateArgument::Pack &&
|
||||
"Missing argument pack");
|
||||
|
@ -1658,13 +1670,14 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
|
|||
|
||||
return new (SemaRef.Context) SubstNonTypeTemplateParmPackExpr(
|
||||
ExprType, TargetType->isReferenceType() ? VK_LValue : VK_PRValue,
|
||||
NTTP, E->getLocation(), Arg);
|
||||
E->getLocation(), Arg, AssociatedDecl, NTTP->getPosition());
|
||||
}
|
||||
|
||||
PackIndex = getSema().ArgumentPackSubstitutionIndex;
|
||||
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
|
||||
}
|
||||
|
||||
return transformNonTypeTemplateParmRef(NTTP, E->getLocation(), Arg);
|
||||
return transformNonTypeTemplateParmRef(AssociatedDecl, NTTP, E->getLocation(),
|
||||
Arg, PackIndex);
|
||||
}
|
||||
|
||||
const LoopHintAttr *
|
||||
|
@ -1685,9 +1698,8 @@ TemplateInstantiator::TransformLoopHintAttr(const LoopHintAttr *LH) {
|
|||
}
|
||||
|
||||
ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef(
|
||||
NonTypeTemplateParmDecl *parm,
|
||||
SourceLocation loc,
|
||||
TemplateArgument arg) {
|
||||
Decl *AssociatedDecl, const NonTypeTemplateParmDecl *parm,
|
||||
SourceLocation loc, TemplateArgument arg, Optional<unsigned> PackIndex) {
|
||||
ExprResult result;
|
||||
|
||||
// Determine the substituted parameter type. We can usually infer this from
|
||||
|
@ -1756,23 +1768,24 @@ ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef(
|
|||
|
||||
Expr *resultExpr = result.get();
|
||||
return new (SemaRef.Context) SubstNonTypeTemplateParmExpr(
|
||||
resultExpr->getType(), resultExpr->getValueKind(), loc, parm, refParam,
|
||||
resultExpr);
|
||||
resultExpr->getType(), resultExpr->getValueKind(), loc, resultExpr,
|
||||
AssociatedDecl, parm->getIndex(), PackIndex, refParam);
|
||||
}
|
||||
|
||||
ExprResult
|
||||
TemplateInstantiator::TransformSubstNonTypeTemplateParmPackExpr(
|
||||
SubstNonTypeTemplateParmPackExpr *E) {
|
||||
if (getSema().ArgumentPackSubstitutionIndex == -1) {
|
||||
int PackIndex = getSema().ArgumentPackSubstitutionIndex;
|
||||
if (PackIndex == -1) {
|
||||
// We aren't expanding the parameter pack, so just return ourselves.
|
||||
return E;
|
||||
}
|
||||
|
||||
TemplateArgument Arg = E->getArgumentPack();
|
||||
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
|
||||
return transformNonTypeTemplateParmRef(E->getParameterPack(),
|
||||
E->getParameterPackLocation(),
|
||||
Arg);
|
||||
return transformNonTypeTemplateParmRef(
|
||||
E->getAssociatedDecl(), E->getParameterPack(),
|
||||
E->getParameterPackLocation(), Arg, PackIndex);
|
||||
}
|
||||
|
||||
ExprResult
|
||||
|
@ -1811,8 +1824,9 @@ TemplateInstantiator::TransformSubstNonTypeTemplateParmExpr(
|
|||
SubstReplacement.get(),
|
||||
Converted).isInvalid())
|
||||
return true;
|
||||
return transformNonTypeTemplateParmRef(E->getParameter(),
|
||||
E->getExprLoc(), Converted);
|
||||
return transformNonTypeTemplateParmRef(E->getAssociatedDecl(),
|
||||
E->getParameter(), E->getExprLoc(),
|
||||
Converted, E->getPackIndex());
|
||||
}
|
||||
|
||||
ExprResult TemplateInstantiator::RebuildVarDeclRefExpr(VarDecl *PD,
|
||||
|
@ -1982,6 +1996,8 @@ TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
|
|||
return NewT;
|
||||
}
|
||||
|
||||
Decl *AssociatedDecl =
|
||||
const_cast<Decl *>(TemplateArgs.getAssociatedDecl(T->getDepth()));
|
||||
Optional<unsigned> PackIndex;
|
||||
if (T->isParameterPack()) {
|
||||
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
|
||||
// enclosing pack expansion yet. Just save the template argument
|
||||
// pack for later substitution.
|
||||
QualType Result
|
||||
= getSema().Context.getSubstTemplateTypeParmPackType(T, Arg);
|
||||
QualType Result = getSema().Context.getSubstTemplateTypeParmPackType(
|
||||
AssociatedDecl, T->getIndex(), Arg);
|
||||
SubstTemplateTypeParmPackTypeLoc NewTL
|
||||
= TLB.push<SubstTemplateTypeParmPackTypeLoc>(Result);
|
||||
NewTL.setNameLoc(TL.getNameLoc());
|
||||
|
@ -2011,7 +2027,7 @@ TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
|
|||
|
||||
// TODO: only do this uniquing once, at the start of instantiation.
|
||||
QualType Result = getSema().Context.getSubstTemplateTypeParmType(
|
||||
T, Replacement, PackIndex);
|
||||
Replacement, AssociatedDecl, T->getIndex(), PackIndex);
|
||||
SubstTemplateTypeParmTypeLoc NewTL
|
||||
= TLB.push<SubstTemplateTypeParmTypeLoc>(Result);
|
||||
NewTL.setNameLoc(TL.getNameLoc());
|
||||
|
@ -2026,7 +2042,6 @@ TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
|
|||
if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl())
|
||||
NewTTPDecl = cast_or_null<TemplateTypeParmDecl>(
|
||||
TransformDecl(TL.getNameLoc(), OldTTPDecl));
|
||||
|
||||
QualType Result = getSema().Context.getTemplateTypeParmType(
|
||||
T->getDepth() - TemplateArgs.getNumSubstitutedLevels(), T->getIndex(),
|
||||
T->isParameterPack(), NewTTPDecl);
|
||||
|
@ -2035,27 +2050,32 @@ TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
|
|||
return Result;
|
||||
}
|
||||
|
||||
QualType
|
||||
TemplateInstantiator::TransformSubstTemplateTypeParmPackType(
|
||||
TypeLocBuilder &TLB,
|
||||
SubstTemplateTypeParmPackTypeLoc TL) {
|
||||
QualType TemplateInstantiator::TransformSubstTemplateTypeParmPackType(
|
||||
TypeLocBuilder &TLB, SubstTemplateTypeParmPackTypeLoc TL) {
|
||||
const SubstTemplateTypeParmPackType *T = TL.getTypePtr();
|
||||
|
||||
Decl *NewReplaced = TransformDecl(TL.getNameLoc(), T->getAssociatedDecl());
|
||||
|
||||
if (getSema().ArgumentPackSubstitutionIndex == -1) {
|
||||
// We aren't expanding the parameter pack, so just return ourselves.
|
||||
SubstTemplateTypeParmPackTypeLoc NewTL
|
||||
= TLB.push<SubstTemplateTypeParmPackTypeLoc>(TL.getType());
|
||||
QualType Result = 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());
|
||||
return TL.getType();
|
||||
return Result;
|
||||
}
|
||||
|
||||
const SubstTemplateTypeParmPackType *T = TL.getTypePtr();
|
||||
TemplateArgument Pack = T->getArgumentPack();
|
||||
TemplateArgument Arg = getPackSubstitutedTemplateArgument(getSema(), Pack);
|
||||
// PackIndex starts from last element.
|
||||
QualType Result = getSema().Context.getSubstTemplateTypeParmType(
|
||||
T->getReplacedParameter(), Arg.getAsType(),
|
||||
Arg.getAsType(), NewReplaced, T->getIndex(),
|
||||
Pack.pack_size() - 1 - getSema().ArgumentPackSubstitutionIndex);
|
||||
SubstTemplateTypeParmTypeLoc NewTL
|
||||
= TLB.push<SubstTemplateTypeParmTypeLoc>(Result);
|
||||
SubstTemplateTypeParmTypeLoc NewTL =
|
||||
TLB.push<SubstTemplateTypeParmTypeLoc>(Result);
|
||||
NewTL.setNameLoc(TL.getNameLoc());
|
||||
return Result;
|
||||
}
|
||||
|
|
|
@ -4761,7 +4761,7 @@ Sema::InstantiateFunctionDeclaration(FunctionTemplateDecl *FTD,
|
|||
return nullptr;
|
||||
|
||||
ContextRAII SavedContext(*this, FD);
|
||||
MultiLevelTemplateArgumentList MArgs(*Args);
|
||||
MultiLevelTemplateArgumentList MArgs(FTD, Args->asArray());
|
||||
|
||||
return cast_or_null<FunctionDecl>(SubstDecl(FD, FD->getParent(), MArgs));
|
||||
}
|
||||
|
@ -5097,8 +5097,7 @@ VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation(
|
|||
const TemplateArgumentList &TemplateArgList,
|
||||
const TemplateArgumentListInfo &TemplateArgsInfo,
|
||||
SmallVectorImpl<TemplateArgument> &Converted,
|
||||
SourceLocation PointOfInstantiation,
|
||||
LateInstantiatedAttrVec *LateAttrs,
|
||||
SourceLocation PointOfInstantiation, LateInstantiatedAttrVec *LateAttrs,
|
||||
LocalInstantiationScope *StartingScope) {
|
||||
if (FromVar->isInvalidDecl())
|
||||
return nullptr;
|
||||
|
@ -5107,9 +5106,6 @@ VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation(
|
|||
if (Inst.isInvalid())
|
||||
return nullptr;
|
||||
|
||||
MultiLevelTemplateArgumentList TemplateArgLists;
|
||||
TemplateArgLists.addOuterTemplateArguments(&TemplateArgList);
|
||||
|
||||
// Instantiate the first declaration of the variable template: for a partial
|
||||
// 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
|
||||
|
@ -5120,15 +5116,21 @@ VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation(
|
|||
// partial specialization, don't do this. The member specialization completely
|
||||
// replaces the original declaration in this case.
|
||||
bool IsMemberSpec = false;
|
||||
if (VarTemplatePartialSpecializationDecl *PartialSpec =
|
||||
dyn_cast<VarTemplatePartialSpecializationDecl>(FromVar))
|
||||
MultiLevelTemplateArgumentList MultiLevelList;
|
||||
if (auto *PartialSpec =
|
||||
dyn_cast<VarTemplatePartialSpecializationDecl>(FromVar)) {
|
||||
IsMemberSpec = PartialSpec->isMemberSpecialization();
|
||||
else if (VarTemplateDecl *FromTemplate = FromVar->getDescribedVarTemplate())
|
||||
IsMemberSpec = FromTemplate->isMemberSpecialization();
|
||||
MultiLevelList.addOuterTemplateArguments(PartialSpec,
|
||||
TemplateArgList.asArray());
|
||||
} else {
|
||||
assert(VarTemplate == FromVar->getDescribedVarTemplate());
|
||||
IsMemberSpec = VarTemplate->isMemberSpecialization();
|
||||
MultiLevelList.addOuterTemplateArguments(VarTemplate,
|
||||
TemplateArgList.asArray());
|
||||
}
|
||||
if (!IsMemberSpec)
|
||||
FromVar = FromVar->getFirstDecl();
|
||||
|
||||
MultiLevelTemplateArgumentList MultiLevelList(TemplateArgList);
|
||||
TemplateDeclInstantiator Instantiator(*this, FromVar->getDeclContext(),
|
||||
MultiLevelList);
|
||||
|
||||
|
|
|
@ -720,7 +720,7 @@ bool Sema::CheckParameterPacksForExpansion(
|
|||
} else if (const auto *STP =
|
||||
P.dyn_cast<const SubstTemplateTypeParmPackType *>()) {
|
||||
NewPackSize = STP->getNumArgs();
|
||||
ND = STP->getReplacedParameter()->getDecl();
|
||||
ND = STP->getReplacedParameter();
|
||||
} else {
|
||||
const auto *SEP = P.get<const SubstNonTypeTemplateParmPackExpr *>();
|
||||
NewPackSize = SEP->getArgumentPack().pack_size();
|
||||
|
|
|
@ -1285,9 +1285,10 @@ public:
|
|||
/// be resolved to a specific template, then builds the appropriate kind of
|
||||
/// template name. Subclasses may override this routine to provide different
|
||||
/// behavior.
|
||||
TemplateName RebuildTemplateName(TemplateTemplateParmDecl *Param,
|
||||
const TemplateArgument &ArgPack) {
|
||||
return getSema().Context.getSubstTemplateTemplateParmPack(Param, ArgPack);
|
||||
TemplateName RebuildTemplateName(const TemplateArgument &ArgPack,
|
||||
Decl *AssociatedDecl, unsigned Index) {
|
||||
return getSema().Context.getSubstTemplateTemplateParmPack(
|
||||
ArgPack, AssociatedDecl, Index);
|
||||
}
|
||||
|
||||
/// Build a new compound statement.
|
||||
|
@ -4391,18 +4392,9 @@ TreeTransform<Derived>::TransformTemplateName(CXXScopeSpec &SS,
|
|||
|
||||
if (SubstTemplateTemplateParmPackStorage *SubstPack
|
||||
= Name.getAsSubstTemplateTemplateParmPack()) {
|
||||
TemplateTemplateParmDecl *TransParam
|
||||
= cast_or_null<TemplateTemplateParmDecl>(
|
||||
getDerived().TransformDecl(NameLoc, SubstPack->getParameterPack()));
|
||||
if (!TransParam)
|
||||
return TemplateName();
|
||||
|
||||
if (!getDerived().AlwaysRebuild() &&
|
||||
TransParam == SubstPack->getParameterPack())
|
||||
return Name;
|
||||
|
||||
return getDerived().RebuildTemplateName(TransParam,
|
||||
SubstPack->getArgumentPack());
|
||||
return getDerived().RebuildTemplateName(SubstPack->getArgumentPack(),
|
||||
SubstPack->getAssociatedDecl(),
|
||||
SubstPack->getIndex());
|
||||
}
|
||||
|
||||
// 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.getUnqualifiedType(), Qs);
|
||||
T = SemaRef.Context.getSubstTemplateTypeParmType(
|
||||
SubstTypeParam->getReplacedParameter(), Replacement,
|
||||
SubstTypeParam->getPackIndex());
|
||||
Replacement, SubstTypeParam->getAssociatedDecl(),
|
||||
SubstTypeParam->getIndex(), SubstTypeParam->getPackIndex());
|
||||
} else if ((AutoTy = dyn_cast<AutoType>(T)) && AutoTy->isDeduced()) {
|
||||
// 'auto' types behave the same way as template parameters.
|
||||
QualType Deduced = AutoTy->getDeducedType();
|
||||
|
@ -6440,6 +6432,9 @@ QualType TreeTransform<Derived>::TransformSubstTemplateTypeParmType(
|
|||
SubstTemplateTypeParmTypeLoc TL) {
|
||||
const SubstTemplateTypeParmType *T = TL.getTypePtr();
|
||||
|
||||
Decl *NewReplaced =
|
||||
getDerived().TransformDecl(TL.getNameLoc(), T->getAssociatedDecl());
|
||||
|
||||
// Substitute into the replacement type, which itself might involve something
|
||||
// that needs to be transformed. This only tends to occur with default
|
||||
// template arguments of template template parameters.
|
||||
|
@ -6449,7 +6444,7 @@ QualType TreeTransform<Derived>::TransformSubstTemplateTypeParmType(
|
|||
return QualType();
|
||||
|
||||
QualType Result = SemaRef.Context.getSubstTemplateTypeParmType(
|
||||
T->getReplacedParameter(), Replacement, T->getPackIndex());
|
||||
Replacement, NewReplaced, T->getIndex(), T->getPackIndex());
|
||||
|
||||
// Propagate type-source information.
|
||||
SubstTemplateTypeParmTypeLoc NewTL
|
||||
|
|
|
@ -382,7 +382,7 @@ namespace clang {
|
|||
void VisitDecompositionDecl(DecompositionDecl *DD);
|
||||
void VisitBindingDecl(BindingDecl *BD);
|
||||
void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
|
||||
DeclID VisitTemplateDecl(TemplateDecl *D);
|
||||
void VisitTemplateDecl(TemplateDecl *D);
|
||||
void VisitConceptDecl(ConceptDecl *D);
|
||||
void VisitRequiresExprBodyDecl(RequiresExprBodyDecl *D);
|
||||
RedeclarableResult VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D);
|
||||
|
@ -415,14 +415,15 @@ namespace clang {
|
|||
template<typename T>
|
||||
RedeclarableResult VisitRedeclarable(Redeclarable<T> *D);
|
||||
|
||||
template<typename T>
|
||||
void mergeRedeclarable(Redeclarable<T> *D, RedeclarableResult &Redecl,
|
||||
DeclID TemplatePatternID = 0);
|
||||
template <typename T>
|
||||
void mergeRedeclarable(Redeclarable<T> *D, RedeclarableResult &Redecl);
|
||||
|
||||
template<typename T>
|
||||
void mergeRedeclarableTemplate(RedeclarableTemplateDecl *D,
|
||||
RedeclarableResult &Redecl);
|
||||
|
||||
template <typename T>
|
||||
void mergeRedeclarable(Redeclarable<T> *D, T *Existing,
|
||||
RedeclarableResult &Redecl,
|
||||
DeclID TemplatePatternID = 0);
|
||||
RedeclarableResult &Redecl);
|
||||
|
||||
template<typename T>
|
||||
void mergeMergeable(Mergeable<T> *D);
|
||||
|
@ -431,7 +432,7 @@ namespace clang {
|
|||
|
||||
void mergeTemplatePattern(RedeclarableTemplateDecl *D,
|
||||
RedeclarableTemplateDecl *Existing,
|
||||
DeclID DsID, bool IsKeyDecl);
|
||||
bool IsKeyDecl);
|
||||
|
||||
ObjCTypeParamList *ReadObjCTypeParamList();
|
||||
|
||||
|
@ -887,90 +888,27 @@ void ASTDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) {
|
|||
|
||||
void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
|
||||
RedeclarableResult Redecl = VisitRedeclarable(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));
|
||||
}
|
||||
}
|
||||
FunctionDecl *Existing = nullptr;
|
||||
|
||||
switch ((FunctionDecl::TemplatedKind)Record.readInt()) {
|
||||
case FunctionDecl::TK_NonTemplate:
|
||||
mergeRedeclarable(FD, Redecl);
|
||||
break;
|
||||
case FunctionDecl::TK_DependentNonTemplate:
|
||||
mergeRedeclarable(FD, Redecl);
|
||||
FD->setInstantiatedFromDecl(readDeclAs<FunctionDecl>());
|
||||
break;
|
||||
case FunctionDecl::TK_FunctionTemplate:
|
||||
// Merged when we merge the template.
|
||||
FD->setDescribedFunctionTemplate(readDeclAs<FunctionTemplateDecl>());
|
||||
case FunctionDecl::TK_FunctionTemplate: {
|
||||
auto *Template = readDeclAs<FunctionTemplateDecl>();
|
||||
Template->init(FD);
|
||||
FD->setDescribedFunctionTemplate(Template);
|
||||
break;
|
||||
}
|
||||
case FunctionDecl::TK_MemberSpecialization: {
|
||||
auto *InstFD = readDeclAs<FunctionDecl>();
|
||||
auto TSK = (TemplateSpecializationKind)Record.readInt();
|
||||
SourceLocation POI = readSourceLocation();
|
||||
FD->setInstantiationOfMemberFunction(Reader.getContext(), InstFD, TSK);
|
||||
FD->getMemberSpecializationInfo()->setPointOfInstantiation(POI);
|
||||
mergeRedeclarable(FD, Redecl);
|
||||
break;
|
||||
}
|
||||
case FunctionDecl::TK_FunctionTemplateSpecialization: {
|
||||
|
@ -1041,7 +979,7 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
|
|||
else {
|
||||
assert(Reader.getContext().getLangOpts().Modules &&
|
||||
"already deserialized this template specialization");
|
||||
mergeRedeclarable(FD, ExistingInfo->getFunction(), Redecl);
|
||||
Existing = ExistingInfo->getFunction();
|
||||
}
|
||||
}
|
||||
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
|
||||
// `DefinitionData` (as this will need to access it).
|
||||
FD->setPure(Pure);
|
||||
|
@ -2187,15 +2215,12 @@ void ASTDeclReader::VisitFriendTemplateDecl(FriendTemplateDecl *D) {
|
|||
D->FriendLoc = readSourceLocation();
|
||||
}
|
||||
|
||||
DeclID ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) {
|
||||
void ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) {
|
||||
VisitNamedDecl(D);
|
||||
|
||||
DeclID PatternID = readDeclID();
|
||||
auto *TemplatedDecl = cast_or_null<NamedDecl>(Reader.GetDecl(PatternID));
|
||||
TemplateParameterList *TemplateParams = Record.readTemplateParameterList();
|
||||
D->init(TemplatedDecl, TemplateParams);
|
||||
|
||||
return PatternID;
|
||||
assert(!D->TemplateParams && "TemplateParams already set!");
|
||||
D->TemplateParams = Record.readTemplateParameterList();
|
||||
D->init(readDeclAs<NamedDecl>());
|
||||
}
|
||||
|
||||
void ASTDeclReader::VisitConceptDecl(ConceptDecl *D) {
|
||||
|
@ -2232,21 +2257,15 @@ ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
|
|||
}
|
||||
}
|
||||
|
||||
DeclID PatternID = VisitTemplateDecl(D);
|
||||
VisitTemplateDecl(D);
|
||||
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;
|
||||
}
|
||||
|
||||
void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
|
||||
RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D);
|
||||
mergeRedeclarableTemplate(D, Redecl);
|
||||
|
||||
if (ThisDeclID == Redecl.getFirstID()) {
|
||||
// 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...
|
||||
void ASTDeclReader::VisitVarTemplateDecl(VarTemplateDecl *D) {
|
||||
RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D);
|
||||
mergeRedeclarableTemplate(D, Redecl);
|
||||
|
||||
if (ThisDeclID == Redecl.getFirstID()) {
|
||||
// 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::VisitVarTemplateSpecializationDeclImpl(
|
||||
VarTemplateSpecializationDecl *D) {
|
||||
RedeclarableResult Redecl = VisitVarDeclImpl(D);
|
||||
|
||||
ASTContext &C = Reader.getContext();
|
||||
if (Decl *InstD = readDecl()) {
|
||||
if (auto *VTD = dyn_cast<VarTemplateDecl>(InstD)) {
|
||||
|
@ -2440,6 +2458,8 @@ ASTDeclReader::VisitVarTemplateSpecializationDeclImpl(
|
|||
D->SpecializationKind = (TemplateSpecializationKind)Record.readInt();
|
||||
D->IsCompleteDefinition = Record.readInt();
|
||||
|
||||
RedeclarableResult Redecl = VisitVarDeclImpl(D);
|
||||
|
||||
bool writtenAsCanonicalDecl = Record.readInt();
|
||||
if (writtenAsCanonicalDecl) {
|
||||
auto *CanonPattern = readDeclAs<VarTemplateDecl>();
|
||||
|
@ -2547,7 +2567,8 @@ void ASTDeclReader::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
|
|||
}
|
||||
|
||||
void ASTDeclReader::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
|
||||
VisitRedeclarableTemplateDecl(D);
|
||||
RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D);
|
||||
mergeRedeclarableTemplate(D, Redecl);
|
||||
}
|
||||
|
||||
void ASTDeclReader::VisitStaticAssertDecl(StaticAssertDecl *D) {
|
||||
|
@ -2644,10 +2665,9 @@ ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
|
|||
|
||||
/// Attempts to merge the given declaration (D) with another declaration
|
||||
/// of the same entity.
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase,
|
||||
RedeclarableResult &Redecl,
|
||||
DeclID TemplatePatternID) {
|
||||
RedeclarableResult &Redecl) {
|
||||
// If modules are not available, there is no reason to perform this merge.
|
||||
if (!Reader.getContext().getLangOpts().Modules)
|
||||
return;
|
||||
|
@ -2660,10 +2680,19 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase,
|
|||
|
||||
if (auto *Existing = Redecl.getKnownMergeTarget())
|
||||
// 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))
|
||||
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.
|
||||
|
@ -2678,7 +2707,7 @@ template<typename T> static T assert_cast(...) {
|
|||
/// declarations.
|
||||
void ASTDeclReader::mergeTemplatePattern(RedeclarableTemplateDecl *D,
|
||||
RedeclarableTemplateDecl *Existing,
|
||||
DeclID DsID, bool IsKeyDecl) {
|
||||
bool IsKeyDecl) {
|
||||
auto *DPattern = D->getTemplatedDecl();
|
||||
auto *ExistingPattern = Existing->getTemplatedDecl();
|
||||
RedeclarableResult Result(/*MergeWith*/ ExistingPattern,
|
||||
|
@ -2718,17 +2747,13 @@ void ASTDeclReader::mergeTemplatePattern(RedeclarableTemplateDecl *D,
|
|||
|
||||
/// Attempts to merge the given declaration (D) with another declaration
|
||||
/// of the same entity.
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, T *Existing,
|
||||
RedeclarableResult &Redecl,
|
||||
DeclID TemplatePatternID) {
|
||||
RedeclarableResult &Redecl) {
|
||||
auto *D = static_cast<T *>(DBase);
|
||||
T *ExistingCanon = Existing->getCanonicalDecl();
|
||||
T *DCanon = D->getCanonicalDecl();
|
||||
if (ExistingCanon != DCanon) {
|
||||
assert(DCanon->getGlobalID() == Redecl.getFirstID() &&
|
||||
"already merged this declaration");
|
||||
|
||||
// Have our redeclaration link point back at the canonical declaration
|
||||
// of the existing declaration, so that this declaration has the
|
||||
// appropriate canonical declaration.
|
||||
|
@ -2747,8 +2772,8 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, T *Existing,
|
|||
// When we merge a template, merge its pattern.
|
||||
if (auto *DTemplate = dyn_cast<RedeclarableTemplateDecl>(D))
|
||||
mergeTemplatePattern(
|
||||
DTemplate, assert_cast<RedeclarableTemplateDecl*>(ExistingCanon),
|
||||
TemplatePatternID, Redecl.isKeyDecl());
|
||||
DTemplate, assert_cast<RedeclarableTemplateDecl *>(ExistingCanon),
|
||||
Redecl.isKeyDecl());
|
||||
|
||||
// If this declaration is a key declaration, make a note of that.
|
||||
if (Redecl.isKeyDecl())
|
||||
|
|
|
@ -2118,8 +2118,10 @@ void ASTStmtReader::VisitSizeOfPackExpr(SizeOfPackExpr *E) {
|
|||
void ASTStmtReader::VisitSubstNonTypeTemplateParmExpr(
|
||||
SubstNonTypeTemplateParmExpr *E) {
|
||||
VisitExpr(E);
|
||||
E->ParamAndRef.setPointer(readDeclAs<NonTypeTemplateParmDecl>());
|
||||
E->ParamAndRef.setInt(Record.readInt());
|
||||
E->AssociatedDeclAndRef.setPointer(readDeclAs<Decl>());
|
||||
E->AssociatedDeclAndRef.setInt(Record.readInt());
|
||||
E->Index = Record.readInt();
|
||||
E->PackIndex = Record.readInt();
|
||||
E->SubstNonTypeTemplateParmExprBits.NameLoc = readSourceLocation();
|
||||
E->Replacement = Record.readSubExpr();
|
||||
}
|
||||
|
@ -2127,7 +2129,8 @@ void ASTStmtReader::VisitSubstNonTypeTemplateParmExpr(
|
|||
void ASTStmtReader::VisitSubstNonTypeTemplateParmPackExpr(
|
||||
SubstNonTypeTemplateParmPackExpr *E) {
|
||||
VisitExpr(E);
|
||||
E->Param = readDeclAs<NonTypeTemplateParmDecl>();
|
||||
E->AssociatedDecl = readDeclAs<Decl>();
|
||||
E->Index = Record.readInt();
|
||||
TemplateArgument ArgPack = Record.readTemplateArgument();
|
||||
if (ArgPack.getKind() != TemplateArgument::Pack)
|
||||
return;
|
||||
|
|
|
@ -539,48 +539,6 @@ void ASTDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) {
|
|||
|
||||
void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *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());
|
||||
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());
|
||||
for (auto *P : D->parameters())
|
||||
Record.AddDeclRef(P);
|
||||
|
@ -1405,14 +1407,12 @@ void ASTDeclWriter::VisitCXXMethodDecl(CXXMethodDecl *D) {
|
|||
}
|
||||
|
||||
if (D->getDeclContext() == D->getLexicalDeclContext() &&
|
||||
D->getFirstDecl() == D->getMostRecentDecl() &&
|
||||
!D->isInvalidDecl() &&
|
||||
!D->hasAttrs() &&
|
||||
!D->isTopLevelDeclInObjCContainer() &&
|
||||
D->getFirstDecl() == D->getMostRecentDecl() && !D->isInvalidDecl() &&
|
||||
!D->hasAttrs() && !D->isTopLevelDeclInObjCContainer() &&
|
||||
D->getDeclName().getNameKind() == DeclarationName::Identifier &&
|
||||
!D->hasExtInfo() &&
|
||||
!D->hasInheritedPrototype() &&
|
||||
D->hasWrittenPrototype())
|
||||
!D->hasExtInfo() && !D->hasInheritedPrototype() &&
|
||||
D->hasWrittenPrototype() &&
|
||||
D->getTemplatedKind() == FunctionDecl::TK_NonTemplate)
|
||||
AbbrevToUse = Writer.getDeclCXXMethodAbbrev();
|
||||
|
||||
Code = serialization::DECL_CXX_METHOD;
|
||||
|
@ -1506,8 +1506,8 @@ void ASTDeclWriter::VisitFriendTemplateDecl(FriendTemplateDecl *D) {
|
|||
void ASTDeclWriter::VisitTemplateDecl(TemplateDecl *D) {
|
||||
VisitNamedDecl(D);
|
||||
|
||||
Record.AddDeclRef(D->getTemplatedDecl());
|
||||
Record.AddTemplateParameterList(D->getTemplateParameters());
|
||||
Record.AddDeclRef(D->getTemplatedDecl());
|
||||
}
|
||||
|
||||
void ASTDeclWriter::VisitConceptDecl(ConceptDecl *D) {
|
||||
|
@ -1608,8 +1608,6 @@ void ASTDeclWriter::VisitVarTemplateSpecializationDecl(
|
|||
VarTemplateSpecializationDecl *D) {
|
||||
RegisterTemplateSpecialization(D->getSpecializedTemplate(), D);
|
||||
|
||||
VisitVarDecl(D);
|
||||
|
||||
llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>
|
||||
InstFrom = D->getSpecializedTemplateOrPartial();
|
||||
if (Decl *InstFromD = InstFrom.dyn_cast<VarTemplateDecl *>()) {
|
||||
|
@ -1630,6 +1628,9 @@ void ASTDeclWriter::VisitVarTemplateSpecializationDecl(
|
|||
Record.AddSourceLocation(D->getPointOfInstantiation());
|
||||
Record.push_back(D->getSpecializationKind());
|
||||
Record.push_back(D->IsCompleteDefinition);
|
||||
|
||||
VisitVarDecl(D);
|
||||
|
||||
Record.push_back(D->isCanonicalDecl());
|
||||
|
||||
if (D->isCanonicalDecl()) {
|
||||
|
@ -2245,6 +2246,8 @@ void ASTWriter::WriteDeclAbbrevs() {
|
|||
Abv->Add(BitCodeAbbrevOp(serialization::DECL_CXX_METHOD));
|
||||
// RedeclarableDecl
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // CanonicalDecl
|
||||
// FIXME: Implement abbreviation for other template kinds.
|
||||
Abv->Add(BitCodeAbbrevOp(FunctionDecl::TK_NonTemplate)); // TemplateKind
|
||||
// Decl
|
||||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
|
||||
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)); // Default
|
||||
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
|
||||
// (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
|
||||
// NumOverriddenMethods, OverriddenMethods[] from CXXMethodDecl.
|
||||
//
|
||||
|
|
|
@ -2028,8 +2028,13 @@ void ASTStmtWriter::VisitSizeOfPackExpr(SizeOfPackExpr *E) {
|
|||
void ASTStmtWriter::VisitSubstNonTypeTemplateParmExpr(
|
||||
SubstNonTypeTemplateParmExpr *E) {
|
||||
VisitExpr(E);
|
||||
Record.AddDeclRef(E->getParameter());
|
||||
Record.AddDeclRef(E->getAssociatedDecl());
|
||||
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.AddStmt(E->getReplacement());
|
||||
Code = serialization::EXPR_SUBST_NON_TYPE_TEMPLATE_PARM;
|
||||
|
@ -2038,7 +2043,8 @@ void ASTStmtWriter::VisitSubstNonTypeTemplateParmExpr(
|
|||
void ASTStmtWriter::VisitSubstNonTypeTemplateParmPackExpr(
|
||||
SubstNonTypeTemplateParmPackExpr *E) {
|
||||
VisitExpr(E);
|
||||
Record.AddDeclRef(E->getParameterPack());
|
||||
Record.AddDeclRef(E->getAssociatedDecl());
|
||||
Record.push_back(E->getIndex());
|
||||
Record.AddTemplateArgument(E->getArgumentPack());
|
||||
Record.AddSourceLocation(E->getParameterPackLocation());
|
||||
Code = serialization::EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK;
|
||||
|
|
|
@ -176,8 +176,10 @@ void MismatchedIteratorChecker::checkPreCall(const CallEvent &Call,
|
|||
const auto *Param = Func->getParamDecl(J);
|
||||
const auto *ParamType =
|
||||
Param->getType()->getAs<SubstTemplateTypeParmType>();
|
||||
if (!ParamType ||
|
||||
ParamType->getReplacedParameter()->getDecl() != TPDecl)
|
||||
if (!ParamType)
|
||||
continue;
|
||||
const TemplateTypeParmDecl *D = ParamType->getReplacedParameter();
|
||||
if (D != TPDecl)
|
||||
continue;
|
||||
if (LHS.isUndef()) {
|
||||
LHS = Call.getArgSVal(J);
|
||||
|
|
|
@ -122,9 +122,8 @@ int test(float &&f, short &&s) {
|
|||
// 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: | | `-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: | | |-TemplateTypeParmType [[ADDR_12:0x[a-z0-9]*]] '_Tp' dependent depth 0 index 0
|
||||
// CHECK-NEXT: | | | `-TemplateTypeParm [[ADDR_13:0x[a-z0-9]*]] '_Tp'
|
||||
// CHECK-NEXT: | | `-SubstTemplateTypeParmType [[ADDR_11:0x[a-z0-9]*]] 'float' sugar class depth 0 index 0 _Tp
|
||||
// CHECK-NEXT: | | |-ClassTemplateSpecialization [[ADDR_6]] 'remove_reference'
|
||||
// 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: | |-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: | |-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: | `-SubstTemplateTypeParmType [[ADDR_19:0x[a-z0-9]*]] 'short' sugar
|
||||
// CHECK-NEXT: | |-TemplateTypeParmType [[ADDR_12]] '_Tp' dependent depth 0 index 0
|
||||
// CHECK-NEXT: | | `-TemplateTypeParm [[ADDR_13]] '_Tp'
|
||||
// CHECK-NEXT: | `-SubstTemplateTypeParmType [[ADDR_19:0x[a-z0-9]*]] 'short' sugar class depth 0 index 0 _Tp
|
||||
// CHECK-NEXT: | |-ClassTemplateSpecialization [[ADDR_14]] 'remove_reference'
|
||||
// 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: | |-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: | | `-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: | |-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: | `-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: |-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
|
||||
|
@ -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: | | | `-TypedefType [[ADDR_48:0x[a-z0-9]*]] 'remove_reference<float &>::type' sugar
|
||||
// CHECK-NEXT: | | | |-Typedef [[ADDR_10]] 'type'
|
||||
// CHECK-NEXT: | | | `-SubstTemplateTypeParmType [[ADDR_11]] 'float' sugar
|
||||
// CHECK-NEXT: | | | |-TemplateTypeParmType [[ADDR_12]] '_Tp' dependent depth 0 index 0
|
||||
// CHECK-NEXT: | | | | `-TemplateTypeParm [[ADDR_13]] '_Tp'
|
||||
// CHECK-NEXT: | | | `-SubstTemplateTypeParmType [[ADDR_11]] 'float' sugar class depth 0 index 0 _Tp
|
||||
// CHECK-NEXT: | | | |-ClassTemplateSpecialization [[ADDR_6]] 'remove_reference'
|
||||
// CHECK-NEXT: | | | `-BuiltinType [[ADDR_8]] 'float'
|
||||
// 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>
|
||||
|
@ -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: | | `-TypedefType [[ADDR_58:0x[a-z0-9]*]] 'remove_reference<short &>::type' sugar
|
||||
// CHECK-NEXT: | | |-Typedef [[ADDR_18]] 'type'
|
||||
// CHECK-NEXT: | | `-SubstTemplateTypeParmType [[ADDR_19]] 'short' sugar
|
||||
// CHECK-NEXT: | | |-TemplateTypeParmType [[ADDR_12]] '_Tp' dependent depth 0 index 0
|
||||
// CHECK-NEXT: | | | `-TemplateTypeParm [[ADDR_13]] '_Tp'
|
||||
// CHECK-NEXT: | | `-SubstTemplateTypeParmType [[ADDR_19]] 'short' sugar class depth 0 index 0 _Tp
|
||||
// CHECK-NEXT: | | |-ClassTemplateSpecialization [[ADDR_14]] 'remove_reference'
|
||||
// CHECK-NEXT: | | `-BuiltinType [[ADDR_16]] 'short'
|
||||
// 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>
|
||||
|
|
|
@ -120,12 +120,12 @@ using type2 = typename C<int>::type1<void>;
|
|||
// CHECK-NEXT: TemplateArgument type 'void'
|
||||
// CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'void'
|
||||
// CHECK-NEXT: FunctionProtoType 0x{{[^ ]*}} 'void (int)' cdecl
|
||||
// CHECK-NEXT: SubstTemplateTypeParmType 0x{{[^ ]*}} 'void' sugar
|
||||
// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'U' dependent depth 0 index 0
|
||||
// CHECK-NEXT: TemplateTypeParm 0x{{[^ ]*}} 'U'
|
||||
// CHECK-NEXT: SubstTemplateTypeParmType 0x{{[^ ]*}} 'void' sugar class depth 0 index 0 U
|
||||
// CHECK-NEXT: TypeAliasTemplate 0x{{[^ ]*}} 'type1'
|
||||
// CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'void'
|
||||
// CHECK-NEXT: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar
|
||||
// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'T' dependent depth 0 index 0
|
||||
// CHECK-NEXT: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar class depth 0 index 0 T
|
||||
// CHECK-NEXT: ClassTemplateSpecialization 0x{{[^ ]*}} 'C'
|
||||
// CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'int'
|
||||
} // namespace PR55886
|
||||
|
||||
namespace PR56099 {
|
||||
|
@ -136,14 +136,14 @@ template <typename... Cs> struct foo {
|
|||
};
|
||||
using t1 = foo<int, short>::bind<char, float>;
|
||||
// CHECK: TemplateSpecializationType 0x{{[^ ]*}} 'Y<char, float, int, short>' sugar Y
|
||||
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'char' sugar pack_index 3
|
||||
// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'Bs' dependent contains_unexpanded_pack depth 0 index 0 pack
|
||||
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'float' sugar pack_index 2
|
||||
// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'Bs' dependent contains_unexpanded_pack depth 0 index 0 pack
|
||||
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar pack_index 1
|
||||
// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'Bs' dependent contains_unexpanded_pack depth 0 index 0 pack
|
||||
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'short' sugar pack_index 0
|
||||
// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'Bs' dependent contains_unexpanded_pack depth 0 index 0 pack
|
||||
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'char' sugar typename depth 0 index 0 ... Bs pack_index 3
|
||||
// CHECK-NEXT: TypeAliasTemplate 0x{{[^ ]*}} 'Z'
|
||||
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'float' sugar typename depth 0 index 0 ... Bs pack_index 2
|
||||
// CHECK-NEXT: TypeAliasTemplate 0x{{[^ ]*}} 'Z'
|
||||
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar typename depth 0 index 0 ... Bs pack_index 1
|
||||
// CHECK-NEXT: TypeAliasTemplate 0x{{[^ ]*}} 'Z'
|
||||
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'short' sugar typename depth 0 index 0 ... Bs pack_index 0
|
||||
// CHECK-NEXT: TypeAliasTemplate 0x{{[^ ]*}} 'Z'
|
||||
|
||||
template <typename... T> struct D {
|
||||
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: FunctionProtoType 0x{{[^ ]*}} 'int (int (*)(float, int), int (*)(char, short))' cdecl
|
||||
// CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (float, int)' cdecl
|
||||
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'float' sugar pack_index 1
|
||||
// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'T' dependent contains_unexpanded_pack depth 0 index 0 pack
|
||||
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar pack_index 1
|
||||
// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'U' dependent contains_unexpanded_pack depth 0 index 0 pack
|
||||
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'float' sugar typename depth 0 index 0 ... T pack_index 1
|
||||
// CHECK-NEXT: ClassTemplateSpecialization 0x{{[^ ]*}} 'D'
|
||||
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar typename depth 0 index 0 ... U pack_index 1
|
||||
// CHECK-NEXT: TypeAliasTemplate 0x{{[^ ]*}} 'B'
|
||||
// CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (char, short)' cdecl
|
||||
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'char' sugar pack_index 0
|
||||
// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'T' dependent contains_unexpanded_pack depth 0 index 0 pack
|
||||
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'short' sugar pack_index 0
|
||||
// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'U' dependent contains_unexpanded_pack depth 0 index 0 pack
|
||||
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'char' sugar typename depth 0 index 0 ... T pack_index 0
|
||||
// CHECK-NEXT: ClassTemplateSpecialization 0x{{[^ ]*}} 'D'
|
||||
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'short' sugar typename depth 0 index 0 ... U pack_index 0
|
||||
// CHECK-NEXT: TypeAliasTemplate 0x{{[^ ]*}} 'B'
|
||||
} // namespace PR56099
|
||||
|
||||
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: TemplateSpecializationType 0x{{[^ ]*}} 'A<int>' sugar A
|
||||
// CHECK-NEXT: |-TemplateArgument type 'int':'int'
|
||||
// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar
|
||||
// CHECK-NEXT: | |-TemplateTypeParmType 0x{{[^ ]*}} 'C1' dependent depth 1 index 0
|
||||
// CHECK-NEXT: | | `-TemplateTypeParm 0x{{[^ ]*}} 'C1'
|
||||
// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar
|
||||
// CHECK-NEXT: | |-TemplateTypeParmType 0x{{[^ ]*}} 'type-parameter-0-1' dependent depth 0 index 1
|
||||
// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar class depth 0 index 0 E1
|
||||
// CHECK-NEXT: | |-ClassTemplate 0x{{[^ ]*}} 'E'
|
||||
// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar class depth 0 index 1 D2
|
||||
// CHECK-NEXT: | |-TypeAliasTemplate 0x{{[^ ]*}} 'D'
|
||||
// CHECK-NEXT: | `-BuiltinType 0x{{[^ ]*}} 'int'
|
||||
// CHECK-NEXT: `-RecordType 0x{{[^ ]*}} 'subst_default_argument::A<int>'
|
||||
// CHECK-NEXT: `-ClassTemplateSpecialization 0x{{[^ ]*}} 'A'
|
||||
|
|
|
@ -67,9 +67,8 @@ namespace PR48177 {
|
|||
// CHECK-NEXT: ElaboratedType {{.*}} 'typename Derived<int, 1, int>::type_alias' sugar
|
||||
// CHECK-NEXT: TypedefType {{.*}} 'PR48177::Base<int>::type_alias' sugar
|
||||
// CHECK-NEXT: TypeAlias {{.*}} 'type_alias'
|
||||
// CHECK-NEXT: SubstTemplateTypeParmType {{.*}} 'int' sugar
|
||||
// CHECK-NEXT: TemplateTypeParmType {{.*}} 'A'
|
||||
// CHECK-NEXT: TemplateTypeParm {{.*}} 'A'
|
||||
// CHECK-NEXT: SubstTemplateTypeParmType {{.*}} 'int' sugar class depth 0 index 0 A
|
||||
// CHECK-NEXT: ClassTemplateSpecialization {{.*}} 'Base'
|
||||
// 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>'
|
||||
|
|
|
@ -156,9 +156,8 @@ using DT = D<int, int>;
|
|||
// CHECK: |-BuiltinType {{.*}} 'int'
|
||||
// CHECK: |-TemplateTypeParmType {{.*}} 'T' dependent contains_unexpanded_pack depth 0 index 0 pack
|
||||
// CHECK: | `-TemplateTypeParm {{.*}} 'T'
|
||||
// CHECK: `-SubstTemplateTypeParmPackType {{.*}} 'U' dependent contains_unexpanded_pack
|
||||
// CHECK: |-TemplateTypeParmType {{.*}} 'U' dependent contains_unexpanded_pack depth 1 index 0 pack
|
||||
// CHECK: | `-TemplateTypeParm {{.*}} 'U'
|
||||
// CHECK: `-SubstTemplateTypeParmPackType {{.*}} 'U' dependent contains_unexpanded_pack typename depth 1 index 0 ... U
|
||||
// CHECK: |-TypeAliasTemplate {{.*}} 'B'
|
||||
// CHECK: `-TemplateArgument pack
|
||||
// CHECK: |-TemplateArgument type 'type-parameter-0-1'
|
||||
// CHECK-NOT: Subst
|
||||
|
|
|
@ -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: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} 'A<int, 0>' sugar A
|
||||
// CHECK-NEXT: |-TemplateArgument type 'int':'int'
|
||||
// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'int' sugar
|
||||
// CHECK-NEXT: | |-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'auto' dependent depth 0 index 1
|
||||
// CHECK-NEXT: | | `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} ''
|
||||
// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'int' sugar typename depth 0 index 1
|
||||
// CHECK-NEXT: | |-BuiltinTemplate 0x{{[0-9A-Fa-f]+}} '__make_integer_seq'
|
||||
// CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
|
||||
// CHECK-NEXT: |-TemplateArgument expr
|
||||
// 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>;
|
||||
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: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} 'B<int, 1>' sugar alias B
|
||||
// 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: |-TemplateArgument template A
|
||||
// CHECK-NEXT: |-TemplateArgument type 'int':'int'
|
||||
// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'int' sugar
|
||||
// CHECK-NEXT: | |-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'B1' dependent depth 0 index 0
|
||||
// CHECK-NEXT: | | `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} 'B1'
|
||||
// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'int' sugar class depth 0 index 0 B1
|
||||
// CHECK-NEXT: | |-TypeAliasTemplate 0x{{[0-9A-Fa-f]+}} 'B'
|
||||
// CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
|
||||
// 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: | `-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: | `-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: |-TemplateArgument type 'int':'int'
|
||||
// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'int' sugar
|
||||
// CHECK-NEXT: | |-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'auto' dependent depth 0 index 1
|
||||
// CHECK-NEXT: | | `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} ''
|
||||
// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'int' sugar typename depth 0 index 1
|
||||
// CHECK-NEXT: | |-BuiltinTemplate 0x{{[0-9A-Fa-f]+}} '__make_integer_seq'
|
||||
// CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
|
||||
// CHECK-NEXT: |-TemplateArgument expr
|
||||
// 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 {
|
||||
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: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<S, T, N>' sugar dependent alias __make_integer_seq
|
||||
// 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'
|
||||
|
||||
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: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, T, 1>' sugar dependent alias __make_integer_seq
|
||||
// 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
|
||||
|
||||
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: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, int, N>' sugar dependent alias __make_integer_seq
|
||||
// CHECK-NEXT: |-TemplateArgument template A
|
||||
|
|
|
@ -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: |-TemplateArgument type '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: |-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'auto' dependent depth 0 index 1
|
||||
// CHECK-NEXT: | `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} ''
|
||||
// CHECK-NEXT: `-SubstTemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'int' sugar typename depth 0 index 1 ... pack_index 0
|
||||
// CHECK-NEXT: |-BuiltinTemplate 0x{{[0-9A-Fa-f]+}} '__type_pack_element'
|
||||
// CHECK-NEXT: `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
|
||||
|
||||
template<int N, class ...Ts> struct A {
|
||||
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: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, Ts...>' sugar dependent alias __type_pack_element
|
||||
// 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
|
||||
|
||||
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: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<0, Ts...>' sugar dependent alias __type_pack_element
|
||||
// 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
|
||||
|
||||
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: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, int>' sugar dependent alias __type_pack_element
|
||||
// CHECK-NEXT: |-TemplateArgument expr
|
||||
|
|
|
@ -1445,7 +1445,8 @@ clang::FunctionTemplateDecl *TypeSystemClang::CreateFunctionTemplateDecl(
|
|||
func_tmpl_decl->setDeclContext(decl_ctx);
|
||||
func_tmpl_decl->setLocation(func_decl->getLocation());
|
||||
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);
|
||||
|
||||
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?
|
||||
class_template_decl->setDeclContext(decl_ctx);
|
||||
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);
|
||||
SetOwningModule(class_template_decl, owning_module);
|
||||
|
||||
|
|
Loading…
Reference in New Issue