authorgravatar for evan@lagerdata.comEvan Haas <evan@lagerdata.com> 2021-08-31 10:30:36-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-09-01 17:54:07-07:00
log89dd2b7ac23f298b5ac37ae022724b43c2137091
tree8e4ce82a0f3f9305c2cbae6d38501a9bca82ac7a
parentcca57042df374305390b5b0000be75ba6d24fb63

translate-c: emit compileError for undefined identifiers in macros


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

src/translate_c.zig+20
...@@ -5248,6 +5248,23 @@ const MacroCtx = struct {...@@ -5248,6 +5248,23 @@ const MacroCtx = struct {
5248 fn makeSlicer(self: *const MacroCtx) MacroSlicer {5248 fn makeSlicer(self: *const MacroCtx) MacroSlicer {
5249 return MacroSlicer{ .source = self.source, .tokens = self.list };5249 return MacroSlicer{ .source = self.source, .tokens = self.list };
5250 }5250 }
5251
5252 fn containsUndefinedIdentifier(self: *MacroCtx, scope: *Scope) ?[]const u8 {
5253 const slicer = self.makeSlicer();
5254 var i: usize = 1; // index 0 is the macro name
5255 while (i < self.list.len) : (i += 1) {
5256 const token = self.list[i];
5257 switch (token.id) {
5258 .Period => i += 1, // skip next token since field identifiers can be unknown
5259 .Identifier => {
5260 const identifier = slicer.slice(token);
5261 if (!scope.contains(identifier)) return identifier;
5262 },
5263 else => {},
5264 }
5265 }
5266 return null;
5267 }
5251};5268};
52525269
5253fn tokenizeMacro(source: []const u8, tok_list: *std.ArrayList(CToken)) Error!void {5270fn tokenizeMacro(source: []const u8, tok_list: *std.ArrayList(CToken)) Error!void {
...@@ -5344,6 +5361,9 @@ fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void {...@@ -5344,6 +5361,9 @@ fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void {
5344fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void {5361fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void {
5345 const scope = &c.global_scope.base;5362 const scope = &c.global_scope.base;
53465363
5364 if (m.containsUndefinedIdentifier(scope)) |ident|
5365 return m.fail(c, "unable to translate macro: undefined identifier `{s}`", .{ident});
5366
5347 const init_node = try parseCExpr(c, m, scope);5367 const init_node = try parseCExpr(c, m, scope);
5348 const last = m.next().?;5368 const last = m.next().?;
5349 if (last != .Eof and last != .Nl)5369 if (last != .Eof and last != .Nl)
test/translate_c.zig+12
...@@ -228,6 +228,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -228,6 +228,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
228 });228 });
229229
230 cases.add("macro expressions respect C operator precedence",230 cases.add("macro expressions respect C operator precedence",
231 \\int *foo = 0;
231 \\#define FOO *((foo) + 2)232 \\#define FOO *((foo) + 2)
232 \\#define VALUE (1 + 2 * 3 + 4 * 5 + 6 << 7 | 8 == 9)233 \\#define VALUE (1 + 2 * 3 + 4 * 5 + 6 << 7 | 8 == 9)
233 \\#define _AL_READ3BYTES(p) ((*(unsigned char *)(p)) \234 \\#define _AL_READ3BYTES(p) ((*(unsigned char *)(p)) \
...@@ -459,6 +460,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -459,6 +460,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
459 });460 });
460461
461 cases.add("macro line continuation",462 cases.add("macro line continuation",
463 \\int BAR = 0;
462 \\#define FOO -\464 \\#define FOO -\
463 \\BAR465 \\BAR
464 , &[_][]const u8{466 , &[_][]const u8{
...@@ -1833,6 +1835,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1833,6 +1835,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1833 });1835 });
18341836
1835 cases.add("macro pointer cast",1837 cases.add("macro pointer cast",
1838 \\#define NRF_GPIO_BASE 0
1836 \\typedef struct { int dummy; } NRF_GPIO_Type;1839 \\typedef struct { int dummy; } NRF_GPIO_Type;
1837 \\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE)1840 \\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE)
1838 , &[_][]const u8{1841 , &[_][]const u8{
...@@ -1873,6 +1876,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1873,6 +1876,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1873 });1876 });
18741877
1875 cases.add("macro add",1878 cases.add("macro add",
1879 \\#define D3_AHB1PERIPH_BASE 0
1876 \\#define PERIPH_BASE (0x40000000UL) /*!< Base address of : AHB/APB Peripherals */1880 \\#define PERIPH_BASE (0x40000000UL) /*!< Base address of : AHB/APB Peripherals */
1877 \\#define D3_APB1PERIPH_BASE (PERIPH_BASE + 0x18000000UL)1881 \\#define D3_APB1PERIPH_BASE (PERIPH_BASE + 0x18000000UL)
1878 \\#define RCC_BASE (D3_AHB1PERIPH_BASE + 0x4400UL)1882 \\#define RCC_BASE (D3_AHB1PERIPH_BASE + 0x4400UL)
...@@ -3138,6 +3142,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -3138,6 +3142,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
3138 \\#define FOO(bar) baz((void *)(baz))3142 \\#define FOO(bar) baz((void *)(baz))
3139 \\#define BAR (void*) a3143 \\#define BAR (void*) a
3140 \\#define BAZ (uint32_t)(2)3144 \\#define BAZ (uint32_t)(2)
3145 \\#define a 2
3141 , &[_][]const u8{3146 , &[_][]const u8{
3142 \\pub inline fn FOO(bar: anytype) @TypeOf(baz(@import("std").zig.c_translation.cast(?*c_void, baz))) {3147 \\pub inline fn FOO(bar: anytype) @TypeOf(baz(@import("std").zig.c_translation.cast(?*c_void, baz))) {
3143 \\ _ = bar;3148 \\ _ = bar;
...@@ -3160,6 +3165,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -3160,6 +3165,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
3160 });3165 });
31613166
3162 cases.add("macro conditional operator",3167 cases.add("macro conditional operator",
3168 \\ int a, b, c;
3163 \\#define FOO a ? b : c3169 \\#define FOO a ? b : c
3164 , &[_][]const u8{3170 , &[_][]const u8{
3165 \\pub const FOO = if (a) b else c;3171 \\pub const FOO = if (a) b else c;
...@@ -3649,4 +3655,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -3649,4 +3655,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
3649 ,3655 ,
3650 \\_ = p[@intCast(c_uint, @as(c_int, 1))];3656 \\_ = p[@intCast(c_uint, @as(c_int, 1))];
3651 });3657 });
3658
3659 cases.add("Undefined macro identifier",
3660 \\#define FOO BAR
3661 , &[_][]const u8{
3662 \\pub const FOO = @compileError("unable to translate macro: undefined identifier `BAR`");
3663 });
3652}3664}