authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-04-18 19:42:45+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-04-18 23:56:03+03:00
logfff00c3bbb9ed211f46eb1f1be07ebab84bc8d9d
tree9263b550d8beed693e8ef2ad930039bd50794917
parent6c907a350989aa881cc0b0f71ec81d1ae1b449b7
signaturelock-open Commit is signed but in an unrecognized format.

disallow declarations between container fields


2 files changed, 52 insertions(+), 0 deletions(-)

src/parser.cpp+37
......@@ -526,6 +526,15 @@ static void ast_parse_container_doc_comments(ParseContext *pc, Buf *buf) {
526526 }
527527}
528528
529enum ContainerFieldState {
530 // no fields have been seen
531 ContainerFieldStateNone,
532 // currently parsing fields
533 ContainerFieldStateSeen,
534 // saw fields and then a declaration after them
535 ContainerFieldStateEnd,
536};
537
529538// ContainerMembers
530539// <- TestDecl ContainerMembers
531540// / TopLevelComptime ContainerMembers
......@@ -537,17 +546,29 @@ static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc) {
537546 AstNodeContainerDecl res = {};
538547 Buf tld_doc_comment_buf = BUF_INIT;
539548 buf_resize(&tld_doc_comment_buf, 0);
549 ContainerFieldState field_state = ContainerFieldStateNone;
550 Token *first_token = nullptr;
540551 for (;;) {
541552 ast_parse_container_doc_comments(pc, &tld_doc_comment_buf);
542553
554 Token *peeked_token = peek_token(pc);
555
543556 AstNode *test_decl = ast_parse_test_decl(pc);
544557 if (test_decl != nullptr) {
558 if (field_state == ContainerFieldStateSeen) {
559 field_state = ContainerFieldStateEnd;
560 first_token = peeked_token;
561 }
545562 res.decls.append(test_decl);
546563 continue;
547564 }
548565
549566 AstNode *top_level_comptime = ast_parse_top_level_comptime(pc);
550567 if (top_level_comptime != nullptr) {
568 if (field_state == ContainerFieldStateSeen) {
569 field_state = ContainerFieldStateEnd;
570 first_token = peeked_token;
571 }
551572 res.decls.append(top_level_comptime);
552573 continue;
553574 }
......@@ -555,11 +576,17 @@ static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc) {
555576 Buf doc_comment_buf = BUF_INIT;
556577 ast_parse_doc_comments(pc, &doc_comment_buf);
557578
579 peeked_token = peek_token(pc);
580
558581 Token *visib_token = eat_token_if(pc, TokenIdKeywordPub);
559582 VisibMod visib_mod = visib_token != nullptr ? VisibModPub : VisibModPrivate;
560583
561584 AstNode *top_level_decl = ast_parse_top_level_decl(pc, visib_mod, &doc_comment_buf);
562585 if (top_level_decl != nullptr) {
586 if (field_state == ContainerFieldStateSeen) {
587 field_state = ContainerFieldStateEnd;
588 first_token = peeked_token;
589 }
563590 res.decls.append(top_level_decl);
564591 continue;
565592 }
......@@ -572,6 +599,16 @@ static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc) {
572599
573600 AstNode *container_field = ast_parse_container_field(pc);
574601 if (container_field != nullptr) {
602 switch (field_state) {
603 case ContainerFieldStateNone:
604 field_state = ContainerFieldStateSeen;
605 break;
606 case ContainerFieldStateSeen:
607 break;
608 case ContainerFieldStateEnd:
609 ast_error(pc, first_token, "declarations are not allowed between container fields");
610 }
611
575612 assert(container_field->type == NodeTypeStructField);
576613 container_field->data.struct_field.doc_comments = doc_comment_buf;
577614 container_field->data.struct_field.comptime_token = comptime_token;
test/compile_errors.zig+15
......@@ -2,6 +2,21 @@ const tests = @import("tests.zig");
22const std = @import("std");
33
44pub fn addCases(cases: *tests.CompileErrorContext) void {
5 cases.add("declaration between fields",
6 \\const S = struct {
7 \\ a: usize,
8 \\ const foo = 2;
9 \\ const bar = 2;
10 \\ const baz = 2;
11 \\ b: usize,
12 \\};
13 \\comptime {
14 \\ _ = S;
15 \\}
16 , &[_][]const u8{
17 "tmp.zig:3:5: error: declarations are not allowed between container fields",
18 });
19
520 cases.add("non-extern function with var args",
621 \\fn foo(args: ...) void {}
722 \\export fn entry() void {