| ... | ... | @@ -3280,7 +3280,8 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, |
| 3280 | 3280 | } |
| 3281 | 3281 | |
| 3282 | 3282 | static VariableTableEntry *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_scope, |
| 3283 | | Buf *name, bool src_is_const, bool gen_is_const, bool is_shadowable, IrInstruction *is_comptime) |
| 3283 | Buf *name, bool src_is_const, bool gen_is_const, bool is_shadowable, IrInstruction *is_comptime, |
| 3284 | bool skip_name_check) |
| 3284 | 3285 | { |
| 3285 | 3286 | VariableTableEntry *variable_entry = allocate<VariableTableEntry>(1); |
| 3286 | 3287 | variable_entry->parent_scope = parent_scope; |
| ... | ... | @@ -3293,29 +3294,30 @@ static VariableTableEntry *create_local_var(CodeGen *codegen, AstNode *node, Sco |
| 3293 | 3294 | if (name) { |
| 3294 | 3295 | buf_init_from_buf(&variable_entry->name, name); |
| 3295 | 3296 | |
| 3296 | | VariableTableEntry *existing_var = find_variable(codegen, parent_scope, name); |
| 3297 | | if (existing_var && !existing_var->shadowable) { |
| 3298 | | ErrorMsg *msg = add_node_error(codegen, node, |
| 3299 | | buf_sprintf("redeclaration of variable '%s'", buf_ptr(name))); |
| 3300 | | add_error_note(codegen, msg, existing_var->decl_node, buf_sprintf("previous declaration is here")); |
| 3301 | | variable_entry->value->type = codegen->builtin_types.entry_invalid; |
| 3302 | | } else { |
| 3303 | | TypeTableEntry *type = get_primitive_type(codegen, name); |
| 3304 | | if (type != nullptr) { |
| 3305 | | add_node_error(codegen, node, |
| 3306 | | buf_sprintf("variable shadows type '%s'", buf_ptr(&type->name))); |
| 3297 | if (!skip_name_check) { |
| 3298 | VariableTableEntry *existing_var = find_variable(codegen, parent_scope, name); |
| 3299 | if (existing_var && !existing_var->shadowable) { |
| 3300 | ErrorMsg *msg = add_node_error(codegen, node, |
| 3301 | buf_sprintf("redeclaration of variable '%s'", buf_ptr(name))); |
| 3302 | add_error_note(codegen, msg, existing_var->decl_node, buf_sprintf("previous declaration is here")); |
| 3307 | 3303 | variable_entry->value->type = codegen->builtin_types.entry_invalid; |
| 3308 | 3304 | } else { |
| 3309 | | Tld *tld = find_decl(codegen, parent_scope, name); |
| 3310 | | if (tld != nullptr) { |
| 3311 | | ErrorMsg *msg = add_node_error(codegen, node, |
| 3312 | | buf_sprintf("redefinition of '%s'", buf_ptr(name))); |
| 3313 | | add_error_note(codegen, msg, tld->source_node, buf_sprintf("previous definition is here")); |
| 3305 | TypeTableEntry *type = get_primitive_type(codegen, name); |
| 3306 | if (type != nullptr) { |
| 3307 | add_node_error(codegen, node, |
| 3308 | buf_sprintf("variable shadows type '%s'", buf_ptr(&type->name))); |
| 3314 | 3309 | variable_entry->value->type = codegen->builtin_types.entry_invalid; |
| 3310 | } else { |
| 3311 | Tld *tld = find_decl(codegen, parent_scope, name); |
| 3312 | if (tld != nullptr) { |
| 3313 | ErrorMsg *msg = add_node_error(codegen, node, |
| 3314 | buf_sprintf("redefinition of '%s'", buf_ptr(name))); |
| 3315 | add_error_note(codegen, msg, tld->source_node, buf_sprintf("previous definition is here")); |
| 3316 | variable_entry->value->type = codegen->builtin_types.entry_invalid; |
| 3317 | } |
| 3315 | 3318 | } |
| 3316 | 3319 | } |
| 3317 | 3320 | } |
| 3318 | | |
| 3319 | 3321 | } else { |
| 3320 | 3322 | assert(is_shadowable); |
| 3321 | 3323 | // TODO make this name not actually be in scope. user should be able to make a variable called "_anon" |
| ... | ... | @@ -3338,14 +3340,9 @@ static VariableTableEntry *ir_create_var(IrBuilder *irb, AstNode *node, Scope *s |
| 3338 | 3340 | bool src_is_const, bool gen_is_const, bool is_shadowable, IrInstruction *is_comptime) |
| 3339 | 3341 | { |
| 3340 | 3342 | bool is_underscored = name ? buf_eql_str(name, "_") : false; |
| 3341 | | VariableTableEntry *var = create_local_var( irb->codegen |
| 3342 | | , node |
| 3343 | | , scope |
| 3344 | | , (is_underscored ? nullptr : name) |
| 3345 | | , src_is_const |
| 3346 | | , gen_is_const |
| 3347 | | , (is_underscored ? true : is_shadowable) |
| 3348 | | , is_comptime ); |
| 3343 | VariableTableEntry *var = create_local_var(irb->codegen, node, scope, |
| 3344 | (is_underscored ? nullptr : name), src_is_const, gen_is_const, |
| 3345 | (is_underscored ? true : is_shadowable), is_comptime, false); |
| 3349 | 3346 | if (is_comptime != nullptr || gen_is_const) { |
| 3350 | 3347 | var->mem_slot_index = exec_next_mem_slot(irb->exec); |
| 3351 | 3348 | var->owner_exec = irb->exec; |
| ... | ... | @@ -12495,6 +12492,17 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc |
| 12495 | 12492 | } |
| 12496 | 12493 | } |
| 12497 | 12494 | |
| 12495 | if (var->value->type != nullptr && var->value->type != result_type && !is_comptime_var) { |
| 12496 | // This is at least the second time we've seen this variable declaration during analysis. |
| 12497 | // This means that this is actually a different variable due to, e.g. an inline while loop. |
| 12498 | // We make a new variable so that it can hold a different type, and so the debug info can |
| 12499 | // be distinct. |
| 12500 | VariableTableEntry *new_var = create_local_var(ira->codegen, var->decl_node, var->child_scope, |
| 12501 | &var->name, var->src_is_const, var->gen_is_const, var->shadowable, var->is_comptime, true); |
| 12502 | var->next_var = new_var; |
| 12503 | var = new_var; |
| 12504 | } |
| 12505 | |
| 12498 | 12506 | var->value->type = result_type; |
| 12499 | 12507 | assert(var->value->type); |
| 12500 | 12508 | |
| ... | ... | @@ -12977,6 +12985,10 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, |
| 12977 | 12985 | VariableTableEntry *var) |
| 12978 | 12986 | { |
| 12979 | 12987 | Error err; |
| 12988 | while (var->next_var != nullptr) { |
| 12989 | var = var->next_var; |
| 12990 | } |
| 12991 | |
| 12980 | 12992 | if (var->mem_slot_index != SIZE_MAX && var->owner_exec->analysis == nullptr) { |
| 12981 | 12993 | assert(ira->codegen->errors.length != 0); |
| 12982 | 12994 | return ira->codegen->invalid_instruction; |