re PR c++/64433 (Segmentation fault while compiling)
authorNathan Sidwell <nathan@acm.org>
Fri, 7 Oct 2016 20:01:17 +0000 (20:01 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Fri, 7 Oct 2016 20:01:17 +0000 (20:01 +0000)
cp/
PR c++/64433
DR1658, DR1611
* init.c (emit_mem_initializers): Don't construct vbases of
abstract classes.
(push_base_cleanups): Don't push vbase cleanups for abstract class
when in C++14 mode.
* method.c (synthethesized_method_walk): Don't walk vbases of
abstract classes when in C++14 mode.

testsuite/
PR c++/66443
* g++.dg/cpp0x/pr66443-cxx11.C: New.
* g++.dg/cpp0x/pr66443-cxx11-2.C: New.
* g++.dg/cpp1y/pr66443-cxx14.C: New
* g++.dg/cpp1y/pr66443-cxx14-2.C: New.
* g++.dg/cpp1y/pr66443-cxx14-3.C: New.

From-SVN: r240874

gcc/cp/ChangeLog
gcc/cp/init.c
gcc/cp/method.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/pr66443-cxx11-2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/pr66443-cxx11.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/pr66443-cxx14-2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/pr66443-cxx14-3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/pr66443-cxx14.C [new file with mode: 0644]

index ce875ce..da2ca07 100644 (file)
@@ -1,3 +1,14 @@
+2016-10-07  Nathan Sidwell  <nathan@acm.org>
+
+       PR c++/64433
+       DR1658, DR1611
+       * init.c (emit_mem_initializers): Don't construct vbases of
+       abstract classes.
+       (push_base_cleanups): Don't push vbase cleanups for abstract class
+       when in C++14 mode.
+       * method.c (synthethesized_method_walk): Don't walk vbases of
+       abstract classes when in C++14 mode.
+
 2016-10-07  Jakub Jelinek  <jakub@redhat.com>
 
        Implement LWG2296 helper intrinsic
index 63c3dab..a873bb1 100644 (file)
@@ -1154,9 +1154,7 @@ emit_mem_initializers (tree mem_inits)
        }
 
       /* Initialize the base.  */
-      if (BINFO_VIRTUAL_P (subobject))
-       construct_virtual_base (subobject, arguments);
-      else
+      if (!BINFO_VIRTUAL_P (subobject))
        {
          tree base_addr;
 
@@ -1170,6 +1168,10 @@ emit_mem_initializers (tree mem_inits)
                               tf_warning_or_error);
          expand_cleanup_for_base (subobject, NULL_TREE);
        }
+      else if (!ABSTRACT_CLASS_TYPE_P (current_class_type))
+       /* C++14 DR1658 Means we do not have to construct vbases of
+          abstract classes.  */
+       construct_virtual_base (subobject, arguments);
     }
   in_base_initializer = 0;
 
@@ -4536,7 +4538,8 @@ push_base_cleanups (void)
   vec<tree, va_gc> *vbases;
 
   /* Run destructors for all virtual baseclasses.  */
-  if (CLASSTYPE_VBASECLASSES (current_class_type))
+  if (!ABSTRACT_CLASS_TYPE_P (current_class_type)
+      && CLASSTYPE_VBASECLASSES (current_class_type))
     {
       tree cond = (condition_conversion
                   (build2 (BIT_AND_EXPR, integer_type_node,
index bbbf59b..73a670b 100644 (file)
@@ -1319,12 +1319,12 @@ walk_field_subobs (tree fields, tree fnname, special_function_kind sfk,
     }
 }
 
-/* The caller wants to generate an implicit declaration of SFK for CTYPE
-   which is const if relevant and CONST_P is set.  If spec_p, trivial_p and
-   deleted_p are non-null, set their referent appropriately.  If diag is
-   true, we're either being called from maybe_explain_implicit_delete to
-   give errors, or if constexpr_p is non-null, from
-   explain_invalid_constexpr_fn.  */
+/* The caller wants to generate an implicit declaration of SFK for
+   CTYPE which is const if relevant and CONST_P is set.  If SPEC_P,
+   TRIVIAL_P, DELETED_P or CONSTEXPR_P are non-null, set their
+   referent appropriately.  If DIAG is true, we're either being called
+   from maybe_explain_implicit_delete to give errors, or if
+   CONSTEXPR_P is non-null, from explain_invalid_constexpr_fn.  */
 
 static void
 synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
@@ -1534,9 +1534,13 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
     }
 
   vbases = CLASSTYPE_VBASECLASSES (ctype);
-  if (vec_safe_is_empty (vbases))
+  if (assign_p)
+    /* No need to examine vbases here.  */;
+  else if (vec_safe_is_empty (vbases))
     /* No virtual bases to worry about.  */;
-  else if (!assign_p)
+  else if (ABSTRACT_CLASS_TYPE_P (ctype) && cxx_dialect >= cxx14)
+    /* Vbase cdtors are not relevant.  */;
+  else
     {
       if (constexpr_p)
        *constexpr_p = false;
index 07cfac4..4d79c78 100644 (file)
@@ -1,3 +1,12 @@
+2016-10-07  Nathan Sidwell  <nathan@acm.org>
+
+       PR c++/66443
+       * g++.dg/cpp0x/pr66443-cxx11.C: New.
+       * g++.dg/cpp0x/pr66443-cxx11-2.C: New.
+       * g++.dg/cpp1y/pr66443-cxx14.C: New
+       * g++.dg/cpp1y/pr66443-cxx14-2.C: New.
+       * g++.dg/cpp1y/pr66443-cxx14-3.C: New.
+
 2016-10-07  Jakub Jelinek  <jakub@redhat.com>
 
        * g++.dg/cpp0x/addressof1.C: New test.
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr66443-cxx11-2.C b/gcc/testsuite/g++.dg/cpp0x/pr66443-cxx11-2.C
new file mode 100644 (file)
index 0000000..4bd641d
--- /dev/null
@@ -0,0 +1,23 @@
+// { dg-do compile { target c++11_only } }
+
+class C;
+
+  
+struct A {
+  A ();
+private:
+  ~A (){ }
+  friend class C;
+};
+
+struct B : virtual A {  // { dg-error "is private" }
+  B ();
+  virtual bool Ok () = 0; // abstract
+};
+
+struct C : B {  // { dg-error "use of deleted" }
+  C ();
+  virtual bool Ok ();
+};
+
+C c; // { dg-error "use of deleted" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr66443-cxx11.C b/gcc/testsuite/g++.dg/cpp0x/pr66443-cxx11.C
new file mode 100644 (file)
index 0000000..7ba0074
--- /dev/null
@@ -0,0 +1,30 @@
+// { dg-do compile { target c++11_only } }
+
+// pr c++/66443 it is still ill-formed in C++ 11 for a synthesized
+// ctor that's deleted only because of virtual base construction
+
+static bool a_made;
+
+struct A { // { dg-message "candidate" }
+  A( int ) { a_made = true; } // { dg-message "candidate" }
+};
+
+struct B: virtual A { // { dg-message "no matching function" }
+  int m;
+  virtual void Frob () = 0;
+};
+
+class C: public B {
+public:
+  C();
+  virtual void Frob ();
+};
+
+void C::Frob ()
+{
+}
+
+C::C ()
+  : A( 1 ) // { dg-error "deleted function" }
+{ }
+
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr66443-cxx14-2.C b/gcc/testsuite/g++.dg/cpp1y/pr66443-cxx14-2.C
new file mode 100644 (file)
index 0000000..e033f1f
--- /dev/null
@@ -0,0 +1,29 @@
+// { dg-do compile { target c++14 } }
+
+// pr c++/66443 a synthesized ctor of an abstract class that's deleted
+// only because of virtual base construction doesn't stop a derived
+// class using it as a base object constructor (provided it has a
+// suitable ctor invocation of the virtual base).
+
+// However we should still complain if the intermediate base is a
+// non-abstract type.
+
+static int a_made;
+
+struct A {
+  A *m_a = this;
+  A (int) { a_made++; }
+};
+
+struct B : virtual A { // { dg-error "no matching function" }
+  A *m_b = this;
+  virtual bool Ok (); // not abstract
+};
+
+bool B::Ok ()
+{
+  return false;
+}
+
+
+B b; // { dg-error "deleted" }
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr66443-cxx14-3.C b/gcc/testsuite/g++.dg/cpp1y/pr66443-cxx14-3.C
new file mode 100644 (file)
index 0000000..b335c4b
--- /dev/null
@@ -0,0 +1,25 @@
+// { dg-do compile { target c++14 } }
+
+// DR 1658, inaccessible dtor of virtual base doesn't affect an
+// abstract class
+
+int a_unmade;
+
+class C;
+
+  
+struct A {
+private:
+  ~A (){ a_unmade++; }
+  friend class C;
+};
+
+struct B : virtual A {
+  virtual bool Ok () = 0; // abstract
+};
+
+struct C : B {
+  virtual bool Ok ();
+};
+
+C c;
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr66443-cxx14.C b/gcc/testsuite/g++.dg/cpp1y/pr66443-cxx14.C
new file mode 100644 (file)
index 0000000..5834808
--- /dev/null
@@ -0,0 +1,47 @@
+// { dg-do run { target c++14 } }
+
+// pr c++/66443 a synthesized ctor of an abstract class that's deleted
+// only because of virtual base construction doesn't stop a derived
+// class using it as a base object constructor (provided it has a
+// suitable ctor invocation of the virtual base).
+
+static int a_made;
+
+struct A {
+  A *m_a = this;
+  A (int) { a_made++; }
+};
+
+struct B : virtual A {
+  A *m_b = this;
+  virtual bool Ok () = 0; // abstract
+};
+
+struct C : B {
+  // C::m_c is placed where a complete B object would put A
+  int m_c = 1729;
+public:
+  C();
+  virtual bool Ok ();
+};
+
+bool C::Ok ()
+{
+  // check everyone agreed on where A is
+  return a_made == 1 && m_a == this && m_b == this && m_c == 1729;
+}
+
+C::C ()
+  : A (1) // Explicit call of A's ctor
+{  }
+
+bool Ok (C &c)
+{
+}
+
+int main ()
+{
+  C c;
+
+  return !c.Ok ();
+}