aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaTemplate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaTemplate.cpp')
-rw-r--r--lib/Sema/SemaTemplate.cpp78
1 files changed, 66 insertions, 12 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 297410471b..1a2da84642 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -555,7 +555,27 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
/// It returns true if an error occurred, and false otherwise.
bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param,
DeclRefExpr *Arg) {
- return false;
+ assert(isa<TemplateDecl>(Arg->getDecl()) && "Only template decls allowed");
+ TemplateDecl *Template = cast<TemplateDecl>(Arg->getDecl());
+
+ // C++ [temp.arg.template]p1:
+ // A template-argument for a template template-parameter shall be
+ // the name of a class template, expressed as id-expression. Only
+ // primary class templates are considered when matching the
+ // template template argument with the corresponding parameter;
+ // partial specializations are not considered even if their
+ // parameter lists match that of the template template parameter.
+ if (!isa<ClassTemplateDecl>(Template)) {
+ assert(isa<FunctionTemplateDecl>(Template) &&
+ "Only function templates are possible here");
+ Diag(Arg->getSourceRange().getBegin(), diag::note_template_arg_refers_here)
+ << Template;
+ }
+
+ return !TemplateParameterListsAreEqual(Template->getTemplateParameters(),
+ Param->getTemplateParameters(),
+ true, true,
+ Arg->getSourceRange().getBegin());
}
/// \brief Determine whether the given template parameter lists are
@@ -571,19 +591,35 @@ bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param,
/// \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 TemplateArgLoc If this source location is valid, then we
+/// are actually checking the template parameter list of a template
+/// argument (New) against the template parameter list of its
+/// corresponding template template parameter (Old). We produce
+/// slightly different diagnostics in this scenario.
+///
/// \returns True if the template parameter lists are equal, false
/// otherwise.
bool
Sema::TemplateParameterListsAreEqual(TemplateParameterList *New,
TemplateParameterList *Old,
bool Complain,
- bool IsTemplateTemplateParm) {
+ bool IsTemplateTemplateParm,
+ SourceLocation TemplateArgLoc) {
if (Old->size() != New->size()) {
if (Complain) {
- Diag(New->getTemplateLoc(), diag::err_template_param_list_different_arity)
- << (New->size() > Old->size())
- << IsTemplateTemplateParm
- << SourceRange(New->getTemplateLoc(), New->getRAngleLoc());
+ unsigned NextDiag = diag::err_template_param_list_different_arity;
+ if (TemplateArgLoc.isValid()) {
+ Diag(TemplateArgLoc, diag::err_template_arg_template_params_mismatch);
+ NextDiag = diag::note_template_param_list_different_arity;
+ }
+ Diag(New->getTemplateLoc(), NextDiag)
+ << (New->size() > Old->size())
+ << IsTemplateTemplateParm
+ << SourceRange(New->getTemplateLoc(), New->getRAngleLoc());
Diag(Old->getTemplateLoc(), diag::note_template_prev_declaration)
<< IsTemplateTemplateParm
<< SourceRange(Old->getTemplateLoc(), Old->getRAngleLoc());
@@ -596,7 +632,12 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New,
OldParmEnd = Old->end(), NewParm = New->begin();
OldParm != OldParmEnd; ++OldParm, ++NewParm) {
if ((*OldParm)->getKind() != (*NewParm)->getKind()) {
- Diag((*NewParm)->getLocation(), diag::err_template_param_different_kind)
+ unsigned NextDiag = diag::err_template_param_different_kind;
+ if (TemplateArgLoc.isValid()) {
+ Diag(TemplateArgLoc, diag::err_template_arg_template_params_mismatch);
+ NextDiag = diag::note_template_param_different_kind;
+ }
+ Diag((*NewParm)->getLocation(), NextDiag)
<< IsTemplateTemplateParm;
Diag((*OldParm)->getLocation(), diag::note_template_prev_declaration)
<< IsTemplateTemplateParm;
@@ -605,8 +646,15 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New,
if (isa<TemplateTypeParmDecl>(*OldParm)) {
// Okay; all template type parameters are equivalent (since we
- // know we're at the same depth/level).
-#ifndef NDEBUG
+ // know we're at the same index).
+#if 0
+ // FIXME: Enable this code in debug mode *after* we properly go
+ // through and "instantiate" the template parameter lists of
+ // template template parameters. It's only after this
+ // instantiation that (1) any dependent types within the
+ // template parameter list of the template template parameter
+ // can be checked, and (2) the template type parameter depths
+ // will match up.
QualType OldParmType
= Context.getTypeDeclType(cast<TemplateTypeParmDecl>(*OldParm));
QualType NewParmType
@@ -623,8 +671,13 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New,
if (Context.getCanonicalType(OldNTTP->getType()) !=
Context.getCanonicalType(NewNTTP->getType())) {
if (Complain) {
- Diag(NewNTTP->getLocation(),
- diag::err_template_nontype_parm_different_type)
+ unsigned NextDiag = diag::err_template_nontype_parm_different_type;
+ if (TemplateArgLoc.isValid()) {
+ Diag(TemplateArgLoc,
+ diag::err_template_arg_template_params_mismatch);
+ NextDiag = diag::note_template_nontype_parm_different_type;
+ }
+ Diag(NewNTTP->getLocation(), NextDiag)
<< NewNTTP->getType()
<< IsTemplateTemplateParm;
Diag(OldNTTP->getLocation(),
@@ -646,7 +699,8 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New,
if (!TemplateParameterListsAreEqual(NewTTP->getTemplateParameters(),
OldTTP->getTemplateParameters(),
Complain,
- /*IsTemplateTemplateParm=*/true))
+ /*IsTemplateTemplateParm=*/true,
+ TemplateArgLoc))
return false;
}
}