From 08c8c973c082457a7d6192673e87475f1fdfdbef Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 14 Jan 2020 13:59:54 -0500 Subject: [PATCH] PR c++/92590 - wrong handling of inherited default ctor. I thought my earlier fix for 91930 was an obvious bug fix, but apparently an inherited constructor does not count as user-declared. So this patch reverts that change and the other follow-on patches, and fixes 91930 differently, by not letting the inherited default constructor hide the implicitly-declared default constructor. * class.c (add_method): A constrained inherited ctor doesn't hide an implicit derived ctor. Revert: PR c++/91930 - ICE with constrained inherited default ctor. * name-lookup.c (do_class_using_decl): Set TYPE_HAS_USER_CONSTRUCTOR for inherited constructor. PR c++/92552 - ICE with inherited constrained default ctor. * pt.c (instantiate_class_template_1): Copy TYPE_HAS_USER_CONSTRUCTOR. PR c++/92594 - ICE with inherited trivial default ctor. * method.c (trivial_fn_p): Treat an inherited default constructor like a normal default constructor. --- gcc/cp/ChangeLog | 14 ++++++++++++++ gcc/cp/class.c | 5 +++-- gcc/cp/method.c | 7 +------ gcc/cp/name-lookup.c | 1 - gcc/cp/pt.c | 1 - gcc/testsuite/g++.dg/concepts/inherit-ctor3.C | 4 ++-- gcc/testsuite/g++.dg/cpp0x/inh-ctor35.C | 14 ++++++++++++++ gcc/testsuite/g++.dg/cpp0x/inh-ctor5.C | 4 ++-- gcc/testsuite/g++.dg/cpp1z/inh-ctor22.C | 4 ++-- .../g++.dg/cpp2a/concepts-inherit-ctor2.C | 4 ++-- gcc/testsuite/g++.dg/template/crash7.C | 4 +++- gcc/testsuite/g++.old-deja/g++.pt/error2.C | 2 +- 12 files changed, 44 insertions(+), 20 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/inh-ctor35.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 3cc7c48b490..c1375398517 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -14,6 +14,20 @@ 2020-01-14 Jason Merrill + PR c++/92590 - wrong handling of inherited default ctor. + * class.c (add_method): A constrained inherited ctor doesn't hide an + implicit derived ctor. + Revert: + PR c++/92552 - ICE with inherited constrained default ctor. + * pt.c (instantiate_class_template_1): Copy + TYPE_HAS_USER_CONSTRUCTOR. + PR c++/91930 - ICE with constrained inherited default ctor. + * name-lookup.c (do_class_using_decl): Set TYPE_HAS_USER_CONSTRUCTOR + for inherited constructor. + PR c++/92594 - ICE with inherited trivial default ctor. + * method.c (trivial_fn_p): Treat an inherited default constructor + like a normal default constructor. + PR c++/92594 - ICE with inherited trivial default ctor. * method.c (trivial_fn_p): Treat an inherited default constructor like a normal default constructor. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 07abe5298d1..719c3ece6e1 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -1079,9 +1079,10 @@ add_method (tree type, tree method, bool via_using) { special_function_kind sfk = special_memfn_p (method); - if (sfk == sfk_none) + if (sfk == sfk_none || DECL_INHERITED_CTOR (fn)) /* Non-special member functions coexist if they are not - equivalently constrained. */ + equivalently constrained. A member function is not hidden + by an inherited constructor. */ continue; /* P0848: For special member functions, deleted, unsatisfied, or diff --git a/gcc/cp/method.c b/gcc/cp/method.c index e20a88febdc..fef19e18196 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -458,12 +458,7 @@ trivial_fn_p (tree fn) /* If fn is a clone, get the primary variant. */ if (tree prim = DECL_CLONED_FUNCTION (fn)) fn = prim; - special_function_kind sfk = special_function_p (fn); - /* An inherited default constructor is equivalent to a non-inherited default - constructor, so let it be trivial. */ - if (sfk == sfk_inheriting_constructor && default_ctor_p (fn)) - sfk = sfk_constructor; - return type_has_trivial_fn (DECL_CONTEXT (fn), sfk); + return type_has_trivial_fn (DECL_CONTEXT (fn), special_function_p (fn)); } /* PARM is a PARM_DECL for a function which we want to forward to another diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 3c2c50d13a4..cd7a5816e46 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -4634,7 +4634,6 @@ lookup_using_decl (tree scope, name_lookup &lookup) maybe_warn_cpp0x (CPP0X_INHERITING_CTORS); lookup.name = ctor_identifier; CLASSTYPE_NON_AGGREGATE (current) = true; - TYPE_HAS_USER_CONSTRUCTOR (current) = true; } /* Cannot introduce a constructor name. */ diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 4fdc74f9ca8..7e675ce9039 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -11578,7 +11578,6 @@ instantiate_class_template_1 (tree type) SET_TYPE_ALIGN (type, TYPE_ALIGN (pattern)); TYPE_USER_ALIGN (type) = TYPE_USER_ALIGN (pattern); CLASSTYPE_NON_AGGREGATE (type) = CLASSTYPE_NON_AGGREGATE (pattern); - TYPE_HAS_USER_CONSTRUCTOR (type) = TYPE_HAS_USER_CONSTRUCTOR (pattern); if (ANON_AGGR_TYPE_P (pattern)) SET_ANON_AGGR_TYPE_P (type); if (CLASSTYPE_VISIBILITY_SPECIFIED (pattern)) diff --git a/gcc/testsuite/g++.dg/concepts/inherit-ctor3.C b/gcc/testsuite/g++.dg/concepts/inherit-ctor3.C index dda202f4c24..abfe96e8240 100644 --- a/gcc/testsuite/g++.dg/concepts/inherit-ctor3.C +++ b/gcc/testsuite/g++.dg/concepts/inherit-ctor3.C @@ -11,7 +11,7 @@ template }; template - struct S2 : S1 { + struct S2 : S1 { // { dg-error "no matching function" } using S1::S1; // { dg-error "no matching function" } }; @@ -19,5 +19,5 @@ struct X { } x; int main() { S2 s1(0); // { dg-error "use of deleted function" } - S2 s2; // { dg-error "no matching function" } + S2 s2; // { dg-error "use of deleted function" } } diff --git a/gcc/testsuite/g++.dg/cpp0x/inh-ctor35.C b/gcc/testsuite/g++.dg/cpp0x/inh-ctor35.C new file mode 100644 index 00000000000..0ec43938848 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/inh-ctor35.C @@ -0,0 +1,14 @@ +// PR c++/92590 +// { dg-do compile { target c++11 } } + +class Base { + protected: + Base(); +}; + +class Derived : public Base { + public: + using Base::Base; +}; + +Derived d; diff --git a/gcc/testsuite/g++.dg/cpp0x/inh-ctor5.C b/gcc/testsuite/g++.dg/cpp0x/inh-ctor5.C index 673b6380504..d0038c16a14 100644 --- a/gcc/testsuite/g++.dg/cpp0x/inh-ctor5.C +++ b/gcc/testsuite/g++.dg/cpp0x/inh-ctor5.C @@ -6,13 +6,13 @@ struct B1 { struct B2 { B2(double) { } }; -struct D1 : B1 { +struct D1 : B1 { // { dg-error "no match" } using B1::B1; // implicitly declares D1(int) int x; }; void test() { D1 d(6); // OK: d.x is not initialized - D1 e; // { dg-error "no match" } D1 has no default constructor + D1 e; // { dg-error "deleted" } D1 has no default constructor } struct D2 : B2 { using B2::B2; // { dg-error "B1::B1" } diff --git a/gcc/testsuite/g++.dg/cpp1z/inh-ctor22.C b/gcc/testsuite/g++.dg/cpp1z/inh-ctor22.C index 98336a158c1..02ec58a3e8e 100644 --- a/gcc/testsuite/g++.dg/cpp1z/inh-ctor22.C +++ b/gcc/testsuite/g++.dg/cpp1z/inh-ctor22.C @@ -12,7 +12,7 @@ struct B2 { int get(); -struct D1 : B1 { +struct D1 : B1 { // { dg-message "B1::B1" } using B1::B1; // inherits B1(int, ...) int x; int y = get(); @@ -22,7 +22,7 @@ void test() { D1 d(2, 3, 4); // OK: B1 is initialized by calling B1(2, 3, 4), // then d.x is default-initialized (no initialization is performed), // then d.y is initialized by calling get() - D1 e; // { dg-error "" } D1 has no default constructor + D1 e; // { dg-error "" } D1 has a deleted default constructor } struct D2 : B2 { diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor2.C b/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor2.C index 82d14746df2..aa244bc04c1 100644 --- a/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor2.C +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor2.C @@ -9,10 +9,10 @@ template }; template - struct S2 : S1 { + struct S2 : S1 { // { dg-error "matching" } using S1::S1; }; int main() { - S2 s; // { dg-error "no matching function" } + S2 s; // { dg-error "deleted function" } } diff --git a/gcc/testsuite/g++.dg/template/crash7.C b/gcc/testsuite/g++.dg/template/crash7.C index 00d387c1197..691628e7878 100644 --- a/gcc/testsuite/g++.dg/template/crash7.C +++ b/gcc/testsuite/g++.dg/template/crash7.C @@ -10,4 +10,6 @@ template struct A template A(typename A::X) {} // { dg-error "incomplete" } }; -A a; // { dg-message "no match" } +// We currently don't give the "no match" error because we don't add the +// invalid constructor template to TYPE_METHODS. +A a; // { dg-message "required" } diff --git a/gcc/testsuite/g++.old-deja/g++.pt/error2.C b/gcc/testsuite/g++.old-deja/g++.pt/error2.C index 666aea0a1ef..2e65718b679 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/error2.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/error2.C @@ -9,7 +9,7 @@ public: void f () { - Test c; // { dg-error "no match" } + Test c; // { dg-message "required" } } -- 2.30.2