From 44ff72195e0a5a3b0bfd4b8b3cef919cfa9661ef Mon Sep 17 00:00:00 2001 From: Richo Healey Date: Wed, 21 Jan 2015 12:07:03 -0800 Subject: [PATCH 1/3] lint: warn about #[no_mangle] fns that aren't exported The usecase is that functions made visible to systems outside of the rust ecosystem require the symbol to be visible. --- src/librustc/lint/builtin.rs | 29 +++++++++++++++++++++++++++++ src/librustc/lint/context.rs | 1 + 2 files changed, 30 insertions(+) diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index f13814527cd..bef9e6be8d9 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -2036,6 +2036,35 @@ impl LintPass for HardwiredLints { } } +declare_lint! { + PRIVATE_NO_MANGLE_FNS, + Warn, + "functions marked #[no_mangle] should be exported" +} + +#[derive(Copy)] +pub struct PrivateNoMangleFns; + +impl LintPass for PrivateNoMangleFns { + fn get_lints(&self) -> LintArray { + lint_array!(PRIVATE_NO_MANGLE_FNS) + } + + fn check_item(&mut self, cx: &Context, it: &ast::Item) { + match it.node { + ast::ItemFn(..) => { + if attr::contains_name(it.attrs.as_slice(), "no_mangle") && + !cx.exported_items.contains(&it.id) { + let msg = format!("function {} is marked #[no_mangle], but not exported", + it.ident); + cx.span_lint(PRIVATE_NO_MANGLE_FNS, it.span, msg.as_slice()); + } + }, + _ => {}, + } + } +} + /// Forbids using the `#[feature(...)]` attribute #[derive(Copy)] pub struct UnstableFeatures; diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index f57d7956edf..76f874f2428 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -213,6 +213,7 @@ impl LintStore { UnstableFeatures, Stability, UnconditionalRecursion, + PrivateNoMangleFns, ); add_builtin_with_new!(sess, From d2ab7d3ea8ff80089c9f5d8a3db37de0000eb246 Mon Sep 17 00:00:00 2001 From: Richo Healey Date: Tue, 27 Jan 2015 22:24:17 -0800 Subject: [PATCH 2/3] rt: allow unexported functions rust_panic is unexported, however the metadata exported will usually include it for attaching breakpoints. --- src/libstd/rt/unwind.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/libstd/rt/unwind.rs b/src/libstd/rt/unwind.rs index 18298f1c7f4..dd4d3bbc5fc 100644 --- a/src/libstd/rt/unwind.rs +++ b/src/libstd/rt/unwind.rs @@ -160,6 +160,7 @@ pub fn panicking() -> bool { // An uninlined, unmangled function upon which to slap yer breakpoints #[inline(never)] #[no_mangle] +#[allow(private_no_mangle_fns)] fn rust_panic(cause: Box) -> ! { rtdebug!("begin_unwind()"); @@ -237,6 +238,7 @@ pub mod eabi { #[lang="eh_personality"] #[no_mangle] // referenced from rust_try.ll + #[allow(private_no_mangle_fns)] extern fn rust_eh_personality( version: c_int, actions: uw::_Unwind_Action, @@ -252,6 +254,7 @@ pub mod eabi { } #[no_mangle] // referenced from rust_try.ll + #[allow(unexported_no_mangle)] pub extern "C" fn rust_eh_personality_catch( _version: c_int, actions: uw::_Unwind_Action, @@ -290,6 +293,7 @@ pub mod eabi { #[lang="eh_personality"] #[no_mangle] // referenced from rust_try.ll + #[allow(unexported_no_mangle)] pub extern "C" fn rust_eh_personality( version: c_int, actions: uw::_Unwind_Action, @@ -305,6 +309,7 @@ pub mod eabi { } #[no_mangle] // referenced from rust_try.ll + #[allow(unexported_no_mangle)] pub extern "C" fn rust_eh_personality_catch( _version: c_int, actions: uw::_Unwind_Action, @@ -343,6 +348,7 @@ pub mod eabi { #[lang="eh_personality"] #[no_mangle] // referenced from rust_try.ll + #[allow(unexported_no_mangle)] extern "C" fn rust_eh_personality( state: uw::_Unwind_State, ue_header: *mut uw::_Unwind_Exception, @@ -355,6 +361,7 @@ pub mod eabi { } #[no_mangle] // referenced from rust_try.ll + #[allow(unexported_no_mangle)] pub extern "C" fn rust_eh_personality_catch( state: uw::_Unwind_State, _ue_header: *mut uw::_Unwind_Exception, @@ -432,6 +439,7 @@ pub mod eabi { #[lang="eh_personality"] #[no_mangle] // referenced from rust_try.ll + #[allow(unexported_no_mangle)] extern "C" fn rust_eh_personality( exceptionRecord: *mut EXCEPTION_RECORD, establisherFrame: *mut c_void, @@ -446,6 +454,7 @@ pub mod eabi { } #[no_mangle] // referenced from rust_try.ll + #[allow(unexported_no_mangle)] pub extern "C" fn rust_eh_personality_catch( exceptionRecord: *mut EXCEPTION_RECORD, establisherFrame: *mut c_void, From ff25fd660ac7240f4c8379e74108a462a9aaba77 Mon Sep 17 00:00:00 2001 From: Richo Healey Date: Wed, 28 Jan 2015 23:21:56 -0800 Subject: [PATCH 3/3] lint: Add test for no_mangle --- src/libstd/rt/unwind.rs | 10 +++----- .../compile-fail/lint-unexported-no-mangle.rs | 25 +++++++++++++++++++ 2 files changed, 28 insertions(+), 7 deletions(-) create mode 100644 src/test/compile-fail/lint-unexported-no-mangle.rs diff --git a/src/libstd/rt/unwind.rs b/src/libstd/rt/unwind.rs index dd4d3bbc5fc..757aecaaaff 100644 --- a/src/libstd/rt/unwind.rs +++ b/src/libstd/rt/unwind.rs @@ -254,7 +254,6 @@ pub mod eabi { } #[no_mangle] // referenced from rust_try.ll - #[allow(unexported_no_mangle)] pub extern "C" fn rust_eh_personality_catch( _version: c_int, actions: uw::_Unwind_Action, @@ -293,7 +292,7 @@ pub mod eabi { #[lang="eh_personality"] #[no_mangle] // referenced from rust_try.ll - #[allow(unexported_no_mangle)] + #[allow(private_no_mangle_fns)] pub extern "C" fn rust_eh_personality( version: c_int, actions: uw::_Unwind_Action, @@ -309,7 +308,6 @@ pub mod eabi { } #[no_mangle] // referenced from rust_try.ll - #[allow(unexported_no_mangle)] pub extern "C" fn rust_eh_personality_catch( _version: c_int, actions: uw::_Unwind_Action, @@ -348,7 +346,7 @@ pub mod eabi { #[lang="eh_personality"] #[no_mangle] // referenced from rust_try.ll - #[allow(unexported_no_mangle)] + #[allow(private_no_mangle_fns)] extern "C" fn rust_eh_personality( state: uw::_Unwind_State, ue_header: *mut uw::_Unwind_Exception, @@ -361,7 +359,6 @@ pub mod eabi { } #[no_mangle] // referenced from rust_try.ll - #[allow(unexported_no_mangle)] pub extern "C" fn rust_eh_personality_catch( state: uw::_Unwind_State, _ue_header: *mut uw::_Unwind_Exception, @@ -439,7 +436,7 @@ pub mod eabi { #[lang="eh_personality"] #[no_mangle] // referenced from rust_try.ll - #[allow(unexported_no_mangle)] + #[allow(private_no_mangle_fns)] extern "C" fn rust_eh_personality( exceptionRecord: *mut EXCEPTION_RECORD, establisherFrame: *mut c_void, @@ -454,7 +451,6 @@ pub mod eabi { } #[no_mangle] // referenced from rust_try.ll - #[allow(unexported_no_mangle)] pub extern "C" fn rust_eh_personality_catch( exceptionRecord: *mut EXCEPTION_RECORD, establisherFrame: *mut c_void, diff --git a/src/test/compile-fail/lint-unexported-no-mangle.rs b/src/test/compile-fail/lint-unexported-no-mangle.rs new file mode 100644 index 00000000000..3227a78c2ef --- /dev/null +++ b/src/test/compile-fail/lint-unexported-no-mangle.rs @@ -0,0 +1,25 @@ +// Copyright 2015 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. + +// compile-flags:-F private_no_mangle_fns + +// FIXME(#19495) no_mangle'ing main ICE's. +#[no_mangle] +fn foo() { //~ ERROR function foo is marked #[no_mangle], but not exported +} + +#[no_mangle] +pub fn bar() { +} + +fn main() { + foo(); + bar(); +}