Skip to content

Commit 6c38ffc

Browse files
author
Erich Keane
committed
[Concepts] Fix friend-checking to include NTTPs
More work for temp.friend p9, this fixes a previous bug where we didn't properly consider a friend to depend on the enclosing template if it only did so via an NTTP.
1 parent ed4943d commit 6c38ffc

File tree

2 files changed

+44
-0
lines changed

2 files changed

+44
-0
lines changed

clang/lib/Sema/SemaTemplate.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -1707,6 +1707,18 @@ class ConstraintRefersToContainingTemplateChecker
17071707
Result = true;
17081708
}
17091709

1710+
void CheckNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
1711+
assert(D->getDepth() <= TemplateDepth &&
1712+
"Nothing should reference a value below the actual template depth, "
1713+
"depth is likely wrong");
1714+
if (D->getDepth() != TemplateDepth)
1715+
Result = true;
1716+
1717+
// Necessary because the type of the NTTP might be what refers to the parent
1718+
// constriant.
1719+
TransformType(D->getType());
1720+
}
1721+
17101722
public:
17111723
using inherited = TreeTransform<ConstraintRefersToContainingTemplateChecker>;
17121724

@@ -1742,6 +1754,8 @@ class ConstraintRefersToContainingTemplateChecker
17421754
// unreachable should catch future instances/cases.
17431755
if (auto *TD = dyn_cast<TypedefNameDecl>(D))
17441756
TransformType(TD->getUnderlyingType());
1757+
else if (auto *NTTPD = dyn_cast<NonTypeTemplateParmDecl>(D))
1758+
CheckNonTypeTemplateParmDecl(NTTPD);
17451759
else if (auto *VD = dyn_cast<ValueDecl>(D))
17461760
TransformType(VD->getType());
17471761
else if (auto *TD = dyn_cast<TemplateDecl>(D))

clang/test/SemaTemplate/concepts-friends.cpp

+30
Original file line numberDiff line numberDiff line change
@@ -411,3 +411,33 @@ namespace RefersToParentInConstraint {
411411
S<long> y;
412412
}
413413
} // namespace RefersToParentInConstraint
414+
415+
namespace NTTP {
416+
struct Base{};
417+
template<int N>
418+
struct S : Base {
419+
// N is from the parent template.
420+
template<typename T>
421+
friend int templ_func(Base&) requires(N > 0)
422+
{ return 10; }
423+
};
424+
425+
template<typename T>
426+
struct U : Base {
427+
template<T N>
428+
friend int templ_func(Base&) requires(N>0)
429+
{ return 10; }
430+
};
431+
432+
void use() {
433+
S<1> s1;
434+
templ_func<float>(s1);
435+
S<2> s2;
436+
templ_func<float>(s2);
437+
438+
U<int> u1;
439+
templ_func<1>(u1);
440+
U<short> u2;
441+
templ_func<1>(u2);
442+
}
443+
}

0 commit comments

Comments
 (0)