[pushed] c++: inherited default constructor [CWG2799]
Checks
Commit Message
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
base-commit: 5c5851bd93b8078bdd9665bc9bfe91fbf0028dc1
@@ -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;
}
new file mode 100644
@@ -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, "");