| ... | @@ -1,13 +1,13 @@ | ... | @@ -1,13 +1,13 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const testing = std.testing; | 2 | const testing = std.testing; |
| 3 | const assert = std.debug.assert; | 3 | const assert = std.debug.assert; |
| 4 | const clang = @import("clang.zig"); | | |
| 5 | const ctok = std.c.tokenizer; | | |
| 6 | const CToken = std.c.Token; | | |
| 7 | const mem = std.mem; | 4 | const mem = std.mem; |
| 8 | const math = std.math; | 5 | const math = std.math; |
| 9 | const meta = std.meta; | 6 | const meta = std.meta; |
| 10 | const CallingConvention = std.builtin.CallingConvention; | 7 | const CallingConvention = std.builtin.CallingConvention; |
| | 8 | const clang = @import("clang.zig"); |
| | 9 | const aro = @import("aro"); |
| | 10 | const CToken = aro.Tokenizer.Token; |
| 11 | const ast = @import("translate_c/ast.zig"); | 11 | const ast = @import("translate_c/ast.zig"); |
| 12 | const Node = ast.Node; | 12 | const Node = ast.Node; |
| 13 | const Tag = Node.Tag; | 13 | const Tag = Node.Tag; |
| ... | @@ -190,19 +190,21 @@ pub fn translate( | ... | @@ -190,19 +190,21 @@ pub fn translate( |
| 190 | | 190 | |
| 191 | /// Determines whether macro is of the form: `#define FOO FOO` (Possibly with trailing tokens) | 191 | /// Determines whether macro is of the form: `#define FOO FOO` (Possibly with trailing tokens) |
| 192 | /// Macros of this form will not be translated. | 192 | /// Macros of this form will not be translated. |
| 193 | fn isSelfDefinedMacro(unit: *const clang.ASTUnit, c: *const Context, macro: *const clang.MacroDefinitionRecord) bool { | 193 | fn isSelfDefinedMacro(unit: *const clang.ASTUnit, c: *const Context, macro: *const clang.MacroDefinitionRecord) !bool { |
| 194 | const source = getMacroText(unit, c, macro); | 194 | const source = try getMacroText(unit, c, macro); |
| 195 | var tokenizer = std.c.Tokenizer{ | 195 | var tokenizer: aro.Tokenizer = .{ |
| 196 | .buffer = source, | 196 | .buf = source, |
| | 197 | .source = .unused, |
| | 198 | .langopts = .{}, |
| 197 | }; | 199 | }; |
| 198 | const name_tok = tokenizer.next(); | 200 | const name_tok = tokenizer.nextNoWS(); |
| 199 | const name = source[name_tok.start..name_tok.end]; | 201 | const name = source[name_tok.start..name_tok.end]; |
| 200 | | 202 | |
| 201 | const first_tok = tokenizer.next(); | 203 | const first_tok = tokenizer.nextNoWS(); |
| 202 | // We do not just check for `.Identifier` below because keyword tokens are preferentially matched first by | 204 | // We do not just check for `.Identifier` below because keyword tokens are preferentially matched first by |
| 203 | // the tokenizer. | 205 | // the tokenizer. |
| 204 | // In other words we would miss `#define inline inline` (`inline` is a valid c89 identifier) | 206 | // In other words we would miss `#define inline inline` (`inline` is a valid c89 identifier) |
| 205 | if (first_tok.id == .Eof) return false; | 207 | if (first_tok.id == .eof) return false; |
| 206 | return mem.eql(u8, name, source[first_tok.start..first_tok.end]); | 208 | return mem.eql(u8, name, source[first_tok.start..first_tok.end]); |
| 207 | } | 209 | } |
| 208 | | 210 | |
| ... | @@ -223,7 +225,7 @@ fn prepopulateGlobalNameTable(ast_unit: *clang.ASTUnit, c: *Context) !void { | ... | @@ -223,7 +225,7 @@ fn prepopulateGlobalNameTable(ast_unit: *clang.ASTUnit, c: *Context) !void { |
| 223 | const raw_name = macro.getName_getNameStart(); | 225 | const raw_name = macro.getName_getNameStart(); |
| 224 | const name = try c.str(raw_name); | 226 | const name = try c.str(raw_name); |
| 225 | | 227 | |
| 226 | if (!isSelfDefinedMacro(ast_unit, c, macro)) { | 228 | if (!try isSelfDefinedMacro(ast_unit, c, macro)) { |
| 227 | try c.global_names.put(c.gpa, name, {}); | 229 | try c.global_names.put(c.gpa, name, {}); |
| 228 | } | 230 | } |
| 229 | }, | 231 | }, |
| ... | @@ -5159,16 +5161,16 @@ pub const PatternList = struct { | ... | @@ -5159,16 +5161,16 @@ pub const PatternList = struct { |
| 5159 | /// Assumes that `ms` represents a tokenized function-like macro. | 5161 | /// Assumes that `ms` represents a tokenized function-like macro. |
| 5160 | fn buildArgsHash(allocator: mem.Allocator, ms: MacroSlicer, hash: *ArgsPositionMap) MacroProcessingError!void { | 5162 | fn buildArgsHash(allocator: mem.Allocator, ms: MacroSlicer, hash: *ArgsPositionMap) MacroProcessingError!void { |
| 5161 | assert(ms.tokens.len > 2); | 5163 | assert(ms.tokens.len > 2); |
| 5162 | assert(ms.tokens[0].id == .Identifier); | 5164 | assert(ms.tokens[0].id == .identifier or ms.tokens[0].id == .extended_identifier); |
| 5163 | assert(ms.tokens[1].id == .LParen); | 5165 | assert(ms.tokens[1].id == .l_paren); |
| 5164 | | 5166 | |
| 5165 | var i: usize = 2; | 5167 | var i: usize = 2; |
| 5166 | while (true) : (i += 1) { | 5168 | while (true) : (i += 1) { |
| 5167 | const token = ms.tokens[i]; | 5169 | const token = ms.tokens[i]; |
| 5168 | switch (token.id) { | 5170 | switch (token.id) { |
| 5169 | .RParen => break, | 5171 | .r_paren => break, |
| 5170 | .Comma => continue, | 5172 | .comma => continue, |
| 5171 | .Identifier => { | 5173 | .identifier, .extended_identifier => { |
| 5172 | const identifier = ms.slice(token); | 5174 | const identifier = ms.slice(token); |
| 5173 | try hash.put(allocator, identifier, i); | 5175 | try hash.put(allocator, identifier, i); |
| 5174 | }, | 5176 | }, |
| ... | @@ -5220,18 +5222,18 @@ pub const PatternList = struct { | ... | @@ -5220,18 +5222,18 @@ pub const PatternList = struct { |
| 5220 | if (args_hash.count() != self.args_hash.count()) return false; | 5222 | if (args_hash.count() != self.args_hash.count()) return false; |
| 5221 | | 5223 | |
| 5222 | var i: usize = 2; | 5224 | var i: usize = 2; |
| 5223 | while (self.tokens[i].id != .RParen) : (i += 1) {} | 5225 | while (self.tokens[i].id != .r_paren) : (i += 1) {} |
| 5224 | | 5226 | |
| 5225 | const pattern_slicer = MacroSlicer{ .source = self.source, .tokens = self.tokens }; | 5227 | const pattern_slicer = MacroSlicer{ .source = self.source, .tokens = self.tokens }; |
| 5226 | while (i < self.tokens.len) : (i += 1) { | 5228 | while (i < self.tokens.len) : (i += 1) { |
| 5227 | const pattern_token = self.tokens[i]; | 5229 | const pattern_token = self.tokens[i]; |
| 5228 | const macro_token = ms.tokens[i]; | 5230 | const macro_token = ms.tokens[i]; |
| 5229 | if (meta.activeTag(pattern_token.id) != meta.activeTag(macro_token.id)) return false; | 5231 | if (pattern_token.id != macro_token.id) return false; |
| 5230 | | 5232 | |
| 5231 | const pattern_bytes = pattern_slicer.slice(pattern_token); | 5233 | const pattern_bytes = pattern_slicer.slice(pattern_token); |
| 5232 | const macro_bytes = ms.slice(macro_token); | 5234 | const macro_bytes = ms.slice(macro_token); |
| 5233 | switch (pattern_token.id) { | 5235 | switch (pattern_token.id) { |
| 5234 | .Identifier => { | 5236 | .identifier, .extended_identifier => { |
| 5235 | const pattern_arg_index = self.args_hash.get(pattern_bytes); | 5237 | const pattern_arg_index = self.args_hash.get(pattern_bytes); |
| 5236 | const macro_arg_index = args_hash.get(macro_bytes); | 5238 | const macro_arg_index = args_hash.get(macro_bytes); |
| 5237 | | 5239 | |
| ... | @@ -5243,7 +5245,7 @@ pub const PatternList = struct { | ... | @@ -5243,7 +5245,7 @@ pub const PatternList = struct { |
| 5243 | return false; | 5245 | return false; |
| 5244 | } | 5246 | } |
| 5245 | }, | 5247 | }, |
| 5246 | .MacroString, .StringLiteral, .CharLiteral, .IntegerLiteral, .FloatLiteral => { | 5248 | .string_literal, .char_literal, .pp_num => { |
| 5247 | if (!mem.eql(u8, pattern_bytes, macro_bytes)) return false; | 5249 | if (!mem.eql(u8, pattern_bytes, macro_bytes)) return false; |
| 5248 | }, | 5250 | }, |
| 5249 | else => { | 5251 | else => { |
| ... | @@ -5359,13 +5361,13 @@ const MacroCtx = struct { | ... | @@ -5359,13 +5361,13 @@ const MacroCtx = struct { |
| 5359 | return self.list[self.i].id; | 5361 | return self.list[self.i].id; |
| 5360 | } | 5362 | } |
| 5361 | | 5363 | |
| 5362 | fn skip(self: *MacroCtx, c: *Context, expected_id: std.meta.Tag(CToken.Id)) ParseError!void { | 5364 | fn skip(self: *MacroCtx, c: *Context, expected_id: CToken.Id) ParseError!void { |
| 5363 | const next_id = self.next().?; | 5365 | const next_id = self.next().?; |
| 5364 | if (next_id != expected_id) { | 5366 | if (next_id != expected_id and !(expected_id == .identifier and next_id == .extended_identifier)) { |
| 5365 | try self.fail( | 5367 | try self.fail( |
| 5366 | c, | 5368 | c, |
| 5367 | "unable to translate C expr: expected '{s}' instead got '{s}'", | 5369 | "unable to translate C expr: expected '{s}' instead got '{s}'", |
| 5368 | .{ CToken.Id.symbolName(expected_id), next_id.symbol() }, | 5370 | .{ expected_id.symbol(), next_id.symbol() }, |
| 5369 | ); | 5371 | ); |
| 5370 | return error.ParseError; | 5372 | return error.ParseError; |
| 5371 | } | 5373 | } |
| ... | @@ -5396,12 +5398,12 @@ const MacroCtx = struct { | ... | @@ -5396,12 +5398,12 @@ const MacroCtx = struct { |
| 5396 | while (i < self.list.len) : (i += 1) { | 5398 | while (i < self.list.len) : (i += 1) { |
| 5397 | const token = self.list[i]; | 5399 | const token = self.list[i]; |
| 5398 | switch (token.id) { | 5400 | switch (token.id) { |
| 5399 | .Period, .Arrow => i += 1, // skip next token since field identifiers can be unknown | 5401 | .period, .arrow => i += 1, // skip next token since field identifiers can be unknown |
| 5400 | .Keyword_struct, .Keyword_union, .Keyword_enum => if (!last_is_type_kw) { | 5402 | .keyword_struct, .keyword_union, .keyword_enum => if (!last_is_type_kw) { |
| 5401 | last_is_type_kw = true; | 5403 | last_is_type_kw = true; |
| 5402 | continue; | 5404 | continue; |
| 5403 | }, | 5405 | }, |
| 5404 | .Identifier => { | 5406 | .identifier, .extended_identifier => { |
| 5405 | const identifier = slicer.slice(token); | 5407 | const identifier = slicer.slice(token); |
| 5406 | const is_param = for (params) |param| { | 5408 | const is_param = for (params) |param| { |
| 5407 | if (param.name != null and mem.eql(u8, identifier, param.name.?)) break true; | 5409 | if (param.name != null and mem.eql(u8, identifier, param.name.?)) break true; |
| ... | @@ -5422,31 +5424,38 @@ const MacroCtx = struct { | ... | @@ -5422,31 +5424,38 @@ const MacroCtx = struct { |
| 5422 | }; | 5424 | }; |
| 5423 | | 5425 | |
| 5424 | fn tokenizeMacro(source: []const u8, tok_list: *std.ArrayList(CToken)) Error!void { | 5426 | fn tokenizeMacro(source: []const u8, tok_list: *std.ArrayList(CToken)) Error!void { |
| 5425 | var tokenizer = std.c.Tokenizer{ | 5427 | var tokenizer: aro.Tokenizer = .{ |
| 5426 | .buffer = source, | 5428 | .buf = source, |
| | 5429 | .source = .unused, |
| | 5430 | .langopts = .{}, |
| 5427 | }; | 5431 | }; |
| 5428 | while (true) { | 5432 | while (true) { |
| 5429 | const tok = tokenizer.next(); | 5433 | const tok = tokenizer.next(); |
| 5430 | switch (tok.id) { | 5434 | switch (tok.id) { |
| 5431 | .Nl, .Eof => { | 5435 | .whitespace => continue, |
| | 5436 | .nl, .eof => { |
| 5432 | try tok_list.append(tok); | 5437 | try tok_list.append(tok); |
| 5433 | break; | 5438 | break; |
| 5434 | }, | 5439 | }, |
| 5435 | .LineComment, .MultiLineComment => continue, | | |
| 5436 | else => {}, | 5440 | else => {}, |
| 5437 | } | 5441 | } |
| 5438 | try tok_list.append(tok); | 5442 | try tok_list.append(tok); |
| 5439 | } | 5443 | } |
| 5440 | } | 5444 | } |
| 5441 | | 5445 | |
| 5442 | fn getMacroText(unit: *const clang.ASTUnit, c: *const Context, macro: *const clang.MacroDefinitionRecord) []const u8 { | 5446 | fn getMacroText(unit: *const clang.ASTUnit, c: *const Context, macro: *const clang.MacroDefinitionRecord) ![]const u8 { |
| 5443 | const begin_loc = macro.getSourceRange_getBegin(); | 5447 | const begin_loc = macro.getSourceRange_getBegin(); |
| 5444 | const end_loc = clang.Lexer.getLocForEndOfToken(macro.getSourceRange_getEnd(), c.source_manager, unit); | 5448 | const end_loc = clang.Lexer.getLocForEndOfToken(macro.getSourceRange_getEnd(), c.source_manager, unit); |
| 5445 | | 5449 | |
| 5446 | const begin_c = c.source_manager.getCharacterData(begin_loc); | 5450 | const begin_c = c.source_manager.getCharacterData(begin_loc); |
| 5447 | const end_c = c.source_manager.getCharacterData(end_loc); | 5451 | const end_c = c.source_manager.getCharacterData(end_loc); |
| 5448 | const slice_len = @intFromPtr(end_c) - @intFromPtr(begin_c); | 5452 | const slice_len = @intFromPtr(end_c) - @intFromPtr(begin_c); |
| 5449 | return begin_c[0..slice_len]; | 5453 | |
| | 5454 | var comp = aro.Compilation.init(c.gpa); |
| | 5455 | defer comp.deinit(); |
| | 5456 | const result = comp.addSourceFromBuffer("", begin_c[0..slice_len]) catch return error.OutOfMemory; |
| | 5457 | |
| | 5458 | return c.arena.dupe(u8, result.buf); |
| 5450 | } | 5459 | } |
| 5451 | | 5460 | |
| 5452 | fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void { | 5461 | fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void { |
| ... | @@ -5471,7 +5480,7 @@ fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void { | ... | @@ -5471,7 +5480,7 @@ fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void { |
| 5471 | continue; | 5480 | continue; |
| 5472 | } | 5481 | } |
| 5473 | | 5482 | |
| 5474 | const source = getMacroText(unit, c, macro); | 5483 | const source = try getMacroText(unit, c, macro); |
| 5475 | | 5484 | |
| 5476 | try tokenizeMacro(source, &tok_list); | 5485 | try tokenizeMacro(source, &tok_list); |
| 5477 | | 5486 | |
| ... | @@ -5485,7 +5494,7 @@ fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void { | ... | @@ -5485,7 +5494,7 @@ fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void { |
| 5485 | | 5494 | |
| 5486 | var macro_fn = false; | 5495 | var macro_fn = false; |
| 5487 | switch (macro_ctx.peek().?) { | 5496 | switch (macro_ctx.peek().?) { |
| 5488 | .Identifier => { | 5497 | .identifier, .extended_identifier => { |
| 5489 | // if it equals itself, ignore. for example, from stdio.h: | 5498 | // if it equals itself, ignore. for example, from stdio.h: |
| 5490 | // #define stdin stdin | 5499 | // #define stdin stdin |
| 5491 | const tok = macro_ctx.list[1]; | 5500 | const tok = macro_ctx.list[1]; |
| ... | @@ -5494,7 +5503,7 @@ fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void { | ... | @@ -5494,7 +5503,7 @@ fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void { |
| 5494 | continue; | 5503 | continue; |
| 5495 | } | 5504 | } |
| 5496 | }, | 5505 | }, |
| 5497 | .Nl, .Eof => { | 5506 | .nl, .eof => { |
| 5498 | // this means it is a macro without a value | 5507 | // this means it is a macro without a value |
| 5499 | // We define it as an empty string so that it can still be used with ++ | 5508 | // We define it as an empty string so that it can still be used with ++ |
| 5500 | const str_node = try Tag.string_literal.create(c.arena, "\"\""); | 5509 | const str_node = try Tag.string_literal.create(c.arena, "\"\""); |
| ... | @@ -5503,7 +5512,7 @@ fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void { | ... | @@ -5503,7 +5512,7 @@ fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void { |
| 5503 | try c.global_scope.blank_macros.put(name, {}); | 5512 | try c.global_scope.blank_macros.put(name, {}); |
| 5504 | continue; | 5513 | continue; |
| 5505 | }, | 5514 | }, |
| 5506 | .LParen => { | 5515 | .l_paren => { |
| 5507 | // if the name is immediately followed by a '(' then it is a function | 5516 | // if the name is immediately followed by a '(' then it is a function |
| 5508 | macro_fn = macro_ctx.list[0].end == macro_ctx.list[1].start; | 5517 | macro_fn = macro_ctx.list[0].end == macro_ctx.list[1].start; |
| 5509 | }, | 5518 | }, |
| ... | @@ -5534,7 +5543,7 @@ fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void { | ... | @@ -5534,7 +5543,7 @@ fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void { |
| 5534 | // Check if the macro only uses other blank macros. | 5543 | // Check if the macro only uses other blank macros. |
| 5535 | while (true) { | 5544 | while (true) { |
| 5536 | switch (m.peek().?) { | 5545 | switch (m.peek().?) { |
| 5537 | .Identifier => { | 5546 | .identifier, .extended_identifier => { |
| 5538 | const tok = m.list[m.i + 1]; | 5547 | const tok = m.list[m.i + 1]; |
| 5539 | const slice = m.source[tok.start..tok.end]; | 5548 | const slice = m.source[tok.start..tok.end]; |
| 5540 | if (c.global_scope.blank_macros.contains(slice)) { | 5549 | if (c.global_scope.blank_macros.contains(slice)) { |
| ... | @@ -5542,7 +5551,7 @@ fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void { | ... | @@ -5542,7 +5551,7 @@ fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void { |
| 5542 | continue; | 5551 | continue; |
| 5543 | } | 5552 | } |
| 5544 | }, | 5553 | }, |
| 5545 | .Eof, .Nl => { | 5554 | .eof, .nl => { |
| 5546 | try c.global_scope.blank_macros.put(m.name, {}); | 5555 | try c.global_scope.blank_macros.put(m.name, {}); |
| 5547 | const init_node = try Tag.string_literal.create(c.arena, "\"\""); | 5556 | const init_node = try Tag.string_literal.create(c.arena, "\"\""); |
| 5548 | const var_decl = try Tag.pub_var_simple.create(c.arena, .{ .name = m.name, .init = init_node }); | 5557 | const var_decl = try Tag.pub_var_simple.create(c.arena, .{ .name = m.name, .init = init_node }); |
| ... | @@ -5556,7 +5565,7 @@ fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void { | ... | @@ -5556,7 +5565,7 @@ fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void { |
| 5556 | | 5565 | |
| 5557 | const init_node = try parseCExpr(c, m, scope); | 5566 | const init_node = try parseCExpr(c, m, scope); |
| 5558 | const last = m.next().?; | 5567 | const last = m.next().?; |
| 5559 | if (last != .Eof and last != .Nl) | 5568 | if (last != .eof and last != .nl) |
| 5560 | return m.fail(c, "unable to translate C expr: unexpected token '{s}'", .{last.symbol()}); | 5569 | return m.fail(c, "unable to translate C expr: unexpected token '{s}'", .{last.symbol()}); |
| 5561 | | 5570 | |
| 5562 | const var_decl = try Tag.pub_var_simple.create(c.arena, .{ .name = m.name, .init = init_node }); | 5571 | const var_decl = try Tag.pub_var_simple.create(c.arena, .{ .name = m.name, .init = init_node }); |
| ... | @@ -5578,14 +5587,16 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void { | ... | @@ -5578,14 +5587,16 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void { |
| 5578 | defer block_scope.deinit(); | 5587 | defer block_scope.deinit(); |
| 5579 | const scope = &block_scope.base; | 5588 | const scope = &block_scope.base; |
| 5580 | | 5589 | |
| 5581 | try m.skip(c, .LParen); | 5590 | try m.skip(c, .l_paren); |
| 5582 | | 5591 | |
| 5583 | var fn_params = std.ArrayList(ast.Payload.Param).init(c.gpa); | 5592 | var fn_params = std.ArrayList(ast.Payload.Param).init(c.gpa); |
| 5584 | defer fn_params.deinit(); | 5593 | defer fn_params.deinit(); |
| 5585 | | 5594 | |
| 5586 | while (true) { | 5595 | while (true) { |
| 5587 | if (m.peek().? != .Identifier) break; | 5596 | switch (m.peek().?) { |
| 5588 | _ = m.next(); | 5597 | .identifier, .extended_identifier => _ = m.next(), |
| | 5598 | else => break, |
| | 5599 | } |
| 5589 | | 5600 | |
| 5590 | const mangled_name = try block_scope.makeMangledName(c, m.slice()); | 5601 | const mangled_name = try block_scope.makeMangledName(c, m.slice()); |
| 5591 | try fn_params.append(.{ | 5602 | try fn_params.append(.{ |
| ... | @@ -5594,11 +5605,11 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void { | ... | @@ -5594,11 +5605,11 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void { |
| 5594 | .type = Tag.@"anytype".init(), | 5605 | .type = Tag.@"anytype".init(), |
| 5595 | }); | 5606 | }); |
| 5596 | try block_scope.discardVariable(c, mangled_name); | 5607 | try block_scope.discardVariable(c, mangled_name); |
| 5597 | if (m.peek().? != .Comma) break; | 5608 | if (m.peek().? != .comma) break; |
| 5598 | _ = m.next(); | 5609 | _ = m.next(); |
| 5599 | } | 5610 | } |
| 5600 | | 5611 | |
| 5601 | try m.skip(c, .RParen); | 5612 | try m.skip(c, .r_paren); |
| 5602 | | 5613 | |
| 5603 | if (m.checkTranslatableMacro(scope, fn_params.items)) |err| switch (err) { | 5614 | if (m.checkTranslatableMacro(scope, fn_params.items)) |err| switch (err) { |
| 5604 | .undefined_identifier => |ident| return m.fail(c, "unable to translate macro: undefined identifier `{s}`", .{ident}), | 5615 | .undefined_identifier => |ident| return m.fail(c, "unable to translate macro: undefined identifier `{s}`", .{ident}), |
| ... | @@ -5607,7 +5618,7 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void { | ... | @@ -5607,7 +5618,7 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void { |
| 5607 | | 5618 | |
| 5608 | const expr = try parseCExpr(c, m, scope); | 5619 | const expr = try parseCExpr(c, m, scope); |
| 5609 | const last = m.next().?; | 5620 | const last = m.next().?; |
| 5610 | if (last != .Eof and last != .Nl) | 5621 | if (last != .eof and last != .nl) |
| 5611 | return m.fail(c, "unable to translate C expr: unexpected token '{s}'", .{last.symbol()}); | 5622 | return m.fail(c, "unable to translate C expr: unexpected token '{s}'", .{last.symbol()}); |
| 5612 | | 5623 | |
| 5613 | const typeof_arg = if (expr.castTag(.block)) |some| blk: { | 5624 | const typeof_arg = if (expr.castTag(.block)) |some| blk: { |
| ... | @@ -5644,7 +5655,7 @@ fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | ... | @@ -5644,7 +5655,7 @@ fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 5644 | defer block_scope.deinit(); | 5655 | defer block_scope.deinit(); |
| 5645 | | 5656 | |
| 5646 | const node = try parseCCondExpr(c, m, &block_scope.base); | 5657 | const node = try parseCCondExpr(c, m, &block_scope.base); |
| 5647 | if (m.next().? != .Comma) { | 5658 | if (m.next().? != .comma) { |
| 5648 | m.i -= 1; | 5659 | m.i -= 1; |
| 5649 | return node; | 5660 | return node; |
| 5650 | } | 5661 | } |
| ... | @@ -5656,7 +5667,7 @@ fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | ... | @@ -5656,7 +5667,7 @@ fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 5656 | try block_scope.statements.append(ignore); | 5667 | try block_scope.statements.append(ignore); |
| 5657 | | 5668 | |
| 5658 | last = try parseCCondExpr(c, m, &block_scope.base); | 5669 | last = try parseCCondExpr(c, m, &block_scope.base); |
| 5659 | if (m.next().? != .Comma) { | 5670 | if (m.next().? != .comma) { |
| 5660 | m.i -= 1; | 5671 | m.i -= 1; |
| 5661 | break; | 5672 | break; |
| 5662 | } | 5673 | } |
| ... | @@ -5670,118 +5681,135 @@ fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | ... | @@ -5670,118 +5681,135 @@ fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 5670 | return try block_scope.complete(c); | 5681 | return try block_scope.complete(c); |
| 5671 | } | 5682 | } |
| 5672 | | 5683 | |
| 5673 | fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node { | 5684 | fn parseCNumLit(ctx: *Context, m: *MacroCtx) ParseError!Node { |
| 5674 | var lit_bytes = m.slice(); | 5685 | const lit_bytes = m.slice(); |
| | 5686 | var bytes = try std.ArrayListUnmanaged(u8).initCapacity(ctx.arena, lit_bytes.len + 3); |
| 5675 | | 5687 | |
| 5676 | switch (m.list[m.i].id) { | 5688 | const prefix = aro.Tree.Token.NumberPrefix.fromString(lit_bytes); |
| 5677 | .IntegerLiteral => |suffix| { | 5689 | switch (prefix) { |
| 5678 | var base: []const u8 = "decimal"; | 5690 | .binary => bytes.appendSliceAssumeCapacity("0b"), |
| 5679 | if (lit_bytes.len >= 2 and lit_bytes[0] == '0') { | 5691 | .octal => bytes.appendSliceAssumeCapacity("0o"), |
| 5680 | switch (lit_bytes[1]) { | 5692 | .hex => bytes.appendSliceAssumeCapacity("0x"), |
| 5681 | '0'...'7' => { | 5693 | .decimal => {}, |
| 5682 | // Octal | 5694 | } |
| 5683 | lit_bytes = try std.fmt.allocPrint(c.arena, "0o{s}", .{lit_bytes[1..]}); | | |
| 5684 | base = "octal"; | | |
| 5685 | }, | | |
| 5686 | 'X' => { | | |
| 5687 | // Hexadecimal with capital X, valid in C but not in Zig | | |
| 5688 | lit_bytes = try std.fmt.allocPrint(c.arena, "0x{s}", .{lit_bytes[2..]}); | | |
| 5689 | base = "hexadecimal"; | | |
| 5690 | }, | | |
| 5691 | 'x' => { | | |
| 5692 | base = "hexadecimal"; | | |
| 5693 | }, | | |
| 5694 | else => {}, | | |
| 5695 | } | | |
| 5696 | } | | |
| 5697 | | | |
| 5698 | const type_node = try Tag.type.create(c.arena, switch (suffix) { | | |
| 5699 | .none => "c_int", | | |
| 5700 | .u => "c_uint", | | |
| 5701 | .l => "c_long", | | |
| 5702 | .lu => "c_ulong", | | |
| 5703 | .ll => "c_longlong", | | |
| 5704 | .llu => "c_ulonglong", | | |
| 5705 | .f => unreachable, | | |
| 5706 | }); | | |
| 5707 | lit_bytes = lit_bytes[0 .. lit_bytes.len - switch (suffix) { | | |
| 5708 | .none => @as(u8, 0), | | |
| 5709 | .u, .l => 1, | | |
| 5710 | .lu, .ll => 2, | | |
| 5711 | .llu => 3, | | |
| 5712 | .f => unreachable, | | |
| 5713 | }]; | | |
| 5714 | | | |
| 5715 | const value = std.fmt.parseInt(i128, lit_bytes, 0) catch math.maxInt(i128); | | |
| 5716 | | | |
| 5717 | // make the output less noisy by skipping promoteIntLiteral where | | |
| 5718 | // it's guaranteed to not be required because of C standard type constraints | | |
| 5719 | const guaranteed_to_fit = switch (suffix) { | | |
| 5720 | .none => math.cast(i16, value) != null, | | |
| 5721 | .u => math.cast(u16, value) != null, | | |
| 5722 | .l => math.cast(i32, value) != null, | | |
| 5723 | .lu => math.cast(u32, value) != null, | | |
| 5724 | .ll => math.cast(i64, value) != null, | | |
| 5725 | .llu => math.cast(u64, value) != null, | | |
| 5726 | .f => unreachable, | | |
| 5727 | }; | | |
| 5728 | | | |
| 5729 | const literal_node = try transCreateNodeNumber(c, lit_bytes, .int); | | |
| 5730 | | 5695 | |
| 5731 | if (guaranteed_to_fit) { | 5696 | const after_prefix = lit_bytes[prefix.stringLen()..]; |
| 5732 | return Tag.as.create(c.arena, .{ .lhs = type_node, .rhs = literal_node }); | 5697 | const after_int = for (after_prefix, 0..) |c, i| switch (c) { |
| 5733 | } else { | 5698 | '.' => { |
| 5734 | return Tag.helpers_promoteIntLiteral.create(c.arena, .{ | 5699 | if (i == 0) { |
| 5735 | .type = type_node, | 5700 | bytes.appendAssumeCapacity('0'); |
| 5736 | .value = literal_node, | | |
| 5737 | .base = try Tag.enum_literal.create(c.arena, base), | | |
| 5738 | }); | | |
| 5739 | } | 5701 | } |
| | 5702 | break after_prefix[i..]; |
| 5740 | }, | 5703 | }, |
| 5741 | .FloatLiteral => |suffix| { | 5704 | 'e', 'E' => { |
| 5742 | if (suffix != .none) lit_bytes = lit_bytes[0 .. lit_bytes.len - 1]; | 5705 | if (prefix != .hex) break after_prefix[i..]; |
| 5743 | | 5706 | bytes.appendAssumeCapacity(c); |
| 5744 | if (lit_bytes.len >= 2 and std.ascii.eqlIgnoreCase(lit_bytes[0..2], "0x")) { | 5707 | }, |
| 5745 | if (mem.indexOfScalar(u8, lit_bytes, '.')) |dot_index| { | 5708 | 'p', 'P' => break after_prefix[i..], |
| 5746 | if (dot_index == 2) { | 5709 | '0'...'9', 'a'...'d', 'A'...'D', 'f', 'F' => { |
| 5747 | lit_bytes = try std.fmt.allocPrint(c.arena, "0x0{s}", .{lit_bytes[2..]}); | 5710 | if (!prefix.digitAllowed(c)) break after_prefix[i..]; |
| 5748 | } else if (dot_index + 1 == lit_bytes.len or !std.ascii.isHex(lit_bytes[dot_index + 1])) { | 5711 | bytes.appendAssumeCapacity(c); |
| 5749 | // If the literal lacks a digit after the `.`, we need to | 5712 | }, |
| 5750 | // add one since `0x1.p10` would be invalid syntax in Zig. | 5713 | '\'' => { |
| 5751 | lit_bytes = try std.fmt.allocPrint(c.arena, "0x{s}0{s}", .{ | 5714 | bytes.appendAssumeCapacity('_'); |
| 5752 | lit_bytes[2 .. dot_index + 1], | 5715 | }, |
| 5753 | lit_bytes[dot_index + 1 ..], | 5716 | else => break after_prefix[i..], |
| 5754 | }); | 5717 | } else ""; |
| 5755 | } | | |
| 5756 | } | | |
| 5757 | | 5718 | |
| 5758 | if (lit_bytes[1] == 'X') { | 5719 | const after_frac = frac: { |
| 5759 | // Hexadecimal with capital X, valid in C but not in Zig | 5720 | if (after_int.len == 0 or after_int[0] != '.') break :frac after_int; |
| 5760 | lit_bytes = try std.fmt.allocPrint(c.arena, "0x{s}", .{lit_bytes[2..]}); | 5721 | bytes.appendAssumeCapacity('.'); |
| 5761 | } | 5722 | for (after_int[1..], 1..) |c, i| { |
| 5762 | } else if (mem.indexOfScalar(u8, lit_bytes, '.')) |dot_index| { | 5723 | if (c == '\'') { |
| 5763 | if (dot_index == 0) { | 5724 | bytes.appendAssumeCapacity('_'); |
| 5764 | lit_bytes = try std.fmt.allocPrint(c.arena, "0{s}", .{lit_bytes}); | 5725 | continue; |
| 5765 | } else if (dot_index + 1 == lit_bytes.len or !std.ascii.isDigit(lit_bytes[dot_index + 1])) { | | |
| 5766 | // If the literal lacks a digit after the `.`, we need to | | |
| 5767 | // add one since `1.` or `1.e10` would be invalid syntax in Zig. | | |
| 5768 | lit_bytes = try std.fmt.allocPrint(c.arena, "{s}0{s}", .{ | | |
| 5769 | lit_bytes[0 .. dot_index + 1], | | |
| 5770 | lit_bytes[dot_index + 1 ..], | | |
| 5771 | }); | | |
| 5772 | } | | |
| 5773 | } | 5726 | } |
| | 5727 | if (!prefix.digitAllowed(c)) break :frac after_int[i..]; |
| | 5728 | bytes.appendAssumeCapacity(c); |
| | 5729 | } |
| | 5730 | break :frac ""; |
| | 5731 | }; |
| | 5732 | |
| | 5733 | const suffix_str = exponent: { |
| | 5734 | if (after_frac.len == 0) break :exponent after_frac; |
| | 5735 | switch (after_frac[0]) { |
| | 5736 | 'e', 'E' => {}, |
| | 5737 | 'p', 'P' => if (prefix != .hex) break :exponent after_frac, |
| | 5738 | else => break :exponent after_frac, |
| | 5739 | } |
| | 5740 | bytes.appendAssumeCapacity(after_frac[0]); |
| | 5741 | for (after_frac[1..], 1..) |c, i| switch (c) { |
| | 5742 | '+', '-', '0'...'9' => { |
| | 5743 | bytes.appendAssumeCapacity(c); |
| | 5744 | }, |
| | 5745 | '\'' => { |
| | 5746 | bytes.appendAssumeCapacity('_'); |
| | 5747 | }, |
| | 5748 | else => break :exponent after_frac[i..], |
| | 5749 | }; |
| | 5750 | break :exponent ""; |
| | 5751 | }; |
| | 5752 | |
| | 5753 | const is_float = after_int.len != suffix_str.len; |
| | 5754 | const suffix = aro.Tree.Token.NumberSuffix.fromString(suffix_str, if (is_float) .float else .int) orelse { |
| | 5755 | try m.fail(ctx, "invalid number suffix: '{s}'", .{suffix_str}); |
| | 5756 | return error.ParseError; |
| | 5757 | }; |
| | 5758 | if (suffix.isImaginary()) { |
| | 5759 | try m.fail(ctx, "TODO: imaginary literals", .{}); |
| | 5760 | return error.ParseError; |
| | 5761 | } |
| | 5762 | if (suffix.isBitInt()) { |
| | 5763 | try m.fail(ctx, "TODO: _BitInt literals", .{}); |
| | 5764 | return error.ParseError; |
| | 5765 | } |
| | 5766 | |
| | 5767 | if (is_float) { |
| | 5768 | const type_node = try Tag.type.create(ctx.arena, switch (suffix) { |
| | 5769 | .F16 => "f16", |
| | 5770 | .F => "f32", |
| | 5771 | .None => "f64", |
| | 5772 | .L => "c_longdouble", |
| | 5773 | .W => "f80", |
| | 5774 | .Q, .F128 => "f128", |
| | 5775 | else => unreachable, |
| | 5776 | }); |
| | 5777 | const rhs = try Tag.float_literal.create(ctx.arena, bytes.items); |
| | 5778 | return Tag.as.create(ctx.arena, .{ .lhs = type_node, .rhs = rhs }); |
| | 5779 | } else { |
| | 5780 | const type_node = try Tag.type.create(ctx.arena, switch (suffix) { |
| | 5781 | .None => "c_int", |
| | 5782 | .U => "c_uint", |
| | 5783 | .L => "c_long", |
| | 5784 | .UL => "c_ulong", |
| | 5785 | .LL => "c_longlong", |
| | 5786 | .ULL => "c_ulonglong", |
| | 5787 | else => unreachable, |
| | 5788 | }); |
| | 5789 | const value = std.fmt.parseInt(i128, bytes.items, 0) catch math.maxInt(i128); |
| | 5790 | |
| | 5791 | // make the output less noisy by skipping promoteIntLiteral where |
| | 5792 | // it's guaranteed to not be required because of C standard type constraints |
| | 5793 | const guaranteed_to_fit = switch (suffix) { |
| | 5794 | .None => math.cast(i16, value) != null, |
| | 5795 | .U => math.cast(u16, value) != null, |
| | 5796 | .L => math.cast(i32, value) != null, |
| | 5797 | .UL => math.cast(u32, value) != null, |
| | 5798 | .LL => math.cast(i64, value) != null, |
| | 5799 | .ULL => math.cast(u64, value) != null, |
| | 5800 | else => unreachable, |
| | 5801 | }; |
| 5774 | | 5802 | |
| 5775 | const type_node = try Tag.type.create(c.arena, switch (suffix) { | 5803 | const literal_node = try Tag.integer_literal.create(ctx.arena, bytes.items); |
| 5776 | .f => "f32", | 5804 | if (guaranteed_to_fit) { |
| 5777 | .none => "f64", | 5805 | return Tag.as.create(ctx.arena, .{ .lhs = type_node, .rhs = literal_node }); |
| 5778 | .l => "c_longdouble", | 5806 | } else { |
| 5779 | else => unreachable, | 5807 | return Tag.helpers_promoteIntLiteral.create(ctx.arena, .{ |
| | 5808 | .type = type_node, |
| | 5809 | .value = literal_node, |
| | 5810 | .base = try Tag.enum_literal.create(ctx.arena, @tagName(prefix)), |
| 5780 | }); | 5811 | }); |
| 5781 | const rhs = try transCreateNodeNumber(c, lit_bytes, .float); | 5812 | } |
| 5782 | return Tag.as.create(c.arena, .{ .lhs = type_node, .rhs = rhs }); | | |
| 5783 | }, | | |
| 5784 | else => unreachable, | | |
| 5785 | } | 5813 | } |
| 5786 | } | 5814 | } |
| 5787 | | 5815 | |
| ... | @@ -5800,17 +5828,17 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 { | ... | @@ -5800,17 +5828,17 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 { |
| 5800 | } else return source; | 5828 | } else return source; |
| 5801 | var bytes = try ctx.arena.alloc(u8, source.len * 2); | 5829 | var bytes = try ctx.arena.alloc(u8, source.len * 2); |
| 5802 | var state: enum { | 5830 | var state: enum { |
| 5803 | Start, | 5831 | start, |
| 5804 | Escape, | 5832 | escape, |
| 5805 | Hex, | 5833 | hex, |
| 5806 | Octal, | 5834 | octal, |
| 5807 | } = .Start; | 5835 | } = .start; |
| 5808 | var i: usize = 0; | 5836 | var i: usize = 0; |
| 5809 | var count: u8 = 0; | 5837 | var count: u8 = 0; |
| 5810 | var num: u8 = 0; | 5838 | var num: u8 = 0; |
| 5811 | for (source) |c| { | 5839 | for (source) |c| { |
| 5812 | switch (state) { | 5840 | switch (state) { |
| 5813 | .Escape => { | 5841 | .escape => { |
| 5814 | switch (c) { | 5842 | switch (c) { |
| 5815 | 'n', 'r', 't', '\\', '\'', '\"' => { | 5843 | 'n', 'r', 't', '\\', '\'', '\"' => { |
| 5816 | bytes[i] = c; | 5844 | bytes[i] = c; |
| ... | @@ -5818,11 +5846,11 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 { | ... | @@ -5818,11 +5846,11 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 { |
| 5818 | '0'...'7' => { | 5846 | '0'...'7' => { |
| 5819 | count += 1; | 5847 | count += 1; |
| 5820 | num += c - '0'; | 5848 | num += c - '0'; |
| 5821 | state = .Octal; | 5849 | state = .octal; |
| 5822 | bytes[i] = 'x'; | 5850 | bytes[i] = 'x'; |
| 5823 | }, | 5851 | }, |
| 5824 | 'x' => { | 5852 | 'x' => { |
| 5825 | state = .Hex; | 5853 | state = .hex; |
| 5826 | bytes[i] = 'x'; | 5854 | bytes[i] = 'x'; |
| 5827 | }, | 5855 | }, |
| 5828 | 'a' => { | 5856 | 'a' => { |
| ... | @@ -5867,10 +5895,10 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 { | ... | @@ -5867,10 +5895,10 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 { |
| 5867 | }, | 5895 | }, |
| 5868 | } | 5896 | } |
| 5869 | i += 1; | 5897 | i += 1; |
| 5870 | if (state == .Escape) | 5898 | if (state == .escape) |
| 5871 | state = .Start; | 5899 | state = .start; |
| 5872 | }, | 5900 | }, |
| 5873 | .Start => { | 5901 | .start => { |
| 5874 | if (c == '\t') { | 5902 | if (c == '\t') { |
| 5875 | bytes[i] = '\\'; | 5903 | bytes[i] = '\\'; |
| 5876 | i += 1; | 5904 | i += 1; |
| ... | @@ -5879,12 +5907,12 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 { | ... | @@ -5879,12 +5907,12 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 { |
| 5879 | continue; | 5907 | continue; |
| 5880 | } | 5908 | } |
| 5881 | if (c == '\\') { | 5909 | if (c == '\\') { |
| 5882 | state = .Escape; | 5910 | state = .escape; |
| 5883 | } | 5911 | } |
| 5884 | bytes[i] = c; | 5912 | bytes[i] = c; |
| 5885 | i += 1; | 5913 | i += 1; |
| 5886 | }, | 5914 | }, |
| 5887 | .Hex => { | 5915 | .hex => { |
| 5888 | switch (c) { | 5916 | switch (c) { |
| 5889 | '0'...'9' => { | 5917 | '0'...'9' => { |
| 5890 | num = std.math.mul(u8, num, 16) catch { | 5918 | num = std.math.mul(u8, num, 16) catch { |
| ... | @@ -5911,15 +5939,15 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 { | ... | @@ -5911,15 +5939,15 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 { |
| 5911 | i += std.fmt.formatIntBuf(bytes[i..], num, 16, .lower, std.fmt.FormatOptions{ .fill = '0', .width = 2 }); | 5939 | i += std.fmt.formatIntBuf(bytes[i..], num, 16, .lower, std.fmt.FormatOptions{ .fill = '0', .width = 2 }); |
| 5912 | num = 0; | 5940 | num = 0; |
| 5913 | if (c == '\\') | 5941 | if (c == '\\') |
| 5914 | state = .Escape | 5942 | state = .escape |
| 5915 | else | 5943 | else |
| 5916 | state = .Start; | 5944 | state = .start; |
| 5917 | bytes[i] = c; | 5945 | bytes[i] = c; |
| 5918 | i += 1; | 5946 | i += 1; |
| 5919 | }, | 5947 | }, |
| 5920 | } | 5948 | } |
| 5921 | }, | 5949 | }, |
| 5922 | .Octal => { | 5950 | .octal => { |
| 5923 | const accept_digit = switch (c) { | 5951 | const accept_digit = switch (c) { |
| 5924 | // The maximum length of a octal literal is 3 digits | 5952 | // The maximum length of a octal literal is 3 digits |
| 5925 | '0'...'7' => count < 3, | 5953 | '0'...'7' => count < 3, |
| ... | @@ -5938,16 +5966,16 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 { | ... | @@ -5938,16 +5966,16 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 { |
| 5938 | num = 0; | 5966 | num = 0; |
| 5939 | count = 0; | 5967 | count = 0; |
| 5940 | if (c == '\\') | 5968 | if (c == '\\') |
| 5941 | state = .Escape | 5969 | state = .escape |
| 5942 | else | 5970 | else |
| 5943 | state = .Start; | 5971 | state = .start; |
| 5944 | bytes[i] = c; | 5972 | bytes[i] = c; |
| 5945 | i += 1; | 5973 | i += 1; |
| 5946 | } | 5974 | } |
| 5947 | }, | 5975 | }, |
| 5948 | } | 5976 | } |
| 5949 | } | 5977 | } |
| 5950 | if (state == .Hex or state == .Octal) | 5978 | if (state == .hex or state == .octal) |
| 5951 | i += std.fmt.formatIntBuf(bytes[i..], num, 16, .lower, std.fmt.FormatOptions{ .fill = '0', .width = 2 }); | 5979 | i += std.fmt.formatIntBuf(bytes[i..], num, 16, .lower, std.fmt.FormatOptions{ .fill = '0', .width = 2 }); |
| 5952 | return bytes[0..i]; | 5980 | return bytes[0..i]; |
| 5953 | } | 5981 | } |
| ... | @@ -5972,7 +6000,12 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N | ... | @@ -5972,7 +6000,12 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N |
| 5972 | const tok = m.next().?; | 6000 | const tok = m.next().?; |
| 5973 | const slice = m.slice(); | 6001 | const slice = m.slice(); |
| 5974 | switch (tok) { | 6002 | switch (tok) { |
| 5975 | .CharLiteral => { | 6003 | .char_literal, |
| | 6004 | .char_literal_utf_8, |
| | 6005 | .char_literal_utf_16, |
| | 6006 | .char_literal_utf_32, |
| | 6007 | .char_literal_wide, |
| | 6008 | => { |
| 5976 | if (slice[0] != '\'' or slice[1] == '\\' or slice.len == 3) { | 6009 | if (slice[0] != '\'' or slice[1] == '\\' or slice.len == 3) { |
| 5977 | return Tag.char_literal.create(c.arena, try escapeUnprintables(c, m)); | 6010 | return Tag.char_literal.create(c.arena, try escapeUnprintables(c, m)); |
| 5978 | } else { | 6011 | } else { |
| ... | @@ -5980,13 +6013,18 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N | ... | @@ -5980,13 +6013,18 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N |
| 5980 | return Tag.integer_literal.create(c.arena, str); | 6013 | return Tag.integer_literal.create(c.arena, str); |
| 5981 | } | 6014 | } |
| 5982 | }, | 6015 | }, |
| 5983 | .StringLiteral => { | 6016 | .string_literal, |
| | 6017 | .string_literal_utf_16, |
| | 6018 | .string_literal_utf_8, |
| | 6019 | .string_literal_utf_32, |
| | 6020 | .string_literal_wide, |
| | 6021 | => { |
| 5984 | return Tag.string_literal.create(c.arena, try escapeUnprintables(c, m)); | 6022 | return Tag.string_literal.create(c.arena, try escapeUnprintables(c, m)); |
| 5985 | }, | 6023 | }, |
| 5986 | .IntegerLiteral, .FloatLiteral => { | 6024 | .pp_num => { |
| 5987 | return parseCNumLit(c, m); | 6025 | return parseCNumLit(c, m); |
| 5988 | }, | 6026 | }, |
| 5989 | .Identifier => { | 6027 | .identifier, .extended_identifier => { |
| 5990 | if (c.global_scope.blank_macros.contains(slice)) { | 6028 | if (c.global_scope.blank_macros.contains(slice)) { |
| 5991 | return parseCPrimaryExprInner(c, m, scope); | 6029 | return parseCPrimaryExprInner(c, m, scope); |
| 5992 | } | 6030 | } |
| ... | @@ -5996,10 +6034,10 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N | ... | @@ -5996,10 +6034,10 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N |
| 5996 | scope.skipVariableDiscard(identifier.castTag(.identifier).?.data); | 6034 | scope.skipVariableDiscard(identifier.castTag(.identifier).?.data); |
| 5997 | return identifier; | 6035 | return identifier; |
| 5998 | }, | 6036 | }, |
| 5999 | .LParen => { | 6037 | .l_paren => { |
| 6000 | const inner_node = try parseCExpr(c, m, scope); | 6038 | const inner_node = try parseCExpr(c, m, scope); |
| 6001 | | 6039 | |
| 6002 | try m.skip(c, .RParen); | 6040 | try m.skip(c, .r_paren); |
| 6003 | return inner_node; | 6041 | return inner_node; |
| 6004 | }, | 6042 | }, |
| 6005 | else => { | 6043 | else => { |
| ... | @@ -6022,8 +6060,13 @@ fn parseCPrimaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | ... | @@ -6022,8 +6060,13 @@ fn parseCPrimaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6022 | // after a primary expression. | 6060 | // after a primary expression. |
| 6023 | while (true) { | 6061 | while (true) { |
| 6024 | switch (m.peek().?) { | 6062 | switch (m.peek().?) { |
| 6025 | .StringLiteral => {}, | 6063 | .string_literal, |
| 6026 | .Identifier => { | 6064 | .string_literal_utf_16, |
| | 6065 | .string_literal_utf_8, |
| | 6066 | .string_literal_utf_32, |
| | 6067 | .string_literal_wide, |
| | 6068 | => {}, |
| | 6069 | .identifier, .extended_identifier => { |
| 6027 | const tok = m.list[m.i + 1]; | 6070 | const tok = m.list[m.i + 1]; |
| 6028 | const slice = m.source[tok.start..tok.end]; | 6071 | const slice = m.source[tok.start..tok.end]; |
| 6029 | if (c.global_scope.blank_macros.contains(slice)) { | 6072 | if (c.global_scope.blank_macros.contains(slice)) { |
| ... | @@ -6057,20 +6100,20 @@ fn macroIntToBool(c: *Context, node: Node) !Node { | ... | @@ -6057,20 +6100,20 @@ fn macroIntToBool(c: *Context, node: Node) !Node { |
| 6057 | | 6100 | |
| 6058 | fn parseCCondExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | 6101 | fn parseCCondExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6059 | const node = try parseCOrExpr(c, m, scope); | 6102 | const node = try parseCOrExpr(c, m, scope); |
| 6060 | if (m.peek().? != .QuestionMark) { | 6103 | if (m.peek().? != .question_mark) { |
| 6061 | return node; | 6104 | return node; |
| 6062 | } | 6105 | } |
| 6063 | _ = m.next(); | 6106 | _ = m.next(); |
| 6064 | | 6107 | |
| 6065 | const then_body = try parseCOrExpr(c, m, scope); | 6108 | const then_body = try parseCOrExpr(c, m, scope); |
| 6066 | try m.skip(c, .Colon); | 6109 | try m.skip(c, .colon); |
| 6067 | const else_body = try parseCCondExpr(c, m, scope); | 6110 | const else_body = try parseCCondExpr(c, m, scope); |
| 6068 | return Tag.@"if".create(c.arena, .{ .cond = node, .then = then_body, .@"else" = else_body }); | 6111 | return Tag.@"if".create(c.arena, .{ .cond = node, .then = then_body, .@"else" = else_body }); |
| 6069 | } | 6112 | } |
| 6070 | | 6113 | |
| 6071 | fn parseCOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | 6114 | fn parseCOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6072 | var node = try parseCAndExpr(c, m, scope); | 6115 | var node = try parseCAndExpr(c, m, scope); |
| 6073 | while (m.next().? == .PipePipe) { | 6116 | while (m.next().? == .pipe_pipe) { |
| 6074 | const lhs = try macroIntToBool(c, node); | 6117 | const lhs = try macroIntToBool(c, node); |
| 6075 | const rhs = try macroIntToBool(c, try parseCAndExpr(c, m, scope)); | 6118 | const rhs = try macroIntToBool(c, try parseCAndExpr(c, m, scope)); |
| 6076 | node = try Tag.@"or".create(c.arena, .{ .lhs = lhs, .rhs = rhs }); | 6119 | node = try Tag.@"or".create(c.arena, .{ .lhs = lhs, .rhs = rhs }); |
| ... | @@ -6081,7 +6124,7 @@ fn parseCOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | ... | @@ -6081,7 +6124,7 @@ fn parseCOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6081 | | 6124 | |
| 6082 | fn parseCAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | 6125 | fn parseCAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6083 | var node = try parseCBitOrExpr(c, m, scope); | 6126 | var node = try parseCBitOrExpr(c, m, scope); |
| 6084 | while (m.next().? == .AmpersandAmpersand) { | 6127 | while (m.next().? == .ampersand_ampersand) { |
| 6085 | const lhs = try macroIntToBool(c, node); | 6128 | const lhs = try macroIntToBool(c, node); |
| 6086 | const rhs = try macroIntToBool(c, try parseCBitOrExpr(c, m, scope)); | 6129 | const rhs = try macroIntToBool(c, try parseCBitOrExpr(c, m, scope)); |
| 6087 | node = try Tag.@"and".create(c.arena, .{ .lhs = lhs, .rhs = rhs }); | 6130 | node = try Tag.@"and".create(c.arena, .{ .lhs = lhs, .rhs = rhs }); |
| ... | @@ -6092,7 +6135,7 @@ fn parseCAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | ... | @@ -6092,7 +6135,7 @@ fn parseCAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6092 | | 6135 | |
| 6093 | fn parseCBitOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | 6136 | fn parseCBitOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6094 | var node = try parseCBitXorExpr(c, m, scope); | 6137 | var node = try parseCBitXorExpr(c, m, scope); |
| 6095 | while (m.next().? == .Pipe) { | 6138 | while (m.next().? == .pipe) { |
| 6096 | const lhs = try macroIntFromBool(c, node); | 6139 | const lhs = try macroIntFromBool(c, node); |
| 6097 | const rhs = try macroIntFromBool(c, try parseCBitXorExpr(c, m, scope)); | 6140 | const rhs = try macroIntFromBool(c, try parseCBitXorExpr(c, m, scope)); |
| 6098 | node = try Tag.bit_or.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); | 6141 | node = try Tag.bit_or.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); |
| ... | @@ -6103,7 +6146,7 @@ fn parseCBitOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | ... | @@ -6103,7 +6146,7 @@ fn parseCBitOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6103 | | 6146 | |
| 6104 | fn parseCBitXorExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | 6147 | fn parseCBitXorExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6105 | var node = try parseCBitAndExpr(c, m, scope); | 6148 | var node = try parseCBitAndExpr(c, m, scope); |
| 6106 | while (m.next().? == .Caret) { | 6149 | while (m.next().? == .caret) { |
| 6107 | const lhs = try macroIntFromBool(c, node); | 6150 | const lhs = try macroIntFromBool(c, node); |
| 6108 | const rhs = try macroIntFromBool(c, try parseCBitAndExpr(c, m, scope)); | 6151 | const rhs = try macroIntFromBool(c, try parseCBitAndExpr(c, m, scope)); |
| 6109 | node = try Tag.bit_xor.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); | 6152 | node = try Tag.bit_xor.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); |
| ... | @@ -6114,7 +6157,7 @@ fn parseCBitXorExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | ... | @@ -6114,7 +6157,7 @@ fn parseCBitXorExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6114 | | 6157 | |
| 6115 | fn parseCBitAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | 6158 | fn parseCBitAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6116 | var node = try parseCEqExpr(c, m, scope); | 6159 | var node = try parseCEqExpr(c, m, scope); |
| 6117 | while (m.next().? == .Ampersand) { | 6160 | while (m.next().? == .ampersand) { |
| 6118 | const lhs = try macroIntFromBool(c, node); | 6161 | const lhs = try macroIntFromBool(c, node); |
| 6119 | const rhs = try macroIntFromBool(c, try parseCEqExpr(c, m, scope)); | 6162 | const rhs = try macroIntFromBool(c, try parseCEqExpr(c, m, scope)); |
| 6120 | node = try Tag.bit_and.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); | 6163 | node = try Tag.bit_and.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); |
| ... | @@ -6127,13 +6170,13 @@ fn parseCEqExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | ... | @@ -6127,13 +6170,13 @@ fn parseCEqExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6127 | var node = try parseCRelExpr(c, m, scope); | 6170 | var node = try parseCRelExpr(c, m, scope); |
| 6128 | while (true) { | 6171 | while (true) { |
| 6129 | switch (m.peek().?) { | 6172 | switch (m.peek().?) { |
| 6130 | .BangEqual => { | 6173 | .bang_equal => { |
| 6131 | _ = m.next(); | 6174 | _ = m.next(); |
| 6132 | const lhs = try macroIntFromBool(c, node); | 6175 | const lhs = try macroIntFromBool(c, node); |
| 6133 | const rhs = try macroIntFromBool(c, try parseCRelExpr(c, m, scope)); | 6176 | const rhs = try macroIntFromBool(c, try parseCRelExpr(c, m, scope)); |
| 6134 | node = try Tag.not_equal.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); | 6177 | node = try Tag.not_equal.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); |
| 6135 | }, | 6178 | }, |
| 6136 | .EqualEqual => { | 6179 | .equal_equal => { |
| 6137 | _ = m.next(); | 6180 | _ = m.next(); |
| 6138 | const lhs = try macroIntFromBool(c, node); | 6181 | const lhs = try macroIntFromBool(c, node); |
| 6139 | const rhs = try macroIntFromBool(c, try parseCRelExpr(c, m, scope)); | 6182 | const rhs = try macroIntFromBool(c, try parseCRelExpr(c, m, scope)); |
| ... | @@ -6148,25 +6191,25 @@ fn parseCRelExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | ... | @@ -6148,25 +6191,25 @@ fn parseCRelExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6148 | var node = try parseCShiftExpr(c, m, scope); | 6191 | var node = try parseCShiftExpr(c, m, scope); |
| 6149 | while (true) { | 6192 | while (true) { |
| 6150 | switch (m.peek().?) { | 6193 | switch (m.peek().?) { |
| 6151 | .AngleBracketRight => { | 6194 | .angle_bracket_right => { |
| 6152 | _ = m.next(); | 6195 | _ = m.next(); |
| 6153 | const lhs = try macroIntFromBool(c, node); | 6196 | const lhs = try macroIntFromBool(c, node); |
| 6154 | const rhs = try macroIntFromBool(c, try parseCShiftExpr(c, m, scope)); | 6197 | const rhs = try macroIntFromBool(c, try parseCShiftExpr(c, m, scope)); |
| 6155 | node = try Tag.greater_than.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); | 6198 | node = try Tag.greater_than.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); |
| 6156 | }, | 6199 | }, |
| 6157 | .AngleBracketRightEqual => { | 6200 | .angle_bracket_right_equal => { |
| 6158 | _ = m.next(); | 6201 | _ = m.next(); |
| 6159 | const lhs = try macroIntFromBool(c, node); | 6202 | const lhs = try macroIntFromBool(c, node); |
| 6160 | const rhs = try macroIntFromBool(c, try parseCShiftExpr(c, m, scope)); | 6203 | const rhs = try macroIntFromBool(c, try parseCShiftExpr(c, m, scope)); |
| 6161 | node = try Tag.greater_than_equal.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); | 6204 | node = try Tag.greater_than_equal.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); |
| 6162 | }, | 6205 | }, |
| 6163 | .AngleBracketLeft => { | 6206 | .angle_bracket_left => { |
| 6164 | _ = m.next(); | 6207 | _ = m.next(); |
| 6165 | const lhs = try macroIntFromBool(c, node); | 6208 | const lhs = try macroIntFromBool(c, node); |
| 6166 | const rhs = try macroIntFromBool(c, try parseCShiftExpr(c, m, scope)); | 6209 | const rhs = try macroIntFromBool(c, try parseCShiftExpr(c, m, scope)); |
| 6167 | node = try Tag.less_than.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); | 6210 | node = try Tag.less_than.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); |
| 6168 | }, | 6211 | }, |
| 6169 | .AngleBracketLeftEqual => { | 6212 | .angle_bracket_left_equal => { |
| 6170 | _ = m.next(); | 6213 | _ = m.next(); |
| 6171 | const lhs = try macroIntFromBool(c, node); | 6214 | const lhs = try macroIntFromBool(c, node); |
| 6172 | const rhs = try macroIntFromBool(c, try parseCShiftExpr(c, m, scope)); | 6215 | const rhs = try macroIntFromBool(c, try parseCShiftExpr(c, m, scope)); |
| ... | @@ -6181,13 +6224,13 @@ fn parseCShiftExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | ... | @@ -6181,13 +6224,13 @@ fn parseCShiftExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6181 | var node = try parseCAddSubExpr(c, m, scope); | 6224 | var node = try parseCAddSubExpr(c, m, scope); |
| 6182 | while (true) { | 6225 | while (true) { |
| 6183 | switch (m.peek().?) { | 6226 | switch (m.peek().?) { |
| 6184 | .AngleBracketAngleBracketLeft => { | 6227 | .angle_bracket_angle_bracket_left => { |
| 6185 | _ = m.next(); | 6228 | _ = m.next(); |
| 6186 | const lhs = try macroIntFromBool(c, node); | 6229 | const lhs = try macroIntFromBool(c, node); |
| 6187 | const rhs = try macroIntFromBool(c, try parseCAddSubExpr(c, m, scope)); | 6230 | const rhs = try macroIntFromBool(c, try parseCAddSubExpr(c, m, scope)); |
| 6188 | node = try Tag.shl.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); | 6231 | node = try Tag.shl.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); |
| 6189 | }, | 6232 | }, |
| 6190 | .AngleBracketAngleBracketRight => { | 6233 | .angle_bracket_angle_bracket_right => { |
| 6191 | _ = m.next(); | 6234 | _ = m.next(); |
| 6192 | const lhs = try macroIntFromBool(c, node); | 6235 | const lhs = try macroIntFromBool(c, node); |
| 6193 | const rhs = try macroIntFromBool(c, try parseCAddSubExpr(c, m, scope)); | 6236 | const rhs = try macroIntFromBool(c, try parseCAddSubExpr(c, m, scope)); |
| ... | @@ -6202,13 +6245,13 @@ fn parseCAddSubExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | ... | @@ -6202,13 +6245,13 @@ fn parseCAddSubExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6202 | var node = try parseCMulExpr(c, m, scope); | 6245 | var node = try parseCMulExpr(c, m, scope); |
| 6203 | while (true) { | 6246 | while (true) { |
| 6204 | switch (m.peek().?) { | 6247 | switch (m.peek().?) { |
| 6205 | .Plus => { | 6248 | .plus => { |
| 6206 | _ = m.next(); | 6249 | _ = m.next(); |
| 6207 | const lhs = try macroIntFromBool(c, node); | 6250 | const lhs = try macroIntFromBool(c, node); |
| 6208 | const rhs = try macroIntFromBool(c, try parseCMulExpr(c, m, scope)); | 6251 | const rhs = try macroIntFromBool(c, try parseCMulExpr(c, m, scope)); |
| 6209 | node = try Tag.add.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); | 6252 | node = try Tag.add.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); |
| 6210 | }, | 6253 | }, |
| 6211 | .Minus => { | 6254 | .minus => { |
| 6212 | _ = m.next(); | 6255 | _ = m.next(); |
| 6213 | const lhs = try macroIntFromBool(c, node); | 6256 | const lhs = try macroIntFromBool(c, node); |
| 6214 | const rhs = try macroIntFromBool(c, try parseCMulExpr(c, m, scope)); | 6257 | const rhs = try macroIntFromBool(c, try parseCMulExpr(c, m, scope)); |
| ... | @@ -6223,17 +6266,17 @@ fn parseCMulExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | ... | @@ -6223,17 +6266,17 @@ fn parseCMulExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6223 | var node = try parseCCastExpr(c, m, scope); | 6266 | var node = try parseCCastExpr(c, m, scope); |
| 6224 | while (true) { | 6267 | while (true) { |
| 6225 | switch (m.next().?) { | 6268 | switch (m.next().?) { |
| 6226 | .Asterisk => { | 6269 | .asterisk => { |
| 6227 | const lhs = try macroIntFromBool(c, node); | 6270 | const lhs = try macroIntFromBool(c, node); |
| 6228 | const rhs = try macroIntFromBool(c, try parseCCastExpr(c, m, scope)); | 6271 | const rhs = try macroIntFromBool(c, try parseCCastExpr(c, m, scope)); |
| 6229 | node = try Tag.mul.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); | 6272 | node = try Tag.mul.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); |
| 6230 | }, | 6273 | }, |
| 6231 | .Slash => { | 6274 | .slash => { |
| 6232 | const lhs = try macroIntFromBool(c, node); | 6275 | const lhs = try macroIntFromBool(c, node); |
| 6233 | const rhs = try macroIntFromBool(c, try parseCCastExpr(c, m, scope)); | 6276 | const rhs = try macroIntFromBool(c, try parseCCastExpr(c, m, scope)); |
| 6234 | node = try Tag.macro_arithmetic.create(c.arena, .{ .op = .div, .lhs = lhs, .rhs = rhs }); | 6277 | node = try Tag.macro_arithmetic.create(c.arena, .{ .op = .div, .lhs = lhs, .rhs = rhs }); |
| 6235 | }, | 6278 | }, |
| 6236 | .Percent => { | 6279 | .percent => { |
| 6237 | const lhs = try macroIntFromBool(c, node); | 6280 | const lhs = try macroIntFromBool(c, node); |
| 6238 | const rhs = try macroIntFromBool(c, try parseCCastExpr(c, m, scope)); | 6281 | const rhs = try macroIntFromBool(c, try parseCCastExpr(c, m, scope)); |
| 6239 | node = try Tag.macro_arithmetic.create(c.arena, .{ .op = .rem, .lhs = lhs, .rhs = rhs }); | 6282 | node = try Tag.macro_arithmetic.create(c.arena, .{ .op = .rem, .lhs = lhs, .rhs = rhs }); |
| ... | @@ -6248,17 +6291,18 @@ fn parseCMulExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | ... | @@ -6248,17 +6291,18 @@ fn parseCMulExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6248 | | 6291 | |
| 6249 | fn parseCCastExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | 6292 | fn parseCCastExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6250 | switch (m.next().?) { | 6293 | switch (m.next().?) { |
| 6251 | .LParen => { | 6294 | .l_paren => { |
| 6252 | if (try parseCTypeName(c, m, scope, true)) |type_name| { | 6295 | if (try parseCTypeName(c, m, scope, true)) |type_name| { |
| 6253 | while (true) { | 6296 | while (true) { |
| 6254 | const next_token = m.next().?; | 6297 | const next_token = m.next().?; |
| 6255 | switch (next_token) { | 6298 | switch (next_token) { |
| 6256 | .RParen => break, | 6299 | .r_paren => break, |
| 6257 | else => |next_tag| { | 6300 | else => |next_tag| { |
| 6258 | // Skip trailing blank defined before the RParen. | 6301 | // Skip trailing blank defined before the RParen. |
| 6259 | if (next_tag == .Identifier and c.global_scope.blank_macros.contains(m.slice())) { | 6302 | if ((next_tag == .identifier or next_tag == .extended_identifier) and |
| | 6303 | c.global_scope.blank_macros.contains(m.slice())) |
| 6260 | continue; | 6304 | continue; |
| 6261 | } | 6305 | |
| 6262 | try m.fail( | 6306 | try m.fail( |
| 6263 | c, | 6307 | c, |
| 6264 | "unable to translate C expr: expected ')' instead got '{s}'", | 6308 | "unable to translate C expr: expected ')' instead got '{s}'", |
| ... | @@ -6268,7 +6312,7 @@ fn parseCCastExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | ... | @@ -6268,7 +6312,7 @@ fn parseCCastExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6268 | }, | 6312 | }, |
| 6269 | } | 6313 | } |
| 6270 | } | 6314 | } |
| 6271 | if (m.peek().? == .LBrace) { | 6315 | if (m.peek().? == .l_brace) { |
| 6272 | // initializer list | 6316 | // initializer list |
| 6273 | return parseCPostfixExpr(c, m, scope, type_name); | 6317 | return parseCPostfixExpr(c, m, scope, type_name); |
| 6274 | } | 6318 | } |
| ... | @@ -6294,7 +6338,7 @@ fn parseCTypeName(c: *Context, m: *MacroCtx, scope: *Scope, allow_fail: bool) Pa | ... | @@ -6294,7 +6338,7 @@ fn parseCTypeName(c: *Context, m: *MacroCtx, scope: *Scope, allow_fail: bool) Pa |
| 6294 | fn parseCSpecifierQualifierList(c: *Context, m: *MacroCtx, scope: *Scope, allow_fail: bool) ParseError!?Node { | 6338 | fn parseCSpecifierQualifierList(c: *Context, m: *MacroCtx, scope: *Scope, allow_fail: bool) ParseError!?Node { |
| 6295 | const tok = m.next().?; | 6339 | const tok = m.next().?; |
| 6296 | switch (tok) { | 6340 | switch (tok) { |
| 6297 | .Identifier => { | 6341 | .identifier, .extended_identifier => { |
| 6298 | if (c.global_scope.blank_macros.contains(m.slice())) { | 6342 | if (c.global_scope.blank_macros.contains(m.slice())) { |
| 6299 | return try parseCSpecifierQualifierList(c, m, scope, allow_fail); | 6343 | return try parseCSpecifierQualifierList(c, m, scope, allow_fail); |
| 6300 | } | 6344 | } |
| ... | @@ -6304,25 +6348,25 @@ fn parseCSpecifierQualifierList(c: *Context, m: *MacroCtx, scope: *Scope, allow_ | ... | @@ -6304,25 +6348,25 @@ fn parseCSpecifierQualifierList(c: *Context, m: *MacroCtx, scope: *Scope, allow_ |
| 6304 | return try Tag.identifier.create(c.arena, mangled_name); | 6348 | return try Tag.identifier.create(c.arena, mangled_name); |
| 6305 | } | 6349 | } |
| 6306 | }, | 6350 | }, |
| 6307 | .Keyword_void => return try Tag.type.create(c.arena, "anyopaque"), | 6351 | .keyword_void => return try Tag.type.create(c.arena, "anyopaque"), |
| 6308 | .Keyword_bool => return try Tag.type.create(c.arena, "bool"), | 6352 | .keyword_bool => return try Tag.type.create(c.arena, "bool"), |
| 6309 | .Keyword_char, | 6353 | .keyword_char, |
| 6310 | .Keyword_int, | 6354 | .keyword_int, |
| 6311 | .Keyword_short, | 6355 | .keyword_short, |
| 6312 | .Keyword_long, | 6356 | .keyword_long, |
| 6313 | .Keyword_float, | 6357 | .keyword_float, |
| 6314 | .Keyword_double, | 6358 | .keyword_double, |
| 6315 | .Keyword_signed, | 6359 | .keyword_signed, |
| 6316 | .Keyword_unsigned, | 6360 | .keyword_unsigned, |
| 6317 | .Keyword_complex, | 6361 | .keyword_complex, |
| 6318 | => { | 6362 | => { |
| 6319 | m.i -= 1; | 6363 | m.i -= 1; |
| 6320 | return try parseCNumericType(c, m); | 6364 | return try parseCNumericType(c, m); |
| 6321 | }, | 6365 | }, |
| 6322 | .Keyword_enum, .Keyword_struct, .Keyword_union => { | 6366 | .keyword_enum, .keyword_struct, .keyword_union => { |
| 6323 | // struct Foo will be declared as struct_Foo by transRecordDecl | 6367 | // struct Foo will be declared as struct_Foo by transRecordDecl |
| 6324 | const slice = m.slice(); | 6368 | const slice = m.slice(); |
| 6325 | try m.skip(c, .Identifier); | 6369 | try m.skip(c, .identifier); |
| 6326 | | 6370 | |
| 6327 | const name = try std.fmt.allocPrint(c.arena, "{s}_{s}", .{ slice, m.slice() }); | 6371 | const name = try std.fmt.allocPrint(c.arena, "{s}_{s}", .{ slice, m.slice() }); |
| 6328 | return try Tag.identifier.create(c.arena, name); | 6372 | return try Tag.identifier.create(c.arena, name); |
| ... | @@ -6364,15 +6408,15 @@ fn parseCNumericType(c: *Context, m: *MacroCtx) ParseError!Node { | ... | @@ -6364,15 +6408,15 @@ fn parseCNumericType(c: *Context, m: *MacroCtx) ParseError!Node { |
| 6364 | var i: u8 = 0; | 6408 | var i: u8 = 0; |
| 6365 | while (i < math.maxInt(u8)) : (i += 1) { | 6409 | while (i < math.maxInt(u8)) : (i += 1) { |
| 6366 | switch (m.next().?) { | 6410 | switch (m.next().?) { |
| 6367 | .Keyword_double => kw.double += 1, | 6411 | .keyword_double => kw.double += 1, |
| 6368 | .Keyword_long => kw.long += 1, | 6412 | .keyword_long => kw.long += 1, |
| 6369 | .Keyword_int => kw.int += 1, | 6413 | .keyword_int => kw.int += 1, |
| 6370 | .Keyword_float => kw.float += 1, | 6414 | .keyword_float => kw.float += 1, |
| 6371 | .Keyword_short => kw.short += 1, | 6415 | .keyword_short => kw.short += 1, |
| 6372 | .Keyword_char => kw.char += 1, | 6416 | .keyword_char => kw.char += 1, |
| 6373 | .Keyword_unsigned => kw.unsigned += 1, | 6417 | .keyword_unsigned => kw.unsigned += 1, |
| 6374 | .Keyword_signed => kw.signed += 1, | 6418 | .keyword_signed => kw.signed += 1, |
| 6375 | .Keyword_complex => kw.complex += 1, | 6419 | .keyword_complex => kw.complex += 1, |
| 6376 | else => { | 6420 | else => { |
| 6377 | m.i -= 1; | 6421 | m.i -= 1; |
| 6378 | break; | 6422 | break; |
| ... | @@ -6442,11 +6486,11 @@ fn parseCNumericType(c: *Context, m: *MacroCtx) ParseError!Node { | ... | @@ -6442,11 +6486,11 @@ fn parseCNumericType(c: *Context, m: *MacroCtx) ParseError!Node { |
| 6442 | | 6486 | |
| 6443 | fn parseCAbstractDeclarator(c: *Context, m: *MacroCtx, node: Node) ParseError!Node { | 6487 | fn parseCAbstractDeclarator(c: *Context, m: *MacroCtx, node: Node) ParseError!Node { |
| 6444 | switch (m.next().?) { | 6488 | switch (m.next().?) { |
| 6445 | .Asterisk => { | 6489 | .asterisk => { |
| 6446 | // last token of `node` | 6490 | // last token of `node` |
| 6447 | const prev_id = m.list[m.i - 1].id; | 6491 | const prev_id = m.list[m.i - 1].id; |
| 6448 | | 6492 | |
| 6449 | if (prev_id == .Keyword_void) { | 6493 | if (prev_id == .keyword_void) { |
| 6450 | const ptr = try Tag.single_pointer.create(c.arena, .{ | 6494 | const ptr = try Tag.single_pointer.create(c.arena, .{ |
| 6451 | .is_const = false, | 6495 | .is_const = false, |
| 6452 | .is_volatile = false, | 6496 | .is_volatile = false, |
| ... | @@ -6472,28 +6516,28 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope, type_name: ?Node) | ... | @@ -6472,28 +6516,28 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope, type_name: ?Node) |
| 6472 | var node = type_name orelse try parseCPrimaryExpr(c, m, scope); | 6516 | var node = type_name orelse try parseCPrimaryExpr(c, m, scope); |
| 6473 | while (true) { | 6517 | while (true) { |
| 6474 | switch (m.next().?) { | 6518 | switch (m.next().?) { |
| 6475 | .Period => { | 6519 | .period => { |
| 6476 | try m.skip(c, .Identifier); | 6520 | try m.skip(c, .identifier); |
| 6477 | | 6521 | |
| 6478 | node = try Tag.field_access.create(c.arena, .{ .lhs = node, .field_name = m.slice() }); | 6522 | node = try Tag.field_access.create(c.arena, .{ .lhs = node, .field_name = m.slice() }); |
| 6479 | }, | 6523 | }, |
| 6480 | .Arrow => { | 6524 | .arrow => { |
| 6481 | try m.skip(c, .Identifier); | 6525 | try m.skip(c, .identifier); |
| 6482 | | 6526 | |
| 6483 | const deref = try Tag.deref.create(c.arena, node); | 6527 | const deref = try Tag.deref.create(c.arena, node); |
| 6484 | node = try Tag.field_access.create(c.arena, .{ .lhs = deref, .field_name = m.slice() }); | 6528 | node = try Tag.field_access.create(c.arena, .{ .lhs = deref, .field_name = m.slice() }); |
| 6485 | }, | 6529 | }, |
| 6486 | .LBracket => { | 6530 | .l_bracket => { |
| 6487 | const index_val = try macroIntFromBool(c, try parseCExpr(c, m, scope)); | 6531 | const index_val = try macroIntFromBool(c, try parseCExpr(c, m, scope)); |
| 6488 | const index = try Tag.as.create(c.arena, .{ | 6532 | const index = try Tag.as.create(c.arena, .{ |
| 6489 | .lhs = try Tag.type.create(c.arena, "usize"), | 6533 | .lhs = try Tag.type.create(c.arena, "usize"), |
| 6490 | .rhs = try Tag.int_cast.create(c.arena, index_val), | 6534 | .rhs = try Tag.int_cast.create(c.arena, index_val), |
| 6491 | }); | 6535 | }); |
| 6492 | node = try Tag.array_access.create(c.arena, .{ .lhs = node, .rhs = index }); | 6536 | node = try Tag.array_access.create(c.arena, .{ .lhs = node, .rhs = index }); |
| 6493 | try m.skip(c, .RBracket); | 6537 | try m.skip(c, .r_bracket); |
| 6494 | }, | 6538 | }, |
| 6495 | .LParen => { | 6539 | .l_paren => { |
| 6496 | if (m.peek().? == .RParen) { | 6540 | if (m.peek().? == .r_paren) { |
| 6497 | m.i += 1; | 6541 | m.i += 1; |
| 6498 | node = try Tag.call.create(c.arena, .{ .lhs = node, .args = &[0]Node{} }); | 6542 | node = try Tag.call.create(c.arena, .{ .lhs = node, .args = &[0]Node{} }); |
| 6499 | } else { | 6543 | } else { |
| ... | @@ -6504,8 +6548,8 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope, type_name: ?Node) | ... | @@ -6504,8 +6548,8 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope, type_name: ?Node) |
| 6504 | try args.append(arg); | 6548 | try args.append(arg); |
| 6505 | const next_id = m.next().?; | 6549 | const next_id = m.next().?; |
| 6506 | switch (next_id) { | 6550 | switch (next_id) { |
| 6507 | .Comma => {}, | 6551 | .comma => {}, |
| 6508 | .RParen => break, | 6552 | .r_paren => break, |
| 6509 | else => { | 6553 | else => { |
| 6510 | try m.fail(c, "unable to translate C expr: expected ',' or ')' instead got '{s}'", .{next_id.symbol()}); | 6554 | try m.fail(c, "unable to translate C expr: expected ',' or ')' instead got '{s}'", .{next_id.symbol()}); |
| 6511 | return error.ParseError; | 6555 | return error.ParseError; |
| ... | @@ -6515,24 +6559,24 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope, type_name: ?Node) | ... | @@ -6515,24 +6559,24 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope, type_name: ?Node) |
| 6515 | node = try Tag.call.create(c.arena, .{ .lhs = node, .args = try c.arena.dupe(Node, args.items) }); | 6559 | node = try Tag.call.create(c.arena, .{ .lhs = node, .args = try c.arena.dupe(Node, args.items) }); |
| 6516 | } | 6560 | } |
| 6517 | }, | 6561 | }, |
| 6518 | .LBrace => { | 6562 | .l_brace => { |
| 6519 | // Check for designated field initializers | 6563 | // Check for designated field initializers |
| 6520 | if (m.peek().? == .Period) { | 6564 | if (m.peek().? == .period) { |
| 6521 | var init_vals = std.ArrayList(ast.Payload.ContainerInitDot.Initializer).init(c.gpa); | 6565 | var init_vals = std.ArrayList(ast.Payload.ContainerInitDot.Initializer).init(c.gpa); |
| 6522 | defer init_vals.deinit(); | 6566 | defer init_vals.deinit(); |
| 6523 | | 6567 | |
| 6524 | while (true) { | 6568 | while (true) { |
| 6525 | try m.skip(c, .Period); | 6569 | try m.skip(c, .period); |
| 6526 | try m.skip(c, .Identifier); | 6570 | try m.skip(c, .identifier); |
| 6527 | const name = m.slice(); | 6571 | const name = m.slice(); |
| 6528 | try m.skip(c, .Equal); | 6572 | try m.skip(c, .equal); |
| 6529 | | 6573 | |
| 6530 | const val = try parseCCondExpr(c, m, scope); | 6574 | const val = try parseCCondExpr(c, m, scope); |
| 6531 | try init_vals.append(.{ .name = name, .value = val }); | 6575 | try init_vals.append(.{ .name = name, .value = val }); |
| 6532 | const next_id = m.next().?; | 6576 | const next_id = m.next().?; |
| 6533 | switch (next_id) { | 6577 | switch (next_id) { |
| 6534 | .Comma => {}, | 6578 | .comma => {}, |
| 6535 | .RBrace => break, | 6579 | .r_brace => break, |
| 6536 | else => { | 6580 | else => { |
| 6537 | try m.fail(c, "unable to translate C expr: expected ',' or '}}' instead got '{s}'", .{next_id.symbol()}); | 6581 | try m.fail(c, "unable to translate C expr: expected ',' or '}}' instead got '{s}'", .{next_id.symbol()}); |
| 6538 | return error.ParseError; | 6582 | return error.ParseError; |
| ... | @@ -6552,8 +6596,8 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope, type_name: ?Node) | ... | @@ -6552,8 +6596,8 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope, type_name: ?Node) |
| 6552 | try init_vals.append(val); | 6596 | try init_vals.append(val); |
| 6553 | const next_id = m.next().?; | 6597 | const next_id = m.next().?; |
| 6554 | switch (next_id) { | 6598 | switch (next_id) { |
| 6555 | .Comma => {}, | 6599 | .comma => {}, |
| 6556 | .RBrace => break, | 6600 | .r_brace => break, |
| 6557 | else => { | 6601 | else => { |
| 6558 | try m.fail(c, "unable to translate C expr: expected ',' or '}}' instead got '{s}'", .{next_id.symbol()}); | 6602 | try m.fail(c, "unable to translate C expr: expected ',' or '}}' instead got '{s}'", .{next_id.symbol()}); |
| 6559 | return error.ParseError; | 6603 | return error.ParseError; |
| ... | @@ -6563,7 +6607,7 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope, type_name: ?Node) | ... | @@ -6563,7 +6607,7 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope, type_name: ?Node) |
| 6563 | const tuple_node = try Tag.tuple.create(c.arena, try c.arena.dupe(Node, init_vals.items)); | 6607 | const tuple_node = try Tag.tuple.create(c.arena, try c.arena.dupe(Node, init_vals.items)); |
| 6564 | node = try Tag.std_mem_zeroinit.create(c.arena, .{ .lhs = node, .rhs = tuple_node }); | 6608 | node = try Tag.std_mem_zeroinit.create(c.arena, .{ .lhs = node, .rhs = tuple_node }); |
| 6565 | }, | 6609 | }, |
| 6566 | .PlusPlus, .MinusMinus => { | 6610 | .plus_plus, .minus_minus => { |
| 6567 | try m.fail(c, "TODO postfix inc/dec expr", .{}); | 6611 | try m.fail(c, "TODO postfix inc/dec expr", .{}); |
| 6568 | return error.ParseError; | 6612 | return error.ParseError; |
| 6569 | }, | 6613 | }, |
| ... | @@ -6577,47 +6621,47 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope, type_name: ?Node) | ... | @@ -6577,47 +6621,47 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope, type_name: ?Node) |
| 6577 | | 6621 | |
| 6578 | fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | 6622 | fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6579 | switch (m.next().?) { | 6623 | switch (m.next().?) { |
| 6580 | .Bang => { | 6624 | .bang => { |
| 6581 | const operand = try macroIntToBool(c, try parseCCastExpr(c, m, scope)); | 6625 | const operand = try macroIntToBool(c, try parseCCastExpr(c, m, scope)); |
| 6582 | return Tag.not.create(c.arena, operand); | 6626 | return Tag.not.create(c.arena, operand); |
| 6583 | }, | 6627 | }, |
| 6584 | .Minus => { | 6628 | .minus => { |
| 6585 | const operand = try macroIntFromBool(c, try parseCCastExpr(c, m, scope)); | 6629 | const operand = try macroIntFromBool(c, try parseCCastExpr(c, m, scope)); |
| 6586 | return Tag.negate.create(c.arena, operand); | 6630 | return Tag.negate.create(c.arena, operand); |
| 6587 | }, | 6631 | }, |
| 6588 | .Plus => return try parseCCastExpr(c, m, scope), | 6632 | .plus => return try parseCCastExpr(c, m, scope), |
| 6589 | .Tilde => { | 6633 | .tilde => { |
| 6590 | const operand = try macroIntFromBool(c, try parseCCastExpr(c, m, scope)); | 6634 | const operand = try macroIntFromBool(c, try parseCCastExpr(c, m, scope)); |
| 6591 | return Tag.bit_not.create(c.arena, operand); | 6635 | return Tag.bit_not.create(c.arena, operand); |
| 6592 | }, | 6636 | }, |
| 6593 | .Asterisk => { | 6637 | .asterisk => { |
| 6594 | const operand = try parseCCastExpr(c, m, scope); | 6638 | const operand = try parseCCastExpr(c, m, scope); |
| 6595 | return Tag.deref.create(c.arena, operand); | 6639 | return Tag.deref.create(c.arena, operand); |
| 6596 | }, | 6640 | }, |
| 6597 | .Ampersand => { | 6641 | .ampersand => { |
| 6598 | const operand = try parseCCastExpr(c, m, scope); | 6642 | const operand = try parseCCastExpr(c, m, scope); |
| 6599 | return Tag.address_of.create(c.arena, operand); | 6643 | return Tag.address_of.create(c.arena, operand); |
| 6600 | }, | 6644 | }, |
| 6601 | .Keyword_sizeof => { | 6645 | .keyword_sizeof => { |
| 6602 | const operand = if (m.peek().? == .LParen) blk: { | 6646 | const operand = if (m.peek().? == .l_paren) blk: { |
| 6603 | _ = m.next(); | 6647 | _ = m.next(); |
| 6604 | const inner = (try parseCTypeName(c, m, scope, false)).?; | 6648 | const inner = (try parseCTypeName(c, m, scope, false)).?; |
| 6605 | try m.skip(c, .RParen); | 6649 | try m.skip(c, .r_paren); |
| 6606 | break :blk inner; | 6650 | break :blk inner; |
| 6607 | } else try parseCUnaryExpr(c, m, scope); | 6651 | } else try parseCUnaryExpr(c, m, scope); |
| 6608 | | 6652 | |
| 6609 | return Tag.helpers_sizeof.create(c.arena, operand); | 6653 | return Tag.helpers_sizeof.create(c.arena, operand); |
| 6610 | }, | 6654 | }, |
| 6611 | .Keyword_alignof => { | 6655 | .keyword_alignof => { |
| 6612 | // TODO this won't work if using <stdalign.h>'s | 6656 | // TODO this won't work if using <stdalign.h>'s |
| 6613 | // #define alignof _Alignof | 6657 | // #define alignof _Alignof |
| 6614 | try m.skip(c, .LParen); | 6658 | try m.skip(c, .l_paren); |
| 6615 | const operand = (try parseCTypeName(c, m, scope, false)).?; | 6659 | const operand = (try parseCTypeName(c, m, scope, false)).?; |
| 6616 | try m.skip(c, .RParen); | 6660 | try m.skip(c, .r_paren); |
| 6617 | | 6661 | |
| 6618 | return Tag.alignof.create(c.arena, operand); | 6662 | return Tag.alignof.create(c.arena, operand); |
| 6619 | }, | 6663 | }, |
| 6620 | .PlusPlus, .MinusMinus => { | 6664 | .plus_plus, .minus_minus => { |
| 6621 | try m.fail(c, "TODO unary inc/dec expr", .{}); | 6665 | try m.fail(c, "TODO unary inc/dec expr", .{}); |
| 6622 | return error.ParseError; | 6666 | return error.ParseError; |
| 6623 | }, | 6667 | }, |