forked from OSchip/llvm-project
Implement support for non-type template parameter packs whose type is
a pack expansion, e.g., the parameter pack Values in: template<typename ...Types> struct Outer { template<Types ...Values> struct Inner; }; This new implementation approach introduces the notion of an "expanded" non-type template parameter pack, for which we have already expanded the types of the parameter pack (to, say, "int*, float*", for Outer<int*, float*>) but have not yet expanded the values. Aside from creating these expanded non-type template parameter packs, this patch updates template argument checking and non-type template parameter pack instantiation to make use of the appropriate types in the parameter pack. llvm-svn: 123845
This commit is contained in:
parent
2a67aa721f
commit
0231d8dac7
|
@ -1411,7 +1411,8 @@ public:
|
||||||
/// initialized to a given location, which defaults to the empty
|
/// initialized to a given location, which defaults to the empty
|
||||||
/// location.
|
/// location.
|
||||||
TypeSourceInfo *
|
TypeSourceInfo *
|
||||||
getTrivialTypeSourceInfo(QualType T, SourceLocation Loc = SourceLocation());
|
getTrivialTypeSourceInfo(QualType T,
|
||||||
|
SourceLocation Loc = SourceLocation()) const;
|
||||||
|
|
||||||
TypeSourceInfo *getNullTypeSourceInfo() { return &NullTypeSourceInfo; }
|
TypeSourceInfo *getNullTypeSourceInfo() { return &NullTypeSourceInfo; }
|
||||||
|
|
||||||
|
|
|
@ -996,14 +996,30 @@ class NonTypeTemplateParmDecl
|
||||||
/// \brief Whether this non-type template parameter is a parameter pack.
|
/// \brief Whether this non-type template parameter is a parameter pack.
|
||||||
bool ParameterPack;
|
bool ParameterPack;
|
||||||
|
|
||||||
|
/// \brief Whether this non-type template parameter is an "expanded"
|
||||||
|
/// parameter pack, meaning that its type is a pack expansion and we
|
||||||
|
/// already know the set of types that expansion expands to.
|
||||||
|
bool ExpandedParameterPack;
|
||||||
|
|
||||||
|
/// \brief The number of types in an expanded parameter pack.
|
||||||
|
unsigned NumExpandedTypes;
|
||||||
|
|
||||||
NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D,
|
NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D,
|
||||||
unsigned P, IdentifierInfo *Id, QualType T,
|
unsigned P, IdentifierInfo *Id, QualType T,
|
||||||
bool ParameterPack, TypeSourceInfo *TInfo)
|
bool ParameterPack, TypeSourceInfo *TInfo)
|
||||||
: VarDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo, SC_None, SC_None),
|
: VarDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo, SC_None, SC_None),
|
||||||
TemplateParmPosition(D, P), DefaultArgumentAndInherited(0, false),
|
TemplateParmPosition(D, P), DefaultArgumentAndInherited(0, false),
|
||||||
ParameterPack(ParameterPack)
|
ParameterPack(ParameterPack), ExpandedParameterPack(false),
|
||||||
|
NumExpandedTypes(0)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D,
|
||||||
|
unsigned P, IdentifierInfo *Id, QualType T,
|
||||||
|
TypeSourceInfo *TInfo,
|
||||||
|
const QualType *ExpandedTypes,
|
||||||
|
unsigned NumExpandedTypes,
|
||||||
|
TypeSourceInfo **ExpandedTInfos);
|
||||||
|
|
||||||
friend class ASTDeclReader;
|
friend class ASTDeclReader;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -1012,6 +1028,12 @@ public:
|
||||||
unsigned P, IdentifierInfo *Id, QualType T, bool ParameterPack,
|
unsigned P, IdentifierInfo *Id, QualType T, bool ParameterPack,
|
||||||
TypeSourceInfo *TInfo);
|
TypeSourceInfo *TInfo);
|
||||||
|
|
||||||
|
static NonTypeTemplateParmDecl *
|
||||||
|
Create(const ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D,
|
||||||
|
unsigned P, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo,
|
||||||
|
const QualType *ExpandedTypes, unsigned NumExpandedTypes,
|
||||||
|
TypeSourceInfo **ExpandedTInfos);
|
||||||
|
|
||||||
using TemplateParmPosition::getDepth;
|
using TemplateParmPosition::getDepth;
|
||||||
using TemplateParmPosition::setDepth;
|
using TemplateParmPosition::setDepth;
|
||||||
using TemplateParmPosition::getPosition;
|
using TemplateParmPosition::getPosition;
|
||||||
|
@ -1063,6 +1085,54 @@ public:
|
||||||
/// \endcode
|
/// \endcode
|
||||||
bool isParameterPack() const { return ParameterPack; }
|
bool isParameterPack() const { return ParameterPack; }
|
||||||
|
|
||||||
|
/// \brief Whether this parameter is a non-type template parameter pack
|
||||||
|
/// that has different types at different positions.
|
||||||
|
///
|
||||||
|
/// A parameter pack is an expanded parameter pack when the original
|
||||||
|
/// parameter pack's type was itself a pack expansion, and that expansion
|
||||||
|
/// has already been expanded. For example, given:
|
||||||
|
///
|
||||||
|
/// \code
|
||||||
|
/// template<typename ...Types>
|
||||||
|
/// struct X {
|
||||||
|
/// template<Types ...Values>
|
||||||
|
/// struct Y { /* ... */ };
|
||||||
|
/// };
|
||||||
|
/// \endcode
|
||||||
|
///
|
||||||
|
/// The parameter pack \c Values has a \c PackExpansionType as its type,
|
||||||
|
/// which expands \c Types. When \c Types is supplied with template arguments
|
||||||
|
/// by instantiating \c X, the instantiation of \c Values becomes an
|
||||||
|
/// expanded parameter pack. For example, instantiating
|
||||||
|
/// \c X<int, unsigned int> results in \c Values being an expanded parameter
|
||||||
|
/// pack with expansion types \c int and \c unsigned int.
|
||||||
|
///
|
||||||
|
/// The \c getExpansionType() and \c getExpansionTypeSourceInfo() functions
|
||||||
|
/// return the expansion types.
|
||||||
|
bool isExpandedParameterPack() const { return ExpandedParameterPack; }
|
||||||
|
|
||||||
|
/// \brief Retrieves the number of expansion types in an expanded parameter pack.
|
||||||
|
unsigned getNumExpansionTypes() const {
|
||||||
|
assert(ExpandedParameterPack && "Not an expansion parameter pack");
|
||||||
|
return NumExpandedTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Retrieve a particular expansion type within an expanded parameter
|
||||||
|
/// pack.
|
||||||
|
QualType getExpansionType(unsigned I) const {
|
||||||
|
assert(I < NumExpandedTypes && "Out-of-range expansion type index");
|
||||||
|
void * const *TypesAndInfos = reinterpret_cast<void * const*>(this + 1);
|
||||||
|
return QualType::getFromOpaquePtr(TypesAndInfos[2*I]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Retrieve a particular expansion type source info within an
|
||||||
|
/// expanded parameter pack.
|
||||||
|
TypeSourceInfo *getExpansionTypeSourceInfo(unsigned I) const {
|
||||||
|
assert(I < NumExpandedTypes && "Out-of-range expansion type index");
|
||||||
|
void * const *TypesAndInfos = reinterpret_cast<void * const*>(this + 1);
|
||||||
|
return static_cast<TypeSourceInfo *>(TypesAndInfos[2*I+1]);
|
||||||
|
}
|
||||||
|
|
||||||
// Implement isa/cast/dyncast/etc.
|
// Implement isa/cast/dyncast/etc.
|
||||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||||
static bool classof(const NonTypeTemplateParmDecl *D) { return true; }
|
static bool classof(const NonTypeTemplateParmDecl *D) { return true; }
|
||||||
|
|
|
@ -3028,6 +3028,7 @@ public:
|
||||||
NamedDecl *Template,
|
NamedDecl *Template,
|
||||||
SourceLocation TemplateLoc,
|
SourceLocation TemplateLoc,
|
||||||
SourceLocation RAngleLoc,
|
SourceLocation RAngleLoc,
|
||||||
|
unsigned ArgumentPackIndex,
|
||||||
llvm::SmallVectorImpl<TemplateArgument> &Converted,
|
llvm::SmallVectorImpl<TemplateArgument> &Converted,
|
||||||
CheckTemplateArgumentKind CTAK = CTAK_Specified);
|
CheckTemplateArgumentKind CTAK = CTAK_Specified);
|
||||||
|
|
||||||
|
|
|
@ -728,7 +728,10 @@ namespace clang {
|
||||||
/// \brief A record containing CXXBaseSpecifiers.
|
/// \brief A record containing CXXBaseSpecifiers.
|
||||||
DECL_CXX_BASE_SPECIFIERS,
|
DECL_CXX_BASE_SPECIFIERS,
|
||||||
/// \brief A IndirectFieldDecl record.
|
/// \brief A IndirectFieldDecl record.
|
||||||
DECL_INDIRECTFIELD
|
DECL_INDIRECTFIELD,
|
||||||
|
/// \brief A NonTypeTemplateParmDecl record that stores an expanded
|
||||||
|
/// non-type template parameter pack.
|
||||||
|
DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief Record codes for each kind of statement or expression.
|
/// \brief Record codes for each kind of statement or expression.
|
||||||
|
|
|
@ -69,6 +69,13 @@ ASTContext::CanonicalTemplateTemplateParm::Profile(llvm::FoldingSetNodeID &ID,
|
||||||
ID.AddInteger(1);
|
ID.AddInteger(1);
|
||||||
ID.AddBoolean(NTTP->isParameterPack());
|
ID.AddBoolean(NTTP->isParameterPack());
|
||||||
ID.AddPointer(NTTP->getType().getAsOpaquePtr());
|
ID.AddPointer(NTTP->getType().getAsOpaquePtr());
|
||||||
|
if (NTTP->isExpandedParameterPack()) {
|
||||||
|
ID.AddBoolean(true);
|
||||||
|
ID.AddInteger(NTTP->getNumExpansionTypes());
|
||||||
|
for (unsigned I = 0, N = NTTP->getNumExpansionTypes(); I != N; ++I)
|
||||||
|
ID.AddPointer(NTTP->getExpansionType(I).getAsOpaquePtr());
|
||||||
|
} else
|
||||||
|
ID.AddBoolean(false);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,15 +111,40 @@ ASTContext::getCanonicalTemplateTemplateParmDecl(
|
||||||
TTP->getIndex(), 0, false,
|
TTP->getIndex(), 0, false,
|
||||||
TTP->isParameterPack()));
|
TTP->isParameterPack()));
|
||||||
else if (NonTypeTemplateParmDecl *NTTP
|
else if (NonTypeTemplateParmDecl *NTTP
|
||||||
= dyn_cast<NonTypeTemplateParmDecl>(*P))
|
= dyn_cast<NonTypeTemplateParmDecl>(*P)) {
|
||||||
CanonParams.push_back(
|
QualType T = getCanonicalType(NTTP->getType());
|
||||||
NonTypeTemplateParmDecl::Create(*this, getTranslationUnitDecl(),
|
TypeSourceInfo *TInfo = getTrivialTypeSourceInfo(T);
|
||||||
SourceLocation(), NTTP->getDepth(),
|
NonTypeTemplateParmDecl *Param;
|
||||||
|
if (NTTP->isExpandedParameterPack()) {
|
||||||
|
llvm::SmallVector<QualType, 2> ExpandedTypes;
|
||||||
|
llvm::SmallVector<TypeSourceInfo *, 2> ExpandedTInfos;
|
||||||
|
for (unsigned I = 0, N = NTTP->getNumExpansionTypes(); I != N; ++I) {
|
||||||
|
ExpandedTypes.push_back(getCanonicalType(NTTP->getExpansionType(I)));
|
||||||
|
ExpandedTInfos.push_back(
|
||||||
|
getTrivialTypeSourceInfo(ExpandedTypes.back()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Param = NonTypeTemplateParmDecl::Create(*this, getTranslationUnitDecl(),
|
||||||
|
SourceLocation(),
|
||||||
|
NTTP->getDepth(),
|
||||||
NTTP->getPosition(), 0,
|
NTTP->getPosition(), 0,
|
||||||
getCanonicalType(NTTP->getType()),
|
T,
|
||||||
|
TInfo,
|
||||||
|
ExpandedTypes.data(),
|
||||||
|
ExpandedTypes.size(),
|
||||||
|
ExpandedTInfos.data());
|
||||||
|
} else {
|
||||||
|
Param = NonTypeTemplateParmDecl::Create(*this, getTranslationUnitDecl(),
|
||||||
|
SourceLocation(),
|
||||||
|
NTTP->getDepth(),
|
||||||
|
NTTP->getPosition(), 0,
|
||||||
|
T,
|
||||||
NTTP->isParameterPack(),
|
NTTP->isParameterPack(),
|
||||||
0));
|
TInfo);
|
||||||
else
|
}
|
||||||
|
CanonParams.push_back(Param);
|
||||||
|
|
||||||
|
} else
|
||||||
CanonParams.push_back(getCanonicalTemplateTemplateParmDecl(
|
CanonParams.push_back(getCanonicalTemplateTemplateParmDecl(
|
||||||
cast<TemplateTemplateParmDecl>(*P)));
|
cast<TemplateTemplateParmDecl>(*P)));
|
||||||
}
|
}
|
||||||
|
@ -1071,7 +1103,7 @@ TypeSourceInfo *ASTContext::CreateTypeSourceInfo(QualType T,
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeSourceInfo *ASTContext::getTrivialTypeSourceInfo(QualType T,
|
TypeSourceInfo *ASTContext::getTrivialTypeSourceInfo(QualType T,
|
||||||
SourceLocation L) {
|
SourceLocation L) const {
|
||||||
TypeSourceInfo *DI = CreateTypeSourceInfo(T);
|
TypeSourceInfo *DI = CreateTypeSourceInfo(T);
|
||||||
DI->getTypeLoc().initialize(L);
|
DI->getTypeLoc().initialize(L);
|
||||||
return DI;
|
return DI;
|
||||||
|
|
|
@ -133,11 +133,21 @@ getLVForTemplateParameterList(const TemplateParameterList *Params) {
|
||||||
for (TemplateParameterList::const_iterator P = Params->begin(),
|
for (TemplateParameterList::const_iterator P = Params->begin(),
|
||||||
PEnd = Params->end();
|
PEnd = Params->end();
|
||||||
P != PEnd; ++P) {
|
P != PEnd; ++P) {
|
||||||
if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P))
|
if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
|
||||||
|
if (NTTP->isExpandedParameterPack()) {
|
||||||
|
for (unsigned I = 0, N = NTTP->getNumExpansionTypes(); I != N; ++I) {
|
||||||
|
QualType T = NTTP->getExpansionType(I);
|
||||||
|
if (!T->isDependentType())
|
||||||
|
LV = merge(LV, T->getLinkageAndVisibility());
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!NTTP->getType()->isDependentType()) {
|
if (!NTTP->getType()->isDependentType()) {
|
||||||
LV = merge(LV, NTTP->getType()->getLinkageAndVisibility());
|
LV = merge(LV, NTTP->getType()->getLinkageAndVisibility());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (TemplateTemplateParmDecl *TTP
|
if (TemplateTemplateParmDecl *TTP
|
||||||
= dyn_cast<TemplateTemplateParmDecl>(*P)) {
|
= dyn_cast<TemplateTemplateParmDecl>(*P)) {
|
||||||
|
|
|
@ -50,22 +50,31 @@ TemplateParameterList::Create(const ASTContext &C, SourceLocation TemplateLoc,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned TemplateParameterList::getMinRequiredArguments() const {
|
unsigned TemplateParameterList::getMinRequiredArguments() const {
|
||||||
unsigned NumRequiredArgs = size();
|
unsigned NumRequiredArgs = 0;
|
||||||
iterator Param = const_cast<TemplateParameterList *>(this)->end(),
|
for (iterator P = const_cast<TemplateParameterList *>(this)->begin(),
|
||||||
ParamBegin = const_cast<TemplateParameterList *>(this)->begin();
|
PEnd = const_cast<TemplateParameterList *>(this)->end();
|
||||||
while (Param != ParamBegin) {
|
P != PEnd; ++P) {
|
||||||
--Param;
|
if ((*P)->isTemplateParameterPack()) {
|
||||||
|
if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P))
|
||||||
|
if (NTTP->isExpandedParameterPack()) {
|
||||||
|
NumRequiredArgs += NTTP->getNumExpansionTypes();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(*Param)->isTemplateParameterPack() &&
|
break;
|
||||||
!(isa<TemplateTypeParmDecl>(*Param) &&
|
}
|
||||||
cast<TemplateTypeParmDecl>(*Param)->hasDefaultArgument()) &&
|
|
||||||
!(isa<NonTypeTemplateParmDecl>(*Param) &&
|
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
|
||||||
cast<NonTypeTemplateParmDecl>(*Param)->hasDefaultArgument()) &&
|
if (TTP->hasDefaultArgument())
|
||||||
!(isa<TemplateTemplateParmDecl>(*Param) &&
|
break;
|
||||||
cast<TemplateTemplateParmDecl>(*Param)->hasDefaultArgument()))
|
} else if (NonTypeTemplateParmDecl *NTTP
|
||||||
|
= dyn_cast<NonTypeTemplateParmDecl>(*P)) {
|
||||||
|
if (NTTP->hasDefaultArgument())
|
||||||
|
break;
|
||||||
|
} else if (cast<TemplateTemplateParmDecl>(*P)->hasDefaultArgument())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
--NumRequiredArgs;
|
++NumRequiredArgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NumRequiredArgs;
|
return NumRequiredArgs;
|
||||||
|
@ -391,6 +400,28 @@ unsigned TemplateTypeParmDecl::getIndex() const {
|
||||||
// NonTypeTemplateParmDecl Method Implementations
|
// NonTypeTemplateParmDecl Method Implementations
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
NonTypeTemplateParmDecl::NonTypeTemplateParmDecl(DeclContext *DC,
|
||||||
|
SourceLocation L, unsigned D,
|
||||||
|
unsigned P, IdentifierInfo *Id,
|
||||||
|
QualType T,
|
||||||
|
TypeSourceInfo *TInfo,
|
||||||
|
const QualType *ExpandedTypes,
|
||||||
|
unsigned NumExpandedTypes,
|
||||||
|
TypeSourceInfo **ExpandedTInfos)
|
||||||
|
: VarDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo, SC_None, SC_None),
|
||||||
|
TemplateParmPosition(D, P), DefaultArgumentAndInherited(0, false),
|
||||||
|
ParameterPack(true), ExpandedParameterPack(true),
|
||||||
|
NumExpandedTypes(NumExpandedTypes)
|
||||||
|
{
|
||||||
|
if (ExpandedTypes && ExpandedTInfos) {
|
||||||
|
void **TypesAndInfos = reinterpret_cast<void **>(this + 1);
|
||||||
|
for (unsigned I = 0; I != NumExpandedTypes; ++I) {
|
||||||
|
TypesAndInfos[2*I] = ExpandedTypes[I].getAsOpaquePtr();
|
||||||
|
TypesAndInfos[2*I + 1] = ExpandedTInfos[I];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NonTypeTemplateParmDecl *
|
NonTypeTemplateParmDecl *
|
||||||
NonTypeTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
|
NonTypeTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
|
||||||
SourceLocation L, unsigned D, unsigned P,
|
SourceLocation L, unsigned D, unsigned P,
|
||||||
|
@ -400,6 +431,22 @@ NonTypeTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
|
||||||
TInfo);
|
TInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NonTypeTemplateParmDecl *
|
||||||
|
NonTypeTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
|
||||||
|
SourceLocation L, unsigned D, unsigned P,
|
||||||
|
IdentifierInfo *Id, QualType T,
|
||||||
|
TypeSourceInfo *TInfo,
|
||||||
|
const QualType *ExpandedTypes,
|
||||||
|
unsigned NumExpandedTypes,
|
||||||
|
TypeSourceInfo **ExpandedTInfos) {
|
||||||
|
unsigned Size = sizeof(NonTypeTemplateParmDecl)
|
||||||
|
+ NumExpandedTypes * 2 * sizeof(void*);
|
||||||
|
void *Mem = C.Allocate(Size);
|
||||||
|
return new (Mem) NonTypeTemplateParmDecl(DC, L, D, P, Id, T, TInfo,
|
||||||
|
ExpandedTypes, NumExpandedTypes,
|
||||||
|
ExpandedTInfos);
|
||||||
|
}
|
||||||
|
|
||||||
SourceLocation NonTypeTemplateParmDecl::getDefaultArgumentLoc() const {
|
SourceLocation NonTypeTemplateParmDecl::getDefaultArgumentLoc() const {
|
||||||
return hasDefaultArgument()
|
return hasDefaultArgument()
|
||||||
? getDefaultArgument()->getSourceRange().getBegin()
|
? getDefaultArgument()->getSourceRange().getBegin()
|
||||||
|
|
|
@ -911,8 +911,11 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
|
||||||
|
|
||||||
// type-name
|
// type-name
|
||||||
case tok::annot_typename: {
|
case tok::annot_typename: {
|
||||||
|
if (getTypeAnnotation(Tok))
|
||||||
DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID,
|
DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID,
|
||||||
getTypeAnnotation(Tok));
|
getTypeAnnotation(Tok));
|
||||||
|
else
|
||||||
|
DS.SetTypeSpecError();
|
||||||
|
|
||||||
DS.SetRangeEnd(Tok.getAnnotationEndLoc());
|
DS.SetRangeEnd(Tok.getAnnotationEndLoc());
|
||||||
ConsumeToken();
|
ConsumeToken();
|
||||||
|
|
|
@ -5967,8 +5967,6 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) {
|
||||||
cast<NonTypeTemplateParmDecl>(Params->getParam(0));
|
cast<NonTypeTemplateParmDecl>(Params->getParam(0));
|
||||||
|
|
||||||
// The template parameter must be a char parameter pack.
|
// The template parameter must be a char parameter pack.
|
||||||
// FIXME: This test will always fail because non-type parameter packs
|
|
||||||
// have not been implemented.
|
|
||||||
if (PmDecl && PmDecl->isTemplateParameterPack() &&
|
if (PmDecl && PmDecl->isTemplateParameterPack() &&
|
||||||
Context.hasSameType(PmDecl->getType(), Context.CharTy))
|
Context.hasSameType(PmDecl->getType(), Context.CharTy))
|
||||||
Valid = true;
|
Valid = true;
|
||||||
|
|
|
@ -2197,11 +2197,36 @@ Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template,
|
||||||
|
|
||||||
/// \brief Check that the given template argument corresponds to the given
|
/// \brief Check that the given template argument corresponds to the given
|
||||||
/// template parameter.
|
/// template parameter.
|
||||||
|
///
|
||||||
|
/// \param Param The template parameter against which the argument will be
|
||||||
|
/// checked.
|
||||||
|
///
|
||||||
|
/// \param Arg The template argument.
|
||||||
|
///
|
||||||
|
/// \param Template The template in which the template argument resides.
|
||||||
|
///
|
||||||
|
/// \param TemplateLoc The location of the template name for the template
|
||||||
|
/// whose argument list we're matching.
|
||||||
|
///
|
||||||
|
/// \param RAngleLoc The location of the right angle bracket ('>') that closes
|
||||||
|
/// the template argument list.
|
||||||
|
///
|
||||||
|
/// \param ArgumentPackIndex The index into the argument pack where this
|
||||||
|
/// argument will be placed. Only valid if the parameter is a parameter pack.
|
||||||
|
///
|
||||||
|
/// \param Converted The checked, converted argument will be added to the
|
||||||
|
/// end of this small vector.
|
||||||
|
///
|
||||||
|
/// \param CTAK Describes how we arrived at this particular template argument:
|
||||||
|
/// explicitly written, deduced, etc.
|
||||||
|
///
|
||||||
|
/// \returns true on error, false otherwise.
|
||||||
bool Sema::CheckTemplateArgument(NamedDecl *Param,
|
bool Sema::CheckTemplateArgument(NamedDecl *Param,
|
||||||
const TemplateArgumentLoc &Arg,
|
const TemplateArgumentLoc &Arg,
|
||||||
NamedDecl *Template,
|
NamedDecl *Template,
|
||||||
SourceLocation TemplateLoc,
|
SourceLocation TemplateLoc,
|
||||||
SourceLocation RAngleLoc,
|
SourceLocation RAngleLoc,
|
||||||
|
unsigned ArgumentPackIndex,
|
||||||
llvm::SmallVectorImpl<TemplateArgument> &Converted,
|
llvm::SmallVectorImpl<TemplateArgument> &Converted,
|
||||||
CheckTemplateArgumentKind CTAK) {
|
CheckTemplateArgumentKind CTAK) {
|
||||||
// Check template type parameters.
|
// Check template type parameters.
|
||||||
|
@ -2214,6 +2239,9 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
|
||||||
// with the template arguments we've seen thus far. But if the
|
// with the template arguments we've seen thus far. But if the
|
||||||
// template has a dependent context then we cannot substitute yet.
|
// template has a dependent context then we cannot substitute yet.
|
||||||
QualType NTTPType = NTTP->getType();
|
QualType NTTPType = NTTP->getType();
|
||||||
|
if (NTTP->isParameterPack() && NTTP->isExpandedParameterPack())
|
||||||
|
NTTPType = NTTP->getExpansionType(ArgumentPackIndex);
|
||||||
|
|
||||||
if (NTTPType->isDependentType() &&
|
if (NTTPType->isDependentType() &&
|
||||||
!isa<TemplateTemplateParmDecl>(Template) &&
|
!isa<TemplateTemplateParmDecl>(Template) &&
|
||||||
!Template->getDeclContext()->isDependentContext()) {
|
!Template->getDeclContext()->isDependentContext()) {
|
||||||
|
@ -2447,9 +2475,28 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (ArgIdx < NumArgs) {
|
if (ArgIdx < NumArgs) {
|
||||||
|
// If we have an expanded parameter pack, make sure we don't have too
|
||||||
|
// many arguments.
|
||||||
|
if (NonTypeTemplateParmDecl *NTTP
|
||||||
|
= dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
|
||||||
|
if (NTTP->isExpandedParameterPack() &&
|
||||||
|
ArgumentPack.size() >= NTTP->getNumExpansionTypes()) {
|
||||||
|
Diag(TemplateLoc, diag::err_template_arg_list_different_arity)
|
||||||
|
<< true
|
||||||
|
<< (isa<ClassTemplateDecl>(Template)? 0 :
|
||||||
|
isa<FunctionTemplateDecl>(Template)? 1 :
|
||||||
|
isa<TemplateTemplateParmDecl>(Template)? 2 : 3)
|
||||||
|
<< Template;
|
||||||
|
Diag(Template->getLocation(), diag::note_template_decl_here)
|
||||||
|
<< Params->getSourceRange();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check the template argument we were given.
|
// Check the template argument we were given.
|
||||||
if (CheckTemplateArgument(*Param, TemplateArgs[ArgIdx], Template,
|
if (CheckTemplateArgument(*Param, TemplateArgs[ArgIdx], Template,
|
||||||
TemplateLoc, RAngleLoc, Converted))
|
TemplateLoc, RAngleLoc,
|
||||||
|
ArgumentPack.size(), Converted))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if ((*Param)->isTemplateParameterPack()) {
|
if ((*Param)->isTemplateParameterPack()) {
|
||||||
|
@ -2544,7 +2591,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
|
||||||
|
|
||||||
// Check the default template argument.
|
// Check the default template argument.
|
||||||
if (CheckTemplateArgument(*Param, Arg, Template, TemplateLoc,
|
if (CheckTemplateArgument(*Param, Arg, Template, TemplateLoc,
|
||||||
RAngleLoc, Converted))
|
RAngleLoc, 0, Converted))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Move to the next template parameter and argument.
|
// Move to the next template parameter and argument.
|
||||||
|
|
|
@ -1705,6 +1705,7 @@ static bool ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
|
||||||
DeducedTemplateArgument Arg,
|
DeducedTemplateArgument Arg,
|
||||||
NamedDecl *Template,
|
NamedDecl *Template,
|
||||||
QualType NTTPType,
|
QualType NTTPType,
|
||||||
|
unsigned ArgumentPackIndex,
|
||||||
TemplateDeductionInfo &Info,
|
TemplateDeductionInfo &Info,
|
||||||
bool InFunctionTemplate,
|
bool InFunctionTemplate,
|
||||||
llvm::SmallVectorImpl<TemplateArgument> &Output) {
|
llvm::SmallVectorImpl<TemplateArgument> &Output) {
|
||||||
|
@ -1721,8 +1722,8 @@ static bool ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
|
||||||
DeducedTemplateArgument InnerArg(*PA);
|
DeducedTemplateArgument InnerArg(*PA);
|
||||||
InnerArg.setDeducedFromArrayBound(Arg.wasDeducedFromArrayBound());
|
InnerArg.setDeducedFromArrayBound(Arg.wasDeducedFromArrayBound());
|
||||||
if (ConvertDeducedTemplateArgument(S, Param, InnerArg, Template,
|
if (ConvertDeducedTemplateArgument(S, Param, InnerArg, Template,
|
||||||
NTTPType, Info,
|
NTTPType, PackedArgsBuilder.size(),
|
||||||
InFunctionTemplate, Output))
|
Info, InFunctionTemplate, Output))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Move the converted template argument into our argument pack.
|
// Move the converted template argument into our argument pack.
|
||||||
|
@ -1748,6 +1749,7 @@ static bool ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
|
||||||
Template,
|
Template,
|
||||||
Template->getLocation(),
|
Template->getLocation(),
|
||||||
Template->getSourceRange().getEnd(),
|
Template->getSourceRange().getEnd(),
|
||||||
|
ArgumentPackIndex,
|
||||||
Output,
|
Output,
|
||||||
InFunctionTemplate
|
InFunctionTemplate
|
||||||
? (Arg.wasDeducedFromArrayBound()
|
? (Arg.wasDeducedFromArrayBound()
|
||||||
|
@ -1810,7 +1812,7 @@ FinishTemplateArgumentDeduction(Sema &S,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ConvertDeducedTemplateArgument(S, Param, Deduced[I],
|
if (ConvertDeducedTemplateArgument(S, Param, Deduced[I],
|
||||||
Partial, NTTPType, Info, false,
|
Partial, NTTPType, 0, Info, false,
|
||||||
Builder)) {
|
Builder)) {
|
||||||
Info.Param = makeTemplateParameter(Param);
|
Info.Param = makeTemplateParameter(Param);
|
||||||
// FIXME: These template arguments are temporary. Free them!
|
// FIXME: These template arguments are temporary. Free them!
|
||||||
|
@ -2160,7 +2162,7 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ConvertDeducedTemplateArgument(*this, Param, Deduced[I],
|
if (ConvertDeducedTemplateArgument(*this, Param, Deduced[I],
|
||||||
FunctionTemplate, NTTPType, Info,
|
FunctionTemplate, NTTPType, 0, Info,
|
||||||
true, Builder)) {
|
true, Builder)) {
|
||||||
Info.Param = makeTemplateParameter(Param);
|
Info.Param = makeTemplateParameter(Param);
|
||||||
// FIXME: These template arguments are temporary. Free them!
|
// FIXME: These template arguments are temporary. Free them!
|
||||||
|
@ -2212,7 +2214,7 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
|
||||||
FunctionTemplate,
|
FunctionTemplate,
|
||||||
FunctionTemplate->getLocation(),
|
FunctionTemplate->getLocation(),
|
||||||
FunctionTemplate->getSourceRange().getEnd(),
|
FunctionTemplate->getSourceRange().getEnd(),
|
||||||
Builder,
|
0, Builder,
|
||||||
CTAK_Deduced)) {
|
CTAK_Deduced)) {
|
||||||
Info.Param = makeTemplateParameter(
|
Info.Param = makeTemplateParameter(
|
||||||
const_cast<NamedDecl *>(TemplateParams->getParam(I)));
|
const_cast<NamedDecl *>(TemplateParams->getParam(I)));
|
||||||
|
|
|
@ -1016,9 +1016,19 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
|
||||||
|
|
||||||
// Derive the type we want the substituted decl to have. This had
|
// Derive the type we want the substituted decl to have. This had
|
||||||
// better be non-dependent, or these checks will have serious problems.
|
// better be non-dependent, or these checks will have serious problems.
|
||||||
QualType TargetType = SemaRef.SubstType(NTTP->getType(), TemplateArgs,
|
QualType TargetType;
|
||||||
E->getLocation(),
|
if (NTTP->isExpandedParameterPack())
|
||||||
DeclarationName());
|
TargetType = NTTP->getExpansionType(
|
||||||
|
getSema().ArgumentPackSubstitutionIndex);
|
||||||
|
else if (NTTP->isParameterPack() &&
|
||||||
|
isa<PackExpansionType>(NTTP->getType())) {
|
||||||
|
TargetType = SemaRef.SubstType(
|
||||||
|
cast<PackExpansionType>(NTTP->getType())->getPattern(),
|
||||||
|
TemplateArgs, E->getLocation(),
|
||||||
|
NTTP->getDeclName());
|
||||||
|
} else
|
||||||
|
TargetType = SemaRef.SubstType(NTTP->getType(), TemplateArgs,
|
||||||
|
E->getLocation(), NTTP->getDeclName());
|
||||||
assert(!TargetType.isNull() && "type substitution failed for param type");
|
assert(!TargetType.isNull() && "type substitution failed for param type");
|
||||||
assert(!TargetType->isDependentType() && "param type still dependent");
|
assert(!TargetType->isDependentType() && "param type still dependent");
|
||||||
return SemaRef.BuildExpressionFromDeclTemplateArgument(Arg,
|
return SemaRef.BuildExpressionFromDeclTemplateArgument(Arg,
|
||||||
|
@ -1038,7 +1048,6 @@ TemplateInstantiator::TransformSubstNonTypeTemplateParmPackExpr(
|
||||||
return getSema().Owned(E);
|
return getSema().Owned(E);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Variadic templates select Nth from type?
|
|
||||||
const TemplateArgument &ArgPack = E->getArgumentPack();
|
const TemplateArgument &ArgPack = E->getArgumentPack();
|
||||||
unsigned Index = (unsigned)getSema().ArgumentPackSubstitutionIndex;
|
unsigned Index = (unsigned)getSema().ArgumentPackSubstitutionIndex;
|
||||||
assert(Index < ArgPack.pack_size() && "Substitution index out-of-range");
|
assert(Index < ArgPack.pack_size() && "Substitution index out-of-range");
|
||||||
|
@ -1058,8 +1067,17 @@ TemplateInstantiator::TransformSubstNonTypeTemplateParmPackExpr(
|
||||||
if (!VD)
|
if (!VD)
|
||||||
return ExprError();
|
return ExprError();
|
||||||
|
|
||||||
return SemaRef.BuildExpressionFromDeclTemplateArgument(Arg,
|
QualType T;
|
||||||
E->getType(),
|
NonTypeTemplateParmDecl *NTTP = E->getParameterPack();
|
||||||
|
if (NTTP->isExpandedParameterPack())
|
||||||
|
T = NTTP->getExpansionType(getSema().ArgumentPackSubstitutionIndex);
|
||||||
|
else if (const PackExpansionType *Expansion
|
||||||
|
= dyn_cast<PackExpansionType>(NTTP->getType()))
|
||||||
|
T = SemaRef.SubstType(Expansion->getPattern(), TemplateArgs,
|
||||||
|
E->getParameterPackLocation(), NTTP->getDeclName());
|
||||||
|
else
|
||||||
|
T = E->getType();
|
||||||
|
return SemaRef.BuildExpressionFromDeclTemplateArgument(Arg, T,
|
||||||
E->getParameterPackLocation());
|
E->getParameterPackLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1778,6 +1796,11 @@ Sema::InstantiateClassTemplateSpecialization(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we're dealing with a member template where the template parameters
|
||||||
|
// have been instantiated, this provides the original template parameters
|
||||||
|
// from which the member template's parameters were instantiated.
|
||||||
|
llvm::SmallVector<const NamedDecl *, 4> InstantiatedTemplateParameters;
|
||||||
|
|
||||||
if (Matched.size() >= 1) {
|
if (Matched.size() >= 1) {
|
||||||
llvm::SmallVector<MatchResult, 4>::iterator Best = Matched.begin();
|
llvm::SmallVector<MatchResult, 4>::iterator Best = Matched.begin();
|
||||||
if (Matched.size() == 1) {
|
if (Matched.size() == 1) {
|
||||||
|
|
|
@ -1455,28 +1455,140 @@ Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl(
|
||||||
Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl(
|
Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl(
|
||||||
NonTypeTemplateParmDecl *D) {
|
NonTypeTemplateParmDecl *D) {
|
||||||
// Substitute into the type of the non-type template parameter.
|
// Substitute into the type of the non-type template parameter.
|
||||||
|
TypeLoc TL = D->getTypeSourceInfo()->getTypeLoc();
|
||||||
|
llvm::SmallVector<TypeSourceInfo *, 4> ExpandedParameterPackTypesAsWritten;
|
||||||
|
llvm::SmallVector<QualType, 4> ExpandedParameterPackTypes;
|
||||||
|
bool IsExpandedParameterPack = false;
|
||||||
|
TypeSourceInfo *DI;
|
||||||
QualType T;
|
QualType T;
|
||||||
TypeSourceInfo *DI = SemaRef.SubstType(D->getTypeSourceInfo(), TemplateArgs, D->getLocation(),
|
bool Invalid = false;
|
||||||
|
|
||||||
|
if (D->isExpandedParameterPack()) {
|
||||||
|
// The non-type template parameter pack is an already-expanded pack
|
||||||
|
// expansion of types. Substitute into each of the expanded types.
|
||||||
|
ExpandedParameterPackTypes.reserve(D->getNumExpansionTypes());
|
||||||
|
ExpandedParameterPackTypesAsWritten.reserve(D->getNumExpansionTypes());
|
||||||
|
for (unsigned I = 0, N = D->getNumExpansionTypes(); I != N; ++I) {
|
||||||
|
TypeSourceInfo *NewDI =SemaRef.SubstType(D->getExpansionTypeSourceInfo(I),
|
||||||
|
TemplateArgs,
|
||||||
|
D->getLocation(),
|
||||||
D->getDeclName());
|
D->getDeclName());
|
||||||
|
if (!NewDI)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ExpandedParameterPackTypesAsWritten.push_back(NewDI);
|
||||||
|
QualType NewT =SemaRef.CheckNonTypeTemplateParameterType(NewDI->getType(),
|
||||||
|
D->getLocation());
|
||||||
|
if (NewT.isNull())
|
||||||
|
return 0;
|
||||||
|
ExpandedParameterPackTypes.push_back(NewT);
|
||||||
|
}
|
||||||
|
|
||||||
|
IsExpandedParameterPack = true;
|
||||||
|
DI = D->getTypeSourceInfo();
|
||||||
|
T = DI->getType();
|
||||||
|
} else if (isa<PackExpansionTypeLoc>(TL)) {
|
||||||
|
// The non-type template parameter pack's type is a pack expansion of types.
|
||||||
|
// Determine whether we need to expand this parameter pack into separate
|
||||||
|
// types.
|
||||||
|
PackExpansionTypeLoc Expansion = cast<PackExpansionTypeLoc>(TL);
|
||||||
|
TypeLoc Pattern = Expansion.getPatternLoc();
|
||||||
|
llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
|
||||||
|
SemaRef.collectUnexpandedParameterPacks(Pattern, Unexpanded);
|
||||||
|
|
||||||
|
// Determine whether the set of unexpanded parameter packs can and should
|
||||||
|
// be expanded.
|
||||||
|
bool Expand = true;
|
||||||
|
bool RetainExpansion = false;
|
||||||
|
llvm::Optional<unsigned> OrigNumExpansions
|
||||||
|
= Expansion.getTypePtr()->getNumExpansions();
|
||||||
|
llvm::Optional<unsigned> NumExpansions = OrigNumExpansions;
|
||||||
|
if (SemaRef.CheckParameterPacksForExpansion(Expansion.getEllipsisLoc(),
|
||||||
|
Pattern.getSourceRange(),
|
||||||
|
Unexpanded.data(),
|
||||||
|
Unexpanded.size(),
|
||||||
|
TemplateArgs,
|
||||||
|
Expand, RetainExpansion,
|
||||||
|
NumExpansions))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (Expand) {
|
||||||
|
for (unsigned I = 0; I != *NumExpansions; ++I) {
|
||||||
|
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, I);
|
||||||
|
TypeSourceInfo *NewDI = SemaRef.SubstType(Pattern, TemplateArgs,
|
||||||
|
D->getLocation(),
|
||||||
|
D->getDeclName());
|
||||||
|
if (!NewDI)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ExpandedParameterPackTypesAsWritten.push_back(NewDI);
|
||||||
|
QualType NewT = SemaRef.CheckNonTypeTemplateParameterType(
|
||||||
|
NewDI->getType(),
|
||||||
|
D->getLocation());
|
||||||
|
if (NewT.isNull())
|
||||||
|
return 0;
|
||||||
|
ExpandedParameterPackTypes.push_back(NewT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note that we have an expanded parameter pack. The "type" of this
|
||||||
|
// expanded parameter pack is the original expansion type, but callers
|
||||||
|
// will end up using the expanded parameter pack types for type-checking.
|
||||||
|
IsExpandedParameterPack = true;
|
||||||
|
DI = D->getTypeSourceInfo();
|
||||||
|
T = DI->getType();
|
||||||
|
} else {
|
||||||
|
// We cannot fully expand the pack expansion now, so substitute into the
|
||||||
|
// pattern and create a new pack expansion type.
|
||||||
|
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, -1);
|
||||||
|
TypeSourceInfo *NewPattern = SemaRef.SubstType(Pattern, TemplateArgs,
|
||||||
|
D->getLocation(),
|
||||||
|
D->getDeclName());
|
||||||
|
if (!NewPattern)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
DI = SemaRef.CheckPackExpansion(NewPattern, Expansion.getEllipsisLoc(),
|
||||||
|
NumExpansions);
|
||||||
if (!DI)
|
if (!DI)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
T = DI->getType();
|
T = DI->getType();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Simple case: substitution into a parameter that is not a parameter pack.
|
||||||
|
DI = SemaRef.SubstType(D->getTypeSourceInfo(), TemplateArgs,
|
||||||
|
D->getLocation(), D->getDeclName());
|
||||||
|
if (!DI)
|
||||||
|
return 0;
|
||||||
|
|
||||||
// Check that this type is acceptable for a non-type template parameter.
|
// Check that this type is acceptable for a non-type template parameter.
|
||||||
bool Invalid = false;
|
bool Invalid = false;
|
||||||
T = SemaRef.CheckNonTypeTemplateParameterType(T, D->getLocation());
|
T = SemaRef.CheckNonTypeTemplateParameterType(DI->getType(),
|
||||||
|
D->getLocation());
|
||||||
if (T.isNull()) {
|
if (T.isNull()) {
|
||||||
T = SemaRef.Context.IntTy;
|
T = SemaRef.Context.IntTy;
|
||||||
Invalid = true;
|
Invalid = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: Variadic templates.
|
NonTypeTemplateParmDecl *Param;
|
||||||
NonTypeTemplateParmDecl *Param
|
if (IsExpandedParameterPack)
|
||||||
= NonTypeTemplateParmDecl::Create(SemaRef.Context, Owner, D->getLocation(),
|
Param = NonTypeTemplateParmDecl::Create(SemaRef.Context, Owner,
|
||||||
|
D->getLocation(),
|
||||||
D->getDepth() - TemplateArgs.getNumLevels(),
|
D->getDepth() - TemplateArgs.getNumLevels(),
|
||||||
D->getPosition(), D->getIdentifier(), T,
|
D->getPosition(),
|
||||||
|
D->getIdentifier(), T,
|
||||||
|
DI,
|
||||||
|
ExpandedParameterPackTypes.data(),
|
||||||
|
ExpandedParameterPackTypes.size(),
|
||||||
|
ExpandedParameterPackTypesAsWritten.data());
|
||||||
|
else
|
||||||
|
Param = NonTypeTemplateParmDecl::Create(SemaRef.Context, Owner,
|
||||||
|
D->getLocation(),
|
||||||
|
D->getDepth() - TemplateArgs.getNumLevels(),
|
||||||
|
D->getPosition(),
|
||||||
|
D->getIdentifier(), T,
|
||||||
D->isParameterPack(), DI);
|
D->isParameterPack(), DI);
|
||||||
|
|
||||||
if (Invalid)
|
if (Invalid)
|
||||||
Param->setInvalidDecl();
|
Param->setInvalidDecl();
|
||||||
|
|
||||||
|
|
|
@ -1155,6 +1155,13 @@ void ASTDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
|
||||||
// TemplateParmPosition.
|
// TemplateParmPosition.
|
||||||
D->setDepth(Record[Idx++]);
|
D->setDepth(Record[Idx++]);
|
||||||
D->setPosition(Record[Idx++]);
|
D->setPosition(Record[Idx++]);
|
||||||
|
if (D->isExpandedParameterPack()) {
|
||||||
|
void **Data = reinterpret_cast<void **>(D + 1);
|
||||||
|
for (unsigned I = 0, N = D->getNumExpansionTypes(); I != N; ++I) {
|
||||||
|
Data[2*I] = Reader.GetType(Record[Idx++]).getAsOpaquePtr();
|
||||||
|
Data[2*I + 1] = GetTypeSourceInfo(Record, Idx);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
// Rest of NonTypeTemplateParmDecl.
|
// Rest of NonTypeTemplateParmDecl.
|
||||||
D->ParameterPack = Record[Idx++];
|
D->ParameterPack = Record[Idx++];
|
||||||
if (Record[Idx++]) {
|
if (Record[Idx++]) {
|
||||||
|
@ -1162,6 +1169,7 @@ void ASTDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
|
||||||
bool Inherited = Record[Idx++];
|
bool Inherited = Record[Idx++];
|
||||||
D->setDefaultArgument(DefArg, Inherited);
|
D->setDefaultArgument(DefArg, Inherited);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASTDeclReader::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
|
void ASTDeclReader::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
|
||||||
|
@ -1433,6 +1441,11 @@ Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) {
|
||||||
D = NonTypeTemplateParmDecl::Create(*Context, 0, SourceLocation(), 0,0,0,
|
D = NonTypeTemplateParmDecl::Create(*Context, 0, SourceLocation(), 0,0,0,
|
||||||
QualType(), false, 0);
|
QualType(), false, 0);
|
||||||
break;
|
break;
|
||||||
|
case DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK:
|
||||||
|
D = NonTypeTemplateParmDecl::Create(*Context, 0, SourceLocation(), 0, 0,
|
||||||
|
0, QualType(), 0, 0, Record[Idx++],
|
||||||
|
0);
|
||||||
|
break;
|
||||||
case DECL_TEMPLATE_TEMPLATE_PARM:
|
case DECL_TEMPLATE_TEMPLATE_PARM:
|
||||||
D = TemplateTemplateParmDecl::Create(*Context, 0, SourceLocation(), 0, 0,
|
D = TemplateTemplateParmDecl::Create(*Context, 0, SourceLocation(), 0, 0,
|
||||||
false, 0, 0);
|
false, 0, 0);
|
||||||
|
|
|
@ -988,10 +988,24 @@ void ASTDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASTDeclWriter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
|
void ASTDeclWriter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
|
||||||
|
// For an expanded parameter pack, record the number of expansion types here
|
||||||
|
// so that it's easier for
|
||||||
|
if (D->isExpandedParameterPack())
|
||||||
|
Record.push_back(D->getNumExpansionTypes());
|
||||||
|
|
||||||
VisitVarDecl(D);
|
VisitVarDecl(D);
|
||||||
// TemplateParmPosition.
|
// TemplateParmPosition.
|
||||||
Record.push_back(D->getDepth());
|
Record.push_back(D->getDepth());
|
||||||
Record.push_back(D->getPosition());
|
Record.push_back(D->getPosition());
|
||||||
|
|
||||||
|
if (D->isExpandedParameterPack()) {
|
||||||
|
for (unsigned I = 0, N = D->getNumExpansionTypes(); I != N; ++I) {
|
||||||
|
Writer.AddTypeRef(D->getExpansionType(I), Record);
|
||||||
|
Writer.AddTypeSourceInfo(D->getExpansionTypeSourceInfo(I), Record);
|
||||||
|
}
|
||||||
|
|
||||||
|
Code = serialization::DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK;
|
||||||
|
} else {
|
||||||
// Rest of NonTypeTemplateParmDecl.
|
// Rest of NonTypeTemplateParmDecl.
|
||||||
Record.push_back(D->isParameterPack());
|
Record.push_back(D->isParameterPack());
|
||||||
Record.push_back(D->getDefaultArgument() != 0);
|
Record.push_back(D->getDefaultArgument() != 0);
|
||||||
|
@ -1000,6 +1014,7 @@ void ASTDeclWriter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
|
||||||
Record.push_back(D->defaultArgumentWasInherited());
|
Record.push_back(D->defaultArgumentWasInherited());
|
||||||
}
|
}
|
||||||
Code = serialization::DECL_NON_TYPE_TEMPLATE_PARM;
|
Code = serialization::DECL_NON_TYPE_TEMPLATE_PARM;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASTDeclWriter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
|
void ASTDeclWriter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
|
||||||
|
|
|
@ -1,6 +1,20 @@
|
||||||
// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
|
// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
|
||||||
|
|
||||||
template<typename T, T ...Values> struct value_tuple {};
|
template<typename T, T ...Values> struct value_tuple {};
|
||||||
|
template<typename...> struct tuple { };
|
||||||
|
template<typename T, typename U> struct pair { };
|
||||||
|
|
||||||
|
template<typename T, T Value> struct value_c;
|
||||||
|
|
||||||
|
template<typename T, typename U>
|
||||||
|
struct is_same {
|
||||||
|
static const bool value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct is_same<T, T> {
|
||||||
|
static const bool value = true;
|
||||||
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct X0 {
|
struct X0 {
|
||||||
|
@ -13,8 +27,6 @@ void test_X0() {
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace PacksAtDifferentLevels {
|
namespace PacksAtDifferentLevels {
|
||||||
template<typename...> struct tuple { };
|
|
||||||
template<typename T, typename U> struct pair { };
|
|
||||||
|
|
||||||
template<typename ...Types>
|
template<typename ...Types>
|
||||||
struct X {
|
struct X {
|
||||||
|
@ -176,3 +188,31 @@ namespace PacksAtDifferentLevels {
|
||||||
add_const<double>>>::value == 0? 1 : -1];
|
add_const<double>>>::value == 0? 1 : -1];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace ExpandingNonTypeTemplateParameters {
|
||||||
|
template<typename ...Types>
|
||||||
|
struct tuple_of_values {
|
||||||
|
template<Types ...Values> // expected-error{{a non-type template parameter cannot have type 'float'}} \
|
||||||
|
// expected-note{{template parameter is declared here}}
|
||||||
|
struct apply { // expected-note 2{{template is declared here}}
|
||||||
|
typedef tuple<value_c<Types, Values>...> type;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
int i;
|
||||||
|
float f;
|
||||||
|
int check_tuple_of_values_1[
|
||||||
|
is_same<tuple_of_values<int&, float&, char, int>::apply<i, f, 'a', 17>
|
||||||
|
::type,
|
||||||
|
tuple<value_c<int&, i>, value_c<float&, f>, value_c<char, 'a'>,
|
||||||
|
value_c<int, 17>>
|
||||||
|
>::value? 1 : -1];
|
||||||
|
|
||||||
|
tuple_of_values<int, float> tv1; // expected-note{{in instantiation of template class 'ExpandingNonTypeTemplateParameters::tuple_of_values<int, float>' requested here}}
|
||||||
|
|
||||||
|
tuple_of_values<int&, float&>::apply<i, i>::type tv2; // expected-error{{non-type template parameter of reference type 'float &' cannot bind to template argument of type 'int'}}
|
||||||
|
|
||||||
|
tuple_of_values<int&, float&>::apply<i>::type tv3; // expected-error{{too few template arguments for class template 'apply'}}
|
||||||
|
|
||||||
|
tuple_of_values<int&, float&>::apply<i, f, i>::type tv4; // expected-error{{too many template arguments for class template 'apply'}}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue