PR c++/91930 - ICE with constrained inherited default ctor.
authorJason Merrill <jason@redhat.com>
Mon, 14 Oct 2019 20:13:49 +0000 (16:13 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 14 Oct 2019 20:13:49 +0000 (16:13 -0400)
The testcase was crashing because lazily_declare_fn was failing to add a
defaulted constructor, because the implicit declaration was less constrained
than the inherited default constructor.  But when we have an inherited
constructor, we shouldn't be trying to declare a default constructor in the
first place, because it counts as "a user-declared constructor".  With that
fixed I needed to adjust a couple of inherited constructor testcases that
previously had been diagnosing the default constructor as deleted rather
than not declared.

* name-lookup.c (do_class_using_decl): Set TYPE_HAS_USER_CONSTRUCTOR
for inherited constructor.

From-SVN: r276968

gcc/cp/ChangeLog
gcc/cp/name-lookup.c
gcc/testsuite/g++.dg/cpp0x/inh-ctor5.C
gcc/testsuite/g++.dg/cpp1z/inh-ctor22.C
gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor6.C [new file with mode: 0644]

index 2864107..7245b3e 100644 (file)
@@ -1,3 +1,9 @@
+2019-10-14  Jason Merrill  <jason@redhat.com>
+
+       PR c++/91930 - ICE with constrained inherited default ctor.
+       * name-lookup.c (do_class_using_decl): Set TYPE_HAS_USER_CONSTRUCTOR
+       for inherited constructor.
+
 2019-10-14  Paolo Carlini  <paolo.carlini@oracle.com>
 
        * decl.c (check_tag_decl): Use DECL_SOURCE_LOCATION.
index 57ab129..9352ce5 100644 (file)
@@ -4613,6 +4613,7 @@ do_class_using_decl (tree scope, tree name)
       maybe_warn_cpp0x (CPP0X_INHERITING_CTORS);
       name = ctor_identifier;
       CLASSTYPE_NON_AGGREGATE (current_class_type) = true;
+      TYPE_HAS_USER_CONSTRUCTOR (current_class_type) = true;
     }
 
   /* Cannot introduce a constructor name.  */
index d0038c1..673b638 100644 (file)
@@ -6,13 +6,13 @@ struct B1 {
 struct B2 {
   B2(double) { }
 };
-struct D1 : B1 {    // { dg-error "no match" }
+struct D1 : B1 {
   using B1::B1;            // implicitly declares D1(int)
   int x;
 };
 void test() {
   D1 d(6);         // OK: d.x is not initialized
-  D1 e;                    // { dg-error "deleted" } D1 has no default constructor
+  D1 e;                    // { dg-error "no match" } D1 has no default constructor
 }
 struct D2 : B2 {
   using B2::B2;            // { dg-error "B1::B1" }
index 02ec58a..98336a1 100644 (file)
@@ -12,7 +12,7 @@ struct B2 {
 
 int get();
 
-struct D1 : B1 {               // { dg-message "B1::B1" }
+struct D1 : 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 a deleted default constructor
+  D1 e;          // { dg-error "" } D1 has no default constructor
 }
 
 struct D2 : B2 {
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor6.C b/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor6.C
new file mode 100644 (file)
index 0000000..c92d6ac
--- /dev/null
@@ -0,0 +1,12 @@
+// PR c++/91930
+// { dg-do compile { target c++2a } }
+
+template <typename T> struct basic_mixin {
+  basic_mixin() requires true;
+};
+
+struct mixin : basic_mixin<int> {
+  using basic_mixin<int>::basic_mixin;
+};
+
+mixin m;