| author | |
| committer | |
| log | 46b0b84b90119a1eb70a30f78baa8239cafb2524 |
| tree | 8dc295fa3eb52dc966444b381724206eb4e445ff |
| parent | a299de2265ae1fc2da31214725ea5bf399848319 |
closes #1014 files changed, 32 insertions(+), 13 deletions(-)
doc/langref.md+1-1| ... | ... | @@ -31,7 +31,7 @@ Directive = "#" "Symbol" "(" Expression ")" |
| 31 | 31 | |
| 32 | 32 | VisibleMod = "pub" | "export" |
| 33 | 33 | |
| 34 | FnDef = option("inline") FnProto Block | |
| 34 | FnDef = option("inline" | "extern") FnProto Block | |
| 35 | 35 | |
| 36 | 36 | ParamDeclList = "(" list(ParamDecl, ",") ")" |
| 37 | 37 |
src/analyze.cpp+8-8| ... | ... | @@ -994,9 +994,9 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t |
| 994 | 994 | buf_sprintf("invalid function attribute: '%s'", buf_ptr(name))); |
| 995 | 995 | } |
| 996 | 996 | } else if (buf_eql_str(name, "debug_safety")) { |
| 997 | if (fn_table_entry->is_extern) { | |
| 997 | if (!fn_table_entry->fn_def_node) { | |
| 998 | 998 | add_node_error(g, directive_node, |
| 999 | buf_sprintf("#debug_safety invalid on extern functions")); | |
| 999 | buf_sprintf("#debug_safety valid only on function definitions")); | |
| 1000 | 1000 | } else { |
| 1001 | 1001 | bool enable; |
| 1002 | 1002 | bool ok = resolve_const_expr_bool(g, import, import->block_context, |
| ... | ... | @@ -1018,9 +1018,9 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t |
| 1018 | 1018 | buf_sprintf("#condition valid only on exported symbols")); |
| 1019 | 1019 | } |
| 1020 | 1020 | } else if (buf_eql_str(name, "static_eval_enable")) { |
| 1021 | if (fn_table_entry->is_extern) { | |
| 1021 | if (!fn_table_entry->fn_def_node) { | |
| 1022 | 1022 | add_node_error(g, directive_node, |
| 1023 | buf_sprintf("#static_val_enable invalid on extern functions")); | |
| 1023 | buf_sprintf("#static_val_enable valid only on function definitions")); | |
| 1024 | 1024 | } else { |
| 1025 | 1025 | bool enable; |
| 1026 | 1026 | bool ok = resolve_const_expr_bool(g, import, import->block_context, |
| ... | ... | @@ -1470,9 +1470,9 @@ static void preview_fn_proto_instance(CodeGen *g, ImportTableEntry *import, AstN |
| 1470 | 1470 | |
| 1471 | 1471 | assert(!is_extern || !is_generic_instance); |
| 1472 | 1472 | |
| 1473 | if (!is_extern && proto_node->data.fn_proto.is_var_args) { | |
| 1473 | if (fn_def_node && proto_node->data.fn_proto.is_var_args) { | |
| 1474 | 1474 | add_node_error(g, proto_node, |
| 1475 | buf_sprintf("variadic arguments only allowed in extern functions")); | |
| 1475 | buf_sprintf("variadic arguments only allowed in extern function declarations")); | |
| 1476 | 1476 | } |
| 1477 | 1477 | |
| 1478 | 1478 | FnTableEntry *fn_table_entry = allocate<FnTableEntry>(1); |
| ... | ... | @@ -1480,13 +1480,13 @@ static void preview_fn_proto_instance(CodeGen *g, ImportTableEntry *import, AstN |
| 1480 | 1480 | fn_table_entry->proto_node = proto_node; |
| 1481 | 1481 | fn_table_entry->fn_def_node = fn_def_node; |
| 1482 | 1482 | fn_table_entry->is_extern = is_extern; |
| 1483 | fn_table_entry->is_pure = !is_extern; | |
| 1483 | fn_table_entry->is_pure = fn_def_node != nullptr; | |
| 1484 | 1484 | |
| 1485 | 1485 | get_fully_qualified_decl_name(&fn_table_entry->symbol_name, proto_node, '_'); |
| 1486 | 1486 | |
| 1487 | 1487 | g->fn_protos.append(fn_table_entry); |
| 1488 | 1488 | |
| 1489 | if (!is_extern) { | |
| 1489 | if (fn_def_node) { | |
| 1490 | 1490 | g->fn_defs.append(fn_table_entry); |
| 1491 | 1491 | } |
| 1492 | 1492 |
src/parser.cpp+22-3| ... | ... | @@ -2414,27 +2414,46 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mand |
| 2414 | 2414 | } |
| 2415 | 2415 | |
| 2416 | 2416 | /* |
| 2417 | FnDef = option("inline") FnProto Block | |
| 2417 | FnDef = option("inline" | "extern") FnProto Block | |
| 2418 | 2418 | */ |
| 2419 | 2419 | static AstNode *ast_parse_fn_def(ParseContext *pc, int *token_index, bool mandatory, |
| 2420 | 2420 | ZigList<AstNode*> *directives, VisibMod visib_mod) |
| 2421 | 2421 | { |
| 2422 | 2422 | Token *first_token = &pc->tokens->at(*token_index); |
| 2423 | 2423 | bool is_inline; |
| 2424 | bool is_extern; | |
| 2424 | 2425 | if (first_token->id == TokenIdKeywordInline) { |
| 2425 | 2426 | *token_index += 1; |
| 2426 | 2427 | is_inline = true; |
| 2428 | is_extern = false; | |
| 2429 | } else if (first_token->id == TokenIdKeywordExtern) { | |
| 2430 | *token_index += 1; | |
| 2431 | is_extern = true; | |
| 2432 | is_inline = false; | |
| 2427 | 2433 | } else { |
| 2428 | 2434 | is_inline = false; |
| 2435 | is_extern = false; | |
| 2429 | 2436 | } |
| 2430 | 2437 | |
| 2431 | 2438 | AstNode *fn_proto = ast_parse_fn_proto(pc, token_index, mandatory, directives, visib_mod); |
| 2432 | if (!fn_proto) | |
| 2439 | if (!fn_proto) { | |
| 2440 | if (is_inline || is_extern) { | |
| 2441 | *token_index -= 1; | |
| 2442 | } | |
| 2433 | 2443 | return nullptr; |
| 2434 | AstNode *node = ast_create_node(pc, NodeTypeFnDef, first_token); | |
| 2444 | } | |
| 2435 | 2445 | |
| 2436 | 2446 | fn_proto->data.fn_proto.is_inline = is_inline; |
| 2447 | fn_proto->data.fn_proto.is_extern = is_extern; | |
| 2437 | 2448 | |
| 2449 | Token *semi_token = &pc->tokens->at(*token_index); | |
| 2450 | if (semi_token->id == TokenIdSemicolon) { | |
| 2451 | *token_index += 1; | |
| 2452 | normalize_parent_ptrs(fn_proto); | |
| 2453 | return fn_proto; | |
| 2454 | } | |
| 2455 | ||
| 2456 | AstNode *node = ast_create_node(pc, NodeTypeFnDef, first_token); | |
| 2438 | 2457 | node->data.fn_def.fn_proto = fn_proto; |
| 2439 | 2458 | node->data.fn_def.body = ast_parse_block(pc, token_index, true); |
| 2440 | 2459 | normalize_parent_ptrs(node); |
test/run_tests.cpp+1-1| ... | ... | @@ -819,7 +819,7 @@ fn f() { |
| 819 | 819 | |
| 820 | 820 | add_compile_fail_case("variadic functions only allowed in extern", R"SOURCE( |
| 821 | 821 | fn f(...) {} |
| 822 | )SOURCE", 1, ".tmp_source.zig:2:1: error: variadic arguments only allowed in extern functions"); | |
| 822 | )SOURCE", 1, ".tmp_source.zig:2:1: error: variadic arguments only allowed in extern function declarations"); | |
| 823 | 823 | |
| 824 | 824 | add_compile_fail_case("write to const global variable", R"SOURCE( |
| 825 | 825 | const x : i32 = 99; |