Hi!

On the following testcase we ICE, because expand_or_defer_fn is called
multiple times on the same ctor (once from instantiation of constexpr
functions, once from c_parse_final_cleanups) and this calls maybe_clone_body
which isn't really prepared to be called multiple times.  In particular,
when the clones already have DECL_INITIAL etc., calling
start_preparsed_function on it again doesn't set cfun to non-NULL and the
code wants to store something there (but generally, it is pointless to do it
again even if it worked).  If maybe_clone_body returns true, we set
TREE_ASM_WRITTEN:
  if (maybe_clone_body (fn))
    {
      /* We don't want to process FN again, so pretend we've written
         it out, even though we haven't.  */
      TREE_ASM_WRITTEN (fn) = 1;
      /* If this is a constexpr function, keep DECL_SAVED_TREE.  */
      if (!DECL_DECLARED_CONSTEXPR_P (fn))
        DECL_SAVED_TREE (fn) = NULL_TREE;
      return false;
    }
but if it doesn't because it wants to emit the original ctor as well (can't
use aliases), then we don't set that.  This patch moves the -fsyntax-only
setting of the TREE_ASM_WRITTEN bit from c_parse_final_cleanups to
expand_or_defer_fn_1, so that if we do it once, we don't do that again.
For -fsyntax-only, I believe there is nothing further we want to do on the
cdtor.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2019-02-20  Jakub Jelinek  <ja...@redhat.com>

        PR c++/89403
        * decl2.c (c_parse_final_cleanups): Move TREE_ASM_WRITTEN setting
        for flag_syntax_only from here...
        * semantics.c (expand_or_defer_fn_1): ... here.

        * g++.dg/cpp0x/pr89403.C: New test.

--- gcc/cp/decl2.c.jj   2019-01-25 23:46:07.045183165 +0100
+++ gcc/cp/decl2.c      2019-02-20 18:37:36.824869503 +0100
@@ -4965,11 +4965,6 @@ c_parse_final_cleanups (void)
              /* Generate RTL for this function now that we know we
                 need it.  */
              expand_or_defer_fn (decl);
-             /* If we're compiling -fsyntax-only pretend that this
-                function has been written out so that we don't try to
-                expand it again.  */
-             if (flag_syntax_only)
-               TREE_ASM_WRITTEN (decl) = 1;
              reconsider = true;
            }
        }
--- gcc/cp/semantics.c.jj       2019-02-18 20:48:37.667649895 +0100
+++ gcc/cp/semantics.c  2019-02-20 18:45:00.582682109 +0100
@@ -4352,7 +4352,12 @@ expand_or_defer_fn_1 (tree fn)
   /* There's no reason to do any of the work here if we're only doing
      semantic analysis; this code just generates RTL.  */
   if (flag_syntax_only)
-    return false;
+    {
+      /* Pretend that this function has been written out so that we don't try
+        to expand it again.  */
+      TREE_ASM_WRITTEN (fn) = 1;
+      return false;
+    }
 
   return true;
 }
--- gcc/testsuite/g++.dg/cpp0x/pr89403.C.jj     2019-02-20 18:41:01.007535052 
+0100
+++ gcc/testsuite/g++.dg/cpp0x/pr89403.C        2019-02-20 18:40:05.687424739 
+0100
@@ -0,0 +1,18 @@
+// PR c++/89403
+// { dg-do compile { target c++11 } }
+// { dg-options "-Os -fsyntax-only" }
+
+template <typename T>
+struct A : T {
+  constexpr A() : T() { }
+};
+
+template <typename T>
+struct B {
+  A<T> b;
+  constexpr B() { }
+};
+
+struct C { struct {} s; };
+constexpr B<C> b{};
+constexpr C c = b.b;

        Jakub

Reply via email to