[cfe-commits] r123343 - /cfe/trunk/lib/Sema/SemaTemplate.cpp
Douglas Gregor
dgregor at apple.com
Wed Jan 12 15:45:45 PST 2011
Author: dgregor
Date: Wed Jan 12 17:45:44 2011
New Revision: 123343
URL: http://llvm.org/viewvc/llvm-project?rev=123343&view=rev
Log:
Refactor and simplify Sema::TemplateParameterListsAreEqual. We had a
bunch of duplicated checks for parameter pack/non-pack mismatches.
Modified:
cfe/trunk/lib/Sema/SemaTemplate.cpp
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=123343&r1=123342&r2=123343&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Jan 12 17:45:44 2011
@@ -3628,6 +3628,103 @@
return Owned(E);
}
+/// \brief Match two template parameters within template parameter lists.
+static bool MatchTemplateParameterKind(Sema &S, NamedDecl *New, NamedDecl *Old,
+ bool Complain,
+ Sema::TemplateParameterListEqualKind Kind,
+ SourceLocation TemplateArgLoc) {
+ // Check the actual kind (type, non-type, template).
+ if (Old->getKind() != New->getKind()) {
+ if (Complain) {
+ unsigned NextDiag = diag::err_template_param_different_kind;
+ if (TemplateArgLoc.isValid()) {
+ S.Diag(TemplateArgLoc, diag::err_template_arg_template_params_mismatch);
+ NextDiag = diag::note_template_param_different_kind;
+ }
+ S.Diag(New->getLocation(), NextDiag)
+ << (Kind != Sema::TPL_TemplateMatch);
+ S.Diag(Old->getLocation(), diag::note_template_prev_declaration)
+ << (Kind != Sema::TPL_TemplateMatch);
+ }
+
+ return false;
+ }
+
+ // Check that both are parameter packs are neither are parameter packs.
+ if (Old->isTemplateParameterPack() != New->isTemplateParameterPack()) {
+ if (Complain) {
+ unsigned NextDiag = diag::err_template_parameter_pack_non_pack;
+ if (TemplateArgLoc.isValid()) {
+ S.Diag(TemplateArgLoc,
+ diag::err_template_arg_template_params_mismatch);
+ NextDiag = diag::note_template_parameter_pack_non_pack;
+ }
+
+ unsigned ParamKind = isa<TemplateTypeParmDecl>(New)? 0
+ : isa<NonTypeTemplateParmDecl>(New)? 1
+ : 2;
+ S.Diag(New->getLocation(), NextDiag)
+ << ParamKind << New->isParameterPack();
+ S.Diag(Old->getLocation(), diag::note_template_parameter_pack_here)
+ << ParamKind << Old->isParameterPack();
+ }
+
+ return false;
+ }
+
+ // For non-type template parameters, check the type of the parameter.
+ if (NonTypeTemplateParmDecl *OldNTTP
+ = dyn_cast<NonTypeTemplateParmDecl>(Old)) {
+ NonTypeTemplateParmDecl *NewNTTP = cast<NonTypeTemplateParmDecl>(New);
+
+ // 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 == Sema::TPL_TemplateTemplateArgumentMatch &&
+ (OldNTTP->getType()->isDependentType() ||
+ NewNTTP->getType()->isDependentType()))
+ return true;
+
+ if (!S.Context.hasSameType(OldNTTP->getType(), NewNTTP->getType())) {
+ if (Complain) {
+ unsigned NextDiag = diag::err_template_nontype_parm_different_type;
+ if (TemplateArgLoc.isValid()) {
+ S.Diag(TemplateArgLoc,
+ diag::err_template_arg_template_params_mismatch);
+ NextDiag = diag::note_template_nontype_parm_different_type;
+ }
+ S.Diag(NewNTTP->getLocation(), NextDiag)
+ << NewNTTP->getType()
+ << (Kind != Sema::TPL_TemplateMatch);
+ S.Diag(OldNTTP->getLocation(),
+ diag::note_template_nontype_parm_prev_declaration)
+ << OldNTTP->getType();
+ }
+
+ return false;
+ }
+
+ return true;
+ }
+
+ // For template template parameters, check the template parameter types.
+ // The template parameter lists of template template
+ // parameters must agree.
+ if (TemplateTemplateParmDecl *OldTTP
+ = dyn_cast<TemplateTemplateParmDecl>(Old)) {
+ TemplateTemplateParmDecl *NewTTP = cast<TemplateTemplateParmDecl>(New);
+ return S.TemplateParameterListsAreEqual(NewTTP->getTemplateParameters(),
+ OldTTP->getTemplateParameters(),
+ Complain,
+ (Kind == Sema::TPL_TemplateMatch
+ ? Sema::TPL_TemplateTemplateParmMatch
+ : Kind),
+ TemplateArgLoc);
+ }
+
+ return true;
+}
/// \brief Determine whether the given template parameter lists are
/// equivalent.
@@ -3677,142 +3774,18 @@
return false;
}
+ // C++0x [temp.arg.template]p3:
+ // A template-argument matches a template template-parameter (call it P)
+ // when each of the template parameters in the template-parameter-list of
+ // the template-argumentâs corresponding class template or template alias
+ // (call it A) matches the corresponding template parameter in the
+ // template-parameter-list of P.
for (TemplateParameterList::iterator OldParm = Old->begin(),
OldParmEnd = Old->end(), NewParm = New->begin();
OldParm != OldParmEnd; ++OldParm, ++NewParm) {
- if ((*OldParm)->getKind() != (*NewParm)->getKind()) {
- if (Complain) {
- 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)
- << (Kind != TPL_TemplateMatch);
- Diag((*OldParm)->getLocation(), diag::note_template_prev_declaration)
- << (Kind != TPL_TemplateMatch);
- }
- return false;
- }
-
- if (TemplateTypeParmDecl *OldTTP
- = dyn_cast<TemplateTypeParmDecl>(*OldParm)) {
- // Template type parameters are equivalent if either both are template
- // type parameter packs or neither are (since we know we're at the same
- // index).
- TemplateTypeParmDecl *NewTTP = cast<TemplateTypeParmDecl>(*NewParm);
- if (OldTTP->isParameterPack() != NewTTP->isParameterPack()) {
- // FIXME: Implement the rules in C++0x [temp.arg.template]p5 that
- // allow one to match a template parameter pack in the template
- // parameter list of a template template parameter to one or more
- // template parameters in the template parameter list of the
- // corresponding template template argument.
- if (Complain) {
- unsigned NextDiag = diag::err_template_parameter_pack_non_pack;
- if (TemplateArgLoc.isValid()) {
- Diag(TemplateArgLoc,
- diag::err_template_arg_template_params_mismatch);
- NextDiag = diag::note_template_parameter_pack_non_pack;
- }
- Diag(NewTTP->getLocation(), NextDiag)
- << 0 << NewTTP->isParameterPack();
- Diag(OldTTP->getLocation(), diag::note_template_parameter_pack_here)
- << 0 << OldTTP->isParameterPack();
- }
- return false;
- }
- } else if (NonTypeTemplateParmDecl *OldNTTP
- = dyn_cast<NonTypeTemplateParmDecl>(*OldParm)) {
- // The types of non-type template parameters must agree.
- NonTypeTemplateParmDecl *NewNTTP
- = cast<NonTypeTemplateParmDecl>(*NewParm);
-
- if (OldNTTP->isParameterPack() != NewNTTP->isParameterPack()) {
- // FIXME: Implement the rules in C++0x [temp.arg.template]p5 that
- // allow one to match a template parameter pack in the template
- // parameter list of a template template parameter to one or more
- // template parameters in the template parameter list of the
- // corresponding template template argument.
- if (Complain) {
- unsigned NextDiag = diag::err_template_parameter_pack_non_pack;
- if (TemplateArgLoc.isValid()) {
- Diag(TemplateArgLoc,
- diag::err_template_arg_template_params_mismatch);
- NextDiag = diag::note_template_parameter_pack_non_pack;
- }
- Diag(NewNTTP->getLocation(), NextDiag)
- << 1 << NewNTTP->isParameterPack();
- Diag(OldNTTP->getLocation(), diag::note_template_parameter_pack_here)
- << 1 << OldNTTP->isParameterPack();
- }
- return false;
- }
-
- // 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) {
- 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()
- << (Kind != TPL_TemplateMatch);
- Diag(OldNTTP->getLocation(),
- diag::note_template_nontype_parm_prev_declaration)
- << OldNTTP->getType();
- }
- return false;
- }
- } else {
- // The template parameter lists of template template
- // parameters must agree.
- assert(isa<TemplateTemplateParmDecl>(*OldParm) &&
- "Only template template parameters handled here");
- TemplateTemplateParmDecl *OldTTP
- = cast<TemplateTemplateParmDecl>(*OldParm);
- TemplateTemplateParmDecl *NewTTP
- = cast<TemplateTemplateParmDecl>(*NewParm);
-
- if (OldTTP->isParameterPack() != NewTTP->isParameterPack()) {
- // FIXME: Implement the rules in C++0x [temp.arg.template]p5 that
- // allow one to match a template parameter pack in the template
- // parameter list of a template template parameter to one or more
- // template parameters in the template parameter list of the
- // corresponding template template argument.
- if (Complain) {
- unsigned NextDiag = diag::err_template_parameter_pack_non_pack;
- if (TemplateArgLoc.isValid()) {
- Diag(TemplateArgLoc,
- diag::err_template_arg_template_params_mismatch);
- NextDiag = diag::note_template_parameter_pack_non_pack;
- }
- Diag(NewTTP->getLocation(), NextDiag)
- << 2 << NewTTP->isParameterPack();
- Diag(OldTTP->getLocation(), diag::note_template_parameter_pack_here)
- << 2 << OldTTP->isParameterPack();
- }
- return false;
- }
-
- if (!TemplateParameterListsAreEqual(NewTTP->getTemplateParameters(),
- OldTTP->getTemplateParameters(),
- Complain,
- (Kind == TPL_TemplateMatch? TPL_TemplateTemplateParmMatch : Kind),
- TemplateArgLoc))
- return false;
- }
+ if (!MatchTemplateParameterKind(*this, *NewParm, *OldParm, Complain,
+ Kind, TemplateArgLoc))
+ return false;
}
return true;
More information about the cfe-commits
mailing list