diff options
Diffstat (limited to 'src/test/run-make-fulldeps')
713 files changed, 10475 insertions, 0 deletions
diff --git a/src/test/run-make-fulldeps/a-b-a-linker-guard/Makefile b/src/test/run-make-fulldeps/a-b-a-linker-guard/Makefile new file mode 100644 index 000000000..4a9b3d709 --- /dev/null +++ b/src/test/run-make-fulldeps/a-b-a-linker-guard/Makefile @@ -0,0 +1,15 @@ +-include ../tools.mk + +# Test that if we build `b` against a version of `a` that has one set +# of types, it will not run with a dylib that has a different set of +# types. + +# NOTE(eddyb) this test only works with the `legacy` mangling, +# and will probably get removed once `legacy` is gone. + +all: + $(RUSTC) a.rs --cfg x -C prefer-dynamic -Z unstable-options -C symbol-mangling-version=legacy + $(RUSTC) b.rs -C prefer-dynamic -Z unstable-options -C symbol-mangling-version=legacy + $(call RUN,b) + $(RUSTC) a.rs --cfg y -C prefer-dynamic -Z unstable-options -C symbol-mangling-version=legacy + $(call FAIL,b) diff --git a/src/test/run-make-fulldeps/a-b-a-linker-guard/a.rs b/src/test/run-make-fulldeps/a-b-a-linker-guard/a.rs new file mode 100644 index 000000000..aa07b1e71 --- /dev/null +++ b/src/test/run-make-fulldeps/a-b-a-linker-guard/a.rs @@ -0,0 +1,8 @@ +#![crate_name = "a"] +#![crate_type = "dylib"] + +#[cfg(x)] +pub fn foo(x: u32) { } + +#[cfg(y)] +pub fn foo(x: i32) { } diff --git a/src/test/run-make-fulldeps/a-b-a-linker-guard/b.rs b/src/test/run-make-fulldeps/a-b-a-linker-guard/b.rs new file mode 100644 index 000000000..f30df120a --- /dev/null +++ b/src/test/run-make-fulldeps/a-b-a-linker-guard/b.rs @@ -0,0 +1,7 @@ +#![crate_name = "b"] + +extern crate a; + +fn main() { + a::foo(22_u32); +} diff --git a/src/test/run-make-fulldeps/alloc-no-oom-handling/Makefile b/src/test/run-make-fulldeps/alloc-no-oom-handling/Makefile new file mode 100644 index 000000000..eb6ad9bd1 --- /dev/null +++ b/src/test/run-make-fulldeps/alloc-no-oom-handling/Makefile @@ -0,0 +1,4 @@ +-include ../tools.mk + +all: + $(RUSTC) --edition=2021 -Dwarnings --crate-type=rlib ../../../../library/alloc/src/lib.rs --cfg no_global_oom_handling diff --git a/src/test/run-make-fulldeps/allow-non-lint-warnings-cmdline/Makefile b/src/test/run-make-fulldeps/allow-non-lint-warnings-cmdline/Makefile new file mode 100644 index 000000000..c14006cc2 --- /dev/null +++ b/src/test/run-make-fulldeps/allow-non-lint-warnings-cmdline/Makefile @@ -0,0 +1,11 @@ +-include ../tools.mk + +# Test that -A warnings makes the 'empty trait list for derive' warning go away +OUT=$(shell $(RUSTC) foo.rs -A warnings 2>&1 | grep "warning" ) + +all: foo + test -z '$(OUT)' + +# This is just to make sure the above command actually succeeds +foo: + $(RUSTC) foo.rs -A warnings diff --git a/src/test/run-make-fulldeps/allow-non-lint-warnings-cmdline/foo.rs b/src/test/run-make-fulldeps/allow-non-lint-warnings-cmdline/foo.rs new file mode 100644 index 000000000..46e72da2d --- /dev/null +++ b/src/test/run-make-fulldeps/allow-non-lint-warnings-cmdline/foo.rs @@ -0,0 +1,5 @@ +#[derive()] +#[derive(Copy, Clone)] +pub struct Foo; + +pub fn main() { } diff --git a/src/test/run-make-fulldeps/allow-warnings-cmdline-stability/Makefile b/src/test/run-make-fulldeps/allow-warnings-cmdline-stability/Makefile new file mode 100644 index 000000000..3eecaf931 --- /dev/null +++ b/src/test/run-make-fulldeps/allow-warnings-cmdline-stability/Makefile @@ -0,0 +1,15 @@ +-include ../tools.mk + +# Test that -A warnings makes the 'empty trait list for derive' warning go away +DEP=$(shell $(RUSTC) bar.rs) +OUT=$(shell $(RUSTC) foo.rs -A warnings 2>&1 | grep "warning" ) + +all: foo bar + test -z '$(OUT)' + +# These are just to ensure that the above commands actually work +bar: + $(RUSTC) bar.rs + +foo: bar + $(RUSTC) foo.rs -A warnings diff --git a/src/test/run-make-fulldeps/allow-warnings-cmdline-stability/bar.rs b/src/test/run-make-fulldeps/allow-warnings-cmdline-stability/bar.rs new file mode 100644 index 000000000..3dcfb9dad --- /dev/null +++ b/src/test/run-make-fulldeps/allow-warnings-cmdline-stability/bar.rs @@ -0,0 +1,5 @@ +#![crate_type = "lib"] +#![feature(staged_api)] +#![unstable(feature = "unstable_test_feature", issue = "none")] + +pub fn baz() {} diff --git a/src/test/run-make-fulldeps/allow-warnings-cmdline-stability/foo.rs b/src/test/run-make-fulldeps/allow-warnings-cmdline-stability/foo.rs new file mode 100644 index 000000000..869b54354 --- /dev/null +++ b/src/test/run-make-fulldeps/allow-warnings-cmdline-stability/foo.rs @@ -0,0 +1,5 @@ +#![feature(unstable_test_feature)] + +extern crate bar; + +pub fn main() { bar::baz() } diff --git a/src/test/run-make-fulldeps/archive-duplicate-names/Makefile b/src/test/run-make-fulldeps/archive-duplicate-names/Makefile new file mode 100644 index 000000000..93711c41d --- /dev/null +++ b/src/test/run-make-fulldeps/archive-duplicate-names/Makefile @@ -0,0 +1,11 @@ +-include ../tools.mk + +all: + mkdir $(TMPDIR)/a + mkdir $(TMPDIR)/b + $(call COMPILE_OBJ,$(TMPDIR)/a/foo.o,foo.c) + $(call COMPILE_OBJ,$(TMPDIR)/b/foo.o,bar.c) + $(AR) crus $(TMPDIR)/libfoo.a $(TMPDIR)/a/foo.o $(TMPDIR)/b/foo.o + $(RUSTC) foo.rs + $(RUSTC) bar.rs + $(call RUN,bar) diff --git a/src/test/run-make-fulldeps/archive-duplicate-names/bar.c b/src/test/run-make-fulldeps/archive-duplicate-names/bar.c new file mode 100644 index 000000000..e42599986 --- /dev/null +++ b/src/test/run-make-fulldeps/archive-duplicate-names/bar.c @@ -0,0 +1 @@ +void bar() {} diff --git a/src/test/run-make-fulldeps/archive-duplicate-names/bar.rs b/src/test/run-make-fulldeps/archive-duplicate-names/bar.rs new file mode 100644 index 000000000..994a98c2c --- /dev/null +++ b/src/test/run-make-fulldeps/archive-duplicate-names/bar.rs @@ -0,0 +1,5 @@ +extern crate foo; + +fn main() { + foo::baz(); +} diff --git a/src/test/run-make-fulldeps/archive-duplicate-names/foo.c b/src/test/run-make-fulldeps/archive-duplicate-names/foo.c new file mode 100644 index 000000000..85e6cd8c3 --- /dev/null +++ b/src/test/run-make-fulldeps/archive-duplicate-names/foo.c @@ -0,0 +1 @@ +void foo() {} diff --git a/src/test/run-make-fulldeps/archive-duplicate-names/foo.rs b/src/test/run-make-fulldeps/archive-duplicate-names/foo.rs new file mode 100644 index 000000000..0bf13c406 --- /dev/null +++ b/src/test/run-make-fulldeps/archive-duplicate-names/foo.rs @@ -0,0 +1,14 @@ +#![crate_type = "rlib"] + +#[link(name = "foo", kind = "static")] +extern "C" { + fn foo(); + fn bar(); +} + +pub fn baz() { + unsafe { + foo(); + bar(); + } +} diff --git a/src/test/run-make-fulldeps/arguments-non-c-like-enum/Makefile b/src/test/run-make-fulldeps/arguments-non-c-like-enum/Makefile new file mode 100644 index 000000000..5b5d620ef --- /dev/null +++ b/src/test/run-make-fulldeps/arguments-non-c-like-enum/Makefile @@ -0,0 +1,7 @@ +-include ../tools.mk + +all: + $(RUSTC) --crate-type=staticlib nonclike.rs + $(CC) test.c $(call STATICLIB,nonclike) $(call OUT_EXE,test) \ + $(EXTRACFLAGS) $(EXTRACXXFLAGS) + $(call RUN,test) diff --git a/src/test/run-make-fulldeps/arguments-non-c-like-enum/nonclike.rs b/src/test/run-make-fulldeps/arguments-non-c-like-enum/nonclike.rs new file mode 100644 index 000000000..57c2c6127 --- /dev/null +++ b/src/test/run-make-fulldeps/arguments-non-c-like-enum/nonclike.rs @@ -0,0 +1,31 @@ +#[repr(C, u8)] +pub enum TT { + AA(u64, u64), + BB, +} + +#[no_mangle] +pub extern "C" fn tt_add(a: TT, b: TT) -> u64 { + match (a, b) { + (TT::AA(a1, b1), TT::AA(a2, b2)) => a1 + a2 + b1 + b2, + (TT::AA(a1, b1), TT::BB) => a1 + b1, + (TT::BB, TT::AA(a1, b1)) => a1 + b1, + _ => 0, + } +} + +#[repr(C, u8)] +pub enum T { + A(u64), + B, +} + +#[no_mangle] +pub extern "C" fn t_add(a: T, b: T) -> u64 { + match (a, b) { + (T::A(a), T::A(b)) => a + b, + (T::A(a), T::B) => a, + (T::B, T::A(b)) => b, + _ => 0, + } +} diff --git a/src/test/run-make-fulldeps/arguments-non-c-like-enum/test.c b/src/test/run-make-fulldeps/arguments-non-c-like-enum/test.c new file mode 100644 index 000000000..0a1621e49 --- /dev/null +++ b/src/test/run-make-fulldeps/arguments-non-c-like-enum/test.c @@ -0,0 +1,66 @@ +#include <stdint.h> +#include <assert.h> + +#include <stdio.h> + +/* This is the code generated by cbindgen 0.12.1 for the `enum TT` + * type in nonclike.rs . */ +enum TT_Tag { + AA, + BB, +}; +typedef uint8_t TT_Tag; + +typedef struct { + uint64_t _0; + uint64_t _1; +} AA_Body; + +typedef struct { + TT_Tag tag; + union { + AA_Body aa; + }; +} TT; + +/* This is the code generated by cbindgen 0.12.1 for the `enum T` type + * in nonclike.rs . */ +enum T_Tag { + A, + B, +}; +typedef uint8_t T_Tag; + +typedef struct { + uint64_t _0; +} A_Body; + +typedef struct { + T_Tag tag; + union { + A_Body a; + }; +} T; + +/* These symbols are defined by the Rust staticlib built from + * nonclike.rs. */ +extern uint64_t t_add(T a, T b); +extern uint64_t tt_add(TT a, TT b); + +int main(int argc, char *argv[]) { + (void)argc; (void)argv; + + /* This example works. */ + TT xx = { .tag = AA, .aa = { ._0 = 1, ._1 = 2 } }; + TT yy = { .tag = AA, .aa = { ._0 = 10, ._1 = 20 } }; + uint64_t rr = tt_add(xx, yy); + assert(33 == rr); + + /* This one used to return an incorrect result (see issue #68190). */ + T x = { .tag = A, .a = { ._0 = 1 } }; + T y = { .tag = A, .a = { ._0 = 10 } }; + uint64_t r = t_add(x, y); + assert(11 == r); + + return 0; +} diff --git a/src/test/run-make-fulldeps/atomic-lock-free/Makefile b/src/test/run-make-fulldeps/atomic-lock-free/Makefile new file mode 100644 index 000000000..9e8b4fabf --- /dev/null +++ b/src/test/run-make-fulldeps/atomic-lock-free/Makefile @@ -0,0 +1,48 @@ +-include ../tools.mk + +# This tests ensure that atomic types are never lowered into runtime library calls that are not +# guaranteed to be lock-free. + +all: +ifeq ($(UNAME),Linux) +ifeq ($(filter x86,$(LLVM_COMPONENTS)),x86) + $(RUSTC) --target=i686-unknown-linux-gnu atomic_lock_free.rs + nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add + $(RUSTC) --target=x86_64-unknown-linux-gnu atomic_lock_free.rs + nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add +endif +ifeq ($(filter arm,$(LLVM_COMPONENTS)),arm) + $(RUSTC) --target=arm-unknown-linux-gnueabi atomic_lock_free.rs + nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add + $(RUSTC) --target=arm-unknown-linux-gnueabihf atomic_lock_free.rs + nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add + $(RUSTC) --target=armv7-unknown-linux-gnueabihf atomic_lock_free.rs + nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add + $(RUSTC) --target=thumbv7neon-unknown-linux-gnueabihf atomic_lock_free.rs + nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add +endif +ifeq ($(filter aarch64,$(LLVM_COMPONENTS)),aarch64) + $(RUSTC) --target=aarch64-unknown-linux-gnu atomic_lock_free.rs + nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add +endif +ifeq ($(filter mips,$(LLVM_COMPONENTS)),mips) + $(RUSTC) --target=mips-unknown-linux-gnu atomic_lock_free.rs + nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add + $(RUSTC) --target=mipsel-unknown-linux-gnu atomic_lock_free.rs + nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add +endif +ifeq ($(filter powerpc,$(LLVM_COMPONENTS)),powerpc) + $(RUSTC) --target=powerpc-unknown-linux-gnu atomic_lock_free.rs + nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add + $(RUSTC) --target=powerpc-unknown-linux-gnuspe atomic_lock_free.rs + nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add + $(RUSTC) --target=powerpc64-unknown-linux-gnu atomic_lock_free.rs + nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add + $(RUSTC) --target=powerpc64le-unknown-linux-gnu atomic_lock_free.rs + nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add +endif +ifeq ($(filter systemz,$(LLVM_COMPONENTS)),systemz) + $(RUSTC) --target=s390x-unknown-linux-gnu atomic_lock_free.rs + nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add +endif +endif diff --git a/src/test/run-make-fulldeps/atomic-lock-free/atomic_lock_free.rs b/src/test/run-make-fulldeps/atomic-lock-free/atomic_lock_free.rs new file mode 100644 index 000000000..47d90b185 --- /dev/null +++ b/src/test/run-make-fulldeps/atomic-lock-free/atomic_lock_free.rs @@ -0,0 +1,66 @@ +#![feature(no_core, intrinsics, lang_items)] +#![crate_type="rlib"] +#![no_core] + +extern "rust-intrinsic" { + fn atomic_xadd_seqcst<T>(dst: *mut T, src: T) -> T; +} + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} +#[lang = "freeze"] +trait Freeze {} + +impl<T: ?Sized> Copy for *mut T {} + +#[cfg(target_has_atomic = "8")] +pub unsafe fn atomic_u8(x: *mut u8) { + atomic_xadd_seqcst(x, 1); + atomic_xadd_seqcst(x, 1); +} +#[cfg(target_has_atomic = "8")] +pub unsafe fn atomic_i8(x: *mut i8) { + atomic_xadd_seqcst(x, 1); +} +#[cfg(target_has_atomic = "16")] +pub unsafe fn atomic_u16(x: *mut u16) { + atomic_xadd_seqcst(x, 1); +} +#[cfg(target_has_atomic = "16")] +pub unsafe fn atomic_i16(x: *mut i16) { + atomic_xadd_seqcst(x, 1); +} +#[cfg(target_has_atomic = "32")] +pub unsafe fn atomic_u32(x: *mut u32) { + atomic_xadd_seqcst(x, 1); +} +#[cfg(target_has_atomic = "32")] +pub unsafe fn atomic_i32(x: *mut i32) { + atomic_xadd_seqcst(x, 1); +} +#[cfg(target_has_atomic = "64")] +pub unsafe fn atomic_u64(x: *mut u64) { + atomic_xadd_seqcst(x, 1); +} +#[cfg(target_has_atomic = "64")] +pub unsafe fn atomic_i64(x: *mut i64) { + atomic_xadd_seqcst(x, 1); +} +#[cfg(target_has_atomic = "128")] +pub unsafe fn atomic_u128(x: *mut u128) { + atomic_xadd_seqcst(x, 1); +} +#[cfg(target_has_atomic = "128")] +pub unsafe fn atomic_i128(x: *mut i128) { + atomic_xadd_seqcst(x, 1); +} +#[cfg(target_has_atomic = "ptr")] +pub unsafe fn atomic_usize(x: *mut usize) { + atomic_xadd_seqcst(x, 1); +} +#[cfg(target_has_atomic = "ptr")] +pub unsafe fn atomic_isize(x: *mut isize) { + atomic_xadd_seqcst(x, 1); +} diff --git a/src/test/run-make-fulldeps/bare-outfile/Makefile b/src/test/run-make-fulldeps/bare-outfile/Makefile new file mode 100644 index 000000000..baa4c1c02 --- /dev/null +++ b/src/test/run-make-fulldeps/bare-outfile/Makefile @@ -0,0 +1,6 @@ +-include ../tools.mk + +all: + cp foo.rs $(TMPDIR) + cd $(TMPDIR) && $(RUSTC) -o foo foo.rs + $(call RUN,foo) diff --git a/src/test/run-make-fulldeps/bare-outfile/foo.rs b/src/test/run-make-fulldeps/bare-outfile/foo.rs new file mode 100644 index 000000000..f79c691f0 --- /dev/null +++ b/src/test/run-make-fulldeps/bare-outfile/foo.rs @@ -0,0 +1,2 @@ +fn main() { +} diff --git a/src/test/run-make-fulldeps/c-dynamic-dylib/Makefile b/src/test/run-make-fulldeps/c-dynamic-dylib/Makefile new file mode 100644 index 000000000..c524610bf --- /dev/null +++ b/src/test/run-make-fulldeps/c-dynamic-dylib/Makefile @@ -0,0 +1,12 @@ +-include ../tools.mk + +# ignore-macos +# +# This hits an assertion in the linker on older versions of osx apparently + +all: $(call DYLIB,cfoo) + $(RUSTC) foo.rs -C prefer-dynamic + $(RUSTC) bar.rs + $(call RUN,bar) + $(call REMOVE_DYLIBS,cfoo) + $(call FAIL,bar) diff --git a/src/test/run-make-fulldeps/c-dynamic-dylib/bar.rs b/src/test/run-make-fulldeps/c-dynamic-dylib/bar.rs new file mode 100644 index 000000000..b8c798ffd --- /dev/null +++ b/src/test/run-make-fulldeps/c-dynamic-dylib/bar.rs @@ -0,0 +1,5 @@ +extern crate foo; + +fn main() { + foo::rsfoo(); +} diff --git a/src/test/run-make-fulldeps/c-dynamic-dylib/cfoo.c b/src/test/run-make-fulldeps/c-dynamic-dylib/cfoo.c new file mode 100644 index 000000000..fea490cf9 --- /dev/null +++ b/src/test/run-make-fulldeps/c-dynamic-dylib/cfoo.c @@ -0,0 +1,4 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif +int foo() { return 0; } diff --git a/src/test/run-make-fulldeps/c-dynamic-dylib/foo.rs b/src/test/run-make-fulldeps/c-dynamic-dylib/foo.rs new file mode 100644 index 000000000..9f7a9e221 --- /dev/null +++ b/src/test/run-make-fulldeps/c-dynamic-dylib/foo.rs @@ -0,0 +1,10 @@ +#![crate_type = "dylib"] + +#[link(name = "cfoo")] +extern "C" { + fn foo(); +} + +pub fn rsfoo() { + unsafe { foo() } +} diff --git a/src/test/run-make-fulldeps/c-dynamic-rlib/Makefile b/src/test/run-make-fulldeps/c-dynamic-rlib/Makefile new file mode 100644 index 000000000..91343e73e --- /dev/null +++ b/src/test/run-make-fulldeps/c-dynamic-rlib/Makefile @@ -0,0 +1,15 @@ +-include ../tools.mk + +# ignore-macos +# +# This hits an assertion in the linker on older versions of osx apparently + +# This overrides the LD_LIBRARY_PATH for RUN +TARGET_RPATH_DIR:=$(TARGET_RPATH_DIR):$(TMPDIR) + +all: $(call DYLIB,cfoo) + $(RUSTC) foo.rs + $(RUSTC) bar.rs + $(call RUN,bar) + $(call REMOVE_DYLIBS,cfoo) + $(call FAIL,bar) diff --git a/src/test/run-make-fulldeps/c-dynamic-rlib/bar.rs b/src/test/run-make-fulldeps/c-dynamic-rlib/bar.rs new file mode 100644 index 000000000..b8c798ffd --- /dev/null +++ b/src/test/run-make-fulldeps/c-dynamic-rlib/bar.rs @@ -0,0 +1,5 @@ +extern crate foo; + +fn main() { + foo::rsfoo(); +} diff --git a/src/test/run-make-fulldeps/c-dynamic-rlib/cfoo.c b/src/test/run-make-fulldeps/c-dynamic-rlib/cfoo.c new file mode 100644 index 000000000..fea490cf9 --- /dev/null +++ b/src/test/run-make-fulldeps/c-dynamic-rlib/cfoo.c @@ -0,0 +1,4 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif +int foo() { return 0; } diff --git a/src/test/run-make-fulldeps/c-dynamic-rlib/foo.rs b/src/test/run-make-fulldeps/c-dynamic-rlib/foo.rs new file mode 100644 index 000000000..3dd376f1f --- /dev/null +++ b/src/test/run-make-fulldeps/c-dynamic-rlib/foo.rs @@ -0,0 +1,10 @@ +#![crate_type = "rlib"] + +#[link(name = "cfoo")] +extern "C" { + fn foo(); +} + +pub fn rsfoo() { + unsafe { foo() } +} diff --git a/src/test/run-make-fulldeps/c-link-to-rust-dylib/Makefile b/src/test/run-make-fulldeps/c-link-to-rust-dylib/Makefile new file mode 100644 index 000000000..98e112a37 --- /dev/null +++ b/src/test/run-make-fulldeps/c-link-to-rust-dylib/Makefile @@ -0,0 +1,17 @@ +-include ../tools.mk + +all: $(TMPDIR)/$(call BIN,bar) + $(call RUN,bar) + $(call REMOVE_DYLIBS,foo) + $(call FAIL,bar) + +ifdef IS_MSVC +$(TMPDIR)/$(call BIN,bar): $(call DYLIB,foo) + $(CC) bar.c $(TMPDIR)/foo.dll.lib $(call OUT_EXE,bar) +else +$(TMPDIR)/$(call BIN,bar): $(call DYLIB,foo) + $(CC) bar.c -lfoo -o $(call RUN_BINFILE,bar) -L $(TMPDIR) +endif + +$(call DYLIB,foo): foo.rs + $(RUSTC) foo.rs diff --git a/src/test/run-make-fulldeps/c-link-to-rust-dylib/bar.c b/src/test/run-make-fulldeps/c-link-to-rust-dylib/bar.c new file mode 100644 index 000000000..bb4036b06 --- /dev/null +++ b/src/test/run-make-fulldeps/c-link-to-rust-dylib/bar.c @@ -0,0 +1,6 @@ +void foo(); + +int main() { + foo(); + return 0; +} diff --git a/src/test/run-make-fulldeps/c-link-to-rust-dylib/foo.rs b/src/test/run-make-fulldeps/c-link-to-rust-dylib/foo.rs new file mode 100644 index 000000000..f197fa513 --- /dev/null +++ b/src/test/run-make-fulldeps/c-link-to-rust-dylib/foo.rs @@ -0,0 +1,4 @@ +#![crate_type = "dylib"] + +#[no_mangle] +pub extern "C" fn foo() {} diff --git a/src/test/run-make-fulldeps/c-link-to-rust-staticlib/Makefile b/src/test/run-make-fulldeps/c-link-to-rust-staticlib/Makefile new file mode 100644 index 000000000..687b59ac0 --- /dev/null +++ b/src/test/run-make-fulldeps/c-link-to-rust-staticlib/Makefile @@ -0,0 +1,12 @@ +-include ../tools.mk + +# ignore-freebsd +# FIXME + +all: + $(RUSTC) foo.rs + $(CC) bar.c $(call STATICLIB,foo) $(call OUT_EXE,bar) \ + $(EXTRACFLAGS) $(EXTRACXXFLAGS) + $(call RUN,bar) + rm $(call STATICLIB,foo) + $(call RUN,bar) diff --git a/src/test/run-make-fulldeps/c-link-to-rust-staticlib/bar.c b/src/test/run-make-fulldeps/c-link-to-rust-staticlib/bar.c new file mode 100644 index 000000000..bb4036b06 --- /dev/null +++ b/src/test/run-make-fulldeps/c-link-to-rust-staticlib/bar.c @@ -0,0 +1,6 @@ +void foo(); + +int main() { + foo(); + return 0; +} diff --git a/src/test/run-make-fulldeps/c-link-to-rust-staticlib/foo.rs b/src/test/run-make-fulldeps/c-link-to-rust-staticlib/foo.rs new file mode 100644 index 000000000..2e59432cd --- /dev/null +++ b/src/test/run-make-fulldeps/c-link-to-rust-staticlib/foo.rs @@ -0,0 +1,4 @@ +#![crate_type = "staticlib"] + +#[no_mangle] +pub extern "C" fn foo() {} diff --git a/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/Makefile b/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/Makefile new file mode 100644 index 000000000..f124ca2ab --- /dev/null +++ b/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/Makefile @@ -0,0 +1,6 @@ +-include ../tools.mk + +all: + $(RUSTC) checkrust.rs + $(CC) test.c $(call STATICLIB,checkrust) $(call OUT_EXE,test) $(EXTRACFLAGS) + $(call RUN,test) diff --git a/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/checkrust.rs b/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/checkrust.rs new file mode 100644 index 000000000..5830ef033 --- /dev/null +++ b/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/checkrust.rs @@ -0,0 +1,148 @@ +#![crate_type = "staticlib"] +#![feature(c_variadic)] +#![feature(rustc_private)] + +extern crate libc; + +use libc::{c_char, c_double, c_int, c_long, c_longlong}; +use std::ffi::VaList; +use std::ffi::{CString, CStr}; + +macro_rules! continue_if { + ($cond:expr) => { + if !($cond) { + return 0xff; + } + } +} + +unsafe fn compare_c_str(ptr: *const c_char, val: &str) -> bool { + let cstr0 = CStr::from_ptr(ptr); + match CString::new(val) { + Ok(cstr1) => &*cstr1 == cstr0, + Err(_) => false, + } +} + +#[no_mangle] +pub unsafe extern "C" fn check_list_0(mut ap: VaList) -> usize { + continue_if!(ap.arg::<c_longlong>() == 1); + continue_if!(ap.arg::<c_int>() == 2); + continue_if!(ap.arg::<c_longlong>() == 3); + 0 +} + +#[no_mangle] +pub unsafe extern "C" fn check_list_1(mut ap: VaList) -> usize { + continue_if!(ap.arg::<c_int>() == -1); + continue_if!(ap.arg::<c_char>() == 'A' as c_char); + continue_if!(ap.arg::<c_char>() == '4' as c_char); + continue_if!(ap.arg::<c_char>() == ';' as c_char); + continue_if!(ap.arg::<c_int>() == 0x32); + continue_if!(ap.arg::<c_int>() == 0x10000001); + continue_if!(compare_c_str(ap.arg::<*const c_char>(), "Valid!")); + 0 +} + +#[no_mangle] +pub unsafe extern "C" fn check_list_2(mut ap: VaList) -> usize { + continue_if!(ap.arg::<c_double>().floor() == 3.14f64.floor()); + continue_if!(ap.arg::<c_long>() == 12); + continue_if!(ap.arg::<c_char>() == 'a' as c_char); + continue_if!(ap.arg::<c_double>().floor() == 6.18f64.floor()); + continue_if!(compare_c_str(ap.arg::<*const c_char>(), "Hello")); + continue_if!(ap.arg::<c_int>() == 42); + continue_if!(compare_c_str(ap.arg::<*const c_char>(), "World")); + 0 +} + +#[no_mangle] +pub unsafe extern "C" fn check_list_copy_0(mut ap: VaList) -> usize { + continue_if!(ap.arg::<c_double>().floor() == 6.28f64.floor()); + continue_if!(ap.arg::<c_int>() == 16); + continue_if!(ap.arg::<c_char>() == 'A' as c_char); + continue_if!(compare_c_str(ap.arg::<*const c_char>(), "Skip Me!")); + ap.with_copy(|mut ap| { + if compare_c_str(ap.arg::<*const c_char>(), "Correct") { + 0 + } else { + 0xff + } + }) +} + +#[no_mangle] +pub unsafe extern "C" fn check_varargs_0(_: c_int, mut ap: ...) -> usize { + continue_if!(ap.arg::<c_int>() == 42); + continue_if!(compare_c_str(ap.arg::<*const c_char>(), "Hello, World!")); + 0 +} + +#[no_mangle] +pub unsafe extern "C" fn check_varargs_1(_: c_int, mut ap: ...) -> usize { + continue_if!(ap.arg::<c_double>().floor() == 3.14f64.floor()); + continue_if!(ap.arg::<c_long>() == 12); + continue_if!(ap.arg::<c_char>() == 'A' as c_char); + continue_if!(ap.arg::<c_longlong>() == 1); + 0 +} + +#[no_mangle] +pub unsafe extern "C" fn check_varargs_2(_: c_int, _ap: ...) -> usize { + 0 +} + +#[no_mangle] +pub unsafe extern "C" fn check_varargs_3(_: c_int, mut ap: ...) -> usize { + continue_if!(ap.arg::<c_int>() == 1); + continue_if!(ap.arg::<c_int>() == 2); + continue_if!(ap.arg::<c_int>() == 3); + continue_if!(ap.arg::<c_int>() == 4); + continue_if!(ap.arg::<c_int>() == 5); + continue_if!(ap.arg::<c_int>() == 6); + continue_if!(ap.arg::<c_int>() == 7); + continue_if!(ap.arg::<c_int>() == 8); + continue_if!(ap.arg::<c_int>() == 9); + continue_if!(ap.arg::<c_int>() == 10); + 0 +} + +#[no_mangle] +pub unsafe extern "C" fn check_varargs_4(_: c_double, mut ap: ...) -> usize { + continue_if!(ap.arg::<c_double>() == 1.0); + continue_if!(ap.arg::<c_double>() == 2.0); + continue_if!(ap.arg::<c_double>() == 3.0); + continue_if!(ap.arg::<c_double>() == 4.0); + continue_if!(ap.arg::<c_double>() == 5.0); + continue_if!(ap.arg::<c_double>() == 6.0); + continue_if!(ap.arg::<c_double>() == 7.0); + continue_if!(ap.arg::<c_double>() == 8.0); + continue_if!(ap.arg::<c_double>() == 9.0); + continue_if!(ap.arg::<c_double>() == 10.0); + 0 +} + +#[no_mangle] +pub unsafe extern "C" fn check_varargs_5(_: c_int, mut ap: ...) -> usize { + continue_if!(ap.arg::<c_double>() == 1.0); + continue_if!(ap.arg::<c_int>() == 1); + continue_if!(ap.arg::<c_double>() == 2.0); + continue_if!(ap.arg::<c_int>() == 2); + continue_if!(ap.arg::<c_double>() == 3.0); + continue_if!(ap.arg::<c_int>() == 3); + continue_if!(ap.arg::<c_double>() == 4.0); + continue_if!(ap.arg::<c_int>() == 4); + continue_if!(ap.arg::<c_int>() == 5); + continue_if!(ap.arg::<c_double>() == 5.0); + continue_if!(ap.arg::<c_int>() == 6); + continue_if!(ap.arg::<c_double>() == 6.0); + continue_if!(ap.arg::<c_int>() == 7); + continue_if!(ap.arg::<c_double>() == 7.0); + continue_if!(ap.arg::<c_int>() == 8); + continue_if!(ap.arg::<c_double>() == 8.0); + continue_if!(ap.arg::<c_int>() == 9); + continue_if!(ap.arg::<c_double>() == 9.0); + continue_if!(ap.arg::<c_int>() == 10); + continue_if!(ap.arg::<c_double>() == 10.0); + 0 +} diff --git a/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/test.c b/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/test.c new file mode 100644 index 000000000..5bdb51680 --- /dev/null +++ b/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/test.c @@ -0,0 +1,50 @@ +#include <stdarg.h> +#include <assert.h> +#include <stdint.h> +#include <stdlib.h> +#include <stdio.h> + +extern size_t check_list_0(va_list ap); +extern size_t check_list_1(va_list ap); +extern size_t check_list_2(va_list ap); +extern size_t check_list_copy_0(va_list ap); +extern size_t check_varargs_0(int fixed, ...); +extern size_t check_varargs_1(int fixed, ...); +extern size_t check_varargs_2(int fixed, ...); +extern size_t check_varargs_3(int fixed, ...); +extern size_t check_varargs_4(double fixed, ...); +extern size_t check_varargs_5(int fixed, ...); + +int test_rust(size_t (*fn)(va_list), ...) { + size_t ret = 0; + va_list ap; + va_start(ap, fn); + ret = fn(ap); + va_end(ap); + return ret; +} + +int main(int argc, char* argv[]) { + assert(test_rust(check_list_0, 0x01LL, 0x02, 0x03LL) == 0); + + assert(test_rust(check_list_1, -1, 'A', '4', ';', 0x32, 0x10000001, "Valid!") == 0); + + assert(test_rust(check_list_2, 3.14, 12l, 'a', 6.28, "Hello", 42, "World") == 0); + + assert(test_rust(check_list_copy_0, 6.28, 16, 'A', "Skip Me!", "Correct") == 0); + + assert(check_varargs_0(0, 42, "Hello, World!") == 0); + + assert(check_varargs_1(0, 3.14, 12l, 'A', 0x1LL) == 0); + + assert(check_varargs_2(0, "All", "of", "these", "are", "ignored", ".") == 0); + + assert(check_varargs_3(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) == 0); + + assert(check_varargs_4(0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0) == 0); + + assert(check_varargs_5(0, 1.0, 1, 2.0, 2, 3.0, 3, 4.0, 4, 5, 5.0, 6, 6.0, 7, 7.0, 8, 8.0, + 9, 9.0, 10, 10.0) == 0); + + return 0; +} diff --git a/src/test/run-make-fulldeps/c-static-dylib/Makefile b/src/test/run-make-fulldeps/c-static-dylib/Makefile new file mode 100644 index 000000000..f88786857 --- /dev/null +++ b/src/test/run-make-fulldeps/c-static-dylib/Makefile @@ -0,0 +1,9 @@ +-include ../tools.mk + +all: $(call NATIVE_STATICLIB,cfoo) + $(RUSTC) foo.rs -C prefer-dynamic + $(RUSTC) bar.rs + rm $(call NATIVE_STATICLIB,cfoo) + $(call RUN,bar) + $(call REMOVE_DYLIBS,foo) + $(call FAIL,bar) diff --git a/src/test/run-make-fulldeps/c-static-dylib/bar.rs b/src/test/run-make-fulldeps/c-static-dylib/bar.rs new file mode 100644 index 000000000..b8c798ffd --- /dev/null +++ b/src/test/run-make-fulldeps/c-static-dylib/bar.rs @@ -0,0 +1,5 @@ +extern crate foo; + +fn main() { + foo::rsfoo(); +} diff --git a/src/test/run-make-fulldeps/c-static-dylib/cfoo.c b/src/test/run-make-fulldeps/c-static-dylib/cfoo.c new file mode 100644 index 000000000..9fe07f82f --- /dev/null +++ b/src/test/run-make-fulldeps/c-static-dylib/cfoo.c @@ -0,0 +1 @@ +int foo() { return 0; } diff --git a/src/test/run-make-fulldeps/c-static-dylib/foo.rs b/src/test/run-make-fulldeps/c-static-dylib/foo.rs new file mode 100644 index 000000000..1e8af4d44 --- /dev/null +++ b/src/test/run-make-fulldeps/c-static-dylib/foo.rs @@ -0,0 +1,10 @@ +#![crate_type = "dylib"] + +#[link(name = "cfoo", kind = "static")] +extern "C" { + fn foo(); +} + +pub fn rsfoo() { + unsafe { foo() } +} diff --git a/src/test/run-make-fulldeps/c-static-rlib/Makefile b/src/test/run-make-fulldeps/c-static-rlib/Makefile new file mode 100644 index 000000000..be22b2728 --- /dev/null +++ b/src/test/run-make-fulldeps/c-static-rlib/Makefile @@ -0,0 +1,8 @@ +-include ../tools.mk + +all: $(call NATIVE_STATICLIB,cfoo) + $(RUSTC) foo.rs + $(RUSTC) bar.rs + $(call REMOVE_RLIBS,foo) + rm $(call NATIVE_STATICLIB,cfoo) + $(call RUN,bar) diff --git a/src/test/run-make-fulldeps/c-static-rlib/bar.rs b/src/test/run-make-fulldeps/c-static-rlib/bar.rs new file mode 100644 index 000000000..b8c798ffd --- /dev/null +++ b/src/test/run-make-fulldeps/c-static-rlib/bar.rs @@ -0,0 +1,5 @@ +extern crate foo; + +fn main() { + foo::rsfoo(); +} diff --git a/src/test/run-make-fulldeps/c-static-rlib/cfoo.c b/src/test/run-make-fulldeps/c-static-rlib/cfoo.c new file mode 100644 index 000000000..9fe07f82f --- /dev/null +++ b/src/test/run-make-fulldeps/c-static-rlib/cfoo.c @@ -0,0 +1 @@ +int foo() { return 0; } diff --git a/src/test/run-make-fulldeps/c-static-rlib/foo.rs b/src/test/run-make-fulldeps/c-static-rlib/foo.rs new file mode 100644 index 000000000..9c6d2080e --- /dev/null +++ b/src/test/run-make-fulldeps/c-static-rlib/foo.rs @@ -0,0 +1,10 @@ +#![crate_type = "rlib"] + +#[link(name = "cfoo", kind = "static")] +extern "C" { + fn foo(); +} + +pub fn rsfoo() { + unsafe { foo() } +} diff --git a/src/test/run-make-fulldeps/c-unwind-abi-catch-lib-panic/Makefile b/src/test/run-make-fulldeps/c-unwind-abi-catch-lib-panic/Makefile new file mode 100644 index 000000000..a8515c533 --- /dev/null +++ b/src/test/run-make-fulldeps/c-unwind-abi-catch-lib-panic/Makefile @@ -0,0 +1,30 @@ +-include ../tools.mk + +all: archive + # Compile `main.rs`, which will link into our library, and run it. + $(RUSTC) main.rs + $(call RUN,main) + +ifdef IS_MSVC +archive: add.o panic.o + # Now, create an archive using these two objects. + $(AR) crus $(TMPDIR)/add.lib $(TMPDIR)/add.o $(TMPDIR)/panic.o +else +archive: add.o panic.o + # Now, create an archive using these two objects. + $(AR) crus $(TMPDIR)/libadd.a $(TMPDIR)/add.o $(TMPDIR)/panic.o +endif + +# Compile `panic.rs` into an object file. +# +# Note that we invoke `rustc` directly, so we may emit an object rather +# than an archive. We'll do that later. +panic.o: + $(BARE_RUSTC) $(RUSTFLAGS) \ + --out-dir $(TMPDIR) \ + --emit=obj panic.rs + +# Compile `add.c` into an object file. +add.o: + $(call COMPILE_OBJ,$(TMPDIR)/add.o,add.c) + diff --git a/src/test/run-make-fulldeps/c-unwind-abi-catch-lib-panic/add.c b/src/test/run-make-fulldeps/c-unwind-abi-catch-lib-panic/add.c new file mode 100644 index 000000000..444359451 --- /dev/null +++ b/src/test/run-make-fulldeps/c-unwind-abi-catch-lib-panic/add.c @@ -0,0 +1,12 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif + +// An external function, defined in Rust. +extern void panic_if_greater_than_10(unsigned x); + +unsigned add_small_numbers(unsigned a, unsigned b) { + unsigned c = a + b; + panic_if_greater_than_10(c); + return c; +} diff --git a/src/test/run-make-fulldeps/c-unwind-abi-catch-lib-panic/main.rs b/src/test/run-make-fulldeps/c-unwind-abi-catch-lib-panic/main.rs new file mode 100644 index 000000000..78a71219c --- /dev/null +++ b/src/test/run-make-fulldeps/c-unwind-abi-catch-lib-panic/main.rs @@ -0,0 +1,35 @@ +//! A test for calling `C-unwind` functions across foreign function boundaries. +//! +//! This test triggers a panic in a Rust library that our foreign function invokes. This shows +//! that we can unwind through the C code in that library, and catch the underlying panic. +#![feature(c_unwind)] + +use std::panic::{catch_unwind, AssertUnwindSafe}; + +fn main() { + // Call `add_small_numbers`, passing arguments that will NOT trigger a panic. + let (a, b) = (9, 1); + let c = unsafe { add_small_numbers(a, b) }; + assert_eq!(c, 10); + + // Call `add_small_numbers`, passing arguments that will trigger a panic, and catch it. + let caught_unwind = catch_unwind(AssertUnwindSafe(|| { + let (a, b) = (10, 1); + let _c = unsafe { add_small_numbers(a, b) }; + unreachable!("should have unwound instead of returned"); + })); + + // Assert that we did indeed panic, then unwrap and downcast the panic into the sum. + assert!(caught_unwind.is_err()); + let panic_obj = caught_unwind.unwrap_err(); + let msg = panic_obj.downcast_ref::<String>().unwrap(); + assert_eq!(msg, "11"); +} + +#[link(name = "add", kind = "static")] +extern "C-unwind" { + /// An external function, defined in C. + /// + /// Returns the sum of two numbers, or panics if the sum is greater than 10. + fn add_small_numbers(a: u32, b: u32) -> u32; +} diff --git a/src/test/run-make-fulldeps/c-unwind-abi-catch-lib-panic/panic.rs b/src/test/run-make-fulldeps/c-unwind-abi-catch-lib-panic/panic.rs new file mode 100644 index 000000000..a99a04d5c --- /dev/null +++ b/src/test/run-make-fulldeps/c-unwind-abi-catch-lib-panic/panic.rs @@ -0,0 +1,12 @@ +#![crate_type = "staticlib"] +#![feature(c_unwind)] + +/// This function will panic if `x` is greater than 10. +/// +/// This function is called by `add_small_numbers`. +#[no_mangle] +pub extern "C-unwind" fn panic_if_greater_than_10(x: u32) { + if x > 10 { + panic!("{}", x); // That is too big! + } +} diff --git a/src/test/run-make-fulldeps/c-unwind-abi-catch-panic/Makefile b/src/test/run-make-fulldeps/c-unwind-abi-catch-panic/Makefile new file mode 100644 index 000000000..9553b7aee --- /dev/null +++ b/src/test/run-make-fulldeps/c-unwind-abi-catch-panic/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: $(call NATIVE_STATICLIB,add) + $(RUSTC) main.rs + $(call RUN,main) || exit 1 diff --git a/src/test/run-make-fulldeps/c-unwind-abi-catch-panic/add.c b/src/test/run-make-fulldeps/c-unwind-abi-catch-panic/add.c new file mode 100644 index 000000000..444359451 --- /dev/null +++ b/src/test/run-make-fulldeps/c-unwind-abi-catch-panic/add.c @@ -0,0 +1,12 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif + +// An external function, defined in Rust. +extern void panic_if_greater_than_10(unsigned x); + +unsigned add_small_numbers(unsigned a, unsigned b) { + unsigned c = a + b; + panic_if_greater_than_10(c); + return c; +} diff --git a/src/test/run-make-fulldeps/c-unwind-abi-catch-panic/main.rs b/src/test/run-make-fulldeps/c-unwind-abi-catch-panic/main.rs new file mode 100644 index 000000000..15d38d721 --- /dev/null +++ b/src/test/run-make-fulldeps/c-unwind-abi-catch-panic/main.rs @@ -0,0 +1,44 @@ +//! A test for calling `C-unwind` functions across foreign function boundaries. +//! +//! This test triggers a panic when calling a foreign function that calls *back* into Rust. +#![feature(c_unwind)] + +use std::panic::{catch_unwind, AssertUnwindSafe}; + +fn main() { + // Call `add_small_numbers`, passing arguments that will NOT trigger a panic. + let (a, b) = (9, 1); + let c = unsafe { add_small_numbers(a, b) }; + assert_eq!(c, 10); + + // Call `add_small_numbers`, passing arguments that will trigger a panic, and catch it. + let caught_unwind = catch_unwind(AssertUnwindSafe(|| { + let (a, b) = (10, 1); + let _c = unsafe { add_small_numbers(a, b) }; + unreachable!("should have unwound instead of returned"); + })); + + // Assert that we did indeed panic, then unwrap and downcast the panic into the sum. + assert!(caught_unwind.is_err()); + let panic_obj = caught_unwind.unwrap_err(); + let msg = panic_obj.downcast_ref::<String>().unwrap(); + assert_eq!(msg, "11"); +} + +#[link(name = "add", kind = "static")] +extern "C-unwind" { + /// An external function, defined in C. + /// + /// Returns the sum of two numbers, or panics if the sum is greater than 10. + fn add_small_numbers(a: u32, b: u32) -> u32; +} + +/// This function will panic if `x` is greater than 10. +/// +/// This function is called by `add_small_numbers`. +#[no_mangle] +pub extern "C-unwind" fn panic_if_greater_than_10(x: u32) { + if x > 10 { + panic!("{}", x); // That is too big! + } +} diff --git a/src/test/run-make-fulldeps/cat-and-grep-sanity-check/Makefile b/src/test/run-make-fulldeps/cat-and-grep-sanity-check/Makefile new file mode 100644 index 000000000..fead197ce --- /dev/null +++ b/src/test/run-make-fulldeps/cat-and-grep-sanity-check/Makefile @@ -0,0 +1,46 @@ +-include ../tools.mk + +all: + echo a | $(CGREP) a + ! echo b | $(CGREP) a + echo xyz | $(CGREP) x y z + ! echo abc | $(CGREP) b c d + printf "x\ny\nz" | $(CGREP) x y z + + echo AbCd | $(CGREP) -i a b C D + ! echo AbCd | $(CGREP) a b C D + + true | $(CGREP) -v nothing + ! echo nothing | $(CGREP) -v nothing + ! echo xyz | $(CGREP) -v w x y + ! echo xyz | $(CGREP) -v x y z + echo xyz | $(CGREP) -v a b c + + ! echo 'foo bar baz' | $(CGREP) 'foo baz' + echo 'foo bar baz' | $(CGREP) foo baz + echo 'x a `b` c y z' | $(CGREP) 'a `b` c' + + echo baaac | $(CGREP) -e 'ba*c' + echo bc | $(CGREP) -e 'ba*c' + ! echo aaac | $(CGREP) -e 'ba*c' + + echo aaa | $(CGREP) -e 'a+' + ! echo bbb | $(CGREP) -e 'a+' + + echo abc | $(CGREP) -e 'a|e|i|o|u' + ! echo fgh | $(CGREP) -e 'a|e|i|o|u' + echo abc | $(CGREP) -e '[aeiou]' + ! echo fgh | $(CGREP) -e '[aeiou]' + ! echo abc | $(CGREP) -e '[^aeiou]{3}' + echo fgh | $(CGREP) -e '[^aeiou]{3}' + echo ab cd ef gh | $(CGREP) -e '\bcd\b' + ! echo abcdefgh | $(CGREP) -e '\bcd\b' + echo xyz | $(CGREP) -e '...' + ! echo xy | $(CGREP) -e '...' + ! echo xyz | $(CGREP) -e '\.\.\.' + echo ... | $(CGREP) -e '\.\.\.' + + echo foo bar baz | $(CGREP) -e 'foo.*baz' + ! echo foo bar baz | $(CGREP) -ve 'foo.*baz' + ! echo foo bar baz | $(CGREP) -e 'baz.*foo' + echo foo bar baz | $(CGREP) -ve 'baz.*foo' diff --git a/src/test/run-make-fulldeps/cdylib-dylib-linkage/Makefile b/src/test/run-make-fulldeps/cdylib-dylib-linkage/Makefile new file mode 100644 index 000000000..5c9b2d1bb --- /dev/null +++ b/src/test/run-make-fulldeps/cdylib-dylib-linkage/Makefile @@ -0,0 +1,27 @@ +include ../tools.mk + +TARGET_SYSROOT := $(shell $(RUSTC) --print sysroot)/lib/rustlib/$(TARGET)/lib + +ifdef IS_MSVC +LIBSTD := $(wildcard $(TARGET_SYSROOT)/libstd-*.dll.lib) +else +LIBSTD := $(wildcard $(TARGET_SYSROOT)/$(call DYLIB_GLOB,std)) +STD := $(basename $(patsubst lib%,%, $(notdir $(LIBSTD)))) +endif + +all: $(call RUN_BINFILE,foo) + $(call RUN,foo) + +ifdef IS_MSVC +CLIBS := $(TMPDIR)/foo.dll.lib $(TMPDIR)/bar.dll.lib $(LIBSTD) +$(call RUN_BINFILE,foo): $(call DYLIB,foo) + $(CC) $(CFLAGS) foo.c $(CLIBS) $(call OUT_EXE,foo) +else +CLIBS := -lfoo -lbar -l$(STD) -L $(TMPDIR) -L $(TARGET_SYSROOT) +$(call RUN_BINFILE,foo): $(call DYLIB,foo) + $(CC) $(CFLAGS) foo.c $(CLIBS) -o $(call RUN_BINFILE,foo) +endif + +$(call DYLIB,foo): + $(RUSTC) -C prefer-dynamic bar.rs + $(RUSTC) foo.rs diff --git a/src/test/run-make-fulldeps/cdylib-dylib-linkage/bar.rs b/src/test/run-make-fulldeps/cdylib-dylib-linkage/bar.rs new file mode 100644 index 000000000..b3a7539ab --- /dev/null +++ b/src/test/run-make-fulldeps/cdylib-dylib-linkage/bar.rs @@ -0,0 +1,5 @@ +#![crate_type = "dylib"] + +pub fn bar() { + println!("hello!"); +} diff --git a/src/test/run-make-fulldeps/cdylib-dylib-linkage/foo.c b/src/test/run-make-fulldeps/cdylib-dylib-linkage/foo.c new file mode 100644 index 000000000..154f9682e --- /dev/null +++ b/src/test/run-make-fulldeps/cdylib-dylib-linkage/foo.c @@ -0,0 +1,10 @@ +#include <assert.h> + +extern void foo(); +extern unsigned bar(unsigned a, unsigned b); + +int main() { + foo(); + assert(bar(1, 2) == 3); + return 0; +} diff --git a/src/test/run-make-fulldeps/cdylib-dylib-linkage/foo.rs b/src/test/run-make-fulldeps/cdylib-dylib-linkage/foo.rs new file mode 100644 index 000000000..c4069495a --- /dev/null +++ b/src/test/run-make-fulldeps/cdylib-dylib-linkage/foo.rs @@ -0,0 +1,13 @@ +#![crate_type = "cdylib"] + +extern crate bar; + +#[no_mangle] +pub extern "C" fn foo() { + bar::bar(); +} + +#[no_mangle] +pub extern "C" fn bar(a: u32, b: u32) -> u32 { + a + b +} diff --git a/src/test/run-make-fulldeps/cdylib-fewer-symbols/Makefile b/src/test/run-make-fulldeps/cdylib-fewer-symbols/Makefile new file mode 100644 index 000000000..23491d814 --- /dev/null +++ b/src/test/run-make-fulldeps/cdylib-fewer-symbols/Makefile @@ -0,0 +1,12 @@ +# Test that allocator-related symbols don't show up as exported from a cdylib as +# they're internal to Rust and not part of the public ABI. + +-include ../tools.mk + +# ignore-windows +# FIXME: The __rdl_ and __rust_ symbol still remains, no matter using MSVC or GNU +# See https://github.com/rust-lang/rust/pull/46207#issuecomment-347561753 + +all: + $(RUSTC) foo.rs + nm -g "$(call DYLIB,foo)" | $(CGREP) -v __rdl_ __rde_ __rg_ __rust_ diff --git a/src/test/run-make-fulldeps/cdylib-fewer-symbols/foo.rs b/src/test/run-make-fulldeps/cdylib-fewer-symbols/foo.rs new file mode 100644 index 000000000..af37bc8e9 --- /dev/null +++ b/src/test/run-make-fulldeps/cdylib-fewer-symbols/foo.rs @@ -0,0 +1,6 @@ +#![crate_type = "cdylib"] + +#[no_mangle] +pub extern "C" fn foo() -> u32 { + 3 +} diff --git a/src/test/run-make-fulldeps/cdylib/Makefile b/src/test/run-make-fulldeps/cdylib/Makefile new file mode 100644 index 000000000..47ec762b3 --- /dev/null +++ b/src/test/run-make-fulldeps/cdylib/Makefile @@ -0,0 +1,19 @@ +include ../tools.mk + +all: $(call RUN_BINFILE,foo) + $(call RUN,foo) + rm $(call DYLIB,foo) + $(RUSTC) foo.rs -C lto + $(call RUN,foo) + +ifdef IS_MSVC +$(call RUN_BINFILE,foo): $(call DYLIB,foo) + $(CC) $(CFLAGS) foo.c $(TMPDIR)/foo.dll.lib $(call OUT_EXE,foo) +else +$(call RUN_BINFILE,foo): $(call DYLIB,foo) + $(CC) $(CFLAGS) foo.c -lfoo -o $(call RUN_BINFILE,foo) -L $(TMPDIR) +endif + +$(call DYLIB,foo): + $(RUSTC) bar.rs + $(RUSTC) foo.rs diff --git a/src/test/run-make-fulldeps/cdylib/bar.rs b/src/test/run-make-fulldeps/cdylib/bar.rs new file mode 100644 index 000000000..fe665abc7 --- /dev/null +++ b/src/test/run-make-fulldeps/cdylib/bar.rs @@ -0,0 +1,5 @@ +#![crate_type = "rlib"] + +pub fn bar() { + println!("hello!"); +} diff --git a/src/test/run-make-fulldeps/cdylib/foo.c b/src/test/run-make-fulldeps/cdylib/foo.c new file mode 100644 index 000000000..154f9682e --- /dev/null +++ b/src/test/run-make-fulldeps/cdylib/foo.c @@ -0,0 +1,10 @@ +#include <assert.h> + +extern void foo(); +extern unsigned bar(unsigned a, unsigned b); + +int main() { + foo(); + assert(bar(1, 2) == 3); + return 0; +} diff --git a/src/test/run-make-fulldeps/cdylib/foo.rs b/src/test/run-make-fulldeps/cdylib/foo.rs new file mode 100644 index 000000000..c4069495a --- /dev/null +++ b/src/test/run-make-fulldeps/cdylib/foo.rs @@ -0,0 +1,13 @@ +#![crate_type = "cdylib"] + +extern crate bar; + +#[no_mangle] +pub extern "C" fn foo() { + bar::bar(); +} + +#[no_mangle] +pub extern "C" fn bar(a: u32, b: u32) -> u32 { + a + b +} diff --git a/src/test/run-make-fulldeps/codegen-options-parsing/Makefile b/src/test/run-make-fulldeps/codegen-options-parsing/Makefile new file mode 100644 index 000000000..f1410b69b --- /dev/null +++ b/src/test/run-make-fulldeps/codegen-options-parsing/Makefile @@ -0,0 +1,31 @@ +-include ../tools.mk + +all: + #Option taking a number + $(RUSTC) -C codegen-units dummy.rs 2>&1 | \ + $(CGREP) 'codegen option `codegen-units` requires a number' + $(RUSTC) -C codegen-units= dummy.rs 2>&1 | \ + $(CGREP) 'incorrect value `` for codegen option `codegen-units` - a number was expected' + $(RUSTC) -C codegen-units=foo dummy.rs 2>&1 | \ + $(CGREP) 'incorrect value `foo` for codegen option `codegen-units` - a number was expected' + $(RUSTC) -C codegen-units=1 dummy.rs + #Option taking a string + $(RUSTC) -C extra-filename dummy.rs 2>&1 | \ + $(CGREP) 'codegen option `extra-filename` requires a string' + $(RUSTC) -C extra-filename= dummy.rs 2>&1 + $(RUSTC) -C extra-filename=foo dummy.rs 2>&1 + #Option taking no argument + $(RUSTC) -C lto= dummy.rs 2>&1 | \ + $(CGREP) 'codegen option `lto` - either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted' + $(RUSTC) -C lto=1 dummy.rs 2>&1 | \ + $(CGREP) 'codegen option `lto` - either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted' + $(RUSTC) -C lto=foo dummy.rs 2>&1 | \ + $(CGREP) 'codegen option `lto` - either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted' + $(RUSTC) -C lto dummy.rs + + # Should not link dead code... + $(RUSTC) --print link-args dummy.rs 2>&1 | \ + $(CGREP) -e '--gc-sections|-z[^ ]* [^ ]*<ignore>|-dead_strip|/OPT:REF' + # ... unless you specifically ask to keep it + $(RUSTC) --print link-args -C link-dead-code dummy.rs 2>&1 | \ + $(CGREP) -ve '--gc-sections|-z[^ ]* [^ ]*<ignore>|-dead_strip|/OPT:REF' diff --git a/src/test/run-make-fulldeps/codegen-options-parsing/dummy.rs b/src/test/run-make-fulldeps/codegen-options-parsing/dummy.rs new file mode 100644 index 000000000..f328e4d9d --- /dev/null +++ b/src/test/run-make-fulldeps/codegen-options-parsing/dummy.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/src/test/run-make-fulldeps/compile-stdin/Makefile b/src/test/run-make-fulldeps/compile-stdin/Makefile new file mode 100644 index 000000000..1442224cf --- /dev/null +++ b/src/test/run-make-fulldeps/compile-stdin/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: + echo 'fn main(){}' | $(RUSTC) - + $(call RUN,rust_out) diff --git a/src/test/run-make-fulldeps/compiler-lookup-paths-2/Makefile b/src/test/run-make-fulldeps/compiler-lookup-paths-2/Makefile new file mode 100644 index 000000000..bd7f62d5c --- /dev/null +++ b/src/test/run-make-fulldeps/compiler-lookup-paths-2/Makefile @@ -0,0 +1,8 @@ +-include ../tools.mk + +all: + mkdir -p $(TMPDIR)/a $(TMPDIR)/b + $(RUSTC) a.rs && mv $(TMPDIR)/liba.rlib $(TMPDIR)/a + $(RUSTC) b.rs -L $(TMPDIR)/a && mv $(TMPDIR)/libb.rlib $(TMPDIR)/b + $(RUSTC) c.rs -L crate=$(TMPDIR)/b -L dependency=$(TMPDIR)/a \ + && exit 1 || exit 0 diff --git a/src/test/run-make-fulldeps/compiler-lookup-paths-2/a.rs b/src/test/run-make-fulldeps/compiler-lookup-paths-2/a.rs new file mode 100644 index 000000000..83be6e807 --- /dev/null +++ b/src/test/run-make-fulldeps/compiler-lookup-paths-2/a.rs @@ -0,0 +1 @@ +#![crate_type = "lib"] diff --git a/src/test/run-make-fulldeps/compiler-lookup-paths-2/b.rs b/src/test/run-make-fulldeps/compiler-lookup-paths-2/b.rs new file mode 100644 index 000000000..1be6cbc91 --- /dev/null +++ b/src/test/run-make-fulldeps/compiler-lookup-paths-2/b.rs @@ -0,0 +1,2 @@ +#![crate_type = "lib"] +extern crate a; diff --git a/src/test/run-make-fulldeps/compiler-lookup-paths-2/c.rs b/src/test/run-make-fulldeps/compiler-lookup-paths-2/c.rs new file mode 100644 index 000000000..e37bc2e1d --- /dev/null +++ b/src/test/run-make-fulldeps/compiler-lookup-paths-2/c.rs @@ -0,0 +1,3 @@ +#![crate_type = "lib"] +extern crate b; +extern crate a; diff --git a/src/test/run-make-fulldeps/compiler-lookup-paths/Makefile b/src/test/run-make-fulldeps/compiler-lookup-paths/Makefile new file mode 100644 index 000000000..e22b937a0 --- /dev/null +++ b/src/test/run-make-fulldeps/compiler-lookup-paths/Makefile @@ -0,0 +1,38 @@ +-include ../tools.mk + +all: $(TMPDIR)/libnative.a + mkdir -p $(TMPDIR)/crate + mkdir -p $(TMPDIR)/native + mv $(TMPDIR)/libnative.a $(TMPDIR)/native + $(RUSTC) a.rs + mv $(TMPDIR)/liba.rlib $(TMPDIR)/crate + $(RUSTC) b.rs -L native=$(TMPDIR)/crate && exit 1 || exit 0 + $(RUSTC) b.rs -L dependency=$(TMPDIR)/crate && exit 1 || exit 0 + $(RUSTC) b.rs -L crate=$(TMPDIR)/crate + $(RUSTC) b.rs -L all=$(TMPDIR)/crate + $(RUSTC) c.rs -L native=$(TMPDIR)/crate && exit 1 || exit 0 + $(RUSTC) c.rs -L crate=$(TMPDIR)/crate && exit 1 || exit 0 + $(RUSTC) c.rs -L dependency=$(TMPDIR)/crate + $(RUSTC) c.rs -L all=$(TMPDIR)/crate + $(RUSTC) d.rs -L dependency=$(TMPDIR)/native && exit 1 || exit 0 + $(RUSTC) d.rs -L crate=$(TMPDIR)/native && exit 1 || exit 0 + $(RUSTC) d.rs -L native=$(TMPDIR)/native + $(RUSTC) d.rs -L all=$(TMPDIR)/native + # Deduplication tests: + # Same hash, no errors. + mkdir -p $(TMPDIR)/e1 + mkdir -p $(TMPDIR)/e2 + $(RUSTC) e.rs -o $(TMPDIR)/e1/libe.rlib + $(RUSTC) e.rs -o $(TMPDIR)/e2/libe.rlib + $(RUSTC) f.rs -L $(TMPDIR)/e1 -L $(TMPDIR)/e2 + $(RUSTC) f.rs -L crate=$(TMPDIR)/e1 -L $(TMPDIR)/e2 + $(RUSTC) f.rs -L crate=$(TMPDIR)/e1 -L crate=$(TMPDIR)/e2 + # Different hash, errors. + $(RUSTC) e2.rs -o $(TMPDIR)/e2/libe.rlib + $(RUSTC) f.rs -L $(TMPDIR)/e1 -L $(TMPDIR)/e2 && exit 1 || exit 0 + $(RUSTC) f.rs -L crate=$(TMPDIR)/e1 -L $(TMPDIR)/e2 && exit 1 || exit 0 + $(RUSTC) f.rs -L crate=$(TMPDIR)/e1 -L crate=$(TMPDIR)/e2 && exit 1 || exit 0 + # Native/dependency paths don't cause errors. + $(RUSTC) f.rs -L native=$(TMPDIR)/e1 -L $(TMPDIR)/e2 + $(RUSTC) f.rs -L dependency=$(TMPDIR)/e1 -L $(TMPDIR)/e2 + $(RUSTC) f.rs -L dependency=$(TMPDIR)/e1 -L crate=$(TMPDIR)/e2 diff --git a/src/test/run-make-fulldeps/compiler-lookup-paths/a.rs b/src/test/run-make-fulldeps/compiler-lookup-paths/a.rs new file mode 100644 index 000000000..83be6e807 --- /dev/null +++ b/src/test/run-make-fulldeps/compiler-lookup-paths/a.rs @@ -0,0 +1 @@ +#![crate_type = "lib"] diff --git a/src/test/run-make-fulldeps/compiler-lookup-paths/b.rs b/src/test/run-make-fulldeps/compiler-lookup-paths/b.rs new file mode 100644 index 000000000..1be6cbc91 --- /dev/null +++ b/src/test/run-make-fulldeps/compiler-lookup-paths/b.rs @@ -0,0 +1,2 @@ +#![crate_type = "lib"] +extern crate a; diff --git a/src/test/run-make-fulldeps/compiler-lookup-paths/c.rs b/src/test/run-make-fulldeps/compiler-lookup-paths/c.rs new file mode 100644 index 000000000..4c7ce01b6 --- /dev/null +++ b/src/test/run-make-fulldeps/compiler-lookup-paths/c.rs @@ -0,0 +1,2 @@ +#![crate_type = "lib"] +extern crate b; diff --git a/src/test/run-make-fulldeps/compiler-lookup-paths/d.rs b/src/test/run-make-fulldeps/compiler-lookup-paths/d.rs new file mode 100644 index 000000000..6cd9916b6 --- /dev/null +++ b/src/test/run-make-fulldeps/compiler-lookup-paths/d.rs @@ -0,0 +1,4 @@ +#![crate_type = "rlib"] + +#[link(name = "native", kind = "static")] +extern "C" {} diff --git a/src/test/run-make-fulldeps/compiler-lookup-paths/e.rs b/src/test/run-make-fulldeps/compiler-lookup-paths/e.rs new file mode 100644 index 000000000..18eb60aca --- /dev/null +++ b/src/test/run-make-fulldeps/compiler-lookup-paths/e.rs @@ -0,0 +1,2 @@ +#![crate_name = "e"] +#![crate_type = "rlib"] diff --git a/src/test/run-make-fulldeps/compiler-lookup-paths/e2.rs b/src/test/run-make-fulldeps/compiler-lookup-paths/e2.rs new file mode 100644 index 000000000..cbf08b98e --- /dev/null +++ b/src/test/run-make-fulldeps/compiler-lookup-paths/e2.rs @@ -0,0 +1,4 @@ +#![crate_name = "e"] +#![crate_type = "rlib"] + +pub fn f() {} diff --git a/src/test/run-make-fulldeps/compiler-lookup-paths/f.rs b/src/test/run-make-fulldeps/compiler-lookup-paths/f.rs new file mode 100644 index 000000000..483deaaea --- /dev/null +++ b/src/test/run-make-fulldeps/compiler-lookup-paths/f.rs @@ -0,0 +1,2 @@ +#![crate_type = "rlib"] +extern crate e; diff --git a/src/test/run-make-fulldeps/compiler-lookup-paths/native.c b/src/test/run-make-fulldeps/compiler-lookup-paths/native.c new file mode 100644 index 000000000..d11c69f81 --- /dev/null +++ b/src/test/run-make-fulldeps/compiler-lookup-paths/native.c @@ -0,0 +1 @@ +// intentionally empty diff --git a/src/test/run-make-fulldeps/compiler-rt-works-on-mingw/Makefile b/src/test/run-make-fulldeps/compiler-rt-works-on-mingw/Makefile new file mode 100644 index 000000000..0cf5d1855 --- /dev/null +++ b/src/test/run-make-fulldeps/compiler-rt-works-on-mingw/Makefile @@ -0,0 +1,9 @@ +-include ../tools.mk + +# only-windows-gnu + +all: + $(CXX) foo.cpp -c -o $(TMPDIR)/foo.o + $(AR) crus $(TMPDIR)/libfoo.a $(TMPDIR)/foo.o + $(RUSTC) foo.rs -lfoo -lstdc++ + $(call RUN,foo) diff --git a/src/test/run-make-fulldeps/compiler-rt-works-on-mingw/foo.cpp b/src/test/run-make-fulldeps/compiler-rt-works-on-mingw/foo.cpp new file mode 100644 index 000000000..4c2fb9cdb --- /dev/null +++ b/src/test/run-make-fulldeps/compiler-rt-works-on-mingw/foo.cpp @@ -0,0 +1,4 @@ +extern "C" void foo() { + int *a = new int(3); + delete a; +} diff --git a/src/test/run-make-fulldeps/compiler-rt-works-on-mingw/foo.rs b/src/test/run-make-fulldeps/compiler-rt-works-on-mingw/foo.rs new file mode 100644 index 000000000..7fdb81588 --- /dev/null +++ b/src/test/run-make-fulldeps/compiler-rt-works-on-mingw/foo.rs @@ -0,0 +1,10 @@ +extern "C" { + fn foo(); +} + +pub fn main() { + unsafe { + foo(); + } + assert_eq!(7f32.powi(3), 343f32); +} diff --git a/src/test/run-make-fulldeps/core-no-fp-fmt-parse/Makefile b/src/test/run-make-fulldeps/core-no-fp-fmt-parse/Makefile new file mode 100644 index 000000000..f79e4c3f4 --- /dev/null +++ b/src/test/run-make-fulldeps/core-no-fp-fmt-parse/Makefile @@ -0,0 +1,4 @@ +-include ../tools.mk + +all: + $(RUSTC) --edition=2021 --crate-type=rlib ../../../../library/core/src/lib.rs --cfg no_fp_fmt_parse diff --git a/src/test/run-make-fulldeps/crate-data-smoke/Makefile b/src/test/run-make-fulldeps/crate-data-smoke/Makefile new file mode 100644 index 000000000..1afda4574 --- /dev/null +++ b/src/test/run-make-fulldeps/crate-data-smoke/Makefile @@ -0,0 +1,10 @@ +-include ../tools.mk + +all: + [ `$(RUSTC) --print crate-name crate.rs` = "foo" ] + [ `$(RUSTC) --print file-names crate.rs` = "$(call BIN,foo)" ] + [ `$(RUSTC) --print file-names --crate-type=lib \ + --test crate.rs` = "$(call BIN,foo)" ] + [ `$(RUSTC) --print file-names --test lib.rs` = "$(call BIN,mylib)" ] + $(RUSTC) --print file-names lib.rs + $(RUSTC) --print file-names rlib.rs diff --git a/src/test/run-make-fulldeps/crate-data-smoke/crate.rs b/src/test/run-make-fulldeps/crate-data-smoke/crate.rs new file mode 100644 index 000000000..a48a6f51c --- /dev/null +++ b/src/test/run-make-fulldeps/crate-data-smoke/crate.rs @@ -0,0 +1,7 @@ +#![crate_name = "foo"] + +// Querying about the crate metadata should *not* parse the entire crate, it +// only needs the crate attributes (which are guaranteed to be at the top) be +// sure that if we have an error like a missing module that we can still query +// about the crate id. +mod error; diff --git a/src/test/run-make-fulldeps/crate-data-smoke/lib.rs b/src/test/run-make-fulldeps/crate-data-smoke/lib.rs new file mode 100644 index 000000000..8002f11ec --- /dev/null +++ b/src/test/run-make-fulldeps/crate-data-smoke/lib.rs @@ -0,0 +1,2 @@ +#![crate_name = "mylib"] +#![crate_type = "lib"] diff --git a/src/test/run-make-fulldeps/crate-data-smoke/rlib.rs b/src/test/run-make-fulldeps/crate-data-smoke/rlib.rs new file mode 100644 index 000000000..47fcce4a7 --- /dev/null +++ b/src/test/run-make-fulldeps/crate-data-smoke/rlib.rs @@ -0,0 +1,2 @@ +#![crate_name = "mylib"] +#![crate_type = "rlib"] diff --git a/src/test/run-make-fulldeps/crate-hash-rustc-version/Makefile b/src/test/run-make-fulldeps/crate-hash-rustc-version/Makefile new file mode 100644 index 000000000..091508cd8 --- /dev/null +++ b/src/test/run-make-fulldeps/crate-hash-rustc-version/Makefile @@ -0,0 +1,37 @@ +-include ../../run-make-fulldeps/tools.mk + +# Ensure that crates compiled with different rustc versions cannot +# be dynamically linked. + +FLAGS := -Cprefer-dynamic -Zsymbol-mangling-version=v0 +UNAME := $(shell uname) +ifeq ($(UNAME),Linux) + EXT=".so" + NM_CMD := nm -D +endif +ifeq ($(UNAME),Darwin) + EXT=".dylib" + NM_CMD := nm +endif + +ifndef NM_CMD +all: + exit 0 +else +all: + # a.rs is a dylib + $(RUSTC) a.rs --crate-type=dylib $(FLAGS) + # Write symbols to disk. + $(NM_CMD) $(call DYLIB,a) > $(TMPDIR)/symbolsbefore + # b.rs is a binary + $(RUSTC) b.rs --extern a=$(TMPDIR)/liba$(EXT) --crate-type=bin -Crpath $(FLAGS) + $(call RUN,b) + # Now re-compile a.rs with another rustc version + RUSTC_FORCE_RUSTC_VERSION=deadfeed $(RUSTC) a.rs --crate-type=dylib $(FLAGS) + # After compiling with a different rustc version, write symbols to disk again. + $(NM_CMD) $(call DYLIB,a) > $(TMPDIR)/symbolsafter + # As a sanity check, test if the symbols changed: + # If the symbols are identical, there's been an error. + if diff $(TMPDIR)/symbolsbefore $(TMPDIR)/symbolsafter; then exit 1; fi + $(call FAIL,b) +endif diff --git a/src/test/run-make-fulldeps/crate-hash-rustc-version/a.rs b/src/test/run-make-fulldeps/crate-hash-rustc-version/a.rs new file mode 100644 index 000000000..d65b5ce8e --- /dev/null +++ b/src/test/run-make-fulldeps/crate-hash-rustc-version/a.rs @@ -0,0 +1,4 @@ +pub fn foo(mut x: String) -> String { + x.push_str(", world!"); + x +} diff --git a/src/test/run-make-fulldeps/crate-hash-rustc-version/b.rs b/src/test/run-make-fulldeps/crate-hash-rustc-version/b.rs new file mode 100644 index 000000000..316ac26e7 --- /dev/null +++ b/src/test/run-make-fulldeps/crate-hash-rustc-version/b.rs @@ -0,0 +1,8 @@ +extern crate a; + +use a::foo; + +fn main() { + let x = String::from("Hello"); + println!("{}", foo(x)); +} diff --git a/src/test/run-make-fulldeps/crate-name-priority/Makefile b/src/test/run-make-fulldeps/crate-name-priority/Makefile new file mode 100644 index 000000000..17ecb33ab --- /dev/null +++ b/src/test/run-make-fulldeps/crate-name-priority/Makefile @@ -0,0 +1,11 @@ +-include ../tools.mk + +all: + $(RUSTC) foo.rs + rm $(TMPDIR)/$(call BIN,foo) + $(RUSTC) foo.rs --crate-name bar + rm $(TMPDIR)/$(call BIN,bar) + $(RUSTC) foo1.rs + rm $(TMPDIR)/$(call BIN,foo) + $(RUSTC) foo1.rs -o $(TMPDIR)/$(call BIN,bar1) + rm $(TMPDIR)/$(call BIN,bar1) diff --git a/src/test/run-make-fulldeps/crate-name-priority/foo.rs b/src/test/run-make-fulldeps/crate-name-priority/foo.rs new file mode 100644 index 000000000..f328e4d9d --- /dev/null +++ b/src/test/run-make-fulldeps/crate-name-priority/foo.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/src/test/run-make-fulldeps/crate-name-priority/foo1.rs b/src/test/run-make-fulldeps/crate-name-priority/foo1.rs new file mode 100644 index 000000000..4ff3bd951 --- /dev/null +++ b/src/test/run-make-fulldeps/crate-name-priority/foo1.rs @@ -0,0 +1,3 @@ +#![crate_name = "foo"] + +fn main() {} diff --git a/src/test/run-make-fulldeps/cross-lang-lto-clang/Makefile b/src/test/run-make-fulldeps/cross-lang-lto-clang/Makefile new file mode 100644 index 000000000..3ca2a8afa --- /dev/null +++ b/src/test/run-make-fulldeps/cross-lang-lto-clang/Makefile @@ -0,0 +1,25 @@ +# needs-matching-clang + +# This test makes sure that cross-language inlining actually works by checking +# the generated machine code. + +-include ../tools.mk + +all: cpp-executable rust-executable + +cpp-executable: + $(RUSTC) -Clinker-plugin-lto=on -o $(TMPDIR)/librustlib-xlto.a -Copt-level=2 -Ccodegen-units=1 ./rustlib.rs + $(CLANG) -flto=thin -fuse-ld=lld -L $(TMPDIR) -lrustlib-xlto -o $(TMPDIR)/cmain ./cmain.c -O3 + # Make sure we don't find a call instruction to the function we expect to + # always be inlined. + "$(LLVM_BIN_DIR)"/llvm-objdump -d $(TMPDIR)/cmain | $(CGREP) -v -e "call.*rust_always_inlined" + # As a sanity check, make sure we do find a call instruction to a + # non-inlined function + "$(LLVM_BIN_DIR)"/llvm-objdump -d $(TMPDIR)/cmain | $(CGREP) -e "call.*rust_never_inlined" + +rust-executable: + $(CLANG) ./clib.c -flto=thin -c -o $(TMPDIR)/clib.o -O2 + (cd $(TMPDIR); $(AR) crus ./libxyz.a ./clib.o) + $(RUSTC) -Clinker-plugin-lto=on -L$(TMPDIR) -Copt-level=2 -Clinker=$(CLANG) -Clink-arg=-fuse-ld=lld ./main.rs -o $(TMPDIR)/rsmain + "$(LLVM_BIN_DIR)"/llvm-objdump -d $(TMPDIR)/rsmain | $(CGREP) -e "call.*c_never_inlined" + "$(LLVM_BIN_DIR)"/llvm-objdump -d $(TMPDIR)/rsmain | $(CGREP) -v -e "call.*c_always_inlined" diff --git a/src/test/run-make-fulldeps/cross-lang-lto-clang/clib.c b/src/test/run-make-fulldeps/cross-lang-lto-clang/clib.c new file mode 100644 index 000000000..90f33f24d --- /dev/null +++ b/src/test/run-make-fulldeps/cross-lang-lto-clang/clib.c @@ -0,0 +1,9 @@ +#include <stdint.h> + +uint32_t c_always_inlined() { + return 1234; +} + +__attribute__((noinline)) uint32_t c_never_inlined() { + return 12345; +} diff --git a/src/test/run-make-fulldeps/cross-lang-lto-clang/cmain.c b/src/test/run-make-fulldeps/cross-lang-lto-clang/cmain.c new file mode 100644 index 000000000..e62a40117 --- /dev/null +++ b/src/test/run-make-fulldeps/cross-lang-lto-clang/cmain.c @@ -0,0 +1,12 @@ +#include <stdint.h> + +// A trivial function defined in Rust, returning a constant value. This should +// always be inlined. +uint32_t rust_always_inlined(); + + +uint32_t rust_never_inlined(); + +int main(int argc, char** argv) { + return rust_never_inlined() + rust_always_inlined(); +} diff --git a/src/test/run-make-fulldeps/cross-lang-lto-clang/main.rs b/src/test/run-make-fulldeps/cross-lang-lto-clang/main.rs new file mode 100644 index 000000000..8129dcb85 --- /dev/null +++ b/src/test/run-make-fulldeps/cross-lang-lto-clang/main.rs @@ -0,0 +1,11 @@ +#[link(name = "xyz")] +extern "C" { + fn c_always_inlined() -> u32; + fn c_never_inlined() -> u32; +} + +fn main() { + unsafe { + println!("blub: {}", c_always_inlined() + c_never_inlined()); + } +} diff --git a/src/test/run-make-fulldeps/cross-lang-lto-clang/rustlib.rs b/src/test/run-make-fulldeps/cross-lang-lto-clang/rustlib.rs new file mode 100644 index 000000000..8a74d74a4 --- /dev/null +++ b/src/test/run-make-fulldeps/cross-lang-lto-clang/rustlib.rs @@ -0,0 +1,12 @@ +#![crate_type="staticlib"] + +#[no_mangle] +pub extern "C" fn rust_always_inlined() -> u32 { + 42 +} + +#[no_mangle] +#[inline(never)] +pub extern "C" fn rust_never_inlined() -> u32 { + 421 +} diff --git a/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/Makefile b/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/Makefile new file mode 100644 index 000000000..f8efeca56 --- /dev/null +++ b/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/Makefile @@ -0,0 +1,87 @@ +# needs-matching-clang + +# This test makes sure that cross-language inlining can be used in conjunction +# with profile-guided optimization. The test only tests that the whole workflow +# can be executed without anything crashing. It does not test whether PGO or +# xLTO have any specific effect on the generated code. + +-include ../tools.mk + +COMMON_FLAGS=-Copt-level=3 -Ccodegen-units=1 + +# LLVM doesn't support instrumenting binaries that use SEH: +# https://bugs.llvm.org/show_bug.cgi?id=41279 +# +# Things work fine with -Cpanic=abort though. +ifdef IS_MSVC +COMMON_FLAGS+= -Cpanic=abort +endif + +all: cpp-executable rust-executable + +cpp-executable: + $(RUSTC) -Clinker-plugin-lto=on \ + -Cprofile-generate="$(TMPDIR)"/cpp-profdata \ + -o "$(TMPDIR)"/librustlib-xlto.a \ + $(COMMON_FLAGS) \ + ./rustlib.rs + $(CLANG) -flto=thin \ + -fprofile-generate="$(TMPDIR)"/cpp-profdata \ + -fuse-ld=lld \ + -L "$(TMPDIR)" \ + -lrustlib-xlto \ + -o "$(TMPDIR)"/cmain \ + -O3 \ + ./cmain.c + $(TMPDIR)/cmain + # Postprocess the profiling data so it can be used by the compiler + "$(LLVM_BIN_DIR)"/llvm-profdata merge \ + -o "$(TMPDIR)"/cpp-profdata/merged.profdata \ + "$(TMPDIR)"/cpp-profdata/default_*.profraw + $(RUSTC) -Clinker-plugin-lto=on \ + -Cprofile-use="$(TMPDIR)"/cpp-profdata/merged.profdata \ + -o "$(TMPDIR)"/librustlib-xlto.a \ + $(COMMON_FLAGS) \ + ./rustlib.rs + $(CLANG) -flto=thin \ + -fprofile-use="$(TMPDIR)"/cpp-profdata/merged.profdata \ + -fuse-ld=lld \ + -L "$(TMPDIR)" \ + -lrustlib-xlto \ + -o "$(TMPDIR)"/cmain \ + -O3 \ + ./cmain.c + +rust-executable: + exit + $(CLANG) ./clib.c -fprofile-generate="$(TMPDIR)"/rs-profdata -flto=thin -c -o $(TMPDIR)/clib.o -O3 + (cd $(TMPDIR); $(AR) crus ./libxyz.a ./clib.o) + $(RUSTC) -Clinker-plugin-lto=on \ + -Cprofile-generate="$(TMPDIR)"/rs-profdata \ + -L$(TMPDIR) \ + $(COMMON_FLAGS) \ + -Clinker=$(CLANG) \ + -Clink-arg=-fuse-ld=lld \ + -o $(TMPDIR)/rsmain \ + ./main.rs + $(TMPDIR)/rsmain + # Postprocess the profiling data so it can be used by the compiler + "$(LLVM_BIN_DIR)"/llvm-profdata merge \ + -o "$(TMPDIR)"/rs-profdata/merged.profdata \ + "$(TMPDIR)"/rs-profdata/default_*.profraw + $(CLANG) ./clib.c \ + -fprofile-use="$(TMPDIR)"/rs-profdata/merged.profdata \ + -flto=thin \ + -c \ + -o $(TMPDIR)/clib.o \ + -O3 + rm "$(TMPDIR)"/libxyz.a + (cd $(TMPDIR); $(AR) crus ./libxyz.a ./clib.o) + $(RUSTC) -Clinker-plugin-lto=on \ + -Cprofile-use="$(TMPDIR)"/rs-profdata/merged.profdata \ + -L$(TMPDIR) \ + $(COMMON_FLAGS) \ + -Clinker=$(CLANG) \ + -Clink-arg=-fuse-ld=lld \ + -o $(TMPDIR)/rsmain \ + ./main.rs diff --git a/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/clib.c b/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/clib.c new file mode 100644 index 000000000..90f33f24d --- /dev/null +++ b/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/clib.c @@ -0,0 +1,9 @@ +#include <stdint.h> + +uint32_t c_always_inlined() { + return 1234; +} + +__attribute__((noinline)) uint32_t c_never_inlined() { + return 12345; +} diff --git a/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/cmain.c b/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/cmain.c new file mode 100644 index 000000000..e3f24828b --- /dev/null +++ b/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/cmain.c @@ -0,0 +1,12 @@ +#include <stdint.h> + +// A trivial function defined in Rust, returning a constant value. This should +// always be inlined. +uint32_t rust_always_inlined(); + + +uint32_t rust_never_inlined(); + +int main(int argc, char** argv) { + return (rust_never_inlined() + rust_always_inlined()) * 0; +} diff --git a/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/main.rs b/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/main.rs new file mode 100644 index 000000000..8129dcb85 --- /dev/null +++ b/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/main.rs @@ -0,0 +1,11 @@ +#[link(name = "xyz")] +extern "C" { + fn c_always_inlined() -> u32; + fn c_never_inlined() -> u32; +} + +fn main() { + unsafe { + println!("blub: {}", c_always_inlined() + c_never_inlined()); + } +} diff --git a/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/rustlib.rs b/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/rustlib.rs new file mode 100644 index 000000000..8a74d74a4 --- /dev/null +++ b/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/rustlib.rs @@ -0,0 +1,12 @@ +#![crate_type="staticlib"] + +#[no_mangle] +pub extern "C" fn rust_always_inlined() -> u32 { + 42 +} + +#[no_mangle] +#[inline(never)] +pub extern "C" fn rust_never_inlined() -> u32 { + 421 +} diff --git a/src/test/run-make-fulldeps/cross-lang-lto-upstream-rlibs/Makefile b/src/test/run-make-fulldeps/cross-lang-lto-upstream-rlibs/Makefile new file mode 100644 index 000000000..f70b411d7 --- /dev/null +++ b/src/test/run-make-fulldeps/cross-lang-lto-upstream-rlibs/Makefile @@ -0,0 +1,32 @@ +-include ../tools.mk + +# ignore windows due to libLLVM being present in PATH and the PATH and library path being the same +# (so fixing it is harder). See #57765 for context +ifndef IS_WINDOWS + +# This test makes sure that we don't loose upstream object files when compiling +# staticlibs with -C linker-plugin-lto + +all: staticlib.rs upstream.rs + $(RUSTC) upstream.rs -C linker-plugin-lto -Ccodegen-units=1 + + # Check No LTO + $(RUSTC) staticlib.rs -C linker-plugin-lto -Ccodegen-units=1 -L. -o $(TMPDIR)/staticlib.a + (cd $(TMPDIR); "$(LLVM_BIN_DIR)"/llvm-ar x ./staticlib.a) + # Make sure the upstream object file was included + ls $(TMPDIR)/upstream.*.rcgu.o + + # Cleanup + rm $(TMPDIR)/* + + # Check ThinLTO + $(RUSTC) upstream.rs -C linker-plugin-lto -Ccodegen-units=1 -Clto=thin + $(RUSTC) staticlib.rs -C linker-plugin-lto -Ccodegen-units=1 -Clto=thin -L. -o $(TMPDIR)/staticlib.a + (cd $(TMPDIR); "$(LLVM_BIN_DIR)"/llvm-ar x ./staticlib.a) + ls $(TMPDIR)/upstream.*.rcgu.o + +else + +all: + +endif diff --git a/src/test/run-make-fulldeps/cross-lang-lto-upstream-rlibs/staticlib.rs b/src/test/run-make-fulldeps/cross-lang-lto-upstream-rlibs/staticlib.rs new file mode 100644 index 000000000..34951dda3 --- /dev/null +++ b/src/test/run-make-fulldeps/cross-lang-lto-upstream-rlibs/staticlib.rs @@ -0,0 +1,8 @@ +#![crate_type="staticlib"] + +extern crate upstream; + +#[no_mangle] +pub extern "C" fn bar() { + upstream::foo(); +} diff --git a/src/test/run-make-fulldeps/cross-lang-lto-upstream-rlibs/upstream.rs b/src/test/run-make-fulldeps/cross-lang-lto-upstream-rlibs/upstream.rs new file mode 100644 index 000000000..bd6820098 --- /dev/null +++ b/src/test/run-make-fulldeps/cross-lang-lto-upstream-rlibs/upstream.rs @@ -0,0 +1,3 @@ +#![crate_type = "rlib"] + +pub fn foo() {} diff --git a/src/test/run-make-fulldeps/cross-lang-lto/Makefile b/src/test/run-make-fulldeps/cross-lang-lto/Makefile new file mode 100644 index 000000000..b4394cb5b --- /dev/null +++ b/src/test/run-make-fulldeps/cross-lang-lto/Makefile @@ -0,0 +1,57 @@ + +-include ../tools.mk + +# ignore windows due to libLLVM being present in PATH and the PATH and library path being the same +# (so fixing it is harder). See #57765 for context +ifndef IS_WINDOWS + +# This test makes sure that the object files we generate are actually +# LLVM bitcode files (as used by linker LTO plugins) when compiling with +# -Clinker-plugin-lto. + +# this only succeeds for bitcode files +ASSERT_IS_BITCODE_OBJ=("$(LLVM_BIN_DIR)"/llvm-bcanalyzer $(1)) +EXTRACT_OBJS=(cd $(TMPDIR); rm -f ./*.o; "$(LLVM_BIN_DIR)"/llvm-ar x $(1)) + +BUILD_LIB=$(RUSTC) lib.rs -Copt-level=2 -Clinker-plugin-lto -Ccodegen-units=1 +BUILD_EXE=$(RUSTC) main.rs -Copt-level=2 -Clinker-plugin-lto -Ccodegen-units=1 --emit=obj + +all: staticlib staticlib-fat-lto staticlib-thin-lto rlib exe cdylib rdylib + +staticlib: lib.rs + $(BUILD_LIB) --crate-type=staticlib -o $(TMPDIR)/liblib.a + $(call EXTRACT_OBJS, liblib.a) + for file in $(TMPDIR)/liblib.*.rcgu.o; do $(call ASSERT_IS_BITCODE_OBJ, $$file); done + +staticlib-fat-lto: lib.rs + $(BUILD_LIB) --crate-type=staticlib -o $(TMPDIR)/liblib-fat-lto.a -Clto=fat + $(call EXTRACT_OBJS, liblib-fat-lto.a) + for file in $(TMPDIR)/liblib-fat-lto.*.rcgu.o; do $(call ASSERT_IS_BITCODE_OBJ, $$file); done + +staticlib-thin-lto: lib.rs + $(BUILD_LIB) --crate-type=staticlib -o $(TMPDIR)/liblib-thin-lto.a -Clto=thin + $(call EXTRACT_OBJS, liblib-thin-lto.a) + for file in $(TMPDIR)/liblib-thin-lto.*.rcgu.o; do $(call ASSERT_IS_BITCODE_OBJ, $$file); done + +rlib: lib.rs + $(BUILD_LIB) --crate-type=rlib -o $(TMPDIR)/liblib.rlib + $(call EXTRACT_OBJS, liblib.rlib) + for file in $(TMPDIR)/liblib.*.rcgu.o; do $(call ASSERT_IS_BITCODE_OBJ, $$file); done + +cdylib: lib.rs + $(BUILD_LIB) --crate-type=cdylib --emit=obj -o $(TMPDIR)/cdylib.o + $(call ASSERT_IS_BITCODE_OBJ, $(TMPDIR)/cdylib.o) + +rdylib: lib.rs + $(BUILD_LIB) --crate-type=dylib --emit=obj -o $(TMPDIR)/rdylib.o + $(call ASSERT_IS_BITCODE_OBJ, $(TMPDIR)/rdylib.o) + +exe: lib.rs + $(BUILD_EXE) -o $(TMPDIR)/exe.o + $(call ASSERT_IS_BITCODE_OBJ, $(TMPDIR)/exe.o) + +else + +all: + +endif diff --git a/src/test/run-make-fulldeps/cross-lang-lto/lib.rs b/src/test/run-make-fulldeps/cross-lang-lto/lib.rs new file mode 100644 index 000000000..94cfef6ad --- /dev/null +++ b/src/test/run-make-fulldeps/cross-lang-lto/lib.rs @@ -0,0 +1,4 @@ +#[no_mangle] +pub extern "C" fn foo() { + println!("abc"); +} diff --git a/src/test/run-make-fulldeps/cross-lang-lto/main.rs b/src/test/run-make-fulldeps/cross-lang-lto/main.rs new file mode 100644 index 000000000..f6320bcb0 --- /dev/null +++ b/src/test/run-make-fulldeps/cross-lang-lto/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello World"); +} diff --git a/src/test/run-make-fulldeps/debug-assertions/Makefile b/src/test/run-make-fulldeps/debug-assertions/Makefile new file mode 100644 index 000000000..76ada90f1 --- /dev/null +++ b/src/test/run-make-fulldeps/debug-assertions/Makefile @@ -0,0 +1,25 @@ +-include ../tools.mk + +all: + $(RUSTC) debug.rs -C debug-assertions=no + $(call RUN,debug) good + $(RUSTC) debug.rs -C opt-level=0 + $(call RUN,debug) bad + $(RUSTC) debug.rs -C opt-level=1 + $(call RUN,debug) good + $(RUSTC) debug.rs -C opt-level=2 + $(call RUN,debug) good + $(RUSTC) debug.rs -C opt-level=3 + $(call RUN,debug) good + $(RUSTC) debug.rs -C opt-level=s + $(call RUN,debug) good + $(RUSTC) debug.rs -C opt-level=z + $(call RUN,debug) good + $(RUSTC) debug.rs -O + $(call RUN,debug) good + $(RUSTC) debug.rs + $(call RUN,debug) bad + $(RUSTC) debug.rs -C debug-assertions=yes -O + $(call RUN,debug) bad + $(RUSTC) debug.rs -C debug-assertions=yes -C opt-level=1 + $(call RUN,debug) bad diff --git a/src/test/run-make-fulldeps/debug-assertions/debug.rs b/src/test/run-make-fulldeps/debug-assertions/debug.rs new file mode 100644 index 000000000..76ca60a71 --- /dev/null +++ b/src/test/run-make-fulldeps/debug-assertions/debug.rs @@ -0,0 +1,33 @@ +#![feature(rustc_attrs)] +#![deny(warnings)] + +use std::env; +use std::thread; + +fn main() { + let should_fail = env::args().nth(1) == Some("bad".to_string()); + + assert_eq!(thread::spawn(debug_assert_eq).join().is_err(), should_fail); + assert_eq!(thread::spawn(debug_assert).join().is_err(), should_fail); + assert_eq!(thread::spawn(overflow).join().is_err(), should_fail); +} + +fn debug_assert_eq() { + let mut hit1 = false; + let mut hit2 = false; + debug_assert_eq!({ hit1 = true; 1 }, { hit2 = true; 2 }); + assert!(!hit1); + assert!(!hit2); +} + +fn debug_assert() { + let mut hit = false; + debug_assert!({ hit = true; false }); + assert!(!hit); +} + +fn overflow() { + fn add(a: u8, b: u8) -> u8 { a + b } + + add(200u8, 200u8); +} diff --git a/src/test/run-make-fulldeps/dep-info-doesnt-run-much/Makefile b/src/test/run-make-fulldeps/dep-info-doesnt-run-much/Makefile new file mode 100644 index 000000000..2fd84639f --- /dev/null +++ b/src/test/run-make-fulldeps/dep-info-doesnt-run-much/Makefile @@ -0,0 +1,4 @@ +-include ../tools.mk + +all: + $(RUSTC) foo.rs --emit dep-info diff --git a/src/test/run-make-fulldeps/dep-info-doesnt-run-much/foo.rs b/src/test/run-make-fulldeps/dep-info-doesnt-run-much/foo.rs new file mode 100644 index 000000000..316e68129 --- /dev/null +++ b/src/test/run-make-fulldeps/dep-info-doesnt-run-much/foo.rs @@ -0,0 +1,5 @@ +// We're only emitting dep info, so we shouldn't be running static analysis to +// figure out that this program is erroneous. +fn main() { + let a: u8 = "a"; +} diff --git a/src/test/run-make-fulldeps/dep-info-spaces/Makefile b/src/test/run-make-fulldeps/dep-info-spaces/Makefile new file mode 100644 index 000000000..339a751ff --- /dev/null +++ b/src/test/run-make-fulldeps/dep-info-spaces/Makefile @@ -0,0 +1,19 @@ +-include ../tools.mk + +# ignore-windows +# ignore-freebsd +# FIXME: (windows: see `../dep-info/Makefile`) + +all: + cp lib.rs $(TMPDIR)/ + cp 'foo foo.rs' $(TMPDIR)/ + cp bar.rs $(TMPDIR)/ + $(RUSTC) --emit link,dep-info --crate-type=lib $(TMPDIR)/lib.rs + sleep 1 + touch $(TMPDIR)/'foo foo.rs' + -rm -f $(TMPDIR)/done + $(MAKE) -drf Makefile.foo + rm $(TMPDIR)/done + pwd + $(MAKE) -drf Makefile.foo + rm $(TMPDIR)/done && exit 1 || exit 0 diff --git a/src/test/run-make-fulldeps/dep-info-spaces/Makefile.foo b/src/test/run-make-fulldeps/dep-info-spaces/Makefile.foo new file mode 100644 index 000000000..80a5d4333 --- /dev/null +++ b/src/test/run-make-fulldeps/dep-info-spaces/Makefile.foo @@ -0,0 +1,7 @@ +LIB := $(shell $(RUSTC) --print file-names --crate-type=lib $(TMPDIR)/lib.rs) + +$(TMPDIR)/$(LIB): + $(RUSTC) --emit link,dep-info --crate-type=lib $(TMPDIR)/lib.rs + touch $(TMPDIR)/done + +-include $(TMPDIR)/lib.d diff --git a/src/test/run-make-fulldeps/dep-info-spaces/bar.rs b/src/test/run-make-fulldeps/dep-info-spaces/bar.rs new file mode 100644 index 000000000..c5c0bc606 --- /dev/null +++ b/src/test/run-make-fulldeps/dep-info-spaces/bar.rs @@ -0,0 +1 @@ +pub fn bar() {} diff --git a/src/test/run-make-fulldeps/dep-info-spaces/foo foo.rs b/src/test/run-make-fulldeps/dep-info-spaces/foo foo.rs new file mode 100644 index 000000000..b76b4321d --- /dev/null +++ b/src/test/run-make-fulldeps/dep-info-spaces/foo foo.rs @@ -0,0 +1 @@ +pub fn foo() {} diff --git a/src/test/run-make-fulldeps/dep-info-spaces/lib.rs b/src/test/run-make-fulldeps/dep-info-spaces/lib.rs new file mode 100644 index 000000000..6264e7b67 --- /dev/null +++ b/src/test/run-make-fulldeps/dep-info-spaces/lib.rs @@ -0,0 +1,4 @@ +#[path="foo foo.rs"] +pub mod foo; + +pub mod bar; diff --git a/src/test/run-make-fulldeps/dep-info/Makefile b/src/test/run-make-fulldeps/dep-info/Makefile new file mode 100644 index 000000000..afb9db177 --- /dev/null +++ b/src/test/run-make-fulldeps/dep-info/Makefile @@ -0,0 +1,25 @@ +-include ../tools.mk + +# ignore-windows +# ignore-freebsd +# FIXME: on windows `rustc --dep-info` produces Makefile dependency with +# windows native paths (e.g. `c:\path\to\libfoo.a`) +# but msys make seems to fail to recognize such paths, so test fails. + +all: + cp *.rs $(TMPDIR) + $(RUSTC) --emit dep-info,link --crate-type=lib $(TMPDIR)/lib.rs + sleep 2 + touch $(TMPDIR)/foo.rs + -rm -f $(TMPDIR)/done + $(MAKE) -drf Makefile.foo + sleep 2 + rm $(TMPDIR)/done + pwd + $(MAKE) -drf Makefile.foo + rm $(TMPDIR)/done && exit 1 || exit 0 + + # When a source file is deleted `make` should still work + rm $(TMPDIR)/bar.rs + cp $(TMPDIR)/lib2.rs $(TMPDIR)/lib.rs + $(MAKE) -drf Makefile.foo diff --git a/src/test/run-make-fulldeps/dep-info/Makefile.foo b/src/test/run-make-fulldeps/dep-info/Makefile.foo new file mode 100644 index 000000000..e5df31f88 --- /dev/null +++ b/src/test/run-make-fulldeps/dep-info/Makefile.foo @@ -0,0 +1,7 @@ +LIB := $(shell $(RUSTC) --print file-names --crate-type=lib lib.rs) + +$(TMPDIR)/$(LIB): + $(RUSTC) --emit dep-info,link --crate-type=lib lib.rs + touch $(TMPDIR)/done + +-include $(TMPDIR)/foo.d diff --git a/src/test/run-make-fulldeps/dep-info/bar.rs b/src/test/run-make-fulldeps/dep-info/bar.rs new file mode 100644 index 000000000..c5c0bc606 --- /dev/null +++ b/src/test/run-make-fulldeps/dep-info/bar.rs @@ -0,0 +1 @@ +pub fn bar() {} diff --git a/src/test/run-make-fulldeps/dep-info/foo.rs b/src/test/run-make-fulldeps/dep-info/foo.rs new file mode 100644 index 000000000..b76b4321d --- /dev/null +++ b/src/test/run-make-fulldeps/dep-info/foo.rs @@ -0,0 +1 @@ +pub fn foo() {} diff --git a/src/test/run-make-fulldeps/dep-info/lib.rs b/src/test/run-make-fulldeps/dep-info/lib.rs new file mode 100644 index 000000000..eb8631259 --- /dev/null +++ b/src/test/run-make-fulldeps/dep-info/lib.rs @@ -0,0 +1,4 @@ +#![crate_name = "foo"] + +pub mod foo; +pub mod bar; diff --git a/src/test/run-make-fulldeps/dep-info/lib2.rs b/src/test/run-make-fulldeps/dep-info/lib2.rs new file mode 100644 index 000000000..f4fda9c93 --- /dev/null +++ b/src/test/run-make-fulldeps/dep-info/lib2.rs @@ -0,0 +1,3 @@ +#![crate_name = "foo"] + +pub mod foo; diff --git a/src/test/run-make-fulldeps/doctests-keep-binaries/Makefile b/src/test/run-make-fulldeps/doctests-keep-binaries/Makefile new file mode 100644 index 000000000..273c8980b --- /dev/null +++ b/src/test/run-make-fulldeps/doctests-keep-binaries/Makefile @@ -0,0 +1,21 @@ +include ../../run-make-fulldeps/tools.mk + +# Check that valid binaries are persisted by running them, regardless of whether the --run or --no-run option is used. + +all: run no_run + +run: + mkdir -p $(TMPDIR)/doctests + $(RUSTC) --crate-type rlib t.rs + $(RUSTDOC) -Zunstable-options --test --persist-doctests $(TMPDIR)/doctests --extern t=$(TMPDIR)/libt.rlib t.rs + $(TMPDIR)/doctests/t_rs_2_0/rust_out + $(TMPDIR)/doctests/t_rs_8_0/rust_out + rm -rf $(TMPDIR)/doctests + +no_run: + mkdir -p $(TMPDIR)/doctests + $(RUSTC) --crate-type rlib t.rs + $(RUSTDOC) -Zunstable-options --test --persist-doctests $(TMPDIR)/doctests --extern t=$(TMPDIR)/libt.rlib t.rs --no-run + $(TMPDIR)/doctests/t_rs_2_0/rust_out + $(TMPDIR)/doctests/t_rs_8_0/rust_out + rm -rf $(TMPDIR)/doctests diff --git a/src/test/run-make-fulldeps/doctests-keep-binaries/t.rs b/src/test/run-make-fulldeps/doctests-keep-binaries/t.rs new file mode 100644 index 000000000..c38cf0a0b --- /dev/null +++ b/src/test/run-make-fulldeps/doctests-keep-binaries/t.rs @@ -0,0 +1,11 @@ +/// Fungle the foople. +/// ``` +/// t::foople(); +/// ``` +pub fn foople() {} + +/// Flomble the florp +/// ``` +/// t::florp(); +/// ``` +pub fn florp() {} diff --git a/src/test/run-make-fulldeps/duplicate-output-flavors/Makefile b/src/test/run-make-fulldeps/duplicate-output-flavors/Makefile new file mode 100644 index 000000000..e33279966 --- /dev/null +++ b/src/test/run-make-fulldeps/duplicate-output-flavors/Makefile @@ -0,0 +1,5 @@ +include ../tools.mk + +all: + $(RUSTC) --crate-type=rlib foo.rs + $(RUSTC) --crate-type=rlib,rlib foo.rs diff --git a/src/test/run-make-fulldeps/duplicate-output-flavors/foo.rs b/src/test/run-make-fulldeps/duplicate-output-flavors/foo.rs new file mode 100644 index 000000000..c1bfaa6ca --- /dev/null +++ b/src/test/run-make-fulldeps/duplicate-output-flavors/foo.rs @@ -0,0 +1 @@ +#![crate_type = "rlib"] diff --git a/src/test/run-make-fulldeps/dylib-chain/Makefile b/src/test/run-make-fulldeps/dylib-chain/Makefile new file mode 100644 index 000000000..a33177197 --- /dev/null +++ b/src/test/run-make-fulldeps/dylib-chain/Makefile @@ -0,0 +1,12 @@ +-include ../tools.mk + +all: + $(RUSTC) m1.rs -C prefer-dynamic + $(RUSTC) m2.rs -C prefer-dynamic + $(RUSTC) m3.rs -C prefer-dynamic + $(RUSTC) m4.rs + $(call RUN,m4) + $(call REMOVE_DYLIBS,m1) + $(call REMOVE_DYLIBS,m2) + $(call REMOVE_DYLIBS,m3) + $(call FAIL,m4) diff --git a/src/test/run-make-fulldeps/dylib-chain/m1.rs b/src/test/run-make-fulldeps/dylib-chain/m1.rs new file mode 100644 index 000000000..08c3f3752 --- /dev/null +++ b/src/test/run-make-fulldeps/dylib-chain/m1.rs @@ -0,0 +1,2 @@ +#![crate_type = "dylib"] +pub fn m1() {} diff --git a/src/test/run-make-fulldeps/dylib-chain/m2.rs b/src/test/run-make-fulldeps/dylib-chain/m2.rs new file mode 100644 index 000000000..62176ddc9 --- /dev/null +++ b/src/test/run-make-fulldeps/dylib-chain/m2.rs @@ -0,0 +1,4 @@ +#![crate_type = "dylib"] +extern crate m1; + +pub fn m2() { m1::m1() } diff --git a/src/test/run-make-fulldeps/dylib-chain/m3.rs b/src/test/run-make-fulldeps/dylib-chain/m3.rs new file mode 100644 index 000000000..d213aeda9 --- /dev/null +++ b/src/test/run-make-fulldeps/dylib-chain/m3.rs @@ -0,0 +1,4 @@ +#![crate_type = "dylib"] +extern crate m2; + +pub fn m3() { m2::m2() } diff --git a/src/test/run-make-fulldeps/dylib-chain/m4.rs b/src/test/run-make-fulldeps/dylib-chain/m4.rs new file mode 100644 index 000000000..fa8ec6079 --- /dev/null +++ b/src/test/run-make-fulldeps/dylib-chain/m4.rs @@ -0,0 +1,3 @@ +extern crate m3; + +fn main() { m3::m3() } diff --git a/src/test/run-make-fulldeps/emit-stack-sizes/Makefile b/src/test/run-make-fulldeps/emit-stack-sizes/Makefile new file mode 100644 index 000000000..d27028948 --- /dev/null +++ b/src/test/run-make-fulldeps/emit-stack-sizes/Makefile @@ -0,0 +1,12 @@ +-include ../tools.mk + +# ignore-windows +# ignore-macos +# +# This feature only works when the output object format is ELF so we ignore +# macOS and Windows + +# check that the .stack_sizes section is generated +all: + $(RUSTC) -C opt-level=3 -Z emit-stack-sizes --emit=obj foo.rs + size -A $(TMPDIR)/foo.o | $(CGREP) .stack_sizes diff --git a/src/test/run-make-fulldeps/emit-stack-sizes/foo.rs b/src/test/run-make-fulldeps/emit-stack-sizes/foo.rs new file mode 100644 index 000000000..ee51ae328 --- /dev/null +++ b/src/test/run-make-fulldeps/emit-stack-sizes/foo.rs @@ -0,0 +1,3 @@ +#![crate_type = "lib"] + +pub fn foo() {} diff --git a/src/test/run-make-fulldeps/emit/Makefile b/src/test/run-make-fulldeps/emit/Makefile new file mode 100644 index 000000000..e0b57107e --- /dev/null +++ b/src/test/run-make-fulldeps/emit/Makefile @@ -0,0 +1,21 @@ +-include ../tools.mk + +all: + $(RUSTC) -Copt-level=0 --emit=llvm-bc,llvm-ir,asm,obj,link test-24876.rs + $(RUSTC) -Copt-level=1 --emit=llvm-bc,llvm-ir,asm,obj,link test-24876.rs + $(RUSTC) -Copt-level=2 --emit=llvm-bc,llvm-ir,asm,obj,link test-24876.rs + $(RUSTC) -Copt-level=3 --emit=llvm-bc,llvm-ir,asm,obj,link test-24876.rs + $(RUSTC) -Copt-level=s --emit=llvm-bc,llvm-ir,asm,obj,link test-24876.rs + $(RUSTC) -Copt-level=z --emit=llvm-bc,llvm-ir,asm,obj,link test-24876.rs + $(RUSTC) -Copt-level=0 --emit=llvm-bc,llvm-ir,asm,obj,link test-26235.rs + $(call RUN,test-26235) || exit 1 + $(RUSTC) -Copt-level=1 --emit=llvm-bc,llvm-ir,asm,obj,link test-26235.rs + $(call RUN,test-26235) || exit 1 + $(RUSTC) -Copt-level=2 --emit=llvm-bc,llvm-ir,asm,obj,link test-26235.rs + $(call RUN,test-26235) || exit 1 + $(RUSTC) -Copt-level=3 --emit=llvm-bc,llvm-ir,asm,obj,link test-26235.rs + $(call RUN,test-26235) || exit 1 + $(RUSTC) -Copt-level=s --emit=llvm-bc,llvm-ir,asm,obj,link test-26235.rs + $(call RUN,test-26235) || exit 1 + $(RUSTC) -Copt-level=z --emit=llvm-bc,llvm-ir,asm,obj,link test-26235.rs + $(call RUN,test-26235) || exit 1 diff --git a/src/test/run-make-fulldeps/emit/test-24876.rs b/src/test/run-make-fulldeps/emit/test-24876.rs new file mode 100644 index 000000000..734e2ee4b --- /dev/null +++ b/src/test/run-make-fulldeps/emit/test-24876.rs @@ -0,0 +1,9 @@ +// Checks for issue #24876 + +fn main() { + let mut v = 0; + for i in 0..0 { + v += i; + } + println!("{}", v) +} diff --git a/src/test/run-make-fulldeps/emit/test-26235.rs b/src/test/run-make-fulldeps/emit/test-26235.rs new file mode 100644 index 000000000..07d975f33 --- /dev/null +++ b/src/test/run-make-fulldeps/emit/test-26235.rs @@ -0,0 +1,46 @@ +// Checks for issue #26235 + +fn main() { + use std::thread; + + type Key = u32; + const NUM_THREADS: usize = 2; + + #[derive(Clone,Copy)] + struct Stats<S> { + upsert: S, + delete: S, + insert: S, + update: S + }; + + impl<S> Stats<S> where S: Copy { + fn dot<B, F, T>(self, s: Stats<T>, f: F) -> Stats<B> where F: Fn(S, T) -> B { + let Stats { upsert: u1, delete: d1, insert: i1, update: p1 } = self; + let Stats { upsert: u2, delete: d2, insert: i2, update: p2 } = s; + Stats { upsert: f(u1, u2), delete: f(d1, d2), insert: f(i1, i2), update: f(p1, p2) } + } + + fn new(init: S) -> Self { + Stats { upsert: init, delete: init, insert: init, update: init } + } + } + + fn make_threads() -> Vec<thread::JoinHandle<()>> { + let mut t = Vec::with_capacity(NUM_THREADS); + for _ in 0..NUM_THREADS { + t.push(thread::spawn(move || {})); + } + t + } + + let stats = [Stats::new(0); NUM_THREADS]; + make_threads(); + + { + let Stats { ref upsert, ref delete, ref insert, ref update } = stats.iter().fold( + Stats::new(0), |res, &s| res.dot(s, |x: Key, y: Key| x.wrapping_add(y))); + println!("upserts: {}, deletes: {}, inserts: {}, updates: {}", + upsert, delete, insert, update); + } +} diff --git a/src/test/run-make-fulldeps/error-found-staticlib-instead-crate/Makefile b/src/test/run-make-fulldeps/error-found-staticlib-instead-crate/Makefile new file mode 100644 index 000000000..fef12c4da --- /dev/null +++ b/src/test/run-make-fulldeps/error-found-staticlib-instead-crate/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: + $(RUSTC) foo.rs --crate-type staticlib + $(RUSTC) bar.rs 2>&1 | $(CGREP) "found staticlib" diff --git a/src/test/run-make-fulldeps/error-found-staticlib-instead-crate/bar.rs b/src/test/run-make-fulldeps/error-found-staticlib-instead-crate/bar.rs new file mode 100644 index 000000000..fe35f1f8e --- /dev/null +++ b/src/test/run-make-fulldeps/error-found-staticlib-instead-crate/bar.rs @@ -0,0 +1,5 @@ +extern crate foo; + +fn main() { + foo::foo(); +} diff --git a/src/test/run-make-fulldeps/error-found-staticlib-instead-crate/foo.rs b/src/test/run-make-fulldeps/error-found-staticlib-instead-crate/foo.rs new file mode 100644 index 000000000..b76b4321d --- /dev/null +++ b/src/test/run-make-fulldeps/error-found-staticlib-instead-crate/foo.rs @@ -0,0 +1 @@ +pub fn foo() {} diff --git a/src/test/run-make-fulldeps/error-writing-dependencies/Makefile b/src/test/run-make-fulldeps/error-writing-dependencies/Makefile new file mode 100644 index 000000000..cbc96901a --- /dev/null +++ b/src/test/run-make-fulldeps/error-writing-dependencies/Makefile @@ -0,0 +1,8 @@ +-include ../tools.mk + +all: + # Let's get a nice error message + $(BARE_RUSTC) foo.rs --emit dep-info --out-dir foo/bar/baz 2>&1 | \ + $(CGREP) "error writing dependencies" + # Make sure the filename shows up + $(BARE_RUSTC) foo.rs --emit dep-info --out-dir foo/bar/baz 2>&1 | $(CGREP) "baz" diff --git a/src/test/run-make-fulldeps/error-writing-dependencies/foo.rs b/src/test/run-make-fulldeps/error-writing-dependencies/foo.rs new file mode 100644 index 000000000..f328e4d9d --- /dev/null +++ b/src/test/run-make-fulldeps/error-writing-dependencies/foo.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/src/test/run-make-fulldeps/exit-code/Makefile b/src/test/run-make-fulldeps/exit-code/Makefile new file mode 100644 index 000000000..007f19852 --- /dev/null +++ b/src/test/run-make-fulldeps/exit-code/Makefile @@ -0,0 +1,11 @@ +-include ../tools.mk + +all: + $(RUSTC) success.rs; [ $$? -eq 0 ] + $(RUSTC) --invalid-arg-foo; [ $$? -eq 1 ] + $(RUSTC) compile-error.rs; [ $$? -eq 1 ] + $(RUSTC) -Ztreat-err-as-bug compile-error.rs; [ $$? -eq 101 ] + $(RUSTDOC) -o $(TMPDIR)/exit-code success.rs; [ $$? -eq 0 ] + $(RUSTDOC) --invalid-arg-foo; [ $$? -eq 1 ] + $(RUSTDOC) compile-error.rs; [ $$? -eq 1 ] + $(RUSTDOC) lint-failure.rs; [ $$? -eq 1 ] diff --git a/src/test/run-make-fulldeps/exit-code/compile-error.rs b/src/test/run-make-fulldeps/exit-code/compile-error.rs new file mode 100644 index 000000000..a96c19760 --- /dev/null +++ b/src/test/run-make-fulldeps/exit-code/compile-error.rs @@ -0,0 +1,3 @@ +fn main() { + compile_error!("kaboom"); +} diff --git a/src/test/run-make-fulldeps/exit-code/lint-failure.rs b/src/test/run-make-fulldeps/exit-code/lint-failure.rs new file mode 100644 index 000000000..df876ec23 --- /dev/null +++ b/src/test/run-make-fulldeps/exit-code/lint-failure.rs @@ -0,0 +1,6 @@ +#![deny(broken_intra_doc_links)] + +/// [intradoc::failure] +pub fn main() { + println!("Hello, world!"); +} diff --git a/src/test/run-make-fulldeps/exit-code/success.rs b/src/test/run-make-fulldeps/exit-code/success.rs new file mode 100644 index 000000000..55b8e42b6 --- /dev/null +++ b/src/test/run-make-fulldeps/exit-code/success.rs @@ -0,0 +1,4 @@ +/// Main function +fn main() { + println!("Hello, world!"); +} diff --git a/src/test/run-make-fulldeps/extern-diff-internal-name/Makefile b/src/test/run-make-fulldeps/extern-diff-internal-name/Makefile new file mode 100644 index 000000000..b84e93075 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-diff-internal-name/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: + $(RUSTC) lib.rs + $(RUSTC) test.rs --extern foo=$(TMPDIR)/libbar.rlib diff --git a/src/test/run-make-fulldeps/extern-diff-internal-name/lib.rs b/src/test/run-make-fulldeps/extern-diff-internal-name/lib.rs new file mode 100644 index 000000000..ad96f7086 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-diff-internal-name/lib.rs @@ -0,0 +1,2 @@ +#![crate_name = "bar"] +#![crate_type = "rlib"] diff --git a/src/test/run-make-fulldeps/extern-diff-internal-name/test.rs b/src/test/run-make-fulldeps/extern-diff-internal-name/test.rs new file mode 100644 index 000000000..4c53dc28a --- /dev/null +++ b/src/test/run-make-fulldeps/extern-diff-internal-name/test.rs @@ -0,0 +1,5 @@ +#[macro_use] +extern crate foo; + +fn main() { +} diff --git a/src/test/run-make-fulldeps/extern-flag-disambiguates/Makefile b/src/test/run-make-fulldeps/extern-flag-disambiguates/Makefile new file mode 100644 index 000000000..81930e969 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-flag-disambiguates/Makefile @@ -0,0 +1,25 @@ +-include ../tools.mk + +# Attempt to build this dependency tree: +# +# A.1 A.2 +# |\ | +# | \ | +# B \ C +# \ | / +# \|/ +# D +# +# Note that A.1 and A.2 are crates with the same name. + +all: + $(RUSTC) -C metadata=1 -C extra-filename=-1 a.rs + $(RUSTC) -C metadata=2 -C extra-filename=-2 a.rs + $(RUSTC) b.rs --extern a=$(TMPDIR)/liba-1.rlib + $(RUSTC) c.rs --extern a=$(TMPDIR)/liba-2.rlib + @echo before + $(RUSTC) --cfg before d.rs --extern a=$(TMPDIR)/liba-1.rlib + $(call RUN,d) + @echo after + $(RUSTC) --cfg after d.rs --extern a=$(TMPDIR)/liba-1.rlib + $(call RUN,d) diff --git a/src/test/run-make-fulldeps/extern-flag-disambiguates/a.rs b/src/test/run-make-fulldeps/extern-flag-disambiguates/a.rs new file mode 100644 index 000000000..2b1a31901 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-flag-disambiguates/a.rs @@ -0,0 +1,6 @@ +#![crate_name = "a"] +#![crate_type = "rlib"] + +static FOO: usize = 3; + +pub fn token() -> &'static usize { &FOO } diff --git a/src/test/run-make-fulldeps/extern-flag-disambiguates/b.rs b/src/test/run-make-fulldeps/extern-flag-disambiguates/b.rs new file mode 100644 index 000000000..1d7a7339c --- /dev/null +++ b/src/test/run-make-fulldeps/extern-flag-disambiguates/b.rs @@ -0,0 +1,9 @@ +#![crate_name = "b"] +#![crate_type = "rlib"] + +extern crate a; + +static FOO: usize = 3; + +pub fn token() -> &'static usize { &FOO } +pub fn a_token() -> &'static usize { a::token() } diff --git a/src/test/run-make-fulldeps/extern-flag-disambiguates/c.rs b/src/test/run-make-fulldeps/extern-flag-disambiguates/c.rs new file mode 100644 index 000000000..3f9d143ed --- /dev/null +++ b/src/test/run-make-fulldeps/extern-flag-disambiguates/c.rs @@ -0,0 +1,9 @@ +#![crate_name = "c"] +#![crate_type = "rlib"] + +extern crate a; + +static FOO: usize = 3; + +pub fn token() -> &'static usize { &FOO } +pub fn a_token() -> &'static usize { a::token() } diff --git a/src/test/run-make-fulldeps/extern-flag-disambiguates/d.rs b/src/test/run-make-fulldeps/extern-flag-disambiguates/d.rs new file mode 100644 index 000000000..249c6a107 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-flag-disambiguates/d.rs @@ -0,0 +1,11 @@ +#[cfg(before)] extern crate a; +extern crate b; +extern crate c; +#[cfg(after)] extern crate a; + +fn t(a: &'static usize) -> usize { a as *const _ as usize } + +fn main() { + assert_eq!(t(a::token()), t(b::a_token())); + assert!(t(a::token()) != t(c::a_token())); +} diff --git a/src/test/run-make-fulldeps/extern-flag-fun/Makefile b/src/test/run-make-fulldeps/extern-flag-fun/Makefile new file mode 100644 index 000000000..38d1d5bb8 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-flag-fun/Makefile @@ -0,0 +1,19 @@ +-include ../tools.mk + +all: + $(RUSTC) bar.rs --crate-type=rlib + $(RUSTC) bar.rs --crate-type=rlib -C extra-filename=-a + $(RUSTC) bar-alt.rs --crate-type=rlib + $(RUSTC) foo.rs --extern bar=no-exist && exit 1 || exit 0 + $(RUSTC) foo.rs --extern bar=foo.rs && exit 1 || exit 0 + $(RUSTC) foo.rs \ + --extern bar=$(TMPDIR)/libbar.rlib \ + --extern bar=$(TMPDIR)/libbar-alt.rlib \ + && exit 1 || exit 0 + $(RUSTC) foo.rs \ + --extern bar=$(TMPDIR)/libbar.rlib \ + --extern bar=$(TMPDIR)/libbar-a.rlib + $(RUSTC) foo.rs --extern bar=$(TMPDIR)/libbar.rlib + # Try to be sneaky and load a private crate from with a non-private name. + $(RUSTC) rustc.rs -Zforce-unstable-if-unmarked --crate-type=rlib + $(RUSTC) gated_unstable.rs --extern alloc=$(TMPDIR)/librustc.rlib 2>&1 | $(CGREP) 'rustc_private' diff --git a/src/test/run-make-fulldeps/extern-flag-fun/bar-alt.rs b/src/test/run-make-fulldeps/extern-flag-fun/bar-alt.rs new file mode 100644 index 000000000..cdc6c27d8 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-flag-fun/bar-alt.rs @@ -0,0 +1 @@ +pub fn f() {} diff --git a/src/test/run-make-fulldeps/extern-flag-fun/bar.rs b/src/test/run-make-fulldeps/extern-flag-fun/bar.rs new file mode 100644 index 000000000..d11c69f81 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-flag-fun/bar.rs @@ -0,0 +1 @@ +// intentionally empty diff --git a/src/test/run-make-fulldeps/extern-flag-fun/foo.rs b/src/test/run-make-fulldeps/extern-flag-fun/foo.rs new file mode 100644 index 000000000..0edda7d7b --- /dev/null +++ b/src/test/run-make-fulldeps/extern-flag-fun/foo.rs @@ -0,0 +1,3 @@ +extern crate bar; + +fn main() {} diff --git a/src/test/run-make-fulldeps/extern-flag-fun/gated_unstable.rs b/src/test/run-make-fulldeps/extern-flag-fun/gated_unstable.rs new file mode 100644 index 000000000..03600c830 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-flag-fun/gated_unstable.rs @@ -0,0 +1,3 @@ +extern crate alloc; + +fn main() {} diff --git a/src/test/run-make-fulldeps/extern-flag-fun/rustc.rs b/src/test/run-make-fulldeps/extern-flag-fun/rustc.rs new file mode 100644 index 000000000..b76b4321d --- /dev/null +++ b/src/test/run-make-fulldeps/extern-flag-fun/rustc.rs @@ -0,0 +1 @@ +pub fn foo() {} diff --git a/src/test/run-make-fulldeps/extern-flag-pathless/Makefile b/src/test/run-make-fulldeps/extern-flag-pathless/Makefile new file mode 100644 index 000000000..4849fc62f --- /dev/null +++ b/src/test/run-make-fulldeps/extern-flag-pathless/Makefile @@ -0,0 +1,18 @@ +-include ../tools.mk + +# Test mixing pathless --extern with paths. + +all: + $(RUSTC) bar-static.rs --crate-name=bar --crate-type=rlib + $(RUSTC) bar-dynamic.rs --crate-name=bar --crate-type=dylib -C prefer-dynamic + # rlib preferred over dylib + $(RUSTC) foo.rs --extern bar + $(call RUN,foo) | $(CGREP) 'static' + $(RUSTC) foo.rs --extern bar=$(TMPDIR)/libbar.rlib --extern bar + $(call RUN,foo) | $(CGREP) 'static' + # explicit --extern overrides pathless + $(RUSTC) foo.rs --extern bar=$(call DYLIB,bar) --extern bar + $(call RUN,foo) | $(CGREP) 'dynamic' + # prefer-dynamic does what it says + $(RUSTC) foo.rs --extern bar -C prefer-dynamic + $(call RUN,foo) | $(CGREP) 'dynamic' diff --git a/src/test/run-make-fulldeps/extern-flag-pathless/bar-dynamic.rs b/src/test/run-make-fulldeps/extern-flag-pathless/bar-dynamic.rs new file mode 100644 index 000000000..e2d68d517 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-flag-pathless/bar-dynamic.rs @@ -0,0 +1,3 @@ +pub fn f() { + println!("dynamic"); +} diff --git a/src/test/run-make-fulldeps/extern-flag-pathless/bar-static.rs b/src/test/run-make-fulldeps/extern-flag-pathless/bar-static.rs new file mode 100644 index 000000000..240d8bde4 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-flag-pathless/bar-static.rs @@ -0,0 +1,3 @@ +pub fn f() { + println!("static"); +} diff --git a/src/test/run-make-fulldeps/extern-flag-pathless/foo.rs b/src/test/run-make-fulldeps/extern-flag-pathless/foo.rs new file mode 100644 index 000000000..1ea64da7d --- /dev/null +++ b/src/test/run-make-fulldeps/extern-flag-pathless/foo.rs @@ -0,0 +1,3 @@ +fn main() { + bar::f(); +} diff --git a/src/test/run-make-fulldeps/extern-flag-rename-transitive/Makefile b/src/test/run-make-fulldeps/extern-flag-rename-transitive/Makefile new file mode 100644 index 000000000..4354209a7 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-flag-rename-transitive/Makefile @@ -0,0 +1,7 @@ +-include ../tools.mk + +all: + $(RUSTC) foo.rs + $(RUSTC) bar.rs + $(RUSTC) baz.rs --extern a=$(TMPDIR)/libfoo.rlib + diff --git a/src/test/run-make-fulldeps/extern-flag-rename-transitive/bar.rs b/src/test/run-make-fulldeps/extern-flag-rename-transitive/bar.rs new file mode 100644 index 000000000..94446a07d --- /dev/null +++ b/src/test/run-make-fulldeps/extern-flag-rename-transitive/bar.rs @@ -0,0 +1,3 @@ +#![crate_type = "rlib"] + +extern crate foo; diff --git a/src/test/run-make-fulldeps/extern-flag-rename-transitive/baz.rs b/src/test/run-make-fulldeps/extern-flag-rename-transitive/baz.rs new file mode 100644 index 000000000..c3908db34 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-flag-rename-transitive/baz.rs @@ -0,0 +1,4 @@ +#![crate_type = "rlib"] + +extern crate a; +extern crate bar; diff --git a/src/test/run-make-fulldeps/extern-flag-rename-transitive/foo.rs b/src/test/run-make-fulldeps/extern-flag-rename-transitive/foo.rs new file mode 100644 index 000000000..c1bfaa6ca --- /dev/null +++ b/src/test/run-make-fulldeps/extern-flag-rename-transitive/foo.rs @@ -0,0 +1 @@ +#![crate_type = "rlib"] diff --git a/src/test/run-make-fulldeps/extern-fn-generic/Makefile b/src/test/run-make-fulldeps/extern-fn-generic/Makefile new file mode 100644 index 000000000..cf897dba1 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-fn-generic/Makefile @@ -0,0 +1,6 @@ +-include ../tools.mk + +all: $(call NATIVE_STATICLIB,test) + $(RUSTC) testcrate.rs + $(RUSTC) test.rs + $(call RUN,test) || exit 1 diff --git a/src/test/run-make-fulldeps/extern-fn-generic/test.c b/src/test/run-make-fulldeps/extern-fn-generic/test.c new file mode 100644 index 000000000..a8504ff2a --- /dev/null +++ b/src/test/run-make-fulldeps/extern-fn-generic/test.c @@ -0,0 +1,16 @@ +#include <stdint.h> + +typedef struct TestStruct { + uint8_t x; + int32_t y; +} TestStruct; + +typedef int callback(TestStruct s); + +uint32_t call(callback *c) { + TestStruct s; + s.x = 'a'; + s.y = 3; + + return c(s); +} diff --git a/src/test/run-make-fulldeps/extern-fn-generic/test.rs b/src/test/run-make-fulldeps/extern-fn-generic/test.rs new file mode 100644 index 000000000..c9baa4898 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-fn-generic/test.rs @@ -0,0 +1,20 @@ +extern crate testcrate; + +extern "C" fn bar<T>(ts: testcrate::TestStruct<T>) -> T { + ts.y +} + +#[link(name = "test", kind = "static")] +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>) }; + assert_eq!(3, back); + + // And just within this crate + let back = unsafe { call(bar::<i32>) }; + assert_eq!(3, back); +} diff --git a/src/test/run-make-fulldeps/extern-fn-generic/testcrate.rs b/src/test/run-make-fulldeps/extern-fn-generic/testcrate.rs new file mode 100644 index 000000000..39f76e59c --- /dev/null +++ b/src/test/run-make-fulldeps/extern-fn-generic/testcrate.rs @@ -0,0 +1,16 @@ +#![crate_type = "lib"] + +#[repr(C)] +pub struct TestStruct<T> { + pub x: u8, + pub y: T, +} + +pub extern "C" fn foo<T>(ts: TestStruct<T>) -> T { + ts.y +} + +#[link(name = "test", kind = "static")] +extern "C" { + pub fn call(c: extern "C" fn(TestStruct<i32>) -> i32) -> i32; +} diff --git a/src/test/run-make-fulldeps/extern-fn-mangle/Makefile b/src/test/run-make-fulldeps/extern-fn-mangle/Makefile new file mode 100644 index 000000000..042048ec2 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-fn-mangle/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: $(call NATIVE_STATICLIB,test) + $(RUSTC) test.rs + $(call RUN,test) || exit 1 diff --git a/src/test/run-make-fulldeps/extern-fn-mangle/test.c b/src/test/run-make-fulldeps/extern-fn-mangle/test.c new file mode 100644 index 000000000..e94d75083 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-fn-mangle/test.c @@ -0,0 +1,8 @@ +#include <stdint.h> + +uint32_t foo(); +uint32_t bar(); + +uint32_t add() { + return foo() + bar(); +} diff --git a/src/test/run-make-fulldeps/extern-fn-mangle/test.rs b/src/test/run-make-fulldeps/extern-fn-mangle/test.rs new file mode 100644 index 000000000..40b08f1ed --- /dev/null +++ b/src/test/run-make-fulldeps/extern-fn-mangle/test.rs @@ -0,0 +1,19 @@ +#[no_mangle] +pub extern "C" fn foo() -> i32 { + 3 +} + +#[no_mangle] +pub extern "C" fn bar() -> i32 { + 5 +} + +#[link(name = "test", kind = "static")] +extern "C" { + fn add() -> i32; +} + +fn main() { + let back = unsafe { add() }; + assert_eq!(8, back); +} diff --git a/src/test/run-make-fulldeps/extern-fn-reachable/Makefile b/src/test/run-make-fulldeps/extern-fn-reachable/Makefile new file mode 100644 index 000000000..9231a2b35 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-fn-reachable/Makefile @@ -0,0 +1,25 @@ +-include ../tools.mk + +# ignore-windows-msvc + +NM=nm -D + +ifeq ($(UNAME),Darwin) +NM=nm -gU +endif + +ifdef IS_WINDOWS +NM=nm -g +endif + +# This overrides the LD_LIBRARY_PATH for RUN +TARGET_RPATH_DIR:=$(TARGET_RPATH_DIR):$(TMPDIR) + +all: + $(RUSTC) dylib.rs -o $(TMPDIR)/libdylib.so -C prefer-dynamic + + [ "$$($(NM) $(TMPDIR)/libdylib.so | grep -v __imp_ | grep -c fun1)" -eq "1" ] + [ "$$($(NM) $(TMPDIR)/libdylib.so | grep -v __imp_ | grep -c fun2)" -eq "1" ] + [ "$$($(NM) $(TMPDIR)/libdylib.so | grep -v __imp_ | grep -c fun3)" -eq "1" ] + [ "$$($(NM) $(TMPDIR)/libdylib.so | grep -v __imp_ | grep -c fun4)" -eq "1" ] + [ "$$($(NM) $(TMPDIR)/libdylib.so | grep -v __imp_ | grep -c fun5)" -eq "1" ] diff --git a/src/test/run-make-fulldeps/extern-fn-reachable/dylib.rs b/src/test/run-make-fulldeps/extern-fn-reachable/dylib.rs new file mode 100644 index 000000000..cd0179348 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-fn-reachable/dylib.rs @@ -0,0 +1,14 @@ +#![crate_type = "dylib"] +#![allow(dead_code)] + +#[no_mangle] pub extern "C" fn fun1() {} +#[no_mangle] extern "C" fn fun2() {} + +mod foo { + #[no_mangle] pub extern "C" fn fun3() {} +} +pub mod bar { + #[no_mangle] pub extern "C" fn fun4() {} +} + +#[no_mangle] pub fn fun5() {} diff --git a/src/test/run-make-fulldeps/extern-fn-struct-passing-abi/Makefile b/src/test/run-make-fulldeps/extern-fn-struct-passing-abi/Makefile new file mode 100644 index 000000000..042048ec2 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-fn-struct-passing-abi/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: $(call NATIVE_STATICLIB,test) + $(RUSTC) test.rs + $(call RUN,test) || exit 1 diff --git a/src/test/run-make-fulldeps/extern-fn-struct-passing-abi/test.c b/src/test/run-make-fulldeps/extern-fn-struct-passing-abi/test.c new file mode 100644 index 000000000..136b07129 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-fn-struct-passing-abi/test.c @@ -0,0 +1,314 @@ +#include <assert.h> +#include <stdint.h> + +struct Rect { + int32_t a; + int32_t b; + int32_t c; + int32_t d; +}; + +struct BiggerRect { + struct Rect s; + int32_t a; + int32_t b; +}; + +struct FloatRect { + int32_t a; + int32_t b; + double c; +}; + +struct Huge { + int32_t a; + int32_t b; + int32_t c; + int32_t d; + int32_t e; +}; + +struct FloatPoint { + double x; + double y; +}; + +struct FloatOne { + double x; +}; + +struct IntOdd { + int8_t a; + int8_t b; + int8_t c; +}; + +// System V x86_64 ABI: +// a, b, c, d, e should be in registers +// s should be byval pointer +// +// Win64 ABI: +// a, b, c, d should be in registers +// e should be on the stack +// s should be byval pointer +void byval_rect(int32_t a, int32_t b, int32_t c, int32_t d, int32_t e, struct Rect s) { + assert(a == 1); + assert(b == 2); + assert(c == 3); + assert(d == 4); + assert(e == 5); + assert(s.a == 553); + assert(s.b == 554); + assert(s.c == 555); + assert(s.d == 556); +} + +// System V x86_64 ABI: +// a, b, c, d, e, f should be in registers +// s should be byval pointer on the stack +// +// Win64 ABI: +// a, b, c, d should be in registers +// e, f should be on the stack +// s should be byval pointer on the stack +void byval_many_rect(int32_t a, int32_t b, int32_t c, int32_t d, int32_t e, + int32_t f, struct Rect s) { + assert(a == 1); + assert(b == 2); + assert(c == 3); + assert(d == 4); + assert(e == 5); + assert(f == 6); + assert(s.a == 553); + assert(s.b == 554); + assert(s.c == 555); + assert(s.d == 556); +} + +// System V x86_64 ABI: +// a, b, c, d, e, f, g should be in sse registers +// s should be split across 2 registers +// t should be byval pointer +// +// Win64 ABI: +// a, b, c, d should be in sse registers +// e, f, g should be on the stack +// s should be on the stack (treated as 2 i64's) +// t should be on the stack (treated as an i64 and a double) +void byval_rect_floats(float a, float b, double c, float d, float e, + float f, double g, struct Rect s, struct FloatRect t) { + assert(a == 1.); + assert(b == 2.); + assert(c == 3.); + assert(d == 4.); + assert(e == 5.); + assert(f == 6.); + assert(g == 7.); + assert(s.a == 553); + assert(s.b == 554); + assert(s.c == 555); + assert(s.d == 556); + assert(t.a == 3489); + assert(t.b == 3490); + assert(t.c == 8.); +} + +// System V x86_64 ABI: +// a, b, d, e, f should be in registers +// c passed via sse registers +// s should be byval pointer +// +// Win64 ABI: +// a, b, d should be in registers +// c passed via sse registers +// e, f should be on the stack +// s should be byval pointer +void byval_rect_with_float(int32_t a, int32_t b, float c, int32_t d, + int32_t e, int32_t f, struct Rect s) { + assert(a == 1); + assert(b == 2); + assert(c == 3.); + assert(d == 4); + assert(e == 5); + assert(f == 6); + assert(s.a == 553); + assert(s.b == 554); + assert(s.c == 555); + assert(s.d == 556); +} + +// System V x86_64 ABI: +// a, b, d, e, f should be byval pointer (on the stack) +// g passed via register (fixes #41375) +// +// Win64 ABI: +// a, b, d, e, f, g should be byval pointer +void byval_rect_with_many_huge(struct Huge a, struct Huge b, struct Huge c, + struct Huge d, struct Huge e, struct Huge f, + struct Rect g) { + assert(g.a == 123); + assert(g.b == 456); + assert(g.c == 789); + assert(g.d == 420); +} + +// System V x86_64 & Win64 ABI: +// a, b should be in registers +// s should be split across 2 integer registers +void split_rect(int32_t a, int32_t b, struct Rect s) { + assert(a == 1); + assert(b == 2); + assert(s.a == 553); + assert(s.b == 554); + assert(s.c == 555); + assert(s.d == 556); +} + +// System V x86_64 & Win64 ABI: +// a, b should be in sse registers +// s should be split across integer & sse registers +void split_rect_floats(float a, float b, struct FloatRect s) { + assert(a == 1.); + assert(b == 2.); + assert(s.a == 3489); + assert(s.b == 3490); + assert(s.c == 8.); +} + +// System V x86_64 ABI: +// a, b, d, f should be in registers +// c, e passed via sse registers +// s should be split across 2 registers +// +// Win64 ABI: +// a, b, d should be in registers +// c passed via sse registers +// e, f should be on the stack +// s should be on the stack (treated as 2 i64's) +void split_rect_with_floats(int32_t a, int32_t b, float c, + int32_t d, float e, int32_t f, struct Rect s) { + assert(a == 1); + assert(b == 2); + assert(c == 3.); + assert(d == 4); + assert(e == 5.); + assert(f == 6); + assert(s.a == 553); + assert(s.b == 554); + assert(s.c == 555); + assert(s.d == 556); +} + +// System V x86_64 & Win64 ABI: +// a, b, c should be in registers +// s should be split across 2 registers +// t should be a byval pointer +void split_and_byval_rect(int32_t a, int32_t b, int32_t c, struct Rect s, struct Rect t) { + assert(a == 1); + assert(b == 2); + assert(c == 3); + assert(s.a == 553); + assert(s.b == 554); + assert(s.c == 555); + assert(s.d == 556); + assert(t.a == 553); + assert(t.b == 554); + assert(t.c == 555); + assert(t.d == 556); +} + +// System V x86_64 & Win64 ABI: +// a, b should in registers +// s and return should be split across 2 registers +struct Rect split_ret_byval_struct(int32_t a, int32_t b, struct Rect s) { + assert(a == 1); + assert(b == 2); + assert(s.a == 553); + assert(s.b == 554); + assert(s.c == 555); + assert(s.d == 556); + return s; +} + +// System V x86_64 & Win64 ABI: +// a, b, c, d should be in registers +// return should be in a hidden sret pointer +// s should be a byval pointer +struct BiggerRect sret_byval_struct(int32_t a, int32_t b, int32_t c, int32_t d, struct Rect s) { + assert(a == 1); + assert(b == 2); + assert(c == 3); + assert(d == 4); + assert(s.a == 553); + assert(s.b == 554); + assert(s.c == 555); + assert(s.d == 556); + + struct BiggerRect t; + t.s = s; t.a = 27834; t.b = 7657; + return t; +} + +// System V x86_64 & Win64 ABI: +// a, b should be in registers +// return should be in a hidden sret pointer +// s should be split across 2 registers +struct BiggerRect sret_split_struct(int32_t a, int32_t b, struct Rect s) { + assert(a == 1); + assert(b == 2); + assert(s.a == 553); + assert(s.b == 554); + assert(s.c == 555); + assert(s.d == 556); + + struct BiggerRect t; + t.s = s; t.a = 27834; t.b = 7657; + return t; +} + +// System V x86_64 & Win64 ABI: +// s should be byval pointer (since sizeof(s) > 16) +// return should in a hidden sret pointer +struct Huge huge_struct(struct Huge s) { + assert(s.a == 5647); + assert(s.b == 5648); + assert(s.c == 5649); + assert(s.d == 5650); + assert(s.e == 5651); + + return s; +} + +// System V x86_64 ABI: +// p should be in registers +// return should be in registers +// +// Win64 ABI and 64-bit PowerPC ELFv1 ABI: +// p should be a byval pointer +// return should be in a hidden sret pointer +struct FloatPoint float_point(struct FloatPoint p) { + assert(p.x == 5.); + assert(p.y == -3.); + + return p; +} + +// 64-bit PowerPC ELFv1 ABI: +// f1 should be in a register +// return should be in a hidden sret pointer +struct FloatOne float_one(struct FloatOne f1) { + assert(f1.x == 7.); + + return f1; +} + +// 64-bit PowerPC ELFv1 ABI: +// i should be in the least-significant bits of a register +// return should be in a hidden sret pointer +struct IntOdd int_odd(struct IntOdd i) { + assert(i.a == 1); + assert(i.b == 2); + assert(i.c == 3); + + return i; +} diff --git a/src/test/run-make-fulldeps/extern-fn-struct-passing-abi/test.rs b/src/test/run-make-fulldeps/extern-fn-struct-passing-abi/test.rs new file mode 100644 index 000000000..afe0f52ef --- /dev/null +++ b/src/test/run-make-fulldeps/extern-fn-struct-passing-abi/test.rs @@ -0,0 +1,138 @@ +// Passing structs via FFI should work regardless of whether +// they get passed in multiple registers, byval pointers or the stack + +#[derive(Clone, Copy, Debug, PartialEq)] +#[repr(C)] +struct Rect { + a: i32, + b: i32, + c: i32, + d: i32, +} + +#[derive(Clone, Copy, Debug, PartialEq)] +#[repr(C)] +struct BiggerRect { + s: Rect, + a: i32, + b: i32, +} + +#[derive(Clone, Copy, Debug, PartialEq)] +#[repr(C)] +struct FloatRect { + a: i32, + b: i32, + c: f64, +} + +#[derive(Clone, Copy, Debug, PartialEq)] +#[repr(C)] +struct Huge { + a: i32, + b: i32, + c: i32, + d: i32, + e: i32, +} + +#[derive(Clone, Copy, Debug, PartialEq)] +#[repr(C)] +struct FloatPoint { + x: f64, + y: f64, +} + +#[derive(Clone, Copy, Debug, PartialEq)] +#[repr(C)] +struct FloatOne { + x: f64, +} + +#[derive(Clone, Copy, Debug, PartialEq)] +#[repr(C)] +struct IntOdd { + a: i8, + b: i8, + c: i8, +} + +#[link(name = "test", kind = "static")] +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_with_float(a: i32, b: i32, c: f32, d: i32, e: i32, f: i32, s: Rect); + + fn byval_rect_with_many_huge(a: Huge, b: Huge, c: Huge, d: Huge, e: Huge, f: Huge, g: Rect); + + fn split_rect(a: i32, b: i32, s: Rect); + + fn split_rect_floats(a: f32, b: f32, s: FloatRect); + + fn split_rect_with_floats(a: i32, b: i32, c: f32, d: i32, e: f32, f: i32, s: Rect); + + fn split_and_byval_rect(a: i32, b: i32, c: i32, s: Rect, t: Rect); + + fn split_ret_byval_struct(a: i32, b: i32, s: Rect) -> Rect; + + fn sret_byval_struct(a: i32, b: i32, c: i32, d: i32, s: Rect) -> BiggerRect; + + fn sret_split_struct(a: i32, b: i32, s: Rect) -> BiggerRect; + + fn huge_struct(s: Huge) -> Huge; + + fn float_point(p: FloatPoint) -> FloatPoint; + + fn float_one(f: FloatOne) -> FloatOne; + + fn int_odd(i: IntOdd) -> IntOdd; +} + +fn main() { + let s = Rect { a: 553, b: 554, c: 555, d: 556 }; + let t = BiggerRect { s: s, a: 27834, b: 7657 }; + let u = FloatRect { a: 3489, b: 3490, c: 8. }; + let v = Huge { a: 5647, b: 5648, c: 5649, d: 5650, e: 5651 }; + let p = FloatPoint { x: 5., y: -3. }; + let f1 = FloatOne { x: 7. }; + let i = IntOdd { a: 1, b: 2, c: 3 }; + + unsafe { + byval_rect(1, 2, 3, 4, 5, s); + 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 }); + split_rect(1, 2, s); + split_rect_floats(1., 2., u); + split_rect_with_floats(1, 2, 3.0, 4, 5.0, 6, s); + split_and_byval_rect(1, 2, 3, s, s); + split_rect(1, 2, s); + assert_eq!(huge_struct(v), v); + assert_eq!(split_ret_byval_struct(1, 2, s), s); + assert_eq!(sret_byval_struct(1, 2, 3, 4, s), t); + assert_eq!(sret_split_struct(1, 2, s), t); + assert_eq!(float_point(p), p); + assert_eq!(int_odd(i), i); + + // MSVC/GCC/Clang are not consistent in the ABI of single-float aggregates. + // x86_64: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82028 + // i686: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82041 + #[cfg(not(all(windows, target_env = "gnu")))] + assert_eq!(float_one(f1), f1); + } +} diff --git a/src/test/run-make-fulldeps/extern-fn-with-extern-types/Makefile b/src/test/run-make-fulldeps/extern-fn-with-extern-types/Makefile new file mode 100644 index 000000000..8977e14c3 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-fn-with-extern-types/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: $(call NATIVE_STATICLIB,ctest) + $(RUSTC) test.rs + $(call RUN,test) || exit 1 diff --git a/src/test/run-make-fulldeps/extern-fn-with-extern-types/ctest.c b/src/test/run-make-fulldeps/extern-fn-with-extern-types/ctest.c new file mode 100644 index 000000000..3b6fb4cfc --- /dev/null +++ b/src/test/run-make-fulldeps/extern-fn-with-extern-types/ctest.c @@ -0,0 +1,16 @@ +#include <stdio.h> +#include <stdint.h> + +typedef struct data { + uint32_t magic; +} data; + +data* data_create(uint32_t magic) { + static data d; + d.magic = magic; + return &d; +} + +uint32_t data_get(data* p) { + return p->magic; +} diff --git a/src/test/run-make-fulldeps/extern-fn-with-extern-types/test.rs b/src/test/run-make-fulldeps/extern-fn-with-extern-types/test.rs new file mode 100644 index 000000000..90a6ebaf1 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-fn-with-extern-types/test.rs @@ -0,0 +1,17 @@ +#![feature(extern_types)] + +#[link(name = "ctest", kind = "static")] +extern "C" { + type data; + + fn data_create(magic: u32) -> *mut data; + fn data_get(data: *mut data) -> u32; +} + +const MAGIC: u32 = 0xdeadbeef; +fn main() { + unsafe { + let data = data_create(MAGIC); + assert_eq!(data_get(data), MAGIC); + } +} diff --git a/src/test/run-make-fulldeps/extern-fn-with-packed-struct/Makefile b/src/test/run-make-fulldeps/extern-fn-with-packed-struct/Makefile new file mode 100644 index 000000000..042048ec2 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-fn-with-packed-struct/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: $(call NATIVE_STATICLIB,test) + $(RUSTC) test.rs + $(call RUN,test) || exit 1 diff --git a/src/test/run-make-fulldeps/extern-fn-with-packed-struct/test.c b/src/test/run-make-fulldeps/extern-fn-with-packed-struct/test.c new file mode 100644 index 000000000..c89f8272b --- /dev/null +++ b/src/test/run-make-fulldeps/extern-fn-with-packed-struct/test.c @@ -0,0 +1,26 @@ +// Pragma needed cause of gcc bug on windows: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52991 + +#include <assert.h> + +#ifdef _MSC_VER +#pragma pack(push,1) +struct Foo { + char a; + short b; + char c; +}; +#else +#pragma pack(1) +struct __attribute__((packed)) Foo { + char a; + short b; + char c; +}; +#endif + +struct Foo foo(struct Foo foo) { + assert(foo.a == 1); + assert(foo.b == 2); + assert(foo.c == 3); + return foo; +} diff --git a/src/test/run-make-fulldeps/extern-fn-with-packed-struct/test.rs b/src/test/run-make-fulldeps/extern-fn-with-packed-struct/test.rs new file mode 100644 index 000000000..2f261efb5 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-fn-with-packed-struct/test.rs @@ -0,0 +1,20 @@ +#[repr(C, packed)] +#[derive(Copy, Clone, Debug, PartialEq)] +struct Foo { + a: i8, + b: i16, + c: i8, +} + +#[link(name = "test", kind = "static")] +extern "C" { + fn foo(f: Foo) -> Foo; +} + +fn main() { + unsafe { + let a = Foo { a: 1, b: 2, c: 3 }; + let b = foo(a); + assert_eq!(a, b); + } +} diff --git a/src/test/run-make-fulldeps/extern-fn-with-union/Makefile b/src/test/run-make-fulldeps/extern-fn-with-union/Makefile new file mode 100644 index 000000000..71a5407e8 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-fn-with-union/Makefile @@ -0,0 +1,6 @@ +-include ../tools.mk + +all: $(call NATIVE_STATICLIB,ctest) + $(RUSTC) testcrate.rs + $(RUSTC) test.rs + $(call RUN,test) || exit 1 diff --git a/src/test/run-make-fulldeps/extern-fn-with-union/ctest.c b/src/test/run-make-fulldeps/extern-fn-with-union/ctest.c new file mode 100644 index 000000000..86cb64537 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-fn-with-union/ctest.c @@ -0,0 +1,10 @@ +#include <stdio.h> +#include <stdint.h> + +typedef union TestUnion { + uint64_t bits; +} TestUnion; + +uint64_t give_back(TestUnion tu) { + return tu.bits; +} diff --git a/src/test/run-make-fulldeps/extern-fn-with-union/test.rs b/src/test/run-make-fulldeps/extern-fn-with-union/test.rs new file mode 100644 index 000000000..438fbddf3 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-fn-with-union/test.rs @@ -0,0 +1,19 @@ +extern crate testcrate; + +use std::mem; + +extern "C" { + fn give_back(tu: testcrate::TestUnion) -> u64; +} + +fn main() { + let magic: u64 = 0xDEADBEEF; + + // Let's test calling it cross crate + 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)) }; + assert_eq!(magic, back); +} diff --git a/src/test/run-make-fulldeps/extern-fn-with-union/testcrate.rs b/src/test/run-make-fulldeps/extern-fn-with-union/testcrate.rs new file mode 100644 index 000000000..28d91ff37 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-fn-with-union/testcrate.rs @@ -0,0 +1,11 @@ +#![crate_type = "lib"] + +#[repr(C)] +pub struct TestUnion { + _val: u64, +} + +#[link(name = "ctest", kind = "static")] +extern "C" { + pub fn give_back(tu: TestUnion) -> u64; +} diff --git a/src/test/run-make-fulldeps/extern-multiple-copies/Makefile b/src/test/run-make-fulldeps/extern-multiple-copies/Makefile new file mode 100644 index 000000000..1631aa806 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-multiple-copies/Makefile @@ -0,0 +1,8 @@ +-include ../tools.mk + +all: + $(RUSTC) foo1.rs + $(RUSTC) foo2.rs + mkdir $(TMPDIR)/foo + cp $(TMPDIR)/libfoo1.rlib $(TMPDIR)/foo/libfoo1.rlib + $(RUSTC) bar.rs --extern foo1=$(TMPDIR)/libfoo1.rlib -L $(TMPDIR)/foo diff --git a/src/test/run-make-fulldeps/extern-multiple-copies/bar.rs b/src/test/run-make-fulldeps/extern-multiple-copies/bar.rs new file mode 100644 index 000000000..c6b3595f6 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-multiple-copies/bar.rs @@ -0,0 +1,6 @@ +extern crate foo2; // foo2 first to exhibit the bug +extern crate foo1; + +fn main() { + /* ... */ +} diff --git a/src/test/run-make-fulldeps/extern-multiple-copies/foo1.rs b/src/test/run-make-fulldeps/extern-multiple-copies/foo1.rs new file mode 100644 index 000000000..c1bfaa6ca --- /dev/null +++ b/src/test/run-make-fulldeps/extern-multiple-copies/foo1.rs @@ -0,0 +1 @@ +#![crate_type = "rlib"] diff --git a/src/test/run-make-fulldeps/extern-multiple-copies/foo2.rs b/src/test/run-make-fulldeps/extern-multiple-copies/foo2.rs new file mode 100644 index 000000000..c1bfaa6ca --- /dev/null +++ b/src/test/run-make-fulldeps/extern-multiple-copies/foo2.rs @@ -0,0 +1 @@ +#![crate_type = "rlib"] diff --git a/src/test/run-make-fulldeps/extern-multiple-copies2/Makefile b/src/test/run-make-fulldeps/extern-multiple-copies2/Makefile new file mode 100644 index 000000000..567d7e78a --- /dev/null +++ b/src/test/run-make-fulldeps/extern-multiple-copies2/Makefile @@ -0,0 +1,10 @@ +-include ../tools.mk + +all: + $(RUSTC) foo1.rs + $(RUSTC) foo2.rs + mkdir $(TMPDIR)/foo + cp $(TMPDIR)/libfoo1.rlib $(TMPDIR)/foo/libfoo1.rlib + $(RUSTC) bar.rs \ + --extern foo1=$(TMPDIR)/foo/libfoo1.rlib \ + --extern foo2=$(TMPDIR)/libfoo2.rlib diff --git a/src/test/run-make-fulldeps/extern-multiple-copies2/bar.rs b/src/test/run-make-fulldeps/extern-multiple-copies2/bar.rs new file mode 100644 index 000000000..b3088152d --- /dev/null +++ b/src/test/run-make-fulldeps/extern-multiple-copies2/bar.rs @@ -0,0 +1,8 @@ +#[macro_use] +extern crate foo2; // foo2 first to exhibit the bug +#[macro_use] +extern crate foo1; + +fn main() { + foo2::foo2(foo1::A); +} diff --git a/src/test/run-make-fulldeps/extern-multiple-copies2/foo1.rs b/src/test/run-make-fulldeps/extern-multiple-copies2/foo1.rs new file mode 100644 index 000000000..4c778e52f --- /dev/null +++ b/src/test/run-make-fulldeps/extern-multiple-copies2/foo1.rs @@ -0,0 +1,7 @@ +#![crate_type = "rlib"] + +pub struct A; + +pub fn foo1(a: A) { + drop(a); +} diff --git a/src/test/run-make-fulldeps/extern-multiple-copies2/foo2.rs b/src/test/run-make-fulldeps/extern-multiple-copies2/foo2.rs new file mode 100644 index 000000000..2be103507 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-multiple-copies2/foo2.rs @@ -0,0 +1,8 @@ +#![crate_type = "rlib"] + +#[macro_use] +extern crate foo1; + +pub fn foo2(a: foo1::A) { + foo1::foo1(a); +} diff --git a/src/test/run-make-fulldeps/extern-overrides-distribution/Makefile b/src/test/run-make-fulldeps/extern-overrides-distribution/Makefile new file mode 100644 index 000000000..7d063a4c8 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-overrides-distribution/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: + $(RUSTC) libc.rs -Cmetadata=foo + $(RUSTC) main.rs --extern libc=$(TMPDIR)/liblibc.rlib diff --git a/src/test/run-make-fulldeps/extern-overrides-distribution/libc.rs b/src/test/run-make-fulldeps/extern-overrides-distribution/libc.rs new file mode 100644 index 000000000..ee51ae328 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-overrides-distribution/libc.rs @@ -0,0 +1,3 @@ +#![crate_type = "lib"] + +pub fn foo() {} diff --git a/src/test/run-make-fulldeps/extern-overrides-distribution/main.rs b/src/test/run-make-fulldeps/extern-overrides-distribution/main.rs new file mode 100644 index 000000000..1290a8c56 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-overrides-distribution/main.rs @@ -0,0 +1,5 @@ +extern crate libc; + +fn main() { + libc::foo(); +} diff --git a/src/test/run-make-fulldeps/extra-filename-with-temp-outputs/Makefile b/src/test/run-make-fulldeps/extra-filename-with-temp-outputs/Makefile new file mode 100644 index 000000000..e46390a9d --- /dev/null +++ b/src/test/run-make-fulldeps/extra-filename-with-temp-outputs/Makefile @@ -0,0 +1,6 @@ +-include ../tools.mk + +all: + $(RUSTC) -C extra-filename=bar foo.rs -C save-temps + rm $(TMPDIR)/foobar.foo*0.rcgu.o + rm $(TMPDIR)/$(call BIN,foobar) diff --git a/src/test/run-make-fulldeps/extra-filename-with-temp-outputs/foo.rs b/src/test/run-make-fulldeps/extra-filename-with-temp-outputs/foo.rs new file mode 100644 index 000000000..f328e4d9d --- /dev/null +++ b/src/test/run-make-fulldeps/extra-filename-with-temp-outputs/foo.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/src/test/run-make-fulldeps/foreign-double-unwind/Makefile b/src/test/run-make-fulldeps/foreign-double-unwind/Makefile new file mode 100644 index 000000000..27cf4d19c --- /dev/null +++ b/src/test/run-make-fulldeps/foreign-double-unwind/Makefile @@ -0,0 +1,10 @@ +-include ../tools.mk + +all: foo + $(call RUN,foo) | $(CGREP) -v unreachable + +foo: foo.rs $(call NATIVE_STATICLIB,foo) + $(RUSTC) $< -lfoo $(EXTRARSCXXFLAGS) + +$(TMPDIR)/libfoo.o: foo.cpp + $(call COMPILE_OBJ_CXX,$@,$<) diff --git a/src/test/run-make-fulldeps/foreign-double-unwind/foo.cpp b/src/test/run-make-fulldeps/foreign-double-unwind/foo.cpp new file mode 100644 index 000000000..69a8f11c2 --- /dev/null +++ b/src/test/run-make-fulldeps/foreign-double-unwind/foo.cpp @@ -0,0 +1,33 @@ +#include <cstdio> +#include <exception> + +void println(const char* s) { + puts(s); + fflush(stdout); +} + +struct outer_exception {}; +struct inner_exception {}; + +extern "C" { + void throw_cxx_exception() { + if (std::uncaught_exception()) { + println("throwing inner C++ exception"); + throw inner_exception(); + } else { + println("throwing outer C++ exception"); + throw outer_exception(); + } + } + + void cxx_catch_callback(void (*cb)()) { + try { + cb(); + println("unreachable: callback returns"); + } catch (outer_exception) { + println("unreachable: caught outer exception in catch (...)"); + } catch (inner_exception) { + println("unreachable: caught inner exception in catch (...)"); + } + } +} diff --git a/src/test/run-make-fulldeps/foreign-double-unwind/foo.rs b/src/test/run-make-fulldeps/foreign-double-unwind/foo.rs new file mode 100644 index 000000000..cae8aa940 --- /dev/null +++ b/src/test/run-make-fulldeps/foreign-double-unwind/foo.rs @@ -0,0 +1,26 @@ +// Tests that C++ double unwinding through Rust code will be properly guarded +// against instead of exhibiting undefined behaviour. + +#![feature(c_unwind)] + +extern "C-unwind" { + fn throw_cxx_exception(); + fn cxx_catch_callback(cb: extern "C-unwind" fn()); +} + +struct ThrowOnDrop; + +impl Drop for ThrowOnDrop { + fn drop(&mut self) { + unsafe { throw_cxx_exception() }; + } +} + +extern "C-unwind" fn test_double_unwind() { + let _a = ThrowOnDrop; + let _b = ThrowOnDrop; +} + +fn main() { + unsafe { cxx_catch_callback(test_double_unwind) }; +} diff --git a/src/test/run-make-fulldeps/foreign-exceptions/Makefile b/src/test/run-make-fulldeps/foreign-exceptions/Makefile new file mode 100644 index 000000000..7eba52f3c --- /dev/null +++ b/src/test/run-make-fulldeps/foreign-exceptions/Makefile @@ -0,0 +1,10 @@ +-include ../tools.mk + +all: foo + $(call RUN,foo) + +foo: foo.rs $(call NATIVE_STATICLIB,foo) + $(RUSTC) $< -lfoo $(EXTRARSCXXFLAGS) + +$(TMPDIR)/libfoo.o: foo.cpp + $(call COMPILE_OBJ_CXX,$@,$<) diff --git a/src/test/run-make-fulldeps/foreign-exceptions/foo.cpp b/src/test/run-make-fulldeps/foreign-exceptions/foo.cpp new file mode 100644 index 000000000..8182021a2 --- /dev/null +++ b/src/test/run-make-fulldeps/foreign-exceptions/foo.cpp @@ -0,0 +1,60 @@ +#include <assert.h> +#include <stddef.h> +#include <stdio.h> + +void println(const char* s) { + puts(s); + fflush(stdout); +} + +struct exception {}; +struct rust_panic {}; + +struct drop_check { + bool* ok; + ~drop_check() { + println("~drop_check"); + + if (ok) + *ok = true; + } +}; + +extern "C" { + void rust_catch_callback(void (*cb)(), bool* rust_ok); + + void throw_cxx_exception() { + println("throwing C++ exception"); + throw exception(); + } + + void test_cxx_exception() { + bool rust_ok = false; + try { + rust_catch_callback(throw_cxx_exception, &rust_ok); + assert(false && "unreachable"); + } catch (exception e) { + println("caught C++ exception"); + assert(rust_ok); + return; + } + assert(false && "did not catch thrown C++ exception"); + } + + void cxx_catch_callback(void (*cb)(), bool* cxx_ok) { + drop_check x; + x.ok = NULL; + try { + cb(); + } catch (rust_panic e) { + assert(false && "shouldn't be able to catch a rust panic"); + } catch (...) { + println("caught foreign exception in catch (...)"); + // Foreign exceptions are caught by catch (...). We only set the ok + // flag if we successfully caught the panic. The destructor of + // drop_check will then set the flag to true if it is executed. + x.ok = cxx_ok; + throw; + } + } +} diff --git a/src/test/run-make-fulldeps/foreign-exceptions/foo.rs b/src/test/run-make-fulldeps/foreign-exceptions/foo.rs new file mode 100644 index 000000000..dd3b7c76f --- /dev/null +++ b/src/test/run-make-fulldeps/foreign-exceptions/foo.rs @@ -0,0 +1,59 @@ +// Tests that C++ exceptions can unwind through Rust code run destructors and +// are caught by catch_unwind. Also tests that Rust panics can unwind through +// C++ code. + +#![feature(c_unwind)] + +use std::panic::{catch_unwind, AssertUnwindSafe}; + +struct DropCheck<'a>(&'a mut bool); +impl<'a> Drop for DropCheck<'a> { + fn drop(&mut self) { + println!("DropCheck::drop"); + *self.0 = true; + } +} + +extern "C" { + fn test_cxx_exception(); +} + +extern "C-unwind" { + fn cxx_catch_callback(cb: extern "C-unwind" fn(), ok: *mut bool); +} + +#[no_mangle] +extern "C-unwind" fn rust_catch_callback(cb: extern "C-unwind" fn(), rust_ok: &mut bool) { + let _drop = DropCheck(rust_ok); + cb(); + unreachable!("should have unwound instead of returned"); +} + +fn test_rust_panic() { + extern "C-unwind" fn callback() { + println!("throwing rust panic"); + panic!(1234i32); + } + + let mut dropped = false; + let mut cxx_ok = false; + let caught_unwind = catch_unwind(AssertUnwindSafe(|| { + let _drop = DropCheck(&mut dropped); + unsafe { + cxx_catch_callback(callback, &mut cxx_ok); + } + unreachable!("should have unwound instead of returned"); + })); + println!("caught rust panic"); + assert!(dropped); + assert!(caught_unwind.is_err()); + let panic_obj = caught_unwind.unwrap_err(); + let panic_int = *panic_obj.downcast_ref::<i32>().unwrap(); + assert_eq!(panic_int, 1234); + assert!(cxx_ok); +} + +fn main() { + unsafe { test_cxx_exception() }; + test_rust_panic(); +} diff --git a/src/test/run-make-fulldeps/fpic/Makefile b/src/test/run-make-fulldeps/fpic/Makefile new file mode 100644 index 000000000..a3d0190ee --- /dev/null +++ b/src/test/run-make-fulldeps/fpic/Makefile @@ -0,0 +1,10 @@ +-include ../tools.mk + +# ignore-windows +# ignore-macos + +# Test for #39529. +# `-z text` causes ld to error if there are any non-PIC sections + +all: + $(RUSTC) hello.rs -C link-args=-Wl,-z,text diff --git a/src/test/run-make-fulldeps/fpic/hello.rs b/src/test/run-make-fulldeps/fpic/hello.rs new file mode 100644 index 000000000..45590d86b --- /dev/null +++ b/src/test/run-make-fulldeps/fpic/hello.rs @@ -0,0 +1 @@ +fn main() { } diff --git a/src/test/run-make-fulldeps/glibc-staticlib-args/Makefile b/src/test/run-make-fulldeps/glibc-staticlib-args/Makefile new file mode 100644 index 000000000..ad841ec61 --- /dev/null +++ b/src/test/run-make-fulldeps/glibc-staticlib-args/Makefile @@ -0,0 +1,12 @@ +# only-gnu +# only-linux + +-include ../tools.mk + +# This ensures that std::env::args works in a library called from C on glibc Linux. + +all: + $(RUSTC) --crate-type=staticlib library.rs + $(CC) program.c $(call STATICLIB,library) $(call OUT_EXE,program) \ + $(EXTRACFLAGS) $(EXTRACXXFLAGS) + $(call RUN,program) diff --git a/src/test/run-make-fulldeps/glibc-staticlib-args/library.rs b/src/test/run-make-fulldeps/glibc-staticlib-args/library.rs new file mode 100644 index 000000000..5ab627a2a --- /dev/null +++ b/src/test/run-make-fulldeps/glibc-staticlib-args/library.rs @@ -0,0 +1,4 @@ +#[no_mangle] +pub extern "C" fn args_check() { + assert_ne!(std::env::args_os().count(), 0); +} diff --git a/src/test/run-make-fulldeps/glibc-staticlib-args/program.c b/src/test/run-make-fulldeps/glibc-staticlib-args/program.c new file mode 100644 index 000000000..30f6974b7 --- /dev/null +++ b/src/test/run-make-fulldeps/glibc-staticlib-args/program.c @@ -0,0 +1,6 @@ +void args_check(); + +int main() { + args_check(); + return 0; +} diff --git a/src/test/run-make-fulldeps/hir-tree/Makefile b/src/test/run-make-fulldeps/hir-tree/Makefile new file mode 100644 index 000000000..3412c8ce1 --- /dev/null +++ b/src/test/run-make-fulldeps/hir-tree/Makefile @@ -0,0 +1,8 @@ +-include ../tools.mk + +# Test that hir-tree output doesn't crash and includes +# the string constant we would expect to see. + +all: + $(RUSTC) -o $(TMPDIR)/input.hir -Z unpretty=hir-tree input.rs + $(CGREP) '"Hello, Rustaceans!\n"' < $(TMPDIR)/input.hir diff --git a/src/test/run-make-fulldeps/hir-tree/input.rs b/src/test/run-make-fulldeps/hir-tree/input.rs new file mode 100644 index 000000000..9d1a4e9e4 --- /dev/null +++ b/src/test/run-make-fulldeps/hir-tree/input.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, Rustaceans!"); +} diff --git a/src/test/run-make-fulldeps/hotplug_codegen_backend/Makefile b/src/test/run-make-fulldeps/hotplug_codegen_backend/Makefile new file mode 100644 index 000000000..4cda243ff --- /dev/null +++ b/src/test/run-make-fulldeps/hotplug_codegen_backend/Makefile @@ -0,0 +1,26 @@ +include ../tools.mk + +# ignore-stage1 + +# This test both exists as a check that -Zcodegen-backend is capable of loading external codegen +# backends and that this external codegen backend is only included in the dep info if +# -Zbinary-dep-depinfo is used. + +all: + /bin/echo || exit 0 # This test requires /bin/echo to exist + $(RUSTC) the_backend.rs --crate-name the_backend --crate-type dylib \ + -o $(TMPDIR)/the_backend.dylib + + $(RUSTC) some_crate.rs --crate-name some_crate --crate-type lib -o $(TMPDIR)/some_crate \ + -Z codegen-backend=$(TMPDIR)/the_backend.dylib -Z unstable-options \ + --emit link,dep-info + grep -x "This has been \"compiled\" successfully." $(TMPDIR)/libsome_crate.rlib + # don't declare a dependency on the codegen backend if -Zbinary-dep-depinfo isn't used. + grep -v "the_backend.dylib" $(TMPDIR)/some_crate.d + + $(RUSTC) some_crate.rs --crate-name some_crate --crate-type lib -o $(TMPDIR)/some_crate \ + -Z codegen-backend=$(TMPDIR)/the_backend.dylib -Z unstable-options \ + --emit link,dep-info -Zbinary-dep-depinfo + grep -x "This has been \"compiled\" successfully." $(TMPDIR)/libsome_crate.rlib + # but declare a dependency on the codegen backend if -Zbinary-dep-depinfo it used. + grep "the_backend.dylib" $(TMPDIR)/some_crate.d diff --git a/src/test/run-make-fulldeps/hotplug_codegen_backend/some_crate.rs b/src/test/run-make-fulldeps/hotplug_codegen_backend/some_crate.rs new file mode 100644 index 000000000..da27b7f34 --- /dev/null +++ b/src/test/run-make-fulldeps/hotplug_codegen_backend/some_crate.rs @@ -0,0 +1,2 @@ +#![feature(no_core)] +#![no_core] diff --git a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs new file mode 100644 index 000000000..2c4309fbe --- /dev/null +++ b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs @@ -0,0 +1,82 @@ +#![feature(rustc_private)] +#![deny(warnings)] + +extern crate rustc_codegen_ssa; +extern crate rustc_data_structures; +extern crate rustc_driver; +extern crate rustc_errors; +extern crate rustc_hir; +extern crate rustc_metadata; +extern crate rustc_middle; +extern crate rustc_session; +extern crate rustc_span; +extern crate rustc_symbol_mangling; +extern crate rustc_target; + +use rustc_codegen_ssa::traits::CodegenBackend; +use rustc_codegen_ssa::{CodegenResults, CrateInfo}; +use rustc_data_structures::fx::FxHashMap; +use rustc_errors::ErrorGuaranteed; +use rustc_metadata::EncodedMetadata; +use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; +use rustc_middle::ty::TyCtxt; +use rustc_session::config::OutputFilenames; +use rustc_session::Session; +use std::any::Any; + +struct TheBackend; + +impl CodegenBackend for TheBackend { + fn codegen_crate<'a, 'tcx>( + &self, + tcx: TyCtxt<'tcx>, + metadata: EncodedMetadata, + _need_metadata_module: bool, + ) -> Box<dyn Any> { + Box::new(CodegenResults { + modules: vec![], + allocator_module: None, + metadata_module: None, + metadata, + crate_info: CrateInfo::new(tcx, "fake_target_cpu".to_string()), + }) + } + + fn join_codegen( + &self, + ongoing_codegen: Box<dyn Any>, + _sess: &Session, + _outputs: &OutputFilenames, + ) -> Result<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>), ErrorGuaranteed> { + let codegen_results = ongoing_codegen + .downcast::<CodegenResults>() + .expect("in join_codegen: ongoing_codegen is not a CodegenResults"); + Ok((*codegen_results, FxHashMap::default())) + } + + fn link( + &self, + sess: &Session, + codegen_results: CodegenResults, + outputs: &OutputFilenames, + ) -> Result<(), ErrorGuaranteed> { + use rustc_session::{config::CrateType, output::out_filename}; + use std::io::Write; + let crate_name = codegen_results.crate_info.local_crate_name; + for &crate_type in sess.opts.crate_types.iter() { + if crate_type != CrateType::Rlib { + sess.fatal(&format!("Crate type is {:?}", crate_type)); + } + let output_name = out_filename(sess, crate_type, &outputs, &*crate_name.as_str()); + let mut out_file = ::std::fs::File::create(output_name).unwrap(); + write!(out_file, "This has been \"compiled\" successfully.").unwrap(); + } + Ok(()) + } +} + +/// This is the entrypoint for a hot plugged rustc_codegen_llvm +#[no_mangle] +pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> { + Box::new(TheBackend) +} diff --git a/src/test/run-make-fulldeps/include_bytes_deps/Makefile b/src/test/run-make-fulldeps/include_bytes_deps/Makefile new file mode 100644 index 000000000..f91af88ef --- /dev/null +++ b/src/test/run-make-fulldeps/include_bytes_deps/Makefile @@ -0,0 +1,7 @@ +-include ../tools.mk + +# ignore-freebsd + +all: + $(RUSTC) --emit dep-info main.rs + $(CGREP) "input.txt" "input.bin" "input.md" < $(TMPDIR)/main.d diff --git a/src/test/run-make-fulldeps/include_bytes_deps/input.bin b/src/test/run-make-fulldeps/include_bytes_deps/input.bin new file mode 100644 index 000000000..cd0875583 --- /dev/null +++ b/src/test/run-make-fulldeps/include_bytes_deps/input.bin @@ -0,0 +1 @@ +Hello world! diff --git a/src/test/run-make-fulldeps/include_bytes_deps/input.md b/src/test/run-make-fulldeps/include_bytes_deps/input.md new file mode 100644 index 000000000..2a19b7405 --- /dev/null +++ b/src/test/run-make-fulldeps/include_bytes_deps/input.md @@ -0,0 +1 @@ +# Hello, world! diff --git a/src/test/run-make-fulldeps/include_bytes_deps/input.txt b/src/test/run-make-fulldeps/include_bytes_deps/input.txt new file mode 100644 index 000000000..cd0875583 --- /dev/null +++ b/src/test/run-make-fulldeps/include_bytes_deps/input.txt @@ -0,0 +1 @@ +Hello world! diff --git a/src/test/run-make-fulldeps/include_bytes_deps/main.rs b/src/test/run-make-fulldeps/include_bytes_deps/main.rs new file mode 100644 index 000000000..2fd55699d --- /dev/null +++ b/src/test/run-make-fulldeps/include_bytes_deps/main.rs @@ -0,0 +1,10 @@ +#[doc = include_str!("input.md")] +pub struct SomeStruct; + +pub fn main() { + const INPUT_TXT: &'static str = include_str!("input.txt"); + const INPUT_BIN: &'static [u8] = include_bytes!("input.bin"); + + println!("{}", INPUT_TXT); + println!("{:?}", INPUT_BIN); +} diff --git a/src/test/run-make-fulldeps/incr-add-rust-src-component/Makefile b/src/test/run-make-fulldeps/incr-add-rust-src-component/Makefile new file mode 100644 index 000000000..371f94715 --- /dev/null +++ b/src/test/run-make-fulldeps/incr-add-rust-src-component/Makefile @@ -0,0 +1,44 @@ +-include ../tools.mk + +# rust-lang/rust#70924: Test that if we add rust-src component in between two +# incremental compiles, the compiler does not ICE on the second. + +# This test uses `ln -s` rather than copying to save testing time, but its +# usage doesn't work on windows. So ignore windows. + +# ignore-windows + +SYSROOT:=$(shell $(RUSTC) --print sysroot) +FAKEROOT=$(TMPDIR)/fakeroot +INCR=$(TMPDIR)/incr + +# Make a local copy of the sysroot; then remove the rust-src part of it, if +# present, for the *first* build. Then put in a facsimile of the rust-src +# component for the second build, in order to expose the ICE from issue #70924. +# +# Note that it is much easier to just do `cp -a $(SYSROOT)/* $(FAKEROOT)` as a +# first step, but I am concerned that would be too expensive in a unit test +# compared to making symbolic links. +# +# Anyway, the pattern you'll see here is: For every prefix in +# root/lib/rustlib/src, link all of prefix parent content, then remove the +# prefix, then loop on the next prefix. This way, we basically create a copy of +# the context around root/lib/rustlib/src, and can freely add/remove the src +# component itself. +all: + mkdir $(FAKEROOT) + ln -s $(SYSROOT)/* $(FAKEROOT) + rm -f $(FAKEROOT)/lib + mkdir $(FAKEROOT)/lib + ln -s $(SYSROOT)/lib/* $(FAKEROOT)/lib + rm -f $(FAKEROOT)/lib/rustlib + mkdir $(FAKEROOT)/lib/rustlib + ln -s $(SYSROOT)/lib/rustlib/* $(FAKEROOT)/lib/rustlib + rm -f $(FAKEROOT)/lib/rustlib/src + mkdir $(FAKEROOT)/lib/rustlib/src + ln -s $(SYSROOT)/lib/rustlib/src/* $(FAKEROOT)/lib/rustlib/src + rm -f $(FAKEROOT)/lib/rustlib/src/rust + $(RUSTC) --sysroot $(FAKEROOT) -C incremental=$(INCR) main.rs + mkdir -p $(FAKEROOT)/lib/rustlib/src/rust/src/libstd + touch $(FAKEROOT)/lib/rustlib/src/rust/src/libstd/lib.rs + $(RUSTC) --sysroot $(FAKEROOT) -C incremental=$(INCR) main.rs diff --git a/src/test/run-make-fulldeps/incr-add-rust-src-component/main.rs b/src/test/run-make-fulldeps/incr-add-rust-src-component/main.rs new file mode 100644 index 000000000..f6320bcb0 --- /dev/null +++ b/src/test/run-make-fulldeps/incr-add-rust-src-component/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello World"); +} diff --git a/src/test/run-make-fulldeps/inline-always-many-cgu/Makefile b/src/test/run-make-fulldeps/inline-always-many-cgu/Makefile new file mode 100644 index 000000000..0cab955f6 --- /dev/null +++ b/src/test/run-make-fulldeps/inline-always-many-cgu/Makefile @@ -0,0 +1,8 @@ +-include ../tools.mk + +all: + $(RUSTC) foo.rs --emit llvm-ir -C codegen-units=2 + if cat $(TMPDIR)/*.ll | $(CGREP) -e '\bcall\b'; then \ + echo "found call instruction when one wasn't expected"; \ + exit 1; \ + fi diff --git a/src/test/run-make-fulldeps/inline-always-many-cgu/foo.rs b/src/test/run-make-fulldeps/inline-always-many-cgu/foo.rs new file mode 100644 index 000000000..65fe69c16 --- /dev/null +++ b/src/test/run-make-fulldeps/inline-always-many-cgu/foo.rs @@ -0,0 +1,15 @@ +#![crate_type = "lib"] + +pub mod a { + #[inline(always)] + pub fn foo() { + } + + pub fn bar() { + } +} + +#[no_mangle] +pub fn bar() { + a::foo(); +} diff --git a/src/test/run-make-fulldeps/interdependent-c-libraries/Makefile b/src/test/run-make-fulldeps/interdependent-c-libraries/Makefile new file mode 100644 index 000000000..0a50859cd --- /dev/null +++ b/src/test/run-make-fulldeps/interdependent-c-libraries/Makefile @@ -0,0 +1,14 @@ +-include ../tools.mk + +# The rust crate foo will link to the native library foo, while the rust crate +# bar will link to the native library bar. There is also a dependency between +# the native library bar to the natibe library foo. +# +# This test ensures that the ordering of -lfoo and -lbar on the command line is +# correct to complete the linkage. If passed as "-lfoo -lbar", then the 'foo' +# library will be stripped out, and the linkage will fail. + +all: $(call NATIVE_STATICLIB,foo) $(call NATIVE_STATICLIB,bar) + $(RUSTC) foo.rs + $(RUSTC) bar.rs + $(RUSTC) main.rs --print link-args diff --git a/src/test/run-make-fulldeps/interdependent-c-libraries/bar.c b/src/test/run-make-fulldeps/interdependent-c-libraries/bar.c new file mode 100644 index 000000000..812c97535 --- /dev/null +++ b/src/test/run-make-fulldeps/interdependent-c-libraries/bar.c @@ -0,0 +1,3 @@ +void foo(); + +void bar() { foo(); } diff --git a/src/test/run-make-fulldeps/interdependent-c-libraries/bar.rs b/src/test/run-make-fulldeps/interdependent-c-libraries/bar.rs new file mode 100644 index 000000000..3c2c3f218 --- /dev/null +++ b/src/test/run-make-fulldeps/interdependent-c-libraries/bar.rs @@ -0,0 +1,14 @@ +#![crate_type = "rlib"] + +extern crate foo; + +#[link(name = "bar", kind = "static")] +extern "C" { + fn bar(); +} + +pub fn doit() { + unsafe { + bar(); + } +} diff --git a/src/test/run-make-fulldeps/interdependent-c-libraries/foo.c b/src/test/run-make-fulldeps/interdependent-c-libraries/foo.c new file mode 100644 index 000000000..85e6cd8c3 --- /dev/null +++ b/src/test/run-make-fulldeps/interdependent-c-libraries/foo.c @@ -0,0 +1 @@ +void foo() {} diff --git a/src/test/run-make-fulldeps/interdependent-c-libraries/foo.rs b/src/test/run-make-fulldeps/interdependent-c-libraries/foo.rs new file mode 100644 index 000000000..a69809726 --- /dev/null +++ b/src/test/run-make-fulldeps/interdependent-c-libraries/foo.rs @@ -0,0 +1,12 @@ +#![crate_type = "rlib"] + +#[link(name = "foo", kind = "static")] +extern "C" { + fn foo(); +} + +pub fn doit() { + unsafe { + foo(); + } +} diff --git a/src/test/run-make-fulldeps/interdependent-c-libraries/main.rs b/src/test/run-make-fulldeps/interdependent-c-libraries/main.rs new file mode 100644 index 000000000..2aba427df --- /dev/null +++ b/src/test/run-make-fulldeps/interdependent-c-libraries/main.rs @@ -0,0 +1,6 @@ +extern crate foo; +extern crate bar; + +fn main() { + bar::doit(); +} diff --git a/src/test/run-make-fulldeps/intrinsic-unreachable/Makefile b/src/test/run-make-fulldeps/intrinsic-unreachable/Makefile new file mode 100644 index 000000000..203772856 --- /dev/null +++ b/src/test/run-make-fulldeps/intrinsic-unreachable/Makefile @@ -0,0 +1,11 @@ +-include ../tools.mk + +# ignore-windows-msvc +# +# Because of Windows exception handling, the code is not necessarily any shorter. +# https://github.com/llvm-mirror/llvm/commit/64b2297786f7fd6f5fa24cdd4db0298fbf211466 + +all: + $(RUSTC) -O --emit asm exit-ret.rs + $(RUSTC) -O --emit asm exit-unreachable.rs + test `wc -l < $(TMPDIR)/exit-unreachable.s` -lt `wc -l < $(TMPDIR)/exit-ret.s` diff --git a/src/test/run-make-fulldeps/intrinsic-unreachable/exit-ret.rs b/src/test/run-make-fulldeps/intrinsic-unreachable/exit-ret.rs new file mode 100644 index 000000000..e7b9694d9 --- /dev/null +++ b/src/test/run-make-fulldeps/intrinsic-unreachable/exit-ret.rs @@ -0,0 +1,14 @@ +#![crate_type="lib"] +use std::arch::asm; + +#[deny(unreachable_code)] +pub fn exit(n: usize) -> i32 { + unsafe { + // Pretend this asm is an exit() syscall. + asm!("/*{0}*/", in(reg) n); + } + // This return value is just here to generate some extra code for a return + // value, making it easier for the test script to detect whether the + // compiler deleted it. + 42 +} diff --git a/src/test/run-make-fulldeps/intrinsic-unreachable/exit-unreachable.rs b/src/test/run-make-fulldeps/intrinsic-unreachable/exit-unreachable.rs new file mode 100644 index 000000000..ec85db733 --- /dev/null +++ b/src/test/run-make-fulldeps/intrinsic-unreachable/exit-unreachable.rs @@ -0,0 +1,18 @@ +#![feature(core_intrinsics)] +#![crate_type="lib"] +use std::arch::asm; + +use std::intrinsics; + +#[allow(unreachable_code)] +pub fn exit(n: usize) -> i32 { + unsafe { + // Pretend this asm is an exit() syscall. + asm!("/*{0}*/", in(reg) n); + intrinsics::unreachable() + } + // This return value is just here to generate some extra code for a return + // value, making it easier for the test script to detect whether the + // compiler deleted it. + 42 +} diff --git a/src/test/run-make-fulldeps/invalid-library/Makefile b/src/test/run-make-fulldeps/invalid-library/Makefile new file mode 100644 index 000000000..de463a330 --- /dev/null +++ b/src/test/run-make-fulldeps/invalid-library/Makefile @@ -0,0 +1,6 @@ +-include ../tools.mk + +all: + touch $(TMPDIR)/lib.rmeta + $(AR) crus $(TMPDIR)/libfoo-ffffffff-1.0.rlib $(TMPDIR)/lib.rmeta + $(RUSTC) foo.rs 2>&1 | $(CGREP) "found invalid metadata" diff --git a/src/test/run-make-fulldeps/invalid-library/foo.rs b/src/test/run-make-fulldeps/invalid-library/foo.rs new file mode 100644 index 000000000..bb7b36c49 --- /dev/null +++ b/src/test/run-make-fulldeps/invalid-library/foo.rs @@ -0,0 +1,3 @@ +extern crate foo; + +fn main() {} diff --git a/src/test/run-make-fulldeps/invalid-staticlib/Makefile b/src/test/run-make-fulldeps/invalid-staticlib/Makefile new file mode 100644 index 000000000..3a91902cc --- /dev/null +++ b/src/test/run-make-fulldeps/invalid-staticlib/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: + touch $(TMPDIR)/libfoo.a + echo | $(RUSTC) - --crate-type=rlib -lstatic=foo 2>&1 | $(CGREP) "failed to add native library" diff --git a/src/test/run-make-fulldeps/issue-11908/Makefile b/src/test/run-make-fulldeps/issue-11908/Makefile new file mode 100644 index 000000000..cf6572c27 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-11908/Makefile @@ -0,0 +1,21 @@ +# This test ensures that if you have the same rlib or dylib at two locations +# in the same path that you don't hit an assertion in the compiler. +# +# Note that this relies on `liburl` to be in the path somewhere else, +# and then our aux-built libraries will collide with liburl (they have +# the same version listed) + +-include ../tools.mk + +all: + mkdir $(TMPDIR)/other + $(RUSTC) foo.rs --crate-type=dylib -C prefer-dynamic + mv $(call DYLIB,foo) $(TMPDIR)/other + $(RUSTC) foo.rs --crate-type=dylib -C prefer-dynamic + $(RUSTC) bar.rs -L $(TMPDIR)/other + rm -rf $(TMPDIR) + mkdir -p $(TMPDIR)/other + $(RUSTC) foo.rs --crate-type=rlib + mv $(TMPDIR)/libfoo.rlib $(TMPDIR)/other + $(RUSTC) foo.rs --crate-type=rlib + $(RUSTC) bar.rs -L $(TMPDIR)/other diff --git a/src/test/run-make-fulldeps/issue-11908/bar.rs b/src/test/run-make-fulldeps/issue-11908/bar.rs new file mode 100644 index 000000000..bb7b36c49 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-11908/bar.rs @@ -0,0 +1,3 @@ +extern crate foo; + +fn main() {} diff --git a/src/test/run-make-fulldeps/issue-11908/foo.rs b/src/test/run-make-fulldeps/issue-11908/foo.rs new file mode 100644 index 000000000..82b2dfe9f --- /dev/null +++ b/src/test/run-make-fulldeps/issue-11908/foo.rs @@ -0,0 +1 @@ +#![crate_name = "foo"] diff --git a/src/test/run-make-fulldeps/issue-14500/Makefile b/src/test/run-make-fulldeps/issue-14500/Makefile new file mode 100644 index 000000000..0c0e331da --- /dev/null +++ b/src/test/run-make-fulldeps/issue-14500/Makefile @@ -0,0 +1,13 @@ +-include ../tools.mk + +# Test to make sure that reachable extern fns are always available in final +# productcs, including when LTO is used. In this test, the `foo` crate has a +# reahable symbol, and is a dependency of the `bar` crate. When the `bar` crate +# is compiled with LTO, it shouldn't strip the symbol from `foo`, and that's the +# only way that `foo.c` will successfully compile. + +all: + $(RUSTC) foo.rs --crate-type=rlib + $(RUSTC) bar.rs --crate-type=staticlib -C lto -L. -o $(TMPDIR)/libbar.a + $(CC) foo.c $(TMPDIR)/libbar.a $(EXTRACFLAGS) $(call OUT_EXE,foo) + $(call RUN,foo) diff --git a/src/test/run-make-fulldeps/issue-14500/bar.rs b/src/test/run-make-fulldeps/issue-14500/bar.rs new file mode 100644 index 000000000..49af74e1b --- /dev/null +++ b/src/test/run-make-fulldeps/issue-14500/bar.rs @@ -0,0 +1 @@ +extern crate foo; diff --git a/src/test/run-make-fulldeps/issue-14500/foo.c b/src/test/run-make-fulldeps/issue-14500/foo.c new file mode 100644 index 000000000..2353d400d --- /dev/null +++ b/src/test/run-make-fulldeps/issue-14500/foo.c @@ -0,0 +1,7 @@ +extern void foo(); +extern char FOO_STATIC; + +int main() { + foo(); + return (int)FOO_STATIC; +} diff --git a/src/test/run-make-fulldeps/issue-14500/foo.rs b/src/test/run-make-fulldeps/issue-14500/foo.rs new file mode 100644 index 000000000..7c19c1f2c --- /dev/null +++ b/src/test/run-make-fulldeps/issue-14500/foo.rs @@ -0,0 +1,5 @@ +#[no_mangle] +pub extern "C" fn foo() {} + +#[no_mangle] +pub static FOO_STATIC: u8 = 0; diff --git a/src/test/run-make-fulldeps/issue-14698/Makefile b/src/test/run-make-fulldeps/issue-14698/Makefile new file mode 100644 index 000000000..dbe8317db --- /dev/null +++ b/src/test/run-make-fulldeps/issue-14698/Makefile @@ -0,0 +1,4 @@ +-include ../tools.mk + +all: + TMP=fake TMPDIR=fake $(RUSTC) foo.rs 2>&1 | $(CGREP) "couldn't create a temp dir:" diff --git a/src/test/run-make-fulldeps/issue-14698/foo.rs b/src/test/run-make-fulldeps/issue-14698/foo.rs new file mode 100644 index 000000000..f328e4d9d --- /dev/null +++ b/src/test/run-make-fulldeps/issue-14698/foo.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/src/test/run-make-fulldeps/issue-15460/Makefile b/src/test/run-make-fulldeps/issue-15460/Makefile new file mode 100644 index 000000000..846805686 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-15460/Makefile @@ -0,0 +1,6 @@ +-include ../tools.mk + +all: $(call NATIVE_STATICLIB,foo) + $(RUSTC) foo.rs -C extra-filename=-383hf8 -C prefer-dynamic + $(RUSTC) bar.rs + $(call RUN,bar) diff --git a/src/test/run-make-fulldeps/issue-15460/bar.rs b/src/test/run-make-fulldeps/issue-15460/bar.rs new file mode 100644 index 000000000..e66aeb6bd --- /dev/null +++ b/src/test/run-make-fulldeps/issue-15460/bar.rs @@ -0,0 +1,4 @@ +extern crate foo; +fn main() { + unsafe { foo::foo() } +} diff --git a/src/test/run-make-fulldeps/issue-15460/foo.c b/src/test/run-make-fulldeps/issue-15460/foo.c new file mode 100644 index 000000000..fdf595b57 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-15460/foo.c @@ -0,0 +1,6 @@ +// ignore-license + +#ifdef _WIN32 +__declspec(dllexport) +#endif +void foo() {} diff --git a/src/test/run-make-fulldeps/issue-15460/foo.rs b/src/test/run-make-fulldeps/issue-15460/foo.rs new file mode 100644 index 000000000..b4eaa0b31 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-15460/foo.rs @@ -0,0 +1,6 @@ +#![crate_type = "dylib"] + +#[link(name = "foo", kind = "static")] +extern "C" { + pub fn foo(); +} diff --git a/src/test/run-make-fulldeps/issue-18943/Makefile b/src/test/run-make-fulldeps/issue-18943/Makefile new file mode 100644 index 000000000..bef70a0ed --- /dev/null +++ b/src/test/run-make-fulldeps/issue-18943/Makefile @@ -0,0 +1,7 @@ +-include ../tools.mk + +# Regression test for ICE #18943 when compiling as lib + +all: + $(RUSTC) foo.rs --crate-type lib + $(call REMOVE_RLIBS,foo) && exit 0 || exit 1 diff --git a/src/test/run-make-fulldeps/issue-18943/foo.rs b/src/test/run-make-fulldeps/issue-18943/foo.rs new file mode 100644 index 000000000..d18400dd3 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-18943/foo.rs @@ -0,0 +1,5 @@ +trait Foo { } + +trait Bar { } + +impl<'a> Foo for Bar + 'a { } diff --git a/src/test/run-make-fulldeps/issue-19371/Makefile b/src/test/run-make-fulldeps/issue-19371/Makefile new file mode 100644 index 000000000..9f3ec7846 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-19371/Makefile @@ -0,0 +1,9 @@ +-include ../tools.mk + +# This test ensures that rustc compile_input can be called twice in one task +# without causing a panic. +# The program needs the path to rustc to get sysroot. + +all: + $(RUSTC) foo.rs + $(call RUN,foo $(TMPDIR) $(RUSTC)) diff --git a/src/test/run-make-fulldeps/issue-19371/foo.rs b/src/test/run-make-fulldeps/issue-19371/foo.rs new file mode 100644 index 000000000..fd294b018 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-19371/foo.rs @@ -0,0 +1,76 @@ +#![feature(rustc_private)] + +extern crate rustc_interface; +extern crate rustc_driver; +extern crate rustc_session; +extern crate rustc_span; + +use rustc_session::DiagnosticOutput; +use rustc_session::config::{Input, Options, OutputType, OutputTypes}; +use rustc_interface::interface; +use rustc_span::source_map::FileName; + +use std::path::PathBuf; + +fn main() { + let src = r#" + fn main() {} + "#; + + let args: Vec<String> = std::env::args().collect(); + + if args.len() < 4 { + panic!("expected rustc path"); + } + + let tmpdir = PathBuf::from(&args[1]); + + let mut sysroot = PathBuf::from(&args[3]); + sysroot.pop(); + sysroot.pop(); + + compile(src.to_string(), tmpdir.join("out"), sysroot.clone()); + + compile(src.to_string(), tmpdir.join("out"), sysroot.clone()); +} + +fn compile(code: String, output: PathBuf, sysroot: PathBuf) { + let mut opts = Options::default(); + opts.output_types = OutputTypes::new(&[(OutputType::Exe, None)]); + opts.maybe_sysroot = Some(sysroot); + + if let Ok(linker) = std::env::var("RUSTC_LINKER") { + opts.cg.linker = Some(linker.into()); + } + + let name = FileName::anon_source_code(&code); + let input = Input::Str { name, input: code }; + + let config = interface::Config { + opts, + crate_cfg: Default::default(), + crate_check_cfg: Default::default(), + input, + input_path: None, + output_file: Some(output), + output_dir: None, + file_loader: None, + diagnostic_output: DiagnosticOutput::Default, + lint_caps: Default::default(), + parse_sess_created: None, + register_lints: None, + override_queries: None, + make_codegen_backend: None, + registry: rustc_driver::diagnostics_registry(), + }; + + interface::run_compiler(config, |compiler| { + // This runs all the passes prior to linking, too. + let linker = compiler.enter(|queries| { + queries.linker() + }); + if let Ok(linker) = linker { + linker.link(); + } + }); +} diff --git a/src/test/run-make-fulldeps/issue-20626/Makefile b/src/test/run-make-fulldeps/issue-20626/Makefile new file mode 100644 index 000000000..0487b2404 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-20626/Makefile @@ -0,0 +1,8 @@ +-include ../tools.mk + +# Test output to be four +# The original error only occurred when printing, not when comparing using assert! + +all: + $(RUSTC) foo.rs -O + [ `$(call RUN,foo)` = "4" ] diff --git a/src/test/run-make-fulldeps/issue-20626/foo.rs b/src/test/run-make-fulldeps/issue-20626/foo.rs new file mode 100644 index 000000000..a474e234e --- /dev/null +++ b/src/test/run-make-fulldeps/issue-20626/foo.rs @@ -0,0 +1,13 @@ +fn identity(a: &u32) -> &u32 { a } + +fn print_foo(f: &fn(&u32) -> &u32, x: &u32) { + print!("{}", (*f)(x)); +} + +fn main() { + let x = &4; + let f: fn(&u32) -> &u32 = identity; + + // Didn't print 4 on optimized builds + print_foo(&f, x); +} diff --git a/src/test/run-make-fulldeps/issue-22131/Makefile b/src/test/run-make-fulldeps/issue-22131/Makefile new file mode 100644 index 000000000..d76aaf5c1 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-22131/Makefile @@ -0,0 +1,7 @@ +-include ../tools.mk + +all: foo.rs + $(RUSTC) --cfg 'feature="bar"' --crate-type lib foo.rs + $(RUSTDOC) --test --cfg 'feature="bar"' \ + -L $(TMPDIR) foo.rs |\ + $(CGREP) 'foo.rs - foo (line 1) ... ok' diff --git a/src/test/run-make-fulldeps/issue-22131/foo.rs b/src/test/run-make-fulldeps/issue-22131/foo.rs new file mode 100644 index 000000000..33255d768 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-22131/foo.rs @@ -0,0 +1,5 @@ +/// ```rust +/// assert_eq!(foo::foo(), 1); +/// ``` +#[cfg(feature = "bar")] +pub fn foo() -> i32 { 1 } diff --git a/src/test/run-make-fulldeps/issue-24445/Makefile b/src/test/run-make-fulldeps/issue-24445/Makefile new file mode 100644 index 000000000..f7ad238af --- /dev/null +++ b/src/test/run-make-fulldeps/issue-24445/Makefile @@ -0,0 +1,10 @@ +-include ../tools.mk + +# only-linux + +all: + $(RUSTC) foo.rs + $(CC) foo.c -lfoo -L $(TMPDIR) -Wl,--gc-sections -lpthread -ldl -o $(TMPDIR)/foo + $(call RUN,foo) + $(CC) foo.c -lfoo -L $(TMPDIR) -Wl,--gc-sections -lpthread -ldl -pie -fPIC -o $(TMPDIR)/foo + $(call RUN,foo) diff --git a/src/test/run-make-fulldeps/issue-24445/foo.c b/src/test/run-make-fulldeps/issue-24445/foo.c new file mode 100644 index 000000000..bb4036b06 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-24445/foo.c @@ -0,0 +1,6 @@ +void foo(); + +int main() { + foo(); + return 0; +} diff --git a/src/test/run-make-fulldeps/issue-24445/foo.rs b/src/test/run-make-fulldeps/issue-24445/foo.rs new file mode 100644 index 000000000..b67f3847c --- /dev/null +++ b/src/test/run-make-fulldeps/issue-24445/foo.rs @@ -0,0 +1,15 @@ +#![crate_type = "staticlib"] + +struct Destroy; +impl Drop for Destroy { + fn drop(&mut self) { println!("drop"); } +} + +thread_local! { + static X: Destroy = Destroy +} + +#[no_mangle] +pub extern "C" fn foo() { + X.with(|_| ()); +} diff --git a/src/test/run-make-fulldeps/issue-25581/Makefile b/src/test/run-make-fulldeps/issue-25581/Makefile new file mode 100644 index 000000000..042048ec2 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-25581/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: $(call NATIVE_STATICLIB,test) + $(RUSTC) test.rs + $(call RUN,test) || exit 1 diff --git a/src/test/run-make-fulldeps/issue-25581/test.c b/src/test/run-make-fulldeps/issue-25581/test.c new file mode 100644 index 000000000..52fbf7851 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-25581/test.c @@ -0,0 +1,15 @@ +#include <stddef.h> +#include <stdint.h> + +struct ByteSlice { + uint8_t *data; + size_t len; +}; + +size_t slice_len(struct ByteSlice bs) { + return bs.len; +} + +uint8_t slice_elem(struct ByteSlice bs, size_t idx) { + return bs.data[idx]; +} diff --git a/src/test/run-make-fulldeps/issue-25581/test.rs b/src/test/run-make-fulldeps/issue-25581/test.rs new file mode 100644 index 000000000..ba6749c97 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-25581/test.rs @@ -0,0 +1,18 @@ +#[link(name = "test", kind = "static")] +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]; + + unsafe { + assert_eq!(data.len(), slice_len(&data) as usize); + assert_eq!(data[0], slice_elem(&data, 0)); + assert_eq!(data[1], slice_elem(&data, 1)); + assert_eq!(data[2], slice_elem(&data, 2)); + assert_eq!(data[3], slice_elem(&data, 3)); + assert_eq!(data[4], slice_elem(&data, 4)); + } +} diff --git a/src/test/run-make-fulldeps/issue-26006/Makefile b/src/test/run-make-fulldeps/issue-26006/Makefile new file mode 100644 index 000000000..dd023c32b --- /dev/null +++ b/src/test/run-make-fulldeps/issue-26006/Makefile @@ -0,0 +1,16 @@ +-include ../tools.mk + +# ignore-windows + +OUT := $(TMPDIR)/out + +all: time + +time: libc + mkdir -p $(OUT)/time $(OUT)/time/deps + ln -sf $(OUT)/libc/liblibc.rlib $(OUT)/time/deps/ + $(RUSTC) in/time/lib.rs -Ldependency=$(OUT)/time/deps/ + +libc: + mkdir -p $(OUT)/libc + $(RUSTC) in/libc/lib.rs --crate-name=libc -Cmetadata=foo -o $(OUT)/libc/liblibc.rlib diff --git a/src/test/run-make-fulldeps/issue-26006/in/libc/lib.rs b/src/test/run-make-fulldeps/issue-26006/in/libc/lib.rs new file mode 100644 index 000000000..23f2bf518 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-26006/in/libc/lib.rs @@ -0,0 +1,3 @@ +#![crate_type="rlib"] + +pub fn something(){} diff --git a/src/test/run-make-fulldeps/issue-26006/in/time/lib.rs b/src/test/run-make-fulldeps/issue-26006/in/time/lib.rs new file mode 100644 index 000000000..87f2f824a --- /dev/null +++ b/src/test/run-make-fulldeps/issue-26006/in/time/lib.rs @@ -0,0 +1,4 @@ +#![feature(rustc_private)] +extern crate libc; + +fn main(){} diff --git a/src/test/run-make-fulldeps/issue-26092/Makefile b/src/test/run-make-fulldeps/issue-26092/Makefile new file mode 100644 index 000000000..885f45a02 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-26092/Makefile @@ -0,0 +1,6 @@ +-include ../tools.mk + +# This test ensures that rustc does not panic with `-o ""` option. + +all: + $(RUSTC) -o "" blank.rs 2>&1 | $(CGREP) -i 'panic' && exit 1 || exit 0 diff --git a/src/test/run-make-fulldeps/issue-26092/blank.rs b/src/test/run-make-fulldeps/issue-26092/blank.rs new file mode 100644 index 000000000..f328e4d9d --- /dev/null +++ b/src/test/run-make-fulldeps/issue-26092/blank.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/src/test/run-make-fulldeps/issue-28595/Makefile b/src/test/run-make-fulldeps/issue-28595/Makefile new file mode 100644 index 000000000..61e9d0c65 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-28595/Makefile @@ -0,0 +1,6 @@ +-include ../tools.mk + +all: $(call NATIVE_STATICLIB,a) $(call NATIVE_STATICLIB,b) + $(RUSTC) a.rs + $(RUSTC) b.rs + $(call RUN,b) diff --git a/src/test/run-make-fulldeps/issue-28595/a.c b/src/test/run-make-fulldeps/issue-28595/a.c new file mode 100644 index 000000000..7bfd83cca --- /dev/null +++ b/src/test/run-make-fulldeps/issue-28595/a.c @@ -0,0 +1 @@ +void a(void) {} diff --git a/src/test/run-make-fulldeps/issue-28595/a.rs b/src/test/run-make-fulldeps/issue-28595/a.rs new file mode 100644 index 000000000..07863cf64 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-28595/a.rs @@ -0,0 +1,6 @@ +#![crate_type = "rlib"] + +#[link(name = "a", kind = "static")] +extern "C" { + pub fn a(); +} diff --git a/src/test/run-make-fulldeps/issue-28595/b.c b/src/test/run-make-fulldeps/issue-28595/b.c new file mode 100644 index 000000000..6aecb5f9e --- /dev/null +++ b/src/test/run-make-fulldeps/issue-28595/b.c @@ -0,0 +1,5 @@ +extern void a(void); + +void b(void) { + a(); +} diff --git a/src/test/run-make-fulldeps/issue-28595/b.rs b/src/test/run-make-fulldeps/issue-28595/b.rs new file mode 100644 index 000000000..1f389859f --- /dev/null +++ b/src/test/run-make-fulldeps/issue-28595/b.rs @@ -0,0 +1,12 @@ +extern crate a; + +#[link(name = "b", kind = "static")] +extern "C" { + pub fn b(); +} + +fn main() { + unsafe { + b(); + } +} diff --git a/src/test/run-make-fulldeps/issue-28766/Makefile b/src/test/run-make-fulldeps/issue-28766/Makefile new file mode 100644 index 000000000..1f47ef15b --- /dev/null +++ b/src/test/run-make-fulldeps/issue-28766/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: + $(RUSTC) -O foo.rs + $(RUSTC) -O -L $(TMPDIR) main.rs diff --git a/src/test/run-make-fulldeps/issue-28766/foo.rs b/src/test/run-make-fulldeps/issue-28766/foo.rs new file mode 100644 index 000000000..1dcabe42d --- /dev/null +++ b/src/test/run-make-fulldeps/issue-28766/foo.rs @@ -0,0 +1,8 @@ +#![crate_type="lib"] +pub struct Foo(()); + +impl Foo { + pub fn new() -> Foo { + Foo(()) + } +} diff --git a/src/test/run-make-fulldeps/issue-28766/main.rs b/src/test/run-make-fulldeps/issue-28766/main.rs new file mode 100644 index 000000000..de12b1fd9 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-28766/main.rs @@ -0,0 +1,7 @@ +#![crate_type="lib"] +extern crate foo; +use foo::Foo; + +pub fn crash() -> Box<Foo> { + Box::new(Foo::new()) +} diff --git a/src/test/run-make-fulldeps/issue-30063/Makefile b/src/test/run-make-fulldeps/issue-30063/Makefile new file mode 100644 index 000000000..a76051dc8 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-30063/Makefile @@ -0,0 +1,35 @@ +-include ../tools.mk + +all: + rm -f $(TMPDIR)/foo-output + $(RUSTC) -C codegen-units=4 -o $(TMPDIR)/foo-output foo.rs + rm $(TMPDIR)/foo-output + + rm -f $(TMPDIR)/asm-output + $(RUSTC) -C codegen-units=4 --emit=asm -o $(TMPDIR)/asm-output foo.rs + rm $(TMPDIR)/asm-output + + rm -f $(TMPDIR)/bc-output + $(RUSTC) -C codegen-units=4 --emit=llvm-bc -o $(TMPDIR)/bc-output foo.rs + rm $(TMPDIR)/bc-output + + rm -f $(TMPDIR)/ir-output + $(RUSTC) -C codegen-units=4 --emit=llvm-ir -o $(TMPDIR)/ir-output foo.rs + rm $(TMPDIR)/ir-output + + rm -f $(TMPDIR)/link-output + $(RUSTC) -C codegen-units=4 --emit=link -o $(TMPDIR)/link-output foo.rs + rm $(TMPDIR)/link-output + + rm -f $(TMPDIR)/obj-output + $(RUSTC) -C codegen-units=4 --emit=obj -o $(TMPDIR)/obj-output foo.rs + rm $(TMPDIR)/obj-output + + rm -f $(TMPDIR)/dep-output + $(RUSTC) -C codegen-units=4 --emit=dep-info -o $(TMPDIR)/dep-output foo.rs + rm $(TMPDIR)/dep-output + +# # (This case doesn't work yet, and may be fundamentally wrong-headed anyway.) +# rm -f $(TMPDIR)/multi-output +# $(RUSTC) -C codegen-units=4 --emit=asm,obj -o $(TMPDIR)/multi-output foo.rs +# rm $(TMPDIR)/multi-output diff --git a/src/test/run-make-fulldeps/issue-30063/foo.rs b/src/test/run-make-fulldeps/issue-30063/foo.rs new file mode 100644 index 000000000..45590d86b --- /dev/null +++ b/src/test/run-make-fulldeps/issue-30063/foo.rs @@ -0,0 +1 @@ +fn main() { } diff --git a/src/test/run-make-fulldeps/issue-33329/Makefile b/src/test/run-make-fulldeps/issue-33329/Makefile new file mode 100644 index 000000000..591e4e3dd --- /dev/null +++ b/src/test/run-make-fulldeps/issue-33329/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: + $(RUSTC) --target x86_64_unknown-linux-musl main.rs 2>&1 | $(CGREP) \ + "error: Error loading target specification: Could not find specification for target" diff --git a/src/test/run-make-fulldeps/issue-33329/main.rs b/src/test/run-make-fulldeps/issue-33329/main.rs new file mode 100644 index 000000000..f328e4d9d --- /dev/null +++ b/src/test/run-make-fulldeps/issue-33329/main.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/src/test/run-make-fulldeps/issue-35164/Makefile b/src/test/run-make-fulldeps/issue-35164/Makefile new file mode 100644 index 000000000..a95125c56 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-35164/Makefile @@ -0,0 +1,4 @@ +-include ../tools.mk + +all: + $(RUSTC) main.rs --error-format json 2>&1 | $(CGREP) -e '"byte_start":23\b' '"byte_end":29\b' diff --git a/src/test/run-make-fulldeps/issue-35164/main.rs b/src/test/run-make-fulldeps/issue-35164/main.rs new file mode 100644 index 000000000..1333d6322 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-35164/main.rs @@ -0,0 +1,5 @@ +mod submodule; + +fn main() { + submodule::foo(); +} diff --git a/src/test/run-make-fulldeps/issue-35164/submodule/mod.rs b/src/test/run-make-fulldeps/issue-35164/submodule/mod.rs new file mode 100644 index 000000000..a9045b242 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-35164/submodule/mod.rs @@ -0,0 +1,3 @@ +pub fn foo() { + let _MyFoo = 2; +} diff --git a/src/test/run-make-fulldeps/issue-37839/Makefile b/src/test/run-make-fulldeps/issue-37839/Makefile new file mode 100644 index 000000000..f17ce537f --- /dev/null +++ b/src/test/run-make-fulldeps/issue-37839/Makefile @@ -0,0 +1,6 @@ +-include ../tools.mk + +all: + $(RUSTC) a.rs && $(RUSTC) b.rs + $(BARE_RUSTC) c.rs -L dependency=$(TMPDIR) --extern b=$(TMPDIR)/libb.rlib \ + --out-dir=$(TMPDIR) diff --git a/src/test/run-make-fulldeps/issue-37839/a.rs b/src/test/run-make-fulldeps/issue-37839/a.rs new file mode 100644 index 000000000..b5dffac3f --- /dev/null +++ b/src/test/run-make-fulldeps/issue-37839/a.rs @@ -0,0 +1,2 @@ +#![allow(unused)] +#![crate_type = "proc-macro"] diff --git a/src/test/run-make-fulldeps/issue-37839/b.rs b/src/test/run-make-fulldeps/issue-37839/b.rs new file mode 100644 index 000000000..355d2b165 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-37839/b.rs @@ -0,0 +1,2 @@ +#![crate_type = "lib"] +#[macro_use] extern crate a; diff --git a/src/test/run-make-fulldeps/issue-37839/c.rs b/src/test/run-make-fulldeps/issue-37839/c.rs new file mode 100644 index 000000000..4c7ce01b6 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-37839/c.rs @@ -0,0 +1,2 @@ +#![crate_type = "lib"] +extern crate b; diff --git a/src/test/run-make-fulldeps/issue-37893/Makefile b/src/test/run-make-fulldeps/issue-37893/Makefile new file mode 100644 index 000000000..27b69baf9 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-37893/Makefile @@ -0,0 +1,4 @@ +-include ../tools.mk + +all: + $(RUSTC) a.rs && $(RUSTC) b.rs && $(RUSTC) c.rs diff --git a/src/test/run-make-fulldeps/issue-37893/a.rs b/src/test/run-make-fulldeps/issue-37893/a.rs new file mode 100644 index 000000000..b5dffac3f --- /dev/null +++ b/src/test/run-make-fulldeps/issue-37893/a.rs @@ -0,0 +1,2 @@ +#![allow(unused)] +#![crate_type = "proc-macro"] diff --git a/src/test/run-make-fulldeps/issue-37893/b.rs b/src/test/run-make-fulldeps/issue-37893/b.rs new file mode 100644 index 000000000..355d2b165 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-37893/b.rs @@ -0,0 +1,2 @@ +#![crate_type = "lib"] +#[macro_use] extern crate a; diff --git a/src/test/run-make-fulldeps/issue-37893/c.rs b/src/test/run-make-fulldeps/issue-37893/c.rs new file mode 100644 index 000000000..b9c215572 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-37893/c.rs @@ -0,0 +1,3 @@ +#![crate_type = "staticlib"] +extern crate b; +extern crate a; diff --git a/src/test/run-make-fulldeps/issue-38237/Makefile b/src/test/run-make-fulldeps/issue-38237/Makefile new file mode 100644 index 000000000..0a681401b --- /dev/null +++ b/src/test/run-make-fulldeps/issue-38237/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: + $(RUSTC) foo.rs; $(RUSTC) bar.rs + $(RUSTDOC) baz.rs -L $(TMPDIR) -o $(TMPDIR) diff --git a/src/test/run-make-fulldeps/issue-38237/bar.rs b/src/test/run-make-fulldeps/issue-38237/bar.rs new file mode 100644 index 000000000..2b839f3a3 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-38237/bar.rs @@ -0,0 +1,4 @@ +#![crate_type = "lib"] + +#[derive(Debug)] +pub struct S; diff --git a/src/test/run-make-fulldeps/issue-38237/baz.rs b/src/test/run-make-fulldeps/issue-38237/baz.rs new file mode 100644 index 000000000..cd2425f9b --- /dev/null +++ b/src/test/run-make-fulldeps/issue-38237/baz.rs @@ -0,0 +1,8 @@ +extern crate foo; +extern crate bar; + +pub struct Bar; +impl ::std::ops::Deref for Bar { + type Target = bar::S; + fn deref(&self) -> &Self::Target { unimplemented!() } +} diff --git a/src/test/run-make-fulldeps/issue-38237/foo.rs b/src/test/run-make-fulldeps/issue-38237/foo.rs new file mode 100644 index 000000000..a106e4fde --- /dev/null +++ b/src/test/run-make-fulldeps/issue-38237/foo.rs @@ -0,0 +1,9 @@ +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +#[proc_macro_derive(A)] +pub fn derive(ts: proc_macro::TokenStream) -> proc_macro::TokenStream { ts } + +#[derive(Debug)] +struct S; diff --git a/src/test/run-make-fulldeps/issue-40535/Makefile b/src/test/run-make-fulldeps/issue-40535/Makefile new file mode 100644 index 000000000..49db1d43e --- /dev/null +++ b/src/test/run-make-fulldeps/issue-40535/Makefile @@ -0,0 +1,13 @@ +-include ../tools.mk + +# The ICE occurred in the following situation: +# * `foo` declares `extern crate bar, baz`, depends only on `bar` (forgetting `baz` in `Cargo.toml`) +# * `bar` declares and depends on `extern crate baz` +# * All crates built in metadata-only mode (`cargo check`) +all: + # cc https://github.com/rust-lang/rust/issues/40623 + $(RUSTC) baz.rs --emit=metadata + $(RUSTC) bar.rs --emit=metadata --extern baz=$(TMPDIR)/libbaz.rmeta + $(RUSTC) foo.rs --emit=metadata --extern bar=$(TMPDIR)/libbar.rmeta 2>&1 | \ + $(CGREP) -v "unexpectedly panicked" + # ^ Succeeds if it doesn't find the ICE message diff --git a/src/test/run-make-fulldeps/issue-40535/bar.rs b/src/test/run-make-fulldeps/issue-40535/bar.rs new file mode 100644 index 000000000..b02b28f59 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-40535/bar.rs @@ -0,0 +1,3 @@ +#![crate_type = "lib"] + +extern crate baz; diff --git a/src/test/run-make-fulldeps/issue-40535/baz.rs b/src/test/run-make-fulldeps/issue-40535/baz.rs new file mode 100644 index 000000000..83be6e807 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-40535/baz.rs @@ -0,0 +1 @@ +#![crate_type = "lib"] diff --git a/src/test/run-make-fulldeps/issue-40535/foo.rs b/src/test/run-make-fulldeps/issue-40535/foo.rs new file mode 100644 index 000000000..270202664 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-40535/foo.rs @@ -0,0 +1,4 @@ +#![crate_type = "lib"] + +extern crate bar; +extern crate baz; diff --git a/src/test/run-make-fulldeps/issue-46239/Makefile b/src/test/run-make-fulldeps/issue-46239/Makefile new file mode 100644 index 000000000..698a605f7 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-46239/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: + $(RUSTC) main.rs -C opt-level=1 + $(call RUN,main) diff --git a/src/test/run-make-fulldeps/issue-46239/main.rs b/src/test/run-make-fulldeps/issue-46239/main.rs new file mode 100644 index 000000000..b7df5cf4d --- /dev/null +++ b/src/test/run-make-fulldeps/issue-46239/main.rs @@ -0,0 +1,8 @@ +fn project<T>(x: &(T,)) -> &T { &x.0 } + +fn dummy() {} + +fn main() { + let f = (dummy as fn(),); + (*project(&f))(); +} diff --git a/src/test/run-make-fulldeps/issue-47551/Makefile b/src/test/run-make-fulldeps/issue-47551/Makefile new file mode 100644 index 000000000..f4495e6b6 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-47551/Makefile @@ -0,0 +1,9 @@ +# only-linux +# ignore-32bit + +-include ../tools.mk + +all: + $(RUSTC) eh_frame-terminator.rs + $(call RUN,eh_frame-terminator) | $(CGREP) '1122334455667788' + objdump --dwarf=frames $(TMPDIR)/eh_frame-terminator | $(CGREP) 'ZERO terminator' diff --git a/src/test/run-make-fulldeps/issue-47551/eh_frame-terminator.rs b/src/test/run-make-fulldeps/issue-47551/eh_frame-terminator.rs new file mode 100644 index 000000000..2f740dc4f --- /dev/null +++ b/src/test/run-make-fulldeps/issue-47551/eh_frame-terminator.rs @@ -0,0 +1,23 @@ +// run-pass + +#![feature(backtrace)] +#[derive(Clone, Copy)] +struct Foo { + array: [u64; 10240], +} + +impl Foo { + const fn new() -> Self { + Self { + array: [0x1122_3344_5566_7788; 10240] + } + } +} + +static BAR: [Foo; 10240] = [Foo::new(); 10240]; + +fn main() { + let bt = std::backtrace::Backtrace::force_capture(); + println!("Hello, world! {:?}", bt); + println!("{:x}", BAR[0].array[0]); +} diff --git a/src/test/run-make-fulldeps/issue-51671/Makefile b/src/test/run-make-fulldeps/issue-51671/Makefile new file mode 100644 index 000000000..ba3d3b710 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-51671/Makefile @@ -0,0 +1,9 @@ +-include ../tools.mk + +# ignore-windows-msvc + +all: + $(RUSTC) --emit=obj app.rs + nm $(TMPDIR)/app.o | $(CGREP) rust_begin_unwind + nm $(TMPDIR)/app.o | $(CGREP) rust_eh_personality + nm $(TMPDIR)/app.o | $(CGREP) rust_oom diff --git a/src/test/run-make-fulldeps/issue-51671/app.rs b/src/test/run-make-fulldeps/issue-51671/app.rs new file mode 100644 index 000000000..c13937dcf --- /dev/null +++ b/src/test/run-make-fulldeps/issue-51671/app.rs @@ -0,0 +1,20 @@ +#![crate_type = "bin"] +#![feature(lang_items)] +#![no_main] +#![no_std] + +use core::alloc::Layout; +use core::panic::PanicInfo; + +#[panic_handler] +fn panic(_: &PanicInfo) -> ! { + loop {} +} + +#[lang = "eh_personality"] +fn eh() {} + +#[lang = "oom"] +fn oom(_: Layout) -> ! { + loop {} +} diff --git a/src/test/run-make-fulldeps/issue-53964/Makefile b/src/test/run-make-fulldeps/issue-53964/Makefile new file mode 100644 index 000000000..c56beb52f --- /dev/null +++ b/src/test/run-make-fulldeps/issue-53964/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: + $(RUSTC) panic.rs + $(RUSTC) -C panic=abort --emit=obj app.rs -L $(TMPDIR) diff --git a/src/test/run-make-fulldeps/issue-53964/app.rs b/src/test/run-make-fulldeps/issue-53964/app.rs new file mode 100644 index 000000000..8127b9578 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-53964/app.rs @@ -0,0 +1,8 @@ +#![crate_type = "bin"] +#![no_main] +#![no_std] + +#![deny(unused_extern_crates)] + +// `panic` provides a `panic_handler` so it shouldn't trip the `unused_extern_crates` lint +extern crate panic; diff --git a/src/test/run-make-fulldeps/issue-53964/panic.rs b/src/test/run-make-fulldeps/issue-53964/panic.rs new file mode 100644 index 000000000..a87812050 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-53964/panic.rs @@ -0,0 +1,10 @@ +#![crate_type = "lib"] +#![feature(panic_handler)] +#![no_std] + +use core::panic::PanicInfo; + +#[panic_handler] +fn panic(_: &PanicInfo) -> ! { + loop {} +} diff --git a/src/test/run-make-fulldeps/issue-64153/Makefile b/src/test/run-make-fulldeps/issue-64153/Makefile new file mode 100644 index 000000000..9c0c3fe6e --- /dev/null +++ b/src/test/run-make-fulldeps/issue-64153/Makefile @@ -0,0 +1,26 @@ +-include ../tools.mk + +# `llvm-objdump`'s output looks different on windows than on other platforms. +# It should be enough to check on Unix platforms, so: +# ignore-windows + +# Staticlibs don't include Rust object files from upstream crates if the same +# code was already pulled into the lib via LTO. However, the bug described in +# https://github.com/rust-lang/rust/issues/64153 lead to this exclusion not +# working properly if the upstream crate was compiled with an explicit filename +# (via `-o`). +# +# This test makes sure that functions defined in the upstream crates do not +# appear twice in the final staticlib when listing all the symbols from it. + +all: + $(RUSTC) --crate-type rlib upstream.rs -o $(TMPDIR)/libupstream.rlib -Ccodegen-units=1 + $(RUSTC) --crate-type staticlib downstream.rs -Clto -Ccodegen-units=1 -o $(TMPDIR)/libdownstream.a + # Dump all the symbols from the staticlib into `syms` + "$(LLVM_BIN_DIR)"/llvm-objdump -t $(TMPDIR)/libdownstream.a > $(TMPDIR)/syms + # Count the global instances of `issue64153_test_function`. There'll be 2 + # if the `upstream` object file got erronously included twice. + # The line we are testing for with the regex looks something like: + # 0000000000000000 g F .text.issue64153_test_function 00000023 issue64153_test_function + grep -c -e "[[:space:]]g[[:space:]]*F[[:space:]].*issue64153_test_function" $(TMPDIR)/syms > $(TMPDIR)/count + [ "$$(cat $(TMPDIR)/count)" -eq "1" ] diff --git a/src/test/run-make-fulldeps/issue-64153/downstream.rs b/src/test/run-make-fulldeps/issue-64153/downstream.rs new file mode 100644 index 000000000..e03704665 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-64153/downstream.rs @@ -0,0 +1,6 @@ +extern crate upstream; + +#[no_mangle] +pub extern "C" fn foo() { + print!("1 + 1 = {}", upstream::issue64153_test_function(1)); +} diff --git a/src/test/run-make-fulldeps/issue-64153/upstream.rs b/src/test/run-make-fulldeps/issue-64153/upstream.rs new file mode 100644 index 000000000..861a00298 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-64153/upstream.rs @@ -0,0 +1,6 @@ +// Make this function extern "C", public, and no-mangle, so that it gets +// exported from the downstream staticlib. +#[no_mangle] +pub extern "C" fn issue64153_test_function(x: u32) -> u32 { + x + 1 +} diff --git a/src/test/run-make-fulldeps/issue-68794-textrel-on-minimal-lib/Makefile b/src/test/run-make-fulldeps/issue-68794-textrel-on-minimal-lib/Makefile new file mode 100644 index 000000000..2f16ad328 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-68794-textrel-on-minimal-lib/Makefile @@ -0,0 +1,17 @@ +# Regression test for issue #68794 +# +# Verify that no text relocations are accidentally introduced by linking a +# minimal rust staticlib. +# +# The test links a rust static library into a shared library, and checks that +# the linker doesn't have to flag the resulting file as containing TEXTRELs. + +-include ../tools.mk + +# only-linux + +all: + $(RUSTC) foo.rs + $(CC) bar.c $(call STATICLIB,foo) -fPIC -shared -o $(call DYLIB,bar) \ + $(EXTRACFLAGS) $(EXTRACXXFLAGS) + readelf -d $(call DYLIB,bar) | grep TEXTREL; test $$? -eq 1 diff --git a/src/test/run-make-fulldeps/issue-68794-textrel-on-minimal-lib/bar.c b/src/test/run-make-fulldeps/issue-68794-textrel-on-minimal-lib/bar.c new file mode 100644 index 000000000..bb4036b06 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-68794-textrel-on-minimal-lib/bar.c @@ -0,0 +1,6 @@ +void foo(); + +int main() { + foo(); + return 0; +} diff --git a/src/test/run-make-fulldeps/issue-68794-textrel-on-minimal-lib/foo.rs b/src/test/run-make-fulldeps/issue-68794-textrel-on-minimal-lib/foo.rs new file mode 100644 index 000000000..a3e865b63 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-68794-textrel-on-minimal-lib/foo.rs @@ -0,0 +1,8 @@ +#![crate_type = "staticlib"] + +#[no_mangle] +pub extern "C" fn foo(x: u32) { + // using the println! makes it so that enough code from the standard + // library is included (see issue #68794) + println!("foo: {}", x); +} diff --git a/src/test/run-make-fulldeps/issue-69368/Makefile b/src/test/run-make-fulldeps/issue-69368/Makefile new file mode 100644 index 000000000..dbb044d8f --- /dev/null +++ b/src/test/run-make-fulldeps/issue-69368/Makefile @@ -0,0 +1,18 @@ +-include ../tools.mk + +# Test that previously triggered a linker failure with root cause +# similar to one found in the issue #69368. +# +# The crate that provides oom lang item is missing some other lang +# items. Necessary to prevent the use of start-group / end-group. +# +# The weak lang items are defined in a separate compilation units, +# so that linker could omit them if not used. +# +# The crates that need those weak lang items are dependencies of +# crates that provide them. + +all: + $(RUSTC) a.rs + $(RUSTC) b.rs + $(RUSTC) c.rs diff --git a/src/test/run-make-fulldeps/issue-69368/a.rs b/src/test/run-make-fulldeps/issue-69368/a.rs new file mode 100644 index 000000000..7d339c5a5 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-69368/a.rs @@ -0,0 +1,21 @@ +#![crate_type = "rlib"] +#![feature(lang_items)] +#![feature(panic_unwind)] +#![no_std] + +extern crate panic_unwind; + +#[panic_handler] +pub fn panic_handler(_: &core::panic::PanicInfo) -> ! { + loop {} +} + +#[no_mangle] +extern "C" fn __rust_drop_panic() -> ! { + loop {} +} + +#[no_mangle] +extern "C" fn __rust_foreign_exception() -> ! { + loop {} +} diff --git a/src/test/run-make-fulldeps/issue-69368/b.rs b/src/test/run-make-fulldeps/issue-69368/b.rs new file mode 100644 index 000000000..4d6af0266 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-69368/b.rs @@ -0,0 +1,8 @@ +#![crate_type = "rlib"] +#![feature(alloc_error_handler)] +#![no_std] + +#[alloc_error_handler] +pub fn error_handler(_: core::alloc::Layout) -> ! { + panic!(); +} diff --git a/src/test/run-make-fulldeps/issue-69368/c.rs b/src/test/run-make-fulldeps/issue-69368/c.rs new file mode 100644 index 000000000..729c4249a --- /dev/null +++ b/src/test/run-make-fulldeps/issue-69368/c.rs @@ -0,0 +1,34 @@ +#![crate_type = "bin"] +#![feature(start)] +#![no_std] + +extern crate alloc; +extern crate a; +extern crate b; + +use alloc::vec::Vec; +use core::alloc::*; + +struct Allocator; + +unsafe impl GlobalAlloc for Allocator { + unsafe fn alloc(&self, _: Layout) -> *mut u8 { + loop {} + } + + unsafe fn dealloc(&self, _: *mut u8, _: Layout) { + loop {} + } +} + +#[global_allocator] +static ALLOCATOR: Allocator = Allocator; + +#[start] +fn main(argc: isize, _argv: *const *const u8) -> isize { + let mut v = Vec::new(); + for i in 0..argc { + v.push(i); + } + v.iter().sum() +} diff --git a/src/test/run-make-fulldeps/issue-7349/Makefile b/src/test/run-make-fulldeps/issue-7349/Makefile new file mode 100644 index 000000000..9658b99e3 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-7349/Makefile @@ -0,0 +1,11 @@ +-include ../tools.mk + +# Test to make sure that inner functions within a polymorphic outer function +# don't get re-codegened when the outer function is monomorphized. The test +# code monomorphizes the outer functions several times, but the magic constants +# used in the inner functions should each appear only once in the generated IR. + +all: + $(RUSTC) foo.rs --emit=llvm-ir + [ "$$(grep -c 'ret i32 8675309' "$(TMPDIR)/foo.ll")" -eq "1" ] + [ "$$(grep -c 'ret i32 11235813' "$(TMPDIR)/foo.ll")" -eq "1" ] diff --git a/src/test/run-make-fulldeps/issue-7349/foo.rs b/src/test/run-make-fulldeps/issue-7349/foo.rs new file mode 100644 index 000000000..246a12595 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-7349/foo.rs @@ -0,0 +1,22 @@ +fn outer<T>() { + #[allow(dead_code)] + fn inner() -> u32 { + 8675309 + } + inner(); +} + +extern "C" fn outer_foreign<T>() { + #[allow(dead_code)] + fn inner() -> u32 { + 11235813 + } + inner(); +} + +fn main() { + outer::<isize>(); + outer::<usize>(); + outer_foreign::<isize>(); + outer_foreign::<usize>(); +} diff --git a/src/test/run-make-fulldeps/issue-83045/Makefile b/src/test/run-make-fulldeps/issue-83045/Makefile new file mode 100644 index 000000000..34853cb1d --- /dev/null +++ b/src/test/run-make-fulldeps/issue-83045/Makefile @@ -0,0 +1,33 @@ +include ../../run-make-fulldeps/tools.mk + +# This test case creates a situation where the crate loader would run +# into an ICE when confronted with an invalid setup where it cannot +# find the dependency of a direct dependency. +# +# The test case makes sure that the compiler produces the expected +# error message but does not ICE immediately after. +# +# See https://github.com/rust-lang/rust/issues/83045 + +# This is a platform-independent issue, no need to waste time testing +# everywhere. +# only-x86_64 +# only-linux + +# NOTE: We use BARE_RUSTC below so that the compiler can't find liba.rlib +# If we used RUSTC the additional '-L TMPDIR' option would allow rustc to +# actually find the crate. +# +# We check that we get the expected error message +# But that we do not get an ICE + +all: + $(RUSTC) --crate-name=a --crate-type=rlib a.rs --verbose + $(RUSTC) --crate-name=b --crate-type=rlib --extern a=$(TMPDIR)/liba.rlib b.rs --verbose + $(BARE_RUSTC) --out-dir $(TMPDIR) \ + --extern b=$(TMPDIR)/libb.rlib \ + --crate-type=rlib \ + --edition=2018 \ + c.rs 2>&1 | tee $(TMPDIR)/output.txt || exit 0 + $(CGREP) E0463 < $(TMPDIR)/output.txt + $(CGREP) -v "internal compiler error" < $(TMPDIR)/output.txt diff --git a/src/test/run-make-fulldeps/issue-83045/a.rs b/src/test/run-make-fulldeps/issue-83045/a.rs new file mode 100644 index 000000000..66d9f758e --- /dev/null +++ b/src/test/run-make-fulldeps/issue-83045/a.rs @@ -0,0 +1 @@ +// empty on purpose diff --git a/src/test/run-make-fulldeps/issue-83045/b.rs b/src/test/run-make-fulldeps/issue-83045/b.rs new file mode 100644 index 000000000..f4876cfa4 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-83045/b.rs @@ -0,0 +1 @@ +extern crate a; diff --git a/src/test/run-make-fulldeps/issue-83045/c.rs b/src/test/run-make-fulldeps/issue-83045/c.rs new file mode 100644 index 000000000..e0c452549 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-83045/c.rs @@ -0,0 +1 @@ +use b as _; diff --git a/src/test/run-make-fulldeps/issue-84395-lto-embed-bitcode/Makefile b/src/test/run-make-fulldeps/issue-84395-lto-embed-bitcode/Makefile new file mode 100644 index 000000000..157edb20c --- /dev/null +++ b/src/test/run-make-fulldeps/issue-84395-lto-embed-bitcode/Makefile @@ -0,0 +1,11 @@ +# needs-matching-clang + +# This test makes sure the embed bitcode in elf created with +# lto-embed-bitcode=optimized is valid llvm BC module. + +-include ../../run-make-fulldeps/tools.mk + +all: + $(RUSTC) test.rs --target $(TARGET) -Clink-arg=-fuse-ld=lld -Clinker-plugin-lto -Clinker=$(CLANG) -Clink-arg=-Wl,--plugin-opt=-lto-embed-bitcode=optimized -Zemit-thin-lto=no + $(LLVM_BIN_DIR)/objcopy --dump-section .llvmbc=$(TMPDIR)/test.bc $(TMPDIR)/test + $(LLVM_BIN_DIR)/llvm-dis $(TMPDIR)/test.bc diff --git a/src/test/run-make-fulldeps/issue-84395-lto-embed-bitcode/test.rs b/src/test/run-make-fulldeps/issue-84395-lto-embed-bitcode/test.rs new file mode 100644 index 000000000..47ad8c634 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-84395-lto-embed-bitcode/test.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello World!"); +} diff --git a/src/test/run-make-fulldeps/issue64319/Makefile b/src/test/run-make-fulldeps/issue64319/Makefile new file mode 100644 index 000000000..5592f5a71 --- /dev/null +++ b/src/test/run-make-fulldeps/issue64319/Makefile @@ -0,0 +1,39 @@ +-include ../../run-make-fulldeps/tools.mk + +# Different optimization levels imply different values for `-Zshare-generics`, +# so try out a whole bunch of combinations to make sure everything is compatible +all: + # First up, try some defaults + $(RUSTC) --crate-type rlib foo.rs + $(RUSTC) --crate-type dylib bar.rs -C opt-level=3 + + # Next try mixing up some things explicitly + $(RUSTC) --crate-type rlib foo.rs -Z share-generics=no + $(RUSTC) --crate-type dylib bar.rs -Z share-generics=no + $(RUSTC) --crate-type rlib foo.rs -Z share-generics=no + $(RUSTC) --crate-type dylib bar.rs -Z share-generics=yes + $(RUSTC) --crate-type rlib foo.rs -Z share-generics=yes + $(RUSTC) --crate-type dylib bar.rs -Z share-generics=no + $(RUSTC) --crate-type rlib foo.rs -Z share-generics=yes + $(RUSTC) --crate-type dylib bar.rs -Z share-generics=yes + + # Now combine a whole bunch of options together + $(RUSTC) --crate-type rlib foo.rs + $(RUSTC) --crate-type dylib bar.rs + $(RUSTC) --crate-type dylib bar.rs -Z share-generics=no + $(RUSTC) --crate-type dylib bar.rs -Z share-generics=yes + $(RUSTC) --crate-type dylib bar.rs -C opt-level=1 + $(RUSTC) --crate-type dylib bar.rs -C opt-level=1 -Z share-generics=no + $(RUSTC) --crate-type dylib bar.rs -C opt-level=1 -Z share-generics=yes + $(RUSTC) --crate-type dylib bar.rs -C opt-level=2 + $(RUSTC) --crate-type dylib bar.rs -C opt-level=2 -Z share-generics=no + $(RUSTC) --crate-type dylib bar.rs -C opt-level=2 -Z share-generics=yes + $(RUSTC) --crate-type dylib bar.rs -C opt-level=3 + $(RUSTC) --crate-type dylib bar.rs -C opt-level=3 -Z share-generics=no + $(RUSTC) --crate-type dylib bar.rs -C opt-level=3 -Z share-generics=yes + $(RUSTC) --crate-type dylib bar.rs -C opt-level=s + $(RUSTC) --crate-type dylib bar.rs -C opt-level=s -Z share-generics=no + $(RUSTC) --crate-type dylib bar.rs -C opt-level=s -Z share-generics=yes + $(RUSTC) --crate-type dylib bar.rs -C opt-level=z + $(RUSTC) --crate-type dylib bar.rs -C opt-level=z -Z share-generics=no + $(RUSTC) --crate-type dylib bar.rs -C opt-level=z -Z share-generics=yes diff --git a/src/test/run-make-fulldeps/issue64319/bar.rs b/src/test/run-make-fulldeps/issue64319/bar.rs new file mode 100644 index 000000000..3895c0b6c --- /dev/null +++ b/src/test/run-make-fulldeps/issue64319/bar.rs @@ -0,0 +1,5 @@ +extern crate foo; + +pub fn bar() { + foo::foo(); +} diff --git a/src/test/run-make-fulldeps/issue64319/foo.rs b/src/test/run-make-fulldeps/issue64319/foo.rs new file mode 100644 index 000000000..c54a238e9 --- /dev/null +++ b/src/test/run-make-fulldeps/issue64319/foo.rs @@ -0,0 +1,9 @@ +pub fn foo() { + bar::<usize>(); +} + +pub fn bar<T>() { + baz(); +} + +fn baz() {} diff --git a/src/test/run-make-fulldeps/issues-41478-43796/Makefile b/src/test/run-make-fulldeps/issues-41478-43796/Makefile new file mode 100644 index 000000000..f9735253a --- /dev/null +++ b/src/test/run-make-fulldeps/issues-41478-43796/Makefile @@ -0,0 +1,8 @@ +-include ../tools.mk + +all: + # Work in /tmp, because we need to create the `save-analysis-temp` folder. + cp a.rs $(TMPDIR)/ + cd $(TMPDIR) && $(RUSTC) -Zsave-analysis $(TMPDIR)/a.rs 2> $(TMPDIR)/stderr.txt || ( cat $(TMPDIR)/stderr.txt && exit 1 ) + [ ! -s $(TMPDIR)/stderr.txt ] || ( cat $(TMPDIR)/stderr.txt && exit 1 ) + [ -f $(TMPDIR)/save-analysis/liba.json ] || ( ls -la $(TMPDIR) && exit 1 ) diff --git a/src/test/run-make-fulldeps/issues-41478-43796/a.rs b/src/test/run-make-fulldeps/issues-41478-43796/a.rs new file mode 100644 index 000000000..b072235b5 --- /dev/null +++ b/src/test/run-make-fulldeps/issues-41478-43796/a.rs @@ -0,0 +1,9 @@ +#![crate_type = "lib"] +pub struct V<S>(#[allow(unused_tuple_struct_fields)] S); +pub trait An { + type U; +} +pub trait F<A> { +} +impl<A: An> F<A> for V<<A as An>::U> { +} diff --git a/src/test/run-make-fulldeps/libs-through-symlinks/Makefile b/src/test/run-make-fulldeps/libs-through-symlinks/Makefile new file mode 100644 index 000000000..8be2e234f --- /dev/null +++ b/src/test/run-make-fulldeps/libs-through-symlinks/Makefile @@ -0,0 +1,11 @@ +-include ../tools.mk + +# ignore-windows + +NAME := $(shell $(RUSTC) --print file-names foo.rs) + +all: + mkdir -p $(TMPDIR)/outdir + $(RUSTC) foo.rs -o $(TMPDIR)/outdir/$(NAME) + ln -nsf outdir/$(NAME) $(TMPDIR) + RUSTC_LOG=rustc_metadata::loader $(RUSTC) bar.rs diff --git a/src/test/run-make-fulldeps/libs-through-symlinks/bar.rs b/src/test/run-make-fulldeps/libs-through-symlinks/bar.rs new file mode 100644 index 000000000..bb7b36c49 --- /dev/null +++ b/src/test/run-make-fulldeps/libs-through-symlinks/bar.rs @@ -0,0 +1,3 @@ +extern crate foo; + +fn main() {} diff --git a/src/test/run-make-fulldeps/libs-through-symlinks/foo.rs b/src/test/run-make-fulldeps/libs-through-symlinks/foo.rs new file mode 100644 index 000000000..8e3df2c6d --- /dev/null +++ b/src/test/run-make-fulldeps/libs-through-symlinks/foo.rs @@ -0,0 +1,2 @@ +#![crate_type = "rlib"] +#![crate_name = "foo"] diff --git a/src/test/run-make-fulldeps/libtest-json/Makefile b/src/test/run-make-fulldeps/libtest-json/Makefile new file mode 100644 index 000000000..67b5fc2ed --- /dev/null +++ b/src/test/run-make-fulldeps/libtest-json/Makefile @@ -0,0 +1,18 @@ +-include ../tools.mk + +# Test expected libtest's JSON output + +OUTPUT_FILE_DEFAULT := $(TMPDIR)/libtest-json-output-default.json +OUTPUT_FILE_STDOUT_SUCCESS := $(TMPDIR)/libtest-json-output-stdout-success.json + +all: f.rs validate_json.py output-default.json output-stdout-success.json + $(RUSTC) --test f.rs + RUST_BACKTRACE=0 $(call RUN,f) -Z unstable-options --test-threads=1 --format=json > $(OUTPUT_FILE_DEFAULT) || true + RUST_BACKTRACE=0 $(call RUN,f) -Z unstable-options --test-threads=1 --format=json --show-output > $(OUTPUT_FILE_STDOUT_SUCCESS) || true + + cat $(OUTPUT_FILE_DEFAULT) | "$(PYTHON)" validate_json.py + cat $(OUTPUT_FILE_STDOUT_SUCCESS) | "$(PYTHON)" validate_json.py + + # Normalize the actual output and compare to expected output file + cat $(OUTPUT_FILE_DEFAULT) | sed 's/"exec_time": [0-9.]*/"exec_time": $$TIME/' | diff output-default.json - + cat $(OUTPUT_FILE_STDOUT_SUCCESS) | sed 's/"exec_time": [0-9.]*/"exec_time": $$TIME/' | diff output-stdout-success.json - diff --git a/src/test/run-make-fulldeps/libtest-json/f.rs b/src/test/run-make-fulldeps/libtest-json/f.rs new file mode 100644 index 000000000..edfe25086 --- /dev/null +++ b/src/test/run-make-fulldeps/libtest-json/f.rs @@ -0,0 +1,22 @@ +#[test] +fn a() { + println!("print from successful test"); + // Should pass +} + +#[test] +fn b() { + assert!(false); +} + +#[test] +#[should_panic] +fn c() { + assert!(false); +} + +#[test] +#[ignore = "msg"] +fn d() { + assert!(false); +} diff --git a/src/test/run-make-fulldeps/libtest-json/output-default.json b/src/test/run-make-fulldeps/libtest-json/output-default.json new file mode 100644 index 000000000..63342abc6 --- /dev/null +++ b/src/test/run-make-fulldeps/libtest-json/output-default.json @@ -0,0 +1,10 @@ +{ "type": "suite", "event": "started", "test_count": 4 } +{ "type": "test", "event": "started", "name": "a" } +{ "type": "test", "name": "a", "event": "ok" } +{ "type": "test", "event": "started", "name": "b" } +{ "type": "test", "name": "b", "event": "failed", "stdout": "thread 'main' panicked at 'assertion failed: false', f.rs:9:5\nnote: run with `RUST_BACKTRACE=1` environment variable to display a backtrace\n" } +{ "type": "test", "event": "started", "name": "c" } +{ "type": "test", "name": "c", "event": "ok" } +{ "type": "test", "event": "started", "name": "d" } +{ "type": "test", "name": "d", "event": "ignored", "message": "msg" } +{ "type": "suite", "event": "failed", "passed": 2, "failed": 1, "ignored": 1, "measured": 0, "filtered_out": 0, "exec_time": $TIME } diff --git a/src/test/run-make-fulldeps/libtest-json/output-stdout-success.json b/src/test/run-make-fulldeps/libtest-json/output-stdout-success.json new file mode 100644 index 000000000..8f1911446 --- /dev/null +++ b/src/test/run-make-fulldeps/libtest-json/output-stdout-success.json @@ -0,0 +1,10 @@ +{ "type": "suite", "event": "started", "test_count": 4 } +{ "type": "test", "event": "started", "name": "a" } +{ "type": "test", "name": "a", "event": "ok", "stdout": "print from successful test\n" } +{ "type": "test", "event": "started", "name": "b" } +{ "type": "test", "name": "b", "event": "failed", "stdout": "thread 'main' panicked at 'assertion failed: false', f.rs:9:5\nnote: run with `RUST_BACKTRACE=1` environment variable to display a backtrace\n" } +{ "type": "test", "event": "started", "name": "c" } +{ "type": "test", "name": "c", "event": "ok", "stdout": "thread 'main' panicked at 'assertion failed: false', f.rs:15:5\n" } +{ "type": "test", "event": "started", "name": "d" } +{ "type": "test", "name": "d", "event": "ignored", "message": "msg" } +{ "type": "suite", "event": "failed", "passed": 2, "failed": 1, "ignored": 1, "measured": 0, "filtered_out": 0, "exec_time": $TIME } diff --git a/src/test/run-make-fulldeps/libtest-json/validate_json.py b/src/test/run-make-fulldeps/libtest-json/validate_json.py new file mode 100755 index 000000000..657f732f2 --- /dev/null +++ b/src/test/run-make-fulldeps/libtest-json/validate_json.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python + +import sys +import json + +# Try to decode line in order to ensure it is a valid JSON document +for line in sys.stdin: + json.loads(line) diff --git a/src/test/run-make-fulldeps/link-arg/Makefile b/src/test/run-make-fulldeps/link-arg/Makefile new file mode 100644 index 000000000..0360ede76 --- /dev/null +++ b/src/test/run-make-fulldeps/link-arg/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk +RUSTC_FLAGS = -C link-arg="-lfoo" -C link-arg="-lbar" --print link-args + +all: + $(RUSTC) $(RUSTC_FLAGS) empty.rs | $(CGREP) lfoo lbar diff --git a/src/test/run-make-fulldeps/link-arg/empty.rs b/src/test/run-make-fulldeps/link-arg/empty.rs new file mode 100644 index 000000000..45590d86b --- /dev/null +++ b/src/test/run-make-fulldeps/link-arg/empty.rs @@ -0,0 +1 @@ +fn main() { } diff --git a/src/test/run-make-fulldeps/link-args-order/Makefile b/src/test/run-make-fulldeps/link-args-order/Makefile new file mode 100644 index 000000000..f94e882cc --- /dev/null +++ b/src/test/run-make-fulldeps/link-args-order/Makefile @@ -0,0 +1,10 @@ +# ignore-msvc + +-include ../tools.mk + +RUSTC_FLAGS = -C linker-flavor=ld -C link-arg=a -C link-args="b c" -C link-args="d e" -C link-arg=f +RUSTC_FLAGS_PRE = -C linker-flavor=ld -Z pre-link-arg=a -Z pre-link-args="b c" -Z pre-link-args="d e" -Z pre-link-arg=f + +all: + $(RUSTC) $(RUSTC_FLAGS) empty.rs 2>&1 | $(CGREP) '"a" "b" "c" "d" "e" "f"' + $(RUSTC) $(RUSTC_FLAGS_PRE) empty.rs 2>&1 | $(CGREP) '"a" "b" "c" "d" "e" "f"' diff --git a/src/test/run-make-fulldeps/link-args-order/empty.rs b/src/test/run-make-fulldeps/link-args-order/empty.rs new file mode 100644 index 000000000..f328e4d9d --- /dev/null +++ b/src/test/run-make-fulldeps/link-args-order/empty.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/src/test/run-make-fulldeps/link-cfg/Makefile b/src/test/run-make-fulldeps/link-cfg/Makefile new file mode 100644 index 000000000..2701b4a59 --- /dev/null +++ b/src/test/run-make-fulldeps/link-cfg/Makefile @@ -0,0 +1,22 @@ +-include ../tools.mk + +all: $(call DYLIB,return1) $(call DYLIB,return2) $(call NATIVE_STATICLIB,return3) + ls $(TMPDIR) + $(BARE_RUSTC) --print cfg --target x86_64-unknown-linux-musl | $(CGREP) crt-static + + $(RUSTC) no-deps.rs --cfg foo + $(call RUN,no-deps) + $(RUSTC) no-deps.rs --cfg bar + $(call RUN,no-deps) + + $(RUSTC) dep.rs + $(RUSTC) with-deps.rs --cfg foo + $(call RUN,with-deps) + $(RUSTC) with-deps.rs --cfg bar + $(call RUN,with-deps) + + $(RUSTC) dep-with-staticlib.rs + $(RUSTC) with-staticlib-deps.rs --cfg foo + $(call RUN,with-staticlib-deps) + $(RUSTC) with-staticlib-deps.rs --cfg bar + $(call RUN,with-staticlib-deps) diff --git a/src/test/run-make-fulldeps/link-cfg/dep-with-staticlib.rs b/src/test/run-make-fulldeps/link-cfg/dep-with-staticlib.rs new file mode 100644 index 000000000..5ad66475d --- /dev/null +++ b/src/test/run-make-fulldeps/link-cfg/dep-with-staticlib.rs @@ -0,0 +1,8 @@ +#![feature(link_cfg)] +#![crate_type = "rlib"] + +#[link(name = "return1", cfg(foo))] +#[link(name = "return3", kind = "static", cfg(bar))] +extern "C" { + pub fn my_function() -> i32; +} diff --git a/src/test/run-make-fulldeps/link-cfg/dep.rs b/src/test/run-make-fulldeps/link-cfg/dep.rs new file mode 100644 index 000000000..40de77f05 --- /dev/null +++ b/src/test/run-make-fulldeps/link-cfg/dep.rs @@ -0,0 +1,8 @@ +#![feature(link_cfg)] +#![crate_type = "rlib"] + +#[link(name = "return1", cfg(foo))] +#[link(name = "return2", cfg(bar))] +extern "C" { + pub fn my_function() -> i32; +} diff --git a/src/test/run-make-fulldeps/link-cfg/no-deps.rs b/src/test/run-make-fulldeps/link-cfg/no-deps.rs new file mode 100644 index 000000000..ba5a8711a --- /dev/null +++ b/src/test/run-make-fulldeps/link-cfg/no-deps.rs @@ -0,0 +1,20 @@ +#![feature(link_cfg)] + +#[link(name = "return1", cfg(foo))] +#[link(name = "return2", cfg(bar))] +extern "C" { + fn my_function() -> i32; +} + +fn main() { + unsafe { + let v = my_function(); + if cfg!(foo) { + assert_eq!(v, 1); + } else if cfg!(bar) { + assert_eq!(v, 2); + } else { + panic!("unknown"); + } + } +} diff --git a/src/test/run-make-fulldeps/link-cfg/return1.c b/src/test/run-make-fulldeps/link-cfg/return1.c new file mode 100644 index 000000000..41c2809ad --- /dev/null +++ b/src/test/run-make-fulldeps/link-cfg/return1.c @@ -0,0 +1,6 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif +int my_function() { + return 1; +} diff --git a/src/test/run-make-fulldeps/link-cfg/return2.c b/src/test/run-make-fulldeps/link-cfg/return2.c new file mode 100644 index 000000000..622aeaa29 --- /dev/null +++ b/src/test/run-make-fulldeps/link-cfg/return2.c @@ -0,0 +1,6 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif +int my_function() { + return 2; +} diff --git a/src/test/run-make-fulldeps/link-cfg/return3.c b/src/test/run-make-fulldeps/link-cfg/return3.c new file mode 100644 index 000000000..f29dc60d5 --- /dev/null +++ b/src/test/run-make-fulldeps/link-cfg/return3.c @@ -0,0 +1,6 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif +int my_function() { + return 3; +} diff --git a/src/test/run-make-fulldeps/link-cfg/with-deps.rs b/src/test/run-make-fulldeps/link-cfg/with-deps.rs new file mode 100644 index 000000000..48b782815 --- /dev/null +++ b/src/test/run-make-fulldeps/link-cfg/with-deps.rs @@ -0,0 +1,14 @@ +extern crate dep; + +fn main() { + unsafe { + let v = dep::my_function(); + if cfg!(foo) { + assert_eq!(v, 1); + } else if cfg!(bar) { + assert_eq!(v, 2); + } else { + panic!("unknown"); + } + } +} diff --git a/src/test/run-make-fulldeps/link-cfg/with-staticlib-deps.rs b/src/test/run-make-fulldeps/link-cfg/with-staticlib-deps.rs new file mode 100644 index 000000000..23e5926a7 --- /dev/null +++ b/src/test/run-make-fulldeps/link-cfg/with-staticlib-deps.rs @@ -0,0 +1,14 @@ +extern crate dep_with_staticlib; + +fn main() { + unsafe { + let v = dep_with_staticlib::my_function(); + if cfg!(foo) { + assert_eq!(v, 1); + } else if cfg!(bar) { + assert_eq!(v, 3); + } else { + panic!("unknown"); + } + } +} diff --git a/src/test/run-make-fulldeps/link-dedup/Makefile b/src/test/run-make-fulldeps/link-dedup/Makefile new file mode 100644 index 000000000..4e7ce0f02 --- /dev/null +++ b/src/test/run-make-fulldeps/link-dedup/Makefile @@ -0,0 +1,12 @@ +# ignore-msvc + +-include ../tools.mk + +all: + $(RUSTC) depa.rs + $(RUSTC) depb.rs + $(RUSTC) depc.rs + $(RUSTC) empty.rs --cfg bar 2>&1 | $(CGREP) '"-ltesta" "-ltestb" "-ltesta"' + $(RUSTC) empty.rs 2>&1 | $(CGREP) '"-ltesta"' + $(RUSTC) empty.rs 2>&1 | $(CGREP) -v '"-ltestb"' + $(RUSTC) empty.rs 2>&1 | $(CGREP) -v '"-ltesta" "-ltesta"' diff --git a/src/test/run-make-fulldeps/link-dedup/depa.rs b/src/test/run-make-fulldeps/link-dedup/depa.rs new file mode 100644 index 000000000..e48ffd641 --- /dev/null +++ b/src/test/run-make-fulldeps/link-dedup/depa.rs @@ -0,0 +1,7 @@ +#![crate_type = "rlib"] + +#[link(name = "testa")] +extern "C" {} + +#[link(name = "testa")] +extern "C" {} diff --git a/src/test/run-make-fulldeps/link-dedup/depb.rs b/src/test/run-make-fulldeps/link-dedup/depb.rs new file mode 100644 index 000000000..b1be21fe0 --- /dev/null +++ b/src/test/run-make-fulldeps/link-dedup/depb.rs @@ -0,0 +1,8 @@ +#![feature(link_cfg)] +#![crate_type = "rlib"] + +#[link(name = "testb", cfg(foo))] +extern "C" {} + +#[link(name = "testb", cfg(bar))] +extern "C" {} diff --git a/src/test/run-make-fulldeps/link-dedup/depc.rs b/src/test/run-make-fulldeps/link-dedup/depc.rs new file mode 100644 index 000000000..8dcb3dee5 --- /dev/null +++ b/src/test/run-make-fulldeps/link-dedup/depc.rs @@ -0,0 +1,4 @@ +#![crate_type = "rlib"] + +#[link(name = "testa")] +extern "C" {} diff --git a/src/test/run-make-fulldeps/link-dedup/empty.rs b/src/test/run-make-fulldeps/link-dedup/empty.rs new file mode 100644 index 000000000..e00ae18f4 --- /dev/null +++ b/src/test/run-make-fulldeps/link-dedup/empty.rs @@ -0,0 +1,5 @@ +extern crate depa; +extern crate depb; +extern crate depc; + +fn main() {} diff --git a/src/test/run-make-fulldeps/link-path-order/Makefile b/src/test/run-make-fulldeps/link-path-order/Makefile new file mode 100644 index 000000000..eeea0e371 --- /dev/null +++ b/src/test/run-make-fulldeps/link-path-order/Makefile @@ -0,0 +1,18 @@ +-include ../tools.mk + +# Verifies that the -L arguments given to the linker is in the same order +# as the -L arguments on the rustc command line. + +CORRECT_DIR=$(TMPDIR)/correct +WRONG_DIR=$(TMPDIR)/wrong + +F := $(call NATIVE_STATICLIB_FILE,foo) + +all: $(call NATIVE_STATICLIB,correct) $(call NATIVE_STATICLIB,wrong) + mkdir -p $(CORRECT_DIR) $(WRONG_DIR) + mv $(call NATIVE_STATICLIB,correct) $(CORRECT_DIR)/$(F) + mv $(call NATIVE_STATICLIB,wrong) $(WRONG_DIR)/$(F) + $(RUSTC) main.rs -o $(TMPDIR)/should_succeed -L $(CORRECT_DIR) -L $(WRONG_DIR) + $(call RUN,should_succeed) + $(RUSTC) main.rs -o $(TMPDIR)/should_fail -L $(WRONG_DIR) -L $(CORRECT_DIR) + $(call FAIL,should_fail) diff --git a/src/test/run-make-fulldeps/link-path-order/correct.c b/src/test/run-make-fulldeps/link-path-order/correct.c new file mode 100644 index 000000000..3064af952 --- /dev/null +++ b/src/test/run-make-fulldeps/link-path-order/correct.c @@ -0,0 +1 @@ +int should_return_one() { return 1; } diff --git a/src/test/run-make-fulldeps/link-path-order/main.rs b/src/test/run-make-fulldeps/link-path-order/main.rs new file mode 100644 index 000000000..8024e343d --- /dev/null +++ b/src/test/run-make-fulldeps/link-path-order/main.rs @@ -0,0 +1,16 @@ +#![feature(rustc_private)] + +extern crate libc; + +#[link(name = "foo", kind = "static")] +extern "C" { + fn should_return_one() -> libc::c_int; +} + +fn main() { + let result = unsafe { should_return_one() }; + + if result != 1 { + std::process::exit(255); + } +} diff --git a/src/test/run-make-fulldeps/link-path-order/wrong.c b/src/test/run-make-fulldeps/link-path-order/wrong.c new file mode 100644 index 000000000..64275b3ad --- /dev/null +++ b/src/test/run-make-fulldeps/link-path-order/wrong.c @@ -0,0 +1 @@ +int should_return_one() { return 0; } diff --git a/src/test/run-make-fulldeps/linkage-attr-on-static/Makefile b/src/test/run-make-fulldeps/linkage-attr-on-static/Makefile new file mode 100644 index 000000000..4befbe144 --- /dev/null +++ b/src/test/run-make-fulldeps/linkage-attr-on-static/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: $(call NATIVE_STATICLIB,foo) + $(RUSTC) bar.rs + $(call RUN,bar) || exit 1 diff --git a/src/test/run-make-fulldeps/linkage-attr-on-static/bar.rs b/src/test/run-make-fulldeps/linkage-attr-on-static/bar.rs new file mode 100644 index 000000000..68607cbb6 --- /dev/null +++ b/src/test/run-make-fulldeps/linkage-attr-on-static/bar.rs @@ -0,0 +1,16 @@ +#![feature(linkage)] + +#[no_mangle] +#[linkage = "external"] +static BAZ: i32 = 21; + +#[link(name = "foo", kind = "static")] +extern "C" { + fn what() -> i32; +} + +fn main() { + unsafe { + assert_eq!(what(), BAZ); + } +} diff --git a/src/test/run-make-fulldeps/linkage-attr-on-static/foo.c b/src/test/run-make-fulldeps/linkage-attr-on-static/foo.c new file mode 100644 index 000000000..78a6934f5 --- /dev/null +++ b/src/test/run-make-fulldeps/linkage-attr-on-static/foo.c @@ -0,0 +1,7 @@ +#include <stdint.h> + +extern int32_t BAZ; + +int32_t what() { + return BAZ; +} diff --git a/src/test/run-make-fulldeps/long-linker-command-lines-cmd-exe/Makefile b/src/test/run-make-fulldeps/long-linker-command-lines-cmd-exe/Makefile new file mode 100644 index 000000000..debe9e938 --- /dev/null +++ b/src/test/run-make-fulldeps/long-linker-command-lines-cmd-exe/Makefile @@ -0,0 +1,6 @@ +-include ../tools.mk + +all: + $(RUSTC) foo.rs -g + cp foo.bat $(TMPDIR)/ + OUT_DIR="$(TMPDIR)" RUSTC="$(RUSTC_ORIGINAL)" $(call RUN,foo) diff --git a/src/test/run-make-fulldeps/long-linker-command-lines-cmd-exe/foo.bat b/src/test/run-make-fulldeps/long-linker-command-lines-cmd-exe/foo.bat new file mode 100644 index 000000000..a9350f12b --- /dev/null +++ b/src/test/run-make-fulldeps/long-linker-command-lines-cmd-exe/foo.bat @@ -0,0 +1 @@ +%MY_LINKER% %* diff --git a/src/test/run-make-fulldeps/long-linker-command-lines-cmd-exe/foo.rs b/src/test/run-make-fulldeps/long-linker-command-lines-cmd-exe/foo.rs new file mode 100644 index 000000000..74d7b9b07 --- /dev/null +++ b/src/test/run-make-fulldeps/long-linker-command-lines-cmd-exe/foo.rs @@ -0,0 +1,101 @@ +// Like the `long-linker-command-lines` test this test attempts to blow +// a command line limit for running the linker. Unlike that test, however, +// this test is testing `cmd.exe` specifically rather than the OS. +// +// Unfortunately `cmd.exe` has a 8192 limit which is relatively small +// in the grand scheme of things and anyone sripting rustc's linker +// is probably using a `*.bat` script and is likely to hit this limit. +// +// This test uses a `foo.bat` script as the linker which just simply +// delegates back to this program. The compiler should use a lower +// limit for arguments before passing everything via `@`, which +// means that everything should still succeed here. + +use std::env; +use std::fs::{self, File}; +use std::io::{BufWriter, Write, Read}; +use std::path::PathBuf; +use std::process::Command; + +fn main() { + if !cfg!(windows) { + return + } + + let tmpdir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); + let ok = tmpdir.join("ok"); + let not_ok = tmpdir.join("not_ok"); + if env::var("YOU_ARE_A_LINKER").is_ok() { + match env::args_os().find(|a| a.to_string_lossy().contains("@")) { + Some(file) => { + let file = file.to_str().unwrap(); + fs::copy(&file[1..], &ok).unwrap(); + } + None => { File::create(¬_ok).unwrap(); } + } + return + } + + let rustc = env::var_os("RUSTC").unwrap_or("rustc".into()); + let me = env::current_exe().unwrap(); + let bat = me.parent() + .unwrap() + .join("foo.bat"); + let bat_linker = format!("linker={}", bat.display()); + for i in (1..).map(|i| i * 10) { + println!("attempt: {}", i); + + let file = tmpdir.join("bar.rs"); + let mut f = BufWriter::new(File::create(&file).unwrap()); + let mut lib_name = String::new(); + for _ in 0..i { + lib_name.push_str("foo"); + } + for j in 0..i { + writeln!(f, "#[link(name = \"{}{}\")]", lib_name, j).unwrap(); + } + writeln!(f, "extern {{}}\nfn main() {{}}").unwrap(); + f.into_inner().unwrap(); + + drop(fs::remove_file(&ok)); + drop(fs::remove_file(¬_ok)); + let status = Command::new(&rustc) + .arg(&file) + .arg("-C").arg(&bat_linker) + .arg("--out-dir").arg(&tmpdir) + .env("YOU_ARE_A_LINKER", "1") + .env("MY_LINKER", &me) + .status() + .unwrap(); + + if !status.success() { + panic!("rustc didn't succeed: {}", status); + } + + if !ok.exists() { + assert!(not_ok.exists()); + continue + } + + let mut contents = Vec::new(); + File::open(&ok).unwrap().read_to_end(&mut contents).unwrap(); + + for j in 0..i { + let exp = format!("{}{}", lib_name, j); + let exp = if cfg!(target_env = "msvc") { + let mut out = Vec::with_capacity(exp.len() * 2); + for c in exp.encode_utf16() { + // encode in little endian + out.push(c as u8); + out.push((c >> 8) as u8); + } + out + } else { + exp.into_bytes() + }; + assert!(contents.windows(exp.len()).any(|w| w == &exp[..])); + } + + break + } +} diff --git a/src/test/run-make-fulldeps/long-linker-command-lines/Makefile b/src/test/run-make-fulldeps/long-linker-command-lines/Makefile new file mode 100644 index 000000000..5876fbc94 --- /dev/null +++ b/src/test/run-make-fulldeps/long-linker-command-lines/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: + $(RUSTC) foo.rs -g -O + RUSTC="$(RUSTC_ORIGINAL)" $(call RUN,foo) diff --git a/src/test/run-make-fulldeps/long-linker-command-lines/foo.rs b/src/test/run-make-fulldeps/long-linker-command-lines/foo.rs new file mode 100644 index 000000000..db238c0cf --- /dev/null +++ b/src/test/run-make-fulldeps/long-linker-command-lines/foo.rs @@ -0,0 +1,106 @@ +// This is a test which attempts to blow out the system limit with how many +// arguments can be passed to a process. This'll successively call rustc with +// larger and larger argument lists in an attempt to find one that's way too +// big for the system at hand. This file itself is then used as a "linker" to +// detect when the process creation succeeds. +// +// Eventually we should see an argument that looks like `@` as we switch from +// passing literal arguments to passing everything in the file. + +use std::collections::HashSet; +use std::env; +use std::fs::{self, File}; +use std::io::{BufWriter, Write}; +use std::path::{Path, PathBuf}; +use std::process::Command; + +fn write_test_case(file: &Path, n: usize) -> HashSet<String> { + let mut libs = HashSet::new(); + let mut f = BufWriter::new(File::create(&file).unwrap()); + let mut prefix = String::new(); + for _ in 0..n { + prefix.push_str("foo"); + } + for i in 0..n { + writeln!(f, "#[link(name = \"S{}{}S\")]", prefix, i).unwrap(); + libs.insert(format!("{}{}", prefix, i)); + } + writeln!(f, "extern \"C\" {{}}\nfn main() {{}}").unwrap(); + f.into_inner().unwrap(); + + libs +} + +fn read_linker_args(path: &Path) -> String { + let contents = fs::read(path).unwrap(); + if cfg!(target_env = "msvc") { + let mut i = contents.chunks(2).map(|c| { + c[0] as u16 | ((c[1] as u16) << 8) + }); + assert_eq!(i.next(), Some(0xfeff), "Expected UTF-16 BOM"); + String::from_utf16(&i.collect::<Vec<u16>>()).unwrap() + } else { + String::from_utf8(contents).unwrap() + } +} + +fn main() { + let tmpdir = PathBuf::from(env::var_os("TMPDIR").unwrap()); + let ok = tmpdir.join("ok"); + if env::var("YOU_ARE_A_LINKER").is_ok() { + if let Some(file) = env::args_os().find(|a| a.to_string_lossy().contains("@")) { + let file = file.to_str().expect("non-utf8 file argument"); + fs::copy(&file[1..], &ok).unwrap(); + } + return + } + + let rustc = env::var_os("RUSTC").unwrap_or("rustc".into()); + let me_as_linker = format!("linker={}", env::current_exe().unwrap().display()); + for i in (1..).map(|i| i * 100) { + println!("attempt: {}", i); + let file = tmpdir.join("bar.rs"); + let mut expected_libs = write_test_case(&file, i); + + drop(fs::remove_file(&ok)); + let output = Command::new(&rustc) + .arg(&file) + .arg("-C").arg(&me_as_linker) + .arg("--out-dir").arg(&tmpdir) + .env("YOU_ARE_A_LINKER", "1") + .output() + .unwrap(); + + if !output.status.success() { + let stderr = String::from_utf8_lossy(&output.stderr); + panic!("status: {}\nstdout:\n{}\nstderr:\n{}", + output.status, + String::from_utf8_lossy(&output.stdout), + stderr.lines().map(|l| { + if l.len() > 200 { + format!("{}...\n", &l[..200]) + } else { + format!("{}\n", l) + } + }).collect::<String>()); + } + + if !ok.exists() { + continue + } + + let linker_args = read_linker_args(&ok); + for arg in linker_args.split('S') { + expected_libs.remove(arg); + } + + assert!( + expected_libs.is_empty(), + "expected but missing libraries: {:#?}\nlinker arguments: \n{}", + expected_libs, + linker_args, + ); + + break + } +} diff --git a/src/test/run-make-fulldeps/longjmp-across-rust/Makefile b/src/test/run-make-fulldeps/longjmp-across-rust/Makefile new file mode 100644 index 000000000..9d71ed8fc --- /dev/null +++ b/src/test/run-make-fulldeps/longjmp-across-rust/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: $(call NATIVE_STATICLIB,foo) + $(RUSTC) main.rs + $(call RUN,main) diff --git a/src/test/run-make-fulldeps/longjmp-across-rust/foo.c b/src/test/run-make-fulldeps/longjmp-across-rust/foo.c new file mode 100644 index 000000000..bd71cc4d7 --- /dev/null +++ b/src/test/run-make-fulldeps/longjmp-across-rust/foo.c @@ -0,0 +1,18 @@ +#include <assert.h> +#include <setjmp.h> + +static jmp_buf ENV; + +extern void test_middle(); + +void test_start(void(*f)()) { + if (setjmp(ENV) != 0) + return; + f(); + assert(0); +} + +void test_end() { + longjmp(ENV, 1); + assert(0); +} diff --git a/src/test/run-make-fulldeps/longjmp-across-rust/main.rs b/src/test/run-make-fulldeps/longjmp-across-rust/main.rs new file mode 100644 index 000000000..cc1d5b126 --- /dev/null +++ b/src/test/run-make-fulldeps/longjmp-across-rust/main.rs @@ -0,0 +1,29 @@ +#[link(name = "foo", kind = "static")] +extern "C" { + fn test_start(f: extern "C" fn()); + fn test_end(); +} + +fn main() { + unsafe { + test_start(test_middle); + } +} + +struct A; + +impl Drop for A { + fn drop(&mut self) {} +} + +extern "C" fn test_middle() { + let _a = A; + foo(); +} + +fn foo() { + let _a = A; + unsafe { + test_end(); + } +} diff --git a/src/test/run-make-fulldeps/ls-metadata/Makefile b/src/test/run-make-fulldeps/ls-metadata/Makefile new file mode 100644 index 000000000..fc3f5bce0 --- /dev/null +++ b/src/test/run-make-fulldeps/ls-metadata/Makefile @@ -0,0 +1,7 @@ +-include ../tools.mk + +all: + $(RUSTC) foo.rs + $(RUSTC) -Z ls $(TMPDIR)/foo + touch $(TMPDIR)/bar + $(RUSTC) -Z ls $(TMPDIR)/bar diff --git a/src/test/run-make-fulldeps/ls-metadata/foo.rs b/src/test/run-make-fulldeps/ls-metadata/foo.rs new file mode 100644 index 000000000..f328e4d9d --- /dev/null +++ b/src/test/run-make-fulldeps/ls-metadata/foo.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/src/test/run-make-fulldeps/lto-dylib-dep/Makefile b/src/test/run-make-fulldeps/lto-dylib-dep/Makefile new file mode 100644 index 000000000..ab8ee6c2e --- /dev/null +++ b/src/test/run-make-fulldeps/lto-dylib-dep/Makefile @@ -0,0 +1,10 @@ +-include ../tools.mk + +# Test that we don't run into an assertion when using a Rust dylib dependency +# while compiling with full LTO. +# See https://github.com/rust-lang/rust/issues/59137 + +all: + $(RUSTC) a_dylib.rs --crate-type=dylib -C prefer-dynamic + $(RUSTC) main.rs -C lto + $(call RUN,main) diff --git a/src/test/run-make-fulldeps/lto-dylib-dep/a_dylib.rs b/src/test/run-make-fulldeps/lto-dylib-dep/a_dylib.rs new file mode 100644 index 000000000..e63457e6e --- /dev/null +++ b/src/test/run-make-fulldeps/lto-dylib-dep/a_dylib.rs @@ -0,0 +1,3 @@ +pub fn foo() { + println!("bar"); +} diff --git a/src/test/run-make-fulldeps/lto-dylib-dep/main.rs b/src/test/run-make-fulldeps/lto-dylib-dep/main.rs new file mode 100644 index 000000000..4fb3c4730 --- /dev/null +++ b/src/test/run-make-fulldeps/lto-dylib-dep/main.rs @@ -0,0 +1,5 @@ +extern crate a_dylib; + +fn main() { + a_dylib::foo(); +} diff --git a/src/test/run-make-fulldeps/lto-empty/Makefile b/src/test/run-make-fulldeps/lto-empty/Makefile new file mode 100644 index 000000000..345d10bc4 --- /dev/null +++ b/src/test/run-make-fulldeps/lto-empty/Makefile @@ -0,0 +1,12 @@ +-include ../tools.mk + +all: cdylib-fat cdylib-thin + +cdylib-fat: + $(RUSTC) lib.rs -C lto=fat -C opt-level=3 -C incremental=$(TMPDIR)/inc-fat + $(RUSTC) lib.rs -C lto=fat -C opt-level=3 -C incremental=$(TMPDIR)/inc-fat + +cdylib-thin: + $(RUSTC) lib.rs -C lto=thin -C opt-level=3 -C incremental=$(TMPDIR)/inc-thin + $(RUSTC) lib.rs -C lto=thin -C opt-level=3 -C incremental=$(TMPDIR)/inc-thin + diff --git a/src/test/run-make-fulldeps/lto-empty/lib.rs b/src/test/run-make-fulldeps/lto-empty/lib.rs new file mode 100644 index 000000000..e3663c790 --- /dev/null +++ b/src/test/run-make-fulldeps/lto-empty/lib.rs @@ -0,0 +1 @@ +#![crate_type = "cdylib"] diff --git a/src/test/run-make-fulldeps/lto-no-link-whole-rlib/Makefile b/src/test/run-make-fulldeps/lto-no-link-whole-rlib/Makefile new file mode 100644 index 000000000..25afad92a --- /dev/null +++ b/src/test/run-make-fulldeps/lto-no-link-whole-rlib/Makefile @@ -0,0 +1,8 @@ +-include ../tools.mk + +all: $(call NATIVE_STATICLIB,foo) $(call NATIVE_STATICLIB,bar) + $(RUSTC) lib1.rs + $(RUSTC) lib2.rs + $(RUSTC) main.rs -Clto + $(call RUN,main) + diff --git a/src/test/run-make-fulldeps/lto-no-link-whole-rlib/bar.c b/src/test/run-make-fulldeps/lto-no-link-whole-rlib/bar.c new file mode 100644 index 000000000..b25011930 --- /dev/null +++ b/src/test/run-make-fulldeps/lto-no-link-whole-rlib/bar.c @@ -0,0 +1,3 @@ +int foo() { + return 2; +} diff --git a/src/test/run-make-fulldeps/lto-no-link-whole-rlib/foo.c b/src/test/run-make-fulldeps/lto-no-link-whole-rlib/foo.c new file mode 100644 index 000000000..75010458e --- /dev/null +++ b/src/test/run-make-fulldeps/lto-no-link-whole-rlib/foo.c @@ -0,0 +1,3 @@ +int foo() { + return 1; +} diff --git a/src/test/run-make-fulldeps/lto-no-link-whole-rlib/lib1.rs b/src/test/run-make-fulldeps/lto-no-link-whole-rlib/lib1.rs new file mode 100644 index 000000000..f70bb3382 --- /dev/null +++ b/src/test/run-make-fulldeps/lto-no-link-whole-rlib/lib1.rs @@ -0,0 +1,10 @@ +#![crate_type = "rlib"] + +#[link(name = "foo", kind = "static")] +extern "C" { + fn foo() -> i32; +} + +pub fn foo1() -> i32 { + unsafe { foo() } +} diff --git a/src/test/run-make-fulldeps/lto-no-link-whole-rlib/lib2.rs b/src/test/run-make-fulldeps/lto-no-link-whole-rlib/lib2.rs new file mode 100644 index 000000000..2dec2a271 --- /dev/null +++ b/src/test/run-make-fulldeps/lto-no-link-whole-rlib/lib2.rs @@ -0,0 +1,12 @@ +#![crate_type = "rlib"] + +extern crate lib1; + +#[link(name = "bar", kind = "static")] +extern "C" { + fn foo() -> i32; +} + +pub fn foo2() -> i32 { + unsafe { foo() } +} diff --git a/src/test/run-make-fulldeps/lto-no-link-whole-rlib/main.rs b/src/test/run-make-fulldeps/lto-no-link-whole-rlib/main.rs new file mode 100644 index 000000000..0c658808e --- /dev/null +++ b/src/test/run-make-fulldeps/lto-no-link-whole-rlib/main.rs @@ -0,0 +1,7 @@ +extern crate lib1; +extern crate lib2; + +fn main() { + assert_eq!(lib1::foo1(), 2); + assert_eq!(lib2::foo2(), 2); +} diff --git a/src/test/run-make-fulldeps/lto-readonly-lib/Makefile b/src/test/run-make-fulldeps/lto-readonly-lib/Makefile new file mode 100644 index 000000000..0afbbc345 --- /dev/null +++ b/src/test/run-make-fulldeps/lto-readonly-lib/Makefile @@ -0,0 +1,12 @@ +-include ../tools.mk + +all: + $(RUSTC) lib.rs + + # the compiler needs to copy and modify the rlib file when performing + # LTO, so we should ensure that it can cope with the original rlib + # being read-only. + chmod 444 $(TMPDIR)/*.rlib + + $(RUSTC) main.rs -C lto + $(call RUN,main) diff --git a/src/test/run-make-fulldeps/lto-readonly-lib/lib.rs b/src/test/run-make-fulldeps/lto-readonly-lib/lib.rs new file mode 100644 index 000000000..c1bfaa6ca --- /dev/null +++ b/src/test/run-make-fulldeps/lto-readonly-lib/lib.rs @@ -0,0 +1 @@ +#![crate_type = "rlib"] diff --git a/src/test/run-make-fulldeps/lto-readonly-lib/main.rs b/src/test/run-make-fulldeps/lto-readonly-lib/main.rs new file mode 100644 index 000000000..69da798b3 --- /dev/null +++ b/src/test/run-make-fulldeps/lto-readonly-lib/main.rs @@ -0,0 +1,3 @@ +extern crate lib; + +fn main() {} diff --git a/src/test/run-make-fulldeps/lto-smoke-c/Makefile b/src/test/run-make-fulldeps/lto-smoke-c/Makefile new file mode 100644 index 000000000..0f61f5de9 --- /dev/null +++ b/src/test/run-make-fulldeps/lto-smoke-c/Makefile @@ -0,0 +1,11 @@ +-include ../tools.mk + +# Apparently older versions of GCC segfault if -g is passed... +CC := $(CC:-g=) + +all: + $(RUSTC) foo.rs -C lto + $(CC) bar.c $(call STATICLIB,foo) \ + $(call OUT_EXE,bar) \ + $(EXTRACFLAGS) $(EXTRACXXFLAGS) + $(call RUN,bar) diff --git a/src/test/run-make-fulldeps/lto-smoke-c/bar.c b/src/test/run-make-fulldeps/lto-smoke-c/bar.c new file mode 100644 index 000000000..bb4036b06 --- /dev/null +++ b/src/test/run-make-fulldeps/lto-smoke-c/bar.c @@ -0,0 +1,6 @@ +void foo(); + +int main() { + foo(); + return 0; +} diff --git a/src/test/run-make-fulldeps/lto-smoke-c/foo.rs b/src/test/run-make-fulldeps/lto-smoke-c/foo.rs new file mode 100644 index 000000000..2e59432cd --- /dev/null +++ b/src/test/run-make-fulldeps/lto-smoke-c/foo.rs @@ -0,0 +1,4 @@ +#![crate_type = "staticlib"] + +#[no_mangle] +pub extern "C" fn foo() {} diff --git a/src/test/run-make-fulldeps/lto-smoke/Makefile b/src/test/run-make-fulldeps/lto-smoke/Makefile new file mode 100644 index 000000000..9b1dc2550 --- /dev/null +++ b/src/test/run-make-fulldeps/lto-smoke/Makefile @@ -0,0 +1,30 @@ +-include ../tools.mk + +all: noparam bool_true bool_false thin fat + +noparam: + $(RUSTC) lib.rs + $(RUSTC) main.rs -C lto + $(call RUN,main) + +bool_true: + $(RUSTC) lib.rs + $(RUSTC) main.rs -C lto=yes + $(call RUN,main) + + +bool_false: + $(RUSTC) lib.rs + $(RUSTC) main.rs -C lto=off + $(call RUN,main) + +thin: + $(RUSTC) lib.rs + $(RUSTC) main.rs -C lto=thin + $(call RUN,main) + +fat: + $(RUSTC) lib.rs + $(RUSTC) main.rs -C lto=fat + $(call RUN,main) + diff --git a/src/test/run-make-fulldeps/lto-smoke/lib.rs b/src/test/run-make-fulldeps/lto-smoke/lib.rs new file mode 100644 index 000000000..c1bfaa6ca --- /dev/null +++ b/src/test/run-make-fulldeps/lto-smoke/lib.rs @@ -0,0 +1 @@ +#![crate_type = "rlib"] diff --git a/src/test/run-make-fulldeps/lto-smoke/main.rs b/src/test/run-make-fulldeps/lto-smoke/main.rs new file mode 100644 index 000000000..69da798b3 --- /dev/null +++ b/src/test/run-make-fulldeps/lto-smoke/main.rs @@ -0,0 +1,3 @@ +extern crate lib; + +fn main() {} diff --git a/src/test/run-make-fulldeps/manual-crate-name/Makefile b/src/test/run-make-fulldeps/manual-crate-name/Makefile new file mode 100644 index 000000000..1d1419997 --- /dev/null +++ b/src/test/run-make-fulldeps/manual-crate-name/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: + $(RUSTC) --crate-name foo bar.rs + rm $(TMPDIR)/libfoo.rlib diff --git a/src/test/run-make-fulldeps/manual-crate-name/bar.rs b/src/test/run-make-fulldeps/manual-crate-name/bar.rs new file mode 100644 index 000000000..c1bfaa6ca --- /dev/null +++ b/src/test/run-make-fulldeps/manual-crate-name/bar.rs @@ -0,0 +1 @@ +#![crate_type = "rlib"] diff --git a/src/test/run-make-fulldeps/manual-link/Makefile b/src/test/run-make-fulldeps/manual-link/Makefile new file mode 100644 index 000000000..dccf0d99b --- /dev/null +++ b/src/test/run-make-fulldeps/manual-link/Makefile @@ -0,0 +1,6 @@ +-include ../tools.mk + +all: $(TMPDIR)/libbar.a + $(RUSTC) foo.rs -lstatic=bar + $(RUSTC) main.rs + $(call RUN,main) diff --git a/src/test/run-make-fulldeps/manual-link/bar.c b/src/test/run-make-fulldeps/manual-link/bar.c new file mode 100644 index 000000000..e42599986 --- /dev/null +++ b/src/test/run-make-fulldeps/manual-link/bar.c @@ -0,0 +1 @@ +void bar() {} diff --git a/src/test/run-make-fulldeps/manual-link/foo.c b/src/test/run-make-fulldeps/manual-link/foo.c new file mode 100644 index 000000000..e42599986 --- /dev/null +++ b/src/test/run-make-fulldeps/manual-link/foo.c @@ -0,0 +1 @@ +void bar() {} diff --git a/src/test/run-make-fulldeps/manual-link/foo.rs b/src/test/run-make-fulldeps/manual-link/foo.rs new file mode 100644 index 000000000..c1f28236f --- /dev/null +++ b/src/test/run-make-fulldeps/manual-link/foo.rs @@ -0,0 +1,11 @@ +#![crate_type = "rlib"] + +extern "C" { + fn bar(); +} + +pub fn foo() { + unsafe { + bar(); + } +} diff --git a/src/test/run-make-fulldeps/manual-link/main.rs b/src/test/run-make-fulldeps/manual-link/main.rs new file mode 100644 index 000000000..fe35f1f8e --- /dev/null +++ b/src/test/run-make-fulldeps/manual-link/main.rs @@ -0,0 +1,5 @@ +extern crate foo; + +fn main() { + foo::foo(); +} diff --git a/src/test/run-make-fulldeps/many-crates-but-no-match/Makefile b/src/test/run-make-fulldeps/many-crates-but-no-match/Makefile new file mode 100644 index 000000000..e7268311b --- /dev/null +++ b/src/test/run-make-fulldeps/many-crates-but-no-match/Makefile @@ -0,0 +1,35 @@ +-include ../tools.mk + +# Modelled after ui/changing-crates.rs test, but this one puts +# more than one (mismatching) candidate crate into the search path, +# which did not appear directly expressible in UI testing infrastructure. +# +# Note that we move the built libraries into target direcrtories rather than +# use the `--out-dir` option because the `../tools.mk` file already bakes a +# use of `--out-dir` into the definition of $(RUSTC). + +A1=$(TMPDIR)/a1 +A2=$(TMPDIR)/a2 +A3=$(TMPDIR)/a3 + +# A hack to match distinct lines of output from a single run. +LOG=$(TMPDIR)/log.txt + +all: + mkdir -p $(A1) $(A2) $(A3) + $(RUSTC) --crate-type=rlib crateA1.rs + mv $(TMPDIR)/$(call RLIB_GLOB,crateA) $(A1) + $(RUSTC) --crate-type=rlib -L $(A1) crateB.rs + $(RUSTC) --crate-type=rlib crateA2.rs + mv $(TMPDIR)/$(call RLIB_GLOB,crateA) $(A2) + $(RUSTC) --crate-type=rlib crateA3.rs + mv $(TMPDIR)/$(call RLIB_GLOB,crateA) $(A3) + # Ensure crateC fails to compile since A1 is "missing" and A2/A3 hashes do not match + $(RUSTC) -L $(A2) -L $(A3) crateC.rs >$(LOG) 2>&1 || true + $(CGREP) \ + 'found possibly newer version of crate `crateA` which `crateB` depends on' \ + 'note: perhaps that crate needs to be recompiled?' \ + 'crate `crateA`:' \ + 'crate `crateB`:' \ + < $(LOG) + # the 'crate `crateA`' will match two entries. diff --git a/src/test/run-make-fulldeps/many-crates-but-no-match/crateA1.rs b/src/test/run-make-fulldeps/many-crates-but-no-match/crateA1.rs new file mode 100644 index 000000000..3fed5a38e --- /dev/null +++ b/src/test/run-make-fulldeps/many-crates-but-no-match/crateA1.rs @@ -0,0 +1,4 @@ +#![crate_name="crateA"] + +// Base crate +pub fn func<T>() {} diff --git a/src/test/run-make-fulldeps/many-crates-but-no-match/crateA2.rs b/src/test/run-make-fulldeps/many-crates-but-no-match/crateA2.rs new file mode 100644 index 000000000..8db07a015 --- /dev/null +++ b/src/test/run-make-fulldeps/many-crates-but-no-match/crateA2.rs @@ -0,0 +1,4 @@ +#![crate_name="crateA"] + +// Base crate +pub fn func<T>() { println!("hello"); } diff --git a/src/test/run-make-fulldeps/many-crates-but-no-match/crateA3.rs b/src/test/run-make-fulldeps/many-crates-but-no-match/crateA3.rs new file mode 100644 index 000000000..a1e8e40a3 --- /dev/null +++ b/src/test/run-make-fulldeps/many-crates-but-no-match/crateA3.rs @@ -0,0 +1,4 @@ +#![crate_name="crateA"] + +// Base crate +pub fn foo<T>() { println!("world!"); } diff --git a/src/test/run-make-fulldeps/many-crates-but-no-match/crateB.rs b/src/test/run-make-fulldeps/many-crates-but-no-match/crateB.rs new file mode 100644 index 000000000..4ccd65d65 --- /dev/null +++ b/src/test/run-make-fulldeps/many-crates-but-no-match/crateB.rs @@ -0,0 +1 @@ +extern crate crateA; diff --git a/src/test/run-make-fulldeps/many-crates-but-no-match/crateC.rs b/src/test/run-make-fulldeps/many-crates-but-no-match/crateC.rs new file mode 100644 index 000000000..a8b817ec6 --- /dev/null +++ b/src/test/run-make-fulldeps/many-crates-but-no-match/crateC.rs @@ -0,0 +1,3 @@ +extern crate crateB; + +fn main() {} diff --git a/src/test/run-make-fulldeps/metadata-flag-frobs-symbols/Makefile b/src/test/run-make-fulldeps/metadata-flag-frobs-symbols/Makefile new file mode 100644 index 000000000..3ffbba944 --- /dev/null +++ b/src/test/run-make-fulldeps/metadata-flag-frobs-symbols/Makefile @@ -0,0 +1,10 @@ +-include ../tools.mk + +all: + $(RUSTC) foo.rs -C metadata=a -C extra-filename=-a + $(RUSTC) foo.rs -C metadata=b -C extra-filename=-b + $(RUSTC) bar.rs \ + --extern foo1=$(TMPDIR)/libfoo-a.rlib \ + --extern foo2=$(TMPDIR)/libfoo-b.rlib \ + --print link-args + $(call RUN,bar) diff --git a/src/test/run-make-fulldeps/metadata-flag-frobs-symbols/bar.rs b/src/test/run-make-fulldeps/metadata-flag-frobs-symbols/bar.rs new file mode 100644 index 000000000..1e6957a36 --- /dev/null +++ b/src/test/run-make-fulldeps/metadata-flag-frobs-symbols/bar.rs @@ -0,0 +1,8 @@ +extern crate foo1; +extern crate foo2; + +fn main() { + let a = foo1::foo(); + let b = foo2::foo(); + assert!(a as *const _ != b as *const _); +} diff --git a/src/test/run-make-fulldeps/metadata-flag-frobs-symbols/foo.rs b/src/test/run-make-fulldeps/metadata-flag-frobs-symbols/foo.rs new file mode 100644 index 000000000..696aed2fa --- /dev/null +++ b/src/test/run-make-fulldeps/metadata-flag-frobs-symbols/foo.rs @@ -0,0 +1,6 @@ +#![crate_name = "foo"] +#![crate_type = "rlib"] + +static FOO: usize = 3; + +pub fn foo() -> &'static usize { &FOO } diff --git a/src/test/run-make-fulldeps/min-global-align/Makefile b/src/test/run-make-fulldeps/min-global-align/Makefile new file mode 100644 index 000000000..621027470 --- /dev/null +++ b/src/test/run-make-fulldeps/min-global-align/Makefile @@ -0,0 +1,22 @@ +-include ../tools.mk + +# only-linux + +# This tests ensure that global variables respect the target minimum alignment. +# The three bools `STATIC_BOOL`, `STATIC_MUT_BOOL`, and `CONST_BOOL` all have +# type-alignment of 1, but some targets require greater global alignment. + +SRC = min_global_align.rs +LL = $(TMPDIR)/min_global_align.ll + +all: +# Most targets are happy with default alignment -- take i686 for example. +ifeq ($(filter x86,$(LLVM_COMPONENTS)),x86) + $(RUSTC) --target=i686-unknown-linux-gnu --emit=llvm-ir $(SRC) + [ "$$(grep -c 'align 1' "$(LL)")" -eq "3" ] +endif +# SystemZ requires even alignment for PC-relative addressing. +ifeq ($(filter systemz,$(LLVM_COMPONENTS)),systemz) + $(RUSTC) --target=s390x-unknown-linux-gnu --emit=llvm-ir $(SRC) + [ "$$(grep -c 'align 2' "$(LL)")" -eq "3" ] +endif diff --git a/src/test/run-make-fulldeps/min-global-align/min_global_align.rs b/src/test/run-make-fulldeps/min-global-align/min_global_align.rs new file mode 100644 index 000000000..135792e93 --- /dev/null +++ b/src/test/run-make-fulldeps/min-global-align/min_global_align.rs @@ -0,0 +1,32 @@ +#![feature(no_core, lang_items)] +#![crate_type = "rlib"] +#![no_core] + +pub static STATIC_BOOL: bool = true; + +pub static mut STATIC_MUT_BOOL: bool = true; + +const CONST_BOOL: bool = true; +pub static CONST_BOOL_REF: &'static bool = &CONST_BOOL; + +#[lang = "sized"] +trait Sized {} + +#[lang = "copy"] +trait Copy {} +impl Copy for bool {} +impl Copy for &bool {} + +#[lang = "freeze"] +trait Freeze {} + +// No `UnsafeCell`, so everything is `Freeze`. +impl<T: ?Sized> Freeze for T {} + +#[lang = "sync"] +trait Sync {} +impl Sync for bool {} +impl Sync for &'static bool {} + +#[lang = "drop_in_place"] +pub unsafe fn drop_in_place<T: ?Sized>(_: *mut T) {} diff --git a/src/test/run-make-fulldeps/mingw-export-call-convention/Makefile b/src/test/run-make-fulldeps/mingw-export-call-convention/Makefile new file mode 100644 index 000000000..4a60059cc --- /dev/null +++ b/src/test/run-make-fulldeps/mingw-export-call-convention/Makefile @@ -0,0 +1,9 @@ +include ../tools.mk + +# only-windows-gnu + +all: + $(RUSTC) foo.rs + # FIXME: we should make sure __stdcall calling convention is used here + # but that only works with LLD right now + nm -g "$(call IMPLIB,foo)" | $(CGREP) bar diff --git a/src/test/run-make-fulldeps/mingw-export-call-convention/foo.rs b/src/test/run-make-fulldeps/mingw-export-call-convention/foo.rs new file mode 100644 index 000000000..1fec00311 --- /dev/null +++ b/src/test/run-make-fulldeps/mingw-export-call-convention/foo.rs @@ -0,0 +1,4 @@ +#![crate_type = "cdylib"] + +#[no_mangle] +pub extern "system" fn bar() {} diff --git a/src/test/run-make-fulldeps/mismatching-target-triples/Makefile b/src/test/run-make-fulldeps/mismatching-target-triples/Makefile new file mode 100644 index 000000000..1636e41b0 --- /dev/null +++ b/src/test/run-make-fulldeps/mismatching-target-triples/Makefile @@ -0,0 +1,11 @@ +-include ../tools.mk + +# Issue #10814 +# +# these are no_std to avoid having to have the standard library or any +# linkers/assemblers for the relevant platform + +all: + $(RUSTC) foo.rs --target=i686-unknown-linux-gnu + $(RUSTC) bar.rs --target=x86_64-unknown-linux-gnu 2>&1 \ + | $(CGREP) 'couldn'"'"'t find crate `foo` with expected target triple x86_64-unknown-linux-gnu' diff --git a/src/test/run-make-fulldeps/mismatching-target-triples/bar.rs b/src/test/run-make-fulldeps/mismatching-target-triples/bar.rs new file mode 100644 index 000000000..b2c2fc1c4 --- /dev/null +++ b/src/test/run-make-fulldeps/mismatching-target-triples/bar.rs @@ -0,0 +1,3 @@ +#![feature(no_core)] +#![no_core] +extern crate foo; diff --git a/src/test/run-make-fulldeps/mismatching-target-triples/foo.rs b/src/test/run-make-fulldeps/mismatching-target-triples/foo.rs new file mode 100644 index 000000000..6fa054914 --- /dev/null +++ b/src/test/run-make-fulldeps/mismatching-target-triples/foo.rs @@ -0,0 +1,3 @@ +#![feature(no_core)] +#![no_core] +#![crate_type = "lib"] diff --git a/src/test/run-make-fulldeps/missing-crate-dependency/Makefile b/src/test/run-make-fulldeps/missing-crate-dependency/Makefile new file mode 100644 index 000000000..b5a5bf492 --- /dev/null +++ b/src/test/run-make-fulldeps/missing-crate-dependency/Makefile @@ -0,0 +1,9 @@ +-include ../tools.mk + +all: + $(RUSTC) --crate-type=rlib crateA.rs + $(RUSTC) --crate-type=rlib crateB.rs + $(call REMOVE_RLIBS,crateA) + # Ensure crateC fails to compile since dependency crateA is missing + $(RUSTC) crateC.rs 2>&1 | \ + $(CGREP) 'can'"'"'t find crate for `crateA` which `crateB` depends on' diff --git a/src/test/run-make-fulldeps/missing-crate-dependency/crateA.rs b/src/test/run-make-fulldeps/missing-crate-dependency/crateA.rs new file mode 100644 index 000000000..31433cb60 --- /dev/null +++ b/src/test/run-make-fulldeps/missing-crate-dependency/crateA.rs @@ -0,0 +1,2 @@ +// Base crate +pub fn func() {} diff --git a/src/test/run-make-fulldeps/missing-crate-dependency/crateB.rs b/src/test/run-make-fulldeps/missing-crate-dependency/crateB.rs new file mode 100644 index 000000000..4ccd65d65 --- /dev/null +++ b/src/test/run-make-fulldeps/missing-crate-dependency/crateB.rs @@ -0,0 +1 @@ +extern crate crateA; diff --git a/src/test/run-make-fulldeps/missing-crate-dependency/crateC.rs b/src/test/run-make-fulldeps/missing-crate-dependency/crateC.rs new file mode 100644 index 000000000..a8b817ec6 --- /dev/null +++ b/src/test/run-make-fulldeps/missing-crate-dependency/crateC.rs @@ -0,0 +1,3 @@ +extern crate crateB; + +fn main() {} diff --git a/src/test/run-make-fulldeps/mixing-deps/Makefile b/src/test/run-make-fulldeps/mixing-deps/Makefile new file mode 100644 index 000000000..0e52d4a8b --- /dev/null +++ b/src/test/run-make-fulldeps/mixing-deps/Makefile @@ -0,0 +1,7 @@ +-include ../tools.mk + +all: + $(RUSTC) both.rs -C prefer-dynamic + $(RUSTC) dylib.rs -C prefer-dynamic + $(RUSTC) prog.rs + $(call RUN,prog) diff --git a/src/test/run-make-fulldeps/mixing-deps/both.rs b/src/test/run-make-fulldeps/mixing-deps/both.rs new file mode 100644 index 000000000..6a5818763 --- /dev/null +++ b/src/test/run-make-fulldeps/mixing-deps/both.rs @@ -0,0 +1,4 @@ +#![crate_type = "rlib"] +#![crate_type = "dylib"] + +pub static foo: isize = 4; diff --git a/src/test/run-make-fulldeps/mixing-deps/dylib.rs b/src/test/run-make-fulldeps/mixing-deps/dylib.rs new file mode 100644 index 000000000..88976d5b6 --- /dev/null +++ b/src/test/run-make-fulldeps/mixing-deps/dylib.rs @@ -0,0 +1,6 @@ +#![crate_type = "dylib"] +extern crate both; + +use std::mem; + +pub fn addr() -> usize { unsafe { mem::transmute(&both::foo) } } diff --git a/src/test/run-make-fulldeps/mixing-deps/prog.rs b/src/test/run-make-fulldeps/mixing-deps/prog.rs new file mode 100644 index 000000000..188981dc1 --- /dev/null +++ b/src/test/run-make-fulldeps/mixing-deps/prog.rs @@ -0,0 +1,9 @@ +extern crate dylib; +extern crate both; + +use std::mem; + +fn main() { + assert_eq!(unsafe { mem::transmute::<&isize, usize>(&both::foo) }, + dylib::addr()); +} diff --git a/src/test/run-make-fulldeps/mixing-formats/Makefile b/src/test/run-make-fulldeps/mixing-formats/Makefile new file mode 100644 index 000000000..48257669b --- /dev/null +++ b/src/test/run-make-fulldeps/mixing-formats/Makefile @@ -0,0 +1,74 @@ +-include ../tools.mk + +# Testing various mixings of rlibs and dylibs. Makes sure that it's possible to +# link an rlib to a dylib. The dependency tree among the file looks like: +# +# foo +# / \ +# bar1 bar2 +# / \ / +# baz baz2 +# +# This is generally testing the permutations of the foo/bar1/bar2 layer against +# the baz/baz2 layer + +all: + # Building just baz + $(RUSTC) --crate-type=rlib foo.rs + $(RUSTC) --crate-type=dylib bar1.rs -C prefer-dynamic + $(RUSTC) --crate-type=dylib,rlib baz.rs -C prefer-dynamic + $(RUSTC) --crate-type=bin baz.rs + rm $(TMPDIR)/* + $(RUSTC) --crate-type=dylib foo.rs -C prefer-dynamic + $(RUSTC) --crate-type=rlib bar1.rs + $(RUSTC) --crate-type=dylib,rlib baz.rs -C prefer-dynamic + $(RUSTC) --crate-type=bin baz.rs + rm $(TMPDIR)/* + # Building baz2 + $(RUSTC) --crate-type=rlib foo.rs + $(RUSTC) --crate-type=dylib bar1.rs -C prefer-dynamic + $(RUSTC) --crate-type=dylib bar2.rs -C prefer-dynamic + $(RUSTC) --crate-type=dylib baz2.rs && exit 1 || exit 0 + $(RUSTC) --crate-type=bin baz2.rs && exit 1 || exit 0 + rm $(TMPDIR)/* + $(RUSTC) --crate-type=rlib foo.rs + $(RUSTC) --crate-type=rlib bar1.rs + $(RUSTC) --crate-type=dylib bar2.rs -C prefer-dynamic + $(RUSTC) --crate-type=dylib,rlib baz2.rs + $(RUSTC) --crate-type=bin baz2.rs + rm $(TMPDIR)/* + $(RUSTC) --crate-type=rlib foo.rs + $(RUSTC) --crate-type=dylib bar1.rs -C prefer-dynamic + $(RUSTC) --crate-type=rlib bar2.rs + $(RUSTC) --crate-type=dylib,rlib baz2.rs -C prefer-dynamic + $(RUSTC) --crate-type=bin baz2.rs + rm $(TMPDIR)/* + $(RUSTC) --crate-type=rlib foo.rs + $(RUSTC) --crate-type=rlib bar1.rs + $(RUSTC) --crate-type=rlib bar2.rs + $(RUSTC) --crate-type=dylib,rlib baz2.rs -C prefer-dynamic + $(RUSTC) --crate-type=bin baz2.rs + rm $(TMPDIR)/* + $(RUSTC) --crate-type=dylib foo.rs -C prefer-dynamic + $(RUSTC) --crate-type=rlib bar1.rs + $(RUSTC) --crate-type=rlib bar2.rs + $(RUSTC) --crate-type=dylib,rlib baz2.rs -C prefer-dynamic + $(RUSTC) --crate-type=bin baz2.rs + rm $(TMPDIR)/* + $(RUSTC) --crate-type=dylib foo.rs -C prefer-dynamic + $(RUSTC) --crate-type=dylib bar1.rs -C prefer-dynamic + $(RUSTC) --crate-type=rlib bar2.rs + $(RUSTC) --crate-type=dylib,rlib baz2.rs + $(RUSTC) --crate-type=bin baz2.rs + rm $(TMPDIR)/* + $(RUSTC) --crate-type=dylib foo.rs -C prefer-dynamic + $(RUSTC) --crate-type=rlib bar1.rs + $(RUSTC) --crate-type=dylib bar2.rs -C prefer-dynamic + $(RUSTC) --crate-type=dylib,rlib baz2.rs + $(RUSTC) --crate-type=bin baz2.rs + rm $(TMPDIR)/* + $(RUSTC) --crate-type=dylib foo.rs -C prefer-dynamic + $(RUSTC) --crate-type=dylib bar1.rs -C prefer-dynamic + $(RUSTC) --crate-type=dylib bar2.rs -C prefer-dynamic + $(RUSTC) --crate-type=dylib,rlib baz2.rs + $(RUSTC) --crate-type=bin baz2.rs diff --git a/src/test/run-make-fulldeps/mixing-formats/bar1.rs b/src/test/run-make-fulldeps/mixing-formats/bar1.rs new file mode 100644 index 000000000..49af74e1b --- /dev/null +++ b/src/test/run-make-fulldeps/mixing-formats/bar1.rs @@ -0,0 +1 @@ +extern crate foo; diff --git a/src/test/run-make-fulldeps/mixing-formats/bar2.rs b/src/test/run-make-fulldeps/mixing-formats/bar2.rs new file mode 100644 index 000000000..49af74e1b --- /dev/null +++ b/src/test/run-make-fulldeps/mixing-formats/bar2.rs @@ -0,0 +1 @@ +extern crate foo; diff --git a/src/test/run-make-fulldeps/mixing-formats/baz.rs b/src/test/run-make-fulldeps/mixing-formats/baz.rs new file mode 100644 index 000000000..99a73159e --- /dev/null +++ b/src/test/run-make-fulldeps/mixing-formats/baz.rs @@ -0,0 +1,3 @@ +extern crate bar1; + +fn main() {} diff --git a/src/test/run-make-fulldeps/mixing-formats/baz2.rs b/src/test/run-make-fulldeps/mixing-formats/baz2.rs new file mode 100644 index 000000000..d0fab1e4c --- /dev/null +++ b/src/test/run-make-fulldeps/mixing-formats/baz2.rs @@ -0,0 +1,4 @@ +extern crate bar1; +extern crate bar2; + +fn main() {} diff --git a/src/test/run-make-fulldeps/mixing-formats/foo.rs b/src/test/run-make-fulldeps/mixing-formats/foo.rs new file mode 100644 index 000000000..d11c69f81 --- /dev/null +++ b/src/test/run-make-fulldeps/mixing-formats/foo.rs @@ -0,0 +1 @@ +// intentionally empty diff --git a/src/test/run-make-fulldeps/mixing-libs/Makefile b/src/test/run-make-fulldeps/mixing-libs/Makefile new file mode 100644 index 000000000..babeeef16 --- /dev/null +++ b/src/test/run-make-fulldeps/mixing-libs/Makefile @@ -0,0 +1,9 @@ +-include ../tools.mk + +all: + $(RUSTC) rlib.rs + $(RUSTC) dylib.rs + $(RUSTC) rlib.rs --crate-type=dylib + $(RUSTC) dylib.rs + $(call REMOVE_DYLIBS,rlib) + $(RUSTC) prog.rs && exit 1 || exit 0 diff --git a/src/test/run-make-fulldeps/mixing-libs/dylib.rs b/src/test/run-make-fulldeps/mixing-libs/dylib.rs new file mode 100644 index 000000000..685688750 --- /dev/null +++ b/src/test/run-make-fulldeps/mixing-libs/dylib.rs @@ -0,0 +1,4 @@ +#![crate_type = "dylib"] +extern crate rlib; + +pub fn dylib() { rlib::rlib() } diff --git a/src/test/run-make-fulldeps/mixing-libs/prog.rs b/src/test/run-make-fulldeps/mixing-libs/prog.rs new file mode 100644 index 000000000..14ce5c951 --- /dev/null +++ b/src/test/run-make-fulldeps/mixing-libs/prog.rs @@ -0,0 +1,7 @@ +extern crate dylib; +extern crate rlib; + +fn main() { + dylib::dylib(); + rlib::rlib(); +} diff --git a/src/test/run-make-fulldeps/mixing-libs/rlib.rs b/src/test/run-make-fulldeps/mixing-libs/rlib.rs new file mode 100644 index 000000000..96dcd16bb --- /dev/null +++ b/src/test/run-make-fulldeps/mixing-libs/rlib.rs @@ -0,0 +1,2 @@ +#![crate_type = "rlib"] +pub fn rlib() {} diff --git a/src/test/run-make-fulldeps/msvc-opt-minsize/Makefile b/src/test/run-make-fulldeps/msvc-opt-minsize/Makefile new file mode 100644 index 000000000..1095a047d --- /dev/null +++ b/src/test/run-make-fulldeps/msvc-opt-minsize/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: + $(RUSTC) foo.rs -Copt-level=z 2>&1 + $(call RUN,foo) diff --git a/src/test/run-make-fulldeps/msvc-opt-minsize/foo.rs b/src/test/run-make-fulldeps/msvc-opt-minsize/foo.rs new file mode 100644 index 000000000..3f5496c08 --- /dev/null +++ b/src/test/run-make-fulldeps/msvc-opt-minsize/foo.rs @@ -0,0 +1,19 @@ +#![feature(test)] +extern crate test; + +fn foo(x: i32, y: i32) -> i64 { + (x + y) as i64 +} + +#[inline(never)] +fn bar() { + let _f = Box::new(0); + // This call used to trigger an LLVM bug in opt-level z where the base + // pointer gets corrupted, see issue #45034 + let y: fn(i32, i32) -> i64 = test::black_box(foo); + test::black_box(y(1, 2)); +} + +fn main() { + bar(); +} diff --git a/src/test/run-make-fulldeps/multiple-emits/Makefile b/src/test/run-make-fulldeps/multiple-emits/Makefile new file mode 100644 index 000000000..e12642283 --- /dev/null +++ b/src/test/run-make-fulldeps/multiple-emits/Makefile @@ -0,0 +1,7 @@ +-include ../tools.mk + +all: + $(RUSTC) foo.rs --emit=asm,llvm-ir -o $(TMPDIR)/out 2>&1 + rm $(TMPDIR)/out.ll $(TMPDIR)/out.s + $(RUSTC) foo.rs --emit=asm,llvm-ir -o $(TMPDIR)/out2.ext 2>&1 + rm $(TMPDIR)/out2.ll $(TMPDIR)/out2.s diff --git a/src/test/run-make-fulldeps/multiple-emits/foo.rs b/src/test/run-make-fulldeps/multiple-emits/foo.rs new file mode 100644 index 000000000..f328e4d9d --- /dev/null +++ b/src/test/run-make-fulldeps/multiple-emits/foo.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/src/test/run-make-fulldeps/no-builtins-lto/Makefile b/src/test/run-make-fulldeps/no-builtins-lto/Makefile new file mode 100644 index 000000000..2e41be39d --- /dev/null +++ b/src/test/run-make-fulldeps/no-builtins-lto/Makefile @@ -0,0 +1,9 @@ +-include ../tools.mk + +all: + # Compile a `#![no_builtins]` rlib crate + $(RUSTC) no_builtins.rs + # Build an executable that depends on that crate using LTO. The no_builtins crate doesn't + # participate in LTO, so its rlib must be explicitly linked into the final binary. Verify this by + # grepping the linker arguments. + $(RUSTC) main.rs -C lto --print link-args | $(CGREP) 'libno_builtins.rlib' diff --git a/src/test/run-make-fulldeps/no-builtins-lto/main.rs b/src/test/run-make-fulldeps/no-builtins-lto/main.rs new file mode 100644 index 000000000..890c999c8 --- /dev/null +++ b/src/test/run-make-fulldeps/no-builtins-lto/main.rs @@ -0,0 +1,3 @@ +extern crate no_builtins; + +fn main() {} diff --git a/src/test/run-make-fulldeps/no-builtins-lto/no_builtins.rs b/src/test/run-make-fulldeps/no-builtins-lto/no_builtins.rs new file mode 100644 index 000000000..5d001031a --- /dev/null +++ b/src/test/run-make-fulldeps/no-builtins-lto/no_builtins.rs @@ -0,0 +1,2 @@ +#![crate_type = "lib"] +#![no_builtins] diff --git a/src/test/run-make-fulldeps/no-duplicate-libs/Makefile b/src/test/run-make-fulldeps/no-duplicate-libs/Makefile new file mode 100644 index 000000000..13d8366c6 --- /dev/null +++ b/src/test/run-make-fulldeps/no-duplicate-libs/Makefile @@ -0,0 +1,10 @@ +-include ../tools.mk + +ifdef IS_MSVC +# FIXME(#27979) +all: +else +all: $(call STATICLIB,foo) $(call STATICLIB,bar) + $(RUSTC) main.rs + $(call RUN,main) +endif diff --git a/src/test/run-make-fulldeps/no-duplicate-libs/bar.c b/src/test/run-make-fulldeps/no-duplicate-libs/bar.c new file mode 100644 index 000000000..e36952657 --- /dev/null +++ b/src/test/run-make-fulldeps/no-duplicate-libs/bar.c @@ -0,0 +1,5 @@ +extern void foo(); + +void bar() { + foo(); +} diff --git a/src/test/run-make-fulldeps/no-duplicate-libs/foo.c b/src/test/run-make-fulldeps/no-duplicate-libs/foo.c new file mode 100644 index 000000000..85e6cd8c3 --- /dev/null +++ b/src/test/run-make-fulldeps/no-duplicate-libs/foo.c @@ -0,0 +1 @@ +void foo() {} diff --git a/src/test/run-make-fulldeps/no-duplicate-libs/main.rs b/src/test/run-make-fulldeps/no-duplicate-libs/main.rs new file mode 100644 index 000000000..b25ef35ad --- /dev/null +++ b/src/test/run-make-fulldeps/no-duplicate-libs/main.rs @@ -0,0 +1,10 @@ +#[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 "C" { + fn bar(); +} + +fn main() { + unsafe { bar() } +} diff --git a/src/test/run-make-fulldeps/no-intermediate-extras/Makefile b/src/test/run-make-fulldeps/no-intermediate-extras/Makefile new file mode 100644 index 000000000..258cbf04c --- /dev/null +++ b/src/test/run-make-fulldeps/no-intermediate-extras/Makefile @@ -0,0 +1,7 @@ +# Regression test for issue #10973 + +-include ../tools.mk + +all: + $(RUSTC) --crate-type=rlib --test foo.rs + rm $(TMPDIR)/foo.bc && exit 1 || exit 0 diff --git a/src/test/run-make-fulldeps/no-intermediate-extras/foo.rs b/src/test/run-make-fulldeps/no-intermediate-extras/foo.rs new file mode 100644 index 000000000..d11c69f81 --- /dev/null +++ b/src/test/run-make-fulldeps/no-intermediate-extras/foo.rs @@ -0,0 +1 @@ +// intentionally empty diff --git a/src/test/run-make-fulldeps/obey-crate-type-flag/Makefile b/src/test/run-make-fulldeps/obey-crate-type-flag/Makefile new file mode 100644 index 000000000..903349152 --- /dev/null +++ b/src/test/run-make-fulldeps/obey-crate-type-flag/Makefile @@ -0,0 +1,13 @@ +-include ../tools.mk + +# check that rustc builds all crate_type attributes +# delete rlib +# delete whatever dylib is made for this system +# check that rustc only builds --crate-type flags, ignoring attributes +# fail if an rlib was built +all: + $(RUSTC) test.rs + $(call REMOVE_RLIBS,test) + $(call REMOVE_DYLIBS,test) + $(RUSTC) --crate-type dylib test.rs + $(call REMOVE_RLIBS,test) && exit 1 || exit 0 diff --git a/src/test/run-make-fulldeps/obey-crate-type-flag/test.rs b/src/test/run-make-fulldeps/obey-crate-type-flag/test.rs new file mode 100644 index 000000000..8a768f9de --- /dev/null +++ b/src/test/run-make-fulldeps/obey-crate-type-flag/test.rs @@ -0,0 +1,2 @@ +#![crate_type = "rlib"] +#![crate_type = "dylib"] diff --git a/src/test/run-make-fulldeps/obtain-borrowck/Makefile b/src/test/run-make-fulldeps/obtain-borrowck/Makefile new file mode 100644 index 000000000..223993125 --- /dev/null +++ b/src/test/run-make-fulldeps/obtain-borrowck/Makefile @@ -0,0 +1,26 @@ +include ../tools.mk + +# This example shows how to implement a rustc driver that retrieves MIR bodies +# together with the borrow checker information. + +# How to run this +# $ ./x.py test src/test/run-make-fulldeps/obtain-borrowck + +DRIVER_BINARY := "$(TMPDIR)"/driver +SYSROOT := $(shell $(RUSTC) --print sysroot) + +ifdef IS_WINDOWS +LIBSTD := -L "$(SYSROOT)\\lib\\rustlib\\$(TARGET)\\lib" +else +LIBSTD := +endif + +all: + $(RUSTC) driver.rs -o "$(DRIVER_BINARY)" + $(TARGET_RPATH_ENV) "$(DRIVER_BINARY)" --sysroot $(SYSROOT) $(LIBSTD) test.rs -o "$(TMPDIR)/driver_test" > "$(TMPDIR)"/output.stdout + +ifdef RUSTC_BLESS_TEST + cp "$(TMPDIR)"/output.stdout output.stdout +else + $(DIFF) output.stdout "$(TMPDIR)"/output.stdout +endif diff --git a/src/test/run-make-fulldeps/obtain-borrowck/driver.rs b/src/test/run-make-fulldeps/obtain-borrowck/driver.rs new file mode 100644 index 000000000..8f78bda03 --- /dev/null +++ b/src/test/run-make-fulldeps/obtain-borrowck/driver.rs @@ -0,0 +1,161 @@ +#![feature(rustc_private)] + +//! This program implements a rustc driver that retrieves MIR bodies with +//! borrowck information. This cannot be done in a straightforward way because +//! `get_body_with_borrowck_facts`–the function for retrieving a MIR body with +//! borrowck facts–can panic if the body is stolen before it is invoked. +//! Therefore, the driver overrides `mir_borrowck` query (this is done in the +//! `config` callback), which retrieves the body that is about to be borrow +//! checked and stores it in a thread local `MIR_BODIES`. Then, `after_analysis` +//! callback triggers borrow checking of all MIR bodies by retrieving +//! `optimized_mir` and pulls out the MIR bodies with the borrowck information +//! from the thread local storage. + +extern crate rustc_borrowck; +extern crate rustc_driver; +extern crate rustc_hir; +extern crate rustc_interface; +extern crate rustc_middle; +extern crate rustc_session; + +use rustc_borrowck::consumers::BodyWithBorrowckFacts; +use rustc_driver::Compilation; +use rustc_hir::def_id::LocalDefId; +use rustc_hir::def::DefKind; +use rustc_interface::interface::Compiler; +use rustc_interface::{Config, Queries}; +use rustc_middle::ty::query::query_values::mir_borrowck; +use rustc_middle::ty::query::{ExternProviders, Providers}; +use rustc_middle::ty::{self, TyCtxt}; +use rustc_session::Session; +use std::cell::RefCell; +use std::collections::HashMap; +use std::thread_local; + +fn main() { + let exit_code = rustc_driver::catch_with_exit_code(move || { + let mut rustc_args: Vec<_> = std::env::args().collect(); + // We must pass -Zpolonius so that the borrowck information is computed. + rustc_args.push("-Zpolonius".to_owned()); + let mut callbacks = CompilerCalls::default(); + // Call the Rust compiler with our callbacks. + rustc_driver::RunCompiler::new(&rustc_args, &mut callbacks).run() + }); + std::process::exit(exit_code); +} + +#[derive(Default)] +pub struct CompilerCalls; + +impl rustc_driver::Callbacks for CompilerCalls { + // In this callback we override the mir_borrowck query. + fn config(&mut self, config: &mut Config) { + assert!(config.override_queries.is_none()); + config.override_queries = Some(override_queries); + } + + // In this callback we trigger borrow checking of all functions and obtain + // the result. + fn after_analysis<'tcx>( + &mut self, + compiler: &Compiler, + queries: &'tcx Queries<'tcx>, + ) -> Compilation { + compiler.session().abort_if_errors(); + queries.global_ctxt().unwrap().peek_mut().enter(|tcx| { + // Collect definition ids of MIR bodies. + let hir = tcx.hir(); + let mut bodies = Vec::new(); + + let crate_items = tcx.hir_crate_items(()); + for id in crate_items.items() { + if matches!(tcx.def_kind(id.def_id), DefKind::Fn) { + bodies.push(id.def_id); + } + } + + for id in crate_items.trait_items() { + if matches!(tcx.def_kind(id.def_id), DefKind::AssocFn) { + let trait_item = hir.trait_item(id); + if let rustc_hir::TraitItemKind::Fn(_, trait_fn) = &trait_item.kind { + if let rustc_hir::TraitFn::Provided(_) = trait_fn { + bodies.push(trait_item.def_id); + } + } + } + } + + for id in crate_items.impl_items() { + if matches!(tcx.def_kind(id.def_id), DefKind::AssocFn) { + bodies.push(id.def_id); + } + } + + // Trigger borrow checking of all bodies. + for def_id in bodies { + let _ = tcx.optimized_mir(def_id); + } + + // See what bodies were borrow checked. + let mut bodies = get_bodies(tcx); + bodies.sort_by(|(def_id1, _), (def_id2, _)| def_id1.cmp(def_id2)); + println!("Bodies retrieved for:"); + for (def_id, body) in bodies { + println!("{}", def_id); + assert!(body.input_facts.cfg_edge.len() > 0); + } + }); + + Compilation::Continue + } +} + +fn override_queries(_session: &Session, local: &mut Providers, _external: &mut ExternProviders) { + local.mir_borrowck = mir_borrowck; +} + +// Since mir_borrowck does not have access to any other state, we need to use a +// thread-local for storing the obtained MIR bodies. +// +// Note: We are using 'static lifetime here, which is in general unsound. +// Unfortunately, that is the only lifetime allowed here. Our use is safe +// because we cast it back to `'tcx` before using. +thread_local! { + pub static MIR_BODIES: + RefCell<HashMap<LocalDefId, BodyWithBorrowckFacts<'static>>> = + RefCell::new(HashMap::new()); +} + +fn mir_borrowck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> mir_borrowck<'tcx> { + let body_with_facts = rustc_borrowck::consumers::get_body_with_borrowck_facts( + tcx, + ty::WithOptConstParam::unknown(def_id), + ); + // SAFETY: The reader casts the 'static lifetime to 'tcx before using it. + let body_with_facts: BodyWithBorrowckFacts<'static> = + unsafe { std::mem::transmute(body_with_facts) }; + MIR_BODIES.with(|state| { + let mut map = state.borrow_mut(); + assert!(map.insert(def_id, body_with_facts).is_none()); + }); + let mut providers = Providers::default(); + rustc_borrowck::provide(&mut providers); + let original_mir_borrowck = providers.mir_borrowck; + original_mir_borrowck(tcx, def_id) +} + +/// Pull MIR bodies stored in the thread-local. +fn get_bodies<'tcx>(tcx: TyCtxt<'tcx>) -> Vec<(String, BodyWithBorrowckFacts<'tcx>)> { + MIR_BODIES.with(|state| { + let mut map = state.borrow_mut(); + map.drain() + .map(|(def_id, body)| { + let def_path = tcx.def_path(def_id.to_def_id()); + // SAFETY: For soundness we need to ensure that the bodies have + // the same lifetime (`'tcx`), which they had before they were + // stored in the thread local. + (def_path.to_string_no_crate_verbose(), unsafe { std::mem::transmute(body) }) + }) + .collect() + }) +} diff --git a/src/test/run-make-fulldeps/obtain-borrowck/output.stdout b/src/test/run-make-fulldeps/obtain-borrowck/output.stdout new file mode 100644 index 000000000..e011622e6 --- /dev/null +++ b/src/test/run-make-fulldeps/obtain-borrowck/output.stdout @@ -0,0 +1,8 @@ +Bodies retrieved for: +::X::provided +::foo +::main +::main::{constant#0} +::{impl#0}::new +::{impl#1}::provided +::{impl#1}::required diff --git a/src/test/run-make-fulldeps/obtain-borrowck/test.rs b/src/test/run-make-fulldeps/obtain-borrowck/test.rs new file mode 100644 index 000000000..f7b4b41fe --- /dev/null +++ b/src/test/run-make-fulldeps/obtain-borrowck/test.rs @@ -0,0 +1,32 @@ +trait X { + fn provided(&self) -> usize { + 5 + } + fn required(&self) -> u32; +} + +struct Bar; + +impl Bar { + fn new() -> Self { + Self + } +} + +impl X for Bar { + fn provided(&self) -> usize { + 1 + } + fn required(&self) -> u32 { + 7 + } +} + +const fn foo() -> usize { + 1 +} + +fn main() { + let bar: [Bar; foo()] = [Bar::new()]; + assert_eq!(bar[0].provided(), foo()); +} diff --git a/src/test/run-make-fulldeps/output-filename-conflicts-with-directory/Makefile b/src/test/run-make-fulldeps/output-filename-conflicts-with-directory/Makefile new file mode 100644 index 000000000..74e5dcfcf --- /dev/null +++ b/src/test/run-make-fulldeps/output-filename-conflicts-with-directory/Makefile @@ -0,0 +1,7 @@ +-include ../tools.mk + +all: + cp foo.rs $(TMPDIR)/foo.rs + mkdir $(TMPDIR)/foo + $(RUSTC) $(TMPDIR)/foo.rs -o $(TMPDIR)/foo 2>&1 \ + | $(CGREP) -e "the generated executable for the input file \".*foo\.rs\" conflicts with the existing directory \".*foo\"" diff --git a/src/test/run-make-fulldeps/output-filename-conflicts-with-directory/foo.rs b/src/test/run-make-fulldeps/output-filename-conflicts-with-directory/foo.rs new file mode 100644 index 000000000..f328e4d9d --- /dev/null +++ b/src/test/run-make-fulldeps/output-filename-conflicts-with-directory/foo.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/src/test/run-make-fulldeps/output-filename-overwrites-input/Makefile b/src/test/run-make-fulldeps/output-filename-overwrites-input/Makefile new file mode 100644 index 000000000..6377038b7 --- /dev/null +++ b/src/test/run-make-fulldeps/output-filename-overwrites-input/Makefile @@ -0,0 +1,13 @@ +-include ../tools.mk + +all: + cp foo.rs $(TMPDIR)/foo + $(RUSTC) $(TMPDIR)/foo -o $(TMPDIR)/foo 2>&1 \ + | $(CGREP) -e "the input file \".*foo\" would be overwritten by the generated executable" + cp bar.rs $(TMPDIR)/bar.rlib + $(RUSTC) $(TMPDIR)/bar.rlib -o $(TMPDIR)/bar.rlib 2>&1 \ + | $(CGREP) -e "the input file \".*bar.rlib\" would be overwritten by the generated executable" + $(RUSTC) foo.rs 2>&1 && $(RUSTC) -Z ls $(TMPDIR)/foo 2>&1 + cp foo.rs $(TMPDIR)/foo.rs + $(RUSTC) $(TMPDIR)/foo.rs -o $(TMPDIR)/foo.rs 2>&1 \ + | $(CGREP) -e "the input file \".*foo.rs\" would be overwritten by the generated executable" diff --git a/src/test/run-make-fulldeps/output-filename-overwrites-input/bar.rs b/src/test/run-make-fulldeps/output-filename-overwrites-input/bar.rs new file mode 100644 index 000000000..83be6e807 --- /dev/null +++ b/src/test/run-make-fulldeps/output-filename-overwrites-input/bar.rs @@ -0,0 +1 @@ +#![crate_type = "lib"] diff --git a/src/test/run-make-fulldeps/output-filename-overwrites-input/foo.rs b/src/test/run-make-fulldeps/output-filename-overwrites-input/foo.rs new file mode 100644 index 000000000..f328e4d9d --- /dev/null +++ b/src/test/run-make-fulldeps/output-filename-overwrites-input/foo.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/src/test/run-make-fulldeps/output-type-permutations/Makefile b/src/test/run-make-fulldeps/output-type-permutations/Makefile new file mode 100644 index 000000000..b6e0cbaf5 --- /dev/null +++ b/src/test/run-make-fulldeps/output-type-permutations/Makefile @@ -0,0 +1,146 @@ +-include ../tools.mk + +all: + $(RUSTC) foo.rs --crate-type=rlib,dylib,staticlib + $(call REMOVE_RLIBS,bar) + $(call REMOVE_DYLIBS,bar) + rm $(call STATICLIB,bar) + rm -f $(TMPDIR)/{lib,}bar.{dll.exp,dll.lib,pdb,dll.a} + # Check that $(TMPDIR) is empty. + [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] + + $(RUSTC) foo.rs --crate-type=bin + rm $(TMPDIR)/$(call BIN,bar) + rm -f $(TMPDIR)/bar.pdb + [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] + + $(RUSTC) foo.rs --emit=asm,llvm-ir,llvm-bc,obj,link + rm $(TMPDIR)/bar.ll + rm $(TMPDIR)/bar.bc + rm $(TMPDIR)/bar.s + rm $(TMPDIR)/bar.o + rm $(TMPDIR)/$(call BIN,bar) + rm -f $(TMPDIR)/bar.pdb + [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] + + $(RUSTC) foo.rs --emit asm -o $(TMPDIR)/foo + rm $(TMPDIR)/foo + $(RUSTC) foo.rs --emit asm=$(TMPDIR)/foo + rm $(TMPDIR)/foo + $(RUSTC) foo.rs --emit=asm=$(TMPDIR)/foo + rm $(TMPDIR)/foo + [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] + + $(RUSTC) foo.rs --emit llvm-bc -o $(TMPDIR)/foo + rm $(TMPDIR)/foo + $(RUSTC) foo.rs --emit llvm-bc=$(TMPDIR)/foo + rm $(TMPDIR)/foo + $(RUSTC) foo.rs --emit=llvm-bc=$(TMPDIR)/foo + rm $(TMPDIR)/foo + [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] + + $(RUSTC) foo.rs --emit llvm-ir -o $(TMPDIR)/foo + rm $(TMPDIR)/foo + $(RUSTC) foo.rs --emit llvm-ir=$(TMPDIR)/foo + rm $(TMPDIR)/foo + $(RUSTC) foo.rs --emit=llvm-ir=$(TMPDIR)/foo + rm $(TMPDIR)/foo + [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] + + $(RUSTC) foo.rs --emit obj -o $(TMPDIR)/foo + rm $(TMPDIR)/foo + $(RUSTC) foo.rs --emit obj=$(TMPDIR)/foo + rm $(TMPDIR)/foo + $(RUSTC) foo.rs --emit=obj=$(TMPDIR)/foo + rm $(TMPDIR)/foo + [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] + + $(RUSTC) foo.rs --emit link -o $(TMPDIR)/$(call BIN,foo) + rm $(TMPDIR)/$(call BIN,foo) + $(RUSTC) foo.rs --emit link=$(TMPDIR)/$(call BIN,foo) + rm $(TMPDIR)/$(call BIN,foo) + $(RUSTC) foo.rs --emit=link=$(TMPDIR)/$(call BIN,foo) + rm $(TMPDIR)/$(call BIN,foo) + rm -f $(TMPDIR)/foo.pdb + [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] + + $(RUSTC) foo.rs --crate-type=rlib -o $(TMPDIR)/foo + rm $(TMPDIR)/foo + $(RUSTC) foo.rs --crate-type=rlib --emit link=$(TMPDIR)/foo + rm $(TMPDIR)/foo + $(RUSTC) foo.rs --crate-type=rlib --emit=link=$(TMPDIR)/foo + rm $(TMPDIR)/foo + [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] + + $(RUSTC) foo.rs --crate-type=dylib -o $(TMPDIR)/$(call BIN,foo) + rm $(TMPDIR)/$(call BIN,foo) + $(RUSTC) foo.rs --crate-type=dylib --emit link=$(TMPDIR)/$(call BIN,foo) + rm $(TMPDIR)/$(call BIN,foo) + $(RUSTC) foo.rs --crate-type=dylib --emit=link=$(TMPDIR)/$(call BIN,foo) + rm $(TMPDIR)/$(call BIN,foo) + rm -f $(TMPDIR)/{lib,}foo.{dll.exp,dll.lib,pdb,dll.a,exe.a} + [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] || (ls -1 $(TMPDIR) && exit 1) + + $(RUSTC) foo.rs --crate-type=staticlib -o $(TMPDIR)/foo + rm $(TMPDIR)/foo + $(RUSTC) foo.rs --crate-type=staticlib --emit link=$(TMPDIR)/foo + rm $(TMPDIR)/foo + $(RUSTC) foo.rs --crate-type=staticlib --emit=link=$(TMPDIR)/foo + rm $(TMPDIR)/foo + [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] + + $(RUSTC) foo.rs --crate-type=bin -o $(TMPDIR)/$(call BIN,foo) + rm $(TMPDIR)/$(call BIN,foo) + $(RUSTC) foo.rs --crate-type=bin --emit link=$(TMPDIR)/$(call BIN,foo) + rm $(TMPDIR)/$(call BIN,foo) + $(RUSTC) foo.rs --crate-type=bin --emit=link=$(TMPDIR)/$(call BIN,foo) + rm $(TMPDIR)/$(call BIN,foo) + rm -f $(TMPDIR)/foo.pdb + [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] + + $(RUSTC) foo.rs --emit llvm-ir=$(TMPDIR)/ir \ + --emit link \ + --crate-type=rlib + rm $(TMPDIR)/ir + rm $(TMPDIR)/libbar.rlib + [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] + + $(RUSTC) foo.rs --emit asm=$(TMPDIR)/asm \ + --emit llvm-ir=$(TMPDIR)/ir \ + --emit llvm-bc=$(TMPDIR)/bc \ + --emit obj=$(TMPDIR)/obj \ + --emit link=$(TMPDIR)/link \ + --crate-type=staticlib + rm $(TMPDIR)/asm + rm $(TMPDIR)/ir + rm $(TMPDIR)/bc + rm $(TMPDIR)/obj + rm $(TMPDIR)/link + $(RUSTC) foo.rs --emit=asm=$(TMPDIR)/asm \ + --emit llvm-ir=$(TMPDIR)/ir \ + --emit=llvm-bc=$(TMPDIR)/bc \ + --emit obj=$(TMPDIR)/obj \ + --emit=link=$(TMPDIR)/link \ + --crate-type=staticlib + rm $(TMPDIR)/asm + rm $(TMPDIR)/ir + rm $(TMPDIR)/bc + rm $(TMPDIR)/obj + rm $(TMPDIR)/link + [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] + + $(RUSTC) foo.rs --emit=asm,llvm-ir,llvm-bc,obj,link --crate-type=staticlib + rm $(TMPDIR)/bar.ll + rm $(TMPDIR)/bar.s + rm $(TMPDIR)/bar.o + rm $(call STATICLIB,bar) + mv $(TMPDIR)/bar.bc $(TMPDIR)/foo.bc + # Don't check that the $(TMPDIR) is empty - we left `foo.bc` for later + # comparison. + + $(RUSTC) foo.rs --emit=llvm-bc,link --crate-type=rlib + cmp $(TMPDIR)/foo.bc $(TMPDIR)/bar.bc + rm $(TMPDIR)/bar.bc + rm $(TMPDIR)/foo.bc + $(call REMOVE_RLIBS,bar) + [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] diff --git a/src/test/run-make-fulldeps/output-type-permutations/foo.rs b/src/test/run-make-fulldeps/output-type-permutations/foo.rs new file mode 100644 index 000000000..f0a2cc6ad --- /dev/null +++ b/src/test/run-make-fulldeps/output-type-permutations/foo.rs @@ -0,0 +1,3 @@ +#![crate_name = "bar"] + +fn main() {} diff --git a/src/test/run-make-fulldeps/output-with-hyphens/Makefile b/src/test/run-make-fulldeps/output-with-hyphens/Makefile new file mode 100644 index 000000000..69a286f0b --- /dev/null +++ b/src/test/run-make-fulldeps/output-with-hyphens/Makefile @@ -0,0 +1,7 @@ +-include ../tools.mk + +all: + $(RUSTC) foo-bar.rs --crate-type bin + [ -f $(TMPDIR)/$(call BIN,foo-bar) ] + $(RUSTC) foo-bar.rs --crate-type lib + [ -f $(TMPDIR)/libfoo_bar.rlib ] diff --git a/src/test/run-make-fulldeps/output-with-hyphens/foo-bar.rs b/src/test/run-make-fulldeps/output-with-hyphens/foo-bar.rs new file mode 100644 index 000000000..f328e4d9d --- /dev/null +++ b/src/test/run-make-fulldeps/output-with-hyphens/foo-bar.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/src/test/run-make-fulldeps/override-aliased-flags/Makefile b/src/test/run-make-fulldeps/override-aliased-flags/Makefile new file mode 100644 index 000000000..bea610eeb --- /dev/null +++ b/src/test/run-make-fulldeps/override-aliased-flags/Makefile @@ -0,0 +1,22 @@ +-include ../tools.mk + +# FIXME: it would be good to check that it's actually the rightmost flags +# that are used when multiple flags are specified, but I can't think of a +# reliable way to check this. + +all: + # Test that `-O` and `-C opt-level` can be specified multiple times. + # The rightmost flag will be used over any previous flags. + $(RUSTC) -O -O main.rs + $(RUSTC) -O -C opt-level=0 main.rs + $(RUSTC) -C opt-level=0 -O main.rs + $(RUSTC) -C opt-level=0 -C opt-level=2 main.rs + $(RUSTC) -C opt-level=2 -C opt-level=0 main.rs + + # Test that `-g` and `-C debuginfo` can be specified multiple times. + # The rightmost flag will be used over any previous flags. + $(RUSTC) -g -g main.rs + $(RUSTC) -g -C debuginfo=0 main.rs + $(RUSTC) -C debuginfo=0 -g main.rs + $(RUSTC) -C debuginfo=0 -C debuginfo=2 main.rs + $(RUSTC) -C debuginfo=2 -C debuginfo=0 main.rs diff --git a/src/test/run-make-fulldeps/override-aliased-flags/main.rs b/src/test/run-make-fulldeps/override-aliased-flags/main.rs new file mode 100644 index 000000000..f328e4d9d --- /dev/null +++ b/src/test/run-make-fulldeps/override-aliased-flags/main.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/src/test/run-make-fulldeps/panic-impl-transitive/Makefile b/src/test/run-make-fulldeps/panic-impl-transitive/Makefile new file mode 100644 index 000000000..1714578b2 --- /dev/null +++ b/src/test/run-make-fulldeps/panic-impl-transitive/Makefile @@ -0,0 +1,7 @@ +-include ../../run-make-fulldeps/tools.mk + +# NOTE we use --emit=llvm-ir to avoid running the linker (linking will fail because there's no main +# in this crate) +all: + $(RUSTC) panic-impl-provider.rs + $(RUSTC) panic-impl-consumer.rs -C panic=abort --emit=llvm-ir -L $(TMPDIR) diff --git a/src/test/run-make-fulldeps/panic-impl-transitive/panic-impl-consumer.rs b/src/test/run-make-fulldeps/panic-impl-transitive/panic-impl-consumer.rs new file mode 100644 index 000000000..82a98b12d --- /dev/null +++ b/src/test/run-make-fulldeps/panic-impl-transitive/panic-impl-consumer.rs @@ -0,0 +1,5 @@ +#![no_std] +#![no_main] + +// this crate provides the `panic_impl` lang item so we don't need to define it here +extern crate panic_impl_provider; diff --git a/src/test/run-make-fulldeps/panic-impl-transitive/panic-impl-provider.rs b/src/test/run-make-fulldeps/panic-impl-transitive/panic-impl-provider.rs new file mode 100644 index 000000000..f1b9873c8 --- /dev/null +++ b/src/test/run-make-fulldeps/panic-impl-transitive/panic-impl-provider.rs @@ -0,0 +1,9 @@ +#![crate_type = "rlib"] +#![no_std] + +use core::panic::PanicInfo; + +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + loop {} +} diff --git a/src/test/run-make-fulldeps/pass-non-c-like-enum-to-c/Makefile b/src/test/run-make-fulldeps/pass-non-c-like-enum-to-c/Makefile new file mode 100644 index 000000000..f3d935786 --- /dev/null +++ b/src/test/run-make-fulldeps/pass-non-c-like-enum-to-c/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: $(call NATIVE_STATICLIB,test) + $(RUSTC) nonclike.rs -L$(TMPDIR) -ltest + $(call RUN,nonclike) diff --git a/src/test/run-make-fulldeps/pass-non-c-like-enum-to-c/nonclike.rs b/src/test/run-make-fulldeps/pass-non-c-like-enum-to-c/nonclike.rs new file mode 100644 index 000000000..517286a86 --- /dev/null +++ b/src/test/run-make-fulldeps/pass-non-c-like-enum-to-c/nonclike.rs @@ -0,0 +1,21 @@ +#[repr(C, u8)] +pub enum TT { + AA(u64, u64), + BB, +} + +#[repr(C,u8)] +pub enum T { + A(u64), + B, +} + +extern "C" { + pub fn t_add(a: T, b: T) -> u64; + pub fn tt_add(a: TT, b: TT) -> u64; +} + +fn main() { + assert_eq!(33, unsafe { tt_add(TT::AA(1,2), TT::AA(10,20)) }); + assert_eq!(11, unsafe { t_add(T::A(1), T::A(10)) }); +} diff --git a/src/test/run-make-fulldeps/pass-non-c-like-enum-to-c/test.c b/src/test/run-make-fulldeps/pass-non-c-like-enum-to-c/test.c new file mode 100644 index 000000000..99511b253 --- /dev/null +++ b/src/test/run-make-fulldeps/pass-non-c-like-enum-to-c/test.c @@ -0,0 +1,85 @@ +#include <stdint.h> + +/* This is the code generated by cbindgen 0.12.1 for the `enum TT` + * type in nonclike.rs . */ +enum TT_Tag { + AA, + BB, +}; +typedef uint8_t TT_Tag; + +typedef struct { + uint64_t _0; + uint64_t _1; +} AA_Body; + +typedef struct { + TT_Tag tag; + union { + AA_Body aa; + }; +} TT; + +/* This is the code generated by cbindgen 0.12.1 for the `enum T` type + * in nonclike.rs . */ +enum T_Tag { + A, + B, +}; +typedef uint8_t T_Tag; + +typedef struct { + uint64_t _0; +} A_Body; + +typedef struct { + T_Tag tag; + union { + A_Body a; + }; +} T; + +uint64_t tt_add(TT a, TT b) { + if (a.tag == AA && b.tag == AA) { + return a.aa._0 + a.aa._1 + b.aa._0 + b.aa._1; + } else if (a.tag == AA) { + return a.aa._0 + a.aa._1; + } else if (b.tag == BB) { + return b.aa._0 + b.aa._1; + } else { + return 0; + } +} + +uint64_t t_add(T a, T b) { + if (a.tag == A && b.tag == A) { + return a.a._0 + b.a._0; + } else if (a.tag == AA) { + return a.a._0; + } else if (b.tag == BB) { + return b.a._0; + } else { + return 0; + } +} + +TT tt_new(uint64_t a, uint64_t b) { + TT tt = { + .tag = AA, + .aa = { + ._0 = a, + ._1 = b, + }, + }; + return tt; +} + +T t_new(uint64_t a) { + T t = { + .tag = A, + .a = { + ._0 = a, + }, + }; + return t; +} diff --git a/src/test/run-make-fulldeps/pgo-branch-weights/Makefile b/src/test/run-make-fulldeps/pgo-branch-weights/Makefile new file mode 100644 index 000000000..9773e3f1f --- /dev/null +++ b/src/test/run-make-fulldeps/pgo-branch-weights/Makefile @@ -0,0 +1,34 @@ +# needs-profiler-support +# ignore-windows-gnu + +# FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works +# properly. Since we only have GCC on the CI ignore the test for now. + +-include ../tools.mk + +# For some very small programs GNU ld seems to not properly handle +# instrumentation sections correctly. Neither Gold nor LLD have that problem. +ifeq ($(UNAME),Linux) +ifneq (,$(findstring x86,$(TARGET))) +COMMON_FLAGS=-Clink-args=-fuse-ld=gold +endif +endif + + +all: + # We don't compile `opaque` with either optimizations or instrumentation. + $(RUSTC) $(COMMON_FLAGS) opaque.rs || exit 1 + # Compile the test program with instrumentation + mkdir -p "$(TMPDIR)/prof_data_dir" || exit 1 + $(RUSTC) $(COMMON_FLAGS) interesting.rs \ + -Cprofile-generate="$(TMPDIR)/prof_data_dir" -O -Ccodegen-units=1 || exit 1 + $(RUSTC) $(COMMON_FLAGS) main.rs -Cprofile-generate="$(TMPDIR)/prof_data_dir" -O || exit 1 + # The argument below generates to the expected branch weights + $(call RUN,main aaaaaaaaaaaa2bbbbbbbbbbbb2bbbbbbbbbbbbbbbbcc) || exit 1 + "$(LLVM_BIN_DIR)/llvm-profdata" merge \ + -o "$(TMPDIR)/prof_data_dir/merged.profdata" \ + "$(TMPDIR)/prof_data_dir" || exit 1 + $(RUSTC) $(COMMON_FLAGS) interesting.rs \ + -Cprofile-use="$(TMPDIR)/prof_data_dir/merged.profdata" -O \ + -Ccodegen-units=1 --emit=llvm-ir || exit 1 + cat "$(TMPDIR)/interesting.ll" | "$(LLVM_FILECHECK)" filecheck-patterns.txt diff --git a/src/test/run-make-fulldeps/pgo-branch-weights/filecheck-patterns.txt b/src/test/run-make-fulldeps/pgo-branch-weights/filecheck-patterns.txt new file mode 100644 index 000000000..70d5a645c --- /dev/null +++ b/src/test/run-make-fulldeps/pgo-branch-weights/filecheck-patterns.txt @@ -0,0 +1,24 @@ + +# First, establish that certain !prof labels are attached to the expected +# functions and branching instructions. + +CHECK: define void @function_called_twice(i32 {{.*}} !prof [[function_called_twice_id:![0-9]+]] { +CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !prof [[branch_weights0:![0-9]+]] + +CHECK: define void @function_called_42_times(i32{{.*}} %c) {{.*}} !prof [[function_called_42_times_id:![0-9]+]] { +CHECK: switch i32 %c, label {{.*}} [ +CHECK-NEXT: i32 97, label {{.*}} +CHECK-NEXT: i32 98, label {{.*}} +CHECK-NEXT: ], !prof [[branch_weights1:![0-9]+]] + +CHECK: define void @function_called_never(i32 {{.*}} !prof [[function_called_never_id:![0-9]+]] { + + + +# Now check that those !prof tags hold the expected counts + +CHECK: [[function_called_twice_id]] = !{!"function_entry_count", i64 2} +CHECK: [[branch_weights0]] = !{!"branch_weights", i32 2, i32 0} +CHECK: [[function_called_42_times_id]] = !{!"function_entry_count", i64 42} +CHECK: [[branch_weights1]] = !{!"branch_weights", i32 2, i32 12, i32 28} +CHECK: [[function_called_never_id]] = !{!"function_entry_count", i64 0} diff --git a/src/test/run-make-fulldeps/pgo-branch-weights/interesting.rs b/src/test/run-make-fulldeps/pgo-branch-weights/interesting.rs new file mode 100644 index 000000000..a26d6fd69 --- /dev/null +++ b/src/test/run-make-fulldeps/pgo-branch-weights/interesting.rs @@ -0,0 +1,40 @@ +#![crate_name="interesting"] +#![crate_type="rlib"] + +extern crate opaque; + +#[no_mangle] +#[inline(never)] +pub fn function_called_twice(c: char) { + if c == '2' { + // This branch is taken twice + opaque::f1(); + } else { + // This branch is never taken + opaque::f2(); + } +} + +#[no_mangle] +#[inline(never)] +pub fn function_called_42_times(c: char) { + if c == 'a' { + // This branch is taken 12 times + opaque::f1(); + } else { + + if c == 'b' { + // This branch is taken 28 times + opaque::f2(); + } else { + // This branch is taken 2 times + opaque::f3(); + } + } +} + +#[no_mangle] +#[inline(never)] +pub fn function_called_never(_: char) { + opaque::f1(); +} diff --git a/src/test/run-make-fulldeps/pgo-branch-weights/main.rs b/src/test/run-make-fulldeps/pgo-branch-weights/main.rs new file mode 100644 index 000000000..619cf9c69 --- /dev/null +++ b/src/test/run-make-fulldeps/pgo-branch-weights/main.rs @@ -0,0 +1,17 @@ +extern crate interesting; + +fn main() { + let arg = std::env::args().skip(1).next().unwrap(); + + for c in arg.chars() { + if c == '2' { + interesting::function_called_twice(c); + } else { + interesting::function_called_42_times(c); + } + + if c == '0' { + interesting::function_called_never(c); + } + } +} diff --git a/src/test/run-make-fulldeps/pgo-branch-weights/opaque.rs b/src/test/run-make-fulldeps/pgo-branch-weights/opaque.rs new file mode 100644 index 000000000..72f93c9fe --- /dev/null +++ b/src/test/run-make-fulldeps/pgo-branch-weights/opaque.rs @@ -0,0 +1,6 @@ +#![crate_name="opaque"] +#![crate_type="rlib"] + +pub fn f1() {} +pub fn f2() {} +pub fn f3() {} diff --git a/src/test/run-make-fulldeps/pgo-gen-lto/Makefile b/src/test/run-make-fulldeps/pgo-gen-lto/Makefile new file mode 100644 index 000000000..a7d5c5616 --- /dev/null +++ b/src/test/run-make-fulldeps/pgo-gen-lto/Makefile @@ -0,0 +1,14 @@ +# needs-profiler-support +# ignore-windows-gnu + +# FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works +# properly. Since we only have GCC on the CI ignore the test for now. + +-include ../tools.mk + +COMPILE_FLAGS=-Copt-level=3 -Clto=fat -Cprofile-generate="$(TMPDIR)" + +all: + $(RUSTC) $(COMPILE_FLAGS) test.rs + $(call RUN,test) || exit 1 + [ -e "$(TMPDIR)"/default_*.profraw ] || (echo "No .profraw file"; exit 1) diff --git a/src/test/run-make-fulldeps/pgo-gen-lto/test.rs b/src/test/run-make-fulldeps/pgo-gen-lto/test.rs new file mode 100644 index 000000000..f328e4d9d --- /dev/null +++ b/src/test/run-make-fulldeps/pgo-gen-lto/test.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/Makefile b/src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/Makefile new file mode 100644 index 000000000..425bfc28a --- /dev/null +++ b/src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/Makefile @@ -0,0 +1,13 @@ +# needs-profiler-support + +-include ../tools.mk + +COMPILE_FLAGS=-O -Ccodegen-units=1 -Cprofile-generate="$(TMPDIR)" + +all: + $(RUSTC) $(COMPILE_FLAGS) --emit=llvm-ir test.rs + # We expect symbols starting with "__llvm_profile_". + $(CGREP) "__llvm_profile_" < $(TMPDIR)/test.ll + # We do NOT expect the "__imp_" version of these symbols. + $(CGREP) -v "__imp___llvm_profile_" < $(TMPDIR)/test.ll # 64 bit + $(CGREP) -v "__imp____llvm_profile_" < $(TMPDIR)/test.ll # 32 bit diff --git a/src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/test.rs b/src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/test.rs new file mode 100644 index 000000000..f328e4d9d --- /dev/null +++ b/src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/test.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/src/test/run-make-fulldeps/pgo-gen/Makefile b/src/test/run-make-fulldeps/pgo-gen/Makefile new file mode 100644 index 000000000..6533355be --- /dev/null +++ b/src/test/run-make-fulldeps/pgo-gen/Makefile @@ -0,0 +1,14 @@ +# needs-profiler-support +# ignore-windows-gnu + +# FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works +# properly. Since we only have GCC on the CI ignore the test for now. + +-include ../tools.mk + +COMPILE_FLAGS=-g -Cprofile-generate="$(TMPDIR)" + +all: + $(RUSTC) $(COMPILE_FLAGS) test.rs + $(call RUN,test) || exit 1 + [ -e "$(TMPDIR)"/default_*.profraw ] || (echo "No .profraw file"; exit 1) diff --git a/src/test/run-make-fulldeps/pgo-gen/test.rs b/src/test/run-make-fulldeps/pgo-gen/test.rs new file mode 100644 index 000000000..f328e4d9d --- /dev/null +++ b/src/test/run-make-fulldeps/pgo-gen/test.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/src/test/run-make-fulldeps/pgo-indirect-call-promotion/Makefile b/src/test/run-make-fulldeps/pgo-indirect-call-promotion/Makefile new file mode 100644 index 000000000..c0195dcbb --- /dev/null +++ b/src/test/run-make-fulldeps/pgo-indirect-call-promotion/Makefile @@ -0,0 +1,26 @@ +# needs-profiler-support +# ignore-windows-gnu + +# FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works +# properly. Since we only have GCC on the CI ignore the test for now. + +-include ../tools.mk + +all: + # We don't compile `opaque` with either optimizations or instrumentation. + # We don't compile `opaque` with either optimizations or instrumentation. + $(RUSTC) $(COMMON_FLAGS) opaque.rs + # Compile the test program with instrumentation + mkdir -p "$(TMPDIR)"/prof_data_dir + $(RUSTC) $(COMMON_FLAGS) interesting.rs \ + -Cprofile-generate="$(TMPDIR)"/prof_data_dir -O -Ccodegen-units=1 + $(RUSTC) $(COMMON_FLAGS) main.rs -Cprofile-generate="$(TMPDIR)"/prof_data_dir -O + # The argument below generates to the expected branch weights + $(call RUN,main) || exit 1 + "$(LLVM_BIN_DIR)"/llvm-profdata merge \ + -o "$(TMPDIR)"/prof_data_dir/merged.profdata \ + "$(TMPDIR)"/prof_data_dir + $(RUSTC) $(COMMON_FLAGS) interesting.rs \ + -Cprofile-use="$(TMPDIR)"/prof_data_dir/merged.profdata -O \ + -Ccodegen-units=1 --emit=llvm-ir + cat "$(TMPDIR)"/interesting.ll | "$(LLVM_FILECHECK)" filecheck-patterns.txt diff --git a/src/test/run-make-fulldeps/pgo-indirect-call-promotion/filecheck-patterns.txt b/src/test/run-make-fulldeps/pgo-indirect-call-promotion/filecheck-patterns.txt new file mode 100644 index 000000000..e19c78350 --- /dev/null +++ b/src/test/run-make-fulldeps/pgo-indirect-call-promotion/filecheck-patterns.txt @@ -0,0 +1,16 @@ +CHECK: define void @call_a_bunch_of_functions({{.*}} { + +# Make sure that indirect call promotion inserted a check against the most +# frequently called function. +CHECK: %{{.*}} = icmp eq {{void \(\)\*|ptr}} %{{.*}}, @function_called_always + +# Check that the call to `function_called_always` was inlined, so that we +# directly call `opaque_f1` from the upstream crate. +CHECK: call void @opaque_f1() + + +# Same checks as above, repeated for the trait object case + +CHECK: define void @call_a_bunch_of_trait_methods({{.*}} +CHECK: %{{.*}} = icmp eq {{void \(\{\}\*\)\*|ptr}} %{{.*}}, {{.*}}@foo +CHECK: tail call void @opaque_f2() diff --git a/src/test/run-make-fulldeps/pgo-indirect-call-promotion/interesting.rs b/src/test/run-make-fulldeps/pgo-indirect-call-promotion/interesting.rs new file mode 100644 index 000000000..4fd096d62 --- /dev/null +++ b/src/test/run-make-fulldeps/pgo-indirect-call-promotion/interesting.rs @@ -0,0 +1,56 @@ +#![crate_name="interesting"] +#![crate_type="rlib"] + +extern crate opaque; + +#[no_mangle] +pub fn function_called_always() { + opaque::opaque_f1(); +} + +#[no_mangle] +pub fn function_called_never() { + opaque::opaque_f2(); +} + +#[no_mangle] +pub fn call_a_bunch_of_functions(fns: &[fn()]) { + + // Indirect call promotion transforms the below into something like + // + // for f in fns { + // if f == function_called_always { + // function_called_always() + // } else { + // f(); + // } + // } + // + // where `function_called_always` actually gets inlined too. + + for f in fns { + f(); + } +} + + +pub trait Foo { + fn foo(&self); +} + +impl Foo for u32 { + + #[no_mangle] + fn foo(&self) { + opaque::opaque_f2(); + } +} + +#[no_mangle] +pub fn call_a_bunch_of_trait_methods(trait_objects: &[&dyn Foo]) { + + // Same as above, just with vtables in between + for x in trait_objects { + x.foo(); + } +} diff --git a/src/test/run-make-fulldeps/pgo-indirect-call-promotion/main.rs b/src/test/run-make-fulldeps/pgo-indirect-call-promotion/main.rs new file mode 100644 index 000000000..27181f307 --- /dev/null +++ b/src/test/run-make-fulldeps/pgo-indirect-call-promotion/main.rs @@ -0,0 +1,14 @@ +extern crate interesting; + +fn main() { + // function pointer case + let fns: Vec<_> = std::iter::repeat(interesting::function_called_always as fn()) + .take(1000) + .collect(); + interesting::call_a_bunch_of_functions(&fns[..]); + + // Trait object case + let trait_objects = vec![0u32; 1000]; + let trait_objects: Vec<_> = trait_objects.iter().map(|x| x as &dyn interesting::Foo).collect(); + interesting::call_a_bunch_of_trait_methods(&trait_objects[..]); +} diff --git a/src/test/run-make-fulldeps/pgo-indirect-call-promotion/opaque.rs b/src/test/run-make-fulldeps/pgo-indirect-call-promotion/opaque.rs new file mode 100644 index 000000000..9628d711c --- /dev/null +++ b/src/test/run-make-fulldeps/pgo-indirect-call-promotion/opaque.rs @@ -0,0 +1,7 @@ +#![crate_name="opaque"] +#![crate_type="rlib"] + +#[no_mangle] +pub fn opaque_f1() {} +#[no_mangle] +pub fn opaque_f2() {} diff --git a/src/test/run-make-fulldeps/pgo-use/Makefile b/src/test/run-make-fulldeps/pgo-use/Makefile new file mode 100644 index 000000000..d7863c9c5 --- /dev/null +++ b/src/test/run-make-fulldeps/pgo-use/Makefile @@ -0,0 +1,46 @@ +# needs-profiler-support +# ignore-windows-gnu + +# FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works +# properly. Since we only have GCC on the CI ignore the test for now. + +-include ../tools.mk + +# This test makes sure that PGO profiling data leads to cold functions being +# marked as `cold` and hot functions with `inlinehint`. +# The test program contains an `if` were actual execution only ever takes the +# `else` branch. Accordingly, we expect the function that is never called to +# be marked as cold. +# +# Disable the pre-inlining pass (i.e. a pass that does some inlining before +# it adds the profiling instrumentation). Disabling this pass leads to +# rather predictable IR which we need for this test to be stable. + +COMMON_FLAGS=-Copt-level=2 -Ccodegen-units=1 -Cllvm-args=-disable-preinline + +ifeq ($(UNAME),Darwin) +# macOS does not have the `tac` command, but `tail -r` does the same thing +TAC := tail -r +else +# some other platforms don't support the `-r` flag for `tail`, so use `tac` +TAC := tac +endif + +all: + # Compile the test program with instrumentation + $(RUSTC) $(COMMON_FLAGS) -Cprofile-generate="$(TMPDIR)" main.rs + # Run it in order to generate some profiling data + $(call RUN,main some-argument) || exit 1 + # Postprocess the profiling data so it can be used by the compiler + "$(LLVM_BIN_DIR)"/llvm-profdata merge \ + -o "$(TMPDIR)"/merged.profdata \ + "$(TMPDIR)"/default_*.profraw + # Compile the test program again, making use of the profiling data + $(RUSTC) $(COMMON_FLAGS) -Cprofile-use="$(TMPDIR)"/merged.profdata --emit=llvm-ir main.rs + # Check that the generate IR contains some things that we expect + # + # We feed the file into LLVM FileCheck tool *in reverse* so that we see the + # line with the function name before the line with the function attributes. + # FileCheck only supports checking that something matches on the next line, + # but not if something matches on the previous line. + $(TAC) "$(TMPDIR)"/main.ll | "$(LLVM_FILECHECK)" filecheck-patterns.txt diff --git a/src/test/run-make-fulldeps/pgo-use/filecheck-patterns.txt b/src/test/run-make-fulldeps/pgo-use/filecheck-patterns.txt new file mode 100644 index 000000000..6da34f88f --- /dev/null +++ b/src/test/run-make-fulldeps/pgo-use/filecheck-patterns.txt @@ -0,0 +1,11 @@ +# Add a check that the IR contains some expected metadata +CHECK: !{!"ProfileFormat", !"InstrProf"} +CHECK: !"ProfileSummary" + +# Make sure that the hot function is marked with `inlinehint` +CHECK: define {{.*}} @hot_function +CHECK-NEXT: Function Attrs:{{.*}}inlinehint + +# Make sure that the cold function is marked with `cold` +CHECK: define {{.*}} @cold_function +CHECK-NEXT: Function Attrs:{{.*}}cold diff --git a/src/test/run-make-fulldeps/pgo-use/main.rs b/src/test/run-make-fulldeps/pgo-use/main.rs new file mode 100644 index 000000000..eb9192c87 --- /dev/null +++ b/src/test/run-make-fulldeps/pgo-use/main.rs @@ -0,0 +1,23 @@ +#[no_mangle] +pub fn cold_function(c: u8) { + println!("cold {}", c); +} + +#[no_mangle] +pub fn hot_function(c: u8) { + std::env::set_var(format!("var{}", c), format!("hot {}", c)); +} + +fn main() { + let arg = std::env::args().skip(1).next().unwrap(); + + for i in 0 .. 1000_000 { + let some_value = arg.as_bytes()[i % arg.len()]; + if some_value == b'!' { + // This branch is never taken at runtime + cold_function(some_value); + } else { + hot_function(some_value); + } + } +} diff --git a/src/test/run-make-fulldeps/pointer-auth-link-with-c/Makefile b/src/test/run-make-fulldeps/pointer-auth-link-with-c/Makefile new file mode 100644 index 000000000..d0e22cfef --- /dev/null +++ b/src/test/run-make-fulldeps/pointer-auth-link-with-c/Makefile @@ -0,0 +1,14 @@ +-include ../tools.mk + +# only-aarch64 + +all: + $(COMPILE_OBJ) $(TMPDIR)/test.o test.c + $(AR) rcs $(TMPDIR)/libtest.a $(TMPDIR)/test.o + $(RUSTC) -Z branch-protection=bti,pac-ret,leaf test.rs + $(call RUN,test) + + $(COMPILE_OBJ) $(TMPDIR)/test.o test.c -mbranch-protection=bti+pac-ret+leaf + $(AR) rcs $(TMPDIR)/libtest.a $(TMPDIR)/test.o + $(RUSTC) -Z branch-protection=bti,pac-ret,leaf test.rs + $(call RUN,test) diff --git a/src/test/run-make-fulldeps/pointer-auth-link-with-c/test.c b/src/test/run-make-fulldeps/pointer-auth-link-with-c/test.c new file mode 100644 index 000000000..9fe07f82f --- /dev/null +++ b/src/test/run-make-fulldeps/pointer-auth-link-with-c/test.c @@ -0,0 +1 @@ +int foo() { return 0; } diff --git a/src/test/run-make-fulldeps/pointer-auth-link-with-c/test.rs b/src/test/run-make-fulldeps/pointer-auth-link-with-c/test.rs new file mode 100644 index 000000000..615ad0aeb --- /dev/null +++ b/src/test/run-make-fulldeps/pointer-auth-link-with-c/test.rs @@ -0,0 +1,8 @@ +#[link(name = "test")] +extern "C" { + fn foo() -> i32; +} + +fn main() { + unsafe {foo();} +} diff --git a/src/test/run-make-fulldeps/prefer-dylib/Makefile b/src/test/run-make-fulldeps/prefer-dylib/Makefile new file mode 100644 index 000000000..bd44feecf --- /dev/null +++ b/src/test/run-make-fulldeps/prefer-dylib/Makefile @@ -0,0 +1,8 @@ +-include ../tools.mk + +all: + $(RUSTC) bar.rs --crate-type=dylib --crate-type=rlib -C prefer-dynamic + $(RUSTC) foo.rs -C prefer-dynamic + $(call RUN,foo) + rm $(TMPDIR)/*bar* + $(call FAIL,foo) diff --git a/src/test/run-make-fulldeps/prefer-dylib/bar.rs b/src/test/run-make-fulldeps/prefer-dylib/bar.rs new file mode 100644 index 000000000..c5c0bc606 --- /dev/null +++ b/src/test/run-make-fulldeps/prefer-dylib/bar.rs @@ -0,0 +1 @@ +pub fn bar() {} diff --git a/src/test/run-make-fulldeps/prefer-dylib/foo.rs b/src/test/run-make-fulldeps/prefer-dylib/foo.rs new file mode 100644 index 000000000..8d68535e3 --- /dev/null +++ b/src/test/run-make-fulldeps/prefer-dylib/foo.rs @@ -0,0 +1,5 @@ +extern crate bar; + +fn main() { + bar::bar(); +} diff --git a/src/test/run-make-fulldeps/prefer-rlib/Makefile b/src/test/run-make-fulldeps/prefer-rlib/Makefile new file mode 100644 index 000000000..c6a239eef --- /dev/null +++ b/src/test/run-make-fulldeps/prefer-rlib/Makefile @@ -0,0 +1,8 @@ +-include ../tools.mk + +all: + $(RUSTC) bar.rs --crate-type=dylib --crate-type=rlib + ls $(TMPDIR)/$(call RLIB_GLOB,bar) + $(RUSTC) foo.rs + rm $(TMPDIR)/*bar* + $(call RUN,foo) diff --git a/src/test/run-make-fulldeps/prefer-rlib/bar.rs b/src/test/run-make-fulldeps/prefer-rlib/bar.rs new file mode 100644 index 000000000..c5c0bc606 --- /dev/null +++ b/src/test/run-make-fulldeps/prefer-rlib/bar.rs @@ -0,0 +1 @@ +pub fn bar() {} diff --git a/src/test/run-make-fulldeps/prefer-rlib/foo.rs b/src/test/run-make-fulldeps/prefer-rlib/foo.rs new file mode 100644 index 000000000..8d68535e3 --- /dev/null +++ b/src/test/run-make-fulldeps/prefer-rlib/foo.rs @@ -0,0 +1,5 @@ +extern crate bar; + +fn main() { + bar::bar(); +} diff --git a/src/test/run-make-fulldeps/pretty-expanded/Makefile b/src/test/run-make-fulldeps/pretty-expanded/Makefile new file mode 100644 index 000000000..e721c5afd --- /dev/null +++ b/src/test/run-make-fulldeps/pretty-expanded/Makefile @@ -0,0 +1,4 @@ +-include ../tools.mk + +all: + $(RUSTC) -o $(TMPDIR)/input.expanded.rs -Zunpretty=expanded input.rs diff --git a/src/test/run-make-fulldeps/pretty-expanded/input.rs b/src/test/run-make-fulldeps/pretty-expanded/input.rs new file mode 100644 index 000000000..af3d75b3b --- /dev/null +++ b/src/test/run-make-fulldeps/pretty-expanded/input.rs @@ -0,0 +1,12 @@ +#[crate_type="lib"] + +// #13544 + +extern crate rustc_serialize; + +#[derive(RustcEncodable)] pub struct A; +#[derive(RustcEncodable)] pub struct B(isize); +#[derive(RustcEncodable)] pub struct C { x: isize } +#[derive(RustcEncodable)] pub enum D {} +#[derive(RustcEncodable)] pub enum E { y } +#[derive(RustcEncodable)] pub enum F { z(isize) } diff --git a/src/test/run-make-fulldeps/pretty-print-to-file/Makefile b/src/test/run-make-fulldeps/pretty-print-to-file/Makefile new file mode 100644 index 000000000..b224c52fc --- /dev/null +++ b/src/test/run-make-fulldeps/pretty-print-to-file/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: + $(RUSTC) -o $(TMPDIR)/input.out -Zunpretty=normal input.rs + diff -u $(TMPDIR)/input.out input.pp diff --git a/src/test/run-make-fulldeps/pretty-print-to-file/input.pp b/src/test/run-make-fulldeps/pretty-print-to-file/input.pp new file mode 100644 index 000000000..e3f03242a --- /dev/null +++ b/src/test/run-make-fulldeps/pretty-print-to-file/input.pp @@ -0,0 +1,3 @@ + +#[crate_type = "lib"] +pub fn foo() -> i32 { 45 } diff --git a/src/test/run-make-fulldeps/pretty-print-to-file/input.rs b/src/test/run-make-fulldeps/pretty-print-to-file/input.rs new file mode 100644 index 000000000..aa828155b --- /dev/null +++ b/src/test/run-make-fulldeps/pretty-print-to-file/input.rs @@ -0,0 +1,5 @@ +#[crate_type="lib"] + +pub fn +foo() -> i32 +{ 45 } diff --git a/src/test/run-make-fulldeps/print-cfg/Makefile b/src/test/run-make-fulldeps/print-cfg/Makefile new file mode 100644 index 000000000..5472baae3 --- /dev/null +++ b/src/test/run-make-fulldeps/print-cfg/Makefile @@ -0,0 +1,20 @@ +# needs-llvm-components: x86 arm + +-include ../tools.mk + +all: default + $(RUSTC) --target x86_64-pc-windows-gnu --print cfg | $(CGREP) windows + $(RUSTC) --target x86_64-pc-windows-gnu --print cfg | $(CGREP) x86_64 + $(RUSTC) --target i686-pc-windows-msvc --print cfg | $(CGREP) msvc + $(RUSTC) --target i686-apple-darwin --print cfg | $(CGREP) macos + $(RUSTC) --target i686-unknown-linux-gnu --print cfg | $(CGREP) gnu + $(RUSTC) --target arm-unknown-linux-gnueabihf --print cfg | $(CGREP) target_abi= + $(RUSTC) --target arm-unknown-linux-gnueabihf --print cfg | $(CGREP) eabihf + +ifdef IS_WINDOWS +default: + $(RUSTC) --print cfg | $(CGREP) windows +else +default: + $(RUSTC) --print cfg | $(CGREP) unix +endif diff --git a/src/test/run-make-fulldeps/print-target-list/Makefile b/src/test/run-make-fulldeps/print-target-list/Makefile new file mode 100644 index 000000000..5f10f2aa3 --- /dev/null +++ b/src/test/run-make-fulldeps/print-target-list/Makefile @@ -0,0 +1,8 @@ +-include ../tools.mk + +# Checks that all the targets returned by `rustc --print target-list` are valid +# target specifications +all: + for target in $(shell $(BARE_RUSTC) --print target-list); do \ + $(BARE_RUSTC) --target $$target --print sysroot; \ + done diff --git a/src/test/run-make-fulldeps/profile/Makefile b/src/test/run-make-fulldeps/profile/Makefile new file mode 100644 index 000000000..04d382b47 --- /dev/null +++ b/src/test/run-make-fulldeps/profile/Makefile @@ -0,0 +1,12 @@ +# needs-profiler-support + +-include ../tools.mk + +all: + $(RUSTC) -g -Z profile test.rs + $(call RUN,test) || exit 1 + [ -e "$(TMPDIR)/test.gcno" ] || (echo "No .gcno file"; exit 1) + [ -e "$(TMPDIR)/test.gcda" ] || (echo "No .gcda file"; exit 1) + $(RUSTC) -g -Z profile -Z profile-emit=$(TMPDIR)/abc/abc.gcda test.rs + $(call RUN,test) || exit 1 + [ -e "$(TMPDIR)/abc/abc.gcda" ] || (echo "gcda file not emitted to defined path"; exit 1) diff --git a/src/test/run-make-fulldeps/profile/test.rs b/src/test/run-make-fulldeps/profile/test.rs new file mode 100644 index 000000000..f328e4d9d --- /dev/null +++ b/src/test/run-make-fulldeps/profile/test.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/src/test/run-make-fulldeps/prune-link-args/Makefile b/src/test/run-make-fulldeps/prune-link-args/Makefile new file mode 100644 index 000000000..3589f98e7 --- /dev/null +++ b/src/test/run-make-fulldeps/prune-link-args/Makefile @@ -0,0 +1,9 @@ +-include ../tools.mk + +# ignore-windows + +# Notice the space in the end, this emulates the output of pkg-config +RUSTC_FLAGS = -C link-args="-lc " + +all: + $(RUSTC) $(RUSTC_FLAGS) empty.rs diff --git a/src/test/run-make-fulldeps/prune-link-args/empty.rs b/src/test/run-make-fulldeps/prune-link-args/empty.rs new file mode 100644 index 000000000..45590d86b --- /dev/null +++ b/src/test/run-make-fulldeps/prune-link-args/empty.rs @@ -0,0 +1 @@ +fn main() { } diff --git a/src/test/run-make-fulldeps/redundant-libs/Makefile b/src/test/run-make-fulldeps/redundant-libs/Makefile new file mode 100644 index 000000000..e09841fb4 --- /dev/null +++ b/src/test/run-make-fulldeps/redundant-libs/Makefile @@ -0,0 +1,23 @@ +-include ../tools.mk + +# ignore-windows-msvc + +# rustc will remove one of the two redundant references to foo below. Depending +# on which one gets removed, we'll get a linker error on SOME platforms (like +# Linux). On these platforms, when a library is referenced, the linker will +# only pull in the symbols needed _at that point in time_. If a later library +# depends on additional symbols from the library, they will not have been pulled +# in, and you'll get undefined symbols errors. +# +# So in this example, we need to ensure that rustc keeps the _later_ reference +# to foo, and not the former one. +RUSTC_FLAGS = \ + -l static=bar \ + -l foo \ + -l static=baz \ + -l foo \ + --print link-args + +all: $(call DYLIB,foo) $(call STATICLIB,bar) $(call STATICLIB,baz) + $(RUSTC) $(RUSTC_FLAGS) main.rs + $(call RUN,main) diff --git a/src/test/run-make-fulldeps/redundant-libs/bar.c b/src/test/run-make-fulldeps/redundant-libs/bar.c new file mode 100644 index 000000000..e42599986 --- /dev/null +++ b/src/test/run-make-fulldeps/redundant-libs/bar.c @@ -0,0 +1 @@ +void bar() {} diff --git a/src/test/run-make-fulldeps/redundant-libs/baz.c b/src/test/run-make-fulldeps/redundant-libs/baz.c new file mode 100644 index 000000000..a4e2c2b71 --- /dev/null +++ b/src/test/run-make-fulldeps/redundant-libs/baz.c @@ -0,0 +1,7 @@ +extern void foo1(); +extern void foo2(); + +void baz() { + foo1(); + foo2(); +} diff --git a/src/test/run-make-fulldeps/redundant-libs/foo.c b/src/test/run-make-fulldeps/redundant-libs/foo.c new file mode 100644 index 000000000..339ee86c9 --- /dev/null +++ b/src/test/run-make-fulldeps/redundant-libs/foo.c @@ -0,0 +1,2 @@ +void foo1() {} +void foo2() {} diff --git a/src/test/run-make-fulldeps/redundant-libs/main.rs b/src/test/run-make-fulldeps/redundant-libs/main.rs new file mode 100644 index 000000000..90d185ff5 --- /dev/null +++ b/src/test/run-make-fulldeps/redundant-libs/main.rs @@ -0,0 +1,11 @@ +extern "C" { + fn bar(); + fn baz(); +} + +fn main() { + unsafe { + bar(); + baz(); + } +} diff --git a/src/test/run-make-fulldeps/relocation-model/Makefile b/src/test/run-make-fulldeps/relocation-model/Makefile new file mode 100644 index 000000000..485ecbb4b --- /dev/null +++ b/src/test/run-make-fulldeps/relocation-model/Makefile @@ -0,0 +1,19 @@ +-include ../tools.mk + +all: others + $(RUSTC) -C relocation-model=dynamic-no-pic foo.rs + $(call RUN,foo) + + $(RUSTC) -C relocation-model=default foo.rs + $(call RUN,foo) + + $(RUSTC) -C relocation-model=dynamic-no-pic --crate-type=dylib foo.rs --emit=link,obj + +ifdef IS_MSVC +# FIXME(#28026) +others: +else +others: + $(RUSTC) -C relocation-model=static foo.rs + $(call RUN,foo) +endif diff --git a/src/test/run-make-fulldeps/relocation-model/foo.rs b/src/test/run-make-fulldeps/relocation-model/foo.rs new file mode 100644 index 000000000..da0f5d925 --- /dev/null +++ b/src/test/run-make-fulldeps/relocation-model/foo.rs @@ -0,0 +1 @@ +pub fn main() {} diff --git a/src/test/run-make-fulldeps/relro-levels/Makefile b/src/test/run-make-fulldeps/relro-levels/Makefile new file mode 100644 index 000000000..aacb5acb7 --- /dev/null +++ b/src/test/run-make-fulldeps/relro-levels/Makefile @@ -0,0 +1,21 @@ +-include ../tools.mk + +# only-linux +# +# This tests the different -Zrelro-level values, and makes sure that they work properly. + +all: + # Ensure that binaries built with the full relro level links them with both + # RELRO and BIND_NOW for doing eager symbol resolving. + $(RUSTC) -Zrelro-level=full hello.rs + readelf -l $(TMPDIR)/hello | grep -q GNU_RELRO + readelf -d $(TMPDIR)/hello | grep -q BIND_NOW + + $(RUSTC) -Zrelro-level=partial hello.rs + readelf -l $(TMPDIR)/hello | grep -q GNU_RELRO + + # Ensure that we're *not* built with RELRO when setting it to off. We do + # not want to check for BIND_NOW however, as the linker might have that + # enabled by default. + $(RUSTC) -Zrelro-level=off hello.rs + ! readelf -l $(TMPDIR)/hello | grep -q GNU_RELRO diff --git a/src/test/run-make-fulldeps/relro-levels/hello.rs b/src/test/run-make-fulldeps/relro-levels/hello.rs new file mode 100644 index 000000000..e7a11a969 --- /dev/null +++ b/src/test/run-make-fulldeps/relro-levels/hello.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/src/test/run-make-fulldeps/remap-path-prefix/Makefile b/src/test/run-make-fulldeps/remap-path-prefix/Makefile new file mode 100644 index 000000000..86785c595 --- /dev/null +++ b/src/test/run-make-fulldeps/remap-path-prefix/Makefile @@ -0,0 +1,9 @@ +-include ../tools.mk + +# ignore-windows + +# Checks if remapping works if the remap-from string contains path to the working directory plus more +all: + $(RUSTC) --remap-path-prefix $$PWD/auxiliary=/the/aux --crate-type=lib --emit=metadata auxiliary/lib.rs + grep "/the/aux/lib.rs" $(TMPDIR)/liblib.rmeta || exit 1 + ! grep "$$PWD/auxiliary" $(TMPDIR)/liblib.rmeta || exit 1 diff --git a/src/test/run-make-fulldeps/remap-path-prefix/auxiliary/lib.rs b/src/test/run-make-fulldeps/remap-path-prefix/auxiliary/lib.rs new file mode 100644 index 000000000..019c786a9 --- /dev/null +++ b/src/test/run-make-fulldeps/remap-path-prefix/auxiliary/lib.rs @@ -0,0 +1,3 @@ +pub fn lib() { + panic!("calm"); +} diff --git a/src/test/run-make-fulldeps/reproducible-build-2/Makefile b/src/test/run-make-fulldeps/reproducible-build-2/Makefile new file mode 100644 index 000000000..fd94516fb --- /dev/null +++ b/src/test/run-make-fulldeps/reproducible-build-2/Makefile @@ -0,0 +1,26 @@ +-include ../tools.mk + +# ignore-musl +# ignore-windows +# Objects are reproducible but their path is not. + +all: \ + fat_lto \ + sysroot + +fat_lto: + rm -rf $(TMPDIR) && mkdir $(TMPDIR) + $(RUSTC) reproducible-build-aux.rs + $(RUSTC) reproducible-build.rs -C lto=fat + cp $(TMPDIR)/reproducible-build $(TMPDIR)/reproducible-build-a + $(RUSTC) reproducible-build.rs -C lto=fat + cmp "$(TMPDIR)/reproducible-build-a" "$(TMPDIR)/reproducible-build" || exit 1 + +sysroot: + rm -rf $(TMPDIR) && mkdir $(TMPDIR) + $(RUSTC) reproducible-build-aux.rs + $(RUSTC) reproducible-build.rs --crate-type rlib --sysroot $(shell $(RUSTC) --print sysroot) --remap-path-prefix=$(shell $(RUSTC) --print sysroot)=/sysroot + cp -R $(shell $(RUSTC) --print sysroot) $(TMPDIR)/sysroot + cp $(TMPDIR)/libreproducible_build.rlib $(TMPDIR)/libfoo.rlib + $(RUSTC) reproducible-build.rs --crate-type rlib --sysroot $(TMPDIR)/sysroot --remap-path-prefix=$(TMPDIR)/sysroot=/sysroot + cmp "$(TMPDIR)/libreproducible_build.rlib" "$(TMPDIR)/libfoo.rlib" || exit 1 diff --git a/src/test/run-make-fulldeps/reproducible-build-2/linker.rs b/src/test/run-make-fulldeps/reproducible-build-2/linker.rs new file mode 100644 index 000000000..998d1f328 --- /dev/null +++ b/src/test/run-make-fulldeps/reproducible-build-2/linker.rs @@ -0,0 +1,44 @@ +use std::env; +use std::path::Path; +use std::fs::File; +use std::io::{Read, Write}; + +fn main() { + let mut dst = env::current_exe().unwrap(); + dst.pop(); + dst.push("linker-arguments1"); + if dst.exists() { + dst.pop(); + dst.push("linker-arguments2"); + assert!(!dst.exists()); + } + + let mut out = String::new(); + for arg in env::args().skip(1) { + let path = Path::new(&arg); + if !path.is_file() { + out.push_str(&arg); + out.push_str("\n"); + continue + } + + let mut contents = Vec::new(); + File::open(path).unwrap().read_to_end(&mut contents).unwrap(); + + out.push_str(&format!("{}: {}\n", arg, hash(&contents))); + } + + File::create(dst).unwrap().write_all(out.as_bytes()).unwrap(); +} + +// fnv hash for now +fn hash(contents: &[u8]) -> u64 { + let mut hash = 0xcbf29ce484222325; + + for byte in contents { + hash = hash ^ (*byte as u64); + hash = hash.wrapping_mul(0x100000001b3); + } + + hash +} diff --git a/src/test/run-make-fulldeps/reproducible-build-2/reproducible-build-aux.rs b/src/test/run-make-fulldeps/reproducible-build-2/reproducible-build-aux.rs new file mode 100644 index 000000000..8105b3d2b --- /dev/null +++ b/src/test/run-make-fulldeps/reproducible-build-2/reproducible-build-aux.rs @@ -0,0 +1,28 @@ +#![crate_type="lib"] + +pub static STATIC: i32 = 1234; + +pub struct Struct<T1, T2> { + _t1: std::marker::PhantomData<T1>, + _t2: std::marker::PhantomData<T2>, +} + +pub fn regular_fn(_: i32) {} + +pub fn generic_fn<T1, T2>() {} + +impl<T1, T2> Drop for Struct<T1, T2> { + fn drop(&mut self) {} +} + +pub enum Enum { + Variant1, + Variant2(u32), + Variant3 { x: u32 } +} + +pub struct TupleStruct(pub i8, pub i16, pub i32, pub i64); + +pub trait Trait<T1, T2> { + fn foo(&self); +} diff --git a/src/test/run-make-fulldeps/reproducible-build-2/reproducible-build.rs b/src/test/run-make-fulldeps/reproducible-build-2/reproducible-build.rs new file mode 100644 index 000000000..a6c04774c --- /dev/null +++ b/src/test/run-make-fulldeps/reproducible-build-2/reproducible-build.rs @@ -0,0 +1,116 @@ +// This test case makes sure that two identical invocations of the compiler +// (i.e., same code base, same compile-flags, same compiler-versions, etc.) +// produce the same output. In the past, symbol names of monomorphized functions +// were not deterministic (which we want to avoid). +// +// The test tries to exercise as many different paths into symbol name +// generation as possible: +// +// - regular functions +// - generic functions +// - methods +// - statics +// - closures +// - enum variant constructors +// - tuple struct constructors +// - drop glue +// - FnOnce adapters +// - Trait object shims +// - Fn Pointer shims + +#![allow(dead_code, warnings)] + +extern crate reproducible_build_aux; + +static STATIC: i32 = 1234; + +pub struct Struct<T1, T2> { + x: T1, + y: T2, +} + +fn regular_fn(_: i32) {} + +fn generic_fn<T1, T2>() {} + +impl<T1, T2> Drop for Struct<T1, T2> { + fn drop(&mut self) {} +} + +pub enum Enum { + Variant1, + Variant2(u32), + Variant3 { x: u32 } +} + +struct TupleStruct(i8, i16, i32, i64); + +impl TupleStruct { + pub fn bar(&self) {} +} + +trait Trait<T1, T2> { + fn foo(&self); +} + +impl Trait<i32, u64> for u64 { + fn foo(&self) {} +} + +impl reproducible_build_aux::Trait<char, String> for TupleStruct { + fn foo(&self) {} +} + +fn main() { + regular_fn(STATIC); + generic_fn::<u32, char>(); + generic_fn::<char, Struct<u32, u64>>(); + generic_fn::<Struct<u64, u32>, reproducible_build_aux::Struct<u32, u64>>(); + + let dropped = Struct { + x: "", + y: 'a', + }; + + let _ = Enum::Variant1; + let _ = Enum::Variant2(0); + let _ = Enum::Variant3 { x: 0 }; + let _ = TupleStruct(1, 2, 3, 4); + + let closure = |x| { + x + 1i32 + }; + + fn inner<F: Fn(i32) -> i32>(f: F) -> i32 { + f(STATIC) + } + + println!("{}", inner(closure)); + + let object_shim: &Trait<i32, u64> = &0u64; + object_shim.foo(); + + fn with_fn_once_adapter<F: FnOnce(i32)>(f: F) { + f(0); + } + + with_fn_once_adapter(|_:i32| { }); + + reproducible_build_aux::regular_fn(STATIC); + reproducible_build_aux::generic_fn::<u32, char>(); + reproducible_build_aux::generic_fn::<char, Struct<u32, u64>>(); + reproducible_build_aux::generic_fn::<Struct<u64, u32>, + reproducible_build_aux::Struct<u32, u64>>(); + + let _ = reproducible_build_aux::Enum::Variant1; + let _ = reproducible_build_aux::Enum::Variant2(0); + let _ = reproducible_build_aux::Enum::Variant3 { x: 0 }; + let _ = reproducible_build_aux::TupleStruct(1, 2, 3, 4); + + let object_shim: &reproducible_build_aux::Trait<char, String> = &TupleStruct(0, 1, 2, 3); + object_shim.foo(); + + let pointer_shim: &Fn(i32) = ®ular_fn; + + TupleStruct(1, 2, 3, 4).bar(); +} diff --git a/src/test/run-make-fulldeps/reproducible-build/Makefile b/src/test/run-make-fulldeps/reproducible-build/Makefile new file mode 100644 index 000000000..adccc1535 --- /dev/null +++ b/src/test/run-make-fulldeps/reproducible-build/Makefile @@ -0,0 +1,139 @@ +-include ../tools.mk + +# ignore-musl +# Objects are reproducible but their path is not. + +all: \ + smoke \ + debug \ + opt \ + link_paths \ + remap_paths \ + different_source_dirs_rlib \ + remap_cwd_rlib \ + remap_cwd_to_empty \ + extern_flags + +# TODO: Builds of `bin` crate types are not deterministic with debuginfo=2 on +# Windows. +# See: https://github.com/rust-lang/rust/pull/87320#issuecomment-920105533 +# Issue: https://github.com/rust-lang/rust/issues/88982 +# +# different_source_dirs_bin \ +# remap_cwd_bin \ + +smoke: + rm -rf $(TMPDIR) && mkdir $(TMPDIR) + $(RUSTC) linker.rs -O + $(RUSTC) reproducible-build-aux.rs + $(RUSTC) reproducible-build.rs -C linker=$(call RUN_BINFILE,linker) + $(RUSTC) reproducible-build.rs -C linker=$(call RUN_BINFILE,linker) + diff -u "$(TMPDIR)/linker-arguments1" "$(TMPDIR)/linker-arguments2" + +debug: + rm -rf $(TMPDIR) && mkdir $(TMPDIR) + $(RUSTC) linker.rs -O + $(RUSTC) reproducible-build-aux.rs -g + $(RUSTC) reproducible-build.rs -C linker=$(call RUN_BINFILE,linker) -g + $(RUSTC) reproducible-build.rs -C linker=$(call RUN_BINFILE,linker) -g + diff -u "$(TMPDIR)/linker-arguments1" "$(TMPDIR)/linker-arguments2" + +opt: + rm -rf $(TMPDIR) && mkdir $(TMPDIR) + $(RUSTC) linker.rs -O + $(RUSTC) reproducible-build-aux.rs -O + $(RUSTC) reproducible-build.rs -C linker=$(call RUN_BINFILE,linker) -O + $(RUSTC) reproducible-build.rs -C linker=$(call RUN_BINFILE,linker) -O + diff -u "$(TMPDIR)/linker-arguments1" "$(TMPDIR)/linker-arguments2" + +link_paths: + rm -rf $(TMPDIR) && mkdir $(TMPDIR) + $(RUSTC) reproducible-build-aux.rs + $(RUSTC) reproducible-build.rs --crate-type rlib -L /b + cp $(TMPDIR)/libreproducible_build.rlib $(TMPDIR)/libfoo.rlib + $(RUSTC) reproducible-build.rs --crate-type rlib -L /a + cmp "$(TMPDIR)/libreproducible_build.rlib" "$(TMPDIR)/libfoo.rlib" || exit 1 + +remap_paths: + rm -rf $(TMPDIR) && mkdir $(TMPDIR) + $(RUSTC) reproducible-build-aux.rs + $(RUSTC) reproducible-build.rs --crate-type rlib --remap-path-prefix=/a=/c + cp $(TMPDIR)/libreproducible_build.rlib $(TMPDIR)/libfoo.rlib + $(RUSTC) reproducible-build.rs --crate-type rlib --remap-path-prefix=/b=/c + cmp "$(TMPDIR)/libreproducible_build.rlib" "$(TMPDIR)/libfoo.rlib" || exit 1 + +different_source_dirs_bin: + rm -rf $(TMPDIR) && mkdir $(TMPDIR) + $(RUSTC) reproducible-build-aux.rs + mkdir $(TMPDIR)/test + cp reproducible-build.rs $(TMPDIR)/test + $(RUSTC) reproducible-build.rs --crate-type bin --remap-path-prefix=$$PWD=/b + cp $(TMPDIR)/reproducible-build $(TMPDIR)/foo + (cd $(TMPDIR)/test && $(RUSTC) reproducible-build.rs \ + --remap-path-prefix=$(TMPDIR)/test=/b \ + --crate-type bin) + cmp "$(TMPDIR)/reproducible-build" "$(TMPDIR)/foo" || exit 1 + +different_source_dirs_rlib: + rm -rf $(TMPDIR) && mkdir $(TMPDIR) + $(RUSTC) reproducible-build-aux.rs + mkdir $(TMPDIR)/test + cp reproducible-build.rs $(TMPDIR)/test + $(RUSTC) reproducible-build.rs --crate-type rlib --remap-path-prefix=$$PWD=/b + cp $(TMPDIR)/libreproducible_build.rlib $(TMPDIR)/libfoo.rlib + (cd $(TMPDIR)/test && $(RUSTC) reproducible-build.rs \ + --remap-path-prefix=$(TMPDIR)/test=/b \ + --crate-type rlib) + cmp "$(TMPDIR)/libreproducible_build.rlib" "$(TMPDIR)/libfoo.rlib" || exit 1 + +remap_cwd_bin: + rm -rf $(TMPDIR) && mkdir $(TMPDIR) + $(RUSTC) reproducible-build-aux.rs + mkdir $(TMPDIR)/test + cp reproducible-build.rs $(TMPDIR)/test + $(RUSTC) reproducible-build.rs --crate-type bin -C debuginfo=2 \ + -Z remap-cwd-prefix=. + cp $(TMPDIR)/reproducible-build $(TMPDIR)/first + (cd $(TMPDIR)/test && \ + $(RUSTC) reproducible-build.rs --crate-type bin -C debuginfo=2 \ + -Z remap-cwd-prefix=.) + cmp "$(TMPDIR)/first" "$(TMPDIR)/reproducible-build" || exit 1 + +remap_cwd_rlib: + rm -rf $(TMPDIR) && mkdir $(TMPDIR) + $(RUSTC) reproducible-build-aux.rs + mkdir $(TMPDIR)/test + cp reproducible-build.rs $(TMPDIR)/test + $(RUSTC) reproducible-build.rs --crate-type rlib -C debuginfo=2 \ + -Z remap-cwd-prefix=. + cp $(TMPDIR)/libreproducible_build.rlib $(TMPDIR)/libfirst.rlib + (cd $(TMPDIR)/test && \ + $(RUSTC) reproducible-build.rs --crate-type rlib -C debuginfo=2 \ + -Z remap-cwd-prefix=.) + cmp "$(TMPDIR)/libfirst.rlib" "$(TMPDIR)/libreproducible_build.rlib" || exit 1 + +remap_cwd_to_empty: + rm -rf $(TMPDIR) && mkdir $(TMPDIR) + $(RUSTC) reproducible-build-aux.rs + mkdir $(TMPDIR)/test + cp reproducible-build.rs $(TMPDIR)/test + $(RUSTC) reproducible-build.rs --crate-type rlib -C debuginfo=2 \ + -Z remap-cwd-prefix= + cp $(TMPDIR)/libreproducible_build.rlib $(TMPDIR)/libfirst.rlib + (cd $(TMPDIR)/test && \ + $(RUSTC) reproducible-build.rs --crate-type rlib -C debuginfo=2 \ + -Z remap-cwd-prefix=) + cmp "$(TMPDIR)/libfirst.rlib" "$(TMPDIR)/libreproducible_build.rlib" || exit 1 + +extern_flags: + rm -rf $(TMPDIR) && mkdir $(TMPDIR) + $(RUSTC) reproducible-build-aux.rs + $(RUSTC) reproducible-build.rs \ + --extern reproducible_build_aux=$(TMPDIR)/libreproducible_build_aux.rlib \ + --crate-type rlib + cp $(TMPDIR)/libreproducible_build_aux.rlib $(TMPDIR)/libbar.rlib + cp $(TMPDIR)/libreproducible_build.rlib $(TMPDIR)/libfoo.rlib + $(RUSTC) reproducible-build.rs \ + --extern reproducible_build_aux=$(TMPDIR)/libbar.rlib \ + --crate-type rlib + cmp "$(TMPDIR)/libreproducible_build.rlib" "$(TMPDIR)/libfoo.rlib" || exit 1 diff --git a/src/test/run-make-fulldeps/reproducible-build/linker.rs b/src/test/run-make-fulldeps/reproducible-build/linker.rs new file mode 100644 index 000000000..3dda6f190 --- /dev/null +++ b/src/test/run-make-fulldeps/reproducible-build/linker.rs @@ -0,0 +1,50 @@ +use std::env; +use std::path::Path; +use std::fs::File; +use std::io::{Read, Write}; + +fn main() { + let mut dst = env::current_exe().unwrap(); + dst.pop(); + dst.push("linker-arguments1"); + if dst.exists() { + dst.pop(); + dst.push("linker-arguments2"); + assert!(!dst.exists()); + } + + let mut out = String::new(); + for arg in env::args().skip(1) { + let path = Path::new(&arg); + if !path.is_file() { + out.push_str(&arg); + out.push_str("\n"); + continue + } + + let mut contents = Vec::new(); + File::open(path).unwrap().read_to_end(&mut contents).unwrap(); + + // This file is produced during linking in a temporary directory. + let arg = if arg.ends_with("/symbols.o") || arg.ends_with("\\symbols.o") { + "symbols.o" + } else { + &*arg + }; + out.push_str(&format!("{}: {}\n", arg, hash(&contents))); + } + + File::create(dst).unwrap().write_all(out.as_bytes()).unwrap(); +} + +// fnv hash for now +fn hash(contents: &[u8]) -> u64 { + let mut hash = 0xcbf29ce484222325; + + for byte in contents { + hash = hash ^ (*byte as u64); + hash = hash.wrapping_mul(0x100000001b3); + } + + hash +} diff --git a/src/test/run-make-fulldeps/reproducible-build/reproducible-build-aux.rs b/src/test/run-make-fulldeps/reproducible-build/reproducible-build-aux.rs new file mode 100644 index 000000000..8105b3d2b --- /dev/null +++ b/src/test/run-make-fulldeps/reproducible-build/reproducible-build-aux.rs @@ -0,0 +1,28 @@ +#![crate_type="lib"] + +pub static STATIC: i32 = 1234; + +pub struct Struct<T1, T2> { + _t1: std::marker::PhantomData<T1>, + _t2: std::marker::PhantomData<T2>, +} + +pub fn regular_fn(_: i32) {} + +pub fn generic_fn<T1, T2>() {} + +impl<T1, T2> Drop for Struct<T1, T2> { + fn drop(&mut self) {} +} + +pub enum Enum { + Variant1, + Variant2(u32), + Variant3 { x: u32 } +} + +pub struct TupleStruct(pub i8, pub i16, pub i32, pub i64); + +pub trait Trait<T1, T2> { + fn foo(&self); +} diff --git a/src/test/run-make-fulldeps/reproducible-build/reproducible-build.rs b/src/test/run-make-fulldeps/reproducible-build/reproducible-build.rs new file mode 100644 index 000000000..a6c04774c --- /dev/null +++ b/src/test/run-make-fulldeps/reproducible-build/reproducible-build.rs @@ -0,0 +1,116 @@ +// This test case makes sure that two identical invocations of the compiler +// (i.e., same code base, same compile-flags, same compiler-versions, etc.) +// produce the same output. In the past, symbol names of monomorphized functions +// were not deterministic (which we want to avoid). +// +// The test tries to exercise as many different paths into symbol name +// generation as possible: +// +// - regular functions +// - generic functions +// - methods +// - statics +// - closures +// - enum variant constructors +// - tuple struct constructors +// - drop glue +// - FnOnce adapters +// - Trait object shims +// - Fn Pointer shims + +#![allow(dead_code, warnings)] + +extern crate reproducible_build_aux; + +static STATIC: i32 = 1234; + +pub struct Struct<T1, T2> { + x: T1, + y: T2, +} + +fn regular_fn(_: i32) {} + +fn generic_fn<T1, T2>() {} + +impl<T1, T2> Drop for Struct<T1, T2> { + fn drop(&mut self) {} +} + +pub enum Enum { + Variant1, + Variant2(u32), + Variant3 { x: u32 } +} + +struct TupleStruct(i8, i16, i32, i64); + +impl TupleStruct { + pub fn bar(&self) {} +} + +trait Trait<T1, T2> { + fn foo(&self); +} + +impl Trait<i32, u64> for u64 { + fn foo(&self) {} +} + +impl reproducible_build_aux::Trait<char, String> for TupleStruct { + fn foo(&self) {} +} + +fn main() { + regular_fn(STATIC); + generic_fn::<u32, char>(); + generic_fn::<char, Struct<u32, u64>>(); + generic_fn::<Struct<u64, u32>, reproducible_build_aux::Struct<u32, u64>>(); + + let dropped = Struct { + x: "", + y: 'a', + }; + + let _ = Enum::Variant1; + let _ = Enum::Variant2(0); + let _ = Enum::Variant3 { x: 0 }; + let _ = TupleStruct(1, 2, 3, 4); + + let closure = |x| { + x + 1i32 + }; + + fn inner<F: Fn(i32) -> i32>(f: F) -> i32 { + f(STATIC) + } + + println!("{}", inner(closure)); + + let object_shim: &Trait<i32, u64> = &0u64; + object_shim.foo(); + + fn with_fn_once_adapter<F: FnOnce(i32)>(f: F) { + f(0); + } + + with_fn_once_adapter(|_:i32| { }); + + reproducible_build_aux::regular_fn(STATIC); + reproducible_build_aux::generic_fn::<u32, char>(); + reproducible_build_aux::generic_fn::<char, Struct<u32, u64>>(); + reproducible_build_aux::generic_fn::<Struct<u64, u32>, + reproducible_build_aux::Struct<u32, u64>>(); + + let _ = reproducible_build_aux::Enum::Variant1; + let _ = reproducible_build_aux::Enum::Variant2(0); + let _ = reproducible_build_aux::Enum::Variant3 { x: 0 }; + let _ = reproducible_build_aux::TupleStruct(1, 2, 3, 4); + + let object_shim: &reproducible_build_aux::Trait<char, String> = &TupleStruct(0, 1, 2, 3); + object_shim.foo(); + + let pointer_shim: &Fn(i32) = ®ular_fn; + + TupleStruct(1, 2, 3, 4).bar(); +} diff --git a/src/test/run-make-fulldeps/resolve-rename/Makefile b/src/test/run-make-fulldeps/resolve-rename/Makefile new file mode 100644 index 000000000..4b0c36d01 --- /dev/null +++ b/src/test/run-make-fulldeps/resolve-rename/Makefile @@ -0,0 +1,7 @@ +-include ../tools.mk + +all: + $(RUSTC) -C extra-filename=-hash foo.rs + $(RUSTC) bar.rs + mv $(TMPDIR)/libfoo-hash.rlib $(TMPDIR)/libfoo-another-hash.rlib + $(RUSTC) baz.rs diff --git a/src/test/run-make-fulldeps/resolve-rename/bar.rs b/src/test/run-make-fulldeps/resolve-rename/bar.rs new file mode 100644 index 000000000..4a09ce355 --- /dev/null +++ b/src/test/run-make-fulldeps/resolve-rename/bar.rs @@ -0,0 +1,5 @@ +#![crate_type = "rlib"] + +extern crate foo; + +pub fn bar() { foo::foo() } diff --git a/src/test/run-make-fulldeps/resolve-rename/baz.rs b/src/test/run-make-fulldeps/resolve-rename/baz.rs new file mode 100644 index 000000000..9176073ef --- /dev/null +++ b/src/test/run-make-fulldeps/resolve-rename/baz.rs @@ -0,0 +1,5 @@ +#![crate_type = "rlib"] + +extern crate bar; + +pub fn baz() { bar::bar() } diff --git a/src/test/run-make-fulldeps/resolve-rename/foo.rs b/src/test/run-make-fulldeps/resolve-rename/foo.rs new file mode 100644 index 000000000..bd6820098 --- /dev/null +++ b/src/test/run-make-fulldeps/resolve-rename/foo.rs @@ -0,0 +1,3 @@ +#![crate_type = "rlib"] + +pub fn foo() {} diff --git a/src/test/run-make-fulldeps/return-non-c-like-enum-from-c/Makefile b/src/test/run-make-fulldeps/return-non-c-like-enum-from-c/Makefile new file mode 100644 index 000000000..f3d935786 --- /dev/null +++ b/src/test/run-make-fulldeps/return-non-c-like-enum-from-c/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: $(call NATIVE_STATICLIB,test) + $(RUSTC) nonclike.rs -L$(TMPDIR) -ltest + $(call RUN,nonclike) diff --git a/src/test/run-make-fulldeps/return-non-c-like-enum-from-c/nonclike.rs b/src/test/run-make-fulldeps/return-non-c-like-enum-from-c/nonclike.rs new file mode 100644 index 000000000..ea22a2a56 --- /dev/null +++ b/src/test/run-make-fulldeps/return-non-c-like-enum-from-c/nonclike.rs @@ -0,0 +1,31 @@ +#[repr(C, u8)] +pub enum TT { + AA(u64, u64), + BB, +} + +#[repr(C,u8)] +pub enum T { + A(u64), + B, +} + +extern "C" { + pub fn t_new(a: u64) -> T; + pub fn tt_new(a: u64, b: u64) -> TT; +} + +fn main() { + if let TT::AA(a, b) = unsafe { tt_new(10, 11) } { + assert_eq!(10, a); + assert_eq!(11, b); + } else { + panic!("expected TT::AA"); + } + + if let T::A(a) = unsafe { t_new(10) } { + assert_eq!(10, a); + } else { + panic!("expected T::A"); + } +} diff --git a/src/test/run-make-fulldeps/return-non-c-like-enum-from-c/test.c b/src/test/run-make-fulldeps/return-non-c-like-enum-from-c/test.c new file mode 100644 index 000000000..3ad135bab --- /dev/null +++ b/src/test/run-make-fulldeps/return-non-c-like-enum-from-c/test.c @@ -0,0 +1,61 @@ +#include <stdint.h> + +/* This is the code generated by cbindgen 0.12.1 for the `enum TT` + * type in nonclike.rs . */ +enum TT_Tag { + AA, + BB, +}; +typedef uint8_t TT_Tag; + +typedef struct { + uint64_t _0; + uint64_t _1; +} AA_Body; + +typedef struct { + TT_Tag tag; + union { + AA_Body aa; + }; +} TT; + +/* This is the code generated by cbindgen 0.12.1 for the `enum T` type + * in nonclike.rs . */ +enum T_Tag { + A, + B, +}; +typedef uint8_t T_Tag; + +typedef struct { + uint64_t _0; +} A_Body; + +typedef struct { + T_Tag tag; + union { + A_Body a; + }; +} T; + +TT tt_new(uint64_t a, uint64_t b) { + TT tt = { + .tag = AA, + .aa = { + ._0 = a, + ._1 = b, + }, + }; + return tt; +} + +T t_new(uint64_t a) { + T t = { + .tag = A, + .a = { + ._0 = a, + }, + }; + return t; +} diff --git a/src/test/run-make-fulldeps/return-non-c-like-enum/Makefile b/src/test/run-make-fulldeps/return-non-c-like-enum/Makefile new file mode 100644 index 000000000..5b5d620ef --- /dev/null +++ b/src/test/run-make-fulldeps/return-non-c-like-enum/Makefile @@ -0,0 +1,7 @@ +-include ../tools.mk + +all: + $(RUSTC) --crate-type=staticlib nonclike.rs + $(CC) test.c $(call STATICLIB,nonclike) $(call OUT_EXE,test) \ + $(EXTRACFLAGS) $(EXTRACXXFLAGS) + $(call RUN,test) diff --git a/src/test/run-make-fulldeps/return-non-c-like-enum/nonclike.rs b/src/test/run-make-fulldeps/return-non-c-like-enum/nonclike.rs new file mode 100644 index 000000000..de529cf64 --- /dev/null +++ b/src/test/run-make-fulldeps/return-non-c-like-enum/nonclike.rs @@ -0,0 +1,21 @@ +#[repr(C, u8)] +pub enum TT { + AA(u64, u64), + BB, +} + +#[no_mangle] +pub extern "C" fn tt_new(a: u64, b: u64) -> TT { + TT::AA(a, b) +} + +#[repr(C,u8)] +pub enum T { + A(u64), + B, +} + +#[no_mangle] +pub extern "C" fn t_new(a: u64) -> T { + T::A(a) +} diff --git a/src/test/run-make-fulldeps/return-non-c-like-enum/test.c b/src/test/run-make-fulldeps/return-non-c-like-enum/test.c new file mode 100644 index 000000000..afadd3c10 --- /dev/null +++ b/src/test/run-make-fulldeps/return-non-c-like-enum/test.c @@ -0,0 +1,63 @@ +#include <stdint.h> +#include <assert.h> + +/* This is the code generated by cbindgen 0.12.1 for the `enum TT` + * type in nonclike.rs . */ +enum TT_Tag { + AA, + BB, +}; +typedef uint8_t TT_Tag; + +typedef struct { + uint64_t _0; + uint64_t _1; +} AA_Body; + +typedef struct { + TT_Tag tag; + union { + AA_Body aa; + }; +} TT; + +/* This is the code generated by cbindgen 0.12.1 for the `enum T` type + * in nonclike.rs . */ +enum T_Tag { + A, + B, +}; +typedef uint8_t T_Tag; + +typedef struct { + uint64_t _0; +} A_Body; + +typedef struct { + T_Tag tag; + union { + A_Body a; + }; +} T; + +/* These symbols are defined by the Rust staticlib built from + * nonclike.rs. */ +extern TT tt_new(uint64_t a, uint64_t b); +extern T t_new(uint64_t v); + +int main(int argc, char *argv[]) { + (void)argc; (void)argv; + + /* This example works. */ + TT tt = tt_new(10, 20); + assert(AA == tt.tag); + assert(10 == tt.aa._0); + assert(20 == tt.aa._1); + + /* This one used to segfault (see issue #68190). */ + T t = t_new(10); + assert(A == t.tag); + assert(10 == t.a._0); + + return 0; +} diff --git a/src/test/run-make-fulldeps/rlib-chain/Makefile b/src/test/run-make-fulldeps/rlib-chain/Makefile new file mode 100644 index 000000000..30b6811a3 --- /dev/null +++ b/src/test/run-make-fulldeps/rlib-chain/Makefile @@ -0,0 +1,10 @@ +-include ../tools.mk + +all: + $(RUSTC) m1.rs + $(RUSTC) m2.rs + $(RUSTC) m3.rs + $(RUSTC) m4.rs + $(call RUN,m4) + rm $(TMPDIR)/*lib + $(call RUN,m4) diff --git a/src/test/run-make-fulldeps/rlib-chain/m1.rs b/src/test/run-make-fulldeps/rlib-chain/m1.rs new file mode 100644 index 000000000..665b206cc --- /dev/null +++ b/src/test/run-make-fulldeps/rlib-chain/m1.rs @@ -0,0 +1,2 @@ +#![crate_type = "rlib"] +pub fn m1() {} diff --git a/src/test/run-make-fulldeps/rlib-chain/m2.rs b/src/test/run-make-fulldeps/rlib-chain/m2.rs new file mode 100644 index 000000000..eba12fe12 --- /dev/null +++ b/src/test/run-make-fulldeps/rlib-chain/m2.rs @@ -0,0 +1,4 @@ +#![crate_type = "rlib"] +extern crate m1; + +pub fn m2() { m1::m1() } diff --git a/src/test/run-make-fulldeps/rlib-chain/m3.rs b/src/test/run-make-fulldeps/rlib-chain/m3.rs new file mode 100644 index 000000000..ade191db4 --- /dev/null +++ b/src/test/run-make-fulldeps/rlib-chain/m3.rs @@ -0,0 +1,4 @@ +#![crate_type = "rlib"] +extern crate m2; + +pub fn m3() { m2::m2() } diff --git a/src/test/run-make-fulldeps/rlib-chain/m4.rs b/src/test/run-make-fulldeps/rlib-chain/m4.rs new file mode 100644 index 000000000..fa8ec6079 --- /dev/null +++ b/src/test/run-make-fulldeps/rlib-chain/m4.rs @@ -0,0 +1,3 @@ +extern crate m3; + +fn main() { m3::m3() } diff --git a/src/test/run-make-fulldeps/rustdoc-determinism/Makefile b/src/test/run-make-fulldeps/rustdoc-determinism/Makefile new file mode 100644 index 000000000..0534c2c38 --- /dev/null +++ b/src/test/run-make-fulldeps/rustdoc-determinism/Makefile @@ -0,0 +1,16 @@ +-include ../tools.mk + +# Assert that the search index is generated deterministically, regardless of the +# order that crates are documented in. + +# ignore-windows +# Uses `diff`. + +all: + $(RUSTDOC) foo.rs -o $(TMPDIR)/foo_first + $(RUSTDOC) bar.rs -o $(TMPDIR)/foo_first + + $(RUSTDOC) bar.rs -o $(TMPDIR)/bar_first + $(RUSTDOC) foo.rs -o $(TMPDIR)/bar_first + + diff $(TMPDIR)/foo_first/search-index.js $(TMPDIR)/bar_first/search-index.js diff --git a/src/test/run-make-fulldeps/rustdoc-determinism/bar.rs b/src/test/run-make-fulldeps/rustdoc-determinism/bar.rs new file mode 100644 index 000000000..ca05a6a90 --- /dev/null +++ b/src/test/run-make-fulldeps/rustdoc-determinism/bar.rs @@ -0,0 +1 @@ +pub struct Bar; diff --git a/src/test/run-make-fulldeps/rustdoc-determinism/foo.rs b/src/test/run-make-fulldeps/rustdoc-determinism/foo.rs new file mode 100644 index 000000000..4a835673a --- /dev/null +++ b/src/test/run-make-fulldeps/rustdoc-determinism/foo.rs @@ -0,0 +1 @@ +pub struct Foo; diff --git a/src/test/run-make-fulldeps/rustdoc-error-lines/Makefile b/src/test/run-make-fulldeps/rustdoc-error-lines/Makefile new file mode 100644 index 000000000..c9d41f0ec --- /dev/null +++ b/src/test/run-make-fulldeps/rustdoc-error-lines/Makefile @@ -0,0 +1,13 @@ +-include ../tools.mk + +# Test that hir-tree output doesn't crash and includes +# the string constant we would expect to see. + +all: + $(RUSTDOC) --test input.rs > $(TMPDIR)/output || true + $(CGREP) 'input.rs - foo (line 5)' < $(TMPDIR)/output + $(CGREP) 'input.rs:7:15' < $(TMPDIR)/output + $(CGREP) 'input.rs - bar (line 15)' < $(TMPDIR)/output + $(CGREP) 'input.rs:17:15' < $(TMPDIR)/output + $(CGREP) 'input.rs - bar (line 24)' < $(TMPDIR)/output + $(CGREP) 'input.rs:26:15' < $(TMPDIR)/output diff --git a/src/test/run-make-fulldeps/rustdoc-error-lines/input.rs b/src/test/run-make-fulldeps/rustdoc-error-lines/input.rs new file mode 100644 index 000000000..b4db182e8 --- /dev/null +++ b/src/test/run-make-fulldeps/rustdoc-error-lines/input.rs @@ -0,0 +1,28 @@ +// Test for #45868 + +// random #![feature] to ensure that crate attrs +// do not offset things +/// ```rust +/// #![feature(bool_to_option)] +/// let x: char = 1; +/// ``` +pub fn foo() { + +} + +/// Add some text around the test... +/// +/// ```rust +/// #![feature(bool_to_option)] +/// let x: char = 1; +/// ``` +/// +/// ...to make sure that the line number is still correct. +/// +/// Let's also add a second test in the same doc comment. +/// +/// ```rust +/// #![feature(bool_to_option)] +/// let x: char = 1; +/// ``` +pub fn bar() {} diff --git a/src/test/run-make-fulldeps/rustdoc-io-error/Makefile b/src/test/run-make-fulldeps/rustdoc-io-error/Makefile new file mode 100644 index 000000000..f95fa88d4 --- /dev/null +++ b/src/test/run-make-fulldeps/rustdoc-io-error/Makefile @@ -0,0 +1,20 @@ +-include ../tools.mk + +# This test verifies that rustdoc doesn't ICE when it encounters an IO error +# while generating files. Ideally this would be a rustdoc-ui test, so we could +# verify the error message as well. + +# ignore-windows +# The test uses `chmod`. + +OUTPUT_DIR := "$(TMPDIR)/rustdoc-io-error" + +# This test operates by creating a temporary directory and modifying its +# permissions so that it is not writable. We have to take special care to set +# the permissions back to normal so that it's able to be deleted later. +all: + mkdir -p $(OUTPUT_DIR) + chmod u-w $(OUTPUT_DIR) + -$(shell $(RUSTDOC) -o $(OUTPUT_DIR) foo.rs) + chmod u+w $(OUTPUT_DIR) + exit $($(.SHELLSTATUS) -eq 1) diff --git a/src/test/run-make-fulldeps/rustdoc-io-error/foo.rs b/src/test/run-make-fulldeps/rustdoc-io-error/foo.rs new file mode 100644 index 000000000..4a835673a --- /dev/null +++ b/src/test/run-make-fulldeps/rustdoc-io-error/foo.rs @@ -0,0 +1 @@ +pub struct Foo; diff --git a/src/test/run-make-fulldeps/rustdoc-map-file/Makefile b/src/test/run-make-fulldeps/rustdoc-map-file/Makefile new file mode 100644 index 000000000..ce977fa0c --- /dev/null +++ b/src/test/run-make-fulldeps/rustdoc-map-file/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: + $(RUSTDOC) -Z unstable-options --generate-redirect-map foo.rs -o "$(TMPDIR)/out" + "$(PYTHON)" validate_json.py "$(TMPDIR)/out" diff --git a/src/test/run-make-fulldeps/rustdoc-map-file/expected.json b/src/test/run-make-fulldeps/rustdoc-map-file/expected.json new file mode 100644 index 000000000..6b1ccbeac --- /dev/null +++ b/src/test/run-make-fulldeps/rustdoc-map-file/expected.json @@ -0,0 +1,5 @@ +{ + "foo/macro.foo!.html": "foo/macro.foo.html", + "foo/private/struct.Quz.html": "foo/struct.Quz.html", + "foo/hidden/struct.Bar.html": "foo/struct.Bar.html" +} diff --git a/src/test/run-make-fulldeps/rustdoc-map-file/foo.rs b/src/test/run-make-fulldeps/rustdoc-map-file/foo.rs new file mode 100644 index 000000000..e12b9d229 --- /dev/null +++ b/src/test/run-make-fulldeps/rustdoc-map-file/foo.rs @@ -0,0 +1,16 @@ +pub use private::Quz; +pub use hidden::Bar; + +mod private { + pub struct Quz; +} + +#[doc(hidden)] +pub mod hidden { + pub struct Bar; +} + +#[macro_export] +macro_rules! foo { + () => {} +} diff --git a/src/test/run-make-fulldeps/rustdoc-map-file/validate_json.py b/src/test/run-make-fulldeps/rustdoc-map-file/validate_json.py new file mode 100755 index 000000000..5c14c90b7 --- /dev/null +++ b/src/test/run-make-fulldeps/rustdoc-map-file/validate_json.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python + +import os +import sys +import json + + +def find_redirect_map_file(folder, errors): + for root, dirs, files in os.walk(folder): + for name in files: + if not name.endswith("redirect-map.json"): + continue + with open(os.path.join(root, name)) as f: + data = json.load(f) + with open("expected.json") as f: + expected = json.load(f) + for key in expected: + if expected[key] != data.get(key): + errors.append("Expected `{}` for key `{}`, found: `{}`".format( + expected[key], key, data.get(key))) + else: + del data[key] + for key in data: + errors.append("Extra data not expected: key: `{}`, data: `{}`".format( + key, data[key])) + return True + return False + + +if len(sys.argv) != 2: + print("Expected doc directory to check!") + sys.exit(1) + +errors = [] +if not find_redirect_map_file(sys.argv[1], errors): + print("Didn't find the map file in `{}`...".format(sys.argv[1])) + sys.exit(1) +for err in errors: + print("=> {}".format(err)) +if len(errors) != 0: + sys.exit(1) diff --git a/src/test/run-make-fulldeps/rustdoc-output-path/Makefile b/src/test/run-make-fulldeps/rustdoc-output-path/Makefile new file mode 100644 index 000000000..8ce1c6995 --- /dev/null +++ b/src/test/run-make-fulldeps/rustdoc-output-path/Makefile @@ -0,0 +1,4 @@ +-include ../tools.mk + +all: + $(RUSTDOC) -o "$(TMPDIR)/foo/bar/doc" foo.rs diff --git a/src/test/run-make-fulldeps/rustdoc-output-path/foo.rs b/src/test/run-make-fulldeps/rustdoc-output-path/foo.rs new file mode 100644 index 000000000..4a835673a --- /dev/null +++ b/src/test/run-make-fulldeps/rustdoc-output-path/foo.rs @@ -0,0 +1 @@ +pub struct Foo; diff --git a/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/Makefile b/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/Makefile new file mode 100644 index 000000000..4934e875d --- /dev/null +++ b/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/Makefile @@ -0,0 +1,18 @@ +-include ../../run-make-fulldeps/tools.mk + +OUTPUT_DIR := "$(TMPDIR)/rustdoc" +DYLIB_NAME := $(shell echo | $(RUSTC) --crate-name foobar_macro --crate-type dylib --print file-names -) + +all: + $(RUSTC) src/proc.rs --crate-name foobar_macro --edition=2021 --crate-type proc-macro --emit=dep-info,link + + $(RUSTC) src/lib.rs --crate-name foobar --edition=2021 --crate-type lib --emit=dep-info,link + + $(RUSTDOC) examples/ex.rs --crate-name ex --crate-type bin --output $(OUTPUT_DIR) \ + --extern foobar=$(TMPDIR)/libfoobar.rlib --extern foobar_macro=$(TMPDIR)/$(DYLIB_NAME) \ + -Z unstable-options --scrape-examples-output-path $(TMPDIR)/ex.calls --scrape-examples-target-crate foobar + + $(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --output $(OUTPUT_DIR) \ + -Z unstable-options --with-examples $(TMPDIR)/ex.calls + + $(HTMLDOCCK) $(OUTPUT_DIR) src/lib.rs diff --git a/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/examples/ex.rs b/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/examples/ex.rs new file mode 100644 index 000000000..4d8c8b30e --- /dev/null +++ b/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/examples/ex.rs @@ -0,0 +1,27 @@ +extern crate foobar; +extern crate foobar_macro; + +use foobar::*; +use foobar_macro::*; + +a_proc_macro!(); // no + +#[an_attr_macro] +fn a() { + f(); // no +} + +#[an_attr_macro(with_span)] +fn b() { + f(); // yes +} + +fn c() { + a_rules_macro!(f()); // yes +} + +fn d() { + a_rules_macro!(()); // no +} + +fn main(){} diff --git a/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/lib.rs b/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/lib.rs new file mode 100644 index 000000000..bac3970a4 --- /dev/null +++ b/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/lib.rs @@ -0,0 +1,12 @@ +// Scraped example should only include line numbers for items b and c in ex.rs +// @!has foobar/fn.f.html '//*[@class="line-numbers"]' '14' +// @has foobar/fn.f.html '//*[@class="line-numbers"]' '15' +// @has foobar/fn.f.html '//*[@class="line-numbers"]' '21' +// @!has foobar/fn.f.html '//*[@class="line-numbers"]' '22' + +pub fn f() {} + +#[macro_export] +macro_rules! a_rules_macro { + ($e:expr) => { ($e, foobar::f()); } +} diff --git a/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/proc.rs b/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/proc.rs new file mode 100644 index 000000000..46e518fdf --- /dev/null +++ b/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/proc.rs @@ -0,0 +1,39 @@ +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro] +pub fn a_proc_macro(_item: TokenStream) -> TokenStream { + "fn ex() { foobar::f(); }".parse().unwrap() +} + +// inserts foobar::f() to the end of the function +#[proc_macro_attribute] +pub fn an_attr_macro(attr: TokenStream, item: TokenStream) -> TokenStream { + let new_call: TokenStream = "foobar::f();".parse().unwrap(); + + let mut tokens = item.into_iter(); + + let fn_tok = tokens.next().unwrap(); + let ident_tok = tokens.next().unwrap(); + let args_tok = tokens.next().unwrap(); + let body = match tokens.next().unwrap() { + TokenTree::Group(g) => { + let new_g = Group::new(g.delimiter(), new_call); + let mut outer_g = Group::new( + g.delimiter(), + [TokenTree::Group(g.clone()), TokenTree::Group(new_g)].into_iter().collect(), + ); + + if attr.to_string() == "with_span" { + outer_g.set_span(g.span()); + } + + TokenTree::Group(outer_g) + } + _ => unreachable!(), + }; + + let tokens = vec![fn_tok, ident_tok, args_tok, body].into_iter().collect::<TokenStream>(); + + tokens +} diff --git a/src/test/run-make-fulldeps/rustdoc-target-spec-json-path/Makefile b/src/test/run-make-fulldeps/rustdoc-target-spec-json-path/Makefile new file mode 100644 index 000000000..6d0bc4186 --- /dev/null +++ b/src/test/run-make-fulldeps/rustdoc-target-spec-json-path/Makefile @@ -0,0 +1,9 @@ +include ../tools.mk + +# Test that rustdoc will properly canonicalize the target spec json path just like rustc + +OUTPUT_DIR := "$(TMPDIR)/rustdoc-target-spec-json-path" + +all: + $(RUSTC) --crate-type lib dummy_core.rs --target target.json + $(RUSTDOC) -o $(OUTPUT_DIR) -L $(TMPDIR) my_crate.rs --target target.json diff --git a/src/test/run-make-fulldeps/rustdoc-target-spec-json-path/dummy_core.rs b/src/test/run-make-fulldeps/rustdoc-target-spec-json-path/dummy_core.rs new file mode 100644 index 000000000..da27b7f34 --- /dev/null +++ b/src/test/run-make-fulldeps/rustdoc-target-spec-json-path/dummy_core.rs @@ -0,0 +1,2 @@ +#![feature(no_core)] +#![no_core] diff --git a/src/test/run-make-fulldeps/rustdoc-target-spec-json-path/my_crate.rs b/src/test/run-make-fulldeps/rustdoc-target-spec-json-path/my_crate.rs new file mode 100644 index 000000000..12aa08220 --- /dev/null +++ b/src/test/run-make-fulldeps/rustdoc-target-spec-json-path/my_crate.rs @@ -0,0 +1,3 @@ +#![feature(no_core)] +#![no_core] +extern crate dummy_core; diff --git a/src/test/run-make-fulldeps/rustdoc-target-spec-json-path/target.json b/src/test/run-make-fulldeps/rustdoc-target-spec-json-path/target.json new file mode 100644 index 000000000..34357182c --- /dev/null +++ b/src/test/run-make-fulldeps/rustdoc-target-spec-json-path/target.json @@ -0,0 +1,38 @@ +{ + "arch": "x86_64", + "cpu": "x86-64", + "crt-static-respected": true, + "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", + "dynamic-linking": true, + "env": "gnu", + "executables": true, + "has-elf-tls": true, + "has-rpath": true, + "linker-is-gnu": true, + "llvm-target": "x86_64-unknown-linux-gnu", + "max-atomic-width": 64, + "os": "linux", + "position-independent-executables": true, + "pre-link-args": { + "gcc": [ + "-m64" + ] + }, + "relro-level": "full", + "stack-probes": { + "kind": "inline-or-call", + "min-llvm-version-for-inline": [ + 11, + 0, + 1 + ] + }, + "supported-sanitizers": [ + "address", + "leak", + "memory", + "thread" + ], + "target-family": "unix", + "target-pointer-width": "64" +} diff --git a/src/test/run-make-fulldeps/rustdoc-themes/Makefile b/src/test/run-make-fulldeps/rustdoc-themes/Makefile new file mode 100644 index 000000000..f3d07b25c --- /dev/null +++ b/src/test/run-make-fulldeps/rustdoc-themes/Makefile @@ -0,0 +1,10 @@ +-include ../tools.mk + +# Test that rustdoc will properly load in a theme file and display it in the theme selector. + +OUTPUT_DIR := "$(TMPDIR)/rustdoc-themes" + +all: + cp $(S)/src/librustdoc/html/static/css/themes/light.css $(TMPDIR)/test.css + $(RUSTDOC) -o $(OUTPUT_DIR) foo.rs --theme $(TMPDIR)/test.css + $(HTMLDOCCK) $(OUTPUT_DIR) foo.rs diff --git a/src/test/run-make-fulldeps/rustdoc-themes/foo.rs b/src/test/run-make-fulldeps/rustdoc-themes/foo.rs new file mode 100644 index 000000000..58efaf7d5 --- /dev/null +++ b/src/test/run-make-fulldeps/rustdoc-themes/foo.rs @@ -0,0 +1,4 @@ +// @has test.css +// @has foo/struct.Foo.html +// @has - '//link[@rel="stylesheet"]/@href' '../test.css' +pub struct Foo; diff --git a/src/test/run-make-fulldeps/sanitizer-cdylib-link/Makefile b/src/test/run-make-fulldeps/sanitizer-cdylib-link/Makefile new file mode 100644 index 000000000..e72fe5a50 --- /dev/null +++ b/src/test/run-make-fulldeps/sanitizer-cdylib-link/Makefile @@ -0,0 +1,16 @@ +# needs-sanitizer-support +# needs-sanitizer-address + +-include ../tools.mk + +LOG := $(TMPDIR)/log.txt + +# This test builds a shared object, then an executable that links it as a native +# rust library (contrast to an rlib). The shared library and executable both +# are compiled with address sanitizer, and we assert that a fault in the cdylib +# is correctly detected. + +all: + $(RUSTC) -g -Z sanitizer=address --crate-type cdylib --target $(TARGET) library.rs + $(RUSTC) -g -Z sanitizer=address --crate-type bin --target $(TARGET) -llibrary program.rs + LD_LIBRARY_PATH=$(TMPDIR) $(TMPDIR)/program 2>&1 | $(CGREP) stack-buffer-overflow diff --git a/src/test/run-make-fulldeps/sanitizer-cdylib-link/library.rs b/src/test/run-make-fulldeps/sanitizer-cdylib-link/library.rs new file mode 100644 index 000000000..f2a52cb5c --- /dev/null +++ b/src/test/run-make-fulldeps/sanitizer-cdylib-link/library.rs @@ -0,0 +1,5 @@ +#[no_mangle] +pub extern "C" fn overflow() { + let xs = [0, 1, 2, 3]; + let _y = unsafe { *xs.as_ptr().offset(4) }; +} diff --git a/src/test/run-make-fulldeps/sanitizer-cdylib-link/program.rs b/src/test/run-make-fulldeps/sanitizer-cdylib-link/program.rs new file mode 100644 index 000000000..ef053aa2e --- /dev/null +++ b/src/test/run-make-fulldeps/sanitizer-cdylib-link/program.rs @@ -0,0 +1,7 @@ +extern "C" { + fn overflow(); +} + +fn main() { + unsafe { overflow() } +} diff --git a/src/test/run-make-fulldeps/sanitizer-dylib-link/Makefile b/src/test/run-make-fulldeps/sanitizer-dylib-link/Makefile new file mode 100644 index 000000000..b9a3f8295 --- /dev/null +++ b/src/test/run-make-fulldeps/sanitizer-dylib-link/Makefile @@ -0,0 +1,16 @@ +# needs-sanitizer-support +# needs-sanitizer-address + +-include ../tools.mk + +LOG := $(TMPDIR)/log.txt + +# This test builds a shared object, then an executable that links it as a native +# rust library (contrast to an rlib). The shared library and executable both +# are compiled with address sanitizer, and we assert that a fault in the dylib +# is correctly detected. + +all: + $(RUSTC) -g -Z sanitizer=address --crate-type dylib --target $(TARGET) library.rs + $(RUSTC) -g -Z sanitizer=address --crate-type bin --target $(TARGET) -llibrary program.rs + LD_LIBRARY_PATH=$(TMPDIR) $(TMPDIR)/program 2>&1 | $(CGREP) stack-buffer-overflow diff --git a/src/test/run-make-fulldeps/sanitizer-dylib-link/library.rs b/src/test/run-make-fulldeps/sanitizer-dylib-link/library.rs new file mode 100644 index 000000000..f2a52cb5c --- /dev/null +++ b/src/test/run-make-fulldeps/sanitizer-dylib-link/library.rs @@ -0,0 +1,5 @@ +#[no_mangle] +pub extern "C" fn overflow() { + let xs = [0, 1, 2, 3]; + let _y = unsafe { *xs.as_ptr().offset(4) }; +} diff --git a/src/test/run-make-fulldeps/sanitizer-dylib-link/program.rs b/src/test/run-make-fulldeps/sanitizer-dylib-link/program.rs new file mode 100644 index 000000000..ef053aa2e --- /dev/null +++ b/src/test/run-make-fulldeps/sanitizer-dylib-link/program.rs @@ -0,0 +1,7 @@ +extern "C" { + fn overflow(); +} + +fn main() { + unsafe { overflow() } +} diff --git a/src/test/run-make-fulldeps/sanitizer-staticlib-link/Makefile b/src/test/run-make-fulldeps/sanitizer-staticlib-link/Makefile new file mode 100644 index 000000000..4894f65b1 --- /dev/null +++ b/src/test/run-make-fulldeps/sanitizer-staticlib-link/Makefile @@ -0,0 +1,20 @@ +# needs-sanitizer-support +# needs-sanitizer-address + +-include ../tools.mk + +# This test first builds a staticlib with AddressSanitizer and checks that +# linking it to an executable fails due to the missing sanitizer runtime. +# It then builds an executable linking to the staticlib and checks that +# the fault in the staticlib is detected correctly. + +# Note that checking for the link failure actually checks two things at once: +# 1) That the library has the sanitizer intrumentation +# 2) and that library does not have the sanitizer runtime + +all: + $(RUSTC) -g -Z sanitizer=address --crate-type staticlib --target $(TARGET) library.rs + ! $(CC) program.c $(call STATICLIB,library) $(call OUT_EXE,program) $(EXTRACFLAGS) $(EXTRACXXFLAGS) + $(RUSTC) -g -Z sanitizer=address --crate-type bin --target $(TARGET) -L . program.rs + LD_LIBRARY_PATH=$(TMPDIR) $(TMPDIR)/program 2>&1 | $(CGREP) stack-buffer-overflow + diff --git a/src/test/run-make-fulldeps/sanitizer-staticlib-link/library.rs b/src/test/run-make-fulldeps/sanitizer-staticlib-link/library.rs new file mode 100644 index 000000000..f2a52cb5c --- /dev/null +++ b/src/test/run-make-fulldeps/sanitizer-staticlib-link/library.rs @@ -0,0 +1,5 @@ +#[no_mangle] +pub extern "C" fn overflow() { + let xs = [0, 1, 2, 3]; + let _y = unsafe { *xs.as_ptr().offset(4) }; +} diff --git a/src/test/run-make-fulldeps/sanitizer-staticlib-link/program.c b/src/test/run-make-fulldeps/sanitizer-staticlib-link/program.c new file mode 100644 index 000000000..735e2b147 --- /dev/null +++ b/src/test/run-make-fulldeps/sanitizer-staticlib-link/program.c @@ -0,0 +1,6 @@ +void overflow(); + +int main() { + overflow(); + return 0; +} diff --git a/src/test/run-make-fulldeps/sanitizer-staticlib-link/program.rs b/src/test/run-make-fulldeps/sanitizer-staticlib-link/program.rs new file mode 100644 index 000000000..ec59bdb11 --- /dev/null +++ b/src/test/run-make-fulldeps/sanitizer-staticlib-link/program.rs @@ -0,0 +1,10 @@ +#[link(name = "library")] +extern "C" { + fn overflow(); +} + +fn main() { + unsafe { + overflow(); + } +} diff --git a/src/test/run-make-fulldeps/save-analysis-fail/Makefile b/src/test/run-make-fulldeps/save-analysis-fail/Makefile new file mode 100644 index 000000000..f29f907cf --- /dev/null +++ b/src/test/run-make-fulldeps/save-analysis-fail/Makefile @@ -0,0 +1,6 @@ +-include ../tools.mk +all: code +krate2: krate2.rs + $(RUSTC) $< +code: foo.rs krate2 + $(RUSTC) foo.rs -Zsave-analysis || exit 0 diff --git a/src/test/run-make-fulldeps/save-analysis-fail/SameDir.rs b/src/test/run-make-fulldeps/save-analysis-fail/SameDir.rs new file mode 100644 index 000000000..2c690d5f7 --- /dev/null +++ b/src/test/run-make-fulldeps/save-analysis-fail/SameDir.rs @@ -0,0 +1,5 @@ +// sub-module in the same directory as the main crate file + +pub struct SameStruct { + pub name: String +} diff --git a/src/test/run-make-fulldeps/save-analysis-fail/SameDir3.rs b/src/test/run-make-fulldeps/save-analysis-fail/SameDir3.rs new file mode 100644 index 000000000..fab03ee2e --- /dev/null +++ b/src/test/run-make-fulldeps/save-analysis-fail/SameDir3.rs @@ -0,0 +1,3 @@ +pub fn hello(x: isize) { + println!("macro {} :-(", x); +} diff --git a/src/test/run-make-fulldeps/save-analysis-fail/SubDir/mod.rs b/src/test/run-make-fulldeps/save-analysis-fail/SubDir/mod.rs new file mode 100644 index 000000000..511721d92 --- /dev/null +++ b/src/test/run-make-fulldeps/save-analysis-fail/SubDir/mod.rs @@ -0,0 +1,27 @@ +// sub-module in a sub-directory + +use sub::sub2 as msalias; +use sub::sub2; + +static yy: usize = 25; + +mod sub { + pub mod sub2 { + pub mod sub3 { + pub fn hello() { + println!("hello from module 3"); + } + } + pub fn hello() { + println!("hello from a module"); + } + + pub struct nested_struct { + pub field2: u32, + } + } +} + +pub struct SubStruct { + pub name: String +} diff --git a/src/test/run-make-fulldeps/save-analysis-fail/foo.rs b/src/test/run-make-fulldeps/save-analysis-fail/foo.rs new file mode 100644 index 000000000..94879c2a6 --- /dev/null +++ b/src/test/run-make-fulldeps/save-analysis-fail/foo.rs @@ -0,0 +1,464 @@ +#![crate_name = "test"] +#![feature(box_syntax)] +#![feature(rustc_private)] + +extern crate rustc_graphviz; +// A simple rust project + +extern crate krate2; +extern crate krate2 as krate3; + +use rustc_graphviz::RenderOption; +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; + +use std::mem::size_of; + +use std::char::from_u32; + +static uni: &'static str = "Les Miséééééééérables"; +static yy: usize = 25; + +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 }; + + // import tests + fn foo(x: &Write) {} + let _: Option<_> = from_u32(45); + + let x = 42usize; + + krate2::hello(); + krate3::hello(); + + let x = (3isize, 4usize); + let y = x.1; +} + +// Issue #37700 +const LUT_BITS: usize = 3; +pub struct HuffmanTable { + ac_lut: Option<[(i16, u8); 1 << LUT_BITS]>, +} + +struct TupStruct(isize, isize, Box<str>); + +fn test_tup_struct(x: TupStruct) -> isize { + x.1 +} + +fn println(s: &str) { + std::io::stdout().write_all(s.as_bytes()); +} + +mod sub { + pub mod sub2 { + use std::io::Write; + pub mod sub3 { + use std::io::Write; + pub fn hello() { + ::println("hello from module 3"); + } + } + pub fn hello() { + ::println("hello from a module"); + } + + pub struct nested_struct { + pub field2: u32, + } + + pub enum nested_enum { + Nest2 = 2, + Nest3 = 3, + } + } +} + +pub mod SameDir; +pub mod SubDir; + +#[path = "SameDir3.rs"] +pub mod SameDir2; + +struct nofields; + +#[derive(Clone)] +struct some_fields { + field1: u32, +} + +type SF = some_fields; + +trait SuperTrait { + fn qux(&self) { + panic!(); + } +} + +trait SomeTrait: SuperTrait { + fn Method(&self, x: u32) -> u32; + + fn prov(&self, x: u32) -> u32 { + println(&x.to_string()); + 42 + } + fn provided_method(&self) -> u32 { + 42 + } +} + +trait SubTrait: SomeTrait { + fn stat2(x: &Self) -> u32 { + 32 + } +} + +trait SizedTrait: Sized {} + +fn error(s: &SizedTrait) { + let foo = 42; + println!("Hello world! {}", foo); +} + +impl SomeTrait for some_fields { + fn Method(&self, x: u32) -> u32 { + println(&x.to_string()); + self.field1 + } +} + +impl SuperTrait for some_fields {} + +impl SubTrait for some_fields {} + +impl some_fields { + fn stat(x: u32) -> u32 { + println(&x.to_string()); + 42 + } + fn stat2(x: &some_fields) -> u32 { + 42 + } + + fn align_to<T>(&mut self) {} + + fn test(&mut self) { + self.align_to::<bool>(); + } +} + +impl SuperTrait for nofields {} +impl SomeTrait for nofields { + fn Method(&self, x: u32) -> u32 { + self.Method(x); + 43 + } + + fn provided_method(&self) -> u32 { + 21 + } +} + +impl SubTrait for nofields {} + +impl SuperTrait for (Box<nofields>, Box<some_fields>) {} + +fn f_with_params<T: SomeTrait>(x: &T) { + x.Method(41); +} + +type MyType = Box<some_fields>; + +enum SomeEnum<'a> { + Ints(isize, isize), + Floats(f64, f64), + Strings(&'a str, &'a str, &'a str), + MyTypes(MyType, MyType), +} + +#[derive(Copy, Clone)] +enum SomeOtherEnum { + SomeConst1, + SomeConst2, + SomeConst3, +} + +enum SomeStructEnum { + 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()); + } + } +} + +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()), + } +} + +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()), + _ => {} + } +} + +fn matchSomeOtherEnum(val: SomeOtherEnum) { + use SomeOtherEnum::{SomeConst2, SomeConst3}; + match val { + SomeOtherEnum::SomeConst1 => { + println("I'm const1."); + } + SomeConst2 | SomeConst3 => { + println("I'm const2 or const3."); + } + } +} + +fn hello<X: SomeTrait>((z, a): (u32, String), ex: X) { + SameDir2::hello(43); + + println(&yy.to_string()); + let (x, y): (u32, u32) = (5, 3); + println(&x.to_string()); + println(&z.to_string()); + let x: u32 = x; + println(&x.to_string()); + let x = "hello"; + println(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 s3 = box nofields; + + s.Method(43); + s3.Method(43); + s2.Method(43); + + ex.prov(43); + + let y: u32 = 56; + // static method on struct + let r = some_fields::stat(y); + // trait static method, calls default + let r = SubTrait::stat2(&*s3); + + let s4 = s3 as Box<SomeTrait>; + s4.Method(43); + + s4.provided_method(); + s2.prov(45); + + let closure = |x: u32, s: &SomeTrait| { + s.Method(23); + return x + y; + }; + + let z = closure(10, &*s); +} + +pub struct blah { + used_link_args: RefCell<[&'static str; 0]>, +} + +#[macro_use] +mod macro_use_test { + macro_rules! test_rec { + (q, $src: expr) => {{ + print!("{}", $src); + test_rec!($src); + }}; + ($src: expr) => { + print!("{}", $src); + }; + } + + macro_rules! internal_vars { + ($src: ident) => {{ + let mut x = $src; + x += 100; + }}; + } +} + +fn main() { + // foo + let s = box some_fields { field1: 43 }; + hello((43, "a".to_string()), *s); + sub::sub2::hello(); + sub2::sub3::hello(); + + let h = sub2::sub3::hello; + h(); + + // utf8 chars + let ut = "Les Miséééééééérables"; + + // For some reason, this pattern of macro_rules foiled our generated code + // avoiding strategy. + macro_rules! variable_str(($name:expr) => ( + some_fields { + field1: $name, + } + )); + 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 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 }; + 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 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 }; + matchSomeStructEnum(s9); + + for x in &vec![1, 2, 3] { + let _y = x; + } + + let s7: SomeEnum = SomeEnum::Strings("one", "two", "three"); + if let SomeEnum::Strings(..) = s7 { + println!("hello!"); + } + + for i in 0..5 { + foo_foo(i); + } + + if let Some(x) = None { + foo_foo(x); + } + + if false { + } else if let Some(y) = None { + foo_foo(y); + } + + while let Some(z) = None { + foo_foo(z); + } + + let mut x = 4; + test_rec!(q, "Hello"); + assert_eq!(x, 4); + internal_vars!(x); +} + +fn foo_foo(_: i32) {} + +impl Iterator for nofields { + type Item = (usize, usize); + + fn next(&mut self) -> Option<(usize, usize)> { + panic!() + } + + fn size_hint(&self) -> (usize, Option<usize>) { + panic!() + } +} + +trait Pattern<'a> { + type Searcher; +} + +struct CharEqPattern; + +impl<'a> Pattern<'a> for CharEqPattern { + type Searcher = CharEqPattern; +} + +struct CharSearcher<'a>(<CharEqPattern as Pattern<'a>>::Searcher); + +pub trait Error {} + +impl Error + 'static { + pub fn is<T: Error + 'static>(&self) -> bool { + panic!() + } +} + +impl Error + 'static + Send { + pub fn is<T: Error + 'static>(&self) -> bool { + <Error + 'static>::is::<T>(self) + } +} +extern crate serialize; +#[derive(Clone, Copy, Hash, Encodable, Decodable, PartialEq, Eq, PartialOrd, Ord, Debug, Default)] +struct AllDerives(i32); + +fn test_format_args() { + let x = 1; + let y = 2; + let name = "Joe Blogg"; + println!("Hello {}", name); + print!("Hello {0}", name); + print!("{0} + {} = {}", x, y); + print!("x is {}, y is {1}, name is {n}", x, y, n = name); +} + +extern "C" { + static EXTERN_FOO: u8; + fn extern_foo(a: u8, b: i32) -> String; +} + +struct Rls699 { + f: u32, +} + +fn new(f: u32) -> Rls699 { + Rls699 { fs } +} + +fn invalid_tuple_struct_access() { + bar.0; + + struct S; + S.0; +} diff --git a/src/test/run-make-fulldeps/save-analysis-fail/krate2.rs b/src/test/run-make-fulldeps/save-analysis-fail/krate2.rs new file mode 100644 index 000000000..7d787e0c9 --- /dev/null +++ b/src/test/run-make-fulldeps/save-analysis-fail/krate2.rs @@ -0,0 +1,8 @@ +#![ crate_name = "krate2" ] +#![ crate_type = "lib" ] + +use std::io::Write; + +pub fn hello() { + std::io::stdout().write_all(b"hello world!\n"); +} diff --git a/src/test/run-make-fulldeps/save-analysis-rfc2126/Makefile b/src/test/run-make-fulldeps/save-analysis-rfc2126/Makefile new file mode 100644 index 000000000..36288c4b8 --- /dev/null +++ b/src/test/run-make-fulldeps/save-analysis-rfc2126/Makefile @@ -0,0 +1,8 @@ +-include ../tools.mk + +all: extern_absolute_paths.rs krate2 + $(RUSTC) extern_absolute_paths.rs -Zsave-analysis --edition=2018 --extern krate2 + cat $(TMPDIR)/save-analysis/extern_absolute_paths.json | "$(PYTHON)" validate_json.py + +krate2: krate2.rs + $(RUSTC) $< diff --git a/src/test/run-make-fulldeps/save-analysis-rfc2126/extern_absolute_paths.rs b/src/test/run-make-fulldeps/save-analysis-rfc2126/extern_absolute_paths.rs new file mode 100644 index 000000000..7a8e3fff0 --- /dev/null +++ b/src/test/run-make-fulldeps/save-analysis-rfc2126/extern_absolute_paths.rs @@ -0,0 +1,6 @@ +use krate2::hello; + +fn main() { + hello(); + ::krate2::hello(); +} diff --git a/src/test/run-make-fulldeps/save-analysis-rfc2126/krate2.rs b/src/test/run-make-fulldeps/save-analysis-rfc2126/krate2.rs new file mode 100644 index 000000000..d24c68862 --- /dev/null +++ b/src/test/run-make-fulldeps/save-analysis-rfc2126/krate2.rs @@ -0,0 +1,5 @@ +#![crate_name = "krate2"] +#![crate_type = "lib"] + +pub fn hello() { +} diff --git a/src/test/run-make-fulldeps/save-analysis-rfc2126/validate_json.py b/src/test/run-make-fulldeps/save-analysis-rfc2126/validate_json.py new file mode 100644 index 000000000..882d29a8b --- /dev/null +++ b/src/test/run-make-fulldeps/save-analysis-rfc2126/validate_json.py @@ -0,0 +1,7 @@ +#!/usr/bin/env python + +import sys +import json + +crates = json.loads(sys.stdin.readline().strip())["prelude"]["external_crates"] +assert any(map(lambda c: c["id"]["name"] == "krate2", crates)) diff --git a/src/test/run-make-fulldeps/save-analysis/Makefile b/src/test/run-make-fulldeps/save-analysis/Makefile new file mode 100644 index 000000000..7296fb9cc --- /dev/null +++ b/src/test/run-make-fulldeps/save-analysis/Makefile @@ -0,0 +1,6 @@ +-include ../tools.mk +all: code +krate2: krate2.rs + $(RUSTC) $< +code: foo.rs krate2 + $(RUSTC) foo.rs -Zsave-analysis diff --git a/src/test/run-make-fulldeps/save-analysis/SameDir.rs b/src/test/run-make-fulldeps/save-analysis/SameDir.rs new file mode 100644 index 000000000..2c690d5f7 --- /dev/null +++ b/src/test/run-make-fulldeps/save-analysis/SameDir.rs @@ -0,0 +1,5 @@ +// sub-module in the same directory as the main crate file + +pub struct SameStruct { + pub name: String +} diff --git a/src/test/run-make-fulldeps/save-analysis/SameDir3.rs b/src/test/run-make-fulldeps/save-analysis/SameDir3.rs new file mode 100644 index 000000000..fab03ee2e --- /dev/null +++ b/src/test/run-make-fulldeps/save-analysis/SameDir3.rs @@ -0,0 +1,3 @@ +pub fn hello(x: isize) { + println!("macro {} :-(", x); +} diff --git a/src/test/run-make-fulldeps/save-analysis/SubDir/mod.rs b/src/test/run-make-fulldeps/save-analysis/SubDir/mod.rs new file mode 100644 index 000000000..511721d92 --- /dev/null +++ b/src/test/run-make-fulldeps/save-analysis/SubDir/mod.rs @@ -0,0 +1,27 @@ +// sub-module in a sub-directory + +use sub::sub2 as msalias; +use sub::sub2; + +static yy: usize = 25; + +mod sub { + pub mod sub2 { + pub mod sub3 { + pub fn hello() { + println!("hello from module 3"); + } + } + pub fn hello() { + println!("hello from a module"); + } + + pub struct nested_struct { + pub field2: u32, + } + } +} + +pub struct SubStruct { + pub name: String +} diff --git a/src/test/run-make-fulldeps/save-analysis/extra-docs.md b/src/test/run-make-fulldeps/save-analysis/extra-docs.md new file mode 100644 index 000000000..0605ca517 --- /dev/null +++ b/src/test/run-make-fulldeps/save-analysis/extra-docs.md @@ -0,0 +1 @@ +Extra docs for this struct. diff --git a/src/test/run-make-fulldeps/save-analysis/foo.rs b/src/test/run-make-fulldeps/save-analysis/foo.rs new file mode 100644 index 000000000..dd7067503 --- /dev/null +++ b/src/test/run-make-fulldeps/save-analysis/foo.rs @@ -0,0 +1,461 @@ +#![crate_name = "test"] +#![feature(box_syntax)] +#![feature(rustc_private)] +#![feature(associated_type_defaults)] + +extern crate rustc_graphviz; +// A simple rust project + +extern crate krate2; +extern crate krate2 as krate3; + +use rustc_graphviz::RenderOption; +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; + +use std::mem::size_of; + +use std::char::from_u32; + +static uni: &'static str = "Les Miséééééééérables"; +static yy: usize = 25; + +static bob: Option<rustc_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 }; + + // import tests + fn foo(x: &Write) {} + let _: Option<_> = from_u32(45); + + let x = 42usize; + + krate2::hello(); + krate3::hello(); + + let x = (3isize, 4usize); + let y = x.1; +} + +// Issue #37700 +const LUT_BITS: usize = 3; +pub struct HuffmanTable { + ac_lut: Option<[(i16, u8); 1 << LUT_BITS]>, +} + +struct TupStruct(isize, isize, Box<str>); + +fn test_tup_struct(x: TupStruct) -> isize { + x.1 +} + +fn println(s: &str) { + std::io::stdout().write_all(s.as_bytes()); +} + +mod sub { + pub mod sub2 { + use std::io::Write; + pub mod sub3 { + use std::io::Write; + pub fn hello() { + ::println("hello from module 3"); + } + } + pub fn hello() { + ::println("hello from a module"); + } + + pub struct nested_struct { + pub field2: u32, + } + + pub enum nested_enum { + Nest2 = 2, + Nest3 = 3, + } + } +} + +pub mod SameDir; +pub mod SubDir; + +#[path = "SameDir3.rs"] +pub mod SameDir2; + +struct nofields; + +#[derive(Clone)] +struct some_fields { + field1: u32, +} + +type SF = some_fields; + +trait SuperTrait { + fn qux(&self) { + panic!(); + } +} + +trait SomeTrait: SuperTrait { + fn Method(&self, x: u32) -> u32; + + fn prov(&self, x: u32) -> u32 { + println(&x.to_string()); + 42 + } + fn provided_method(&self) -> u32 { + 42 + } +} + +trait SubTrait: SomeTrait { + fn stat2(x: &Self) -> u32 { + 32 + } +} + +impl SomeTrait for some_fields { + fn Method(&self, x: u32) -> u32 { + println(&x.to_string()); + self.field1 + } +} + +impl SuperTrait for some_fields {} + +impl SubTrait for some_fields {} + +impl some_fields { + fn stat(x: u32) -> u32 { + println(&x.to_string()); + 42 + } + fn stat2(x: &some_fields) -> u32 { + 42 + } + + fn align_to<T>(&mut self) {} + + fn test(&mut self) { + self.align_to::<bool>(); + } +} + +impl SuperTrait for nofields {} +impl SomeTrait for nofields { + fn Method(&self, x: u32) -> u32 { + self.Method(x); + 43 + } + + fn provided_method(&self) -> u32 { + 21 + } +} + +impl SubTrait for nofields {} + +impl SuperTrait for (Box<nofields>, Box<some_fields>) {} + +fn f_with_params<T: SomeTrait>(x: &T) { + x.Method(41); +} + +type MyType = Box<some_fields>; + +enum SomeEnum<'a> { + Ints(isize, isize), + Floats(f64, f64), + Strings(&'a str, &'a str, &'a str), + MyTypes(MyType, MyType), +} + +#[derive(Copy, Clone)] +enum SomeOtherEnum { + SomeConst1, + SomeConst2, + SomeConst3, +} + +enum SomeStructEnum { + 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()); + } + } +} + +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()), + } +} + +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()), + _ => {} + } +} + +fn matchSomeOtherEnum(val: SomeOtherEnum) { + use SomeOtherEnum::{SomeConst2, SomeConst3}; + match val { + SomeOtherEnum::SomeConst1 => { + println("I'm const1."); + } + SomeConst2 | SomeConst3 => { + println("I'm const2 or const3."); + } + } +} + +fn hello<X: SomeTrait>((z, a): (u32, String), ex: X) { + SameDir2::hello(43); + + println(&yy.to_string()); + let (x, y): (u32, u32) = (5, 3); + println(&x.to_string()); + println(&z.to_string()); + let x: u32 = x; + println(&x.to_string()); + let x = "hello"; + println(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 s3 = box nofields; + + s.Method(43); + s3.Method(43); + s2.Method(43); + + ex.prov(43); + + let y: u32 = 56; + // static method on struct + let r = some_fields::stat(y); + // trait static method, calls default + let r = SubTrait::stat2(&*s3); + + let s4 = s3 as Box<SomeTrait>; + s4.Method(43); + + s4.provided_method(); + s2.prov(45); + + let closure = |x: u32, s: &SomeTrait| { + s.Method(23); + return x + y; + }; + + let z = closure(10, &*s); +} + +pub struct blah { + used_link_args: RefCell<[&'static str; 0]>, +} + +#[macro_use] +mod macro_use_test { + macro_rules! test_rec { + (q, $src: expr) => {{ + print!("{}", $src); + test_rec!($src); + }}; + ($src: expr) => { + print!("{}", $src); + }; + } + + macro_rules! internal_vars { + ($src: ident) => {{ + let mut x = $src; + x += 100; + }}; + } +} + +fn main() { + // foo + let s = box some_fields { field1: 43 }; + hello((43, "a".to_string()), *s); + sub::sub2::hello(); + sub2::sub3::hello(); + + let h = sub2::sub3::hello; + h(); + + // utf8 chars + let ut = "Les Miséééééééérables"; + + // For some reason, this pattern of macro_rules foiled our generated code + // avoiding strategy. + macro_rules! variable_str(($name:expr) => ( + some_fields { + field1: $name, + } + )); + 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 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 }; + 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 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 }; + matchSomeStructEnum(s9); + + for x in &vec![1, 2, 3] { + let _y = x; + } + + let s7: SomeEnum = SomeEnum::Strings("one", "two", "three"); + if let SomeEnum::Strings(..) = s7 { + println!("hello!"); + } + + for i in 0..5 { + foo_foo(i); + } + + if let Some(x) = None { + foo_foo(x); + } + + if false { + } else if let Some(y) = None { + foo_foo(y); + } + + while let Some(z) = None { + foo_foo(z); + } + + let mut x = 4; + test_rec!(q, "Hello"); + assert_eq!(x, 4); + internal_vars!(x); +} + +fn foo_foo(_: i32) {} + +impl Iterator for nofields { + type Item = (usize, usize); + + fn next(&mut self) -> Option<(usize, usize)> { + panic!() + } + + fn size_hint(&self) -> (usize, Option<usize>) { + panic!() + } +} + +trait Pattern<'a> { + type Searcher; +} + +struct CharEqPattern; + +impl<'a> Pattern<'a> for CharEqPattern { + type Searcher = CharEqPattern; +} + +struct CharSearcher<'a>(<CharEqPattern as Pattern<'a>>::Searcher); + +pub trait Error {} + +impl Error + 'static { + pub fn is<T: Error + 'static>(&self) -> bool { + panic!() + } +} + +impl Error + 'static + Send { + pub fn is<T: Error + 'static>(&self) -> bool { + <Error + 'static>::is::<T>(self) + } +} +extern crate rustc_serialize; +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Default)] +struct AllDerives(i32); + +fn test_format_args() { + let x = 1; + let y = 2; + let name = "Joe Blogg"; + println!("Hello {}", name); + print!("Hello {0}", name); + print!("{0} + {} = {}", x, y); + print!("x is {}, y is {1}, name is {n}", x, y, n = name); +} + +union TestUnion { + f1: u32, +} + +struct FrameBuffer; + +struct SilenceGenerator; + +impl Iterator for SilenceGenerator { + type Item = FrameBuffer; + + fn next(&mut self) -> Option<Self::Item> { + panic!(); + } +} + +#[doc = include_str!("extra-docs.md")] +struct StructWithDocs; + +trait Foo { + type Bar = FrameBuffer; +} diff --git a/src/test/run-make-fulldeps/save-analysis/krate2.rs b/src/test/run-make-fulldeps/save-analysis/krate2.rs new file mode 100644 index 000000000..7d787e0c9 --- /dev/null +++ b/src/test/run-make-fulldeps/save-analysis/krate2.rs @@ -0,0 +1,8 @@ +#![ crate_name = "krate2" ] +#![ crate_type = "lib" ] + +use std::io::Write; + +pub fn hello() { + std::io::stdout().write_all(b"hello world!\n"); +} diff --git a/src/test/run-make-fulldeps/separate-link-fail/Makefile b/src/test/run-make-fulldeps/separate-link-fail/Makefile new file mode 100644 index 000000000..c759f42a2 --- /dev/null +++ b/src/test/run-make-fulldeps/separate-link-fail/Makefile @@ -0,0 +1,7 @@ +-include ../tools.mk + +all: + echo 'fn main(){}' > $(TMPDIR)/main.rs + # Make sure that this fails + ! $(RUSTC) -Z link-only $(TMPDIR)/main.rs 2> $(TMPDIR)/stderr.txt + $(CGREP) "The input does not look like a .rlink file" < $(TMPDIR)/stderr.txt diff --git a/src/test/run-make-fulldeps/separate-link/Makefile b/src/test/run-make-fulldeps/separate-link/Makefile new file mode 100644 index 000000000..060484e89 --- /dev/null +++ b/src/test/run-make-fulldeps/separate-link/Makefile @@ -0,0 +1,6 @@ +-include ../tools.mk + +all: + echo 'fn main(){}' | $(RUSTC) -Z no-link - + $(RUSTC) -Z link-only $(TMPDIR)/rust_out.rlink + $(call RUN,rust_out) diff --git a/src/test/run-make-fulldeps/sepcomp-cci-copies/Makefile b/src/test/run-make-fulldeps/sepcomp-cci-copies/Makefile new file mode 100644 index 000000000..77d1d71e9 --- /dev/null +++ b/src/test/run-make-fulldeps/sepcomp-cci-copies/Makefile @@ -0,0 +1,12 @@ +-include ../tools.mk + +# Check that cross-crate inlined items are inlined in all compilation units +# that refer to them, and not in any other compilation units. +# Note that we have to pass `-C codegen-units=6` because up to two CGUs may be +# created for each source module (see `rustc_const_eval::monomorphize::partitioning`). + +all: + $(RUSTC) cci_lib.rs + $(RUSTC) foo.rs --emit=llvm-ir -C codegen-units=6 \ + -Z inline-in-all-cgus + [ "$$(cat "$(TMPDIR)"/foo.*.ll | grep -c define\ .*cci_fn)" -eq "2" ] diff --git a/src/test/run-make-fulldeps/sepcomp-cci-copies/cci_lib.rs b/src/test/run-make-fulldeps/sepcomp-cci-copies/cci_lib.rs new file mode 100644 index 000000000..869d4a6cd --- /dev/null +++ b/src/test/run-make-fulldeps/sepcomp-cci-copies/cci_lib.rs @@ -0,0 +1,6 @@ +#![crate_type = "rlib"] + +#[inline] +pub fn cci_fn() -> usize { + 1234 +} diff --git a/src/test/run-make-fulldeps/sepcomp-cci-copies/foo.rs b/src/test/run-make-fulldeps/sepcomp-cci-copies/foo.rs new file mode 100644 index 000000000..ba251fcb0 --- /dev/null +++ b/src/test/run-make-fulldeps/sepcomp-cci-copies/foo.rs @@ -0,0 +1,25 @@ +extern crate cci_lib; +use cci_lib::cci_fn; + +fn call1() -> usize { + cci_fn() +} + +mod a { + use cci_lib::cci_fn; + pub fn call2() -> usize { + cci_fn() + } +} + +mod b { + pub fn call3() -> usize { + 0 + } +} + +fn main() { + call1(); + a::call2(); + b::call3(); +} diff --git a/src/test/run-make-fulldeps/sepcomp-inlining/Makefile b/src/test/run-make-fulldeps/sepcomp-inlining/Makefile new file mode 100644 index 000000000..1d20d9400 --- /dev/null +++ b/src/test/run-make-fulldeps/sepcomp-inlining/Makefile @@ -0,0 +1,15 @@ +-include ../tools.mk + +# Test that #[inline] functions still get inlined across compilation unit +# boundaries. Compilation should produce three IR files, but only the two +# compilation units that have a usage of the #[inline] function should +# contain a definition. Also, the non-#[inline] function should be defined +# in only one compilation unit. + +all: + $(RUSTC) foo.rs --emit=llvm-ir -C codegen-units=3 \ + -Z inline-in-all-cgus + [ "$$(cat "$(TMPDIR)"/foo.*.ll | grep -c define\ i32\ .*inlined)" -eq "0" ] + [ "$$(cat "$(TMPDIR)"/foo.*.ll | grep -c define\ internal\ i32\ .*inlined)" -eq "2" ] + [ "$$(cat "$(TMPDIR)"/foo.*.ll | grep -c define\ hidden\ i32\ .*normal)" -eq "1" ] + [ "$$(cat "$(TMPDIR)"/foo.*.ll | grep -c declare\ hidden\ i32\ .*normal)" -eq "2" ] diff --git a/src/test/run-make-fulldeps/sepcomp-inlining/foo.rs b/src/test/run-make-fulldeps/sepcomp-inlining/foo.rs new file mode 100644 index 000000000..2fe5f9cb7 --- /dev/null +++ b/src/test/run-make-fulldeps/sepcomp-inlining/foo.rs @@ -0,0 +1,30 @@ +#![feature(start)] + +#[inline] +fn inlined() -> u32 { + 1234 +} + +fn normal() -> u32 { + 2345 +} + +mod a { + pub fn f() -> u32 { + ::inlined() + ::normal() + } +} + +mod b { + pub fn f() -> u32 { + ::inlined() + ::normal() + } +} + +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + a::f(); + b::f(); + + 0 +} diff --git a/src/test/run-make-fulldeps/sepcomp-separate/Makefile b/src/test/run-make-fulldeps/sepcomp-separate/Makefile new file mode 100644 index 000000000..5b8bdb0fa --- /dev/null +++ b/src/test/run-make-fulldeps/sepcomp-separate/Makefile @@ -0,0 +1,9 @@ +-include ../tools.mk + +# Test that separate compilation actually puts code into separate compilation +# units. `foo.rs` defines `magic_fn` in three different modules, which should +# wind up in three different compilation units. + +all: + $(RUSTC) foo.rs --emit=llvm-ir -C codegen-units=3 + [ "$$(cat "$(TMPDIR)"/foo.*.ll | grep -c define\ .*magic_fn)" -eq "3" ] diff --git a/src/test/run-make-fulldeps/sepcomp-separate/foo.rs b/src/test/run-make-fulldeps/sepcomp-separate/foo.rs new file mode 100644 index 000000000..169bafa9b --- /dev/null +++ b/src/test/run-make-fulldeps/sepcomp-separate/foo.rs @@ -0,0 +1,21 @@ +fn magic_fn() -> usize { + 1234 +} + +mod a { + pub fn magic_fn() -> usize { + 2345 + } +} + +mod b { + pub fn magic_fn() -> usize { + 3456 + } +} + +fn main() { + magic_fn(); + a::magic_fn(); + b::magic_fn(); +} diff --git a/src/test/run-make-fulldeps/share-generics-dylib/Makefile b/src/test/run-make-fulldeps/share-generics-dylib/Makefile new file mode 100644 index 000000000..282cb2461 --- /dev/null +++ b/src/test/run-make-fulldeps/share-generics-dylib/Makefile @@ -0,0 +1,22 @@ +# This test makes sure all generic instances get re-exported from Rust dylibs for use by +# `-Zshare-generics`. There are two rlibs (`instance_provider_a` and `instance_provider_b`) +# which both provide an instance of `Cell<i32>::set`. There is `instance_user_dylib` which is +# supposed to re-export both these instances, and then there are `instance_user_a_rlib` and +# `instance_user_b_rlib` which each rely on a specific instance to be available. +# +# In the end everything is linked together into `linked_leaf`. If `instance_user_dylib` does +# not export both then we'll get an `undefined reference` error for one of the instances. +# +# This is regression test for https://github.com/rust-lang/rust/issues/67276. + +-include ../../run-make-fulldeps/tools.mk + +COMMON_ARGS=-Cprefer-dynamic -Zshare-generics=yes -Ccodegen-units=1 -Csymbol-mangling-version=v0 + +all: + $(RUSTC) instance_provider_a.rs $(COMMON_ARGS) --crate-type=rlib + $(RUSTC) instance_provider_b.rs $(COMMON_ARGS) --crate-type=rlib + $(RUSTC) instance_user_dylib.rs $(COMMON_ARGS) --crate-type=dylib + $(RUSTC) instance_user_a_rlib.rs $(COMMON_ARGS) --crate-type=rlib + $(RUSTC) instance_user_b_rlib.rs $(COMMON_ARGS) --crate-type=rlib + $(RUSTC) linked_leaf.rs $(COMMON_ARGS) --crate-type=bin diff --git a/src/test/run-make-fulldeps/share-generics-dylib/instance_provider_a.rs b/src/test/run-make-fulldeps/share-generics-dylib/instance_provider_a.rs new file mode 100644 index 000000000..b4e125ac0 --- /dev/null +++ b/src/test/run-make-fulldeps/share-generics-dylib/instance_provider_a.rs @@ -0,0 +1,6 @@ +use std::cell::Cell; + +pub fn foo() { + let a: Cell<i32> = Cell::new(1); + a.set(123); +} diff --git a/src/test/run-make-fulldeps/share-generics-dylib/instance_provider_b.rs b/src/test/run-make-fulldeps/share-generics-dylib/instance_provider_b.rs new file mode 100644 index 000000000..f613db873 --- /dev/null +++ b/src/test/run-make-fulldeps/share-generics-dylib/instance_provider_b.rs @@ -0,0 +1,6 @@ +use std::cell::Cell; + +pub fn foo() { + let b: Cell<i32> = Cell::new(1); + b.set(123); +} diff --git a/src/test/run-make-fulldeps/share-generics-dylib/instance_user_a_rlib.rs b/src/test/run-make-fulldeps/share-generics-dylib/instance_user_a_rlib.rs new file mode 100644 index 000000000..c8e6ab95c --- /dev/null +++ b/src/test/run-make-fulldeps/share-generics-dylib/instance_user_a_rlib.rs @@ -0,0 +1,9 @@ +extern crate instance_provider_a as upstream; +use std::cell::Cell; + +pub fn foo() { + upstream::foo(); + + let b: Cell<i32> = Cell::new(1); + b.set(123); +} diff --git a/src/test/run-make-fulldeps/share-generics-dylib/instance_user_b_rlib.rs b/src/test/run-make-fulldeps/share-generics-dylib/instance_user_b_rlib.rs new file mode 100644 index 000000000..7c34af6d0 --- /dev/null +++ b/src/test/run-make-fulldeps/share-generics-dylib/instance_user_b_rlib.rs @@ -0,0 +1,9 @@ +extern crate instance_provider_b as upstream; +use std::cell::Cell; + +pub fn foo() { + upstream::foo(); + + let b: Cell<i32> = Cell::new(1); + b.set(123); +} diff --git a/src/test/run-make-fulldeps/share-generics-dylib/instance_user_dylib.rs b/src/test/run-make-fulldeps/share-generics-dylib/instance_user_dylib.rs new file mode 100644 index 000000000..7c8368eec --- /dev/null +++ b/src/test/run-make-fulldeps/share-generics-dylib/instance_user_dylib.rs @@ -0,0 +1,7 @@ +extern crate instance_provider_a; +extern crate instance_provider_b; + +pub fn foo() { + instance_provider_a::foo(); + instance_provider_b::foo(); +} diff --git a/src/test/run-make-fulldeps/share-generics-dylib/linked_leaf.rs b/src/test/run-make-fulldeps/share-generics-dylib/linked_leaf.rs new file mode 100644 index 000000000..e510dad69 --- /dev/null +++ b/src/test/run-make-fulldeps/share-generics-dylib/linked_leaf.rs @@ -0,0 +1,15 @@ +extern crate instance_user_dylib; +extern crate instance_user_a_rlib; +extern crate instance_user_b_rlib; + +use std::cell::Cell; + +fn main() { + + instance_user_a_rlib::foo(); + instance_user_b_rlib::foo(); + instance_user_dylib::foo(); + + let a: Cell<i32> = Cell::new(1); + a.set(123); +} diff --git a/src/test/run-make-fulldeps/simd-ffi/Makefile b/src/test/run-make-fulldeps/simd-ffi/Makefile new file mode 100644 index 000000000..e9c974a01 --- /dev/null +++ b/src/test/run-make-fulldeps/simd-ffi/Makefile @@ -0,0 +1,47 @@ +-include ../tools.mk + +TARGETS = +ifeq ($(filter arm,$(LLVM_COMPONENTS)),arm) +# construct a fairly exhaustive list of platforms that we +# support. These ones don't follow a pattern +TARGETS += arm-linux-androideabi arm-unknown-linux-gnueabihf arm-unknown-linux-gnueabi +endif + +ifeq ($(filter x86,$(LLVM_COMPONENTS)),x86) +X86_ARCHS = i686 x86_64 +else +X86_ARCHS = +endif + +# these ones do, each OS lists the architectures it supports +LINUX=$(filter aarch64 mips,$(LLVM_COMPONENTS)) $(X86_ARCHS) +ifeq ($(filter mips,$(LLVM_COMPONENTS)),mips) +LINUX += mipsel +endif + +WINDOWS=$(X86_ARCHS) +# fails with: failed to get iphonesimulator SDK path: no such file or directory +#IOS=i386 aarch64 armv7 +DARWIN=$(X86_ARCHS) + +$(foreach arch,$(LINUX),$(eval TARGETS += $(arch)-unknown-linux-gnu)) +$(foreach arch,$(WINDOWS),$(eval TARGETS += $(arch)-pc-windows-gnu)) +#$(foreach arch,$(IOS),$(eval TARGETS += $(arch)-apple-ios)) +$(foreach arch,$(DARWIN),$(eval TARGETS += $(arch)-apple-darwin)) + +all: $(TARGETS) + +define MK_TARGETS +# compile the rust file to the given target, but only to asm and IR +# form, to avoid having to have an appropriate linker. +# +# we need some features because the integer SIMD instructions are not +# enabled by-default for i686 and ARM; these features will be invalid +# on some platforms, but LLVM just prints a warning so that's fine for +# now. +$(1): simd.rs + $$(RUSTC) --target=$(1) --emit=llvm-ir,asm simd.rs \ + -C target-feature='+neon,+sse2' -C extra-filename=-$(1) +endef + +$(foreach targetxxx,$(TARGETS),$(eval $(call MK_TARGETS,$(targetxxx)))) diff --git a/src/test/run-make-fulldeps/simd-ffi/simd.rs b/src/test/run-make-fulldeps/simd-ffi/simd.rs new file mode 100644 index 000000000..d11cfd77c --- /dev/null +++ b/src/test/run-make-fulldeps/simd-ffi/simd.rs @@ -0,0 +1,82 @@ +// ensures that public symbols are not removed completely +#![crate_type = "lib"] +// we can compile to a variety of platforms, because we don't need +// cross-compiled standard libraries. +#![feature(no_core, auto_traits)] +#![no_core] +#![feature(repr_simd, simd_ffi, link_llvm_intrinsics, lang_items, rustc_attrs)] + +#[derive(Copy)] +#[repr(simd)] +pub struct f32x4(f32, f32, f32, f32); + +extern "C" { + #[link_name = "llvm.sqrt.v4f32"] + fn vsqrt(x: f32x4) -> f32x4; +} + +pub fn foo(x: f32x4) -> f32x4 { + unsafe { vsqrt(x) } +} + +#[derive(Copy)] +#[repr(simd)] +pub struct i32x4(i32, i32, i32, i32); + +extern "C" { + // _mm_sll_epi32 + #[cfg(any(target_arch = "x86", target_arch = "x86-64"))] + #[link_name = "llvm.x86.sse2.psll.d"] + fn integer(a: i32x4, b: i32x4) -> i32x4; + + // vmaxq_s32 + #[cfg(target_arch = "arm")] + #[link_name = "llvm.arm.neon.vmaxs.v4i32"] + fn integer(a: i32x4, b: i32x4) -> i32x4; + // vmaxq_s32 + #[cfg(target_arch = "aarch64")] + #[link_name = "llvm.aarch64.neon.maxs.v4i32"] + fn integer(a: i32x4, b: i32x4) -> i32x4; + + // just some substitute foreign symbol, not an LLVM intrinsic; so + // we still get type checking, but not as detailed as (ab)using + // LLVM. + #[cfg(not(any( + target_arch = "x86", + target_arch = "x86-64", + target_arch = "arm", + target_arch = "aarch64" + )))] + fn integer(a: i32x4, b: i32x4) -> i32x4; +} + +pub fn bar(a: i32x4, b: i32x4) -> i32x4 { + unsafe { integer(a, b) } +} + +#[lang = "sized"] +pub trait Sized {} + +#[lang = "copy"] +pub trait Copy {} + +impl Copy for f32 {} +impl Copy for i32 {} + +pub mod marker { + pub use Copy; +} + +#[lang = "freeze"] +auto trait Freeze {} + +#[macro_export] +#[rustc_builtin_macro] +macro_rules! Copy { + () => {}; +} +#[macro_export] +#[rustc_builtin_macro] +macro_rules! derive { + () => {}; +} diff --git a/src/test/run-make-fulldeps/simple-dylib/Makefile b/src/test/run-make-fulldeps/simple-dylib/Makefile new file mode 100644 index 000000000..26730820f --- /dev/null +++ b/src/test/run-make-fulldeps/simple-dylib/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk +all: + $(RUSTC) bar.rs --crate-type=dylib -C prefer-dynamic + $(RUSTC) foo.rs + $(call RUN,foo) diff --git a/src/test/run-make-fulldeps/simple-dylib/bar.rs b/src/test/run-make-fulldeps/simple-dylib/bar.rs new file mode 100644 index 000000000..c5c0bc606 --- /dev/null +++ b/src/test/run-make-fulldeps/simple-dylib/bar.rs @@ -0,0 +1 @@ +pub fn bar() {} diff --git a/src/test/run-make-fulldeps/simple-dylib/foo.rs b/src/test/run-make-fulldeps/simple-dylib/foo.rs new file mode 100644 index 000000000..8d68535e3 --- /dev/null +++ b/src/test/run-make-fulldeps/simple-dylib/foo.rs @@ -0,0 +1,5 @@ +extern crate bar; + +fn main() { + bar::bar(); +} diff --git a/src/test/run-make-fulldeps/simple-rlib/Makefile b/src/test/run-make-fulldeps/simple-rlib/Makefile new file mode 100644 index 000000000..7b156cb87 --- /dev/null +++ b/src/test/run-make-fulldeps/simple-rlib/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk +all: + $(RUSTC) bar.rs --crate-type=rlib + $(RUSTC) foo.rs + $(call RUN,foo) diff --git a/src/test/run-make-fulldeps/simple-rlib/bar.rs b/src/test/run-make-fulldeps/simple-rlib/bar.rs new file mode 100644 index 000000000..c5c0bc606 --- /dev/null +++ b/src/test/run-make-fulldeps/simple-rlib/bar.rs @@ -0,0 +1 @@ +pub fn bar() {} diff --git a/src/test/run-make-fulldeps/simple-rlib/foo.rs b/src/test/run-make-fulldeps/simple-rlib/foo.rs new file mode 100644 index 000000000..8d68535e3 --- /dev/null +++ b/src/test/run-make-fulldeps/simple-rlib/foo.rs @@ -0,0 +1,5 @@ +extern crate bar; + +fn main() { + bar::bar(); +} diff --git a/src/test/run-make-fulldeps/split-debuginfo/Makefile b/src/test/run-make-fulldeps/split-debuginfo/Makefile new file mode 100644 index 000000000..e2dc64d8c --- /dev/null +++ b/src/test/run-make-fulldeps/split-debuginfo/Makefile @@ -0,0 +1,121 @@ +-include ../tools.mk + +all: off packed unpacked + +ifeq ($(UNAME),Darwin) +# If disabled, don't run dsymutil +off: + rm -rf $(TMPDIR)/*.dSYM + $(RUSTC) foo.rs -g -C split-debuginfo=off + [ ! -d $(TMPDIR)/foo.dSYM ] + +# Packed by default, but only if debuginfo is requested +packed: + rm -rf $(TMPDIR)/*.dSYM + $(RUSTC) foo.rs + [ ! -d $(TMPDIR)/foo.dSYM ] + rm -rf $(TMPDIR)/*.dSYM + $(RUSTC) foo.rs -g + [ -d $(TMPDIR)/foo.dSYM ] + rm -rf $(TMPDIR)/*.dSYM + $(RUSTC) foo.rs -g -C split-debuginfo=packed + [ -d $(TMPDIR)/foo.dSYM ] + rm -rf $(TMPDIR)/*.dSYM + +# Object files are preserved with unpacked and `dsymutil` isn't run +unpacked: + $(RUSTC) foo.rs -g -C split-debuginfo=unpacked + ls $(TMPDIR)/*.o + [ ! -d $(TMPDIR)/foo.dSYM ] +else +ifdef IS_WINDOWS +# Windows only supports =off +off: +packed: +unpacked: +else +# If disabled, don't run dsymutil +off: + $(RUSTC) foo.rs -g -C split-debuginfo=off -Z unstable-options + [ ! -f $(TMPDIR)/*.dwp ] + [ ! -f $(TMPDIR)/*.dwo ] + + $(RUSTC) foo.rs -g + [ ! -f $(TMPDIR)/*.dwp ] + [ ! -f $(TMPDIR)/*.dwo ] + +packed: packed-split packed-single + +packed-split: + $(RUSTC) foo.rs -g -C split-debuginfo=packed -Z unstable-options -Zsplit-dwarf-kind=split + ls $(TMPDIR)/*.dwp + rm -rf $(TMPDIR)/*.dwp $(TMPDIR)/*.dwo + +packed-single: + $(RUSTC) foo.rs -g -C split-debuginfo=packed -Z unstable-options -Zsplit-dwarf-kind=single + ls $(TMPDIR)/*.dwp + ls $(TMPDIR)/*.dwo && exit 1 || exit 0 + rm -rf $(TMPDIR)/*.dwp + +packed-remapped: packed-remapped-split packed-remapped-single + +packed-remapped-split: + $(RUSTC) -Z unstable-options -C split-debuginfo=packed -C debuginfo=2 \ + -Z split-dwarf-kind=split --remap-path-prefix $(TMPDIR)=/a foo.rs -g + objdump -Wi $(TMPDIR)/foo | grep DW_AT_GNU_dwo_name | (! grep $(TMPDIR)) || exit 1 + +packed-remapped-single: + $(RUSTC) -Z unstable-options -C split-debuginfo=packed -C debuginfo=2 \ + -Z split-dwarf-kind=single --remap-path-prefix $(TMPDIR)=/a foo.rs -g + objdump -Wi $(TMPDIR)/foo | grep DW_AT_GNU_dwo_name | (! grep $(TMPDIR)) || exit 1 + +packed-crosscrate: packed-crosscrate-split packed-crosscrate-single + +packed-crosscrate-split: + $(RUSTC) --crate-type lib -Z unstable-options -C split-debuginfo=packed \ + -Zsplit-dwarf-kind=split -C debuginfo=2 -g bar.rs + ls $(TMPDIR)/*.rlib + ls $(TMPDIR)/*.dwo && exit 1 || exit 0 + ls $(TMPDIR)/*.dwp && exit 1 || exit 0 + $(RUSTC) --extern bar=$(TMPDIR)/libbar.rlib -Z unstable-options -C split-debuginfo=packed \ + -Zsplit-dwarf-kind=split -C debuginfo=2 -g main.rs + rm $(TMPDIR)/*.dwo + rm $(TMPDIR)/main.dwp + rm $(TMPDIR)/$(call BIN,main) + +packed-crosscrate-single: + $(RUSTC) --crate-type lib -Z unstable-options -C split-debuginfo=packed \ + -Zsplit-dwarf-kind=single -C debuginfo=2 -g bar.rs + ls $(TMPDIR)/*.rlib + ls $(TMPDIR)/*.dwo && exit 1 || exit 0 + ls $(TMPDIR)/*.dwp && exit 1 || exit 0 + $(RUSTC) --extern bar=$(TMPDIR)/libbar.rlib -Z unstable-options -C split-debuginfo=packed \ + -Zsplit-dwarf-kind=single -C debuginfo=2 -g main.rs + ls $(TMPDIR)/*.dwo && exit 1 || exit 0 + rm $(TMPDIR)/main.dwp + rm $(TMPDIR)/$(call BIN,main) + +unpacked: unpacked-split unpacked-single unpacked-remapped-split unpacked-remapped-single + +unpacked-split: + $(RUSTC) foo.rs -g -C split-debuginfo=unpacked -Z unstable-options -Zsplit-dwarf-kind=split + ls $(TMPDIR)/*.dwp && exit 1 || exit 0 + ls $(TMPDIR)/*.dwo + rm -rf $(TMPDIR)/*.dwp $(TMPDIR)/*.dwo + +unpacked-single: + $(RUSTC) foo.rs -g -C split-debuginfo=unpacked -Z unstable-options -Zsplit-dwarf-kind=single + ls $(TMPDIR)/*.dwp && exit 1 || exit 0 + ls $(TMPDIR)/*.dwo && exit 1 || exit 0 + +unpacked-remapped-split: + $(RUSTC) -Z unstable-options -C split-debuginfo=unpacked -C debuginfo=2 \ + -Z split-dwarf-kind=split --remap-path-prefix $(TMPDIR)=/a foo.rs -g + objdump -Wi $(TMPDIR)/foo | grep DW_AT_GNU_dwo_name | (! grep $(TMPDIR)) || exit 1 + +unpacked-remapped-single: + $(RUSTC) -Z unstable-options -C split-debuginfo=unpacked -C debuginfo=2 \ + -Z split-dwarf-kind=single --remap-path-prefix $(TMPDIR)=/a foo.rs -g + objdump -Wi $(TMPDIR)/foo | grep DW_AT_GNU_dwo_name | (! grep $(TMPDIR)) || exit 1 +endif +endif diff --git a/src/test/run-make-fulldeps/split-debuginfo/bar.rs b/src/test/run-make-fulldeps/split-debuginfo/bar.rs new file mode 100644 index 000000000..07dd07152 --- /dev/null +++ b/src/test/run-make-fulldeps/split-debuginfo/bar.rs @@ -0,0 +1,13 @@ +pub struct Bar { + x: u32, +} + +impl Bar { + pub fn print(&self) { + println!("{}", self.x); + } +} + +pub fn make_bar(x: u32) -> Bar { + Bar { x } +} diff --git a/src/test/run-make-fulldeps/split-debuginfo/foo.rs b/src/test/run-make-fulldeps/split-debuginfo/foo.rs new file mode 100644 index 000000000..b058e5408 --- /dev/null +++ b/src/test/run-make-fulldeps/split-debuginfo/foo.rs @@ -0,0 +1,15 @@ +pub struct Foo { + x: u32, +} + +impl Foo { + pub fn print(&self) { + println!("{}", self.x); + } +} + +pub fn make_foo(x: u32) -> Foo { + Foo { x } +} + +fn main() {} diff --git a/src/test/run-make-fulldeps/split-debuginfo/main.rs b/src/test/run-make-fulldeps/split-debuginfo/main.rs new file mode 100644 index 000000000..21fa16e40 --- /dev/null +++ b/src/test/run-make-fulldeps/split-debuginfo/main.rs @@ -0,0 +1,8 @@ +extern crate bar; + +use bar::{Bar, make_bar}; + +fn main() { + let b = make_bar(3); + b.print(); +} diff --git a/src/test/run-make-fulldeps/stable-symbol-names/Makefile b/src/test/run-make-fulldeps/stable-symbol-names/Makefile new file mode 100644 index 000000000..451af809b --- /dev/null +++ b/src/test/run-make-fulldeps/stable-symbol-names/Makefile @@ -0,0 +1,41 @@ +-include ../tools.mk + +# The following command will: +# 1. dump the symbols of a library using `nm` +# 2. extract only those lines that we are interested in via `grep` +# 3. from those lines, extract just the symbol name via `sed`, which: +# * always starts with "_ZN" and ends with "E" (`legacy` mangling) +# * always starts with "_R" (`v0` mangling) +# 4. sort those symbol names for deterministic comparison +# 5. write the result into a file + +dump-symbols = nm "$(TMPDIR)/lib$(1).rlib" \ + | grep -E "$(2)" \ + | sed -E "s/.*(_ZN.*E|_R[a-zA-Z0-9_]*).*/\1/" \ + | sort \ + > "$(TMPDIR)/$(1)$(3).nm" + +# This test +# - compiles each of the two crates 2 times and makes sure each time we get +# exactly the same symbol names +# - makes sure that both crates agree on the same symbol names for monomorphic +# functions + +all: + $(RUSTC) stable-symbol-names1.rs + $(call dump-symbols,stable_symbol_names1,generic_|mono_,_v1) + rm $(TMPDIR)/libstable_symbol_names1.rlib + $(RUSTC) stable-symbol-names1.rs + $(call dump-symbols,stable_symbol_names1,generic_|mono_,_v2) + cmp "$(TMPDIR)/stable_symbol_names1_v1.nm" "$(TMPDIR)/stable_symbol_names1_v2.nm" + + $(RUSTC) stable-symbol-names2.rs + $(call dump-symbols,stable_symbol_names2,generic_|mono_,_v1) + rm $(TMPDIR)/libstable_symbol_names2.rlib + $(RUSTC) stable-symbol-names2.rs + $(call dump-symbols,stable_symbol_names2,generic_|mono_,_v2) + cmp "$(TMPDIR)/stable_symbol_names2_v1.nm" "$(TMPDIR)/stable_symbol_names2_v2.nm" + + $(call dump-symbols,stable_symbol_names1,mono_,_cross) + $(call dump-symbols,stable_symbol_names2,mono_,_cross) + cmp "$(TMPDIR)/stable_symbol_names1_cross.nm" "$(TMPDIR)/stable_symbol_names2_cross.nm" diff --git a/src/test/run-make-fulldeps/stable-symbol-names/stable-symbol-names1.rs b/src/test/run-make-fulldeps/stable-symbol-names/stable-symbol-names1.rs new file mode 100644 index 000000000..b85a42827 --- /dev/null +++ b/src/test/run-make-fulldeps/stable-symbol-names/stable-symbol-names1.rs @@ -0,0 +1,31 @@ +#![crate_type="rlib"] + +pub trait Foo { + fn generic_method<T>(); +} + +pub struct Bar; + +impl Foo for Bar { + fn generic_method<T>() {} +} + +pub fn mono_function() { + Bar::generic_method::<Bar>(); +} + +pub fn mono_function_lifetime<'a>(x: &'a u64) -> u64 { + *x +} + +pub fn generic_function<T>(t: T) -> T { + t +} + +pub fn user() { + generic_function(0u32); + generic_function("abc"); + let x = 2u64; + generic_function(&x); + let _ = mono_function_lifetime(&x); +} diff --git a/src/test/run-make-fulldeps/stable-symbol-names/stable-symbol-names2.rs b/src/test/run-make-fulldeps/stable-symbol-names/stable-symbol-names2.rs new file mode 100644 index 000000000..33df9d6c6 --- /dev/null +++ b/src/test/run-make-fulldeps/stable-symbol-names/stable-symbol-names2.rs @@ -0,0 +1,17 @@ +#![crate_type="rlib"] + +extern crate stable_symbol_names1; + +pub fn user() { + stable_symbol_names1::generic_function(1u32); + stable_symbol_names1::generic_function("def"); + let x = 2u64; + stable_symbol_names1::generic_function(&x); + stable_symbol_names1::mono_function(); + stable_symbol_names1::mono_function_lifetime(&0); +} + +pub fn trait_impl_test_function() { + use stable_symbol_names1::*; + Bar::generic_method::<Bar>(); +} diff --git a/src/test/run-make-fulldeps/static-dylib-by-default/Makefile b/src/test/run-make-fulldeps/static-dylib-by-default/Makefile new file mode 100644 index 000000000..6409aa66a --- /dev/null +++ b/src/test/run-make-fulldeps/static-dylib-by-default/Makefile @@ -0,0 +1,16 @@ +-include ../tools.mk + +TO_LINK := $(call DYLIB,bar) +ifdef IS_MSVC +LINK_ARG = $(TO_LINK:dll=dll.lib) +else +LINK_ARG = $(TO_LINK) +endif + +all: + $(RUSTC) foo.rs + $(RUSTC) bar.rs + $(CC) main.c $(call OUT_EXE,main) $(LINK_ARG) $(EXTRACFLAGS) + rm $(TMPDIR)/*.rlib + rm $(call DYLIB,foo) + $(call RUN,main) diff --git a/src/test/run-make-fulldeps/static-dylib-by-default/bar.rs b/src/test/run-make-fulldeps/static-dylib-by-default/bar.rs new file mode 100644 index 000000000..14421165e --- /dev/null +++ b/src/test/run-make-fulldeps/static-dylib-by-default/bar.rs @@ -0,0 +1,8 @@ +#![crate_type = "dylib"] + +extern crate foo; + +#[no_mangle] +pub extern "C" fn bar() { + foo::foo(); +} diff --git a/src/test/run-make-fulldeps/static-dylib-by-default/foo.rs b/src/test/run-make-fulldeps/static-dylib-by-default/foo.rs new file mode 100644 index 000000000..7ebec8720 --- /dev/null +++ b/src/test/run-make-fulldeps/static-dylib-by-default/foo.rs @@ -0,0 +1,4 @@ +#![crate_type = "rlib"] +#![crate_type = "dylib"] + +pub fn foo() {} diff --git a/src/test/run-make-fulldeps/static-dylib-by-default/main.c b/src/test/run-make-fulldeps/static-dylib-by-default/main.c new file mode 100644 index 000000000..5f7f2c27c --- /dev/null +++ b/src/test/run-make-fulldeps/static-dylib-by-default/main.c @@ -0,0 +1,6 @@ +extern void bar(); + +int main() { + bar(); + return 0; +} diff --git a/src/test/run-make-fulldeps/static-extern-type/Makefile b/src/test/run-make-fulldeps/static-extern-type/Makefile new file mode 100644 index 000000000..5879fc0ce --- /dev/null +++ b/src/test/run-make-fulldeps/static-extern-type/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: $(call NATIVE_STATICLIB,define-foo) + $(RUSTC) -ldefine-foo use-foo.rs + $(call RUN,use-foo) || exit 1 diff --git a/src/test/run-make-fulldeps/static-extern-type/define-foo.c b/src/test/run-make-fulldeps/static-extern-type/define-foo.c new file mode 100644 index 000000000..39be5acfa --- /dev/null +++ b/src/test/run-make-fulldeps/static-extern-type/define-foo.c @@ -0,0 +1,11 @@ +#include <stdint.h> + +struct Foo { + uint8_t x; +}; + +struct Foo FOO = { 42 }; + +uint8_t bar(const struct Foo* foo) { + return foo->x; +} diff --git a/src/test/run-make-fulldeps/static-extern-type/use-foo.rs b/src/test/run-make-fulldeps/static-extern-type/use-foo.rs new file mode 100644 index 000000000..932b5b594 --- /dev/null +++ b/src/test/run-make-fulldeps/static-extern-type/use-foo.rs @@ -0,0 +1,14 @@ +#![feature(extern_types)] + +extern "C" { + type Foo; + static FOO: Foo; + fn bar(foo: *const Foo) -> u8; +} + +fn main() { + unsafe { + let foo = &FOO; + assert_eq!(bar(foo), 42); + } +} diff --git a/src/test/run-make-fulldeps/static-unwinding/Makefile b/src/test/run-make-fulldeps/static-unwinding/Makefile new file mode 100644 index 000000000..cb0397442 --- /dev/null +++ b/src/test/run-make-fulldeps/static-unwinding/Makefile @@ -0,0 +1,6 @@ +-include ../tools.mk + +all: + $(RUSTC) lib.rs + $(RUSTC) main.rs + $(call RUN,main) diff --git a/src/test/run-make-fulldeps/static-unwinding/lib.rs b/src/test/run-make-fulldeps/static-unwinding/lib.rs new file mode 100644 index 000000000..3fb1117a1 --- /dev/null +++ b/src/test/run-make-fulldeps/static-unwinding/lib.rs @@ -0,0 +1,15 @@ +#![crate_type = "rlib"] + +pub static mut statik: isize = 0; + +struct A; +impl Drop for A { + fn drop(&mut self) { + unsafe { statik = 1; } + } +} + +pub fn callback<F>(f: F) where F: FnOnce() { + let _a = A; + f(); +} diff --git a/src/test/run-make-fulldeps/static-unwinding/main.rs b/src/test/run-make-fulldeps/static-unwinding/main.rs new file mode 100644 index 000000000..0c66ea1aa --- /dev/null +++ b/src/test/run-make-fulldeps/static-unwinding/main.rs @@ -0,0 +1,24 @@ +extern crate lib; + +use std::thread; + +static mut statik: isize = 0; + +struct A; +impl Drop for A { + fn drop(&mut self) { + unsafe { statik = 1; } + } +} + +fn main() { + thread::spawn(move|| { + let _a = A; + lib::callback(|| panic!()); + }).join().unwrap_err(); + + unsafe { + assert_eq!(lib::statik, 1); + assert_eq!(statik, 1); + } +} diff --git a/src/test/run-make-fulldeps/staticlib-blank-lib/Makefile b/src/test/run-make-fulldeps/staticlib-blank-lib/Makefile new file mode 100644 index 000000000..92a278825 --- /dev/null +++ b/src/test/run-make-fulldeps/staticlib-blank-lib/Makefile @@ -0,0 +1,6 @@ +-include ../tools.mk + +all: + $(AR) crus $(TMPDIR)/libfoo.a foo.rs + $(AR) d $(TMPDIR)/libfoo.a foo.rs + $(RUSTC) foo.rs diff --git a/src/test/run-make-fulldeps/staticlib-blank-lib/foo.rs b/src/test/run-make-fulldeps/staticlib-blank-lib/foo.rs new file mode 100644 index 000000000..bf48d069d --- /dev/null +++ b/src/test/run-make-fulldeps/staticlib-blank-lib/foo.rs @@ -0,0 +1,6 @@ +#![crate_type = "staticlib"] + +#[link(name = "foo", kind = "static")] +extern "C" {} + +fn main() {} diff --git a/src/test/run-make-fulldeps/std-core-cycle/Makefile b/src/test/run-make-fulldeps/std-core-cycle/Makefile new file mode 100644 index 000000000..ce3b2d46b --- /dev/null +++ b/src/test/run-make-fulldeps/std-core-cycle/Makefile @@ -0,0 +1,16 @@ +-include ../tools.mk + +ifeq ($(UNAME),Darwin) +FLAGS := +else +ifdef IS_WINDOWS +FLAGS := +else +FLAGS := -C link-args=-Wl,--no-undefined +endif +endif + +all: + $(RUSTC) bar.rs + $(RUSTC) foo.rs $(FLAGS) + $(RUSTC) foo.rs $(FLAGS) -C panic=abort diff --git a/src/test/run-make-fulldeps/std-core-cycle/bar.rs b/src/test/run-make-fulldeps/std-core-cycle/bar.rs new file mode 100644 index 000000000..9f5e7c29b --- /dev/null +++ b/src/test/run-make-fulldeps/std-core-cycle/bar.rs @@ -0,0 +1,16 @@ +#![feature(allocator_api)] +#![crate_type = "rlib"] + +use std::alloc::*; + +pub struct A; + +unsafe impl GlobalAlloc for A { + unsafe fn alloc(&self, _: Layout) -> *mut u8 { + loop {} + } + + unsafe fn dealloc(&self, _ptr: *mut u8, _: Layout) { + loop {} + } +} diff --git a/src/test/run-make-fulldeps/std-core-cycle/foo.rs b/src/test/run-make-fulldeps/std-core-cycle/foo.rs new file mode 100644 index 000000000..6aa6e1ac3 --- /dev/null +++ b/src/test/run-make-fulldeps/std-core-cycle/foo.rs @@ -0,0 +1,11 @@ +#![crate_type = "cdylib"] + +extern crate bar; + +#[global_allocator] +static A: bar::A = bar::A; + +#[no_mangle] +pub extern "C" fn a(a: u32, b: u32) -> u32 { + a / b +} diff --git a/src/test/run-make-fulldeps/stdin-non-utf8/Makefile b/src/test/run-make-fulldeps/stdin-non-utf8/Makefile new file mode 100644 index 000000000..7948c4426 --- /dev/null +++ b/src/test/run-make-fulldeps/stdin-non-utf8/Makefile @@ -0,0 +1,6 @@ +-include ../tools.mk + +all: + cp non-utf8 $(TMPDIR)/non-utf.rs + cat $(TMPDIR)/non-utf.rs | $(RUSTC) - 2>&1 \ + | $(CGREP) "error: couldn't read from stdin, as it did not contain valid UTF-8" diff --git a/src/test/run-make-fulldeps/stdin-non-utf8/non-utf8 b/src/test/run-make-fulldeps/stdin-non-utf8/non-utf8 new file mode 100644 index 000000000..bc87051a8 --- /dev/null +++ b/src/test/run-make-fulldeps/stdin-non-utf8/non-utf8 @@ -0,0 +1 @@ +Ò diff --git a/src/test/run-make-fulldeps/suspicious-library/Makefile b/src/test/run-make-fulldeps/suspicious-library/Makefile new file mode 100644 index 000000000..12f437075 --- /dev/null +++ b/src/test/run-make-fulldeps/suspicious-library/Makefile @@ -0,0 +1,7 @@ +-include ../tools.mk + +all: + $(RUSTC) foo.rs -C prefer-dynamic + touch $(call DYLIB,foo-something-special) + touch $(call DYLIB,foo-something-special2) + $(RUSTC) bar.rs diff --git a/src/test/run-make-fulldeps/suspicious-library/bar.rs b/src/test/run-make-fulldeps/suspicious-library/bar.rs new file mode 100644 index 000000000..550c94cd0 --- /dev/null +++ b/src/test/run-make-fulldeps/suspicious-library/bar.rs @@ -0,0 +1,3 @@ +extern crate foo; + +fn main() { foo::foo() } diff --git a/src/test/run-make-fulldeps/suspicious-library/foo.rs b/src/test/run-make-fulldeps/suspicious-library/foo.rs new file mode 100644 index 000000000..a382d8f2c --- /dev/null +++ b/src/test/run-make-fulldeps/suspicious-library/foo.rs @@ -0,0 +1,3 @@ +#![crate_type = "dylib"] + +pub fn foo() {} diff --git a/src/test/run-make-fulldeps/symbol-visibility/Makefile b/src/test/run-make-fulldeps/symbol-visibility/Makefile new file mode 100644 index 000000000..17052ef4e --- /dev/null +++ b/src/test/run-make-fulldeps/symbol-visibility/Makefile @@ -0,0 +1,122 @@ +include ../tools.mk + +# ignore-windows-msvc + +NM=nm -D +CDYLIB_NAME=liba_cdylib.so +RDYLIB_NAME=liba_rust_dylib.so +PROC_MACRO_NAME=liba_proc_macro.so +EXE_NAME=an_executable +COMBINED_CDYLIB_NAME=libcombined_rlib_dylib.so + +ifeq ($(UNAME),Darwin) +NM=nm -gU +CDYLIB_NAME=liba_cdylib.dylib +RDYLIB_NAME=liba_rust_dylib.dylib +PROC_MACRO_NAME=liba_proc_macro.dylib +EXE_NAME=an_executable +COMBINED_CDYLIB_NAME=libcombined_rlib_dylib.dylib +endif + +ifdef IS_WINDOWS +NM=nm -g +CDYLIB_NAME=liba_cdylib.dll.a +RDYLIB_NAME=liba_rust_dylib.dll.a +PROC_MACRO_NAME=liba_proc_macro.dll +EXE_NAME=an_executable.exe +COMBINED_CDYLIB_NAME=libcombined_rlib_dylib.dll.a +endif + +# `grep` regex for symbols produced by either `legacy` or `v0` mangling +RE_ANY_RUST_SYMBOL="_ZN.*h.*E\|_R[a-zA-Z0-9_]+" + +all: + $(RUSTC) -Zshare-generics=no an_rlib.rs + $(RUSTC) -Zshare-generics=no a_cdylib.rs + $(RUSTC) -Zshare-generics=no a_rust_dylib.rs + $(RUSTC) -Zshare-generics=no a_proc_macro.rs + $(RUSTC) -Zshare-generics=no an_executable.rs + $(RUSTC) -Zshare-generics=no a_cdylib.rs --crate-name combined_rlib_dylib --crate-type=rlib,cdylib + + # Check that a cdylib exports its public #[no_mangle] functions + [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_cdylib)" -eq "1" ] + # Check that a cdylib exports the public #[no_mangle] functions of dependencies + [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "1" ] + # Check that a cdylib DOES NOT export any public Rust functions + [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c $(RE_ANY_RUST_SYMBOL))" -eq "0" ] + + # Check that a Rust dylib exports its monomorphic functions + [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rust_dylib)" -eq "1" ] + [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_rust_function_from_rust_dylib)" -eq "1" ] + # Check that a Rust dylib does not export generics if -Zshare-generics=no + [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_generic_function_from_rust_dylib)" -eq "0" ] + + + # Check that a Rust dylib exports the monomorphic functions from its dependencies + [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "1" ] + [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_rust_function_from_rlib)" -eq "1" ] + # Check that a Rust dylib does not export generics if -Zshare-generics=no + [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_generic_function_from_rlib)" -eq "0" ] + + # Check that a proc macro exports its public #[no_mangle] functions + # FIXME(#99978) avoid exporting #[no_mangle] symbols for proc macros + [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_cdylib)" -eq "1" ] + # Check that a proc macro exports the public #[no_mangle] functions of dependencies + [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "1" ] + # Check that a proc macro DOES NOT export any public Rust functions + [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c $(RE_ANY_RUST_SYMBOL))" -eq "0" ] + +# FIXME(nbdd0121): This is broken in MinGW, see https://github.com/rust-lang/rust/pull/95604#issuecomment-1101564032 +ifndef IS_WINDOWS + # Check that an executable does not export any dynamic symbols + [ "$$($(NM) $(TMPDIR)/$(EXE_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "0" ] + [ "$$($(NM) $(TMPDIR)/$(EXE_NAME) | grep -v __imp_ | grep -c public_rust_function_from_exe)" -eq "0" ] +endif + + + # Check the combined case, where we generate a cdylib and an rlib in the same + # compilation session: + # Check that a cdylib exports its public #[no_mangle] functions + [ "$$($(NM) $(TMPDIR)/$(COMBINED_CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_cdylib)" -eq "1" ] + # Check that a cdylib exports the public #[no_mangle] functions of dependencies + [ "$$($(NM) $(TMPDIR)/$(COMBINED_CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "1" ] + # Check that a cdylib DOES NOT export any public Rust functions + [ "$$($(NM) $(TMPDIR)/$(COMBINED_CDYLIB_NAME) | grep -v __imp_ | grep -c $(RE_ANY_RUST_SYMBOL))" -eq "0" ] + + + $(RUSTC) -Zshare-generics=yes an_rlib.rs + $(RUSTC) -Zshare-generics=yes a_cdylib.rs + $(RUSTC) -Zshare-generics=yes a_rust_dylib.rs + $(RUSTC) -Zshare-generics=yes a_proc_macro.rs + $(RUSTC) -Zshare-generics=yes an_executable.rs + + # Check that a cdylib exports its public #[no_mangle] functions + [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_cdylib)" -eq "1" ] + # Check that a cdylib exports the public #[no_mangle] functions of dependencies + [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "1" ] + # Check that a cdylib DOES NOT export any public Rust functions + [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c $(RE_ANY_RUST_SYMBOL))" -eq "0" ] + + # Check that a Rust dylib exports its monomorphic functions, including generics this time + [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rust_dylib)" -eq "1" ] + [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_rust_function_from_rust_dylib)" -eq "1" ] + [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_generic_function_from_rust_dylib)" -eq "1" ] + + # Check that a Rust dylib exports the monomorphic functions from its dependencies + [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "1" ] + [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_rust_function_from_rlib)" -eq "1" ] + [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_generic_function_from_rlib)" -eq "1" ] + + # Check that a proc macro exports its public #[no_mangle] functions + # FIXME(#99978) avoid exporting #[no_mangle] symbols for proc macros + [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_cdylib)" -eq "1" ] + # Check that a proc macro exports the public #[no_mangle] functions of dependencies + [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "1" ] + # Check that a proc macro DOES NOT export any public Rust functions + [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c $(RE_ANY_RUST_SYMBOL))" -eq "0" ] + +ifndef IS_WINDOWS + # Check that an executable does not export any dynamic symbols + [ "$$($(NM) $(TMPDIR)/$(EXE_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "0" ] + [ "$$($(NM) $(TMPDIR)/$(EXE_NAME) | grep -v __imp_ | grep -c public_rust_function_from_exe)" -eq "0" ] +endif diff --git a/src/test/run-make-fulldeps/symbol-visibility/a_cdylib.rs b/src/test/run-make-fulldeps/symbol-visibility/a_cdylib.rs new file mode 100644 index 000000000..d4fbff85b --- /dev/null +++ b/src/test/run-make-fulldeps/symbol-visibility/a_cdylib.rs @@ -0,0 +1,12 @@ +#![crate_type="cdylib"] + +extern crate an_rlib; + +// This should not be exported +pub fn public_rust_function_from_cdylib() {} + +// This should be exported +#[no_mangle] +pub extern "C" fn public_c_function_from_cdylib() { + an_rlib::public_c_function_from_rlib(); +} diff --git a/src/test/run-make-fulldeps/symbol-visibility/a_proc_macro.rs b/src/test/run-make-fulldeps/symbol-visibility/a_proc_macro.rs new file mode 100644 index 000000000..9fd1a8a67 --- /dev/null +++ b/src/test/run-make-fulldeps/symbol-visibility/a_proc_macro.rs @@ -0,0 +1,9 @@ +#![crate_type = "proc-macro"] + +extern crate an_rlib; + +// This should not be exported +#[no_mangle] +extern "C" fn public_c_function_from_cdylib() { + an_rlib::public_c_function_from_rlib(); +} diff --git a/src/test/run-make-fulldeps/symbol-visibility/a_rust_dylib.rs b/src/test/run-make-fulldeps/symbol-visibility/a_rust_dylib.rs new file mode 100644 index 000000000..a47df0ab7 --- /dev/null +++ b/src/test/run-make-fulldeps/symbol-visibility/a_rust_dylib.rs @@ -0,0 +1,15 @@ +#![crate_type="dylib"] + +extern crate an_rlib; + +// This should be exported +pub fn public_rust_function_from_rust_dylib() {} + +// This should be exported +#[no_mangle] +pub extern "C" fn public_c_function_from_rust_dylib() { + let _ = public_generic_function_from_rust_dylib(1u16); +} + +// This should be exported if -Zshare-generics=yes +pub fn public_generic_function_from_rust_dylib<T>(x: T) -> T { x } diff --git a/src/test/run-make-fulldeps/symbol-visibility/an_executable.rs b/src/test/run-make-fulldeps/symbol-visibility/an_executable.rs new file mode 100644 index 000000000..3f5e125ad --- /dev/null +++ b/src/test/run-make-fulldeps/symbol-visibility/an_executable.rs @@ -0,0 +1,7 @@ +#![crate_type="bin"] + +extern crate an_rlib; + +pub fn public_rust_function_from_exe() {} + +fn main() {} diff --git a/src/test/run-make-fulldeps/symbol-visibility/an_rlib.rs b/src/test/run-make-fulldeps/symbol-visibility/an_rlib.rs new file mode 100644 index 000000000..3696422b1 --- /dev/null +++ b/src/test/run-make-fulldeps/symbol-visibility/an_rlib.rs @@ -0,0 +1,12 @@ +#![crate_type="rlib"] + +pub fn public_rust_function_from_rlib() {} + +#[no_mangle] +pub extern "C" fn public_c_function_from_rlib() { + let _ = public_generic_function_from_rlib(0u64); +} + +pub fn public_generic_function_from_rlib<T>(x: T) -> T { + x +} diff --git a/src/test/run-make-fulldeps/symbols-include-type-name/Makefile b/src/test/run-make-fulldeps/symbols-include-type-name/Makefile new file mode 100644 index 000000000..0850a2633 --- /dev/null +++ b/src/test/run-make-fulldeps/symbols-include-type-name/Makefile @@ -0,0 +1,9 @@ +-include ../tools.mk + +# Check that symbol names for methods include type names, instead of <impl>. + +OUT=$(TMPDIR)/lib.s + +all: + $(RUSTC) --crate-type staticlib --emit asm lib.rs + $(CGREP) Def < $(OUT) diff --git a/src/test/run-make-fulldeps/symbols-include-type-name/lib.rs b/src/test/run-make-fulldeps/symbols-include-type-name/lib.rs new file mode 100644 index 000000000..37d445917 --- /dev/null +++ b/src/test/run-make-fulldeps/symbols-include-type-name/lib.rs @@ -0,0 +1,14 @@ +pub struct Def { + pub id: i32, +} + +impl Def { + pub fn new(id: i32) -> Def { + Def { id: id } + } +} + +#[no_mangle] +pub fn user() { + let _ = Def::new(0); +} diff --git a/src/test/run-make-fulldeps/symlinked-extern/Makefile b/src/test/run-make-fulldeps/symlinked-extern/Makefile new file mode 100644 index 000000000..e5061fdde --- /dev/null +++ b/src/test/run-make-fulldeps/symlinked-extern/Makefile @@ -0,0 +1,11 @@ +-include ../tools.mk + +# ignore-windows +# `ln` is actually `cp` on msys. + +all: + $(RUSTC) foo.rs + mkdir -p $(TMPDIR)/other + ln -nsf $(TMPDIR)/libfoo.rlib $(TMPDIR)/other + $(RUSTC) bar.rs -L $(TMPDIR) + $(RUSTC) baz.rs --extern foo=$(TMPDIR)/other/libfoo.rlib -L $(TMPDIR) diff --git a/src/test/run-make-fulldeps/symlinked-extern/bar.rs b/src/test/run-make-fulldeps/symlinked-extern/bar.rs new file mode 100644 index 000000000..cd9c959d5 --- /dev/null +++ b/src/test/run-make-fulldeps/symlinked-extern/bar.rs @@ -0,0 +1,6 @@ +#![crate_type = "rlib"] + +extern crate foo; + +pub fn bar(_s: foo::S) { +} diff --git a/src/test/run-make-fulldeps/symlinked-extern/baz.rs b/src/test/run-make-fulldeps/symlinked-extern/baz.rs new file mode 100644 index 000000000..cd433a3ac --- /dev/null +++ b/src/test/run-make-fulldeps/symlinked-extern/baz.rs @@ -0,0 +1,6 @@ +extern crate bar; +extern crate foo; + +fn main() { + bar::bar(foo::foo()); +} diff --git a/src/test/run-make-fulldeps/symlinked-extern/foo.rs b/src/test/run-make-fulldeps/symlinked-extern/foo.rs new file mode 100644 index 000000000..c00700b8c --- /dev/null +++ b/src/test/run-make-fulldeps/symlinked-extern/foo.rs @@ -0,0 +1,5 @@ +#![crate_type = "rlib"] + +pub struct S; + +pub fn foo() -> S { S } diff --git a/src/test/run-make-fulldeps/symlinked-libraries/Makefile b/src/test/run-make-fulldeps/symlinked-libraries/Makefile new file mode 100644 index 000000000..618ae87bf --- /dev/null +++ b/src/test/run-make-fulldeps/symlinked-libraries/Makefile @@ -0,0 +1,10 @@ +-include ../tools.mk + +# ignore-windows +# `ln` is actually `cp` on msys. + +all: + $(RUSTC) foo.rs -C prefer-dynamic + mkdir -p $(TMPDIR)/other + ln -nsf $(TMPDIR)/$(call DYLIB_GLOB,foo) $(TMPDIR)/other + $(RUSTC) bar.rs -L $(TMPDIR)/other diff --git a/src/test/run-make-fulldeps/symlinked-libraries/bar.rs b/src/test/run-make-fulldeps/symlinked-libraries/bar.rs new file mode 100644 index 000000000..fde0d7466 --- /dev/null +++ b/src/test/run-make-fulldeps/symlinked-libraries/bar.rs @@ -0,0 +1,5 @@ +extern crate foo; + +fn main() { + foo::bar(); +} diff --git a/src/test/run-make-fulldeps/symlinked-libraries/foo.rs b/src/test/run-make-fulldeps/symlinked-libraries/foo.rs new file mode 100644 index 000000000..cde9e291b --- /dev/null +++ b/src/test/run-make-fulldeps/symlinked-libraries/foo.rs @@ -0,0 +1,3 @@ +#![crate_type = "dylib"] + +pub fn bar() {} diff --git a/src/test/run-make-fulldeps/symlinked-rlib/Makefile b/src/test/run-make-fulldeps/symlinked-rlib/Makefile new file mode 100644 index 000000000..996989ce4 --- /dev/null +++ b/src/test/run-make-fulldeps/symlinked-rlib/Makefile @@ -0,0 +1,9 @@ +-include ../tools.mk + +# ignore-windows +# `ln` is actually `cp` on msys. + +all: + $(RUSTC) foo.rs --crate-type=rlib -o $(TMPDIR)/foo.xxx + ln -nsf $(TMPDIR)/foo.xxx $(TMPDIR)/libfoo.rlib + $(RUSTC) bar.rs -L $(TMPDIR) diff --git a/src/test/run-make-fulldeps/symlinked-rlib/bar.rs b/src/test/run-make-fulldeps/symlinked-rlib/bar.rs new file mode 100644 index 000000000..fde0d7466 --- /dev/null +++ b/src/test/run-make-fulldeps/symlinked-rlib/bar.rs @@ -0,0 +1,5 @@ +extern crate foo; + +fn main() { + foo::bar(); +} diff --git a/src/test/run-make-fulldeps/symlinked-rlib/foo.rs b/src/test/run-make-fulldeps/symlinked-rlib/foo.rs new file mode 100644 index 000000000..c5c0bc606 --- /dev/null +++ b/src/test/run-make-fulldeps/symlinked-rlib/foo.rs @@ -0,0 +1 @@ +pub fn bar() {} diff --git a/src/test/run-make-fulldeps/sysroot-crates-are-unstable/Makefile b/src/test/run-make-fulldeps/sysroot-crates-are-unstable/Makefile new file mode 100644 index 000000000..1e267fb95 --- /dev/null +++ b/src/test/run-make-fulldeps/sysroot-crates-are-unstable/Makefile @@ -0,0 +1,2 @@ +all: + '$(PYTHON)' test.py diff --git a/src/test/run-make-fulldeps/sysroot-crates-are-unstable/test.py b/src/test/run-make-fulldeps/sysroot-crates-are-unstable/test.py new file mode 100644 index 000000000..cb77eb34f --- /dev/null +++ b/src/test/run-make-fulldeps/sysroot-crates-are-unstable/test.py @@ -0,0 +1,74 @@ +import sys +import os +from os import listdir +from os.path import isfile, join +from subprocess import PIPE, Popen + + +# This is n list of files which are stable crates or simply are not crates, +# we don't check for the instability of these crates as they're all stable! +STABLE_CRATES = ['std', 'alloc', 'core', 'proc_macro', + 'rsbegin.o', 'rsend.o', 'dllcrt2.o', 'crt2.o', 'clang_rt'] + + +def convert_to_string(s): + if s.__class__.__name__ == 'bytes': + return s.decode('utf-8') + return s + + +def set_ld_lib_path(): + var = os.environ.get("LD_LIB_PATH_ENVVAR") + rpath = os.environ.get("HOST_RPATH_DIR") + if var and rpath: + path = os.environ.get(var) + if path: + os.environ[var] = rpath + os.pathsep + path + else: + os.environ[var] = rpath + + +def exec_command(command, to_input=None): + child = None + if to_input is None: + child = Popen(command, stdout=PIPE, stderr=PIPE) + else: + child = Popen(command, stdout=PIPE, stderr=PIPE, stdin=PIPE) + stdout, stderr = child.communicate(input=to_input) + return (convert_to_string(stdout), convert_to_string(stderr)) + + +def check_lib(lib): + if lib['name'] in STABLE_CRATES: + return True + print('verifying if {} is an unstable crate'.format(lib['name'])) + stdout, stderr = exec_command([os.environ['RUSTC'], '-', '--crate-type', 'rlib', + '--extern', '{}={}'.format(lib['name'], lib['path'])], + to_input=('extern crate {};'.format(lib['name'])).encode('utf-8')) + if not 'use of unstable library feature' in '{}{}'.format(stdout, stderr): + print('crate {} "{}" is not unstable'.format(lib['name'], lib['path'])) + print('{}{}'.format(stdout, stderr)) + print('') + return False + return True + +# Generate a list of all crates in the sysroot. To do this we list all files in +# rustc's sysroot, look at the filename, strip everything after the `-`, and +# strip the leading `lib` (if present) +def get_all_libs(dir_path): + return [{ 'path': join(dir_path, f), 'name': f[3:].split('-')[0] } + for f in listdir(dir_path) + if isfile(join(dir_path, f)) and f.endswith('.rlib') and f not in STABLE_CRATES] + + +set_ld_lib_path() +sysroot = exec_command([os.environ['RUSTC'], '--print', 'sysroot'])[0].replace('\n', '') +assert sysroot, "Could not read the rustc sysroot!" +libs = get_all_libs(join(sysroot, 'lib/rustlib/{}/lib'.format(os.environ['TARGET']))) + +ret = 0 +for lib in libs: + if not check_lib(lib): + # We continue so users can see all the not unstable crates. + ret = 1 +sys.exit(ret) diff --git a/src/test/run-make-fulldeps/target-cpu-native/Makefile b/src/test/run-make-fulldeps/target-cpu-native/Makefile new file mode 100644 index 000000000..d152e9f76 --- /dev/null +++ b/src/test/run-make-fulldeps/target-cpu-native/Makefile @@ -0,0 +1,20 @@ +-include ../tools.mk + +# only-linux +# only-x86_64 +# +# I *really* don't want to deal with a cross-platform way to compare file sizes, +# tests in `make` sort of are awful + +all: $(TMPDIR)/out.log + # Make sure no warnings about "unknown CPU `native`" were emitted + if [ "$$(wc -c $(TMPDIR)/out.log | cut -d' ' -f 1)" = "0" ]; then \ + echo no warnings generated; \ + else \ + exit 1; \ + fi + + +$(TMPDIR)/out.log: + $(RUSTC) foo.rs -C target-cpu=native 2>&1 | tee $(TMPDIR)/out.log + $(call RUN,foo) diff --git a/src/test/run-make-fulldeps/target-cpu-native/foo.rs b/src/test/run-make-fulldeps/target-cpu-native/foo.rs new file mode 100644 index 000000000..f79c691f0 --- /dev/null +++ b/src/test/run-make-fulldeps/target-cpu-native/foo.rs @@ -0,0 +1,2 @@ +fn main() { +} diff --git a/src/test/run-make-fulldeps/target-specs/Makefile b/src/test/run-make-fulldeps/target-specs/Makefile new file mode 100644 index 000000000..fb95ee553 --- /dev/null +++ b/src/test/run-make-fulldeps/target-specs/Makefile @@ -0,0 +1,11 @@ +-include ../tools.mk +all: + $(RUSTC) foo.rs --target=my-awesome-platform.json --crate-type=lib --emit=asm + $(CGREP) -v morestack < $(TMPDIR)/foo.s + $(RUSTC) foo.rs --target=my-invalid-platform.json 2>&1 | $(CGREP) "Error loading target specification" + $(RUSTC) foo.rs --target=my-incomplete-platform.json 2>&1 | $(CGREP) 'Field llvm-target' + RUST_TARGET_PATH=. $(RUSTC) foo.rs --target=my-awesome-platform --crate-type=lib --emit=asm + RUST_TARGET_PATH=. $(RUSTC) foo.rs --target=my-x86_64-unknown-linux-gnu-platform --crate-type=lib --emit=asm + $(RUSTC) -Z unstable-options --target=my-awesome-platform.json --print target-spec-json > $(TMPDIR)/test-platform.json && $(RUSTC) -Z unstable-options --target=$(TMPDIR)/test-platform.json --print target-spec-json | diff -q $(TMPDIR)/test-platform.json - + $(RUSTC) foo.rs --target=definitely-not-builtin-target 2>&1 | $(CGREP) 'may not set is_builtin' + $(RUSTC) foo.rs --target=mismatching-data-layout --crate-type=lib diff --git a/src/test/run-make-fulldeps/target-specs/definitely-not-builtin-target.json b/src/test/run-make-fulldeps/target-specs/definitely-not-builtin-target.json new file mode 100644 index 000000000..b36fa993d --- /dev/null +++ b/src/test/run-make-fulldeps/target-specs/definitely-not-builtin-target.json @@ -0,0 +1,7 @@ +{ + "arch": "x86_64", + "is-builtin": true, + "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128", + "llvm-target": "x86_64-unknown-unknown-gnu", + "target-pointer-width": "64" +} diff --git a/src/test/run-make-fulldeps/target-specs/foo.rs b/src/test/run-make-fulldeps/target-specs/foo.rs new file mode 100644 index 000000000..d576a1dd2 --- /dev/null +++ b/src/test/run-make-fulldeps/target-specs/foo.rs @@ -0,0 +1,24 @@ +#![feature(lang_items, no_core, auto_traits)] +#![no_core] + +#[lang = "copy"] +trait Copy {} + +#[lang = "sized"] +trait Sized {} + +#[lang = "freeze"] +auto trait Freeze {} + +#[lang = "start"] +fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize { + 0 +} + +extern "C" { + fn _foo() -> [u8; 16]; +} + +fn _main() { + let _a = unsafe { _foo() }; +} diff --git a/src/test/run-make-fulldeps/target-specs/mismatching-data-layout.json b/src/test/run-make-fulldeps/target-specs/mismatching-data-layout.json new file mode 100644 index 000000000..d12caaad1 --- /dev/null +++ b/src/test/run-make-fulldeps/target-specs/mismatching-data-layout.json @@ -0,0 +1,6 @@ +{ + "arch": "x86_64", + "data-layout": "e-m:e-i64:16:32:64", + "llvm-target": "x86_64-unknown-unknown-gnu", + "target-pointer-width": "64" +} diff --git a/src/test/run-make-fulldeps/target-specs/my-awesome-platform.json b/src/test/run-make-fulldeps/target-specs/my-awesome-platform.json new file mode 100644 index 000000000..00de3de05 --- /dev/null +++ b/src/test/run-make-fulldeps/target-specs/my-awesome-platform.json @@ -0,0 +1,11 @@ +{ + "data-layout": "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-f64:32:64-f80:32-n8:16:32-S128", + "linker-flavor": "gcc", + "llvm-target": "i686-unknown-linux-gnu", + "target-endian": "little", + "target-pointer-width": "32", + "target-c-int-width": "32", + "arch": "x86", + "os": "linux", + "morestack": false +} diff --git a/src/test/run-make-fulldeps/target-specs/my-incomplete-platform.json b/src/test/run-make-fulldeps/target-specs/my-incomplete-platform.json new file mode 100644 index 000000000..ceaa25cdf --- /dev/null +++ b/src/test/run-make-fulldeps/target-specs/my-incomplete-platform.json @@ -0,0 +1,10 @@ +{ + "data-layout": "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32", + "linker-flavor": "gcc", + "target-endian": "little", + "target-pointer-width": "32", + "target-c-int-width": "32", + "arch": "x86", + "os": "foo", + "morestack": false +} diff --git a/src/test/run-make-fulldeps/target-specs/my-invalid-platform.json b/src/test/run-make-fulldeps/target-specs/my-invalid-platform.json new file mode 100644 index 000000000..3feac45b7 --- /dev/null +++ b/src/test/run-make-fulldeps/target-specs/my-invalid-platform.json @@ -0,0 +1 @@ +wow this json is really broke! diff --git a/src/test/run-make-fulldeps/target-specs/my-x86_64-unknown-linux-gnu-platform.json b/src/test/run-make-fulldeps/target-specs/my-x86_64-unknown-linux-gnu-platform.json new file mode 100644 index 000000000..6d5e964ed --- /dev/null +++ b/src/test/run-make-fulldeps/target-specs/my-x86_64-unknown-linux-gnu-platform.json @@ -0,0 +1,12 @@ +{ + "pre-link-args": {"gcc": ["-m64"]}, + "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", + "linker-flavor": "gcc", + "llvm-target": "x86_64-unknown-linux-gnu", + "target-endian": "little", + "target-pointer-width": "64", + "target-c-int-width": "32", + "arch": "x86_64", + "os": "linux", + "morestack": false +} diff --git a/src/test/run-make-fulldeps/target-without-atomic-cas/Makefile b/src/test/run-make-fulldeps/target-without-atomic-cas/Makefile new file mode 100644 index 000000000..9868fc1d4 --- /dev/null +++ b/src/test/run-make-fulldeps/target-without-atomic-cas/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +# The target used below doesn't support atomic CAS operations. Verify that's the case +all: + $(RUSTC) --print cfg --target thumbv6m-none-eabi | $(CGREP) -v 'target_has_atomic="ptr"' diff --git a/src/test/run-make-fulldeps/test-harness/Makefile b/src/test/run-make-fulldeps/test-harness/Makefile new file mode 100644 index 000000000..39477c07c --- /dev/null +++ b/src/test/run-make-fulldeps/test-harness/Makefile @@ -0,0 +1,8 @@ +-include ../tools.mk + +all: + # check that #[cfg_attr(..., ignore)] does the right thing. + $(RUSTC) --test test-ignore-cfg.rs --cfg ignorecfg + $(call RUN,test-ignore-cfg) | $(CGREP) 'shouldnotignore ... ok' 'shouldignore ... ignored' + $(call RUN,test-ignore-cfg --quiet) | $(CGREP) -e "^i\.$$" + $(call RUN,test-ignore-cfg --quiet) | $(CGREP) -v 'should' diff --git a/src/test/run-make-fulldeps/test-harness/test-ignore-cfg.rs b/src/test/run-make-fulldeps/test-harness/test-ignore-cfg.rs new file mode 100644 index 000000000..31ef131f2 --- /dev/null +++ b/src/test/run-make-fulldeps/test-harness/test-ignore-cfg.rs @@ -0,0 +1,9 @@ +#[test] +#[cfg_attr(ignorecfg, ignore)] +fn shouldignore() { +} + +#[test] +#[cfg_attr(noignorecfg, ignore)] +fn shouldnotignore() { +} diff --git a/src/test/run-make-fulldeps/tools.mk b/src/test/run-make-fulldeps/tools.mk new file mode 100644 index 000000000..33bf95ac1 --- /dev/null +++ b/src/test/run-make-fulldeps/tools.mk @@ -0,0 +1,176 @@ +# These deliberately use `=` and not `:=` so that client makefiles can +# augment HOST_RPATH_DIR / TARGET_RPATH_DIR. +HOST_RPATH_ENV = \ + $(LD_LIB_PATH_ENVVAR)="$(TMPDIR):$(HOST_RPATH_DIR):$($(LD_LIB_PATH_ENVVAR))" +TARGET_RPATH_ENV = \ + $(LD_LIB_PATH_ENVVAR)="$(TMPDIR):$(TARGET_RPATH_DIR):$($(LD_LIB_PATH_ENVVAR))" + +RUSTC_ORIGINAL := $(RUSTC) +BARE_RUSTC := $(HOST_RPATH_ENV) '$(RUSTC)' +BARE_RUSTDOC := $(HOST_RPATH_ENV) '$(RUSTDOC)' +RUSTC := $(BARE_RUSTC) --out-dir $(TMPDIR) -L $(TMPDIR) $(RUSTFLAGS) +RUSTDOC := $(BARE_RUSTDOC) -L $(TARGET_RPATH_DIR) +ifdef RUSTC_LINKER +RUSTC := $(RUSTC) -Clinker='$(RUSTC_LINKER)' +RUSTDOC := $(RUSTDOC) -Clinker='$(RUSTC_LINKER)' +endif +#CC := $(CC) -L $(TMPDIR) +HTMLDOCCK := '$(PYTHON)' '$(S)/src/etc/htmldocck.py' +CGREP := "$(S)/src/etc/cat-and-grep.sh" + +# diff with common flags for multi-platform diffs against text output +DIFF := diff -u --strip-trailing-cr + +# Some of the Rust CI platforms use `/bin/dash` to run `shell` script in +# Makefiles. Other platforms, including many developer platforms, default to +# `/bin/bash`. (In many cases, `make` is actually using `/bin/sh`, but `sh` +# is configured to execute one or the other shell binary). `dash` features +# support only a small subset of `bash` features, so `dash` can be thought of as +# the lowest common denominator, and tests should be validated against `dash` +# whenever possible. Most developer platforms include `/bin/dash`, but to ensure +# tests still work when `/bin/dash`, if not available, this `SHELL` override is +# conditional: +ifndef IS_WINDOWS # dash interprets backslashes in executable paths incorrectly +ifneq (,$(wildcard /bin/dash)) +SHELL := /bin/dash +endif +endif + +# This is the name of the binary we will generate and run; use this +# e.g. for `$(CC) -o $(RUN_BINFILE)`. +RUN_BINFILE = $(TMPDIR)/$(1) + +# RUN and FAIL are basic way we will invoke the generated binary. On +# non-windows platforms, they set the LD_LIBRARY_PATH environment +# variable before running the binary. + +RLIB_GLOB = lib$(1)*.rlib +BIN = $(1) + +UNAME = $(shell uname) + +ifeq ($(UNAME),Darwin) +RUN = $(TARGET_RPATH_ENV) $(RUN_BINFILE) +FAIL = $(TARGET_RPATH_ENV) $(RUN_BINFILE) && exit 1 || exit 0 +DYLIB_GLOB = lib$(1)*.dylib +DYLIB = $(TMPDIR)/lib$(1).dylib +STATICLIB = $(TMPDIR)/lib$(1).a +STATICLIB_GLOB = lib$(1)*.a +else +ifdef IS_WINDOWS +RUN = PATH="$(PATH):$(TARGET_RPATH_DIR)" $(RUN_BINFILE) +FAIL = PATH="$(PATH):$(TARGET_RPATH_DIR)" $(RUN_BINFILE) && exit 1 || exit 0 +DYLIB_GLOB = $(1)*.dll +DYLIB = $(TMPDIR)/$(1).dll +ifdef IS_MSVC +STATICLIB = $(TMPDIR)/$(1).lib +STATICLIB_GLOB = $(1)*.lib +else +IMPLIB = $(TMPDIR)/lib$(1).dll.a +STATICLIB = $(TMPDIR)/lib$(1).a +STATICLIB_GLOB = lib$(1)*.a +endif +BIN = $(1).exe +LLVM_FILECHECK := $(shell cygpath -u "$(LLVM_FILECHECK)") +else +RUN = $(TARGET_RPATH_ENV) $(RUN_BINFILE) +FAIL = $(TARGET_RPATH_ENV) $(RUN_BINFILE) && exit 1 || exit 0 +DYLIB_GLOB = lib$(1)*.so +DYLIB = $(TMPDIR)/lib$(1).so +STATICLIB = $(TMPDIR)/lib$(1).a +STATICLIB_GLOB = lib$(1)*.a +endif +endif + +ifdef IS_MSVC +COMPILE_OBJ = $(CC) -c -Fo:`cygpath -w $(1)` $(2) +COMPILE_OBJ_CXX = $(CXX) -EHs -c -Fo:`cygpath -w $(1)` $(2) +NATIVE_STATICLIB_FILE = $(1).lib +NATIVE_STATICLIB = $(TMPDIR)/$(call NATIVE_STATICLIB_FILE,$(1)) +OUT_EXE=-Fe:`cygpath -w $(TMPDIR)/$(call BIN,$(1))` \ + -Fo:`cygpath -w $(TMPDIR)/$(1).obj` +else +COMPILE_OBJ = $(CC) -v -c -o $(1) $(2) +COMPILE_OBJ_CXX = $(CXX) -c -o $(1) $(2) +NATIVE_STATICLIB_FILE = lib$(1).a +NATIVE_STATICLIB = $(call STATICLIB,$(1)) +OUT_EXE=-o $(TMPDIR)/$(1) +endif + + +# Extra flags needed to compile a working executable with the standard library +ifdef IS_WINDOWS +ifdef IS_MSVC + EXTRACFLAGS := ws2_32.lib userenv.lib advapi32.lib bcrypt.lib +else + EXTRACFLAGS := -lws2_32 -luserenv -lbcrypt + EXTRACXXFLAGS := -lstdc++ + # So this is a bit hacky: we can't use the DLL version of libstdc++ because + # it pulls in the DLL version of libgcc, which means that we end up with 2 + # instances of the DW2 unwinding implementation. This is a problem on + # i686-pc-windows-gnu because each module (DLL/EXE) needs to register its + # unwind information with the unwinding implementation, and libstdc++'s + # __cxa_throw won't see the unwinding info we registered with our statically + # linked libgcc. + # + # Now, simply statically linking libstdc++ would fix this problem, except + # that it is compiled with the expectation that pthreads is dynamically + # linked as a DLL and will fail to link with a statically linked libpthread. + # + # So we end up with the following hack: we link use static:-bundle to only + # link the parts of libstdc++ that we actually use, which doesn't include + # the dependency on the pthreads DLL. + EXTRARSCXXFLAGS := -l static:-bundle=stdc++ +endif +else +ifeq ($(UNAME),Darwin) + EXTRACFLAGS := -lresolv + EXTRACXXFLAGS := -lc++ + EXTRARSCXXFLAGS := -lc++ +else +ifeq ($(UNAME),FreeBSD) + EXTRACFLAGS := -lm -lpthread -lgcc_s +else +ifeq ($(UNAME),SunOS) + EXTRACFLAGS := -lm -lpthread -lposix4 -lsocket -lresolv +else +ifeq ($(UNAME),OpenBSD) + EXTRACFLAGS := -lm -lpthread -lc++abi + RUSTC := $(RUSTC) -C linker="$(word 1,$(CC:ccache=))" +else + EXTRACFLAGS := -lm -lrt -ldl -lpthread + EXTRACXXFLAGS := -lstdc++ + EXTRARSCXXFLAGS := -lstdc++ +endif +endif +endif +endif +endif + +REMOVE_DYLIBS = rm $(TMPDIR)/$(call DYLIB_GLOB,$(1)) +REMOVE_RLIBS = rm $(TMPDIR)/$(call RLIB_GLOB,$(1)) + +%.a: %.o + $(AR) crus $@ $< +ifdef IS_MSVC +%.lib: lib%.o + $(MSVC_LIB) -out:`cygpath -w $@` $< +else +%.lib: lib%.o + $(AR) crus $@ $< +endif +%.dylib: %.o + $(CC) -dynamiclib -Wl,-dylib -o $@ $< +%.so: %.o + $(CC) -o $@ $< -shared + +ifdef IS_MSVC +%.dll: lib%.o + $(CC) $< -link -dll -out:`cygpath -w $@` +else +%.dll: lib%.o + $(CC) -o $@ $< -shared -Wl,--out-implib=$@.a +endif + +$(TMPDIR)/lib%.o: %.c + $(call COMPILE_OBJ,$@,$<) diff --git a/src/test/run-make-fulldeps/type-mismatch-same-crate-name/Makefile b/src/test/run-make-fulldeps/type-mismatch-same-crate-name/Makefile new file mode 100644 index 000000000..802b3df46 --- /dev/null +++ b/src/test/run-make-fulldeps/type-mismatch-same-crate-name/Makefile @@ -0,0 +1,19 @@ +-include ../tools.mk + +all: + # compile two different versions of crateA + $(RUSTC) --crate-type=rlib crateA.rs -C metadata=-1 -C extra-filename=-1 + $(RUSTC) --crate-type=rlib crateA.rs -C metadata=-2 -C extra-filename=-2 + # make crateB depend on version 1 of crateA + $(RUSTC) --crate-type=rlib crateB.rs --extern crateA=$(TMPDIR)/libcrateA-1.rlib + # make crateC depend on version 2 of crateA + $(RUSTC) crateC.rs --extern crateA=$(TMPDIR)/libcrateA-2.rlib 2>&1 | \ + tr -d '\r\n' | $(CGREP) -e \ + "mismatched types.*\ + crateB::try_foo\(foo2\);.*\ + expected struct \`crateA::foo::Foo\`, found struct \`Foo\`.*\ + different versions of crate \`crateA\`.*\ + mismatched types.*\ + crateB::try_bar\(bar2\);.*\ + expected trait \`crateA::bar::Bar\`, found trait \`Bar\`.*\ + different versions of crate \`crateA\`" diff --git a/src/test/run-make-fulldeps/type-mismatch-same-crate-name/crateA.rs b/src/test/run-make-fulldeps/type-mismatch-same-crate-name/crateA.rs new file mode 100644 index 000000000..4871c8c2e --- /dev/null +++ b/src/test/run-make-fulldeps/type-mismatch-same-crate-name/crateA.rs @@ -0,0 +1,16 @@ +mod foo { + pub struct Foo; +} + +mod bar { + pub trait Bar{} + + pub fn bar() -> Box<Bar> { + unimplemented!() + } +} + +// This makes the publicly accessible path +// differ from the internal one. +pub use foo::Foo; +pub use bar::{Bar, bar}; diff --git a/src/test/run-make-fulldeps/type-mismatch-same-crate-name/crateB.rs b/src/test/run-make-fulldeps/type-mismatch-same-crate-name/crateB.rs new file mode 100644 index 000000000..24fcc7cad --- /dev/null +++ b/src/test/run-make-fulldeps/type-mismatch-same-crate-name/crateB.rs @@ -0,0 +1,4 @@ +extern crate crateA; + +pub fn try_foo(x: crateA::Foo){} +pub fn try_bar(x: Box<crateA::Bar>){} diff --git a/src/test/run-make-fulldeps/type-mismatch-same-crate-name/crateC.rs b/src/test/run-make-fulldeps/type-mismatch-same-crate-name/crateC.rs new file mode 100644 index 000000000..71b38a9f8 --- /dev/null +++ b/src/test/run-make-fulldeps/type-mismatch-same-crate-name/crateC.rs @@ -0,0 +1,25 @@ +// This tests the extra note reported when a type error deals with +// seemingly identical types. +// The main use case of this error is when there are two crates +// (generally different versions of the same crate) with the same name +// causing a type mismatch. + +// The test is nearly the same as the one in +// ui/type/type-mismatch-same-crate-name.rs +// but deals with the case where one of the crates +// is only introduced as an indirect dependency. +// and the type is accessed via a re-export. +// This is similar to how the error can be introduced +// when using cargo's automatic dependency resolution. + +extern crate crateA; + +fn main() { + let foo2 = crateA::Foo; + let bar2 = crateA::bar(); + { + extern crate crateB; + crateB::try_foo(foo2); + crateB::try_bar(bar2); + } +} diff --git a/src/test/run-make-fulldeps/use-extern-for-plugins/Makefile b/src/test/run-make-fulldeps/use-extern-for-plugins/Makefile new file mode 100644 index 000000000..838b1a271 --- /dev/null +++ b/src/test/run-make-fulldeps/use-extern-for-plugins/Makefile @@ -0,0 +1,17 @@ +-include ../tools.mk + +# ignore-freebsd +# ignore-openbsd +# ignore-sunos + +HOST := $(shell $(RUSTC) -vV | grep 'host:' | sed 's/host: //') +ifeq ($(findstring i686,$(HOST)),i686) +TARGET := $(subst i686,x86_64,$(HOST)) +else +TARGET := $(subst x86_64,i686,$(HOST)) +endif + +all: + $(RUSTC) foo.rs -C extra-filename=-host + $(RUSTC) bar.rs -C extra-filename=-targ --target $(TARGET) + $(RUSTC) baz.rs --extern a=$(TMPDIR)/liba-targ.rlib --target $(TARGET) diff --git a/src/test/run-make-fulldeps/use-extern-for-plugins/bar.rs b/src/test/run-make-fulldeps/use-extern-for-plugins/bar.rs new file mode 100644 index 000000000..704d21203 --- /dev/null +++ b/src/test/run-make-fulldeps/use-extern-for-plugins/bar.rs @@ -0,0 +1,9 @@ +#![feature(no_core)] +#![no_core] +#![crate_type = "lib"] +#![crate_name = "a"] + +#[macro_export] +macro_rules! bar { + () => () +} diff --git a/src/test/run-make-fulldeps/use-extern-for-plugins/baz.rs b/src/test/run-make-fulldeps/use-extern-for-plugins/baz.rs new file mode 100644 index 000000000..49a96a0c8 --- /dev/null +++ b/src/test/run-make-fulldeps/use-extern-for-plugins/baz.rs @@ -0,0 +1,8 @@ +#![feature(no_core)] +#![no_core] +#![crate_type = "lib"] + +#[macro_use] +extern crate a; + +bar!(); diff --git a/src/test/run-make-fulldeps/use-extern-for-plugins/foo.rs b/src/test/run-make-fulldeps/use-extern-for-plugins/foo.rs new file mode 100644 index 000000000..dffdc0798 --- /dev/null +++ b/src/test/run-make-fulldeps/use-extern-for-plugins/foo.rs @@ -0,0 +1,8 @@ +#![no_std] +#![crate_type = "lib"] +#![crate_name = "a"] + +#[macro_export] +macro_rules! foo { + () => () +} diff --git a/src/test/run-make-fulldeps/use-suggestions-rust-2018/Makefile b/src/test/run-make-fulldeps/use-suggestions-rust-2018/Makefile new file mode 100644 index 000000000..fc39691c5 --- /dev/null +++ b/src/test/run-make-fulldeps/use-suggestions-rust-2018/Makefile @@ -0,0 +1,7 @@ +-include ../tools.mk + +all: + $(RUSTC) ep-nested-lib.rs + + $(RUSTC) use-suggestions.rs --edition=2018 --extern ep_nested_lib=$(TMPDIR)/libep_nested_lib.rlib 2>&1 | $(CGREP) "use ep_nested_lib::foo::bar::Baz" + diff --git a/src/test/run-make-fulldeps/use-suggestions-rust-2018/ep-nested-lib.rs b/src/test/run-make-fulldeps/use-suggestions-rust-2018/ep-nested-lib.rs new file mode 100644 index 000000000..62a0a9d8f --- /dev/null +++ b/src/test/run-make-fulldeps/use-suggestions-rust-2018/ep-nested-lib.rs @@ -0,0 +1,7 @@ +#![crate_type = "rlib"] + +pub mod foo { + pub mod bar { + pub struct Baz; + } +} diff --git a/src/test/run-make-fulldeps/use-suggestions-rust-2018/use-suggestions.rs b/src/test/run-make-fulldeps/use-suggestions-rust-2018/use-suggestions.rs new file mode 100644 index 000000000..d262d6f98 --- /dev/null +++ b/src/test/run-make-fulldeps/use-suggestions-rust-2018/use-suggestions.rs @@ -0,0 +1,3 @@ +fn main() { + let x = Baz{}; +} diff --git a/src/test/run-make-fulldeps/used-cdylib-macos/Makefile b/src/test/run-make-fulldeps/used-cdylib-macos/Makefile new file mode 100644 index 000000000..4828d9c8a --- /dev/null +++ b/src/test/run-make-fulldeps/used-cdylib-macos/Makefile @@ -0,0 +1,11 @@ +-include ../tools.mk + +# only-macos +# +# This checks that `#[used]` passes through to the linker on +# darwin. This is subject to change in the future, see +# https://github.com/rust-lang/rust/pull/93718 for discussion + +all: + $(RUSTC) -Copt-level=3 dylib_used.rs + nm $(TMPDIR)/libdylib_used.dylib | $(CGREP) VERY_IMPORTANT_SYMBOL diff --git a/src/test/run-make-fulldeps/used-cdylib-macos/dylib_used.rs b/src/test/run-make-fulldeps/used-cdylib-macos/dylib_used.rs new file mode 100644 index 000000000..85f0ff92f --- /dev/null +++ b/src/test/run-make-fulldeps/used-cdylib-macos/dylib_used.rs @@ -0,0 +1,4 @@ +#![crate_type = "cdylib"] + +#[used] +static VERY_IMPORTANT_SYMBOL: u32 = 12345; diff --git a/src/test/run-make-fulldeps/used/Makefile b/src/test/run-make-fulldeps/used/Makefile new file mode 100644 index 000000000..4d9044729 --- /dev/null +++ b/src/test/run-make-fulldeps/used/Makefile @@ -0,0 +1,7 @@ +-include ../tools.mk + +# ignore-windows-msvc + +all: + $(RUSTC) -C opt-level=3 --emit=obj used.rs + nm $(TMPDIR)/used.o | $(CGREP) FOO diff --git a/src/test/run-make-fulldeps/used/used.rs b/src/test/run-make-fulldeps/used/used.rs new file mode 100644 index 000000000..dca0a5e11 --- /dev/null +++ b/src/test/run-make-fulldeps/used/used.rs @@ -0,0 +1,6 @@ +#![crate_type = "lib"] + +#[used] +static FOO: u32 = 0; + +static BAR: u32 = 0; diff --git a/src/test/run-make-fulldeps/version/Makefile b/src/test/run-make-fulldeps/version/Makefile new file mode 100644 index 000000000..23e14a9cb --- /dev/null +++ b/src/test/run-make-fulldeps/version/Makefile @@ -0,0 +1,6 @@ +-include ../tools.mk + +all: + $(RUSTC) -V + $(RUSTC) -vV + $(RUSTC) --version --verbose diff --git a/src/test/run-make-fulldeps/volatile-intrinsics/Makefile b/src/test/run-make-fulldeps/volatile-intrinsics/Makefile new file mode 100644 index 000000000..acbadbef9 --- /dev/null +++ b/src/test/run-make-fulldeps/volatile-intrinsics/Makefile @@ -0,0 +1,9 @@ +-include ../tools.mk + +all: + # The tests must pass... + $(RUSTC) main.rs + $(call RUN,main) + # ... and the loads/stores must not be optimized out. + $(RUSTC) main.rs --emit=llvm-ir + $(CGREP) "load volatile" "store volatile" < $(TMPDIR)/main.ll diff --git a/src/test/run-make-fulldeps/volatile-intrinsics/main.rs b/src/test/run-make-fulldeps/volatile-intrinsics/main.rs new file mode 100644 index 000000000..4295d95f3 --- /dev/null +++ b/src/test/run-make-fulldeps/volatile-intrinsics/main.rs @@ -0,0 +1,24 @@ +#![feature(core_intrinsics, volatile)] + +use std::intrinsics::{ + unaligned_volatile_load, unaligned_volatile_store, volatile_load, volatile_store, +}; +use std::ptr::{read_volatile, write_volatile}; + +pub fn main() { + unsafe { + let mut i: isize = 1; + volatile_store(&mut i, 2); + assert_eq!(volatile_load(&i), 2); + } + unsafe { + let mut i: isize = 1; + unaligned_volatile_store(&mut i, 2); + assert_eq!(unaligned_volatile_load(&i), 2); + } + unsafe { + let mut i: isize = 1; + write_volatile(&mut i, 2); + assert_eq!(read_volatile(&i), 2); + } +} diff --git a/src/test/run-make-fulldeps/weird-output-filenames/Makefile b/src/test/run-make-fulldeps/weird-output-filenames/Makefile new file mode 100644 index 000000000..f161fe9f8 --- /dev/null +++ b/src/test/run-make-fulldeps/weird-output-filenames/Makefile @@ -0,0 +1,15 @@ +-include ../tools.mk + +all: + cp foo.rs $(TMPDIR)/.foo.rs + $(RUSTC) $(TMPDIR)/.foo.rs 2>&1 \ + | $(CGREP) -e "invalid character.*in crate name:" + cp foo.rs $(TMPDIR)/.foo.bar + $(RUSTC) $(TMPDIR)/.foo.bar 2>&1 \ + | $(CGREP) -e "invalid character.*in crate name:" + cp foo.rs $(TMPDIR)/+foo+bar.rs + $(RUSTC) $(TMPDIR)/+foo+bar.rs 2>&1 \ + | $(CGREP) -e "invalid character.*in crate name:" + cp foo.rs $(TMPDIR)/-foo.rs + $(RUSTC) $(TMPDIR)/-foo.rs 2>&1 \ + | $(CGREP) 'crate names cannot start with a `-`' diff --git a/src/test/run-make-fulldeps/weird-output-filenames/foo.rs b/src/test/run-make-fulldeps/weird-output-filenames/foo.rs new file mode 100644 index 000000000..f328e4d9d --- /dev/null +++ b/src/test/run-make-fulldeps/weird-output-filenames/foo.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/src/test/run-make-fulldeps/windows-binary-no-external-deps/Makefile b/src/test/run-make-fulldeps/windows-binary-no-external-deps/Makefile new file mode 100644 index 000000000..f6adb6d76 --- /dev/null +++ b/src/test/run-make-fulldeps/windows-binary-no-external-deps/Makefile @@ -0,0 +1,9 @@ +-include ../tools.mk + +# only-windows + +PATH=$(SYSTEMROOT)/system32 + +all: + $(RUSTC) hello.rs + $(TMPDIR)/hello.exe diff --git a/src/test/run-make-fulldeps/windows-binary-no-external-deps/hello.rs b/src/test/run-make-fulldeps/windows-binary-no-external-deps/hello.rs new file mode 100644 index 000000000..47ad8c634 --- /dev/null +++ b/src/test/run-make-fulldeps/windows-binary-no-external-deps/hello.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello World!"); +} diff --git a/src/test/run-make-fulldeps/windows-spawn/Makefile b/src/test/run-make-fulldeps/windows-spawn/Makefile new file mode 100644 index 000000000..c09ce8109 --- /dev/null +++ b/src/test/run-make-fulldeps/windows-spawn/Makefile @@ -0,0 +1,8 @@ +-include ../tools.mk + +# only-windows + +all: + $(RUSTC) -o "$(TMPDIR)/hopefullydoesntexist bar.exe" hello.rs + $(RUSTC) spawn.rs + $(TMPDIR)/spawn.exe diff --git a/src/test/run-make-fulldeps/windows-spawn/hello.rs b/src/test/run-make-fulldeps/windows-spawn/hello.rs new file mode 100644 index 000000000..47ad8c634 --- /dev/null +++ b/src/test/run-make-fulldeps/windows-spawn/hello.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello World!"); +} diff --git a/src/test/run-make-fulldeps/windows-spawn/spawn.rs b/src/test/run-make-fulldeps/windows-spawn/spawn.rs new file mode 100644 index 000000000..c34da3d5f --- /dev/null +++ b/src/test/run-make-fulldeps/windows-spawn/spawn.rs @@ -0,0 +1,12 @@ +use std::io::ErrorKind; +use std::process::Command; + +fn main() { + // Make sure it doesn't try to run "hopefullydoesntexist bar.exe". + assert_eq!(Command::new("hopefullydoesntexist") + .arg("bar") + .spawn() + .unwrap_err() + .kind(), + ErrorKind::NotFound); +} diff --git a/src/test/run-make-fulldeps/windows-subsystem/Makefile b/src/test/run-make-fulldeps/windows-subsystem/Makefile new file mode 100644 index 000000000..34fb5db32 --- /dev/null +++ b/src/test/run-make-fulldeps/windows-subsystem/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: + $(RUSTC) windows.rs + $(RUSTC) console.rs diff --git a/src/test/run-make-fulldeps/windows-subsystem/console.rs b/src/test/run-make-fulldeps/windows-subsystem/console.rs new file mode 100644 index 000000000..61a92eb6a --- /dev/null +++ b/src/test/run-make-fulldeps/windows-subsystem/console.rs @@ -0,0 +1,3 @@ +#![windows_subsystem = "console"] + +fn main() {} diff --git a/src/test/run-make-fulldeps/windows-subsystem/windows.rs b/src/test/run-make-fulldeps/windows-subsystem/windows.rs new file mode 100644 index 000000000..1138248f0 --- /dev/null +++ b/src/test/run-make-fulldeps/windows-subsystem/windows.rs @@ -0,0 +1,3 @@ +#![windows_subsystem = "windows"] + +fn main() {} |