authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-02-05 23:20:34-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-02-05 23:20:34-07:00
log6a2ede5a6eb17d6b86e6636457710a3583376fa3
tree5d0968960e8c37e325de3f78d7c1cb86533bdd05
parent4339d555626197f4b8c9598b602f098b76488c2d

parsing code for defer and more

* disable goto and label support see #44 * refactor the way block contexts work

11 files changed, 344 insertions(+), 326 deletions(-)

doc/langref.md+3-1
......@@ -51,7 +51,7 @@ Expression = BlockExpression | NonBlockExpression
5151
5252TypeExpr = PrefixOpExpression
5353
54NonBlockExpression = ReturnExpression | AssignmentExpression
54NonBlockExpression = ReturnExpression | AssignmentExpression | DeferExpression
5555
5656AsmExpression = "asm" option("volatile") "(" "String" option(AsmOutput) ")"
5757
......@@ -91,6 +91,8 @@ BoolOrExpression = BoolAndExpression "||" BoolOrExpression | BoolAndExpression
9191
9292ReturnExpression = option("%" | "?") "return" option(Expression)
9393
94DeferExpression = option("%" | "?") "defer" option(Expression)
95
9496IfExpression = IfVarExpression | IfBoolExpression
9597
9698IfBoolExpression = "if" "(" Expression ")" Expression option(Else)
src/all_types.hpp+39-21
......@@ -24,7 +24,6 @@ struct TypeTableEntry;
2424struct VariableTableEntry;
2525struct ErrorTableEntry;
2626struct BuiltinFnEntry;
27struct LabelTableEntry;
2827struct TypeStructField;
2928struct CodeGen;
3029struct ConstExprValue;
......@@ -118,6 +117,7 @@ enum NodeType {
118117 NodeTypeBlock,
119118 NodeTypeDirective,
120119 NodeTypeReturnExpr,
120 NodeTypeDeferExpr,
121121 NodeTypeVariableDeclaration,
122122 NodeTypeTypeDecl,
123123 NodeTypeErrorValueDecl,
......@@ -235,6 +235,16 @@ struct AstNodeReturnExpr {
235235 Expr resolved_expr;
236236};
237237
238struct AstNodeDeferExpr {
239 ReturnKind kind;
240 AstNode *expr;
241
242 // populated by semantic analyzer:
243 Expr resolved_expr;
244 int index_in_block;
245 LLVMBasicBlockRef basic_block;
246};
247
238248struct AstNodeVariableDeclaration {
239249 Buf symbol;
240250 bool is_const;
......@@ -477,7 +487,6 @@ struct AstNodeWhileExpr {
477487 bool contains_break;
478488 bool contains_continue;
479489 Expr resolved_expr;
480 BlockContext *block_context;
481490};
482491
483492struct AstNodeForExpr {
......@@ -522,7 +531,6 @@ struct AstNodeLabel {
522531 Buf name;
523532
524533 // populated by semantic analyzer
525 LabelTableEntry *label_entry;
526534 Expr resolved_expr;
527535};
528536
......@@ -530,7 +538,6 @@ struct AstNodeGoto {
530538 Buf name;
531539
532540 // populated by semantic analyzer
533 LabelTableEntry *label_entry;
534541 Expr resolved_expr;
535542};
536543
......@@ -732,6 +739,7 @@ struct AstNode {
732739 AstNodeParamDecl param_decl;
733740 AstNodeBlock block;
734741 AstNodeReturnExpr return_expr;
742 AstNodeDeferExpr defer_expr;
735743 AstNodeVariableDeclaration variable_declaration;
736744 AstNodeTypeDecl type_decl;
737745 AstNodeErrorValueDecl error_value_decl;
......@@ -967,13 +975,8 @@ struct ImportTableEntry {
967975
968976 // reminder: hash tables must be initialized before use
969977 HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;
970};
971
972struct LabelTableEntry {
973 AstNode *label_node;
974 LLVMBasicBlockRef basic_block;
975 bool used;
976 bool entered_from_fallthrough;
978 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> type_table;
979 HashMap<Buf *, ErrorTableEntry *, buf_hash, buf_eql_buf> error_table;
977980};
978981
979982struct FnTableEntry {
......@@ -992,8 +995,9 @@ struct FnTableEntry {
992995 bool is_test;
993996 uint32_t ref_count; // if this is 0 we don't have to codegen it
994997
995 // reminder: hash tables must be initialized before use
996 HashMap<Buf *, LabelTableEntry *, buf_hash, buf_eql_buf> label_table;
998 ZigList<AstNode *> cast_alloca_list;
999 ZigList<StructValExprCodeGen *> struct_val_expr_alloca_list;
1000 ZigList<VariableTableEntry *> variable_list;
9971001};
9981002
9991003enum BuiltinFnId {
......@@ -1140,6 +1144,7 @@ struct VariableTableEntry {
11401144 LLVMZigDILocalVariable *di_loc_var;
11411145 int src_arg_index;
11421146 int gen_arg_index;
1147 BlockContext *block_context;
11431148};
11441149
11451150struct ErrorTableEntry {
......@@ -1148,19 +1153,32 @@ struct ErrorTableEntry {
11481153 AstNode *decl_node;
11491154};
11501155
1156enum BlockExitPath {
1157 BlockExitPathFallthrough,
1158 BlockExitPathReturn,
1159 BlockExitPathGoto,
1160};
1161
11511162struct BlockContext {
1152 AstNode *node; // either NodeTypeFnDef or NodeTypeBlock or NodeTypeRoot
1153 FnTableEntry *fn_entry; // null at the module scope
1154 BlockContext *parent; // null when this is the root
1163 // One of: NodeTypeFnDef, NodeTypeBlock, NodeTypeRoot, NodeTypeDeferExpr, NodeTypeVariableDeclaration
1164 AstNode *node;
1165
1166 // any variables that are introduced by this scope
11551167 HashMap<Buf *, VariableTableEntry *, buf_hash, buf_eql_buf> variable_table;
1156 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> type_table;
1157 HashMap<Buf *, ErrorTableEntry *, buf_hash, buf_eql_buf> error_table;
1158 ZigList<AstNode *> cast_alloca_list;
1159 ZigList<StructValExprCodeGen *> struct_val_expr_alloca_list;
1160 ZigList<VariableTableEntry *> variable_list;
1168
1169 // if the block is inside a function, this is the function it is in:
1170 FnTableEntry *fn_entry;
1171
1172 // if the block has a parent, this is it
1173 BlockContext *parent;
1174
1175 // if break or continue is valid in this context, this is the loop node that
1176 // it would pertain to
11611177 AstNode *parent_loop_node;
1178
11621179 LLVMZigDIScope *di_scope;
11631180 Buf *c_import_buf;
1181 bool block_exit_paths[3]; // one for each BlockExitPath
11641182};
11651183
11661184enum CIntType {
src/analyze.cpp+181-181
......@@ -57,6 +57,7 @@ static AstNode *first_executing_node(AstNode *node) {
5757 case NodeTypeBlock:
5858 case NodeTypeDirective:
5959 case NodeTypeReturnExpr:
60 case NodeTypeDeferExpr:
6061 case NodeTypeVariableDeclaration:
6162 case NodeTypeTypeDecl:
6263 case NodeTypeErrorValueDecl:
......@@ -865,23 +866,6 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
865866 }
866867}
867868
868static void preview_function_labels(CodeGen *g, AstNode *node, FnTableEntry *fn_table_entry) {
869 assert(node->type == NodeTypeBlock);
870
871 for (int i = 0; i < node->data.block.statements.length; i += 1) {
872 AstNode *label_node = node->data.block.statements.at(i);
873 if (label_node->type != NodeTypeLabel)
874 continue;
875
876 LabelTableEntry *label_entry = allocate<LabelTableEntry>(1);
877 label_entry->label_node = label_node;
878 Buf *name = &label_node->data.label.name;
879 fn_table_entry->label_table.put(name, label_entry);
880
881 label_node->data.label.label_entry = label_entry;
882 }
883}
884
885869static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *enum_type) {
886870 // if you change this logic you likely must also change similar logic in parseh.cpp
887871 assert(enum_type->id == TypeTableEntryIdEnum);
......@@ -1233,7 +1217,6 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,
12331217 fn_table_entry->fn_def_node = fn_def_node;
12341218 fn_table_entry->internal_linkage = !is_c_compat;
12351219 fn_table_entry->is_extern = is_extern;
1236 fn_table_entry->label_table.init(8);
12371220 fn_table_entry->member_of_struct = struct_type;
12381221 fn_table_entry->ref_count = (proto_node->data.fn_proto.visib_mod == VisibModExport) ? 1 : 0;
12391222
......@@ -1272,10 +1255,6 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,
12721255 proto_node->data.fn_proto.fn_table_entry = fn_table_entry;
12731256 resolve_function_proto(g, proto_node, fn_table_entry, import);
12741257
1275 if (fn_def_node) {
1276 preview_function_labels(g, fn_def_node->data.fn_def.body, fn_table_entry);
1277 }
1278
12791258 if (is_pub && !struct_type) {
12801259 for (int i = 0; i < import->importers.length; i += 1) {
12811260 ImporterInfo importer = import->importers.at(i);
......@@ -1317,13 +1296,13 @@ static void resolve_error_value_decl(CodeGen *g, ImportTableEntry *import, AstNo
13171296
13181297 ErrorTableEntry *err = node->data.error_value_decl.err;
13191298
1320 import->block_context->error_table.put(&err->name, err);
1299 import->error_table.put(&err->name, err);
13211300
13221301 bool is_pub = (node->data.error_value_decl.visib_mod != VisibModPrivate);
13231302 if (is_pub) {
13241303 for (int i = 0; i < import->importers.length; i += 1) {
13251304 ImporterInfo importer = import->importers.at(i);
1326 importer.import->block_context->error_table.put(&err->name, err);
1305 importer.import->error_table.put(&err->name, err);
13271306 }
13281307 }
13291308}
......@@ -1347,6 +1326,8 @@ static void resolve_c_import_decl(CodeGen *g, ImportTableEntry *parent_import, A
13471326
13481327 ImportTableEntry *child_import = allocate<ImportTableEntry>(1);
13491328 child_import->fn_table.init(32);
1329 child_import->type_table.init(8);
1330 child_import->error_table.init(8);
13501331 child_import->c_import_node = node;
13511332
13521333 ZigList<ErrorMsg *> errors = {0};
......@@ -1442,19 +1423,19 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
14421423 }
14431424 }
14441425
1445 import->block_context->type_table.put(decl_name, entry);
1426 import->type_table.put(decl_name, entry);
14461427
14471428 bool is_pub = (node->data.type_decl.visib_mod != VisibModPrivate);
14481429 if (is_pub) {
14491430 for (int i = 0; i < import->importers.length; i += 1) {
14501431 ImporterInfo importer = import->importers.at(i);
1451 auto table_entry = importer.import->block_context->type_table.maybe_get(&entry->name);
1432 auto table_entry = importer.import->type_table.maybe_get(&entry->name);
14521433 if (table_entry) {
14531434 add_node_error(g, importer.source_node,
14541435 buf_sprintf("import of type '%s' overrides existing definition",
14551436 buf_ptr(&entry->name)));
14561437 } else {
1457 importer.import->block_context->type_table.put(&entry->name, entry);
1438 importer.import->type_table.put(&entry->name, entry);
14581439 }
14591440 }
14601441 }
......@@ -1475,6 +1456,7 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
14751456 case NodeTypeParamDecl:
14761457 case NodeTypeFnDecl:
14771458 case NodeTypeReturnExpr:
1459 case NodeTypeDeferExpr:
14781460 case NodeTypeRoot:
14791461 case NodeTypeBlock:
14801462 case NodeTypeBinOpExpr:
......@@ -1953,9 +1935,7 @@ BlockContext *new_block_context(AstNode *node, BlockContext *parent) {
19531935 BlockContext *context = allocate<BlockContext>(1);
19541936 context->node = node;
19551937 context->parent = parent;
1956 context->variable_table.init(8);
1957 context->type_table.init(8);
1958 context->error_table.init(8);
1938 context->variable_table.init(4);
19591939
19601940 if (parent) {
19611941 context->parent_loop_node = parent->parent_loop_node;
......@@ -1976,10 +1956,10 @@ BlockContext *new_block_context(AstNode *node, BlockContext *parent) {
19761956 return context;
19771957}
19781958
1979static VariableTableEntry *find_local_variable(BlockContext *context, Buf *name) {
1980 while (context && context->fn_entry) {
1959static VariableTableEntry *find_variable(BlockContext *context, Buf *name, bool local_only) {
1960 while (context && (!local_only || context->fn_entry)) {
19811961 auto entry = context->variable_table.maybe_get(name);
1982 if (entry != nullptr)
1962 if (entry)
19831963 return entry->value;
19841964
19851965 context = context->parent;
......@@ -1987,26 +1967,12 @@ static VariableTableEntry *find_local_variable(BlockContext *context, Buf *name)
19871967 return nullptr;
19881968}
19891969
1990VariableTableEntry *find_variable(BlockContext *context, Buf *name) {
1991 while (context) {
1992 auto entry = context->variable_table.maybe_get(name);
1993 if (entry != nullptr)
1994 return entry->value;
1995
1996 context = context->parent;
1997 }
1998 return nullptr;
1999}
2000
2001TypeTableEntry *find_container(BlockContext *context, Buf *name) {
2002 while (context) {
2003 auto entry = context->type_table.maybe_get(name);
2004 if (entry != nullptr)
2005 return entry->value;
2006
2007 context = context->parent;
2008 }
2009 return nullptr;
1970static TypeTableEntry *find_container(ImportTableEntry *import, Buf *name) {
1971 auto entry = import->type_table.maybe_get(name);
1972 if (entry)
1973 return entry->value;
1974 else
1975 return nullptr;
20101976}
20111977
20121978static TypeEnumField *get_enum_field(TypeTableEntry *enum_type, Buf *name) {
......@@ -2034,7 +2000,7 @@ static TypeTableEntry *analyze_enum_value_expr(CodeGen *g, ImportTableEntry *imp
20342000 StructValExprCodeGen *codegen = &field_access_node->data.field_access_expr.resolved_struct_val_expr;
20352001 codegen->type_entry = enum_type;
20362002 codegen->source_node = field_access_node;
2037 context->struct_val_expr_alloca_list.append(codegen);
2003 context->fn_entry->struct_val_expr_alloca_list.append(codegen);
20382004
20392005 Expr *expr = get_resolved_expr(field_access_node);
20402006 expr->const_val.ok = false;
......@@ -2099,7 +2065,6 @@ static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry
20992065 StructValExprCodeGen *codegen = &container_init_expr->resolved_struct_val_expr;
21002066 codegen->type_entry = container_type;
21012067 codegen->source_node = node;
2102 context->struct_val_expr_alloca_list.append(codegen);
21032068
21042069
21052070 int expr_field_count = container_init_expr->entries.length;
......@@ -2150,6 +2115,9 @@ static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry
21502115 const_val->ok = false;
21512116 }
21522117 }
2118 if (!const_val->ok) {
2119 context->fn_entry->struct_val_expr_alloca_list.append(codegen);
2120 }
21532121 }
21542122
21552123 for (int i = 0; i < actual_field_count; i += 1) {
......@@ -2192,7 +2160,9 @@ static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry
21922160 StructValExprCodeGen *codegen = &container_init_expr->resolved_struct_val_expr;
21932161 codegen->type_entry = fixed_size_array_type;
21942162 codegen->source_node = node;
2195 context->struct_val_expr_alloca_list.append(codegen);
2163 if (!const_val->ok) {
2164 context->fn_entry->struct_val_expr_alloca_list.append(codegen);
2165 }
21962166
21972167 return fixed_size_array_type;
21982168 } else if (container_type->id == TypeTableEntryIdArray) {
......@@ -2339,7 +2309,7 @@ static TypeTableEntry *analyze_slice_expr(CodeGen *g, ImportTableEntry *import,
23392309 if (return_type->id != TypeTableEntryIdInvalid) {
23402310 node->data.slice_expr.resolved_struct_val_expr.type_entry = return_type;
23412311 node->data.slice_expr.resolved_struct_val_expr.source_node = node;
2342 context->struct_val_expr_alloca_list.append(&node->data.slice_expr.resolved_struct_val_expr);
2312 context->fn_entry->struct_val_expr_alloca_list.append(&node->data.slice_expr.resolved_struct_val_expr);
23432313 }
23442314
23452315 analyze_expression(g, import, context, g->builtin_types.entry_isize, node->data.slice_expr.start);
......@@ -2518,7 +2488,7 @@ static TypeTableEntry *resolve_expr_const_val_as_bignum_op(CodeGen *g, AstNode *
25182488static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *import,
25192489 BlockContext *context, AstNode *node, Buf *err_name)
25202490{
2521 auto err_table_entry = import->block_context->error_table.maybe_get(err_name);
2491 auto err_table_entry = import->error_table.maybe_get(err_name);
25222492
25232493 if (err_table_entry) {
25242494 return resolve_expr_const_val_as_err(g, node, err_table_entry->value);
......@@ -2545,7 +2515,7 @@ static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import,
25452515 return resolve_expr_const_val_as_type(g, node, primitive_table_entry->value);
25462516 }
25472517
2548 VariableTableEntry *var = find_variable(context, variable_name);
2518 VariableTableEntry *var = find_variable(context, variable_name, false);
25492519 if (var) {
25502520 node->data.symbol_expr.variable = var;
25512521 if (var->is_const) {
......@@ -2561,7 +2531,7 @@ static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import,
25612531 return var->type;
25622532 }
25632533
2564 TypeTableEntry *container_type = find_container(context, variable_name);
2534 TypeTableEntry *container_type = find_container(import, variable_name);
25652535 if (container_type) {
25662536 return resolve_expr_const_val_as_type(g, node, container_type);
25672537 }
......@@ -2641,7 +2611,7 @@ static TypeTableEntry *analyze_lvalue(CodeGen *g, ImportTableEntry *import, Bloc
26412611 if (purpose == LValPurposeAddressOf) {
26422612 expected_rhs_type = analyze_symbol_expr(g, import, block_context, nullptr, lhs_node);
26432613 } else {
2644 VariableTableEntry *var = find_variable(block_context, name);
2614 VariableTableEntry *var = find_variable(block_context, name, false);
26452615 if (var) {
26462616 if (var->is_const) {
26472617 add_node_error(g, lhs_node, buf_sprintf("cannot assign to constant"));
......@@ -3011,21 +2981,18 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import,
30112981}
30122982
30132983// Set name to nullptr to make the variable anonymous (not visible to programmer).
3014static VariableTableEntry *add_local_var(CodeGen *g, AstNode *source_node, BlockContext *context,
3015 Buf *name, TypeTableEntry *type_entry, bool is_const)
2984static VariableTableEntry *add_local_var(CodeGen *g, AstNode *source_node, ImportTableEntry *import,
2985 BlockContext *context, Buf *name, TypeTableEntry *type_entry, bool is_const)
30162986{
30172987 VariableTableEntry *variable_entry = allocate<VariableTableEntry>(1);
30182988 variable_entry->type = type_entry;
2989 variable_entry->block_context = context;
30192990
30202991 if (name) {
30212992 buf_init_from_buf(&variable_entry->name, name);
30222993 VariableTableEntry *existing_var;
30232994
3024 if (context->fn_entry) {
3025 existing_var = find_local_variable(context, name);
3026 } else {
3027 existing_var = find_variable(context, name);
3028 }
2995 existing_var = find_variable(context, name, context->fn_entry != nullptr);
30292996
30302997 if (existing_var) {
30312998 add_node_error(g, source_node, buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));
......@@ -3036,7 +3003,7 @@ static VariableTableEntry *add_local_var(CodeGen *g, AstNode *source_node, Block
30363003 if (primitive_table_entry) {
30373004 type = primitive_table_entry->value;
30383005 } else {
3039 type = find_container(context, name);
3006 type = find_container(import, name);
30403007 }
30413008 if (type) {
30423009 add_node_error(g, source_node, buf_sprintf("variable shadows type '%s'", buf_ptr(&type->name)));
......@@ -3045,10 +3012,11 @@ static VariableTableEntry *add_local_var(CodeGen *g, AstNode *source_node, Block
30453012 }
30463013
30473014 context->variable_table.put(&variable_entry->name, variable_entry);
3048 context->variable_list.append(variable_entry);
30493015 } else {
30503016 buf_init_from_str(&variable_entry->name, "_anon");
3051 context->variable_list.append(variable_entry);
3017 }
3018 if (context->fn_entry) {
3019 context->fn_entry->variable_list.append(variable_entry);
30523020 }
30533021
30543022 variable_entry->is_const = is_const;
......@@ -3075,7 +3043,7 @@ static TypeTableEntry *analyze_unwrap_error_expr(CodeGen *g, ImportTableEntry *i
30753043 child_context = new_block_context(node, parent_context);
30763044 var_node->block_context = child_context;
30773045 Buf *var_name = &var_node->data.symbol_expr.symbol;
3078 node->data.unwrap_err_expr.var = add_local_var(g, var_node, child_context, var_name,
3046 node->data.unwrap_err_expr.var = add_local_var(g, var_node, import, child_context, var_name,
30793047 g->builtin_types.entry_pure_error, true);
30803048 } else {
30813049 child_context = parent_context;
......@@ -3153,7 +3121,7 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa
31533121 TypeTableEntry *type = explicit_type != nullptr ? explicit_type : implicit_type;
31543122 assert(type != nullptr); // should have been caught by the parser
31553123
3156 VariableTableEntry *var = add_local_var(g, source_node, context,
3124 VariableTableEntry *var = add_local_var(g, source_node, import, context,
31573125 &variable_declaration->symbol, type, is_const);
31583126
31593127 variable_declaration->variable = var;
......@@ -3199,7 +3167,7 @@ static TypeTableEntry *analyze_null_literal_expr(CodeGen *g, ImportTableEntry *i
31993167
32003168 node->data.null_literal.resolved_struct_val_expr.type_entry = expected_type;
32013169 node->data.null_literal.resolved_struct_val_expr.source_node = node;
3202 block_context->struct_val_expr_alloca_list.append(&node->data.null_literal.resolved_struct_val_expr);
3170 block_context->fn_entry->struct_val_expr_alloca_list.append(&node->data.null_literal.resolved_struct_val_expr);
32033171
32043172 return resolve_expr_const_val_as_null(g, node, expected_type);
32053173}
......@@ -3303,7 +3271,6 @@ static TypeTableEntry *analyze_while_expr(CodeGen *g, ImportTableEntry *import,
33033271
33043272 BlockContext *child_context = new_block_context(node, context);
33053273 child_context->parent_loop_node = node;
3306 node->data.while_expr.block_context = child_context;
33073274
33083275 analyze_expression(g, import, child_context, g->builtin_types.entry_void, while_body_node);
33093276
......@@ -3359,16 +3326,16 @@ static TypeTableEntry *analyze_for_expr(CodeGen *g, ImportTableEntry *import, Bl
33593326 AstNode *elem_var_node = node->data.for_expr.elem_node;
33603327 elem_var_node->block_context = child_context;
33613328 Buf *elem_var_name = &elem_var_node->data.symbol_expr.symbol;
3362 node->data.for_expr.elem_var = add_local_var(g, elem_var_node, child_context, elem_var_name, child_type, true);
3329 node->data.for_expr.elem_var = add_local_var(g, elem_var_node, import, child_context, elem_var_name, child_type, true);
33633330
33643331 AstNode *index_var_node = node->data.for_expr.index_node;
33653332 if (index_var_node) {
33663333 Buf *index_var_name = &index_var_node->data.symbol_expr.symbol;
33673334 index_var_node->block_context = child_context;
3368 node->data.for_expr.index_var = add_local_var(g, index_var_node, child_context, index_var_name,
3335 node->data.for_expr.index_var = add_local_var(g, index_var_node, import, child_context, index_var_name,
33693336 g->builtin_types.entry_isize, true);
33703337 } else {
3371 node->data.for_expr.index_var = add_local_var(g, node, child_context, nullptr,
3338 node->data.for_expr.index_var = add_local_var(g, node, import, child_context, nullptr,
33723339 g->builtin_types.entry_isize, true);
33733340 }
33743341
......@@ -3617,6 +3584,21 @@ static void eval_const_expr_implicit_cast(CodeGen *g, AstNode *node, AstNode *ex
36173584 }
36183585}
36193586
3587static TypeTableEntry *resolve_cast(CodeGen *g, BlockContext *context, AstNode *node,
3588 AstNode *expr_node, TypeTableEntry *wanted_type, CastOp op, bool need_alloca)
3589{
3590 node->data.fn_call_expr.cast_op = op;
3591 eval_const_expr_implicit_cast(g, node, expr_node);
3592 if (need_alloca) {
3593 if (context->fn_entry) {
3594 context->fn_entry->cast_alloca_list.append(node);
3595 } else {
3596 assert(get_resolved_expr(node)->const_val.ok);
3597 }
3598 }
3599 return wanted_type;
3600}
3601
36203602static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
36213603 AstNode *node)
36223604{
......@@ -3642,27 +3624,21 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
36423624
36433625 // explicit match or non-const to const
36443626 if (types_match_const_cast_only(wanted_type, actual_type)) {
3645 node->data.fn_call_expr.cast_op = CastOpNoop;
3646 eval_const_expr_implicit_cast(g, node, expr_node);
3647 return wanted_type;
3627 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpNoop, false);
36483628 }
36493629
36503630 // explicit cast from bool to int
36513631 if (wanted_type->id == TypeTableEntryIdInt &&
36523632 actual_type->id == TypeTableEntryIdBool)
36533633 {
3654 node->data.fn_call_expr.cast_op = CastOpBoolToInt;
3655 eval_const_expr_implicit_cast(g, node, expr_node);
3656 return wanted_type;
3634 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpBoolToInt, false);
36573635 }
36583636
36593637 // explicit cast from pointer to isize or usize
36603638 if ((wanted_type == g->builtin_types.entry_isize || wanted_type == g->builtin_types.entry_usize) &&
36613639 actual_type->id == TypeTableEntryIdPointer)
36623640 {
3663 node->data.fn_call_expr.cast_op = CastOpPtrToInt;
3664 eval_const_expr_implicit_cast(g, node, expr_node);
3665 return wanted_type;
3641 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpPtrToInt, false);
36663642 }
36673643
36683644
......@@ -3670,9 +3646,7 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
36703646 if (wanted_type->id == TypeTableEntryIdPointer &&
36713647 (actual_type == g->builtin_types.entry_isize || actual_type == g->builtin_types.entry_usize))
36723648 {
3673 node->data.fn_call_expr.cast_op = CastOpIntToPtr;
3674 eval_const_expr_implicit_cast(g, node, expr_node);
3675 return wanted_type;
3649 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpIntToPtr, false);
36763650 }
36773651
36783652 // explicit widening or shortening cast
......@@ -3681,27 +3655,21 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
36813655 (wanted_type->id == TypeTableEntryIdFloat &&
36823656 actual_type->id == TypeTableEntryIdFloat))
36833657 {
3684 node->data.fn_call_expr.cast_op = CastOpWidenOrShorten;
3685 eval_const_expr_implicit_cast(g, node, expr_node);
3686 return wanted_type;
3658 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpWidenOrShorten, false);
36873659 }
36883660
36893661 // explicit cast from int to float
36903662 if (wanted_type->id == TypeTableEntryIdFloat &&
36913663 actual_type->id == TypeTableEntryIdInt)
36923664 {
3693 node->data.fn_call_expr.cast_op = CastOpIntToFloat;
3694 eval_const_expr_implicit_cast(g, node, expr_node);
3695 return wanted_type;
3665 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpIntToFloat, false);
36963666 }
36973667
36983668 // explicit cast from float to int
36993669 if (wanted_type->id == TypeTableEntryIdInt &&
37003670 actual_type->id == TypeTableEntryIdFloat)
37013671 {
3702 node->data.fn_call_expr.cast_op = CastOpFloatToInt;
3703 eval_const_expr_implicit_cast(g, node, expr_node);
3704 return wanted_type;
3672 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpFloatToInt, false);
37053673 }
37063674
37073675 // explicit cast from fixed size array to unknown size array
......@@ -3712,36 +3680,25 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
37123680 wanted_type->data.structure.fields[0].type_entry->data.pointer.child_type,
37133681 actual_type->data.array.child_type))
37143682 {
3715 node->data.fn_call_expr.cast_op = CastOpToUnknownSizeArray;
3716 context->cast_alloca_list.append(node);
3717 eval_const_expr_implicit_cast(g, node, expr_node);
3718 return wanted_type;
3683 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpToUnknownSizeArray, true);
37193684 }
37203685
37213686 // explicit cast from pointer to another pointer
37223687 if (actual_type->id == TypeTableEntryIdPointer &&
37233688 wanted_type->id == TypeTableEntryIdPointer)
37243689 {
3725 node->data.fn_call_expr.cast_op = CastOpPointerReinterpret;
3726 eval_const_expr_implicit_cast(g, node, expr_node);
3727 return wanted_type;
3690 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpPointerReinterpret, false);
37283691 }
37293692
37303693 // explicit cast from child type of maybe type to maybe type
37313694 if (wanted_type->id == TypeTableEntryIdMaybe) {
37323695 if (types_match_const_cast_only(wanted_type->data.maybe.child_type, actual_type)) {
3733 node->data.fn_call_expr.cast_op = CastOpMaybeWrap;
3734 context->cast_alloca_list.append(node);
3735 eval_const_expr_implicit_cast(g, node, expr_node);
3736 return wanted_type;
3696 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpMaybeWrap, true);
37373697 } else if (actual_type->id == TypeTableEntryIdNumLitInt ||
37383698 actual_type->id == TypeTableEntryIdNumLitFloat)
37393699 {
37403700 if (num_lit_fits_in_other_type(g, expr_node, wanted_type->data.maybe.child_type)) {
3741 node->data.fn_call_expr.cast_op = CastOpMaybeWrap;
3742 context->cast_alloca_list.append(node);
3743 eval_const_expr_implicit_cast(g, node, expr_node);
3744 return wanted_type;
3701 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpMaybeWrap, true);
37453702 } else {
37463703 return g->builtin_types.entry_invalid;
37473704 }
......@@ -3751,18 +3708,12 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
37513708 // explicit cast from child type of error type to error type
37523709 if (wanted_type->id == TypeTableEntryIdErrorUnion) {
37533710 if (types_match_const_cast_only(wanted_type->data.error.child_type, actual_type)) {
3754 node->data.fn_call_expr.cast_op = CastOpErrorWrap;
3755 context->cast_alloca_list.append(node);
3756 eval_const_expr_implicit_cast(g, node, expr_node);
3757 return wanted_type;
3711 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpErrorWrap, true);
37583712 } else if (actual_type->id == TypeTableEntryIdNumLitInt ||
37593713 actual_type->id == TypeTableEntryIdNumLitFloat)
37603714 {
37613715 if (num_lit_fits_in_other_type(g, expr_node, wanted_type->data.error.child_type)) {
3762 node->data.fn_call_expr.cast_op = CastOpErrorWrap;
3763 context->cast_alloca_list.append(node);
3764 eval_const_expr_implicit_cast(g, node, expr_node);
3765 return wanted_type;
3716 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpErrorWrap, true);
37663717 } else {
37673718 return g->builtin_types.entry_invalid;
37683719 }
......@@ -3773,9 +3724,7 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
37733724 if (wanted_type->id == TypeTableEntryIdErrorUnion &&
37743725 actual_type->id == TypeTableEntryIdPureError)
37753726 {
3776 node->data.fn_call_expr.cast_op = CastOpPureErrorWrap;
3777 eval_const_expr_implicit_cast(g, node, expr_node);
3778 return wanted_type;
3727 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpPureErrorWrap, false);
37793728 }
37803729
37813730 // explicit cast from number literal to another type
......@@ -3783,21 +3732,21 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
37833732 actual_type->id == TypeTableEntryIdNumLitInt)
37843733 {
37853734 if (num_lit_fits_in_other_type(g, expr_node, wanted_type)) {
3735 CastOp op;
37863736 if ((actual_type->id == TypeTableEntryIdNumLitFloat &&
37873737 wanted_type->id == TypeTableEntryIdFloat) ||
37883738 (actual_type->id == TypeTableEntryIdNumLitInt &&
37893739 wanted_type->id == TypeTableEntryIdInt))
37903740 {
3791 node->data.fn_call_expr.cast_op = CastOpNoop;
3741 op = CastOpNoop;
37923742 } else if (wanted_type->id == TypeTableEntryIdInt) {
3793 node->data.fn_call_expr.cast_op = CastOpFloatToInt;
3743 op = CastOpFloatToInt;
37943744 } else if (wanted_type->id == TypeTableEntryIdFloat) {
3795 node->data.fn_call_expr.cast_op = CastOpIntToFloat;
3745 op = CastOpIntToFloat;
37963746 } else {
37973747 zig_unreachable();
37983748 }
3799 eval_const_expr_implicit_cast(g, node, expr_node);
3800 return wanted_type;
3749 return resolve_cast(g, context, node, expr_node, wanted_type, op, false);
38013750 } else {
38023751 return g->builtin_types.entry_invalid;
38033752 }
......@@ -3815,9 +3764,7 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
38153764 if (bignum_fits_in_bits(&bn, wanted_type->data.integral.bit_count,
38163765 wanted_type->data.integral.is_signed))
38173766 {
3818 node->data.fn_call_expr.cast_op = CastOpErrToInt;
3819 eval_const_expr_implicit_cast(g, node, expr_node);
3820 return wanted_type;
3767 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpErrToInt, false);
38213768 } else {
38223769 add_node_error(g, node,
38233770 buf_sprintf("too many error values to fit in '%s'", buf_ptr(&wanted_type->name)));
......@@ -4176,7 +4123,7 @@ static TypeTableEntry *analyze_fn_call_ptr(CodeGen *g, ImportTableEntry *import,
41764123 }
41774124
41784125 if (handle_is_ptr(return_type)) {
4179 context->cast_alloca_list.append(node);
4126 context->fn_entry->cast_alloca_list.append(node);
41804127 }
41814128
41824129 return return_type;
......@@ -4572,8 +4519,8 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import,
45724519 assert(var_node->type == NodeTypeSymbol);
45734520 Buf *var_name = &var_node->data.symbol_expr.symbol;
45744521 var_node->block_context = child_context;
4575 prong_node->data.switch_prong.var = add_local_var(g, var_node, child_context, var_name,
4576 var_type, true);
4522 prong_node->data.switch_prong.var = add_local_var(g, var_node, import,
4523 child_context, var_name, var_type, true);
45774524 prong_node->data.switch_prong.var_is_target_expr = var_is_target_expr;
45784525 }
45794526
......@@ -4598,6 +4545,9 @@ static TypeTableEntry *analyze_return_expr(CodeGen *g, ImportTableEntry *import,
45984545 normalize_parent_ptrs(node);
45994546 }
46004547
4548 // TODO follow the blocks to their parents, loop over all of them, set them all to true
4549 context->block_exit_paths[BlockExitPathReturn] = true;
4550
46014551 TypeTableEntry *expected_return_type = get_return_type(context);
46024552
46034553 switch (node->data.return_expr.kind) {
......@@ -4632,6 +4582,71 @@ static TypeTableEntry *analyze_return_expr(CodeGen *g, ImportTableEntry *import,
46324582 }
46334583}
46344584
4585static void validate_voided_expr(CodeGen *g, AstNode *source_node, TypeTableEntry *type_entry) {
4586 if (type_entry->id == TypeTableEntryIdMetaType) {
4587 add_node_error(g, first_executing_node(source_node), buf_sprintf("expected expression, found type"));
4588 } else if (type_entry->id == TypeTableEntryIdErrorUnion) {
4589 add_node_error(g, first_executing_node(source_node), buf_sprintf("statement ignores error value"));
4590 }
4591}
4592
4593static TypeTableEntry *analyze_defer_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
4594 TypeTableEntry *expected_type, AstNode *node)
4595{
4596 if (!context->fn_entry) {
4597 add_node_error(g, node, buf_sprintf("defer expression outside function definition"));
4598 return g->builtin_types.entry_invalid;
4599 }
4600
4601 if (!node->data.defer_expr.expr) {
4602 add_node_error(g, node, buf_sprintf("defer expects an expression"));
4603 return g->builtin_types.entry_void;
4604 }
4605
4606
4607 switch (node->data.defer_expr.kind) {
4608 case ReturnKindUnconditional:
4609 {
4610 TypeTableEntry *resolved_type = analyze_expression(g, import, context, nullptr,
4611 node->data.defer_expr.expr);
4612 validate_voided_expr(g, node->data.defer_expr.expr, resolved_type);
4613 zig_panic("TODO");
4614
4615 //node->data.defer_expr.index_in_block = context->defer_list.length;
4616 //context->defer_list.append(node);
4617 return g->builtin_types.entry_void;
4618 }
4619 case ReturnKindError:
4620 {
4621 TypeTableEntry *resolved_type = analyze_expression(g, import, context, nullptr,
4622 node->data.defer_expr.expr);
4623 if (resolved_type->id == TypeTableEntryIdInvalid) {
4624 // OK
4625 } else if (resolved_type->id == TypeTableEntryIdErrorUnion) {
4626 // OK
4627 } else {
4628 add_node_error(g, node->data.defer_expr.expr,
4629 buf_sprintf("expected error type, got '%s'", buf_ptr(&resolved_type->name)));
4630 }
4631 return g->builtin_types.entry_void;
4632 }
4633 case ReturnKindMaybe:
4634 {
4635 TypeTableEntry *resolved_type = analyze_expression(g, import, context, nullptr,
4636 node->data.defer_expr.expr);
4637 if (resolved_type->id == TypeTableEntryIdInvalid) {
4638 // OK
4639 } else if (resolved_type->id == TypeTableEntryIdMaybe) {
4640 // OK
4641 } else {
4642 add_node_error(g, node->data.defer_expr.expr,
4643 buf_sprintf("expected maybe type, got '%s'", buf_ptr(&resolved_type->name)));
4644 }
4645 return g->builtin_types.entry_void;
4646 }
4647 }
4648}
4649
46354650static TypeTableEntry *analyze_string_literal_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
46364651 TypeTableEntry *expected_type, AstNode *node)
46374652{
......@@ -4652,10 +4667,8 @@ static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import,
46524667 for (int i = 0; i < node->data.block.statements.length; i += 1) {
46534668 AstNode *child = node->data.block.statements.at(i);
46544669 if (child->type == NodeTypeLabel) {
4655 child->block_context = child_context;
4656 LabelTableEntry *label_entry = child->data.label.label_entry;
4657 assert(label_entry);
4658 label_entry->entered_from_fallthrough = (return_type->id != TypeTableEntryIdUnreachable);
4670 add_node_error(g, child,
4671 buf_sprintf("label and goto not supported yet, see https://github.com/andrewrk/zig/issues/44"));
46594672 return_type = g->builtin_types.entry_void;
46604673 continue;
46614674 }
......@@ -4673,11 +4686,7 @@ static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import,
46734686 TypeTableEntry *passed_expected_type = is_last ? expected_type : nullptr;
46744687 return_type = analyze_expression(g, import, child_context, passed_expected_type, child);
46754688 if (!is_last) {
4676 if (return_type->id == TypeTableEntryIdMetaType) {
4677 add_node_error(g, child, buf_sprintf("expected expression, found type"));
4678 } else if (return_type->id == TypeTableEntryIdErrorUnion) {
4679 add_node_error(g, child, buf_sprintf("statement ignores error value"));
4680 }
4689 validate_voided_expr(g, child, return_type);
46814690 }
46824691 }
46834692 return return_type;
......@@ -4700,7 +4709,7 @@ static TypeTableEntry *analyze_asm_expr(CodeGen *g, ImportTableEntry *import, Bl
47004709 }
47014710 } else {
47024711 Buf *variable_name = &asm_output->variable_name;
4703 VariableTableEntry *var = find_variable(context, variable_name);
4712 VariableTableEntry *var = find_variable(context, variable_name, false);
47044713 if (var) {
47054714 asm_output->variable = var;
47064715 return var->type;
......@@ -4719,6 +4728,13 @@ static TypeTableEntry *analyze_asm_expr(CodeGen *g, ImportTableEntry *import, Bl
47194728 return return_type;
47204729}
47214730
4731static TypeTableEntry *analyze_goto(CodeGen *g, ImportTableEntry *import, BlockContext *context,
4732 TypeTableEntry *expected_type, AstNode *node)
4733{
4734 add_node_error(g, node, buf_sprintf("goto is broken, see https://github.com/andrewrk/zig/issues/44"));
4735 return g->builtin_types.entry_unreachable;
4736}
4737
47224738// When you call analyze_expression, the node you pass might no longer be the child node
47234739// you thought it was due to implicit casting rewriting the AST.
47244740static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,
......@@ -4734,24 +4750,16 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import,
47344750 case NodeTypeReturnExpr:
47354751 return_type = analyze_return_expr(g, import, context, expected_type, node);
47364752 break;
4753 case NodeTypeDeferExpr:
4754 return_type = analyze_defer_expr(g, import, context, expected_type, node);
4755 break;
47374756 case NodeTypeVariableDeclaration:
47384757 analyze_variable_declaration(g, import, context, expected_type, node);
47394758 return_type = g->builtin_types.entry_void;
47404759 break;
47414760 case NodeTypeGoto:
4742 {
4743 FnTableEntry *fn_table_entry = get_context_fn_entry(context);
4744 auto table_entry = fn_table_entry->label_table.maybe_get(&node->data.goto_expr.name);
4745 if (table_entry) {
4746 node->data.goto_expr.label_entry = table_entry->value;
4747 table_entry->value->used = true;
4748 } else {
4749 add_node_error(g, node,
4750 buf_sprintf("use of undeclared label '%s'", buf_ptr(&node->data.goto_expr.name)));
4751 }
4752 return_type = g->builtin_types.entry_unreachable;
4753 break;
4754 }
4761 analyze_goto(g, import, context, expected_type, node);
4762 break;
47554763 case NodeTypeBreak:
47564764 return_type = analyze_break_expr(g, import, context, expected_type, node);
47574765 break;
......@@ -4909,7 +4917,7 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo
49094917 add_node_error(g, param_decl_node, buf_sprintf("missing parameter name"));
49104918 }
49114919
4912 VariableTableEntry *var = add_local_var(g, param_decl_node, context, &param_decl->name, type, true);
4920 VariableTableEntry *var = add_local_var(g, param_decl_node, import, context, &param_decl->name, type, true);
49134921 var->src_arg_index = i;
49144922 param_decl_node->data.param_decl.variable = var;
49154923
......@@ -4920,22 +4928,6 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo
49204928 TypeTableEntry *block_return_type = analyze_expression(g, import, context, expected_type, node->data.fn_def.body);
49214929
49224930 node->data.fn_def.implicit_return_type = block_return_type;
4923
4924 {
4925 auto it = fn_table_entry->label_table.entry_iterator();
4926 for (;;) {
4927 auto *entry = it.next();
4928 if (!entry)
4929 break;
4930
4931 LabelTableEntry *label_entry = entry->value;
4932 if (!label_entry->used) {
4933 add_node_error(g, label_entry->label_node,
4934 buf_sprintf("label '%s' defined but not used",
4935 buf_ptr(&label_entry->label_node->data.label.name)));
4936 }
4937 }
4938 }
49394931}
49404932
49414933static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) {
......@@ -4964,6 +4956,7 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
49644956 case NodeTypeParamDecl:
49654957 case NodeTypeFnDecl:
49664958 case NodeTypeReturnExpr:
4959 case NodeTypeDeferExpr:
49674960 case NodeTypeRoot:
49684961 case NodeTypeBlock:
49694962 case NodeTypeBinOpExpr:
......@@ -5028,7 +5021,7 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode
50285021 Buf *name = &node->data.symbol_expr.symbol;
50295022 auto table_entry = g->primitive_type_table.maybe_get(name);
50305023 if (!table_entry) {
5031 table_entry = import->block_context->type_table.maybe_get(name);
5024 table_entry = import->type_table.maybe_get(name);
50325025 }
50335026 if (!table_entry || !type_is_complete(table_entry->value)) {
50345027 decl_node->deps.put(name, node);
......@@ -5046,6 +5039,9 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode
50465039 case NodeTypeReturnExpr:
50475040 collect_expr_decl_deps(g, import, node->data.return_expr.expr, decl_node);
50485041 break;
5042 case NodeTypeDeferExpr:
5043 collect_expr_decl_deps(g, import, node->data.defer_expr.expr, decl_node);
5044 break;
50495045 case NodeTypePrefixOpExpr:
50505046 collect_expr_decl_deps(g, import, node->data.prefix_op_expr.primary_expr, decl_node);
50515047 break;
......@@ -5196,7 +5192,7 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
51965192 Buf *name = &node->data.struct_decl.name;
51975193 auto table_entry = g->primitive_type_table.maybe_get(name);
51985194 if (!table_entry) {
5199 table_entry = import->block_context->type_table.maybe_get(name);
5195 table_entry = import->type_table.maybe_get(name);
52005196 }
52015197 if (table_entry) {
52025198 node->data.struct_decl.type_entry = table_entry->value;
......@@ -5210,20 +5206,20 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
52105206 node->data.struct_decl.kind, node, buf_ptr(name));
52115207 }
52125208
5213 import->block_context->type_table.put(&entry->name, entry);
5209 import->type_table.put(&entry->name, entry);
52145210 node->data.struct_decl.type_entry = entry;
52155211
52165212 bool is_pub = (node->data.struct_decl.visib_mod != VisibModPrivate);
52175213 if (is_pub) {
52185214 for (int i = 0; i < import->importers.length; i += 1) {
52195215 ImporterInfo importer = import->importers.at(i);
5220 auto table_entry = importer.import->block_context->type_table.maybe_get(&entry->name);
5216 auto table_entry = importer.import->type_table.maybe_get(&entry->name);
52215217 if (table_entry) {
52225218 add_node_error(g, importer.source_node,
52235219 buf_sprintf("import of type '%s' overrides existing definition",
52245220 buf_ptr(&entry->name)));
52255221 } else {
5226 importer.import->block_context->type_table.put(&entry->name, entry);
5222 importer.import->type_table.put(&entry->name, entry);
52275223 }
52285224 }
52295225 }
......@@ -5365,6 +5361,7 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
53655361 case NodeTypeParamDecl:
53665362 case NodeTypeFnDecl:
53675363 case NodeTypeReturnExpr:
5364 case NodeTypeDeferExpr:
53685365 case NodeTypeBlock:
53695366 case NodeTypeBinOpExpr:
53705367 case NodeTypeUnwrapErrorExpr:
......@@ -5555,6 +5552,8 @@ Expr *get_resolved_expr(AstNode *node) {
55555552 switch (node->type) {
55565553 case NodeTypeReturnExpr:
55575554 return &node->data.return_expr.resolved_expr;
5555 case NodeTypeDeferExpr:
5556 return &node->data.defer_expr.resolved_expr;
55585557 case NodeTypeBinOpExpr:
55595558 return &node->data.bin_op_expr.resolved_expr;
55605559 case NodeTypeUnwrapErrorExpr:
......@@ -5653,6 +5652,7 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {
56535652 return &node->data.type_decl.top_level_decl;
56545653 case NodeTypeNumberLiteral:
56555654 case NodeTypeReturnExpr:
5655 case NodeTypeDeferExpr:
56565656 case NodeTypeBinOpExpr:
56575657 case NodeTypeUnwrapErrorExpr:
56585658 case NodeTypePrefixOpExpr:
src/analyze.hpp-2
......@@ -14,8 +14,6 @@ void semantic_analyze(CodeGen *g);
1414ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg);
1515TypeTableEntry *new_type_table_entry(TypeTableEntryId id);
1616TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);
17VariableTableEntry *find_variable(BlockContext *context, Buf *name);
18TypeTableEntry *find_container(BlockContext *context, Buf *name);
1917BlockContext *new_block_context(AstNode *node, BlockContext *parent);
2018Expr *get_resolved_expr(AstNode *node);
2119TopLevelDecl *get_resolved_top_level_decl(AstNode *node);
src/ast_render.cpp+12
......@@ -122,6 +122,8 @@ static const char *node_type_str(NodeType node_type) {
122122 return "Directive";
123123 case NodeTypeReturnExpr:
124124 return "ReturnExpr";
125 case NodeTypeDeferExpr:
126 return "DeferExpr";
125127 case NodeTypeVariableDeclaration:
126128 return "VariableDeclaration";
127129 case NodeTypeTypeDecl:
......@@ -259,6 +261,14 @@ void ast_print(FILE *f, AstNode *node, int indent) {
259261 ast_print(f, node->data.return_expr.expr, indent + 2);
260262 break;
261263 }
264 case NodeTypeDeferExpr:
265 {
266 const char *prefix_str = return_prefix_str(node->data.defer_expr.kind);
267 fprintf(f, "%s%s\n", prefix_str, node_type_str(node->type));
268 if (node->data.defer_expr.expr)
269 ast_print(f, node->data.defer_expr.expr, indent + 2);
270 break;
271 }
262272 case NodeTypeVariableDeclaration:
263273 {
264274 Buf *name_buf = &node->data.variable_declaration.symbol;
......@@ -620,6 +630,8 @@ static void render_node(AstRender *ar, AstNode *node) {
620630 break;
621631 case NodeTypeReturnExpr:
622632 zig_panic("TODO");
633 case NodeTypeDeferExpr:
634 zig_panic("TODO");
623635 case NodeTypeVariableDeclaration:
624636 {
625637 const char *pub_str = visib_mod_string(node->data.variable_declaration.visib_mod);
src/codegen.cpp+79-74
......@@ -1669,6 +1669,15 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {
16691669 }
16701670}
16711671
1672static LLVMValueRef gen_defer_expr(CodeGen *g, AstNode *node) {
1673 assert(node->type == NodeTypeDeferExpr);
1674
1675 zig_panic("TODO");
1676 //node->block_context->cur_defer_index = node->data.defer_expr.index_in_block;
1677
1678 return nullptr;
1679}
1680
16721681static LLVMValueRef gen_if_bool_expr_raw(CodeGen *g, AstNode *source_node, LLVMValueRef cond_value,
16731682 AstNode *then_node, AstNode *else_node)
16741683{
......@@ -1794,6 +1803,21 @@ static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) {
17941803static LLVMValueRef gen_block(CodeGen *g, AstNode *block_node, TypeTableEntry *implicit_return_type) {
17951804 assert(block_node->type == NodeTypeBlock);
17961805
1806 /* TODO
1807 BlockContext *block_context = block_node->data.block.block_context;
1808 if (block_context->defer_list.length > 0) {
1809 LLVMBasicBlockRef exit_scope_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "DeferExitScope");
1810
1811 for (int i = 0; i < block_context->defer_list.length; i += 1) {
1812 AstNode *defer_node = block_context->defer_list.at(i);
1813 defer_node->data.defer_expr.basic_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "DeferExpr");
1814 LLVMPositionBuilderAtEnd(g->builder, body_block);
1815 }
1816
1817 LLVMPositionBuilderAtEnd(g->builder, ?);
1818 }
1819 */
1820
17971821 LLVMValueRef return_value;
17981822 for (int i = 0; i < block_node->data.block.statements.length; i += 1) {
17991823 AstNode *statement_node = block_node->data.block.statements.at(i);
......@@ -2451,6 +2475,8 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
24512475 return gen_unwrap_err_expr(g, node);
24522476 case NodeTypeReturnExpr:
24532477 return gen_return_expr(g, node);
2478 case NodeTypeDeferExpr:
2479 return gen_defer_expr(g, node);
24542480 case NodeTypeVariableDeclaration:
24552481 return gen_var_decl_expr(g, node);
24562482 case NodeTypePrefixOpExpr:
......@@ -2478,24 +2504,13 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
24782504 case NodeTypeBlock:
24792505 return gen_block(g, node, nullptr);
24802506 case NodeTypeGoto:
2481 add_debug_source_node(g, node);
2482 return LLVMBuildBr(g->builder, node->data.goto_expr.label_entry->basic_block);
2507 zig_unreachable();
24832508 case NodeTypeBreak:
24842509 return gen_break(g, node);
24852510 case NodeTypeContinue:
24862511 return gen_continue(g, node);
24872512 case NodeTypeLabel:
2488 {
2489 LabelTableEntry *label_entry = node->data.label.label_entry;
2490 assert(label_entry);
2491 LLVMBasicBlockRef basic_block = label_entry->basic_block;
2492 if (label_entry->entered_from_fallthrough) {
2493 add_debug_source_node(g, node);
2494 LLVMBuildBr(g->builder, basic_block);
2495 }
2496 LLVMPositionBuilderAtEnd(g->builder, basic_block);
2497 return nullptr;
2498 }
2513 zig_unreachable();
24992514 case NodeTypeContainerInitExpr:
25002515 return gen_container_init_expr(g, node);
25012516 case NodeTypeSwitchExpr:
......@@ -2532,19 +2547,6 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
25322547 zig_unreachable();
25332548}
25342549
2535static void build_label_blocks(CodeGen *g, AstNode *block_node) {
2536 assert(block_node->type == NodeTypeBlock);
2537 for (int i = 0; i < block_node->data.block.statements.length; i += 1) {
2538 AstNode *label_node = block_node->data.block.statements.at(i);
2539 if (label_node->type != NodeTypeLabel)
2540 continue;
2541
2542 Buf *name = &label_node->data.label.name;
2543 label_node->data.label.label_entry->basic_block = LLVMAppendBasicBlock(
2544 g->cur_fn->fn_value, buf_ptr(name));
2545 }
2546}
2547
25482550static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val) {
25492551 assert(const_val->ok);
25502552
......@@ -2977,11 +2979,7 @@ static void do_code_gen(CodeGen *g) {
29772979 LLVMPositionBuilderAtEnd(g->builder, entry_block);
29782980
29792981
2980 AstNode *body_node = fn_def_node->data.fn_def.body;
2981 build_label_blocks(g, body_node);
2982
2983 // Set up debug info for blocks and variables and
2984 // allocate all local variables
2982 // Set up debug info for blocks
29852983 for (int bc_i = 0; bc_i < fn_table_entry->all_block_contexts.length; bc_i += 1) {
29862984 BlockContext *block_context = fn_table_entry->all_block_contexts.at(bc_i);
29872985
......@@ -2994,59 +2992,45 @@ static void do_code_gen(CodeGen *g) {
29942992 block_context->di_scope = LLVMZigLexicalBlockToScope(di_block);
29952993 }
29962994
2997 for (int var_i = 0; var_i < block_context->variable_list.length; var_i += 1) {
2998 VariableTableEntry *var = block_context->variable_list.at(var_i);
29992995
3000 if (!type_has_bits(var->type)) {
3001 continue;
3002 }
2996 }
30032997
3004 unsigned tag;
3005 unsigned arg_no;
3006 TypeTableEntry *gen_type;
3007 if (block_context->node->type == NodeTypeFnDef) {
3008 tag = LLVMZigTag_DW_arg_variable();
3009 arg_no = var->gen_arg_index + 1;
2998 // create debug variable declarations for variables and allocate all local variables
2999 for (int var_i = 0; var_i < fn_table_entry->variable_list.length; var_i += 1) {
3000 VariableTableEntry *var = fn_table_entry->variable_list.at(var_i);
30103001
3011 var->is_ptr = false;
3012 assert(var->gen_arg_index >= 0);
3013 var->value_ref = LLVMGetParam(fn, var->gen_arg_index);
3002 if (!type_has_bits(var->type)) {
3003 continue;
3004 }
30143005
3015 gen_type = fn_table_entry->type_entry->data.fn.gen_param_info[var->src_arg_index].type;
3016 } else {
3017 tag = LLVMZigTag_DW_auto_variable();
3018 arg_no = 0;
3006 unsigned tag;
3007 unsigned arg_no;
3008 TypeTableEntry *gen_type;
3009 if (var->block_context->node->type == NodeTypeFnDef) {
3010 tag = LLVMZigTag_DW_arg_variable();
3011 arg_no = var->gen_arg_index + 1;
30193012
3020 add_debug_source_node(g, var->decl_node);
3021 var->value_ref = LLVMBuildAlloca(g->builder, var->type->type_ref, buf_ptr(&var->name));
3022 uint64_t align_bytes = LLVMABISizeOfType(g->target_data_ref, var->type->type_ref);
3023 LLVMSetAlignment(var->value_ref, align_bytes);
3013 var->is_ptr = false;
3014 assert(var->gen_arg_index >= 0);
3015 var->value_ref = LLVMGetParam(fn, var->gen_arg_index);
30243016
3025 gen_type = var->type;
3026 }
3017 gen_type = fn_table_entry->type_entry->data.fn.gen_param_info[var->src_arg_index].type;
3018 } else {
3019 tag = LLVMZigTag_DW_auto_variable();
3020 arg_no = 0;
30273021
3028 var->di_loc_var = LLVMZigCreateLocalVariable(g->dbuilder, tag,
3029 block_context->di_scope, buf_ptr(&var->name),
3030 import->di_file, var->decl_node->line + 1,
3031 gen_type->di_type, !g->strip_debug_symbols, 0, arg_no);
3032 }
3022 add_debug_source_node(g, var->decl_node);
3023 var->value_ref = LLVMBuildAlloca(g->builder, var->type->type_ref, buf_ptr(&var->name));
3024 uint64_t align_bytes = LLVMABISizeOfType(g->target_data_ref, var->type->type_ref);
3025 LLVMSetAlignment(var->value_ref, align_bytes);
30333026
3034 // allocate structs which are the result of casts
3035 for (int cea_i = 0; cea_i < block_context->cast_alloca_list.length; cea_i += 1) {
3036 AstNode *fn_call_node = block_context->cast_alloca_list.at(cea_i);
3037 add_debug_source_node(g, fn_call_node);
3038 Expr *expr = &fn_call_node->data.fn_call_expr.resolved_expr;
3039 fn_call_node->data.fn_call_expr.tmp_ptr = LLVMBuildAlloca(g->builder,
3040 expr->type_entry->type_ref, "");
3027 gen_type = var->type;
30413028 }
30423029
3043 // allocate structs which are struct value expressions
3044 for (int alloca_i = 0; alloca_i < block_context->struct_val_expr_alloca_list.length; alloca_i += 1) {
3045 StructValExprCodeGen *struct_val_expr_node = block_context->struct_val_expr_alloca_list.at(alloca_i);
3046 add_debug_source_node(g, struct_val_expr_node->source_node);
3047 struct_val_expr_node->ptr = LLVMBuildAlloca(g->builder,
3048 struct_val_expr_node->type_entry->type_ref, "");
3049 }
3030 var->di_loc_var = LLVMZigCreateLocalVariable(g->dbuilder, tag,
3031 var->block_context->di_scope, buf_ptr(&var->name),
3032 import->di_file, var->decl_node->line + 1,
3033 gen_type->di_type, !g->strip_debug_symbols, 0, arg_no);
30503034 }
30513035
30523036 // create debug variable declarations for parameters
......@@ -3069,6 +3053,23 @@ static void do_code_gen(CodeGen *g) {
30693053 entry_block);
30703054 }
30713055
3056 // allocate structs which are the result of casts
3057 for (int cea_i = 0; cea_i < fn_table_entry->cast_alloca_list.length; cea_i += 1) {
3058 AstNode *fn_call_node = fn_table_entry->cast_alloca_list.at(cea_i);
3059 add_debug_source_node(g, fn_call_node);
3060 Expr *expr = &fn_call_node->data.fn_call_expr.resolved_expr;
3061 fn_call_node->data.fn_call_expr.tmp_ptr = LLVMBuildAlloca(g->builder,
3062 expr->type_entry->type_ref, "");
3063 }
3064
3065 // allocate structs which are struct value expressions
3066 for (int alloca_i = 0; alloca_i < fn_table_entry->struct_val_expr_alloca_list.length; alloca_i += 1) {
3067 StructValExprCodeGen *struct_val_expr_node = fn_table_entry->struct_val_expr_alloca_list.at(alloca_i);
3068 add_debug_source_node(g, struct_val_expr_node->source_node);
3069 struct_val_expr_node->ptr = LLVMBuildAlloca(g->builder,
3070 struct_val_expr_node->type_entry->type_ref, "");
3071 }
3072
30723073 TypeTableEntry *implicit_return_type = fn_def_node->data.fn_def.implicit_return_type;
30733074 gen_block(g, fn_def_node->data.fn_def.body, implicit_return_type);
30743075
......@@ -3524,6 +3525,8 @@ void codegen_parseh(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source
35243525 import->source_code = source_code;
35253526 import->path = full_path;
35263527 import->fn_table.init(32);
3528 import->type_table.init(8);
3529 import->error_table.init(8);
35273530 g->root_import = import;
35283531
35293532 init(g, full_path);
......@@ -3614,6 +3617,8 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path,
36143617 import_entry->line_offsets = tokenization.line_offsets;
36153618 import_entry->path = full_path;
36163619 import_entry->fn_table.init(32);
3620 import_entry->type_table.init(8);
3621 import_entry->error_table.init(8);
36173622
36183623 import_entry->root = ast_parse(source_code, tokenization.tokens, import_entry, g->err_color,
36193624 &g->next_node_index);
src/parser.cpp+23-12
......@@ -1635,20 +1635,24 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, int *token_index, bool manda
16351635
16361636/*
16371637ReturnExpression : option("%" | "?") "return" option(Expression)
1638DeferExpression = option("%" | "?") "defer" option(Expression)
16381639*/
1639static AstNode *ast_parse_return_expr(ParseContext *pc, int *token_index, bool mandatory) {
1640static AstNode *ast_parse_return_or_defer_expr(ParseContext *pc, int *token_index) {
16401641 Token *token = &pc->tokens->at(*token_index);
16411642
1643 NodeType node_type;
16421644 ReturnKind kind;
16431645
16441646 if (token->id == TokenIdPercent) {
16451647 Token *next_token = &pc->tokens->at(*token_index + 1);
16461648 if (next_token->id == TokenIdKeywordReturn) {
16471649 kind = ReturnKindError;
1650 node_type = NodeTypeReturnExpr;
1651 *token_index += 2;
1652 } else if (next_token->id == TokenIdKeywordDefer) {
1653 kind = ReturnKindError;
1654 node_type = NodeTypeDeferExpr;
16481655 *token_index += 2;
1649 } else if (mandatory) {
1650 ast_expect_token(pc, next_token, TokenIdKeywordReturn);
1651 zig_unreachable();
16521656 } else {
16531657 return nullptr;
16541658 }
......@@ -1656,24 +1660,28 @@ static AstNode *ast_parse_return_expr(ParseContext *pc, int *token_index, bool m
16561660 Token *next_token = &pc->tokens->at(*token_index + 1);
16571661 if (next_token->id == TokenIdKeywordReturn) {
16581662 kind = ReturnKindMaybe;
1663 node_type = NodeTypeReturnExpr;
1664 *token_index += 2;
1665 } else if (next_token->id == TokenIdKeywordDefer) {
1666 kind = ReturnKindMaybe;
1667 node_type = NodeTypeDeferExpr;
16591668 *token_index += 2;
1660 } else if (mandatory) {
1661 ast_expect_token(pc, next_token, TokenIdKeywordReturn);
1662 zig_unreachable();
16631669 } else {
16641670 return nullptr;
16651671 }
16661672 } else if (token->id == TokenIdKeywordReturn) {
16671673 kind = ReturnKindUnconditional;
1674 node_type = NodeTypeReturnExpr;
1675 *token_index += 1;
1676 } else if (token->id == TokenIdKeywordDefer) {
1677 kind = ReturnKindUnconditional;
1678 node_type = NodeTypeDeferExpr;
16681679 *token_index += 1;
1669 } else if (mandatory) {
1670 ast_expect_token(pc, token, TokenIdKeywordReturn);
1671 zig_unreachable();
16721680 } else {
16731681 return nullptr;
16741682 }
16751683
1676 AstNode *node = ast_create_node(pc, NodeTypeReturnExpr, token);
1684 AstNode *node = ast_create_node(pc, node_type, token);
16771685 node->data.return_expr.kind = kind;
16781686 node->data.return_expr.expr = ast_parse_expression(pc, token_index, false);
16791687
......@@ -2060,7 +2068,7 @@ NonBlockExpression : ReturnExpression | AssignmentExpression
20602068static AstNode *ast_parse_non_block_expr(ParseContext *pc, int *token_index, bool mandatory) {
20612069 Token *token = &pc->tokens->at(*token_index);
20622070
2063 AstNode *return_expr = ast_parse_return_expr(pc, token_index, false);
2071 AstNode *return_expr = ast_parse_return_or_defer_expr(pc, token_index);
20642072 if (return_expr)
20652073 return return_expr;
20662074
......@@ -2695,6 +2703,9 @@ void normalize_parent_ptrs(AstNode *node) {
26952703 case NodeTypeReturnExpr:
26962704 set_field(&node->data.return_expr.expr);
26972705 break;
2706 case NodeTypeDeferExpr:
2707 set_field(&node->data.defer_expr.expr);
2708 break;
26982709 case NodeTypeVariableDeclaration:
26992710 set_list_fields(node->data.variable_declaration.directives);
27002711 set_field(&node->data.variable_declaration.type);
src/tokenizer.cpp+4
......@@ -102,6 +102,7 @@ const char * zig_keywords[] = {
102102 "pub", "export", "import", "c_import", "if", "else", "goto", "asm",
103103 "volatile", "struct", "enum", "while", "for", "continue", "break",
104104 "null", "noalias", "switch", "undefined", "error", "type", "inline",
105 "defer",
105106};
106107
107108bool is_zig_keyword(Buf *buf) {
......@@ -275,6 +276,8 @@ static void end_token(Tokenize *t) {
275276 t->cur_tok->id = TokenIdKeywordType;
276277 } else if (mem_eql_str(token_mem, token_len, "inline")) {
277278 t->cur_tok->id = TokenIdKeywordInline;
279 } else if (mem_eql_str(token_mem, token_len, "defer")) {
280 t->cur_tok->id = TokenIdKeywordDefer;
278281 }
279282
280283 t->cur_tok = nullptr;
......@@ -1090,6 +1093,7 @@ const char * token_name(TokenId id) {
10901093 case TokenIdKeywordError: return "error";
10911094 case TokenIdKeywordType: return "type";
10921095 case TokenIdKeywordInline: return "inline";
1096 case TokenIdKeywordDefer: return "defer";
10931097 case TokenIdLParen: return "(";
10941098 case TokenIdRParen: return ")";
10951099 case TokenIdComma: return ",";
src/tokenizer.hpp+1
......@@ -42,6 +42,7 @@ enum TokenId {
4242 TokenIdKeywordError,
4343 TokenIdKeywordType,
4444 TokenIdKeywordInline,
45 TokenIdKeywordDefer,
4546 TokenIdLParen,
4647 TokenIdRParen,
4748 TokenIdComma,
std/std.zig+2
......@@ -50,6 +50,8 @@ pub struct OutStream {
5050 fd: isize,
5151 buffer: [buffer_size]u8,
5252 index: isize,
53 // TODO remove this. let the user flush at will.
54 // for stderr the user can use printf
5355 buffered: bool,
5456
5557 pub fn print_str(os: &OutStream, str: []const u8) -> %isize {
test/run_tests.cpp-35
......@@ -259,25 +259,6 @@ pub fn main(args: [][]u8) -> %void {
259259}
260260 )SOURCE", "pass\n");
261261
262 add_simple_case("goto", R"SOURCE(
263import "std.zig";
264
265fn loop(a : i32) {
266 if (a == 0) {
267 goto done;
268 }
269 %%stdout.printf("loop\n");
270 loop(a - 1);
271
272done:
273 return;
274}
275
276pub fn main(args: [][]u8) -> %void {
277 loop(3);
278}
279 )SOURCE", "loop\nloop\nloop\n");
280
281262 add_simple_case("local variables", R"SOURCE(
282263import "std.zig";
283264
......@@ -1613,16 +1594,6 @@ fn a() {
16131594 ".tmp_source.zig:3:5: error: use of undeclared identifier 'b'",
16141595 ".tmp_source.zig:4:5: error: use of undeclared identifier 'c'");
16151596
1616 add_compile_fail_case("goto cause unreachable code", R"SOURCE(
1617fn a() {
1618 goto done;
1619 b();
1620done:
1621 return;
1622}
1623fn b() {}
1624 )SOURCE", 1, ".tmp_source.zig:4:5: error: unreachable code");
1625
16261597 add_compile_fail_case("parameter redeclaration", R"SOURCE(
16271598fn f(a : i32, a : i32) {
16281599}
......@@ -1670,12 +1641,6 @@ fn f() {
16701641fn f(a : unreachable) {}
16711642 )SOURCE", 1, ".tmp_source.zig:2:10: error: parameter of type 'unreachable' not allowed");
16721643
1673 add_compile_fail_case("unused label", R"SOURCE(
1674fn f() {
1675a_label:
1676}
1677 )SOURCE", 1, ".tmp_source.zig:3:1: error: label 'a_label' defined but not used");
1678
16791644 add_compile_fail_case("bad assignment target", R"SOURCE(
16801645fn f() {
16811646 3 = 3;