From 97c3de251ae03fec9cea97d3bcc0605893d5f70d Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Mon, 6 Nov 2023 14:53:27 +0200 Subject: [PATCH] Parser: implement typeof_unqual --- src/Parser.zig | 23 +++++++++++++---------- src/Tokenizer.zig | 8 +++++++- test/cases/ast/typeof_unqual.c | 9 +++++++++ test/cases/typeof_unqual.c | 4 ++++ 4 files changed, 33 insertions(+), 11 deletions(-) create mode 100644 test/cases/ast/typeof_unqual.c create mode 100644 test/cases/typeof_unqual.c diff --git a/src/Parser.zig b/src/Parser.zig index db1057a1..17d3898a 100644 --- a/src/Parser.zig +++ b/src/Parser.zig @@ -828,6 +828,7 @@ fn nextExternDecl(p: *Parser) void { .keyword_typeof, .keyword_typeof1, .keyword_typeof2, + .keyword_typeof_unqual, .keyword_extension, .keyword_bit_int, => if (parens == 0) return, @@ -1332,8 +1333,13 @@ pub const DeclSpec = struct { /// : keyword_typeof '(' typeName ')' /// | keyword_typeof '(' expr ')' fn typeof(p: *Parser) Error!?Type { + var unqual = false; switch (p.tok_ids[p.tok_i]) { .keyword_typeof, .keyword_typeof1, .keyword_typeof2 => p.tok_i += 1, + .keyword_typeof_unqual => { + p.tok_i += 1; + unqual = true; + }, else => return null, } const l_paren = try p.expectToken(.l_paren); @@ -1342,7 +1348,7 @@ fn typeof(p: *Parser) Error!?Type { const typeof_ty = try p.arena.create(Type); typeof_ty.* = .{ .data = ty.data, - .qual = ty.qual.inheritFromTypeof(), + .qual = if (unqual) .{} else ty.qual.inheritFromTypeof(), .specifier = ty.specifier, }; @@ -1356,7 +1362,10 @@ fn typeof(p: *Parser) Error!?Type { try p.expectClosing(l_paren, .r_paren); // Special case nullptr_t since it's defined as typeof(nullptr) if (typeof_expr.ty.is(.nullptr_t)) { - return Type{ .specifier = .nullptr_t, .qual = typeof_expr.ty.qual.inheritFromTypeof() }; + return Type{ + .specifier = .nullptr_t, + .qual = if (unqual) .{} else typeof_expr.ty.qual.inheritFromTypeof(), + }; } const inner = try p.arena.create(Type.Expr); @@ -1364,7 +1373,7 @@ fn typeof(p: *Parser) Error!?Type { .node = typeof_expr.node, .ty = .{ .data = typeof_expr.ty.data, - .qual = typeof_expr.ty.qual.inheritFromTypeof(), + .qual = if (unqual) .{} else typeof_expr.ty.qual.inheritFromTypeof(), .specifier = typeof_expr.ty.specifier, }, }; @@ -4571,6 +4580,7 @@ fn nextStmt(p: *Parser, l_brace: TokenIndex) !void { .keyword_typeof, .keyword_typeof1, .keyword_typeof2, + .keyword_typeof_unqual, .keyword_extension, => if (parens == 0) return, .keyword_pragma => p.skipToPragmaSentinel(), @@ -7150,13 +7160,6 @@ fn checkComplexArg(p: *Parser, builtin_tok: TokenIndex, first_after: TokenIndex, } } -fn checkVariableBuiltinArgument(p: *Parser, builtin_tok: TokenIndex, first_after: TokenIndex, param_tok: TokenIndex, arg: *Result, arg_idx: u32, tag: Builtin.Tag) !void { - switch (tag) { - .__builtin_va_start, .__va_start, .va_start => return p.checkVaStartArg(builtin_tok, first_after, param_tok, arg, arg_idx), - else => {}, - } -} - fn callExpr(p: *Parser, lhs: Result) Error!Result { const l_paren = p.tok_i; p.tok_i += 1; diff --git a/src/Tokenizer.zig b/src/Tokenizer.zig index 3944e522..cf817b98 100644 --- a/src/Tokenizer.zig +++ b/src/Tokenizer.zig @@ -218,6 +218,7 @@ pub const Token = struct { keyword_true, keyword_false, keyword_nullptr, + keyword_typeof_unqual, // Preprocessor directives keyword_include, @@ -445,6 +446,7 @@ pub const Token = struct { .keyword_true, .keyword_false, .keyword_nullptr, + .keyword_typeof_unqual, => return true, else => return false, } @@ -650,6 +652,7 @@ pub const Token = struct { .keyword_true => "true", .keyword_false => "false", .keyword_nullptr => "nullptr", + .keyword_typeof_unqual => "typeof_unqual", .keyword_include => "include", .keyword_include_next => "include_next", .keyword_embed => "embed", @@ -835,6 +838,7 @@ pub const Token = struct { .keyword_true, .keyword_false, .keyword_nullptr, + .keyword_typeof_unqual, .keyword_elifdef, .keyword_elifndef, => if (standard.atLeast(.c2x)) kw else .identifier, @@ -921,6 +925,7 @@ pub const Token = struct { .{ "true", .keyword_true }, .{ "false", .keyword_false }, .{ "nullptr", .keyword_nullptr }, + .{ "typeof_unqual", .keyword_typeof_unqual }, // Preprocessor directives .{ "include", .keyword_include }, @@ -2094,7 +2099,7 @@ test "digraphs" { } test "C23 keywords" { - try expectTokensExtra("true false alignas alignof bool static_assert thread_local nullptr", &.{ + try expectTokensExtra("true false alignas alignof bool static_assert thread_local nullptr typeof_unqual", &.{ .keyword_true, .keyword_false, .keyword_c23_alignas, @@ -2103,6 +2108,7 @@ test "C23 keywords" { .keyword_c23_static_assert, .keyword_c23_thread_local, .keyword_nullptr, + .keyword_typeof_unqual, }, .c2x); } diff --git a/test/cases/ast/typeof_unqual.c b/test/cases/ast/typeof_unqual.c new file mode 100644 index 00000000..b65bc98c --- /dev/null +++ b/test/cases/ast/typeof_unqual.c @@ -0,0 +1,9 @@ +var: 'const int' + name: a + +var: 'typeof(: const int)' + name: b + +var: 'typeof(: int)' + name: c + diff --git a/test/cases/typeof_unqual.c b/test/cases/typeof_unqual.c new file mode 100644 index 00000000..2181aa39 --- /dev/null +++ b/test/cases/typeof_unqual.c @@ -0,0 +1,4 @@ +//aro-args -std=c2x +const int a; +typeof(a) b; +typeof_unqual(a) c;