Result = true;
}
+ void CheckNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
+ assert(D->getDepth() <= TemplateDepth &&
+ "Nothing should reference a value below the actual template depth, "
+ "depth is likely wrong");
+ if (D->getDepth() != TemplateDepth)
+ Result = true;
+
+ // Necessary because the type of the NTTP might be what refers to the parent
+ // constriant.
+ TransformType(D->getType());
+ }
+
public:
using inherited = TreeTransform<ConstraintRefersToContainingTemplateChecker>;
// unreachable should catch future instances/cases.
if (auto *TD = dyn_cast<TypedefNameDecl>(D))
TransformType(TD->getUnderlyingType());
+ else if (auto *NTTPD = dyn_cast<NonTypeTemplateParmDecl>(D))
+ CheckNonTypeTemplateParmDecl(NTTPD);
else if (auto *VD = dyn_cast<ValueDecl>(D))
TransformType(VD->getType());
else if (auto *TD = dyn_cast<TemplateDecl>(D))
S<long> y;
}
} // namespace RefersToParentInConstraint
+
+namespace NTTP {
+ struct Base{};
+ template<int N>
+ struct S : Base {
+ // N is from the parent template.
+ template<typename T>
+ friend int templ_func(Base&) requires(N > 0)
+ { return 10; }
+ };
+
+ template<typename T>
+ struct U : Base {
+ template<T N>
+ friend int templ_func(Base&) requires(N>0)
+ { return 10; }
+ };
+
+ void use() {
+ S<1> s1;
+ templ_func<float>(s1);
+ S<2> s2;
+ templ_func<float>(s2);
+
+ U<int> u1;
+ templ_func<1>(u1);
+ U<short> u2;
+ templ_func<1>(u2);
+ }
+}