authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-28 23:38:07+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-28 23:38:07+02:00
log1e52b7d690071104544aaae5bef2760aee84c38e
tree5f6648c3b2be421da9857aaa5f13072617a5567b
parentaea46dcd7e8521fc04bc1980a596c748961804ab
signature Commit is signed but in an unrecognized format.

translate-c-2 improve macro errors


2 files changed, 246 insertions(+), 162 deletions(-)

src-self-hosted/c_tokenizer.zig+57-21
...@@ -1,5 +1,8 @@...@@ -1,5 +1,8 @@
1const std = @import("std");1const std = @import("std");
2const expect = std.testing.expect;2const expect = std.testing.expect;
3const ZigClangSourceLocation = @import("clang.zig").ZigClangSourceLocation;
4const Context = @import("translate_c.zig").Context;
5const failDecl = @import("translate_c.zig").failDecl;
36
4pub const TokenList = std.SegmentedList(CToken, 32);7pub const TokenList = std.SegmentedList(CToken, 32);
58
...@@ -46,13 +49,13 @@ pub const CToken = struct {...@@ -46,13 +49,13 @@ pub const CToken = struct {
46 };49 };
47};50};
4851
49pub fn tokenizeCMacro(tl: *TokenList, chars: [*:0]const u8) !void {52pub fn tokenizeCMacro(ctx: *Context, loc: ZigClangSourceLocation, name: []const u8, tl: *TokenList, chars: [*:0]const u8) !void {
50 var index: usize = 0;53 var index: usize = 0;
51 var first = true;54 var first = true;
52 while (true) {55 while (true) {
53 const tok = try next(chars, &index);56 const tok = try next(ctx, loc, name, chars, &index);
54 if (tok.id == .StrLit or tok.id == .CharLit)57 if (tok.id == .StrLit or tok.id == .CharLit)
55 try tl.push(try zigifyEscapeSequences(tl.allocator, tok))58 try tl.push(try zigifyEscapeSequences(ctx, loc, name, tl.allocator, tok))
56 else59 else
57 try tl.push(tok);60 try tl.push(tok);
58 if (tok.id == .Eof)61 if (tok.id == .Eof)
...@@ -70,7 +73,7 @@ pub fn tokenizeCMacro(tl: *TokenList, chars: [*:0]const u8) !void {...@@ -70,7 +73,7 @@ pub fn tokenizeCMacro(tl: *TokenList, chars: [*:0]const u8) !void {
70 }73 }
71}74}
7275
73fn zigifyEscapeSequences(allocator: *std.mem.Allocator, tok: CToken) !CToken {76fn zigifyEscapeSequences(ctx: *Context, loc: ZigClangSourceLocation, name: []const u8, allocator: *std.mem.Allocator, tok: CToken) !CToken {
74 for (tok.bytes) |c| {77 for (tok.bytes) |c| {
75 if (c == '\\') {78 if (c == '\\') {
76 break;79 break;
...@@ -136,11 +139,11 @@ fn zigifyEscapeSequences(allocator: *std.mem.Allocator, tok: CToken) !CToken {...@@ -136,11 +139,11 @@ fn zigifyEscapeSequences(allocator: *std.mem.Allocator, tok: CToken) !CToken {
136 bytes[i] = '?';139 bytes[i] = '?';
137 },140 },
138 'u', 'U' => {141 'u', 'U' => {
139 // TODO unicode escape sequences142 try failDecl(ctx, loc, name, "macro tokenizing failed: TODO unicode escape sequences", .{});
140 return error.TokenizingFailed;143 return error.TokenizingFailed;
141 },144 },
142 else => {145 else => {
143 // unknown escape sequence146 try failDecl(ctx, loc, name, "macro tokenizing failed: unknown escape sequence", .{});
144 return error.TokenizingFailed;147 return error.TokenizingFailed;
145 },148 },
146 }149 }
...@@ -158,19 +161,28 @@ fn zigifyEscapeSequences(allocator: *std.mem.Allocator, tok: CToken) !CToken {...@@ -158,19 +161,28 @@ fn zigifyEscapeSequences(allocator: *std.mem.Allocator, tok: CToken) !CToken {
158 .Hex => {161 .Hex => {
159 switch (c) {162 switch (c) {
160 '0'...'9' => {163 '0'...'9' => {
161 num = std.math.mul(u8, num, 16) catch return error.TokenizingFailed;164 num = std.math.mul(u8, num, 16) catch {
165 try failDecl(ctx, loc, name, "macro tokenizing failed: hex literal overflowed", .{});
166 return error.TokenizingFailed;
167 };
162 num += c - '0';168 num += c - '0';
163 },169 },
164 'a'...'f' => {170 'a'...'f' => {
165 num = std.math.mul(u8, num, 16) catch return error.TokenizingFailed;171 num = std.math.mul(u8, num, 16) catch {
172 try failDecl(ctx, loc, name, "macro tokenizing failed: hex literal overflowed", .{});
173 return error.TokenizingFailed;
174 };
166 num += c - 'a' + 10;175 num += c - 'a' + 10;
167 },176 },
168 'A'...'F' => {177 'A'...'F' => {
169 num = std.math.mul(u8, num, 16) catch return error.TokenizingFailed;178 num = std.math.mul(u8, num, 16) catch {
179 try failDecl(ctx, loc, name, "macro tokenizing failed: hex literal overflowed", .{});
180 return error.TokenizingFailed;
181 };
170 num += c - 'A' + 10;182 num += c - 'A' + 10;
171 },183 },
172 else => {184 else => {
173 i += std.fmt.formatIntBuf(bytes[i..], num, 16, false, std.fmt.FormatOptions{.fill = '0', .width = 2});185 i += std.fmt.formatIntBuf(bytes[i..], num, 16, false, std.fmt.FormatOptions{ .fill = '0', .width = 2 });
174 num = 0;186 num = 0;
175 if (c == '\\')187 if (c == '\\')
176 state = .Escape188 state = .Escape
...@@ -185,14 +197,17 @@ fn zigifyEscapeSequences(allocator: *std.mem.Allocator, tok: CToken) !CToken {...@@ -185,14 +197,17 @@ fn zigifyEscapeSequences(allocator: *std.mem.Allocator, tok: CToken) !CToken {
185 switch (c) {197 switch (c) {
186 '0'...'7' => {198 '0'...'7' => {
187 count += 1;199 count += 1;
188 num = std.math.mul(u8, num, 8) catch return error.TokenizingFailed;200 num = std.math.mul(u8, num, 8) catch {
201 try failDecl(ctx, loc, name, "macro tokenizing failed: octal literal overflowed", .{});
202 return error.TokenizingFailed;
203 };
189 num += c - '0';204 num += c - '0';
190 if (count < 3)205 if (count < 3)
191 continue;206 continue;
192 },207 },
193 else => {},208 else => {},
194 }209 }
195 i += std.fmt.formatIntBuf(bytes[i..], num, 16, false, std.fmt.FormatOptions{.fill = '0', .width = 2});210 i += std.fmt.formatIntBuf(bytes[i..], num, 16, false, std.fmt.FormatOptions{ .fill = '0', .width = 2 });
196 state = .Start;211 state = .Start;
197 count = 0;212 count = 0;
198 num = 0;213 num = 0;
...@@ -200,14 +215,14 @@ fn zigifyEscapeSequences(allocator: *std.mem.Allocator, tok: CToken) !CToken {...@@ -200,14 +215,14 @@ fn zigifyEscapeSequences(allocator: *std.mem.Allocator, tok: CToken) !CToken {
200 }215 }
201 }216 }
202 if (state == .Hex or state == .Octal)217 if (state == .Hex or state == .Octal)
203 i += std.fmt.formatIntBuf(bytes[i..], num, 16, false, std.fmt.FormatOptions{.fill = '0', .width = 2});218 i += std.fmt.formatIntBuf(bytes[i..], num, 16, false, std.fmt.FormatOptions{ .fill = '0', .width = 2 });
204 return CToken{219 return CToken{
205 .id = tok.id,220 .id = tok.id,
206 .bytes = bytes[0..i],221 .bytes = bytes[0..i],
207 };222 };
208}223}
209224
210fn next(chars: [*:0]const u8, i: *usize) !CToken {225fn next(ctx: *Context, loc: ZigClangSourceLocation, name: []const u8, chars: [*:0]const u8, i: *usize) !CToken {
211 var state: enum {226 var state: enum {
212 Start,227 Start,
213 GotLt,228 GotLt,
...@@ -278,7 +293,10 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {...@@ -278,7 +293,10 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
278 .String,293 .String,
279 .ExpSign,294 .ExpSign,
280 .FloatExpFirst,295 .FloatExpFirst,
281 => return error.TokenizingFailed,296 => {
297 try failDecl(ctx, loc, name, "macro tokenizing failed: unexpected EOF", .{});
298 return error.TokenizingFailed;
299 },
282 }300 }
283 }301 }
284 switch (state) {302 switch (state) {
...@@ -375,7 +393,10 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {...@@ -375,7 +393,10 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
375 result.id = .Colon;393 result.id = .Colon;
376 state = .Done;394 state = .Done;
377 },395 },
378 else => return error.TokenizingFailed,396 else => {
397 try failDecl(ctx, loc, name, "macro tokenizing failed: unexpected character '{c}'", .{c});
398 return error.TokenizingFailed;
399 },
379 }400 }
380 },401 },
381 .Done => return result,402 .Done => return result,
...@@ -433,7 +454,10 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {...@@ -433,7 +454,10 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
433 '0'...'9' => {454 '0'...'9' => {
434 state = .FloatExp;455 state = .FloatExp;
435 },456 },
436 else => return error.TokenizingFailed,457 else => {
458 try failDecl(ctx, loc, name, "macro tokenizing failed: expected a digit or '+' or '-'", .{});
459 return error.TokenizingFailed;
460 },
437 }461 }
438 },462 },
439 .FloatExpFirst => {463 .FloatExpFirst => {
...@@ -441,7 +465,10 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {...@@ -441,7 +465,10 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
441 '0'...'9' => {465 '0'...'9' => {
442 state = .FloatExp;466 state = .FloatExp;
443 },467 },
444 else => return error.TokenizingFailed,468 else => {
469 try failDecl(ctx, loc, name, "macro tokenizing failed: expected a digit", .{});
470 return error.TokenizingFailed;
471 },
445 }472 }
446 },473 },
447 .FloatExp => {474 .FloatExp => {
...@@ -518,7 +545,10 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {...@@ -518,7 +545,10 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
518 .Octal => {545 .Octal => {
519 switch (c) {546 switch (c) {
520 '0'...'7' => {},547 '0'...'7' => {},
521 '8', '9' => return error.TokenizingFailed,548 '8', '9' => {
549 try failDecl(ctx, loc, name, "macro tokenizing failed: invalid digit '{c}' in octal number", .{c});
550 return error.TokenizingFailed;
551 },
522 else => {552 else => {
523 result.bytes = chars[begin_index..i.*];553 result.bytes = chars[begin_index..i.*];
524 return result;554 return result;
...@@ -549,7 +579,10 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {...@@ -549,7 +579,10 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
549 .Bin => {579 .Bin => {
550 switch (c) {580 switch (c) {
551 '0'...'1' => {},581 '0'...'1' => {},
552 '2'...'9' => return error.TokenizingFailed,582 '2'...'9' => {
583 try failDecl(ctx, loc, name, "macro tokenizing failed: invalid digit '{c}' in binary number", .{c});
584 return error.TokenizingFailed;
585 },
553 'u', 'U' => {586 'u', 'U' => {
554 // marks the number literal as unsigned587 // marks the number literal as unsigned
555 state = .NumLitIntSuffixU;588 state = .NumLitIntSuffixU;
...@@ -681,7 +714,10 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {...@@ -681,7 +714,10 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
681 '\n', '\r' => {714 '\n', '\r' => {
682 state = .Start;715 state = .Start;
683 },716 },
684 else => return error.TokenizingFailed,717 else => {
718 try failDecl(ctx, loc, name, "macro tokenizing failed: expected whitespace", .{});
719 return error.TokenizingFailed;
720 },
685 }721 }
686 },722 },
687 }723 }
src-self-hosted/translate_c.zig+189-141
...@@ -182,7 +182,7 @@ const Scope = struct {...@@ -182,7 +182,7 @@ const Scope = struct {
182 }182 }
183};183};
184184
185const Context = struct {185pub const Context = struct {
186 tree: *ast.Tree,186 tree: *ast.Tree,
187 source_buffer: *std.Buffer,187 source_buffer: *std.Buffer,
188 err: Error,188 err: Error,
...@@ -3921,7 +3921,7 @@ fn emitWarning(c: *Context, loc: ZigClangSourceLocation, comptime format: []cons...@@ -3921,7 +3921,7 @@ fn emitWarning(c: *Context, loc: ZigClangSourceLocation, comptime format: []cons
3921 _ = try appendTokenFmt(c, .LineComment, "// {}: warning: " ++ format, args_prefix ++ args);3921 _ = try appendTokenFmt(c, .LineComment, "// {}: warning: " ++ format, args_prefix ++ args);
3922}3922}
39233923
3924fn failDecl(c: *Context, loc: ZigClangSourceLocation, name: []const u8, comptime format: []const u8, args: var) !void {3924pub fn failDecl(c: *Context, loc: ZigClangSourceLocation, name: []const u8, comptime format: []const u8, args: var) !void {
3925 // const name = @compileError(msg);3925 // const name = @compileError(msg);
3926 const const_tok = try appendToken(c, .Keyword_const, "const");3926 const const_tok = try appendToken(c, .Keyword_const, "const");
3927 const name_tok = try appendIdentifier(c, name);3927 const name_tok = try appendIdentifier(c, name);
...@@ -4091,10 +4091,9 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void {...@@ -4091,10 +4091,9 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void {
4091 continue;4091 continue;
4092 }4092 }
4093 const begin_c = ZigClangSourceManager_getCharacterData(c.source_manager, begin_loc);4093 const begin_c = ZigClangSourceManager_getCharacterData(c.source_manager, begin_loc);
4094 ctok.tokenizeCMacro(&tok_list, begin_c) catch |err| switch (err) {4094 ctok.tokenizeCMacro(c, begin_loc, checked_name, &tok_list, begin_c) catch |err| switch (err) {
4095 error.OutOfMemory => |e| return e,4095 error.OutOfMemory => |e| return e,
4096 else => {4096 else => {
4097 try failDecl(c, begin_loc, checked_name, "unable to tokenize macro definition", .{});
4098 continue;4097 continue;
4099 },4098 },
4100 };4099 };
...@@ -4127,9 +4126,7 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void {...@@ -4127,9 +4126,7 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void {
4127 transMacroFnDefine(c, &tok_it, checked_name, begin_loc)4126 transMacroFnDefine(c, &tok_it, checked_name, begin_loc)
4128 else4127 else
4129 transMacroDefine(c, &tok_it, checked_name, begin_loc)) catch |err| switch (err) {4128 transMacroDefine(c, &tok_it, checked_name, begin_loc)) catch |err| switch (err) {
4130 error.UnsupportedTranslation,4129 error.ParseError => continue,
4131 error.ParseError,
4132 => try failDecl(c, begin_loc, checked_name, "unable to translate macro", .{}),
4133 error.OutOfMemory => |e| return e,4130 error.OutOfMemory => |e| return e,
4134 };4131 };
4135 },4132 },
...@@ -4139,20 +4136,19 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void {...@@ -4139,20 +4136,19 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void {
4139}4136}
41404137
4141fn transMacroDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u8, source_loc: ZigClangSourceLocation) ParseError!void {4138fn transMacroDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u8, source_loc: ZigClangSourceLocation) ParseError!void {
4142 const rp = makeRestorePoint(c);
4143 const scope = &c.global_scope.base;4139 const scope = &c.global_scope.base;
41444140
4145 const node = try transCreateNodeVarDecl(c, true, true, name);4141 const node = try transCreateNodeVarDecl(c, true, true, name);
4146 node.eq_token = try appendToken(c, .Equal, "=");4142 node.eq_token = try appendToken(c, .Equal, "=");
41474143
4148 node.init_node = try parseCExpr(rp, it, source_loc, scope);4144 node.init_node = try parseCExpr(c, it, source_loc, scope);
4149 const last = it.next().?;4145 const last = it.next().?;
4150 if (last.id != .Eof)4146 if (last.id != .Eof)
4151 return revertAndWarn(4147 return failDecl(
4152 rp,4148 c,
4153 error.UnsupportedTranslation,
4154 source_loc,4149 source_loc,
4155 "unable to translate C expr, unexpected token: {}",4150 name,
4151 "unable to translate C expr: unexpected token {}",
4156 .{last.id},4152 .{last.id},
4157 );4153 );
41584154
...@@ -4161,7 +4157,6 @@ fn transMacroDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u8,...@@ -4161,7 +4157,6 @@ fn transMacroDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u8,
4161}4157}
41624158
4163fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u8, source_loc: ZigClangSourceLocation) ParseError!void {4159fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u8, source_loc: ZigClangSourceLocation) ParseError!void {
4164 const rp = makeRestorePoint(c);
4165 const block_scope = try Scope.Block.init(c, &c.global_scope.base, null);4160 const block_scope = try Scope.Block.init(c, &c.global_scope.base, null);
4166 const scope = &block_scope.base;4161 const scope = &block_scope.base;
41674162
...@@ -4172,13 +4167,26 @@ fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u...@@ -4172,13 +4167,26 @@ fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u
4172 _ = try appendToken(c, .LParen, "(");4167 _ = try appendToken(c, .LParen, "(");
41734168
4174 if (it.next().?.id != .LParen) {4169 if (it.next().?.id != .LParen) {
4175 return error.ParseError;4170 return failDecl(
4171 c,
4172 source_loc,
4173 name,
4174 "unable to translate C expr: expected '('",
4175 .{},
4176 );
4176 }4177 }
4177 var fn_params = ast.Node.FnProto.ParamList.init(c.a());4178 var fn_params = ast.Node.FnProto.ParamList.init(c.a());
4178 while (true) {4179 while (true) {
4179 const param_tok = it.next().?;4180 const param_tok = it.next().?;
4180 if (param_tok.id != .Identifier)4181 if (param_tok.id != .Identifier) {
4181 return error.ParseError;4182 return failDecl(
4183 c,
4184 source_loc,
4185 name,
4186 "unable to translate C expr: expected identifier",
4187 .{},
4188 );
4189 }
41824190
4183 const checked_name = if (try scope.createAlias(c, param_tok.bytes)) |alias| blk: {4191 const checked_name = if (try scope.createAlias(c, param_tok.bytes)) |alias| blk: {
4184 try block_scope.variables.push(.{ .name = param_tok.bytes, .alias = alias });4192 try block_scope.variables.push(.{ .name = param_tok.bytes, .alias = alias });
...@@ -4213,7 +4221,13 @@ fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u...@@ -4213,7 +4221,13 @@ fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u
4213 }4221 }
42144222
4215 if (it.next().?.id != .RParen) {4223 if (it.next().?.id != .RParen) {
4216 return error.ParseError;4224 return failDecl(
4225 c,
4226 source_loc,
4227 name,
4228 "unable to translate C expr: expected ')'",
4229 .{},
4230 );
4217 }4231 }
42184232
4219 _ = try appendToken(c, .RParen, ")");4233 _ = try appendToken(c, .RParen, ")");
...@@ -4241,14 +4255,14 @@ fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u...@@ -4241,14 +4255,14 @@ fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u
4241 const block = try transCreateNodeBlock(c, null);4255 const block = try transCreateNodeBlock(c, null);
42424256
4243 const return_expr = try transCreateNodeReturnExpr(c);4257 const return_expr = try transCreateNodeReturnExpr(c);
4244 const expr = try parseCExpr(rp, it, source_loc, scope);4258 const expr = try parseCExpr(c, it, source_loc, scope);
4245 const last = it.next().?;4259 const last = it.next().?;
4246 if (last.id != .Eof)4260 if (last.id != .Eof)
4247 return revertAndWarn(4261 return failDecl(
4248 rp,4262 c,
4249 error.UnsupportedTranslation,
4250 source_loc,4263 source_loc,
4251 "unable to translate C expr, unexpected token: {}",4264 name,
4265 "unable to translate C expr: unexpected token {}",
4252 .{last.id},4266 .{last.id},
4253 );4267 );
4254 _ = try appendToken(c, .Semicolon, ";");4268 _ = try appendToken(c, .Semicolon, ";");
...@@ -4261,31 +4275,28 @@ fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u...@@ -4261,31 +4275,28 @@ fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u
4261 _ = try c.global_scope.macro_table.put(name, &fn_proto.base);4275 _ = try c.global_scope.macro_table.put(name, &fn_proto.base);
4262}4276}
42634277
4264const ParseError = Error || error{4278const ParseError = Error || error{ParseError};
4265 ParseError,
4266 UnsupportedTranslation,
4267};
42684279
4269fn parseCExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node {4280fn parseCExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node {
4270 return parseCPrefixOpExpr(rp, it, source_loc, scope);4281 return parseCPrefixOpExpr(c, it, source_loc, scope);
4271}4282}
42724283
4273fn parseCNumLit(rp: RestorePoint, tok: *CToken, source_loc: ZigClangSourceLocation) ParseError!*ast.Node {4284fn parseCNumLit(c: *Context, tok: *CToken, source_loc: ZigClangSourceLocation) ParseError!*ast.Node {
4274 if (tok.id == .NumLitInt) {4285 if (tok.id == .NumLitInt) {
4275 if (tok.num_lit_suffix == .None) {4286 if (tok.num_lit_suffix == .None) {
4276 if (tok.bytes.len > 2 and tok.bytes[0] == '0') {4287 if (tok.bytes.len > 2 and tok.bytes[0] == '0') {
4277 switch (tok.bytes[1]) {4288 switch (tok.bytes[1]) {
4278 '0'...'7' => {4289 '0'...'7' => {
4279 // octal4290 // octal
4280 return transCreateNodeInt(rp.c, try std.fmt.allocPrint(rp.c.a(), "0o{}", .{tok.bytes}));4291 return transCreateNodeInt(c, try std.fmt.allocPrint(c.a(), "0o{}", .{tok.bytes}));
4281 },4292 },
4282 else => {},4293 else => {},
4283 }4294 }
4284 }4295 }
4285 return transCreateNodeInt(rp.c, tok.bytes);4296 return transCreateNodeInt(c, tok.bytes);
4286 }4297 }
4287 const cast_node = try transCreateNodeBuiltinFnCall(rp.c, "@as");4298 const cast_node = try transCreateNodeBuiltinFnCall(c, "@as");
4288 try cast_node.params.push(try transCreateNodeIdentifier(rp.c, switch (tok.num_lit_suffix) {4299 try cast_node.params.push(try transCreateNodeIdentifier(c, switch (tok.num_lit_suffix) {
4289 .U => "c_uint",4300 .U => "c_uint",
4290 .L => "c_long",4301 .L => "c_long",
4291 .LU => "c_ulong",4302 .LU => "c_ulong",
...@@ -4293,62 +4304,55 @@ fn parseCNumLit(rp: RestorePoint, tok: *CToken, source_loc: ZigClangSourceLocati...@@ -4293,62 +4304,55 @@ fn parseCNumLit(rp: RestorePoint, tok: *CToken, source_loc: ZigClangSourceLocati
4293 .LLU => "c_ulonglong",4304 .LLU => "c_ulonglong",
4294 else => unreachable,4305 else => unreachable,
4295 }));4306 }));
4296 _ = try appendToken(rp.c, .Comma, ",");4307 _ = try appendToken(c, .Comma, ",");
4297 try cast_node.params.push(try transCreateNodeInt(rp.c, tok.bytes));4308 try cast_node.params.push(try transCreateNodeInt(c, tok.bytes));
4298 cast_node.rparen_token = try appendToken(rp.c, .RParen, ")");4309 cast_node.rparen_token = try appendToken(c, .RParen, ")");
4299 return &cast_node.base;4310 return &cast_node.base;
4300 } else if (tok.id == .NumLitFloat) {4311 } else if (tok.id == .NumLitFloat) {
4301 if (tok.num_lit_suffix == .None) {4312 if (tok.num_lit_suffix == .None) {
4302 return transCreateNodeFloat(rp.c, tok.bytes);4313 return transCreateNodeFloat(c, tok.bytes);
4303 }4314 }
4304 const cast_node = try transCreateNodeBuiltinFnCall(rp.c, "@as");4315 const cast_node = try transCreateNodeBuiltinFnCall(c, "@as");
4305 try cast_node.params.push(try transCreateNodeIdentifier(rp.c, switch (tok.num_lit_suffix) {4316 try cast_node.params.push(try transCreateNodeIdentifier(c, switch (tok.num_lit_suffix) {
4306 .F => "f32",4317 .F => "f32",
4307 .L => "f64",4318 .L => "f64",
4308 else => unreachable,4319 else => unreachable,
4309 }));4320 }));
4310 _ = try appendToken(rp.c, .Comma, ",");4321 _ = try appendToken(c, .Comma, ",");
4311 try cast_node.params.push(try transCreateNodeFloat(rp.c, tok.bytes));4322 try cast_node.params.push(try transCreateNodeFloat(c, tok.bytes));
4312 cast_node.rparen_token = try appendToken(rp.c, .RParen, ")");4323 cast_node.rparen_token = try appendToken(c, .RParen, ")");
4313 return &cast_node.base;4324 return &cast_node.base;
4314 } else4325 } else unreachable;
4315 return revertAndWarn(
4316 rp,
4317 error.ParseError,
4318 source_loc,
4319 "expected number literal",
4320 .{},
4321 );
4322}4326}
43234327
4324fn parseCPrimaryExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node {4328fn parseCPrimaryExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node {
4325 const tok = it.next().?;4329 const tok = it.next().?;
4326 switch (tok.id) {4330 switch (tok.id) {
4327 .CharLit => {4331 .CharLit => {
4328 const token = try appendToken(rp.c, .CharLiteral, tok.bytes);4332 const token = try appendToken(c, .CharLiteral, tok.bytes);
4329 const node = try rp.c.a().create(ast.Node.CharLiteral);4333 const node = try c.a().create(ast.Node.CharLiteral);
4330 node.* = ast.Node.CharLiteral{4334 node.* = ast.Node.CharLiteral{
4331 .token = token,4335 .token = token,
4332 };4336 };
4333 return &node.base;4337 return &node.base;
4334 },4338 },
4335 .StrLit => {4339 .StrLit => {
4336 const token = try appendToken(rp.c, .StringLiteral, tok.bytes);4340 const token = try appendToken(c, .StringLiteral, tok.bytes);
4337 const node = try rp.c.a().create(ast.Node.StringLiteral);4341 const node = try c.a().create(ast.Node.StringLiteral);
4338 node.* = ast.Node.StringLiteral{4342 node.* = ast.Node.StringLiteral{
4339 .token = token,4343 .token = token,
4340 };4344 };
4341 return &node.base;4345 return &node.base;
4342 },4346 },
4343 .NumLitInt, .NumLitFloat => {4347 .NumLitInt, .NumLitFloat => {
4344 return parseCNumLit(rp, tok, source_loc);4348 return parseCNumLit(c, tok, source_loc);
4345 },4349 },
4346 .Identifier => {4350 .Identifier => {
4347 const name = if (scope.getAlias(tok.bytes)) |a| a else tok.bytes;4351 const name = if (scope.getAlias(tok.bytes)) |a| a else tok.bytes;
4348 return transCreateNodeIdentifier(rp.c, name);4352 return transCreateNodeIdentifier(c, name);
4349 },4353 },
4350 .LParen => {4354 .LParen => {
4351 const inner_node = try parseCExpr(rp, it, source_loc, scope);4355 const inner_node = try parseCExpr(c, it, source_loc, scope);
43524356
4353 if (it.peek().?.id == .RParen) {4357 if (it.peek().?.id == .RParen) {
4354 _ = it.next();4358 _ = it.next();
...@@ -4359,18 +4363,19 @@ fn parseCPrimaryExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc:...@@ -4359,18 +4363,19 @@ fn parseCPrimaryExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc:
4359 }4363 }
43604364
4361 // hack to get zig fmt to render a comma in builtin calls4365 // hack to get zig fmt to render a comma in builtin calls
4362 _ = try appendToken(rp.c, .Comma, ",");4366 _ = try appendToken(c, .Comma, ",");
43634367
4364 const node_to_cast = try parseCExpr(rp, it, source_loc, scope);4368 const node_to_cast = try parseCExpr(c, it, source_loc, scope);
43654369
4366 if (it.next().?.id != .RParen) {4370 if (it.next().?.id != .RParen) {
4367 return revertAndWarn(4371 try failDecl(
4368 rp,4372 c,
4369 error.ParseError,
4370 source_loc,4373 source_loc,
4371 "unable to translate C expr",4374 it.list.at(0).*.bytes,
4375 "unable to translate C expr: expected ')''",
4372 .{},4376 .{},
4373 );4377 );
4378 return error.ParseError;
4374 }4379 }
43754380
4376 //if (@typeId(@TypeOf(x)) == .Pointer)4381 //if (@typeId(@TypeOf(x)) == .Pointer)
...@@ -4380,114 +4385,133 @@ fn parseCPrimaryExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc:...@@ -4380,114 +4385,133 @@ fn parseCPrimaryExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc:
4380 //else4385 //else
4381 // @as(dest, x)4386 // @as(dest, x)
43824387
4383 const if_1 = try transCreateNodeIf(rp.c);4388 const if_1 = try transCreateNodeIf(c);
4384 const type_id_1 = try transCreateNodeBuiltinFnCall(rp.c, "@typeId");4389 const type_id_1 = try transCreateNodeBuiltinFnCall(c, "@typeId");
4385 const type_of_1 = try transCreateNodeBuiltinFnCall(rp.c, "@TypeOf");4390 const type_of_1 = try transCreateNodeBuiltinFnCall(c, "@TypeOf");
4386 try type_id_1.params.push(&type_of_1.base);4391 try type_id_1.params.push(&type_of_1.base);
4387 try type_of_1.params.push(node_to_cast);4392 try type_of_1.params.push(node_to_cast);
4388 type_of_1.rparen_token = try appendToken(rp.c, .LParen, ")");4393 type_of_1.rparen_token = try appendToken(c, .LParen, ")");
4389 type_id_1.rparen_token = try appendToken(rp.c, .LParen, ")");4394 type_id_1.rparen_token = try appendToken(c, .LParen, ")");
43904395
4391 const cmp_1 = try rp.c.a().create(ast.Node.InfixOp);4396 const cmp_1 = try c.a().create(ast.Node.InfixOp);
4392 cmp_1.* = .{4397 cmp_1.* = .{
4393 .op_token = try appendToken(rp.c, .EqualEqual, "=="),4398 .op_token = try appendToken(c, .EqualEqual, "=="),
4394 .lhs = &type_id_1.base,4399 .lhs = &type_id_1.base,
4395 .op = .EqualEqual,4400 .op = .EqualEqual,
4396 .rhs = try transCreateNodeEnumLiteral(rp.c, "Pointer"),4401 .rhs = try transCreateNodeEnumLiteral(c, "Pointer"),
4397 };4402 };
4398 if_1.condition = &cmp_1.base;4403 if_1.condition = &cmp_1.base;
4399 _ = try appendToken(rp.c, .LParen, ")");4404 _ = try appendToken(c, .LParen, ")");
44004405
4401 const ptr_cast = try transCreateNodeBuiltinFnCall(rp.c, "@ptrCast");4406 const ptr_cast = try transCreateNodeBuiltinFnCall(c, "@ptrCast");
4402 try ptr_cast.params.push(inner_node);4407 try ptr_cast.params.push(inner_node);
4403 try ptr_cast.params.push(node_to_cast);4408 try ptr_cast.params.push(node_to_cast);
4404 ptr_cast.rparen_token = try appendToken(rp.c, .LParen, ")");4409 ptr_cast.rparen_token = try appendToken(c, .LParen, ")");
4405 if_1.body = &ptr_cast.base;4410 if_1.body = &ptr_cast.base;
44064411
4407 const else_1 = try transCreateNodeElse(rp.c);4412 const else_1 = try transCreateNodeElse(c);
4408 if_1.@"else" = else_1;4413 if_1.@"else" = else_1;
44094414
4410 const if_2 = try transCreateNodeIf(rp.c);4415 const if_2 = try transCreateNodeIf(c);
4411 const type_id_2 = try transCreateNodeBuiltinFnCall(rp.c, "@typeId");4416 const type_id_2 = try transCreateNodeBuiltinFnCall(c, "@typeId");
4412 const type_of_2 = try transCreateNodeBuiltinFnCall(rp.c, "@TypeOf");4417 const type_of_2 = try transCreateNodeBuiltinFnCall(c, "@TypeOf");
4413 try type_id_2.params.push(&type_of_2.base);4418 try type_id_2.params.push(&type_of_2.base);
4414 try type_of_2.params.push(node_to_cast);4419 try type_of_2.params.push(node_to_cast);
4415 type_of_2.rparen_token = try appendToken(rp.c, .LParen, ")");4420 type_of_2.rparen_token = try appendToken(c, .LParen, ")");
4416 type_id_2.rparen_token = try appendToken(rp.c, .LParen, ")");4421 type_id_2.rparen_token = try appendToken(c, .LParen, ")");
44174422
4418 const cmp_2 = try rp.c.a().create(ast.Node.InfixOp);4423 const cmp_2 = try c.a().create(ast.Node.InfixOp);
4419 cmp_2.* = .{4424 cmp_2.* = .{
4420 .op_token = try appendToken(rp.c, .EqualEqual, "=="),4425 .op_token = try appendToken(c, .EqualEqual, "=="),
4421 .lhs = &type_id_2.base,4426 .lhs = &type_id_2.base,
4422 .op = .EqualEqual,4427 .op = .EqualEqual,
4423 .rhs = try transCreateNodeEnumLiteral(rp.c, "Int"),4428 .rhs = try transCreateNodeEnumLiteral(c, "Int"),
4424 };4429 };
4425 if_2.condition = &cmp_2.base;4430 if_2.condition = &cmp_2.base;
4426 else_1.body = &if_2.base;4431 else_1.body = &if_2.base;
4427 _ = try appendToken(rp.c, .LParen, ")");4432 _ = try appendToken(c, .LParen, ")");
44284433
4429 const int_to_ptr = try transCreateNodeBuiltinFnCall(rp.c, "@intToPtr");4434 const int_to_ptr = try transCreateNodeBuiltinFnCall(c, "@intToPtr");
4430 try int_to_ptr.params.push(inner_node);4435 try int_to_ptr.params.push(inner_node);
4431 try int_to_ptr.params.push(node_to_cast);4436 try int_to_ptr.params.push(node_to_cast);
4432 int_to_ptr.rparen_token = try appendToken(rp.c, .LParen, ")");4437 int_to_ptr.rparen_token = try appendToken(c, .LParen, ")");
4433 if_2.body = &int_to_ptr.base;4438 if_2.body = &int_to_ptr.base;
44344439
4435 const else_2 = try transCreateNodeElse(rp.c);4440 const else_2 = try transCreateNodeElse(c);
4436 if_2.@"else" = else_2;4441 if_2.@"else" = else_2;
44374442
4438 const as = try transCreateNodeBuiltinFnCall(rp.c, "@as");4443 const as = try transCreateNodeBuiltinFnCall(c, "@as");
4439 try as.params.push(inner_node);4444 try as.params.push(inner_node);
4440 try as.params.push(node_to_cast);4445 try as.params.push(node_to_cast);
4441 as.rparen_token = try appendToken(rp.c, .LParen, ")");4446 as.rparen_token = try appendToken(c, .LParen, ")");
4442 else_2.body = &as.base;4447 else_2.body = &as.base;
44434448
4444 return &if_1.base;4449 return &if_1.base;
4445 },4450 },
4446 else => return revertAndWarn(4451 else => {
4447 rp,4452 try failDecl(
4448 error.UnsupportedTranslation,4453 c,
4449 source_loc,4454 source_loc,
4450 "unable to translate C expr, unexpected token: {}",4455 it.list.at(0).*.bytes,
4451 .{tok.id},4456 "unable to translate C expr: unexpected token {}",
4452 ),4457 .{tok.id},
4458 );
4459 return error.ParseError;
4460 },
4453 }4461 }
4454}4462}
44554463
4456fn parseCSuffixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node {4464fn parseCSuffixOpExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node {
4457 var node = try parseCPrimaryExpr(rp, it, source_loc, scope);4465 var node = try parseCPrimaryExpr(c, it, source_loc, scope);
4458 while (true) {4466 while (true) {
4459 const tok = it.next().?;4467 const tok = it.next().?;
4460 switch (tok.id) {4468 switch (tok.id) {
4461 .Dot => {4469 .Dot => {
4462 const name_tok = it.next().?;4470 const name_tok = it.next().?;
4463 if (name_tok.id != .Identifier)4471 if (name_tok.id != .Identifier) {
4472 try failDecl(
4473 c,
4474 source_loc,
4475 it.list.at(0).*.bytes,
4476 "unable to translate C expr: expected identifier",
4477 .{},
4478 );
4464 return error.ParseError;4479 return error.ParseError;
4480 }
44654481
4466 node = try transCreateNodeFieldAccess(rp.c, node, name_tok.bytes);4482 node = try transCreateNodeFieldAccess(c, node, name_tok.bytes);
4467 },4483 },
4468 .Arrow => {4484 .Arrow => {
4469 const name_tok = it.next().?;4485 const name_tok = it.next().?;
4470 if (name_tok.id != .Identifier)4486 if (name_tok.id != .Identifier) {
4487 try failDecl(
4488 c,
4489 source_loc,
4490 it.list.at(0).*.bytes,
4491 "unable to translate C expr: expected identifier",
4492 .{},
4493 );
4471 return error.ParseError;4494 return error.ParseError;
4495 }
44724496
4473 const deref = try transCreateNodePtrDeref(rp.c, node);4497 const deref = try transCreateNodePtrDeref(c, node);
4474 node = try transCreateNodeFieldAccess(rp.c, deref, name_tok.bytes);4498 node = try transCreateNodeFieldAccess(c, deref, name_tok.bytes);
4475 },4499 },
4476 .Asterisk => {4500 .Asterisk => {
4477 if (it.peek().?.id == .RParen) {4501 if (it.peek().?.id == .RParen) {
4478 // type *)4502 // type *)
44794503
4480 // hack to get zig fmt to render a comma in builtin calls4504 // hack to get zig fmt to render a comma in builtin calls
4481 _ = try appendToken(rp.c, .Comma, ",");4505 _ = try appendToken(c, .Comma, ",");
44824506
4483 const ptr = try transCreateNodePtrType(rp.c, false, false, .Identifier);4507 const ptr = try transCreateNodePtrType(c, false, false, .Identifier);
4484 ptr.rhs = node;4508 ptr.rhs = node;
4485 return &ptr.base;4509 return &ptr.base;
4486 } else {4510 } else {
4487 // expr * expr4511 // expr * expr
4488 const op_token = try appendToken(rp.c, .Asterisk, "*");4512 const op_token = try appendToken(c, .Asterisk, "*");
4489 const rhs = try parseCPrimaryExpr(rp, it, source_loc, scope);4513 const rhs = try parseCPrimaryExpr(c, it, source_loc, scope);
4490 const mul_node = try rp.c.a().create(ast.Node.InfixOp);4514 const mul_node = try c.a().create(ast.Node.InfixOp);
4491 mul_node.* = .{4515 mul_node.* = .{
4492 .op_token = op_token,4516 .op_token = op_token,
4493 .lhs = node,4517 .lhs = node,
...@@ -4498,9 +4522,9 @@ fn parseCSuffixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc...@@ -4498,9 +4522,9 @@ fn parseCSuffixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc
4498 }4522 }
4499 },4523 },
4500 .Shl => {4524 .Shl => {
4501 const op_token = try appendToken(rp.c, .AngleBracketAngleBracketLeft, "<<");4525 const op_token = try appendToken(c, .AngleBracketAngleBracketLeft, "<<");
4502 const rhs = try parseCExpr(rp, it, source_loc, scope);4526 const rhs = try parseCExpr(c, it, source_loc, scope);
4503 const bitshift_node = try rp.c.a().create(ast.Node.InfixOp);4527 const bitshift_node = try c.a().create(ast.Node.InfixOp);
4504 bitshift_node.* = .{4528 bitshift_node.* = .{
4505 .op_token = op_token,4529 .op_token = op_token,
4506 .lhs = node,4530 .lhs = node,
...@@ -4510,9 +4534,9 @@ fn parseCSuffixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc...@@ -4510,9 +4534,9 @@ fn parseCSuffixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc
4510 node = &bitshift_node.base;4534 node = &bitshift_node.base;
4511 },4535 },
4512 .Pipe => {4536 .Pipe => {
4513 const op_token = try appendToken(rp.c, .Pipe, "|");4537 const op_token = try appendToken(c, .Pipe, "|");
4514 const rhs = try parseCExpr(rp, it, source_loc, scope);4538 const rhs = try parseCExpr(c, it, source_loc, scope);
4515 const or_node = try rp.c.a().create(ast.Node.InfixOp);4539 const or_node = try c.a().create(ast.Node.InfixOp);
4516 or_node.* = .{4540 or_node.* = .{
4517 .op_token = op_token,4541 .op_token = op_token,
4518 .lhs = node,4542 .lhs = node,
...@@ -4522,39 +4546,63 @@ fn parseCSuffixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc...@@ -4522,39 +4546,63 @@ fn parseCSuffixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc
4522 node = &or_node.base;4546 node = &or_node.base;
4523 },4547 },
4524 .LBrace => {4548 .LBrace => {
4525 const arr_node = try transCreateNodeArrayAccess(rp.c, node);4549 const arr_node = try transCreateNodeArrayAccess(c, node);
4526 arr_node.op.ArrayAccess = try parseCExpr(rp, it, source_loc, scope);4550 arr_node.op.ArrayAccess = try parseCExpr(c, it, source_loc, scope);
4527 arr_node.rtoken = try appendToken(rp.c, .RBrace, "]");4551 arr_node.rtoken = try appendToken(c, .RBrace, "]");
4528 node = &arr_node.base;4552 node = &arr_node.base;
4529 if (it.next().?.id != .RBrace)4553 if (it.next().?.id != .RBrace) {
4554 try failDecl(
4555 c,
4556 source_loc,
4557 it.list.at(0).*.bytes,
4558 "unable to translate C expr: expected ']'",
4559 .{},
4560 );
4530 return error.ParseError;4561 return error.ParseError;
4562 }
4531 },4563 },
4532 .LParen => {4564 .LParen => {
4533 const call_node = try transCreateNodeFnCall(rp.c, node);4565 const call_node = try transCreateNodeFnCall(c, node);
4534 while (true) {4566 while (true) {
4535 const arg = try parseCExpr(rp, it, source_loc, scope);4567 const arg = try parseCExpr(c, it, source_loc, scope);
4536 try call_node.op.Call.params.push(arg);4568 try call_node.op.Call.params.push(arg);
4537 const next = it.next().?;4569 const next = it.next().?;
4538 if (next.id == .Comma)4570 if (next.id == .Comma)
4539 _ = try appendToken(rp.c, .Comma, ",")4571 _ = try appendToken(c, .Comma, ",")
4540 else if (next.id == .RParen)4572 else if (next.id == .RParen)
4541 break4573 break
4542 else4574 else {
4575 try failDecl(
4576 c,
4577 source_loc,
4578 it.list.at(0).*.bytes,
4579 "unable to translate C expr: expected ',' or ')'",
4580 .{},
4581 );
4543 return error.ParseError;4582 return error.ParseError;
4583 }
4544 }4584 }
4545 call_node.rtoken = try appendToken(rp.c, .RParen, ")");4585 call_node.rtoken = try appendToken(c, .RParen, ")");
4546 node = &call_node.base;4586 node = &call_node.base;
4547 },4587 },
4548 .QuestionMark => {4588 .QuestionMark => {
4549 // must come immediately after expr4589 // must come immediately after expr
4550 _ = try appendToken(rp.c, .RParen, ")");4590 _ = try appendToken(c, .RParen, ")");
4551 const if_node = try transCreateNodeIf(rp.c);4591 const if_node = try transCreateNodeIf(c);
4552 if_node.condition = node;4592 if_node.condition = node;
4553 if_node.body = try parseCPrimaryExpr(rp, it, source_loc, scope);4593 if_node.body = try parseCPrimaryExpr(c, it, source_loc, scope);
4554 if (it.next().?.id != .Colon)4594 if (it.next().?.id != .Colon) {
4595 try failDecl(
4596 c,
4597 source_loc,
4598 it.list.at(0).*.bytes,
4599 "unable to translate C expr: expected ':'",
4600 .{},
4601 );
4555 return error.ParseError;4602 return error.ParseError;
4556 if_node.@"else" = try transCreateNodeElse(rp.c);4603 }
4557 if_node.@"else".?.body = try parseCPrimaryExpr(rp, it, source_loc, scope);4604 if_node.@"else" = try transCreateNodeElse(c);
4605 if_node.@"else".?.body = try parseCPrimaryExpr(c, it, source_loc, scope);
4558 node = &if_node.base;4606 node = &if_node.base;
4559 },4607 },
4560 else => {4608 else => {
...@@ -4565,32 +4613,32 @@ fn parseCSuffixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc...@@ -4565,32 +4613,32 @@ fn parseCSuffixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc
4565 }4613 }
4566}4614}
45674615
4568fn parseCPrefixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node {4616fn parseCPrefixOpExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node {
4569 const op_tok = it.next().?;4617 const op_tok = it.next().?;
45704618
4571 switch (op_tok.id) {4619 switch (op_tok.id) {
4572 .Bang => {4620 .Bang => {
4573 const node = try transCreateNodePrefixOp(rp.c, .BoolNot, .Bang, "!");4621 const node = try transCreateNodePrefixOp(c, .BoolNot, .Bang, "!");
4574 node.rhs = try parseCPrefixOpExpr(rp, it, source_loc, scope);4622 node.rhs = try parseCPrefixOpExpr(c, it, source_loc, scope);
4575 return &node.base;4623 return &node.base;
4576 },4624 },
4577 .Minus => {4625 .Minus => {
4578 const node = try transCreateNodePrefixOp(rp.c, .Negation, .Minus, "-");4626 const node = try transCreateNodePrefixOp(c, .Negation, .Minus, "-");
4579 node.rhs = try parseCPrefixOpExpr(rp, it, source_loc, scope);4627 node.rhs = try parseCPrefixOpExpr(c, it, source_loc, scope);
4580 return &node.base;4628 return &node.base;
4581 },4629 },
4582 .Tilde => {4630 .Tilde => {
4583 const node = try transCreateNodePrefixOp(rp.c, .BitNot, .Tilde, "~");4631 const node = try transCreateNodePrefixOp(c, .BitNot, .Tilde, "~");
4584 node.rhs = try parseCPrefixOpExpr(rp, it, source_loc, scope);4632 node.rhs = try parseCPrefixOpExpr(c, it, source_loc, scope);
4585 return &node.base;4633 return &node.base;
4586 },4634 },
4587 .Asterisk => {4635 .Asterisk => {
4588 const prefix_op_expr = try parseCPrefixOpExpr(rp, it, source_loc, scope);4636 const prefix_op_expr = try parseCPrefixOpExpr(c, it, source_loc, scope);
4589 return try transCreateNodePtrDeref(rp.c, prefix_op_expr);4637 return try transCreateNodePtrDeref(c, prefix_op_expr);
4590 },4638 },
4591 else => {4639 else => {
4592 _ = it.prev();4640 _ = it.prev();
4593 return try parseCSuffixOpExpr(rp, it, source_loc, scope);4641 return try parseCSuffixOpExpr(c, it, source_loc, scope);
4594 },4642 },
4595 }4643 }
4596}4644}