authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-01-06 19:18:05-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-01-06 19:18:05-05:00
logbf678a12dfbdf0b3bb50804aa6b7ee081013049a
treec3ec70c8ffc0db33b747897bbec55bca8b84ff96
parentf83b02a581b2491e0a52f7c650ebd65ba8297263
parent62413da9d3481d0fa5c0f53658af447de587f674
signature Commit is signed but in an unrecognized format.

Merge branch 'LemonBoy-c-anon-stuff'

closes #4081

6 files changed, 107 insertions(+), 23 deletions(-)

src-self-hosted/clang.zig+2
...@@ -760,6 +760,7 @@ pub extern fn ZigClangASTUnit_visitLocalTopLevelDecls(self: *struct_ZigClangASTU...@@ -760,6 +760,7 @@ pub extern fn ZigClangASTUnit_visitLocalTopLevelDecls(self: *struct_ZigClangASTU
760pub extern fn ZigClangRecordType_getDecl(record_ty: ?*const struct_ZigClangRecordType) *const struct_ZigClangRecordDecl;760pub extern fn ZigClangRecordType_getDecl(record_ty: ?*const struct_ZigClangRecordType) *const struct_ZigClangRecordDecl;
761pub extern fn ZigClangEnumType_getDecl(record_ty: ?*const struct_ZigClangEnumType) *const struct_ZigClangEnumDecl;761pub extern fn ZigClangEnumType_getDecl(record_ty: ?*const struct_ZigClangEnumType) *const struct_ZigClangEnumDecl;
762pub extern fn ZigClangRecordDecl_getCanonicalDecl(record_decl: ?*const struct_ZigClangRecordDecl) ?*const struct_ZigClangTagDecl;762pub extern fn ZigClangRecordDecl_getCanonicalDecl(record_decl: ?*const struct_ZigClangRecordDecl) ?*const struct_ZigClangTagDecl;
763pub extern fn ZigClangFieldDecl_getCanonicalDecl(field_decl: ?*const struct_ZigClangFieldDecl) ?*const struct_ZigClangFieldDecl;
763pub extern fn ZigClangEnumDecl_getCanonicalDecl(self: ?*const struct_ZigClangEnumDecl) ?*const struct_ZigClangTagDecl;764pub extern fn ZigClangEnumDecl_getCanonicalDecl(self: ?*const struct_ZigClangEnumDecl) ?*const struct_ZigClangTagDecl;
764pub extern fn ZigClangTypedefNameDecl_getCanonicalDecl(self: ?*const struct_ZigClangTypedefNameDecl) ?*const struct_ZigClangTypedefNameDecl;765pub extern fn ZigClangTypedefNameDecl_getCanonicalDecl(self: ?*const struct_ZigClangTypedefNameDecl) ?*const struct_ZigClangTypedefNameDecl;
765pub extern fn ZigClangFunctionDecl_getCanonicalDecl(self: ?*const struct_ZigClangFunctionDecl) ?*const struct_ZigClangFunctionDecl;766pub extern fn ZigClangFunctionDecl_getCanonicalDecl(self: ?*const struct_ZigClangFunctionDecl) ?*const struct_ZigClangFunctionDecl;
...@@ -1055,6 +1056,7 @@ pub extern fn ZigClangStringLiteral_getString_bytes_begin_size(*const ZigClangSt...@@ -1055,6 +1056,7 @@ pub extern fn ZigClangStringLiteral_getString_bytes_begin_size(*const ZigClangSt
10551056
1056pub extern fn ZigClangParenExpr_getSubExpr(*const ZigClangParenExpr) *const ZigClangExpr;1057pub extern fn ZigClangParenExpr_getSubExpr(*const ZigClangParenExpr) *const ZigClangExpr;
10571058
1059pub extern fn ZigClangFieldDecl_isAnonymousStructOrUnion(*const struct_ZigClangFieldDecl) bool;
1058pub extern fn ZigClangFieldDecl_isBitField(*const struct_ZigClangFieldDecl) bool;1060pub extern fn ZigClangFieldDecl_isBitField(*const struct_ZigClangFieldDecl) bool;
1059pub extern fn ZigClangFieldDecl_getType(*const struct_ZigClangFieldDecl) struct_ZigClangQualType;1061pub extern fn ZigClangFieldDecl_getType(*const struct_ZigClangFieldDecl) struct_ZigClangQualType;
1060pub extern fn ZigClangFieldDecl_getLocation(*const struct_ZigClangFieldDecl) struct_ZigClangSourceLocation;1062pub extern fn ZigClangFieldDecl_getLocation(*const struct_ZigClangFieldDecl) struct_ZigClangSourceLocation;
src-self-hosted/translate_c.zig+35-8
...@@ -759,8 +759,13 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*...@@ -759,8 +759,13 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*
759 try emitWarning(c, field_loc, "{} demoted to opaque type - has bitfield", .{container_kind_name});759 try emitWarning(c, field_loc, "{} demoted to opaque type - has bitfield", .{container_kind_name});
760 break :blk opaque;760 break :blk opaque;
761 }761 }
762 const raw_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, field_decl)));762
763 if (raw_name.len < 1) continue; // fix weird windows bug?763 var is_anon = false;
764 var raw_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, field_decl)));
765 if (ZigClangFieldDecl_isAnonymousStructOrUnion(field_decl) or raw_name.len == 0) {
766 raw_name = try std.fmt.allocPrint(c.a(), "unnamed_{}", .{c.getMangle()});
767 is_anon = true;
768 }
764 const field_name = try appendIdentifier(c, raw_name);769 const field_name = try appendIdentifier(c, raw_name);
765 _ = try appendToken(c, .Colon, ":");770 _ = try appendToken(c, .Colon, ":");
766 const field_type = transQualType(rp, ZigClangFieldDecl_getType(field_decl), field_loc) catch |err| switch (err) {771 const field_type = transQualType(rp, ZigClangFieldDecl_getType(field_decl), field_loc) catch |err| switch (err) {
...@@ -781,6 +786,13 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*...@@ -781,6 +786,13 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*
781 .align_expr = null,786 .align_expr = null,
782 };787 };
783788
789 if (is_anon) {
790 _ = try c.decl_table.put(
791 @ptrToInt(ZigClangFieldDecl_getCanonicalDecl(field_decl)),
792 raw_name,
793 );
794 }
795
784 try container_node.fields_and_decls.push(&field_node.base);796 try container_node.fields_and_decls.push(&field_node.base);
785 _ = try appendToken(c, .Comma, ",");797 _ = try appendToken(c, .Comma, ",");
786 }798 }
...@@ -1829,8 +1841,11 @@ fn transInitListExprRecord(...@@ -1829,8 +1841,11 @@ fn transInitListExprRecord(
1829 // .field_name = expr1841 // .field_name = expr
1830 const period_tok = try appendToken(rp.c, .Period, ".");1842 const period_tok = try appendToken(rp.c, .Period, ".");
18311843
1832 const raw_name = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, field_decl)));1844 var raw_name = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, field_decl)));
1833 if (raw_name.len < 1) continue;1845 if (ZigClangFieldDecl_isAnonymousStructOrUnion(field_decl)) {
1846 const name = rp.c.decl_table.get(@ptrToInt(ZigClangFieldDecl_getCanonicalDecl(field_decl))).?;
1847 raw_name = try mem.dupe(rp.c.a(), u8, name.value);
1848 }
1834 const field_name_tok = try appendIdentifier(rp.c, raw_name);1849 const field_name_tok = try appendIdentifier(rp.c, raw_name);
18351850
1836 _ = try appendToken(rp.c, .Equal, "=");1851 _ = try appendToken(rp.c, .Equal, "=");
...@@ -2417,10 +2432,22 @@ fn transMemberExpr(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangMemberE...@@ -2417,10 +2432,22 @@ fn transMemberExpr(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangMemberE
2417 container_node = try transCreateNodePtrDeref(rp.c, container_node);2432 container_node = try transCreateNodePtrDeref(rp.c, container_node);
2418 }2433 }
24192434
2420 const name = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, ZigClangMemberExpr_getMemberDecl(stmt))));2435 const member_decl = ZigClangMemberExpr_getMemberDecl(stmt);
2421 if (name.len == 0) {2436 const name = blk: {
2422 return revertAndWarn(rp, error.UnsupportedTranslation, ZigClangStmt_getBeginLoc(@ptrCast(*const ZigClangStmt, stmt)), "TODO access of anonymous field", .{});2437 const decl_kind = ZigClangDecl_getKind(@ptrCast(*const ZigClangDecl, member_decl));
2423 }2438 // If we're referring to a anonymous struct/enum find the bogus name
2439 // we've assigned to it during the RecordDecl translation
2440 if (decl_kind == .Field) {
2441 const field_decl = @ptrCast(*const struct_ZigClangFieldDecl, member_decl);
2442 if (ZigClangFieldDecl_isAnonymousStructOrUnion(field_decl)) {
2443 const name = rp.c.decl_table.get(@ptrToInt(ZigClangFieldDecl_getCanonicalDecl(field_decl))).?;
2444 break :blk try mem.dupe(rp.c.a(), u8, name.value);
2445 }
2446 }
2447 const decl = @ptrCast(*const ZigClangDecl, member_decl);
2448 break :blk try rp.c.str(ZigClangDecl_getName_bytes_begin(decl));
2449 };
2450
2424 const node = try transCreateNodeFieldAccess(rp.c, container_node, name);2451 const node = try transCreateNodeFieldAccess(rp.c, container_node, name);
2425 return maybeSuppressResult(rp, scope, result_used, node);2452 return maybeSuppressResult(rp, scope, result_used, node);
2426}2453}
src/zig_clang.cpp+9
...@@ -1562,6 +1562,11 @@ const ZigClangTagDecl *ZigClangRecordDecl_getCanonicalDecl(const ZigClangRecordD...@@ -1562,6 +1562,11 @@ const ZigClangTagDecl *ZigClangRecordDecl_getCanonicalDecl(const ZigClangRecordD
1562 return reinterpret_cast<const ZigClangTagDecl *>(tag_decl);1562 return reinterpret_cast<const ZigClangTagDecl *>(tag_decl);
1563}1563}
15641564
1565const ZigClangFieldDecl *ZigClangFieldDecl_getCanonicalDecl(const ZigClangFieldDecl *field_decl) {
1566 const clang::FieldDecl *canon_decl = reinterpret_cast<const clang::FieldDecl*>(field_decl)->getCanonicalDecl();
1567 return reinterpret_cast<const ZigClangFieldDecl *>(canon_decl);
1568}
1569
1565const ZigClangTagDecl *ZigClangEnumDecl_getCanonicalDecl(const ZigClangEnumDecl *enum_decl) {1570const ZigClangTagDecl *ZigClangEnumDecl_getCanonicalDecl(const ZigClangEnumDecl *enum_decl) {
1566 const clang::TagDecl *tag_decl = reinterpret_cast<const clang::EnumDecl*>(enum_decl)->getCanonicalDecl();1571 const clang::TagDecl *tag_decl = reinterpret_cast<const clang::EnumDecl*>(enum_decl)->getCanonicalDecl();
1567 return reinterpret_cast<const ZigClangTagDecl *>(tag_decl);1572 return reinterpret_cast<const ZigClangTagDecl *>(tag_decl);
...@@ -2679,6 +2684,10 @@ bool ZigClangFieldDecl_isBitField(const struct ZigClangFieldDecl *self) {...@@ -2679,6 +2684,10 @@ bool ZigClangFieldDecl_isBitField(const struct ZigClangFieldDecl *self) {
2679 return casted->isBitField();2684 return casted->isBitField();
2680}2685}
26812686
2687bool ZigClangFieldDecl_isAnonymousStructOrUnion(const ZigClangFieldDecl *field_decl) {
2688 return reinterpret_cast<const clang::FieldDecl*>(field_decl)->isAnonymousStructOrUnion();
2689}
2690
2682ZigClangSourceLocation ZigClangFieldDecl_getLocation(const struct ZigClangFieldDecl *self) {2691ZigClangSourceLocation ZigClangFieldDecl_getLocation(const struct ZigClangFieldDecl *self) {
2683 auto casted = reinterpret_cast<const clang::FieldDecl *>(self);2692 auto casted = reinterpret_cast<const clang::FieldDecl *>(self);
2684 return bitcast(casted->getLocation());2693 return bitcast(casted->getLocation());
src/zig_clang.h+2
...@@ -855,6 +855,7 @@ ZIG_EXTERN_C const struct ZigClangEnumDecl *ZigClangEnumType_getDecl(const struc...@@ -855,6 +855,7 @@ ZIG_EXTERN_C const struct ZigClangEnumDecl *ZigClangEnumType_getDecl(const struc
855855
856ZIG_EXTERN_C const struct ZigClangTagDecl *ZigClangRecordDecl_getCanonicalDecl(const struct ZigClangRecordDecl *record_decl);856ZIG_EXTERN_C const struct ZigClangTagDecl *ZigClangRecordDecl_getCanonicalDecl(const struct ZigClangRecordDecl *record_decl);
857ZIG_EXTERN_C const struct ZigClangTagDecl *ZigClangEnumDecl_getCanonicalDecl(const struct ZigClangEnumDecl *);857ZIG_EXTERN_C const struct ZigClangTagDecl *ZigClangEnumDecl_getCanonicalDecl(const struct ZigClangEnumDecl *);
858ZIG_EXTERN_C const struct ZigClangFieldDecl *ZigClangFieldDecl_getCanonicalDecl(const ZigClangFieldDecl *);
858ZIG_EXTERN_C const struct ZigClangTypedefNameDecl *ZigClangTypedefNameDecl_getCanonicalDecl(const struct ZigClangTypedefNameDecl *);859ZIG_EXTERN_C const struct ZigClangTypedefNameDecl *ZigClangTypedefNameDecl_getCanonicalDecl(const struct ZigClangTypedefNameDecl *);
859ZIG_EXTERN_C const struct ZigClangFunctionDecl *ZigClangFunctionDecl_getCanonicalDecl(const ZigClangFunctionDecl *self);860ZIG_EXTERN_C const struct ZigClangFunctionDecl *ZigClangFunctionDecl_getCanonicalDecl(const ZigClangFunctionDecl *self);
860ZIG_EXTERN_C const struct ZigClangVarDecl *ZigClangVarDecl_getCanonicalDecl(const ZigClangVarDecl *self);861ZIG_EXTERN_C const struct ZigClangVarDecl *ZigClangVarDecl_getCanonicalDecl(const ZigClangVarDecl *self);
...@@ -1118,6 +1119,7 @@ ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangMacroDefinitionRecord_getSour...@@ -1118,6 +1119,7 @@ ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangMacroDefinitionRecord_getSour
1118ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangMacroDefinitionRecord_getSourceRange_getEnd(const struct ZigClangMacroDefinitionRecord *);1119ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangMacroDefinitionRecord_getSourceRange_getEnd(const struct ZigClangMacroDefinitionRecord *);
11191120
1120ZIG_EXTERN_C bool ZigClangFieldDecl_isBitField(const struct ZigClangFieldDecl *);1121ZIG_EXTERN_C bool ZigClangFieldDecl_isBitField(const struct ZigClangFieldDecl *);
1122ZIG_EXTERN_C bool ZigClangFieldDecl_isAnonymousStructOrUnion(const ZigClangFieldDecl *);
1121ZIG_EXTERN_C struct ZigClangQualType ZigClangFieldDecl_getType(const struct ZigClangFieldDecl *);1123ZIG_EXTERN_C struct ZigClangQualType ZigClangFieldDecl_getType(const struct ZigClangFieldDecl *);
1122ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangFieldDecl_getLocation(const struct ZigClangFieldDecl *);1124ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangFieldDecl_getLocation(const struct ZigClangFieldDecl *);
11231125
test/run_translated_c.zig+14
...@@ -39,4 +39,18 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {...@@ -39,4 +39,18 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
39 \\ return 0;39 \\ return 0;
40 \\}40 \\}
41 , "");41 , "");
42
43 cases.add("anonymous struct & unions",
44 \\#include <stdlib.h>
45 \\#include <stdint.h>
46 \\static struct { struct { uint16_t x, y; }; } x = { 1 };
47 \\static struct { union { uint32_t x; uint8_t y; }; } y = { 0x55AA55AA };
48 \\int main(int argc, char **argv) {
49 \\ if (x.x != 1) abort();
50 \\ if (x.y != 0) abort();
51 \\ if (y.x != 0x55AA55AA) abort();
52 \\ if (y.y != 0xAA) abort();
53 \\ return 0;
54 \\}
55 , "");
42}56}
test/translate_c.zig+45-15
...@@ -8,6 +8,32 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -8,6 +8,32 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
8 \\pub const VAL = 0xF00D;8 \\pub const VAL = 0xF00D;
9 });9 });
1010
11 cases.add("anonymous struct & unions",
12 \\typedef struct {
13 \\ union {
14 \\ char x;
15 \\ struct { int y; };
16 \\ };
17 \\} outer;
18 \\void foo(outer *x) { x->y = x->x; }
19 , &[_][]const u8{
20 \\const struct_unnamed_5 = extern struct {
21 \\ y: c_int,
22 \\};
23 \\const union_unnamed_3 = extern union {
24 \\ x: u8,
25 \\ unnamed_4: struct_unnamed_5,
26 \\};
27 \\const struct_unnamed_1 = extern struct {
28 \\ unnamed_2: union_unnamed_3,
29 \\};
30 \\pub const outer = struct_unnamed_1;
31 \\pub export fn foo(arg_x: [*c]outer) void {
32 \\ var x = arg_x;
33 \\ x.*.unnamed_2.unnamed_4.y = @bitCast(c_int, @as(c_uint, x.*.unnamed_2.x));
34 \\}
35 });
36
11 cases.add("union initializer",37 cases.add("union initializer",
12 \\union { int x; char c[4]; }38 \\union { int x; char c[4]; }
13 \\ ua = {1},39 \\ ua = {1},
...@@ -1445,21 +1471,25 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1445,21 +1471,25 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1445 \\}1471 \\}
1446 });1472 });
14471473
1448 cases.add("type referenced struct",1474 if (builtin.os != .windows) {
1449 \\struct Foo {1475 // When clang uses the <arch>-windows-none triple it behaves as MSVC and
1450 \\ struct Bar{1476 // interprets the inner `struct Bar` as an anonymous structure
1451 \\ int b;1477 cases.add("type referenced struct",
1452 \\ };1478 \\struct Foo {
1453 \\ struct Bar c;1479 \\ struct Bar{
1454 \\};1480 \\ int b;
1455 , &[_][]const u8{1481 \\ };
1456 \\pub const struct_Bar = extern struct {1482 \\ struct Bar c;
1457 \\ b: c_int,1483 \\};
1458 \\};1484 , &[_][]const u8{
1459 \\pub const struct_Foo = extern struct {1485 \\pub const struct_Bar = extern struct {
1460 \\ c: struct_Bar,1486 \\ b: c_int,
1461 \\};1487 \\};
1462 });1488 \\pub const struct_Foo = extern struct {
1489 \\ c: struct_Bar,
1490 \\};
1491 });
1492 }
14631493
1464 cases.add("undefined array global",1494 cases.add("undefined array global",
1465 \\int array[100] = {};1495 \\int array[100] = {};