Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 49 additions & 37 deletions gcc/rust/checks/lints/rust-lint-scan-deadcode.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

#include "rust-hir-full-decls.h"
#include "rust-hir-map.h"
#include "rust-hir-visibility.h"
#include "rust-lint-marklive.h"
#include "rust-name-resolver.h"
#include "rust-diagnostics.h"
Expand All @@ -29,12 +30,13 @@ namespace Rust {
namespace Analysis {

// Scan item symbols and warn the symbol if it is not in the live_symbols set.
// There are three kinds of item we should handle in this pass.
// There are four kinds of item we should handle in this pass.
// 1. Function item
// 2. The function item in the impl block without trait
// 3. StructStruct, e.g., `Struct Foo{one: 1, two: 2}`. Furthermore, the unused
// struct fields will be warned too.
// 4. TupleStruct, e.g., `Struct Foo(i32, i32)`
// 5. Enum, e.g., `enum Foo { A, B }`
class ScanDeadcode : public MarkLiveBase
{
using Rust::Analysis::MarkLiveBase::visit;
Expand All @@ -48,13 +50,16 @@ class ScanDeadcode : public MarkLiveBase
it.get ()->accept_vis (sdc);
};

bool name_starts_with_underscore (const Identifier &identifier)
{
return identifier.as_string ().rfind ('_', 0) == 0;
}

void visit (HIR::Function &function) override
{
HirId hirId = function.get_mappings ().get_hirid ();
auto starts_with_underscore
= function.get_function_name ().as_string ().rfind ('_', 0) == 0;
if (should_warn (hirId) && !function.get_visibility ().is_public ()
&& !starts_with_underscore)
if (should_warn (hirId, function.get_function_name (),
function.get_visibility ()))
{
if (mappings.is_impl_item (hirId))
{
Expand All @@ -77,46 +82,48 @@ class ScanDeadcode : public MarkLiveBase
}
}

void visit (HIR::StructStruct &stct) override
void visit (HIR::StructStruct &strukt) override
{
HirId hirId = stct.get_mappings ().get_hirid ();
if (should_warn (hirId) && !stct.get_visibility ().is_public ())
HirId hirId = strukt.get_mappings ().get_hirid ();
if (should_warn (hirId, strukt.get_identifier (), strukt.get_visibility ()))
{
bool name_starts_underscore
= stct.get_identifier ().as_string ().at (0) == '_';
if (!name_starts_underscore)
rust_warning_at (stct.get_locus (), 0,
"struct is never constructed: %qs",
stct.get_identifier ().as_string ().c_str ());
rust_warning_at (strukt.get_locus (), 0,
"struct is never constructed: %qs",
strukt.get_identifier ().as_string ().c_str ());
}
else
else if (!name_starts_with_underscore (strukt.get_identifier ()))
{
// only warn the unused fields when in unwarned struct.
for (auto &field : stct.get_fields ())
// only warn the unused fields when in unwarned struct and if its name
// doesn't start with an underscore

for (auto &field : strukt.get_fields ())
{
HirId field_hir_id = field.get_mappings ().get_hirid ();
if (should_warn (field_hir_id)
&& !field.get_visibility ().is_public ()
&& field.get_field_name ().as_string ().at (0) != '_')
{
rust_warning_at (field.get_locus (), 0,
"field is never read: %qs",
field.get_field_name ().as_string ().c_str ());
}
if (should_warn (field_hir_id, field.get_field_name (),
field.get_visibility ()))
rust_warning_at (field.get_locus (), 0,
"field is never read: %qs",
field.get_field_name ().as_string ().c_str ());
}
}
}

void visit (HIR::TupleStruct &stct) override
void visit (HIR::TupleStruct &strukt) override
{
// only warn tuple struct unconstructed, and ignoring unused field
HirId hirId = stct.get_mappings ().get_hirid ();
if (should_warn (hirId) && !stct.get_visibility ().is_public ())
{
rust_warning_at (stct.get_locus (), 0,
"struct is never constructed: %qs",
stct.get_identifier ().as_string ().c_str ());
}
HirId hirId = strukt.get_mappings ().get_hirid ();
if (should_warn (hirId, strukt.get_identifier (), strukt.get_visibility ()))
rust_warning_at (strukt.get_locus (), 0,
"struct is never constructed: %qs",
strukt.get_identifier ().as_string ().c_str ());
}

void visit (HIR::Enum &enm) override
{
HirId hirId = enm.get_mappings ().get_hirid ();
if (should_warn (hirId, enm.get_identifier (), enm.get_visibility ()))
rust_warning_at (enm.get_locus (), 0, "enum is never used: %qs",
enm.get_identifier ().as_string ().c_str ());
}

void visit (HIR::ImplBlock &blc) override
Expand Down Expand Up @@ -145,11 +152,16 @@ class ScanDeadcode : public MarkLiveBase
: live_symbols (live_symbols), resolver (Resolver::Resolver::get ()),
mappings (Analysis::Mappings::get ()){};

bool should_warn (HirId hirId)
bool should_warn (HirId hir_id, const Identifier &identifier,
HIR::Visibility visibility)
{
// TODO: There are more condition to check if should warn, i.e visibility,
// attributes.
return live_symbols.find (hirId) == live_symbols.end ();
if (name_starts_with_underscore (identifier))
return false;

if (visibility.is_public ())
return false;

return live_symbols.find (hir_id) == live_symbols.end ();
}
};

Expand Down
12 changes: 7 additions & 5 deletions gcc/testsuite/rust/compile/derive-debug1.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#![feature(no_core)]
#![no_core]

#![feature(lang_items)]
#[lang = "sized"]
trait Sized {}
Expand Down Expand Up @@ -29,17 +28,20 @@ mod core {

#[derive(Debug)]
// { dg-warning "stub implementation" "" { target *-*-* } .-1 }
struct Foo { a: i32, b: i64 } // { dg-warning "is never constructed" }
struct Foo {
// { dg-warning "is never constructed" "" { target *-*-* } .-1 }
a: i32,
b: i64,
}

#[derive(Debug)]
// { dg-warning "stub implementation" "" { target *-*-* } .-1 }
struct Bar(i32, i32); // { dg-warning "is never constructed" }

#[derive(Debug)]
// { dg-warning "stub implementation" "" { target *-*-* } .-1 }
enum Baz {
pub enum Baz {
A,
B(i32),
C { a: i32 }
C { a: i32 },
}

4 changes: 2 additions & 2 deletions gcc/testsuite/rust/compile/derive-hash1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ struct Foo { // { dg-warning "never constructed" }
struct Bar(i32, i64); // { dg-warning "never constructed" }

#[derive(Hash)]
enum Baz {
pub enum Baz {
A,
B(i32),
C { a: i64 }
C { a: i64 },
}
5 changes: 2 additions & 3 deletions gcc/testsuite/rust/compile/derive_clone_enum1.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#![feature(no_core)]
#![no_core]

#![feature(lang_items)]

#[lang = "clone"]
Expand All @@ -15,7 +14,7 @@ impl Clone for i32 {
}

#[derive(Clone)]
enum AllIdentifiers {
pub enum AllIdentifiers {
A,
B
B,
}
5 changes: 2 additions & 3 deletions gcc/testsuite/rust/compile/derive_clone_enum2.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#![feature(no_core)]
#![no_core]

#![feature(lang_items)]

#[lang = "clone"]
Expand All @@ -15,7 +14,7 @@ impl Clone for i32 {
}

#[derive(Clone)]
enum TupleEnum {
pub enum TupleEnum {
A(i32),
B(i32, i32, i32)
B(i32, i32, i32),
}
5 changes: 2 additions & 3 deletions gcc/testsuite/rust/compile/derive_clone_enum3.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#![feature(no_core)]
#![no_core]

#![feature(lang_items)]

#[lang = "clone"]
Expand All @@ -15,7 +14,7 @@ impl Clone for i32 {
}

#[derive(Clone)]
enum StructEnum {
pub enum StructEnum {
A { i0: i32 },
B { i0: i32, i1: i32, i2: i32 }
B { i0: i32, i1: i32, i2: i32 },
}
4 changes: 2 additions & 2 deletions gcc/testsuite/rust/compile/enum_discriminant1.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#![feature(no_core)]
#![no_core]

enum Foo {
pub enum Foo {
Bar = 3 + 12,
}

fn test() -> Foo { // { dg-warning "function is never used" }
return Foo::Bar;
}
}
2 changes: 1 addition & 1 deletion gcc/testsuite/rust/compile/for-loop1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ mod option {
}

mod result {
enum Result<T, E> {
pub enum Result<T, E> {
Ok(T),
Err(E),
}
Expand Down
2 changes: 1 addition & 1 deletion gcc/testsuite/rust/compile/for-loop2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ mod option {
}

mod result {
enum Result<T, E> {
pub enum Result<T, E> {
Ok(T),
Err(E),
}
Expand Down
2 changes: 1 addition & 1 deletion gcc/testsuite/rust/compile/glob_import_enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use self::Ordering::*;
use Ordering::*;

enum Ordering {
pub enum Ordering {
A,
B,
}
Expand Down
4 changes: 2 additions & 2 deletions gcc/testsuite/rust/compile/if_let_expr_simple.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
#![feature(no_core)]
#![no_core]

enum MyOption {
pub enum MyOption {
Some(i32),
None,
}

pub fn toto(i : MyOption) -> i32 {
pub fn toto(i: MyOption) -> i32 {
if let MyOption::Some(v) = i {
v
} else {
Expand Down
3 changes: 1 addition & 2 deletions gcc/testsuite/rust/compile/issue-3382.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
#![feature(no_core)]
#![no_core]

#![feature(lang_items)]

#[lang = "sized"]
trait Sized {}

enum Result<T, E> {
pub enum Result<T, E> {
#[lang = "Ok"]
Ok(T),
#[lang = "Err"]
Expand Down
4 changes: 2 additions & 2 deletions gcc/testsuite/rust/compile/issue-3550.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
#![no_core]

#[cfg_attr(not(wrong = "32"), repr(i32))]
enum Eu64 {
pub enum Eu64 {
Au64 = 0,
}
}
8 changes: 4 additions & 4 deletions gcc/testsuite/rust/compile/issue-3597.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#![feature(no_core)]
#![no_core]

enum E {
pub enum E {
A = {
enum F { }
pub enum F {}
0
}
},
}

fn main() {}
fn main() {}
4 changes: 2 additions & 2 deletions gcc/testsuite/rust/compile/issue-3605.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#![feature(no_core)]
#![no_core]

enum Foo<'a> {}
pub enum Foo<'a> {}

enum Bar<'a> {
pub enum Bar<'a> {
in_band_def_explicit_impl(Foo<'a>),
}
4 changes: 2 additions & 2 deletions gcc/testsuite/rust/compile/issue-3651.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#![feature(no_core)]
#![no_core]
enum E {
pub enum E {
A = {
enum F {
Ai32 = -1,
Expand All @@ -9,4 +9,4 @@ enum E {
},
}

fn main() {}
fn main() {}
4 changes: 2 additions & 2 deletions gcc/testsuite/rust/compile/issue-3670.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#![feature(no_core)]
#![no_core]
enum E {
pub enum E {
A = {
enum Foo {
pub enum Foo {
Bar(isize),
Baz,
}
Expand Down
13 changes: 13 additions & 0 deletions gcc/testsuite/rust/compile/issue-4367.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#![feature(no_core)]
#![no_core]

enum Foo {
// { dg-warning "enum is never used" "" { target *-*-* } .-1 }
A,
B,
}

enum _Bar {
A,
B,
}
3 changes: 1 addition & 2 deletions gcc/testsuite/rust/compile/issue-850.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#![feature(no_core)]
#![no_core]

#![feature(lang_items)]
#[lang = "sized"]
pub trait Sized {}
Expand All @@ -10,7 +9,7 @@ extern "C" {
}

mod option {
enum Option<T> {
pub enum Option<T> {
#[lang = "None"]
None,
#[lang = "Some"]
Expand Down
Loading
Loading