https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83993

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Priority|P1                          |P2
                 CC|                            |jason at gcc dot gnu.org
   Target Milestone|---                         |8.0
            Summary|[8 Regression] ICE:         |[7/8 Regression] ICE:
                   |constant not recomputed     |constant not recomputed
                   |when ADDR_EXPR changed      |when ADDR_EXPR changed

--- Comment #3 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Because the array has no TYPE_DOMAIN, in cxx_eval_array_reference
  if (TREE_CODE (TREE_TYPE (ary)) == ARRAY_TYPE)
    nelts = array_type_nelts_top (TREE_TYPE (ary));
sets nelts to error_mark_node + 1, and so the cxx_eval_constant_expression
calls sets *non_constant_p.  Then later on the caller of this,
cxx_eval_outermost_constant_expr, does:
4818      else if (non_constant_p && TREE_CONSTANT (r))
4819        {
4820          /* This isn't actually constant, so unset TREE_CONSTANT.  */
4821          if (EXPR_P (r))
4822            r = copy_node (r);
4823          else if (TREE_CODE (r) == CONSTRUCTOR)
4824            r = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (r), r);
4825          else
4826            r = build_nop (TREE_TYPE (r), r);
4827          TREE_CONSTANT (r) = false;
4828        }
on the ADDR_EXPR surrounding the ARRAY_REF.

So, the questions are:
1) if we have such [] arrays, does any access to any element in the array imply
a non-constant expression, or should we ignore the in-bounds check?
E.g. on
extern const int a[];
const int b[5] = { 1, 2, 3, 4, 5 };
extern const int c[5];
constexpr const int *d = &a[0];
constexpr const int *e = &a[10];
constexpr const int *f = &b[0];
constexpr const int *g = &b[5];
constexpr const int *h = &b[6];
constexpr const int *i = &b[0];
constexpr const int *j = &b[5];
constexpr const int *k = &b[6];
g++ errors on h and k definitions, while clang++ errors on e, h, k, somehow it
considers &a[0] to be always ok no matter how large the array is (that is
actually a reasonable assumption for lval case, even if the array has zero
size, it is still valid to form a pointer past it), but considers &a[10]
invalid, even when the other TU could have const int a[100].

2) does cxx_eval_outermost_constant_expr really need to clear TREE_CONSTANT
even on ADDR_EXPRs, or could we special case those?  If we need to clear those,
supposedly during genericization we should try to recompute the ADDR_EXPR flags
and if that would change them, copy node and restore there what the middle-end
expects.

Jason, do you have answers to these questions, please?

Reply via email to