Created attachment 38508 [details] A source file which reproduces the problem Using built-in specs. COLLECT_GCC=g++ COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/6/lto-wrapper Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Debian 6.1.1-3' --with-bugurl=file:///usr/share/doc/gcc-6/README.Bugs --enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-6 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-6-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-6-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-6-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 6.1.1 20160511 (Debian 6.1.1-3) Compile the attached source with "g++ -c foo.cxx": /tmp/foo.cxx: In constructor 'constexpr BarContainer::BarContainer()': /tmp/foo.cxx:8:8: in constexpr expansion of 'Bar()' /tmp/foo.cxx:5:22: in constexpr expansion of 'MakeFoo()' /tmp/foo.cxx:8:8: internal compiler error: in cxx_eval_call_expression, at cp/constexpr.c:1449 struct BarContainer { ^~~~~~~~~~~~ 0x6f9649 cxx_eval_call_expression ../../src/gcc/cp/constexpr.c:1449 0x6fab6f cxx_eval_constant_expression ../../src/gcc/cp/constexpr.c:3556 0x6fae5d cxx_eval_constant_expression ../../src/gcc/cp/constexpr.c:3616 0x6fc651 cxx_eval_store_expression ../../src/gcc/cp/constexpr.c:3123 0x6fa39c cxx_eval_constant_expression ../../src/gcc/cp/constexpr.c:3633 0x6f9f08 cxx_eval_constant_expression ../../src/gcc/cp/constexpr.c:3901 0x6fa185 cxx_eval_constant_expression ../../src/gcc/cp/constexpr.c:3672 0x6fa185 cxx_eval_constant_expression ../../src/gcc/cp/constexpr.c:3672 0x6fab90 cxx_eval_constant_expression ../../src/gcc/cp/constexpr.c:4014 0x6f92d2 cxx_eval_call_expression ../../src/gcc/cp/constexpr.c:1494 0x6fab6f cxx_eval_constant_expression ../../src/gcc/cp/constexpr.c:3556 0x6fd1f6 cxx_eval_outermost_constant_expr ../../src/gcc/cp/constexpr.c:4121 0x6fec81 maybe_constant_init(tree_node*, tree_node*) ../../src/gcc/cp/constexpr.c:4439 0x69b07e build_vec_init(tree_node*, tree_node*, tree_node*, bool, int, int) ../../src/gcc/cp/init.c:4176 0x6eb43d cp_gimplify_expr(tree_node**, gimple**, gimple**) ../../src/gcc/cp/cp-gimplify.c:591 0x8d62b5 gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int) ../../src/gcc/gimplify.c:10196 0x8d9cb6 gimplify_stmt(tree_node**, gimple**) ../../src/gcc/gimplify.c:5688 0x8d6aa8 gimplify_cleanup_point_expr ../../src/gcc/gimplify.c:5464 0x8d6aa8 gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int) ../../src/gcc/gimplify.c:10652 0x8d9cb6 gimplify_stmt(tree_node**, gimple**) ../../src/gcc/gimplify.c:5688
Confirmed. Both 6.1.0 and 7.0 are affected, 5.3.0 is not. If my bisection script isn't lying it looks like r235033 introduced the ICE.
Yes, it is indeed r235033. I have no idea how is constexpr handling meant to work vs. gimplification though, perhaps this is also related to PR68949. What happens in this PR is that we process some constexpr stuff, then gimplify MakeFoo and then process further constexpr stuff. But gimplification is destructive, destroys the individual parts of DECL_SAVED_TREE as well as clears DECL_SAVED_TREE at the end.
Created attachment 38514 [details] slightly more reduced test case We're invoking constexpr evaluation machinery after parsing is complete -- fini_constexpt has already been called. This occurs during the emission of BarContainer's constructor, after we've destructively gimplified MakeFoo. We end up in 0xa05bf2 maybe_constant_init(tree_node*, tree_node*) ../../../src/gcc/cp/constexpr.c:4457 0x929ce6 build_vec_init(tree_node*, tree_node*, tree_node*, bool, int, int) ../../../src/gcc/cp/init.c:4178 0x9db06b cp_gimplify_expr(tree_node**, gimple**, gimple**) ../../../src/gcc/cp/cp-gimplify.c:592 and from there we have const_expr_eval (Bar) -> const_expr_eval (MakeFoo) -> ICE The object we're gimplifying is a vec_init_expr
build_vec_init_elt (tree.c) says: /* Subroutine of build_vec_init_expr: Build up a single element intialization as a proxy for the full array initialization to get things marked as used and any appropriate diagnostics. Since we're deferring building the actual constructor calls until gimplification time, we need to build one now and throw it away so that the relevant constructor gets mark_used before cgraph decides what functions are needed. Here we assume that init is either NULL_TREE, void_type_node (indicating value-initialization), or another array to copy. */ With constexprs now in play, that appears to be an incorrect approach. I'm not sure why it's even sensible to go building things early only to throw them away and redo it. It would seem better to just build the constructor (or whatever) tree and keep it.
(In reply to Nathan Sidwell from comment #4) > build_vec_init_elt (tree.c) says: > > /* Subroutine of build_vec_init_expr: Build up a single element > intialization as a proxy for the full array initialization to get things > marked as used and any appropriate diagnostics. > > Since we're deferring building the actual constructor calls until > gimplification time, we need to build one now and throw it away so > that the relevant constructor gets mark_used before cgraph decides > what functions are needed. Here we assume that init is either > NULL_TREE, void_type_node (indicating value-initialization), or > another array to copy. */ > > With constexprs now in play, that appears to be an incorrect approach. I'm > not sure why it's even sensible to go building things early only to throw > them away and redo it. It would seem better to just build the constructor > (or whatever) tree and keep it. I was trying with VEC_INIT_EXPR to get the same "floating initialization of an object to be determined later" semantics that we have with AGGR_INIT_EXPR, but indeed deferring all that building until after we've thrown away a lot of front end information doesn't make sense. For GCC 6 the minimal fix would be to disable try_const if (at_eof > 1), but for GCC 7 we should reconsider VEC_INIT_EXPR entirely.
Adding an at_eof check into try_const fixes the testcase. (also) Adding an at_eof <= 1 assert into cxx_eval_outermost_constant_expr causes 261 new fails. Although many are obviously init & ctor related, they're a fairly widely distributed bunch -- one is even abi name mangling. I don't see any a priori reason as to why those calls to cxx_eval_outermost_constant_expr couldn't end up evaluating a constexpr call.
Author: jason Date: Tue May 31 21:36:46 2016 New Revision: 236955 URL: https://gcc.gnu.org/viewcvs?rev=236955&root=gcc&view=rev Log: PR c++/71166 - constexpr array init * decl2.c (c_parse_final_cleanups): Don't call fini_constexpr. Added: branches/gcc-6-branch/gcc/testsuite/g++.dg/cpp0x/constexpr-array16.C Modified: branches/gcc-6-branch/gcc/cp/ChangeLog branches/gcc-6-branch/gcc/cp/decl2.c
So is this PR now fixed on the branch and still broken on the trunk? If yes, we should turn it into [7 Regression] then.
Yes. And we should have added a testcase.
At this point it is getting too late to reconsider VEC_INIT_EXPR for GCC 7, so shall we apply the fix from GCC 7 to trunk too?
I think this ought to be P1, because it is a regression from 6.2/6.3 to 7.
Actually, this seems to be fixed on the trunk too. Fixed in r238395. Should I add the testcase from this PR and close it?
Adding the testcase.
Author: mpolacek Date: Fri Jan 13 17:27:54 2017 New Revision: 244450 URL: https://gcc.gnu.org/viewcvs?rev=244450&root=gcc&view=rev Log: PR c++/71166 * g++.dg/cpp0x/constexpr-array18.C: New test. Added: trunk/gcc/testsuite/g++.dg/cpp0x/constexpr-array18.C Modified: trunk/gcc/testsuite/ChangeLog
Fixed.
But gcc-7-branch and 8.x trunk reverted the Remove? -fini_constexpr ();