TemplateArgument &Converted);
bool CheckTemplateArgument(TemplateTemplateParmDecl *Param,
const TemplateArgumentLoc &Arg);
+
+ /// \brief Enumeration describing how template parameter lists are compared
+ /// for equality.
+ enum TemplateParameterListEqualKind {
+ /// \brief We are matching the template parameter lists of two templates
+ /// that might be redeclarations.
+ ///
+ /// \code
+ /// template<typename T> struct X;
+ /// template<typename T> struct X;
+ /// \endcode
+ TPL_TemplateMatch,
+
+ /// \brief We are matching the template parameter lists of two template
+ /// template parameters as part of matching the template parameter lists
+ /// of two templates that might be redeclarations.
+ ///
+ /// \code
+ /// template<template<int I> class TT> struct X;
+ /// template<template<int Value> class Other> struct X;
+ /// \endcode
+ TPL_TemplateTemplateParmMatch,
+
+ /// \brief We are matching the template parameter lists of a template
+ /// template argument against the template parameter lists of a template
+ /// template parameter.
+ ///
+ /// \code
+ /// template<template<int Value> class Metafun> struct X;
+ /// template<int Value> struct integer_c;
+ /// X<integer_c> xic;
+ /// \endcode
+ TPL_TemplateTemplateArgumentMatch
+ };
+
bool TemplateParameterListsAreEqual(TemplateParameterList *New,
TemplateParameterList *Old,
bool Complain,
- bool IsTemplateTemplateParm = false,
+ TemplateParameterListEqualKind Kind,
SourceLocation TemplateArgLoc
= SourceLocation());
// Ensure that the template parameter lists are compatible.
if (!TemplateParameterListsAreEqual(TemplateParams,
PrevClassTemplate->getTemplateParameters(),
- /*Complain=*/true))
+ /*Complain=*/true,
+ TPL_TemplateMatch))
return true;
// C++ [temp.class]p4:
if (ExpectedTemplateParams)
TemplateParameterListsAreEqual(ParamLists[Idx],
ExpectedTemplateParams,
- true);
+ true, TPL_TemplateMatch);
}
} else if (ParamLists[Idx]->size() > 0)
Diag(ParamLists[Idx]->getTemplateLoc(),
return !TemplateParameterListsAreEqual(Template->getTemplateParameters(),
Param->getTemplateParameters(),
- true, true,
+ true,
+ TPL_TemplateTemplateArgumentMatch,
Arg.getLocation());
}
/// \param Complain If true, this routine will produce a diagnostic if
/// the template parameter lists are not equivalent.
///
-/// \param IsTemplateTemplateParm If true, this routine is being
-/// called to compare the template parameter lists of a template
-/// template parameter.
+/// \param Kind describes how we are to match the template parameter lists.
///
/// \param TemplateArgLoc If this source location is valid, then we
/// are actually checking the template parameter list of a template
Sema::TemplateParameterListsAreEqual(TemplateParameterList *New,
TemplateParameterList *Old,
bool Complain,
- bool IsTemplateTemplateParm,
+ TemplateParameterListEqualKind Kind,
SourceLocation TemplateArgLoc) {
if (Old->size() != New->size()) {
if (Complain) {
}
Diag(New->getTemplateLoc(), NextDiag)
<< (New->size() > Old->size())
- << IsTemplateTemplateParm
+ << (Kind != TPL_TemplateMatch)
<< SourceRange(New->getTemplateLoc(), New->getRAngleLoc());
Diag(Old->getTemplateLoc(), diag::note_template_prev_declaration)
- << IsTemplateTemplateParm
+ << (Kind != TPL_TemplateMatch)
<< SourceRange(Old->getTemplateLoc(), Old->getRAngleLoc());
}
NextDiag = diag::note_template_param_different_kind;
}
Diag((*NewParm)->getLocation(), NextDiag)
- << IsTemplateTemplateParm;
+ << (Kind != TPL_TemplateMatch);
Diag((*OldParm)->getLocation(), diag::note_template_prev_declaration)
- << IsTemplateTemplateParm;
+ << (Kind != TPL_TemplateMatch);
}
return false;
}
// The types of non-type template parameters must agree.
NonTypeTemplateParmDecl *NewNTTP
= cast<NonTypeTemplateParmDecl>(*NewParm);
+
+ // If we are matching a template template argument to a template
+ // template parameter and one of the non-type template parameter types
+ // is dependent, then we must wait until template instantiation time
+ // to actually compare the arguments.
+ if (Kind == TPL_TemplateTemplateArgumentMatch &&
+ (OldNTTP->getType()->isDependentType() ||
+ NewNTTP->getType()->isDependentType()))
+ continue;
+
if (Context.getCanonicalType(OldNTTP->getType()) !=
Context.getCanonicalType(NewNTTP->getType())) {
if (Complain) {
}
Diag(NewNTTP->getLocation(), NextDiag)
<< NewNTTP->getType()
- << IsTemplateTemplateParm;
+ << (Kind != TPL_TemplateMatch);
Diag(OldNTTP->getLocation(),
diag::note_template_nontype_parm_prev_declaration)
<< OldNTTP->getType();
if (!TemplateParameterListsAreEqual(NewTTP->getTemplateParameters(),
OldTTP->getTemplateParameters(),
Complain,
- /*IsTemplateTemplateParm=*/true,
+ (Kind == TPL_TemplateMatch? TPL_TemplateTemplateParmMatch : Kind),
TemplateArgLoc))
return false;
}