mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-19 11:36:41 +00:00
[clang][Sema] Fix a CTAD regression after 42239d2e9 (#86914)
The most recent declaration of a template as a friend can introduce a different template parameter depth compared to what we anticipate from a CTAD guide. Fixes https://github.com/llvm/llvm-project/issues/86769
This commit is contained in:
parent
e0f0c463b5
commit
76c721994a
@ -1106,6 +1106,10 @@ Bug Fixes to C++ Support
|
||||
- Fix a crash when an unresolved overload set is encountered on the RHS of a ``.*`` operator.
|
||||
(`#53815 <https://github.com/llvm/llvm-project/issues/53815>`_)
|
||||
|
||||
- Fixed a regression in CTAD that a friend declaration that befriends itself may cause
|
||||
incorrect constraint substitution.
|
||||
(`#86769 <https://github.com/llvm/llvm-project/issues/86769>`_)
|
||||
|
||||
Bug Fixes to AST Handling
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
- Fixed an import failure of recursive friend class template.
|
||||
|
@ -1830,7 +1830,27 @@ static TemplateParameterList *GetTemplateParameterList(TemplateDecl *TD) {
|
||||
// Make sure we get the template parameter list from the most
|
||||
// recent declaration, since that is the only one that is guaranteed to
|
||||
// have all the default template argument information.
|
||||
return cast<TemplateDecl>(TD->getMostRecentDecl())->getTemplateParameters();
|
||||
Decl *D = TD->getMostRecentDecl();
|
||||
// C++11 [temp.param]p12:
|
||||
// A default template argument shall not be specified in a friend class
|
||||
// template declaration.
|
||||
//
|
||||
// Skip past friend *declarations* because they are not supposed to contain
|
||||
// default template arguments. Moreover, these declarations may introduce
|
||||
// template parameters living in different template depths than the
|
||||
// corresponding template parameters in TD, causing unmatched constraint
|
||||
// substitution.
|
||||
//
|
||||
// FIXME: Diagnose such cases within a class template:
|
||||
// template <class T>
|
||||
// struct S {
|
||||
// template <class = void> friend struct C;
|
||||
// };
|
||||
// template struct S<int>;
|
||||
while (D->getFriendObjectKind() != Decl::FriendObjectKind::FOK_None &&
|
||||
D->getPreviousDecl())
|
||||
D = D->getPreviousDecl();
|
||||
return cast<TemplateDecl>(D)->getTemplateParameters();
|
||||
}
|
||||
|
||||
DeclResult Sema::CheckClassTemplate(
|
||||
|
@ -478,3 +478,29 @@ template <Concept> class Foo {
|
||||
};
|
||||
|
||||
} // namespace FriendOfFriend
|
||||
|
||||
namespace GH86769 {
|
||||
|
||||
template <typename T>
|
||||
concept X = true;
|
||||
|
||||
template <X T> struct Y {
|
||||
Y(T) {}
|
||||
template <X U> friend struct Y;
|
||||
template <X U> friend struct Y;
|
||||
template <X U> friend struct Y;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct Z {
|
||||
// FIXME: This is ill-formed per C++11 [temp.param]p12:
|
||||
// A default template argument shall not be specified in a friend class
|
||||
// template declaration.
|
||||
template <X U = void> friend struct Y;
|
||||
};
|
||||
|
||||
template struct Y<int>;
|
||||
template struct Z<int>;
|
||||
Y y(1);
|
||||
|
||||
}
|
||||
|
@ -53,4 +53,4 @@ X x;
|
||||
template<class T, class B> struct Y { Y(T); };
|
||||
template<class T, class B=void> struct Y ;
|
||||
Y y(1);
|
||||
};
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user