Tested x86_64-pc-linux-gnu, applying to trunk. -- 8< --
In this testcase, it seems clear that B should be trivially default-constructible, since the inherited default constructor is trivial and there are no other subobjects to initialize. But we were saying no because we don't define triviality of inherited constructors. CWG discussion suggested that the solution is to implicitly declare a default constructor when inheriting a default constructor; that makes sense to me. DR 2799 gcc/cp/ChangeLog: * class.cc (add_implicit_default_ctor): Split out... (add_implicitly_declared_members): ...from here. Also call it when inheriting a default ctor. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/inh-ctor38.C: New test. --- gcc/cp/class.cc | 36 ++++++++++++++++--------- gcc/testsuite/g++.dg/cpp0x/inh-ctor38.C | 19 +++++++++++++ 2 files changed, 43 insertions(+), 12 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/inh-ctor38.C diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc index d270dcbb14c..469e98ed8b7 100644 --- a/gcc/cp/class.cc +++ b/gcc/cp/class.cc @@ -3292,6 +3292,22 @@ one_inherited_ctor (tree ctor, tree t, tree using_decl) } } +/* Implicitly declare T(). */ + +static void +add_implicit_default_ctor (tree t) +{ + TYPE_HAS_DEFAULT_CONSTRUCTOR (t) = 1; + CLASSTYPE_LAZY_DEFAULT_CTOR (t) = 1; + if (cxx_dialect >= cxx11) + TYPE_HAS_CONSTEXPR_CTOR (t) + /* Don't force the declaration to get a hard answer; if the + definition would have made the class non-literal, it will still be + non-literal because of the base or member in question, and that + gives a better diagnostic. */ + = type_maybe_constexpr_default_constructor (t); +} + /* Create default constructors, assignment operators, and so forth for the type indicated by T, if they are needed. CANT_HAVE_CONST_CTOR, and CANT_HAVE_CONST_ASSIGNMENT are nonzero if, for whatever reason, @@ -3320,17 +3336,7 @@ add_implicitly_declared_members (tree t, tree* access_decls, If there is no user-declared constructor for a class, a default constructor is implicitly declared. */ if (! TYPE_HAS_USER_CONSTRUCTOR (t)) - { - TYPE_HAS_DEFAULT_CONSTRUCTOR (t) = 1; - CLASSTYPE_LAZY_DEFAULT_CTOR (t) = 1; - if (cxx_dialect >= cxx11) - TYPE_HAS_CONSTEXPR_CTOR (t) - /* Don't force the declaration to get a hard answer; if the - definition would have made the class non-literal, it will still be - non-literal because of the base or member in question, and that - gives a better diagnostic. */ - = type_maybe_constexpr_default_constructor (t); - } + add_implicit_default_ctor (t); /* [class.ctor] @@ -3394,7 +3400,13 @@ add_implicitly_declared_members (tree t, tree* access_decls, location_t loc = input_location; input_location = DECL_SOURCE_LOCATION (using_decl); for (tree fn : ovl_range (ctor_list)) - one_inherited_ctor (fn, t, using_decl); + { + if (!TYPE_HAS_DEFAULT_CONSTRUCTOR (t) && default_ctor_p (fn)) + /* CWG2799: Inheriting a default constructor gives us a default + constructor, not just an inherited constructor. */ + add_implicit_default_ctor (t); + one_inherited_ctor (fn, t, using_decl); + } *access_decls = TREE_CHAIN (*access_decls); input_location = loc; } diff --git a/gcc/testsuite/g++.dg/cpp0x/inh-ctor38.C b/gcc/testsuite/g++.dg/cpp0x/inh-ctor38.C new file mode 100644 index 00000000000..56217be1aae --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/inh-ctor38.C @@ -0,0 +1,19 @@ +// CWG 2799 +// Test that inheriting a trivial default constructor produces a trivial +// default constructor. + +// { dg-do compile { target c++11 } } + +#include <type_traits> + +struct A { + A() = default; +}; + +struct B : A +{ + using A::A; + B(int); +}; + +static_assert (std::is_trivially_constructible<B>::value, ""); base-commit: 5c5851bd93b8078bdd9665bc9bfe91fbf0028dc1 -- 2.39.3