aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2022-03-04 15:14:12 +0000
committerPhilip Herron <philip.herron@embecosm.com>2022-03-07 12:16:18 +0000
commit7820ff8b8b14e1309aade205e50ef30bb08cb3e5 (patch)
tree33ca33f20795707b58b694fab16039d0c2c7374a /gcc/rust
parente00311aa9aabf447f27031cc5ffc114c5fbd8551 (diff)
downloadgcc-7820ff8b8b14e1309aade205e50ef30bb08cb3e5.zip
gcc-7820ff8b8b14e1309aade205e50ef30bb08cb3e5.tar.gz
gcc-7820ff8b8b14e1309aade205e50ef30bb08cb3e5.tar.bz2
Remove old unused code pass this was too generic
This now uses the TREE_USED fields on GCC tree's to track the usage of VAR_DECLS, PARM_DECLS and CONST_DECLS. The code does a pass over the body and parameters of functions as a lint pass. Fixes #676
Diffstat (limited to 'gcc/rust')
-rw-r--r--gcc/rust/Make-lang.in1
-rw-r--r--gcc/rust/backend/rust-compile-context.h5
-rw-r--r--gcc/rust/backend/rust-compile-expr.cc9
-rw-r--r--gcc/rust/backend/rust-compile-resolve-path.cc22
-rw-r--r--gcc/rust/lang.opt12
-rw-r--r--gcc/rust/lint/rust-lint-unused-var.cc98
-rw-r--r--gcc/rust/lint/rust-lint-unused-var.h36
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-unused.h61
-rw-r--r--gcc/rust/rust-gcc.cc20
-rw-r--r--gcc/rust/rust-session-manager.cc29
10 files changed, 200 insertions, 93 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index b33d90e..2f52931 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -101,6 +101,7 @@ GRS_OBJS = \
rust/rust-autoderef.o \
rust/rust-substitution-mapper.o \
rust/rust-lint-marklive.o \
+ rust/rust-lint-unused-var.o \
rust/rust-hir-type-check-path.o \
rust/rust-compile-intrinsic.o \
rust/rust-compile-pattern.o \
diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h
index 3fefd8d..4bade5c 100644
--- a/gcc/rust/backend/rust-compile-context.h
+++ b/gcc/rust/backend/rust-compile-context.h
@@ -307,6 +307,11 @@ public:
return mangler.mangle_item (ty, path);
}
+ std::vector<tree> &get_type_decls () { return type_decls; }
+ std::vector<::Bvariable *> &get_var_decls () { return var_decls; }
+ std::vector<tree> &get_const_decls () { return const_decls; }
+ std::vector<tree> &get_func_decls () { return func_decls; }
+
private:
::Backend *backend;
Resolver::Resolver *resolver;
diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc
index 6d50c3f..03e3c2e 100644
--- a/gcc/rust/backend/rust-compile-expr.cc
+++ b/gcc/rust/backend/rust-compile-expr.cc
@@ -1339,18 +1339,22 @@ CompileExpr::visit (HIR::IdentifierExpr &expr)
Bvariable *var = nullptr;
if (ctx->lookup_const_decl (ref, &translated))
{
+ TREE_USED (translated) = 1;
return;
}
else if (ctx->lookup_function_decl (ref, &fn))
{
+ TREE_USED (fn) = 1;
translated = address_expression (fn, expr.get_locus ());
}
else if (ctx->lookup_var_decl (ref, &var))
{
+ // TREE_USED is setup in the gcc abstraction here
translated = ctx->get_backend ()->var_expression (var, expr.get_locus ());
}
else if (ctx->lookup_pattern_binding (ref, &translated))
{
+ TREE_USED (translated) = 1;
return;
}
else
@@ -1371,6 +1375,11 @@ CompileExpr::visit (HIR::IdentifierExpr &expr)
else
translated = CompileItem::compile (resolved_item, ctx, lookup, true,
expr.get_locus ());
+
+ if (translated != error_mark_node)
+ {
+ TREE_USED (translated) = 1;
+ }
}
}
diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc
index e41ee7f..09f3860 100644
--- a/gcc/rust/backend/rust-compile-resolve-path.cc
+++ b/gcc/rust/backend/rust-compile-resolve-path.cc
@@ -23,6 +23,8 @@
#include "rust-hir-trait-resolve.h"
#include "rust-hir-path-probe.h"
+#include "print-tree.h"
+
namespace Rust {
namespace Compile {
@@ -117,12 +119,18 @@ ResolvePathRef::resolve (const HIR::PathIdentSegment &final_segment,
// might be a constant
tree constant_expr;
if (ctx->lookup_const_decl (ref, &constant_expr))
- return constant_expr;
+ {
+ TREE_USED (constant_expr) = 1;
+ return constant_expr;
+ }
// this might be a variable reference or a function reference
Bvariable *var = nullptr;
if (ctx->lookup_var_decl (ref, &var))
- return ctx->get_backend ()->var_expression (var, expr_locus);
+ {
+ // TREE_USED is setup in the gcc abstraction here
+ return ctx->get_backend ()->var_expression (var, expr_locus);
+ }
// it might be a function call
if (lookup->get_kind () == TyTy::TypeKind::FNDEF)
@@ -131,13 +139,19 @@ ResolvePathRef::resolve (const HIR::PathIdentSegment &final_segment,
tree fn = NULL_TREE;
if (ctx->lookup_function_decl (fntype->get_ty_ref (), &fn))
{
+ TREE_USED (fn) = 1;
return address_expression (fn, expr_locus);
}
}
// let the query system figure it out
- return query_compile (ref, lookup, final_segment, mappings, expr_locus,
- is_qualified_path);
+ tree resolved_item = query_compile (ref, lookup, final_segment, mappings,
+ expr_locus, is_qualified_path);
+ if (resolved_item != error_mark_node)
+ {
+ TREE_USED (resolved_item) = 1;
+ }
+ return resolved_item;
}
tree
diff --git a/gcc/rust/lang.opt b/gcc/rust/lang.opt
index 794a667..86a063f 100644
--- a/gcc/rust/lang.opt
+++ b/gcc/rust/lang.opt
@@ -38,6 +38,18 @@ Wall
Rust
; Documented in c.opt
+Wunused-variable
+Rust Var(warn_unused_variable) Init(1) Warning
+; documented in common.opt
+
+Wunused-const-variable
+Rust Warning Alias(Wunused-const-variable=, 2, 0)
+Warn when a const variable is unused.
+
+Wunused-const-variable=
+Rust Joined RejectNegative UInteger Var(warn_unused_const_variable) Init(1) Warning LangEnabledBy(Rust,Wunused-variable, 1, 0) IntegerRange(0, 2)
+Warn when a const variable is unused.
+
Wunused-result
Rust Var(warn_unused_result) Init(1) Warning
Warn if a caller of a function, marked with attribute warn_unused_result, does not use its return value.
diff --git a/gcc/rust/lint/rust-lint-unused-var.cc b/gcc/rust/lint/rust-lint-unused-var.cc
new file mode 100644
index 0000000..d4317e5
--- /dev/null
+++ b/gcc/rust/lint/rust-lint-unused-var.cc
@@ -0,0 +1,98 @@
+// Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-lint-unused-var.h"
+#include "print-tree.h"
+
+namespace Rust {
+namespace Analysis {
+
+static void
+check_decl (tree *t)
+{
+ rust_assert (TREE_CODE (*t) == VAR_DECL || TREE_CODE (*t) == PARM_DECL
+ || TREE_CODE (*t) == CONST_DECL);
+
+ tree var_name = DECL_NAME (*t);
+ const char *var_name_ptr = IDENTIFIER_POINTER (var_name);
+ bool starts_with_under_score = strncmp (var_name_ptr, "_", 1) == 0;
+
+ bool is_constant = TREE_CODE (*t) == CONST_DECL;
+ // if (!is_constant)
+ // {
+ // debug_tree (*t);
+ // rust_debug ("found var-decl: used %s artifical %s underscore %s name
+ // %s",
+ // TREE_USED (*t) ? "true" : "false",
+ // DECL_ARTIFICIAL (*t) ? "true" : "false",
+ // starts_with_under_score ? "true" : "false", var_name_ptr);
+ // }
+
+ if (!TREE_USED (*t) && !DECL_ARTIFICIAL (*t) && !starts_with_under_score)
+ {
+ warning_at (DECL_SOURCE_LOCATION (*t),
+ is_constant ? OPT_Wunused_const_variable_
+ : OPT_Wunused_variable,
+ "unused name %qE", *t);
+ }
+}
+
+static tree
+unused_var_walk_fn (tree *t, int *walk_subtrees, void *closure)
+{
+ switch (TREE_CODE (*t))
+ {
+ case VAR_DECL:
+ case CONST_DECL:
+ check_decl (t);
+ break;
+
+ default:
+ break;
+ }
+ return NULL_TREE;
+}
+
+void
+UnusedVariables::Lint (Compile::Context &ctx)
+{
+ for (auto &fndecl : ctx.get_func_decls ())
+ {
+ for (tree p = DECL_ARGUMENTS (fndecl); p != NULL_TREE; p = DECL_CHAIN (p))
+ {
+ check_decl (&p);
+ }
+
+ walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl),
+ &unused_var_walk_fn, &ctx);
+ }
+
+ for (auto &var : ctx.get_var_decls ())
+ {
+ tree t = ctx.get_backend ()->var_expression (var, Location ());
+ check_decl (&t);
+ }
+
+ for (auto &const_decl : ctx.get_const_decls ())
+ {
+ check_decl (&const_decl);
+ }
+}
+
+} // namespace Analysis
+} // namespace Rust
diff --git a/gcc/rust/lint/rust-lint-unused-var.h b/gcc/rust/lint/rust-lint-unused-var.h
new file mode 100644
index 0000000..6fabfef
--- /dev/null
+++ b/gcc/rust/lint/rust-lint-unused-var.h
@@ -0,0 +1,36 @@
+// Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_LINT_UNUSED_VAR
+#define RUST_LINT_UNUSED_VAR
+
+#include "rust-compile-context.h"
+
+namespace Rust {
+namespace Analysis {
+
+class UnusedVariables
+{
+public:
+ static void Lint (Compile::Context &ctx);
+};
+
+} // namespace Analysis
+} // namespace Rust
+
+#endif // RUST_LINT_UNUSED_VAR
diff --git a/gcc/rust/resolve/rust-ast-resolve-unused.h b/gcc/rust/resolve/rust-ast-resolve-unused.h
deleted file mode 100644
index 6c0fc42..0000000
--- a/gcc/rust/resolve/rust-ast-resolve-unused.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (C) 2020-2022 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#ifndef RUST_AST_RESOLVE_UNUSED_H
-#define RUST_AST_RESOLVE_UNUSED_H
-
-#include "rust-ast-resolve-base.h"
-
-namespace Rust {
-namespace Resolver {
-
-class ScanUnused
-{
-public:
- static bool ScanRib (Rib *r)
- {
- r->iterate_decls ([&] (NodeId decl_node_id, Location locus) -> bool {
- CanonicalPath ident = CanonicalPath::create_empty ();
-
- bool ok = r->lookup_canonical_path (decl_node_id, &ident);
- rust_assert (ok);
-
- bool name_starts_with_underscore = ident.get ().at (0) == '_';
- if (!r->have_references_for_node (decl_node_id)
- && !name_starts_with_underscore)
- {
- rust_warning_at (locus, 0, "unused name '%s'", ident.get ().c_str ());
- }
- return true;
- });
- return true;
- }
-
- static void Scan ()
- {
- auto resolver = Resolver::get ();
- resolver->iterate_name_ribs ([&] (Rib *r) -> bool { return ScanRib (r); });
- resolver->iterate_type_ribs ([&] (Rib *r) -> bool { return ScanRib (r); });
- resolver->iterate_label_ribs ([&] (Rib *r) -> bool { return ScanRib (r); });
- }
-};
-
-} // namespace Resolver
-} // namespace Rust
-
-#endif // RUST_AST_RESOLVE_UNUSED_H
diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc
index 60923d1..70c07c1 100644
--- a/gcc/rust/rust-gcc.cc
+++ b/gcc/rust/rust-gcc.cc
@@ -86,9 +86,15 @@ private:
tree
Bvariable::get_tree (Location location) const
{
- if (this->orig_type_ == NULL || this->t_ == error_mark_node
- || TREE_TYPE (this->t_) == this->orig_type_)
- return this->t_;
+ if (this->t_ == error_mark_node)
+ return error_mark_node;
+
+ TREE_USED (this->t_) = 1;
+ if (this->orig_type_ == NULL || TREE_TYPE (this->t_) == this->orig_type_)
+ {
+ return this->t_;
+ }
+
// Return *(orig_type*)&decl. */
tree t = build_fold_addr_expr_loc (location.gcc_location (), this->t_);
t = fold_build1_loc (location.gcc_location (), NOP_EXPR,
@@ -1063,10 +1069,7 @@ Gcc_backend::zero_expression (tree t)
tree
Gcc_backend::var_expression (Bvariable *var, Location location)
{
- tree ret = var->get_tree (location);
- if (ret == error_mark_node)
- return error_mark_node;
- return ret;
+ return var->get_tree (location);
}
// An expression that indirectly references an expression.
@@ -2394,7 +2397,6 @@ Gcc_backend::local_variable (tree function, const std::string &name,
tree decl = build_decl (location.gcc_location (), VAR_DECL,
get_identifier_from_string (name), type_tree);
DECL_CONTEXT (decl) = function;
- TREE_USED (decl) = 1;
if (decl_var != NULL)
{
@@ -2417,7 +2419,7 @@ Gcc_backend::parameter_variable (tree function, const std::string &name,
get_identifier_from_string (name), type_tree);
DECL_CONTEXT (decl) = function;
DECL_ARG_TYPE (decl) = type_tree;
- TREE_USED (decl) = 1;
+
rust_preserve_from_gc (decl);
return new Bvariable (decl);
}
diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc
index 54a6443..396f35f 100644
--- a/gcc/rust/rust-session-manager.cc
+++ b/gcc/rust/rust-session-manager.cc
@@ -25,11 +25,11 @@
#include "rust-ast-resolve.h"
#include "rust-ast-lower.h"
#include "rust-hir-type-check.h"
-#include "rust-lint-scan-deadcode.h"
#include "rust-tycheck-dump.h"
-#include "rust-ast-resolve-unused.h"
#include "rust-compile.h"
#include "rust-cfg-parser.h"
+#include "rust-lint-scan-deadcode.h"
+#include "rust-lint-unused-var.h"
#include "diagnostic.h"
#include "input.h"
@@ -599,27 +599,18 @@ Session::parse_file (const char *filename)
if (saw_errors ())
return;
- // scan dead code
- Analysis::ScanDeadcode::Scan (hir);
-
- if (saw_errors ())
- return;
-
- // scan unused has to be done after type resolution since methods are
- // resolved at that point
- Resolver::ScanUnused::Scan ();
-
- if (saw_errors ())
- return;
-
- // do compile
+ // do compile to gcc generic
Compile::Context ctx (backend);
Compile::CompileCrate::Compile (hir, &ctx);
- if (saw_errors ())
- return;
+ // we can't do static analysis if there are errors to worry about
+ if (!saw_errors ())
+ {
+ Analysis::ScanDeadcode::Scan (hir);
+ Analysis::UnusedVariables::Lint (ctx);
+ }
- // pass to GCC
+ // pass to GCC middle-end
ctx.write_to_backend ();
}