authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-05-25 13:48:10-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-05-25 13:48:10-04:00
logfcdd808c5c1b866c2582a17839a53ce7bbbb78d6
tree5c8d30ee489a33022ff28d5916d437dd02b5c960
parent68add5d8286e5c517143b16a457a86a6c23dbc64

fix segfault with array of variadic functions

closes #377

5 files changed, 52 insertions(+), 6 deletions(-)

src/all_types.hpp+1
...@@ -2399,6 +2399,7 @@ struct IrInstructionFnProto {...@@ -2399,6 +2399,7 @@ struct IrInstructionFnProto {
23992399
2400 IrInstruction **param_types;2400 IrInstruction **param_types;
2401 IrInstruction *return_type;2401 IrInstruction *return_type;
2402 bool is_var_args;
2402};2403};
24032404
2404// true if the target value is compile time known, false otherwise2405// true if the target value is compile time known, false otherwise
src/analyze.cpp+11-2
...@@ -987,7 +987,7 @@ TypeTableEntry *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {...@@ -987,7 +987,7 @@ TypeTableEntry *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {
987 return result->value.data.x_type;987 return result->value.data.x_type;
988}988}
989989
990static TypeTableEntry *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id) {990TypeTableEntry *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
991 TypeTableEntry *fn_type = new_type_table_entry(TypeTableEntryIdFn);991 TypeTableEntry *fn_type = new_type_table_entry(TypeTableEntryIdFn);
992 fn_type->is_copyable = false;992 fn_type->is_copyable = false;
993 buf_init_from_str(&fn_type->name, "fn(");993 buf_init_from_str(&fn_type->name, "fn(");
...@@ -2504,7 +2504,11 @@ bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *...@@ -2504,7 +2504,11 @@ bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *
2504 if (expected_type->data.fn.fn_type_id.is_cold != actual_type->data.fn.fn_type_id.is_cold) {2504 if (expected_type->data.fn.fn_type_id.is_cold != actual_type->data.fn.fn_type_id.is_cold) {
2505 return false;2505 return false;
2506 }2506 }
2507 if (actual_type->data.fn.fn_type_id.return_type->id != TypeTableEntryIdUnreachable &&2507 if (expected_type->data.fn.fn_type_id.is_var_args != actual_type->data.fn.fn_type_id.is_var_args) {
2508 return false;
2509 }
2510 if (!expected_type->data.fn.fn_type_id.is_var_args &&
2511 actual_type->data.fn.fn_type_id.return_type->id != TypeTableEntryIdUnreachable &&
2508 !types_match_const_cast_only(2512 !types_match_const_cast_only(
2509 expected_type->data.fn.fn_type_id.return_type,2513 expected_type->data.fn.fn_type_id.return_type,
2510 actual_type->data.fn.fn_type_id.return_type))2514 actual_type->data.fn.fn_type_id.return_type))
...@@ -2515,6 +2519,11 @@ bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *...@@ -2515,6 +2519,11 @@ bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *
2515 return false;2519 return false;
2516 }2520 }
2517 for (size_t i = 0; i < expected_type->data.fn.fn_type_id.param_count; i += 1) {2521 for (size_t i = 0; i < expected_type->data.fn.fn_type_id.param_count; i += 1) {
2522 if (i == expected_type->data.fn.fn_type_id.param_count - 1 &&
2523 expected_type->data.fn.fn_type_id.is_var_args)
2524 {
2525 continue;
2526 }
2518 // note it's reversed for parameters2527 // note it's reversed for parameters
2519 FnTypeParamInfo *actual_param_info = &actual_type->data.fn.fn_type_id.param_info[i];2528 FnTypeParamInfo *actual_param_info = &actual_type->data.fn.fn_type_id.param_info[i];
2520 FnTypeParamInfo *expected_param_info = &expected_type->data.fn.fn_type_id.param_info[i];2529 FnTypeParamInfo *expected_param_info = &expected_type->data.fn.fn_type_id.param_info[i];
src/analyze.hpp+1
...@@ -164,5 +164,6 @@ const char *type_id_name(TypeTableEntryId id);...@@ -164,5 +164,6 @@ const char *type_id_name(TypeTableEntryId id);
164TypeTableEntryId type_id_at_index(size_t index);164TypeTableEntryId type_id_at_index(size_t index);
165size_t type_id_len();165size_t type_id_len();
166size_t type_id_index(TypeTableEntryId id);166size_t type_id_index(TypeTableEntryId id);
167TypeTableEntry *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id);
167168
168#endif169#endif
src/ir.cpp+27-4
...@@ -1857,14 +1857,17 @@ static IrInstruction *ir_build_unwrap_err_payload_from(IrBuilder *irb, IrInstruc...@@ -1857,14 +1857,17 @@ static IrInstruction *ir_build_unwrap_err_payload_from(IrBuilder *irb, IrInstruc
1857}1857}
18581858
1859static IrInstruction *ir_build_fn_proto(IrBuilder *irb, Scope *scope, AstNode *source_node,1859static IrInstruction *ir_build_fn_proto(IrBuilder *irb, Scope *scope, AstNode *source_node,
1860 IrInstruction **param_types, IrInstruction *return_type)1860 IrInstruction **param_types, IrInstruction *return_type, bool is_var_args)
1861{1861{
1862 IrInstructionFnProto *instruction = ir_build_instruction<IrInstructionFnProto>(irb, scope, source_node);1862 IrInstructionFnProto *instruction = ir_build_instruction<IrInstructionFnProto>(irb, scope, source_node);
1863 instruction->param_types = param_types;1863 instruction->param_types = param_types;
1864 instruction->return_type = return_type;1864 instruction->return_type = return_type;
1865 instruction->is_var_args = is_var_args;
18651866
1866 assert(source_node->type == NodeTypeFnProto);1867 assert(source_node->type == NodeTypeFnProto);
1867 for (size_t i = 0; i < source_node->data.fn_proto.params.length; i += 1) {1868 size_t param_count = source_node->data.fn_proto.params.length;
1869 if (is_var_args) param_count -= 1;
1870 for (size_t i = 0; i < param_count; i += 1) {
1868 ir_ref_instruction(param_types[i], irb->current_basic_block);1871 ir_ref_instruction(param_types[i], irb->current_basic_block);
1869 }1872 }
1870 ir_ref_instruction(return_type, irb->current_basic_block);1873 ir_ref_instruction(return_type, irb->current_basic_block);
...@@ -5843,8 +5846,13 @@ static IrInstruction *ir_gen_fn_proto(IrBuilder *irb, Scope *parent_scope, AstNo...@@ -5843,8 +5846,13 @@ static IrInstruction *ir_gen_fn_proto(IrBuilder *irb, Scope *parent_scope, AstNo
5843 size_t param_count = node->data.fn_proto.params.length;5846 size_t param_count = node->data.fn_proto.params.length;
5844 IrInstruction **param_types = allocate<IrInstruction*>(param_count);5847 IrInstruction **param_types = allocate<IrInstruction*>(param_count);
58455848
5849 bool is_var_args = false;
5846 for (size_t i = 0; i < param_count; i += 1) {5850 for (size_t i = 0; i < param_count; i += 1) {
5847 AstNode *param_node = node->data.fn_proto.params.at(i);5851 AstNode *param_node = node->data.fn_proto.params.at(i);
5852 if (param_node->data.param_decl.is_var_args) {
5853 is_var_args = true;
5854 break;
5855 }
5848 AstNode *type_node = param_node->data.param_decl.type;5856 AstNode *type_node = param_node->data.param_decl.type;
5849 IrInstruction *type_value = ir_gen_node(irb, type_node, parent_scope);5857 IrInstruction *type_value = ir_gen_node(irb, type_node, parent_scope);
5850 if (type_value == irb->codegen->invalid_instruction)5858 if (type_value == irb->codegen->invalid_instruction)
...@@ -5856,7 +5864,7 @@ static IrInstruction *ir_gen_fn_proto(IrBuilder *irb, Scope *parent_scope, AstNo...@@ -5856,7 +5864,7 @@ static IrInstruction *ir_gen_fn_proto(IrBuilder *irb, Scope *parent_scope, AstNo
5856 if (return_type == irb->codegen->invalid_instruction)5864 if (return_type == irb->codegen->invalid_instruction)
5857 return irb->codegen->invalid_instruction;5865 return irb->codegen->invalid_instruction;
58585866
5859 return ir_build_fn_proto(irb, parent_scope, node, param_types, return_type);5867 return ir_build_fn_proto(irb, parent_scope, node, param_types, return_type, is_var_args);
5860}5868}
58615869
5862static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scope,5870static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scope,
...@@ -9039,7 +9047,11 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal...@@ -9039,7 +9047,11 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
9039 }9047 }
90409048
9041 if (fn_type->data.fn.is_generic) {9049 if (fn_type->data.fn.is_generic) {
9042 assert(fn_entry);9050 if (!fn_entry) {
9051 ir_add_error(ira, call_instruction->fn_ref,
9052 buf_sprintf("calling a generic function requires compile-time known function value"));
9053 return ira->codegen->builtin_types.entry_invalid;
9054 }
90439055
9044 // Count the arguments of the function type id we are creating9056 // Count the arguments of the function type id we are creating
9045 size_t new_fn_arg_count = first_arg_1_or_0;9057 size_t new_fn_arg_count = first_arg_1_or_0;
...@@ -13065,6 +13077,17 @@ static TypeTableEntry *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruc...@@ -13065,6 +13077,17 @@ static TypeTableEntry *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruc
13065 AstNode *param_node = proto_node->data.fn_proto.params.at(fn_type_id.next_param_index);13077 AstNode *param_node = proto_node->data.fn_proto.params.at(fn_type_id.next_param_index);
13066 assert(param_node->type == NodeTypeParamDecl);13078 assert(param_node->type == NodeTypeParamDecl);
1306713079
13080 bool param_is_var_args = param_node->data.param_decl.is_var_args;
13081 if (param_is_var_args) {
13082 if (fn_type_id.is_extern) {
13083 fn_type_id.param_count = fn_type_id.next_param_index;
13084 continue;
13085 } else {
13086 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
13087 out_val->data.x_type = get_generic_fn_type(ira->codegen, &fn_type_id);
13088 return ira->codegen->builtin_types.entry_type;
13089 }
13090 }
13068 IrInstruction *param_type_value = instruction->param_types[fn_type_id.next_param_index]->other;13091 IrInstruction *param_type_value = instruction->param_types[fn_type_id.next_param_index]->other;
1306913092
13070 FnTypeParamInfo *param_info = &fn_type_id.param_info[fn_type_id.next_param_index];13093 FnTypeParamInfo *param_info = &fn_type_id.param_info[fn_type_id.next_param_index];
test/compile_errors.zig+12
...@@ -1892,4 +1892,16 @@ pub fn addCases(cases: &tests.CompileErrorContext) {...@@ -1892,4 +1892,16 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
1892 \\}1892 \\}
1893 ,1893 ,
1894 ".tmp_source.zig:3:9: error: cannot goto out of defer expression");1894 ".tmp_source.zig:3:9: error: cannot goto out of defer expression");
1895
1896 cases.add("calling a var args function only known at runtime",
1897 \\var foos = []fn(...) { foo1, foo2 };
1898 \\
1899 \\fn foo1(args: ...) {}
1900 \\fn foo2(args: ...) {}
1901 \\
1902 \\pub fn main() -> %void {
1903 \\ foos[0]();
1904 \\}
1905 ,
1906 ".tmp_source.zig:7:9: error: calling a generic function requires compile-time known function value");
1895}1907}