Auto merge of #76219 - Mark-Simulacrum:extern-require-abi, r=estebank

Add allow-by-default lint on implicit ABI in extern function pointers and items

This adds a new lint, missing_abi, which lints on omitted ABIs on extern blocks, function declarations, and function pointers.

It is currently not emitting the best possible diagnostics -- we need to track the span of "extern" at least or do some heuristic searching based on the available spans -- but seems good enough for an initial pass than can be expanded in future PRs.

This is a pretty large PR, but mostly due to updating a large number of tests to include ABIs; I can split that into a separate PR if it would be helpful, but test updates are already in dedicated commits.
This commit is contained in:
bors 2021-01-13 13:56:15 +00:00
commit fd2df74902
368 changed files with 1235 additions and 1116 deletions

View File

@ -3896,6 +3896,7 @@ dependencies = [
"rustc_macros",
"rustc_serialize",
"rustc_span",
"rustc_target",
"tracing",
]

View File

@ -310,19 +310,24 @@ impl<'hir> LoweringContext<'_, 'hir> {
);
let sig = hir::FnSig {
decl,
header: this.lower_fn_header(header),
header: this.lower_fn_header(header, fn_sig_span, id),
span: fn_sig_span,
};
hir::ItemKind::Fn(sig, generics, body_id)
})
}
ItemKind::Mod(ref m) => hir::ItemKind::Mod(self.lower_mod(m)),
ItemKind::ForeignMod(ref fm) => hir::ItemKind::ForeignMod {
abi: fm.abi.map_or(abi::Abi::C, |abi| self.lower_abi(abi)),
items: self
.arena
.alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))),
},
ItemKind::ForeignMod(ref fm) => {
if fm.abi.is_none() {
self.maybe_lint_missing_abi(span, id, abi::Abi::C);
}
hir::ItemKind::ForeignMod {
abi: fm.abi.map_or(abi::Abi::C, |abi| self.lower_abi(abi)),
items: self
.arena
.alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))),
}
}
ItemKind::GlobalAsm(ref ga) => hir::ItemKind::GlobalAsm(self.lower_global_asm(ga)),
ItemKind::TyAlias(_, ref gen, _, Some(ref ty)) => {
// We lower
@ -801,13 +806,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
AssocItemKind::Fn(_, ref sig, ref generics, None) => {
let names = self.lower_fn_params_to_names(&sig.decl);
let (generics, sig) =
self.lower_method_sig(generics, sig, trait_item_def_id, false, None);
self.lower_method_sig(generics, sig, trait_item_def_id, false, None, i.id);
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)))
}
AssocItemKind::Fn(_, ref sig, ref generics, Some(ref body)) => {
let body_id = self.lower_fn_body_block(i.span, &sig.decl, Some(body));
let (generics, sig) =
self.lower_method_sig(generics, sig, trait_item_def_id, false, None);
self.lower_method_sig(generics, sig, trait_item_def_id, false, None, i.id);
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)))
}
AssocItemKind::TyAlias(_, ref generics, ref bounds, ref default) => {
@ -877,6 +882,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
impl_item_def_id,
impl_trait_return_allow,
asyncness.opt_return_id(),
i.id,
);
(generics, hir::ImplItemKind::Fn(sig, body_id))
@ -1270,8 +1276,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn_def_id: LocalDefId,
impl_trait_return_allow: bool,
is_async: Option<NodeId>,
id: NodeId,
) -> (hir::Generics<'hir>, hir::FnSig<'hir>) {
let header = self.lower_fn_header(sig.header);
let header = self.lower_fn_header(sig.header, sig.span, id);
let (generics, decl) = self.add_in_band_defs(
generics,
fn_def_id,
@ -1288,12 +1295,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
(generics, hir::FnSig { header, decl, span: sig.span })
}
fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader {
fn lower_fn_header(&mut self, h: FnHeader, span: Span, id: NodeId) -> hir::FnHeader {
hir::FnHeader {
unsafety: self.lower_unsafety(h.unsafety),
asyncness: self.lower_asyncness(h.asyncness),
constness: self.lower_constness(h.constness),
abi: self.lower_extern(h.ext),
abi: self.lower_extern(h.ext, span, id),
}
}
@ -1304,10 +1311,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
})
}
pub(super) fn lower_extern(&mut self, ext: Extern) -> abi::Abi {
pub(super) fn lower_extern(&mut self, ext: Extern, span: Span, id: NodeId) -> abi::Abi {
match ext {
Extern::None => abi::Abi::Rust,
Extern::Implicit => abi::Abi::C,
Extern::Implicit => {
self.maybe_lint_missing_abi(span, id, abi::Abi::C);
abi::Abi::C
}
Extern::Explicit(abi) => self.lower_abi(abi),
}
}

View File

@ -53,13 +53,15 @@ use rustc_hir::definitions::{DefKey, DefPathData, Definitions};
use rustc_hir::intravisit;
use rustc_hir::{ConstArg, GenericArg, ParamName};
use rustc_index::vec::{Idx, IndexVec};
use rustc_session::lint::{builtin::BARE_TRAIT_OBJECTS, BuiltinLintDiagnostics, LintBuffer};
use rustc_session::lint::builtin::{BARE_TRAIT_OBJECTS, MISSING_ABI};
use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
use rustc_session::parse::ParseSess;
use rustc_session::Session;
use rustc_span::hygiene::ExpnId;
use rustc_span::source_map::{respan, DesugaringKind};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::Span;
use rustc_target::spec::abi::Abi;
use smallvec::{smallvec, SmallVec};
use std::collections::BTreeMap;
@ -1288,6 +1290,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
TyKind::BareFn(ref f) => self.with_in_scope_lifetime_defs(&f.generic_params, |this| {
this.with_anonymous_lifetime_mode(AnonymousLifetimeMode::PassThrough, |this| {
let span = this.sess.source_map().next_point(t.span.shrink_to_lo());
hir::TyKind::BareFn(this.arena.alloc(hir::BareFnTy {
generic_params: this.lower_generic_params(
&f.generic_params,
@ -1295,7 +1298,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
ImplTraitContext::disallowed(),
),
unsafety: this.lower_unsafety(f.unsafety),
abi: this.lower_extern(f.ext),
abi: this.lower_extern(f.ext, span, t.id),
decl: this.lower_fn_decl(&f.decl, None, false, None),
param_names: this.lower_fn_params_to_names(&f.decl),
}))
@ -2777,6 +2780,26 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
)
}
}
fn maybe_lint_missing_abi(&mut self, span: Span, id: NodeId, default: Abi) {
// FIXME(davidtwco): This is a hack to detect macros which produce spans of the
// call site which do not have a macro backtrace. See #61963.
let is_macro_callsite = self
.sess
.source_map()
.span_to_snippet(span)
.map(|snippet| snippet.starts_with("#["))
.unwrap_or(true);
if !is_macro_callsite {
self.resolver.lint_buffer().buffer_lint_with_diagnostic(
MISSING_ABI,
id,
span,
"extern declarations without an explicit ABI are deprecated",
BuiltinLintDiagnostics::MissingAbi(span, default),
)
}
}
}
fn body_ids(bodies: &BTreeMap<hir::BodyId, hir::Body<'_>>) -> Vec<hir::BodyId> {

View File

@ -3,13 +3,13 @@ You cannot use type or const parameters on foreign items.
Example of erroneous code:
```compile_fail,E0044
extern { fn some_func<T>(x: T); }
extern "C" { fn some_func<T>(x: T); }
```
To fix this, replace the generic parameter with the specializations that you
need:
```
extern { fn some_func_i32(x: i32); }
extern { fn some_func_i64(x: i64); }
extern "C" { fn some_func_i32(x: i32); }
extern "C" { fn some_func_i64(x: i64); }
```

View File

@ -3,7 +3,7 @@ A pattern was declared as an argument in a foreign function declaration.
Erroneous code example:
```compile_fail,E0130
extern {
extern "C" {
fn foo((a, b): (u32, u32)); // error: patterns aren't allowed in foreign
// function declarations
}
@ -17,7 +17,7 @@ struct SomeStruct {
b: u32,
}
extern {
extern "C" {
fn foo(s: SomeStruct); // ok!
}
```
@ -25,7 +25,7 @@ extern {
Or:
```
extern {
extern "C" {
fn foo(a: (u32, u32)); // ok!
}
```

View File

@ -3,7 +3,7 @@ A link name was given with an empty name.
Erroneous code example:
```compile_fail,E0454
#[link(name = "")] extern {}
#[link(name = "")] extern "C" {}
// error: `#[link(name = "")]` given with empty name
```
@ -11,5 +11,5 @@ The rust compiler cannot link to an external library if you don't give it its
name. Example:
```no_run
#[link(name = "some_lib")] extern {} // ok!
#[link(name = "some_lib")] extern "C" {} // ok!
```

View File

@ -4,7 +4,7 @@ as frameworks are specific to that operating system.
Erroneous code example:
```ignore (should-compile_fail-but-cannot-doctest-conditionally-without-macos)
#[link(name = "FooCoreServices", kind = "framework")] extern {}
#[link(name = "FooCoreServices", kind = "framework")] extern "C" {}
// OS used to compile is Linux for example
```
@ -12,7 +12,7 @@ To solve this error you can use conditional compilation:
```
#[cfg_attr(target="macos", link(name = "FooCoreServices", kind = "framework"))]
extern {}
extern "C" {}
```
Learn more in the [Conditional Compilation][conditional-compilation] section

View File

@ -3,7 +3,7 @@ An unknown "kind" was specified for a link attribute.
Erroneous code example:
```compile_fail,E0458
#[link(kind = "wonderful_unicorn")] extern {}
#[link(kind = "wonderful_unicorn")] extern "C" {}
// error: unknown kind: `wonderful_unicorn`
```

View File

@ -3,7 +3,7 @@ A link was used without a name parameter.
Erroneous code example:
```compile_fail,E0459
#[link(kind = "dylib")] extern {}
#[link(kind = "dylib")] extern "C" {}
// error: `#[link(...)]` specified without `name = "foo"`
```
@ -11,5 +11,5 @@ Please add the name parameter to allow the rust compiler to find the library
you want. Example:
```no_run
#[link(kind = "dylib", name = "some_lib")] extern {} // ok!
#[link(kind = "dylib", name = "some_lib")] extern "C" {} // ok!
```

View File

@ -3,7 +3,7 @@ Attempted to pass an invalid type of variable into a variadic function.
Erroneous code example:
```compile_fail,E0617
extern {
extern "C" {
fn printf(c: *const i8, ...);
}
@ -21,7 +21,7 @@ to import from `std::os::raw`).
In this case, `c_double` has the same size as `f64` so we can use it directly:
```no_run
# extern {
# extern "C" {
# fn printf(c: *const i8, ...);
# }
unsafe {

View File

@ -6,7 +6,7 @@ Erroneous code example:
#![feature(unwind_attributes)]
#[unwind()] // error: expected one argument
pub extern fn something() {}
pub extern "C" fn something() {}
fn main() {}
```

View File

@ -18,7 +18,7 @@ the function inside of an `extern` block.
```
#![feature(ffi_returns_twice)]
extern {
extern "C" {
#[ffi_returns_twice] // ok!
pub fn foo();
}

View File

@ -600,6 +600,10 @@ pub trait LintContext: Sized {
BuiltinLintDiagnostics::PatternsInFnsWithoutBody(span, ident) => {
db.span_suggestion(span, "remove `mut` from the parameter", ident.to_string(), Applicability::MachineApplicable);
}
BuiltinLintDiagnostics::MissingAbi(span, default_abi) => {
db.span_label(span, "ABI should be specified here");
db.help(&format!("the default ABI is {}", default_abi.name()));
}
}
// Rewrap `db`, and pass control to the user.
decorate(LintDiagnosticBuilder::new(db));

View File

@ -11,3 +11,4 @@ rustc_data_structures = { path = "../rustc_data_structures" }
rustc_span = { path = "../rustc_span" }
rustc_serialize = { path = "../rustc_serialize" }
rustc_macros = { path = "../rustc_macros" }
rustc_target = { path = "../rustc_target" }

View File

@ -2917,6 +2917,7 @@ declare_lint_pass! {
FUNCTION_ITEM_REFERENCES,
USELESS_DEPRECATED,
UNSUPPORTED_NAKED_FUNCTIONS,
MISSING_ABI,
]
}
@ -2944,3 +2945,28 @@ declare_lint! {
}
declare_lint_pass!(UnusedDocComment => [UNUSED_DOC_COMMENTS]);
declare_lint! {
/// The `missing_abi` lint detects cases where the ABI is omitted from
/// extern declarations.
///
/// ### Example
///
/// ```rust,compile_fail
/// #![deny(missing_abi)]
///
/// extern fn foo() {}
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// Historically, Rust implicitly selected C as the ABI for extern
/// declarations. We expect to add new ABIs, like `C-unwind`, in the future,
/// though this has not yet happened, and especially with their addition
/// seeing the ABI easily will make code review easier.
pub MISSING_ABI,
Allow,
"No declared ABI for extern declaration"
}

View File

@ -6,6 +6,7 @@ use rustc_ast::node_id::{NodeId, NodeMap};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
use rustc_span::edition::Edition;
use rustc_span::{sym, symbol::Ident, MultiSpan, Span, Symbol};
use rustc_target::spec::abi::Abi;
pub mod builtin;
@ -252,6 +253,7 @@ pub enum BuiltinLintDiagnostics {
UnusedImports(String, Vec<(Span, String)>),
RedundantImport(Vec<(Span, bool)>, Ident),
DeprecatedMacro(Option<Symbol>, Span),
MissingAbi(Span, Abi),
UnusedDocComment(Span),
PatternsInFnsWithoutBody(Span, Ident),
}

View File

@ -38,7 +38,7 @@ pub fn initialize_available_targets() {
($cfg:meta, $($method:ident),*) => { {
#[cfg($cfg)]
fn init() {
extern {
extern "C" {
$(fn $method();)*
}
unsafe {

View File

@ -809,7 +809,7 @@ impl AtomicBool {
/// ```ignore (extern-declaration)
/// # fn main() {
/// use std::sync::atomic::AtomicBool;
/// extern {
/// extern "C" {
/// fn my_atomic_op(arg: *mut bool);
/// }
///
@ -2068,7 +2068,7 @@ macro_rules! atomic_int {
/// # fn main() {
#[doc = concat!($extra_feature, "use std::sync::atomic::", stringify!($atomic_type), ";")]
///
/// extern {
/// extern "C" {
#[doc = concat!(" fn my_atomic_op(arg: *mut ", stringify!($int_type), ");")]
/// }
///

View File

@ -86,7 +86,7 @@ use crate::sys;
/// use std::ffi::CString;
/// use std::os::raw::c_char;
///
/// extern {
/// extern "C" {
/// fn my_printer(s: *const c_char);
/// }
///
@ -144,7 +144,7 @@ pub struct CString {
/// use std::ffi::CStr;
/// use std::os::raw::c_char;
///
/// extern { fn my_string() -> *const c_char; }
/// extern "C" { fn my_string() -> *const c_char; }
///
/// unsafe {
/// let slice = CStr::from_ptr(my_string());
@ -159,7 +159,7 @@ pub struct CString {
/// use std::os::raw::c_char;
///
/// fn work(data: &CStr) {
/// extern { fn work_with(data: *const c_char); }
/// extern "C" { fn work_with(data: *const c_char); }
///
/// unsafe { work_with(data.as_ptr()) }
/// }
@ -174,7 +174,7 @@ pub struct CString {
/// use std::ffi::CStr;
/// use std::os::raw::c_char;
///
/// extern { fn my_string() -> *const c_char; }
/// extern "C" { fn my_string() -> *const c_char; }
///
/// fn my_string_safe() -> String {
/// unsafe {
@ -359,7 +359,7 @@ impl CString {
/// use std::ffi::CString;
/// use std::os::raw::c_char;
///
/// extern { fn puts(s: *const c_char); }
/// extern "C" { fn puts(s: *const c_char); }
///
/// let to_print = CString::new("Hello!").expect("CString::new failed");
/// unsafe {
@ -465,7 +465,7 @@ impl CString {
/// use std::ffi::CString;
/// use std::os::raw::c_char;
///
/// extern {
/// extern "C" {
/// fn some_extern_function(s: *mut c_char);
/// }
///
@ -1147,7 +1147,7 @@ impl CStr {
/// use std::ffi::CStr;
/// use std::os::raw::c_char;
///
/// extern {
/// extern "C" {
/// fn my_string() -> *const c_char;
/// }
///

View File

@ -401,7 +401,7 @@ mod enum_keyword {}
///
/// ```rust
/// #[no_mangle]
/// pub extern fn callable_from_c(x: i32) -> bool {
/// pub extern "C" fn callable_from_c(x: i32) -> bool {
/// x % 3 == 0
/// }
/// ```

View File

@ -28,7 +28,7 @@ use crate::sync::atomic::{self, AtomicUsize, Ordering};
macro_rules! weak {
(fn $name:ident($($t:ty),*) -> $ret:ty) => (
static $name: crate::sys::weak::Weak<unsafe extern fn($($t),*) -> $ret> =
static $name: crate::sys::weak::Weak<unsafe extern "C" fn($($t),*) -> $ret> =
crate::sys::weak::Weak::new(concat!(stringify!($name), '\0'));
)
}

View File

@ -15,7 +15,7 @@ usage would be:
#![feature(link_args)]
#[link_args = "-foo -bar -baz"]
extern {}
extern "C" {}
# fn main() {}
```

View File

@ -13,7 +13,7 @@ impl Drop for A {
}
}
extern {
extern "C" {
#[link_name = "llvm.sqrt.f32"]
fn sqrt(x: f32) -> f32;
}

View File

@ -8,7 +8,7 @@ struct A;
impl Drop for A {
fn drop(&mut self) {
extern { fn foo(); }
extern "C" { fn foo(); }
unsafe { foo(); }
}
}

View File

@ -18,7 +18,7 @@ fn main() {
}
}
extern {
extern "C" {
fn giraffe();
fn turtle();
}

View File

@ -26,17 +26,17 @@ pub mod xyz {
// CHECK: !DISubprogram(name: "e",
// CHECK: linkageName:
// CHECK-SAME: line: 29,
pub extern fn e() {}
pub extern "C" fn e() {}
// CHECK: !DISubprogram(name: "f",
// CHECK-NOT: linkageName:
// CHECK-SAME: line: 35,
#[no_mangle]
pub extern fn f() {}
pub extern "C" fn f() {}
// CHECK: !DISubprogram(name: "g",
// CHECK-NOT: linkageName:
// CHECK-SAME: line: 41,
#[export_name = "g"]
pub extern fn g() {}
pub extern "C" fn g() {}
}

View File

@ -13,19 +13,19 @@ mod private {
// CHECK: void @a()
#[no_mangle]
pub extern fn a() {}
pub extern "C" fn a() {}
// CHECK: void @b()
#[export_name = "b"]
extern fn b() {}
extern "C" fn b() {}
// CHECK: void @c()
#[export_name = "c"]
#[inline]
extern fn c() {}
extern "C" fn c() {}
// CHECK: void @d()
#[export_name = "d"]
#[inline(always)]
extern fn d() {}
extern "C" fn d() {}
}

View File

@ -4,7 +4,7 @@
pub fn bar() { unsafe { foo() } }
extern {
extern "C" {
// CHECK-LABEL: declare void @foo()
// CHECK-SAME: [[ATTRS:#[0-9]+]]
// CHECK-DAG: attributes [[ATTRS]] = { {{.*}}readnone{{.*}} }

View File

@ -11,7 +11,7 @@ struct S {
f3: i32,
}
extern {
extern "C" {
fn foo(s: S);
}

View File

@ -4,7 +4,7 @@
pub fn bar() { unsafe { foo() } }
extern {
extern "C" {
// CHECK-LABEL: declare void @foo()
// CHECK-SAME: [[ATTRS:#[0-9]+]]
// CHECK-DAG: attributes [[ATTRS]] = { {{.*}}readonly{{.*}} }

View File

@ -4,7 +4,7 @@
pub fn bar() { unsafe { foo() } }
extern {
extern "C" {
// CHECK-LABEL: declare void @foo()
// CHECK-SAME: [[ATTRS:#[0-9]+]]
// CHECK-DAG: attributes [[ATTRS]] = { {{.*}}returns_twice{{.*}} }

View File

@ -6,4 +6,4 @@ pub struct Foo(u64);
// CHECK: define {{.*}} @foo(
#[no_mangle]
pub extern fn foo(_: Foo) -> Foo { loop {} }
pub extern "C" fn foo(_: Foo) -> Foo { loop {} }

View File

@ -36,19 +36,19 @@ pub enum TeBigS {
// CHECK: define void @test_BigS(%BigS* [[BIGS_RET_ATTRS:.*]], %BigS* [[BIGS_ARG_ATTRS1:.*]] byval(%BigS) [[BIGS_ARG_ATTRS2:.*]])
#[no_mangle]
pub extern fn test_BigS(_: BigS) -> BigS { loop {} }
pub extern "C" fn test_BigS(_: BigS) -> BigS { loop {} }
// CHECK: define void @test_TsBigS(%TsBigS* [[BIGS_RET_ATTRS]], %TsBigS* [[BIGS_ARG_ATTRS1]] byval(%TsBigS) [[BIGS_ARG_ATTRS2:.*]])
#[no_mangle]
pub extern fn test_TsBigS(_: TsBigS) -> TsBigS { loop {} }
pub extern "C" fn test_TsBigS(_: TsBigS) -> TsBigS { loop {} }
// CHECK: define void @test_TuBigS(%TuBigS* [[BIGS_RET_ATTRS]], %TuBigS* [[BIGS_ARG_ATTRS1]] byval(%TuBigS) [[BIGS_ARG_ATTRS2:.*]])
#[no_mangle]
pub extern fn test_TuBigS(_: TuBigS) -> TuBigS { loop {} }
pub extern "C" fn test_TuBigS(_: TuBigS) -> TuBigS { loop {} }
// CHECK: define void @test_TeBigS(%"TeBigS::Variant"* [[BIGS_RET_ATTRS]], %"TeBigS::Variant"* [[BIGS_ARG_ATTRS1]] byval(%"TeBigS::Variant") [[BIGS_ARG_ATTRS2]])
#[no_mangle]
pub extern fn test_TeBigS(_: TeBigS) -> TeBigS { loop {} }
pub extern "C" fn test_TeBigS(_: TeBigS) -> TeBigS { loop {} }
#[derive(Clone, Copy)]
@ -72,16 +72,16 @@ pub enum TeBigU {
// CHECK: define void @test_BigU(%BigU* [[BIGU_RET_ATTRS:.*]], %BigU* [[BIGU_ARG_ATTRS1:.*]] byval(%BigU) [[BIGU_ARG_ATTRS2:.*]])
#[no_mangle]
pub extern fn test_BigU(_: BigU) -> BigU { loop {} }
pub extern "C" fn test_BigU(_: BigU) -> BigU { loop {} }
// CHECK: define void @test_TsBigU(%TsBigU* [[BIGU_RET_ATTRS:.*]], %TsBigU* [[BIGU_ARG_ATTRS1]] byval(%TsBigU) [[BIGU_ARG_ATTRS2]])
#[no_mangle]
pub extern fn test_TsBigU(_: TsBigU) -> TsBigU { loop {} }
pub extern "C" fn test_TsBigU(_: TsBigU) -> TsBigU { loop {} }
// CHECK: define void @test_TuBigU(%TuBigU* [[BIGU_RET_ATTRS]], %TuBigU* [[BIGU_ARG_ATTRS1]] byval(%TuBigU) [[BIGU_ARG_ATTRS2]])
#[no_mangle]
pub extern fn test_TuBigU(_: TuBigU) -> TuBigU { loop {} }
pub extern "C" fn test_TuBigU(_: TuBigU) -> TuBigU { loop {} }
// CHECK: define void @test_TeBigU(%"TeBigU::Variant"* [[BIGU_RET_ATTRS]], %"TeBigU::Variant"* [[BIGU_ARG_ATTRS1]] byval(%"TeBigU::Variant") [[BIGU_ARG_ATTRS2]])
#[no_mangle]
pub extern fn test_TeBigU(_: TeBigU) -> TeBigU { loop {} }
pub extern "C" fn test_TeBigU(_: TeBigU) -> TeBigU { loop {} }

View File

@ -19,21 +19,21 @@ pub struct F32(f32);
// CHECK: define float @test_F32(float %_1)
#[no_mangle]
pub extern fn test_F32(_: F32) -> F32 { loop {} }
pub extern "C" fn test_F32(_: F32) -> F32 { loop {} }
#[repr(transparent)]
pub struct Ptr(*mut u8);
// CHECK: define i8* @test_Ptr(i8* %_1)
#[no_mangle]
pub extern fn test_Ptr(_: Ptr) -> Ptr { loop {} }
pub extern "C" fn test_Ptr(_: Ptr) -> Ptr { loop {} }
#[repr(transparent)]
pub struct WithZst(u64, Zst1);
// CHECK: define i64 @test_WithZst(i64 %_1)
#[no_mangle]
pub extern fn test_WithZst(_: WithZst) -> WithZst { loop {} }
pub extern "C" fn test_WithZst(_: WithZst) -> WithZst { loop {} }
#[repr(transparent)]
pub struct WithZeroSizedArray(*const f32, [i8; 0]);
@ -41,14 +41,14 @@ pub struct WithZeroSizedArray(*const f32, [i8; 0]);
// Apparently we use i32* when newtype-unwrapping f32 pointers. Whatever.
// CHECK: define i32* @test_WithZeroSizedArray(i32* %_1)
#[no_mangle]
pub extern fn test_WithZeroSizedArray(_: WithZeroSizedArray) -> WithZeroSizedArray { loop {} }
pub extern "C" fn test_WithZeroSizedArray(_: WithZeroSizedArray) -> WithZeroSizedArray { loop {} }
#[repr(transparent)]
pub struct Generic<T>(T);
// CHECK: define double @test_Generic(double %_1)
#[no_mangle]
pub extern fn test_Generic(_: Generic<f64>) -> Generic<f64> { loop {} }
pub extern "C" fn test_Generic(_: Generic<f64>) -> Generic<f64> { loop {} }
#[repr(transparent)]
pub struct GenericPlusZst<T>(T, Zst2);
@ -58,14 +58,14 @@ pub enum Bool { True, False, FileNotFound }
// CHECK: define{{( zeroext)?}} i8 @test_Gpz(i8{{( zeroext)?}} %_1)
#[no_mangle]
pub extern fn test_Gpz(_: GenericPlusZst<Bool>) -> GenericPlusZst<Bool> { loop {} }
pub extern "C" fn test_Gpz(_: GenericPlusZst<Bool>) -> GenericPlusZst<Bool> { loop {} }
#[repr(transparent)]
pub struct LifetimePhantom<'a, T: 'a>(*const T, PhantomData<&'a T>);
// CHECK: define i16* @test_LifetimePhantom(i16* %_1)
#[no_mangle]
pub extern fn test_LifetimePhantom(_: LifetimePhantom<i16>) -> LifetimePhantom<i16> { loop {} }
pub extern "C" fn test_LifetimePhantom(_: LifetimePhantom<i16>) -> LifetimePhantom<i16> { loop {} }
// This works despite current alignment resrictions because PhantomData is always align(1)
#[repr(transparent)]
@ -75,28 +75,28 @@ pub struct Px;
// CHECK: define float @test_UnitPhantom(float %_1)
#[no_mangle]
pub extern fn test_UnitPhantom(_: UnitPhantom<f32, Px>) -> UnitPhantom<f32, Px> { loop {} }
pub extern "C" fn test_UnitPhantom(_: UnitPhantom<f32, Px>) -> UnitPhantom<f32, Px> { loop {} }
#[repr(transparent)]
pub struct TwoZsts(Zst1, i8, Zst2);
// CHECK: define{{( signext)?}} i8 @test_TwoZsts(i8{{( signext)?}} %_1)
#[no_mangle]
pub extern fn test_TwoZsts(_: TwoZsts) -> TwoZsts { loop {} }
pub extern "C" fn test_TwoZsts(_: TwoZsts) -> TwoZsts { loop {} }
#[repr(transparent)]
pub struct Nested1(Zst2, Generic<f64>);
// CHECK: define double @test_Nested1(double %_1)
#[no_mangle]
pub extern fn test_Nested1(_: Nested1) -> Nested1 { loop {} }
pub extern "C" fn test_Nested1(_: Nested1) -> Nested1 { loop {} }
#[repr(transparent)]
pub struct Nested2(Nested1, Zst1);
// CHECK: define double @test_Nested2(double %_1)
#[no_mangle]
pub extern fn test_Nested2(_: Nested2) -> Nested2 { loop {} }
pub extern "C" fn test_Nested2(_: Nested2) -> Nested2 { loop {} }
#[repr(simd)]
struct f32x4(f32, f32, f32, f32);
@ -106,7 +106,7 @@ pub struct Vector(f32x4);
// CHECK: define <4 x float> @test_Vector(<4 x float> %_1)
#[no_mangle]
pub extern fn test_Vector(_: Vector) -> Vector { loop {} }
pub extern "C" fn test_Vector(_: Vector) -> Vector { loop {} }
trait Mirror { type It: ?Sized; }
impl<T: ?Sized> Mirror for T { type It = Self; }
@ -116,7 +116,7 @@ pub struct StructWithProjection(<f32 as Mirror>::It);
// CHECK: define float @test_Projection(float %_1)
#[no_mangle]
pub extern fn test_Projection(_: StructWithProjection) -> StructWithProjection { loop {} }
pub extern "C" fn test_Projection(_: StructWithProjection) -> StructWithProjection { loop {} }
#[repr(transparent)]
pub enum EnumF32 {
@ -125,7 +125,7 @@ pub enum EnumF32 {
// CHECK: define float @test_EnumF32(float %_1)
#[no_mangle]
pub extern fn test_EnumF32(_: EnumF32) -> EnumF32 { loop {} }
pub extern "C" fn test_EnumF32(_: EnumF32) -> EnumF32 { loop {} }
#[repr(transparent)]
pub enum EnumF32WithZsts {
@ -134,7 +134,7 @@ pub enum EnumF32WithZsts {
// CHECK: define float @test_EnumF32WithZsts(float %_1)
#[no_mangle]
pub extern fn test_EnumF32WithZsts(_: EnumF32WithZsts) -> EnumF32WithZsts { loop {} }
pub extern "C" fn test_EnumF32WithZsts(_: EnumF32WithZsts) -> EnumF32WithZsts { loop {} }
#[repr(transparent)]
pub union UnionF32 {
@ -143,7 +143,7 @@ pub union UnionF32 {
// CHECK: define float @test_UnionF32(float %_1)
#[no_mangle]
pub extern fn test_UnionF32(_: UnionF32) -> UnionF32 { loop {} }
pub extern "C" fn test_UnionF32(_: UnionF32) -> UnionF32 { loop {} }
#[repr(transparent)]
pub union UnionF32WithZsts {
@ -154,7 +154,7 @@ pub union UnionF32WithZsts {
// CHECK: define float @test_UnionF32WithZsts(float %_1)
#[no_mangle]
pub extern fn test_UnionF32WithZsts(_: UnionF32WithZsts) -> UnionF32WithZsts { loop {} }
pub extern "C" fn test_UnionF32WithZsts(_: UnionF32WithZsts) -> UnionF32WithZsts { loop {} }
// All that remains to be tested are aggregates. They are tested in separate files called repr-

View File

@ -13,7 +13,7 @@ impl Drop for A {
}
}
extern {
extern "C" {
#[link_name = "llvm.sqrt.f32"]
fn sqrt(x: f32) -> f32;
}

View File

@ -9,7 +9,7 @@
// CHECK-LABEL: define {{.*}} @exported() {{.*}} #0
#[no_mangle]
pub extern fn exported() {
pub extern "C" fn exported() {
not_exported();
}

View File

@ -11,7 +11,7 @@
// "C" ABI
// pub extern fn foo() {} // FIXME right now we don't abort-on-panic but add `nounwind` nevertheless
#[unwind(allowed)]
pub extern fn foo_allowed() {}
pub extern "C" fn foo_allowed() {}
// "Rust"
// (`extern "Rust"` could be removed as all `fn` get it implicitly; we leave it in for clarity.)

View File

@ -4,7 +4,7 @@
#![crate_type = "lib"]
#![feature(unwind_attributes)]
extern {
extern "C" {
// CHECK: Function Attrs:{{.*}}nounwind
// CHECK-NEXT: declare void @extern_fn
fn extern_fn();

View File

@ -23,7 +23,6 @@
// gdbg-check:type = struct Struct2
// gdbr-check:type = type_names::mod1::Struct2
// ENUMS
// gdb-command:whatis simple_enum_1
// gdbg-check:type = union Enum1
@ -45,7 +44,6 @@
// gdbg-check:type = union Enum3<type_names::Struct1>
// gdbr-check:type = type_names::mod1::mod2::Enum3<type_names::Struct1>
// TUPLES
// gdb-command:whatis tuple1
// gdbg-check:type = struct (u32, type_names::Struct1, type_names::mod1::mod2::Enum3<type_names::mod1::Struct2>)
@ -55,7 +53,6 @@
// gdbg-check:type = struct ((type_names::Struct1, type_names::mod1::mod2::Struct3), type_names::mod1::Enum2, char)
// gdbr-check:type = ((type_names::Struct1, type_names::mod1::mod2::Struct3), type_names::mod1::Enum2, char)
// BOX
// gdb-command:whatis box1
// gdbg-check:type = struct (alloc::boxed::Box<f32>, i32)
@ -65,7 +62,6 @@
// gdbg-check:type = struct (alloc::boxed::Box<type_names::mod1::mod2::Enum3<f32>>, i32)
// gdbr-check:type = (alloc::boxed::Box<type_names::mod1::mod2::Enum3<f32>>, i32)
// REFERENCES
// gdb-command:whatis ref1
// gdbg-check:type = struct (&type_names::Struct1, i32)
@ -83,7 +79,6 @@
// gdbg-check:type = struct (&mut type_names::GenericStruct<type_names::mod1::Enum2, f64>, i32)
// gdbr-check:type = (&mut type_names::GenericStruct<type_names::mod1::Enum2, f64>, i32)
// RAW POINTERS
// gdb-command:whatis mut_ptr1
// gdbg-check:type = struct (*mut type_names::Struct1, isize)
@ -109,7 +104,6 @@
// gdbg-check:type = struct (*const type_names::mod1::mod2::Enum3<type_names::Struct1>, isize)
// gdbr-check:type = (*const type_names::mod1::mod2::Enum3<type_names::Struct1>, isize)
// VECTORS
// gdb-command:whatis fixed_size_vec1
// gdbg-check:type = struct ([type_names::Struct1; 3], i16)
@ -127,7 +121,6 @@
// gdbg-check:type = struct &[type_names::mod1::Enum2]
// gdbr-check:type = &[type_names::mod1::Enum2]
// TRAITS
// gdb-command:whatis box_trait
// gdbg-check:type = struct Box<Trait1>
@ -153,7 +146,6 @@
// gdbg-check:type = struct &mut Trait2<type_names::mod1::mod2::Struct3, type_names::GenericStruct<usize, isize>>
// gdbr-check:type = type_names::&mut Trait2<type_names::mod1::mod2::Struct3, type_names::GenericStruct<usize, isize>>
// BARE FUNCTIONS
// gdb-command:whatis rust_fn
// gdbg-check:type = struct (fn(core::option::Option<isize>, core::option::Option<&type_names::mod1::Struct2>), usize)
@ -199,7 +191,6 @@
// gdbg-check:type = struct (unsafe extern "C" fn(*const u8, ...) -> isize, usize)
// gdbr-check:type = (unsafe extern "C" fn(*const u8, ...) -> isize, usize)
// CLOSURES
// gdb-command:whatis closure1
// gdbg-check:type = struct (closure, usize)
@ -219,7 +210,7 @@ use std::marker::PhantomData;
use std::ptr;
pub struct Struct1;
struct GenericStruct<T1, T2>(PhantomData<(T1,T2)>);
struct GenericStruct<T1, T2>(PhantomData<(T1, T2)>);
enum Enum1 {
Variant1,
@ -246,8 +237,12 @@ mod mod1 {
}
}
trait Trait1 { fn dummy(&self) { } }
trait Trait2<T1, T2> { fn dummy(&self, _: T1, _:T2) { } }
trait Trait1 {
fn dummy(&self) {}
}
trait Trait2<T1, T2> {
fn dummy(&self, _: T1, _: T2) {}
}
impl Trait1 for isize {}
impl<T1, T2> Trait2<T1, T2> for isize {}
@ -257,16 +252,26 @@ extern "C" fn extern_c_fn(_: isize) {}
unsafe fn unsafe_fn(_: Result<char, f64>) {}
extern "stdcall" fn extern_stdcall_fn() {}
fn rust_fn_with_return_value(_: f64) -> usize { 4 }
extern "C" fn extern_c_fn_with_return_value() -> Struct1 { Struct1 }
unsafe fn unsafe_fn_with_return_value(_: GenericStruct<u16, u8>) -> mod1::Struct2 { mod1::Struct2 }
extern "stdcall" fn extern_stdcall_fn_with_return_value(_: Box<isize>) -> usize { 0 }
fn rust_fn_with_return_value(_: f64) -> usize {
4
}
extern "C" fn extern_c_fn_with_return_value() -> Struct1 {
Struct1
}
unsafe fn unsafe_fn_with_return_value(_: GenericStruct<u16, u8>) -> mod1::Struct2 {
mod1::Struct2
}
extern "stdcall" fn extern_stdcall_fn_with_return_value(_: Box<isize>) -> usize {
0
}
fn generic_function<T>(x: T) -> T { x }
fn generic_function<T>(x: T) -> T {
x
}
#[allow(improper_ctypes)]
extern {
fn printf(_:*const u8, ...) -> isize;
extern "C" {
fn printf(_: *const u8, ...) -> isize;
}
// In many of the cases below, the type that is actually under test is wrapped
@ -277,7 +282,6 @@ extern {
// printed correctly, so the tests below just construct a tuple type that will
// then *contain* the type name that we want to see.
fn main() {
// Structs
let simple_struct = Struct1;
let generic_struct1: GenericStruct<mod1::Struct2, mod1::mod2::Struct3> =
@ -336,11 +340,11 @@ fn main() {
let mut_ref_trait = (&mut mut_int1) as &mut Trait1;
let generic_box_trait = (box 0_isize) as Box<Trait2<i32, mod1::Struct2>>;
let generic_ref_trait = (&0_isize) as &Trait2<Struct1, Struct1>;
let generic_ref_trait = (&0_isize) as &Trait2<Struct1, Struct1>;
let mut generic_mut_ref_trait_impl = 0_isize;
let generic_mut_ref_trait = (&mut generic_mut_ref_trait_impl) as
&mut Trait2<mod1::mod2::Struct3, GenericStruct<usize, isize>>;
let generic_mut_ref_trait = (&mut generic_mut_ref_trait_impl)
as &mut Trait2<mod1::mod2::Struct3, GenericStruct<usize, isize>>;
// Bare Functions
let rust_fn = (rust_fn, 0_usize);
@ -364,11 +368,13 @@ fn main() {
// how that maps to rustc's internal representation of these forms.
// Once closures have reached their 1.0 form, the tests below should
// probably be expanded.
let closure1 = (|x:isize| {}, 0_usize);
let closure2 = (|x:i8, y: f32| { (x as f32) + y }, 0_usize);
let closure1 = (|x: isize| {}, 0_usize);
let closure2 = (|x: i8, y: f32| (x as f32) + y, 0_usize);
zzz(); // #break
}
#[inline(never)]
fn zzz() { () }
fn zzz() {
()
}

View File

@ -13,7 +13,7 @@ use std::ffi::CString;
mod mlibc {
use libc::{c_char, c_long, c_longlong};
extern {
extern "C" {
pub fn atol(x: *const c_char) -> c_long;
pub fn atoll(x: *const c_char) -> c_longlong;
}
@ -31,6 +31,8 @@ fn atoll(s: String) -> i64 {
pub fn main() {
assert_eq!(atol("1024".to_string()) * 10, atol("10240".to_string()));
assert_eq!((atoll("11111111111111111".to_string()) * 10),
atoll("111111111111111110".to_string()));
assert_eq!(
(atoll("11111111111111111".to_string()) * 10),
atoll("111111111111111110".to_string())
);
}

View File

@ -271,7 +271,7 @@ impl Foo {
impl Foo {
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck")]
#[rustc_clean(cfg="cfail3")]
pub extern fn make_method_extern(&self) { }
pub extern "C" fn make_method_extern(&self) { }
}

View File

@ -312,7 +312,7 @@ trait TraitAddExternModifier {
trait TraitAddExternModifier {
#[rustc_dirty(label="hir_owner", cfg="cfail2")]
#[rustc_clean(label="hir_owner", cfg="cfail3")]
extern fn method();
extern "C" fn method();
}

View File

@ -1,7 +1,7 @@
#![crate_type = "rlib"]
#[link(name = "foo", kind = "static")]
extern {
extern "C" {
fn foo();
fn bar();
}

View File

@ -1,7 +1,7 @@
#![crate_type = "dylib"]
#[link(name = "cfoo")]
extern {
extern "C" {
fn foo();
}

View File

@ -1,7 +1,7 @@
#![crate_type = "rlib"]
#[link(name = "cfoo")]
extern {
extern "C" {
fn foo();
}

View File

@ -1,7 +1,7 @@
#![crate_type = "dylib"]
#[link(name = "cfoo", kind = "static")]
extern {
extern "C" {
fn foo();
}

View File

@ -1,7 +1,7 @@
#![crate_type = "rlib"]
#[link(name = "cfoo", kind = "static")]
extern {
extern "C" {
fn foo();
}

View File

@ -3,11 +3,11 @@
extern crate bar;
#[no_mangle]
pub extern fn foo() {
pub extern "C" fn foo() {
bar::bar();
}
#[no_mangle]
pub extern fn bar(a: u32, b: u32) -> u32 {
pub extern "C" fn bar(a: u32, b: u32) -> u32 {
a + b
}

View File

@ -1,6 +1,6 @@
#![crate_type = "cdylib"]
#[no_mangle]
pub extern fn foo() -> u32 {
pub extern "C" fn foo() -> u32 {
3
}

View File

@ -3,11 +3,11 @@
extern crate bar;
#[no_mangle]
pub extern fn foo() {
pub extern "C" fn foo() {
bar::bar();
}
#[no_mangle]
pub extern fn bar(a: u32, b: u32) -> u32 {
pub extern "C" fn bar(a: u32, b: u32) -> u32 {
a + b
}

View File

@ -1,4 +1,4 @@
#![crate_type = "rlib"]
#[link(name = "native", kind = "static")]
extern {}
extern "C" {}

View File

@ -1,6 +1,10 @@
extern { fn foo(); }
extern "C" {
fn foo();
}
pub fn main() {
unsafe { foo(); }
unsafe {
foo();
}
assert_eq!(7f32.powi(3), 343f32);
}

View File

@ -3,6 +3,6 @@
extern crate upstream;
#[no_mangle]
pub extern fn bar() {
pub extern "C" fn bar() {
upstream::foo();
}

View File

@ -1,22 +1,20 @@
extern crate testcrate;
extern "C" fn bar<T>(ts: testcrate::TestStruct<T>) -> T { ts.y }
extern "C" fn bar<T>(ts: testcrate::TestStruct<T>) -> T {
ts.y
}
#[link(name = "test", kind = "static")]
extern {
extern "C" {
fn call(c: extern "C" fn(testcrate::TestStruct<i32>) -> i32) -> i32;
}
fn main() {
// Let's test calling it cross crate
let back = unsafe {
testcrate::call(testcrate::foo::<i32>)
};
let back = unsafe { testcrate::call(testcrate::foo::<i32>) };
assert_eq!(3, back);
// And just within this crate
let back = unsafe {
call(bar::<i32>)
};
let back = unsafe { call(bar::<i32>) };
assert_eq!(3, back);
}

View File

@ -3,12 +3,14 @@
#[repr(C)]
pub struct TestStruct<T> {
pub x: u8,
pub y: T
pub y: T,
}
pub extern "C" fn foo<T>(ts: TestStruct<T>) -> T { ts.y }
pub extern "C" fn foo<T>(ts: TestStruct<T>) -> T {
ts.y
}
#[link(name = "test", kind = "static")]
extern {
extern "C" {
pub fn call(c: extern "C" fn(TestStruct<i32>) -> i32) -> i32;
}

View File

@ -1,11 +1,15 @@
#[no_mangle]
pub extern "C" fn foo() -> i32 { 3 }
pub extern "C" fn foo() -> i32 {
3
}
#[no_mangle]
pub extern "C" fn bar() -> i32 { 5 }
pub extern "C" fn bar() -> i32 {
5
}
#[link(name = "test", kind = "static")]
extern {
extern "C" {
fn add() -> i32;
}

View File

@ -7,7 +7,7 @@ struct Rect {
a: i32,
b: i32,
c: i32,
d: i32
d: i32,
}
#[derive(Clone, Copy, Debug, PartialEq)]
@ -15,7 +15,7 @@ struct Rect {
struct BiggerRect {
s: Rect,
a: i32,
b: i32
b: i32,
}
#[derive(Clone, Copy, Debug, PartialEq)]
@ -23,7 +23,7 @@ struct BiggerRect {
struct FloatRect {
a: i32,
b: i32,
c: f64
c: f64,
}
#[derive(Clone, Copy, Debug, PartialEq)]
@ -33,14 +33,14 @@ struct Huge {
b: i32,
c: i32,
d: i32,
e: i32
e: i32,
}
#[derive(Clone, Copy, Debug, PartialEq)]
#[repr(C)]
struct FloatPoint {
x: f64,
y: f64
y: f64,
}
#[derive(Clone, Copy, Debug, PartialEq)]
@ -58,13 +58,22 @@ struct IntOdd {
}
#[link(name = "test", kind = "static")]
extern {
extern "C" {
fn byval_rect(a: i32, b: i32, c: i32, d: i32, e: i32, s: Rect);
fn byval_many_rect(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32, s: Rect);
fn byval_rect_floats(a: f32, b: f32, c: f64, d: f32, e: f32,
f: f32, g: f64, s: Rect, t: FloatRect);
fn byval_rect_floats(
a: f32,
b: f32,
c: f64,
d: f32,
e: f32,
f: f32,
g: f64,
s: Rect,
t: FloatRect,
);
fn byval_rect_with_float(a: i32, b: i32, c: f32, d: i32, e: i32, f: i32, s: Rect);
@ -107,12 +116,7 @@ fn main() {
byval_many_rect(1, 2, 3, 4, 5, 6, s);
byval_rect_floats(1., 2., 3., 4., 5., 6., 7., s, u);
byval_rect_with_float(1, 2, 3.0, 4, 5, 6, s);
byval_rect_with_many_huge(v, v, v, v, v, v, Rect {
a: 123,
b: 456,
c: 789,
d: 420
});
byval_rect_with_many_huge(v, v, v, v, v, v, Rect { a: 123, b: 456, c: 789, d: 420 });
split_rect(1, 2, s);
split_rect_floats(1., 2., u);
split_rect_with_floats(1, 2, 3.0, 4, 5.0, 6, s);

View File

@ -1,7 +1,7 @@
#![feature(extern_types)]
#[link(name = "ctest", kind = "static")]
extern {
extern "C" {
type data;
fn data_create(magic: u32) -> *mut data;

View File

@ -3,11 +3,11 @@
struct Foo {
a: i8,
b: i16,
c: i8
c: i8,
}
#[link(name = "test", kind = "static")]
extern {
extern "C" {
fn foo(f: Foo) -> Foo;
}

View File

@ -2,7 +2,7 @@ extern crate testcrate;
use std::mem;
extern {
extern "C" {
fn give_back(tu: testcrate::TestUnion) -> u64;
}
@ -10,14 +10,10 @@ fn main() {
let magic: u64 = 0xDEADBEEF;
// Let's test calling it cross crate
let back = unsafe {
testcrate::give_back(mem::transmute(magic))
};
let back = unsafe { testcrate::give_back(mem::transmute(magic)) };
assert_eq!(magic, back);
// And just within this crate
let back = unsafe {
give_back(mem::transmute(magic))
};
let back = unsafe { give_back(mem::transmute(magic)) };
assert_eq!(magic, back);
}

View File

@ -2,10 +2,10 @@
#[repr(C)]
pub struct TestUnion {
_val: u64
_val: u64,
}
#[link(name = "ctest", kind = "static")]
extern {
extern "C" {
pub fn give_back(tu: TestUnion) -> u64;
}

View File

@ -1,4 +1,4 @@
#[no_mangle]
pub extern fn args_check() {
pub extern "C" fn args_check() {
assert_ne!(std::env::args_os().count(), 0);
}

View File

@ -3,10 +3,12 @@
extern crate foo;
#[link(name = "bar", kind = "static")]
extern {
extern "C" {
fn bar();
}
pub fn doit() {
unsafe { bar(); }
unsafe {
bar();
}
}

View File

@ -1,10 +1,12 @@
#![crate_type = "rlib"]
#[link(name = "foo", kind = "static")]
extern {
extern "C" {
fn foo();
}
pub fn doit() {
unsafe { foo(); }
unsafe {
foo();
}
}

View File

@ -1,5 +1,5 @@
#[no_mangle]
pub extern fn foo() {}
pub extern "C" fn foo() {}
#[no_mangle]
pub static FOO_STATIC: u8 = 0;

View File

@ -1,6 +1,6 @@
#![crate_type = "dylib"]
#[link(name = "foo", kind = "static")]
extern {
extern "C" {
pub fn foo();
}

View File

@ -1,11 +1,11 @@
#[link(name = "test", kind = "static")]
extern {
extern "C" {
fn slice_len(s: &[u8]) -> usize;
fn slice_elem(s: &[u8], idx: usize) -> u8;
}
fn main() {
let data = [1,2,3,4,5];
let data = [1, 2, 3, 4, 5];
unsafe {
assert_eq!(data.len(), slice_len(&data) as usize);

View File

@ -1,6 +1,6 @@
#![crate_type = "rlib"]
#[link(name = "a", kind = "static")]
extern {
extern "C" {
pub fn a();
}

View File

@ -1,11 +1,12 @@
extern crate a;
#[link(name = "b", kind = "static")]
extern {
extern "C" {
pub fn b();
}
fn main() {
unsafe { b(); }
unsafe {
b();
}
}

View File

@ -3,6 +3,6 @@
#[link(name = "return1", cfg(foo))]
#[link(name = "return3", kind = "static", cfg(bar))]
extern {
extern "C" {
pub fn my_function() -> i32;
}

View File

@ -3,6 +3,6 @@
#[link(name = "return1", cfg(foo))]
#[link(name = "return2", cfg(bar))]
extern {
extern "C" {
pub fn my_function() -> i32;
}

View File

@ -2,7 +2,7 @@
#[link(name = "return1", cfg(foo))]
#[link(name = "return2", cfg(bar))]
extern {
extern "C" {
fn my_function() -> i32;
}

View File

@ -2,15 +2,13 @@
extern crate libc;
#[link(name="foo", kind = "static")]
extern {
#[link(name = "foo", kind = "static")]
extern "C" {
fn should_return_one() -> libc::c_int;
}
fn main() {
let result = unsafe {
should_return_one()
};
let result = unsafe { should_return_one() };
if result != 1 {
std::process::exit(255);

View File

@ -5,7 +5,7 @@
static BAZ: i32 = 21;
#[link(name = "foo", kind = "static")]
extern {
extern "C" {
fn what() -> i32;
}

View File

@ -25,7 +25,7 @@ fn write_test_case(file: &Path, n: usize) -> HashSet<String> {
writeln!(f, "#[link(name = \"S{}{}S\")]", prefix, i).unwrap();
libs.insert(format!("{}{}", prefix, i));
}
writeln!(f, "extern {{}}\nfn main() {{}}").unwrap();
writeln!(f, "extern \"C\" {{}}\nfn main() {{}}").unwrap();
f.into_inner().unwrap();
libs

View File

@ -1,6 +1,6 @@
#[link(name = "foo", kind = "static")]
extern {
fn test_start(f: extern fn());
extern "C" {
fn test_start(f: extern "C" fn());
fn test_end();
}
@ -13,11 +13,10 @@ fn main() {
struct A;
impl Drop for A {
fn drop(&mut self) {
}
fn drop(&mut self) {}
}
extern fn test_middle() {
extern "C" fn test_middle() {
let _a = A;
foo();
}

View File

@ -1,7 +1,7 @@
#![crate_type = "rlib"]
#[link(name = "foo", kind = "static")]
extern {
extern "C" {
fn foo() -> i32;
}

View File

@ -3,7 +3,7 @@
extern crate lib1;
#[link(name = "bar", kind = "static")]
extern {
extern "C" {
fn foo() -> i32;
}

View File

@ -1,9 +1,11 @@
#![crate_type = "rlib"]
extern {
extern "C" {
fn bar();
}
pub fn foo() {
unsafe { bar(); }
unsafe {
bar();
}
}

View File

@ -1,7 +1,7 @@
#[link(name = "foo")] // linker should drop this library, no symbols used
#[link(name = "bar")] // symbol comes from this library
#[link(name = "foo")] // now linker picks up `foo` b/c `bar` library needs it
extern {
extern "C" {
fn bar();
}

View File

@ -1,5 +1,5 @@
#[no_mangle]
pub extern fn overflow() {
pub extern "C" fn overflow() {
let xs = [0, 1, 2, 3];
let _y = unsafe { *xs.as_ptr().offset(4) };
}

View File

@ -1,4 +1,4 @@
extern {
extern "C" {
fn overflow();
}

View File

@ -1,5 +1,5 @@
#[no_mangle]
pub extern fn overflow() {
pub extern "C" fn overflow() {
let xs = [0, 1, 2, 3];
let _y = unsafe { *xs.as_ptr().offset(4) };
}

View File

@ -1,4 +1,4 @@
extern {
extern "C" {
fn overflow();
}

View File

@ -1,5 +1,5 @@
#[no_mangle]
pub extern fn overflow() {
pub extern "C" fn overflow() {
let xs = [0, 1, 2, 3];
let _y = unsafe { *xs.as_ptr().offset(4) };
}

View File

@ -1,5 +1,5 @@
#[link(name = "library")]
extern {
extern "C" {
fn overflow();
}

View File

@ -1,4 +1,4 @@
#![ crate_name = "test" ]
#![crate_name = "test"]
#![feature(box_syntax)]
#![feature(rustc_private)]
@ -9,11 +9,10 @@ extern crate krate2;
extern crate krate2 as krate3;
use rustc_graphviz::RenderOption;
use std::collections::{HashMap,HashSet};
use std::cell::RefCell;
use std::collections::{HashMap, HashSet};
use std::io::Write;
use sub::sub2 as msalias;
use sub::sub2;
use sub::sub2::nested_struct as sub_struct;
@ -30,7 +29,7 @@ static bob: Option<graphviz::RenderOption> = None;
// buglink test - see issue #1337.
fn test_alias<I: Iterator>(i: Option<<I as Iterator>::Item>) {
let s = sub_struct{ field2: 45u32, };
let s = sub_struct { field2: 45u32 };
// import tests
fn foo(x: &Write) {}
@ -80,7 +79,7 @@ mod sub {
pub enum nested_enum {
Nest2 = 2,
Nest3 = 3
Nest3 = 3,
}
}
}
@ -101,7 +100,9 @@ struct some_fields {
type SF = some_fields;
trait SuperTrait {
fn qux(&self) { panic!(); }
fn qux(&self) {
panic!();
}
}
trait SomeTrait: SuperTrait {
@ -136,8 +137,7 @@ impl SomeTrait for some_fields {
}
}
impl SuperTrait for some_fields {
}
impl SuperTrait for some_fields {}
impl SubTrait for some_fields {}
@ -150,17 +150,14 @@ impl some_fields {
42
}
fn align_to<T>(&mut self) {
}
fn align_to<T>(&mut self) {}
fn test(&mut self) {
self.align_to::<bool>();
}
}
impl SuperTrait for nofields {
}
impl SuperTrait for nofields {}
impl SomeTrait for nofields {
fn Method(&self, x: u32) -> u32 {
self.Method(x);
@ -186,59 +183,70 @@ enum SomeEnum<'a> {
Ints(isize, isize),
Floats(f64, f64),
Strings(&'a str, &'a str, &'a str),
MyTypes(MyType, MyType)
MyTypes(MyType, MyType),
}
#[derive(Copy, Clone)]
enum SomeOtherEnum {
SomeConst1,
SomeConst2,
SomeConst3
SomeConst3,
}
enum SomeStructEnum {
EnumStruct{a:isize, b:isize},
EnumStruct2{f1:MyType, f2:MyType},
EnumStruct3{f1:MyType, f2:MyType, f3:SomeEnum<'static>}
EnumStruct { a: isize, b: isize },
EnumStruct2 { f1: MyType, f2: MyType },
EnumStruct3 { f1: MyType, f2: MyType, f3: SomeEnum<'static> },
}
fn matchSomeEnum(val: SomeEnum) {
match val {
SomeEnum::Ints(int1, int2) => { println(&(int1+int2).to_string()); }
SomeEnum::Floats(float1, float2) => { println(&(float2*float1).to_string()); }
SomeEnum::Strings(.., s3) => { println(s3); }
SomeEnum::MyTypes(mt1, mt2) => { println(&(mt1.field1 - mt2.field1).to_string()); }
SomeEnum::Ints(int1, int2) => {
println(&(int1 + int2).to_string());
}
SomeEnum::Floats(float1, float2) => {
println(&(float2 * float1).to_string());
}
SomeEnum::Strings(.., s3) => {
println(s3);
}
SomeEnum::MyTypes(mt1, mt2) => {
println(&(mt1.field1 - mt2.field1).to_string());
}
}
}
fn matchSomeStructEnum(se: SomeStructEnum) {
match se {
SomeStructEnum::EnumStruct{a:a, ..} => println(&a.to_string()),
SomeStructEnum::EnumStruct2{f1:f1, f2:f_2} => println(&f_2.field1.to_string()),
SomeStructEnum::EnumStruct3{f1, ..} => println(&f1.field1.to_string()),
SomeStructEnum::EnumStruct { a: a, .. } => println(&a.to_string()),
SomeStructEnum::EnumStruct2 { f1: f1, f2: f_2 } => println(&f_2.field1.to_string()),
SomeStructEnum::EnumStruct3 { f1, .. } => println(&f1.field1.to_string()),
}
}
fn matchSomeStructEnum2(se: SomeStructEnum) {
use SomeStructEnum::*;
match se {
EnumStruct{a: ref aaa, ..} => println(&aaa.to_string()),
EnumStruct2{f1, f2: f2} => println(&f1.field1.to_string()),
EnumStruct3{f1, f3: SomeEnum::Ints(..), f2} => println(&f1.field1.to_string()),
_ => {},
EnumStruct { a: ref aaa, .. } => println(&aaa.to_string()),
EnumStruct2 { f1, f2: f2 } => println(&f1.field1.to_string()),
EnumStruct3 { f1, f3: SomeEnum::Ints(..), f2 } => println(&f1.field1.to_string()),
_ => {}
}
}
fn matchSomeOtherEnum(val: SomeOtherEnum) {
use SomeOtherEnum::{SomeConst2, SomeConst3};
match val {
SomeOtherEnum::SomeConst1 => { println("I'm const1."); }
SomeConst2 | SomeConst3 => { println("I'm const2 or const3."); }
SomeOtherEnum::SomeConst1 => {
println("I'm const1.");
}
SomeConst2 | SomeConst3 => {
println("I'm const2 or const3.");
}
}
}
fn hello<X: SomeTrait>((z, a) : (u32, String), ex: X) {
fn hello<X: SomeTrait>((z, a): (u32, String), ex: X) {
SameDir2::hello(43);
println(&yy.to_string());
@ -253,8 +261,8 @@ fn hello<X: SomeTrait>((z, a) : (u32, String), ex: X) {
let x = 32.0f32;
let _ = (x + ((x * x) + 1.0).sqrt()).ln();
let s: Box<SomeTrait> = box some_fields {field1: 43};
let s2: Box<some_fields> = box some_fields {field1: 43};
let s: Box<SomeTrait> = box some_fields { field1: 43 };
let s2: Box<some_fields> = box some_fields { field1: 43 };
let s3 = box nofields;
s.Method(43);
@ -307,8 +315,9 @@ mod macro_use_test {
}
}
fn main() { // foo
let s = box some_fields {field1: 43};
fn main() {
// foo
let s = box some_fields { field1: 43 };
hello((43, "a".to_string()), *s);
sub::sub2::hello();
sub2::sub3::hello();
@ -329,26 +338,24 @@ fn main() { // foo
let vs = variable_str!(32);
let mut candidates: RefCell<HashMap<&'static str, &'static str>> = RefCell::new(HashMap::new());
let _ = blah {
used_link_args: RefCell::new([]),
};
let _ = blah { used_link_args: RefCell::new([]) };
let s1 = nofields;
let s2 = SF { field1: 55};
let s3: some_fields = some_fields{ field1: 55};
let s4: msalias::nested_struct = sub::sub2::nested_struct{ field2: 55};
let s4: msalias::nested_struct = sub2::nested_struct{ field2: 55};
let s2 = SF { field1: 55 };
let s3: some_fields = some_fields { field1: 55 };
let s4: msalias::nested_struct = sub::sub2::nested_struct { field2: 55 };
let s4: msalias::nested_struct = sub2::nested_struct { field2: 55 };
println(&s2.field1.to_string());
let s5: MyType = box some_fields{ field1: 55};
let s = SameDir::SameStruct{name: "Bob".to_string()};
let s = SubDir::SubStruct{name:"Bob".to_string()};
let s5: MyType = box some_fields { field1: 55 };
let s = SameDir::SameStruct { name: "Bob".to_string() };
let s = SubDir::SubStruct { name: "Bob".to_string() };
let s6: SomeEnum = SomeEnum::MyTypes(box s2.clone(), s5);
let s7: SomeEnum = SomeEnum::Strings("one", "two", "three");
matchSomeEnum(s6);
matchSomeEnum(s7);
let s8: SomeOtherEnum = SomeOtherEnum::SomeConst2;
matchSomeOtherEnum(s8);
let s9: SomeStructEnum = SomeStructEnum::EnumStruct2{ f1: box some_fields{ field1:10 },
f2: box s2 };
let s9: SomeStructEnum =
SomeStructEnum::EnumStruct2 { f1: box some_fields { field1: 10 }, f2: box s2 };
matchSomeStructEnum(s9);
for x in &vec![1, 2, 3] {
@ -409,8 +416,7 @@ impl<'a> Pattern<'a> for CharEqPattern {
struct CharSearcher<'a>(<CharEqPattern as Pattern<'a>>::Searcher);
pub trait Error {
}
pub trait Error {}
impl Error + 'static {
pub fn is<T: Error + 'static>(&self) -> bool {
@ -437,13 +443,13 @@ fn test_format_args() {
print!("x is {}, y is {1}, name is {n}", x, y, n = name);
}
extern {
extern "C" {
static EXTERN_FOO: u8;
fn extern_foo(a: u8, b: i32) -> String;
}
struct Rls699 {
f: u32,
f: u32,
}
fn new(f: u32) -> Rls699 {

View File

@ -3,6 +3,6 @@
extern crate foo;
#[no_mangle]
pub extern fn bar() {
pub extern "C" fn bar() {
foo::foo();
}

View File

@ -2,7 +2,7 @@
#![feature(static_nobundle)]
#[link(name = "aaa", kind = "static-nobundle")]
extern {
extern "C" {
pub fn native_func();
}

View File

@ -1,6 +1,6 @@
#![crate_type = "staticlib"]
#[link(name = "foo", kind = "static")]
extern {}
extern "C" {}
fn main() {}

View File

@ -6,6 +6,6 @@ extern crate bar;
static A: bar::A = bar::A;
#[no_mangle]
pub extern fn a(a: u32, b: u32) -> u32 {
pub extern "C" fn a(a: u32, b: u32) -> u32 {
a / b
}

View File

@ -1,19 +1,21 @@
#![feature(lang_items, no_core, auto_traits)]
#![no_core]
#[lang="copy"]
trait Copy { }
#[lang = "copy"]
trait Copy {}
#[lang="sized"]
trait Sized { }
#[lang = "sized"]
trait Sized {}
#[lang = "freeze"]
auto trait Freeze {}
#[lang="start"]
fn start(_main: *const u8, _argc: isize, _argv: *const *const u8) -> isize { 0 }
#[lang = "start"]
fn start(_main: *const u8, _argc: isize, _argv: *const *const u8) -> isize {
0
}
extern {
extern "C" {
fn _foo() -> [u8; 16];
}

View File

@ -3,7 +3,9 @@
// For linking libstdc++ on MinGW
#![cfg_attr(all(windows, target_env = "gnu"), feature(static_nobundle))]
extern { fn get() -> u32; }
extern "C" {
fn get() -> u32;
}
fn main() {
let i = unsafe { get() };

View File

@ -4,13 +4,13 @@
extern crate foo;
#[link(wasm_import_module = "./me")]
extern {
extern "C" {
#[link_name = "me_in_dep"]
fn dep();
}
#[no_mangle]
pub extern fn foo() {
pub extern "C" fn foo() {
unsafe {
foo::dep();
dep();

View File

@ -2,6 +2,6 @@
#![deny(warnings)]
#[link(wasm_import_module = "./dep")]
extern {
extern "C" {
pub fn dep();
}

View File

@ -6,13 +6,15 @@ extern crate libc;
#[cfg(target_os = "macos")]
#[link(name = "CoreFoundation", kind = "framework")]
extern {
extern "C" {
fn CFRunLoopGetTypeID() -> libc::c_ulong;
}
#[cfg(target_os = "macos")]
pub fn main() {
unsafe { CFRunLoopGetTypeID(); }
unsafe {
CFRunLoopGetTypeID();
}
}
#[cfg(not(target_os = "macos"))]

View File

@ -5,7 +5,7 @@ pub trait Foo {
}
#[doc(alias = "foo")] //~ ERROR
extern {}
extern "C" {}
#[doc(alias = "bar")] //~ ERROR
impl Bar {
@ -17,5 +17,7 @@ impl Bar {
impl Foo for Bar {
#[doc(alias = "assoc")] //~ ERROR
type X = i32;
fn foo() -> Self::X { 0 }
fn foo() -> Self::X {
0
}
}

View File

@ -45,6 +45,6 @@ macro_rules! some_macro {
() => {};
}
extern {
extern "C" {
pub type ExternType;
}

View File

@ -1,3 +1,3 @@
extern {
extern "C" {
pub fn extern_c_fn();
}

View File

@ -1,7 +1,7 @@
#![feature(extern_types)]
mod sub {
extern {
extern "C" {
/// Another extern type.
pub type C2;
pub fn f2();
@ -10,7 +10,7 @@ mod sub {
}
pub mod sub2 {
extern {
extern "C" {
// @has foreigntype_reexport/sub2/foreigntype.C.html
pub type C;
// @has foreigntype_reexport/sub2/fn.f.html
@ -21,7 +21,7 @@ pub mod sub2 {
}
mod sub3 {
extern {
extern "C" {
pub type C4;
pub fn f4();
pub static K4: usize;
@ -35,7 +35,7 @@ mod sub3 {
// @has foreigntype_reexport/index.html '//a[@class="foreigntype"]' 'C2'
// @has foreigntype_reexport/index.html '//a[@class="fn"]' 'f2'
// @has foreigntype_reexport/index.html '//a[@class="static"]' 'K2'
pub use self::sub::{C2, f2, K as K2};
pub use self::sub::{f2, C2, K as K2};
// @has foreigntype_reexport/index.html '//a[@class="foreigntype"]' 'C'
// @has foreigntype_reexport/index.html '//a[@class="fn"]' 'f'
@ -43,7 +43,7 @@ pub use self::sub::{C2, f2, K as K2};
// @has foreigntype_reexport/index.html '//code' 'pub use self::sub2::C as C3;'
// @has foreigntype_reexport/index.html '//code' 'pub use self::sub2::f as f3;'
// @has foreigntype_reexport/index.html '//code' 'pub use self::sub2::K3;'
pub use self::sub2::{C as C3, f as f3, K3};
pub use self::sub2::{f as f3, C as C3, K3};
// @has foreigntype_reexport/foreigntype.C4.html
// @has foreigntype_reexport/fn.f4.html

Some files were not shown because too many files have changed in this diff Show More