diff options
author | Patrick Palka <ppalka@redhat.com> | 2024-08-09 21:15:25 -0400 |
---|---|---|
committer | Patrick Palka <ppalka@redhat.com> | 2024-08-09 21:15:25 -0400 |
commit | 8cc67b520968ca9a13fd96896522aa66e39a99e2 (patch) | |
tree | 9e37bbf8d78bc0b57f6cd2cbb14dbc122ae8fdd9 /gcc/testsuite/g++.dg/cpp23 | |
parent | 70da0ca1239faefa6dec0494a85e998eae34beff (diff) | |
download | gcc-8cc67b520968ca9a13fd96896522aa66e39a99e2.zip gcc-8cc67b520968ca9a13fd96896522aa66e39a99e2.tar.gz gcc-8cc67b520968ca9a13fd96896522aa66e39a99e2.tar.bz2 |
c++: inherited CTAD fixes [PR116276]
This implements the overlooked inherited vs non-inherited guide
tiebreaker from P2582R1. This requires tracking inherited-ness of a
guide, for which it seems natural to reuse the lang_decl_fn::context
field which for a constructor tracks its inherited-ness.
This patch also works around CLASSTYPE_CONSTRUCTORS not reliably
returning all inherited constructors (due to some using-decl handling
quirks in in push_class_level_binding) by iterating over TYPE_FIELDS
instead.
This patch also makes us recognize another written form of inherited
constructor, 'using Base<T>::Base::Base' whose USING_DECL_SCOPE is a
TYPENAME_TYPE.
PR c++/116276
gcc/cp/ChangeLog:
* call.cc (joust): Implement P2582R1 inherited vs non-inherited
guide tiebreaker.
* cp-tree.h (lang_decl_fn::context): Document usage in
deduction_guide_p FUNCTION_DECLs.
(inherited_guide_p): Declare.
* pt.cc (inherited_guide_p): Define.
(set_inherited_guide_context): Define.
(alias_ctad_tweaks): Use set_inherited_guide_context.
(inherited_ctad_tweaks): Recognize some inherited constructors
whose scope is a TYPENAME_TYPE.
(ctor_deduction_guides_for): For C++23 inherited CTAD, iterate
over TYPE_FIELDS instead of CLASSTYPE_CONSTRUCTORS to recognize
all inherited constructors.
gcc/testsuite/ChangeLog:
* g++.dg/cpp23/class-deduction-inherited4.C: Remove an xfail.
* g++.dg/cpp23/class-deduction-inherited5.C: New test.
* g++.dg/cpp23/class-deduction-inherited6.C: New test.
Reviewed-by: Jason Merrill <jason@redhat.com>
Diffstat (limited to 'gcc/testsuite/g++.dg/cpp23')
3 files changed, 73 insertions, 2 deletions
diff --git a/gcc/testsuite/g++.dg/cpp23/class-deduction-inherited4.C b/gcc/testsuite/g++.dg/cpp23/class-deduction-inherited4.C index 5e3a7f4..806f016 100644 --- a/gcc/testsuite/g++.dg/cpp23/class-deduction-inherited4.C +++ b/gcc/testsuite/g++.dg/cpp23/class-deduction-inherited4.C @@ -13,10 +13,10 @@ using ty1 = B<int>; template<class T=void> struct C : A<int> { - using A<int>::A; // FIXME: we don't notice this one either + using A<int>::A; }; -using ty2 = decltype(C(0)); // { dg-bogus "" "" { xfail *-*-* } } +using ty2 = decltype(C(0)); using ty2 = C<void>; template<class T> diff --git a/gcc/testsuite/g++.dg/cpp23/class-deduction-inherited5.C b/gcc/testsuite/g++.dg/cpp23/class-deduction-inherited5.C new file mode 100644 index 0000000..d835acb --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/class-deduction-inherited5.C @@ -0,0 +1,25 @@ +// PR c++/116276 +// { dg-do compile { target c++20 } } + +template<class T> +struct Base1 { }; + +template<class T> +struct Base2 { }; + +template<class T = int> +struct Derived : public Base1<T>, Base2<T> { + using Base1<T>::Base1; + using Base2<T>::Base2; +}; + +Derived d; + +template<class T = int> +struct Derived2 : public Base1<T>, Base2<T> { + using Base1<T>::Base1::Base1; + using Base2<T>::Base2::Base2; + Derived2(); +}; + +Derived2 d2; diff --git a/gcc/testsuite/g++.dg/cpp23/class-deduction-inherited6.C b/gcc/testsuite/g++.dg/cpp23/class-deduction-inherited6.C new file mode 100644 index 0000000..df8199c --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/class-deduction-inherited6.C @@ -0,0 +1,46 @@ +// PR c++/116276 +// { dg-do compile { target c++23 } } + +template<class T> +struct Base1 { + Base1(); + Base1(T); +}; + +template<class T> +struct Base2 { + Base2(); + Base2(T*); +}; + +template<class T = int> +struct Derived : public Base1<T>, Base2<T> { + using Base1<T>::Base1; + using Base2<T>::Base2; +}; + +using ty1 = decltype(Derived{}); +using ty1 = Derived<int>; + +using ty2 = decltype(Derived{true}); +using ty2 = Derived<bool>; + +using ty3 = decltype(Derived{(char*)nullptr}); +using ty3 = Derived<char>; + +template<class T = int> +struct Derived2 : public Base1<T>, Base2<T> { + using Base1<T>::Base1; + using Base2<T>::Base2; + Derived2(); + Derived2(T); +}; + +using ty4 = decltype(Derived2{}); +using ty4 = Derived2<int>; + +using ty5 = decltype(Derived2{true}); +using ty5 = Derived2<bool>; + +using ty6 = decltype(Derived2{(char*)nullptr}); +using ty6 = Derived2<char>; |