Hi,

in this ICE on invalid regression, after a sensible error message about the invalid base type we crash in implicit_declare_fn at the gcc_assert:

  else if (trivial_p && cxx_dialect >= cxx11
       && (kind == sfk_copy_constructor
           || kind == sfk_move_constructor))
    gcc_assert (constexpr_p);

This happens because synthesized_method_walk sets *trivial_p to true and then envisages to check the vbases with:

  if (vbases == NULL)
    /* No virtual bases to worry about.  */;
  else if (!assign_p)
    {
      if (constexpr_p)
    *constexpr_p = false;
      FOR_EACH_VEC_ELT (*vbases, i, base_binfo)

the loop doesn't execute at all, vbases->is_empty is true, and *constexpr_p remains false, inconsistently with *trivial_p.

Normally, that is outside error recovery, either vbases is null or the vector is non-empty, but in the cases at issue, when xref_basetypes bails out early with an error about the invalid base type, that isn't true, the vector is allocated in xref_basetypes but remains empty.

I tried to figure out a way to completely avoid such circumstances, but rearranging the loop in xref_basetypes doesn't seem easy, or at least not completely safe at this stage, thus the below.

Thanks,
Paolo.

//////////////////////////
/cp
2014-02-03  Paolo Carlini  <paolo.carl...@oracle.com>

        PR c++/58871
        * method.c (synthesized_method_walk): If vbases is non-null but
        is_empty is true, likewise don't worry about the virtual bases.

/testsuite
2014-02-03  Paolo Carlini  <paolo.carl...@oracle.com>

        PR c++/58871
        * g++.dg/cpp0x/pr58871.C: New.
Index: cp/method.c
===================================================================
--- cp/method.c (revision 207422)
+++ cp/method.c (working copy)
@@ -1366,7 +1366,9 @@ synthesized_method_walk (tree ctype, special_funct
     }
 
   vbases = CLASSTYPE_VBASECLASSES (ctype);
-  if (vbases == NULL)
+  if (vbases == NULL
+      /* Can happen for invalid base types (c++/58871).  */
+      || vbases->is_empty ())
     /* No virtual bases to worry about.  */;
   else if (!assign_p)
     {
Index: testsuite/g++.dg/cpp0x/pr58871.C
===================================================================
--- testsuite/g++.dg/cpp0x/pr58871.C    (revision 0)
+++ testsuite/g++.dg/cpp0x/pr58871.C    (working copy)
@@ -0,0 +1,12 @@
+// PR c++/59111
+// { dg-do compile { target c++11 } }
+
+template<typename T> struct A : virtual T  // { dg-error "base type" }
+{
+  A();
+  A(const A&);
+};
+
+template<typename T> A<T>::A(const A<T>&) = default;
+
+A<int> a = A<int>();

Reply via email to