| // Compiler: | |
| // | |
| // Run-time: | |
| // status: 0 | |
| // Checks that the `#[linkage]` flavours another object file is allowed to override are emitted as | |
| // weak symbols, by linking against `tests/c/weak_function_linkage.c`, which defines the same | |
| // symbols strongly. | |
| #![feature(linkage, no_core)] | |
| #![no_std] | |
| #![no_core] | |
| #![no_main] | |
| extern crate mini_core; | |
| use mini_core::*; | |
| #[linkage = "weak"] | |
| #[no_mangle] | |
| extern "C" fn weak_function() -> i32 { | |
| 0 | |
| } | |
| // `_odr` promises every definition of the symbol is equivalent, which lets a backend call this body | |
| // instead of the one in the C file. They spell the same value for that reason. | |
| #[linkage = "weak_odr"] | |
| #[no_mangle] | |
| extern "C" fn weak_odr_function() -> i32 { | |
| 2 | |
| } | |
| #[linkage = "linkonce"] | |
| #[no_mangle] | |
| extern "C" fn linkonce_function() -> i32 { | |
| 0 | |
| } | |
| #[linkage = "linkonce_odr"] | |
| #[no_mangle] | |
| extern "C" fn linkonce_odr_function() -> i32 { | |
| 4 | |
| } | |
| // Not overridden by the C side: the definition here is the one that runs. | |
| #[linkage = "weak"] | |
| #[no_mangle] | |
| extern "C" fn only_weak_function() -> i32 { | |
| 6 | |
| } | |
| // The real definition is the one in the C file; a backend may call it or emit an equivalent copy of | |
| // this body, so both spell the same value. | |
| #[linkage = "available_externally"] | |
| #[no_mangle] | |
| extern "C" fn available_externally_function() -> i32 { | |
| 7 | |
| } | |
| // GCC drops `weak` from a function that is also `inline`: a backend that keeps the hint emits this | |
| // as an ordinary global symbol and clashes with the C definition. rustc lints the hint as ignored | |
| // on a function with an explicit `#[linkage]`, hence the `allow`. | |
| #[linkage = "weak"] | |
| #[inline] | |
| #[no_mangle] | |
| #[allow(unused_attributes)] | |
| extern "C" fn weak_inline_function() -> i32 { | |
| 0 | |
| } | |
| extern "C" { | |
| fn c_call_all() -> i32; | |
| } | |
| #[no_mangle] | |
| extern "C" fn main(_argc: i32, _argv: *const *const u8) -> i32 { | |
| let result = unsafe { c_call_all() }; | |
| if result != 0 { | |
| return result; | |
| } | |
| if weak_function() != 1 { | |
| return 1; | |
| } | |
| if weak_odr_function() != 2 { | |
| return 2; | |
| } | |
| if linkonce_function() != 3 { | |
| return 3; | |
| } | |
| if linkonce_odr_function() != 4 { | |
| return 4; | |
| } | |
| if only_weak_function() != 6 { | |
| return 6; | |
| } | |
| if available_externally_function() != 7 { | |
| return 7; | |
| } | |
| if weak_inline_function() != 8 { | |
| return 8; | |
| } | |
| 0 | |
| } |