diff options
author | Philip Herron <philip.herron@embecosm.com> | 2022-03-04 15:14:12 +0000 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2022-03-07 12:16:18 +0000 |
commit | 7820ff8b8b14e1309aade205e50ef30bb08cb3e5 (patch) | |
tree | 33ca33f20795707b58b694fab16039d0c2c7374a /gcc/rust | |
parent | e00311aa9aabf447f27031cc5ffc114c5fbd8551 (diff) | |
download | gcc-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.in | 1 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-context.h | 5 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-expr.cc | 9 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-resolve-path.cc | 22 | ||||
-rw-r--r-- | gcc/rust/lang.opt | 12 | ||||
-rw-r--r-- | gcc/rust/lint/rust-lint-unused-var.cc | 98 | ||||
-rw-r--r-- | gcc/rust/lint/rust-lint-unused-var.h | 36 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-unused.h | 61 | ||||
-rw-r--r-- | gcc/rust/rust-gcc.cc | 20 | ||||
-rw-r--r-- | gcc/rust/rust-session-manager.cc | 29 |
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 (); } |