summaryrefslogtreecommitdiff
path: root/src/parser/parser_utils.c
diff options
context:
space:
mode:
authorSAJJA EASWAR <eshwarsajja20@gmail.com>2026-01-24 11:48:25 +0530
committerSAJJA EASWAR <eshwarsajja20@gmail.com>2026-01-24 11:48:25 +0530
commitf8e6dd33e93474024bd3678d5a98477254ab65a2 (patch)
tree772bdf45530de6dfec64420193c5ea6e0841ab3e /src/parser/parser_utils.c
parent22035400ed7b7fcda088a1a5b1ca6505b23bf63f (diff)
Fix generic struct pointer instantiation bug
Diffstat (limited to 'src/parser/parser_utils.c')
-rw-r--r--src/parser/parser_utils.c165
1 files changed, 165 insertions, 0 deletions
diff --git a/src/parser/parser_utils.c b/src/parser/parser_utils.c
index 05ea74a..ae5adcd 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;
@@ -2260,6 +2388,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;
}