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