| ... | @@ -23,11 +23,6 @@ | ... | @@ -23,11 +23,6 @@ |
| 23 | | 23 | |
| 24 | using namespace clang; | 24 | using namespace clang; |
| 25 | | 25 | |
| 26 | struct MacroSymbol { | | |
| 27 | Buf *name; | | |
| 28 | Buf *value; | | |
| 29 | }; | | |
| 30 | | | |
| 31 | struct Alias { | 26 | struct Alias { |
| 32 | Buf *new_name; | 27 | Buf *new_name; |
| 33 | Buf *canon_name; | 28 | Buf *canon_name; |
| ... | @@ -44,7 +39,6 @@ struct Context { | ... | @@ -44,7 +39,6 @@ struct Context { |
| 44 | HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> global_table; | 39 | HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> global_table; |
| 45 | SourceManager *source_manager; | 40 | SourceManager *source_manager; |
| 46 | ZigList<Alias> aliases; | 41 | ZigList<Alias> aliases; |
| 47 | ZigList<MacroSymbol> macro_symbols; | | |
| 48 | AstNode *source_node; | 42 | AstNode *source_node; |
| 49 | bool warnings_on; | 43 | bool warnings_on; |
| 50 | | 44 | |
| ... | @@ -351,8 +345,7 @@ static AstNode *trans_create_node_var_decl_local(Context *c, bool is_const, Buf | ... | @@ -351,8 +345,7 @@ static AstNode *trans_create_node_var_decl_local(Context *c, bool is_const, Buf |
| 351 | return trans_create_node_var_decl(c, VisibModPrivate, is_const, var_name, type_node, init_node); | 345 | return trans_create_node_var_decl(c, VisibModPrivate, is_const, var_name, type_node, init_node); |
| 352 | } | 346 | } |
| 353 | | 347 | |
| 354 | | 348 | static AstNode *trans_create_node_inline_fn(Context *c, Buf *fn_name, AstNode *ref_node, AstNode *src_proto_node) { |
| 355 | static AstNode *trans_create_node_inline_fn(Context *c, Buf *fn_name, Buf *var_name, AstNode *src_proto_node) { | | |
| 356 | AstNode *fn_def = trans_create_node(c, NodeTypeFnDef); | 349 | AstNode *fn_def = trans_create_node(c, NodeTypeFnDef); |
| 357 | AstNode *fn_proto = trans_create_node(c, NodeTypeFnProto); | 350 | AstNode *fn_proto = trans_create_node(c, NodeTypeFnProto); |
| 358 | fn_proto->data.fn_proto.visib_mod = c->visib_mod; | 351 | fn_proto->data.fn_proto.visib_mod = c->visib_mod; |
| ... | @@ -363,7 +356,7 @@ static AstNode *trans_create_node_inline_fn(Context *c, Buf *fn_name, Buf *var_n | ... | @@ -363,7 +356,7 @@ static AstNode *trans_create_node_inline_fn(Context *c, Buf *fn_name, Buf *var_n |
| 363 | fn_def->data.fn_def.fn_proto = fn_proto; | 356 | fn_def->data.fn_def.fn_proto = fn_proto; |
| 364 | fn_proto->data.fn_proto.fn_def_node = fn_def; | 357 | fn_proto->data.fn_proto.fn_def_node = fn_def; |
| 365 | | 358 | |
| 366 | AstNode *unwrap_node = trans_create_node_prefix_op(c, PrefixOpUnwrapMaybe, trans_create_node_symbol(c, var_name)); | 359 | AstNode *unwrap_node = trans_create_node_prefix_op(c, PrefixOpUnwrapMaybe, ref_node); |
| 367 | AstNode *fn_call_node = trans_create_node(c, NodeTypeFnCallExpr); | 360 | AstNode *fn_call_node = trans_create_node(c, NodeTypeFnCallExpr); |
| 368 | fn_call_node->data.fn_call_expr.fn_ref_expr = unwrap_node; | 361 | fn_call_node->data.fn_call_expr.fn_ref_expr = unwrap_node; |
| 369 | | 362 | |
| ... | @@ -3808,6 +3801,83 @@ static void render_aliases(Context *c) { | ... | @@ -3808,6 +3801,83 @@ static void render_aliases(Context *c) { |
| 3808 | } | 3801 | } |
| 3809 | } | 3802 | } |
| 3810 | | 3803 | |
| | 3804 | static AstNode *trans_lookup_ast_container_typeof(Context *c, AstNode *ref_node); |
| | 3805 | |
| | 3806 | static AstNode *trans_lookup_ast_container(Context *c, AstNode *type_node) { |
| | 3807 | if (type_node == nullptr) { |
| | 3808 | return nullptr; |
| | 3809 | } else if (type_node->type == NodeTypeContainerDecl) { |
| | 3810 | return type_node; |
| | 3811 | } else if (type_node->type == NodeTypePrefixOpExpr) { |
| | 3812 | return type_node; |
| | 3813 | } else if (type_node->type == NodeTypeSymbol) { |
| | 3814 | AstNode *existing_node = get_global(c, type_node->data.symbol_expr.symbol); |
| | 3815 | if (existing_node == nullptr) |
| | 3816 | return nullptr; |
| | 3817 | if (existing_node->type != NodeTypeVariableDeclaration) |
| | 3818 | return nullptr; |
| | 3819 | return trans_lookup_ast_container(c, existing_node->data.variable_declaration.expr); |
| | 3820 | } else if (type_node->type == NodeTypeFieldAccessExpr) { |
| | 3821 | AstNode *container_node = trans_lookup_ast_container_typeof(c, type_node->data.field_access_expr.struct_expr); |
| | 3822 | if (container_node == nullptr) |
| | 3823 | return nullptr; |
| | 3824 | if (container_node->type != NodeTypeContainerDecl) |
| | 3825 | return container_node; |
| | 3826 | |
| | 3827 | for (size_t i = 0; i < container_node->data.container_decl.fields.length; i += 1) { |
| | 3828 | AstNode *field_node = container_node->data.container_decl.fields.items[i]; |
| | 3829 | if (buf_eql_buf(field_node->data.struct_field.name, type_node->data.field_access_expr.field_name)) { |
| | 3830 | return trans_lookup_ast_container(c, field_node->data.struct_field.type); |
| | 3831 | } |
| | 3832 | } |
| | 3833 | return nullptr; |
| | 3834 | } else { |
| | 3835 | return nullptr; |
| | 3836 | } |
| | 3837 | } |
| | 3838 | |
| | 3839 | static AstNode *trans_lookup_ast_container_typeof(Context *c, AstNode *ref_node) { |
| | 3840 | if (ref_node->type == NodeTypeSymbol) { |
| | 3841 | AstNode *existing_node = get_global(c, ref_node->data.symbol_expr.symbol); |
| | 3842 | if (existing_node == nullptr) |
| | 3843 | return nullptr; |
| | 3844 | if (existing_node->type != NodeTypeVariableDeclaration) |
| | 3845 | return nullptr; |
| | 3846 | return trans_lookup_ast_container(c, existing_node->data.variable_declaration.type); |
| | 3847 | } else if (ref_node->type == NodeTypeFieldAccessExpr) { |
| | 3848 | AstNode *container_node = trans_lookup_ast_container_typeof(c, ref_node->data.field_access_expr.struct_expr); |
| | 3849 | if (container_node == nullptr) |
| | 3850 | return nullptr; |
| | 3851 | if (container_node->type != NodeTypeContainerDecl) |
| | 3852 | return container_node; |
| | 3853 | for (size_t i = 0; i < container_node->data.container_decl.fields.length; i += 1) { |
| | 3854 | AstNode *field_node = container_node->data.container_decl.fields.items[i]; |
| | 3855 | if (buf_eql_buf(field_node->data.struct_field.name, ref_node->data.field_access_expr.field_name)) { |
| | 3856 | return trans_lookup_ast_container(c, field_node->data.struct_field.type); |
| | 3857 | } |
| | 3858 | } |
| | 3859 | return nullptr; |
| | 3860 | } else { |
| | 3861 | return nullptr; |
| | 3862 | } |
| | 3863 | } |
| | 3864 | |
| | 3865 | static AstNode *trans_lookup_ast_maybe_fn(Context *c, AstNode *ref_node) { |
| | 3866 | AstNode *prefix_node = trans_lookup_ast_container_typeof(c, ref_node); |
| | 3867 | if (prefix_node == nullptr) |
| | 3868 | return nullptr; |
| | 3869 | if (prefix_node->type != NodeTypePrefixOpExpr) |
| | 3870 | return nullptr; |
| | 3871 | if (prefix_node->data.prefix_op_expr.prefix_op != PrefixOpMaybe) |
| | 3872 | return nullptr; |
| | 3873 | |
| | 3874 | AstNode *fn_proto_node = prefix_node->data.prefix_op_expr.primary_expr; |
| | 3875 | if (fn_proto_node->type != NodeTypeFnProto) |
| | 3876 | return nullptr; |
| | 3877 | |
| | 3878 | return fn_proto_node; |
| | 3879 | } |
| | 3880 | |
| 3811 | static void render_macros(Context *c) { | 3881 | static void render_macros(Context *c) { |
| 3812 | auto it = c->macro_table.entry_iterator(); | 3882 | auto it = c->macro_table.entry_iterator(); |
| 3813 | for (;;) { | 3883 | for (;;) { |
| ... | @@ -3815,9 +3885,16 @@ static void render_macros(Context *c) { | ... | @@ -3815,9 +3885,16 @@ static void render_macros(Context *c) { |
| 3815 | if (!entry) | 3885 | if (!entry) |
| 3816 | break; | 3886 | break; |
| 3817 | | 3887 | |
| | 3888 | AstNode *proto_node; |
| 3818 | AstNode *value_node = entry->value; | 3889 | AstNode *value_node = entry->value; |
| 3819 | if (value_node->type == NodeTypeFnDef) { | 3890 | if (value_node->type == NodeTypeFnDef) { |
| 3820 | add_top_level_decl(c, value_node->data.fn_def.fn_proto->data.fn_proto.name, value_node); | 3891 | add_top_level_decl(c, value_node->data.fn_def.fn_proto->data.fn_proto.name, value_node); |
| | 3892 | } else if ((proto_node = trans_lookup_ast_maybe_fn(c, value_node))) { |
| | 3893 | // If a macro aliases a global variable which is a function pointer, we conclude that |
| | 3894 | // the macro is intended to represent a function that assumes the function pointer |
| | 3895 | // variable is non-null and calls it. |
| | 3896 | AstNode *inline_fn_node = trans_create_node_inline_fn(c, entry->key, value_node, proto_node); |
| | 3897 | add_top_level_decl(c, entry->key, inline_fn_node); |
| 3821 | } else { | 3898 | } else { |
| 3822 | add_global_var(c, entry->key, value_node); | 3899 | add_global_var(c, entry->key, value_node); |
| 3823 | } | 3900 | } |
| ... | @@ -3944,40 +4021,8 @@ static void process_macro(Context *c, CTokenize *ctok, Buf *name, const char *ch | ... | @@ -3944,40 +4021,8 @@ static void process_macro(Context *c, CTokenize *ctok, Buf *name, const char *ch |
| 3944 | if (buf_eql_buf(name, symbol_name)) { | 4021 | if (buf_eql_buf(name, symbol_name)) { |
| 3945 | return; | 4022 | return; |
| 3946 | } | 4023 | } |
| 3947 | c->macro_symbols.append({name, symbol_name}); | | |
| 3948 | } else { | | |
| 3949 | c->macro_table.put(name, result_node); | | |
| 3950 | } | | |
| 3951 | } | | |
| 3952 | | | |
| 3953 | static void process_symbol_macros(Context *c) { | | |
| 3954 | for (size_t i = 0; i < c->macro_symbols.length; i += 1) { | | |
| 3955 | MacroSymbol ms = c->macro_symbols.at(i); | | |
| 3956 | | | |
| 3957 | // Check if this macro aliases another top level declaration | | |
| 3958 | AstNode *existing_node = get_global(c, ms.value); | | |
| 3959 | if (!existing_node || name_exists_global(c, ms.name)) | | |
| 3960 | continue; | | |
| 3961 | | | |
| 3962 | // If a macro aliases a global variable which is a function pointer, we conclude that | | |
| 3963 | // the macro is intended to represent a function that assumes the function pointer | | |
| 3964 | // variable is non-null and calls it. | | |
| 3965 | if (existing_node->type == NodeTypeVariableDeclaration) { | | |
| 3966 | AstNode *var_type = existing_node->data.variable_declaration.type; | | |
| 3967 | if (var_type != nullptr && var_type->type == NodeTypePrefixOpExpr && | | |
| 3968 | var_type->data.prefix_op_expr.prefix_op == PrefixOpMaybe) | | |
| 3969 | { | | |
| 3970 | AstNode *fn_proto_node = var_type->data.prefix_op_expr.primary_expr; | | |
| 3971 | if (fn_proto_node->type == NodeTypeFnProto) { | | |
| 3972 | AstNode *inline_fn_node = trans_create_node_inline_fn(c, ms.name, ms.value, fn_proto_node); | | |
| 3973 | c->macro_table.put(ms.name, inline_fn_node); | | |
| 3974 | continue; | | |
| 3975 | } | | |
| 3976 | } | | |
| 3977 | } | | |
| 3978 | | | |
| 3979 | add_global_var(c, ms.name, trans_create_node_symbol(c, ms.value)); | | |
| 3980 | } | 4024 | } |
| | 4025 | c->macro_table.put(name, result_node); |
| 3981 | } | 4026 | } |
| 3982 | | 4027 | |
| 3983 | static void process_preprocessor_entities(Context *c, ASTUnit &unit) { | 4028 | static void process_preprocessor_entities(Context *c, ASTUnit &unit) { |
| ... | @@ -4194,7 +4239,6 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const ch | ... | @@ -4194,7 +4239,6 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const ch |
| 4194 | | 4239 | |
| 4195 | process_preprocessor_entities(c, *ast_unit); | 4240 | process_preprocessor_entities(c, *ast_unit); |
| 4196 | | 4241 | |
| 4197 | process_symbol_macros(c); | | |
| 4198 | render_macros(c); | 4242 | render_macros(c); |
| 4199 | render_aliases(c); | 4243 | render_aliases(c); |
| 4200 | | 4244 | |