From f4ca164257758e210338765d9fe7ef898ff4bc94 Mon Sep 17 00:00:00 2001 From: drpriver Date: Tue, 15 Apr 2025 00:31:21 -0700 Subject: [PATCH] Fix #20499 - [ImportC] typedef struct with name as a pointer cannot be used with struct name (#21232) Fixes https://github.com/dlang/dmd/issues/20499 Fixes https://github.com/dlang/dmd/issues/20963 ImportC deferred declaring "tagged" types (structs/unions/enums) until after it saw a possible typedef so that the identifier for a typedef declaration like: typedef struct { int x; } Foo; would give the struct the name Foo. In several circumstances, this led to tagged types not being declared. Resolve this by chasing down those circumstances. Also, there were other circumstances where types weren't being correctly declared which caused other issues. Lock those down. --- compiler/src/dmd/cparse.d | 150 +++++---- compiler/test/compilable/imports/imp20499.c | 8 + .../test/compilable/nested_struct_20499.c | 61 ++++ compiler/test/compilable/struct_decls_20499.c | 287 ++++++++++++++++++ compiler/test/compilable/test20499.d | 2 + compiler/test/compilable/test20963.c | 12 + compiler/test/fail_compilation/failcstuff3.c | 2 +- compiler/test/runnable/exe1.c | 2 - 8 files changed, 456 insertions(+), 68 deletions(-) create mode 100644 compiler/test/compilable/imports/imp20499.c create mode 100644 compiler/test/compilable/nested_struct_20499.c create mode 100644 compiler/test/compilable/struct_decls_20499.c create mode 100644 compiler/test/compilable/test20499.d create mode 100644 compiler/test/compilable/test20963.c diff --git a/compiler/src/dmd/cparse.d b/compiler/src/dmd/cparse.d index 86f85e34ce..fd5074f5bf 100644 --- a/compiler/src/dmd/cparse.d +++ b/compiler/src/dmd/cparse.d @@ -1720,6 +1720,34 @@ final class CParser(AST) : Parser!AST /********************************* Declaration Parser ***************************/ //{ + void declareTag(AST.TypeTag tt, ref Specifier specifier, bool generate_enum_id = false) + { + if (!tt.id && (generate_enum_id || tt.tok != TOK.enum_)) tt.id = Identifier.generateId("__tag"); + /* `struct tag;` and `struct tag { ... };` + * always result in a declaration in the current scope + */ + auto stag = (tt.tok == TOK.struct_) ? new AST.StructDeclaration(tt.loc, tt.id, false) : + (tt.tok == TOK.union_) ? new AST.UnionDeclaration(tt.loc, tt.id) : + new AST.EnumDeclaration(tt.loc, tt.id, tt.base); + if (!tt.alignExps && !tt.packalign.isUnknown()) + { + // saw `struct __declspec(align(N)) Tag ...` + auto st = stag.isStructDeclaration(); + st.alignment = tt.packalign; + } + stag.members = tt.members; + tt.members = null; + if (!symbols) + symbols = new AST.Dsymbols(); + AST.Dsymbol stags = stag; + if (tt.alignExps) + { + auto decls = new AST.Dsymbols(1); + (*decls)[0] = stags; + stags = new AST.AlignDeclaration(stags.loc, tt.alignExps, decls); + } + symbols.push(stags); + } /************************************* * C11 6.7 * declaration: @@ -1767,34 +1795,9 @@ final class CParser(AST) : Parser!AST specifier.packalign = this.packalign; auto tspec = cparseDeclarationSpecifiers(level, specifier); - AST.Dsymbol declareTag(AST.TypeTag tt, ref Specifier specifier) - { - /* `struct tag;` and `struct tag { ... };` - * always result in a declaration in the current scope - */ - auto stag = (tt.tok == TOK.struct_) ? new AST.StructDeclaration(tt.loc, tt.id, false) : - (tt.tok == TOK.union_) ? new AST.UnionDeclaration(tt.loc, tt.id) : - new AST.EnumDeclaration(tt.loc, tt.id, tt.base); - if (!tt.alignExps && !tt.packalign.isUnknown()) - { - // saw `struct __declspec(align(N)) Tag ...` - auto st = stag.isStructDeclaration(); - st.alignment = tt.packalign; - } - stag.members = tt.members; - tt.members = null; - if (!symbols) - symbols = new AST.Dsymbols(); - AST.Dsymbol stags = stag; - if (tt.alignExps) - { - auto decls = new AST.Dsymbols(1); - (*decls)[0] = stags; - stags = new AST.AlignDeclaration(stags.loc, tt.alignExps, decls); - } - symbols.push(stags); - return stags; - } + // Defer declaring a tagged type (struct/union/enum) so + // that anonymous types can use a typedef as their id. + /* If a declarator does not follow, it is unnamed */ @@ -1820,12 +1823,13 @@ final class CParser(AST) : Parser!AST !tt.id && (tt.tok == TOK.struct_ || tt.tok == TOK.union_)) return; // legal but meaningless empty declaration, ignore it - auto stags = declareTag(tt, specifier); + if (tt.members || tt.tok != TOK.enum_) + declareTag(tt, specifier); if (0 && tt.tok == TOK.enum_) // C11 proscribes enums with no members, but we allow it { if (!tt.members) - error(tt.loc, "`enum %s` has no members", stags.toChars()); + error(tt.loc, "`enum %s` has no members", tt.toChars()); } return; } @@ -1838,6 +1842,15 @@ final class CParser(AST) : Parser!AST return; } + if (auto tt = tspec.isTypeTag()) + { + if (tt.id && tt.members) + { + // Valid tag decl with name and members, go ahead and declare it now. + declareTag(tt, specifier); + } + } + if (tspec && specifier.mod & MOD.xconst) { tspec = toConst(tspec); @@ -1954,7 +1967,7 @@ final class CParser(AST) : Parser!AST typedefTab.setDim(typedefTabLengthSave); symbols = symbolsSave; if (!symbols) - symbols = new AST.Dsymbols; // lazilly create it + symbols = new AST.Dsymbols; // lazily create it if (level != LVL.global && !tspec && !specifier.scw && !specifier.mod) error("declaration-specifier-seq required"); @@ -1975,38 +1988,33 @@ final class CParser(AST) : Parser!AST bool isalias = true; Identifier idt; - if (auto ts = dt.isTypeStruct()) - { - if (ts.sym.isAnonymous()) - { - // This is a typedef for an anonymous struct-or-union. - // Directly set the ident for the struct-or-union. - ts.sym.ident = id; - isalias = false; - } - idt = ts.sym.ident; - } - else if (auto te = dt.isTypeEnum()) - { - if (te.sym.isAnonymous()) - { - // This is a typedef for an anonymous enum. - te.sym.ident = id; - isalias = false; - } - idt = te.sym.ident; - } - else if (auto tt = dt.isTypeTag()) + if (auto tt = dt.isTypeTag()) { if (!tt.id && id) /* This applies for enums declared as * typedef enum {A} E; + * Or for similar structs and unions. */ tt.id = id; - Specifier spec; - declareTag(tt, spec); + if (tt.members) + { + Specifier spec; + declareTag(tt, spec); + } idt = tt.id; } + else if (auto tt = tspec.isTypeTag()) + { + // The unusual situation of an anonymous typedef struct where the + // first typedef can't be used as its name. + // Just declare it now so we can get a valid id. + if (!tt.id && tt.members) + { + Specifier spec; + declareTag(tt, spec, true); + idt = tt.id; + } + } if (isalias) { //printf("AliasDeclaration %s %s\n", id.toChars(), dt.toChars()); @@ -2035,6 +2043,16 @@ final class CParser(AST) : Parser!AST if (dt.ty == AST.Tvoid) error("`void` has no value"); + if (auto tt = tspec.isTypeTag()) + { + // Anonymous struct being used as a var decl type + if (!tt.id && tt.members && tt.tok != TOK.enum_) + { + Specifier spec; + declareTag(tt, spec); + } + } + AST.Initializer initializer; bool hasInitializer; if (token.value == TOK.assign) @@ -4097,7 +4115,7 @@ final class CParser(AST) : Parser!AST * struct { ... members ... }; * C11 6.7.2.1-13 */ - if (!tt.id && tt.members) + if (!tt.id && tt.members && tt.tok != TOK.enum_) { /* members of anonymous struct are considered members of * the containing struct @@ -4113,17 +4131,19 @@ final class CParser(AST) : Parser!AST /* `struct tag;` and `struct tag { ... };` * always result in a declaration in the current scope */ - // TODO: merge in specifier - auto stag = (tt.tok == TOK.struct_) - ? new AST.StructDeclaration(tt.loc, tt.id, false) - : new AST.UnionDeclaration(tt.loc, tt.id); - stag.members = tt.members; - if (!symbols) - symbols = new AST.Dsymbols(); - auto s = applySpecifier(stag, specifier); - symbols.push(s); + Specifier spec; + declareTag(tt, spec); return; } + if (auto tt = tspec.isTypeTag()) + { + // Declare the tagged type at this point. + if (tt.members) + { + Specifier spec; + declareTag(tt, spec); + } + } while (1) { diff --git a/compiler/test/compilable/imports/imp20499.c b/compiler/test/compilable/imports/imp20499.c new file mode 100644 index 0000000000..7ae74906f7 --- /dev/null +++ b/compiler/test/compilable/imports/imp20499.c @@ -0,0 +1,8 @@ +// https://github.com/dlang/dmd/issues/20499 +typedef struct Foo { + int x; +} *pFoo; + +struct Bar { + struct Foo foo; +}; diff --git a/compiler/test/compilable/nested_struct_20499.c b/compiler/test/compilable/nested_struct_20499.c new file mode 100644 index 0000000000..ec83abde17 --- /dev/null +++ b/compiler/test/compilable/nested_struct_20499.c @@ -0,0 +1,61 @@ +// https://github.com/dlang/dmd/issues/20499 + + +struct Outer { + struct __attribute__((aligned(8))) { + int x; + } n; + enum {A}; + enum {B} b; +}; + +struct Outer2 { + struct __attribute__((aligned(8))) Nested { + int x; + } n; +}; + +const int x = A; +const int y = B; + +struct Outer o = {3}; +_Static_assert(_Alignof(typeof(o.n)) == 8, ""); +_Static_assert(_Alignof(struct Outer) == 8, ""); +_Static_assert(_Alignof(struct Outer2) == 8, ""); +_Static_assert(_Alignof(struct Nested) == 8, ""); + +void test(void){ + struct Outer { + struct __attribute__((aligned(16))) { + int x; + } n; + enum {A=2}; + enum {B=3} b; + }; + + struct Outer2 { + struct __attribute__((aligned(16))) Nested { + int x; + } n; + }; + + const int x = A; + const int y = B; + + struct Outer o = {3}; + _Static_assert(_Alignof(typeof(o.n)) == 16, ""); + _Static_assert(_Alignof(struct Outer) == 16, ""); + _Static_assert(_Alignof(struct Outer2) == 16, ""); + _Static_assert(_Alignof(struct Nested) == 16, ""); +} + +void test2(void){ + const int x = A; + const int y = B; + + struct Outer o = {3}; + _Static_assert(_Alignof(typeof(o.n)) == 8, ""); + _Static_assert(_Alignof(struct Outer) == 8, ""); + _Static_assert(_Alignof(struct Outer2) == 8, ""); + _Static_assert(_Alignof(struct Nested) == 8, ""); +} diff --git a/compiler/test/compilable/struct_decls_20499.c b/compiler/test/compilable/struct_decls_20499.c new file mode 100644 index 0000000000..27f342db4d --- /dev/null +++ b/compiler/test/compilable/struct_decls_20499.c @@ -0,0 +1,287 @@ +// https://github.com/dlang/dmd/issues/20499 + +// +// attribute((aligned())) is so we can tell if attributes are being applied. +// +typedef struct __attribute__((aligned(8))) S { + int x, y; +} S; +_Static_assert(sizeof(struct S) == 8, "sizeof(S)"); +_Static_assert(_Alignof(struct S) == 8, "_Alignof(S)"); + +typedef struct __attribute__((aligned(8))) Foo { + int x, y; +} *pFoo, Foo, FooB; + +_Static_assert(sizeof(struct Foo) == sizeof(struct S), "sizeof(Foo)"); +_Static_assert(_Alignof(struct Foo) == _Alignof(struct S), "_Alignof(Foo)"); +_Static_assert(sizeof(Foo) == sizeof(struct S), "sizeof(Foo)"); +_Static_assert(_Alignof(Foo) == _Alignof(struct S), "_Alignof(Foo)"); +_Static_assert(sizeof(FooB) == sizeof(struct S), "sizeof(FooB)"); +_Static_assert(_Alignof(FooB) == _Alignof(struct S), "_Alignof(FooB)"); + +pFoo pf; +_Static_assert(sizeof(*pf) == sizeof(struct S), "sizeof(*pf)"); +_Static_assert(_Alignof(typeof(*pf)) == _Alignof(struct S), "_Alignof(*pf)"); + +typedef struct __attribute__((aligned(8))) { + int x, y; +} Baz, *pBaz, BazB; +_Static_assert(sizeof(Baz) == sizeof(struct S), "sizeof(Baz)"); +_Static_assert(sizeof(BazB) == sizeof(struct S), "sizeof(BazB)"); +_Static_assert(_Alignof(Baz) == _Alignof(struct S), "_Alignof(Baz)"); +_Static_assert(_Alignof(BazB) == _Alignof(struct S), "_Alignof(BazB)"); + +pBaz pb; +_Static_assert(sizeof(*pb) == sizeof(struct S), "sizeof(*pb)"); +_Static_assert(_Alignof(typeof(*pb)) == _Alignof(struct S), "_Alignof(*pb)"); + +typedef struct __attribute__((aligned(8))) { + int x, y; +} *pTux; +pTux pt; +_Static_assert(sizeof(*pt) == sizeof(struct S), "sizeof(*pt)"); +_Static_assert(_Alignof(typeof(*pt)) == _Alignof(struct S), "_Alignof(*pt)"); + +typedef struct __attribute__((aligned(8))) { + int x, y; +} Qux; +_Static_assert(sizeof(Qux) == sizeof(struct S), "sizeof(FooB)"); +_Static_assert(_Alignof(Qux) == _Alignof(struct S), "_Alignof(FooB)"); + +struct Bar { + struct S foo; +}; +_Static_assert(sizeof(struct Bar) == sizeof(struct S), "sizeof(Bar)"); +_Static_assert(_Alignof(struct Bar) == _Alignof(struct S), "_Alignof(Bar)"); + +typedef struct __attribute__((aligned(8))) { + int x, y; +} *pLux; +pLux pl; +_Static_assert(sizeof(*pl) == sizeof(struct S), "sizeof(*pl)"); +_Static_assert(_Alignof(typeof(*pl)) == _Alignof(struct S), "_Alignof(*pl)"); + + +typedef struct __attribute__((aligned(8))) { + int x, y; +} ****pWux; +pWux pw; +_Static_assert(sizeof(****pw) == sizeof(struct S), "sizeof(****pw)"); +_Static_assert(_Alignof(typeof(****pw)) == _Alignof(struct S), "_Alignof(****pw)"); + +struct __attribute__((aligned(8))) { + int x, y; +} f; +_Static_assert(sizeof(f) == sizeof(struct S), "sizeof(f)"); +_Static_assert(_Alignof(typeof(f)) == _Alignof(struct S), "_Alignof(f)"); + +struct __attribute__((aligned(8))) { + int x, y; +} fa[3]; +_Static_assert(sizeof(fa[0]) == sizeof(struct S), "sizeof(fa[0])"); +_Static_assert(_Alignof(typeof(fa[0])) == _Alignof(struct S), "_Alignof(fa[0])"); + +void locals(void){ + // function local version + // Use different values so we know we aren't just using globals + typedef struct __attribute__((aligned(16))) S { + int x, y[7]; + } S; + _Static_assert(sizeof(struct S) == 32, "sizeof(S)"); + _Static_assert(_Alignof(struct S) == 16, "_Alignof(S)"); + + typedef struct __attribute__((aligned(16))) Foo { + int x, y[7]; + } *pFoo, Foo, FooB; + + _Static_assert(sizeof(struct Foo) == sizeof(struct S), "sizeof(Foo)"); + _Static_assert(_Alignof(struct Foo) == _Alignof(struct S), "_Alignof(Foo)"); + _Static_assert(sizeof(Foo) == sizeof(struct S), "sizeof(Foo)"); + _Static_assert(_Alignof(Foo) == _Alignof(struct S), "_Alignof(Foo)"); + _Static_assert(sizeof(FooB) == sizeof(struct S), "sizeof(FooB)"); + _Static_assert(_Alignof(FooB) == _Alignof(struct S), "_Alignof(FooB)"); + + pFoo pf; + _Static_assert(sizeof(*pf) == sizeof(struct S), "sizeof(*pf)"); + _Static_assert(_Alignof(typeof(*pf)) == _Alignof(struct S), "_Alignof(*pf)"); + + typedef struct __attribute__((aligned(16))) { + int x, y[7]; + } Baz, *pBaz, BazB; + _Static_assert(sizeof(Baz) == sizeof(struct S), "sizeof(Baz)"); + _Static_assert(sizeof(BazB) == sizeof(struct S), "sizeof(BazB)"); + _Static_assert(_Alignof(Baz) == _Alignof(struct S), "_Alignof(Baz)"); + _Static_assert(_Alignof(BazB) == _Alignof(struct S), "_Alignof(BazB)"); + + + pBaz pb; + _Static_assert(sizeof(*pb) == sizeof(struct S), "sizeof(*pb)"); + _Static_assert(_Alignof(typeof(*pb)) == _Alignof(struct S), "_Alignof(*pb)"); + + + typedef struct __attribute__((aligned(16))) { + int x, y[7]; + } *pTux; + pTux pt; + _Static_assert(sizeof(*pt) == sizeof(struct S), "sizeof(*pt)"); + _Static_assert(_Alignof(typeof(*pt)) == _Alignof(struct S), "_Alignof(*pt)"); + + + typedef struct __attribute__((aligned(16))) { + int x, y[7]; + } Qux; + _Static_assert(sizeof(Qux) == sizeof(struct S), "sizeof(FooB)"); + _Static_assert(_Alignof(Qux) == _Alignof(struct S), "_Alignof(FooB)"); + + struct Bar { + struct S foo; + }; + _Static_assert(sizeof(struct Bar) == sizeof(struct S), "sizeof(Bar)"); + _Static_assert(_Alignof(struct Bar) == _Alignof(struct S), "_Alignof(Bar)"); + + typedef struct __attribute__((aligned(16))) { + int x, y[7]; + } *pLux; + pLux pl; + _Static_assert(sizeof(*pl) == sizeof(struct S), "sizeof(*pl)"); + _Static_assert(_Alignof(typeof(*pl)) == _Alignof(struct S), "_Alignof(*pl)"); + + + typedef struct __attribute__((aligned(16))) { + int x, y[7]; + } ****pWux; + pWux pw; + _Static_assert(sizeof(****pw) == sizeof(struct S), "sizeof(****pw)"); + _Static_assert(_Alignof(typeof(****pw)) == _Alignof(struct S), "_Alignof(****pw)"); + + struct __attribute__((aligned(16))) { + int x, y[7]; + } f; + _Static_assert(sizeof(f) == sizeof(struct S), "sizeof(f)"); + _Static_assert(_Alignof(typeof(f)) == _Alignof(struct S), "_Alignof(f)"); + // Verify shadowing works + { + typedef struct __attribute__((aligned(32))) S { + int x, y[15]; + } S; + _Static_assert(sizeof(struct S) == 64, "sizeof(S)"); + _Static_assert(_Alignof(struct S) == 32, "_Alignof(S)"); + + typedef struct __attribute__((aligned(32))) Foo { + int x, y[15]; + } *pFoo, Foo, FooB; + + _Static_assert(sizeof(struct Foo) == sizeof(struct S), "sizeof(Foo)"); + _Static_assert(_Alignof(struct Foo) == _Alignof(struct S), "_Alignof(Foo)"); + _Static_assert(sizeof(Foo) == sizeof(struct S), "sizeof(Foo)"); + _Static_assert(_Alignof(Foo) == _Alignof(struct S), "_Alignof(Foo)"); + _Static_assert(sizeof(FooB) == sizeof(struct S), "sizeof(FooB)"); + _Static_assert(_Alignof(FooB) == _Alignof(struct S), "_Alignof(FooB)"); + + pFoo pf; + _Static_assert(sizeof(*pf) == sizeof(struct S), "sizeof(*pf)"); + _Static_assert(_Alignof(typeof(*pf)) == _Alignof(struct S), "_Alignof(*pf)"); + + typedef struct __attribute__((aligned(32))) { + int x, y[15]; + } Baz, *pBaz, BazB; + _Static_assert(sizeof(Baz) == sizeof(struct S), "sizeof(Baz)"); + _Static_assert(sizeof(BazB) == sizeof(struct S), "sizeof(BazB)"); + _Static_assert(_Alignof(Baz) == _Alignof(struct S), "_Alignof(Baz)"); + _Static_assert(_Alignof(BazB) == _Alignof(struct S), "_Alignof(BazB)"); + + + pBaz pb; + _Static_assert(sizeof(*pb) == sizeof(struct S), "sizeof(*pb)"); + _Static_assert(_Alignof(typeof(*pb)) == _Alignof(struct S), "_Alignof(*pb)"); + + + typedef struct __attribute__((aligned(32))) { + int x, y[15]; + } *pTux; + pTux pt; + _Static_assert(sizeof(*pt) == sizeof(struct S), "sizeof(*pt)"); + _Static_assert(_Alignof(typeof(*pt)) == _Alignof(struct S), "_Alignof(*pt)"); + + + typedef struct __attribute__((aligned(32))) { + int x, y[15]; + } Qux; + _Static_assert(sizeof(Qux) == sizeof(struct S), "sizeof(FooB)"); + _Static_assert(_Alignof(Qux) == _Alignof(struct S), "_Alignof(FooB)"); + + struct Bar { + struct S foo; + }; + _Static_assert(sizeof(struct Bar) == sizeof(struct S), "sizeof(Bar)"); + _Static_assert(_Alignof(struct Bar) == _Alignof(struct S), "_Alignof(Bar)"); + + typedef struct __attribute__((aligned(32))) { + int x, y[15]; + } *pLux; + pLux pl; + _Static_assert(sizeof(*pl) == sizeof(struct S), "sizeof(*pl)"); + _Static_assert(_Alignof(typeof(*pl)) == _Alignof(struct S), "_Alignof(*pl)"); + + + typedef struct __attribute__((aligned(32))) { + int x, y[15]; + } ****pWux; + pWux pw; + _Static_assert(sizeof(****pw) == sizeof(struct S), "sizeof(****pw)"); + _Static_assert(_Alignof(typeof(****pw)) == _Alignof(struct S), "_Alignof(****pw)"); + + struct __attribute__((aligned(32))) { + int x, y[15]; + } f; + _Static_assert(sizeof(f) == sizeof(struct S), "sizeof(f)"); + _Static_assert(_Alignof(typeof(f)) == _Alignof(struct S), "_Alignof(f)"); + } +} + +void globals(void){ + _Static_assert(sizeof(struct S) == 8, "sizeof(S)"); + _Static_assert(_Alignof(struct S) == 8, "_Alignof(S)"); + + _Static_assert(sizeof(struct Foo) == sizeof(struct S), "sizeof(Foo)"); + _Static_assert(_Alignof(struct Foo) == _Alignof(struct S), "_Alignof(Foo)"); + _Static_assert(sizeof(Foo) == sizeof(struct S), "sizeof(Foo)"); + _Static_assert(_Alignof(Foo) == _Alignof(struct S), "_Alignof(Foo)"); + _Static_assert(sizeof(FooB) == sizeof(struct S), "sizeof(FooB)"); + _Static_assert(_Alignof(FooB) == _Alignof(struct S), "_Alignof(FooB)"); + + pFoo pf; + _Static_assert(sizeof(*pf) == sizeof(struct S), "sizeof(*pf)"); + _Static_assert(_Alignof(typeof(*pf)) == _Alignof(struct S), "_Alignof(*pf)"); + + _Static_assert(sizeof(Baz) == sizeof(struct S), "sizeof(Baz)"); + _Static_assert(sizeof(BazB) == sizeof(struct S), "sizeof(BazB)"); + _Static_assert(_Alignof(Baz) == _Alignof(struct S), "_Alignof(Baz)"); + _Static_assert(_Alignof(BazB) == _Alignof(struct S), "_Alignof(BazB)"); + + pBaz pb; + _Static_assert(sizeof(*pb) == sizeof(struct S), "sizeof(*pb)"); + _Static_assert(_Alignof(typeof(*pb)) == _Alignof(struct S), "_Alignof(*pb)"); + + pTux pt; + _Static_assert(sizeof(*pt) == sizeof(struct S), "sizeof(*pt)"); + _Static_assert(_Alignof(typeof(*pt)) == _Alignof(struct S), "_Alignof(*pt)"); + + _Static_assert(sizeof(Qux) == sizeof(struct S), "sizeof(FooB)"); + _Static_assert(_Alignof(Qux) == _Alignof(struct S), "_Alignof(FooB)"); + + _Static_assert(sizeof(struct Bar) == sizeof(struct S), "sizeof(Bar)"); + _Static_assert(_Alignof(struct Bar) == _Alignof(struct S), "_Alignof(Bar)"); + + pLux pl; + _Static_assert(sizeof(*pl) == sizeof(struct S), "sizeof(*pl)"); + _Static_assert(_Alignof(typeof(*pl)) == _Alignof(struct S), "_Alignof(*pl)"); + + + pWux pw; + _Static_assert(sizeof(****pw) == sizeof(struct S), "sizeof(****pw)"); + _Static_assert(_Alignof(typeof(****pw)) == _Alignof(struct S), "_Alignof(****pw)"); + Foo foo = {1, 2, 3}; + struct Foo foo2 = {1, 2, 3}; +} diff --git a/compiler/test/compilable/test20499.d b/compiler/test/compilable/test20499.d new file mode 100644 index 0000000000..9e9e1d2712 --- /dev/null +++ b/compiler/test/compilable/test20499.d @@ -0,0 +1,2 @@ +// https://github.com/dlang/dmd/issues/20499 +import imports.imp20499; diff --git a/compiler/test/compilable/test20963.c b/compiler/test/compilable/test20963.c new file mode 100644 index 0000000000..a5aead13d2 --- /dev/null +++ b/compiler/test/compilable/test20963.c @@ -0,0 +1,12 @@ +// https://github.com/dlang/dmd/issues/20963 + +void cdind() { + struct ABC { + int y; + } *p; + + { + struct ABC { int x; } abc; + abc.x = 1; + } +} diff --git a/compiler/test/fail_compilation/failcstuff3.c b/compiler/test/fail_compilation/failcstuff3.c index f54c942d44..dd07c3e165 100644 --- a/compiler/test/fail_compilation/failcstuff3.c +++ b/compiler/test/fail_compilation/failcstuff3.c @@ -1,7 +1,7 @@ // check importAll analysis of C files /* TEST_OUTPUT: --- -fail_compilation/failcstuff3.c(54): Error: union `failcstuff3.S22061` conflicts with struct `failcstuff3.S22061` at fail_compilation/failcstuff3.c(50) +fail_compilation/failcstuff3.c(54): Error: redeclaration of `S22061` --- */ diff --git a/compiler/test/runnable/exe1.c b/compiler/test/runnable/exe1.c index 104025f295..3f256810fa 100644 --- a/compiler/test/runnable/exe1.c +++ b/compiler/test/runnable/exe1.c @@ -1242,7 +1242,6 @@ void cdind() assert(cbptr->nextread == 4); } -#if 0 // TODO ImportC { struct ABC { char a,b,*l_text; } abc; static struct { int w_doto; struct ABC *w_dotp; } curw,*curwp; @@ -1253,7 +1252,6 @@ void cdind() c = curwp->w_dotp->l_text[curwp->w_doto]&0xFF; assert(c == '2'); } -#endif } void logexp()