summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/TypePrinter.cpp1
-rw-r--r--clang/lib/Sema/Sema.h37
-rw-r--r--clang/lib/Sema/SemaOverload.cpp2
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp36
4 files changed, 61 insertions, 15 deletions
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index ed120062118..234d38a59ff 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -579,6 +579,7 @@ static void PrintTemplateArgument(std::string &Buffer,
case TemplateArgument::Template: {
llvm::raw_string_ostream s(Buffer);
Arg.getAsTemplate().print(s, Policy);
+ break;
}
case TemplateArgument::Integral:
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h
index 30c337dff8f..2557dfeb897 100644
--- a/clang/lib/Sema/Sema.h
+++ b/clang/lib/Sema/Sema.h
@@ -2621,10 +2621,45 @@ public:
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());
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 69e5a523070..3f3627d5900 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -350,7 +350,7 @@ Sema::IsOverload(FunctionDecl *New, Decl* OldD,
if (NewTemplate &&
(!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
OldTemplate->getTemplateParameters(),
- false, false, SourceLocation()) ||
+ false, TPL_TemplateMatch) ||
OldType->getResultType() != NewType->getResultType()))
return true;
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 419347adcf6..af7634ae86a 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -706,7 +706,8 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
// 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:
@@ -1124,7 +1125,7 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
if (ExpectedTemplateParams)
TemplateParameterListsAreEqual(ParamLists[Idx],
ExpectedTemplateParams,
- true);
+ true, TPL_TemplateMatch);
}
} else if (ParamLists[Idx]->size() > 0)
Diag(ParamLists[Idx]->getTemplateLoc(),
@@ -2511,7 +2512,8 @@ bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param,
return !TemplateParameterListsAreEqual(Template->getTemplateParameters(),
Param->getTemplateParameters(),
- true, true,
+ true,
+ TPL_TemplateTemplateArgumentMatch,
Arg.getLocation());
}
@@ -2528,9 +2530,7 @@ 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 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
@@ -2544,7 +2544,7 @@ bool
Sema::TemplateParameterListsAreEqual(TemplateParameterList *New,
TemplateParameterList *Old,
bool Complain,
- bool IsTemplateTemplateParm,
+ TemplateParameterListEqualKind Kind,
SourceLocation TemplateArgLoc) {
if (Old->size() != New->size()) {
if (Complain) {
@@ -2555,10 +2555,10 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New,
}
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());
}
@@ -2576,9 +2576,9 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New,
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;
}
@@ -2591,6 +2591,16 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New,
// 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) {
@@ -2602,7 +2612,7 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New,
}
Diag(NewNTTP->getLocation(), NextDiag)
<< NewNTTP->getType()
- << IsTemplateTemplateParm;
+ << (Kind != TPL_TemplateMatch);
Diag(OldNTTP->getLocation(),
diag::note_template_nontype_parm_prev_declaration)
<< OldNTTP->getType();
@@ -2621,7 +2631,7 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New,
if (!TemplateParameterListsAreEqual(NewTTP->getTemplateParameters(),
OldTTP->getTemplateParameters(),
Complain,
- /*IsTemplateTemplateParm=*/true,
+ (Kind == TPL_TemplateMatch? TPL_TemplateTemplateParmMatch : Kind),
TemplateArgLoc))
return false;
}
OpenPOWER on IntegriCloud