| ... | @@ -105,6 +105,18 @@ static AstNode *create_prefix_node(Context *c, PrefixOp op, AstNode *child_node) | ... | @@ -105,6 +105,18 @@ static AstNode *create_prefix_node(Context *c, PrefixOp op, AstNode *child_node) |
| 105 | return node; | 105 | return node; |
| 106 | } | 106 | } |
| 107 | | 107 | |
| | 108 | static AstNode *create_struct_field_node(Context *c, const char *name, AstNode *type_node) { |
| | 109 | assert(type_node); |
| | 110 | AstNode *node = create_node(c, NodeTypeStructField); |
| | 111 | buf_init_from_str(&node->data.struct_field.name, name); |
| | 112 | node->data.struct_field.directives = create_empty_directives(c); |
| | 113 | node->data.struct_field.visib_mod = VisibModPub; |
| | 114 | node->data.struct_field.type = type_node; |
| | 115 | |
| | 116 | normalize_parent_ptrs(node); |
| | 117 | return node; |
| | 118 | } |
| | 119 | |
| 108 | static const char *decl_name(const Decl *decl) { | 120 | static const char *decl_name(const Decl *decl) { |
| 109 | const NamedDecl *named_decl = static_cast<const NamedDecl *>(decl); | 121 | const NamedDecl *named_decl = static_cast<const NamedDecl *>(decl); |
| 110 | return (const char *)named_decl->getName().bytes_begin(); | 122 | return (const char *)named_decl->getName().bytes_begin(); |
| ... | @@ -386,6 +398,11 @@ static void visit_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl) | ... | @@ -386,6 +398,11 @@ static void visit_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl) |
| 386 | add_typedef_node(c, type_name, make_qual_type_node(c, child_qt, typedef_decl)); | 398 | add_typedef_node(c, type_name, make_qual_type_node(c, child_qt, typedef_decl)); |
| 387 | } | 399 | } |
| 388 | | 400 | |
| | 401 | static void add_alias(Context *c, const char *new_name, const char *target_name) { |
| | 402 | AstNode *alias_node = create_var_decl_node(c, new_name, create_symbol_node(c, target_name)); |
| | 403 | c->aliases.append(alias_node); |
| | 404 | } |
| | 405 | |
| 389 | static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) { | 406 | static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) { |
| 390 | Buf bare_name = BUF_INIT; | 407 | Buf bare_name = BUF_INIT; |
| 391 | buf_init_from_str(&bare_name, decl_name(enum_decl)); | 408 | buf_init_from_str(&bare_name, decl_name(enum_decl)); |
| ... | @@ -403,9 +420,7 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) { | ... | @@ -403,9 +420,7 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) { |
| 403 | if (!enum_def) { | 420 | if (!enum_def) { |
| 404 | // this is a type that we can point to but that's it, same as `struct Foo;`. | 421 | // this is a type that we can point to but that's it, same as `struct Foo;`. |
| 405 | add_typedef_node(c, type_name, create_symbol_node(c, "u8")); | 422 | add_typedef_node(c, type_name, create_symbol_node(c, "u8")); |
| 406 | AstNode *alias_node = create_var_decl_node(c, buf_ptr(&bare_name), | 423 | add_alias(c, buf_ptr(&bare_name), buf_ptr(type_name)); |
| 407 | create_symbol_node(c, buf_ptr(type_name))); | | |
| 408 | c->aliases.append(alias_node); | | |
| 409 | return; | 424 | return; |
| 410 | } | 425 | } |
| 411 | | 426 | |
| ... | @@ -427,32 +442,29 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) { | ... | @@ -427,32 +442,29 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) { |
| 427 | emit_warning(c, enum_const, "skipping enum %s - has init expression\n", buf_ptr(type_name)); | 442 | emit_warning(c, enum_const, "skipping enum %s - has init expression\n", buf_ptr(type_name)); |
| 428 | return; | 443 | return; |
| 429 | } | 444 | } |
| 430 | AstNode *field_node = create_node(c, NodeTypeStructField); | | |
| 431 | Buf enum_val_name = BUF_INIT; | 445 | Buf enum_val_name = BUF_INIT; |
| 432 | buf_init_from_str(&enum_val_name, decl_name(enum_const)); | 446 | buf_init_from_str(&enum_val_name, decl_name(enum_const)); |
| 433 | | 447 | |
| | 448 | Buf field_name = BUF_INIT; |
| | 449 | |
| 434 | if (buf_starts_with_buf(&enum_val_name, &bare_name)) { | 450 | if (buf_starts_with_buf(&enum_val_name, &bare_name)) { |
| 435 | Buf *slice = buf_slice(&enum_val_name, buf_len(&bare_name), buf_len(&enum_val_name)); | 451 | Buf *slice = buf_slice(&enum_val_name, buf_len(&bare_name), buf_len(&enum_val_name)); |
| 436 | if (valid_symbol_starter(buf_ptr(slice)[0])) { | 452 | if (valid_symbol_starter(buf_ptr(slice)[0])) { |
| 437 | buf_init_from_buf(&field_node->data.struct_field.name, slice); | 453 | buf_init_from_buf(&field_name, slice); |
| 438 | } else { | 454 | } else { |
| 439 | buf_resize(&field_node->data.struct_field.name, 0); | 455 | buf_resize(&field_name, 0); |
| 440 | buf_appendf(&field_node->data.struct_field.name, "_%s", buf_ptr(slice)); | 456 | buf_appendf(&field_name, "_%s", buf_ptr(slice)); |
| 441 | } | 457 | } |
| 442 | } else { | 458 | } else { |
| 443 | buf_init_from_buf(&field_node->data.struct_field.name, &enum_val_name); | 459 | buf_init_from_buf(&field_name, &enum_val_name); |
| 444 | } | 460 | } |
| 445 | | 461 | |
| 446 | field_node->data.struct_field.directives = create_empty_directives(c); | 462 | AstNode *field_node = create_struct_field_node(c, buf_ptr(&field_name), create_symbol_node(c, "void")); |
| 447 | field_node->data.struct_field.visib_mod = VisibModPub; | | |
| 448 | field_node->data.struct_field.type = create_symbol_node(c, "void"); | | |
| 449 | | | |
| 450 | normalize_parent_ptrs(field_node); | | |
| 451 | node->data.struct_decl.fields.append(field_node); | 463 | node->data.struct_decl.fields.append(field_node); |
| 452 | | 464 | |
| 453 | // in C each enum value is in the global namespace. so we put them there too. | 465 | // in C each enum value is in the global namespace. so we put them there too. |
| 454 | AstNode *field_access_node = create_field_access_node(c, buf_ptr(type_name), | 466 | AstNode *field_access_node = create_field_access_node(c, buf_ptr(type_name), |
| 455 | buf_ptr(&field_node->data.struct_field.name)); | 467 | buf_ptr(&field_name)); |
| 456 | AstNode *var_node = create_var_decl_node(c, buf_ptr(&enum_val_name), field_access_node); | 468 | AstNode *var_node = create_var_decl_node(c, buf_ptr(&enum_val_name), field_access_node); |
| 457 | var_decls.append(var_node); | 469 | var_decls.append(var_node); |
| 458 | } | 470 | } |
| ... | @@ -469,9 +481,7 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) { | ... | @@ -469,9 +481,7 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) { |
| 469 | | 481 | |
| 470 | // make an alias without the "enum_" prefix. this will get emitted at the | 482 | // make an alias without the "enum_" prefix. this will get emitted at the |
| 471 | // end if it doesn't conflict with anything else | 483 | // end if it doesn't conflict with anything else |
| 472 | AstNode *alias_node = create_var_decl_node(c, buf_ptr(&bare_name), create_symbol_node(c, buf_ptr(type_name))); | 484 | add_alias(c, buf_ptr(&bare_name), buf_ptr(type_name)); |
| 473 | c->aliases.append(alias_node); | | |
| 474 | | | |
| 475 | } | 485 | } |
| 476 | | 486 | |
| 477 | static void visit_record_decl(Context *c, const RecordDecl *record_decl) { | 487 | static void visit_record_decl(Context *c, const RecordDecl *record_decl) { |
| ... | @@ -490,15 +500,15 @@ static void visit_record_decl(Context *c, const RecordDecl *record_decl) { | ... | @@ -490,15 +500,15 @@ static void visit_record_decl(Context *c, const RecordDecl *record_decl) { |
| 490 | if (!record_def) { | 500 | if (!record_def) { |
| 491 | // this is a type that we can point to but that's it, such as `struct Foo;`. | 501 | // this is a type that we can point to but that's it, such as `struct Foo;`. |
| 492 | add_typedef_node(c, type_name, create_symbol_node(c, "u8")); | 502 | add_typedef_node(c, type_name, create_symbol_node(c, "u8")); |
| 493 | AstNode *alias_node = create_var_decl_node(c, buf_ptr(&bare_name), | 503 | add_alias(c, buf_ptr(&bare_name), buf_ptr(type_name)); |
| 494 | create_symbol_node(c, buf_ptr(type_name))); | | |
| 495 | c->aliases.append(alias_node); | | |
| 496 | return; | 504 | return; |
| 497 | } | 505 | } |
| 498 | | 506 | |
| 499 | emit_warning(c, record_decl, "skipping record %s, TODO", buf_ptr(&bare_name)); | 507 | if (!record_def->isStruct()) { |
| | 508 | emit_warning(c, record_decl, "skipping record %s, not a struct", buf_ptr(&bare_name)); |
| | 509 | return; |
| | 510 | } |
| 500 | | 511 | |
| 501 | /* | | |
| 502 | AstNode *node = create_node(c, NodeTypeStructDecl); | 512 | AstNode *node = create_node(c, NodeTypeStructDecl); |
| 503 | buf_init_from_buf(&node->data.struct_decl.name, type_name); | 513 | buf_init_from_buf(&node->data.struct_decl.name, type_name); |
| 504 | | 514 | |
| ... | @@ -506,9 +516,34 @@ static void visit_record_decl(Context *c, const RecordDecl *record_decl) { | ... | @@ -506,9 +516,34 @@ static void visit_record_decl(Context *c, const RecordDecl *record_decl) { |
| 506 | node->data.struct_decl.visib_mod = VisibModExport; | 516 | node->data.struct_decl.visib_mod = VisibModExport; |
| 507 | node->data.struct_decl.directives = create_empty_directives(c); | 517 | node->data.struct_decl.directives = create_empty_directives(c); |
| 508 | | 518 | |
| | 519 | for (auto it = record_def->field_begin(), |
| | 520 | it_end = record_def->field_end(); |
| | 521 | it != it_end; ++it) |
| | 522 | { |
| | 523 | const FieldDecl *field_decl = *it; |
| | 524 | |
| | 525 | if (field_decl->isBitField()) { |
| | 526 | emit_warning(c, field_decl, "skipping struct %s - has bitfield\n", buf_ptr(&bare_name)); |
| | 527 | return; |
| | 528 | } |
| | 529 | |
| | 530 | AstNode *type_node = make_qual_type_node(c, field_decl->getType(), field_decl); |
| | 531 | if (!type_node) { |
| | 532 | emit_warning(c, field_decl, "skipping struct %s - unhandled type\n", buf_ptr(&bare_name)); |
| | 533 | return; |
| | 534 | } |
| | 535 | |
| | 536 | AstNode *field_node = create_struct_field_node(c, decl_name(field_decl), type_node); |
| | 537 | node->data.struct_decl.fields.append(field_node); |
| | 538 | } |
| | 539 | |
| | 540 | c->type_table.put(type_name, true); |
| 509 | normalize_parent_ptrs(node); | 541 | normalize_parent_ptrs(node); |
| 510 | c->root->data.root.top_level_decls.append(node); | 542 | c->root->data.root.top_level_decls.append(node); |
| 511 | */ | 543 | |
| | 544 | // make an alias without the "struct_" prefix. this will get emitted at the |
| | 545 | // end if it doesn't conflict with anything else |
| | 546 | add_alias(c, buf_ptr(&bare_name), buf_ptr(type_name)); |
| 512 | } | 547 | } |
| 513 | | 548 | |
| 514 | static bool decl_visitor(void *context, const Decl *decl) { | 549 | static bool decl_visitor(void *context, const Decl *decl) { |