mirror of
https://github.com/ziglang/zig.git
synced 2026-01-09 17:05:16 +00:00
stage2 astgen: find unused vars
This commit is contained in:
parent
8a6de78e07
commit
75f7a8913e
@ -1826,6 +1826,7 @@ fn blockExprStmts(
|
||||
}
|
||||
|
||||
try genDefers(gz, parent_scope, scope, .none);
|
||||
try checkUsed(gz, parent_scope, scope);
|
||||
}
|
||||
|
||||
fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) InnerError!void {
|
||||
@ -2154,6 +2155,36 @@ fn genDefers(
|
||||
}
|
||||
}
|
||||
|
||||
fn checkUsed(
|
||||
gz: *GenZir,
|
||||
outer_scope: *Scope,
|
||||
inner_scope: *Scope,
|
||||
) InnerError!void {
|
||||
const astgen = gz.astgen;
|
||||
const tree = astgen.tree;
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
|
||||
var scope = inner_scope;
|
||||
while (scope != outer_scope) {
|
||||
switch (scope.tag) {
|
||||
.gen_zir => scope = scope.cast(GenZir).?.parent,
|
||||
.local_val => {
|
||||
const s = scope.cast(Scope.LocalVal).?;
|
||||
if (!s.used) return astgen.failTok(s.token_src, "unused local constant", .{});
|
||||
scope = s.parent;
|
||||
},
|
||||
.local_ptr => {
|
||||
const s = scope.cast(Scope.LocalPtr).?;
|
||||
if (!s.used) return astgen.failTok(s.token_src, "unused local variable", .{});
|
||||
scope = s.parent;
|
||||
},
|
||||
.defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent,
|
||||
.namespace => unreachable,
|
||||
.top => unreachable,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn deferStmt(
|
||||
gz: *GenZir,
|
||||
scope: *Scope,
|
||||
@ -2930,6 +2961,7 @@ fn fnDecl(
|
||||
.name = param_name,
|
||||
.inst = arg_inst,
|
||||
.token_src = name_token,
|
||||
// TODO make function paramater have different message instead of unused constant
|
||||
};
|
||||
params_scope = &sub_scope.base;
|
||||
|
||||
@ -3370,6 +3402,7 @@ fn structDeclInner(
|
||||
};
|
||||
defer block_scope.instructions.deinit(gpa);
|
||||
|
||||
// TODO should we change this to scope in other places too?
|
||||
var namespace: Scope.Namespace = .{ .parent = scope };
|
||||
defer namespace.decls.deinit(gpa);
|
||||
|
||||
@ -6131,10 +6164,14 @@ fn identifier(
|
||||
while (true) switch (s.tag) {
|
||||
.local_val => {
|
||||
const local_val = s.cast(Scope.LocalVal).?;
|
||||
if (local_val.name == name_str_index) {
|
||||
local_val.used = true;
|
||||
}
|
||||
if (hit_namespace) {
|
||||
// captures of non-locals need to be emitted as decl_val or decl_ref
|
||||
// This *might* be capturable depending on if it is comptime known
|
||||
break;
|
||||
s = local_val.parent;
|
||||
continue;
|
||||
}
|
||||
if (local_val.name == name_str_index) {
|
||||
return rvalue(gz, scope, rl, local_val.inst, ident);
|
||||
@ -6144,6 +6181,7 @@ fn identifier(
|
||||
.local_ptr => {
|
||||
const local_ptr = s.cast(Scope.LocalPtr).?;
|
||||
if (local_ptr.name == name_str_index) {
|
||||
local_ptr.used = true;
|
||||
if (hit_namespace) {
|
||||
if (local_ptr.is_comptime)
|
||||
break
|
||||
@ -6151,6 +6189,8 @@ fn identifier(
|
||||
return astgen.failNodeNotes(ident, "'{s}' not accessible from inner function", .{ident_name}, &.{
|
||||
try astgen.errNoteTok(local_ptr.token_src, "declared here", .{}),
|
||||
// TODO add crossed function definition here note.
|
||||
// Maybe add a note to the error about it being because of the var,
|
||||
// maybe recommend copying it into a const variable. -SpexGuy
|
||||
});
|
||||
}
|
||||
switch (rl) {
|
||||
@ -8341,6 +8381,8 @@ const Scope = struct {
|
||||
token_src: ast.TokenIndex,
|
||||
/// String table index.
|
||||
name: u32,
|
||||
/// has this variable been referenced?
|
||||
used: bool = false,
|
||||
};
|
||||
|
||||
/// This could be a `const` or `var` local. It has a pointer instead of a value.
|
||||
@ -8358,6 +8400,8 @@ const Scope = struct {
|
||||
/// String table index.
|
||||
name: u32,
|
||||
is_comptime: bool,
|
||||
/// has this variable been referenced?
|
||||
used: bool = false,
|
||||
};
|
||||
|
||||
const Defer = struct {
|
||||
|
||||
@ -246,6 +246,14 @@ pub fn addCases(ctx: *TestContext) !void {
|
||||
"",
|
||||
);
|
||||
}
|
||||
{
|
||||
var case = ctx.exe("unused vars", linux_x64);
|
||||
case.addError(
|
||||
\\pub fn main() void {
|
||||
\\ const x = 1;
|
||||
\\}
|
||||
, &.{":2:11: error: unused local constant"});
|
||||
}
|
||||
{
|
||||
var case = ctx.exe("@TypeOf", linux_x64);
|
||||
case.addCompareOutput(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user