| author | |
| committer | |
| log | 2e512a0e6e81532b62ddb7fdafdcd28926690eaa |
| tree | c20acbfa1e99c7d7edef93ac57a86dbe8eee5666 |
| parent | 1691074b4b1f080b3a1f7ca7dc7426c6ef4c242a |
closes #3444 files changed, 28 insertions(+), 2 deletions(-)
src/all_types.hpp+7| ... | ... | @@ -201,6 +201,12 @@ enum RuntimeHintMaybe { |
| 201 | 201 | RuntimeHintMaybeNonNull, |
| 202 | 202 | }; |
| 203 | 203 | |
| 204 | enum RuntimeHintPtr { | |
| 205 | RuntimeHintPtrUnknown, | |
| 206 | RuntimeHintPtrStack, | |
| 207 | RuntimeHintPtrNonStack, | |
| 208 | }; | |
| 209 | ||
| 204 | 210 | struct ConstFn { |
| 205 | 211 | FnTableEntry *fn_entry; |
| 206 | 212 | bool is_inline; |
| ... | ... | @@ -233,6 +239,7 @@ struct ConstExprValue { |
| 233 | 239 | // populated if special == ConstValSpecialRuntime |
| 234 | 240 | RuntimeHintErrorUnion rh_error_union; |
| 235 | 241 | RuntimeHintMaybe rh_maybe; |
| 242 | RuntimeHintPtr rh_ptr; | |
| 236 | 243 | } data; |
| 237 | 244 | }; |
| 238 | 245 |
src/ir.cpp+11| ... | ... | @@ -7538,6 +7538,13 @@ static TypeTableEntry *ir_analyze_instruction_return(IrAnalyze *ira, |
| 7538 | 7538 | if (casted_value == ira->codegen->invalid_instruction) |
| 7539 | 7539 | return ir_unreach_error(ira); |
| 7540 | 7540 | |
| 7541 | if (casted_value->value.special == ConstValSpecialRuntime && | |
| 7542 | casted_value->value.type->id == TypeTableEntryIdPointer && | |
| 7543 | casted_value->value.data.rh_ptr == RuntimeHintPtrStack) | |
| 7544 | { | |
| 7545 | ir_add_error(ira, casted_value, buf_sprintf("function returns address of local variable")); | |
| 7546 | return ir_unreach_error(ira); | |
| 7547 | } | |
| 7541 | 7548 | ir_build_return_from(&ira->new_irb, &return_instruction->base, casted_value); |
| 7542 | 7549 | return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable); |
| 7543 | 7550 | } |
| ... | ... | @@ -8467,6 +8474,10 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, |
| 8467 | 8474 | instruction->scope, instruction->source_node, var, is_const, is_volatile); |
| 8468 | 8475 | var_ptr_instruction->value.type = get_pointer_to_type(ira->codegen, var->value->type, var->src_is_const); |
| 8469 | 8476 | type_ensure_zero_bits_known(ira->codegen, var->value->type); |
| 8477 | ||
| 8478 | bool in_fn_scope = (scope_fn_entry(var->parent_scope) != nullptr); | |
| 8479 | var_ptr_instruction->value.data.rh_ptr = in_fn_scope ? RuntimeHintPtrStack : RuntimeHintPtrNonStack; | |
| 8480 | ||
| 8470 | 8481 | return var_ptr_instruction; |
| 8471 | 8482 | } |
| 8472 | 8483 | } |
std/build.zig+2-2| ... | ... | @@ -887,7 +887,7 @@ pub const LibExeObjStep = struct { |
| 887 | 887 | %%zig_args.append(lib_path); |
| 888 | 888 | } |
| 889 | 889 | |
| 890 | %%builder.spawnChild(builder.zig_exe, zig_args.toSliceConst()); | |
| 890 | %return builder.spawnChild(builder.zig_exe, zig_args.toSliceConst()); | |
| 891 | 891 | |
| 892 | 892 | if (self.kind == Kind.Lib and !self.static) { |
| 893 | 893 | // sym link for libfoo.so.1 to libfoo.so.1.2.3 |
| ... | ... | @@ -994,7 +994,7 @@ pub const TestStep = struct { |
| 994 | 994 | %%zig_args.append(lib_path); |
| 995 | 995 | } |
| 996 | 996 | |
| 997 | %%builder.spawnChild(builder.zig_exe, zig_args.toSliceConst()); | |
| 997 | %return builder.spawnChild(builder.zig_exe, zig_args.toSliceConst()); | |
| 998 | 998 | } |
| 999 | 999 | }; |
| 1000 | 1000 |
test/compile_errors.zig+8| ... | ... | @@ -1610,4 +1610,12 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1610 | 1610 | , |
| 1611 | 1611 | ".tmp_source.zig:3:5: error: cannot set section of external function 'foo'", |
| 1612 | 1612 | ".tmp_source.zig:1:8: note: declared here"); |
| 1613 | ||
| 1614 | cases.add("returning address of local variable", | |
| 1615 | \\export fn foo() -> &i32 { | |
| 1616 | \\ var a: i32 = undefined; | |
| 1617 | \\ return &a; | |
| 1618 | \\} | |
| 1619 | , | |
| 1620 | ".tmp_source.zig:3:13: error: function returns address of local variable"); | |
| 1613 | 1621 | } |