File tree Expand file tree Collapse file tree 4 files changed +52
-2
lines changed Expand file tree Collapse file tree 4 files changed +52
-2
lines changed Original file line number Diff line number Diff line change @@ -1106,6 +1106,10 @@ Bug Fixes to C++ Support
11061106- Fix a crash when an unresolved overload set is encountered on the RHS of a ``.* `` operator.
11071107 (`#53815 <https://github.com/llvm/llvm-project/issues/53815 >`_)
11081108
1109+ - Fixed a regression in CTAD that a friend declaration that befriends itself may cause
1110+ incorrect constraint substitution.
1111+ (`#86769 <https://github.com/llvm/llvm-project/issues/86769 >`_)
1112+
11091113Bug Fixes to AST Handling
11101114^^^^^^^^^^^^^^^^^^^^^^^^^
11111115- Fixed an import failure of recursive friend class template.
Original file line number Diff line number Diff line change @@ -1830,7 +1830,27 @@ static TemplateParameterList *GetTemplateParameterList(TemplateDecl *TD) {
18301830 // Make sure we get the template parameter list from the most
18311831 // recent declaration, since that is the only one that is guaranteed to
18321832 // have all the default template argument information.
1833- return cast<TemplateDecl>(TD->getMostRecentDecl ())->getTemplateParameters ();
1833+ Decl *D = TD->getMostRecentDecl ();
1834+ // C++11 [temp.param]p12:
1835+ // A default template argument shall not be specified in a friend class
1836+ // template declaration.
1837+ //
1838+ // Skip past friend *declarations* because they are not supposed to contain
1839+ // default template arguments. Moreover, these declarations may introduce
1840+ // template parameters living in different template depths than the
1841+ // corresponding template parameters in TD, causing unmatched constraint
1842+ // substitution.
1843+ //
1844+ // FIXME: Diagnose such cases within a class template:
1845+ // template <class T>
1846+ // struct S {
1847+ // template <class = void> friend struct C;
1848+ // };
1849+ // template struct S<int>;
1850+ while (D->getFriendObjectKind () != Decl::FriendObjectKind::FOK_None &&
1851+ D->getPreviousDecl ())
1852+ D = D->getPreviousDecl ();
1853+ return cast<TemplateDecl>(D)->getTemplateParameters ();
18341854}
18351855
18361856DeclResult Sema::CheckClassTemplate (
Original file line number Diff line number Diff line change @@ -478,3 +478,29 @@ template <Concept> class Foo {
478478};
479479
480480} // namespace FriendOfFriend
481+
482+ namespace GH86769 {
483+
484+ template <typename T>
485+ concept X = true ;
486+
487+ template <X T> struct Y {
488+ Y (T) {}
489+ template <X U> friend struct Y ;
490+ template <X U> friend struct Y ;
491+ template <X U> friend struct Y ;
492+ };
493+
494+ template <class T >
495+ struct Z {
496+ // FIXME: This is ill-formed per C++11 [temp.param]p12:
497+ // A default template argument shall not be specified in a friend class
498+ // template declaration.
499+ template <X U = void > friend struct Y ;
500+ };
501+
502+ template struct Y <int >;
503+ template struct Z <int >;
504+ Y y (1 );
505+
506+ }
Original file line number Diff line number Diff line change 5353template <class T , class B > struct Y { Y(T); };
5454template <class T , class B =void > struct Y ;
5555Y y (1 );
56- };
56+ }
You can’t perform that action at this time.
0 commit comments