Message ID | 20200420203830.3660750-1-ppalka@redhat.com |
---|---|
State | New |
Headers | show |
Series | c++: Constrained inherited constructor template [PR94549] | expand |
On 4/20/20 4:38 PM, Patrick Palka wrote: > A comment in satisfy_declaration constraints says > > /* For inherited constructors, consider the original declaration; > it has the correct template information attached. */ > d = strip_inheriting_ctors (d); > > But this comment seems to be false when the inherited constructor points to an > instantiation of a constructor template. In this case, DECL_TEMPLATE_INFO is > correct and DECL_INHERITED_CTOR points to the constructor template of the base > class rather than to the particular instantiation of the constructor template > (and so the DECL_TI_ARGS of the DECL_INHERITED_CTOR are in their dependent > form). > > So doing strip_inheriting_ctors in this case then eventually leads to > satisfy_associated_constraints returning true regardless of the constraints > themselves, due to the passed in 'args' being dependent. > > Since DECL_TEMPLATE_INFO seems to be non-NULL for an inherited constructor only > when the inherited constructor points to an instantiation of a constructor > template, this patch fixes this issue by avoiding to call strip_inheriting_ctors > when DECL_TEMPLATE_INFO is already non-NULL. > > There is another unguarded call to strip_inheriting_ctors in > get_normalized_constraints_from_decl, but this one seems to be safe to do > unconditionally because the rest of that function doesn't need/look at the > DECL_TI_ARGS of the decl. > > Passes 'make check-c++', does this look OK to commit after bootstrap/regtesting? OK. > gcc/cp/ChangeLog: > > PR c++/94549 > * constraint.cc (satisfy_declaration_constraints): Don't strip the > inherited constructor if it already has template information. > > gcc/testsuite/ChangeLog: > > PR c++/94549 > * g++.dg/concepts/inherit-ctor3.C: Adjust expected diagnostics. > * g++.dg/cpp2a/concepts-inherit-ctor4.C: Adjust expected diagnostics. > * g++.dg/cpp2a/concepts-inherit-ctor8.C: New test. > --- > gcc/cp/constraint.cc | 7 ++++--- > gcc/testsuite/g++.dg/concepts/inherit-ctor3.C | 4 ++-- > .../g++.dg/cpp2a/concepts-inherit-ctor4.C | 4 ++-- > .../g++.dg/cpp2a/concepts-inherit-ctor8.C | 20 +++++++++++++++++++ > 4 files changed, 28 insertions(+), 7 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor8.C > > diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc > index 320792195d6..b76402c2f85 100644 > --- a/gcc/cp/constraint.cc > +++ b/gcc/cp/constraint.cc > @@ -2737,9 +2737,10 @@ satisfy_declaration_constraints (tree t, subst_info info) > { > gcc_assert (DECL_P (t)); > > - /* For inherited constructors, consider the original declaration; > - it has the correct template information attached. */ > - if (flag_new_inheriting_ctors) > + if (!DECL_TEMPLATE_INFO (t)) > + /* For inherited constructors without template information, consider > + the original declaration; it has the correct template information > + attached. */ > t = strip_inheriting_ctors (t); > > /* Update the declaration for diagnostics. */ > diff --git a/gcc/testsuite/g++.dg/concepts/inherit-ctor3.C b/gcc/testsuite/g++.dg/concepts/inherit-ctor3.C > index abfe96e8240..6b7a7a43910 100644 > --- a/gcc/testsuite/g++.dg/concepts/inherit-ctor3.C > +++ b/gcc/testsuite/g++.dg/concepts/inherit-ctor3.C > @@ -12,12 +12,12 @@ template<typename T> > > template<typename T> > struct S2 : S1<T> { // { dg-error "no matching function" } > - using S1<T>::S1; // { dg-error "no matching function" } > + using S1<T>::S1; > }; > > struct X { } x; > > int main() { > - S2<X> s1(0); // { dg-error "use of deleted function" } > + S2<X> s1(0); // { dg-error "no matching function" } > S2<X> s2; // { dg-error "use of deleted function" } > } > diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor4.C b/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor4.C > index 75190eb3413..34eaf22c26c 100644 > --- a/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor4.C > +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor4.C > @@ -10,9 +10,9 @@ template<typename T> > > template<typename T> > struct S2 : S1<T> { > - using S1<T>::S1; // { dg-error "no matching function" } > + using S1<T>::S1; > }; > > int main() { > - S2<int> s(0); // { dg-error "use of deleted function" } > + S2<int> s(0); // { dg-error "no matching function" } > } > diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor8.C b/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor8.C > new file mode 100644 > index 00000000000..5b571e32318 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor8.C > @@ -0,0 +1,20 @@ > +// PR c++/94549 > +// { dg-do compile { target concepts } } > + > +struct base { > + template <typename type> > + requires false > + base(type); > + > + template <typename type> > + requires true > + base(type); > +}; > + > +struct derived : base { > + using base::base; > +}; > + > +void foo() { > + derived{'G'}; > +} >
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index 320792195d6..b76402c2f85 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -2737,9 +2737,10 @@ satisfy_declaration_constraints (tree t, subst_info info) { gcc_assert (DECL_P (t)); - /* For inherited constructors, consider the original declaration; - it has the correct template information attached. */ - if (flag_new_inheriting_ctors) + if (!DECL_TEMPLATE_INFO (t)) + /* For inherited constructors without template information, consider + the original declaration; it has the correct template information + attached. */ t = strip_inheriting_ctors (t); /* Update the declaration for diagnostics. */ diff --git a/gcc/testsuite/g++.dg/concepts/inherit-ctor3.C b/gcc/testsuite/g++.dg/concepts/inherit-ctor3.C index abfe96e8240..6b7a7a43910 100644 --- a/gcc/testsuite/g++.dg/concepts/inherit-ctor3.C +++ b/gcc/testsuite/g++.dg/concepts/inherit-ctor3.C @@ -12,12 +12,12 @@ template<typename T> template<typename T> struct S2 : S1<T> { // { dg-error "no matching function" } - using S1<T>::S1; // { dg-error "no matching function" } + using S1<T>::S1; }; struct X { } x; int main() { - S2<X> s1(0); // { dg-error "use of deleted function" } + S2<X> s1(0); // { dg-error "no matching function" } S2<X> s2; // { dg-error "use of deleted function" } } diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor4.C b/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor4.C index 75190eb3413..34eaf22c26c 100644 --- a/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor4.C +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor4.C @@ -10,9 +10,9 @@ template<typename T> template<typename T> struct S2 : S1<T> { - using S1<T>::S1; // { dg-error "no matching function" } + using S1<T>::S1; }; int main() { - S2<int> s(0); // { dg-error "use of deleted function" } + S2<int> s(0); // { dg-error "no matching function" } } diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor8.C b/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor8.C new file mode 100644 index 00000000000..5b571e32318 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor8.C @@ -0,0 +1,20 @@ +// PR c++/94549 +// { dg-do compile { target concepts } } + +struct base { + template <typename type> + requires false + base(type); + + template <typename type> + requires true + base(type); +}; + +struct derived : base { + using base::base; +}; + +void foo() { + derived{'G'}; +}