stage2: variable shadowing detection (#6969)

master
g-w1 2020-12-06 12:36:49 -05:00 committed by GitHub
parent 0268f54fcf
commit 6294c1136c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 47 additions and 2 deletions

View File

@ -489,7 +489,6 @@ fn varDecl(
node: *ast.Node.VarDecl,
block_arena: *Allocator,
) InnerError!*Scope {
// TODO implement detection of shadowing
if (node.getComptimeToken()) |comptime_token| {
return mod.failTok(scope, comptime_token, "TODO implement comptime locals", .{});
}
@ -499,6 +498,34 @@ fn varDecl(
const tree = scope.tree();
const name_src = tree.token_locs[node.name_token].start;
const ident_name = try identifierTokenString(mod, scope, node.name_token);
// Local variables shadowing detection, including function parameters.
{
var s = scope;
while (true) switch (s.tag) {
.local_val => {
const local_val = s.cast(Scope.LocalVal).?;
if (mem.eql(u8, local_val.name, ident_name)) {
return mod.fail(scope, name_src, "redefinition of '{}'", .{ident_name});
}
s = local_val.parent;
},
.local_ptr => {
const local_ptr = s.cast(Scope.LocalPtr).?;
if (mem.eql(u8, local_ptr.name, ident_name)) {
return mod.fail(scope, name_src, "redefinition of '{}'", .{ident_name});
}
s = local_ptr.parent;
},
.gen_zir => s = s.cast(Scope.GenZIR).?.parent,
else => break,
};
}
// Namespace vars shadowing detection
if (mod.lookupDeclName(scope, ident_name)) |_| {
return mod.fail(scope, name_src, "redefinition of '{}'", .{ident_name});
}
const init_node = node.getInitNode() orelse
return mod.fail(scope, name_src, "variables must be initialized", .{});

View File

@ -830,7 +830,7 @@ pub fn addCases(ctx: *TestContext) !void {
// Character literals and multiline strings.
case.addCompareOutput(
\\export fn _start() noreturn {
\\ const ignore =
\\ const ignore =
\\ \\ cool thx
\\ \\
\\ ;
@ -1113,6 +1113,24 @@ pub fn addCases(ctx: *TestContext) !void {
\\fn entry() void {}
, &[_][]const u8{":2:4: error: redefinition of 'entry'"});
{
var case = ctx.obj("variable shadowing", linux_x64);
case.addError(
\\export fn _start() noreturn {
\\ var i: u32 = 10;
\\ var i: u32 = 10;
\\ unreachable;
\\}
, &[_][]const u8{":3:9: error: redefinition of 'i'"});
case.addError(
\\var testing: i64 = 10;
\\export fn _start() noreturn {
\\ var testing: i64 = 20;
\\ unreachable;
\\}
, &[_][]const u8{":3:9: error: redefinition of 'testing'"});
}
{
var case = ctx.obj("extern variable has no type", linux_x64);
case.addError(