Skip to content

Commit

Permalink
[clang] Exclude non-template classes when checking if constraint refe…
Browse files Browse the repository at this point in the history
…rs to containing template arguments (#74265)

When checking if the constraint uses any enclosing template parameters
for [temp.friend]p9, if a containing record is used as argument, we
assume that the constraint depends on enclosing template parameters
without checking if the record is templated. The reproducer from the bug
is included as a test case.

Fixes #71595
  • Loading branch information
antangelo committed Dec 7, 2023
1 parent b310932 commit fed4e3a
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 0 deletions.
3 changes: 3 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,9 @@ Bug Fixes in This Version
- Fixed false positive error emitted by clang when performing qualified name
lookup and the current class instantiation has dependent bases.
Fixes (`#13826 <https://github.com/llvm/llvm-project/issues/13826>`_)
- Fix a ``clang-17`` regression where a templated friend with constraints is not
properly applied when its parameters reference an enclosing non-template class.
Fixes (`#71595 <https://github.com/llvm/llvm-project/issues/71595>`_)
- Fix the name of the ifunc symbol emitted for multiversion functions declared with the
``target_clones`` attribute. This addresses a linker error that would otherwise occur
when these functions are referenced from other TUs.
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Sema/SemaTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1712,6 +1712,8 @@ class ConstraintRefersToContainingTemplateChecker
// Friend, likely because it was referred to without its template arguments.
void CheckIfContainingRecord(const CXXRecordDecl *CheckingRD) {
CheckingRD = CheckingRD->getMostRecentDecl();
if (!CheckingRD->isTemplated())
return;

for (const DeclContext *DC = Friend->getLexicalDeclContext();
DC && !DC->isFileContext(); DC = DC->getParent())
Expand Down
34 changes: 34 additions & 0 deletions clang/test/SemaTemplate/GH71595.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// RUN: %clang_cc1 -std=c++20 -verify %s

template<class T, class U>
concept C = true;

class non_temp {
template<C<non_temp> T>
friend void f();

non_temp();
};

template<C<non_temp> T>
void f() {
auto v = non_temp();
}

template<class A>
class temp {
template<C<temp> T>
friend void g();

temp(); // expected-note {{implicitly declared private here}}
};

template<C<temp<int>> T>
void g() {
auto v = temp<T>(); // expected-error {{calling a private constructor of class 'temp<int>'}}
}

void h() {
f<int>();
g<int>(); // expected-note {{in instantiation of function template specialization 'g<int>' requested here}}
}

0 comments on commit fed4e3a

Please sign in to comment.