Hi,

this issue should be easy to fix. Broken code like:

void foo ()
{
  decltype (auto) a = foo;
}

triggers the gcc_assert in digest_init_r:

/* Come here only for aggregates: records, arrays, unions, complex numbers
     and vectors.  */
  gcc_assert (TREE_CODE (type) == ARRAY_TYPE
          || VECTOR_TYPE_P (type)
          || TREE_CODE (type) == RECORD_TYPE
          || TREE_CODE (type) == UNION_TYPE
          || TREE_CODE (type) == COMPLEX_TYPE);

because of course TREE_CODE (type) == FUNCTION_TYPE, none of the above. I said should be easy to fix because in fact convert_for_initialization is perfectly able to handle these cases and emit proper diagnostic, if called. What shall we do then? The patchlet below passes testing but we could also relax the gcc_assert itself, include FUNCTION_TYPE with/without checking cxx_dialect >= cxx14. We could drop the latter check in my patchlet. Or something else entirely.

Thanks!
Paolo.

////////////////////////
Index: cp/typeck2.c
===================================================================
--- cp/typeck2.c        (revision 236400)
+++ cp/typeck2.c        (working copy)
@@ -1074,10 +1074,14 @@ digest_init_r (tree type, tree init, bool nested,
        }
     }
 
-  /* Handle scalar types (including conversions) and references.  */
+  /* Handle scalar types (including conversions) and references.
+     Also handle cases of erroneous C++14 code involving function types
+     like (c++/70572): void foo () { decltype (auto) a = foo; }
+     and get a proper error message from convert_for_initialization.  */
   if ((TREE_CODE (type) != COMPLEX_TYPE
        || BRACE_ENCLOSED_INITIALIZER_P (init))
-      && (SCALAR_TYPE_P (type) || code == REFERENCE_TYPE))
+      && (SCALAR_TYPE_P (type) || code == REFERENCE_TYPE
+         || (TREE_CODE (type) == FUNCTION_TYPE && cxx_dialect >= cxx14)))
     {
       if (nested)
        flags |= LOOKUP_NO_NARROWING;
Index: testsuite/g++.dg/cpp1y/auto-fn31.C
===================================================================
--- testsuite/g++.dg/cpp1y/auto-fn31.C  (revision 0)
+++ testsuite/g++.dg/cpp1y/auto-fn31.C  (working copy)
@@ -0,0 +1,7 @@
+// PR c++/70572
+// { dg-do compile { target c++14 } }
+
+void foo ()
+{
+  decltype (auto) a = foo;  // { dg-error "cannot convert" }
+}

Reply via email to