https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84526
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |jakub at gcc dot gnu.org, | |law at gcc dot gnu.org --- Comment #5 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Slightly cleaned up testcase: struct S { int a; char b[10]; } d; __SIZE_TYPE__ s; void foo (void) { __builtin_strncpy (d.b, (char *) &d, s); } This code is a ticking bomb. What is the base set builtin_memref::set_base_and_offset ? Seems it is called with expr that is a pointer to something (i.e. arguments of some strncpy-like function), but sometimes it sets base to the passed expr (i.e. pointer to that memory), at other times to what it points to, at other times to the get_inner_reference of what it points to. Without a clear agreement of what it is obviously spots like the new: tree basetype = TREE_TYPE (TREE_TYPE (dstref->base)); are wrong, because it doesn't know if base is the pointer pointing to something (the TREE_TYPE (TREE_TYPE (dstref->base)) assumes that and assumes it is a POINTER_TYPE_P), or not. If you sometimes need the pointer and sometimes what it points to, then either you should have a flag that determines what base is, or better use different members for pointer and base of what it points to. What is the TREE_OPERAND (expr, 0) in: base = get_inner_reference (expr, &bitsize, &bitpos, &var_off, &mode, &sign, &reverse, &vol); poly_int64 bytepos = exact_div (bitpos, BITS_PER_UNIT); HOST_WIDE_INT const_off; if (!base || !bytepos.is_constant (&const_off)) { base = get_base_address (TREE_OPERAND (expr, 0)); return; } doing? It doesn't seem you've checked what expr actually is before using TREE_OPERAND (expr, 0) on it. The cases that fall through into this code are either that expr is an operand of ADDR_EXPR, or SSA_NAME, or in theory some constant. I don't think get_inner_reference ever returns NULL though.