diff options
| author | Zuhaitz <zuhaitz.zechhub@gmail.com> | 2026-01-25 23:23:43 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-01-25 23:23:43 +0000 |
| commit | b568f67d75553bbecd2cadc4d61b330b8aea2ad2 (patch) | |
| tree | 93de523967424146ba2b4ccb0f728c47cdbe2251 /src/parser/parser_utils.c | |
| parent | 18b0932249b0df8ddea159ba187cb9c3587197da (diff) | |
| parent | 59951529ba67d3316a01afd45808c1b20b20c1e1 (diff) | |
Merge pull request #109 from iryuken/main
Fix generic struct pointer instantiation bug #105
Diffstat (limited to 'src/parser/parser_utils.c')
| -rw-r--r-- | src/parser/parser_utils.c | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/src/parser/parser_utils.c b/src/parser/parser_utils.c index 385d36c..86e1b50 100644 --- a/src/parser/parser_utils.c +++ b/src/parser/parser_utils.c @@ -1882,6 +1882,129 @@ FuncSig *find_func(ParserContext *ctx, const char *name) return NULL; } +// Helper function to recursively scan AST for sizeof types and trigger instantiation of generic +// structs +static void trigger_sizeof_instantiations(ParserContext *ctx, ASTNode *node) +{ + if (!node) + { + return; + } + + // Process current node + if (node->type == NODE_EXPR_SIZEOF && node->size_of.target_type) + { + const char *type_str = node->size_of.target_type; + if (strchr(type_str, '_')) + { + // Remove trailing '*' or 'Ptr' if present + char *type_copy = xstrdup(type_str); + char *star = strchr(type_copy, '*'); + if (star) + { + *star = '\0'; + } + else + { + // Check for "Ptr" suffix and remove it + size_t len = strlen(type_copy); + if (len > 3 && strcmp(type_copy + len - 3, "Ptr") == 0) + { + type_copy[len - 3] = '\0'; + } + } + + char *underscore = strrchr(type_copy, '_'); + if (underscore && underscore > type_copy) + { + *underscore = '\0'; + char *template_name = type_copy; + char *concrete_arg = underscore + 1; + + // Check if this is a known generic template + GenericTemplate *gt = ctx->templates; + int found = 0; + while (gt) + { + if (strcmp(gt->name, template_name) == 0) + { + found = 1; + break; + } + gt = gt->next; + } + + if (found) + { + char *unmangled = unmangle_ptr_suffix(concrete_arg); + Token dummy_tok = {0}; + instantiate_generic(ctx, template_name, concrete_arg, unmangled, dummy_tok); + free(unmangled); + } + } + free(type_copy); + } + } + + // Recursively visit children based on node type + switch (node->type) + { + case NODE_FUNCTION: + trigger_sizeof_instantiations(ctx, node->func.body); + break; + case NODE_BLOCK: + trigger_sizeof_instantiations(ctx, node->block.statements); + break; + case NODE_VAR_DECL: + trigger_sizeof_instantiations(ctx, node->var_decl.init_expr); + break; + case NODE_RETURN: + trigger_sizeof_instantiations(ctx, node->ret.value); + break; + case NODE_EXPR_BINARY: + trigger_sizeof_instantiations(ctx, node->binary.left); + trigger_sizeof_instantiations(ctx, node->binary.right); + break; + case NODE_EXPR_UNARY: + trigger_sizeof_instantiations(ctx, node->unary.operand); + break; + case NODE_EXPR_CALL: + trigger_sizeof_instantiations(ctx, node->call.callee); + trigger_sizeof_instantiations(ctx, node->call.args); + break; + case NODE_EXPR_MEMBER: + trigger_sizeof_instantiations(ctx, node->member.target); + break; + case NODE_EXPR_INDEX: + trigger_sizeof_instantiations(ctx, node->index.array); + trigger_sizeof_instantiations(ctx, node->index.index); + break; + case NODE_EXPR_CAST: + trigger_sizeof_instantiations(ctx, node->cast.expr); + break; + case NODE_IF: + trigger_sizeof_instantiations(ctx, node->if_stmt.condition); + trigger_sizeof_instantiations(ctx, node->if_stmt.then_body); + trigger_sizeof_instantiations(ctx, node->if_stmt.else_body); + break; + case NODE_WHILE: + trigger_sizeof_instantiations(ctx, node->while_stmt.condition); + trigger_sizeof_instantiations(ctx, node->while_stmt.body); + break; + case NODE_FOR: + trigger_sizeof_instantiations(ctx, node->for_stmt.init); + trigger_sizeof_instantiations(ctx, node->for_stmt.condition); + trigger_sizeof_instantiations(ctx, node->for_stmt.step); + trigger_sizeof_instantiations(ctx, node->for_stmt.body); + break; + default: + break; + } + + // Visit next sibling + trigger_sizeof_instantiations(ctx, node->next); +} + char *instantiate_function_template(ParserContext *ctx, const char *name, const char *concrete_type, const char *unmangled_type) { @@ -2020,6 +2143,11 @@ char *instantiate_function_template(ParserContext *ctx, const char *name, const { return NULL; } + + // Scan the function body for sizeof expressions and trigger instantiation + // of any generic structs referenced there (e.g., sizeof(RcInner_int32_t)) + trigger_sizeof_instantiations(ctx, new_fn->func.body); + free(new_fn->func.name); new_fn->func.name = xstrdup(mangled); new_fn->func.generic_params = NULL; @@ -2265,6 +2393,43 @@ ASTNode *copy_fields_replacing(ParserContext *ctx, ASTNode *fields, const char * } } + // Additional check: if type_info is a pointer to a struct with a mangled name, + // instantiate that struct as well (fixes cases like RcInner<T>* where the + // string check above might not catch it) + if (n->type_info && n->type_info->kind == TYPE_POINTER && n->type_info->inner) + { + Type *inner = n->type_info->inner; + if (inner->kind == TYPE_STRUCT && inner->name && strchr(inner->name, '_')) + { + // Extract template name by checking against known templates + // We can't use strrchr because types like "Inner_int32_t" have multiple underscores + char *template_name = NULL; + char *concrete_arg = NULL; + + // Try each known template to see if the type name starts with it + GenericTemplate *gt = ctx->templates; + while (gt) + { + size_t tlen = strlen(gt->name); + // Check if name starts with template name followed by underscore + if (strncmp(inner->name, gt->name, tlen) == 0 && inner->name[tlen] == '_') + { + template_name = gt->name; + concrete_arg = inner->name + tlen + 1; // Skip template name and underscore + break; + } + gt = gt->next; + } + + if (template_name && concrete_arg) + { + char *unmangled = unmangle_ptr_suffix(concrete_arg); + instantiate_generic(ctx, template_name, concrete_arg, unmangled, fields->token); + free(unmangled); + } + } + } + n->next = copy_fields_replacing(ctx, fields->next, param, concrete); return n; } |
