From 5744556782d072076ba426627fd5594c3c9db174 Mon Sep 17 00:00:00 2001 From: Michael Darakananda Date: Sun, 23 Mar 2014 13:35:52 -0400 Subject: [PATCH] Added lint for #[deriving] structs and enums with unsafe pointers. #13032. --- src/librustc/middle/lint.rs | 41 +++++++++++++++++++ src/librustc/middle/ty.rs | 1 + .../compile-fail/lint-raw-ptr-deriving.rs | 35 ++++++++++++++++ 3 files changed, 77 insertions(+) create mode 100644 src/test/compile-fail/lint-raw-ptr-deriving.rs diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index 8c20cf39b49fe..a0f52021b6e4a 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -115,6 +115,8 @@ pub enum Lint { DeprecatedOwnedVector, Warnings, + + RawPointerDeriving, } pub fn level_to_str(lv: level) -> &'static str { @@ -406,6 +408,13 @@ static lint_table: &'static [(&'static str, LintSpec)] = &[ desc: "use of a `~[T]` vector", default: allow, }), + + ("raw_pointer_deriving", + LintSpec { + lint: RawPointerDeriving, + desc: "uses of #[deriving] with raw pointers are rarely correct", + default: warn, + }), ]; /* @@ -959,6 +968,37 @@ fn check_heap_item(cx: &Context, it: &ast::Item) { } } +struct RawPtrDerivingVisitor<'a> { + cx: &'a Context<'a> +} + +impl<'a> Visitor<()> for RawPtrDerivingVisitor<'a> { + fn visit_ty(&mut self, ty: &ast::Ty, _: ()) { + static MSG: &'static str = "use of `#[deriving]` with a raw pointer"; + match ty.node { + ast::TyPtr(..) => self.cx.span_lint(RawPointerDeriving, ty.span, MSG), + _ => {} + } + visit::walk_ty(self, ty, ()); + } + // explicit override to a no-op to reduce code bloat + fn visit_expr(&mut self, _: &ast::Expr, _: ()) {} + fn visit_block(&mut self, _: &ast::Block, _: ()) {} +} + +fn check_raw_ptr_deriving(cx: &Context, item: &ast::Item) { + if !attr::contains_name(item.attrs.as_slice(), "deriving") { + return + } + match item.node { + ast::ItemStruct(..) | ast::ItemEnum(..) => { + let mut visitor = RawPtrDerivingVisitor { cx: cx }; + visit::walk_item(&mut visitor, item, ()); + } + _ => {} + } +} + static crate_attrs: &'static [&'static str] = &[ "crate_type", "feature", "no_start", "no_main", "no_std", "crate_id", "desc", "comment", "license", "copyright", // not used in rustc now @@ -1585,6 +1625,7 @@ impl<'a> Visitor<()> for Context<'a> { check_heap_item(cx, it); check_missing_doc_item(cx, it); check_attrs_usage(cx, it.attrs.as_slice()); + check_raw_ptr_deriving(cx, it); cx.visit_ids(|v| v.visit_item(it, ())); diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index cdc74f37327c6..7d6f44494cb13 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -384,6 +384,7 @@ pub struct t_box_ { // alive, and using ty::get is unsafe when the ctxt is no longer alive. enum t_opaque {} +#[allow(raw_pointer_deriving)] #[deriving(Clone, Eq, TotalEq, Hash)] pub struct t { priv inner: *t_opaque } diff --git a/src/test/compile-fail/lint-raw-ptr-deriving.rs b/src/test/compile-fail/lint-raw-ptr-deriving.rs new file mode 100644 index 0000000000000..f58ccf2d498a2 --- /dev/null +++ b/src/test/compile-fail/lint-raw-ptr-deriving.rs @@ -0,0 +1,35 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[feature(struct_variant)]; +#[allow(dead_code)]; +#[deny(raw_pointer_deriving)]; + +#[deriving(Clone)] +struct Foo { + x: *int //~ ERROR use of `#[deriving]` with a raw pointer +} + +#[deriving(Clone)] +struct Bar(*mut int); //~ ERROR use of `#[deriving]` with a raw pointer + +#[deriving(Clone)] +enum Baz { + A(*int), //~ ERROR use of `#[deriving]` with a raw pointer + B { x: *mut int } //~ ERROR use of `#[deriving]` with a raw pointer +} + +#[deriving(Clone)] +struct Buzz { + x: (*int, //~ ERROR use of `#[deriving]` with a raw pointer + *uint) //~ ERROR use of `#[deriving]` with a raw pointer +} + +fn main() {}