specialization.
Fixes a crash-on-valid if further template parameters are introduced
within the specialization (by a generic lambda).
bool FirstInstantiation = PointOfInstantiation.isInvalid();
if (FirstInstantiation) {
PointOfInstantiation = Loc;
- Func->setTemplateSpecializationKind(TSK, PointOfInstantiation);
+ if (auto *MSI = Func->getMemberSpecializationInfo())
+ MSI->setPointOfInstantiation(Loc);
+ // FIXME: Notify listener.
+ else
+ Func->setTemplateSpecializationKind(TSK, PointOfInstantiation);
} else if (TSK != TSK_ImplicitInstantiation) {
// Use the point of use as the point of instantiation, instead of the
// point of explicit instantiation (which we track as the actual point
PointOfInstantiation = Loc;
if (MSI)
MSI->setPointOfInstantiation(PointOfInstantiation);
+ // FIXME: Notify listener.
else
Var->setTemplateSpecializationKind(TSK, PointOfInstantiation);
}
TSK_ExplicitSpecialization)
break;
- if (const TemplateArgumentList *TemplateArgs
+ if (!RelativeToPrimary && Function->getTemplateSpecializationKind() ==
+ TSK_ExplicitSpecialization) {
+ // This is an implicit instantiation of an explicit specialization. We
+ // don't get any template arguments from this function but might get
+ // some from an enclosing template.
+ } else if (const TemplateArgumentList *TemplateArgs
= Function->getTemplateSpecializationArgs()) {
// Add the template arguments for this specialization.
Result.addOuterTemplateArguments(TemplateArgs);
--- /dev/null
+// RUN: %clang_cc1 -std=c++20 -verify %s
+// expected-no-diagnostics
+
+namespace FunctionTemplate {
+ template<typename> struct S {
+ template<int> auto foo();
+
+ // Check that we don't confuse the depth-1 level-0 parameter of the generic
+ // lambda with the depth-1 level-0 parameter of the primary 'foo' template.
+ template<> constexpr auto foo<1>() {
+ return [](auto x) { return x; };
+ }
+ };
+
+ static_assert(S<void>().template foo<1>()(2) == 2);
+}