authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-08-11 12:20:58+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-08-11 12:24:45+03:00
log2b28cebf644b29543fcb52504b11931a7c797ffb
tree9346697c4fc2faf5dc8d6bb10acdce38f577cf45
parentcf5932b236424d8e1b52500bc80ffb6d79e20134
signaturelock-open Commit is signed but in an unrecognized format.

translate-c: use mangled name when macro translation fails

Closes #6009

2 files changed, 127 insertions(+), 198 deletions(-)

src-self-hosted/translate_c.zig+123-198
...@@ -3089,7 +3089,7 @@ fn transUnaryExprOrTypeTraitExpr(...@@ -3089,7 +3089,7 @@ fn transUnaryExprOrTypeTraitExpr(
3089 .AlignOf => "@alignOf",3089 .AlignOf => "@alignOf",
3090 .PreferredAlignOf,3090 .PreferredAlignOf,
3091 .VecStep,3091 .VecStep,
3092 .OpenMPRequiredSimdAlign, 3092 .OpenMPRequiredSimdAlign,
3093 => return revertAndWarn(3093 => return revertAndWarn(
3094 rp,3094 rp,
3095 error.UnsupportedTranslation,3095 error.UnsupportedTranslation,
...@@ -5220,26 +5220,32 @@ pub fn freeErrors(errors: []ClangErrMsg) void {...@@ -5220,26 +5220,32 @@ pub fn freeErrors(errors: []ClangErrMsg) void {
5220 ZigClangErrorMsg_delete(errors.ptr, errors.len);5220 ZigClangErrorMsg_delete(errors.ptr, errors.len);
5221}5221}
52225222
5223const CTokIterator = struct {5223const MacroCtx = struct {
5224 source: []const u8,5224 source: []const u8,
5225 list: []const CToken,5225 list: []const CToken,
5226 i: usize = 0,5226 i: usize = 0,
5227 loc: ZigClangSourceLocation,
5228 name: []const u8,
52275229
5228 fn peek(self: *CTokIterator) ?CToken.Id {5230 fn peek(self: *MacroCtx) ?CToken.Id {
5229 if (self.i >= self.list.len) return null;5231 if (self.i >= self.list.len) return null;
5230 return self.list[self.i + 1].id;5232 return self.list[self.i + 1].id;
5231 }5233 }
52325234
5233 fn next(self: *CTokIterator) ?CToken.Id {5235 fn next(self: *MacroCtx) ?CToken.Id {
5234 if (self.i >= self.list.len) return null;5236 if (self.i >= self.list.len) return null;
5235 self.i += 1;5237 self.i += 1;
5236 return self.list[self.i].id;5238 return self.list[self.i].id;
5237 }5239 }
52385240
5239 fn slice(self: *CTokIterator, index: usize) []const u8 {5241 fn slice(self: *MacroCtx) []const u8 {
5240 const tok = self.list[index];5242 const tok = self.list[self.i];
5241 return self.source[tok.start..tok.end];5243 return self.source[tok.start..tok.end];
5242 }5244 }
5245
5246 fn fail(self: *MacroCtx, c: *Context, comptime fmt: []const u8, args: anytype) !void {
5247 return failDecl(c, self.loc, self.name, fmt, args);
5248 }
5243};5249};
52445250
5245fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void {5251fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void {
...@@ -5286,18 +5292,21 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void {...@@ -5286,18 +5292,21 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void {
5286 try tok_list.append(tok);5292 try tok_list.append(tok);
5287 }5293 }
52885294
5289 var tok_it = CTokIterator{5295 var macro_ctx = MacroCtx{
5290 .source = slice,5296 .source = slice,
5291 .list = tok_list.items,5297 .list = tok_list.items,
5298 .name = mangled_name,
5299 .loc = begin_loc,
5292 };5300 };
5293 assert(mem.eql(u8, tok_it.slice(0), name));5301 assert(mem.eql(u8, macro_ctx.slice(), name));
52945302
5295 var macro_fn = false;5303 var macro_fn = false;
5296 switch (tok_it.peek().?) {5304 switch (macro_ctx.peek().?) {
5297 .Identifier => {5305 .Identifier => {
5298 // if it equals itself, ignore. for example, from stdio.h:5306 // if it equals itself, ignore. for example, from stdio.h:
5299 // #define stdin stdin5307 // #define stdin stdin
5300 if (mem.eql(u8, name, tok_it.slice(1))) {5308 const tok = macro_ctx.list[1];
5309 if (mem.eql(u8, name, slice[tok.start..tok.end])) {
5301 continue;5310 continue;
5302 }5311 }
5303 },5312 },
...@@ -5308,15 +5317,15 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void {...@@ -5308,15 +5317,15 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void {
5308 },5317 },
5309 .LParen => {5318 .LParen => {
5310 // if the name is immediately followed by a '(' then it is a function5319 // if the name is immediately followed by a '(' then it is a function
5311 macro_fn = tok_it.list[0].end == tok_it.list[1].start;5320 macro_fn = macro_ctx.list[0].end == macro_ctx.list[1].start;
5312 },5321 },
5313 else => {},5322 else => {},
5314 }5323 }
53155324
5316 (if (macro_fn)5325 (if (macro_fn)
5317 transMacroFnDefine(c, &tok_it, mangled_name, begin_loc)5326 transMacroFnDefine(c, &macro_ctx)
5318 else5327 else
5319 transMacroDefine(c, &tok_it, mangled_name, begin_loc)) catch |err| switch (err) {5328 transMacroDefine(c, &macro_ctx)) catch |err| switch (err) {
5320 error.ParseError => continue,5329 error.ParseError => continue,
5321 error.OutOfMemory => |e| return e,5330 error.OutOfMemory => |e| return e,
5322 };5331 };
...@@ -5326,24 +5335,18 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void {...@@ -5326,24 +5335,18 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void {
5326 }5335 }
5327}5336}
53285337
5329fn transMacroDefine(c: *Context, it: *CTokIterator, name: []const u8, source_loc: ZigClangSourceLocation) ParseError!void {5338fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void {
5330 const scope = &c.global_scope.base;5339 const scope = &c.global_scope.base;
53315340
5332 const visib_tok = try appendToken(c, .Keyword_pub, "pub");5341 const visib_tok = try appendToken(c, .Keyword_pub, "pub");
5333 const mut_tok = try appendToken(c, .Keyword_const, "const");5342 const mut_tok = try appendToken(c, .Keyword_const, "const");
5334 const name_tok = try appendIdentifier(c, name);5343 const name_tok = try appendIdentifier(c, m.name);
5335 const eq_token = try appendToken(c, .Equal, "=");5344 const eq_token = try appendToken(c, .Equal, "=");
53365345
5337 const init_node = try parseCExpr(c, it, source_loc, scope);5346 const init_node = try parseCExpr(c, m, scope);
5338 const last = it.next().?;5347 const last = m.next().?;
5339 if (last != .Eof and last != .Nl)5348 if (last != .Eof and last != .Nl)
5340 return failDecl(5349 return m.fail(c, "unable to translate C expr: unexpected token .{}", .{@tagName(last)});
5341 c,
5342 source_loc,
5343 name,
5344 "unable to translate C expr: unexpected token .{}",
5345 .{@tagName(last)},
5346 );
53475350
5348 const semicolon_token = try appendToken(c, .Semicolon, ";");5351 const semicolon_token = try appendToken(c, .Semicolon, ";");
5349 const node = try ast.Node.VarDecl.create(c.arena, .{5352 const node = try ast.Node.VarDecl.create(c.arena, .{
...@@ -5355,10 +5358,10 @@ fn transMacroDefine(c: *Context, it: *CTokIterator, name: []const u8, source_loc...@@ -5355,10 +5358,10 @@ fn transMacroDefine(c: *Context, it: *CTokIterator, name: []const u8, source_loc
5355 .eq_token = eq_token,5358 .eq_token = eq_token,
5356 .init_node = init_node,5359 .init_node = init_node,
5357 });5360 });
5358 _ = try c.global_scope.macro_table.put(name, &node.base);5361 _ = try c.global_scope.macro_table.put(m.name, &node.base);
5359}5362}
53605363
5361fn transMacroFnDefine(c: *Context, it: *CTokIterator, name: []const u8, source_loc: ZigClangSourceLocation) ParseError!void {5364fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void {
5362 var block_scope = try Scope.Block.init(c, &c.global_scope.base, null);5365 var block_scope = try Scope.Block.init(c, &c.global_scope.base, null);
5363 defer block_scope.deinit();5366 defer block_scope.deinit();
5364 const scope = &block_scope.base;5367 const scope = &block_scope.base;
...@@ -5366,34 +5369,22 @@ fn transMacroFnDefine(c: *Context, it: *CTokIterator, name: []const u8, source_l...@@ -5366,34 +5369,22 @@ fn transMacroFnDefine(c: *Context, it: *CTokIterator, name: []const u8, source_l
5366 const pub_tok = try appendToken(c, .Keyword_pub, "pub");5369 const pub_tok = try appendToken(c, .Keyword_pub, "pub");
5367 const inline_tok = try appendToken(c, .Keyword_inline, "inline");5370 const inline_tok = try appendToken(c, .Keyword_inline, "inline");
5368 const fn_tok = try appendToken(c, .Keyword_fn, "fn");5371 const fn_tok = try appendToken(c, .Keyword_fn, "fn");
5369 const name_tok = try appendIdentifier(c, name);5372 const name_tok = try appendIdentifier(c, m.name);
5370 _ = try appendToken(c, .LParen, "(");5373 _ = try appendToken(c, .LParen, "(");
53715374
5372 if (it.next().? != .LParen) {5375 if (m.next().? != .LParen) {
5373 return failDecl(5376 return m.fail(c, "unable to translate C expr: expected '('", .{});
5374 c,
5375 source_loc,
5376 name,
5377 "unable to translate C expr: expected '('",
5378 .{},
5379 );
5380 }5377 }
53815378
5382 var fn_params = std.ArrayList(ast.Node.FnProto.ParamDecl).init(c.gpa);5379 var fn_params = std.ArrayList(ast.Node.FnProto.ParamDecl).init(c.gpa);
5383 defer fn_params.deinit();5380 defer fn_params.deinit();
53845381
5385 while (true) {5382 while (true) {
5386 if (it.next().? != .Identifier) {5383 if (m.next().? != .Identifier) {
5387 return failDecl(5384 return m.fail(c, "unable to translate C expr: expected identifier", .{});
5388 c,
5389 source_loc,
5390 name,
5391 "unable to translate C expr: expected identifier",
5392 .{},
5393 );
5394 }5385 }
53955386
5396 const mangled_name = try block_scope.makeMangledName(c, it.slice(it.i));5387 const mangled_name = try block_scope.makeMangledName(c, m.slice());
5397 const param_name_tok = try appendIdentifier(c, mangled_name);5388 const param_name_tok = try appendIdentifier(c, mangled_name);
5398 _ = try appendToken(c, .Colon, ":");5389 _ = try appendToken(c, .Colon, ":");
53995390
...@@ -5411,20 +5402,14 @@ fn transMacroFnDefine(c: *Context, it: *CTokIterator, name: []const u8, source_l...@@ -5411,20 +5402,14 @@ fn transMacroFnDefine(c: *Context, it: *CTokIterator, name: []const u8, source_l
5411 .param_type = .{ .any_type = &any_type.base },5402 .param_type = .{ .any_type = &any_type.base },
5412 };5403 };
54135404
5414 if (it.peek().? != .Comma)5405 if (m.peek().? != .Comma)
5415 break;5406 break;
5416 _ = it.next();5407 _ = m.next();
5417 _ = try appendToken(c, .Comma, ",");5408 _ = try appendToken(c, .Comma, ",");
5418 }5409 }
54195410
5420 if (it.next().? != .RParen) {5411 if (m.next().? != .RParen) {
5421 return failDecl(5412 return m.fail(c, "unable to translate C expr: expected ')'", .{});
5422 c,
5423 source_loc,
5424 name,
5425 "unable to translate C expr: expected ')'",
5426 .{},
5427 );
5428 }5413 }
54295414
5430 _ = try appendToken(c, .RParen, ")");5415 _ = try appendToken(c, .RParen, ")");
...@@ -5432,16 +5417,10 @@ fn transMacroFnDefine(c: *Context, it: *CTokIterator, name: []const u8, source_l...@@ -5432,16 +5417,10 @@ fn transMacroFnDefine(c: *Context, it: *CTokIterator, name: []const u8, source_l
5432 const type_of = try c.createBuiltinCall("@TypeOf", 1);5417 const type_of = try c.createBuiltinCall("@TypeOf", 1);
54335418
5434 const return_kw = try appendToken(c, .Keyword_return, "return");5419 const return_kw = try appendToken(c, .Keyword_return, "return");
5435 const expr = try parseCExpr(c, it, source_loc, scope);5420 const expr = try parseCExpr(c, m, scope);
5436 const last = it.next().?;5421 const last = m.next().?;
5437 if (last != .Eof and last != .Nl)5422 if (last != .Eof and last != .Nl)
5438 return failDecl(5423 return m.fail(c, "unable to translate C expr: unexpected token .{}", .{@tagName(last)});
5439 c,
5440 source_loc,
5441 name,
5442 "unable to translate C expr: unexpected token .{}",
5443 .{@tagName(last)},
5444 );
5445 _ = try appendToken(c, .Semicolon, ";");5424 _ = try appendToken(c, .Semicolon, ";");
5446 const type_of_arg = if (expr.tag != .Block) expr else blk: {5425 const type_of_arg = if (expr.tag != .Block) expr else blk: {
5447 const blk = @fieldParentPtr(ast.Node.Block, "base", expr);5426 const blk = @fieldParentPtr(ast.Node.Block, "base", expr);
...@@ -5472,32 +5451,26 @@ fn transMacroFnDefine(c: *Context, it: *CTokIterator, name: []const u8, source_l...@@ -5472,32 +5451,26 @@ fn transMacroFnDefine(c: *Context, it: *CTokIterator, name: []const u8, source_l
5472 });5451 });
5473 mem.copy(ast.Node.FnProto.ParamDecl, fn_proto.params(), fn_params.items);5452 mem.copy(ast.Node.FnProto.ParamDecl, fn_proto.params(), fn_params.items);
54745453
5475 _ = try c.global_scope.macro_table.put(name, &fn_proto.base);5454 _ = try c.global_scope.macro_table.put(m.name, &fn_proto.base);
5476}5455}
54775456
5478const ParseError = Error || error{ParseError};5457const ParseError = Error || error{ParseError};
54795458
5480fn parseCExpr(c: *Context, it: *CTokIterator, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node {5459fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
5481 const node = try parseCPrefixOpExpr(c, it, source_loc, scope);5460 const node = try parseCPrefixOpExpr(c, m, scope);
5482 switch (it.next().?) {5461 switch (m.next().?) {
5483 .QuestionMark => {5462 .QuestionMark => {
5484 // must come immediately after expr5463 // must come immediately after expr
5485 _ = try appendToken(c, .RParen, ")");5464 _ = try appendToken(c, .RParen, ")");
5486 const if_node = try transCreateNodeIf(c);5465 const if_node = try transCreateNodeIf(c);
5487 if_node.condition = node;5466 if_node.condition = node;
5488 if_node.body = try parseCPrimaryExpr(c, it, source_loc, scope);5467 if_node.body = try parseCPrimaryExpr(c, m, scope);
5489 if (it.next().? != .Colon) {5468 if (m.next().? != .Colon) {
5490 try failDecl(5469 try m.fail(c, "unable to translate C expr: expected ':'", .{});
5491 c,
5492 source_loc,
5493 it.slice(0),
5494 "unable to translate C expr: expected ':'",
5495 .{},
5496 );
5497 return error.ParseError;5470 return error.ParseError;
5498 }5471 }
5499 if_node.@"else" = try transCreateNodeElse(c);5472 if_node.@"else" = try transCreateNodeElse(c);
5500 if_node.@"else".?.body = try parseCPrimaryExpr(c, it, source_loc, scope);5473 if_node.@"else".?.body = try parseCPrimaryExpr(c, m, scope);
5501 return &if_node.base;5474 return &if_node.base;
5502 },5475 },
5503 .Comma => {5476 .Comma => {
...@@ -5520,10 +5493,10 @@ fn parseCExpr(c: *Context, it: *CTokIterator, source_loc: ZigClangSourceLocation...@@ -5520,10 +5493,10 @@ fn parseCExpr(c: *Context, it: *CTokIterator, source_loc: ZigClangSourceLocation
5520 };5493 };
5521 try block_scope.statements.append(&op_node.base);5494 try block_scope.statements.append(&op_node.base);
55225495
5523 last = try parseCPrefixOpExpr(c, it, source_loc, scope);5496 last = try parseCPrefixOpExpr(c, m, scope);
5524 _ = try appendToken(c, .Semicolon, ";");5497 _ = try appendToken(c, .Semicolon, ";");
5525 if (it.next().? != .Comma) {5498 if (m.next().? != .Comma) {
5526 it.i -= 1;5499 m.i -= 1;
5527 break;5500 break;
5528 }5501 }
5529 }5502 }
...@@ -5534,16 +5507,16 @@ fn parseCExpr(c: *Context, it: *CTokIterator, source_loc: ZigClangSourceLocation...@@ -5534,16 +5507,16 @@ fn parseCExpr(c: *Context, it: *CTokIterator, source_loc: ZigClangSourceLocation
5534 return &block_node.base;5507 return &block_node.base;
5535 },5508 },
5536 else => {5509 else => {
5537 it.i -= 1;5510 m.i -= 1;
5538 return node;5511 return node;
5539 },5512 },
5540 }5513 }
5541}5514}
55425515
5543fn parseCNumLit(c: *Context, it: *CTokIterator, source_loc: ZigClangSourceLocation) ParseError!*ast.Node {5516fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!*ast.Node {
5544 var lit_bytes = it.slice(it.i);5517 var lit_bytes = m.slice();
55455518
5546 switch (it.list[it.i].id) {5519 switch (m.list[m.i].id) {
5547 .IntegerLiteral => |suffix| {5520 .IntegerLiteral => |suffix| {
5548 if (lit_bytes.len > 2 and lit_bytes[0] == '0') {5521 if (lit_bytes.len > 2 and lit_bytes[0] == '0') {
5549 switch (lit_bytes[1]) {5522 switch (lit_bytes[1]) {
...@@ -5604,8 +5577,8 @@ fn parseCNumLit(c: *Context, it: *CTokIterator, source_loc: ZigClangSourceLocati...@@ -5604,8 +5577,8 @@ fn parseCNumLit(c: *Context, it: *CTokIterator, source_loc: ZigClangSourceLocati
5604 }5577 }
5605}5578}
56065579
5607fn zigifyEscapeSequences(ctx: *Context, source_bytes: []const u8, name: []const u8, source_loc: ZigClangSourceLocation) ![]const u8 {5580fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 {
5608 var source = source_bytes;5581 var source = m.slice();
5609 for (source) |c, i| {5582 for (source) |c, i| {
5610 if (c == '\"' or c == '\'') {5583 if (c == '\"' or c == '\'') {
5611 source = source[i..];5584 source = source[i..];
...@@ -5677,11 +5650,11 @@ fn zigifyEscapeSequences(ctx: *Context, source_bytes: []const u8, name: []const...@@ -5677,11 +5650,11 @@ fn zigifyEscapeSequences(ctx: *Context, source_bytes: []const u8, name: []const
5677 bytes[i] = '?';5650 bytes[i] = '?';
5678 },5651 },
5679 'u', 'U' => {5652 'u', 'U' => {
5680 try failDecl(ctx, source_loc, name, "macro tokenizing failed: TODO unicode escape sequences", .{});5653 try m.fail(ctx, "macro tokenizing failed: TODO unicode escape sequences", .{});
5681 return error.ParseError;5654 return error.ParseError;
5682 },5655 },
5683 else => {5656 else => {
5684 try failDecl(ctx, source_loc, name, "macro tokenizing failed: unknown escape sequence", .{});5657 try m.fail(ctx, "macro tokenizing failed: unknown escape sequence", .{});
5685 return error.ParseError;5658 return error.ParseError;
5686 },5659 },
5687 }5660 }
...@@ -5700,21 +5673,21 @@ fn zigifyEscapeSequences(ctx: *Context, source_bytes: []const u8, name: []const...@@ -5700,21 +5673,21 @@ fn zigifyEscapeSequences(ctx: *Context, source_bytes: []const u8, name: []const
5700 switch (c) {5673 switch (c) {
5701 '0'...'9' => {5674 '0'...'9' => {
5702 num = std.math.mul(u8, num, 16) catch {5675 num = std.math.mul(u8, num, 16) catch {
5703 try failDecl(ctx, source_loc, name, "macro tokenizing failed: hex literal overflowed", .{});5676 try m.fail(ctx, "macro tokenizing failed: hex literal overflowed", .{});
5704 return error.ParseError;5677 return error.ParseError;
5705 };5678 };
5706 num += c - '0';5679 num += c - '0';
5707 },5680 },
5708 'a'...'f' => {5681 'a'...'f' => {
5709 num = std.math.mul(u8, num, 16) catch {5682 num = std.math.mul(u8, num, 16) catch {
5710 try failDecl(ctx, source_loc, name, "macro tokenizing failed: hex literal overflowed", .{});5683 try m.fail(ctx, "macro tokenizing failed: hex literal overflowed", .{});
5711 return error.ParseError;5684 return error.ParseError;
5712 };5685 };
5713 num += c - 'a' + 10;5686 num += c - 'a' + 10;
5714 },5687 },
5715 'A'...'F' => {5688 'A'...'F' => {
5716 num = std.math.mul(u8, num, 16) catch {5689 num = std.math.mul(u8, num, 16) catch {
5717 try failDecl(ctx, source_loc, name, "macro tokenizing failed: hex literal overflowed", .{});5690 try m.fail(ctx, "macro tokenizing failed: hex literal overflowed", .{});
5718 return error.ParseError;5691 return error.ParseError;
5719 };5692 };
5720 num += c - 'A' + 10;5693 num += c - 'A' + 10;
...@@ -5741,7 +5714,7 @@ fn zigifyEscapeSequences(ctx: *Context, source_bytes: []const u8, name: []const...@@ -5741,7 +5714,7 @@ fn zigifyEscapeSequences(ctx: *Context, source_bytes: []const u8, name: []const
5741 if (accept_digit) {5714 if (accept_digit) {
5742 count += 1;5715 count += 1;
5743 num = std.math.mul(u8, num, 8) catch {5716 num = std.math.mul(u8, num, 8) catch {
5744 try failDecl(ctx, source_loc, name, "macro tokenizing failed: octal literal overflowed", .{});5717 try m.fail(ctx, "macro tokenizing failed: octal literal overflowed", .{});
5745 return error.ParseError;5718 return error.ParseError;
5746 };5719 };
5747 num += c - '0';5720 num += c - '0';
...@@ -5764,13 +5737,13 @@ fn zigifyEscapeSequences(ctx: *Context, source_bytes: []const u8, name: []const...@@ -5764,13 +5737,13 @@ fn zigifyEscapeSequences(ctx: *Context, source_bytes: []const u8, name: []const
5764 return bytes[0..i];5737 return bytes[0..i];
5765}5738}
57665739
5767fn parseCPrimaryExpr(c: *Context, it: *CTokIterator, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node {5740fn parseCPrimaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
5768 const tok = it.next().?;5741 const tok = m.next().?;
5769 const slice = it.slice(it.i);5742 const slice = m.slice();
5770 switch (tok) {5743 switch (tok) {
5771 .CharLiteral => {5744 .CharLiteral => {
5772 if (slice[0] != '\'' or slice[1] == '\\' or slice.len == 3) {5745 if (slice[0] != '\'' or slice[1] == '\\' or slice.len == 3) {
5773 const token = try appendToken(c, .CharLiteral, try zigifyEscapeSequences(c, slice, it.slice(0), source_loc));5746 const token = try appendToken(c, .CharLiteral, try zigifyEscapeSequences(c, m));
5774 const node = try c.arena.create(ast.Node.OneToken);5747 const node = try c.arena.create(ast.Node.OneToken);
5775 node.* = .{5748 node.* = .{
5776 .base = .{ .tag = .CharLiteral },5749 .base = .{ .tag = .CharLiteral },
...@@ -5788,7 +5761,7 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokIterator, source_loc: ZigClangSourceL...@@ -5788,7 +5761,7 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokIterator, source_loc: ZigClangSourceL
5788 }5761 }
5789 },5762 },
5790 .StringLiteral => {5763 .StringLiteral => {
5791 const token = try appendToken(c, .StringLiteral, try zigifyEscapeSequences(c, slice, it.slice(0), source_loc));5764 const token = try appendToken(c, .StringLiteral, try zigifyEscapeSequences(c, m));
5792 const node = try c.arena.create(ast.Node.OneToken);5765 const node = try c.arena.create(ast.Node.OneToken);
5793 node.* = .{5766 node.* = .{
5794 .base = .{ .tag = .StringLiteral },5767 .base = .{ .tag = .StringLiteral },
...@@ -5797,7 +5770,7 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokIterator, source_loc: ZigClangSourceL...@@ -5797,7 +5770,7 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokIterator, source_loc: ZigClangSourceL
5797 return &node.base;5770 return &node.base;
5798 },5771 },
5799 .IntegerLiteral, .FloatLiteral => {5772 .IntegerLiteral, .FloatLiteral => {
5800 return parseCNumLit(c, it, source_loc);5773 return parseCNumLit(c, m);
5801 },5774 },
5802 // eventually this will be replaced by std.c.parse which will handle these correctly5775 // eventually this will be replaced by std.c.parse which will handle these correctly
5803 .Keyword_void => return transCreateNodeIdentifierUnchecked(c, "c_void"),5776 .Keyword_void => return transCreateNodeIdentifierUnchecked(c, "c_void"),
...@@ -5808,61 +5781,55 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokIterator, source_loc: ZigClangSourceL...@@ -5808,61 +5781,55 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokIterator, source_loc: ZigClangSourceL
5808 .Keyword_float => return transCreateNodeIdentifierUnchecked(c, "f32"),5781 .Keyword_float => return transCreateNodeIdentifierUnchecked(c, "f32"),
5809 .Keyword_short => return transCreateNodeIdentifierUnchecked(c, "c_short"),5782 .Keyword_short => return transCreateNodeIdentifierUnchecked(c, "c_short"),
5810 .Keyword_char => return transCreateNodeIdentifierUnchecked(c, "u8"),5783 .Keyword_char => return transCreateNodeIdentifierUnchecked(c, "u8"),
5811 .Keyword_unsigned => if (it.next()) |t| switch (t) {5784 .Keyword_unsigned => if (m.next()) |t| switch (t) {
5812 .Keyword_char => return transCreateNodeIdentifierUnchecked(c, "u8"),5785 .Keyword_char => return transCreateNodeIdentifierUnchecked(c, "u8"),
5813 .Keyword_short => return transCreateNodeIdentifierUnchecked(c, "c_ushort"),5786 .Keyword_short => return transCreateNodeIdentifierUnchecked(c, "c_ushort"),
5814 .Keyword_int => return transCreateNodeIdentifierUnchecked(c, "c_uint"),5787 .Keyword_int => return transCreateNodeIdentifierUnchecked(c, "c_uint"),
5815 .Keyword_long => if (it.peek() != null and it.peek().? == .Keyword_long) {5788 .Keyword_long => if (m.peek() != null and m.peek().? == .Keyword_long) {
5816 _ = it.next();5789 _ = m.next();
5817 return transCreateNodeIdentifierUnchecked(c, "c_ulonglong");5790 return transCreateNodeIdentifierUnchecked(c, "c_ulonglong");
5818 } else return transCreateNodeIdentifierUnchecked(c, "c_ulong"),5791 } else return transCreateNodeIdentifierUnchecked(c, "c_ulong"),
5819 else => {5792 else => {
5820 it.i -= 1;5793 m.i -= 1;
5821 return transCreateNodeIdentifierUnchecked(c, "c_uint");5794 return transCreateNodeIdentifierUnchecked(c, "c_uint");
5822 },5795 },
5823 } else {5796 } else {
5824 return transCreateNodeIdentifierUnchecked(c, "c_uint");5797 return transCreateNodeIdentifierUnchecked(c, "c_uint");
5825 },5798 },
5826 .Keyword_signed => if (it.next()) |t| switch (t) {5799 .Keyword_signed => if (m.next()) |t| switch (t) {
5827 .Keyword_char => return transCreateNodeIdentifierUnchecked(c, "i8"),5800 .Keyword_char => return transCreateNodeIdentifierUnchecked(c, "i8"),
5828 .Keyword_short => return transCreateNodeIdentifierUnchecked(c, "c_short"),5801 .Keyword_short => return transCreateNodeIdentifierUnchecked(c, "c_short"),
5829 .Keyword_int => return transCreateNodeIdentifierUnchecked(c, "c_int"),5802 .Keyword_int => return transCreateNodeIdentifierUnchecked(c, "c_int"),
5830 .Keyword_long => if (it.peek() != null and it.peek().? == .Keyword_long) {5803 .Keyword_long => if (m.peek() != null and m.peek().? == .Keyword_long) {
5831 _ = it.next();5804 _ = m.next();
5832 return transCreateNodeIdentifierUnchecked(c, "c_longlong");5805 return transCreateNodeIdentifierUnchecked(c, "c_longlong");
5833 } else return transCreateNodeIdentifierUnchecked(c, "c_long"),5806 } else return transCreateNodeIdentifierUnchecked(c, "c_long"),
5834 else => {5807 else => {
5835 it.i -= 1;5808 m.i -= 1;
5836 return transCreateNodeIdentifierUnchecked(c, "c_int");5809 return transCreateNodeIdentifierUnchecked(c, "c_int");
5837 },5810 },
5838 } else {5811 } else {
5839 return transCreateNodeIdentifierUnchecked(c, "c_int");5812 return transCreateNodeIdentifierUnchecked(c, "c_int");
5840 },5813 },
5841 .Identifier => {5814 .Identifier => {
5842 const mangled_name = scope.getAlias(it.slice(it.i));5815 const mangled_name = scope.getAlias(slice);
5843 return transCreateNodeIdentifier(c, mangled_name);5816 return transCreateNodeIdentifier(c, mangled_name);
5844 },5817 },
5845 .LParen => {5818 .LParen => {
5846 const inner_node = try parseCExpr(c, it, source_loc, scope);5819 const inner_node = try parseCExpr(c, m, scope);
58475820
5848 const next_id = it.next().?;5821 const next_id = m.next().?;
5849 if (next_id != .RParen) {5822 if (next_id != .RParen) {
5850 try failDecl(5823 try m.fail(c, "unable to translate C expr: expected ')'' instead got: {}", .{@tagName(next_id)});
5851 c,
5852 source_loc,
5853 it.slice(0),
5854 "unable to translate C expr: expected ')'' instead got: {}",
5855 .{@tagName(next_id)},
5856 );
5857 return error.ParseError;5824 return error.ParseError;
5858 }5825 }
5859 var saw_l_paren = false;5826 var saw_l_paren = false;
5860 var saw_integer_literal = false;5827 var saw_integer_literal = false;
5861 switch (it.peek().?) {5828 switch (m.peek().?) {
5862 // (type)(to_cast)5829 // (type)(to_cast)
5863 .LParen => {5830 .LParen => {
5864 saw_l_paren = true;5831 saw_l_paren = true;
5865 _ = it.next();5832 _ = m.next();
5866 },5833 },
5867 // (type)identifier5834 // (type)identifier
5868 .Identifier => {},5835 .Identifier => {},
...@@ -5876,16 +5843,10 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokIterator, source_loc: ZigClangSourceL...@@ -5876,16 +5843,10 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokIterator, source_loc: ZigClangSourceL
5876 // hack to get zig fmt to render a comma in builtin calls5843 // hack to get zig fmt to render a comma in builtin calls
5877 _ = try appendToken(c, .Comma, ",");5844 _ = try appendToken(c, .Comma, ",");
58785845
5879 const node_to_cast = try parseCExpr(c, it, source_loc, scope);5846 const node_to_cast = try parseCExpr(c, m, scope);
58805847
5881 if (saw_l_paren and it.next().? != .RParen) {5848 if (saw_l_paren and m.next().? != .RParen) {
5882 try failDecl(5849 try m.fail(c, "unable to translate C expr: expected ')''", .{});
5883 c,
5884 source_loc,
5885 it.slice(0),
5886 "unable to translate C expr: expected ')''",
5887 .{},
5888 );
5889 return error.ParseError;5850 return error.ParseError;
5890 }5851 }
58915852
...@@ -5913,13 +5874,7 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokIterator, source_loc: ZigClangSourceL...@@ -5913,13 +5874,7 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokIterator, source_loc: ZigClangSourceL
5913 return &group_node.base;5874 return &group_node.base;
5914 },5875 },
5915 else => {5876 else => {
5916 try failDecl(5877 try m.fail(c, "unable to translate C expr: unexpected token .{}", .{@tagName(tok)});
5917 c,
5918 source_loc,
5919 it.slice(0),
5920 "unable to translate C expr: unexpected token .{}",
5921 .{@tagName(tok)},
5922 );
5923 return error.ParseError;5878 return error.ParseError;
5924 },5879 },
5925 }5880 }
...@@ -6026,52 +5981,40 @@ fn macroIntToBool(c: *Context, node: *ast.Node) !*ast.Node {...@@ -6026,52 +5981,40 @@ fn macroIntToBool(c: *Context, node: *ast.Node) !*ast.Node {
6026 return &group_node.base;5981 return &group_node.base;
6027}5982}
60285983
6029fn parseCSuffixOpExpr(c: *Context, it: *CTokIterator, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node {5984fn parseCSuffixOpExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
6030 var node = try parseCPrimaryExpr(c, it, source_loc, scope);5985 var node = try parseCPrimaryExpr(c, m, scope);
6031 while (true) {5986 while (true) {
6032 var op_token: ast.TokenIndex = undefined;5987 var op_token: ast.TokenIndex = undefined;
6033 var op_id: ast.Node.Tag = undefined;5988 var op_id: ast.Node.Tag = undefined;
6034 var bool_op = false;5989 var bool_op = false;
6035 switch (it.next().?) {5990 switch (m.next().?) {
6036 .Period => {5991 .Period => {
6037 if (it.next().? != .Identifier) {5992 if (m.next().? != .Identifier) {
6038 try failDecl(5993 try m.fail(c, "unable to translate C expr: expected identifier", .{});
6039 c,
6040 source_loc,
6041 it.slice(0),
6042 "unable to translate C expr: expected identifier",
6043 .{},
6044 );
6045 return error.ParseError;5994 return error.ParseError;
6046 }5995 }
60475996
6048 node = try transCreateNodeFieldAccess(c, node, it.slice(it.i));5997 node = try transCreateNodeFieldAccess(c, node, m.slice());
6049 continue;5998 continue;
6050 },5999 },
6051 .Arrow => {6000 .Arrow => {
6052 if (it.next().? != .Identifier) {6001 if (m.next().? != .Identifier) {
6053 try failDecl(6002 try m.fail(c, "unable to translate C expr: expected identifier", .{});
6054 c,
6055 source_loc,
6056 it.slice(0),
6057 "unable to translate C expr: expected identifier",
6058 .{},
6059 );
6060 return error.ParseError;6003 return error.ParseError;
6061 }6004 }
6062 const deref = try transCreateNodePtrDeref(c, node);6005 const deref = try transCreateNodePtrDeref(c, node);
6063 node = try transCreateNodeFieldAccess(c, deref, it.slice(it.i));6006 node = try transCreateNodeFieldAccess(c, deref, m.slice());
6064 continue;6007 continue;
6065 },6008 },
6066 .Asterisk => {6009 .Asterisk => {
6067 if (it.peek().? == .RParen) {6010 if (m.peek().? == .RParen) {
6068 // type *)6011 // type *)
60696012
6070 // hack to get zig fmt to render a comma in builtin calls6013 // hack to get zig fmt to render a comma in builtin calls
6071 _ = try appendToken(c, .Comma, ",");6014 _ = try appendToken(c, .Comma, ",");
60726015
6073 // last token of `node`6016 // last token of `node`
6074 const prev_id = it.list[it.i - 1].id;6017 const prev_id = m.list[m.i - 1].id;
60756018
6076 if (prev_id == .Keyword_void) {6019 if (prev_id == .Keyword_void) {
6077 const ptr = try transCreateNodePtrType(c, false, false, .Asterisk);6020 const ptr = try transCreateNodePtrType(c, false, false, .Asterisk);
...@@ -6142,17 +6085,11 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokIterator, source_loc: ZigClangSource...@@ -6142,17 +6085,11 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokIterator, source_loc: ZigClangSource
6142 },6085 },
6143 .LBracket => {6086 .LBracket => {
6144 const arr_node = try transCreateNodeArrayAccess(c, node);6087 const arr_node = try transCreateNodeArrayAccess(c, node);
6145 arr_node.index_expr = try parseCPrefixOpExpr(c, it, source_loc, scope);6088 arr_node.index_expr = try parseCPrefixOpExpr(c, m, scope);
6146 arr_node.rtoken = try appendToken(c, .RBracket, "]");6089 arr_node.rtoken = try appendToken(c, .RBracket, "]");
6147 node = &arr_node.base;6090 node = &arr_node.base;
6148 if (it.next().? != .RBracket) {6091 if (m.next().? != .RBracket) {
6149 try failDecl(6092 try m.fail(c, "unable to translate C expr: expected ']'", .{});
6150 c,
6151 source_loc,
6152 it.slice(0),
6153 "unable to translate C expr: expected ']'",
6154 .{},
6155 );
6156 return error.ParseError;6093 return error.ParseError;
6157 }6094 }
6158 continue;6095 continue;
...@@ -6162,19 +6099,13 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokIterator, source_loc: ZigClangSource...@@ -6162,19 +6099,13 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokIterator, source_loc: ZigClangSource
6162 var call_params = std.ArrayList(*ast.Node).init(c.gpa);6099 var call_params = std.ArrayList(*ast.Node).init(c.gpa);
6163 defer call_params.deinit();6100 defer call_params.deinit();
6164 while (true) {6101 while (true) {
6165 const arg = try parseCPrefixOpExpr(c, it, source_loc, scope);6102 const arg = try parseCPrefixOpExpr(c, m, scope);
6166 try call_params.append(arg);6103 try call_params.append(arg);
6167 switch (it.next().?) {6104 switch (m.next().?) {
6168 .Comma => _ = try appendToken(c, .Comma, ","),6105 .Comma => _ = try appendToken(c, .Comma, ","),
6169 .RParen => break,6106 .RParen => break,
6170 else => {6107 else => {
6171 try failDecl(6108 try m.fail(c, "unable to translate C expr: expected ',' or ')'", .{});
6172 c,
6173 source_loc,
6174 it.slice(0),
6175 "unable to translate C expr: expected ',' or ')'",
6176 .{},
6177 );
6178 return error.ParseError;6109 return error.ParseError;
6179 },6110 },
6180 }6111 }
...@@ -6201,19 +6132,13 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokIterator, source_loc: ZigClangSource...@@ -6201,19 +6132,13 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokIterator, source_loc: ZigClangSource
6201 defer init_vals.deinit();6132 defer init_vals.deinit();
62026133
6203 while (true) {6134 while (true) {
6204 const val = try parseCPrefixOpExpr(c, it, source_loc, scope);6135 const val = try parseCPrefixOpExpr(c, m, scope);
6205 try init_vals.append(val);6136 try init_vals.append(val);
6206 switch (it.next().?) {6137 switch (m.next().?) {
6207 .Comma => _ = try appendToken(c, .Comma, ","),6138 .Comma => _ = try appendToken(c, .Comma, ","),
6208 .RBrace => break,6139 .RBrace => break,
6209 else => {6140 else => {
6210 try failDecl(6141 try m.fail(c, "unable to translate C expr: expected ',' or '}}'", .{});
6211 c,
6212 source_loc,
6213 it.slice(0),
6214 "unable to translate C expr: expected ',' or '}}'",
6215 .{},
6216 );
6217 return error.ParseError;6142 return error.ParseError;
6218 },6143 },
6219 }6144 }
...@@ -6262,22 +6187,22 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokIterator, source_loc: ZigClangSource...@@ -6262,22 +6187,22 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokIterator, source_loc: ZigClangSource
6262 op_id = .ArrayCat;6187 op_id = .ArrayCat;
6263 op_token = try appendToken(c, .PlusPlus, "++");6188 op_token = try appendToken(c, .PlusPlus, "++");
62646189
6265 it.i -= 1;6190 m.i -= 1;
6266 },6191 },
6267 .Identifier => {6192 .Identifier => {
6268 op_id = .ArrayCat;6193 op_id = .ArrayCat;
6269 op_token = try appendToken(c, .PlusPlus, "++");6194 op_token = try appendToken(c, .PlusPlus, "++");
62706195
6271 it.i -= 1;6196 m.i -= 1;
6272 },6197 },
6273 else => {6198 else => {
6274 it.i -= 1;6199 m.i -= 1;
6275 return node;6200 return node;
6276 },6201 },
6277 }6202 }
6278 const cast_fn = if (bool_op) macroIntToBool else macroBoolToInt;6203 const cast_fn = if (bool_op) macroIntToBool else macroBoolToInt;
6279 const lhs_node = try cast_fn(c, node);6204 const lhs_node = try cast_fn(c, node);
6280 const rhs_node = try parseCPrefixOpExpr(c, it, source_loc, scope);6205 const rhs_node = try parseCPrefixOpExpr(c, m, scope);
6281 const op_node = try c.arena.create(ast.Node.SimpleInfixOp);6206 const op_node = try c.arena.create(ast.Node.SimpleInfixOp);
6282 op_node.* = .{6207 op_node.* = .{
6283 .base = .{ .tag = op_id },6208 .base = .{ .tag = op_id },
...@@ -6289,36 +6214,36 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokIterator, source_loc: ZigClangSource...@@ -6289,36 +6214,36 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokIterator, source_loc: ZigClangSource
6289 }6214 }
6290}6215}
62916216
6292fn parseCPrefixOpExpr(c: *Context, it: *CTokIterator, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node {6217fn parseCPrefixOpExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
6293 switch (it.next().?) {6218 switch (m.next().?) {
6294 .Bang => {6219 .Bang => {
6295 const node = try transCreateNodeSimplePrefixOp(c, .BoolNot, .Bang, "!");6220 const node = try transCreateNodeSimplePrefixOp(c, .BoolNot, .Bang, "!");
6296 node.rhs = try parseCPrefixOpExpr(c, it, source_loc, scope);6221 node.rhs = try parseCPrefixOpExpr(c, m, scope);
6297 return &node.base;6222 return &node.base;
6298 },6223 },
6299 .Minus => {6224 .Minus => {
6300 const node = try transCreateNodeSimplePrefixOp(c, .Negation, .Minus, "-");6225 const node = try transCreateNodeSimplePrefixOp(c, .Negation, .Minus, "-");
6301 node.rhs = try parseCPrefixOpExpr(c, it, source_loc, scope);6226 node.rhs = try parseCPrefixOpExpr(c, m, scope);
6302 return &node.base;6227 return &node.base;
6303 },6228 },
6304 .Plus => return try parseCPrefixOpExpr(c, it, source_loc, scope),6229 .Plus => return try parseCPrefixOpExpr(c, m, scope),
6305 .Tilde => {6230 .Tilde => {
6306 const node = try transCreateNodeSimplePrefixOp(c, .BitNot, .Tilde, "~");6231 const node = try transCreateNodeSimplePrefixOp(c, .BitNot, .Tilde, "~");
6307 node.rhs = try parseCPrefixOpExpr(c, it, source_loc, scope);6232 node.rhs = try parseCPrefixOpExpr(c, m, scope);
6308 return &node.base;6233 return &node.base;
6309 },6234 },
6310 .Asterisk => {6235 .Asterisk => {
6311 const node = try parseCPrefixOpExpr(c, it, source_loc, scope);6236 const node = try parseCPrefixOpExpr(c, m, scope);
6312 return try transCreateNodePtrDeref(c, node);6237 return try transCreateNodePtrDeref(c, node);
6313 },6238 },
6314 .Ampersand => {6239 .Ampersand => {
6315 const node = try transCreateNodeSimplePrefixOp(c, .AddressOf, .Ampersand, "&");6240 const node = try transCreateNodeSimplePrefixOp(c, .AddressOf, .Ampersand, "&");
6316 node.rhs = try parseCPrefixOpExpr(c, it, source_loc, scope);6241 node.rhs = try parseCPrefixOpExpr(c, m, scope);
6317 return &node.base;6242 return &node.base;
6318 },6243 },
6319 else => {6244 else => {
6320 it.i -= 1;6245 m.i -= 1;
6321 return try parseCSuffixOpExpr(c, it, source_loc, scope);6246 return try parseCSuffixOpExpr(c, m, scope);
6322 },6247 },
6323 }6248 }
6324}6249}
test/translate_c.zig+4
...@@ -1679,8 +1679,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1679,8 +1679,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
16791679
1680 cases.add("shadowing primitive types",1680 cases.add("shadowing primitive types",
1681 \\unsigned anyerror = 2;1681 \\unsigned anyerror = 2;
1682 \\#define noreturn _Noreturn
1682 , &[_][]const u8{1683 , &[_][]const u8{
1683 \\pub export var anyerror_1: c_uint = @bitCast(c_uint, @as(c_int, 2));1684 \\pub export var anyerror_1: c_uint = @bitCast(c_uint, @as(c_int, 2));
1685 ,
1686
1687 \\pub const noreturn_2 = @compileError("unable to translate C expr: unexpected token .Keyword_noreturn");
1684 });1688 });
16851689
1686 cases.add("floats",1690 cases.add("floats",