[Bug c++/80075] New: [7 regression] ICE: "statement marked for throw, but doesn’t" with -fnon-call-exceptions
ian at airs dot com
gcc-bugzilla@gcc.gnu.org
Thu Mar 16 22:46:00 GMT 2017
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80075
Bug ID: 80075
Summary: [7 regression] ICE: "statement marked for throw, but
doesn’t" with -fnon-call-exceptions
Product: gcc
Version: 7.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: ian at airs dot com
Target Milestone: ---
Compiling this C++ code with -O2 -fnon-call-exceptions crashes trunk:
struct s {
int i;
};
extern int use_memcpy;
extern void my_memcpy(void*, void*, int);
int
f (struct s* p)
{
struct s a;
try
{
a = (struct s){};
if (!use_memcpy)
*p = a;
else
my_memcpy (p, &a, sizeof (struct s));
} catch (...)
{
return 0;
}
return 1;
}
I get
foo.cc: In function ‘int f(s*)’:
foo.cc:9:1: error: statement marked for throw, but doesn’t
f (struct s* p)
^
# .MEM_10 = VDEF <.MEM_7>
*p_8(D) = {};
foo.cc:9:1: internal compiler error: verify_gimple failed
0xe040ee verify_gimple_in_cfg(function*, bool)
../../gccgo3/gcc/tree-cfg.c:5266
0xce04ba execute_function_todo
../../gccgo3/gcc/passes.c:1966
0xce0ef5 execute_todo
../../gccgo3/gcc/passes.c:2016
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.
The problem arises when optimize_memcpy in tree-ssa-ccp changes
struct s a;
int use_memcpy.0_1;
<bb 2> [100.00%]:
a = {};
use_memcpy.0_1 = use_memcpy;
if (use_memcpy.0_1 == 0)
goto <bb 3>; [63.36%]
else
goto <bb 4>; [36.64%]
<bb 3> [63.36%]:
*p_5(D) = a;
goto <bb 5>; [100.00%]
<bb 4> [36.64%]:
my_memcpy (p_5(D), &a, 4);
<bb 5> [100.00%]:
a ={v} {CLOBBER};
return;
into
struct s a;
int use_memcpy.0_1;
<bb 2> [100.00%]:
a = {};
use_memcpy.0_1 = use_memcpy;
if (use_memcpy.0_1 == 0)
goto <bb 3>; [63.36%]
else
goto <bb 4>; [36.64%]
<bb 3> [63.36%]:
*p_5(D) = {};
goto <bb 5>; [100.00%]
<bb 4> [36.64%]:
my_memcpy (p_5(D), &a, 4);
<bb 5> [100.00%]:
a ={v} {CLOBBER};
return;
The RHS of the assignment in bb 3 changed from "a" to "{}". That
transformation seems OK. However, the verification pass believes that the new
statement, "*p_5(D) = {};", does not throw. That is of course incorrect.
Because I am using -fnon-call-exceptions, the statement will throw if p is
NULL.
In looking at this, I see stmt_could_throw_1_p in tree-eh.c calls
operation_could_trap_helper_p passing the assignment code, which is now
CONSTRUCTOR. The latter function always returns false for CONSTRUCTOR with
*handled = true. It's correct that CONSTRUCTOR can not trap, but it doesn't
follow that the statement as a whole can not trap. But I don't really
understand why stmt_could_throw_1_p doesn't always check the LHS of the
assignment statement, so basically I'm not sure why this works in general.
I actually ran into this with some Go code, and reverse engineered a C++
example.
This C++ example compiles with GCC 6, so this appears to be a regression.
More information about the Gcc-bugs
mailing list