Bug 70344 - [6/7 Regression] ICE on invalid code at -O1 and above on x86_64-linux-gnu in record_reference, at cgraphbuild.c:64
Summary: [6/7 Regression] ICE on invalid code at -O1 and above on x86_64-linux-gnu in ...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 6.0
: P1 normal
Target Milestone: 6.0
Assignee: Jason Merrill
URL:
Keywords: ice-on-valid-code
Depends on:
Blocks:
 
Reported: 2016-03-21 19:32 UTC by Zhendong Su
Modified: 2016-05-24 04:15 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2016-03-21 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Zhendong Su 2016-03-21 19:32:01 UTC
The following code causes an ICE when compiled with the current GCC trunk on x86_64-linux-gnu at -O1 and above in both 32-bit and 64-bit modes. 

This is a regression from 5.3.x. 


$ g++-trunk -v
Using built-in specs.
COLLECT_GCC=g++-trunk
COLLECT_LTO_WRAPPER=/usr/local/gcc-trunk/libexec/gcc/x86_64-pc-linux-gnu/6.0.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: ../gcc-source-trunk/configure --enable-languages=c,c++,lto --prefix=/usr/local/gcc-trunk --disable-bootstrap
Thread model: posix
gcc version 6.0.0 20160321 (experimental) [trunk revision 234361] (GCC) 
$ 
$ g++-trunk -O0 -std=c++11 -c small.cpp
$ g++-5.3 -O1 -std=c++11 -c small.cpp
$ 
$ g++-trunk -O1 -std=c++11 -c small.cpp
small.cpp: In instantiation of ‘constexpr int fn(T) [with T = Z]’:
small.cpp:15:18:   required from here
small.cpp:13:1: internal compiler error: in adjust_temp_type, at cp/constexpr.c:1078
 }
 ^
0x84505a adjust_temp_type
	../../gcc-source-trunk/gcc/cp/constexpr.c:1078
0x84bbfb cxx_bind_parameters_in_call
	../../gcc-source-trunk/gcc/cp/constexpr.c:1128
0x84bbfb cxx_eval_call_expression
	../../gcc-source-trunk/gcc/cp/constexpr.c:1312
0x84d57b cxx_eval_constant_expression
	../../gcc-source-trunk/gcc/cp/constexpr.c:3381
0x853a19 cxx_eval_outermost_constant_expr
	../../gcc-source-trunk/gcc/cp/constexpr.c:3946
0x85671c maybe_constant_value_1
	../../gcc-source-trunk/gcc/cp/constexpr.c:4134
0x85671c maybe_constant_value(tree_node*, tree_node*)
	../../gcc-source-trunk/gcc/cp/constexpr.c:4155
0x830a9f cp_fold
	../../gcc-source-trunk/gcc/cp/cp-gimplify.c:2188
0x830816 cp_fold_rvalue
	../../gcc-source-trunk/gcc/cp/cp-gimplify.c:1887
0x830816 cp_fold
	../../gcc-source-trunk/gcc/cp/cp-gimplify.c:2072
0x83135e cp_fold_r
	../../gcc-source-trunk/gcc/cp/cp-gimplify.c:944
0x1009b64 walk_tree_1(tree_node**, tree_node* (*)(tree_node**, int*, void*), void*, hash_set<tree_node*, default_hash_traits<tree_node*> >*, tree_node* (*)(tree_node**, int*, tree_node* (*)(tree_node**, int*, void*), void*, hash_set<tree_node*, default_hash_traits<tree_node*> >*))
	../../gcc-source-trunk/gcc/tree.c:11531
0x65701f finish_function(int)
	../../gcc-source-trunk/gcc/cp/decl.c:14688
0x67b622 instantiate_decl(tree_node*, int, bool)
	../../gcc-source-trunk/gcc/cp/pt.c:22029
0x7098ea mark_used(tree_node*, int)
	../../gcc-source-trunk/gcc/cp/decl2.c:5279
0x612481 build_over_call
	../../gcc-source-trunk/gcc/cp/call.c:7706
0x621b3f build_new_function_call(tree_node*, vec<tree_node*, va_gc, vl_embed>**, bool, int)
	../../gcc-source-trunk/gcc/cp/call.c:4152
0x7bc4a1 finish_call_expr(tree_node*, vec<tree_node*, va_gc, vl_embed>**, bool, bool, int)
	../../gcc-source-trunk/gcc/cp/semantics.c:2461
0x736799 cp_parser_postfix_expression
	../../gcc-source-trunk/gcc/cp/parser.c:6904
0x73fb0c cp_parser_unary_expression
	../../gcc-source-trunk/gcc/cp/parser.c:7988
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See <http://gcc.gnu.org/bugs.html> for instructions.
$ 


---------------------------------


struct Z
{
  Z () = default;
  Z (Z const &) = default;
  constexpr Z (Z &&) {}
};

template < typename T > 
constexpr int 
fn (T v)
{
  return fn (v);
}

auto t = fn (Z ());
Comment 1 Marek Polacek 2016-03-21 19:39:48 UTC
Started with r230365.
Comment 2 Patrick Palka 2016-03-23 01:49:03 UTC
fn does not have to be a function template to trigger the ICE:

struct Z
{
  Z () = default;
  Z (Z const &) = default;
  constexpr Z (Z &&) {}
};

constexpr int
fn (Z v)
{
  return fn (v);
}

auto t = fn (Z ());
Comment 3 Patrick Palka 2016-03-23 02:05:23 UTC
Problem ultimately seems to be that we're calling cp_fold_function on fn() before we call cp_genericize on it which is responsible for fixing up fn()'s parameter 'v' which is passed by invisible reference.  The TREE_TYPE of v is a RECORD_TYPE before the fix-up, but after the fix-up it's a REFERENCE_TYPE to a RECORD_TYPE.  The 1st argument to the recursive call to fn() however is a REFERENCE_TYPE. So in cxx_eval_call_expression (called indirectly from cp_fold_function) we see that fn() expects a RECORD_TYPE (because its parms haven't been fixed up yet) but the call passes a REFERENCE_TYPE.  This type confusion triggers the ICE.
Comment 4 Jason Merrill 2016-03-23 18:23:35 UTC
Author: jason
Date: Wed Mar 23 18:23:04 2016
New Revision: 234434

URL: https://gcc.gnu.org/viewcvs?rev=234434&root=gcc&view=rev
Log:
	PR c++/70344

	* constexpr.c (cxx_eval_call_expression): Catch invalid recursion.

Added:
    trunk/gcc/testsuite/g++.dg/cpp0x/constexpr-recursion2.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/constexpr.c
Comment 5 Jason Merrill 2016-03-23 18:30:41 UTC
Fixed.
Comment 6 Jason Merrill 2016-04-02 01:36:17 UTC
Author: jason
Date: Sat Apr  2 01:35:45 2016
New Revision: 234695

URL: https://gcc.gnu.org/viewcvs?rev=234695&root=gcc&view=rev
Log:
	PR c++/70449

	PR c++/70344
	* pt.c (instantiate_decl): A function isn't fully defined if
	DECL_INITIAL is error_mark_node.
	* constexpr.c (cxx_eval_call_expression): Likewise.

Added:
    trunk/gcc/testsuite/g++.dg/cpp1y/constexpr-recursion1.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/constexpr.c
    trunk/gcc/cp/pt.c
Comment 7 Zhendong Su 2016-04-27 20:43:37 UTC
The same ICE is still triggered with the current GCC trunk: 

$ g++-trunk -v
Using built-in specs.
COLLECT_GCC=g++-trunk
COLLECT_LTO_WRAPPER=/usr/local/gcc-trunk/libexec/gcc/x86_64-pc-linux-gnu/7.0.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: ../gcc-source-trunk/configure --enable-languages=c,c++,lto --prefix=/usr/local/gcc-trunk --disable-bootstrap
Thread model: posix
gcc version 7.0.0 20160426 (experimental) [trunk revision 235433] (GCC) 
$ 
$ g++-trunk -O1 -c pr70344.cpp
pr70344.cpp: In instantiation of ‘constexpr int fn(T) [with T = Z]’:
pr70344.cpp:15:18:   required from here
pr70344.cpp:13:1: internal compiler error: in adjust_temp_type, at cp/constexpr.c:1136
 }
 ^
0x89197a adjust_temp_type
	../../gcc-source-trunk/gcc/cp/constexpr.c:1136
0x898797 cxx_bind_parameters_in_call
	../../gcc-source-trunk/gcc/cp/constexpr.c:1210
0x898797 cxx_eval_call_expression
	../../gcc-source-trunk/gcc/cp/constexpr.c:1397
0x89aa5d cxx_eval_constant_expression
	../../gcc-source-trunk/gcc/cp/constexpr.c:3558
0x8a10e9 cxx_eval_outermost_constant_expr
	../../gcc-source-trunk/gcc/cp/constexpr.c:4136
0x8a3f78 maybe_constant_value_1
	../../gcc-source-trunk/gcc/cp/constexpr.c:4330
0x8a3f78 maybe_constant_value(tree_node*, tree_node*)
	../../gcc-source-trunk/gcc/cp/constexpr.c:4354
0x87fad3 cp_fold
	../../gcc-source-trunk/gcc/cp/cp-gimplify.c:2205
0x87f398 cp_fold_rvalue
	../../gcc-source-trunk/gcc/cp/cp-gimplify.c:1894
0x87f398 cp_fold
	../../gcc-source-trunk/gcc/cp/cp-gimplify.c:2083
0x88037e cp_fold_r
	../../gcc-source-trunk/gcc/cp/cp-gimplify.c:940
0x1059734 walk_tree_1(tree_node**, tree_node* (*)(tree_node**, int*, void*), void*, hash_set<tree_node*, default_hash_traits<tree_node*> >*, tree_node* (*)(tree_node**, int*, tree_node* (*)(tree_node**, int*, void*), void*, hash_set<tree_node*, default_hash_traits<tree_node*> >*))
	../../gcc-source-trunk/gcc/tree.c:11531
0x6a2587 finish_function(int)
	../../gcc-source-trunk/gcc/cp/decl.c:14712
0x70cf2a instantiate_decl(tree_node*, int, bool)
	../../gcc-source-trunk/gcc/cp/pt.c:22035
0x75492b mark_used(tree_node*, int)
	../../gcc-source-trunk/gcc/cp/decl2.c:5273
0x65d521 build_over_call
	../../gcc-source-trunk/gcc/cp/call.c:7724
0x66ccff build_new_function_call(tree_node*, vec<tree_node*, va_gc, vl_embed>**, bool, int)
	../../gcc-source-trunk/gcc/cp/call.c:4169
0x808bf1 finish_call_expr(tree_node*, vec<tree_node*, va_gc, vl_embed>**, bool, bool, int)
	../../gcc-source-trunk/gcc/cp/semantics.c:2461
0x782a99 cp_parser_postfix_expression
	../../gcc-source-trunk/gcc/cp/parser.c:6904
0x78bdec cp_parser_unary_expression
	../../gcc-source-trunk/gcc/cp/parser.c:7988
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See <http://gcc.gnu.org/bugs.html> for instructions.
$
Comment 8 Jakub Jelinek 2016-04-28 11:55:41 UTC
Indeed, r234434 fixed the ICE and r234695 started to ICE again on the #c0 testcase with -O1 -std=c++11.
Comment 9 Jason Merrill 2016-05-24 03:35:30 UTC
Author: jason
Date: Tue May 24 03:34:55 2016
New Revision: 236625

URL: https://gcc.gnu.org/viewcvs?rev=236625&root=gcc&view=rev
Log:
	PR c++/70344 - ICE with recursive constexpr

	* constexpr.c (cxx_eval_call_expression): Check for
	fun == current_function_decl again.

Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/constexpr.c
    trunk/gcc/testsuite/g++.dg/cpp0x/constexpr-recursion2.C
Comment 10 Jason Merrill 2016-05-24 03:37:42 UTC
Author: jason
Date: Tue May 24 03:37:10 2016
New Revision: 236626

URL: https://gcc.gnu.org/viewcvs?rev=236626&root=gcc&view=rev
Log:
	PR c++/70344 - ICE with recursive constexpr

	* constexpr.c (cxx_eval_call_expression): Check for
	fun == current_function_decl again.

Modified:
    branches/gcc-6-branch/gcc/cp/ChangeLog
    branches/gcc-6-branch/gcc/cp/constexpr.c
    branches/gcc-6-branch/gcc/testsuite/g++.dg/cpp0x/constexpr-recursion2.C
Comment 11 Jason Merrill 2016-05-24 04:15:49 UTC
Fixed.