authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-28 21:38:01-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-28 21:38:01-07:00
logc3516b80044732e18eedcd8cd49c424fec497bb3
treed629ea5cf6440c2f98434bffcd706f93799da4ae
parenta5c2de5fee67e35c8173b7051675d49648086cbb

parseh handles self referential structs and fn pointers


3 files changed, 80 insertions(+), 19 deletions(-)

src/ast_render.cpp+6-4
...@@ -509,7 +509,8 @@ static void render_node(AstRender *ar, AstNode *node) {...@@ -509,7 +509,8 @@ static void render_node(AstRender *ar, AstNode *node) {
509509
510 if (child->type == NodeTypeImport ||510 if (child->type == NodeTypeImport ||
511 child->type == NodeTypeVariableDeclaration ||511 child->type == NodeTypeVariableDeclaration ||
512 child->type == NodeTypeErrorValueDecl)512 child->type == NodeTypeErrorValueDecl ||
513 child->type == NodeTypeFnProto)
513 {514 {
514 fprintf(ar->f, ";");515 fprintf(ar->f, ";");
515 }516 }
...@@ -530,8 +531,10 @@ static void render_node(AstRender *ar, AstNode *node) {...@@ -530,8 +531,10 @@ static void render_node(AstRender *ar, AstNode *node) {
530 AstNode *param_decl = node->data.fn_proto.params.at(arg_i);531 AstNode *param_decl = node->data.fn_proto.params.at(arg_i);
531 assert(param_decl->type == NodeTypeParamDecl);532 assert(param_decl->type == NodeTypeParamDecl);
532 const char *arg_name = buf_ptr(&param_decl->data.param_decl.name);533 const char *arg_name = buf_ptr(&param_decl->data.param_decl.name);
533 const char *noalias_str = param_decl->data.param_decl.is_noalias ? "noalias " : "";534 if (buf_len(&param_decl->data.param_decl.name) > 0) {
534 fprintf(ar->f, "%s%s: ", noalias_str, arg_name);535 const char *noalias_str = param_decl->data.param_decl.is_noalias ? "noalias " : "";
536 fprintf(ar->f, "%s%s: ", noalias_str, arg_name);
537 }
535 render_node(ar, param_decl->data.param_decl.type);538 render_node(ar, param_decl->data.param_decl.type);
536539
537 if (arg_i + 1 < arg_count || is_var_args) {540 if (arg_i + 1 < arg_count || is_var_args) {
...@@ -548,7 +551,6 @@ static void render_node(AstRender *ar, AstNode *node) {...@@ -548,7 +551,6 @@ static void render_node(AstRender *ar, AstNode *node) {
548 fprintf(ar->f, " -> ");551 fprintf(ar->f, " -> ");
549 render_node(ar, return_type_node);552 render_node(ar, return_type_node);
550 }553 }
551 fprintf(ar->f, ";");
552 break;554 break;
553 }555 }
554 case NodeTypeFnDef:556 case NodeTypeFnDef:
src/parseh.cpp+65-15
...@@ -121,6 +121,17 @@ static AstNode *create_struct_field_node(Context *c, const char *name, AstNode *...@@ -121,6 +121,17 @@ static AstNode *create_struct_field_node(Context *c, const char *name, AstNode *
121 return node;121 return node;
122}122}
123123
124static AstNode *create_param_decl_node(Context *c, const char *name, AstNode *type_node, bool is_noalias) {
125 assert(type_node);
126 AstNode *node = create_node(c, NodeTypeParamDecl);
127 buf_init_from_str(&node->data.param_decl.name, name);
128 node->data.param_decl.type = type_node;
129 node->data.param_decl.is_noalias = is_noalias;
130
131 normalize_parent_ptrs(node);
132 return node;
133}
134
124static AstNode *create_num_lit_unsigned(Context *c, uint64_t x) {135static AstNode *create_num_lit_unsigned(Context *c, uint64_t x) {
125 AstNode *node = create_node(c, NodeTypeNumberLiteral);136 AstNode *node = create_node(c, NodeTypeNumberLiteral);
126 node->data.number_literal.kind = NumLitUInt;137 node->data.number_literal.kind = NumLitUInt;
...@@ -255,6 +266,12 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,...@@ -255,6 +266,12 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,
255 const PointerType *pointer_ty = static_cast<const PointerType*>(ty);266 const PointerType *pointer_ty = static_cast<const PointerType*>(ty);
256 QualType child_qt = pointer_ty->getPointeeType();267 QualType child_qt = pointer_ty->getPointeeType();
257 AstNode *type_node = make_qual_type_node(c, child_qt, decl);268 AstNode *type_node = make_qual_type_node(c, child_qt, decl);
269 if (child_qt.getTypePtr()->getTypeClass() == Type::Paren) {
270 const ParenType *paren_type = static_cast<const ParenType *>(child_qt.getTypePtr());
271 if (paren_type->getInnerType()->getTypeClass() == Type::FunctionProto) {
272 return create_prefix_node(c, PrefixOpMaybe, type_node);
273 }
274 }
258 return pointer_to_type(c, type_node, child_qt.isConstQualified());275 return pointer_to_type(c, type_node, child_qt.isConstQualified());
259 }276 }
260 case Type::Typedef:277 case Type::Typedef:
...@@ -311,8 +328,32 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,...@@ -311,8 +328,32 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,
311 }328 }
312 }329 }
313 case Type::FunctionProto:330 case Type::FunctionProto:
314 emit_warning(c, decl, "ignoring function type");331 {
315 return nullptr;332 const FunctionProtoType *fn_proto_ty = static_cast<const FunctionProtoType*>(ty);
333 AstNode *node = create_node(c, NodeTypeFnProto);
334 buf_resize(&node->data.fn_proto.name, 0);
335 node->data.fn_proto.is_extern = true;
336 node->data.fn_proto.is_var_args = fn_proto_ty->isVariadic();
337 node->data.fn_proto.return_type = make_qual_type_node(c, fn_proto_ty->getReturnType(), decl);
338
339 if (!node->data.fn_proto.return_type) {
340 return nullptr;
341 }
342
343 int arg_count = fn_proto_ty->getNumParams();
344 for (int i = 0; i < arg_count; i += 1) {
345 QualType qt = fn_proto_ty->getParamType(i);
346 bool is_noalias = qt.isRestrictQualified();
347 AstNode *type_node = make_qual_type_node(c, qt, decl);
348 if (!type_node) {
349 return nullptr;
350 }
351 node->data.fn_proto.params.append(create_param_decl_node(c, "", type_node, is_noalias));
352 }
353
354 normalize_parent_ptrs(node);
355 return node;
356 }
316 case Type::Record:357 case Type::Record:
317 {358 {
318 const RecordType *record_ty = static_cast<const RecordType*>(ty);359 const RecordType *record_ty = static_cast<const RecordType*>(ty);
...@@ -356,6 +397,11 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,...@@ -356,6 +397,11 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,
356 uint64_t size = const_arr_ty->getSize().getLimitedValue();397 uint64_t size = const_arr_ty->getSize().getLimitedValue();
357 return create_array_type_node(c, child_type_node, size, false);398 return create_array_type_node(c, child_type_node, size, false);
358 }399 }
400 case Type::Paren:
401 {
402 const ParenType *paren_ty = static_cast<const ParenType *>(ty);
403 return make_qual_type_node(c, paren_ty->getInnerType(), decl);
404 }
359 case Type::BlockPointer:405 case Type::BlockPointer:
360 case Type::LValueReference:406 case Type::LValueReference:
361 case Type::RValueReference:407 case Type::RValueReference:
...@@ -368,7 +414,6 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,...@@ -368,7 +414,6 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,
368 case Type::ExtVector:414 case Type::ExtVector:
369 case Type::FunctionNoProto:415 case Type::FunctionNoProto:
370 case Type::UnresolvedUsing:416 case Type::UnresolvedUsing:
371 case Type::Paren:
372 case Type::Adjusted:417 case Type::Adjusted:
373 case Type::Decayed:418 case Type::Decayed:
374 case Type::TypeOfExpr:419 case Type::TypeOfExpr:
...@@ -423,23 +468,19 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {...@@ -423,23 +468,19 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
423 int arg_count = fn_decl->getNumParams();468 int arg_count = fn_decl->getNumParams();
424 for (int i = 0; i < arg_count; i += 1) {469 for (int i = 0; i < arg_count; i += 1) {
425 const ParmVarDecl *param = fn_decl->getParamDecl(i);470 const ParmVarDecl *param = fn_decl->getParamDecl(i);
426 AstNode *param_decl_node = create_node(c, NodeTypeParamDecl);
427 const char *name = decl_name(param);471 const char *name = decl_name(param);
428 if (strlen(name) == 0) {472 if (strlen(name) == 0) {
429 name = buf_ptr(buf_sprintf("arg%d", i));473 name = buf_ptr(buf_sprintf("arg%d", i));
430 }474 }
431 buf_init_from_str(&param_decl_node->data.param_decl.name, name);
432 QualType qt = param->getOriginalType();475 QualType qt = param->getOriginalType();
433 param_decl_node->data.param_decl.is_noalias = qt.isRestrictQualified();476 bool is_noalias = qt.isRestrictQualified();
434 param_decl_node->data.param_decl.type = make_qual_type_node(c, qt, fn_decl);477 AstNode *type_node = make_qual_type_node(c, qt, fn_decl);
435 if (!param_decl_node->data.param_decl.type) {478 if (!type_node) {
436 emit_warning(c, param, "skipping function %s, unresolved param type\n",479 emit_warning(c, param, "skipping function %s, unresolved param type\n", name);
437 buf_ptr(&node->data.fn_proto.name));
438 return;480 return;
439 }481 }
440482
441 normalize_parent_ptrs(param_decl_node);483 node->data.fn_proto.params.append(create_param_decl_node(c, name, type_node, is_noalias));
442 node->data.fn_proto.params.append(param_decl_node);
443 }484 }
444485
445 if (fn_decl->isNoReturn()) {486 if (fn_decl->isNoReturn()) {
...@@ -512,6 +553,11 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) {...@@ -512,6 +553,11 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) {
512 node->data.struct_decl.visib_mod = VisibModExport;553 node->data.struct_decl.visib_mod = VisibModExport;
513 node->data.struct_decl.directives = create_empty_directives(c);554 node->data.struct_decl.directives = create_empty_directives(c);
514555
556 // eagerly put the name in the table, but we need to remember to remove it if it fails
557 // boy it would be nice to have defer here wouldn't it
558 c->enum_type_table.put(bare_name, true);
559
560
515 ZigList<AstNode *> var_decls = {0};561 ZigList<AstNode *> var_decls = {0};
516 int i = 0;562 int i = 0;
517 for (auto it = enum_def->enumerator_begin(),563 for (auto it = enum_def->enumerator_begin(),
...@@ -520,6 +566,7 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) {...@@ -520,6 +566,7 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) {
520 {566 {
521 const EnumConstantDecl *enum_const = *it;567 const EnumConstantDecl *enum_const = *it;
522 if (enum_const->getInitExpr()) {568 if (enum_const->getInitExpr()) {
569 c->enum_type_table.remove(bare_name);
523 emit_warning(c, enum_const, "skipping enum %s - has init expression\n", buf_ptr(bare_name));570 emit_warning(c, enum_const, "skipping enum %s - has init expression\n", buf_ptr(bare_name));
524 return;571 return;
525 }572 }
...@@ -549,8 +596,6 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) {...@@ -549,8 +596,6 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) {
549 var_decls.append(var_node);596 var_decls.append(var_node);
550 }597 }
551598
552 c->enum_type_table.put(bare_name, true);
553
554 normalize_parent_ptrs(node);599 normalize_parent_ptrs(node);
555 c->root->data.root.top_level_decls.append(node);600 c->root->data.root.top_level_decls.append(node);
556601
...@@ -594,6 +639,10 @@ static void visit_record_decl(Context *c, const RecordDecl *record_decl) {...@@ -594,6 +639,10 @@ static void visit_record_decl(Context *c, const RecordDecl *record_decl) {
594 node->data.struct_decl.visib_mod = VisibModExport;639 node->data.struct_decl.visib_mod = VisibModExport;
595 node->data.struct_decl.directives = create_empty_directives(c);640 node->data.struct_decl.directives = create_empty_directives(c);
596641
642 // eagerly put the name in the table, but we need to remember to remove it if it fails
643 // boy it would be nice to have defer here wouldn't it
644 c->struct_type_table.put(bare_name, true);
645
597 for (auto it = record_def->field_begin(),646 for (auto it = record_def->field_begin(),
598 it_end = record_def->field_end();647 it_end = record_def->field_end();
599 it != it_end; ++it)648 it != it_end; ++it)
...@@ -601,12 +650,14 @@ static void visit_record_decl(Context *c, const RecordDecl *record_decl) {...@@ -601,12 +650,14 @@ static void visit_record_decl(Context *c, const RecordDecl *record_decl) {
601 const FieldDecl *field_decl = *it;650 const FieldDecl *field_decl = *it;
602651
603 if (field_decl->isBitField()) {652 if (field_decl->isBitField()) {
653 c->struct_type_table.remove(bare_name);
604 emit_warning(c, field_decl, "skipping struct %s - has bitfield\n", buf_ptr(bare_name));654 emit_warning(c, field_decl, "skipping struct %s - has bitfield\n", buf_ptr(bare_name));
605 return;655 return;
606 }656 }
607657
608 AstNode *type_node = make_qual_type_node(c, field_decl->getType(), field_decl);658 AstNode *type_node = make_qual_type_node(c, field_decl->getType(), field_decl);
609 if (!type_node) {659 if (!type_node) {
660 c->struct_type_table.remove(bare_name);
610 emit_warning(c, field_decl, "skipping struct %s - unhandled type\n", buf_ptr(bare_name));661 emit_warning(c, field_decl, "skipping struct %s - unhandled type\n", buf_ptr(bare_name));
611 return;662 return;
612 }663 }
...@@ -615,7 +666,6 @@ static void visit_record_decl(Context *c, const RecordDecl *record_decl) {...@@ -615,7 +666,6 @@ static void visit_record_decl(Context *c, const RecordDecl *record_decl) {
615 node->data.struct_decl.fields.append(field_node);666 node->data.struct_decl.fields.append(field_node);
616 }667 }
617668
618 c->struct_type_table.put(bare_name, true);
619 normalize_parent_ptrs(node);669 normalize_parent_ptrs(node);
620 c->root->data.root.top_level_decls.append(node);670 c->root->data.root.top_level_decls.append(node);
621671
test/run_tests.cpp+9
...@@ -1961,6 +1961,15 @@ pub const Bar = enum_Bar;)OUTPUT");...@@ -1961,6 +1961,15 @@ pub const Bar = enum_Bar;)OUTPUT");
1961 add_parseh_case("constant size array", R"SOURCE(1961 add_parseh_case("constant size array", R"SOURCE(
1962void func(int array[20]);1962void func(int array[20]);
1963 )SOURCE", R"OUTPUT(pub extern fn func(array: [20]c_int);)OUTPUT");1963 )SOURCE", R"OUTPUT(pub extern fn func(array: [20]c_int);)OUTPUT");
1964
1965 add_parseh_case("self referential struct with function pointer", R"SOURCE(
1966struct Foo {
1967 void (*derp)(struct Foo *foo);
1968};
1969 )SOURCE", R"OUTPUT(export struct struct_Foo {
1970 derp: ?extern fn (?&struct_Foo),
1971}
1972pub const Foo = struct_Foo;)OUTPUT");
1964}1973}
19651974
1966static void print_compiler_invocation(TestCase *test_case) {1975static void print_compiler_invocation(TestCase *test_case) {