[Bug c++/36566] Cannot bind packed field
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36566 Eric Estievenart changed: What|Removed |Added CC||steve+gcc at tecwec dot eu --- Comment #14 from Eric Estievenart --- What about: struct S { int i; } __attribute__((__packed__)) __attribute((aligned(8))); void f( S* s ) { int& i = s->i; // Error here } S::i is obviously properly aligned, the compiler should know it and accept the referencing. As for the argument 'the field might be unaligned and this would violate... and crash...', I don´t really agree. The compiler knows the arch, the alignment, and it can decide: - to emit an error if unaligned(or unknown) if alignment required by arch - to emit a warning on other arch Note by the way that this seems accepted by clang...
[Bug c++/36566] Cannot bind packed field
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36566 --- Comment #13 from Rene Rahn --- (In reply to Eric Gallager from comment #12) > (In reply to Rene Rahn from comment #10) > > I know this is quite old now. But can someone explain me why using `#pragma > > pack(push, 1)` does work then? I couldn't find enough resources on that. The > > only thing I found is, that it does literally the same. But wouldn't then > > the references/pointers still not be valid? > > > > So if I change the code to: > > > > ``` > > #pragma pack(push, 1) > > struct Squeeze > > { > > short s; > > }; > > #pragma pack(pop) > > ``` > > > > Then it works on godbolt with gcc-trunk. > > There are several bugs open about inconsistencies between > __attribute__((packed)) and #pragma pack; see for example: bug 93910, bug > 92900, bug 68160, and bug 60972 Ah great. Thanks for pointing to this.
[Bug c++/36566] Cannot bind packed field
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36566 Eric Gallager changed: What|Removed |Added CC||egallager at gcc dot gnu.org See Also||https://gcc.gnu.org/bugzill ||a/show_bug.cgi?id=93910, ||https://gcc.gnu.org/bugzill ||a/show_bug.cgi?id=92900, ||https://gcc.gnu.org/bugzill ||a/show_bug.cgi?id=68160, ||https://gcc.gnu.org/bugzill ||a/show_bug.cgi?id=60972 --- Comment #12 from Eric Gallager --- (In reply to Rene Rahn from comment #10) > I know this is quite old now. But can someone explain me why using `#pragma > pack(push, 1)` does work then? I couldn't find enough resources on that. The > only thing I found is, that it does literally the same. But wouldn't then > the references/pointers still not be valid? > > So if I change the code to: > > ``` > #pragma pack(push, 1) > struct Squeeze > { > short s; > }; > #pragma pack(pop) > ``` > > Then it works on godbolt with gcc-trunk. There are several bugs open about inconsistencies between __attribute__((packed)) and #pragma pack; see for example: bug 93910, bug 92900, bug 68160, and bug 60972
[Bug c++/36566] Cannot bind packed field
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36566 --- Comment #11 from Ed Catmur --- (In reply to rene.rahn from comment #10) > I know this is quite old now. But can someone explain me why using `#pragma > pack(push, 1)` does work then? `#pragma pack` has sharper edges. It will let you take unaligned pointers/references, but they will break on architectures that enforce alignment or under ubsan, and the compiler won't try to save you. This is for compatibility with other (older) compilers that behave similarly. nb. Since 4.7 `short& pit(oj.s);` gives error: cannot bind packed field 'oj.Squeeze::s' to 'short int&' (comment #1). Since 9.1 `short* ppit();` and `VerticallyChallenged();` give warning: taking address of packed member of 'Squeeze' may result in an unaligned pointer value [-Waddress-of-packed-member] (comment #3). And the typedef `using un_short = short __attribute__((aligned(1)));` (comment #6) gives a way to form references and pointers to these fields and pass them around. (Note that you have to cast the field access at point of use.) So I think this can be RESOLVED FIXED version 9.1.
[Bug c++/36566] Cannot bind packed field
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36566 rene.r...@fu-berlin.de changed: What|Removed |Added CC||rene.r...@fu-berlin.de --- Comment #10 from rene.r...@fu-berlin.de --- I know this is quite old now. But can someone explain me why using `#pragma pack(push, 1)` does work then? I couldn't find enough resources on that. The only thing I found is, that it does literally the same. But wouldn't then the references/pointers still not be valid? So if I change the code to: ``` #pragma pack(push, 1) struct Squeeze { short s; }; #pragma pack(pop) ``` Then it works on godbolt with gcc-trunk.
[Bug c++/36566] Cannot bind packed field
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36566 --- Comment #9 from Marc Glisse --- I was thinking that struct __attribute__((packed)) A { int i; }; should be handled like typedef int int_unaligned __attribute__((aligned(1))); struct A { int_unaligned i; }; but it appears that for the aligned attribute as well we ignore the attribute when forming pointers or references. Depending on the uses, the compiler can print things like "int_unaligned* {aka int*}" or "ignoring attributes on template argument" etc. It seems to me that we should not drop the alignment-reducing attribute in those cases (it is still fine to remove it when deducing a pass-by-copy type, as in templatevoid f(T);int_unaligned i; f(i); which could safely deduce T=int. Return types may be more tricky when they end up passed as invisible reference). The C/C++ standard only consider _Alignas/alignas to increase alignment, so I don't think changes to the case that decreases alignment would be a conformance issue.
[Bug c++/36566] Cannot bind packed field
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36566 --- Comment #8 from Jonathan Wakely redi at gcc dot gnu.org --- (In reply to Xiao Jia from comment #7) Adding const makes it compile. Is this the intended behavior or not? Yes, of course. A const-reference causes a temporary to be created, you didn't bind to the packed field: Squeeze oj; oj.s = 0; const short pit(oj.s); oj.s = 1; printf(%d %d, oj.s, pit); This shows that oj.s and pit are not the same variable.
[Bug c++/36566] Cannot bind packed field
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36566 Xiao Jia xiaoj at google dot com changed: What|Removed |Added CC||xiaoj at google dot com --- Comment #7 from Xiao Jia xiaoj at google dot com --- What is the status of this? Adding const makes it compile. Is this the intended behavior or not? struct Squeeze { short s; } __attribute__((aligned(1), packed)); void VerticallyChallenged(const short) {} int main() { Squeeze oj; const short pit(oj.s); VerticallyChallenged(pit); VerticallyChallenged(oj.s); }
[Bug c++/36566] Cannot bind packed field
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36566 --- Comment #6 from Gabriel M. Beddingfield gabriel at teuton dot org --- All assignments of obj.s to type short and short* are incorrect, and ideally they would all result in compiler errors. The C++ spec (C++03, Sects. 3.9, 3.9.1, 3.9.2) are very clear that T and pointer to T have implementation-specific alignment requirements. If you have a pointer to T then you may assume that it meets the alignment requirements. I'm sure the C spec has similar language. In the OP's case, the following code could violate the alignment requirements: short pit(obj.s); /* invalid */ For example obj.s could have an address 0x602011 (which has 1-byte alignement). When you assign that pointer to pit... pit is now a reference (i.e. pointer) that violates the alignment requirements of short (which usually requires 2-byte alignment). Why is this a problem? On x86/x86_64 it's *usually* no big deal because the CPU will gracefully handle unaligned memory access (with a performance penalty). On less forgiving hardware platforms, trying to use `pit' will result in illegal instruction exceptions. You can pass the reference if you change the function prototype to something like: typedef short un_short __attribute__((alignment(1))); void VerticallyChallenged(un_short) {} ...and then call it with a cast like this: VerticallyChallenged((un_short)oj.s); [amazing, the kind of stuff you learn over the course of 4 years :-)]
[Bug c++/36566] Cannot bind packed field
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36566 Hei structurechart at yahoo dot com changed: What|Removed |Added CC||structurechart at yahoo dot com --- Comment #5 from Hei structurechart at yahoo dot com --- any update on this? I run into the same issue with gcc 4.6.x
[Bug c++/36566] Cannot bind packed field
--- Comment #4 from gabriel at teuton dot org 2009-10-11 04:38 --- I have the same problem with g++ 4.2.4 and 4.3.2. -- gabriel at teuton dot org changed: What|Removed |Added CC||gabriel at teuton dot org http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36566
[Bug c++/36566] Cannot bind packed field
--- Comment #1 from pinskia at gcc dot gnu dot org 2008-06-18 18:31 --- This is correct you cannot take the address of a field of a packed struct. short pit(oj.s); This should be also an error. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36566
[Bug c++/36566] Cannot bind packed field
--- Comment #2 from nevin at eviloverlord dot com 2008-06-18 18:49 --- Why is this an error (I couldn't find anything in the documentation)? Also, if pointers are used instead of references, should that be an error (currently that compiles just fine)? -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36566
[Bug c++/36566] Cannot bind packed field
--- Comment #3 from nevin at eviloverlord dot com 2008-06-18 19:06 --- Expanding on my last comment: which lines in the following code should fail to compile: struct Squeeze { short s; } __attribute__((aligned(1), packed)); void VerticallyChallenged(short*) {} void VerticallyChallenged(short) {} int main() { Squeeze oj; short pit(oj.s); short* ppit(oj.s); VerticallyChallenged(ppit); // okay VerticallyChallenged(oj.s);// okay VerticallyChallenged(pit); // okay VerticallyChallenged(oj.s); // cannot bind packed field oj.Squeeze::s to short int } -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36566