authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-04-27 19:40:35-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-04-27 19:40:35-04:00
log2e512a0e6e81532b62ddb7fdafdcd28926690eaa
treec20acbfa1e99c7d7edef93ac57a86dbe8eee5666
parent1691074b4b1f080b3a1f7ca7dc7426c6ef4c242a

add compile error for returning local variable address

closes #344

4 files changed, 28 insertions(+), 2 deletions(-)

src/all_types.hpp+7
......@@ -201,6 +201,12 @@ enum RuntimeHintMaybe {
201201 RuntimeHintMaybeNonNull,
202202};
203203
204enum RuntimeHintPtr {
205 RuntimeHintPtrUnknown,
206 RuntimeHintPtrStack,
207 RuntimeHintPtrNonStack,
208};
209
204210struct ConstFn {
205211 FnTableEntry *fn_entry;
206212 bool is_inline;
......@@ -233,6 +239,7 @@ struct ConstExprValue {
233239 // populated if special == ConstValSpecialRuntime
234240 RuntimeHintErrorUnion rh_error_union;
235241 RuntimeHintMaybe rh_maybe;
242 RuntimeHintPtr rh_ptr;
236243 } data;
237244};
238245
src/ir.cpp+11
......@@ -7538,6 +7538,13 @@ static TypeTableEntry *ir_analyze_instruction_return(IrAnalyze *ira,
75387538 if (casted_value == ira->codegen->invalid_instruction)
75397539 return ir_unreach_error(ira);
75407540
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 }
75417548 ir_build_return_from(&ira->new_irb, &return_instruction->base, casted_value);
75427549 return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable);
75437550}
......@@ -8467,6 +8474,10 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
84678474 instruction->scope, instruction->source_node, var, is_const, is_volatile);
84688475 var_ptr_instruction->value.type = get_pointer_to_type(ira->codegen, var->value->type, var->src_is_const);
84698476 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
84708481 return var_ptr_instruction;
84718482 }
84728483}
std/build.zig+2-2
......@@ -887,7 +887,7 @@ pub const LibExeObjStep = struct {
887887 %%zig_args.append(lib_path);
888888 }
889889
890 %%builder.spawnChild(builder.zig_exe, zig_args.toSliceConst());
890 %return builder.spawnChild(builder.zig_exe, zig_args.toSliceConst());
891891
892892 if (self.kind == Kind.Lib and !self.static) {
893893 // sym link for libfoo.so.1 to libfoo.so.1.2.3
......@@ -994,7 +994,7 @@ pub const TestStep = struct {
994994 %%zig_args.append(lib_path);
995995 }
996996
997 %%builder.spawnChild(builder.zig_exe, zig_args.toSliceConst());
997 %return builder.spawnChild(builder.zig_exe, zig_args.toSliceConst());
998998 }
999999};
10001000
test/compile_errors.zig+8
......@@ -1610,4 +1610,12 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
16101610 ,
16111611 ".tmp_source.zig:3:5: error: cannot set section of external function 'foo'",
16121612 ".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");
16131621}