On Mon, May 14, 2018 at 8:00 PM, Martin Sebor <mse...@gmail.com> wrote:
> On 05/14/2018 01:10 PM, H.J. Lu wrote:
>>
>> On Mon, May 14, 2018 at 10:40 AM, H.J. Lu <hjl.to...@gmail.com> wrote:
>>
>>>>>> $ cat c.i
>>>>>> struct B { int i; };
>>>>>> struct C { struct B b; } __attribute__ ((packed));
>>>>>>
>>>>>> long* g8 (struct C *p) { return p; }
>>>>>> $ gcc -O2 -S c.i -Wno-incompatible-pointer-types
>>>>>> c.i: In function ‘g8’:
>>>>>> c.i:4:33: warning: taking value of packed 'struct C *' may result in
>>>>>> an
>>>>>> unaligned pointer value [-Waddress-of-packed-member]
>>>>
>>>>
>>>>                              ^^^^^
>>>> That should read "taking address" (not value) but...
>>>
>>>
>>> The value of 'struct C *' is an address. There is no address taken here.
>>>
>>>> ...to help explain the problem I would suggest to mention the expected
>>>> and actual alignment in the warning message.  E.g.,
>>>>
>>>>   storing the address of a packed 'struct C' in 'struct C *' increases
>>>> the
>>>> alignment of the pointer from 1 to 4.
>>>
>>>
>>> I will take a look.
>>>
>>>> (IIUC, the source type and destination type need not be the same so
>>>> including both should be helpful in those cases.)
>>>>
>>>> Adding a note pointing to the declaration of either the struct or
>>>> the member would help users find it if it's a header far removed
>>>> from the point of use.
>>>
>>>
>>> I will see what I can do.
>>
>>
>> How about this
>>
>> [hjl@gnu-skx-1 pr51628]$ cat n9.i
>> struct B { int i; };
>> struct C { struct B b; } __attribute__ ((packed));
>>
>> long* g8 (struct C *p) { return p; }
>> [hjl@gnu-skx-1 pr51628]$
>> /export/build/gnu/gcc-test/build-x86_64-linux/gcc/xgcc
>> -B/export/build/gnu/gcc-test/build-x86_64-linux/gcc/ -O2 -S n9.i
>> n9.i: In function ‘g8’:
>> n9.i:4:33: warning: returning ‘struct C *’ from a function with
>> incompatible return type ‘long int *’ [-Wincompatible-pointer-types]
>>  long* g8 (struct C *p) { return p; }
>>                                  ^
>> n9.i:4:33: warning: taking value of packed ‘struct C *’ increases the
>> alignment of the pointer from 1 to 8 [-Waddress-of-packed-member]
>> n9.i:2:8: note: defined here
>>  struct C { struct B b; } __attribute__ ((packed));
>
>
> Mentioning the alignments looks good.
>
> I still find the "taking value" phrasing odd.  I think we would
> describe what's going on as "converting a pointer to a packed C
> to a pointer to C (with an alignment of 8)" so I'd suggest to
> use the term converting instead.

How about this?

[hjl@gnu-skx-1 pr51628]$ cat n12.i
struct B { int i; };
struct C { struct B b; } __attribute__ ((packed));

struct B* g8 (struct C *p) { return p; }
[hjl@gnu-skx-1 pr51628]$ make n12.s
/export/build/gnu/gcc-test/build-x86_64-linux/gcc/xgcc
-B/export/build/gnu/gcc-test/build-x86_64-linux/gcc/ -O2 -S n12.i
n12.i: In function ‘g8’:
n12.i:4:37: warning: returning ‘struct C *’ from a function with
incompatible return type ‘struct B *’ [-Wincompatible-pointer-types]
 struct B* g8 (struct C *p) { return p; }
                                     ^
n12.i:4:37: warning: converting a pointer to packed ‘struct C *’
increases the alignment of the pointer to ‘struct B *’ from 1 to 4
[-Waddress-of-packed-member]
n12.i:2:8: note: defined here
 struct C { struct B b; } __attribute__ ((packed));
        ^
n12.i:1:8: note: defined here
 struct B { int i; };
        ^
[hjl@gnu-skx-1 pr51628]$

> I also think mentioning both the source and the destination types
> is useful irrespective of -Wincompatible-pointer-types because
> the latter is often suppressed using a cast, as in:
>
>   struct __attribute__ ((packed)) A { int i; };
>   struct B {
>     struct A a;
>   } b;
>
>   long *p = (long*)&b.a.i;   // -Waddress-of-packed-member
>   int *q = (int*)&b.a;       // missing warning
>
> If the types above were obfuscated by macros, typedefs, or in
> C++ template parameters, it could be difficult to figure out
> what the type of the member is because neither it nor the name
> of the member appears in the message.

How about this

[hjl@gnu-skx-1 pr51628]$ cat n13.i
struct __attribute__ ((packed)) A { int i; };
struct B {
  struct A a;
} b;

long *p = (long*)&b.a.i;
int *q = (int*)&b.a;
[hjl@gnu-skx-1 pr51628]$ make n13.s
/export/build/gnu/gcc-test/build-x86_64-linux/gcc/xgcc
-B/export/build/gnu/gcc-test/build-x86_64-linux/gcc/ -O2 -S n13.i
n13.i:6:18: warning: taking address of packed member of ‘struct A’ may
result in an unaligned pointer value [-Waddress-of-packed-member]
 long *p = (long*)&b.a.i;
                  ^~~~~~
n13.i:7:16: warning: taking address of packed member of ‘struct B’ may
result in an unaligned pointer value [-Waddress-of-packed-member]
 int *q = (int*)&b.a;
                ^~~~
[hjl@gnu-skx-1 pr51628]$


-- 
H.J.

Reply via email to