I use out-of-the-box GCC 5.2.1 in Ubuntu 15.10: gcc version 5.2.1 20151010 (Ubuntu 5.2.1-22ubuntu2) This code makes GCC crash when I define standard --std=c++14 or --std=c++17: #include <cassert> constexpr int ce(int r) { assert(r == 3); return r; } static_assert(ce(3) == 3, "static asser error"); Command to reproduce: $ gcc --std=c++14 bug.cpp bug.cpp:8:17: in constexpr expansion of ‘ce(3)’ bug.cpp:8:48: internal compiler error: Segmentation fault static_assert(ce(3) == 3, "static asser error"); ^ Please submit a full bug report, with preprocessed source if appropriate. See <file:///usr/share/doc/gcc-5/README.Bugs> for instructions.
Confirmed. void foo (const char *); constexpr int ce (int r) { r == 3 ? static_cast<void> (0) : foo (__PRETTY_FUNCTION__); return r; } static_assert (ce (3) == 3, "");
Started with r217663: commit 9c96033c877975303250d6f6156eacba52fc8b44 Author: jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4> Date: Mon Nov 17 18:16:14 2014 +0000 C++14 constexpr support (minus loops and multiple returns)
static_assert is not required. This code also crashes: #include <cassert> constexpr int ce(int r) { assert(r == 3); return r; } const auto c = ce(3); Problem is in assert called from constexpr function.
But we want to avoid the #include <cassert>.
The trigger seems to be __PRETTY_FUNCTION__. Below is a smaller test case: constexpr int ce (int r) { const char *s = __PRETTY_FUNCTION__; return r; } constexpr int i = ce (3); v.c: In function ‘constexpr int ce(int)’: v.c:3:16: warning: unused variable ‘s’ [-Wunused-variable] const char *s = __PRETTY_FUNCTION__; ^ v.c: At global scope: v.c:7:22: in constexpr expansion of ‘ce(3)’ v.c:7:24: internal compiler error: Segmentation fault constexpr int i = ce (3); ^ 0x10d5326 crash_signal /src/gcc/trunk/gcc/toplev.c:335 0x7ce697 bool vec_safe_reserve<tree_node*, va_gc>(vec<tree_node*, va_gc, vl_embed>*&, unsigned int, bool) /src/gcc/trunk/gcc/vec.h:553 0x7ce1aa tree_node** vec_safe_push<tree_node*, va_gc>(vec<tree_node*, va_gc, vl_embed>*&, tree_node* const&) /src/gcc/trunk/gcc/vec.h:647 0xd48a73 add_local_decl(function*, tree_node*) /src/gcc/trunk/gcc/function.c:6795 0x1169cf1 remap_decls /src/gcc/trunk/gcc/tree-inline.c:620 0x116a19a remap_block /src/gcc/trunk/gcc/tree-inline.c:688 0x116a55d copy_bind_expr /src/gcc/trunk/gcc/tree-inline.c:761 0x116ba51 copy_tree_body_r(tree_node**, int*, void*) /src/gcc/trunk/gcc/tree-inline.c:1095 0x140ec4b 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*> >*)) /src/gcc/trunk/gcc/tree.c:11531 0x11720b8 copy_tree_body /src/gcc/trunk/gcc/tree-inline.c:2946 0x117b678 copy_fn(tree_node*, tree_node*&, tree_node*&) /src/gcc/trunk/gcc/tree-inline.c:6151 0xa7a19d cxx_eval_call_expression /src/gcc/trunk/gcc/cp/constexpr.c:1368 0xa81d72 cxx_eval_constant_expression /src/gcc/trunk/gcc/cp/constexpr.c:3407 0xa83fb3 cxx_eval_outermost_constant_expr /src/gcc/trunk/gcc/cp/constexpr.c:3973 0xa84611 cxx_constant_value(tree_node*, tree_node*) /src/gcc/trunk/gcc/cp/constexpr.c:4062 0x89f86c store_init_value(tree_node*, tree_node*, vec<tree_node*, va_gc, vl_embed>**, int) /src/gcc/trunk/gcc/cp/typeck2.c:822 0x7ec411 check_initializer /src/gcc/trunk/gcc/cp/decl.c:6155 0x7ef3db cp_finish_decl(tree_node*, tree_node*, bool, tree_node*, int) /src/gcc/trunk/gcc/cp/decl.c:6800 0x9282b6 cp_parser_init_declarator /src/gcc/trunk/gcc/cp/parser.c:18658 0x91d806 cp_parser_simple_declaration /src/gcc/trunk/gcc/cp/parser.c:12379 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.
GCC 4.9 doesn't crash on the code so technically this could be considered a regression. Although 4.9 doesn't support C++ 14 constexpr functions consisting of more than just a return statement, one might say it's not regression. But the 5.x and 5.0 both ICE even on the test C++ 11 case below, so I think considering this a regression would be appropriate. I've taken the liberty to do that and also to adjust the Summary to better reflect the root cause of the ICE. $ cat v.c && /home/msebor/build/gcc-4.9.3/gcc/xgcc -B/home/msebor/build/gcc-4.9.3/gcc -S -Wall -Wextra -Wpedantic -std=c++14 -xc++ v.c constexpr int f () { return __PRETTY_FUNCTION__ [0]; } constexpr int i = f (); v.c: In function ‘constexpr int f()’: v.c:3:1: error: body of constexpr function ‘constexpr int f()’ not a return-statement } ^ v.c: At global scope: v.c:5:22: error: ‘constexpr int f()’ called in a constant expression constexpr int i = f (); ^
I haven't had time to debug it beyond observing in the debugger that remap_decls() defined in tree-inline.c calls add_local_decl() with the first argument of null. The argument is cfun (function*). Both __func__ and __FUNCTION__ also trigger the same ICE.
Smaller test case: constexpr const char* ce () { return __func__; } const char* c = ce ();
The reason for the ICE is that __PRETTY_FUNCTION__/__FUNCTION__/__func__ are TREE_STATIC (artificial) VAR_DECLs in the context of the corresponding constexpr function, because of the TREE_STATIC we don't want to remap it, and constexpr.c calls copy_fn with NULL cfun (most other callers of inlining APIs have cfun non-NULL and usually cfun->decl matching id->dst_fn). For the ICE, I guess we can do something like: --- gcc/tree-inline.c.jj 2016-03-16 18:50:47.000000000 +0100 +++ gcc/tree-inline.c 2016-03-23 16:27:08.723926525 +0100 @@ -614,9 +614,11 @@ remap_decls (tree decls, vec<tree, va_gc if (can_be_nonlocal (old_var, id)) { /* We need to add this variable to the local decls as otherwise - nothing else will do so. */ + nothing else will do so. Don't do this if there is no current + function, e.g. during constexpr handling calling copy_fn. */ if (TREE_CODE (old_var) == VAR_DECL - && ! DECL_EXTERNAL (old_var)) + && ! DECL_EXTERNAL (old_var) + && cfun) add_local_decl (cfun, old_var); if ((!optimize || debug_info_level > DINFO_LEVEL_TERSE) && !DECL_IGNORED_P (old_var) But, that is insufficient, as e.g. for the #c8 testcase we then get unresolved external symbol, because the definition of the static var is never emitted.
It's a hack, but we could pull the STRING_CST out from the artificial VAR_DECL during constexpr evaluation to avoid referring to __func__'s symbol. --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -3354,6 +3354,11 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, case VAR_DECL: case CONST_DECL: + if (VAR_P (t) + && DECL_ARTIFICIAL (t) + && TREE_STATIC (t) + && TREE_CODE (DECL_INITIAL (t)) == STRING_CST) + return DECL_INITIAL (t); /* We used to not check lval for CONST_DECL, but darwin.c uses CONST_DECL for aggregate constants. */ if (lval)
Core issue 1962 talks about changing __func__ et al to be const char * rather than array; Martin was investigating that change but it fell off my radar. I'll look at finishing up his patch.
Author: jason Date: Fri Mar 25 21:29:26 2016 New Revision: 234484 URL: https://gcc.gnu.org/viewcvs?rev=234484&root=gcc&view=rev Log: PR c++/64266 PR c++/70353 Core issue 1962 * decl.c (cp_fname_init): Decay the initializer to pointer. (cp_make_fname_decl): Set DECL_DECLARED_CONSTEXPR_P, DECL_VALUE_EXPR, DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P. Don't call cp_finish_decl. * pt.c (tsubst_expr) [DECL_EXPR]: Set DECL_VALUE_EXPR, DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P. Don't call cp_finish_decl. * constexpr.c (cxx_eval_constant_expression) [VAR_DECL]: Handle DECL_VALUE_EXPR. Added: trunk/gcc/testsuite/g++.dg/cpp0x/constexpr-__func__2.C trunk/gcc/testsuite/g++.dg/ext/fnname5.C Removed: trunk/gcc/testsuite/g++.old-deja/g++.ext/pretty4.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/constexpr.c trunk/gcc/cp/decl.c trunk/gcc/cp/pt.c
Fixed for 6, but the patch isn't really suitable for backporting since it's a change in behavior. Since 4.9 didn't accept the code, I'm going to close this.
Author: jason Date: Mon Mar 28 20:16:21 2016 New Revision: 234511 URL: https://gcc.gnu.org/viewcvs?rev=234511&root=gcc&view=rev Log: PR c++/70422 PR c++/64266 PR c++/70353 * decl.c, pt.c, constexpr.c: Revert last patch. Added: trunk/gcc/testsuite/g++.old-deja/g++.ext/pretty4.C Removed: trunk/gcc/testsuite/g++.dg/cpp0x/constexpr-__func__2.C trunk/gcc/testsuite/g++.dg/ext/fnname5.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/constexpr.c trunk/gcc/cp/decl.c trunk/gcc/cp/pt.c
Reverted the fix because it broke bootstrap on some targets.
I was just about commit the following patch for the failure (false positive) in the test. Index: gcc/testsuite/ChangeLog =================================================================== --- gcc/testsuite/ChangeLog (revision 234510) +++ gcc/testsuite/ChangeLog (working copy) @@ -1,3 +1,8 @@ +2016-03-28 Martin Sebor <msebor@redhat.com> + + * g++.dg/ext/fnname5.C: Adjust ERE pattern to anticipate any + whitespace character after the .string assembler directive. + 2016-03-28 Dominique d'Humieres <dominiq@lps.ens.fr> g++.dg/ext/fnname5.C: Update the test for Darwin. Index: gcc/testsuite/g++.dg/ext/fnname5.C =================================================================== --- gcc/testsuite/g++.dg/ext/fnname5.C (revision 234510) +++ gcc/testsuite/g++.dg/ext/fnname5.C (working copy) @@ -29,5 +29,5 @@ main () /* { dg-final { scan-assembler-not "_ZZN1A3fooEvE12__FUNCTION__" } } */ /* { dg-final { scan-assembler-not "_ZZN1A3fooEiE12__FUNCTION__" } } */ /* { dg-final { scan-assembler-not "_ZZN1A3fooEiE19__PRETTY_FUNCTION__" } } */ -/* { dg-final { scan-assembler ".(string|ascii) \"void A::foo\\(int\\)(.0)?\"" } } */ -/* { dg-final { scan-assembler ".(string|ascii) \"foo(.0)?\"" } } */ +/* { dg-final { scan-assembler ".(string|ascii)\[\[:space:\]\]*\"void A::foo\\(int\\)(.0)?\"" } } */ +/* { dg-final { scan-assembler ".(string|ascii)\[\[:space:\]\]*\"foo(.0)?\"" } } */
Author: jason Date: Tue Mar 29 18:40:02 2016 New Revision: 234530 URL: https://gcc.gnu.org/viewcvs?rev=234530&root=gcc&view=rev Log: PR c++/70353 gcc/ * tree-inline.c (remap_decls): Don't add_local_decl if cfun is null. gcc/cp/ * decl.c (make_rtl_for_nonlocal_decl): Don't defer local statics in constexpr functions. Added: trunk/gcc/testsuite/g++.dg/cpp0x/constexpr-__func__2.C Modified: trunk/gcc/ChangeLog trunk/gcc/cp/ChangeLog trunk/gcc/cp/decl.c trunk/gcc/tree-inline.c
Fixed again for 6.
*** Bug 70532 has been marked as a duplicate of this bug. ***
*** Bug 66460 has been marked as a duplicate of this bug. ***
*** Bug 70770 has been marked as a duplicate of this bug. ***
Author: jason Date: Wed May 18 15:59:00 2016 New Revision: 236408 URL: https://gcc.gnu.org/viewcvs?rev=236408&root=gcc&view=rev Log: PR c++/70353 - __func__ and constexpr gcc/ * tree-inline.c (remap_decls): Don't add_local_decl if cfun is null. gcc/cp/ * decl.c (make_rtl_for_nonlocal_decl): Don't defer local statics in constexpr functions. Added: branches/gcc-5-branch/gcc/testsuite/g++.dg/cpp0x/constexpr-__func__2.C Modified: branches/gcc-5-branch/gcc/ChangeLog branches/gcc-5-branch/gcc/cp/ChangeLog branches/gcc-5-branch/gcc/cp/decl.c branches/gcc-5-branch/gcc/tree-inline.c
GCC 5.4 is being released, adjusting target milestone.
Should be fixed in 5.4.