| author | |
| committer | |
| log | fabf45f5fc0a1827913be5675130db5db514c136 |
| tree | c81705ac2785869cd53a7a2dc758c0b9be38c718 |
| parent | a7fd14096c8dbc9cb5ed9a3731753b24e32d5757 |
11 files changed, 46 insertions(+), 18 deletions(-)
doc/docgen.zig+1| ... | ... | @@ -786,6 +786,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok |
| 786 | 786 | .Keyword_for, |
| 787 | 787 | .Keyword_if, |
| 788 | 788 | .Keyword_inline, |
| 789 | .Keyword_noinline, | |
| 789 | 790 | .Keyword_nakedcc, |
| 790 | 791 | .Keyword_noalias, |
| 791 | 792 | .Keyword_or, |
src/all_types.hpp+7-7| ... | ... | @@ -603,6 +603,12 @@ enum CallingConvention { |
| 603 | 603 | CallingConventionAsync, |
| 604 | 604 | }; |
| 605 | 605 | |
| 606 | enum FnInline { | |
| 607 | FnInlineAuto, | |
| 608 | FnInlineAlways, | |
| 609 | FnInlineNever, | |
| 610 | }; | |
| 611 | ||
| 606 | 612 | struct AstNodeFnProto { |
| 607 | 613 | VisibMod visib_mod; |
| 608 | 614 | Buf *name; |
| ... | ... | @@ -612,7 +618,7 @@ struct AstNodeFnProto { |
| 612 | 618 | bool is_var_args; |
| 613 | 619 | bool is_extern; |
| 614 | 620 | bool is_export; |
| 615 | bool is_inline; | |
| 621 | FnInline fn_inline; | |
| 616 | 622 | CallingConvention cc; |
| 617 | 623 | AstNode *fn_def_node; |
| 618 | 624 | // populated if this is an extern declaration |
| ... | ... | @@ -1453,12 +1459,6 @@ enum FnAnalState { |
| 1453 | 1459 | FnAnalStateInvalid, |
| 1454 | 1460 | }; |
| 1455 | 1461 | |
| 1456 | enum FnInline { | |
| 1457 | FnInlineAuto, | |
| 1458 | FnInlineAlways, | |
| 1459 | FnInlineNever, | |
| 1460 | }; | |
| 1461 | ||
| 1462 | 1462 | struct GlobalExport { |
| 1463 | 1463 | Buf name; |
| 1464 | 1464 | GlobalLinkageId linkage; |
src/analyze.cpp+1-2| ... | ... | @@ -3066,8 +3066,7 @@ ZigFn *create_fn(CodeGen *g, AstNode *proto_node) { |
| 3066 | 3066 | assert(proto_node->type == NodeTypeFnProto); |
| 3067 | 3067 | AstNodeFnProto *fn_proto = &proto_node->data.fn_proto; |
| 3068 | 3068 | |
| 3069 | FnInline inline_value = fn_proto->is_inline ? FnInlineAlways : FnInlineAuto; | |
| 3070 | ZigFn *fn_entry = create_fn_raw(g, inline_value); | |
| 3069 | ZigFn *fn_entry = create_fn_raw(g, fn_proto->fn_inline); | |
| 3071 | 3070 | |
| 3072 | 3071 | fn_entry->proto_node = proto_node; |
| 3073 | 3072 | fn_entry->body_node = (proto_node->data.fn_proto.fn_def_node == nullptr) ? nullptr : |
src/ast_render.cpp+8-3| ... | ... | @@ -124,8 +124,13 @@ static const char *export_string(bool is_export) { |
| 124 | 124 | // zig_unreachable(); |
| 125 | 125 | //} |
| 126 | 126 | |
| 127 | static const char *inline_string(bool is_inline) { | |
| 128 | return is_inline ? "inline " : ""; | |
| 127 | static const char *inline_string(FnInline fn_inline) { | |
| 128 | switch (fn_inline) { | |
| 129 | case FnInlineAlways: return "inline "; | |
| 130 | case FnInlineNever: return "noinline "; | |
| 131 | case FnInlineAuto: return ""; | |
| 132 | } | |
| 133 | zig_unreachable(); | |
| 129 | 134 | } |
| 130 | 135 | |
| 131 | 136 | static const char *const_or_var_string(bool is_const) { |
| ... | ... | @@ -436,7 +441,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 436 | 441 | const char *pub_str = visib_mod_string(node->data.fn_proto.visib_mod); |
| 437 | 442 | const char *extern_str = extern_string(node->data.fn_proto.is_extern); |
| 438 | 443 | const char *export_str = export_string(node->data.fn_proto.is_export); |
| 439 | const char *inline_str = inline_string(node->data.fn_proto.is_inline); | |
| 444 | const char *inline_str = inline_string(node->data.fn_proto.fn_inline); | |
| 440 | 445 | fprintf(ar->f, "%s%s%s%sfn ", pub_str, inline_str, export_str, extern_str); |
| 441 | 446 | if (node->data.fn_proto.name != nullptr) { |
| 442 | 447 | print_symbol(ar, node->data.fn_proto.name); |
src/parser.cpp+16-3| ... | ... | @@ -578,7 +578,7 @@ static AstNode *ast_parse_top_level_comptime(ParseContext *pc) { |
| 578 | 578 | } |
| 579 | 579 | |
| 580 | 580 | // TopLevelDecl |
| 581 | // <- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / KEYWORD_inline)? FnProto (SEMICOLON / Block) | |
| 581 | // <- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / (KEYWORD_inline / KEYWORD_noinline))? FnProto (SEMICOLON / Block) | |
| 582 | 582 | // / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? KEYWORD_threadlocal? VarDecl |
| 583 | 583 | // / KEYWORD_use Expr SEMICOLON |
| 584 | 584 | static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) { |
| ... | ... | @@ -587,12 +587,14 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) { |
| 587 | 587 | first = eat_token_if(pc, TokenIdKeywordExtern); |
| 588 | 588 | if (first == nullptr) |
| 589 | 589 | first = eat_token_if(pc, TokenIdKeywordInline); |
| 590 | if (first == nullptr) | |
| 591 | first = eat_token_if(pc, TokenIdKeywordNoInline); | |
| 590 | 592 | if (first != nullptr) { |
| 591 | 593 | Token *lib_name = nullptr; |
| 592 | 594 | if (first->id == TokenIdKeywordExtern) |
| 593 | 595 | lib_name = eat_token_if(pc, TokenIdStringLiteral); |
| 594 | 596 | |
| 595 | if (first->id != TokenIdKeywordInline) { | |
| 597 | if (first->id != TokenIdKeywordInline && first->id != TokenIdKeywordNoInline) { | |
| 596 | 598 | Token *thread_local_kw = eat_token_if(pc, TokenIdKeywordThreadLocal); |
| 597 | 599 | AstNode *var_decl = ast_parse_var_decl(pc); |
| 598 | 600 | if (var_decl != nullptr) { |
| ... | ... | @@ -623,8 +625,19 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) { |
| 623 | 625 | fn_proto->data.fn_proto.visib_mod = visib_mod; |
| 624 | 626 | fn_proto->data.fn_proto.is_extern = first->id == TokenIdKeywordExtern; |
| 625 | 627 | fn_proto->data.fn_proto.is_export = first->id == TokenIdKeywordExport; |
| 626 | fn_proto->data.fn_proto.is_inline = first->id == TokenIdKeywordInline; | |
| 628 | switch (first->id) { | |
| 629 | case TokenIdKeywordInline: | |
| 630 | fn_proto->data.fn_proto.fn_inline = FnInlineAlways; | |
| 631 | break; | |
| 632 | case TokenIdKeywordNoInline: | |
| 633 | fn_proto->data.fn_proto.fn_inline = FnInlineNever; | |
| 634 | break; | |
| 635 | default: | |
| 636 | fn_proto->data.fn_proto.fn_inline = FnInlineAuto; | |
| 637 | break; | |
| 638 | } | |
| 627 | 639 | fn_proto->data.fn_proto.lib_name = token_buf(lib_name); |
| 640 | ||
| 628 | 641 | AstNode *res = fn_proto; |
| 629 | 642 | if (body != nullptr) { |
| 630 | 643 | res = ast_create_node_copy_line_info(pc, NodeTypeFnDef, fn_proto); |
src/tokenizer.cpp+2| ... | ... | @@ -130,6 +130,7 @@ static const struct ZigKeyword zig_keywords[] = { |
| 130 | 130 | {"for", TokenIdKeywordFor}, |
| 131 | 131 | {"if", TokenIdKeywordIf}, |
| 132 | 132 | {"inline", TokenIdKeywordInline}, |
| 133 | {"noinline", TokenIdKeywordNoInline}, | |
| 133 | 134 | {"nakedcc", TokenIdKeywordNakedCC}, |
| 134 | 135 | {"noalias", TokenIdKeywordNoAlias}, |
| 135 | 136 | {"null", TokenIdKeywordNull}, |
| ... | ... | @@ -1551,6 +1552,7 @@ const char * token_name(TokenId id) { |
| 1551 | 1552 | case TokenIdKeywordFor: return "for"; |
| 1552 | 1553 | case TokenIdKeywordIf: return "if"; |
| 1553 | 1554 | case TokenIdKeywordInline: return "inline"; |
| 1555 | case TokenIdKeywordNoInline: return "noinline"; | |
| 1554 | 1556 | case TokenIdKeywordNakedCC: return "nakedcc"; |
| 1555 | 1557 | case TokenIdKeywordNoAlias: return "noalias"; |
| 1556 | 1558 | case TokenIdKeywordNull: return "null"; |
src/tokenizer.hpp+1| ... | ... | @@ -74,6 +74,7 @@ enum TokenId { |
| 74 | 74 | TokenIdKeywordFor, |
| 75 | 75 | TokenIdKeywordIf, |
| 76 | 76 | TokenIdKeywordInline, |
| 77 | TokenIdKeywordNoInline, | |
| 77 | 78 | TokenIdKeywordLinkSection, |
| 78 | 79 | TokenIdKeywordNakedCC, |
| 79 | 80 | TokenIdKeywordNoAlias, |
src/translate_c.cpp+1-1| ... | ... | @@ -432,7 +432,7 @@ static AstNode *trans_create_node_inline_fn(Context *c, Buf *fn_name, AstNode *r |
| 432 | 432 | AstNode *fn_proto = trans_create_node(c, NodeTypeFnProto); |
| 433 | 433 | fn_proto->data.fn_proto.visib_mod = c->visib_mod; |
| 434 | 434 | fn_proto->data.fn_proto.name = fn_name; |
| 435 | fn_proto->data.fn_proto.is_inline = true; | |
| 435 | fn_proto->data.fn_proto.fn_inline = FnInlineAlways; | |
| 436 | 436 | fn_proto->data.fn_proto.return_type = src_proto_node->data.fn_proto.return_type; // TODO ok for these to alias? |
| 437 | 437 | |
| 438 | 438 | fn_def->data.fn_def.fn_proto = fn_proto; |
std/zig/parse.zig+4-2| ... | ... | @@ -201,7 +201,7 @@ fn parseTopLevelComptime(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?* |
| 201 | 201 | } |
| 202 | 202 | |
| 203 | 203 | /// TopLevelDecl |
| 204 | /// <- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / KEYWORD_inline)? FnProto (SEMICOLON / Block) | |
| 204 | /// <- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / (KEYWORD_inline / KEYWORD_noinline))? FnProto (SEMICOLON / Block) | |
| 205 | 205 | /// / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? KEYWORD_threadlocal? VarDecl |
| 206 | 206 | /// / KEYWORD_usingnamespace Expr SEMICOLON |
| 207 | 207 | fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { |
| ... | ... | @@ -213,6 +213,7 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node |
| 213 | 213 | break :blk token; |
| 214 | 214 | } |
| 215 | 215 | if (eatToken(it, .Keyword_inline)) |token| break :blk token; |
| 216 | if (eatToken(it, .Keyword_noinline)) |token| break :blk token; | |
| 216 | 217 | break :blk null; |
| 217 | 218 | }; |
| 218 | 219 | |
| ... | ... | @@ -232,7 +233,8 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node |
| 232 | 233 | } |
| 233 | 234 | |
| 234 | 235 | if (extern_export_inline_token) |token| { |
| 235 | if (tree.tokens.at(token).id == .Keyword_inline) { | |
| 236 | if (tree.tokens.at(token).id == .Keyword_inline or | |
| 237 | tree.tokens.at(token).id == .Keyword_noinline) { | |
| 236 | 238 | putBackToken(it, token); |
| 237 | 239 | return null; |
| 238 | 240 | } |
std/zig/parser_test.zig+3| ... | ... | @@ -1677,14 +1677,17 @@ test "zig fmt: functions" { |
| 1677 | 1677 | \\extern "c" fn puts(s: *const u8) c_int; |
| 1678 | 1678 | \\export fn puts(s: *const u8) c_int; |
| 1679 | 1679 | \\inline fn puts(s: *const u8) c_int; |
| 1680 | \\noinline fn puts(s: *const u8) c_int; | |
| 1680 | 1681 | \\pub extern fn puts(s: *const u8) c_int; |
| 1681 | 1682 | \\pub extern "c" fn puts(s: *const u8) c_int; |
| 1682 | 1683 | \\pub export fn puts(s: *const u8) c_int; |
| 1683 | 1684 | \\pub inline fn puts(s: *const u8) c_int; |
| 1685 | \\pub noinline fn puts(s: *const u8) c_int; | |
| 1684 | 1686 | \\pub extern fn puts(s: *const u8) align(2 + 2) c_int; |
| 1685 | 1687 | \\pub extern "c" fn puts(s: *const u8) align(2 + 2) c_int; |
| 1686 | 1688 | \\pub export fn puts(s: *const u8) align(2 + 2) c_int; |
| 1687 | 1689 | \\pub inline fn puts(s: *const u8) align(2 + 2) c_int; |
| 1690 | \\pub noinline fn puts(s: *const u8) align(2 + 2) c_int; | |
| 1688 | 1691 | \\ |
| 1689 | 1692 | ); |
| 1690 | 1693 | } |
std/zig/tokenizer.zig+2| ... | ... | @@ -36,6 +36,7 @@ pub const Token = struct { |
| 36 | 36 | Keyword{ .bytes = "for", .id = Id.Keyword_for }, |
| 37 | 37 | Keyword{ .bytes = "if", .id = Id.Keyword_if }, |
| 38 | 38 | Keyword{ .bytes = "inline", .id = Id.Keyword_inline }, |
| 39 | Keyword{ .bytes = "noinline", .id = Id.Keyword_noinline }, | |
| 39 | 40 | Keyword{ .bytes = "nakedcc", .id = Id.Keyword_nakedcc }, |
| 40 | 41 | Keyword{ .bytes = "noalias", .id = Id.Keyword_noalias }, |
| 41 | 42 | Keyword{ .bytes = "null", .id = Id.Keyword_null }, |
| ... | ... | @@ -166,6 +167,7 @@ pub const Token = struct { |
| 166 | 167 | Keyword_for, |
| 167 | 168 | Keyword_if, |
| 168 | 169 | Keyword_inline, |
| 170 | Keyword_noinline, | |
| 169 | 171 | Keyword_nakedcc, |
| 170 | 172 | Keyword_noalias, |
| 171 | 173 | Keyword_null, |