On Tue, Sep 25, 2018 at 8:46 AM H.J. Lu <hjl.to...@gmail.com> wrote:
>
> On Fri, Aug 31, 2018 at 2:04 PM, Jason Merrill <ja...@redhat.com> wrote:
> > On 07/23/2018 05:24 PM, H.J. Lu wrote:
> >>
> >> On Mon, Jun 18, 2018 at 12:26 PM, Joseph Myers <jos...@codesourcery.com>
> >> wrote:
> >>>
> >>> On Mon, 18 Jun 2018, Jason Merrill wrote:
> >>>
> >>>> On Mon, Jun 18, 2018 at 11:59 AM, Joseph Myers <jos...@codesourcery.com>
> >>>> wrote:
> >>>>>
> >>>>> On Mon, 18 Jun 2018, Jason Merrill wrote:
> >>>>>
> >>>>>>> +  if (TREE_CODE (rhs) == COND_EXPR)
> >>>>>>> +    {
> >>>>>>> +      /* Check the THEN path first.  */
> >>>>>>> +      tree op1 = TREE_OPERAND (rhs, 1);
> >>>>>>> +      context = check_address_of_packed_member (type, op1);
> >>>>>>
> >>>>>>
> >>>>>> This should handle the GNU extension of re-using operand 0 if operand
> >>>>>> 1 is omitted.
> >>>>>
> >>>>>
> >>>>> Doesn't that just use a SAVE_EXPR?
> >>>>
> >>>>
> >>>> Hmm, I suppose it does, but many places in the compiler seem to expect
> >>>> that it produces a COND_EXPR with TREE_OPERAND 1 as NULL_TREE.
> >>>
> >>>
> >>> Maybe that's used somewhere inside the C++ front end.  For C a SAVE_EXPR
> >>> is produced directly.
> >>
> >>
> >> Here is the updated patch.  Changes from the last one:
> >>
> >> 1. Handle COMPOUND_EXPR.
> >> 2. Fixed typos in comments.
> >> 3. Combined warn_for_pointer_of_packed_member and
> >> warn_for_address_of_packed_member into
> >> warn_for_address_or_pointer_of_packed_member.
> >
> >
> >> c.i:4:33: warning: converting a packed ‘struct C *’ pointer increases the
> >> alignment of ‘long int *’ pointer from 1 to 8 [-Waddress-of-packed-member]
> >
> >
> > I think this would read better as
> >
> > c.i:4:33: warning: converting a packed ‘struct C *’ pointer (alignment 1) to
> > ‘long int *’ (alignment 8) may result in an unaligned pointer value
> > [-Waddress-of-packed-member]
>
> Fixed.
>
> >> +      while (TREE_CODE (base) == ARRAY_REF)
> >> +       base = TREE_OPERAND (base, 0);
> >> +      if (TREE_CODE (base) != COMPONENT_REF)
> >> +       return NULL_TREE;
> >
> >
> > Are you deliberately not handling the other handled_component_p cases? If
> > so, there should be a comment.
>
> I changed it to
>
>      while (handled_component_p (base))
>         {
>           enum tree_code code = TREE_CODE (base);
>           if (code == COMPONENT_REF)
>             break;
>           switch (code)
>             {
>             case ARRAY_REF:
>               base = TREE_OPERAND (base, 0);
>               break;
>             default:
>               /* FIXME: Can it ever happen?  */
>               gcc_unreachable ();
>               break;
>             }
>         }
>
> Is there a testcase to trigger this ICE? I couldn't find one.
>
> >> +  /* Check alignment of the object.  */
> >> +  if (TREE_CODE (object) == COMPONENT_REF)
> >> +    {
> >> +      field = TREE_OPERAND (object, 1);
> >> +      if (TREE_CODE (field) == FIELD_DECL && DECL_PACKED (field))
> >> +       {
> >> +         type_align = TYPE_ALIGN (type);
> >> +         context = DECL_CONTEXT (field);
> >> +         record_align = TYPE_ALIGN (context);
> >> +         if ((record_align % type_align) != 0)
> >> +           return context;
> >> +       }
> >> +    }
> >
> >
> > Why doesn't this recurse?  What if you have a packed field three
> > COMPONENT_REFs down?
>
> My patch works on
> [hjl@gnu-cfl-1 pr51628-4]$ cat x.i
> struct A { int i; } __attribute__ ((packed));
> struct B { struct A a; };
> struct C { struct B b; };
>
> extern struct C *p;
>
> int* g8 (void) { return &p->b.a.i; }
> [hjl@gnu-cfl-1 pr51628-4]$ make x.s
> /export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/xgcc
> -B/export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/ -O2
> -S x.i
> x.i: In function ‘g8’:
> x.i:7:25: warning: taking address of packed member of ‘struct A’ may
> result in an unaligned pointer value [-Waddress-of-packed-member]
> 7 | int* g8 (void) { return &p->b.a.i; }
>   |                         ^~~~~~~~~
> [hjl@gnu-cfl-1 pr51628-4]$
>
> If it isn't what you had in mind, can you give me a testcase?
>
> >> +  if (TREE_CODE (rhs) == COND_EXPR)
> >> +    {
> >> +      /* Check the THEN path first.  */
> >> +      tree op1 = TREE_OPERAND (rhs, 1);
> >> +      context = check_address_of_packed_member (type, op1);
> >> +      if (context)
> >> +       rhs = op1;
> >> +      else
> >> +       {
> >> +         /* Check the ELSE path.  */
> >> +         rhs = TREE_OPERAND (rhs, 2);
> >> +         context = check_address_of_packed_member (type, rhs);
> >> +       }
> >> +    }
> >
> >
> > Likewise, what if you have more levels of COND_EXPR?  Or COMPOUND_EXPR
> > within COND_EXPR?
>
> Fixed, now I got
>
> [hjl@gnu-cfl-1 pr51628-5]$ cat z.i
> struct A {
>   int i;
> } __attribute__ ((packed));
>
> int*
> foo3 (struct A *p1, int *q1, int *q2, struct A *p2)
> {
>   return (q1
>           ? &p1->i
>           : (q2 ? &p2->i : q2));
> }
> [hjl@gnu-cfl-1 pr51628-5]$ make z.s
> /export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/xgcc
> -B/export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/ -O2
> -S z.i
> z.i: In function ‘foo3’:
> z.i:9:13: warning: taking address of packed member of ‘struct A’ may
> result in an unaligned pointer value [-Waddress-of-packed-member]
> 9 |           ? &p1->i
>   |             ^~~~~~
> z.i:10:19: warning: taking address of packed member of ‘struct A’ may
> result in an unaligned pointer value [-Waddress-of-packed-member]
> 10 |           : (q2 ? &p2->i : q2));
>    |                   ^~~~~~
> [hjl@gnu-cfl-1 pr51628-5]$
>
> >> @@ -7470,6 +7470,9 @@ convert_for_arg_passing (tree type, tree val,
> >> tsubst_flags_t complain)
> >> +  warn_for_address_or_pointer_of_packed_member (true, type, val);
> >
> >
> >> @@ -8914,6 +8914,8 @@ convert_for_assignment (tree type, tree rhs,
> >> +  warn_for_address_or_pointer_of_packed_member (true, type, rhs);
> >
> >
> > Why would address_p be true in these calls?  It seems that you are warning
> > at the point of assignment but looking for the warning about taking the
> > address rather than the one about assignment.
>
> It happens only with C for incompatible pointer conversion:
>
> [hjl@gnu-cfl-1 pr51628-2]$ cat c.i
> struct B { int i; };
> struct C { struct B b; } __attribute__ ((packed));
>
> long* g8 (struct C *p) { return p; }
> [hjl@gnu-cfl-1 pr51628-2]$ make c.s
> /export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/xgcc
> -B/export/build/gnu/tools-build/gcc-debug/build-x86_64-linux/gcc/ -O2
> -S c.i
> c.i: In function ‘g8’:
> c.i:4:33: warning: returning ‘struct C *’ from a function with
> incompatible return type ‘long int *’ [-Wincompatible-pointer-types]
> 4 | long* g8 (struct C *p) { return p; }
>   |                                 ^
> c.i:4:18: warning: converting a packed ‘struct C *’ pointer (alignment
> 1) to ‘long int *’ (alignment 8) may may result in an unaligned
> pointer value [-Waddress-of-packed-member]
> 4 | long* g8 (struct C *p) { return p; }
>   |                  ^
> c.i:2:8: note: defined here
> 2 | struct C { struct B b; } __attribute__ ((packed));
>   |        ^
> [hjl@gnu-cfl-1 pr51628-2]$
>
> address_p is false in this case and rhs is PARM_DECL, VAR_DECL or
> NOP_EXPR.  This comes from convert_for_assignment in c/c-typeck.c.
>
> For other compatible pointer assignment, address_p is true and rhs is
> ADDR_EXPR, PARM_DECL, VAR_DECL or NOP_EXPR.   Check
> for  ADDR_EXPR won't work.
>
> address_p isn't an appropriate parameter name.  I changed it to convert_p
> to indicate that it is an incompatible pointer type conversion.
>
> > If you want to warn about taking the address, shouldn't that happen under
> > cp_build_addr_expr?  Alternately, drop the address_p parameter and choose
> > your path inside warn_for_*_packed_member based on whether rhs is an
> > ADDR_EXPR there rather than in the caller.
> >
>
> Here is the updated patch.  OK for trunk?
>
> Thanks.

PING:

https://gcc.gnu.org/ml/gcc-patches/2018-09/msg01452.html


-- 
H.J.

Reply via email to