Bug 78572 - [6 Regression] internal compiler error: in output_constructor_regular_field, at varasm.c:4968
Summary: [6 Regression] internal compiler error: in output_constructor_regular_field, ...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 6.2.1
: P2 normal
Target Milestone: 7.0
Assignee: Jason Merrill
URL:
Keywords: ice-on-valid-code
Depends on:
Blocks:
 
Reported: 2016-11-28 19:45 UTC by comer352l
Modified: 2020-04-13 21:04 UTC (History)
5 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail: 6.2.0, 7.0
Last reconfirmed: 2016-11-29 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description comer352l 2016-11-28 19:45:32 UTC
static int array[10] = { array[3]=5, array[7]=3, };

int main ()
{
	return 0;
}

=> leads to the following compilation error:

main.c:7:1: internal compiler error: in output_constructor_regular_field, at varasm.c:4968
 }
 ^
Please submit a full bug report
Comment 1 Martin Sebor 2016-11-29 00:25:46 UTC
Confirmed.  Bisection points to r234636 as the change that caused it.  Looks like it's a 6/7 regression, though designated initializers don't fully work in G++.

(gcc 6.0.0) failed (status 4):
------------------------------------------------------------------------
r234636 | nathan | 2016-03-31 11:30:33 -0400 (Thu, 31 Mar 2016) | 11 lines

	PR c++/70393
	* varasm.c (output_constructor_regular_field): Flush bitfield
	earlier.  Assert we don't want to move backwards.

	cp/
	* constexpr.c (cxx_eval_store_expression): Keep CONSTRUCTOR
	elements in field order.

	testsuite/
	* g++.dg/cpp0x/constexpr-virtual6.C: New.


The full stack trace is below:

t.C:7:1: internal compiler error: in output_constructor_regular_field, at varasm.c:4989
 }
 ^
0x148b5bf output_constructor_regular_field
	../../gcc/varasm.c:4989
0x148c3a5 output_constructor
	../../gcc/varasm.c:5297
0x148aaf4 output_constant
	../../gcc/varasm.c:4794
0x1482165 assemble_variable_contents
	../../gcc/varasm.c:2083
0x1482bbf assemble_variable(tree_node*, int, int, int)
	../../gcc/varasm.c:2259
0x149a0bc varpool_node::assemble_decl()
	../../gcc/varpool.c:588
0xbab20d output_in_order
	../../gcc/cgraphunit.c:2248
0xbab8d2 symbol_table::compile()
	../../gcc/cgraphunit.c:2488
0xbabb1b symbol_table::finalize_compilation_unit()
	../../gcc/cgraphunit.c:2584
Please submit a full bug report,
Comment 2 Jakub Jelinek 2016-12-01 11:54:50 UTC
But this isn't a designed array initializer, it is a normal initializer with side-effects in it.
And presumably the C++ FE lowered that into
{[3]=5, [0]=5, [7]=3, [1]=3}
which is considered invalid by the middle-end, since it isn't sorted by increasing index.
With
static int array[10] = { array[3]=5, array[7]=3, array[7]=8, array[7] = 9 };
it is even worse, we get
{[3]=5, [0]=5, [7]=9, [1]=3, [2]=8, [3]=9}
so [3] is written twice.  Not sure if this isn't undefined behavior (I hope it is), but still we shouldn't ICE on it, best would be not to turn the stores into CONSTRUCTOR elements, but just handle the side-effects at runtime.
Comment 3 Aldy Hernandez 2016-12-20 09:23:19 UTC
I'll take a stab.
Comment 4 Jakub Jelinek 2016-12-21 10:56:55 UTC
GCC 6.3 is being released, adjusting target milestone.
Comment 5 Marek Polacek 2017-01-11 11:09:12 UTC
Bug 78897 might be a dup of this.
Comment 6 Jason Merrill 2017-02-16 16:42:38 UTC
Author: jason
Date: Thu Feb 16 16:42:06 2017
New Revision: 245511

URL: https://gcc.gnu.org/viewcvs?rev=245511&root=gcc&view=rev
Log:
	PR c++/78572 - ICE with self-modifying array initializer

	* constexpr.c (cxx_eval_store_expression): The object we're
	initializing is outside the constant-expression.

Added:
    trunk/gcc/testsuite/g++.dg/init/array47.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/constexpr.c
Comment 7 Jason Merrill 2017-02-16 16:45:21 UTC
Fixed on trunk so far.
Comment 8 Richard Biener 2017-07-04 08:46:48 UTC
GCC 6.4 is being released, adjusting target milestone.
Comment 9 Jakub Jelinek 2018-10-26 11:27:30 UTC
GCC 6 branch is being closed, fixed in 7.x.
Comment 10 GCC Commits 2020-04-13 21:04:48 UTC
The master branch has been updated by Patrick Palka <ppalka@gcc.gnu.org>:

https://gcc.gnu.org/g:077dd9b3f17710da8af6adce816754ddceb57b5a

commit r10-7704-g077dd9b3f17710da8af6adce816754ddceb57b5a
Author: Patrick Palka <ppalka@redhat.com>
Date:   Mon Apr 13 16:53:02 2020 -0400

    c++: More self-modifying constexpr init [PR94470]
    
    In this PR we're incorrectly rejecting a self-modifying constexpr initializer as
    a consequence of the fix for PR78572.
    
    It looks like however that the fix for PR78572 is obsoleted by the fix for
    PR89336: the testcase from the former PR successfully compiles even with its fix
    reverted.
    
    But then further testing showed that the analogous testcase of PR78572 where the
    array has an aggregate element type is still problematic (i.e. we ICE) even with
    the fix for PR78572 applied.  The reason is that in cxx_eval_bare_aggregate we
    attach a constructor_elt of aggregate type always to the end of the new
    CONSTRUCTOR, but that's not necessarily correct if the CONSTRUCTOR is
    self-modifying.  We should instead be using get_or_insert_ctor_field to insert
    the constructor_elt in the right place.
    
    So this patch reverts the PR78572 fix and makes the appropriate changes to
    cxx_eval_bare_aggregate.  This fixes PR94470, and we now are also able to fully
    reduce the initializers of 'arr' and 'arr2' in the new test array57.C to
    constant initializers.
    
    gcc/cp/ChangeLog:
    
            PR c++/94470
            * constexpr.c (get_or_insert_ctor_field): Set default value of parameter
            'pos_hint' to -1.
            (cxx_eval_bare_aggregate): Use get_or_insert_ctor_field instead of
            assuming the the next index belongs at the end of the new CONSTRUCTOR.
            (cxx_eval_store_expression): Revert PR c++/78572 fix.
    
    gcc/testsuite/ChangeLog:
    
            PR c++/94470
            * g++.dg/cpp1y/constexpr-nsdmi8.C: New test.
            * g++.dg/cpp1y/constexpr-nsdmi9.C: New test.
            * g++.dg/init/array57.C: New test.