| ... | ... | @@ -23,11 +23,6 @@ |
| 23 | 23 | |
| 24 | 24 | using namespace clang; |
| 25 | 25 | |
| 26 | | struct MacroSymbol { |
| 27 | | Buf *name; |
| 28 | | Buf *value; |
| 29 | | }; |
| 30 | | |
| 31 | 26 | struct Alias { |
| 32 | 27 | Buf *new_name; |
| 33 | 28 | Buf *canon_name; |
| ... | ... | @@ -44,7 +39,6 @@ struct Context { |
| 44 | 39 | HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> global_table; |
| 45 | 40 | SourceManager *source_manager; |
| 46 | 41 | ZigList<Alias> aliases; |
| 47 | | ZigList<MacroSymbol> macro_symbols; |
| 48 | 42 | AstNode *source_node; |
| 49 | 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 | 345 | return trans_create_node_var_decl(c, VisibModPrivate, is_const, var_name, type_node, init_node); |
| 352 | 346 | } |
| 353 | 347 | |
| 354 | | |
| 355 | | static AstNode *trans_create_node_inline_fn(Context *c, Buf *fn_name, Buf *var_name, AstNode *src_proto_node) { |
| 348 | static AstNode *trans_create_node_inline_fn(Context *c, Buf *fn_name, AstNode *ref_node, AstNode *src_proto_node) { |
| 356 | 349 | AstNode *fn_def = trans_create_node(c, NodeTypeFnDef); |
| 357 | 350 | AstNode *fn_proto = trans_create_node(c, NodeTypeFnProto); |
| 358 | 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 | 356 | fn_def->data.fn_def.fn_proto = fn_proto; |
| 364 | 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 | 360 | AstNode *fn_call_node = trans_create_node(c, NodeTypeFnCallExpr); |
| 368 | 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 | 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 | 3881 | static void render_macros(Context *c) { |
| 3812 | 3882 | auto it = c->macro_table.entry_iterator(); |
| 3813 | 3883 | for (;;) { |
| ... | ... | @@ -3815,9 +3885,16 @@ static void render_macros(Context *c) { |
| 3815 | 3885 | if (!entry) |
| 3816 | 3886 | break; |
| 3817 | 3887 | |
| 3888 | AstNode *proto_node; |
| 3818 | 3889 | AstNode *value_node = entry->value; |
| 3819 | 3890 | if (value_node->type == NodeTypeFnDef) { |
| 3820 | 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 | 3898 | } else { |
| 3822 | 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 | 4021 | if (buf_eql_buf(name, symbol_name)) { |
| 3945 | 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 | 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 | 4239 | |
| 4195 | 4240 | process_preprocessor_entities(c, *ast_unit); |
| 4196 | 4241 | |
| 4197 | | process_symbol_macros(c); |
| 4198 | 4242 | render_macros(c); |
| 4199 | 4243 | render_aliases(c); |
| 4200 | 4244 | |