| ... | ... | @@ -27,12 +27,18 @@ struct Context { |
| 27 | 27 | VisibMod visib_mod; |
| 28 | 28 | bool have_c_void_decl_node; |
| 29 | 29 | AstNode *root; |
| 30 | | HashMap<Buf *, bool, buf_hash, buf_eql_buf> type_table; |
| 30 | HashMap<Buf *, bool, buf_hash, buf_eql_buf> root_type_table; |
| 31 | HashMap<Buf *, bool, buf_hash, buf_eql_buf> struct_type_table; |
| 32 | HashMap<Buf *, bool, buf_hash, buf_eql_buf> enum_type_table; |
| 31 | 33 | HashMap<Buf *, bool, buf_hash, buf_eql_buf> fn_table; |
| 32 | 34 | SourceManager *source_manager; |
| 33 | 35 | ZigList<AstNode *> aliases; |
| 34 | 36 | }; |
| 35 | 37 | |
| 38 | static AstNode *make_qual_type_node(Context *c, QualType qt, const Decl *decl); |
| 39 | static AstNode *make_qual_type_node_with_table(Context *c, QualType qt, const Decl *decl, |
| 40 | HashMap<Buf *, bool, buf_hash, buf_eql_buf> *type_table); |
| 41 | |
| 36 | 42 | __attribute__ ((format (printf, 3, 4))) |
| 37 | 43 | static void emit_warning(Context *c, const Decl *decl, const char *format, ...) { |
| 38 | 44 | if (!c->warnings_on) { |
| ... | ... | @@ -59,8 +65,6 @@ static void emit_warning(Context *c, const Decl *decl, const char *format, ...) |
| 59 | 65 | fprintf(stderr, "%s:%u:%u: warning: %s\n", buf_ptr(path), line, column, buf_ptr(msg)); |
| 60 | 66 | } |
| 61 | 67 | |
| 62 | | static AstNode *make_qual_type_node(Context *c, QualType qt, const Decl *decl); |
| 63 | | |
| 64 | 68 | static AstNode *create_node(Context *c, NodeType type) { |
| 65 | 69 | AstNode *node = allocate<AstNode>(1); |
| 66 | 70 | node->type = type; |
| ... | ... | @@ -129,7 +133,7 @@ static AstNode *add_typedef_node(Context *c, Buf *new_name, AstNode *target_node |
| 129 | 133 | } |
| 130 | 134 | AstNode *node = create_var_decl_node(c, buf_ptr(new_name), target_node); |
| 131 | 135 | |
| 132 | | c->type_table.put(new_name, true); |
| 136 | c->root_type_table.put(new_name, true); |
| 133 | 137 | c->root->data.root.top_level_decls.append(node); |
| 134 | 138 | return node; |
| 135 | 139 | } |
| ... | ... | @@ -157,7 +161,9 @@ static AstNode *pointer_to_type(Context *c, AstNode *type_node, bool is_const) { |
| 157 | 161 | return create_prefix_node(c, PrefixOpMaybe, child_node); |
| 158 | 162 | } |
| 159 | 163 | |
| 160 | | static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl) { |
| 164 | static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl, |
| 165 | HashMap<Buf *, bool, buf_hash, buf_eql_buf> *type_table) |
| 166 | { |
| 161 | 167 | switch (ty->getTypeClass()) { |
| 162 | 168 | case Type::Builtin: |
| 163 | 169 | { |
| ... | ... | @@ -258,7 +264,7 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl) { |
| 258 | 264 | } else if (buf_eql_str(type_name, "uintptr_t")) { |
| 259 | 265 | return create_symbol_node(c, "usize"); |
| 260 | 266 | } else { |
| 261 | | auto entry = c->type_table.maybe_get(type_name); |
| 267 | auto entry = type_table->maybe_get(type_name); |
| 262 | 268 | if (entry) { |
| 263 | 269 | return create_symbol_node(c, buf_ptr(type_name)); |
| 264 | 270 | } else { |
| ... | ... | @@ -267,13 +273,63 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl) { |
| 267 | 273 | } |
| 268 | 274 | } |
| 269 | 275 | case Type::Elaborated: |
| 270 | | emit_warning(c, decl, "ignoring elaborated type"); |
| 271 | | return nullptr; |
| 276 | { |
| 277 | const ElaboratedType *elaborated_ty = static_cast<const ElaboratedType*>(ty); |
| 278 | switch (elaborated_ty->getKeyword()) { |
| 279 | case ETK_Struct: |
| 280 | return make_qual_type_node_with_table(c, elaborated_ty->getNamedType(), |
| 281 | decl, &c->struct_type_table); |
| 282 | case ETK_Enum: |
| 283 | return make_qual_type_node_with_table(c, elaborated_ty->getNamedType(), |
| 284 | decl, &c->enum_type_table); |
| 285 | case ETK_Interface: |
| 286 | case ETK_Union: |
| 287 | case ETK_Class: |
| 288 | case ETK_Typename: |
| 289 | case ETK_None: |
| 290 | emit_warning(c, decl, "unsupported elaborated type"); |
| 291 | return nullptr; |
| 292 | } |
| 293 | } |
| 272 | 294 | case Type::FunctionProto: |
| 273 | 295 | emit_warning(c, decl, "ignoring function type"); |
| 274 | 296 | return nullptr; |
| 275 | 297 | case Type::Record: |
| 298 | { |
| 299 | const RecordType *record_ty = static_cast<const RecordType*>(ty); |
| 300 | Buf *record_name = buf_create_from_str(decl_name(record_ty->getDecl())); |
| 301 | if (type_table->maybe_get(record_name)) { |
| 302 | const char *prefix_str; |
| 303 | if (type_table == &c->enum_type_table) { |
| 304 | prefix_str = "enum_"; |
| 305 | } else if (type_table == &c->struct_type_table) { |
| 306 | prefix_str = "struct_"; |
| 307 | } else { |
| 308 | prefix_str = ""; |
| 309 | } |
| 310 | return create_symbol_node(c, buf_ptr(buf_sprintf("%s%s", prefix_str, buf_ptr(record_name)))); |
| 311 | } else { |
| 312 | return nullptr; |
| 313 | } |
| 314 | } |
| 276 | 315 | case Type::Enum: |
| 316 | { |
| 317 | const EnumType *enum_ty = static_cast<const EnumType*>(ty); |
| 318 | Buf *record_name = buf_create_from_str(decl_name(enum_ty->getDecl())); |
| 319 | if (type_table->maybe_get(record_name)) { |
| 320 | const char *prefix_str; |
| 321 | if (type_table == &c->enum_type_table) { |
| 322 | prefix_str = "enum_"; |
| 323 | } else if (type_table == &c->struct_type_table) { |
| 324 | prefix_str = "struct_"; |
| 325 | } else { |
| 326 | prefix_str = ""; |
| 327 | } |
| 328 | return create_symbol_node(c, buf_ptr(buf_sprintf("%s%s", prefix_str, buf_ptr(record_name)))); |
| 329 | } else { |
| 330 | return nullptr; |
| 331 | } |
| 332 | } |
| 277 | 333 | case Type::BlockPointer: |
| 278 | 334 | case Type::LValueReference: |
| 279 | 335 | case Type::RValueReference: |
| ... | ... | @@ -314,8 +370,14 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl) { |
| 314 | 370 | } |
| 315 | 371 | } |
| 316 | 372 | |
| 373 | static AstNode *make_qual_type_node_with_table(Context *c, QualType qt, const Decl *decl, |
| 374 | HashMap<Buf *, bool, buf_hash, buf_eql_buf> *type_table) |
| 375 | { |
| 376 | return make_type_node(c, qt.getTypePtr(), decl, type_table); |
| 377 | } |
| 378 | |
| 317 | 379 | static AstNode *make_qual_type_node(Context *c, QualType qt, const Decl *decl) { |
| 318 | | return make_type_node(c, qt.getTypePtr(), decl); |
| 380 | return make_qual_type_node_with_table(c, qt, decl, &c->root_type_table); |
| 319 | 381 | } |
| 320 | 382 | |
| 321 | 383 | static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { |
| ... | ... | @@ -334,7 +396,6 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { |
| 334 | 396 | node->data.fn_proto.is_var_args = fn_decl->isVariadic(); |
| 335 | 397 | |
| 336 | 398 | int arg_count = fn_decl->getNumParams(); |
| 337 | | bool all_ok = true; |
| 338 | 399 | for (int i = 0; i < arg_count; i += 1) { |
| 339 | 400 | const ParmVarDecl *param = fn_decl->getParamDecl(i); |
| 340 | 401 | AstNode *param_decl_node = create_node(c, NodeTypeParamDecl); |
| ... | ... | @@ -347,8 +408,9 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { |
| 347 | 408 | param_decl_node->data.param_decl.is_noalias = qt.isRestrictQualified(); |
| 348 | 409 | param_decl_node->data.param_decl.type = make_qual_type_node(c, qt, fn_decl); |
| 349 | 410 | if (!param_decl_node->data.param_decl.type) { |
| 350 | | all_ok = false; |
| 351 | | break; |
| 411 | emit_warning(c, param, "skipping function %s, unresolved param type\n", |
| 412 | buf_ptr(&node->data.fn_proto.name)); |
| 413 | return; |
| 352 | 414 | } |
| 353 | 415 | |
| 354 | 416 | normalize_parent_ptrs(param_decl_node); |
| ... | ... | @@ -362,11 +424,8 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { |
| 362 | 424 | } |
| 363 | 425 | |
| 364 | 426 | if (!node->data.fn_proto.return_type) { |
| 365 | | all_ok = false; |
| 366 | | } |
| 367 | | if (!all_ok) { |
| 368 | | // not all the types could be resolved, so we give up on the function decl |
| 369 | | emit_warning(c, fn_decl, "skipping function %s\n", buf_ptr(&node->data.fn_proto.name)); |
| 427 | emit_warning(c, fn_decl, "skipping function %s, unresolved return type\n", |
| 428 | buf_ptr(&node->data.fn_proto.name)); |
| 370 | 429 | return; |
| 371 | 430 | } |
| 372 | 431 | |
| ... | ... | @@ -404,13 +463,10 @@ static void add_alias(Context *c, const char *new_name, const char *target_name) |
| 404 | 463 | } |
| 405 | 464 | |
| 406 | 465 | static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) { |
| 407 | | Buf bare_name = BUF_INIT; |
| 408 | | buf_init_from_str(&bare_name, decl_name(enum_decl)); |
| 409 | | |
| 410 | | Buf *type_name = buf_alloc(); |
| 411 | | buf_appendf(type_name, "enum_%s", buf_ptr(&bare_name)); |
| 466 | Buf *bare_name = buf_create_from_str(decl_name(enum_decl)); |
| 467 | Buf *full_type_name = buf_sprintf("enum_%s", buf_ptr(bare_name)); |
| 412 | 468 | |
| 413 | | if (c->type_table.maybe_get(type_name)) { |
| 469 | if (c->enum_type_table.maybe_get(bare_name)) { |
| 414 | 470 | // we've already seen it |
| 415 | 471 | return; |
| 416 | 472 | } |
| ... | ... | @@ -419,13 +475,13 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) { |
| 419 | 475 | |
| 420 | 476 | if (!enum_def) { |
| 421 | 477 | // this is a type that we can point to but that's it, same as `struct Foo;`. |
| 422 | | add_typedef_node(c, type_name, create_symbol_node(c, "u8")); |
| 423 | | add_alias(c, buf_ptr(&bare_name), buf_ptr(type_name)); |
| 478 | add_typedef_node(c, full_type_name, create_symbol_node(c, "u8")); |
| 479 | add_alias(c, buf_ptr(bare_name), buf_ptr(full_type_name)); |
| 424 | 480 | return; |
| 425 | 481 | } |
| 426 | 482 | |
| 427 | 483 | AstNode *node = create_node(c, NodeTypeStructDecl); |
| 428 | | buf_init_from_buf(&node->data.struct_decl.name, type_name); |
| 484 | buf_init_from_buf(&node->data.struct_decl.name, full_type_name); |
| 429 | 485 | |
| 430 | 486 | node->data.struct_decl.kind = ContainerKindEnum; |
| 431 | 487 | node->data.struct_decl.visib_mod = VisibModExport; |
| ... | ... | @@ -439,7 +495,7 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) { |
| 439 | 495 | { |
| 440 | 496 | const EnumConstantDecl *enum_const = *it; |
| 441 | 497 | if (enum_const->getInitExpr()) { |
| 442 | | emit_warning(c, enum_const, "skipping enum %s - has init expression\n", buf_ptr(type_name)); |
| 498 | emit_warning(c, enum_const, "skipping enum %s - has init expression\n", buf_ptr(bare_name)); |
| 443 | 499 | return; |
| 444 | 500 | } |
| 445 | 501 | Buf enum_val_name = BUF_INIT; |
| ... | ... | @@ -447,8 +503,8 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) { |
| 447 | 503 | |
| 448 | 504 | Buf field_name = BUF_INIT; |
| 449 | 505 | |
| 450 | | if (buf_starts_with_buf(&enum_val_name, &bare_name)) { |
| 451 | | Buf *slice = buf_slice(&enum_val_name, buf_len(&bare_name), buf_len(&enum_val_name)); |
| 506 | if (buf_starts_with_buf(&enum_val_name, bare_name)) { |
| 507 | Buf *slice = buf_slice(&enum_val_name, buf_len(bare_name), buf_len(&enum_val_name)); |
| 452 | 508 | if (valid_symbol_starter(buf_ptr(slice)[0])) { |
| 453 | 509 | buf_init_from_buf(&field_name, slice); |
| 454 | 510 | } else { |
| ... | ... | @@ -463,13 +519,12 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) { |
| 463 | 519 | node->data.struct_decl.fields.append(field_node); |
| 464 | 520 | |
| 465 | 521 | // in C each enum value is in the global namespace. so we put them there too. |
| 466 | | AstNode *field_access_node = create_field_access_node(c, buf_ptr(type_name), |
| 467 | | buf_ptr(&field_name)); |
| 522 | AstNode *field_access_node = create_field_access_node(c, buf_ptr(full_type_name), buf_ptr(&field_name)); |
| 468 | 523 | AstNode *var_node = create_var_decl_node(c, buf_ptr(&enum_val_name), field_access_node); |
| 469 | 524 | var_decls.append(var_node); |
| 470 | 525 | } |
| 471 | 526 | |
| 472 | | c->type_table.put(type_name, true); |
| 527 | c->enum_type_table.put(bare_name, true); |
| 473 | 528 | |
| 474 | 529 | normalize_parent_ptrs(node); |
| 475 | 530 | c->root->data.root.top_level_decls.append(node); |
| ... | ... | @@ -481,17 +536,20 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) { |
| 481 | 536 | |
| 482 | 537 | // make an alias without the "enum_" prefix. this will get emitted at the |
| 483 | 538 | // end if it doesn't conflict with anything else |
| 484 | | add_alias(c, buf_ptr(&bare_name), buf_ptr(type_name)); |
| 539 | add_alias(c, buf_ptr(bare_name), buf_ptr(full_type_name)); |
| 485 | 540 | } |
| 486 | 541 | |
| 487 | 542 | static void visit_record_decl(Context *c, const RecordDecl *record_decl) { |
| 488 | | Buf bare_name = BUF_INIT; |
| 489 | | buf_init_from_str(&bare_name, decl_name(record_decl)); |
| 543 | Buf *bare_name = buf_create_from_str(decl_name(record_decl)); |
| 544 | |
| 545 | if (!record_decl->isStruct()) { |
| 546 | emit_warning(c, record_decl, "skipping record %s, not a struct", buf_ptr(bare_name)); |
| 547 | return; |
| 548 | } |
| 490 | 549 | |
| 491 | | Buf *type_name = buf_alloc(); |
| 492 | | buf_appendf(type_name, "struct_%s", buf_ptr(&bare_name)); |
| 550 | Buf *full_type_name = buf_sprintf("struct_%s", buf_ptr(bare_name)); |
| 493 | 551 | |
| 494 | | if (c->type_table.maybe_get(type_name)) { |
| 552 | if (c->struct_type_table.maybe_get(bare_name)) { |
| 495 | 553 | // we've already seen it |
| 496 | 554 | return; |
| 497 | 555 | } |
| ... | ... | @@ -499,18 +557,13 @@ static void visit_record_decl(Context *c, const RecordDecl *record_decl) { |
| 499 | 557 | RecordDecl *record_def = record_decl->getDefinition(); |
| 500 | 558 | if (!record_def) { |
| 501 | 559 | // this is a type that we can point to but that's it, such as `struct Foo;`. |
| 502 | | add_typedef_node(c, type_name, create_symbol_node(c, "u8")); |
| 503 | | add_alias(c, buf_ptr(&bare_name), buf_ptr(type_name)); |
| 504 | | return; |
| 505 | | } |
| 506 | | |
| 507 | | if (!record_def->isStruct()) { |
| 508 | | emit_warning(c, record_decl, "skipping record %s, not a struct", buf_ptr(&bare_name)); |
| 560 | add_typedef_node(c, full_type_name, create_symbol_node(c, "u8")); |
| 561 | add_alias(c, buf_ptr(bare_name), buf_ptr(full_type_name)); |
| 509 | 562 | return; |
| 510 | 563 | } |
| 511 | 564 | |
| 512 | 565 | AstNode *node = create_node(c, NodeTypeStructDecl); |
| 513 | | buf_init_from_buf(&node->data.struct_decl.name, type_name); |
| 566 | buf_init_from_buf(&node->data.struct_decl.name, full_type_name); |
| 514 | 567 | |
| 515 | 568 | node->data.struct_decl.kind = ContainerKindStruct; |
| 516 | 569 | node->data.struct_decl.visib_mod = VisibModExport; |
| ... | ... | @@ -523,13 +576,13 @@ static void visit_record_decl(Context *c, const RecordDecl *record_decl) { |
| 523 | 576 | const FieldDecl *field_decl = *it; |
| 524 | 577 | |
| 525 | 578 | if (field_decl->isBitField()) { |
| 526 | | emit_warning(c, field_decl, "skipping struct %s - has bitfield\n", buf_ptr(&bare_name)); |
| 579 | emit_warning(c, field_decl, "skipping struct %s - has bitfield\n", buf_ptr(bare_name)); |
| 527 | 580 | return; |
| 528 | 581 | } |
| 529 | 582 | |
| 530 | 583 | AstNode *type_node = make_qual_type_node(c, field_decl->getType(), field_decl); |
| 531 | 584 | if (!type_node) { |
| 532 | | emit_warning(c, field_decl, "skipping struct %s - unhandled type\n", buf_ptr(&bare_name)); |
| 585 | emit_warning(c, field_decl, "skipping struct %s - unhandled type\n", buf_ptr(bare_name)); |
| 533 | 586 | return; |
| 534 | 587 | } |
| 535 | 588 | |
| ... | ... | @@ -537,13 +590,13 @@ static void visit_record_decl(Context *c, const RecordDecl *record_decl) { |
| 537 | 590 | node->data.struct_decl.fields.append(field_node); |
| 538 | 591 | } |
| 539 | 592 | |
| 540 | | c->type_table.put(type_name, true); |
| 593 | c->struct_type_table.put(bare_name, true); |
| 541 | 594 | normalize_parent_ptrs(node); |
| 542 | 595 | c->root->data.root.top_level_decls.append(node); |
| 543 | 596 | |
| 544 | 597 | // make an alias without the "struct_" prefix. this will get emitted at the |
| 545 | 598 | // end if it doesn't conflict with anything else |
| 546 | | add_alias(c, buf_ptr(&bare_name), buf_ptr(type_name)); |
| 599 | add_alias(c, buf_ptr(bare_name), buf_ptr(full_type_name)); |
| 547 | 600 | } |
| 548 | 601 | |
| 549 | 602 | static bool decl_visitor(void *context, const Decl *decl) { |
| ... | ... | @@ -574,7 +627,7 @@ static void render_aliases(Context *c) { |
| 574 | 627 | AstNode *alias_node = c->aliases.at(i); |
| 575 | 628 | assert(alias_node->type == NodeTypeVariableDeclaration); |
| 576 | 629 | Buf *name = &alias_node->data.variable_declaration.symbol; |
| 577 | | if (c->type_table.maybe_get(name)) { |
| 630 | if (c->root_type_table.maybe_get(name)) { |
| 578 | 631 | continue; |
| 579 | 632 | } |
| 580 | 633 | if (c->fn_table.maybe_get(name)) { |
| ... | ... | @@ -618,8 +671,10 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, |
| 618 | 671 | c->import = import; |
| 619 | 672 | c->errors = errors; |
| 620 | 673 | c->visib_mod = VisibModPub; |
| 621 | | c->type_table.init(32); |
| 622 | | c->fn_table.init(32); |
| 674 | c->root_type_table.init(16); |
| 675 | c->enum_type_table.init(16); |
| 676 | c->struct_type_table.init(16); |
| 677 | c->fn_table.init(16); |
| 623 | 678 | |
| 624 | 679 | char *ZIG_PARSEH_CFLAGS = getenv("ZIG_PARSEH_CFLAGS"); |
| 625 | 680 | if (ZIG_PARSEH_CFLAGS) { |