diff --git a/compiler/src/dmd/dsymbolsem.d b/compiler/src/dmd/dsymbolsem.d index bf0731c185..7127ffc9b3 100644 --- a/compiler/src/dmd/dsymbolsem.d +++ b/compiler/src/dmd/dsymbolsem.d @@ -3091,10 +3091,18 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor StructDeclaration sym = ts.sym; if (sd.isCsymbol() && sym.isCsymbol()) { - /* This is two structs imported from different C files. - * Just ignore sd, the second one. The first one will always - * be found when going through the type. - */ + + if (!isCCompatible(sd, sym)) + { + // Already issued an error. + errorSupplemental(sd.loc, "C %ss with the same name from different imports are merged", sd.kind); + } + else { + /* This is two structs imported from different C files. + * Just ignore sd, the second one. The first one will always + * be found when going through the type. + */ + } } else { @@ -3134,6 +3142,234 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor //printf("-StructDeclaration::semantic(this=%p, '%s', sizeok = %d)\n", sd, sd.toPrettyChars(), sd.sizeok); } + // + // Checks if two structs are compatible + // Implements the rules according to C23 6.2.7 + // + static bool isCCompatible(StructDeclaration a, StructDeclaration b) + { + // Get the name of a type, while avoiding exposing "__tagXXX" anonymous structs + static const(char)* typeName(Type t) + { + if (TypeStruct ts = t.isTypeStruct()) + { + if (ts.sym.ident.toString().startsWith("__tag")) + return ts.sym.isUnionDeclaration() ? "(anonymous union)".ptr: "(anonymous struct)".ptr; + } + return t.toChars(); + } + + void incompatError() + { + .error(a.loc, "%s `%s` already exists with an incompatible definition.", + a.kind, typeName(a.type)); + errorSupplemental(b.loc, "previously declared here"); + } + + + // For recursive calls into unnamed structs (so Type.equals() doesn't work). + static bool isCCompatibleUnnamedStruct(Type a, Type b) + { + TypeStruct ats = a.isTypeStruct(); + if (!ats) return false; + TypeStruct bts = b.isTypeStruct(); + if (!bts) return false; + // Hack, anonymous structs within a struct are given + // an anonymous id starting with __tag. + if (!ats.sym.ident.toString().startsWith("__tag")) + return false; + if (!bts.sym.ident.toString().startsWith("__tag")) + return false; + return isCCompatible(ats.sym, bts.sym); + } + + if (a.fields.length != b.fields.length) + { + incompatError(); + errorSupplemental(a.loc, "`%s` has %zu field(s) while `%s` has %zu field(s)", + a.toPrettyChars(), a.fields.length, b.toPrettyChars(), b.fields.length); + return false; + } + // both are structs or both are unions + if ((a.isUnionDeclaration() is null) != (b.isUnionDeclaration() is null)) + { + incompatError(); + errorSupplemental(a.loc, "`%s` is a %s while `%s` is a %s", + a.toPrettyChars(), a.kind, b.toPrettyChars(), b.kind); + return false; + } + if (a.alignment != b.alignment) + { + incompatError(); + errorSupplemental(a.loc, "`%s` has different alignment or packing", a.toPrettyChars()); + if (a.alignment.isDefault() && ! b.alignment.isDefault()) + { + errorSupplemental(a.loc, "`%s` alignment: default", a.toPrettyChars()); + errorSupplemental(b.loc, "`%s` alignment: %u", + b.toPrettyChars(), cast(uint)b.alignment.get()); + } + else if (!a.alignment.isDefault() && b.alignment.isDefault()) + { + errorSupplemental(a.loc, "`%s` alignment: %u", + a.toPrettyChars(), cast(uint)a.alignment.get()); + errorSupplemental(b.loc, "`%s` alignment: default", + b.toPrettyChars()); + } + else if (a.alignment.get() != b.alignment.get()) + { + errorSupplemental(a.loc, "`%s` alignment: %u", + a.toPrettyChars(), cast(uint)a.alignment.get()); + errorSupplemental(b.loc, "`%s` alignment: %u", + b.toPrettyChars(), cast(uint)b.alignment.get()); + } + if (a.alignment.isPack() != b.alignment.isPack()) + { + errorSupplemental(a.loc, "`%s` packed: %s", + a.toPrettyChars(), a.alignment.isPack()?"true".ptr:"false".ptr); + errorSupplemental(b.loc, "`%s` packed: %s", + b.toPrettyChars(), b.alignment.isPack()?"true".ptr:"false".ptr); + } + return false; + } + foreach (size_t i, VarDeclaration a_field; a.fields[]) + { + VarDeclaration b_field = b.fields[i]; + // + // — there shall be a one-to-one correspondence between + // their members such that each pair of corresponding + // members are declared with compatible types; + // + if (!a_field.type.equals(b_field.type) && !isCCompatibleUnnamedStruct(a_field.type, b_field.type)) + { + // Already errored, just bail + incompatError(); + if (a_field.type.isTypeError()) return false; + if (b_field.type.isTypeError()) return false; + + errorSupplemental(a_field.loc, "Field %zu differs in type", i); + errorSupplemental(a_field.loc, "typeof(%s): %s", + a_field.toChars(), typeName(a_field.type)); + errorSupplemental(b_field.loc, "typeof(%s): %s", + b_field.toChars(), typeName(b_field.type)); + return false; + } + // + // — if one member of the pair is declared with an + // alignment specifier, the second is declared with an + // equivalent alignment specifier; + // + if (a_field.alignment != b_field.alignment) + { + incompatError(); + errorSupplemental(a_field.loc, "Field %zu differs in alignment or packing", i); + if (a_field.alignment.isDefault() && ! b_field.alignment.isDefault()) + { + errorSupplemental(a_field.loc, "`%s.%s` alignment: default", + a.toPrettyChars(),a_field.toChars()); + errorSupplemental(b_field.loc, "`%s.%s` alignment: %u", + b.toPrettyChars(), b_field.toChars(), cast(uint)b_field.alignment.get()); + } + else if (!a_field.alignment.isDefault() && b_field.alignment.isDefault()) + { + errorSupplemental(a_field.loc, "`%s.%s` alignment: %u", + a.toPrettyChars(), a_field.toChars(), cast(uint)a_field.alignment.get()); + errorSupplemental(b_field.loc, "`%s.%s` alignment: default", + b.toPrettyChars(), b_field.toChars()); + } + else if (a_field.alignment.get() != b_field.alignment.get()) + { + errorSupplemental(a_field.loc, "`%s.%s` alignment: %u", + a.toPrettyChars(), a_field.toChars(), + cast(uint)a_field.alignment.get()); + errorSupplemental(b_field.loc, "`%s.%s` alignment: %u", + b.toPrettyChars(), b_field.toChars(), + cast(uint)b_field.alignment.get()); + } + if (a_field.alignment.isPack() != b_field.alignment.isPack()) + { + errorSupplemental(a_field.loc, "`%s.%s` packed: %s", + a.toPrettyChars(), a_field.toChars(), + a_field.alignment.isPack()?"true".ptr:"false".ptr); + errorSupplemental(b_field.loc, "`%s.%s` packed: %s", + b.toPrettyChars(), b_field.toChars(), + b_field.alignment.isPack()?"true".ptr:"false".ptr); + } + return false; + } + // + // - and, if one member of the pair is declared with a + // name, the second is declared with the same name. + // + if (a_field.ident.isAnonymous()) + { + if (!b_field.ident.isAnonymous()) + { + incompatError(); + errorSupplemental(a_field.loc, "Field %zu differs in name", i); + errorSupplemental(a_field.loc, "(anonymous)", a_field.ident.toChars()); + errorSupplemental(b_field.loc, "%s", b_field.ident.toChars()); + return false; + } + } + else if (b_field.ident.isAnonymous()) + { + incompatError(); + errorSupplemental(a_field.loc, "Field %zu differs in name", i); + errorSupplemental(a_field.loc, "%s", a_field.ident.toChars()); + errorSupplemental(b_field.loc, "(anonymous)"); + return false; + } + else if (a_field.ident != b_field.ident) + { + incompatError(); + errorSupplemental(a_field.loc, "Field %zu differs in name", i); + errorSupplemental(a_field.loc, "%s", a_field.ident.toChars()); + errorSupplemental(b_field.loc, "%s", b_field.ident.toChars()); + return false; + } + + // + // For two structures or unions, corresponding bit-fields shall have the same widths. + // + BitFieldDeclaration bfa = a_field.isBitFieldDeclaration(); + BitFieldDeclaration bfb = b_field.isBitFieldDeclaration(); + if ((bfa is null) != (bfb is null)) + { + incompatError(); + errorSupplemental(a_field.loc, "Field %zu differs in being a bitfield", i); + if (bfa is null) + { + errorSupplemental(a_field.loc, "`%s.%s` is not a bitfield", + a.toPrettyChars(), a_field.toChars()); + errorSupplemental(b_field.loc, "`%s.%s` is a bitfield", + b.toPrettyChars(), b_field.toChars()); + } + else if (bfb is null) + { + errorSupplemental(a_field.loc, "`%s.%s` *is a bitfield", + a.toPrettyChars(), a_field.toChars()); + errorSupplemental(b_field.loc, "`%s.%s` is not a bitfield", + b.toPrettyChars(), b_field.toChars()); + } + return false; + } + if (bfa !is null && bfb !is null) + { + if (bfa.fieldWidth != bfb.fieldWidth) + { + incompatError(); + errorSupplemental(a_field.loc, "Field %zu differs in bitfield width", i); + errorSupplemental(a_field.loc, "`%s.%s`: %u", + a.toPrettyChars(), a_field.toChars(), bfa.fieldWidth); + errorSupplemental(b_field.loc, "`%s.%s`: %u", + b.toPrettyChars(), b_field.toChars(), bfb.fieldWidth); + return false; + } + } + } + return true; + } + void interfaceSemantic(ClassDeclaration cd) { cd.vtblInterfaces = new BaseClasses(); diff --git a/compiler/test/compilable/imports/imp18127a.c b/compiler/test/compilable/imports/imp18127a.c new file mode 100644 index 0000000000..cd173151db --- /dev/null +++ b/compiler/test/compilable/imports/imp18127a.c @@ -0,0 +1,74 @@ +// https://github.com/dlang/dmd/issues/18127 +union struct_or_union { + int x; +}; + +struct S_n_fields { + int x, y; +}; + +struct S_types { + float x; +}; + +struct S_names { + float x; +}; + +struct B { + int x; +}; + +struct S_b { + struct B b; +}; + +struct S_contains_anon_named { + struct { + int x; + } a; +}; + +struct S_contains_anon_unnamed { + struct { + int x; + }; +}; + +struct S_bitfields_mismatch1 { + unsigned x: 3; + unsigned y: 1; +}; +struct S_bitfields_mismatch2 { + unsigned x; + unsigned y: 1; +}; + +struct S_bitfields_widths { + unsigned x: 3; + unsigned y: 1; +}; + +struct S_bitfields_anon { + unsigned x: 3; + unsigned : 1; +}; + +struct S_alignas { + _Alignas(8) float x; +}; +struct S_aligned { + float x; +}__attribute__((aligned(8))); + +struct __attribute__((packed)) S_pack_1 { + float x; + char c; +}; +#pragma pack(push) +#pragma pack(1) +struct S_pack_2 { + float x; + char c; +}; +#pragma pack(pop) diff --git a/compiler/test/compilable/imports/imp18127b.c b/compiler/test/compilable/imports/imp18127b.c new file mode 100644 index 0000000000..cd173151db --- /dev/null +++ b/compiler/test/compilable/imports/imp18127b.c @@ -0,0 +1,74 @@ +// https://github.com/dlang/dmd/issues/18127 +union struct_or_union { + int x; +}; + +struct S_n_fields { + int x, y; +}; + +struct S_types { + float x; +}; + +struct S_names { + float x; +}; + +struct B { + int x; +}; + +struct S_b { + struct B b; +}; + +struct S_contains_anon_named { + struct { + int x; + } a; +}; + +struct S_contains_anon_unnamed { + struct { + int x; + }; +}; + +struct S_bitfields_mismatch1 { + unsigned x: 3; + unsigned y: 1; +}; +struct S_bitfields_mismatch2 { + unsigned x; + unsigned y: 1; +}; + +struct S_bitfields_widths { + unsigned x: 3; + unsigned y: 1; +}; + +struct S_bitfields_anon { + unsigned x: 3; + unsigned : 1; +}; + +struct S_alignas { + _Alignas(8) float x; +}; +struct S_aligned { + float x; +}__attribute__((aligned(8))); + +struct __attribute__((packed)) S_pack_1 { + float x; + char c; +}; +#pragma pack(push) +#pragma pack(1) +struct S_pack_2 { + float x; + char c; +}; +#pragma pack(pop) diff --git a/compiler/test/compilable/test18127.d b/compiler/test/compilable/test18127.d new file mode 100644 index 0000000000..35e6bdc5b1 --- /dev/null +++ b/compiler/test/compilable/test18127.d @@ -0,0 +1,4 @@ +// https://github.com/dlang/dmd/issues/18127 + +import imports.imp18127a; +import imports.imp18127b; diff --git a/compiler/test/fail_compilation/imports/imp18127a.c b/compiler/test/fail_compilation/imports/imp18127a.c new file mode 100644 index 0000000000..2ef629e3b5 --- /dev/null +++ b/compiler/test/fail_compilation/imports/imp18127a.c @@ -0,0 +1,83 @@ +// https://github.com/dlang/dmd/issues/18127 +// union in here, struct in other +union struct_or_union { + int x; +}; + +// mismatching number of fields +struct S_n_fields { + int x, y; +}; + +// mismatched types +struct S_types { + float x; +}; + +// mismatched names +struct S_names { + float x; +}; + +struct B { + int x; +}; + +// Contains a struct that is incompatible +struct S_b { + struct B b; +}; + +// mismatched anonymous struct +struct S_contains_anon_named { + struct { + int x; + } a; +}; + +struct S_contains_anon_unnamed { + struct { + int x; + }; +}; + +// bitfields +struct S_bitfields_mismatch1 { + unsigned x: 3; + unsigned y: 1; +}; +struct S_bitfields_mismatch2 { + unsigned x; + unsigned y: 1; +}; + +struct S_bitfields_widths { + unsigned x: 3; + unsigned y: 1; +}; + +struct S_bitfields_anon { + unsigned x: 3; + unsigned : 1; +}; + +// mismatched alignment +struct S_alignas { + _Alignas(8) float x; +}; +struct S_aligned { + float x; +}__attribute__((aligned(8))); + +// mismatched packing +struct __attribute__((packed)) S_pack_1 { + float x; + char c; +}; +#pragma pack(push) +#pragma pack(1) +struct S_pack_2 { + float x; + char c; +}; +#pragma pack(pop) diff --git a/compiler/test/fail_compilation/imports/imp18127b.c b/compiler/test/fail_compilation/imports/imp18127b.c new file mode 100644 index 0000000000..3cbbf7a9a6 --- /dev/null +++ b/compiler/test/fail_compilation/imports/imp18127b.c @@ -0,0 +1,80 @@ +// https://github.com/dlang/dmd/issues/18127 +// struct in here, union in other +struct struct_or_union { + int x; +}; + +// mismatching number of fields +struct S_n_fields { + int x; +}; + +// mismatched types +struct S_types { + int x; +}; + +// mismatched names +struct S_names { + float y; +}; + +struct B { + float x; +}; + +// Contains a struct that is incompatible +struct S_b { + struct B b; +}; + +// mismatched anonymous struct +struct S_contains_anon_named { + struct { + float x; + } a; +}; + +struct S_contains_anon_unnamed { + struct { + float x; + }; +}; + +// bitfields +struct S_bitfields_mismatch1 { + unsigned x: 3; + unsigned y; +}; +struct S_bitfields_mismatch2 { + unsigned x: 3; + unsigned y: 1; +}; + +struct S_bitfields_widths { + unsigned x: 3; + unsigned y: 2; +}; + +struct S_bitfields_anon { + unsigned x: 3; + unsigned y: 1; +}; + +// mismatched alignment +struct S_alignas { + float x; +}; +struct S_aligned { + float x; +}__attribute__((aligned(4))); + +// mismatched packing +struct S_pack_1 { + float x; + char c; +}; +struct S_pack_2 { + float x; + char c; +}; diff --git a/compiler/test/fail_compilation/test18127.d b/compiler/test/fail_compilation/test18127.d new file mode 100644 index 0000000000..ec0487cd89 --- /dev/null +++ b/compiler/test/fail_compilation/test18127.d @@ -0,0 +1,106 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/imports/imp18127b.c(3): Error: struct `struct_or_union` already exists with an incompatible definition. +fail_compilation/imports/imp18127a.c(3): previously declared here +fail_compilation/imports/imp18127b.c(3): `imp18127b.struct_or_union` is a struct while `imp18127a.struct_or_union` is a union +fail_compilation/imports/imp18127b.c(3): C structs with the same name from different imports are merged +fail_compilation/imports/imp18127b.c(8): Error: struct `S_n_fields` already exists with an incompatible definition. +fail_compilation/imports/imp18127a.c(8): previously declared here +fail_compilation/imports/imp18127b.c(8): `imp18127b.S_n_fields` has 1 field(s) while `imp18127a.S_n_fields` has 2 field(s) +fail_compilation/imports/imp18127b.c(8): C structs with the same name from different imports are merged +fail_compilation/imports/imp18127b.c(13): Error: struct `S_types` already exists with an incompatible definition. +fail_compilation/imports/imp18127a.c(13): previously declared here +fail_compilation/imports/imp18127b.c(14): Field 0 differs in type +fail_compilation/imports/imp18127b.c(14): typeof(x): int +fail_compilation/imports/imp18127a.c(14): typeof(x): float +fail_compilation/imports/imp18127b.c(13): C structs with the same name from different imports are merged +fail_compilation/imports/imp18127b.c(18): Error: struct `S_names` already exists with an incompatible definition. +fail_compilation/imports/imp18127a.c(18): previously declared here +fail_compilation/imports/imp18127b.c(19): Field 0 differs in name +fail_compilation/imports/imp18127b.c(19): y +fail_compilation/imports/imp18127a.c(19): x +fail_compilation/imports/imp18127b.c(18): C structs with the same name from different imports are merged +fail_compilation/imports/imp18127b.c(22): Error: struct `B` already exists with an incompatible definition. +fail_compilation/imports/imp18127a.c(22): previously declared here +fail_compilation/imports/imp18127b.c(23): Field 0 differs in type +fail_compilation/imports/imp18127b.c(23): typeof(x): float +fail_compilation/imports/imp18127a.c(23): typeof(x): int +fail_compilation/imports/imp18127b.c(22): C structs with the same name from different imports are merged +fail_compilation/imports/imp18127b.c(27): Error: struct `S_b` already exists with an incompatible definition. +fail_compilation/imports/imp18127a.c(27): previously declared here +fail_compilation/imports/imp18127b.c(27): C structs with the same name from different imports are merged +fail_compilation/imports/imp18127b.c(33): Error: struct `(anonymous struct)` already exists with an incompatible definition. +fail_compilation/imports/imp18127a.c(33): previously declared here +fail_compilation/imports/imp18127b.c(34): Field 0 differs in type +fail_compilation/imports/imp18127b.c(34): typeof(x): float +fail_compilation/imports/imp18127a.c(34): typeof(x): int +fail_compilation/imports/imp18127b.c(32): Error: struct `S_contains_anon_named` already exists with an incompatible definition. +fail_compilation/imports/imp18127a.c(32): previously declared here +fail_compilation/imports/imp18127b.c(35): Field 0 differs in type +fail_compilation/imports/imp18127b.c(35): typeof(a): (anonymous struct) +fail_compilation/imports/imp18127a.c(35): typeof(a): (anonymous struct) +fail_compilation/imports/imp18127b.c(32): C structs with the same name from different imports are merged +fail_compilation/imports/imp18127b.c(38): Error: struct `S_contains_anon_unnamed` already exists with an incompatible definition. +fail_compilation/imports/imp18127a.c(38): previously declared here +fail_compilation/imports/imp18127b.c(40): Field 0 differs in type +fail_compilation/imports/imp18127b.c(40): typeof(x): float +fail_compilation/imports/imp18127a.c(40): typeof(x): int +fail_compilation/imports/imp18127b.c(38): C structs with the same name from different imports are merged +fail_compilation/imports/imp18127b.c(45): Error: struct `S_bitfields_mismatch1` already exists with an incompatible definition. +fail_compilation/imports/imp18127a.c(45): previously declared here +fail_compilation/imports/imp18127b.c(47): Field 1 differs in being a bitfield +fail_compilation/imports/imp18127b.c(47): `imp18127b.S_bitfields_mismatch1.y` is not a bitfield +fail_compilation/imports/imp18127a.c(47): `imp18127a.S_bitfields_mismatch1.y` is a bitfield +fail_compilation/imports/imp18127b.c(45): C structs with the same name from different imports are merged +fail_compilation/imports/imp18127b.c(49): Error: struct `S_bitfields_mismatch2` already exists with an incompatible definition. +fail_compilation/imports/imp18127a.c(49): previously declared here +fail_compilation/imports/imp18127b.c(50): Field 0 differs in being a bitfield +fail_compilation/imports/imp18127b.c(50): `imp18127b.S_bitfields_mismatch2.x` *is a bitfield +fail_compilation/imports/imp18127a.c(50): `imp18127a.S_bitfields_mismatch2.x` is not a bitfield +fail_compilation/imports/imp18127b.c(49): C structs with the same name from different imports are merged +fail_compilation/imports/imp18127b.c(54): Error: struct `S_bitfields_widths` already exists with an incompatible definition. +fail_compilation/imports/imp18127a.c(54): previously declared here +fail_compilation/imports/imp18127b.c(56): Field 1 differs in bitfield width +fail_compilation/imports/imp18127b.c(56): `imp18127b.S_bitfields_widths.y`: 2 +fail_compilation/imports/imp18127a.c(56): `imp18127a.S_bitfields_widths.y`: 1 +fail_compilation/imports/imp18127b.c(54): C structs with the same name from different imports are merged +fail_compilation/imports/imp18127b.c(59): Error: struct `S_bitfields_anon` already exists with an incompatible definition. +fail_compilation/imports/imp18127a.c(59): previously declared here +fail_compilation/imports/imp18127b.c(61): Field 1 differs in name +fail_compilation/imports/imp18127b.c(61): y +fail_compilation/imports/imp18127a.c(61): (anonymous) +fail_compilation/imports/imp18127b.c(59): C structs with the same name from different imports are merged +fail_compilation/imports/imp18127b.c(65): Error: struct `S_alignas` already exists with an incompatible definition. +fail_compilation/imports/imp18127a.c(65): previously declared here +fail_compilation/imports/imp18127b.c(66): Field 0 differs in alignment or packing +fail_compilation/imports/imp18127b.c(66): `imp18127b.S_alignas.x` alignment: default +fail_compilation/imports/imp18127a.c(66): `imp18127a.S_alignas.x` alignment: 8 +fail_compilation/imports/imp18127b.c(65): C structs with the same name from different imports are merged +fail_compilation/imports/imp18127b.c(68): Error: struct `S_aligned` already exists with an incompatible definition. +fail_compilation/imports/imp18127a.c(68): previously declared here +fail_compilation/imports/imp18127b.c(68): `imp18127b.S_aligned` has different alignment or packing +fail_compilation/imports/imp18127b.c(68): `imp18127b.S_aligned` alignment: 4 +fail_compilation/imports/imp18127a.c(68): `imp18127a.S_aligned` alignment: 8 +fail_compilation/imports/imp18127b.c(68): C structs with the same name from different imports are merged +fail_compilation/imports/imp18127b.c(73): Error: struct `S_pack_1` already exists with an incompatible definition. +fail_compilation/imports/imp18127a.c(73): previously declared here +fail_compilation/imports/imp18127b.c(73): `imp18127b.S_pack_1` has different alignment or packing +fail_compilation/imports/imp18127b.c(73): `imp18127b.S_pack_1` alignment: default +fail_compilation/imports/imp18127a.c(73): `imp18127a.S_pack_1` alignment: 1 +fail_compilation/imports/imp18127b.c(73): `imp18127b.S_pack_1` packed: false +fail_compilation/imports/imp18127a.c(73): `imp18127a.S_pack_1` packed: true +fail_compilation/imports/imp18127b.c(73): C structs with the same name from different imports are merged +fail_compilation/imports/imp18127b.c(77): Error: struct `S_pack_2` already exists with an incompatible definition. +fail_compilation/imports/imp18127a.c(79): previously declared here +fail_compilation/imports/imp18127b.c(77): `imp18127b.S_pack_2` has different alignment or packing +fail_compilation/imports/imp18127b.c(77): `imp18127b.S_pack_2` alignment: default +fail_compilation/imports/imp18127a.c(79): `imp18127a.S_pack_2` alignment: 1 +fail_compilation/imports/imp18127b.c(77): C structs with the same name from different imports are merged +--- +*/ + +// https://github.com/dlang/dmd/issues/18127 + +import imports.imp18127a; +import imports.imp18127b;