Re: [PATCH v2] C/C++: Add -Waddress-of-packed-member
On Mon, 18 Jun 2018, Jason Merrill wrote: > On Mon, Jun 18, 2018 at 11:59 AM, Joseph Myers > 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. -- Joseph S. Myers jos...@codesourcery.com
Re: [PATCH v2] C/C++: Add -Waddress-of-packed-member
On Mon, Jun 18, 2018 at 11:59 AM, Joseph Myers 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. Perhaps that code is obsolete. Never mind it here, then. Jason
Re: [PATCH v2] C/C++: Add -Waddress-of-packed-member
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? -- Joseph S. Myers jos...@codesourcery.com
Re: [PATCH v2] C/C++: Add -Waddress-of-packed-member
On Fri, May 18, 2018 at 7:36 AM, H.J. Lu wrote: > On Thu, May 17, 2018 at 10:32:56AM -0700, H.J. Lu wrote: >> On Mon, May 14, 2018 at 8:00 PM, Martin Sebor wrote: >> > On 05/14/2018 01:10 PM, H.J. Lu wrote: >> >> >> >> On Mon, May 14, 2018 at 10:40 AM, H.J. Lu 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*) // -Waddress-of-packed-member >> > int *q = (int*) // 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*) >> int *q = (int*) >> [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*) >> ^~ >>
PING^2: [PATCH v2] C/C++: Add -Waddress-of-packed-member
On Tue, May 29, 2018 at 5:15 AM, H.J. Lu wrote: > On Fri, May 18, 2018 at 4:36 AM, H.J. Lu wrote: >> On Thu, May 17, 2018 at 10:32:56AM -0700, H.J. Lu wrote: >>> On Mon, May 14, 2018 at 8:00 PM, Martin Sebor wrote: >>> > On 05/14/2018 01:10 PM, H.J. Lu wrote: >>> >> >>> >> On Mon, May 14, 2018 at 10:40 AM, H.J. Lu 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*) // -Waddress-of-packed-member >>> > int *q = (int*) // 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*) >>> int *q = (int*) >>> [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:
PING^1: [PATCH v2] C/C++: Add -Waddress-of-packed-member
On Fri, May 18, 2018 at 4:36 AM, H.J. Lu wrote: > On Thu, May 17, 2018 at 10:32:56AM -0700, H.J. Lu wrote: >> On Mon, May 14, 2018 at 8:00 PM, Martin Sebor wrote: >> > On 05/14/2018 01:10 PM, H.J. Lu wrote: >> >> >> >> On Mon, May 14, 2018 at 10:40 AM, H.J. Lu 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*) // -Waddress-of-packed-member >> > int *q = (int*) // 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*) >> int *q = (int*) >> [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*) >> ^~ >>
[PATCH v2] C/C++: Add -Waddress-of-packed-member
On Thu, May 17, 2018 at 10:32:56AM -0700, H.J. Lu wrote: > On Mon, May 14, 2018 at 8:00 PM, Martin Seborwrote: > > On 05/14/2018 01:10 PM, H.J. Lu wrote: > >> > >> On Mon, May 14, 2018 at 10:40 AM, H.J. Lu 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*) // -Waddress-of-packed-member > > int *q = (int*) // 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*) > int *q = (int*) > [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*) > ^~ > 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