about summary refs log tree commit diff
diff options
context:
space:
mode:
authorKeegan McAllister <kmcallister@mozilla.com>2014-09-03 19:03:25 -0700
committerKeegan McAllister <kmcallister@mozilla.com>2014-09-03 19:28:37 -0700
commitf422de1e85e87db51bfb61655da3faa331fbd91a (patch)
tree328fc0843e05d9f5ee776cc642f586db32e847d4
parent7f676b86994edcd6adf27018a5d18e957c9390ab (diff)
downloadrust-f422de1e85e87db51bfb61655da3faa331fbd91a.tar.gz
rust-f422de1e85e87db51bfb61655da3faa331fbd91a.zip
Use a visitor to look for non-FFI-safe types
Fixes #16250.
-rw-r--r--src/librustc/lint/builtin.rs96
-rw-r--r--src/test/compile-fail/issue-16250.rs18
2 files changed, 74 insertions, 40 deletions
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 4b43c685fa9..355cd8203c5 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -45,6 +45,7 @@ use syntax::attr;
 use syntax::codemap::Span;
 use syntax::parse::token;
 use syntax::{ast, ast_util, visit};
+use syntax::visit::Visitor;
 
 declare_lint!(WHILE_TRUE, Warn,
               "suggest using `loop { }` instead of `while true { }`")
@@ -339,6 +340,51 @@ impl LintPass for TypeLimits {
 declare_lint!(CTYPES, Warn,
               "proper use of libc types in foreign modules")
 
+struct CTypesVisitor<'a> {
+    cx: &'a Context<'a>
+}
+
+impl<'a> CTypesVisitor<'a> {
+    fn check_def(&mut self, sp: Span, ty_id: ast::NodeId, path_id: ast::NodeId) {
+        match self.cx.tcx.def_map.borrow().get_copy(&path_id) {
+            def::DefPrimTy(ast::TyInt(ast::TyI)) => {
+                self.cx.span_lint(CTYPES, sp,
+                                  "found rust type `int` in foreign module, while \
+                                   libc::c_int or libc::c_long should be used");
+            }
+            def::DefPrimTy(ast::TyUint(ast::TyU)) => {
+                self.cx.span_lint(CTYPES, sp,
+                                  "found rust type `uint` in foreign module, while \
+                                   libc::c_uint or libc::c_ulong should be used");
+            }
+            def::DefTy(..) => {
+                let tty = match self.cx.tcx.ast_ty_to_ty_cache.borrow().find(&ty_id) {
+                    Some(&ty::atttce_resolved(t)) => t,
+                    _ => fail!("ast_ty_to_ty_cache was incomplete after typeck!")
+                };
+
+                if !ty::is_ffi_safe(self.cx.tcx, tty) {
+                    self.cx.span_lint(CTYPES, sp,
+                                      "found type without foreign-function-safe
+                                      representation annotation in foreign module, consider \
+                                      adding a #[repr(...)] attribute to the type");
+                }
+            }
+            _ => ()
+        }
+    }
+}
+
+impl<'a> Visitor<()> for CTypesVisitor<'a> {
+    fn visit_ty(&mut self, ty: &ast::Ty, _: ()) {
+        match ty.node {
+            ast::TyPath(_, _, id) => self.check_def(ty.span, ty.id, id),
+            _ => (),
+        }
+        visit::walk_ty(self, ty, ());
+    }
+}
+
 pub struct CTypes;
 
 impl LintPass for CTypes {
@@ -348,38 +394,8 @@ impl LintPass for CTypes {
 
     fn check_item(&mut self, cx: &Context, it: &ast::Item) {
         fn check_ty(cx: &Context, ty: &ast::Ty) {
-            match ty.node {
-                ast::TyPath(_, _, id) => {
-                    match cx.tcx.def_map.borrow().get_copy(&id) {
-                        def::DefPrimTy(ast::TyInt(ast::TyI)) => {
-                            cx.span_lint(CTYPES, ty.span,
-                                         "found rust type `int` in foreign module, while \
-                                          libc::c_int or libc::c_long should be used");
-                        }
-                        def::DefPrimTy(ast::TyUint(ast::TyU)) => {
-                            cx.span_lint(CTYPES, ty.span,
-                                         "found rust type `uint` in foreign module, while \
-                                          libc::c_uint or libc::c_ulong should be used");
-                        }
-                        def::DefTy(..) => {
-                            let tty = match cx.tcx.ast_ty_to_ty_cache.borrow().find(&ty.id) {
-                                Some(&ty::atttce_resolved(t)) => t,
-                                _ => fail!("ast_ty_to_ty_cache was incomplete after typeck!")
-                            };
-
-                            if !ty::is_ffi_safe(cx.tcx, tty) {
-                                cx.span_lint(CTYPES, ty.span,
-                                             "found type without foreign-function-safe
-                                             representation annotation in foreign module, consider \
-                                             adding a #[repr(...)] attribute to the type");
-                            }
-                        }
-                        _ => ()
-                    }
-                }
-                ast::TyPtr(ref mt) => { check_ty(cx, &*mt.ty) }
-                _ => {}
-            }
+            let mut vis = CTypesVisitor { cx: cx };
+            vis.visit_ty(ty, ());
         }
 
         fn check_foreign_fn(cx: &Context, decl: &ast::FnDecl) {
@@ -390,15 +406,15 @@ impl LintPass for CTypes {
         }
 
         match it.node {
-          ast::ItemForeignMod(ref nmod) if nmod.abi != abi::RustIntrinsic => {
-            for ni in nmod.items.iter() {
-                match ni.node {
-                    ast::ForeignItemFn(decl, _) => check_foreign_fn(cx, &*decl),
-                    ast::ForeignItemStatic(t, _) => check_ty(cx, &*t)
+            ast::ItemForeignMod(ref nmod) if nmod.abi != abi::RustIntrinsic => {
+                for ni in nmod.items.iter() {
+                    match ni.node {
+                        ast::ForeignItemFn(decl, _) => check_foreign_fn(cx, &*decl),
+                        ast::ForeignItemStatic(t, _) => check_ty(cx, &*t)
+                    }
                 }
             }
-          }
-          _ => {/* nothing to do */ }
+            _ => (),
         }
     }
 }
@@ -493,7 +509,7 @@ struct RawPtrDerivingVisitor<'a> {
     cx: &'a Context<'a>
 }
 
-impl<'a> visit::Visitor<()> for RawPtrDerivingVisitor<'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 {
diff --git a/src/test/compile-fail/issue-16250.rs b/src/test/compile-fail/issue-16250.rs
new file mode 100644
index 00000000000..883e79d75e0
--- /dev/null
+++ b/src/test/compile-fail/issue-16250.rs
@@ -0,0 +1,18 @@
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![deny(warnings)]
+
+extern {
+    pub fn foo(x: (int)); //~ ERROR found rust type `int` in foreign module
+}
+
+fn main() {
+}