@@ -4099,7 +4099,6 @@ static bool CheckTemplateSpecializationScope(Sema &S, NamedDecl *Specialized,
4099
4099
static TemplateSpecializationKind getTemplateSpecializationKind (Decl *D);
4100
4100
4101
4101
static bool isTemplateArgumentTemplateParameter (const TemplateArgument &Arg,
4102
- NamedDecl *Param,
4103
4102
unsigned Depth,
4104
4103
unsigned Index) {
4105
4104
switch (Arg.getKind ()) {
@@ -4126,11 +4125,7 @@ static bool isTemplateArgumentTemplateParameter(const TemplateArgument &Arg,
4126
4125
return false ;
4127
4126
const NonTypeTemplateParmDecl *NTTP =
4128
4127
dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl ());
4129
- if (!NTTP || NTTP->getDepth () != Depth || NTTP->getIndex () != Index)
4130
- return false ;
4131
- QualType ParamType = cast<NonTypeTemplateParmDecl>(Param)->getType ();
4132
- QualType NTTPType = NTTP->getType ();
4133
- return ParamType.getCanonicalType () == NTTPType.getCanonicalType ();
4128
+ return NTTP && NTTP->getDepth () == Depth && NTTP->getIndex () == Index;
4134
4129
}
4135
4130
4136
4131
case TemplateArgument::Template:
@@ -4143,8 +4138,9 @@ static bool isTemplateArgumentTemplateParameter(const TemplateArgument &Arg,
4143
4138
}
4144
4139
4145
4140
static bool isSameAsPrimaryTemplate (TemplateParameterList *Params,
4141
+ TemplateParameterList *SpecParams,
4146
4142
ArrayRef<TemplateArgument> Args) {
4147
- if (Params->size () != Args.size ())
4143
+ if (Params->size () != Args.size () || Params-> size () != SpecParams-> size () )
4148
4144
return false ;
4149
4145
4150
4146
unsigned Depth = Params->getDepth ();
@@ -4161,9 +4157,19 @@ static bool isSameAsPrimaryTemplate(TemplateParameterList *Params,
4161
4157
Arg = Arg.pack_begin ()->getPackExpansionPattern ();
4162
4158
}
4163
4159
4164
- if (!isTemplateArgumentTemplateParameter (Arg, Params->getParam (I), Depth,
4165
- I))
4160
+ if (!isTemplateArgumentTemplateParameter (Arg, Depth, I))
4166
4161
return false ;
4162
+
4163
+ // For NTTPs further specialization is allowed via deduced types, so
4164
+ // we need to make sure to only reject here if primary template and
4165
+ // specialization use the same type for the NTTP.
4166
+ if (auto *SpecNTTP =
4167
+ dyn_cast<NonTypeTemplateParmDecl>(SpecParams->getParam (I))) {
4168
+ auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Params->getParam (I));
4169
+ if (!NTTP || NTTP->getType ().getCanonicalType () !=
4170
+ SpecNTTP->getType ().getCanonicalType ())
4171
+ return false ;
4172
+ }
4167
4173
}
4168
4174
4169
4175
return true ;
@@ -4361,7 +4367,7 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
4361
4367
}
4362
4368
4363
4369
if (isSameAsPrimaryTemplate (VarTemplate->getTemplateParameters (),
4364
- CTAI.CanonicalConverted ) &&
4370
+ TemplateParams, CTAI.CanonicalConverted ) &&
4365
4371
(!Context.getLangOpts ().CPlusPlus20 ||
4366
4372
!TemplateParams->hasAssociatedConstraints ())) {
4367
4373
// C++ [temp.class.spec]p9b3:
0 commit comments