Bug 89336 - internal compiler error when compiling a constexpr function
Summary: internal compiler error when compiling a constexpr function
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 8.2.0
: P3 normal
Target Milestone: ---
Assignee: Jakub Jelinek
URL:
Keywords: ice-on-valid-code
Depends on:
Blocks: constexpr
  Show dependency treegraph
 
Reported: 2019-02-13 15:50 UTC by Marek Szapiel
Modified: 2024-02-16 18:30 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2019-02-13 00:00:00


Attachments
gcc9-pr89336.patch (1.95 KB, patch)
2019-02-13 19:45 UTC, Jakub Jelinek
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Marek Szapiel 2019-02-13 15:50:09 UTC
g++ version: 8.2.0

Trying to compile the following source causes internal compiler error:
-------
#include <array>

constexpr std::array<int, 256> prepare()
{
  std::array<int, 256> r = {0};
  for ( int i = 0; i < 6; ++i )
  {
    r[i + 'a'] = r[i + 'A'] = i + 10;
  }
  return r;
}


int main()
{
  auto v = prepare();
  return 0;
}
-------

g++ -std=c++17 xx.cpp 
xx.cpp: In function ‘int main()’:
xx.cpp:16:20: internal compiler error: Segmentation fault
   auto v = prepare();
Comment 1 Marek Polacek 2019-02-13 16:03:26 UTC
Confirmed.
Comment 2 Marek Polacek 2019-02-13 16:07:16 UTC
The current ICE started with r267253:

89336.C: In function ‘int main()’:
89336.C:16:20: internal compiler error: Segmentation fault
0x13ae0c0 crash_signal
	../../gcc/toplev.c:326
0x89a0e1 initialized_type
	../../gcc/cp/constexpr.c:2830
0x89a2eb init_subob_ctx
	../../gcc/cp/constexpr.c:2864
0x89a8dc cxx_eval_bare_aggregate
	../../gcc/cp/constexpr.c:2951
0x8a205e cxx_eval_constant_expression
	../../gcc/cp/constexpr.c:4692
0x89a94d cxx_eval_bare_aggregate
	../../gcc/cp/constexpr.c:2956
0x8a205e cxx_eval_constant_expression
	../../gcc/cp/constexpr.c:4692
0x8a38ea cxx_eval_outermost_constant_expr
	../../gcc/cp/constexpr.c:5077
0x8a454c maybe_constant_value(tree_node*, tree_node*, bool)
	../../gcc/cp/constexpr.c:5309
0x8c2776 cp_fully_fold(tree_node*)
	../../gcc/cp/cp-gimplify.c:2161
0xb73a19 split_nonconstant_init(tree_node*, tree_node*)
	../../gcc/cp/typeck2.c:753
0xb7421d store_init_value(tree_node*, tree_node*, vec<tree_node*, va_gc, vl_embed>**, int)
	../../gcc/cp/typeck2.c:876
0x9041c4 check_initializer
	../../gcc/cp/decl.c:6491
0x90766d cp_finish_decl(tree_node*, tree_node*, bool, tree_node*, int)
	../../gcc/cp/decl.c:7167
0xa0faa8 cp_parser_init_declarator
	../../gcc/cp/parser.c:20327
0xa02a14 cp_parser_simple_declaration
	../../gcc/cp/parser.c:13414
0xa025a5 cp_parser_block_declaration
	../../gcc/cp/parser.c:13239
0xa01a00 cp_parser_declaration_statement
	../../gcc/cp/parser.c:12844
0x9fdb1a cp_parser_statement
	../../gcc/cp/parser.c:11169
0x9fe815 cp_parser_statement_seq_opt
	../../gcc/cp/parser.c:11531
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See <https://gcc.gnu.org/bugs/> for instructions.

but before that it ICEd also:

89336.C: In function ‘int main()’:
89336.C:16:20: internal compiler error: Segmentation fault
0x13ae0a2 crash_signal
	../../gcc/toplev.c:326
0xb7348a split_nonconstant_init_1
	../../gcc/cp/typeck2.c:641
0xb7350c split_nonconstant_init_1
	../../gcc/cp/typeck2.c:652
0xb73a1b split_nonconstant_init(tree_node*, tree_node*)
	../../gcc/cp/typeck2.c:755
0xb741ff store_init_value(tree_node*, tree_node*, vec<tree_node*, va_gc, vl_embed>**, int)
	../../gcc/cp/typeck2.c:876
0x9041a6 check_initializer
	../../gcc/cp/decl.c:6491
0x90764f cp_finish_decl(tree_node*, tree_node*, bool, tree_node*, int)
	../../gcc/cp/decl.c:7167
0xa0fa8a cp_parser_init_declarator
	../../gcc/cp/parser.c:20327
0xa029f6 cp_parser_simple_declaration
	../../gcc/cp/parser.c:13414
0xa02587 cp_parser_block_declaration
	../../gcc/cp/parser.c:13239
0xa019e2 cp_parser_declaration_statement
	../../gcc/cp/parser.c:12844
0x9fdafc cp_parser_statement
	../../gcc/cp/parser.c:11169
0x9fe7f7 cp_parser_statement_seq_opt
	../../gcc/cp/parser.c:11531
0x9fe6ed cp_parser_compound_statement
	../../gcc/cp/parser.c:11485
0xa13879 cp_parser_function_body
	../../gcc/cp/parser.c:22405
0xa13a3d cp_parser_ctor_initializer_opt_and_function_body
	../../gcc/cp/parser.c:22442
0xa1d7ec cp_parser_function_definition_after_declarator
	../../gcc/cp/parser.c:27495
0xa1d619 cp_parser_function_definition_from_specifiers_and_declarator
	../../gcc/cp/parser.c:27411
0xa0f2a1 cp_parser_init_declarator
	../../gcc/cp/parser.c:20097
0xa029f6 cp_parser_simple_declaration
	../../gcc/cp/parser.c:13414
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See <https://gcc.gnu.org/bugs/> for instructions.
Comment 3 Jakub Jelinek 2019-02-13 16:08:58 UTC
    r[i + 'a'] = i + 10;
    r[i + 'A'] = i + 10;
or
    r[i + 'a'] = i + 10;
    r[i + 'A'] = r[i + 'a'];
doesn't ICE.
Comment 4 Jakub Jelinek 2019-02-13 16:44:23 UTC
Reduced testcase:
template <typename T, int N> struct A {
  T a[N];
  constexpr T &operator[] (int x) { return a[x]; }
};

constexpr A<int, 16>
foo ()
{
  A<int, 16> r{};
  for (int i = 0; i < 6; ++i)
    r[i + 8] = r[i] = i;
  return r;
}

auto x = foo ();

Started to ICE with r217670, before that it has been accepted for a couple of revisions and before that rejected.
Comment 5 Jakub Jelinek 2019-02-13 17:00:02 UTC
The ICE actually isn't when processing the loop, but later on when processing the
VIEW_CONVERT_EXPR<struct A>({.a={0, 1, 2, 3, 4, 5, [8]=1, 2, 3, 4, 5, }});
expression.
When using
    {
      r[i] = i;
      r[i + 8] = i;
    }
as the loop body, I instead get:
{.a={0, 1, 2, 3, 4, 5, [8]=0, 1, 2, 3, 4, 5}}

In the bogus one, [8] doesn't have the value 0 but 1 and all the values are shifted by 1, with [13] having NULL value, just non-NULL purpose.
Comment 6 Jakub Jelinek 2019-02-13 19:45:27 UTC
Created attachment 45706 [details]
gcc9-pr89336.patch

Untested fix.  Pointing a pointer into a middle of vector that might be reallocated or where new elements might be added before the one to which we store (and that addition memmoves all the rest upwards) is dangerous.

This patch should fix that, except that it doesn't fix union handling.  I think
e.g.
constexpr int foo () {
  union U { int a; long b; };
  union V { union U u; short v; };
  V w {};
  w.u.a = w.v = w.u.b = 5L;
  return w.u.a;
}
static_assert (foo () == 5, "");

ICEs with it (previously it would fail).  Is the testcase valid C++?
clang++ rejects it.  The question is when exactly becomes a union member active
on the assignment, if only after evaluating the rhs, or it first becomes active member, then rhs is evaluated.
Comment 7 Jason Merrill 2019-02-19 01:02:22 UTC
Author: jason
Date: Tue Feb 19 01:01:50 2019
New Revision: 269003

URL: https://gcc.gnu.org/viewcvs?rev=269003&root=gcc&view=rev
Log:
	PR c++/89336 - multiple stores in constexpr stmt.

If we evaluate the RHS in the context of the LHS, that evaluation might
change the LHS in ways that mess with being able to store the value later.
So for assignment or scalar values, evaluate the RHS first.

	* constexpr.c (cxx_eval_store_expression): Preevaluate scalar or
	assigned value.

Added:
    trunk/gcc/testsuite/g++.dg/cpp1y/constexpr-89336-1.C
    trunk/gcc/testsuite/g++.dg/cpp1y/constexpr-89336-2.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/constexpr.c
Comment 8 Jakub Jelinek 2019-02-20 21:17:01 UTC
Author: jakub
Date: Wed Feb 20 21:16:27 2019
New Revision: 269052

URL: https://gcc.gnu.org/viewcvs?rev=269052&root=gcc&view=rev
Log:
	PR c++/89336
	* constexpr.c (cxx_eval_store_expression): Diagnose changing of active
	union member for -std=c++17 and earlier.

	* g++.dg/cpp1y/constexpr-89336-3.C: New test.

Added:
    trunk/gcc/testsuite/g++.dg/cpp1y/constexpr-89336-3.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/constexpr.c
    trunk/gcc/testsuite/ChangeLog
Comment 9 Marek Polacek 2020-07-23 19:33:12 UTC
Fixed?
Comment 10 Marek Polacek 2024-02-16 18:30:36 UTC
Assuming fixed.