aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2023-09-18 22:16:04 -0400
committerJason Merrill <jason@redhat.com>2023-09-19 11:28:55 -0400
commit1560cc94e8a6c309a74d0a1a24820087e149733b (patch)
treef35df570fb8e9f7b69a43b97462fc39437737b15
parentbf6b107e2a342319b3787ec960fc8014ef3aff91 (diff)
downloadgcc-1560cc94e8a6c309a74d0a1a24820087e149733b.zip
gcc-1560cc94e8a6c309a74d0a1a24820087e149733b.tar.gz
gcc-1560cc94e8a6c309a74d0a1a24820087e149733b.tar.bz2
c++: inherited default constructor [CWG2799]
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.
-rw-r--r--gcc/cp/class.cc36
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/inh-ctor38.C19
2 files changed, 43 insertions, 12 deletions
diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc
index d270dcbb1..469e98e 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 0000000..56217be
--- /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, "");