https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77357
--- Comment #3 from Richard Biener <rguenth at gcc dot gnu.org> --- Ok, I'm less interested in -O0 but even with -O1 we fail for global_struct and local_struct. We can improve things by doing Index: gcc/expr.c =================================================================== --- gcc/expr.c (revision 239778) +++ gcc/expr.c (working copy) @@ -60,6 +60,7 @@ along with GCC; see the file COPYING3. #include "tree-chkp.h" #include "rtl-chkp.h" #include "ccmp.h" +#include "tree-dfa.h" /* If this is nonzero, we do not bother generating VOLATILE @@ -11098,51 +11081,14 @@ string_constant (tree arg, tree *ptr_off if (TREE_CODE (arg) == ADDR_EXPR) { - if (TREE_CODE (TREE_OPERAND (arg, 0)) == STRING_CST) - { - *ptr_offset = size_zero_node; - return TREE_OPERAND (arg, 0); - } - else if (TREE_CODE (TREE_OPERAND (arg, 0)) == VAR_DECL) - { - array = TREE_OPERAND (arg, 0); - offset = size_zero_node; - } - else if (TREE_CODE (TREE_OPERAND (arg, 0)) == ARRAY_REF) - { - array = TREE_OPERAND (TREE_OPERAND (arg, 0), 0); - offset = TREE_OPERAND (TREE_OPERAND (arg, 0), 1); - if (TREE_CODE (array) != STRING_CST - && TREE_CODE (array) != VAR_DECL) - return 0; - - /* Check if the array has a nonzero lower bound. */ - lower_bound = array_ref_low_bound (TREE_OPERAND (arg, 0)); - if (!integer_zerop (lower_bound)) - { - /* If the offset and base aren't both constants, return 0. */ - if (TREE_CODE (lower_bound) != INTEGER_CST) - return 0; - if (TREE_CODE (offset) != INTEGER_CST) - return 0; - /* Adjust offset by the lower bound. */ - offset = size_diffop (fold_convert (sizetype, offset), - fold_convert (sizetype, lower_bound)); - } - } - else if (TREE_CODE (TREE_OPERAND (arg, 0)) == MEM_REF) - { - array = TREE_OPERAND (TREE_OPERAND (arg, 0), 0); - offset = TREE_OPERAND (TREE_OPERAND (arg, 0), 1); - if (TREE_CODE (array) != ADDR_EXPR) - return 0; - array = TREE_OPERAND (array, 0); - if (TREE_CODE (array) != STRING_CST - && TREE_CODE (array) != VAR_DECL) - return 0; - } - else + HOST_WIDE_INT off; + array = get_addr_base_and_unit_offset (TREE_OPERAND (arg, 0), &off); + if (! array + || (TREE_CODE (array) != VAR_DECL + && TREE_CODE (array) != CONST_DECL + && TREE_CODE (array) != STRING_CST)) return 0; + *ptr_offset = size_int (off); } else if (TREE_CODE (arg) == PLUS_EXPR || TREE_CODE (arg) == POINTER_PLUS_EXPR) { but then we only handle STRING_CST ctors and not {.a="abc"} we do have some generic fold-a-ctor-reference-at-offset thing (gimple-fold.c:fold_*ctor_reference) but that hasn't the get-me-the-ctor-element-at-offset part factored out. Or finding the ctor element that the offset is within (we can then adjust offset). So a bit of refactoring is missing here.