authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-31 14:53:59-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-31 14:54:28-07:00
logc77637d1720bc80f97c21214596cec9ffc617d12
treedfc8f1dc16d6808a8427ee5ada1334f9cf0e1261
parentc1640a924643d0b3d3616c2a41f70918d6150301

parseh understands forward struct definitions

See #88

2 files changed, 94 insertions(+), 59 deletions(-)

src/parseh.cpp+75-59
......@@ -36,6 +36,7 @@ struct Context {
3636 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> global_type_table;
3737 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> global_value_table;
3838 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> struct_type_table;
39 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> struct_decl_table;
3940 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> enum_type_table;
4041 HashMap<Buf *, bool, buf_hash, buf_eql_buf> fn_table;
4142 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> macro_table;
......@@ -51,6 +52,7 @@ static TypeTableEntry *resolve_qual_type_with_table(Context *c, QualType qt, con
5152 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> *type_table);
5253
5354static TypeTableEntry *resolve_qual_type(Context *c, QualType qt, const Decl *decl);
55static TypeTableEntry *resolve_record_decl(Context *c, const RecordDecl *record_decl);
5456
5557
5658__attribute__ ((format (printf, 3, 4)))
......@@ -79,12 +81,17 @@ static void emit_warning(Context *c, const Decl *decl, const char *format, ...)
7981 fprintf(stderr, "%s:%u:%u: warning: %s\n", buf_ptr(path), line, column, buf_ptr(msg));
8082}
8183
84static uint32_t get_next_node_index(Context *c) {
85 uint32_t result = c->codegen->next_node_index;
86 c->codegen->next_node_index += 1;
87 return result;
88}
89
8290static AstNode *create_node(Context *c, NodeType type) {
8391 AstNode *node = allocate<AstNode>(1);
8492 node->type = type;
8593 node->owner = c->import;
86 node->create_index = c->codegen->next_node_index;
87 c->codegen->next_node_index += 1;
94 node->create_index = get_next_node_index(c);
8895 return node;
8996}
9097
......@@ -437,18 +444,7 @@ static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const
437444 case Type::Record:
438445 {
439446 const RecordType *record_ty = static_cast<const RecordType*>(ty);
440 Buf *record_name = buf_create_from_str(decl_name(record_ty->getDecl()));
441 if (buf_len(record_name) == 0) {
442 emit_warning(c, decl, "unhandled anonymous struct");
443 return c->codegen->builtin_types.entry_invalid;
444 }
445
446 auto entry = type_table->maybe_get(record_name);
447 if (!entry) {
448 return c->codegen->builtin_types.entry_invalid;
449 }
450
451 return entry->value;
447 return resolve_record_decl(c, record_ty->getDecl());
452448 }
453449 case Type::Enum:
454450 {
......@@ -754,47 +750,39 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) {
754750
755751}
756752
757static void visit_record_decl(Context *c, const RecordDecl *record_decl) {
753static TypeTableEntry *resolve_record_decl(Context *c, const RecordDecl *record_decl) {
758754 const char *raw_name = decl_name(record_decl);
759755
760 // we have no interest in top level anonymous structs since they're
761 // not exposing anything.
762 if (record_decl->isAnonymousStructOrUnion() || raw_name[0] == 0) {
763 return;
764 }
765
766756 if (!record_decl->isStruct()) {
767757 emit_warning(c, record_decl, "skipping record %s, not a struct", raw_name);
768 return;
758 return c->codegen->builtin_types.entry_invalid;
769759 }
770760
771 Buf *bare_name = buf_create_from_str(raw_name);
772 Buf *full_type_name = buf_sprintf("struct_%s", buf_ptr(bare_name));
761 Buf *bare_name;
762 if (record_decl->isAnonymousStructOrUnion() || raw_name[0] == 0) {
763 bare_name = buf_sprintf("anon_$%" PRIu32, get_next_node_index(c));
764 } else {
765 bare_name = buf_create_from_str(raw_name);
773766
774 if (c->struct_type_table.maybe_get(bare_name)) {
775 // we've already seen it
776 return;
767 auto existing_entry = c->struct_type_table.maybe_get(bare_name);
768 if (existing_entry) {
769 return existing_entry->value;
770 }
777771 }
778772
779 RecordDecl *record_def = record_decl->getDefinition();
780 if (!record_def) {
781 TypeTableEntry *typedecl_type = get_typedecl_type(c->codegen, buf_ptr(full_type_name),
782 c->codegen->builtin_types.entry_u8);
783 c->struct_type_table.put(bare_name, typedecl_type);
773 Buf *full_type_name = buf_sprintf("struct_%s", buf_ptr(bare_name));
784774
785 // this is a type that we can point to but that's it, such as `struct Foo;`.
786 add_typedef_node(c, typedecl_type);
787 add_alias(c, buf_ptr(bare_name), buf_ptr(full_type_name));
788 return;
789 }
790775
791776 TypeTableEntry *struct_type = get_partial_container_type(c->codegen, c->import,
792777 ContainerKindStruct, c->source_node, buf_ptr(full_type_name));
793778
794779 c->struct_type_table.put(bare_name, struct_type);
795 // make an alias without the "struct_" prefix. this will get emitted at the
796 // end if it doesn't conflict with anything else
797 add_alias(c, buf_ptr(bare_name), buf_ptr(full_type_name));
780
781 RecordDecl *record_def = record_decl->getDefinition();
782 if (!record_def) {
783 return struct_type;
784 }
785
798786
799787 // count fields and validate
800788 uint32_t field_count = 0;
......@@ -805,8 +793,8 @@ static void visit_record_decl(Context *c, const RecordDecl *record_decl) {
805793 const FieldDecl *field_decl = *it;
806794
807795 if (field_decl->isBitField()) {
808 emit_warning(c, field_decl, "skipping struct %s - has bitfield\n", buf_ptr(bare_name));
809 return;
796 emit_warning(c, field_decl, "struct %s demoted to typedef - has bitfield\n", buf_ptr(bare_name));
797 return struct_type;
810798 }
811799 }
812800
......@@ -837,8 +825,8 @@ static void visit_record_decl(Context *c, const RecordDecl *record_decl) {
837825 type_struct_field->type_entry = resolve_qual_type(c, field_decl->getType(), field_decl);
838826
839827 if (type_struct_field->type_entry->id == TypeTableEntryIdInvalid) {
840 emit_warning(c, field_decl, "skipping struct %s - unresolved type\n", buf_ptr(bare_name));
841 return;
828 emit_warning(c, field_decl, "struct %s demoted to typedef - unresolved type\n", buf_ptr(bare_name));
829 return struct_type;
842830 }
843831
844832 di_element_types[i] = LLVMZigCreateDebugMemberType(c->codegen->dbuilder,
......@@ -878,25 +866,52 @@ static void visit_record_decl(Context *c, const RecordDecl *record_decl) {
878866 LLVMZigReplaceTemporary(c->codegen->dbuilder, struct_type->di_type, replacement_di_type);
879867 struct_type->di_type = replacement_di_type;
880868
881 //////
869 return struct_type;
870}
882871
883 // now create a top level decl node for the type
884 AstNode *struct_node = create_node(c, NodeTypeStructDecl);
885 buf_init_from_buf(&struct_node->data.struct_decl.name, full_type_name);
886 struct_node->data.struct_decl.kind = ContainerKindStruct;
887 struct_node->data.struct_decl.visib_mod = VisibModExport;
888 struct_node->data.struct_decl.directives = create_empty_directives(c);
889 struct_node->data.struct_decl.type_entry = struct_type;
872static void visit_record_decl(Context *c, const RecordDecl *record_decl) {
873 TypeTableEntry *struct_type = resolve_record_decl(c, record_decl);
890874
891 for (uint32_t i = 0; i < field_count; i += 1) {
892 TypeStructField *type_struct_field = &struct_type->data.structure.fields[i];
893 AstNode *type_node = make_type_node(c, type_struct_field->type_entry);
894 AstNode *field_node = create_struct_field_node(c, buf_ptr(type_struct_field->name), type_node);
895 struct_node->data.struct_decl.fields.append(field_node);
875 if (struct_type->id == TypeTableEntryIdInvalid) {
876 return;
877 }
878
879 assert(struct_type->id == TypeTableEntryIdStruct);
880
881 if (c->struct_decl_table.maybe_get(&struct_type->name)) {
882 return;
883 }
884 c->struct_decl_table.put(&struct_type->name, struct_type);
885
886 // make an alias without the "struct_" prefix. this will get emitted at the
887 // end if it doesn't conflict with anything else
888 if (decl_name(record_decl)[0] != 0) {
889 add_alias(c, decl_name(record_decl), buf_ptr(&struct_type->name));
896890 }
897891
898 normalize_parent_ptrs(struct_node);
899 c->root->data.root.top_level_decls.append(struct_node);
892 if (struct_type->data.structure.complete) {
893 // now create a top level decl node for the type
894 AstNode *struct_node = create_node(c, NodeTypeStructDecl);
895 buf_init_from_buf(&struct_node->data.struct_decl.name, &struct_type->name);
896 struct_node->data.struct_decl.kind = ContainerKindStruct;
897 struct_node->data.struct_decl.visib_mod = VisibModExport;
898 struct_node->data.struct_decl.directives = create_empty_directives(c);
899 struct_node->data.struct_decl.type_entry = struct_type;
900
901 for (uint32_t i = 0; i < struct_type->data.structure.src_field_count; i += 1) {
902 TypeStructField *type_struct_field = &struct_type->data.structure.fields[i];
903 AstNode *type_node = make_type_node(c, type_struct_field->type_entry);
904 AstNode *field_node = create_struct_field_node(c, buf_ptr(type_struct_field->name), type_node);
905 struct_node->data.struct_decl.fields.append(field_node);
906 }
907
908 normalize_parent_ptrs(struct_node);
909 c->root->data.root.top_level_decls.append(struct_node);
910 } else {
911 TypeTableEntry *typedecl_type = get_typedecl_type(c->codegen, buf_ptr(&struct_type->name),
912 c->codegen->builtin_types.entry_u8);
913 add_typedef_node(c, typedecl_type);
914 }
900915}
901916
902917static void visit_var_decl(Context *c, const VarDecl *var_decl) {
......@@ -1253,6 +1268,7 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const ch
12531268 c->global_value_table.init(8);
12541269 c->enum_type_table.init(8);
12551270 c->struct_type_table.init(8);
1271 c->struct_decl_table.init(8);
12561272 c->fn_table.init(8);
12571273 c->macro_table.init(8);
12581274 c->codegen = codegen;
test/run_tests.cpp+19
......@@ -2019,6 +2019,25 @@ static const int int_var = 13;
20192019 )SOURCE", 2,
20202020 "pub extern var extern_var: c_int;",
20212021 "pub const int_var: c_int = 13;");
2022
2023
2024 add_parseh_case("circular struct definitions", R"SOURCE(
2025struct Bar;
2026
2027struct Foo {
2028 struct Bar *next;
2029};
2030
2031struct Bar {
2032 struct Foo *next;
2033};
2034 )SOURCE", 2,
2035 R"SOURCE(export struct struct_Bar {
2036 next: ?&struct_Foo,
2037})SOURCE",
2038 R"SOURCE(export struct struct_Foo {
2039 next: ?&struct_Bar,
2040})SOURCE");
20222041}
20232042
20242043static void print_compiler_invocation(TestCase *test_case) {