authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-05-02 16:56:47-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2018-05-02 16:56:47-04:00
log6f002e724bb4571ff31949a36f2e634e522eb42b
tree951898110c02048ec6c174b402df14624699c68a
parent86a428a4a52172df5e49436212e9f769248e0b15
parent1a9403f38a89d4a55f746d077d725424b8852d44
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #975 from zig-lang/none-pure-enums

Added better support for none pure enums in translate-c

3 files changed, 62 insertions(+), 70 deletions(-)

src/ast_render.cpp+1-1
...@@ -728,7 +728,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {...@@ -728,7 +728,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
728 render_node_grouped(ar, field_node->data.struct_field.type);728 render_node_grouped(ar, field_node->data.struct_field.type);
729 }729 }
730 if (field_node->data.struct_field.value != nullptr) {730 if (field_node->data.struct_field.value != nullptr) {
731 fprintf(ar->f, "= ");731 fprintf(ar->f, " = ");
732 render_node_grouped(ar, field_node->data.struct_field.value);732 render_node_grouped(ar, field_node->data.struct_field.value);
733 }733 }
734 fprintf(ar->f, ",\n");734 fprintf(ar->f, ",\n");
src/translate_c.cpp+39-69
...@@ -3744,6 +3744,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {...@@ -3744,6 +3744,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
3744 return demote_enum_to_opaque(c, enum_decl, full_type_name, bare_name);3744 return demote_enum_to_opaque(c, enum_decl, full_type_name, bare_name);
3745 }3745 }
37463746
3747
3747 bool pure_enum = true;3748 bool pure_enum = true;
3748 uint32_t field_count = 0;3749 uint32_t field_count = 0;
3749 for (auto it = enum_def->enumerator_begin(),3750 for (auto it = enum_def->enumerator_begin(),
...@@ -3755,84 +3756,53 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {...@@ -3755,84 +3756,53 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
3755 pure_enum = false;3756 pure_enum = false;
3756 }3757 }
3757 }3758 }
3758
3759 AstNode *tag_int_type = trans_qual_type(c, enum_decl->getIntegerType(), enum_decl->getLocation());3759 AstNode *tag_int_type = trans_qual_type(c, enum_decl->getIntegerType(), enum_decl->getLocation());
3760 assert(tag_int_type);3760 assert(tag_int_type);
37613761
3762 if (pure_enum) {3762 AstNode *enum_node = trans_create_node(c, NodeTypeContainerDecl);
3763 AstNode *enum_node = trans_create_node(c, NodeTypeContainerDecl);3763 enum_node->data.container_decl.kind = ContainerKindEnum;
3764 enum_node->data.container_decl.kind = ContainerKindEnum;3764 enum_node->data.container_decl.layout = ContainerLayoutExtern;
3765 enum_node->data.container_decl.layout = ContainerLayoutExtern;3765 // TODO only emit this tag type if the enum tag type is not the default.
3766 // TODO only emit this tag type if the enum tag type is not the default.3766 // I don't know what the default is, need to figure out how clang is deciding.
3767 // I don't know what the default is, need to figure out how clang is deciding.3767 // it appears to at least be different across gcc/msvc
3768 // it appears to at least be different across gcc/msvc3768 if (!c_is_builtin_type(c, enum_decl->getIntegerType(), BuiltinType::UInt) &&
3769 if (!c_is_builtin_type(c, enum_decl->getIntegerType(), BuiltinType::UInt) &&3769 !c_is_builtin_type(c, enum_decl->getIntegerType(), BuiltinType::Int))
3770 !c_is_builtin_type(c, enum_decl->getIntegerType(), BuiltinType::Int))3770 {
3771 {3771 enum_node->data.container_decl.init_arg_expr = tag_int_type;
3772 enum_node->data.container_decl.init_arg_expr = tag_int_type;
3773 }
3774
3775 enum_node->data.container_decl.fields.resize(field_count);
3776 uint32_t i = 0;
3777 for (auto it = enum_def->enumerator_begin(),
3778 it_end = enum_def->enumerator_end();
3779 it != it_end; ++it, i += 1)
3780 {
3781 const EnumConstantDecl *enum_const = *it;
3782
3783 Buf *enum_val_name = buf_create_from_str(decl_name(enum_const));
3784 Buf *field_name;
3785 if (bare_name != nullptr && buf_starts_with_buf(enum_val_name, bare_name)) {
3786 field_name = buf_slice(enum_val_name, buf_len(bare_name), buf_len(enum_val_name));
3787 } else {
3788 field_name = enum_val_name;
3789 }
3790
3791 AstNode *field_node = trans_create_node(c, NodeTypeStructField);
3792 field_node->data.struct_field.name = field_name;
3793 field_node->data.struct_field.type = nullptr;
3794 enum_node->data.container_decl.fields.items[i] = field_node;
3795
3796 // in C each enum value is in the global namespace. so we put them there too.
3797 // at this point we can rely on the enum emitting successfully
3798 if (is_anonymous) {
3799 AstNode *lit_node = trans_create_node_unsigned(c, i);
3800 add_global_var(c, enum_val_name, lit_node);
3801 } else {
3802 AstNode *field_access_node = trans_create_node_field_access(c,
3803 trans_create_node_symbol(c, full_type_name), field_name);
3804 add_global_var(c, enum_val_name, field_access_node);
3805 }
3806 }
3807
3808 if (is_anonymous) {
3809 c->decl_table.put(enum_decl->getCanonicalDecl(), enum_node);
3810 return enum_node;
3811 } else {
3812 AstNode *symbol_node = trans_create_node_symbol(c, full_type_name);
3813 add_global_weak_alias(c, bare_name, full_type_name);
3814 add_global_var(c, full_type_name, enum_node);
3815 c->decl_table.put(enum_decl->getCanonicalDecl(), symbol_node);
3816 return enum_node;
3817 }
3818 }3772 }
38193773 enum_node->data.container_decl.fields.resize(field_count);
3820 // TODO after issue #305 is solved, make this be an enum with tag_int_type3774 uint32_t i = 0;
3821 // as the integer type and set the custom enum values
3822 AstNode *enum_node = tag_int_type;
3823
3824
3825 // add variables for all the values with enum_node
3826 for (auto it = enum_def->enumerator_begin(),3775 for (auto it = enum_def->enumerator_begin(),
3827 it_end = enum_def->enumerator_end();3776 it_end = enum_def->enumerator_end();
3828 it != it_end; ++it)3777 it != it_end; ++it, i += 1)
3829 {3778 {
3830 const EnumConstantDecl *enum_const = *it;3779 const EnumConstantDecl *enum_const = *it;
38313780
3832 Buf *enum_val_name = buf_create_from_str(decl_name(enum_const));3781 Buf *enum_val_name = buf_create_from_str(decl_name(enum_const));
3833 AstNode *int_node = trans_create_node_apint(c, enum_const->getInitVal());3782 Buf *field_name;
3834 AstNode *var_node = add_global_var(c, enum_val_name, int_node);3783 if (bare_name != nullptr && buf_starts_with_buf(enum_val_name, bare_name)) {
3835 var_node->data.variable_declaration.type = tag_int_type;3784 field_name = buf_slice(enum_val_name, buf_len(bare_name), buf_len(enum_val_name));
3785 } else {
3786 field_name = enum_val_name;
3787 }
3788
3789 AstNode *int_node = pure_enum && !is_anonymous ? nullptr : trans_create_node_apint(c, enum_const->getInitVal());
3790 AstNode *field_node = trans_create_node(c, NodeTypeStructField);
3791 field_node->data.struct_field.name = field_name;
3792 field_node->data.struct_field.type = nullptr;
3793 field_node->data.struct_field.value = int_node;
3794 enum_node->data.container_decl.fields.items[i] = field_node;
3795
3796 // in C each enum value is in the global namespace. so we put them there too.
3797 // at this point we can rely on the enum emitting successfully
3798 if (is_anonymous) {
3799 Buf *enum_val_name = buf_create_from_str(decl_name(enum_const));
3800 add_global_var(c, enum_val_name, int_node);
3801 } else {
3802 AstNode *field_access_node = trans_create_node_field_access(c,
3803 trans_create_node_symbol(c, full_type_name), field_name);
3804 add_global_var(c, enum_val_name, field_access_node);
3805 }
3836 }3806 }
38373807
3838 if (is_anonymous) {3808 if (is_anonymous) {
...@@ -3843,7 +3813,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {...@@ -3843,7 +3813,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
3843 add_global_weak_alias(c, bare_name, full_type_name);3813 add_global_weak_alias(c, bare_name, full_type_name);
3844 add_global_var(c, full_type_name, enum_node);3814 add_global_var(c, full_type_name, enum_node);
3845 c->decl_table.put(enum_decl->getCanonicalDecl(), symbol_node);3815 c->decl_table.put(enum_decl->getCanonicalDecl(), symbol_node);
3846 return symbol_node;3816 return enum_node;
3847 }3817 }
3848}3818}
38493819
test/translate_c.zig+22
...@@ -53,6 +53,28 @@ pub fn addCases(cases: &tests.TranslateCContext) void {...@@ -53,6 +53,28 @@ pub fn addCases(cases: &tests.TranslateCContext) void {
53 \\pub const Foo = enum_Foo;53 \\pub const Foo = enum_Foo;
54 );54 );
5555
56 cases.add("enums",
57 \\enum Foo {
58 \\ FooA = 2,
59 \\ FooB = 5,
60 \\ Foo1,
61 \\};
62 ,
63 \\pub const enum_Foo = extern enum {
64 \\ A = 2,
65 \\ B = 5,
66 \\ @"1" = 6,
67 \\};
68 ,
69 \\pub const FooA = enum_Foo.A;
70 ,
71 \\pub const FooB = enum_Foo.B;
72 ,
73 \\pub const Foo1 = enum_Foo.@"1";
74 ,
75 \\pub const Foo = enum_Foo;
76 );
77
56 cases.add("restrict -> noalias",78 cases.add("restrict -> noalias",
57 \\void foo(void *restrict bar, void *restrict);79 \\void foo(void *restrict bar, void *restrict);
58 ,80 ,