mirror of
https://github.com/dlang/dmd.git
synced 2025-04-26 05:00:16 +03:00
Fix bugzilla 24594 - ImportC: Packed struct has wrong layout (#16611)
Packed structs were already implemented with the Microsoft syntax (e.g. `#pragma pack(push, 1)`), but the GCC syntax was ignored.
This commit is contained in:
parent
1917164050
commit
557e1d5eea
4 changed files with 58 additions and 3 deletions
|
@ -3634,6 +3634,12 @@ final class CParser(AST) : Parser!AST
|
||||||
* type on the target machine. It's the opposite of __attribute__((packed))
|
* type on the target machine. It's the opposite of __attribute__((packed))
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
else if (token.ident == Id.packed)
|
||||||
|
{
|
||||||
|
specifier.packalign.set(1);
|
||||||
|
specifier.packalign.setPack(true);
|
||||||
|
nextToken();
|
||||||
|
}
|
||||||
else if (token.ident == Id.always_inline) // https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html
|
else if (token.ident == Id.always_inline) // https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html
|
||||||
{
|
{
|
||||||
specifier.scw |= SCW.xinline;
|
specifier.scw |= SCW.xinline;
|
||||||
|
@ -3982,7 +3988,7 @@ final class CParser(AST) : Parser!AST
|
||||||
members = new AST.Dsymbols(); // so `members` will be non-null even with 0 members
|
members = new AST.Dsymbols(); // so `members` will be non-null even with 0 members
|
||||||
while (token.value != TOK.rightCurly)
|
while (token.value != TOK.rightCurly)
|
||||||
{
|
{
|
||||||
cparseStructDeclaration(members);
|
cparseStructDeclaration(members, packalign);
|
||||||
|
|
||||||
if (token.value == TOK.endOfFile)
|
if (token.value == TOK.endOfFile)
|
||||||
break;
|
break;
|
||||||
|
@ -3996,6 +4002,24 @@ final class CParser(AST) : Parser!AST
|
||||||
* struct-declarator (opt)
|
* struct-declarator (opt)
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* GNU Extensions
|
||||||
|
* Parse the postfix gnu-attributes (opt)
|
||||||
|
*/
|
||||||
|
Specifier specifier;
|
||||||
|
if (token.value == TOK.__attribute__)
|
||||||
|
cparseGnuAttributes(specifier);
|
||||||
|
if (!specifier.packalign.isUnknown)
|
||||||
|
{
|
||||||
|
packalign.set(specifier.packalign.get());
|
||||||
|
packalign.setPack(specifier.packalign.isPack());
|
||||||
|
foreach (ref d; (*members)[])
|
||||||
|
{
|
||||||
|
auto decls = new AST.Dsymbols(1);
|
||||||
|
(*decls)[0] = d;
|
||||||
|
d = new AST.AlignDeclaration(d.loc, specifier.packalign, decls);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (!tag)
|
else if (!tag)
|
||||||
error("missing tag `identifier` after `%s`", Token.toChars(structOrUnion));
|
error("missing tag `identifier` after `%s`", Token.toChars(structOrUnion));
|
||||||
|
@ -4027,8 +4051,9 @@ final class CParser(AST) : Parser!AST
|
||||||
* declarator (opt) : constant-expression
|
* declarator (opt) : constant-expression
|
||||||
* Params:
|
* Params:
|
||||||
* members = where to put the fields (members)
|
* members = where to put the fields (members)
|
||||||
|
* packalign = alignment to use for struct members
|
||||||
*/
|
*/
|
||||||
void cparseStructDeclaration(AST.Dsymbols* members)
|
void cparseStructDeclaration(AST.Dsymbols* members, structalign_t packalign)
|
||||||
{
|
{
|
||||||
//printf("cparseStructDeclaration()\n");
|
//printf("cparseStructDeclaration()\n");
|
||||||
if (token.value == TOK._Static_assert)
|
if (token.value == TOK._Static_assert)
|
||||||
|
@ -4039,7 +4064,7 @@ final class CParser(AST) : Parser!AST
|
||||||
}
|
}
|
||||||
|
|
||||||
Specifier specifier;
|
Specifier specifier;
|
||||||
specifier.packalign = this.packalign;
|
specifier.packalign = packalign.isUnknown ? this.packalign : packalign;
|
||||||
auto tspec = cparseSpecifierQualifierList(LVL.member, specifier);
|
auto tspec = cparseSpecifierQualifierList(LVL.member, specifier);
|
||||||
if (!tspec)
|
if (!tspec)
|
||||||
{
|
{
|
||||||
|
|
|
@ -8799,6 +8799,7 @@ struct Id final
|
||||||
static Identifier* define;
|
static Identifier* define;
|
||||||
static Identifier* undef;
|
static Identifier* undef;
|
||||||
static Identifier* ident;
|
static Identifier* ident;
|
||||||
|
static Identifier* packed;
|
||||||
static void initialize();
|
static void initialize();
|
||||||
Id()
|
Id()
|
||||||
{
|
{
|
||||||
|
|
|
@ -574,6 +574,7 @@ immutable Msgtable[] msgtable =
|
||||||
{ "define" },
|
{ "define" },
|
||||||
{ "undef" },
|
{ "undef" },
|
||||||
{ "ident" },
|
{ "ident" },
|
||||||
|
{ "packed" },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
|
|
28
compiler/test/compilable/test24594.c
Normal file
28
compiler/test/compilable/test24594.c
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct S1
|
||||||
|
{
|
||||||
|
uint32_t a;
|
||||||
|
uint64_t b;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
_Static_assert(sizeof(S1) == 12, "S1 size");
|
||||||
|
_Static_assert(&((struct S1*)0)->b == 4, "S1::b offset");
|
||||||
|
|
||||||
|
struct __attribute__((packed)) S2
|
||||||
|
{
|
||||||
|
uint8_t a;
|
||||||
|
uint16_t b;
|
||||||
|
};
|
||||||
|
|
||||||
|
_Static_assert(sizeof(S2) == 3, "S2 size");
|
||||||
|
_Static_assert(&((struct S2*)0)->b == 1, "S2::b offset");
|
||||||
|
|
||||||
|
struct __attribute__((packed)) S3
|
||||||
|
{
|
||||||
|
uint32_t a;
|
||||||
|
uint8_t b;
|
||||||
|
};
|
||||||
|
|
||||||
|
_Static_assert(sizeof(S3) == 5, "S3 size");
|
||||||
|
_Static_assert(&((struct S3*)0)->b == 4, "S3::b offset");
|
Loading…
Add table
Add a link
Reference in a new issue