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

Martin Sebor <msebor at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|ASSIGNED                    |RESOLVED
            Summary|[12 Regression] Bootstrap   |[12 Regression]
                   |failure compiling           |-Warray-bounds in
                   |gcc/cp/module.cc            |gcc/cp/module.cc causing
                   |                            |bootstrap failure
             Blocks|                            |56456
         Resolution|---                         |FIXED

--- Comment #7 from Martin Sebor <msebor at gcc dot gnu.org> ---
The warning triggers here because the code accesses an object using an address
computed by adding a negative constant to the address of a member subobject. 
The arithmetic result is a pointer to another object but logically (in C) the
computation is invalid.

The preprocessed code for the identifier() function does this:

static inline tree identifier (const cpp_hashnode *node)
{
  return ((tree) ((char *) ((&(const_cast<cpp_hashnode *> (node))->ident)) -
sizeof (struct tree_common)));
}

That's strictly incorrect (undefined) and the warning points it out.  The IL
below shows where the problem is detected:

void module_state::install_macros (struct module_state * const this)
{
  ...
  union tree_node * _95;
  ...
  <bb 11> [local count: 710990510]:
  _95 = get_identifier_with_length (_93, len.30_94);
  _96 = &MEM[(struct tree_identifier *)_95].id;             <<< subobject

  <bb 12> [local count: 1014686043]:
  # _97 = PHI <0B(10), _96(11)>
  len ={v} {CLOBBER};
  _43 = get_macro_imports (_97);
  _45 = bytes_in::u (sec_32);
  flags_46 = _45 & 3;
  if (flags_46 == 0)
    goto <bb 13>; [50.00%]
  else
    goto <bb 14>; [50.00%]

  <bb 18> [local count: 479439156]:
  _47 = &MEM <struct ht_identifier> [(void *)_97 + -24B];   <<< -Warray-bounds

Pointer arithmetic needs to be bounded to the innermost object (or subobject)
the pointer was derived from.  The warning enforces it to prevent accessing the
wrong member by accident.  The following alternate way code the same function
avoids the warning:

static inline tree identifier (const cpp_hashnode *node)
{
  char *p = (char *)const_cast<cpp_hashnode *> (node);
  p += __builtin_offsetof (cpp_hashnode, ident);
  p -= sizeof (struct tree_common);
  return (tree)p;
}

But rewriting it this way using the HT_XXX macros would be cumbersome so it
might be better to suppress the warning.  I have committed r12-2178 moving the
suppression from the callers to the identifier() function.


Referenced Bugs:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56456
[Bug 56456] [meta-bug] bogus/missing -Warray-bounds

Reply via email to