parent
7f676b8699
commit
f422de1e85
@ -45,6 +45,7 @@
|
|||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
use syntax::parse::token;
|
use syntax::parse::token;
|
||||||
use syntax::{ast, ast_util, visit};
|
use syntax::{ast, ast_util, visit};
|
||||||
|
use syntax::visit::Visitor;
|
||||||
|
|
||||||
declare_lint!(WHILE_TRUE, Warn,
|
declare_lint!(WHILE_TRUE, Warn,
|
||||||
"suggest using `loop { }` instead of `while true { }`")
|
"suggest using `loop { }` instead of `while true { }`")
|
||||||
@ -339,6 +340,51 @@ fn is_comparison(binop: ast::BinOp) -> bool {
|
|||||||
declare_lint!(CTYPES, Warn,
|
declare_lint!(CTYPES, Warn,
|
||||||
"proper use of libc types in foreign modules")
|
"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;
|
pub struct CTypes;
|
||||||
|
|
||||||
impl LintPass for CTypes {
|
impl LintPass for CTypes {
|
||||||
@ -348,38 +394,8 @@ fn get_lints(&self) -> LintArray {
|
|||||||
|
|
||||||
fn check_item(&mut self, cx: &Context, it: &ast::Item) {
|
fn check_item(&mut self, cx: &Context, it: &ast::Item) {
|
||||||
fn check_ty(cx: &Context, ty: &ast::Ty) {
|
fn check_ty(cx: &Context, ty: &ast::Ty) {
|
||||||
match ty.node {
|
let mut vis = CTypesVisitor { cx: cx };
|
||||||
ast::TyPath(_, _, id) => {
|
vis.visit_ty(ty, ());
|
||||||
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) }
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_foreign_fn(cx: &Context, decl: &ast::FnDecl) {
|
fn check_foreign_fn(cx: &Context, decl: &ast::FnDecl) {
|
||||||
@ -398,7 +414,7 @@ fn check_foreign_fn(cx: &Context, decl: &ast::FnDecl) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {/* nothing to do */ }
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -493,7 +509,7 @@ struct RawPtrDerivingVisitor<'a> {
|
|||||||
cx: &'a Context<'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, _: ()) {
|
fn visit_ty(&mut self, ty: &ast::Ty, _: ()) {
|
||||||
static MSG: &'static str = "use of `#[deriving]` with a raw pointer";
|
static MSG: &'static str = "use of `#[deriving]` with a raw pointer";
|
||||||
match ty.node {
|
match ty.node {
|
||||||
|
18
src/test/compile-fail/issue-16250.rs
Normal file
18
src/test/compile-fail/issue-16250.rs
Normal file
@ -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() {
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user