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.
This commit is contained in:
parent
a5a3c2dcf7
commit
08c8c973c0
12 changed files with 44 additions and 20 deletions
|
@ -14,6 +14,20 @@
|
|||
|
||||
2020-01-14 Jason Merrill <jason@redhat.com>
|
||||
|
||||
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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -11,7 +11,7 @@ template<typename T>
|
|||
};
|
||||
|
||||
template<typename T>
|
||||
struct S2 : S1<T> {
|
||||
struct S2 : S1<T> { // { dg-error "no matching function" }
|
||||
using S1<T>::S1; // { dg-error "no matching function" }
|
||||
};
|
||||
|
||||
|
@ -19,5 +19,5 @@ struct X { } x;
|
|||
|
||||
int main() {
|
||||
S2<X> s1(0); // { dg-error "use of deleted function" }
|
||||
S2<X> s2; // { dg-error "no matching function" }
|
||||
S2<X> s2; // { dg-error "use of deleted function" }
|
||||
}
|
||||
|
|
14
gcc/testsuite/g++.dg/cpp0x/inh-ctor35.C
Normal file
14
gcc/testsuite/g++.dg/cpp0x/inh-ctor35.C
Normal file
|
@ -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;
|
|
@ -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" }
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -9,10 +9,10 @@ template<typename T>
|
|||
};
|
||||
|
||||
template<typename T>
|
||||
struct S2 : S1<T> {
|
||||
struct S2 : S1<T> { // { dg-error "matching" }
|
||||
using S1<T>::S1;
|
||||
};
|
||||
|
||||
int main() {
|
||||
S2<int> s; // { dg-error "no matching function" }
|
||||
S2<int> s; // { dg-error "deleted function" }
|
||||
}
|
||||
|
|
|
@ -10,4 +10,6 @@ template <typename> struct A
|
|||
template <typename> A(typename A::X) {} // { dg-error "incomplete" }
|
||||
};
|
||||
|
||||
A<void> 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<void> a; // { dg-message "required" }
|
||||
|
|
|
@ -9,7 +9,7 @@ public:
|
|||
|
||||
void f ()
|
||||
{
|
||||
Test<void> c; // { dg-error "no match" }
|
||||
Test<void> c; // { dg-message "required" }
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue