summaryrefslogtreecommitdiffstats
path: root/src/test/run-make
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/test/run-make-fulldeps/a-b-a-linker-guard/Makefile15
-rw-r--r--src/test/run-make-fulldeps/a-b-a-linker-guard/a.rs8
-rw-r--r--src/test/run-make-fulldeps/a-b-a-linker-guard/b.rs7
-rw-r--r--src/test/run-make-fulldeps/alloc-no-oom-handling/Makefile4
-rw-r--r--src/test/run-make-fulldeps/allow-non-lint-warnings-cmdline/Makefile11
-rw-r--r--src/test/run-make-fulldeps/allow-non-lint-warnings-cmdline/foo.rs5
-rw-r--r--src/test/run-make-fulldeps/allow-warnings-cmdline-stability/Makefile15
-rw-r--r--src/test/run-make-fulldeps/allow-warnings-cmdline-stability/bar.rs5
-rw-r--r--src/test/run-make-fulldeps/allow-warnings-cmdline-stability/foo.rs5
-rw-r--r--src/test/run-make-fulldeps/archive-duplicate-names/Makefile11
-rw-r--r--src/test/run-make-fulldeps/archive-duplicate-names/bar.c1
-rw-r--r--src/test/run-make-fulldeps/archive-duplicate-names/bar.rs5
-rw-r--r--src/test/run-make-fulldeps/archive-duplicate-names/foo.c1
-rw-r--r--src/test/run-make-fulldeps/archive-duplicate-names/foo.rs14
-rw-r--r--src/test/run-make-fulldeps/arguments-non-c-like-enum/Makefile7
-rw-r--r--src/test/run-make-fulldeps/arguments-non-c-like-enum/nonclike.rs31
-rw-r--r--src/test/run-make-fulldeps/arguments-non-c-like-enum/test.c66
-rw-r--r--src/test/run-make-fulldeps/atomic-lock-free/Makefile48
-rw-r--r--src/test/run-make-fulldeps/atomic-lock-free/atomic_lock_free.rs66
-rw-r--r--src/test/run-make-fulldeps/bare-outfile/Makefile6
-rw-r--r--src/test/run-make-fulldeps/bare-outfile/foo.rs2
-rw-r--r--src/test/run-make-fulldeps/c-dynamic-dylib/Makefile12
-rw-r--r--src/test/run-make-fulldeps/c-dynamic-dylib/bar.rs5
-rw-r--r--src/test/run-make-fulldeps/c-dynamic-dylib/cfoo.c4
-rw-r--r--src/test/run-make-fulldeps/c-dynamic-dylib/foo.rs10
-rw-r--r--src/test/run-make-fulldeps/c-dynamic-rlib/Makefile15
-rw-r--r--src/test/run-make-fulldeps/c-dynamic-rlib/bar.rs5
-rw-r--r--src/test/run-make-fulldeps/c-dynamic-rlib/cfoo.c4
-rw-r--r--src/test/run-make-fulldeps/c-dynamic-rlib/foo.rs10
-rw-r--r--src/test/run-make-fulldeps/c-link-to-rust-dylib/Makefile17
-rw-r--r--src/test/run-make-fulldeps/c-link-to-rust-dylib/bar.c6
-rw-r--r--src/test/run-make-fulldeps/c-link-to-rust-dylib/foo.rs4
-rw-r--r--src/test/run-make-fulldeps/c-link-to-rust-staticlib/Makefile12
-rw-r--r--src/test/run-make-fulldeps/c-link-to-rust-staticlib/bar.c6
-rw-r--r--src/test/run-make-fulldeps/c-link-to-rust-staticlib/foo.rs4
-rw-r--r--src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/Makefile6
-rw-r--r--src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/checkrust.rs148
-rw-r--r--src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/test.c50
-rw-r--r--src/test/run-make-fulldeps/c-static-dylib/Makefile9
-rw-r--r--src/test/run-make-fulldeps/c-static-dylib/bar.rs5
-rw-r--r--src/test/run-make-fulldeps/c-static-dylib/cfoo.c1
-rw-r--r--src/test/run-make-fulldeps/c-static-dylib/foo.rs10
-rw-r--r--src/test/run-make-fulldeps/c-static-rlib/Makefile8
-rw-r--r--src/test/run-make-fulldeps/c-static-rlib/bar.rs5
-rw-r--r--src/test/run-make-fulldeps/c-static-rlib/cfoo.c1
-rw-r--r--src/test/run-make-fulldeps/c-static-rlib/foo.rs10
-rw-r--r--src/test/run-make-fulldeps/c-unwind-abi-catch-lib-panic/Makefile30
-rw-r--r--src/test/run-make-fulldeps/c-unwind-abi-catch-lib-panic/add.c12
-rw-r--r--src/test/run-make-fulldeps/c-unwind-abi-catch-lib-panic/main.rs35
-rw-r--r--src/test/run-make-fulldeps/c-unwind-abi-catch-lib-panic/panic.rs12
-rw-r--r--src/test/run-make-fulldeps/c-unwind-abi-catch-panic/Makefile5
-rw-r--r--src/test/run-make-fulldeps/c-unwind-abi-catch-panic/add.c12
-rw-r--r--src/test/run-make-fulldeps/c-unwind-abi-catch-panic/main.rs44
-rw-r--r--src/test/run-make-fulldeps/cat-and-grep-sanity-check/Makefile46
-rw-r--r--src/test/run-make-fulldeps/cdylib-dylib-linkage/Makefile27
-rw-r--r--src/test/run-make-fulldeps/cdylib-dylib-linkage/bar.rs5
-rw-r--r--src/test/run-make-fulldeps/cdylib-dylib-linkage/foo.c10
-rw-r--r--src/test/run-make-fulldeps/cdylib-dylib-linkage/foo.rs13
-rw-r--r--src/test/run-make-fulldeps/cdylib-fewer-symbols/Makefile12
-rw-r--r--src/test/run-make-fulldeps/cdylib-fewer-symbols/foo.rs6
-rw-r--r--src/test/run-make-fulldeps/cdylib/Makefile19
-rw-r--r--src/test/run-make-fulldeps/cdylib/bar.rs5
-rw-r--r--src/test/run-make-fulldeps/cdylib/foo.c10
-rw-r--r--src/test/run-make-fulldeps/cdylib/foo.rs13
-rw-r--r--src/test/run-make-fulldeps/codegen-options-parsing/Makefile31
-rw-r--r--src/test/run-make-fulldeps/codegen-options-parsing/dummy.rs1
-rw-r--r--src/test/run-make-fulldeps/compile-stdin/Makefile5
-rw-r--r--src/test/run-make-fulldeps/compiler-lookup-paths-2/Makefile8
-rw-r--r--src/test/run-make-fulldeps/compiler-lookup-paths-2/a.rs1
-rw-r--r--src/test/run-make-fulldeps/compiler-lookup-paths-2/b.rs2
-rw-r--r--src/test/run-make-fulldeps/compiler-lookup-paths-2/c.rs3
-rw-r--r--src/test/run-make-fulldeps/compiler-lookup-paths/Makefile38
-rw-r--r--src/test/run-make-fulldeps/compiler-lookup-paths/a.rs1
-rw-r--r--src/test/run-make-fulldeps/compiler-lookup-paths/b.rs2
-rw-r--r--src/test/run-make-fulldeps/compiler-lookup-paths/c.rs2
-rw-r--r--src/test/run-make-fulldeps/compiler-lookup-paths/d.rs4
-rw-r--r--src/test/run-make-fulldeps/compiler-lookup-paths/e.rs2
-rw-r--r--src/test/run-make-fulldeps/compiler-lookup-paths/e2.rs4
-rw-r--r--src/test/run-make-fulldeps/compiler-lookup-paths/f.rs2
-rw-r--r--src/test/run-make-fulldeps/compiler-lookup-paths/native.c1
-rw-r--r--src/test/run-make-fulldeps/compiler-rt-works-on-mingw/Makefile9
-rw-r--r--src/test/run-make-fulldeps/compiler-rt-works-on-mingw/foo.cpp4
-rw-r--r--src/test/run-make-fulldeps/compiler-rt-works-on-mingw/foo.rs10
-rw-r--r--src/test/run-make-fulldeps/core-no-fp-fmt-parse/Makefile4
-rw-r--r--src/test/run-make-fulldeps/crate-data-smoke/Makefile10
-rw-r--r--src/test/run-make-fulldeps/crate-data-smoke/crate.rs7
-rw-r--r--src/test/run-make-fulldeps/crate-data-smoke/lib.rs2
-rw-r--r--src/test/run-make-fulldeps/crate-data-smoke/rlib.rs2
-rw-r--r--src/test/run-make-fulldeps/crate-hash-rustc-version/Makefile37
-rw-r--r--src/test/run-make-fulldeps/crate-hash-rustc-version/a.rs4
-rw-r--r--src/test/run-make-fulldeps/crate-hash-rustc-version/b.rs8
-rw-r--r--src/test/run-make-fulldeps/crate-name-priority/Makefile11
-rw-r--r--src/test/run-make-fulldeps/crate-name-priority/foo.rs1
-rw-r--r--src/test/run-make-fulldeps/crate-name-priority/foo1.rs3
-rw-r--r--src/test/run-make-fulldeps/cross-lang-lto-clang/Makefile25
-rw-r--r--src/test/run-make-fulldeps/cross-lang-lto-clang/clib.c9
-rw-r--r--src/test/run-make-fulldeps/cross-lang-lto-clang/cmain.c12
-rw-r--r--src/test/run-make-fulldeps/cross-lang-lto-clang/main.rs11
-rw-r--r--src/test/run-make-fulldeps/cross-lang-lto-clang/rustlib.rs12
-rw-r--r--src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/Makefile87
-rw-r--r--src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/clib.c9
-rw-r--r--src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/cmain.c12
-rw-r--r--src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/main.rs11
-rw-r--r--src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/rustlib.rs12
-rw-r--r--src/test/run-make-fulldeps/cross-lang-lto-upstream-rlibs/Makefile32
-rw-r--r--src/test/run-make-fulldeps/cross-lang-lto-upstream-rlibs/staticlib.rs8
-rw-r--r--src/test/run-make-fulldeps/cross-lang-lto-upstream-rlibs/upstream.rs3
-rw-r--r--src/test/run-make-fulldeps/cross-lang-lto/Makefile57
-rw-r--r--src/test/run-make-fulldeps/cross-lang-lto/lib.rs4
-rw-r--r--src/test/run-make-fulldeps/cross-lang-lto/main.rs3
-rw-r--r--src/test/run-make-fulldeps/debug-assertions/Makefile25
-rw-r--r--src/test/run-make-fulldeps/debug-assertions/debug.rs33
-rw-r--r--src/test/run-make-fulldeps/dep-info-doesnt-run-much/Makefile4
-rw-r--r--src/test/run-make-fulldeps/dep-info-doesnt-run-much/foo.rs5
-rw-r--r--src/test/run-make-fulldeps/dep-info-spaces/Makefile19
-rw-r--r--src/test/run-make-fulldeps/dep-info-spaces/Makefile.foo7
-rw-r--r--src/test/run-make-fulldeps/dep-info-spaces/bar.rs1
-rw-r--r--src/test/run-make-fulldeps/dep-info-spaces/foo foo.rs1
-rw-r--r--src/test/run-make-fulldeps/dep-info-spaces/lib.rs4
-rw-r--r--src/test/run-make-fulldeps/dep-info/Makefile25
-rw-r--r--src/test/run-make-fulldeps/dep-info/Makefile.foo7
-rw-r--r--src/test/run-make-fulldeps/dep-info/bar.rs1
-rw-r--r--src/test/run-make-fulldeps/dep-info/foo.rs1
-rw-r--r--src/test/run-make-fulldeps/dep-info/lib.rs4
-rw-r--r--src/test/run-make-fulldeps/dep-info/lib2.rs3
-rw-r--r--src/test/run-make-fulldeps/doctests-keep-binaries/Makefile21
-rw-r--r--src/test/run-make-fulldeps/doctests-keep-binaries/t.rs11
-rw-r--r--src/test/run-make-fulldeps/duplicate-output-flavors/Makefile5
-rw-r--r--src/test/run-make-fulldeps/duplicate-output-flavors/foo.rs1
-rw-r--r--src/test/run-make-fulldeps/dylib-chain/Makefile12
-rw-r--r--src/test/run-make-fulldeps/dylib-chain/m1.rs2
-rw-r--r--src/test/run-make-fulldeps/dylib-chain/m2.rs4
-rw-r--r--src/test/run-make-fulldeps/dylib-chain/m3.rs4
-rw-r--r--src/test/run-make-fulldeps/dylib-chain/m4.rs3
-rw-r--r--src/test/run-make-fulldeps/emit-stack-sizes/Makefile12
-rw-r--r--src/test/run-make-fulldeps/emit-stack-sizes/foo.rs3
-rw-r--r--src/test/run-make-fulldeps/emit/Makefile21
-rw-r--r--src/test/run-make-fulldeps/emit/test-24876.rs9
-rw-r--r--src/test/run-make-fulldeps/emit/test-26235.rs46
-rw-r--r--src/test/run-make-fulldeps/error-found-staticlib-instead-crate/Makefile5
-rw-r--r--src/test/run-make-fulldeps/error-found-staticlib-instead-crate/bar.rs5
-rw-r--r--src/test/run-make-fulldeps/error-found-staticlib-instead-crate/foo.rs1
-rw-r--r--src/test/run-make-fulldeps/error-writing-dependencies/Makefile8
-rw-r--r--src/test/run-make-fulldeps/error-writing-dependencies/foo.rs1
-rw-r--r--src/test/run-make-fulldeps/exit-code/Makefile11
-rw-r--r--src/test/run-make-fulldeps/exit-code/compile-error.rs3
-rw-r--r--src/test/run-make-fulldeps/exit-code/lint-failure.rs6
-rw-r--r--src/test/run-make-fulldeps/exit-code/success.rs4
-rw-r--r--src/test/run-make-fulldeps/extern-diff-internal-name/Makefile5
-rw-r--r--src/test/run-make-fulldeps/extern-diff-internal-name/lib.rs2
-rw-r--r--src/test/run-make-fulldeps/extern-diff-internal-name/test.rs5
-rw-r--r--src/test/run-make-fulldeps/extern-flag-disambiguates/Makefile25
-rw-r--r--src/test/run-make-fulldeps/extern-flag-disambiguates/a.rs6
-rw-r--r--src/test/run-make-fulldeps/extern-flag-disambiguates/b.rs9
-rw-r--r--src/test/run-make-fulldeps/extern-flag-disambiguates/c.rs9
-rw-r--r--src/test/run-make-fulldeps/extern-flag-disambiguates/d.rs11
-rw-r--r--src/test/run-make-fulldeps/extern-flag-fun/Makefile19
-rw-r--r--src/test/run-make-fulldeps/extern-flag-fun/bar-alt.rs1
-rw-r--r--src/test/run-make-fulldeps/extern-flag-fun/bar.rs1
-rw-r--r--src/test/run-make-fulldeps/extern-flag-fun/foo.rs3
-rw-r--r--src/test/run-make-fulldeps/extern-flag-fun/gated_unstable.rs3
-rw-r--r--src/test/run-make-fulldeps/extern-flag-fun/rustc.rs1
-rw-r--r--src/test/run-make-fulldeps/extern-flag-pathless/Makefile18
-rw-r--r--src/test/run-make-fulldeps/extern-flag-pathless/bar-dynamic.rs3
-rw-r--r--src/test/run-make-fulldeps/extern-flag-pathless/bar-static.rs3
-rw-r--r--src/test/run-make-fulldeps/extern-flag-pathless/foo.rs3
-rw-r--r--src/test/run-make-fulldeps/extern-flag-rename-transitive/Makefile7
-rw-r--r--src/test/run-make-fulldeps/extern-flag-rename-transitive/bar.rs3
-rw-r--r--src/test/run-make-fulldeps/extern-flag-rename-transitive/baz.rs4
-rw-r--r--src/test/run-make-fulldeps/extern-flag-rename-transitive/foo.rs1
-rw-r--r--src/test/run-make-fulldeps/extern-fn-generic/Makefile6
-rw-r--r--src/test/run-make-fulldeps/extern-fn-generic/test.c16
-rw-r--r--src/test/run-make-fulldeps/extern-fn-generic/test.rs20
-rw-r--r--src/test/run-make-fulldeps/extern-fn-generic/testcrate.rs16
-rw-r--r--src/test/run-make-fulldeps/extern-fn-mangle/Makefile5
-rw-r--r--src/test/run-make-fulldeps/extern-fn-mangle/test.c8
-rw-r--r--src/test/run-make-fulldeps/extern-fn-mangle/test.rs19
-rw-r--r--src/test/run-make-fulldeps/extern-fn-reachable/Makefile25
-rw-r--r--src/test/run-make-fulldeps/extern-fn-reachable/dylib.rs14
-rw-r--r--src/test/run-make-fulldeps/extern-fn-struct-passing-abi/Makefile5
-rw-r--r--src/test/run-make-fulldeps/extern-fn-struct-passing-abi/test.c314
-rw-r--r--src/test/run-make-fulldeps/extern-fn-struct-passing-abi/test.rs138
-rw-r--r--src/test/run-make-fulldeps/extern-fn-with-extern-types/Makefile5
-rw-r--r--src/test/run-make-fulldeps/extern-fn-with-extern-types/ctest.c16
-rw-r--r--src/test/run-make-fulldeps/extern-fn-with-extern-types/test.rs17
-rw-r--r--src/test/run-make-fulldeps/extern-fn-with-packed-struct/Makefile5
-rw-r--r--src/test/run-make-fulldeps/extern-fn-with-packed-struct/test.c26
-rw-r--r--src/test/run-make-fulldeps/extern-fn-with-packed-struct/test.rs20
-rw-r--r--src/test/run-make-fulldeps/extern-fn-with-union/Makefile6
-rw-r--r--src/test/run-make-fulldeps/extern-fn-with-union/ctest.c10
-rw-r--r--src/test/run-make-fulldeps/extern-fn-with-union/test.rs19
-rw-r--r--src/test/run-make-fulldeps/extern-fn-with-union/testcrate.rs11
-rw-r--r--src/test/run-make-fulldeps/extern-multiple-copies/Makefile8
-rw-r--r--src/test/run-make-fulldeps/extern-multiple-copies/bar.rs6
-rw-r--r--src/test/run-make-fulldeps/extern-multiple-copies/foo1.rs1
-rw-r--r--src/test/run-make-fulldeps/extern-multiple-copies/foo2.rs1
-rw-r--r--src/test/run-make-fulldeps/extern-multiple-copies2/Makefile10
-rw-r--r--src/test/run-make-fulldeps/extern-multiple-copies2/bar.rs8
-rw-r--r--src/test/run-make-fulldeps/extern-multiple-copies2/foo1.rs7
-rw-r--r--src/test/run-make-fulldeps/extern-multiple-copies2/foo2.rs8
-rw-r--r--src/test/run-make-fulldeps/extern-overrides-distribution/Makefile5
-rw-r--r--src/test/run-make-fulldeps/extern-overrides-distribution/libc.rs3
-rw-r--r--src/test/run-make-fulldeps/extern-overrides-distribution/main.rs5
-rw-r--r--src/test/run-make-fulldeps/extra-filename-with-temp-outputs/Makefile6
-rw-r--r--src/test/run-make-fulldeps/extra-filename-with-temp-outputs/foo.rs1
-rw-r--r--src/test/run-make-fulldeps/foreign-double-unwind/Makefile10
-rw-r--r--src/test/run-make-fulldeps/foreign-double-unwind/foo.cpp33
-rw-r--r--src/test/run-make-fulldeps/foreign-double-unwind/foo.rs26
-rw-r--r--src/test/run-make-fulldeps/foreign-exceptions/Makefile10
-rw-r--r--src/test/run-make-fulldeps/foreign-exceptions/foo.cpp60
-rw-r--r--src/test/run-make-fulldeps/foreign-exceptions/foo.rs59
-rw-r--r--src/test/run-make-fulldeps/fpic/Makefile10
-rw-r--r--src/test/run-make-fulldeps/fpic/hello.rs1
-rw-r--r--src/test/run-make-fulldeps/glibc-staticlib-args/Makefile12
-rw-r--r--src/test/run-make-fulldeps/glibc-staticlib-args/library.rs4
-rw-r--r--src/test/run-make-fulldeps/glibc-staticlib-args/program.c6
-rw-r--r--src/test/run-make-fulldeps/hir-tree/Makefile8
-rw-r--r--src/test/run-make-fulldeps/hir-tree/input.rs3
-rw-r--r--src/test/run-make-fulldeps/hotplug_codegen_backend/Makefile26
-rw-r--r--src/test/run-make-fulldeps/hotplug_codegen_backend/some_crate.rs2
-rw-r--r--src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs82
-rw-r--r--src/test/run-make-fulldeps/include_bytes_deps/Makefile7
-rw-r--r--src/test/run-make-fulldeps/include_bytes_deps/input.bin1
-rw-r--r--src/test/run-make-fulldeps/include_bytes_deps/input.md1
-rw-r--r--src/test/run-make-fulldeps/include_bytes_deps/input.txt1
-rw-r--r--src/test/run-make-fulldeps/include_bytes_deps/main.rs10
-rw-r--r--src/test/run-make-fulldeps/incr-add-rust-src-component/Makefile44
-rw-r--r--src/test/run-make-fulldeps/incr-add-rust-src-component/main.rs3
-rw-r--r--src/test/run-make-fulldeps/inline-always-many-cgu/Makefile8
-rw-r--r--src/test/run-make-fulldeps/inline-always-many-cgu/foo.rs15
-rw-r--r--src/test/run-make-fulldeps/interdependent-c-libraries/Makefile14
-rw-r--r--src/test/run-make-fulldeps/interdependent-c-libraries/bar.c3
-rw-r--r--src/test/run-make-fulldeps/interdependent-c-libraries/bar.rs14
-rw-r--r--src/test/run-make-fulldeps/interdependent-c-libraries/foo.c1
-rw-r--r--src/test/run-make-fulldeps/interdependent-c-libraries/foo.rs12
-rw-r--r--src/test/run-make-fulldeps/interdependent-c-libraries/main.rs6
-rw-r--r--src/test/run-make-fulldeps/intrinsic-unreachable/Makefile11
-rw-r--r--src/test/run-make-fulldeps/intrinsic-unreachable/exit-ret.rs14
-rw-r--r--src/test/run-make-fulldeps/intrinsic-unreachable/exit-unreachable.rs18
-rw-r--r--src/test/run-make-fulldeps/invalid-library/Makefile6
-rw-r--r--src/test/run-make-fulldeps/invalid-library/foo.rs3
-rw-r--r--src/test/run-make-fulldeps/invalid-staticlib/Makefile5
-rw-r--r--src/test/run-make-fulldeps/issue-11908/Makefile21
-rw-r--r--src/test/run-make-fulldeps/issue-11908/bar.rs3
-rw-r--r--src/test/run-make-fulldeps/issue-11908/foo.rs1
-rw-r--r--src/test/run-make-fulldeps/issue-14500/Makefile13
-rw-r--r--src/test/run-make-fulldeps/issue-14500/bar.rs1
-rw-r--r--src/test/run-make-fulldeps/issue-14500/foo.c7
-rw-r--r--src/test/run-make-fulldeps/issue-14500/foo.rs5
-rw-r--r--src/test/run-make-fulldeps/issue-14698/Makefile4
-rw-r--r--src/test/run-make-fulldeps/issue-14698/foo.rs1
-rw-r--r--src/test/run-make-fulldeps/issue-15460/Makefile6
-rw-r--r--src/test/run-make-fulldeps/issue-15460/bar.rs4
-rw-r--r--src/test/run-make-fulldeps/issue-15460/foo.c6
-rw-r--r--src/test/run-make-fulldeps/issue-15460/foo.rs6
-rw-r--r--src/test/run-make-fulldeps/issue-18943/Makefile7
-rw-r--r--src/test/run-make-fulldeps/issue-18943/foo.rs5
-rw-r--r--src/test/run-make-fulldeps/issue-19371/Makefile9
-rw-r--r--src/test/run-make-fulldeps/issue-19371/foo.rs76
-rw-r--r--src/test/run-make-fulldeps/issue-20626/Makefile8
-rw-r--r--src/test/run-make-fulldeps/issue-20626/foo.rs13
-rw-r--r--src/test/run-make-fulldeps/issue-22131/Makefile7
-rw-r--r--src/test/run-make-fulldeps/issue-22131/foo.rs5
-rw-r--r--src/test/run-make-fulldeps/issue-24445/Makefile10
-rw-r--r--src/test/run-make-fulldeps/issue-24445/foo.c6
-rw-r--r--src/test/run-make-fulldeps/issue-24445/foo.rs15
-rw-r--r--src/test/run-make-fulldeps/issue-25581/Makefile5
-rw-r--r--src/test/run-make-fulldeps/issue-25581/test.c15
-rw-r--r--src/test/run-make-fulldeps/issue-25581/test.rs18
-rw-r--r--src/test/run-make-fulldeps/issue-26006/Makefile16
-rw-r--r--src/test/run-make-fulldeps/issue-26006/in/libc/lib.rs3
-rw-r--r--src/test/run-make-fulldeps/issue-26006/in/time/lib.rs4
-rw-r--r--src/test/run-make-fulldeps/issue-26092/Makefile6
-rw-r--r--src/test/run-make-fulldeps/issue-26092/blank.rs1
-rw-r--r--src/test/run-make-fulldeps/issue-28595/Makefile6
-rw-r--r--src/test/run-make-fulldeps/issue-28595/a.c1
-rw-r--r--src/test/run-make-fulldeps/issue-28595/a.rs6
-rw-r--r--src/test/run-make-fulldeps/issue-28595/b.c5
-rw-r--r--src/test/run-make-fulldeps/issue-28595/b.rs12
-rw-r--r--src/test/run-make-fulldeps/issue-28766/Makefile5
-rw-r--r--src/test/run-make-fulldeps/issue-28766/foo.rs8
-rw-r--r--src/test/run-make-fulldeps/issue-28766/main.rs7
-rw-r--r--src/test/run-make-fulldeps/issue-30063/Makefile35
-rw-r--r--src/test/run-make-fulldeps/issue-30063/foo.rs1
-rw-r--r--src/test/run-make-fulldeps/issue-33329/Makefile5
-rw-r--r--src/test/run-make-fulldeps/issue-33329/main.rs1
-rw-r--r--src/test/run-make-fulldeps/issue-35164/Makefile4
-rw-r--r--src/test/run-make-fulldeps/issue-35164/main.rs5
-rw-r--r--src/test/run-make-fulldeps/issue-35164/submodule/mod.rs3
-rw-r--r--src/test/run-make-fulldeps/issue-37839/Makefile6
-rw-r--r--src/test/run-make-fulldeps/issue-37839/a.rs2
-rw-r--r--src/test/run-make-fulldeps/issue-37839/b.rs2
-rw-r--r--src/test/run-make-fulldeps/issue-37839/c.rs2
-rw-r--r--src/test/run-make-fulldeps/issue-37893/Makefile4
-rw-r--r--src/test/run-make-fulldeps/issue-37893/a.rs2
-rw-r--r--src/test/run-make-fulldeps/issue-37893/b.rs2
-rw-r--r--src/test/run-make-fulldeps/issue-37893/c.rs3
-rw-r--r--src/test/run-make-fulldeps/issue-38237/Makefile5
-rw-r--r--src/test/run-make-fulldeps/issue-38237/bar.rs4
-rw-r--r--src/test/run-make-fulldeps/issue-38237/baz.rs8
-rw-r--r--src/test/run-make-fulldeps/issue-38237/foo.rs9
-rw-r--r--src/test/run-make-fulldeps/issue-40535/Makefile13
-rw-r--r--src/test/run-make-fulldeps/issue-40535/bar.rs3
-rw-r--r--src/test/run-make-fulldeps/issue-40535/baz.rs1
-rw-r--r--src/test/run-make-fulldeps/issue-40535/foo.rs4
-rw-r--r--src/test/run-make-fulldeps/issue-46239/Makefile5
-rw-r--r--src/test/run-make-fulldeps/issue-46239/main.rs8
-rw-r--r--src/test/run-make-fulldeps/issue-47551/Makefile9
-rw-r--r--src/test/run-make-fulldeps/issue-47551/eh_frame-terminator.rs23
-rw-r--r--src/test/run-make-fulldeps/issue-51671/Makefile9
-rw-r--r--src/test/run-make-fulldeps/issue-51671/app.rs20
-rw-r--r--src/test/run-make-fulldeps/issue-53964/Makefile5
-rw-r--r--src/test/run-make-fulldeps/issue-53964/app.rs8
-rw-r--r--src/test/run-make-fulldeps/issue-53964/panic.rs10
-rw-r--r--src/test/run-make-fulldeps/issue-64153/Makefile26
-rw-r--r--src/test/run-make-fulldeps/issue-64153/downstream.rs6
-rw-r--r--src/test/run-make-fulldeps/issue-64153/upstream.rs6
-rw-r--r--src/test/run-make-fulldeps/issue-68794-textrel-on-minimal-lib/Makefile17
-rw-r--r--src/test/run-make-fulldeps/issue-68794-textrel-on-minimal-lib/bar.c6
-rw-r--r--src/test/run-make-fulldeps/issue-68794-textrel-on-minimal-lib/foo.rs8
-rw-r--r--src/test/run-make-fulldeps/issue-69368/Makefile18
-rw-r--r--src/test/run-make-fulldeps/issue-69368/a.rs21
-rw-r--r--src/test/run-make-fulldeps/issue-69368/b.rs8
-rw-r--r--src/test/run-make-fulldeps/issue-69368/c.rs34
-rw-r--r--src/test/run-make-fulldeps/issue-7349/Makefile11
-rw-r--r--src/test/run-make-fulldeps/issue-7349/foo.rs22
-rw-r--r--src/test/run-make-fulldeps/issue-83045/Makefile33
-rw-r--r--src/test/run-make-fulldeps/issue-83045/a.rs1
-rw-r--r--src/test/run-make-fulldeps/issue-83045/b.rs1
-rw-r--r--src/test/run-make-fulldeps/issue-83045/c.rs1
-rw-r--r--src/test/run-make-fulldeps/issue-84395-lto-embed-bitcode/Makefile11
-rw-r--r--src/test/run-make-fulldeps/issue-84395-lto-embed-bitcode/test.rs3
-rw-r--r--src/test/run-make-fulldeps/issue64319/Makefile39
-rw-r--r--src/test/run-make-fulldeps/issue64319/bar.rs5
-rw-r--r--src/test/run-make-fulldeps/issue64319/foo.rs9
-rw-r--r--src/test/run-make-fulldeps/issues-41478-43796/Makefile8
-rw-r--r--src/test/run-make-fulldeps/issues-41478-43796/a.rs9
-rw-r--r--src/test/run-make-fulldeps/libs-through-symlinks/Makefile11
-rw-r--r--src/test/run-make-fulldeps/libs-through-symlinks/bar.rs3
-rw-r--r--src/test/run-make-fulldeps/libs-through-symlinks/foo.rs2
-rw-r--r--src/test/run-make-fulldeps/libtest-json/Makefile18
-rw-r--r--src/test/run-make-fulldeps/libtest-json/f.rs22
-rw-r--r--src/test/run-make-fulldeps/libtest-json/output-default.json10
-rw-r--r--src/test/run-make-fulldeps/libtest-json/output-stdout-success.json10
-rwxr-xr-xsrc/test/run-make-fulldeps/libtest-json/validate_json.py8
-rw-r--r--src/test/run-make-fulldeps/link-arg/Makefile5
-rw-r--r--src/test/run-make-fulldeps/link-arg/empty.rs1
-rw-r--r--src/test/run-make-fulldeps/link-args-order/Makefile10
-rw-r--r--src/test/run-make-fulldeps/link-args-order/empty.rs1
-rw-r--r--src/test/run-make-fulldeps/link-cfg/Makefile22
-rw-r--r--src/test/run-make-fulldeps/link-cfg/dep-with-staticlib.rs8
-rw-r--r--src/test/run-make-fulldeps/link-cfg/dep.rs8
-rw-r--r--src/test/run-make-fulldeps/link-cfg/no-deps.rs20
-rw-r--r--src/test/run-make-fulldeps/link-cfg/return1.c6
-rw-r--r--src/test/run-make-fulldeps/link-cfg/return2.c6
-rw-r--r--src/test/run-make-fulldeps/link-cfg/return3.c6
-rw-r--r--src/test/run-make-fulldeps/link-cfg/with-deps.rs14
-rw-r--r--src/test/run-make-fulldeps/link-cfg/with-staticlib-deps.rs14
-rw-r--r--src/test/run-make-fulldeps/link-dedup/Makefile12
-rw-r--r--src/test/run-make-fulldeps/link-dedup/depa.rs7
-rw-r--r--src/test/run-make-fulldeps/link-dedup/depb.rs8
-rw-r--r--src/test/run-make-fulldeps/link-dedup/depc.rs4
-rw-r--r--src/test/run-make-fulldeps/link-dedup/empty.rs5
-rw-r--r--src/test/run-make-fulldeps/link-path-order/Makefile18
-rw-r--r--src/test/run-make-fulldeps/link-path-order/correct.c1
-rw-r--r--src/test/run-make-fulldeps/link-path-order/main.rs16
-rw-r--r--src/test/run-make-fulldeps/link-path-order/wrong.c1
-rw-r--r--src/test/run-make-fulldeps/linkage-attr-on-static/Makefile5
-rw-r--r--src/test/run-make-fulldeps/linkage-attr-on-static/bar.rs16
-rw-r--r--src/test/run-make-fulldeps/linkage-attr-on-static/foo.c7
-rw-r--r--src/test/run-make-fulldeps/long-linker-command-lines-cmd-exe/Makefile6
-rw-r--r--src/test/run-make-fulldeps/long-linker-command-lines-cmd-exe/foo.bat1
-rw-r--r--src/test/run-make-fulldeps/long-linker-command-lines-cmd-exe/foo.rs101
-rw-r--r--src/test/run-make-fulldeps/long-linker-command-lines/Makefile5
-rw-r--r--src/test/run-make-fulldeps/long-linker-command-lines/foo.rs106
-rw-r--r--src/test/run-make-fulldeps/longjmp-across-rust/Makefile5
-rw-r--r--src/test/run-make-fulldeps/longjmp-across-rust/foo.c18
-rw-r--r--src/test/run-make-fulldeps/longjmp-across-rust/main.rs29
-rw-r--r--src/test/run-make-fulldeps/ls-metadata/Makefile7
-rw-r--r--src/test/run-make-fulldeps/ls-metadata/foo.rs1
-rw-r--r--src/test/run-make-fulldeps/lto-dylib-dep/Makefile10
-rw-r--r--src/test/run-make-fulldeps/lto-dylib-dep/a_dylib.rs3
-rw-r--r--src/test/run-make-fulldeps/lto-dylib-dep/main.rs5
-rw-r--r--src/test/run-make-fulldeps/lto-empty/Makefile12
-rw-r--r--src/test/run-make-fulldeps/lto-empty/lib.rs1
-rw-r--r--src/test/run-make-fulldeps/lto-no-link-whole-rlib/Makefile8
-rw-r--r--src/test/run-make-fulldeps/lto-no-link-whole-rlib/bar.c3
-rw-r--r--src/test/run-make-fulldeps/lto-no-link-whole-rlib/foo.c3
-rw-r--r--src/test/run-make-fulldeps/lto-no-link-whole-rlib/lib1.rs10
-rw-r--r--src/test/run-make-fulldeps/lto-no-link-whole-rlib/lib2.rs12
-rw-r--r--src/test/run-make-fulldeps/lto-no-link-whole-rlib/main.rs7
-rw-r--r--src/test/run-make-fulldeps/lto-readonly-lib/Makefile12
-rw-r--r--src/test/run-make-fulldeps/lto-readonly-lib/lib.rs1
-rw-r--r--src/test/run-make-fulldeps/lto-readonly-lib/main.rs3
-rw-r--r--src/test/run-make-fulldeps/lto-smoke-c/Makefile11
-rw-r--r--src/test/run-make-fulldeps/lto-smoke-c/bar.c6
-rw-r--r--src/test/run-make-fulldeps/lto-smoke-c/foo.rs4
-rw-r--r--src/test/run-make-fulldeps/lto-smoke/Makefile30
-rw-r--r--src/test/run-make-fulldeps/lto-smoke/lib.rs1
-rw-r--r--src/test/run-make-fulldeps/lto-smoke/main.rs3
-rw-r--r--src/test/run-make-fulldeps/manual-crate-name/Makefile5
-rw-r--r--src/test/run-make-fulldeps/manual-crate-name/bar.rs1
-rw-r--r--src/test/run-make-fulldeps/manual-link/Makefile6
-rw-r--r--src/test/run-make-fulldeps/manual-link/bar.c1
-rw-r--r--src/test/run-make-fulldeps/manual-link/foo.c1
-rw-r--r--src/test/run-make-fulldeps/manual-link/foo.rs11
-rw-r--r--src/test/run-make-fulldeps/manual-link/main.rs5
-rw-r--r--src/test/run-make-fulldeps/many-crates-but-no-match/Makefile35
-rw-r--r--src/test/run-make-fulldeps/many-crates-but-no-match/crateA1.rs4
-rw-r--r--src/test/run-make-fulldeps/many-crates-but-no-match/crateA2.rs4
-rw-r--r--src/test/run-make-fulldeps/many-crates-but-no-match/crateA3.rs4
-rw-r--r--src/test/run-make-fulldeps/many-crates-but-no-match/crateB.rs1
-rw-r--r--src/test/run-make-fulldeps/many-crates-but-no-match/crateC.rs3
-rw-r--r--src/test/run-make-fulldeps/metadata-flag-frobs-symbols/Makefile10
-rw-r--r--src/test/run-make-fulldeps/metadata-flag-frobs-symbols/bar.rs8
-rw-r--r--src/test/run-make-fulldeps/metadata-flag-frobs-symbols/foo.rs6
-rw-r--r--src/test/run-make-fulldeps/min-global-align/Makefile22
-rw-r--r--src/test/run-make-fulldeps/min-global-align/min_global_align.rs32
-rw-r--r--src/test/run-make-fulldeps/mingw-export-call-convention/Makefile9
-rw-r--r--src/test/run-make-fulldeps/mingw-export-call-convention/foo.rs4
-rw-r--r--src/test/run-make-fulldeps/mismatching-target-triples/Makefile11
-rw-r--r--src/test/run-make-fulldeps/mismatching-target-triples/bar.rs3
-rw-r--r--src/test/run-make-fulldeps/mismatching-target-triples/foo.rs3
-rw-r--r--src/test/run-make-fulldeps/missing-crate-dependency/Makefile9
-rw-r--r--src/test/run-make-fulldeps/missing-crate-dependency/crateA.rs2
-rw-r--r--src/test/run-make-fulldeps/missing-crate-dependency/crateB.rs1
-rw-r--r--src/test/run-make-fulldeps/missing-crate-dependency/crateC.rs3
-rw-r--r--src/test/run-make-fulldeps/mixing-deps/Makefile7
-rw-r--r--src/test/run-make-fulldeps/mixing-deps/both.rs4
-rw-r--r--src/test/run-make-fulldeps/mixing-deps/dylib.rs6
-rw-r--r--src/test/run-make-fulldeps/mixing-deps/prog.rs9
-rw-r--r--src/test/run-make-fulldeps/mixing-formats/Makefile74
-rw-r--r--src/test/run-make-fulldeps/mixing-formats/bar1.rs1
-rw-r--r--src/test/run-make-fulldeps/mixing-formats/bar2.rs1
-rw-r--r--src/test/run-make-fulldeps/mixing-formats/baz.rs3
-rw-r--r--src/test/run-make-fulldeps/mixing-formats/baz2.rs4
-rw-r--r--src/test/run-make-fulldeps/mixing-formats/foo.rs1
-rw-r--r--src/test/run-make-fulldeps/mixing-libs/Makefile9
-rw-r--r--src/test/run-make-fulldeps/mixing-libs/dylib.rs4
-rw-r--r--src/test/run-make-fulldeps/mixing-libs/prog.rs7
-rw-r--r--src/test/run-make-fulldeps/mixing-libs/rlib.rs2
-rw-r--r--src/test/run-make-fulldeps/msvc-opt-minsize/Makefile5
-rw-r--r--src/test/run-make-fulldeps/msvc-opt-minsize/foo.rs19
-rw-r--r--src/test/run-make-fulldeps/multiple-emits/Makefile7
-rw-r--r--src/test/run-make-fulldeps/multiple-emits/foo.rs1
-rw-r--r--src/test/run-make-fulldeps/no-builtins-lto/Makefile9
-rw-r--r--src/test/run-make-fulldeps/no-builtins-lto/main.rs3
-rw-r--r--src/test/run-make-fulldeps/no-builtins-lto/no_builtins.rs2
-rw-r--r--src/test/run-make-fulldeps/no-duplicate-libs/Makefile10
-rw-r--r--src/test/run-make-fulldeps/no-duplicate-libs/bar.c5
-rw-r--r--src/test/run-make-fulldeps/no-duplicate-libs/foo.c1
-rw-r--r--src/test/run-make-fulldeps/no-duplicate-libs/main.rs10
-rw-r--r--src/test/run-make-fulldeps/no-intermediate-extras/Makefile7
-rw-r--r--src/test/run-make-fulldeps/no-intermediate-extras/foo.rs1
-rw-r--r--src/test/run-make-fulldeps/obey-crate-type-flag/Makefile13
-rw-r--r--src/test/run-make-fulldeps/obey-crate-type-flag/test.rs2
-rw-r--r--src/test/run-make-fulldeps/obtain-borrowck/Makefile26
-rw-r--r--src/test/run-make-fulldeps/obtain-borrowck/driver.rs161
-rw-r--r--src/test/run-make-fulldeps/obtain-borrowck/output.stdout8
-rw-r--r--src/test/run-make-fulldeps/obtain-borrowck/test.rs32
-rw-r--r--src/test/run-make-fulldeps/output-filename-conflicts-with-directory/Makefile7
-rw-r--r--src/test/run-make-fulldeps/output-filename-conflicts-with-directory/foo.rs1
-rw-r--r--src/test/run-make-fulldeps/output-filename-overwrites-input/Makefile13
-rw-r--r--src/test/run-make-fulldeps/output-filename-overwrites-input/bar.rs1
-rw-r--r--src/test/run-make-fulldeps/output-filename-overwrites-input/foo.rs1
-rw-r--r--src/test/run-make-fulldeps/output-type-permutations/Makefile146
-rw-r--r--src/test/run-make-fulldeps/output-type-permutations/foo.rs3
-rw-r--r--src/test/run-make-fulldeps/output-with-hyphens/Makefile7
-rw-r--r--src/test/run-make-fulldeps/output-with-hyphens/foo-bar.rs1
-rw-r--r--src/test/run-make-fulldeps/override-aliased-flags/Makefile22
-rw-r--r--src/test/run-make-fulldeps/override-aliased-flags/main.rs1
-rw-r--r--src/test/run-make-fulldeps/panic-impl-transitive/Makefile7
-rw-r--r--src/test/run-make-fulldeps/panic-impl-transitive/panic-impl-consumer.rs5
-rw-r--r--src/test/run-make-fulldeps/panic-impl-transitive/panic-impl-provider.rs9
-rw-r--r--src/test/run-make-fulldeps/pass-non-c-like-enum-to-c/Makefile5
-rw-r--r--src/test/run-make-fulldeps/pass-non-c-like-enum-to-c/nonclike.rs21
-rw-r--r--src/test/run-make-fulldeps/pass-non-c-like-enum-to-c/test.c85
-rw-r--r--src/test/run-make-fulldeps/pgo-branch-weights/Makefile34
-rw-r--r--src/test/run-make-fulldeps/pgo-branch-weights/filecheck-patterns.txt24
-rw-r--r--src/test/run-make-fulldeps/pgo-branch-weights/interesting.rs40
-rw-r--r--src/test/run-make-fulldeps/pgo-branch-weights/main.rs17
-rw-r--r--src/test/run-make-fulldeps/pgo-branch-weights/opaque.rs6
-rw-r--r--src/test/run-make-fulldeps/pgo-gen-lto/Makefile14
-rw-r--r--src/test/run-make-fulldeps/pgo-gen-lto/test.rs1
-rw-r--r--src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/Makefile13
-rw-r--r--src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/test.rs1
-rw-r--r--src/test/run-make-fulldeps/pgo-gen/Makefile14
-rw-r--r--src/test/run-make-fulldeps/pgo-gen/test.rs1
-rw-r--r--src/test/run-make-fulldeps/pgo-indirect-call-promotion/Makefile26
-rw-r--r--src/test/run-make-fulldeps/pgo-indirect-call-promotion/filecheck-patterns.txt16
-rw-r--r--src/test/run-make-fulldeps/pgo-indirect-call-promotion/interesting.rs56
-rw-r--r--src/test/run-make-fulldeps/pgo-indirect-call-promotion/main.rs14
-rw-r--r--src/test/run-make-fulldeps/pgo-indirect-call-promotion/opaque.rs7
-rw-r--r--src/test/run-make-fulldeps/pgo-use/Makefile46
-rw-r--r--src/test/run-make-fulldeps/pgo-use/filecheck-patterns.txt11
-rw-r--r--src/test/run-make-fulldeps/pgo-use/main.rs23
-rw-r--r--src/test/run-make-fulldeps/pointer-auth-link-with-c/Makefile14
-rw-r--r--src/test/run-make-fulldeps/pointer-auth-link-with-c/test.c1
-rw-r--r--src/test/run-make-fulldeps/pointer-auth-link-with-c/test.rs8
-rw-r--r--src/test/run-make-fulldeps/prefer-dylib/Makefile8
-rw-r--r--src/test/run-make-fulldeps/prefer-dylib/bar.rs1
-rw-r--r--src/test/run-make-fulldeps/prefer-dylib/foo.rs5
-rw-r--r--src/test/run-make-fulldeps/prefer-rlib/Makefile8
-rw-r--r--src/test/run-make-fulldeps/prefer-rlib/bar.rs1
-rw-r--r--src/test/run-make-fulldeps/prefer-rlib/foo.rs5
-rw-r--r--src/test/run-make-fulldeps/pretty-expanded/Makefile4
-rw-r--r--src/test/run-make-fulldeps/pretty-expanded/input.rs12
-rw-r--r--src/test/run-make-fulldeps/pretty-print-to-file/Makefile5
-rw-r--r--src/test/run-make-fulldeps/pretty-print-to-file/input.pp3
-rw-r--r--src/test/run-make-fulldeps/pretty-print-to-file/input.rs5
-rw-r--r--src/test/run-make-fulldeps/print-cfg/Makefile20
-rw-r--r--src/test/run-make-fulldeps/print-target-list/Makefile8
-rw-r--r--src/test/run-make-fulldeps/profile/Makefile12
-rw-r--r--src/test/run-make-fulldeps/profile/test.rs1
-rw-r--r--src/test/run-make-fulldeps/prune-link-args/Makefile9
-rw-r--r--src/test/run-make-fulldeps/prune-link-args/empty.rs1
-rw-r--r--src/test/run-make-fulldeps/redundant-libs/Makefile23
-rw-r--r--src/test/run-make-fulldeps/redundant-libs/bar.c1
-rw-r--r--src/test/run-make-fulldeps/redundant-libs/baz.c7
-rw-r--r--src/test/run-make-fulldeps/redundant-libs/foo.c2
-rw-r--r--src/test/run-make-fulldeps/redundant-libs/main.rs11
-rw-r--r--src/test/run-make-fulldeps/relocation-model/Makefile19
-rw-r--r--src/test/run-make-fulldeps/relocation-model/foo.rs1
-rw-r--r--src/test/run-make-fulldeps/relro-levels/Makefile21
-rw-r--r--src/test/run-make-fulldeps/relro-levels/hello.rs3
-rw-r--r--src/test/run-make-fulldeps/remap-path-prefix/Makefile9
-rw-r--r--src/test/run-make-fulldeps/remap-path-prefix/auxiliary/lib.rs3
-rw-r--r--src/test/run-make-fulldeps/reproducible-build-2/Makefile26
-rw-r--r--src/test/run-make-fulldeps/reproducible-build-2/linker.rs44
-rw-r--r--src/test/run-make-fulldeps/reproducible-build-2/reproducible-build-aux.rs28
-rw-r--r--src/test/run-make-fulldeps/reproducible-build-2/reproducible-build.rs116
-rw-r--r--src/test/run-make-fulldeps/reproducible-build/Makefile139
-rw-r--r--src/test/run-make-fulldeps/reproducible-build/linker.rs50
-rw-r--r--src/test/run-make-fulldeps/reproducible-build/reproducible-build-aux.rs28
-rw-r--r--src/test/run-make-fulldeps/reproducible-build/reproducible-build.rs116
-rw-r--r--src/test/run-make-fulldeps/resolve-rename/Makefile7
-rw-r--r--src/test/run-make-fulldeps/resolve-rename/bar.rs5
-rw-r--r--src/test/run-make-fulldeps/resolve-rename/baz.rs5
-rw-r--r--src/test/run-make-fulldeps/resolve-rename/foo.rs3
-rw-r--r--src/test/run-make-fulldeps/return-non-c-like-enum-from-c/Makefile5
-rw-r--r--src/test/run-make-fulldeps/return-non-c-like-enum-from-c/nonclike.rs31
-rw-r--r--src/test/run-make-fulldeps/return-non-c-like-enum-from-c/test.c61
-rw-r--r--src/test/run-make-fulldeps/return-non-c-like-enum/Makefile7
-rw-r--r--src/test/run-make-fulldeps/return-non-c-like-enum/nonclike.rs21
-rw-r--r--src/test/run-make-fulldeps/return-non-c-like-enum/test.c63
-rw-r--r--src/test/run-make-fulldeps/rlib-chain/Makefile10
-rw-r--r--src/test/run-make-fulldeps/rlib-chain/m1.rs2
-rw-r--r--src/test/run-make-fulldeps/rlib-chain/m2.rs4
-rw-r--r--src/test/run-make-fulldeps/rlib-chain/m3.rs4
-rw-r--r--src/test/run-make-fulldeps/rlib-chain/m4.rs3
-rw-r--r--src/test/run-make-fulldeps/rustdoc-determinism/Makefile16
-rw-r--r--src/test/run-make-fulldeps/rustdoc-determinism/bar.rs1
-rw-r--r--src/test/run-make-fulldeps/rustdoc-determinism/foo.rs1
-rw-r--r--src/test/run-make-fulldeps/rustdoc-error-lines/Makefile13
-rw-r--r--src/test/run-make-fulldeps/rustdoc-error-lines/input.rs28
-rw-r--r--src/test/run-make-fulldeps/rustdoc-io-error/Makefile20
-rw-r--r--src/test/run-make-fulldeps/rustdoc-io-error/foo.rs1
-rw-r--r--src/test/run-make-fulldeps/rustdoc-map-file/Makefile5
-rw-r--r--src/test/run-make-fulldeps/rustdoc-map-file/expected.json5
-rw-r--r--src/test/run-make-fulldeps/rustdoc-map-file/foo.rs16
-rwxr-xr-xsrc/test/run-make-fulldeps/rustdoc-map-file/validate_json.py41
-rw-r--r--src/test/run-make-fulldeps/rustdoc-output-path/Makefile4
-rw-r--r--src/test/run-make-fulldeps/rustdoc-output-path/foo.rs1
-rw-r--r--src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/Makefile18
-rw-r--r--src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/examples/ex.rs27
-rw-r--r--src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/lib.rs12
-rw-r--r--src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/proc.rs39
-rw-r--r--src/test/run-make-fulldeps/rustdoc-target-spec-json-path/Makefile9
-rw-r--r--src/test/run-make-fulldeps/rustdoc-target-spec-json-path/dummy_core.rs2
-rw-r--r--src/test/run-make-fulldeps/rustdoc-target-spec-json-path/my_crate.rs3
-rw-r--r--src/test/run-make-fulldeps/rustdoc-target-spec-json-path/target.json38
-rw-r--r--src/test/run-make-fulldeps/rustdoc-themes/Makefile10
-rw-r--r--src/test/run-make-fulldeps/rustdoc-themes/foo.rs4
-rw-r--r--src/test/run-make-fulldeps/sanitizer-cdylib-link/Makefile16
-rw-r--r--src/test/run-make-fulldeps/sanitizer-cdylib-link/library.rs5
-rw-r--r--src/test/run-make-fulldeps/sanitizer-cdylib-link/program.rs7
-rw-r--r--src/test/run-make-fulldeps/sanitizer-dylib-link/Makefile16
-rw-r--r--src/test/run-make-fulldeps/sanitizer-dylib-link/library.rs5
-rw-r--r--src/test/run-make-fulldeps/sanitizer-dylib-link/program.rs7
-rw-r--r--src/test/run-make-fulldeps/sanitizer-staticlib-link/Makefile20
-rw-r--r--src/test/run-make-fulldeps/sanitizer-staticlib-link/library.rs5
-rw-r--r--src/test/run-make-fulldeps/sanitizer-staticlib-link/program.c6
-rw-r--r--src/test/run-make-fulldeps/sanitizer-staticlib-link/program.rs10
-rw-r--r--src/test/run-make-fulldeps/save-analysis-fail/Makefile6
-rw-r--r--src/test/run-make-fulldeps/save-analysis-fail/SameDir.rs5
-rw-r--r--src/test/run-make-fulldeps/save-analysis-fail/SameDir3.rs3
-rw-r--r--src/test/run-make-fulldeps/save-analysis-fail/SubDir/mod.rs27
-rw-r--r--src/test/run-make-fulldeps/save-analysis-fail/foo.rs464
-rw-r--r--src/test/run-make-fulldeps/save-analysis-fail/krate2.rs8
-rw-r--r--src/test/run-make-fulldeps/save-analysis-rfc2126/Makefile8
-rw-r--r--src/test/run-make-fulldeps/save-analysis-rfc2126/extern_absolute_paths.rs6
-rw-r--r--src/test/run-make-fulldeps/save-analysis-rfc2126/krate2.rs5
-rw-r--r--src/test/run-make-fulldeps/save-analysis-rfc2126/validate_json.py7
-rw-r--r--src/test/run-make-fulldeps/save-analysis/Makefile6
-rw-r--r--src/test/run-make-fulldeps/save-analysis/SameDir.rs5
-rw-r--r--src/test/run-make-fulldeps/save-analysis/SameDir3.rs3
-rw-r--r--src/test/run-make-fulldeps/save-analysis/SubDir/mod.rs27
-rw-r--r--src/test/run-make-fulldeps/save-analysis/extra-docs.md1
-rw-r--r--src/test/run-make-fulldeps/save-analysis/foo.rs461
-rw-r--r--src/test/run-make-fulldeps/save-analysis/krate2.rs8
-rw-r--r--src/test/run-make-fulldeps/separate-link-fail/Makefile7
-rw-r--r--src/test/run-make-fulldeps/separate-link/Makefile6
-rw-r--r--src/test/run-make-fulldeps/sepcomp-cci-copies/Makefile12
-rw-r--r--src/test/run-make-fulldeps/sepcomp-cci-copies/cci_lib.rs6
-rw-r--r--src/test/run-make-fulldeps/sepcomp-cci-copies/foo.rs25
-rw-r--r--src/test/run-make-fulldeps/sepcomp-inlining/Makefile15
-rw-r--r--src/test/run-make-fulldeps/sepcomp-inlining/foo.rs30
-rw-r--r--src/test/run-make-fulldeps/sepcomp-separate/Makefile9
-rw-r--r--src/test/run-make-fulldeps/sepcomp-separate/foo.rs21
-rw-r--r--src/test/run-make-fulldeps/share-generics-dylib/Makefile22
-rw-r--r--src/test/run-make-fulldeps/share-generics-dylib/instance_provider_a.rs6
-rw-r--r--src/test/run-make-fulldeps/share-generics-dylib/instance_provider_b.rs6
-rw-r--r--src/test/run-make-fulldeps/share-generics-dylib/instance_user_a_rlib.rs9
-rw-r--r--src/test/run-make-fulldeps/share-generics-dylib/instance_user_b_rlib.rs9
-rw-r--r--src/test/run-make-fulldeps/share-generics-dylib/instance_user_dylib.rs7
-rw-r--r--src/test/run-make-fulldeps/share-generics-dylib/linked_leaf.rs15
-rw-r--r--src/test/run-make-fulldeps/simd-ffi/Makefile47
-rw-r--r--src/test/run-make-fulldeps/simd-ffi/simd.rs82
-rw-r--r--src/test/run-make-fulldeps/simple-dylib/Makefile5
-rw-r--r--src/test/run-make-fulldeps/simple-dylib/bar.rs1
-rw-r--r--src/test/run-make-fulldeps/simple-dylib/foo.rs5
-rw-r--r--src/test/run-make-fulldeps/simple-rlib/Makefile5
-rw-r--r--src/test/run-make-fulldeps/simple-rlib/bar.rs1
-rw-r--r--src/test/run-make-fulldeps/simple-rlib/foo.rs5
-rw-r--r--src/test/run-make-fulldeps/split-debuginfo/Makefile121
-rw-r--r--src/test/run-make-fulldeps/split-debuginfo/bar.rs13
-rw-r--r--src/test/run-make-fulldeps/split-debuginfo/foo.rs15
-rw-r--r--src/test/run-make-fulldeps/split-debuginfo/main.rs8
-rw-r--r--src/test/run-make-fulldeps/stable-symbol-names/Makefile41
-rw-r--r--src/test/run-make-fulldeps/stable-symbol-names/stable-symbol-names1.rs31
-rw-r--r--src/test/run-make-fulldeps/stable-symbol-names/stable-symbol-names2.rs17
-rw-r--r--src/test/run-make-fulldeps/static-dylib-by-default/Makefile16
-rw-r--r--src/test/run-make-fulldeps/static-dylib-by-default/bar.rs8
-rw-r--r--src/test/run-make-fulldeps/static-dylib-by-default/foo.rs4
-rw-r--r--src/test/run-make-fulldeps/static-dylib-by-default/main.c6
-rw-r--r--src/test/run-make-fulldeps/static-extern-type/Makefile5
-rw-r--r--src/test/run-make-fulldeps/static-extern-type/define-foo.c11
-rw-r--r--src/test/run-make-fulldeps/static-extern-type/use-foo.rs14
-rw-r--r--src/test/run-make-fulldeps/static-unwinding/Makefile6
-rw-r--r--src/test/run-make-fulldeps/static-unwinding/lib.rs15
-rw-r--r--src/test/run-make-fulldeps/static-unwinding/main.rs24
-rw-r--r--src/test/run-make-fulldeps/staticlib-blank-lib/Makefile6
-rw-r--r--src/test/run-make-fulldeps/staticlib-blank-lib/foo.rs6
-rw-r--r--src/test/run-make-fulldeps/std-core-cycle/Makefile16
-rw-r--r--src/test/run-make-fulldeps/std-core-cycle/bar.rs16
-rw-r--r--src/test/run-make-fulldeps/std-core-cycle/foo.rs11
-rw-r--r--src/test/run-make-fulldeps/stdin-non-utf8/Makefile6
-rw-r--r--src/test/run-make-fulldeps/stdin-non-utf8/non-utf81
-rw-r--r--src/test/run-make-fulldeps/suspicious-library/Makefile7
-rw-r--r--src/test/run-make-fulldeps/suspicious-library/bar.rs3
-rw-r--r--src/test/run-make-fulldeps/suspicious-library/foo.rs3
-rw-r--r--src/test/run-make-fulldeps/symbol-visibility/Makefile122
-rw-r--r--src/test/run-make-fulldeps/symbol-visibility/a_cdylib.rs12
-rw-r--r--src/test/run-make-fulldeps/symbol-visibility/a_proc_macro.rs9
-rw-r--r--src/test/run-make-fulldeps/symbol-visibility/a_rust_dylib.rs15
-rw-r--r--src/test/run-make-fulldeps/symbol-visibility/an_executable.rs7
-rw-r--r--src/test/run-make-fulldeps/symbol-visibility/an_rlib.rs12
-rw-r--r--src/test/run-make-fulldeps/symbols-include-type-name/Makefile9
-rw-r--r--src/test/run-make-fulldeps/symbols-include-type-name/lib.rs14
-rw-r--r--src/test/run-make-fulldeps/symlinked-extern/Makefile11
-rw-r--r--src/test/run-make-fulldeps/symlinked-extern/bar.rs6
-rw-r--r--src/test/run-make-fulldeps/symlinked-extern/baz.rs6
-rw-r--r--src/test/run-make-fulldeps/symlinked-extern/foo.rs5
-rw-r--r--src/test/run-make-fulldeps/symlinked-libraries/Makefile10
-rw-r--r--src/test/run-make-fulldeps/symlinked-libraries/bar.rs5
-rw-r--r--src/test/run-make-fulldeps/symlinked-libraries/foo.rs3
-rw-r--r--src/test/run-make-fulldeps/symlinked-rlib/Makefile9
-rw-r--r--src/test/run-make-fulldeps/symlinked-rlib/bar.rs5
-rw-r--r--src/test/run-make-fulldeps/symlinked-rlib/foo.rs1
-rw-r--r--src/test/run-make-fulldeps/sysroot-crates-are-unstable/Makefile2
-rw-r--r--src/test/run-make-fulldeps/sysroot-crates-are-unstable/test.py74
-rw-r--r--src/test/run-make-fulldeps/target-cpu-native/Makefile20
-rw-r--r--src/test/run-make-fulldeps/target-cpu-native/foo.rs2
-rw-r--r--src/test/run-make-fulldeps/target-specs/Makefile11
-rw-r--r--src/test/run-make-fulldeps/target-specs/definitely-not-builtin-target.json7
-rw-r--r--src/test/run-make-fulldeps/target-specs/foo.rs24
-rw-r--r--src/test/run-make-fulldeps/target-specs/mismatching-data-layout.json6
-rw-r--r--src/test/run-make-fulldeps/target-specs/my-awesome-platform.json11
-rw-r--r--src/test/run-make-fulldeps/target-specs/my-incomplete-platform.json10
-rw-r--r--src/test/run-make-fulldeps/target-specs/my-invalid-platform.json1
-rw-r--r--src/test/run-make-fulldeps/target-specs/my-x86_64-unknown-linux-gnu-platform.json12
-rw-r--r--src/test/run-make-fulldeps/target-without-atomic-cas/Makefile5
-rw-r--r--src/test/run-make-fulldeps/test-harness/Makefile8
-rw-r--r--src/test/run-make-fulldeps/test-harness/test-ignore-cfg.rs9
-rw-r--r--src/test/run-make-fulldeps/tools.mk176
-rw-r--r--src/test/run-make-fulldeps/type-mismatch-same-crate-name/Makefile19
-rw-r--r--src/test/run-make-fulldeps/type-mismatch-same-crate-name/crateA.rs16
-rw-r--r--src/test/run-make-fulldeps/type-mismatch-same-crate-name/crateB.rs4
-rw-r--r--src/test/run-make-fulldeps/type-mismatch-same-crate-name/crateC.rs25
-rw-r--r--src/test/run-make-fulldeps/use-extern-for-plugins/Makefile17
-rw-r--r--src/test/run-make-fulldeps/use-extern-for-plugins/bar.rs9
-rw-r--r--src/test/run-make-fulldeps/use-extern-for-plugins/baz.rs8
-rw-r--r--src/test/run-make-fulldeps/use-extern-for-plugins/foo.rs8
-rw-r--r--src/test/run-make-fulldeps/use-suggestions-rust-2018/Makefile7
-rw-r--r--src/test/run-make-fulldeps/use-suggestions-rust-2018/ep-nested-lib.rs7
-rw-r--r--src/test/run-make-fulldeps/use-suggestions-rust-2018/use-suggestions.rs3
-rw-r--r--src/test/run-make-fulldeps/used-cdylib-macos/Makefile11
-rw-r--r--src/test/run-make-fulldeps/used-cdylib-macos/dylib_used.rs4
-rw-r--r--src/test/run-make-fulldeps/used/Makefile7
-rw-r--r--src/test/run-make-fulldeps/used/used.rs6
-rw-r--r--src/test/run-make-fulldeps/version/Makefile6
-rw-r--r--src/test/run-make-fulldeps/volatile-intrinsics/Makefile9
-rw-r--r--src/test/run-make-fulldeps/volatile-intrinsics/main.rs24
-rw-r--r--src/test/run-make-fulldeps/weird-output-filenames/Makefile15
-rw-r--r--src/test/run-make-fulldeps/weird-output-filenames/foo.rs1
-rw-r--r--src/test/run-make-fulldeps/windows-binary-no-external-deps/Makefile9
-rw-r--r--src/test/run-make-fulldeps/windows-binary-no-external-deps/hello.rs3
-rw-r--r--src/test/run-make-fulldeps/windows-spawn/Makefile8
-rw-r--r--src/test/run-make-fulldeps/windows-spawn/hello.rs3
-rw-r--r--src/test/run-make-fulldeps/windows-spawn/spawn.rs12
-rw-r--r--src/test/run-make-fulldeps/windows-subsystem/Makefile5
-rw-r--r--src/test/run-make-fulldeps/windows-subsystem/console.rs3
-rw-r--r--src/test/run-make-fulldeps/windows-subsystem/windows.rs3
-rw-r--r--src/test/run-make/const_fn_mir/Makefile10
-rw-r--r--src/test/run-make/const_fn_mir/dump.mir42
-rw-r--r--src/test/run-make/const_fn_mir/main.rs10
-rw-r--r--src/test/run-make/coverage-llvmir/Makefile64
-rw-r--r--src/test/run-make/coverage-llvmir/filecheck.testprog.txt50
-rw-r--r--src/test/run-make/coverage-llvmir/testprog.rs38
-rw-r--r--src/test/run-make/coverage-reports/Makefile180
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.abort.txt69
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.assert.txt34
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.async.txt139
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.async2.txt116
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.closure.txt222
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.closure_macro.txt42
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.closure_macro_async.txt83
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.conditions.txt94
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.continue.txt70
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.dead_code.txt39
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.doctest.txt121
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.drop_trait.txt34
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.generator.txt32
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.generics.txt71
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.if.txt30
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.if_else.txt41
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.inline-dead.txt28
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.inline.txt54
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.inner_items.txt60
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.issue-83601.txt22
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.issue-84561.txt195
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.issue-85461.txt36
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.issue-93054.txt29
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.lazy_boolean.txt64
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.loop_break_value.txt14
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.loops_branches.txt68
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.match_or_pattern.txt50
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.nested_loops.txt26
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.no_cov_crate.txt87
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.overflow.txt64
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.panic_unwind.txt32
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.partial_eq.txt53
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.simple_loop.txt37
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.simple_match.txt45
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.tight_inf_loop.txt6
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.try_error_result.txt125
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.unused.txt62
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.unused_mod.txt4
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.uses_crate.txt148
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.uses_inline_crate.txt139
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.while.txt6
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.while_early_ret.txt43
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.yield.txt38
-rwxr-xr-xsrc/test/run-make/coverage-reports/normalize_paths.py12
-rw-r--r--src/test/run-make/coverage/WARNING_KEEP_NAMES_SHORT.txt10
-rw-r--r--src/test/run-make/coverage/abort.rs66
-rw-r--r--src/test/run-make/coverage/assert.rs32
-rw-r--r--src/test/run-make/coverage/async.rs128
-rw-r--r--src/test/run-make/coverage/async2.rs69
-rw-r--r--src/test/run-make/coverage/closure.rs215
-rw-r--r--src/test/run-make/coverage/closure_macro.rs40
-rw-r--r--src/test/run-make/coverage/closure_macro_async.rs81
-rw-r--r--src/test/run-make/coverage/compiletest-ignore-dir3
-rw-r--r--src/test/run-make/coverage/conditions.rs87
-rw-r--r--src/test/run-make/coverage/continue.rs69
-rw-r--r--src/test/run-make/coverage/coverage_tools.mk6
-rw-r--r--src/test/run-make/coverage/dead_code.rs37
-rw-r--r--src/test/run-make/coverage/doctest.rs99
-rw-r--r--src/test/run-make/coverage/drop_trait.rs33
-rw-r--r--src/test/run-make/coverage/generator.rs30
-rw-r--r--src/test/run-make/coverage/generics.rs48
-rw-r--r--src/test/run-make/coverage/if.rs28
-rw-r--r--src/test/run-make/coverage/if_else.rs40
-rw-r--r--src/test/run-make/coverage/inline-dead.rs27
-rw-r--r--src/test/run-make/coverage/inline.rs51
-rw-r--r--src/test/run-make/coverage/inner_items.rs57
-rw-r--r--src/test/run-make/coverage/issue-83601.rs14
-rw-r--r--src/test/run-make/coverage/issue-84561.rs182
-rw-r--r--src/test/run-make/coverage/issue-85461.rs10
-rw-r--r--src/test/run-make/coverage/issue-93054.rs28
-rw-r--r--src/test/run-make/coverage/lazy_boolean.rs61
-rw-r--r--src/test/run-make/coverage/lib/doctest_crate.rs9
-rw-r--r--src/test/run-make/coverage/lib/inline_always_with_dead_code.rs22
-rw-r--r--src/test/run-make/coverage/lib/unused_mod_helper.rs3
-rw-r--r--src/test/run-make/coverage/lib/used_crate.rs100
-rw-r--r--src/test/run-make/coverage/lib/used_inline_crate.rs90
-rw-r--r--src/test/run-make/coverage/loop_break_value.rs13
-rw-r--r--src/test/run-make/coverage/loops_branches.rs61
-rw-r--r--src/test/run-make/coverage/match_or_pattern.rs45
-rw-r--r--src/test/run-make/coverage/nested_loops.rs25
-rw-r--r--src/test/run-make/coverage/no_cov_crate.rs86
-rw-r--r--src/test/run-make/coverage/overflow.rs63
-rw-r--r--src/test/run-make/coverage/panic_unwind.rs31
-rw-r--r--src/test/run-make/coverage/partial_eq.rs46
-rw-r--r--src/test/run-make/coverage/simple_loop.rs35
-rw-r--r--src/test/run-make/coverage/simple_match.rs43
-rw-r--r--src/test/run-make/coverage/tight_inf_loop.rs5
-rw-r--r--src/test/run-make/coverage/try_error_result.rs118
-rw-r--r--src/test/run-make/coverage/unused.rs39
-rw-r--r--src/test/run-make/coverage/unused_mod.rs6
-rw-r--r--src/test/run-make/coverage/uses_crate.rs12
-rw-r--r--src/test/run-make/coverage/uses_inline_crate.rs17
-rw-r--r--src/test/run-make/coverage/while.rs5
-rw-r--r--src/test/run-make/coverage/while_early_ret.rs42
-rw-r--r--src/test/run-make/coverage/yield.rs37
-rw-r--r--src/test/run-make/dep-graph/Makefile12
-rw-r--r--src/test/run-make/dep-graph/foo.rs1
-rw-r--r--src/test/run-make/emit-named-files/Makefile33
-rw-r--r--src/test/run-make/emit-named-files/foo.rs1
-rw-r--r--src/test/run-make/emit-path-unhashed/Makefile37
-rw-r--r--src/test/run-make/emit-path-unhashed/foo.rs1
-rw-r--r--src/test/run-make/emit-shared-files/Makefile46
-rw-r--r--src/test/run-make/emit-shared-files/x.rs1
-rw-r--r--src/test/run-make/emit-shared-files/y.css0
-rw-r--r--src/test/run-make/emit-shared-files/z.css0
-rw-r--r--src/test/run-make/env-dep-info/Makefile19
-rw-r--r--src/test/run-make/env-dep-info/macro_def.rs12
-rw-r--r--src/test/run-make/env-dep-info/macro_use.rs6
-rw-r--r--src/test/run-make/env-dep-info/main.rs6
-rw-r--r--src/test/run-make/export-executable-symbols/Makefile11
-rw-r--r--src/test/run-make/export-executable-symbols/main.rs8
-rw-r--r--src/test/run-make/fmt-write-bloat/Makefile25
-rw-r--r--src/test/run-make/fmt-write-bloat/main.rs32
-rw-r--r--src/test/run-make/git_clone_sha1.sh23
-rw-r--r--src/test/run-make/incr-foreign-head-span/Makefile21
-rw-r--r--src/test/run-make/incr-foreign-head-span/first_crate.rs1
-rw-r--r--src/test/run-make/incr-foreign-head-span/second_crate.rs8
-rw-r--r--src/test/run-make/incr-prev-body-beyond-eof/Makefile19
-rw-r--r--src/test/run-make/incr-prev-body-beyond-eof/a.rs16
-rw-r--r--src/test/run-make/incr-prev-body-beyond-eof/b.rs12
-rw-r--r--src/test/run-make/incremental-session-fail/Makefile14
-rw-r--r--src/test/run-make/incremental-session-fail/foo.rs1
-rw-r--r--src/test/run-make/invalid-so/Makefile7
-rw-r--r--src/test/run-make/invalid-so/bar.rs1
-rw-r--r--src/test/run-make/issue-10971-temps-dir/Makefile10
-rw-r--r--src/test/run-make/issue-36710/Makefile20
-rw-r--r--src/test/run-make/issue-36710/foo.cpp15
-rw-r--r--src/test/run-make/issue-36710/foo.rs10
-rw-r--r--src/test/run-make/issue-47384/Makefile12
-rw-r--r--src/test/run-make/issue-47384/lib.rs12
-rw-r--r--src/test/run-make/issue-47384/linker.ld7
-rw-r--r--src/test/run-make/issue-47384/main.rs1
-rw-r--r--src/test/run-make/issue-71519/Makefile6
-rw-r--r--src/test/run-make/issue-71519/main.rs4
-rw-r--r--src/test/run-make/issue-83112-incr-test-moved-file/Makefile25
-rw-r--r--src/test/run-make/issue-83112-incr-test-moved-file/main.rs1
-rw-r--r--src/test/run-make/issue-85019-moved-src-dir/Makefile28
-rw-r--r--src/test/run-make/issue-85019-moved-src-dir/main.rs5
-rw-r--r--src/test/run-make/issue-85019-moved-src-dir/my_lib.rs1
-rw-r--r--src/test/run-make/issue-85441/Makefile9
-rw-r--r--src/test/run-make/issue-85441/empty.rs1
-rw-r--r--src/test/run-make/issue-88756-default-output/Makefile4
-rw-r--r--src/test/run-make/issue-88756-default-output/README.md1
-rw-r--r--src/test/run-make/issue-88756-default-output/output-default.stdout197
-rw-r--r--src/test/run-make/issue-88756-default-output/x.rs1
-rw-r--r--src/test/run-make/issue-96498/Makefile8
-rw-r--r--src/test/run-make/issue-96498/foo.rs4
-rw-r--r--src/test/run-make/libtest-thread-limit/Makefile7
-rw-r--r--src/test/run-make/libtest-thread-limit/test.rs20
-rw-r--r--src/test/run-make/llvm-outputs/Makefile5
-rw-r--r--src/test/run-make/native-link-modifier-bundle/Makefile33
-rw-r--r--src/test/run-make/native-link-modifier-bundle/bundled.rs11
-rw-r--r--src/test/run-make/native-link-modifier-bundle/cdylib-bundled.rs1
-rw-r--r--src/test/run-make/native-link-modifier-bundle/cdylib-non-bundled.rs1
-rw-r--r--src/test/run-make/native-link-modifier-bundle/native-staticlib.c1
-rw-r--r--src/test/run-make/native-link-modifier-bundle/non-bundled.rs11
-rw-r--r--src/test/run-make/native-link-modifier-whole-archive/Makefile52
-rw-r--r--src/test/run-make/native-link-modifier-whole-archive/c_static_lib_with_constructor.cpp11
-rw-r--r--src/test/run-make/native-link-modifier-whole-archive/directly_linked.rs6
-rw-r--r--src/test/run-make/native-link-modifier-whole-archive/directly_linked_test_minus_whole_archive.rs7
-rw-r--r--src/test/run-make/native-link-modifier-whole-archive/directly_linked_test_plus_whole_archive.rs7
-rw-r--r--src/test/run-make/native-link-modifier-whole-archive/indirectly_linked.rs5
-rw-r--r--src/test/run-make/native-link-modifier-whole-archive/indirectly_linked_via_attr.rs5
-rw-r--r--src/test/run-make/native-link-modifier-whole-archive/native_lib_in_src.rs11
-rw-r--r--src/test/run-make/native-link-modifier-whole-archive/rlib_with_cmdline_native_lib.rs6
-rw-r--r--src/test/run-make/pass-linker-flags-from-dep/Makefile10
-rw-r--r--src/test/run-make/pass-linker-flags-from-dep/main.rs3
-rw-r--r--src/test/run-make/pass-linker-flags-from-dep/native_dep_1.rs1
-rw-r--r--src/test/run-make/pass-linker-flags-from-dep/native_dep_2.rs1
-rw-r--r--src/test/run-make/pass-linker-flags-from-dep/rust_dep.rs9
-rw-r--r--src/test/run-make/pass-linker-flags/Makefile4
-rw-r--r--src/test/run-make/pass-linker-flags/rs.rs1
-rw-r--r--src/test/run-make/raw-dylib-alt-calling-convention/Makefile32
-rw-r--r--src/test/run-make/raw-dylib-alt-calling-convention/driver.rs8
-rw-r--r--src/test/run-make/raw-dylib-alt-calling-convention/extern.c178
-rw-r--r--src/test/run-make/raw-dylib-alt-calling-convention/lib.rs106
-rw-r--r--src/test/run-make/raw-dylib-alt-calling-convention/output.msvc.txt11
-rw-r--r--src/test/run-make/raw-dylib-alt-calling-convention/output.txt16
-rw-r--r--src/test/run-make/raw-dylib-c/Makefile28
-rw-r--r--src/test/run-make/raw-dylib-c/driver.rs5
-rw-r--r--src/test/run-make/raw-dylib-c/extern_1.c16
-rw-r--r--src/test/run-make/raw-dylib-c/extern_2.c6
-rw-r--r--src/test/run-make/raw-dylib-c/lib.rs26
-rw-r--r--src/test/run-make/raw-dylib-c/output.txt3
-rw-r--r--src/test/run-make/raw-dylib-link-ordinal/Makefile22
-rw-r--r--src/test/run-make/raw-dylib-link-ordinal/driver.rs5
-rw-r--r--src/test/run-make/raw-dylib-link-ordinal/exporter.c5
-rw-r--r--src/test/run-make/raw-dylib-link-ordinal/exporter.def3
-rw-r--r--src/test/run-make/raw-dylib-link-ordinal/lib.rs13
-rw-r--r--src/test/run-make/raw-dylib-link-ordinal/output.txt1
-rw-r--r--src/test/run-make/raw-dylib-stdcall-ordinal/Makefile23
-rw-r--r--src/test/run-make/raw-dylib-stdcall-ordinal/driver.rs5
-rw-r--r--src/test/run-make/raw-dylib-stdcall-ordinal/expected_output.txt2
-rw-r--r--src/test/run-make/raw-dylib-stdcall-ordinal/exporter-gnu.def4
-rw-r--r--src/test/run-make/raw-dylib-stdcall-ordinal/exporter-msvc.def4
-rw-r--r--src/test/run-make/raw-dylib-stdcall-ordinal/exporter.c11
-rw-r--r--src/test/run-make/raw-dylib-stdcall-ordinal/lib.rs20
-rw-r--r--src/test/run-make/remap-path-prefix-dwarf/Makefile77
-rw-r--r--src/test/run-make/remap-path-prefix-dwarf/src/quux.rs5
-rw-r--r--src/test/run-make/rustc-macro-dep-files/Makefile11
-rw-r--r--src/test/run-make/rustc-macro-dep-files/bar.rs8
-rw-r--r--src/test/run-make/rustc-macro-dep-files/foo.rs12
-rw-r--r--src/test/run-make/rustdoc-scrape-examples-invalid-expr/Makefile5
-rw-r--r--src/test/run-make/rustdoc-scrape-examples-invalid-expr/examples/ex.rs2
-rw-r--r--src/test/run-make/rustdoc-scrape-examples-invalid-expr/src/lib.rs1
-rw-r--r--src/test/run-make/rustdoc-scrape-examples-multiple/Makefile5
-rw-r--r--src/test/run-make/rustdoc-scrape-examples-multiple/examples/ex.rs4
-rw-r--r--src/test/run-make/rustdoc-scrape-examples-multiple/examples/ex2.rs3
-rw-r--r--src/test/run-make/rustdoc-scrape-examples-multiple/scrape.mk21
-rw-r--r--src/test/run-make/rustdoc-scrape-examples-multiple/src/lib.rs6
-rw-r--r--src/test/run-make/rustdoc-scrape-examples-ordering/Makefile5
-rw-r--r--src/test/run-make/rustdoc-scrape-examples-ordering/examples/ex1.rs11
-rw-r--r--src/test/run-make/rustdoc-scrape-examples-ordering/examples/ex2.rs8
-rw-r--r--src/test/run-make/rustdoc-scrape-examples-ordering/src/lib.rs6
-rw-r--r--src/test/run-make/rustdoc-scrape-examples-remap/Makefile5
-rw-r--r--src/test/run-make/rustdoc-scrape-examples-remap/examples/ex.rs4
-rw-r--r--src/test/run-make/rustdoc-scrape-examples-remap/src/a.rs1
-rw-r--r--src/test/run-make/rustdoc-scrape-examples-remap/src/lib.rs8
-rw-r--r--src/test/run-make/rustdoc-scrape-examples-test/Makefile6
-rw-r--r--src/test/run-make/rustdoc-scrape-examples-test/examples/ex.rs6
-rw-r--r--src/test/run-make/rustdoc-scrape-examples-test/src/lib.rs3
-rw-r--r--src/test/run-make/rustdoc-scrape-examples-whitespace/Makefile5
-rw-r--r--src/test/run-make/rustdoc-scrape-examples-whitespace/examples/ex.rs8
-rw-r--r--src/test/run-make/rustdoc-scrape-examples-whitespace/src/lib.rs3
-rw-r--r--src/test/run-make/rustdoc-with-out-dir-option/Makefile8
-rw-r--r--src/test/run-make/rustdoc-with-out-dir-option/src/lib.rs2
-rw-r--r--src/test/run-make/rustdoc-with-output-option/Makefile8
-rw-r--r--src/test/run-make/rustdoc-with-output-option/src/lib.rs2
-rw-r--r--src/test/run-make/rustdoc-with-short-out-dir-option/Makefile8
-rw-r--r--src/test/run-make/rustdoc-with-short-out-dir-option/src/lib.rs2
-rw-r--r--src/test/run-make/static-pie/Makefile18
-rwxr-xr-xsrc/test/run-make/static-pie/check_clang_version.sh20
-rwxr-xr-xsrc/test/run-make/static-pie/check_gcc_version.sh20
-rw-r--r--src/test/run-make/static-pie/test-aslr.rs43
-rw-r--r--src/test/run-make/thumb-none-cortex-m/Makefile38
-rw-r--r--src/test/run-make/thumb-none-qemu/Makefile27
-rw-r--r--src/test/run-make/thumb-none-qemu/example/.cargo/config45
-rw-r--r--src/test/run-make/thumb-none-qemu/example/Cargo.lock199
-rw-r--r--src/test/run-make/thumb-none-qemu/example/Cargo.toml10
-rw-r--r--src/test/run-make/thumb-none-qemu/example/memory.x23
-rw-r--r--src/test/run-make/thumb-none-qemu/example/src/main.rs24
-rw-r--r--src/test/run-make/thumb-none-qemu/script.sh20
-rw-r--r--src/test/run-make/track-path-dep-info/Makefile13
-rw-r--r--src/test/run-make/track-path-dep-info/emojis.txt1
-rw-r--r--src/test/run-make/track-path-dep-info/macro_def.rs11
-rw-r--r--src/test/run-make/track-path-dep-info/macro_use.rs6
-rw-r--r--src/test/run-make/translation/Makefile59
-rw-r--r--src/test/run-make/translation/basic-translation.ftl2
-rw-r--r--src/test/run-make/translation/basic-translation.rs18
-rw-r--r--src/test/run-make/unstable-flag-required/Makefile4
-rw-r--r--src/test/run-make/unstable-flag-required/README.md3
-rw-r--r--src/test/run-make/unstable-flag-required/output-format-json.stderr2
-rw-r--r--src/test/run-make/unstable-flag-required/x.rs1
-rw-r--r--src/test/run-make/wasm-abi/Makefile7
-rw-r--r--src/test/run-make/wasm-abi/foo.js22
-rw-r--r--src/test/run-make/wasm-abi/foo.rs87
-rw-r--r--src/test/run-make/wasm-custom-section/Makefile8
-rw-r--r--src/test/run-make/wasm-custom-section/bar.rs13
-rw-r--r--src/test/run-make/wasm-custom-section/foo.js36
-rw-r--r--src/test/run-make/wasm-custom-section/foo.rs8
-rw-r--r--src/test/run-make/wasm-custom-sections-opt/Makefile7
-rw-r--r--src/test/run-make/wasm-custom-sections-opt/foo.js15
-rw-r--r--src/test/run-make/wasm-custom-sections-opt/foo.rs21
-rw-r--r--src/test/run-make/wasm-export-all-symbols/Makefile19
-rw-r--r--src/test/run-make/wasm-export-all-symbols/bar.rs7
-rw-r--r--src/test/run-make/wasm-export-all-symbols/foo.rs3
-rw-r--r--src/test/run-make/wasm-export-all-symbols/main.rs3
-rw-r--r--src/test/run-make/wasm-export-all-symbols/verify.js32
-rw-r--r--src/test/run-make/wasm-import-module/Makefile8
-rw-r--r--src/test/run-make/wasm-import-module/bar.rs18
-rw-r--r--src/test/run-make/wasm-import-module/foo.js18
-rw-r--r--src/test/run-make/wasm-import-module/foo.rs7
-rw-r--r--src/test/run-make/wasm-panic-small/Makefile17
-rw-r--r--src/test/run-make/wasm-panic-small/foo.rs27
-rw-r--r--src/test/run-make/wasm-spurious-import/Makefile7
-rw-r--r--src/test/run-make/wasm-spurious-import/main.rs14
-rw-r--r--src/test/run-make/wasm-spurious-import/verify.js9
-rw-r--r--src/test/run-make/wasm-stringify-ints-small/Makefile10
-rw-r--r--src/test/run-make/wasm-stringify-ints-small/foo.rs33
-rw-r--r--src/test/run-make/wasm-symbols-different-module/Makefile28
-rw-r--r--src/test/run-make/wasm-symbols-different-module/bar.rs33
-rw-r--r--src/test/run-make/wasm-symbols-different-module/baz.rs22
-rw-r--r--src/test/run-make/wasm-symbols-different-module/foo.rs23
-rw-r--r--src/test/run-make/wasm-symbols-different-module/log.rs16
-rw-r--r--src/test/run-make/wasm-symbols-different-module/verify-imports.js32
-rw-r--r--src/test/run-make/wasm-symbols-not-exported/Makefile13
-rw-r--r--src/test/run-make/wasm-symbols-not-exported/bar.rs35
-rw-r--r--src/test/run-make/wasm-symbols-not-exported/foo.rs7
-rw-r--r--src/test/run-make/wasm-symbols-not-exported/verify-exported-symbols.js21
-rw-r--r--src/test/run-make/wasm-symbols-not-imported/Makefile13
-rw-r--r--src/test/run-make/wasm-symbols-not-imported/foo.rs14
-rw-r--r--src/test/run-make/wasm-symbols-not-imported/verify-no-imports.js10
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/Makefile23
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_asm.checks8
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_c.checks6
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_c_asm.checks15
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_cxx.checks6
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_cxx_asm.checks16
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_asm.checks7
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c.checks6
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c_asm.checks16
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c_global_asm.checks2
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx.checks6
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx_asm.checks16
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx_global_asm.checks2
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/Cargo.toml12
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/build.rs30
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/foo.c18
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/foo_asm.s7
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/foo_cxx.cpp21
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/CMakeLists.txt33
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo.c26
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo_asm.s7
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo_cxx.cpp29
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/src/main.rs49
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/jumpto.checks8
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/print.checks7
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/rust_plus_one_global_asm.checks2
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh58
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/unw_getcontext.checks6
1040 files changed, 19736 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(&not_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(&not_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) = &regular_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) = &regular_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() {}
diff --git a/src/test/run-make/const_fn_mir/Makefile b/src/test/run-make/const_fn_mir/Makefile
new file mode 100644
index 000000000..2aa0bc9d4
--- /dev/null
+++ b/src/test/run-make/const_fn_mir/Makefile
@@ -0,0 +1,10 @@
+-include ../../run-make-fulldeps/tools.mk
+
+all:
+ $(RUSTC) main.rs --emit=mir -o "$(TMPDIR)"/dump.mir
+
+ifdef RUSTC_BLESS_TEST
+ cp "$(TMPDIR)"/dump.mir dump.mir
+else
+ $(DIFF) dump.mir "$(TMPDIR)"/dump.mir
+endif
diff --git a/src/test/run-make/const_fn_mir/dump.mir b/src/test/run-make/const_fn_mir/dump.mir
new file mode 100644
index 000000000..ab4084c95
--- /dev/null
+++ b/src/test/run-make/const_fn_mir/dump.mir
@@ -0,0 +1,42 @@
+// WARNING: This output format is intended for human consumers only
+// and is subject to change without notice. Knock yourself out.
+fn foo() -> i32 {
+ let mut _0: i32; // return place in scope 0 at main.rs:4:19: 4:22
+
+ bb0: {
+ _0 = const 11_i32; // scope 0 at main.rs:5:5: 5:10
+ return; // scope 0 at main.rs:6:2: 6:2
+ }
+}
+
+// MIR FOR CTFE
+fn foo() -> i32 {
+ let mut _0: i32; // return place in scope 0 at main.rs:4:19: 4:22
+ let mut _1: (i32, bool); // in scope 0 at main.rs:5:5: 5:10
+
+ bb0: {
+ _1 = CheckedAdd(const 5_i32, const 6_i32); // scope 0 at main.rs:5:5: 5:10
+ assert(!move (_1.1: bool), "attempt to compute `{} + {}`, which would overflow", const 5_i32, const 6_i32) -> bb1; // scope 0 at main.rs:5:5: 5:10
+ }
+
+ bb1: {
+ _0 = move (_1.0: i32); // scope 0 at main.rs:5:5: 5:10
+ return; // scope 0 at main.rs:6:2: 6:2
+ }
+}
+
+fn main() -> () {
+ let mut _0: (); // return place in scope 0 at main.rs:8:11: 8:11
+ let _1: i32; // in scope 0 at main.rs:9:5: 9:10
+
+ bb0: {
+ _1 = foo() -> bb1; // scope 0 at main.rs:9:5: 9:10
+ // mir::Constant
+ // + span: main.rs:9:5: 9:8
+ // + literal: Const { ty: fn() -> i32 {foo}, val: Value(<ZST>) }
+ }
+
+ bb1: {
+ return; // scope 0 at main.rs:10:2: 10:2
+ }
+}
diff --git a/src/test/run-make/const_fn_mir/main.rs b/src/test/run-make/const_fn_mir/main.rs
new file mode 100644
index 000000000..e8552bd28
--- /dev/null
+++ b/src/test/run-make/const_fn_mir/main.rs
@@ -0,0 +1,10 @@
+// emit-mir
+// check-pass
+
+const fn foo() -> i32 {
+ 5 + 6
+}
+
+fn main() {
+ foo();
+}
diff --git a/src/test/run-make/coverage-llvmir/Makefile b/src/test/run-make/coverage-llvmir/Makefile
new file mode 100644
index 000000000..7be655053
--- /dev/null
+++ b/src/test/run-make/coverage-llvmir/Makefile
@@ -0,0 +1,64 @@
+# needs-profiler-support
+
+# Rust coverage maps support LLVM Coverage Mapping Format versions 5 and 6,
+# corresponding with LLVM versions 12 and 13, respectively.
+# When upgrading LLVM versions, consider whether to enforce a minimum LLVM
+# version during testing, with an additional directive at the top of this file
+# that sets, for example: `min-llvm-version: 12.0`
+
+include ../coverage/coverage_tools.mk
+
+BASEDIR=../coverage-llvmir
+
+ifeq ($(UNAME),Darwin)
+ INSTR_PROF_DATA_SUFFIX=,regular,live_support
+ DATA_SECTION_PREFIX=__DATA,
+ LLVM_COV_SECTION_PREFIX=__LLVM_COV,
+ COMDAT_IF_SUPPORTED=
+else
+ INSTR_PROF_DATA_SUFFIX=
+ DATA_SECTION_PREFIX=
+ LLVM_COV_SECTION_PREFIX=
+ COMDAT_IF_SUPPORTED=, comdat
+endif
+
+DEFINE_INTERNAL=define internal
+
+ifdef IS_WINDOWS
+ LLVM_FILECHECK_OPTIONS=\
+ -check-prefixes=CHECK,WINDOWS \
+ -DDEFINE_INTERNAL='$(DEFINE_INTERNAL)' \
+ -DCOMDAT_IF_SUPPORTED='$(COMDAT_IF_SUPPORTED)' \
+ -DINSTR_PROF_DATA='.lprfd$$M' \
+ -DINSTR_PROF_NAME='.lprfn$$M' \
+ -DINSTR_PROF_CNTS='.lprfc$$M' \
+ -DINSTR_PROF_VALS='.lprfv$$M' \
+ -DINSTR_PROF_VNODES='.lprfnd$$M' \
+ -DINSTR_PROF_COVMAP='.lcovmap$$M' \
+ -DINSTR_PROF_COVFUN='.lcovfun$$M' \
+ -DINSTR_PROF_ORDERFILE='.lorderfile$$M'
+else
+ LLVM_FILECHECK_OPTIONS=\
+ -check-prefixes=CHECK \
+ -DDEFINE_INTERNAL='$(DEFINE_INTERNAL)' \
+ -DCOMDAT_IF_SUPPORTED='$(COMDAT_IF_SUPPORTED)' \
+ -DINSTR_PROF_DATA='$(DATA_SECTION_PREFIX)__llvm_prf_data$(INSTR_PROF_DATA_SUFFIX)' \
+ -DINSTR_PROF_NAME='$(DATA_SECTION_PREFIX)__llvm_prf_names' \
+ -DINSTR_PROF_CNTS='$(DATA_SECTION_PREFIX)__llvm_prf_cnts' \
+ -DINSTR_PROF_VALS='$(DATA_SECTION_PREFIX)__llvm_prf_vals' \
+ -DINSTR_PROF_VNODES='$(DATA_SECTION_PREFIX)__llvm_prf_vnds' \
+ -DINSTR_PROF_COVMAP='$(LLVM_COV_SECTION_PREFIX)__llvm_covmap' \
+ -DINSTR_PROF_COVFUN='$(LLVM_COV_SECTION_PREFIX)__llvm_covfun' \
+ -DINSTR_PROF_ORDERFILE='$(DATA_SECTION_PREFIX)__llvm_orderfile'
+endif
+
+all: test_llvm_ir
+
+test_llvm_ir:
+ # Compile the test program with non-experimental coverage instrumentation, and generate LLVM IR
+ $(RUSTC) $(BASEDIR)/testprog.rs \
+ -Cinstrument-coverage \
+ --emit=llvm-ir
+
+ cat "$(TMPDIR)"/testprog.ll | \
+ "$(LLVM_FILECHECK)" $(BASEDIR)/filecheck.testprog.txt $(LLVM_FILECHECK_OPTIONS)
diff --git a/src/test/run-make/coverage-llvmir/filecheck.testprog.txt b/src/test/run-make/coverage-llvmir/filecheck.testprog.txt
new file mode 100644
index 000000000..7a5f21922
--- /dev/null
+++ b/src/test/run-make/coverage-llvmir/filecheck.testprog.txt
@@ -0,0 +1,50 @@
+# Check for metadata, variables, declarations, and function definitions injected
+# into LLVM IR when compiling with -Cinstrument-coverage.
+
+WINDOWS: $__llvm_profile_runtime_user = comdat any
+
+CHECK: @__covrec_{{[A-F0-9]+}}u = linkonce_odr hidden constant
+CHECK-SAME: section "[[INSTR_PROF_COVFUN]]"[[COMDAT_IF_SUPPORTED]], align 8
+
+CHECK: @__llvm_coverage_mapping = private constant
+CHECK-SAME: section "[[INSTR_PROF_COVMAP]]", align 8
+
+WINDOWS: @__llvm_profile_runtime = external global i32
+
+CHECK: @__profc__R{{[a-zA-Z0-9_]+}}testprog14will_be_called = {{private|internal}} global
+CHECK-SAME: section "[[INSTR_PROF_CNTS]]"{{.*}}, align 8
+
+CHECK: @__profd__R{{[a-zA-Z0-9_]+}}testprog14will_be_called = {{private|internal}} global
+CHECK-SAME: @__profc__R{{[a-zA-Z0-9_]+}}testprog14will_be_called
+CHECK-SAME: section "[[INSTR_PROF_DATA]]"{{.*}}, align 8
+
+CHECK: @__profc__R{{[a-zA-Z0-9_]+}}testprog4main = {{private|internal}} global
+CHECK-SAME: section "[[INSTR_PROF_CNTS]]"{{.*}}, align 8
+
+CHECK: @__profd__R{{[a-zA-Z0-9_]+}}testprog4main = {{private|internal}} global
+CHECK-SAME: @__profc__R{{[a-zA-Z0-9_]+}}testprog4main
+CHECK-SAME: section "[[INSTR_PROF_DATA]]"{{.*}}, align 8
+
+CHECK: @__llvm_prf_nm = private constant
+CHECK-SAME: section "[[INSTR_PROF_NAME]]", align 1
+
+CHECK: @llvm.used = appending global
+CHECK-SAME: @__llvm_coverage_mapping
+CHECK-SAME: @__llvm_prf_nm
+CHECK-SAME: section "llvm.metadata"
+
+CHECK: [[DEFINE_INTERNAL]] { {{.*}} } @_R{{[a-zA-Z0-9_]+}}testprog14will_be_called() unnamed_addr #{{[0-9]+}} {
+CHECK-NEXT: start:
+CHECK-NOT: [[DEFINE_INTERNAL]]
+CHECK: %pgocount = load i64, {{i64\*|ptr}}
+CHECK-SAME: @__profc__R{{[a-zA-Z0-9_]+}}testprog14will_be_called,
+
+CHECK: declare void @llvm.instrprof.increment({{i8\*|ptr}}, i64, i32, i32) #[[LLVM_INSTRPROF_INCREMENT_ATTR:[0-9]+]]
+
+WINDOWS: define linkonce_odr hidden i32 @__llvm_profile_runtime_user() #[[LLVM_PROFILE_RUNTIME_USER_ATTR:[0-9]+]] comdat {
+WINDOWS-NEXT: %1 = load i32, {{i32\*|ptr}} @__llvm_profile_runtime
+WINDOWS-NEXT: ret i32 %1
+WINDOWS-NEXT: }
+
+CHECK: attributes #[[LLVM_INSTRPROF_INCREMENT_ATTR]] = { nounwind }
+WINDOWS: attributes #[[LLVM_PROFILE_RUNTIME_USER_ATTR]] = { noinline }
diff --git a/src/test/run-make/coverage-llvmir/testprog.rs b/src/test/run-make/coverage-llvmir/testprog.rs
new file mode 100644
index 000000000..358c25677
--- /dev/null
+++ b/src/test/run-make/coverage-llvmir/testprog.rs
@@ -0,0 +1,38 @@
+pub fn will_be_called() -> &'static str {
+ let val = "called";
+ println!("{}", val);
+ val
+}
+
+pub fn will_not_be_called() -> bool {
+ println!("should not have been called");
+ false
+}
+
+pub fn print<T>(left: &str, value: T, right: &str)
+where
+ T: std::fmt::Display,
+{
+ println!("{}{}{}", left, value, right);
+}
+
+pub fn wrap_with<F, T>(inner: T, should_wrap: bool, wrapper: F)
+where
+ F: FnOnce(&T)
+{
+ if should_wrap {
+ wrapper(&inner)
+ }
+}
+
+fn main() {
+ let less = 1;
+ let more = 100;
+
+ if less < more {
+ wrap_with(will_be_called(), less < more, |inner| print(" ***", inner, "*** "));
+ wrap_with(will_be_called(), more < less, |inner| print(" ***", inner, "*** "));
+ } else {
+ wrap_with(will_not_be_called(), true, |inner| print("wrapped result is: ", inner, ""));
+ }
+}
diff --git a/src/test/run-make/coverage-reports/Makefile b/src/test/run-make/coverage-reports/Makefile
new file mode 100644
index 000000000..4e75672f2
--- /dev/null
+++ b/src/test/run-make/coverage-reports/Makefile
@@ -0,0 +1,180 @@
+# needs-profiler-support
+# ignore-windows-gnu
+
+# Rust coverage maps support LLVM Coverage Mapping Format versions 5 and 6,
+# corresponding with LLVM versions 12 and 13, respectively.
+# When upgrading LLVM versions, consider whether to enforce a minimum LLVM
+# version during testing, with an additional directive at the top of this file
+# that sets, for example: `min-llvm-version: 12.0`
+
+# 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 ../coverage/coverage_tools.mk
+
+BASEDIR=../coverage-reports
+SOURCEDIR=../coverage
+
+# The `llvm-cov show` flag `--debug`, used to generate the `counters` output files, is only
+# enabled if LLVM assertions are enabled. This requires Rust config `llvm/optimize` and not
+# `llvm/release_debuginfo`. Note that some CI builds disable debug assertions (by setting
+# `NO_LLVM_ASSERTIONS=1`), so the tests must still pass even if the `--debug` flag is
+# not supported. (Note that `counters` files are only produced in the `$(TMPDIR)`
+# directory, for inspection and debugging support. They are *not* copied to `expected_*`
+# files when `--bless`ed.)
+LLVM_COV_DEBUG := $(shell \
+ "$(LLVM_BIN_DIR)"/llvm-cov show --debug 2>&1 | \
+ grep -q "Unknown command line argument '--debug'"; \
+ echo $$?)
+ifeq ($(LLVM_COV_DEBUG), 1)
+DEBUG_FLAG=--debug
+endif
+
+# FIXME(richkadel): I'm adding `--ignore-filename-regex=` line(s) for specific test(s) that produce
+# `llvm-cov` results for multiple files (for example `uses_crate.rs` and `used_crate/mod.rs`) as a
+# workaround for two problems causing tests to fail on Windows:
+#
+# 1. When multiple files appear in the `llvm-cov show` results, each file's coverage results can
+# appear in different a different order. Whether this is random or, somehow, platform-specific,
+# the Windows output flips the order of the files, compared to Linux. In the `uses_crate.rs`
+# test, the only test-unique (interesting) results we care about are the results for only one
+# of the two files, `mod/uses_crate.rs`, so the workaround is to ignore all but this one file.
+# In the future, we may want a more sophisticated solution that splits apart `llvm-cov show`
+# results into separate results files for each result (taking care not to create new file
+# paths that might be too long for Windows MAX_PATH limits when creating these new sub-results,
+# as well).
+# 2. When multiple files appear in the `llvm-cov show` results, the results for each file are
+# prefixed with their filename, including platform-specific path separators (`\` for Windows,
+# and `/` everywhere else). This could be filtered or normalized of course, but by ignoring
+# coverage results for all but one of the file, the filenames are no longer included anyway.
+# If this changes (if/when we decide to support `llvm-cov show` results for multiple files),
+# the file path separator differences may need to be addressed.
+#
+# Since this is only a workaround, I decided to implement the override by adding an option for
+# each file to be ignored, using a `--ignore-filename-regex=` entry for each one, rather than
+# implement some more sophisticated solution with a new custom test directive in the test file
+# itself (similar to `expect-exit-status`) because that would add a lot of complexity and still
+# be a workaround, with the same result, with no benefit.
+#
+# Yes these `--ignore-filename-regex=` options are included in all invocations of `llvm-cov show`
+# for now, but it is effectively ignored for all tests that don't include this file anyway.
+#
+# (Note that it's also possible the `_counters.<test>.txt` and `<test>.json` files (if generated)
+# may order results from multiple files inconsistently, which might also have to be accomodated
+# if and when we allow `llvm-cov` to produce results for multiple files. Note, the path separators
+# appear to be normalized to `/` in those files, thankfully.)
+LLVM_COV_IGNORE_FILES=\
+ --ignore-filename-regex='(uses_crate.rs|uses_inline_crate.rs|unused_mod.rs)'
+
+all: $(patsubst $(SOURCEDIR)/lib/%.rs,%,$(wildcard $(SOURCEDIR)/lib/*.rs)) $(patsubst $(SOURCEDIR)/%.rs,%,$(wildcard $(SOURCEDIR)/*.rs))
+
+# Ensure there are no `expected` results for tests that may have been removed or renamed
+.PHONY: clear_expected_if_blessed
+clear_expected_if_blessed:
+ifdef RUSTC_BLESS_TEST
+ rm -f expected_*
+endif
+
+-include clear_expected_if_blessed
+
+%: $(SOURCEDIR)/lib/%.rs
+ # Compile the test library with coverage instrumentation
+ $(RUSTC) $(SOURCEDIR)/lib/$@.rs \
+ $$( sed -n 's/^\/\/ compile-flags: \([^#]*\).*/\1/p' $(SOURCEDIR)/lib/$@.rs ) \
+ --crate-type rlib -Cinstrument-coverage
+
+%: $(SOURCEDIR)/%.rs
+ # Compile the test program with coverage instrumentation
+ $(RUSTC) $(SOURCEDIR)/$@.rs \
+ $$( sed -n 's/^\/\/ compile-flags: \([^#]*\).*/\1/p' $(SOURCEDIR)/$@.rs ) \
+ -L "$(TMPDIR)" -Cinstrument-coverage
+
+ # Run it in order to generate some profiling data,
+ # with `LLVM_PROFILE_FILE=<profdata_file>` environment variable set to
+ # output the coverage stats for this run.
+ LLVM_PROFILE_FILE="$(TMPDIR)"/$@.profraw \
+ $(call RUN,$@) || \
+ ( \
+ status=$$?; \
+ grep -q "^\/\/ expect-exit-status-$$status" $(SOURCEDIR)/$@.rs || \
+ ( >&2 echo "program exited with an unexpected exit status: $$status"; \
+ false \
+ ) \
+ )
+
+ # Run it through rustdoc as well to cover doctests.
+ # `%p` is the pid, and `%m` the binary signature. We suspect that the pid alone
+ # might result in overwritten files and failed tests, as rustdoc spawns each
+ # doctest as its own process, so make sure the filename is as unique as possible.
+ LLVM_PROFILE_FILE="$(TMPDIR)"/$@-%p-%m.profraw \
+ $(RUSTDOC) --crate-name workaround_for_79771 --test $(SOURCEDIR)/$@.rs \
+ $$( sed -n 's/^\/\/ compile-flags: \([^#]*\).*/\1/p' $(SOURCEDIR)/$@.rs ) \
+ -L "$(TMPDIR)" -Cinstrument-coverage \
+ -Z unstable-options --persist-doctests=$(TMPDIR)/rustdoc-$@
+
+ # Postprocess the profiling data so it can be used by the llvm-cov tool
+ "$(LLVM_BIN_DIR)"/llvm-profdata merge --sparse \
+ "$(TMPDIR)"/$@*.profraw \
+ -o "$(TMPDIR)"/$@.profdata
+
+ # Generate a coverage report using `llvm-cov show`.
+ "$(LLVM_BIN_DIR)"/llvm-cov show \
+ $(DEBUG_FLAG) \
+ $(LLVM_COV_IGNORE_FILES) \
+ --compilation-dir=. \
+ --Xdemangler="$(RUST_DEMANGLER)" \
+ --show-line-counts-or-regions \
+ --instr-profile="$(TMPDIR)"/$@.profdata \
+ $(call BIN,"$(TMPDIR)"/$@) \
+ $$( \
+ for file in $(TMPDIR)/rustdoc-$@/*/rust_out; do \
+ [ -x "$$file" ] && printf "%s %s " -object $$file; \
+ done \
+ ) \
+ 2> "$(TMPDIR)"/show_coverage_stderr.$@.txt \
+ | "$(PYTHON)" $(BASEDIR)/normalize_paths.py \
+ > "$(TMPDIR)"/actual_show_coverage.$@.txt || \
+ ( status=$$? ; \
+ >&2 cat "$(TMPDIR)"/show_coverage_stderr.$@.txt ; \
+ exit $$status \
+ )
+
+ifdef DEBUG_FLAG
+ # The first line (beginning with "Args:" contains hard-coded, build-specific
+ # file paths. Strip that line and keep the remaining lines with counter debug
+ # data.
+ tail -n +2 "$(TMPDIR)"/show_coverage_stderr.$@.txt \
+ > "$(TMPDIR)"/actual_show_coverage_counters.$@.txt
+endif
+
+ifdef RUSTC_BLESS_TEST
+ cp "$(TMPDIR)"/actual_show_coverage.$@.txt \
+ expected_show_coverage.$@.txt
+else
+ # Compare the show coverage output (`--bless` refreshes `typical` files).
+ #
+ # FIXME(richkadel): None of the Rust test source samples have the
+ # `// ignore-llvm-cov-show-diffs` anymore. This directive exists to work around a limitation
+ # with `llvm-cov show`. When reporting coverage for multiple instantiations of a generic function,
+ # with different type substitutions, `llvm-cov show` prints these in a non-deterministic order,
+ # breaking the `diff` comparision.
+ #
+ # A partial workaround is implemented below, with `diff --ignore-matching-lines=RE`
+ # to ignore each line prefixing each generic instantiation coverage code region.
+ #
+ # This workaround only works if the coverage counts are identical across all reported
+ # instantiations. If there is no way to ensure this, you may need to apply the
+ # `// ignore-llvm-cov-show-diffs` directive, and check for differences using the
+ # `.json` files to validate that results have not changed. (Until then, the JSON
+ # files are redundant, so there is no need to generate `expected_*.json` files or
+ # compare actual JSON results.)
+
+ $(DIFF) --ignore-matching-lines='^ | .*::<.*>.*:$$' --ignore-matching-lines='^ | <.*>::.*:$$' \
+ expected_show_coverage.$@.txt "$(TMPDIR)"/actual_show_coverage.$@.txt || \
+ ( grep -q '^\/\/ ignore-llvm-cov-show-diffs' $(SOURCEDIR)/$@.rs && \
+ >&2 echo 'diff failed, but suppressed with `// ignore-llvm-cov-show-diffs` in $(SOURCEDIR)/$@.rs' \
+ ) || \
+ ( >&2 echo 'diff failed, and not suppressed without `// ignore-llvm-cov-show-diffs` in $(SOURCEDIR)/$@.rs'; \
+ false \
+ )
+endif
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.abort.txt b/src/test/run-make/coverage-reports/expected_show_coverage.abort.txt
new file mode 100644
index 000000000..00f46f42a
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.abort.txt
@@ -0,0 +1,69 @@
+ 1| |#![feature(c_unwind)]
+ 2| |#![allow(unused_assignments)]
+ 3| |
+ 4| 12|extern "C" fn might_abort(should_abort: bool) {
+ 5| 12| if should_abort {
+ 6| 0| println!("aborting...");
+ 7| 0| panic!("panics and aborts");
+ 8| 12| } else {
+ 9| 12| println!("Don't Panic");
+ 10| 12| }
+ 11| 12|}
+ 12| |
+ 13| 1|fn main() -> Result<(), u8> {
+ 14| 1| let mut countdown = 10;
+ 15| 11| while countdown > 0 {
+ 16| 10| if countdown < 5 {
+ 17| 4| might_abort(false);
+ 18| 6| }
+ 19| | // See discussion (below the `Notes` section) on coverage results for the closing brace.
+ 20| 10| if countdown < 5 { might_abort(false); } // Counts for different regions on one line.
+ ^4 ^6
+ 21| | // For the following example, the closing brace is the last character on the line.
+ 22| | // This shows the character after the closing brace is highlighted, even if that next
+ 23| | // character is a newline.
+ 24| 10| if countdown < 5 { might_abort(false); }
+ ^4 ^6
+ 25| 10| countdown -= 1;
+ 26| | }
+ 27| 1| Ok(())
+ 28| 1|}
+ 29| |
+ 30| |// Notes:
+ 31| |// 1. Compare this program and its coverage results to those of the similar tests
+ 32| |// `panic_unwind.rs` and `try_error_result.rs`.
+ 33| |// 2. This test confirms the coverage generated when a program includes `TerminatorKind::Abort`.
+ 34| |// 3. The test does not invoke the abort. By executing to a successful completion, the coverage
+ 35| |// results show where the program did and did not execute.
+ 36| |// 4. If the program actually aborted, the coverage counters would not be saved (which "works as
+ 37| |// intended"). Coverage results would show no executed coverage regions.
+ 38| |// 6. If `should_abort` is `true` and the program aborts, the program exits with a `132` status
+ 39| |// (on Linux at least).
+ 40| |
+ 41| |/*
+ 42| |
+ 43| |Expect the following coverage results:
+ 44| |
+ 45| |```text
+ 46| | 16| 11| while countdown > 0 {
+ 47| | 17| 10| if countdown < 5 {
+ 48| | 18| 4| might_abort(false);
+ 49| | 19| 6| }
+ 50| |```
+ 51| |
+ 52| |This is actually correct.
+ 53| |
+ 54| |The condition `countdown < 5` executed 10 times (10 loop iterations).
+ 55| |
+ 56| |It evaluated to `true` 4 times, and executed the `might_abort()` call.
+ 57| |
+ 58| |It skipped the body of the `might_abort()` call 6 times. If an `if` does not include an explicit
+ 59| |`else`, the coverage implementation injects a counter, at the character immediately after the `if`s
+ 60| |closing brace, to count the "implicit" `else`. This is the only way to capture the coverage of the
+ 61| |non-true condition.
+ 62| |
+ 63| |As another example of why this is important, say the condition was `countdown < 50`, which is always
+ 64| |`true`. In that case, we wouldn't have a test for what happens if `might_abort()` is not called.
+ 65| |The closing brace would have a count of `0`, highlighting the missed coverage.
+ 66| |*/
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.assert.txt b/src/test/run-make/coverage-reports/expected_show_coverage.assert.txt
new file mode 100644
index 000000000..405688806
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.assert.txt
@@ -0,0 +1,34 @@
+ 1| |#![allow(unused_assignments)]
+ 2| |// expect-exit-status-101
+ 3| |
+ 4| 4|fn might_fail_assert(one_plus_one: u32) {
+ 5| 4| println!("does 1 + 1 = {}?", one_plus_one);
+ 6| 4| assert_eq!(1 + 1, one_plus_one, "the argument was wrong");
+ ^1
+ 7| 3|}
+ 8| |
+ 9| 1|fn main() -> Result<(),u8> {
+ 10| 1| let mut countdown = 10;
+ 11| 11| while countdown > 0 {
+ 12| 11| if countdown == 1 {
+ 13| 1| might_fail_assert(3);
+ 14| 10| } else if countdown < 5 {
+ 15| 3| might_fail_assert(2);
+ 16| 6| }
+ 17| 10| countdown -= 1;
+ 18| | }
+ 19| 0| Ok(())
+ 20| 0|}
+ 21| |
+ 22| |// Notes:
+ 23| |// 1. Compare this program and its coverage results to those of the very similar test
+ 24| |// `panic_unwind.rs`, and similar tests `abort.rs` and `try_error_result.rs`.
+ 25| |// 2. This test confirms the coverage generated when a program passes or fails an `assert!()` or
+ 26| |// related `assert_*!()` macro.
+ 27| |// 3. Notably, the `assert` macros *do not* generate `TerminatorKind::Assert`. The macros produce
+ 28| |// conditional expressions, `TerminatorKind::SwitchInt` branches, and a possible call to
+ 29| |// `begin_panic_fmt()` (that begins a panic unwind, if the assertion test fails).
+ 30| |// 4. `TerminatoKind::Assert` is, however, also present in the MIR generated for this test
+ 31| |// (and in many other coverage tests). The `Assert` terminator is typically generated by the
+ 32| |// Rust compiler to check for runtime failures, such as numeric overflows.
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.async.txt b/src/test/run-make/coverage-reports/expected_show_coverage.async.txt
new file mode 100644
index 000000000..2f69adbd8
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.async.txt
@@ -0,0 +1,139 @@
+ 1| |#![allow(unused_assignments, dead_code)]
+ 2| |
+ 3| |// compile-flags: --edition=2018 -C opt-level=1
+ 4| |
+ 5| 1|async fn c(x: u8) -> u8 {
+ 6| 1| if x == 8 {
+ 7| 1| 1
+ 8| | } else {
+ 9| 0| 0
+ 10| | }
+ 11| 1|}
+ 12| |
+ 13| 0|async fn d() -> u8 { 1 }
+ 14| |
+ 15| 0|async fn e() -> u8 { 1 } // unused function; executor does not block on `g()`
+ 16| |
+ 17| 1|async fn f() -> u8 { 1 }
+ 18| |
+ 19| 0|async fn foo() -> [bool; 10] { [false; 10] } // unused function; executor does not block on `h()`
+ 20| |
+ 21| 1|pub async fn g(x: u8) {
+ 22| 0| match x {
+ 23| 0| y if e().await == y => (),
+ 24| 0| y if f().await == y => (),
+ 25| 0| _ => (),
+ 26| | }
+ 27| 0|}
+ 28| |
+ 29| 1|async fn h(x: usize) { // The function signature is counted when called, but the body is not
+ 30| 0| // executed (not awaited) so the open brace has a `0` count (at least when
+ 31| 0| // displayed with `llvm-cov show` in color-mode).
+ 32| 0| match x {
+ 33| 0| y if foo().await[y] => (),
+ 34| 0| _ => (),
+ 35| | }
+ 36| 0|}
+ 37| |
+ 38| 1|async fn i(x: u8) { // line coverage is 1, but there are 2 regions:
+ 39| 1| // (a) the function signature, counted when the function is called; and
+ 40| 1| // (b) the open brace for the function body, counted once when the body is
+ 41| 1| // executed asynchronously.
+ 42| 1| match x {
+ 43| 1| y if c(x).await == y + 1 => { d().await; }
+ ^0 ^0 ^0 ^0
+ 44| 1| y if f().await == y + 1 => (),
+ ^0 ^0 ^0
+ 45| 1| _ => (),
+ 46| | }
+ 47| 1|}
+ 48| |
+ 49| 1|fn j(x: u8) {
+ 50| 1| // non-async versions of `c()`, `d()`, and `f()` to make it similar to async `i()`.
+ 51| 1| fn c(x: u8) -> u8 {
+ 52| 1| if x == 8 {
+ 53| 1| 1 // This line appears covered, but the 1-character expression span covering the `1`
+ ^0
+ 54| 1| // is not executed. (`llvm-cov show` displays a `^0` below the `1` ). This is because
+ 55| 1| // `fn j()` executes the open brace for the funciton body, followed by the function's
+ 56| 1| // first executable statement, `match x`. Inner function declarations are not
+ 57| 1| // "visible" to the MIR for `j()`, so the code region counts all lines between the
+ 58| 1| // open brace and the first statement as executed, which is, in a sense, true.
+ 59| 1| // `llvm-cov show` overcomes this kind of situation by showing the actual counts
+ 60| 1| // of the enclosed coverages, (that is, the `1` expression was not executed, and
+ 61| 1| // accurately displays a `0`).
+ 62| 1| } else {
+ 63| 1| 0
+ 64| 1| }
+ 65| 1| }
+ 66| 1| fn d() -> u8 { 1 } // inner function is defined in-line, but the function is not executed
+ ^0
+ 67| 1| fn f() -> u8 { 1 }
+ 68| 1| match x {
+ 69| 1| y if c(x) == y + 1 => { d(); }
+ ^0 ^0
+ 70| 1| y if f() == y + 1 => (),
+ ^0 ^0
+ 71| 1| _ => (),
+ 72| | }
+ 73| 1|}
+ 74| |
+ 75| 0|fn k(x: u8) { // unused function
+ 76| 0| match x {
+ 77| 0| 1 => (),
+ 78| 0| 2 => (),
+ 79| 0| _ => (),
+ 80| | }
+ 81| 0|}
+ 82| |
+ 83| 1|fn l(x: u8) {
+ 84| 1| match x {
+ 85| 0| 1 => (),
+ 86| 0| 2 => (),
+ 87| 1| _ => (),
+ 88| | }
+ 89| 1|}
+ 90| |
+ 91| 1|async fn m(x: u8) -> u8 { x - 1 }
+ ^0
+ 92| |
+ 93| 1|fn main() {
+ 94| 1| let _ = g(10);
+ 95| 1| let _ = h(9);
+ 96| 1| let mut future = Box::pin(i(8));
+ 97| 1| j(7);
+ 98| 1| l(6);
+ 99| 1| let _ = m(5);
+ 100| 1| executor::block_on(future.as_mut());
+ 101| 1|}
+ 102| |
+ 103| |mod executor {
+ 104| | use core::{
+ 105| | future::Future,
+ 106| | pin::Pin,
+ 107| | task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
+ 108| | };
+ 109| |
+ 110| 1| pub fn block_on<F: Future>(mut future: F) -> F::Output {
+ 111| 1| let mut future = unsafe { Pin::new_unchecked(&mut future) };
+ 112| 1| use std::hint::unreachable_unchecked;
+ 113| 1| static VTABLE: RawWakerVTable = RawWakerVTable::new(
+ 114| 1| |_| unsafe { unreachable_unchecked() }, // clone
+ ^0
+ 115| 1| |_| unsafe { unreachable_unchecked() }, // wake
+ ^0
+ 116| 1| |_| unsafe { unreachable_unchecked() }, // wake_by_ref
+ ^0
+ 117| 1| |_| (),
+ 118| 1| );
+ 119| 1| let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
+ 120| 1| let mut context = Context::from_waker(&waker);
+ 121| |
+ 122| | loop {
+ 123| 1| if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+ 124| 1| break val;
+ 125| 0| }
+ 126| | }
+ 127| 1| }
+ 128| |}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.async2.txt b/src/test/run-make/coverage-reports/expected_show_coverage.async2.txt
new file mode 100644
index 000000000..dc06a485a
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.async2.txt
@@ -0,0 +1,116 @@
+ 1| |// compile-flags: --edition=2018
+ 2| |
+ 3| |use core::{
+ 4| | future::Future,
+ 5| | marker::Send,
+ 6| | pin::Pin,
+ 7| |};
+ 8| |
+ 9| 1|fn non_async_func() {
+ 10| 1| println!("non_async_func was covered");
+ 11| 1| let b = true;
+ 12| 1| if b {
+ 13| 1| println!("non_async_func println in block");
+ 14| 1| }
+ ^0
+ 15| 1|}
+ 16| |
+ 17| |
+ 18| |
+ 19| |
+ 20| 1|async fn async_func() {
+ 21| 1| println!("async_func was covered");
+ 22| 1| let b = true;
+ 23| 1| if b {
+ 24| 1| println!("async_func println in block");
+ 25| 1| }
+ ^0
+ 26| 1|}
+ 27| |
+ 28| |
+ 29| |
+ 30| |
+ 31| 1|async fn async_func_just_println() {
+ 32| 1| println!("async_func_just_println was covered");
+ 33| 1|}
+ 34| |
+ 35| 1|fn main() {
+ 36| 1| println!("codecovsample::main");
+ 37| 1|
+ 38| 1| non_async_func();
+ 39| 1|
+ 40| 1| executor::block_on(async_func());
+ 41| 1| executor::block_on(async_func_just_println());
+ 42| 1|}
+ 43| |
+ 44| |mod executor {
+ 45| | use core::{
+ 46| | future::Future,
+ 47| | pin::Pin,
+ 48| | task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
+ 49| | };
+ 50| |
+ 51| 2| pub fn block_on<F: Future>(mut future: F) -> F::Output {
+ 52| 2| let mut future = unsafe { Pin::new_unchecked(&mut future) };
+ 53| 2| use std::hint::unreachable_unchecked;
+ 54| 2| static VTABLE: RawWakerVTable = RawWakerVTable::new(
+ 55| 2| |_| unsafe { unreachable_unchecked() }, // clone
+ ^0
+ 56| 2| |_| unsafe { unreachable_unchecked() }, // wake
+ ^0
+ 57| 2| |_| unsafe { unreachable_unchecked() }, // wake_by_ref
+ ^0
+ 58| 2| |_| (),
+ 59| 2| );
+ 60| 2| let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
+ 61| 2| let mut context = Context::from_waker(&waker);
+ 62| |
+ 63| | loop {
+ 64| 2| if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+ 65| 2| break val;
+ 66| 0| }
+ 67| | }
+ 68| 2| }
+ ------------------
+ | async2::executor::block_on::<core::future::from_generator::GenFuture<async2::async_func::{closure#0}>>:
+ | 51| 1| pub fn block_on<F: Future>(mut future: F) -> F::Output {
+ | 52| 1| let mut future = unsafe { Pin::new_unchecked(&mut future) };
+ | 53| 1| use std::hint::unreachable_unchecked;
+ | 54| 1| static VTABLE: RawWakerVTable = RawWakerVTable::new(
+ | 55| 1| |_| unsafe { unreachable_unchecked() }, // clone
+ | 56| 1| |_| unsafe { unreachable_unchecked() }, // wake
+ | 57| 1| |_| unsafe { unreachable_unchecked() }, // wake_by_ref
+ | 58| 1| |_| (),
+ | 59| 1| );
+ | 60| 1| let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
+ | 61| 1| let mut context = Context::from_waker(&waker);
+ | 62| |
+ | 63| | loop {
+ | 64| 1| if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+ | 65| 1| break val;
+ | 66| 0| }
+ | 67| | }
+ | 68| 1| }
+ ------------------
+ | async2::executor::block_on::<core::future::from_generator::GenFuture<async2::async_func_just_println::{closure#0}>>:
+ | 51| 1| pub fn block_on<F: Future>(mut future: F) -> F::Output {
+ | 52| 1| let mut future = unsafe { Pin::new_unchecked(&mut future) };
+ | 53| 1| use std::hint::unreachable_unchecked;
+ | 54| 1| static VTABLE: RawWakerVTable = RawWakerVTable::new(
+ | 55| 1| |_| unsafe { unreachable_unchecked() }, // clone
+ | 56| 1| |_| unsafe { unreachable_unchecked() }, // wake
+ | 57| 1| |_| unsafe { unreachable_unchecked() }, // wake_by_ref
+ | 58| 1| |_| (),
+ | 59| 1| );
+ | 60| 1| let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
+ | 61| 1| let mut context = Context::from_waker(&waker);
+ | 62| |
+ | 63| | loop {
+ | 64| 1| if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+ | 65| 1| break val;
+ | 66| 0| }
+ | 67| | }
+ | 68| 1| }
+ ------------------
+ 69| |}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.closure.txt b/src/test/run-make/coverage-reports/expected_show_coverage.closure.txt
new file mode 100644
index 000000000..09ad276aa
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.closure.txt
@@ -0,0 +1,222 @@
+ 1| |#![allow(unused_assignments, unused_variables)]
+ 2| |// compile-flags: -C opt-level=2 # fix described in rustc_middle/mir/mono.rs
+ 3| 1|fn main() {
+ 4| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ 5| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ 6| 1| // dependent conditions.
+ 7| 1| let is_true = std::env::args().len() == 1;
+ 8| 1| let is_false = ! is_true;
+ 9| 1|
+ 10| 1| let mut some_string = Some(String::from("the string content"));
+ 11| 1| println!(
+ 12| 1| "The string or alt: {}"
+ 13| 1| ,
+ 14| 1| some_string
+ 15| 1| .
+ 16| 1| unwrap_or_else
+ 17| 1| (
+ 18| 1| ||
+ 19| 0| {
+ 20| 0| let mut countdown = 0;
+ 21| 0| if is_false {
+ 22| 0| countdown = 10;
+ 23| 0| }
+ 24| 0| "alt string 1".to_owned()
+ 25| 1| }
+ 26| 1| )
+ 27| 1| );
+ 28| 1|
+ 29| 1| some_string = Some(String::from("the string content"));
+ 30| 1| let
+ 31| 1| a
+ 32| 1| =
+ 33| 1| ||
+ 34| 0| {
+ 35| 0| let mut countdown = 0;
+ 36| 0| if is_false {
+ 37| 0| countdown = 10;
+ 38| 0| }
+ 39| 0| "alt string 2".to_owned()
+ 40| | };
+ 41| 1| println!(
+ 42| 1| "The string or alt: {}"
+ 43| 1| ,
+ 44| 1| some_string
+ 45| 1| .
+ 46| 1| unwrap_or_else
+ 47| 1| (
+ 48| 1| a
+ 49| 1| )
+ 50| 1| );
+ 51| 1|
+ 52| 1| some_string = None;
+ 53| 1| println!(
+ 54| 1| "The string or alt: {}"
+ 55| 1| ,
+ 56| 1| some_string
+ 57| 1| .
+ 58| 1| unwrap_or_else
+ 59| 1| (
+ 60| 1| ||
+ 61| 1| {
+ 62| 1| let mut countdown = 0;
+ 63| 1| if is_false {
+ 64| 0| countdown = 10;
+ 65| 1| }
+ 66| 1| "alt string 3".to_owned()
+ 67| 1| }
+ 68| 1| )
+ 69| 1| );
+ 70| 1|
+ 71| 1| some_string = None;
+ 72| 1| let
+ 73| 1| a
+ 74| 1| =
+ 75| 1| ||
+ 76| 1| {
+ 77| 1| let mut countdown = 0;
+ 78| 1| if is_false {
+ 79| 0| countdown = 10;
+ 80| 1| }
+ 81| 1| "alt string 4".to_owned()
+ 82| | };
+ 83| 1| println!(
+ 84| 1| "The string or alt: {}"
+ 85| 1| ,
+ 86| 1| some_string
+ 87| 1| .
+ 88| 1| unwrap_or_else
+ 89| 1| (
+ 90| 1| a
+ 91| 1| )
+ 92| 1| );
+ 93| 1|
+ 94| 1| let
+ 95| 1| quote_closure
+ 96| 1| =
+ 97| 1| |val|
+ 98| 5| {
+ 99| 5| let mut countdown = 0;
+ 100| 5| if is_false {
+ 101| 0| countdown = 10;
+ 102| 5| }
+ 103| 5| format!("'{}'", val)
+ 104| | };
+ 105| 1| println!(
+ 106| 1| "Repeated, quoted string: {:?}"
+ 107| 1| ,
+ 108| 1| std::iter::repeat("repeat me")
+ 109| 1| .take(5)
+ 110| 1| .map
+ 111| 1| (
+ 112| 1| quote_closure
+ 113| 1| )
+ 114| 1| .collect::<Vec<_>>()
+ 115| 1| );
+ 116| 1|
+ 117| 1| let
+ 118| 1| _unused_closure
+ 119| | =
+ 120| | |
+ 121| | mut countdown
+ 122| | |
+ 123| 0| {
+ 124| 0| if is_false {
+ 125| 0| countdown = 10;
+ 126| 0| }
+ 127| 0| "closure should be unused".to_owned()
+ 128| | };
+ 129| |
+ 130| 1| let mut countdown = 10;
+ 131| 1| let _short_unused_closure = | _unused_arg: u8 | countdown += 1;
+ ^0
+ 132| |
+ 133| |
+ 134| 1| let short_used_covered_closure_macro = | used_arg: u8 | println!("called");
+ 135| 1| let short_used_not_covered_closure_macro = | used_arg: u8 | println!("not called");
+ ^0
+ 136| 1| let _short_unused_closure_macro = | _unused_arg: u8 | println!("not called");
+ ^0
+ 137| |
+ 138| |
+ 139| |
+ 140| |
+ 141| 1| let _short_unused_closure_block = | _unused_arg: u8 | { println!("not called") };
+ ^0
+ 142| |
+ 143| 1| let _shortish_unused_closure = | _unused_arg: u8 | {
+ 144| 0| println!("not called")
+ 145| 0| };
+ 146| |
+ 147| 1| let _as_short_unused_closure = |
+ 148| | _unused_arg: u8
+ 149| 0| | { println!("not called") };
+ 150| |
+ 151| 1| let _almost_as_short_unused_closure = |
+ 152| | _unused_arg: u8
+ 153| 0| | { println!("not called") }
+ 154| | ;
+ 155| |
+ 156| |
+ 157| |
+ 158| |
+ 159| |
+ 160| 1| let _short_unused_closure_line_break_no_block = | _unused_arg: u8 |
+ 161| 0|println!("not called")
+ 162| | ;
+ 163| |
+ 164| 1| let _short_unused_closure_line_break_no_block2 =
+ 165| | | _unused_arg: u8 |
+ 166| 0| println!(
+ 167| 0| "not called"
+ 168| 0| )
+ 169| | ;
+ 170| |
+ 171| 1| let short_used_not_covered_closure_line_break_no_block_embedded_branch =
+ 172| | | _unused_arg: u8 |
+ 173| 0| println!(
+ 174| 0| "not called: {}",
+ 175| 0| if is_true { "check" } else { "me" }
+ 176| | )
+ 177| | ;
+ 178| |
+ 179| 1| let short_used_not_covered_closure_line_break_block_embedded_branch =
+ 180| 1| | _unused_arg: u8 |
+ 181| 0| {
+ 182| 0| println!(
+ 183| 0| "not called: {}",
+ 184| 0| if is_true { "check" } else { "me" }
+ 185| | )
+ 186| | }
+ 187| | ;
+ 188| |
+ 189| 1| let short_used_covered_closure_line_break_no_block_embedded_branch =
+ 190| 1| | _unused_arg: u8 |
+ 191| 1| println!(
+ 192| 1| "not called: {}",
+ 193| 1| if is_true { "check" } else { "me" }
+ ^0
+ 194| | )
+ 195| | ;
+ 196| |
+ 197| 1| let short_used_covered_closure_line_break_block_embedded_branch =
+ 198| 1| | _unused_arg: u8 |
+ 199| 1| {
+ 200| 1| println!(
+ 201| 1| "not called: {}",
+ 202| 1| if is_true { "check" } else { "me" }
+ ^0
+ 203| | )
+ 204| | }
+ 205| | ;
+ 206| |
+ 207| 1| if is_false {
+ 208| 0| short_used_not_covered_closure_macro(0);
+ 209| 0| short_used_not_covered_closure_line_break_no_block_embedded_branch(0);
+ 210| 0| short_used_not_covered_closure_line_break_block_embedded_branch(0);
+ 211| 1| }
+ 212| 1| short_used_covered_closure_macro(0);
+ 213| 1| short_used_covered_closure_line_break_no_block_embedded_branch(0);
+ 214| 1| short_used_covered_closure_line_break_block_embedded_branch(0);
+ 215| 1|}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.closure_macro.txt b/src/test/run-make/coverage-reports/expected_show_coverage.closure_macro.txt
new file mode 100644
index 000000000..87f701476
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.closure_macro.txt
@@ -0,0 +1,42 @@
+ 1| |// compile-flags: --edition=2018
+ 2| |#![feature(no_coverage)]
+ 3| |
+ 4| |macro_rules! bail {
+ 5| | ($msg:literal $(,)?) => {
+ 6| | if $msg.len() > 0 {
+ 7| | println!("no msg");
+ 8| | } else {
+ 9| | println!($msg);
+ 10| | }
+ 11| | return Err(String::from($msg));
+ 12| | };
+ 13| |}
+ 14| |
+ 15| |macro_rules! on_error {
+ 16| | ($value:expr, $error_message:expr) => {
+ 17| | $value.or_else(|e| { // FIXME(85000): no coverage in closure macros
+ 18| | let message = format!($error_message, e);
+ 19| | if message.len() > 0 {
+ 20| | println!("{}", message);
+ 21| | Ok(String::from("ok"))
+ 22| | } else {
+ 23| | bail!("error");
+ 24| | }
+ 25| | })
+ 26| | };
+ 27| |}
+ 28| |
+ 29| 1|fn load_configuration_files() -> Result<String, String> {
+ 30| 1| Ok(String::from("config"))
+ 31| 1|}
+ 32| |
+ 33| 1|pub fn main() -> Result<(), String> {
+ 34| 1| println!("Starting service");
+ 35| 1| let config = on_error!(load_configuration_files(), "Error loading configs: {}")?;
+ ^0
+ 36| |
+ 37| 1| let startup_delay_duration = String::from("arg");
+ 38| 1| let _ = (config, startup_delay_duration);
+ 39| 1| Ok(())
+ 40| 1|}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.closure_macro_async.txt b/src/test/run-make/coverage-reports/expected_show_coverage.closure_macro_async.txt
new file mode 100644
index 000000000..2b5418132
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.closure_macro_async.txt
@@ -0,0 +1,83 @@
+ 1| |// compile-flags: --edition=2018
+ 2| |#![feature(no_coverage)]
+ 3| |
+ 4| |macro_rules! bail {
+ 5| | ($msg:literal $(,)?) => {
+ 6| | if $msg.len() > 0 {
+ 7| | println!("no msg");
+ 8| | } else {
+ 9| | println!($msg);
+ 10| | }
+ 11| | return Err(String::from($msg));
+ 12| | };
+ 13| |}
+ 14| |
+ 15| |macro_rules! on_error {
+ 16| | ($value:expr, $error_message:expr) => {
+ 17| | $value.or_else(|e| { // FIXME(85000): no coverage in closure macros
+ 18| | let message = format!($error_message, e);
+ 19| | if message.len() > 0 {
+ 20| | println!("{}", message);
+ 21| | Ok(String::from("ok"))
+ 22| | } else {
+ 23| | bail!("error");
+ 24| | }
+ 25| | })
+ 26| | };
+ 27| |}
+ 28| |
+ 29| 1|fn load_configuration_files() -> Result<String, String> {
+ 30| 1| Ok(String::from("config"))
+ 31| 1|}
+ 32| |
+ 33| 1|pub async fn test() -> Result<(), String> {
+ 34| 1| println!("Starting service");
+ 35| 1| let config = on_error!(load_configuration_files(), "Error loading configs: {}")?;
+ ^0
+ 36| |
+ 37| 1| let startup_delay_duration = String::from("arg");
+ 38| 1| let _ = (config, startup_delay_duration);
+ 39| 1| Ok(())
+ 40| 1|}
+ 41| |
+ 42| |#[no_coverage]
+ 43| |fn main() {
+ 44| | executor::block_on(test());
+ 45| |}
+ 46| |
+ 47| |mod executor {
+ 48| | use core::{
+ 49| | future::Future,
+ 50| | pin::Pin,
+ 51| | task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
+ 52| | };
+ 53| |
+ 54| | #[no_coverage]
+ 55| | pub fn block_on<F: Future>(mut future: F) -> F::Output {
+ 56| | let mut future = unsafe { Pin::new_unchecked(&mut future) };
+ 57| | use std::hint::unreachable_unchecked;
+ 58| | static VTABLE: RawWakerVTable = RawWakerVTable::new(
+ 59| |
+ 60| | #[no_coverage]
+ 61| | |_| unsafe { unreachable_unchecked() }, // clone
+ 62| |
+ 63| | #[no_coverage]
+ 64| | |_| unsafe { unreachable_unchecked() }, // wake
+ 65| |
+ 66| | #[no_coverage]
+ 67| | |_| unsafe { unreachable_unchecked() }, // wake_by_ref
+ 68| |
+ 69| | #[no_coverage]
+ 70| | |_| (),
+ 71| | );
+ 72| | let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
+ 73| | let mut context = Context::from_waker(&waker);
+ 74| |
+ 75| | loop {
+ 76| | if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+ 77| | break val;
+ 78| | }
+ 79| | }
+ 80| | }
+ 81| |}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.conditions.txt b/src/test/run-make/coverage-reports/expected_show_coverage.conditions.txt
new file mode 100644
index 000000000..2d8a98a5d
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.conditions.txt
@@ -0,0 +1,94 @@
+ 1| |#![allow(unused_assignments, unused_variables)]
+ 2| |
+ 3| 1|fn main() {
+ 4| 1| let mut countdown = 0;
+ 5| 1| if true {
+ 6| 1| countdown = 10;
+ 7| 1| }
+ ^0
+ 8| |
+ 9| | const B: u32 = 100;
+ 10| 1| let x = if countdown > 7 {
+ 11| 1| countdown -= 4;
+ 12| 1| B
+ 13| 0| } else if countdown > 2 {
+ 14| 0| if countdown < 1 || countdown > 5 || countdown != 9 {
+ 15| 0| countdown = 0;
+ 16| 0| }
+ 17| 0| countdown -= 5;
+ 18| 0| countdown
+ 19| | } else {
+ 20| 0| return;
+ 21| | };
+ 22| |
+ 23| 1| let mut countdown = 0;
+ 24| 1| if true {
+ 25| 1| countdown = 10;
+ 26| 1| }
+ ^0
+ 27| |
+ 28| 1| if countdown > 7 {
+ 29| 1| countdown -= 4;
+ 30| 1| } else if countdown > 2 {
+ ^0
+ 31| 0| if countdown < 1 || countdown > 5 || countdown != 9 {
+ 32| 0| countdown = 0;
+ 33| 0| }
+ 34| 0| countdown -= 5;
+ 35| | } else {
+ 36| 0| return;
+ 37| | }
+ 38| |
+ 39| 1| if true {
+ 40| 1| let mut countdown = 0;
+ 41| 1| if true {
+ 42| 1| countdown = 10;
+ 43| 1| }
+ ^0
+ 44| |
+ 45| 1| if countdown > 7 {
+ 46| 1| countdown -= 4;
+ 47| 1| }
+ 48| 0| else if countdown > 2 {
+ 49| 0| if countdown < 1 || countdown > 5 || countdown != 9 {
+ 50| 0| countdown = 0;
+ 51| 0| }
+ 52| 0| countdown -= 5;
+ 53| | } else {
+ 54| 0| return;
+ 55| | }
+ 56| 0| }
+ 57| |
+ 58| |
+ 59| 1| let mut countdown = 0;
+ 60| 1| if true {
+ 61| 1| countdown = 1;
+ 62| 1| }
+ ^0
+ 63| |
+ 64| 1| let z = if countdown > 7 {
+ ^0
+ 65| 0| countdown -= 4;
+ 66| 1| } else if countdown > 2 {
+ 67| 0| if countdown < 1 || countdown > 5 || countdown != 9 {
+ 68| 0| countdown = 0;
+ 69| 0| }
+ 70| 0| countdown -= 5;
+ 71| | } else {
+ 72| 1| let should_be_reachable = countdown;
+ 73| 1| println!("reached");
+ 74| 1| return;
+ 75| | };
+ 76| |
+ 77| 0| let w = if countdown > 7 {
+ 78| 0| countdown -= 4;
+ 79| 0| } else if countdown > 2 {
+ 80| 0| if countdown < 1 || countdown > 5 || countdown != 9 {
+ 81| 0| countdown = 0;
+ 82| 0| }
+ 83| 0| countdown -= 5;
+ 84| | } else {
+ 85| 0| return;
+ 86| | };
+ 87| 1|}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.continue.txt b/src/test/run-make/coverage-reports/expected_show_coverage.continue.txt
new file mode 100644
index 000000000..1c64ead9f
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.continue.txt
@@ -0,0 +1,70 @@
+ 1| |#![allow(unused_assignments, unused_variables)]
+ 2| |
+ 3| 1|fn main() {
+ 4| 1| let is_true = std::env::args().len() == 1;
+ 5| 1|
+ 6| 1| let mut x = 0;
+ 7| 11| for _ in 0..10 {
+ 8| 10| match is_true {
+ 9| | true => {
+ 10| 10| continue;
+ 11| | }
+ 12| 0| _ => {
+ 13| 0| x = 1;
+ 14| 0| }
+ 15| 0| }
+ 16| 0| x = 3;
+ 17| | }
+ 18| 11| for _ in 0..10 {
+ 19| 10| match is_true {
+ 20| 0| false => {
+ 21| 0| x = 1;
+ 22| 0| }
+ 23| | _ => {
+ 24| 10| continue;
+ 25| | }
+ 26| | }
+ 27| 0| x = 3;
+ 28| | }
+ 29| 11| for _ in 0..10 {
+ 30| 10| match is_true {
+ 31| 10| true => {
+ 32| 10| x = 1;
+ 33| 10| }
+ 34| | _ => {
+ 35| 0| continue;
+ 36| | }
+ 37| | }
+ 38| 10| x = 3;
+ 39| | }
+ 40| 11| for _ in 0..10 {
+ 41| 10| if is_true {
+ 42| 10| continue;
+ 43| 0| }
+ 44| 0| x = 3;
+ 45| | }
+ 46| 11| for _ in 0..10 {
+ 47| 10| match is_true {
+ 48| 0| false => {
+ 49| 0| x = 1;
+ 50| 0| }
+ 51| 10| _ => {
+ 52| 10| let _ = x;
+ 53| 10| }
+ 54| | }
+ 55| 10| x = 3;
+ 56| | }
+ 57| 1| for _ in 0..10 {
+ 58| 1| match is_true {
+ 59| 0| false => {
+ 60| 0| x = 1;
+ 61| 0| }
+ 62| | _ => {
+ 63| 1| break;
+ 64| | }
+ 65| | }
+ 66| 0| x = 3;
+ 67| | }
+ 68| | let _ = x;
+ 69| 1|}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.dead_code.txt b/src/test/run-make/coverage-reports/expected_show_coverage.dead_code.txt
new file mode 100644
index 000000000..09ff14c6f
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.dead_code.txt
@@ -0,0 +1,39 @@
+ 1| |#![allow(unused_assignments, unused_variables)]
+ 2| |
+ 3| 0|pub fn unused_pub_fn_not_in_library() {
+ 4| 0| // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ 5| 0| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ 6| 0| // dependent conditions.
+ 7| 0| let is_true = std::env::args().len() == 1;
+ 8| 0|
+ 9| 0| let mut countdown = 0;
+ 10| 0| if is_true {
+ 11| 0| countdown = 10;
+ 12| 0| }
+ 13| 0|}
+ 14| |
+ 15| 0|fn unused_fn() {
+ 16| 0| // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ 17| 0| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ 18| 0| // dependent conditions.
+ 19| 0| let is_true = std::env::args().len() == 1;
+ 20| 0|
+ 21| 0| let mut countdown = 0;
+ 22| 0| if is_true {
+ 23| 0| countdown = 10;
+ 24| 0| }
+ 25| 0|}
+ 26| |
+ 27| 1|fn main() {
+ 28| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ 29| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ 30| 1| // dependent conditions.
+ 31| 1| let is_true = std::env::args().len() == 1;
+ 32| 1|
+ 33| 1| let mut countdown = 0;
+ 34| 1| if is_true {
+ 35| 1| countdown = 10;
+ 36| 1| }
+ ^0
+ 37| 1|}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.doctest.txt b/src/test/run-make/coverage-reports/expected_show_coverage.doctest.txt
new file mode 100644
index 000000000..7ae0e9788
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.doctest.txt
@@ -0,0 +1,121 @@
+../coverage/doctest.rs:
+ 1| |//! This test ensures that code from doctests is properly re-mapped.
+ 2| |//! See <https://github.com/rust-lang/rust/issues/79417> for more info.
+ 3| |//!
+ 4| |//! Just some random code:
+ 5| 1|//! ```
+ 6| 1|//! if true {
+ 7| |//! // this is executed!
+ 8| 1|//! assert_eq!(1, 1);
+ 9| |//! } else {
+ 10| |//! // this is not!
+ 11| 0|//! assert_eq!(1, 2);
+ 12| |//! }
+ 13| 1|//! ```
+ 14| |//!
+ 15| |//! doctest testing external code:
+ 16| |//! ```
+ 17| 1|//! extern crate doctest_crate;
+ 18| 1|//! doctest_crate::fn_run_in_doctests(1);
+ 19| 1|//! ```
+ 20| |//!
+ 21| |//! doctest returning a result:
+ 22| 1|//! ```
+ 23| 2|//! #[derive(Debug, PartialEq)]
+ ^1
+ ------------------
+ | Unexecuted instantiation: <rust_out::main::_doctest_main____coverage_doctest_rs_22_0::SomeError as core::cmp::PartialEq>::ne
+ ------------------
+ | <rust_out::main::_doctest_main____coverage_doctest_rs_22_0::SomeError as core::cmp::PartialEq>::eq:
+ | 23| 2|//! #[derive(Debug, PartialEq)]
+ ------------------
+ 24| 1|//! struct SomeError {
+ 25| 1|//! msg: String,
+ 26| 1|//! }
+ 27| 1|//! let mut res = Err(SomeError { msg: String::from("a message") });
+ 28| 1|//! if res.is_ok() {
+ 29| 0|//! res?;
+ 30| |//! } else {
+ 31| 1|//! if *res.as_ref().unwrap_err() == *res.as_ref().unwrap_err() {
+ 32| 1|//! println!("{:?}", res);
+ 33| 1|//! }
+ ^0
+ 34| 1|//! if *res.as_ref().unwrap_err() == *res.as_ref().unwrap_err() {
+ 35| 1|//! res = Ok(1);
+ 36| 1|//! }
+ ^0
+ 37| 1|//! res = Ok(0);
+ 38| |//! }
+ 39| |//! // need to be explicit because rustdoc cant infer the return type
+ 40| 1|//! Ok::<(), SomeError>(())
+ 41| 1|//! ```
+ 42| |//!
+ 43| |//! doctest with custom main:
+ 44| |//! ```
+ 45| 1|//! fn some_func() {
+ 46| 1|//! println!("called some_func()");
+ 47| 1|//! }
+ 48| |//!
+ 49| 0|//! #[derive(Debug)]
+ 50| |//! struct SomeError;
+ 51| |//!
+ 52| |//! extern crate doctest_crate;
+ 53| |//!
+ 54| 1|//! fn doctest_main() -> Result<(), SomeError> {
+ 55| 1|//! some_func();
+ 56| 1|//! doctest_crate::fn_run_in_doctests(2);
+ 57| 1|//! Ok(())
+ 58| 1|//! }
+ 59| |//!
+ 60| |//! // this `main` is not shown as covered, as it clashes with all the other
+ 61| |//! // `main` functions that were automatically generated for doctests
+ 62| |//! fn main() -> Result<(), SomeError> {
+ 63| |//! doctest_main()
+ 64| |//! }
+ 65| |//! ```
+ 66| |
+ 67| |/// doctest attached to fn testing external code:
+ 68| |/// ```
+ 69| 1|/// extern crate doctest_crate;
+ 70| 1|/// doctest_crate::fn_run_in_doctests(3);
+ 71| 1|/// ```
+ 72| |///
+ 73| 1|fn main() {
+ 74| 1| if true {
+ 75| 1| assert_eq!(1, 1);
+ 76| | } else {
+ 77| 0| assert_eq!(1, 2);
+ 78| | }
+ 79| 1|}
+ 80| |
+ 81| |// FIXME(Swatinem): Fix known issue that coverage code region columns need to be offset by the
+ 82| |// doc comment line prefix (`///` or `//!`) and any additional indent (before or after the doc
+ 83| |// comment characters). This test produces `llvm-cov show` results demonstrating the problem.
+ 84| |//
+ 85| |// One of the above tests now includes: `derive(Debug, PartialEq)`, producing an `llvm-cov show`
+ 86| |// result with a distinct count for `Debug`, denoted by `^1`, but the caret points to the wrong
+ 87| |// column. Similarly, the `if` blocks without `else` blocks show `^0`, which should point at, or
+ 88| |// one character past, the `if` block's closing brace. In both cases, these are most likely off
+ 89| |// by the number of characters stripped from the beginning of each doc comment line: indent
+ 90| |// whitespace, if any, doc comment prefix (`//!` in this case) and (I assume) one space character
+ 91| |// (?). Note, when viewing `llvm-cov show` results in `--color` mode, the column offset errors are
+ 92| |// more pronounced, and show up in more places, with background color used to show some distinct
+ 93| |// code regions with different coverage counts.
+ 94| |//
+ 95| |// NOTE: Since the doc comment line prefix may vary, one possible solution is to replace each
+ 96| |// character stripped from the beginning of doc comment lines with a space. This will give coverage
+ 97| |// results the correct column offsets, and I think it should compile correctly, but I don't know
+ 98| |// what affect it might have on diagnostic messages from the compiler, and whether anyone would care
+ 99| |// if the indentation changed. I don't know if there is a more viable solution.
+
+../coverage/lib/doctest_crate.rs:
+ 1| |/// A function run only from within doctests
+ 2| 3|pub fn fn_run_in_doctests(conditional: usize) {
+ 3| 3| match conditional {
+ 4| 1| 1 => assert_eq!(1, 1), // this is run,
+ 5| 1| 2 => assert_eq!(1, 1), // this,
+ 6| 1| 3 => assert_eq!(1, 1), // and this too
+ 7| 0| _ => assert_eq!(1, 2), // however this is not
+ 8| | }
+ 9| 3|}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.drop_trait.txt b/src/test/run-make/coverage-reports/expected_show_coverage.drop_trait.txt
new file mode 100644
index 000000000..fe6a9e93c
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.drop_trait.txt
@@ -0,0 +1,34 @@
+ 1| |#![allow(unused_assignments)]
+ 2| |// expect-exit-status-1
+ 3| |
+ 4| |struct Firework {
+ 5| | strength: i32,
+ 6| |}
+ 7| |
+ 8| |impl Drop for Firework {
+ 9| 2| fn drop(&mut self) {
+ 10| 2| println!("BOOM times {}!!!", self.strength);
+ 11| 2| }
+ 12| |}
+ 13| |
+ 14| 1|fn main() -> Result<(),u8> {
+ 15| 1| let _firecracker = Firework { strength: 1 };
+ 16| 1|
+ 17| 1| let _tnt = Firework { strength: 100 };
+ 18| 1|
+ 19| 1| if true {
+ 20| 1| println!("Exiting with error...");
+ 21| 1| return Err(1);
+ 22| 0| }
+ 23| 0|
+ 24| 0| let _ = Firework { strength: 1000 };
+ 25| 0|
+ 26| 0| Ok(())
+ 27| 1|}
+ 28| |
+ 29| |// Expected program output:
+ 30| |// Exiting with error...
+ 31| |// BOOM times 100!!!
+ 32| |// BOOM times 1!!!
+ 33| |// Error: 1
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.generator.txt b/src/test/run-make/coverage-reports/expected_show_coverage.generator.txt
new file mode 100644
index 000000000..d70e12e41
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.generator.txt
@@ -0,0 +1,32 @@
+ 1| |#![feature(generators, generator_trait)]
+ 2| |
+ 3| |use std::ops::{Generator, GeneratorState};
+ 4| |use std::pin::Pin;
+ 5| |
+ 6| |// The following implementation of a function called from a `yield` statement
+ 7| |// (apparently requiring the Result and the `String` type or constructor)
+ 8| |// creates conditions where the `generator::StateTransform` MIR transform will
+ 9| |// drop all `Counter` `Coverage` statements from a MIR. `simplify.rs` has logic
+ 10| |// to handle this condition, and still report dead block coverage.
+ 11| 1|fn get_u32(val: bool) -> Result<u32, String> {
+ 12| 1| if val { Ok(1) } else { Err(String::from("some error")) }
+ ^0
+ 13| 1|}
+ 14| |
+ 15| 1|fn main() {
+ 16| 1| let is_true = std::env::args().len() == 1;
+ 17| 1| let mut generator = || {
+ 18| 1| yield get_u32(is_true);
+ 19| 1| return "foo";
+ 20| | };
+ 21| |
+ 22| 1| match Pin::new(&mut generator).resume(()) {
+ 23| 1| GeneratorState::Yielded(Ok(1)) => {}
+ 24| 0| _ => panic!("unexpected return from resume"),
+ 25| | }
+ 26| 1| match Pin::new(&mut generator).resume(()) {
+ 27| 1| GeneratorState::Complete("foo") => {}
+ 28| 0| _ => panic!("unexpected return from resume"),
+ 29| | }
+ 30| 1|}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.generics.txt b/src/test/run-make/coverage-reports/expected_show_coverage.generics.txt
new file mode 100644
index 000000000..48983ba43
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.generics.txt
@@ -0,0 +1,71 @@
+ 1| |#![allow(unused_assignments)]
+ 2| |// expect-exit-status-1
+ 3| |
+ 4| |struct Firework<T> where T: Copy + std::fmt::Display {
+ 5| | strength: T,
+ 6| |}
+ 7| |
+ 8| |impl<T> Firework<T> where T: Copy + std::fmt::Display {
+ 9| | #[inline(always)]
+ 10| 3| fn set_strength(&mut self, new_strength: T) {
+ 11| 3| self.strength = new_strength;
+ 12| 3| }
+ ------------------
+ | <generics::Firework<i32>>::set_strength:
+ | 10| 1| fn set_strength(&mut self, new_strength: T) {
+ | 11| 1| self.strength = new_strength;
+ | 12| 1| }
+ ------------------
+ | <generics::Firework<f64>>::set_strength:
+ | 10| 2| fn set_strength(&mut self, new_strength: T) {
+ | 11| 2| self.strength = new_strength;
+ | 12| 2| }
+ ------------------
+ 13| |}
+ 14| |
+ 15| |impl<T> Drop for Firework<T> where T: Copy + std::fmt::Display {
+ 16| | #[inline(always)]
+ 17| 2| fn drop(&mut self) {
+ 18| 2| println!("BOOM times {}!!!", self.strength);
+ 19| 2| }
+ ------------------
+ | <generics::Firework<f64> as core::ops::drop::Drop>::drop:
+ | 17| 1| fn drop(&mut self) {
+ | 18| 1| println!("BOOM times {}!!!", self.strength);
+ | 19| 1| }
+ ------------------
+ | <generics::Firework<i32> as core::ops::drop::Drop>::drop:
+ | 17| 1| fn drop(&mut self) {
+ | 18| 1| println!("BOOM times {}!!!", self.strength);
+ | 19| 1| }
+ ------------------
+ 20| |}
+ 21| |
+ 22| 1|fn main() -> Result<(),u8> {
+ 23| 1| let mut firecracker = Firework { strength: 1 };
+ 24| 1| firecracker.set_strength(2);
+ 25| 1|
+ 26| 1| let mut tnt = Firework { strength: 100.1 };
+ 27| 1| tnt.set_strength(200.1);
+ 28| 1| tnt.set_strength(300.3);
+ 29| 1|
+ 30| 1| if true {
+ 31| 1| println!("Exiting with error...");
+ 32| 1| return Err(1);
+ 33| 0| }
+ 34| 0|
+ 35| 0|
+ 36| 0|
+ 37| 0|
+ 38| 0|
+ 39| 0| let _ = Firework { strength: 1000 };
+ 40| 0|
+ 41| 0| Ok(())
+ 42| 1|}
+ 43| |
+ 44| |// Expected program output:
+ 45| |// Exiting with error...
+ 46| |// BOOM times 100!!!
+ 47| |// BOOM times 1!!!
+ 48| |// Error: 1
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.if.txt b/src/test/run-make/coverage-reports/expected_show_coverage.if.txt
new file mode 100644
index 000000000..0c9eff227
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.if.txt
@@ -0,0 +1,30 @@
+ 1| |#![allow(unused_assignments, unused_variables)]
+ 2| |
+ 3| 1|fn main() {
+ 4| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ 5| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ 6| 1| // dependent conditions.
+ 7| 1| let
+ 8| 1| is_true
+ 9| 1| =
+ 10| 1| std::env::args().len()
+ 11| 1| ==
+ 12| 1| 1
+ 13| 1| ;
+ 14| 1| let
+ 15| 1| mut
+ 16| 1| countdown
+ 17| 1| =
+ 18| 1| 0
+ 19| 1| ;
+ 20| 1| if
+ 21| 1| is_true
+ 22| 1| {
+ 23| 1| countdown
+ 24| 1| =
+ 25| 1| 10
+ 26| 1| ;
+ 27| 1| }
+ ^0
+ 28| 1|}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.if_else.txt b/src/test/run-make/coverage-reports/expected_show_coverage.if_else.txt
new file mode 100644
index 000000000..4285d3186
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.if_else.txt
@@ -0,0 +1,41 @@
+ 1| |#![allow(unused_assignments, unused_variables)]
+ 2| |
+ 3| 1|fn main() {
+ 4| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ 5| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ 6| 1| // dependent conditions.
+ 7| 1| let is_true = std::env::args().len() == 1;
+ 8| 1|
+ 9| 1| let mut countdown = 0;
+ 10| 1| if
+ 11| 1| is_true
+ 12| 1| {
+ 13| 1| countdown
+ 14| 1| =
+ 15| 1| 10
+ 16| 1| ;
+ 17| 1| }
+ 18| | else // Note coverage region difference without semicolon
+ 19| | {
+ 20| 0| countdown
+ 21| 0| =
+ 22| 0| 100
+ 23| | }
+ 24| |
+ 25| | if
+ 26| 1| is_true
+ 27| 1| {
+ 28| 1| countdown
+ 29| 1| =
+ 30| 1| 10
+ 31| 1| ;
+ 32| 1| }
+ 33| | else
+ 34| 0| {
+ 35| 0| countdown
+ 36| 0| =
+ 37| 0| 100
+ 38| 0| ;
+ 39| 0| }
+ 40| 1|}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.inline-dead.txt b/src/test/run-make/coverage-reports/expected_show_coverage.inline-dead.txt
new file mode 100644
index 000000000..effdef80e
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.inline-dead.txt
@@ -0,0 +1,28 @@
+ 1| |// Regression test for issue #98833.
+ 2| |// compile-flags: -Zinline-mir -Cdebug-assertions=off
+ 3| |
+ 4| 1|fn main() {
+ 5| 1| println!("{}", live::<false>());
+ 6| 1|
+ 7| 1| let f = |x: bool| {
+ 8| | debug_assert!(
+ 9| | x
+ 10| | );
+ 11| 1| };
+ 12| 1| f(false);
+ 13| 1|}
+ 14| |
+ 15| |#[inline]
+ 16| 1|fn live<const B: bool>() -> u32 {
+ 17| 1| if B {
+ 18| 0| dead()
+ 19| | } else {
+ 20| 1| 0
+ 21| | }
+ 22| 1|}
+ 23| |
+ 24| |#[inline]
+ 25| 0|fn dead() -> u32 {
+ 26| 0| 42
+ 27| 0|}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.inline.txt b/src/test/run-make/coverage-reports/expected_show_coverage.inline.txt
new file mode 100644
index 000000000..6f5d1544f
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.inline.txt
@@ -0,0 +1,54 @@
+ 1| |// compile-flags: -Zinline-mir
+ 2| |
+ 3| |use std::fmt::Display;
+ 4| |
+ 5| 1|fn main() {
+ 6| 1| permutations(&['a', 'b', 'c']);
+ 7| 1|}
+ 8| |
+ 9| |#[inline(always)]
+ 10| 1|fn permutations<T: Copy + Display>(xs: &[T]) {
+ 11| 1| let mut ys = xs.to_owned();
+ 12| 1| permutate(&mut ys, 0);
+ 13| 1|}
+ 14| |
+ 15| 16|fn permutate<T: Copy + Display>(xs: &mut [T], k: usize) {
+ 16| 16| let n = length(xs);
+ 17| 16| if k == n {
+ 18| 6| display(xs);
+ 19| 10| } else if k < n {
+ 20| 15| for i in k..n {
+ ^10
+ 21| 15| swap(xs, i, k);
+ 22| 15| permutate(xs, k + 1);
+ 23| 15| swap(xs, i, k);
+ 24| 15| }
+ 25| 0| } else {
+ 26| 0| error();
+ 27| 0| }
+ 28| 16|}
+ 29| |
+ 30| 16|fn length<T>(xs: &[T]) -> usize {
+ 31| 16| xs.len()
+ 32| 16|}
+ 33| |
+ 34| |#[inline]
+ 35| 30|fn swap<T: Copy>(xs: &mut [T], i: usize, j: usize) {
+ 36| 30| let t = xs[i];
+ 37| 30| xs[i] = xs[j];
+ 38| 30| xs[j] = t;
+ 39| 30|}
+ 40| |
+ 41| 6|fn display<T: Display>(xs: &[T]) {
+ 42| 24| for x in xs {
+ ^18
+ 43| 18| print!("{}", x);
+ 44| 18| }
+ 45| 6| println!();
+ 46| 6|}
+ 47| |
+ 48| |#[inline(always)]
+ 49| 0|fn error() {
+ 50| 0| panic!("error");
+ 51| 0|}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.inner_items.txt b/src/test/run-make/coverage-reports/expected_show_coverage.inner_items.txt
new file mode 100644
index 000000000..883254a09
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.inner_items.txt
@@ -0,0 +1,60 @@
+ 1| |#![allow(unused_assignments, unused_variables, dead_code)]
+ 2| |
+ 3| 1|fn main() {
+ 4| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ 5| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ 6| 1| // dependent conditions.
+ 7| 1| let is_true = std::env::args().len() == 1;
+ 8| 1|
+ 9| 1| let mut countdown = 0;
+ 10| 1| if is_true {
+ 11| 1| countdown = 10;
+ 12| 1| }
+ ^0
+ 13| |
+ 14| | mod in_mod {
+ 15| | const IN_MOD_CONST: u32 = 1000;
+ 16| | }
+ 17| |
+ 18| 3| fn in_func(a: u32) {
+ 19| 3| let b = 1;
+ 20| 3| let c = a + b;
+ 21| 3| println!("c = {}", c)
+ 22| 3| }
+ 23| |
+ 24| | struct InStruct {
+ 25| | in_struct_field: u32,
+ 26| | }
+ 27| |
+ 28| | const IN_CONST: u32 = 1234;
+ 29| |
+ 30| | trait InTrait {
+ 31| | fn trait_func(&mut self, incr: u32);
+ 32| |
+ 33| 1| fn default_trait_func(&mut self) {
+ 34| 1| in_func(IN_CONST);
+ 35| 1| self.trait_func(IN_CONST);
+ 36| 1| }
+ 37| | }
+ 38| |
+ 39| | impl InTrait for InStruct {
+ 40| 1| fn trait_func(&mut self, incr: u32) {
+ 41| 1| self.in_struct_field += incr;
+ 42| 1| in_func(self.in_struct_field);
+ 43| 1| }
+ 44| | }
+ 45| |
+ 46| | type InType = String;
+ 47| |
+ 48| 1| if is_true {
+ 49| 1| in_func(countdown);
+ 50| 1| }
+ ^0
+ 51| |
+ 52| 1| let mut val = InStruct {
+ 53| 1| in_struct_field: 101,
+ 54| 1| };
+ 55| 1|
+ 56| 1| val.default_trait_func();
+ 57| 1|}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.issue-83601.txt b/src/test/run-make/coverage-reports/expected_show_coverage.issue-83601.txt
new file mode 100644
index 000000000..de32c88b7
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.issue-83601.txt
@@ -0,0 +1,22 @@
+ 1| |// Shows that rust-lang/rust/83601 is resolved
+ 2| |
+ 3| 3|#[derive(Debug, PartialEq, Eq)]
+ ^2
+ ------------------
+ | <issue_83601::Foo as core::cmp::PartialEq>::eq:
+ | 3| 2|#[derive(Debug, PartialEq, Eq)]
+ ------------------
+ | Unexecuted instantiation: <issue_83601::Foo as core::cmp::PartialEq>::ne
+ ------------------
+ 4| |struct Foo(u32);
+ 5| |
+ 6| 1|fn main() {
+ 7| 1| let bar = Foo(1);
+ 8| 1| assert_eq!(bar, Foo(1));
+ 9| 1| let baz = Foo(0);
+ 10| 1| assert_ne!(baz, Foo(1));
+ 11| 1| println!("{:?}", Foo(1));
+ 12| 1| println!("{:?}", bar);
+ 13| 1| println!("{:?}", baz);
+ 14| 1|}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.issue-84561.txt b/src/test/run-make/coverage-reports/expected_show_coverage.issue-84561.txt
new file mode 100644
index 000000000..f24f7c694
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.issue-84561.txt
@@ -0,0 +1,195 @@
+ 1| |// This demonstrated Issue #84561: function-like macros produce unintuitive coverage results.
+ 2| |
+ 3| |// expect-exit-status-101
+ 4| 21|#[derive(PartialEq, Eq)]
+ ------------------
+ | <issue_84561::Foo as core::cmp::PartialEq>::eq:
+ | 4| 21|#[derive(PartialEq, Eq)]
+ ------------------
+ | Unexecuted instantiation: <issue_84561::Foo as core::cmp::PartialEq>::ne
+ ------------------
+ 5| |struct Foo(u32);
+ 6| 1|fn test3() {
+ 7| 1| let is_true = std::env::args().len() == 1;
+ 8| 1| let bar = Foo(1);
+ 9| 1| assert_eq!(bar, Foo(1));
+ 10| 1| let baz = Foo(0);
+ 11| 1| assert_ne!(baz, Foo(1));
+ 12| 1| println!("{:?}", Foo(1));
+ 13| 1| println!("{:?}", bar);
+ 14| 1| println!("{:?}", baz);
+ 15| 1|
+ 16| 1| assert_eq!(Foo(1), Foo(1));
+ 17| 1| assert_ne!(Foo(0), Foo(1));
+ 18| 1| assert_eq!(Foo(2), Foo(2));
+ 19| 1| let bar = Foo(0);
+ 20| 1| assert_ne!(bar, Foo(3));
+ 21| 1| assert_ne!(Foo(0), Foo(4));
+ 22| 1| assert_eq!(Foo(3), Foo(3), "with a message");
+ ^0
+ 23| 1| println!("{:?}", bar);
+ 24| 1| println!("{:?}", Foo(1));
+ 25| 1|
+ 26| 1| assert_ne!(Foo(0), Foo(5), "{}", if is_true { "true message" } else { "false message" });
+ ^0 ^0 ^0
+ 27| 1| assert_ne!(
+ 28| | Foo(0)
+ 29| | ,
+ 30| | Foo(5)
+ 31| | ,
+ 32| 0| "{}"
+ 33| 0| ,
+ 34| 0| if
+ 35| 0| is_true
+ 36| | {
+ 37| 0| "true message"
+ 38| | } else {
+ 39| 0| "false message"
+ 40| | }
+ 41| | );
+ 42| |
+ 43| 1| let is_true = std::env::args().len() == 1;
+ 44| 1|
+ 45| 1| assert_eq!(
+ 46| 1| Foo(1),
+ 47| 1| Foo(1)
+ 48| 1| );
+ 49| 1| assert_ne!(
+ 50| 1| Foo(0),
+ 51| 1| Foo(1)
+ 52| 1| );
+ 53| 1| assert_eq!(
+ 54| 1| Foo(2),
+ 55| 1| Foo(2)
+ 56| 1| );
+ 57| 1| let bar = Foo(1);
+ 58| 1| assert_ne!(
+ 59| 1| bar,
+ 60| 1| Foo(3)
+ 61| 1| );
+ 62| 1| if is_true {
+ 63| 1| assert_ne!(
+ 64| 1| Foo(0),
+ 65| 1| Foo(4)
+ 66| 1| );
+ 67| | } else {
+ 68| 0| assert_eq!(
+ 69| 0| Foo(3),
+ 70| 0| Foo(3)
+ 71| 0| );
+ 72| | }
+ 73| 1| if is_true {
+ 74| 1| assert_ne!(
+ 75| | Foo(0),
+ 76| | Foo(4),
+ 77| 0| "with a message"
+ 78| | );
+ 79| | } else {
+ 80| 0| assert_eq!(
+ 81| | Foo(3),
+ 82| | Foo(3),
+ 83| 0| "with a message"
+ 84| | );
+ 85| | }
+ 86| 1| assert_ne!(
+ 87| 1| if is_true {
+ 88| 1| Foo(0)
+ 89| | } else {
+ 90| 0| Foo(1)
+ 91| | },
+ 92| | Foo(5)
+ 93| | );
+ 94| 1| assert_ne!(
+ 95| 1| Foo(5),
+ 96| 1| if is_true {
+ 97| 1| Foo(0)
+ 98| | } else {
+ 99| 0| Foo(1)
+ 100| | }
+ 101| | );
+ 102| 1| assert_ne!(
+ 103| 1| if is_true {
+ 104| 1| assert_eq!(
+ 105| 1| Foo(3),
+ 106| 1| Foo(3)
+ 107| 1| );
+ 108| 1| Foo(0)
+ 109| | } else {
+ 110| 0| assert_ne!(
+ 111| 0| if is_true {
+ 112| 0| Foo(0)
+ 113| | } else {
+ 114| 0| Foo(1)
+ 115| | },
+ 116| | Foo(5)
+ 117| | );
+ 118| 0| Foo(1)
+ 119| | },
+ 120| | Foo(5),
+ 121| 0| "with a message"
+ 122| | );
+ 123| 1| assert_eq!(
+ 124| | Foo(1),
+ 125| | Foo(3),
+ 126| 1| "this assert should fail"
+ 127| | );
+ 128| 0| assert_eq!(
+ 129| | Foo(3),
+ 130| | Foo(3),
+ 131| 0| "this assert should not be reached"
+ 132| | );
+ 133| 0|}
+ 134| |
+ 135| |impl std::fmt::Debug for Foo {
+ 136| | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ 137| 7| write!(f, "try and succeed")?;
+ ^0
+ 138| 7| Ok(())
+ 139| 7| }
+ 140| |}
+ 141| |
+ 142| |static mut DEBUG_LEVEL_ENABLED: bool = false;
+ 143| |
+ 144| |macro_rules! debug {
+ 145| | ($($arg:tt)+) => (
+ 146| | if unsafe { DEBUG_LEVEL_ENABLED } {
+ 147| | println!($($arg)+);
+ 148| | }
+ 149| | );
+ 150| |}
+ 151| |
+ 152| 1|fn test1() {
+ 153| 1| debug!("debug is enabled");
+ ^0
+ 154| 1| debug!("debug is enabled");
+ ^0
+ 155| 1| let _ = 0;
+ 156| 1| debug!("debug is enabled");
+ ^0
+ 157| 1| unsafe {
+ 158| 1| DEBUG_LEVEL_ENABLED = true;
+ 159| 1| }
+ 160| 1| debug!("debug is enabled");
+ 161| 1|}
+ 162| |
+ 163| |macro_rules! call_debug {
+ 164| | ($($arg:tt)+) => (
+ 165| 1| fn call_print(s: &str) {
+ 166| 1| print!("{}", s);
+ 167| 1| }
+ 168| |
+ 169| | call_print("called from call_debug: ");
+ 170| | debug!($($arg)+);
+ 171| | );
+ 172| |}
+ 173| |
+ 174| 1|fn test2() {
+ 175| 1| call_debug!("debug is enabled");
+ 176| 1|}
+ 177| |
+ 178| 1|fn main() {
+ 179| 1| test1();
+ 180| 1| test2();
+ 181| 1| test3();
+ 182| 1|}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.issue-85461.txt b/src/test/run-make/coverage-reports/expected_show_coverage.issue-85461.txt
new file mode 100644
index 000000000..1aa4a22c3
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.issue-85461.txt
@@ -0,0 +1,36 @@
+../coverage/issue-85461.rs:
+ 1| |// Regression test for #85461: MSVC sometimes fail to link with dead code and #[inline(always)]
+ 2| |
+ 3| |extern crate inline_always_with_dead_code;
+ 4| |
+ 5| |use inline_always_with_dead_code::{bar, baz};
+ 6| |
+ 7| 1|fn main() {
+ 8| 1| bar::call_me();
+ 9| 1| baz::call_me();
+ 10| 1|}
+
+../coverage/lib/inline_always_with_dead_code.rs:
+ 1| |// compile-flags: -Cinstrument-coverage -Ccodegen-units=4 -Copt-level=0
+ 2| |
+ 3| |#![allow(dead_code)]
+ 4| |
+ 5| |mod foo {
+ 6| | #[inline(always)]
+ 7| 2| pub fn called() { }
+ 8| |
+ 9| 0| fn uncalled() { }
+ 10| |}
+ 11| |
+ 12| |pub mod bar {
+ 13| 1| pub fn call_me() {
+ 14| 1| super::foo::called();
+ 15| 1| }
+ 16| |}
+ 17| |
+ 18| |pub mod baz {
+ 19| 1| pub fn call_me() {
+ 20| 1| super::foo::called();
+ 21| 1| }
+ 22| |}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.issue-93054.txt b/src/test/run-make/coverage-reports/expected_show_coverage.issue-93054.txt
new file mode 100644
index 000000000..a1655aded
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.issue-93054.txt
@@ -0,0 +1,29 @@
+ 1| |// Regression test for #93054: Functions using uninhabited types often only have a single,
+ 2| |// unreachable basic block which doesn't get instrumented. This should not cause llvm-cov to fail.
+ 3| |// Since these kinds functions can't be invoked anyway, it's ok to not have coverage data for them.
+ 4| |
+ 5| |// compile-flags: --edition=2021
+ 6| |
+ 7| |enum Never { }
+ 8| |
+ 9| |impl Never {
+ 10| | fn foo(self) {
+ 11| | match self { }
+ 12| | make().map(|never| match never { });
+ 13| | }
+ 14| |
+ 15| | fn bar(&self) {
+ 16| | match *self { }
+ 17| | }
+ 18| |}
+ 19| |
+ 20| 0|async fn foo2(never: Never) {
+ 21| | match never { }
+ 22| |}
+ 23| |
+ 24| 0|fn make() -> Option<Never> {
+ 25| 0| None
+ 26| 0|}
+ 27| |
+ 28| 1|fn main() { }
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.lazy_boolean.txt b/src/test/run-make/coverage-reports/expected_show_coverage.lazy_boolean.txt
new file mode 100644
index 000000000..bd349df2f
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.lazy_boolean.txt
@@ -0,0 +1,64 @@
+ 1| |#![allow(unused_assignments, unused_variables)]
+ 2| |
+ 3| 1|fn main() {
+ 4| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ 5| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ 6| 1| // dependent conditions.
+ 7| 1| let is_true = std::env::args().len() == 1;
+ 8| 1|
+ 9| 1| let (mut a, mut b, mut c) = (0, 0, 0);
+ 10| 1| if is_true {
+ 11| 1| a = 1;
+ 12| 1| b = 10;
+ 13| 1| c = 100;
+ 14| 1| }
+ ^0
+ 15| | let
+ 16| 1| somebool
+ 17| | =
+ 18| 1| a < b
+ 19| | ||
+ 20| 0| b < c
+ 21| | ;
+ 22| | let
+ 23| 1| somebool
+ 24| | =
+ 25| 1| b < a
+ 26| | ||
+ 27| 1| b < c
+ 28| | ;
+ 29| 1| let somebool = a < b && b < c;
+ 30| 1| let somebool = b < a && b < c;
+ ^0
+ 31| |
+ 32| | if
+ 33| 1| !
+ 34| 1| is_true
+ 35| 0| {
+ 36| 0| a = 2
+ 37| 0| ;
+ 38| 1| }
+ 39| |
+ 40| | if
+ 41| 1| is_true
+ 42| 1| {
+ 43| 1| b = 30
+ 44| 1| ;
+ 45| 1| }
+ 46| | else
+ 47| 0| {
+ 48| 0| c = 400
+ 49| 0| ;
+ 50| 0| }
+ 51| |
+ 52| 1| if !is_true {
+ 53| 0| a = 2;
+ 54| 1| }
+ 55| |
+ 56| 1| if is_true {
+ 57| 1| b = 30;
+ 58| 1| } else {
+ 59| 0| c = 400;
+ 60| 0| }
+ 61| 1|}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.loop_break_value.txt b/src/test/run-make/coverage-reports/expected_show_coverage.loop_break_value.txt
new file mode 100644
index 000000000..022fe4c59
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.loop_break_value.txt
@@ -0,0 +1,14 @@
+ 1| |#![allow(unused_assignments, unused_variables)]
+ 2| |
+ 3| 1|fn main() {
+ 4| 1| let result
+ 5| 1| =
+ 6| 1| loop
+ 7| 1| {
+ 8| 1| break
+ 9| 1| 10
+ 10| 1| ;
+ 11| 1| }
+ 12| 1| ;
+ 13| 1|}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.loops_branches.txt b/src/test/run-make/coverage-reports/expected_show_coverage.loops_branches.txt
new file mode 100644
index 000000000..b7ad79a24
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.loops_branches.txt
@@ -0,0 +1,68 @@
+ 1| |#![allow(unused_assignments, unused_variables, while_true)]
+ 2| |
+ 3| |// This test confirms that (1) unexecuted infinite loops are handled correctly by the
+ 4| |// InstrumentCoverage MIR pass; and (2) Counter Expressions that subtract from zero can be dropped.
+ 5| |
+ 6| |struct DebugTest;
+ 7| |
+ 8| |impl std::fmt::Debug for DebugTest {
+ 9| 1| fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ 10| 1| if true {
+ 11| 1| if false {
+ 12| 0| while true {
+ 13| 0| }
+ 14| 1| }
+ 15| 1| write!(f, "cool")?;
+ ^0
+ 16| 0| } else {
+ 17| 0| }
+ 18| |
+ 19| 11| for i in 0..10 {
+ ^10
+ 20| 10| if true {
+ 21| 10| if false {
+ 22| 0| while true {}
+ 23| 10| }
+ 24| 10| write!(f, "cool")?;
+ ^0
+ 25| 0| } else {
+ 26| 0| }
+ 27| | }
+ 28| 1| Ok(())
+ 29| 1| }
+ 30| |}
+ 31| |
+ 32| |struct DisplayTest;
+ 33| |
+ 34| |impl std::fmt::Display for DisplayTest {
+ 35| 1| fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ 36| 1| if false {
+ 37| 0| } else {
+ 38| 1| if false {
+ 39| 0| while true {}
+ 40| 1| }
+ 41| 1| write!(f, "cool")?;
+ ^0
+ 42| | }
+ 43| 11| for i in 0..10 {
+ ^10
+ 44| 10| if false {
+ 45| 0| } else {
+ 46| 10| if false {
+ 47| 0| while true {}
+ 48| 10| }
+ 49| 10| write!(f, "cool")?;
+ ^0
+ 50| | }
+ 51| | }
+ 52| 1| Ok(())
+ 53| 1| }
+ 54| |}
+ 55| |
+ 56| 1|fn main() {
+ 57| 1| let debug_test = DebugTest;
+ 58| 1| println!("{:?}", debug_test);
+ 59| 1| let display_test = DisplayTest;
+ 60| 1| println!("{}", display_test);
+ 61| 1|}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.match_or_pattern.txt b/src/test/run-make/coverage-reports/expected_show_coverage.match_or_pattern.txt
new file mode 100644
index 000000000..a0fccb24f
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.match_or_pattern.txt
@@ -0,0 +1,50 @@
+ 1| |#![feature(or_patterns)]
+ 2| |
+ 3| 1|fn main() {
+ 4| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ 5| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ 6| 1| // dependent conditions.
+ 7| 1| let is_true = std::env::args().len() == 1;
+ 8| 1|
+ 9| 1| let mut a: u8 = 0;
+ 10| 1| let mut b: u8 = 0;
+ 11| 1| if is_true {
+ 12| 1| a = 2;
+ 13| 1| b = 0;
+ 14| 1| }
+ ^0
+ 15| 1| match (a, b) {
+ 16| | // Or patterns generate MIR `SwitchInt` with multiple targets to the same `BasicBlock`.
+ 17| | // This test confirms a fix for Issue #79569.
+ 18| 0| (0 | 1, 2 | 3) => {}
+ 19| 1| _ => {}
+ 20| | }
+ 21| 1| if is_true {
+ 22| 1| a = 0;
+ 23| 1| b = 0;
+ 24| 1| }
+ ^0
+ 25| 1| match (a, b) {
+ 26| 0| (0 | 1, 2 | 3) => {}
+ 27| 1| _ => {}
+ 28| | }
+ 29| 1| if is_true {
+ 30| 1| a = 2;
+ 31| 1| b = 2;
+ 32| 1| }
+ ^0
+ 33| 1| match (a, b) {
+ 34| 0| (0 | 1, 2 | 3) => {}
+ 35| 1| _ => {}
+ 36| | }
+ 37| 1| if is_true {
+ 38| 1| a = 0;
+ 39| 1| b = 2;
+ 40| 1| }
+ ^0
+ 41| 1| match (a, b) {
+ 42| 1| (0 | 1, 2 | 3) => {}
+ 43| 0| _ => {}
+ 44| | }
+ 45| 1|}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.nested_loops.txt b/src/test/run-make/coverage-reports/expected_show_coverage.nested_loops.txt
new file mode 100644
index 000000000..0dbd6bcf3
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.nested_loops.txt
@@ -0,0 +1,26 @@
+ 1| 1|fn main() {
+ 2| 1| let is_true = std::env::args().len() == 1;
+ 3| 1| let mut countdown = 10;
+ 4| |
+ 5| 1| 'outer: while countdown > 0 {
+ 6| 1| let mut a = 100;
+ 7| 1| let mut b = 100;
+ 8| 3| for _ in 0..50 {
+ 9| 3| if a < 30 {
+ 10| 0| break;
+ 11| 3| }
+ 12| 3| a -= 5;
+ 13| 3| b -= 5;
+ 14| 3| if b < 90 {
+ 15| 1| a -= 10;
+ 16| 1| if is_true {
+ 17| 1| break 'outer;
+ 18| 0| } else {
+ 19| 0| a -= 2;
+ 20| 0| }
+ 21| 2| }
+ 22| | }
+ 23| 0| countdown -= 1;
+ 24| | }
+ 25| 1|}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.no_cov_crate.txt b/src/test/run-make/coverage-reports/expected_show_coverage.no_cov_crate.txt
new file mode 100644
index 000000000..83a920413
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.no_cov_crate.txt
@@ -0,0 +1,87 @@
+ 1| |// Enables `no_coverage` on the entire crate
+ 2| |#![feature(no_coverage)]
+ 3| |
+ 4| |#[no_coverage]
+ 5| |fn do_not_add_coverage_1() {
+ 6| | println!("called but not covered");
+ 7| |}
+ 8| |
+ 9| |fn do_not_add_coverage_2() {
+ 10| | #![no_coverage]
+ 11| | println!("called but not covered");
+ 12| |}
+ 13| |
+ 14| |#[no_coverage]
+ 15| |fn do_not_add_coverage_not_called() {
+ 16| | println!("not called and not covered");
+ 17| |}
+ 18| |
+ 19| 1|fn add_coverage_1() {
+ 20| 1| println!("called and covered");
+ 21| 1|}
+ 22| |
+ 23| 1|fn add_coverage_2() {
+ 24| 1| println!("called and covered");
+ 25| 1|}
+ 26| |
+ 27| 0|fn add_coverage_not_called() {
+ 28| 0| println!("not called but covered");
+ 29| 0|}
+ 30| |
+ 31| |// FIXME: These test-cases illustrate confusing results of nested functions.
+ 32| |// See https://github.com/rust-lang/rust/issues/93319
+ 33| |mod nested_fns {
+ 34| | #[no_coverage]
+ 35| | pub fn outer_not_covered(is_true: bool) {
+ 36| 1| fn inner(is_true: bool) {
+ 37| 1| if is_true {
+ 38| 1| println!("called and covered");
+ 39| 1| } else {
+ 40| 0| println!("absolutely not covered");
+ 41| 0| }
+ 42| 1| }
+ 43| | println!("called but not covered");
+ 44| | inner(is_true);
+ 45| | }
+ 46| |
+ 47| 1| pub fn outer(is_true: bool) {
+ 48| 1| println!("called and covered");
+ 49| 1| inner_not_covered(is_true);
+ 50| 1|
+ 51| 1| #[no_coverage]
+ 52| 1| fn inner_not_covered(is_true: bool) {
+ 53| 1| if is_true {
+ 54| 1| println!("called but not covered");
+ 55| 1| } else {
+ 56| 1| println!("absolutely not covered");
+ 57| 1| }
+ 58| 1| }
+ 59| 1| }
+ 60| |
+ 61| 1| pub fn outer_both_covered(is_true: bool) {
+ 62| 1| println!("called and covered");
+ 63| 1| inner(is_true);
+ 64| 1|
+ 65| 1| fn inner(is_true: bool) {
+ 66| 1| if is_true {
+ 67| 1| println!("called and covered");
+ 68| 1| } else {
+ 69| 0| println!("absolutely not covered");
+ 70| 0| }
+ 71| 1| }
+ 72| 1| }
+ 73| |}
+ 74| |
+ 75| 1|fn main() {
+ 76| 1| let is_true = std::env::args().len() == 1;
+ 77| 1|
+ 78| 1| do_not_add_coverage_1();
+ 79| 1| do_not_add_coverage_2();
+ 80| 1| add_coverage_1();
+ 81| 1| add_coverage_2();
+ 82| 1|
+ 83| 1| nested_fns::outer_not_covered(is_true);
+ 84| 1| nested_fns::outer(is_true);
+ 85| 1| nested_fns::outer_both_covered(is_true);
+ 86| 1|}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.overflow.txt b/src/test/run-make/coverage-reports/expected_show_coverage.overflow.txt
new file mode 100644
index 000000000..25e822bff
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.overflow.txt
@@ -0,0 +1,64 @@
+ 1| |#![allow(unused_assignments)]
+ 2| |// expect-exit-status-101
+ 3| |
+ 4| 4|fn might_overflow(to_add: u32) -> u32 {
+ 5| 4| if to_add > 5 {
+ 6| 1| println!("this will probably overflow");
+ 7| 3| }
+ 8| 4| let add_to = u32::MAX - 5;
+ 9| 4| println!("does {} + {} overflow?", add_to, to_add);
+ 10| 4| let result = to_add + add_to;
+ 11| 4| println!("continuing after overflow check");
+ 12| 4| result
+ 13| 4|}
+ 14| |
+ 15| 1|fn main() -> Result<(),u8> {
+ 16| 1| let mut countdown = 10;
+ 17| 11| while countdown > 0 {
+ 18| 11| if countdown == 1 {
+ 19| 1| let result = might_overflow(10);
+ 20| 1| println!("Result: {}", result);
+ 21| 10| } else if countdown < 5 {
+ 22| 3| let result = might_overflow(1);
+ 23| 3| println!("Result: {}", result);
+ 24| 6| }
+ 25| 10| countdown -= 1;
+ 26| | }
+ 27| 0| Ok(())
+ 28| 0|}
+ 29| |
+ 30| |// Notes:
+ 31| |// 1. Compare this program and its coverage results to those of the very similar test `assert.rs`,
+ 32| |// and similar tests `panic_unwind.rs`, abort.rs` and `try_error_result.rs`.
+ 33| |// 2. This test confirms the coverage generated when a program passes or fails a
+ 34| |// compiler-generated `TerminatorKind::Assert` (based on an overflow check, in this case).
+ 35| |// 3. Similar to how the coverage instrumentation handles `TerminatorKind::Call`,
+ 36| |// compiler-generated assertion failures are assumed to be a symptom of a program bug, not
+ 37| |// expected behavior. To simplify the coverage graphs and keep instrumented programs as
+ 38| |// small and fast as possible, `Assert` terminators are assumed to always succeed, and
+ 39| |// therefore are considered "non-branching" terminators. So, an `Assert` terminator does not
+ 40| |// get its own coverage counter.
+ 41| |// 4. After an unhandled panic or failed Assert, coverage results may not always be intuitive.
+ 42| |// In this test, the final count for the statements after the `if` block in `might_overflow()`
+ 43| |// is 4, even though the lines after `to_add + add_to` were executed only 3 times. Depending
+ 44| |// on the MIR graph and the structure of the code, this count could have been 3 (which might
+ 45| |// have been valid for the overflowed add `+`, but should have been 4 for the lines before
+ 46| |// the overflow. The reason for this potential uncertainty is, a `CounterKind` is incremented
+ 47| |// via StatementKind::Counter at the end of the block, but (as in the case in this test),
+ 48| |// a CounterKind::Expression is always evaluated. In this case, the expression was based on
+ 49| |// a `Counter` incremented as part of the evaluation of the `if` expression, which was
+ 50| |// executed, and counted, 4 times, before reaching the overflow add.
+ 51| |
+ 52| |// If the program did not overflow, the coverage for `might_overflow()` would look like this:
+ 53| |//
+ 54| |// 4| |fn might_overflow(to_add: u32) -> u32 {
+ 55| |// 5| 4| if to_add > 5 {
+ 56| |// 6| 0| println!("this will probably overflow");
+ 57| |// 7| 4| }
+ 58| |// 8| 4| let add_to = u32::MAX - 5;
+ 59| |// 9| 4| println!("does {} + {} overflow?", add_to, to_add);
+ 60| |// 10| 4| let result = to_add + add_to;
+ 61| |// 11| 4| println!("continuing after overflow check");
+ 62| |// 12| 4| result
+ 63| |// 13| 4|}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.panic_unwind.txt b/src/test/run-make/coverage-reports/expected_show_coverage.panic_unwind.txt
new file mode 100644
index 000000000..114507dc9
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.panic_unwind.txt
@@ -0,0 +1,32 @@
+ 1| |#![allow(unused_assignments)]
+ 2| |// expect-exit-status-101
+ 3| |
+ 4| 4|fn might_panic(should_panic: bool) {
+ 5| 4| if should_panic {
+ 6| 1| println!("panicking...");
+ 7| 1| panic!("panics");
+ 8| 3| } else {
+ 9| 3| println!("Don't Panic");
+ 10| 3| }
+ 11| 3|}
+ 12| |
+ 13| 1|fn main() -> Result<(), u8> {
+ 14| 1| let mut countdown = 10;
+ 15| 11| while countdown > 0 {
+ 16| 11| if countdown == 1 {
+ 17| 1| might_panic(true);
+ 18| 10| } else if countdown < 5 {
+ 19| 3| might_panic(false);
+ 20| 6| }
+ 21| 10| countdown -= 1;
+ 22| | }
+ 23| 0| Ok(())
+ 24| 0|}
+ 25| |
+ 26| |// Notes:
+ 27| |// 1. Compare this program and its coverage results to those of the similar tests `abort.rs` and
+ 28| |// `try_error_result.rs`.
+ 29| |// 2. Since the `panic_unwind.rs` test is allowed to unwind, it is also allowed to execute the
+ 30| |// normal program exit cleanup, including writing out the current values of the coverage
+ 31| |// counters.
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.partial_eq.txt b/src/test/run-make/coverage-reports/expected_show_coverage.partial_eq.txt
new file mode 100644
index 000000000..fc2666533
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.partial_eq.txt
@@ -0,0 +1,53 @@
+ 1| |// This test confirms an earlier problem was resolved, supporting the MIR graph generated by the
+ 2| |// structure of this test.
+ 3| |
+ 4| 2|#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+ ^0 ^0 ^0 ^1 ^1 ^0^0
+ ------------------
+ | Unexecuted instantiation: <partial_eq::Version as core::cmp::PartialEq>::ne
+ ------------------
+ | Unexecuted instantiation: <partial_eq::Version as core::cmp::PartialEq>::eq
+ ------------------
+ 5| |pub struct Version {
+ 6| | major: usize,
+ 7| | minor: usize,
+ 8| | patch: usize,
+ 9| |}
+ 10| |
+ 11| |impl Version {
+ 12| 2| pub fn new(major: usize, minor: usize, patch: usize) -> Self {
+ 13| 2| Self {
+ 14| 2| major,
+ 15| 2| minor,
+ 16| 2| patch,
+ 17| 2| }
+ 18| 2| }
+ 19| |}
+ 20| |
+ 21| 1|fn main() {
+ 22| 1| let version_3_2_1 = Version::new(3, 2, 1);
+ 23| 1| let version_3_3_0 = Version::new(3, 3, 0);
+ 24| 1|
+ 25| 1| println!("{:?} < {:?} = {}", version_3_2_1, version_3_3_0, version_3_2_1 < version_3_3_0);
+ 26| 1|}
+ 27| |
+ 28| |/*
+ 29| |
+ 30| |This test verifies a bug was fixed that otherwise generated this error:
+ 31| |
+ 32| |thread 'rustc' panicked at 'No counters provided the source_hash for function:
+ 33| | Instance {
+ 34| | def: Item(WithOptConstParam {
+ 35| | did: DefId(0:101 ~ autocfg[c44a]::version::{impl#2}::partial_cmp),
+ 36| | const_param_did: None
+ 37| | }),
+ 38| | substs: []
+ 39| | }'
+ 40| |The `PartialOrd` derived by `Version` happened to generate a MIR that generated coverage
+ 41| |without a code region associated with any `Counter`. Code regions were associated with at least
+ 42| |one expression, which is allowed, but the `function_source_hash` was only passed to the codegen
+ 43| |(coverage mapgen) phase from a `Counter`s code region. A new method was added to pass the
+ 44| |`function_source_hash` without a code region, if necessary.
+ 45| |
+ 46| |*/
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.simple_loop.txt b/src/test/run-make/coverage-reports/expected_show_coverage.simple_loop.txt
new file mode 100644
index 000000000..feb83bad6
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.simple_loop.txt
@@ -0,0 +1,37 @@
+ 1| |#![allow(unused_assignments)]
+ 2| |
+ 3| 1|fn main() {
+ 4| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ 5| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ 6| 1| // dependent conditions.
+ 7| 1| let is_true = std::env::args().len() == 1;
+ 8| 1|
+ 9| 1| let mut countdown = 0;
+ 10| 1|
+ 11| 1| if
+ 12| 1| is_true
+ 13| 1| {
+ 14| 1| countdown
+ 15| 1| =
+ 16| 1| 10
+ 17| 1| ;
+ 18| 1| }
+ ^0
+ 19| |
+ 20| | loop
+ 21| | {
+ 22| | if
+ 23| 11| countdown
+ 24| 11| ==
+ 25| 11| 0
+ 26| | {
+ 27| 1| break
+ 28| | ;
+ 29| 10| }
+ 30| 10| countdown
+ 31| 10| -=
+ 32| 10| 1
+ 33| | ;
+ 34| | }
+ 35| 1|}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.simple_match.txt b/src/test/run-make/coverage-reports/expected_show_coverage.simple_match.txt
new file mode 100644
index 000000000..b92982131
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.simple_match.txt
@@ -0,0 +1,45 @@
+ 1| |#![allow(unused_assignments, unused_variables)]
+ 2| |
+ 3| 1|fn main() {
+ 4| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ 5| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ 6| 1| // dependent conditions.
+ 7| 1| let is_true = std::env::args().len() == 1;
+ 8| 1|
+ 9| 1| let mut countdown = 1;
+ 10| 1| if is_true {
+ 11| 1| countdown = 0;
+ 12| 1| }
+ ^0
+ 13| |
+ 14| | for
+ 15| | _
+ 16| | in
+ 17| 3| 0..2
+ 18| | {
+ 19| | let z
+ 20| | ;
+ 21| | match
+ 22| 2| countdown
+ 23| | {
+ 24| 1| x
+ 25| | if
+ 26| 2| x
+ 27| 2| <
+ 28| 2| 1
+ 29| | =>
+ 30| 1| {
+ 31| 1| z = countdown
+ 32| 1| ;
+ 33| 1| let y = countdown
+ 34| 1| ;
+ 35| 1| countdown = 10
+ 36| 1| ;
+ 37| 1| }
+ 38| | _
+ 39| | =>
+ 40| 1| {}
+ 41| | }
+ 42| | }
+ 43| 1|}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.tight_inf_loop.txt b/src/test/run-make/coverage-reports/expected_show_coverage.tight_inf_loop.txt
new file mode 100644
index 000000000..2d4c57f45
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.tight_inf_loop.txt
@@ -0,0 +1,6 @@
+ 1| 1|fn main() {
+ 2| 1| if false {
+ 3| 0| loop {}
+ 4| 1| }
+ 5| 1|}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.try_error_result.txt b/src/test/run-make/coverage-reports/expected_show_coverage.try_error_result.txt
new file mode 100644
index 000000000..0ad0180b7
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.try_error_result.txt
@@ -0,0 +1,125 @@
+ 1| |#![allow(unused_assignments)]
+ 2| |// expect-exit-status-1
+ 3| |
+ 4| 6|fn call(return_error: bool) -> Result<(),()> {
+ 5| 6| if return_error {
+ 6| 1| Err(())
+ 7| | } else {
+ 8| 5| Ok(())
+ 9| | }
+ 10| 6|}
+ 11| |
+ 12| 1|fn test1() -> Result<(),()> {
+ 13| 1| let mut
+ 14| 1| countdown = 10
+ 15| | ;
+ 16| | for
+ 17| | _
+ 18| | in
+ 19| 6| 0..10
+ 20| | {
+ 21| 6| countdown
+ 22| 6| -= 1
+ 23| 6| ;
+ 24| 6| if
+ 25| 6| countdown < 5
+ 26| | {
+ 27| 1| call(/*return_error=*/ true)?;
+ 28| 0| call(/*return_error=*/ false)?;
+ 29| | }
+ 30| | else
+ 31| | {
+ 32| 5| call(/*return_error=*/ false)?;
+ ^0
+ 33| | }
+ 34| | }
+ 35| 0| Ok(())
+ 36| 1|}
+ 37| |
+ 38| |struct Thing1;
+ 39| |impl Thing1 {
+ 40| 18| fn get_thing_2(&self, return_error: bool) -> Result<Thing2,()> {
+ 41| 18| if return_error {
+ 42| 1| Err(())
+ 43| | } else {
+ 44| 17| Ok(Thing2{})
+ 45| | }
+ 46| 18| }
+ 47| |}
+ 48| |
+ 49| |struct Thing2;
+ 50| |impl Thing2 {
+ 51| 17| fn call(&self, return_error: bool) -> Result<u32,()> {
+ 52| 17| if return_error {
+ 53| 2| Err(())
+ 54| | } else {
+ 55| 15| Ok(57)
+ 56| | }
+ 57| 17| }
+ 58| |}
+ 59| |
+ 60| 1|fn test2() -> Result<(),()> {
+ 61| 1| let thing1 = Thing1{};
+ 62| 1| let mut
+ 63| 1| countdown = 10
+ 64| | ;
+ 65| | for
+ 66| | _
+ 67| | in
+ 68| 6| 0..10
+ 69| | {
+ 70| 6| countdown
+ 71| 6| -= 1
+ 72| 6| ;
+ 73| 6| if
+ 74| 6| countdown < 5
+ 75| | {
+ 76| 1| thing1.get_thing_2(/*err=*/ false)?.call(/*err=*/ true).expect_err("call should fail");
+ ^0
+ 77| 1| thing1
+ 78| 1| .
+ 79| 1| get_thing_2(/*return_error=*/ false)
+ 80| 0| ?
+ 81| | .
+ 82| 1| call(/*return_error=*/ true)
+ 83| 1| .
+ 84| 1| expect_err(
+ 85| 1| "call should fail"
+ 86| 1| );
+ 87| 1| let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ true)?;
+ ^0 ^0 ^0
+ 88| 0| assert_eq!(val, 57);
+ 89| 0| let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ false)?;
+ 90| 0| assert_eq!(val, 57);
+ 91| | }
+ 92| | else
+ 93| | {
+ 94| 5| let val = thing1.get_thing_2(/*return_error=*/ false)?.call(/*return_error=*/ false)?;
+ ^0 ^0
+ 95| 5| assert_eq!(val, 57);
+ 96| 5| let val = thing1
+ 97| 5| .get_thing_2(/*return_error=*/ false)?
+ ^0
+ 98| 5| .call(/*return_error=*/ false)?;
+ ^0
+ 99| 5| assert_eq!(val, 57);
+ 100| 5| let val = thing1
+ 101| 5| .get_thing_2(/*return_error=*/ false)
+ 102| 0| ?
+ 103| 5| .call(/*return_error=*/ false)
+ 104| 0| ?
+ 105| | ;
+ 106| 5| assert_eq!(val, 57);
+ 107| | }
+ 108| | }
+ 109| 0| Ok(())
+ 110| 1|}
+ 111| |
+ 112| 1|fn main() -> Result<(),()> {
+ 113| 1| test1().expect_err("test1 should fail");
+ 114| 1| test2()
+ 115| 1| ?
+ 116| | ;
+ 117| 0| Ok(())
+ 118| 1|}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.unused.txt b/src/test/run-make/coverage-reports/expected_show_coverage.unused.txt
new file mode 100644
index 000000000..15fcf21c0
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.unused.txt
@@ -0,0 +1,62 @@
+ 1| 2|fn foo<T>(x: T) {
+ 2| 2| let mut i = 0;
+ 3| 22| while i < 10 {
+ 4| 20| i != 0 || i != 0;
+ ^2
+ 5| 20| i += 1;
+ 6| | }
+ 7| 2|}
+ ------------------
+ | unused::foo::<f32>:
+ | 1| 1|fn foo<T>(x: T) {
+ | 2| 1| let mut i = 0;
+ | 3| 11| while i < 10 {
+ | 4| 10| i != 0 || i != 0;
+ | ^1
+ | 5| 10| i += 1;
+ | 6| | }
+ | 7| 1|}
+ ------------------
+ | unused::foo::<u32>:
+ | 1| 1|fn foo<T>(x: T) {
+ | 2| 1| let mut i = 0;
+ | 3| 11| while i < 10 {
+ | 4| 10| i != 0 || i != 0;
+ | ^1
+ | 5| 10| i += 1;
+ | 6| | }
+ | 7| 1|}
+ ------------------
+ 8| |
+ 9| 0|fn unused_template_func<T>(x: T) {
+ 10| 0| let mut i = 0;
+ 11| 0| while i < 10 {
+ 12| 0| i != 0 || i != 0;
+ 13| 0| i += 1;
+ 14| | }
+ 15| 0|}
+ 16| |
+ 17| 0|fn unused_func(mut a: u32) {
+ 18| 0| if a != 0 {
+ 19| 0| a += 1;
+ 20| 0| }
+ 21| 0|}
+ 22| |
+ 23| 0|fn unused_func2(mut a: u32) {
+ 24| 0| if a != 0 {
+ 25| 0| a += 1;
+ 26| 0| }
+ 27| 0|}
+ 28| |
+ 29| 0|fn unused_func3(mut a: u32) {
+ 30| 0| if a != 0 {
+ 31| 0| a += 1;
+ 32| 0| }
+ 33| 0|}
+ 34| |
+ 35| 1|fn main() -> Result<(), u8> {
+ 36| 1| foo::<u32>(0);
+ 37| 1| foo::<f32>(0.0);
+ 38| 1| Ok(())
+ 39| 1|}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.unused_mod.txt b/src/test/run-make/coverage-reports/expected_show_coverage.unused_mod.txt
new file mode 100644
index 000000000..82d6fccc2
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.unused_mod.txt
@@ -0,0 +1,4 @@
+ 1| 0|pub fn never_called_function() {
+ 2| 0| println!("I am never called");
+ 3| 0|}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.uses_crate.txt b/src/test/run-make/coverage-reports/expected_show_coverage.uses_crate.txt
new file mode 100644
index 000000000..65eb1008d
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.uses_crate.txt
@@ -0,0 +1,148 @@
+ 1| |#![allow(unused_assignments, unused_variables)]
+ 2| |// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
+ 3| |use std::fmt::Debug;
+ 4| |
+ 5| 1|pub fn used_function() {
+ 6| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ 7| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ 8| 1| // dependent conditions.
+ 9| 1| let is_true = std::env::args().len() == 1;
+ 10| 1| let mut countdown = 0;
+ 11| 1| if is_true {
+ 12| 1| countdown = 10;
+ 13| 1| }
+ ^0
+ 14| 1| use_this_lib_crate();
+ 15| 1|}
+ 16| |
+ 17| 2|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
+ 18| 2| println!("used_only_from_bin_crate_generic_function with {:?}", arg);
+ 19| 2|}
+ ------------------
+ | used_crate::used_only_from_bin_crate_generic_function::<&str>:
+ | 17| 1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
+ | 18| 1| println!("used_only_from_bin_crate_generic_function with {:?}", arg);
+ | 19| 1|}
+ ------------------
+ | used_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec<i32>>:
+ | 17| 1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
+ | 18| 1| println!("used_only_from_bin_crate_generic_function with {:?}", arg);
+ | 19| 1|}
+ ------------------
+ | Unexecuted instantiation: used_crate::used_only_from_bin_crate_generic_function::<_>
+ ------------------
+ 20| |// Expect for above function: `Unexecuted instantiation` (see below)
+ 21| 2|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
+ 22| 2| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
+ 23| 2|}
+ ------------------
+ | used_crate::used_only_from_this_lib_crate_generic_function::<alloc::vec::Vec<i32>>:
+ | 21| 1|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
+ | 22| 1| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
+ | 23| 1|}
+ ------------------
+ | used_crate::used_only_from_this_lib_crate_generic_function::<&str>:
+ | 21| 1|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
+ | 22| 1| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
+ | 23| 1|}
+ ------------------
+ 24| |
+ 25| 2|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+ 26| 2| println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+ 27| 2|}
+ ------------------
+ | used_crate::used_from_bin_crate_and_lib_crate_generic_function::<alloc::vec::Vec<i32>>:
+ | 25| 1|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+ | 26| 1| println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+ | 27| 1|}
+ ------------------
+ | used_crate::used_from_bin_crate_and_lib_crate_generic_function::<&str>:
+ | 25| 1|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+ | 26| 1| println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+ | 27| 1|}
+ ------------------
+ 28| |
+ 29| 2|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+ 30| 2| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+ 31| 2|}
+ ------------------
+ | used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>:
+ | 29| 1|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+ | 30| 1| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+ | 31| 1|}
+ ------------------
+ | used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>:
+ | 29| 1|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+ | 30| 1| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+ | 31| 1|}
+ ------------------
+ 32| |
+ 33| 0|pub fn unused_generic_function<T: Debug>(arg: T) {
+ 34| 0| println!("unused_generic_function with {:?}", arg);
+ 35| 0|}
+ 36| |
+ 37| 0|pub fn unused_function() {
+ 38| 0| let is_true = std::env::args().len() == 1;
+ 39| 0| let mut countdown = 2;
+ 40| 0| if !is_true {
+ 41| 0| countdown = 20;
+ 42| 0| }
+ 43| 0|}
+ 44| |
+ 45| 0|fn unused_private_function() {
+ 46| 0| let is_true = std::env::args().len() == 1;
+ 47| 0| let mut countdown = 2;
+ 48| 0| if !is_true {
+ 49| 0| countdown = 20;
+ 50| 0| }
+ 51| 0|}
+ 52| |
+ 53| 1|fn use_this_lib_crate() {
+ 54| 1| used_from_bin_crate_and_lib_crate_generic_function("used from library used_crate.rs");
+ 55| 1| used_with_same_type_from_bin_crate_and_lib_crate_generic_function(
+ 56| 1| "used from library used_crate.rs",
+ 57| 1| );
+ 58| 1| let some_vec = vec![5, 6, 7, 8];
+ 59| 1| used_only_from_this_lib_crate_generic_function(some_vec);
+ 60| 1| used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs");
+ 61| 1|}
+ 62| |
+ 63| |// FIXME(#79651): "Unexecuted instantiation" errors appear in coverage results,
+ 64| |// for example:
+ 65| |//
+ 66| |// | Unexecuted instantiation: used_crate::used_only_from_bin_crate_generic_function::<_>
+ 67| |//
+ 68| |// These notices appear when `llvm-cov` shows instantiations. This may be a
+ 69| |// default option, but it can be suppressed with:
+ 70| |//
+ 71| |// ```shell
+ 72| |// $ `llvm-cov show --show-instantiations=0 ...`
+ 73| |// ```
+ 74| |//
+ 75| |// The notice is triggered because the function is unused by the library itself,
+ 76| |// and when the library is compiled, a synthetic function is generated, so
+ 77| |// unused function coverage can be reported. Coverage can be skipped for unused
+ 78| |// generic functions with:
+ 79| |//
+ 80| |// ```shell
+ 81| |// $ `rustc -Zunstable-options -C instrument-coverage=except-unused-generics ...`
+ 82| |// ```
+ 83| |//
+ 84| |// Even though this function is used by `uses_crate.rs` (and
+ 85| |// counted), with substitutions for `T`, those instantiations are only generated
+ 86| |// when the generic function is actually used (from the binary, not from this
+ 87| |// library crate). So the test result shows coverage for all instantiated
+ 88| |// versions and their generic type substitutions, plus the `Unexecuted
+ 89| |// instantiation` message for the non-substituted version. This is valid, but
+ 90| |// unfortunately a little confusing.
+ 91| |//
+ 92| |// The library crate has its own coverage map, and the only way to show unused
+ 93| |// coverage of a generic function is to include the generic function in the
+ 94| |// coverage map, marked as an "unused function". If the library were used by
+ 95| |// another binary that never used this generic function, then it would be valid
+ 96| |// to show the unused generic, with unknown substitution (`_`).
+ 97| |//
+ 98| |// The alternative is to exclude all generics from being included in the "unused
+ 99| |// functions" list, which would then omit coverage results for
+ 100| |// `unused_generic_function<T>()`, below.
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.uses_inline_crate.txt b/src/test/run-make/coverage-reports/expected_show_coverage.uses_inline_crate.txt
new file mode 100644
index 000000000..dab31cbf4
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.uses_inline_crate.txt
@@ -0,0 +1,139 @@
+ 1| |#![allow(unused_assignments, unused_variables)]
+ 2| |
+ 3| |// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
+ 4| |
+ 5| |use std::fmt::Debug;
+ 6| |
+ 7| 1|pub fn used_function() {
+ 8| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ 9| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ 10| 1| // dependent conditions.
+ 11| 1| let is_true = std::env::args().len() == 1;
+ 12| 1| let mut countdown = 0;
+ 13| 1| if is_true {
+ 14| 1| countdown = 10;
+ 15| 1| }
+ ^0
+ 16| 1| use_this_lib_crate();
+ 17| 1|}
+ 18| |
+ 19| |#[inline(always)]
+ 20| 1|pub fn used_inline_function() {
+ 21| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ 22| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ 23| 1| // dependent conditions.
+ 24| 1| let is_true = std::env::args().len() == 1;
+ 25| 1| let mut countdown = 0;
+ 26| 1| if is_true {
+ 27| 1| countdown = 10;
+ 28| 1| }
+ ^0
+ 29| 1| use_this_lib_crate();
+ 30| 1|}
+ 31| |
+ 32| |
+ 33| |
+ 34| |
+ 35| |
+ 36| |
+ 37| |
+ 38| |#[inline(always)]
+ 39| 2|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
+ 40| 2| println!("used_only_from_bin_crate_generic_function with {:?}", arg);
+ 41| 2|}
+ ------------------
+ | used_inline_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec<i32>>:
+ | 39| 1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
+ | 40| 1| println!("used_only_from_bin_crate_generic_function with {:?}", arg);
+ | 41| 1|}
+ ------------------
+ | used_inline_crate::used_only_from_bin_crate_generic_function::<&str>:
+ | 39| 1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
+ | 40| 1| println!("used_only_from_bin_crate_generic_function with {:?}", arg);
+ | 41| 1|}
+ ------------------
+ | Unexecuted instantiation: used_inline_crate::used_only_from_bin_crate_generic_function::<_>
+ ------------------
+ 42| |// Expect for above function: `Unexecuted instantiation` (see notes in `used_crate.rs`)
+ 43| |
+ 44| |#[inline(always)]
+ 45| 4|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
+ 46| 4| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
+ 47| 4|}
+ ------------------
+ | used_inline_crate::used_only_from_this_lib_crate_generic_function::<alloc::vec::Vec<i32>>:
+ | 45| 2|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
+ | 46| 2| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
+ | 47| 2|}
+ ------------------
+ | used_inline_crate::used_only_from_this_lib_crate_generic_function::<&str>:
+ | 45| 2|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
+ | 46| 2| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
+ | 47| 2|}
+ ------------------
+ 48| |
+ 49| |#[inline(always)]
+ 50| 3|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+ 51| 3| println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+ 52| 3|}
+ ------------------
+ | used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function::<alloc::vec::Vec<i32>>:
+ | 50| 1|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+ | 51| 1| println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+ | 52| 1|}
+ ------------------
+ | used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function::<&str>:
+ | 50| 2|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+ | 51| 2| println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+ | 52| 2|}
+ ------------------
+ 53| |
+ 54| |#[inline(always)]
+ 55| 3|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+ 56| 3| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+ 57| 3|}
+ ------------------
+ | used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>:
+ | 55| 1|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+ | 56| 1| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+ | 57| 1|}
+ ------------------
+ | used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>:
+ | 55| 2|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+ | 56| 2| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+ | 57| 2|}
+ ------------------
+ 58| |
+ 59| |#[inline(always)]
+ 60| 0|pub fn unused_generic_function<T: Debug>(arg: T) {
+ 61| 0| println!("unused_generic_function with {:?}", arg);
+ 62| 0|}
+ 63| |
+ 64| |#[inline(always)]
+ 65| 0|pub fn unused_function() {
+ 66| 0| let is_true = std::env::args().len() == 1;
+ 67| 0| let mut countdown = 2;
+ 68| 0| if !is_true {
+ 69| 0| countdown = 20;
+ 70| 0| }
+ 71| 0|}
+ 72| |
+ 73| |#[inline(always)]
+ 74| 0|fn unused_private_function() {
+ 75| 0| let is_true = std::env::args().len() == 1;
+ 76| 0| let mut countdown = 2;
+ 77| 0| if !is_true {
+ 78| 0| countdown = 20;
+ 79| 0| }
+ 80| 0|}
+ 81| |
+ 82| 2|fn use_this_lib_crate() {
+ 83| 2| used_from_bin_crate_and_lib_crate_generic_function("used from library used_crate.rs");
+ 84| 2| used_with_same_type_from_bin_crate_and_lib_crate_generic_function(
+ 85| 2| "used from library used_crate.rs",
+ 86| 2| );
+ 87| 2| let some_vec = vec![5, 6, 7, 8];
+ 88| 2| used_only_from_this_lib_crate_generic_function(some_vec);
+ 89| 2| used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs");
+ 90| 2|}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.while.txt b/src/test/run-make/coverage-reports/expected_show_coverage.while.txt
new file mode 100644
index 000000000..efa7d083f
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.while.txt
@@ -0,0 +1,6 @@
+ 1| 1|fn main() {
+ 2| 1| let num = 9;
+ 3| 1| while num >= 10 {
+ 4| 0| }
+ 5| 1|}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.while_early_ret.txt b/src/test/run-make/coverage-reports/expected_show_coverage.while_early_ret.txt
new file mode 100644
index 000000000..d19afc0de
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.while_early_ret.txt
@@ -0,0 +1,43 @@
+ 1| |#![allow(unused_assignments)]
+ 2| |// expect-exit-status-1
+ 3| |
+ 4| 1|fn main() -> Result<(),u8> {
+ 5| 1| let mut countdown = 10;
+ 6| | while
+ 7| 7| countdown
+ 8| 7| >
+ 9| 7| 0
+ 10| | {
+ 11| | if
+ 12| 7| countdown
+ 13| 7| <
+ 14| 7| 5
+ 15| | {
+ 16| | return
+ 17| | if
+ 18| 1| countdown
+ 19| 1| >
+ 20| 1| 8
+ 21| | {
+ 22| 0| Ok(())
+ 23| | }
+ 24| | else
+ 25| | {
+ 26| 1| Err(1)
+ 27| | }
+ 28| | ;
+ 29| 6| }
+ 30| 6| countdown
+ 31| 6| -=
+ 32| 6| 1
+ 33| | ;
+ 34| | }
+ 35| 0| Ok(())
+ 36| 1|}
+ 37| |
+ 38| |// ISSUE(77553): Originally, this test had `Err(1)` on line 22 (instead of `Ok(())`) and
+ 39| |// `std::process::exit(2)` on line 26 (instead of `Err(1)`); and this worked as expected on Linux
+ 40| |// and MacOS. But on Windows (MSVC, at least), the call to `std::process::exit()` exits the program
+ 41| |// without saving the InstrProf coverage counters. The use of `std::process:exit()` is not critical
+ 42| |// to the coverage test for early returns, but this is a limitation that should be fixed.
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.yield.txt b/src/test/run-make/coverage-reports/expected_show_coverage.yield.txt
new file mode 100644
index 000000000..60a8d943f
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.yield.txt
@@ -0,0 +1,38 @@
+ 1| |#![feature(generators, generator_trait)]
+ 2| |#![allow(unused_assignments)]
+ 3| |
+ 4| |use std::ops::{Generator, GeneratorState};
+ 5| |use std::pin::Pin;
+ 6| |
+ 7| 1|fn main() {
+ 8| 1| let mut generator = || {
+ 9| 1| yield 1;
+ 10| 1| return "foo"
+ 11| | };
+ 12| |
+ 13| 1| match Pin::new(&mut generator).resume(()) {
+ 14| 1| GeneratorState::Yielded(1) => {}
+ 15| 0| _ => panic!("unexpected value from resume"),
+ 16| | }
+ 17| 1| match Pin::new(&mut generator).resume(()) {
+ 18| 1| GeneratorState::Complete("foo") => {}
+ 19| 0| _ => panic!("unexpected value from resume"),
+ 20| | }
+ 21| |
+ 22| 1| let mut generator = || {
+ 23| 1| yield 1;
+ 24| 1| yield 2;
+ 25| 0| yield 3;
+ 26| 0| return "foo"
+ 27| | };
+ 28| |
+ 29| 1| match Pin::new(&mut generator).resume(()) {
+ 30| 1| GeneratorState::Yielded(1) => {}
+ 31| 0| _ => panic!("unexpected value from resume"),
+ 32| | }
+ 33| 1| match Pin::new(&mut generator).resume(()) {
+ 34| 1| GeneratorState::Yielded(2) => {}
+ 35| 0| _ => panic!("unexpected value from resume"),
+ 36| | }
+ 37| 1|}
+
diff --git a/src/test/run-make/coverage-reports/normalize_paths.py b/src/test/run-make/coverage-reports/normalize_paths.py
new file mode 100755
index 000000000..e5777ad25
--- /dev/null
+++ b/src/test/run-make/coverage-reports/normalize_paths.py
@@ -0,0 +1,12 @@
+#!/usr/bin/env python
+
+from __future__ import print_function
+
+import sys
+
+# Normalize file paths in output
+for line in sys.stdin:
+ if line.startswith("..") and line.rstrip().endswith(".rs:"):
+ print(line.replace("\\", "/"), end='')
+ else:
+ print(line, end='')
diff --git a/src/test/run-make/coverage/WARNING_KEEP_NAMES_SHORT.txt b/src/test/run-make/coverage/WARNING_KEEP_NAMES_SHORT.txt
new file mode 100644
index 000000000..6a1403b8a
--- /dev/null
+++ b/src/test/run-make/coverage/WARNING_KEEP_NAMES_SHORT.txt
@@ -0,0 +1,10 @@
+IMPORTANT: The Rust test programs in this directory generate various output
+files in the `../coverage*` directories (`expected` and `actual` files).
+
+Microsoft Windows has a relatively short limit on file paths (not individual
+path components, but the entire path). The files generated by these
+`../coverage*` tests typically have file paths that include the program
+source file name plus function and type names (depending on the program).
+
+Keep the test file names short, and keep function names and other symbols
+short as well, to avoid hitting the Windows limits.
diff --git a/src/test/run-make/coverage/abort.rs b/src/test/run-make/coverage/abort.rs
new file mode 100644
index 000000000..3dac43df8
--- /dev/null
+++ b/src/test/run-make/coverage/abort.rs
@@ -0,0 +1,66 @@
+#![feature(c_unwind)]
+#![allow(unused_assignments)]
+
+extern "C" fn might_abort(should_abort: bool) {
+ if should_abort {
+ println!("aborting...");
+ panic!("panics and aborts");
+ } else {
+ println!("Don't Panic");
+ }
+}
+
+fn main() -> Result<(), u8> {
+ let mut countdown = 10;
+ while countdown > 0 {
+ if countdown < 5 {
+ might_abort(false);
+ }
+ // See discussion (below the `Notes` section) on coverage results for the closing brace.
+ if countdown < 5 { might_abort(false); } // Counts for different regions on one line.
+ // For the following example, the closing brace is the last character on the line.
+ // This shows the character after the closing brace is highlighted, even if that next
+ // character is a newline.
+ if countdown < 5 { might_abort(false); }
+ countdown -= 1;
+ }
+ Ok(())
+}
+
+// Notes:
+// 1. Compare this program and its coverage results to those of the similar tests
+// `panic_unwind.rs` and `try_error_result.rs`.
+// 2. This test confirms the coverage generated when a program includes `TerminatorKind::Abort`.
+// 3. The test does not invoke the abort. By executing to a successful completion, the coverage
+// results show where the program did and did not execute.
+// 4. If the program actually aborted, the coverage counters would not be saved (which "works as
+// intended"). Coverage results would show no executed coverage regions.
+// 6. If `should_abort` is `true` and the program aborts, the program exits with a `132` status
+// (on Linux at least).
+
+/*
+
+Expect the following coverage results:
+
+```text
+ 16| 11| while countdown > 0 {
+ 17| 10| if countdown < 5 {
+ 18| 4| might_abort(false);
+ 19| 6| }
+```
+
+This is actually correct.
+
+The condition `countdown < 5` executed 10 times (10 loop iterations).
+
+It evaluated to `true` 4 times, and executed the `might_abort()` call.
+
+It skipped the body of the `might_abort()` call 6 times. If an `if` does not include an explicit
+`else`, the coverage implementation injects a counter, at the character immediately after the `if`s
+closing brace, to count the "implicit" `else`. This is the only way to capture the coverage of the
+non-true condition.
+
+As another example of why this is important, say the condition was `countdown < 50`, which is always
+`true`. In that case, we wouldn't have a test for what happens if `might_abort()` is not called.
+The closing brace would have a count of `0`, highlighting the missed coverage.
+*/
diff --git a/src/test/run-make/coverage/assert.rs b/src/test/run-make/coverage/assert.rs
new file mode 100644
index 000000000..c85f2748e
--- /dev/null
+++ b/src/test/run-make/coverage/assert.rs
@@ -0,0 +1,32 @@
+#![allow(unused_assignments)]
+// expect-exit-status-101
+
+fn might_fail_assert(one_plus_one: u32) {
+ println!("does 1 + 1 = {}?", one_plus_one);
+ assert_eq!(1 + 1, one_plus_one, "the argument was wrong");
+}
+
+fn main() -> Result<(),u8> {
+ let mut countdown = 10;
+ while countdown > 0 {
+ if countdown == 1 {
+ might_fail_assert(3);
+ } else if countdown < 5 {
+ might_fail_assert(2);
+ }
+ countdown -= 1;
+ }
+ Ok(())
+}
+
+// Notes:
+// 1. Compare this program and its coverage results to those of the very similar test
+// `panic_unwind.rs`, and similar tests `abort.rs` and `try_error_result.rs`.
+// 2. This test confirms the coverage generated when a program passes or fails an `assert!()` or
+// related `assert_*!()` macro.
+// 3. Notably, the `assert` macros *do not* generate `TerminatorKind::Assert`. The macros produce
+// conditional expressions, `TerminatorKind::SwitchInt` branches, and a possible call to
+// `begin_panic_fmt()` (that begins a panic unwind, if the assertion test fails).
+// 4. `TerminatoKind::Assert` is, however, also present in the MIR generated for this test
+// (and in many other coverage tests). The `Assert` terminator is typically generated by the
+// Rust compiler to check for runtime failures, such as numeric overflows.
diff --git a/src/test/run-make/coverage/async.rs b/src/test/run-make/coverage/async.rs
new file mode 100644
index 000000000..a6e387747
--- /dev/null
+++ b/src/test/run-make/coverage/async.rs
@@ -0,0 +1,128 @@
+#![allow(unused_assignments, dead_code)]
+
+// compile-flags: --edition=2018 -C opt-level=1
+
+async fn c(x: u8) -> u8 {
+ if x == 8 {
+ 1
+ } else {
+ 0
+ }
+}
+
+async fn d() -> u8 { 1 }
+
+async fn e() -> u8 { 1 } // unused function; executor does not block on `g()`
+
+async fn f() -> u8 { 1 }
+
+async fn foo() -> [bool; 10] { [false; 10] } // unused function; executor does not block on `h()`
+
+pub async fn g(x: u8) {
+ match x {
+ y if e().await == y => (),
+ y if f().await == y => (),
+ _ => (),
+ }
+}
+
+async fn h(x: usize) { // The function signature is counted when called, but the body is not
+ // executed (not awaited) so the open brace has a `0` count (at least when
+ // displayed with `llvm-cov show` in color-mode).
+ match x {
+ y if foo().await[y] => (),
+ _ => (),
+ }
+}
+
+async fn i(x: u8) { // line coverage is 1, but there are 2 regions:
+ // (a) the function signature, counted when the function is called; and
+ // (b) the open brace for the function body, counted once when the body is
+ // executed asynchronously.
+ match x {
+ y if c(x).await == y + 1 => { d().await; }
+ y if f().await == y + 1 => (),
+ _ => (),
+ }
+}
+
+fn j(x: u8) {
+ // non-async versions of `c()`, `d()`, and `f()` to make it similar to async `i()`.
+ fn c(x: u8) -> u8 {
+ if x == 8 {
+ 1 // This line appears covered, but the 1-character expression span covering the `1`
+ // is not executed. (`llvm-cov show` displays a `^0` below the `1` ). This is because
+ // `fn j()` executes the open brace for the funciton body, followed by the function's
+ // first executable statement, `match x`. Inner function declarations are not
+ // "visible" to the MIR for `j()`, so the code region counts all lines between the
+ // open brace and the first statement as executed, which is, in a sense, true.
+ // `llvm-cov show` overcomes this kind of situation by showing the actual counts
+ // of the enclosed coverages, (that is, the `1` expression was not executed, and
+ // accurately displays a `0`).
+ } else {
+ 0
+ }
+ }
+ fn d() -> u8 { 1 } // inner function is defined in-line, but the function is not executed
+ fn f() -> u8 { 1 }
+ match x {
+ y if c(x) == y + 1 => { d(); }
+ y if f() == y + 1 => (),
+ _ => (),
+ }
+}
+
+fn k(x: u8) { // unused function
+ match x {
+ 1 => (),
+ 2 => (),
+ _ => (),
+ }
+}
+
+fn l(x: u8) {
+ match x {
+ 1 => (),
+ 2 => (),
+ _ => (),
+ }
+}
+
+async fn m(x: u8) -> u8 { x - 1 }
+
+fn main() {
+ let _ = g(10);
+ let _ = h(9);
+ let mut future = Box::pin(i(8));
+ j(7);
+ l(6);
+ let _ = m(5);
+ executor::block_on(future.as_mut());
+}
+
+mod executor {
+ use core::{
+ future::Future,
+ pin::Pin,
+ task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
+ };
+
+ pub fn block_on<F: Future>(mut future: F) -> F::Output {
+ let mut future = unsafe { Pin::new_unchecked(&mut future) };
+ use std::hint::unreachable_unchecked;
+ static VTABLE: RawWakerVTable = RawWakerVTable::new(
+ |_| unsafe { unreachable_unchecked() }, // clone
+ |_| unsafe { unreachable_unchecked() }, // wake
+ |_| unsafe { unreachable_unchecked() }, // wake_by_ref
+ |_| (),
+ );
+ let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
+ let mut context = Context::from_waker(&waker);
+
+ loop {
+ if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+ break val;
+ }
+ }
+ }
+}
diff --git a/src/test/run-make/coverage/async2.rs b/src/test/run-make/coverage/async2.rs
new file mode 100644
index 000000000..959d48ce9
--- /dev/null
+++ b/src/test/run-make/coverage/async2.rs
@@ -0,0 +1,69 @@
+// compile-flags: --edition=2018
+
+use core::{
+ future::Future,
+ marker::Send,
+ pin::Pin,
+};
+
+fn non_async_func() {
+ println!("non_async_func was covered");
+ let b = true;
+ if b {
+ println!("non_async_func println in block");
+ }
+}
+
+
+
+
+async fn async_func() {
+ println!("async_func was covered");
+ let b = true;
+ if b {
+ println!("async_func println in block");
+ }
+}
+
+
+
+
+async fn async_func_just_println() {
+ println!("async_func_just_println was covered");
+}
+
+fn main() {
+ println!("codecovsample::main");
+
+ non_async_func();
+
+ executor::block_on(async_func());
+ executor::block_on(async_func_just_println());
+}
+
+mod executor {
+ use core::{
+ future::Future,
+ pin::Pin,
+ task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
+ };
+
+ pub fn block_on<F: Future>(mut future: F) -> F::Output {
+ let mut future = unsafe { Pin::new_unchecked(&mut future) };
+ use std::hint::unreachable_unchecked;
+ static VTABLE: RawWakerVTable = RawWakerVTable::new(
+ |_| unsafe { unreachable_unchecked() }, // clone
+ |_| unsafe { unreachable_unchecked() }, // wake
+ |_| unsafe { unreachable_unchecked() }, // wake_by_ref
+ |_| (),
+ );
+ let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
+ let mut context = Context::from_waker(&waker);
+
+ loop {
+ if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+ break val;
+ }
+ }
+ }
+}
diff --git a/src/test/run-make/coverage/closure.rs b/src/test/run-make/coverage/closure.rs
new file mode 100644
index 000000000..32ec0bcdf
--- /dev/null
+++ b/src/test/run-make/coverage/closure.rs
@@ -0,0 +1,215 @@
+#![allow(unused_assignments, unused_variables)]
+// compile-flags: -C opt-level=2 # fix described in rustc_middle/mir/mono.rs
+fn main() {
+ // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ // dependent conditions.
+ let is_true = std::env::args().len() == 1;
+ let is_false = ! is_true;
+
+ let mut some_string = Some(String::from("the string content"));
+ println!(
+ "The string or alt: {}"
+ ,
+ some_string
+ .
+ unwrap_or_else
+ (
+ ||
+ {
+ let mut countdown = 0;
+ if is_false {
+ countdown = 10;
+ }
+ "alt string 1".to_owned()
+ }
+ )
+ );
+
+ some_string = Some(String::from("the string content"));
+ let
+ a
+ =
+ ||
+ {
+ let mut countdown = 0;
+ if is_false {
+ countdown = 10;
+ }
+ "alt string 2".to_owned()
+ };
+ println!(
+ "The string or alt: {}"
+ ,
+ some_string
+ .
+ unwrap_or_else
+ (
+ a
+ )
+ );
+
+ some_string = None;
+ println!(
+ "The string or alt: {}"
+ ,
+ some_string
+ .
+ unwrap_or_else
+ (
+ ||
+ {
+ let mut countdown = 0;
+ if is_false {
+ countdown = 10;
+ }
+ "alt string 3".to_owned()
+ }
+ )
+ );
+
+ some_string = None;
+ let
+ a
+ =
+ ||
+ {
+ let mut countdown = 0;
+ if is_false {
+ countdown = 10;
+ }
+ "alt string 4".to_owned()
+ };
+ println!(
+ "The string or alt: {}"
+ ,
+ some_string
+ .
+ unwrap_or_else
+ (
+ a
+ )
+ );
+
+ let
+ quote_closure
+ =
+ |val|
+ {
+ let mut countdown = 0;
+ if is_false {
+ countdown = 10;
+ }
+ format!("'{}'", val)
+ };
+ println!(
+ "Repeated, quoted string: {:?}"
+ ,
+ std::iter::repeat("repeat me")
+ .take(5)
+ .map
+ (
+ quote_closure
+ )
+ .collect::<Vec<_>>()
+ );
+
+ let
+ _unused_closure
+ =
+ |
+ mut countdown
+ |
+ {
+ if is_false {
+ countdown = 10;
+ }
+ "closure should be unused".to_owned()
+ };
+
+ let mut countdown = 10;
+ let _short_unused_closure = | _unused_arg: u8 | countdown += 1;
+
+
+ let short_used_covered_closure_macro = | used_arg: u8 | println!("called");
+ let short_used_not_covered_closure_macro = | used_arg: u8 | println!("not called");
+ let _short_unused_closure_macro = | _unused_arg: u8 | println!("not called");
+
+
+
+
+ let _short_unused_closure_block = | _unused_arg: u8 | { println!("not called") };
+
+ let _shortish_unused_closure = | _unused_arg: u8 | {
+ println!("not called")
+ };
+
+ let _as_short_unused_closure = |
+ _unused_arg: u8
+ | { println!("not called") };
+
+ let _almost_as_short_unused_closure = |
+ _unused_arg: u8
+ | { println!("not called") }
+ ;
+
+
+
+
+
+ let _short_unused_closure_line_break_no_block = | _unused_arg: u8 |
+println!("not called")
+ ;
+
+ let _short_unused_closure_line_break_no_block2 =
+ | _unused_arg: u8 |
+ println!(
+ "not called"
+ )
+ ;
+
+ let short_used_not_covered_closure_line_break_no_block_embedded_branch =
+ | _unused_arg: u8 |
+ println!(
+ "not called: {}",
+ if is_true { "check" } else { "me" }
+ )
+ ;
+
+ let short_used_not_covered_closure_line_break_block_embedded_branch =
+ | _unused_arg: u8 |
+ {
+ println!(
+ "not called: {}",
+ if is_true { "check" } else { "me" }
+ )
+ }
+ ;
+
+ let short_used_covered_closure_line_break_no_block_embedded_branch =
+ | _unused_arg: u8 |
+ println!(
+ "not called: {}",
+ if is_true { "check" } else { "me" }
+ )
+ ;
+
+ let short_used_covered_closure_line_break_block_embedded_branch =
+ | _unused_arg: u8 |
+ {
+ println!(
+ "not called: {}",
+ if is_true { "check" } else { "me" }
+ )
+ }
+ ;
+
+ if is_false {
+ short_used_not_covered_closure_macro(0);
+ short_used_not_covered_closure_line_break_no_block_embedded_branch(0);
+ short_used_not_covered_closure_line_break_block_embedded_branch(0);
+ }
+ short_used_covered_closure_macro(0);
+ short_used_covered_closure_line_break_no_block_embedded_branch(0);
+ short_used_covered_closure_line_break_block_embedded_branch(0);
+}
diff --git a/src/test/run-make/coverage/closure_macro.rs b/src/test/run-make/coverage/closure_macro.rs
new file mode 100644
index 000000000..5e3b00d1e
--- /dev/null
+++ b/src/test/run-make/coverage/closure_macro.rs
@@ -0,0 +1,40 @@
+// compile-flags: --edition=2018
+#![feature(no_coverage)]
+
+macro_rules! bail {
+ ($msg:literal $(,)?) => {
+ if $msg.len() > 0 {
+ println!("no msg");
+ } else {
+ println!($msg);
+ }
+ return Err(String::from($msg));
+ };
+}
+
+macro_rules! on_error {
+ ($value:expr, $error_message:expr) => {
+ $value.or_else(|e| { // FIXME(85000): no coverage in closure macros
+ let message = format!($error_message, e);
+ if message.len() > 0 {
+ println!("{}", message);
+ Ok(String::from("ok"))
+ } else {
+ bail!("error");
+ }
+ })
+ };
+}
+
+fn load_configuration_files() -> Result<String, String> {
+ Ok(String::from("config"))
+}
+
+pub fn main() -> Result<(), String> {
+ println!("Starting service");
+ let config = on_error!(load_configuration_files(), "Error loading configs: {}")?;
+
+ let startup_delay_duration = String::from("arg");
+ let _ = (config, startup_delay_duration);
+ Ok(())
+}
diff --git a/src/test/run-make/coverage/closure_macro_async.rs b/src/test/run-make/coverage/closure_macro_async.rs
new file mode 100644
index 000000000..e3e89e9c8
--- /dev/null
+++ b/src/test/run-make/coverage/closure_macro_async.rs
@@ -0,0 +1,81 @@
+// compile-flags: --edition=2018
+#![feature(no_coverage)]
+
+macro_rules! bail {
+ ($msg:literal $(,)?) => {
+ if $msg.len() > 0 {
+ println!("no msg");
+ } else {
+ println!($msg);
+ }
+ return Err(String::from($msg));
+ };
+}
+
+macro_rules! on_error {
+ ($value:expr, $error_message:expr) => {
+ $value.or_else(|e| { // FIXME(85000): no coverage in closure macros
+ let message = format!($error_message, e);
+ if message.len() > 0 {
+ println!("{}", message);
+ Ok(String::from("ok"))
+ } else {
+ bail!("error");
+ }
+ })
+ };
+}
+
+fn load_configuration_files() -> Result<String, String> {
+ Ok(String::from("config"))
+}
+
+pub async fn test() -> Result<(), String> {
+ println!("Starting service");
+ let config = on_error!(load_configuration_files(), "Error loading configs: {}")?;
+
+ let startup_delay_duration = String::from("arg");
+ let _ = (config, startup_delay_duration);
+ Ok(())
+}
+
+#[no_coverage]
+fn main() {
+ executor::block_on(test());
+}
+
+mod executor {
+ use core::{
+ future::Future,
+ pin::Pin,
+ task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
+ };
+
+ #[no_coverage]
+ pub fn block_on<F: Future>(mut future: F) -> F::Output {
+ let mut future = unsafe { Pin::new_unchecked(&mut future) };
+ use std::hint::unreachable_unchecked;
+ static VTABLE: RawWakerVTable = RawWakerVTable::new(
+
+ #[no_coverage]
+ |_| unsafe { unreachable_unchecked() }, // clone
+
+ #[no_coverage]
+ |_| unsafe { unreachable_unchecked() }, // wake
+
+ #[no_coverage]
+ |_| unsafe { unreachable_unchecked() }, // wake_by_ref
+
+ #[no_coverage]
+ |_| (),
+ );
+ let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
+ let mut context = Context::from_waker(&waker);
+
+ loop {
+ if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+ break val;
+ }
+ }
+ }
+}
diff --git a/src/test/run-make/coverage/compiletest-ignore-dir b/src/test/run-make/coverage/compiletest-ignore-dir
new file mode 100644
index 000000000..b533b272d
--- /dev/null
+++ b/src/test/run-make/coverage/compiletest-ignore-dir
@@ -0,0 +1,3 @@
+# Directory "coverage" supports the tests at prefix ../coverage-*
+
+# Use ./x.py [options] test src/test/run-make/coverage to run all related tests.
diff --git a/src/test/run-make/coverage/conditions.rs b/src/test/run-make/coverage/conditions.rs
new file mode 100644
index 000000000..057599d1b
--- /dev/null
+++ b/src/test/run-make/coverage/conditions.rs
@@ -0,0 +1,87 @@
+#![allow(unused_assignments, unused_variables)]
+
+fn main() {
+ let mut countdown = 0;
+ if true {
+ countdown = 10;
+ }
+
+ const B: u32 = 100;
+ let x = if countdown > 7 {
+ countdown -= 4;
+ B
+ } else if countdown > 2 {
+ if countdown < 1 || countdown > 5 || countdown != 9 {
+ countdown = 0;
+ }
+ countdown -= 5;
+ countdown
+ } else {
+ return;
+ };
+
+ let mut countdown = 0;
+ if true {
+ countdown = 10;
+ }
+
+ if countdown > 7 {
+ countdown -= 4;
+ } else if countdown > 2 {
+ if countdown < 1 || countdown > 5 || countdown != 9 {
+ countdown = 0;
+ }
+ countdown -= 5;
+ } else {
+ return;
+ }
+
+ if true {
+ let mut countdown = 0;
+ if true {
+ countdown = 10;
+ }
+
+ if countdown > 7 {
+ countdown -= 4;
+ }
+ else if countdown > 2 {
+ if countdown < 1 || countdown > 5 || countdown != 9 {
+ countdown = 0;
+ }
+ countdown -= 5;
+ } else {
+ return;
+ }
+ }
+
+
+ let mut countdown = 0;
+ if true {
+ countdown = 1;
+ }
+
+ let z = if countdown > 7 {
+ countdown -= 4;
+ } else if countdown > 2 {
+ if countdown < 1 || countdown > 5 || countdown != 9 {
+ countdown = 0;
+ }
+ countdown -= 5;
+ } else {
+ let should_be_reachable = countdown;
+ println!("reached");
+ return;
+ };
+
+ let w = if countdown > 7 {
+ countdown -= 4;
+ } else if countdown > 2 {
+ if countdown < 1 || countdown > 5 || countdown != 9 {
+ countdown = 0;
+ }
+ countdown -= 5;
+ } else {
+ return;
+ };
+}
diff --git a/src/test/run-make/coverage/continue.rs b/src/test/run-make/coverage/continue.rs
new file mode 100644
index 000000000..624aa9834
--- /dev/null
+++ b/src/test/run-make/coverage/continue.rs
@@ -0,0 +1,69 @@
+#![allow(unused_assignments, unused_variables)]
+
+fn main() {
+ let is_true = std::env::args().len() == 1;
+
+ let mut x = 0;
+ for _ in 0..10 {
+ match is_true {
+ true => {
+ continue;
+ }
+ _ => {
+ x = 1;
+ }
+ }
+ x = 3;
+ }
+ for _ in 0..10 {
+ match is_true {
+ false => {
+ x = 1;
+ }
+ _ => {
+ continue;
+ }
+ }
+ x = 3;
+ }
+ for _ in 0..10 {
+ match is_true {
+ true => {
+ x = 1;
+ }
+ _ => {
+ continue;
+ }
+ }
+ x = 3;
+ }
+ for _ in 0..10 {
+ if is_true {
+ continue;
+ }
+ x = 3;
+ }
+ for _ in 0..10 {
+ match is_true {
+ false => {
+ x = 1;
+ }
+ _ => {
+ let _ = x;
+ }
+ }
+ x = 3;
+ }
+ for _ in 0..10 {
+ match is_true {
+ false => {
+ x = 1;
+ }
+ _ => {
+ break;
+ }
+ }
+ x = 3;
+ }
+ let _ = x;
+}
diff --git a/src/test/run-make/coverage/coverage_tools.mk b/src/test/run-make/coverage/coverage_tools.mk
new file mode 100644
index 000000000..0b6bbc331
--- /dev/null
+++ b/src/test/run-make/coverage/coverage_tools.mk
@@ -0,0 +1,6 @@
+# Common Makefile include for Rust `run-make/coverage-* tests. Include this
+# file with the line:
+#
+# include ../coverage/coverage_tools.mk
+
+include ../../run-make-fulldeps/tools.mk
diff --git a/src/test/run-make/coverage/dead_code.rs b/src/test/run-make/coverage/dead_code.rs
new file mode 100644
index 000000000..a1285df0e
--- /dev/null
+++ b/src/test/run-make/coverage/dead_code.rs
@@ -0,0 +1,37 @@
+#![allow(unused_assignments, unused_variables)]
+
+pub fn unused_pub_fn_not_in_library() {
+ // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ // dependent conditions.
+ let is_true = std::env::args().len() == 1;
+
+ let mut countdown = 0;
+ if is_true {
+ countdown = 10;
+ }
+}
+
+fn unused_fn() {
+ // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ // dependent conditions.
+ let is_true = std::env::args().len() == 1;
+
+ let mut countdown = 0;
+ if is_true {
+ countdown = 10;
+ }
+}
+
+fn main() {
+ // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ // dependent conditions.
+ let is_true = std::env::args().len() == 1;
+
+ let mut countdown = 0;
+ if is_true {
+ countdown = 10;
+ }
+}
diff --git a/src/test/run-make/coverage/doctest.rs b/src/test/run-make/coverage/doctest.rs
new file mode 100644
index 000000000..ec04ea570
--- /dev/null
+++ b/src/test/run-make/coverage/doctest.rs
@@ -0,0 +1,99 @@
+//! This test ensures that code from doctests is properly re-mapped.
+//! See <https://github.com/rust-lang/rust/issues/79417> for more info.
+//!
+//! Just some random code:
+//! ```
+//! if true {
+//! // this is executed!
+//! assert_eq!(1, 1);
+//! } else {
+//! // this is not!
+//! assert_eq!(1, 2);
+//! }
+//! ```
+//!
+//! doctest testing external code:
+//! ```
+//! extern crate doctest_crate;
+//! doctest_crate::fn_run_in_doctests(1);
+//! ```
+//!
+//! doctest returning a result:
+//! ```
+//! #[derive(Debug, PartialEq)]
+//! struct SomeError {
+//! msg: String,
+//! }
+//! let mut res = Err(SomeError { msg: String::from("a message") });
+//! if res.is_ok() {
+//! res?;
+//! } else {
+//! if *res.as_ref().unwrap_err() == *res.as_ref().unwrap_err() {
+//! println!("{:?}", res);
+//! }
+//! if *res.as_ref().unwrap_err() == *res.as_ref().unwrap_err() {
+//! res = Ok(1);
+//! }
+//! res = Ok(0);
+//! }
+//! // need to be explicit because rustdoc cant infer the return type
+//! Ok::<(), SomeError>(())
+//! ```
+//!
+//! doctest with custom main:
+//! ```
+//! fn some_func() {
+//! println!("called some_func()");
+//! }
+//!
+//! #[derive(Debug)]
+//! struct SomeError;
+//!
+//! extern crate doctest_crate;
+//!
+//! fn doctest_main() -> Result<(), SomeError> {
+//! some_func();
+//! doctest_crate::fn_run_in_doctests(2);
+//! Ok(())
+//! }
+//!
+//! // this `main` is not shown as covered, as it clashes with all the other
+//! // `main` functions that were automatically generated for doctests
+//! fn main() -> Result<(), SomeError> {
+//! doctest_main()
+//! }
+//! ```
+
+/// doctest attached to fn testing external code:
+/// ```
+/// extern crate doctest_crate;
+/// doctest_crate::fn_run_in_doctests(3);
+/// ```
+///
+fn main() {
+ if true {
+ assert_eq!(1, 1);
+ } else {
+ assert_eq!(1, 2);
+ }
+}
+
+// FIXME(Swatinem): Fix known issue that coverage code region columns need to be offset by the
+// doc comment line prefix (`///` or `//!`) and any additional indent (before or after the doc
+// comment characters). This test produces `llvm-cov show` results demonstrating the problem.
+//
+// One of the above tests now includes: `derive(Debug, PartialEq)`, producing an `llvm-cov show`
+// result with a distinct count for `Debug`, denoted by `^1`, but the caret points to the wrong
+// column. Similarly, the `if` blocks without `else` blocks show `^0`, which should point at, or
+// one character past, the `if` block's closing brace. In both cases, these are most likely off
+// by the number of characters stripped from the beginning of each doc comment line: indent
+// whitespace, if any, doc comment prefix (`//!` in this case) and (I assume) one space character
+// (?). Note, when viewing `llvm-cov show` results in `--color` mode, the column offset errors are
+// more pronounced, and show up in more places, with background color used to show some distinct
+// code regions with different coverage counts.
+//
+// NOTE: Since the doc comment line prefix may vary, one possible solution is to replace each
+// character stripped from the beginning of doc comment lines with a space. This will give coverage
+// results the correct column offsets, and I think it should compile correctly, but I don't know
+// what affect it might have on diagnostic messages from the compiler, and whether anyone would care
+// if the indentation changed. I don't know if there is a more viable solution.
diff --git a/src/test/run-make/coverage/drop_trait.rs b/src/test/run-make/coverage/drop_trait.rs
new file mode 100644
index 000000000..d15bfc0f8
--- /dev/null
+++ b/src/test/run-make/coverage/drop_trait.rs
@@ -0,0 +1,33 @@
+#![allow(unused_assignments)]
+// expect-exit-status-1
+
+struct Firework {
+ strength: i32,
+}
+
+impl Drop for Firework {
+ fn drop(&mut self) {
+ println!("BOOM times {}!!!", self.strength);
+ }
+}
+
+fn main() -> Result<(),u8> {
+ let _firecracker = Firework { strength: 1 };
+
+ let _tnt = Firework { strength: 100 };
+
+ if true {
+ println!("Exiting with error...");
+ return Err(1);
+ }
+
+ let _ = Firework { strength: 1000 };
+
+ Ok(())
+}
+
+// Expected program output:
+// Exiting with error...
+// BOOM times 100!!!
+// BOOM times 1!!!
+// Error: 1
diff --git a/src/test/run-make/coverage/generator.rs b/src/test/run-make/coverage/generator.rs
new file mode 100644
index 000000000..431999102
--- /dev/null
+++ b/src/test/run-make/coverage/generator.rs
@@ -0,0 +1,30 @@
+#![feature(generators, generator_trait)]
+
+use std::ops::{Generator, GeneratorState};
+use std::pin::Pin;
+
+// The following implementation of a function called from a `yield` statement
+// (apparently requiring the Result and the `String` type or constructor)
+// creates conditions where the `generator::StateTransform` MIR transform will
+// drop all `Counter` `Coverage` statements from a MIR. `simplify.rs` has logic
+// to handle this condition, and still report dead block coverage.
+fn get_u32(val: bool) -> Result<u32, String> {
+ if val { Ok(1) } else { Err(String::from("some error")) }
+}
+
+fn main() {
+ let is_true = std::env::args().len() == 1;
+ let mut generator = || {
+ yield get_u32(is_true);
+ return "foo";
+ };
+
+ match Pin::new(&mut generator).resume(()) {
+ GeneratorState::Yielded(Ok(1)) => {}
+ _ => panic!("unexpected return from resume"),
+ }
+ match Pin::new(&mut generator).resume(()) {
+ GeneratorState::Complete("foo") => {}
+ _ => panic!("unexpected return from resume"),
+ }
+}
diff --git a/src/test/run-make/coverage/generics.rs b/src/test/run-make/coverage/generics.rs
new file mode 100644
index 000000000..18b388684
--- /dev/null
+++ b/src/test/run-make/coverage/generics.rs
@@ -0,0 +1,48 @@
+#![allow(unused_assignments)]
+// expect-exit-status-1
+
+struct Firework<T> where T: Copy + std::fmt::Display {
+ strength: T,
+}
+
+impl<T> Firework<T> where T: Copy + std::fmt::Display {
+ #[inline(always)]
+ fn set_strength(&mut self, new_strength: T) {
+ self.strength = new_strength;
+ }
+}
+
+impl<T> Drop for Firework<T> where T: Copy + std::fmt::Display {
+ #[inline(always)]
+ fn drop(&mut self) {
+ println!("BOOM times {}!!!", self.strength);
+ }
+}
+
+fn main() -> Result<(),u8> {
+ let mut firecracker = Firework { strength: 1 };
+ firecracker.set_strength(2);
+
+ let mut tnt = Firework { strength: 100.1 };
+ tnt.set_strength(200.1);
+ tnt.set_strength(300.3);
+
+ if true {
+ println!("Exiting with error...");
+ return Err(1);
+ }
+
+
+
+
+
+ let _ = Firework { strength: 1000 };
+
+ Ok(())
+}
+
+// Expected program output:
+// Exiting with error...
+// BOOM times 100!!!
+// BOOM times 1!!!
+// Error: 1
diff --git a/src/test/run-make/coverage/if.rs b/src/test/run-make/coverage/if.rs
new file mode 100644
index 000000000..8ad5042ff
--- /dev/null
+++ b/src/test/run-make/coverage/if.rs
@@ -0,0 +1,28 @@
+#![allow(unused_assignments, unused_variables)]
+
+fn main() {
+ // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ // dependent conditions.
+ let
+ is_true
+ =
+ std::env::args().len()
+ ==
+ 1
+ ;
+ let
+ mut
+ countdown
+ =
+ 0
+ ;
+ if
+ is_true
+ {
+ countdown
+ =
+ 10
+ ;
+ }
+}
diff --git a/src/test/run-make/coverage/if_else.rs b/src/test/run-make/coverage/if_else.rs
new file mode 100644
index 000000000..3244e1e3a
--- /dev/null
+++ b/src/test/run-make/coverage/if_else.rs
@@ -0,0 +1,40 @@
+#![allow(unused_assignments, unused_variables)]
+
+fn main() {
+ // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ // dependent conditions.
+ let is_true = std::env::args().len() == 1;
+
+ let mut countdown = 0;
+ if
+ is_true
+ {
+ countdown
+ =
+ 10
+ ;
+ }
+ else // Note coverage region difference without semicolon
+ {
+ countdown
+ =
+ 100
+ }
+
+ if
+ is_true
+ {
+ countdown
+ =
+ 10
+ ;
+ }
+ else
+ {
+ countdown
+ =
+ 100
+ ;
+ }
+}
diff --git a/src/test/run-make/coverage/inline-dead.rs b/src/test/run-make/coverage/inline-dead.rs
new file mode 100644
index 000000000..854fa0629
--- /dev/null
+++ b/src/test/run-make/coverage/inline-dead.rs
@@ -0,0 +1,27 @@
+// Regression test for issue #98833.
+// compile-flags: -Zinline-mir -Cdebug-assertions=off
+
+fn main() {
+ println!("{}", live::<false>());
+
+ let f = |x: bool| {
+ debug_assert!(
+ x
+ );
+ };
+ f(false);
+}
+
+#[inline]
+fn live<const B: bool>() -> u32 {
+ if B {
+ dead()
+ } else {
+ 0
+ }
+}
+
+#[inline]
+fn dead() -> u32 {
+ 42
+}
diff --git a/src/test/run-make/coverage/inline.rs b/src/test/run-make/coverage/inline.rs
new file mode 100644
index 000000000..9cfab9ddb
--- /dev/null
+++ b/src/test/run-make/coverage/inline.rs
@@ -0,0 +1,51 @@
+// compile-flags: -Zinline-mir
+
+use std::fmt::Display;
+
+fn main() {
+ permutations(&['a', 'b', 'c']);
+}
+
+#[inline(always)]
+fn permutations<T: Copy + Display>(xs: &[T]) {
+ let mut ys = xs.to_owned();
+ permutate(&mut ys, 0);
+}
+
+fn permutate<T: Copy + Display>(xs: &mut [T], k: usize) {
+ let n = length(xs);
+ if k == n {
+ display(xs);
+ } else if k < n {
+ for i in k..n {
+ swap(xs, i, k);
+ permutate(xs, k + 1);
+ swap(xs, i, k);
+ }
+ } else {
+ error();
+ }
+}
+
+fn length<T>(xs: &[T]) -> usize {
+ xs.len()
+}
+
+#[inline]
+fn swap<T: Copy>(xs: &mut [T], i: usize, j: usize) {
+ let t = xs[i];
+ xs[i] = xs[j];
+ xs[j] = t;
+}
+
+fn display<T: Display>(xs: &[T]) {
+ for x in xs {
+ print!("{}", x);
+ }
+ println!();
+}
+
+#[inline(always)]
+fn error() {
+ panic!("error");
+}
diff --git a/src/test/run-make/coverage/inner_items.rs b/src/test/run-make/coverage/inner_items.rs
new file mode 100644
index 000000000..bcb62b303
--- /dev/null
+++ b/src/test/run-make/coverage/inner_items.rs
@@ -0,0 +1,57 @@
+#![allow(unused_assignments, unused_variables, dead_code)]
+
+fn main() {
+ // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ // dependent conditions.
+ let is_true = std::env::args().len() == 1;
+
+ let mut countdown = 0;
+ if is_true {
+ countdown = 10;
+ }
+
+ mod in_mod {
+ const IN_MOD_CONST: u32 = 1000;
+ }
+
+ fn in_func(a: u32) {
+ let b = 1;
+ let c = a + b;
+ println!("c = {}", c)
+ }
+
+ struct InStruct {
+ in_struct_field: u32,
+ }
+
+ const IN_CONST: u32 = 1234;
+
+ trait InTrait {
+ fn trait_func(&mut self, incr: u32);
+
+ fn default_trait_func(&mut self) {
+ in_func(IN_CONST);
+ self.trait_func(IN_CONST);
+ }
+ }
+
+ impl InTrait for InStruct {
+ fn trait_func(&mut self, incr: u32) {
+ self.in_struct_field += incr;
+ in_func(self.in_struct_field);
+ }
+ }
+
+ type InType = String;
+
+ if is_true {
+ in_func(countdown);
+ }
+
+ let mut val = InStruct {
+ in_struct_field: 101,
+ };
+
+ val.default_trait_func();
+}
diff --git a/src/test/run-make/coverage/issue-83601.rs b/src/test/run-make/coverage/issue-83601.rs
new file mode 100644
index 000000000..0b72a8194
--- /dev/null
+++ b/src/test/run-make/coverage/issue-83601.rs
@@ -0,0 +1,14 @@
+// Shows that rust-lang/rust/83601 is resolved
+
+#[derive(Debug, PartialEq, Eq)]
+struct Foo(u32);
+
+fn main() {
+ let bar = Foo(1);
+ assert_eq!(bar, Foo(1));
+ let baz = Foo(0);
+ assert_ne!(baz, Foo(1));
+ println!("{:?}", Foo(1));
+ println!("{:?}", bar);
+ println!("{:?}", baz);
+}
diff --git a/src/test/run-make/coverage/issue-84561.rs b/src/test/run-make/coverage/issue-84561.rs
new file mode 100644
index 000000000..b39a289c4
--- /dev/null
+++ b/src/test/run-make/coverage/issue-84561.rs
@@ -0,0 +1,182 @@
+// This demonstrated Issue #84561: function-like macros produce unintuitive coverage results.
+
+// expect-exit-status-101
+#[derive(PartialEq, Eq)]
+struct Foo(u32);
+fn test3() {
+ let is_true = std::env::args().len() == 1;
+ let bar = Foo(1);
+ assert_eq!(bar, Foo(1));
+ let baz = Foo(0);
+ assert_ne!(baz, Foo(1));
+ println!("{:?}", Foo(1));
+ println!("{:?}", bar);
+ println!("{:?}", baz);
+
+ assert_eq!(Foo(1), Foo(1));
+ assert_ne!(Foo(0), Foo(1));
+ assert_eq!(Foo(2), Foo(2));
+ let bar = Foo(0);
+ assert_ne!(bar, Foo(3));
+ assert_ne!(Foo(0), Foo(4));
+ assert_eq!(Foo(3), Foo(3), "with a message");
+ println!("{:?}", bar);
+ println!("{:?}", Foo(1));
+
+ assert_ne!(Foo(0), Foo(5), "{}", if is_true { "true message" } else { "false message" });
+ assert_ne!(
+ Foo(0)
+ ,
+ Foo(5)
+ ,
+ "{}"
+ ,
+ if
+ is_true
+ {
+ "true message"
+ } else {
+ "false message"
+ }
+ );
+
+ let is_true = std::env::args().len() == 1;
+
+ assert_eq!(
+ Foo(1),
+ Foo(1)
+ );
+ assert_ne!(
+ Foo(0),
+ Foo(1)
+ );
+ assert_eq!(
+ Foo(2),
+ Foo(2)
+ );
+ let bar = Foo(1);
+ assert_ne!(
+ bar,
+ Foo(3)
+ );
+ if is_true {
+ assert_ne!(
+ Foo(0),
+ Foo(4)
+ );
+ } else {
+ assert_eq!(
+ Foo(3),
+ Foo(3)
+ );
+ }
+ if is_true {
+ assert_ne!(
+ Foo(0),
+ Foo(4),
+ "with a message"
+ );
+ } else {
+ assert_eq!(
+ Foo(3),
+ Foo(3),
+ "with a message"
+ );
+ }
+ assert_ne!(
+ if is_true {
+ Foo(0)
+ } else {
+ Foo(1)
+ },
+ Foo(5)
+ );
+ assert_ne!(
+ Foo(5),
+ if is_true {
+ Foo(0)
+ } else {
+ Foo(1)
+ }
+ );
+ assert_ne!(
+ if is_true {
+ assert_eq!(
+ Foo(3),
+ Foo(3)
+ );
+ Foo(0)
+ } else {
+ assert_ne!(
+ if is_true {
+ Foo(0)
+ } else {
+ Foo(1)
+ },
+ Foo(5)
+ );
+ Foo(1)
+ },
+ Foo(5),
+ "with a message"
+ );
+ assert_eq!(
+ Foo(1),
+ Foo(3),
+ "this assert should fail"
+ );
+ assert_eq!(
+ Foo(3),
+ Foo(3),
+ "this assert should not be reached"
+ );
+}
+
+impl std::fmt::Debug for Foo {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ write!(f, "try and succeed")?;
+ Ok(())
+ }
+}
+
+static mut DEBUG_LEVEL_ENABLED: bool = false;
+
+macro_rules! debug {
+ ($($arg:tt)+) => (
+ if unsafe { DEBUG_LEVEL_ENABLED } {
+ println!($($arg)+);
+ }
+ );
+}
+
+fn test1() {
+ debug!("debug is enabled");
+ debug!("debug is enabled");
+ let _ = 0;
+ debug!("debug is enabled");
+ unsafe {
+ DEBUG_LEVEL_ENABLED = true;
+ }
+ debug!("debug is enabled");
+}
+
+macro_rules! call_debug {
+ ($($arg:tt)+) => (
+ fn call_print(s: &str) {
+ print!("{}", s);
+ }
+
+ call_print("called from call_debug: ");
+ debug!($($arg)+);
+ );
+}
+
+fn test2() {
+ call_debug!("debug is enabled");
+}
+
+fn main() {
+ test1();
+ test2();
+ test3();
+}
diff --git a/src/test/run-make/coverage/issue-85461.rs b/src/test/run-make/coverage/issue-85461.rs
new file mode 100644
index 000000000..a1b9ebb1e
--- /dev/null
+++ b/src/test/run-make/coverage/issue-85461.rs
@@ -0,0 +1,10 @@
+// Regression test for #85461: MSVC sometimes fail to link with dead code and #[inline(always)]
+
+extern crate inline_always_with_dead_code;
+
+use inline_always_with_dead_code::{bar, baz};
+
+fn main() {
+ bar::call_me();
+ baz::call_me();
+}
diff --git a/src/test/run-make/coverage/issue-93054.rs b/src/test/run-make/coverage/issue-93054.rs
new file mode 100644
index 000000000..c160b3db0
--- /dev/null
+++ b/src/test/run-make/coverage/issue-93054.rs
@@ -0,0 +1,28 @@
+// Regression test for #93054: Functions using uninhabited types often only have a single,
+// unreachable basic block which doesn't get instrumented. This should not cause llvm-cov to fail.
+// Since these kinds functions can't be invoked anyway, it's ok to not have coverage data for them.
+
+// compile-flags: --edition=2021
+
+enum Never { }
+
+impl Never {
+ fn foo(self) {
+ match self { }
+ make().map(|never| match never { });
+ }
+
+ fn bar(&self) {
+ match *self { }
+ }
+}
+
+async fn foo2(never: Never) {
+ match never { }
+}
+
+fn make() -> Option<Never> {
+ None
+}
+
+fn main() { }
diff --git a/src/test/run-make/coverage/lazy_boolean.rs b/src/test/run-make/coverage/lazy_boolean.rs
new file mode 100644
index 000000000..bb6219e85
--- /dev/null
+++ b/src/test/run-make/coverage/lazy_boolean.rs
@@ -0,0 +1,61 @@
+#![allow(unused_assignments, unused_variables)]
+
+fn main() {
+ // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ // dependent conditions.
+ let is_true = std::env::args().len() == 1;
+
+ let (mut a, mut b, mut c) = (0, 0, 0);
+ if is_true {
+ a = 1;
+ b = 10;
+ c = 100;
+ }
+ let
+ somebool
+ =
+ a < b
+ ||
+ b < c
+ ;
+ let
+ somebool
+ =
+ b < a
+ ||
+ b < c
+ ;
+ let somebool = a < b && b < c;
+ let somebool = b < a && b < c;
+
+ if
+ !
+ is_true
+ {
+ a = 2
+ ;
+ }
+
+ if
+ is_true
+ {
+ b = 30
+ ;
+ }
+ else
+ {
+ c = 400
+ ;
+ }
+
+ if !is_true {
+ a = 2;
+ }
+
+ if is_true {
+ b = 30;
+ } else {
+ c = 400;
+ }
+}
diff --git a/src/test/run-make/coverage/lib/doctest_crate.rs b/src/test/run-make/coverage/lib/doctest_crate.rs
new file mode 100644
index 000000000..c3210146d
--- /dev/null
+++ b/src/test/run-make/coverage/lib/doctest_crate.rs
@@ -0,0 +1,9 @@
+/// A function run only from within doctests
+pub fn fn_run_in_doctests(conditional: usize) {
+ match conditional {
+ 1 => assert_eq!(1, 1), // this is run,
+ 2 => assert_eq!(1, 1), // this,
+ 3 => assert_eq!(1, 1), // and this too
+ _ => assert_eq!(1, 2), // however this is not
+ }
+}
diff --git a/src/test/run-make/coverage/lib/inline_always_with_dead_code.rs b/src/test/run-make/coverage/lib/inline_always_with_dead_code.rs
new file mode 100644
index 000000000..2b21dee6c
--- /dev/null
+++ b/src/test/run-make/coverage/lib/inline_always_with_dead_code.rs
@@ -0,0 +1,22 @@
+// compile-flags: -Cinstrument-coverage -Ccodegen-units=4 -Copt-level=0
+
+#![allow(dead_code)]
+
+mod foo {
+ #[inline(always)]
+ pub fn called() { }
+
+ fn uncalled() { }
+}
+
+pub mod bar {
+ pub fn call_me() {
+ super::foo::called();
+ }
+}
+
+pub mod baz {
+ pub fn call_me() {
+ super::foo::called();
+ }
+}
diff --git a/src/test/run-make/coverage/lib/unused_mod_helper.rs b/src/test/run-make/coverage/lib/unused_mod_helper.rs
new file mode 100644
index 000000000..ae1cc1531
--- /dev/null
+++ b/src/test/run-make/coverage/lib/unused_mod_helper.rs
@@ -0,0 +1,3 @@
+pub fn never_called_function() {
+ println!("I am never called");
+}
diff --git a/src/test/run-make/coverage/lib/used_crate.rs b/src/test/run-make/coverage/lib/used_crate.rs
new file mode 100644
index 000000000..8b8b1f7f3
--- /dev/null
+++ b/src/test/run-make/coverage/lib/used_crate.rs
@@ -0,0 +1,100 @@
+#![allow(unused_assignments, unused_variables)]
+// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
+use std::fmt::Debug;
+
+pub fn used_function() {
+ // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ // dependent conditions.
+ let is_true = std::env::args().len() == 1;
+ let mut countdown = 0;
+ if is_true {
+ countdown = 10;
+ }
+ use_this_lib_crate();
+}
+
+pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
+ println!("used_only_from_bin_crate_generic_function with {:?}", arg);
+}
+// Expect for above function: `Unexecuted instantiation` (see below)
+pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
+ println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
+}
+
+pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+ println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+}
+
+pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+ println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+}
+
+pub fn unused_generic_function<T: Debug>(arg: T) {
+ println!("unused_generic_function with {:?}", arg);
+}
+
+pub fn unused_function() {
+ let is_true = std::env::args().len() == 1;
+ let mut countdown = 2;
+ if !is_true {
+ countdown = 20;
+ }
+}
+
+fn unused_private_function() {
+ let is_true = std::env::args().len() == 1;
+ let mut countdown = 2;
+ if !is_true {
+ countdown = 20;
+ }
+}
+
+fn use_this_lib_crate() {
+ used_from_bin_crate_and_lib_crate_generic_function("used from library used_crate.rs");
+ used_with_same_type_from_bin_crate_and_lib_crate_generic_function(
+ "used from library used_crate.rs",
+ );
+ let some_vec = vec![5, 6, 7, 8];
+ used_only_from_this_lib_crate_generic_function(some_vec);
+ used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs");
+}
+
+// FIXME(#79651): "Unexecuted instantiation" errors appear in coverage results,
+// for example:
+//
+// | Unexecuted instantiation: used_crate::used_only_from_bin_crate_generic_function::<_>
+//
+// These notices appear when `llvm-cov` shows instantiations. This may be a
+// default option, but it can be suppressed with:
+//
+// ```shell
+// $ `llvm-cov show --show-instantiations=0 ...`
+// ```
+//
+// The notice is triggered because the function is unused by the library itself,
+// and when the library is compiled, a synthetic function is generated, so
+// unused function coverage can be reported. Coverage can be skipped for unused
+// generic functions with:
+//
+// ```shell
+// $ `rustc -Zunstable-options -C instrument-coverage=except-unused-generics ...`
+// ```
+//
+// Even though this function is used by `uses_crate.rs` (and
+// counted), with substitutions for `T`, those instantiations are only generated
+// when the generic function is actually used (from the binary, not from this
+// library crate). So the test result shows coverage for all instantiated
+// versions and their generic type substitutions, plus the `Unexecuted
+// instantiation` message for the non-substituted version. This is valid, but
+// unfortunately a little confusing.
+//
+// The library crate has its own coverage map, and the only way to show unused
+// coverage of a generic function is to include the generic function in the
+// coverage map, marked as an "unused function". If the library were used by
+// another binary that never used this generic function, then it would be valid
+// to show the unused generic, with unknown substitution (`_`).
+//
+// The alternative is to exclude all generics from being included in the "unused
+// functions" list, which would then omit coverage results for
+// `unused_generic_function<T>()`, below.
diff --git a/src/test/run-make/coverage/lib/used_inline_crate.rs b/src/test/run-make/coverage/lib/used_inline_crate.rs
new file mode 100644
index 000000000..4a052756d
--- /dev/null
+++ b/src/test/run-make/coverage/lib/used_inline_crate.rs
@@ -0,0 +1,90 @@
+#![allow(unused_assignments, unused_variables)]
+
+// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
+
+use std::fmt::Debug;
+
+pub fn used_function() {
+ // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ // dependent conditions.
+ let is_true = std::env::args().len() == 1;
+ let mut countdown = 0;
+ if is_true {
+ countdown = 10;
+ }
+ use_this_lib_crate();
+}
+
+#[inline(always)]
+pub fn used_inline_function() {
+ // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ // dependent conditions.
+ let is_true = std::env::args().len() == 1;
+ let mut countdown = 0;
+ if is_true {
+ countdown = 10;
+ }
+ use_this_lib_crate();
+}
+
+
+
+
+
+
+
+#[inline(always)]
+pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
+ println!("used_only_from_bin_crate_generic_function with {:?}", arg);
+}
+// Expect for above function: `Unexecuted instantiation` (see notes in `used_crate.rs`)
+
+#[inline(always)]
+pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
+ println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
+}
+
+#[inline(always)]
+pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+ println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+}
+
+#[inline(always)]
+pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+ println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+}
+
+#[inline(always)]
+pub fn unused_generic_function<T: Debug>(arg: T) {
+ println!("unused_generic_function with {:?}", arg);
+}
+
+#[inline(always)]
+pub fn unused_function() {
+ let is_true = std::env::args().len() == 1;
+ let mut countdown = 2;
+ if !is_true {
+ countdown = 20;
+ }
+}
+
+#[inline(always)]
+fn unused_private_function() {
+ let is_true = std::env::args().len() == 1;
+ let mut countdown = 2;
+ if !is_true {
+ countdown = 20;
+ }
+}
+
+fn use_this_lib_crate() {
+ used_from_bin_crate_and_lib_crate_generic_function("used from library used_crate.rs");
+ used_with_same_type_from_bin_crate_and_lib_crate_generic_function(
+ "used from library used_crate.rs",
+ );
+ let some_vec = vec![5, 6, 7, 8];
+ used_only_from_this_lib_crate_generic_function(some_vec);
+ used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs");
+}
diff --git a/src/test/run-make/coverage/loop_break_value.rs b/src/test/run-make/coverage/loop_break_value.rs
new file mode 100644
index 000000000..dbc4fad7a
--- /dev/null
+++ b/src/test/run-make/coverage/loop_break_value.rs
@@ -0,0 +1,13 @@
+#![allow(unused_assignments, unused_variables)]
+
+fn main() {
+ let result
+ =
+ loop
+ {
+ break
+ 10
+ ;
+ }
+ ;
+}
diff --git a/src/test/run-make/coverage/loops_branches.rs b/src/test/run-make/coverage/loops_branches.rs
new file mode 100644
index 000000000..7116ce47f
--- /dev/null
+++ b/src/test/run-make/coverage/loops_branches.rs
@@ -0,0 +1,61 @@
+#![allow(unused_assignments, unused_variables, while_true)]
+
+// This test confirms that (1) unexecuted infinite loops are handled correctly by the
+// InstrumentCoverage MIR pass; and (2) Counter Expressions that subtract from zero can be dropped.
+
+struct DebugTest;
+
+impl std::fmt::Debug for DebugTest {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ if true {
+ if false {
+ while true {
+ }
+ }
+ write!(f, "cool")?;
+ } else {
+ }
+
+ for i in 0..10 {
+ if true {
+ if false {
+ while true {}
+ }
+ write!(f, "cool")?;
+ } else {
+ }
+ }
+ Ok(())
+ }
+}
+
+struct DisplayTest;
+
+impl std::fmt::Display for DisplayTest {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ if false {
+ } else {
+ if false {
+ while true {}
+ }
+ write!(f, "cool")?;
+ }
+ for i in 0..10 {
+ if false {
+ } else {
+ if false {
+ while true {}
+ }
+ write!(f, "cool")?;
+ }
+ }
+ Ok(())
+ }
+}
+
+fn main() {
+ let debug_test = DebugTest;
+ println!("{:?}", debug_test);
+ let display_test = DisplayTest;
+ println!("{}", display_test);
+}
diff --git a/src/test/run-make/coverage/match_or_pattern.rs b/src/test/run-make/coverage/match_or_pattern.rs
new file mode 100644
index 000000000..4c6a8a9b7
--- /dev/null
+++ b/src/test/run-make/coverage/match_or_pattern.rs
@@ -0,0 +1,45 @@
+#![feature(or_patterns)]
+
+fn main() {
+ // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ // dependent conditions.
+ let is_true = std::env::args().len() == 1;
+
+ let mut a: u8 = 0;
+ let mut b: u8 = 0;
+ if is_true {
+ a = 2;
+ b = 0;
+ }
+ match (a, b) {
+ // Or patterns generate MIR `SwitchInt` with multiple targets to the same `BasicBlock`.
+ // This test confirms a fix for Issue #79569.
+ (0 | 1, 2 | 3) => {}
+ _ => {}
+ }
+ if is_true {
+ a = 0;
+ b = 0;
+ }
+ match (a, b) {
+ (0 | 1, 2 | 3) => {}
+ _ => {}
+ }
+ if is_true {
+ a = 2;
+ b = 2;
+ }
+ match (a, b) {
+ (0 | 1, 2 | 3) => {}
+ _ => {}
+ }
+ if is_true {
+ a = 0;
+ b = 2;
+ }
+ match (a, b) {
+ (0 | 1, 2 | 3) => {}
+ _ => {}
+ }
+}
diff --git a/src/test/run-make/coverage/nested_loops.rs b/src/test/run-make/coverage/nested_loops.rs
new file mode 100644
index 000000000..4c7c78427
--- /dev/null
+++ b/src/test/run-make/coverage/nested_loops.rs
@@ -0,0 +1,25 @@
+fn main() {
+ let is_true = std::env::args().len() == 1;
+ let mut countdown = 10;
+
+ 'outer: while countdown > 0 {
+ let mut a = 100;
+ let mut b = 100;
+ for _ in 0..50 {
+ if a < 30 {
+ break;
+ }
+ a -= 5;
+ b -= 5;
+ if b < 90 {
+ a -= 10;
+ if is_true {
+ break 'outer;
+ } else {
+ a -= 2;
+ }
+ }
+ }
+ countdown -= 1;
+ }
+}
diff --git a/src/test/run-make/coverage/no_cov_crate.rs b/src/test/run-make/coverage/no_cov_crate.rs
new file mode 100644
index 000000000..0bfbdda2c
--- /dev/null
+++ b/src/test/run-make/coverage/no_cov_crate.rs
@@ -0,0 +1,86 @@
+// Enables `no_coverage` on the entire crate
+#![feature(no_coverage)]
+
+#[no_coverage]
+fn do_not_add_coverage_1() {
+ println!("called but not covered");
+}
+
+fn do_not_add_coverage_2() {
+ #![no_coverage]
+ println!("called but not covered");
+}
+
+#[no_coverage]
+fn do_not_add_coverage_not_called() {
+ println!("not called and not covered");
+}
+
+fn add_coverage_1() {
+ println!("called and covered");
+}
+
+fn add_coverage_2() {
+ println!("called and covered");
+}
+
+fn add_coverage_not_called() {
+ println!("not called but covered");
+}
+
+// FIXME: These test-cases illustrate confusing results of nested functions.
+// See https://github.com/rust-lang/rust/issues/93319
+mod nested_fns {
+ #[no_coverage]
+ pub fn outer_not_covered(is_true: bool) {
+ fn inner(is_true: bool) {
+ if is_true {
+ println!("called and covered");
+ } else {
+ println!("absolutely not covered");
+ }
+ }
+ println!("called but not covered");
+ inner(is_true);
+ }
+
+ pub fn outer(is_true: bool) {
+ println!("called and covered");
+ inner_not_covered(is_true);
+
+ #[no_coverage]
+ fn inner_not_covered(is_true: bool) {
+ if is_true {
+ println!("called but not covered");
+ } else {
+ println!("absolutely not covered");
+ }
+ }
+ }
+
+ pub fn outer_both_covered(is_true: bool) {
+ println!("called and covered");
+ inner(is_true);
+
+ fn inner(is_true: bool) {
+ if is_true {
+ println!("called and covered");
+ } else {
+ println!("absolutely not covered");
+ }
+ }
+ }
+}
+
+fn main() {
+ let is_true = std::env::args().len() == 1;
+
+ do_not_add_coverage_1();
+ do_not_add_coverage_2();
+ add_coverage_1();
+ add_coverage_2();
+
+ nested_fns::outer_not_covered(is_true);
+ nested_fns::outer(is_true);
+ nested_fns::outer_both_covered(is_true);
+}
diff --git a/src/test/run-make/coverage/overflow.rs b/src/test/run-make/coverage/overflow.rs
new file mode 100644
index 000000000..e537b0e95
--- /dev/null
+++ b/src/test/run-make/coverage/overflow.rs
@@ -0,0 +1,63 @@
+#![allow(unused_assignments)]
+// expect-exit-status-101
+
+fn might_overflow(to_add: u32) -> u32 {
+ if to_add > 5 {
+ println!("this will probably overflow");
+ }
+ let add_to = u32::MAX - 5;
+ println!("does {} + {} overflow?", add_to, to_add);
+ let result = to_add + add_to;
+ println!("continuing after overflow check");
+ result
+}
+
+fn main() -> Result<(),u8> {
+ let mut countdown = 10;
+ while countdown > 0 {
+ if countdown == 1 {
+ let result = might_overflow(10);
+ println!("Result: {}", result);
+ } else if countdown < 5 {
+ let result = might_overflow(1);
+ println!("Result: {}", result);
+ }
+ countdown -= 1;
+ }
+ Ok(())
+}
+
+// Notes:
+// 1. Compare this program and its coverage results to those of the very similar test `assert.rs`,
+// and similar tests `panic_unwind.rs`, abort.rs` and `try_error_result.rs`.
+// 2. This test confirms the coverage generated when a program passes or fails a
+// compiler-generated `TerminatorKind::Assert` (based on an overflow check, in this case).
+// 3. Similar to how the coverage instrumentation handles `TerminatorKind::Call`,
+// compiler-generated assertion failures are assumed to be a symptom of a program bug, not
+// expected behavior. To simplify the coverage graphs and keep instrumented programs as
+// small and fast as possible, `Assert` terminators are assumed to always succeed, and
+// therefore are considered "non-branching" terminators. So, an `Assert` terminator does not
+// get its own coverage counter.
+// 4. After an unhandled panic or failed Assert, coverage results may not always be intuitive.
+// In this test, the final count for the statements after the `if` block in `might_overflow()`
+// is 4, even though the lines after `to_add + add_to` were executed only 3 times. Depending
+// on the MIR graph and the structure of the code, this count could have been 3 (which might
+// have been valid for the overflowed add `+`, but should have been 4 for the lines before
+// the overflow. The reason for this potential uncertainty is, a `CounterKind` is incremented
+// via StatementKind::Counter at the end of the block, but (as in the case in this test),
+// a CounterKind::Expression is always evaluated. In this case, the expression was based on
+// a `Counter` incremented as part of the evaluation of the `if` expression, which was
+// executed, and counted, 4 times, before reaching the overflow add.
+
+// If the program did not overflow, the coverage for `might_overflow()` would look like this:
+//
+// 4| |fn might_overflow(to_add: u32) -> u32 {
+// 5| 4| if to_add > 5 {
+// 6| 0| println!("this will probably overflow");
+// 7| 4| }
+// 8| 4| let add_to = u32::MAX - 5;
+// 9| 4| println!("does {} + {} overflow?", add_to, to_add);
+// 10| 4| let result = to_add + add_to;
+// 11| 4| println!("continuing after overflow check");
+// 12| 4| result
+// 13| 4|}
diff --git a/src/test/run-make/coverage/panic_unwind.rs b/src/test/run-make/coverage/panic_unwind.rs
new file mode 100644
index 000000000..03128c2cc
--- /dev/null
+++ b/src/test/run-make/coverage/panic_unwind.rs
@@ -0,0 +1,31 @@
+#![allow(unused_assignments)]
+// expect-exit-status-101
+
+fn might_panic(should_panic: bool) {
+ if should_panic {
+ println!("panicking...");
+ panic!("panics");
+ } else {
+ println!("Don't Panic");
+ }
+}
+
+fn main() -> Result<(), u8> {
+ let mut countdown = 10;
+ while countdown > 0 {
+ if countdown == 1 {
+ might_panic(true);
+ } else if countdown < 5 {
+ might_panic(false);
+ }
+ countdown -= 1;
+ }
+ Ok(())
+}
+
+// Notes:
+// 1. Compare this program and its coverage results to those of the similar tests `abort.rs` and
+// `try_error_result.rs`.
+// 2. Since the `panic_unwind.rs` test is allowed to unwind, it is also allowed to execute the
+// normal program exit cleanup, including writing out the current values of the coverage
+// counters.
diff --git a/src/test/run-make/coverage/partial_eq.rs b/src/test/run-make/coverage/partial_eq.rs
new file mode 100644
index 000000000..4ceaba9b1
--- /dev/null
+++ b/src/test/run-make/coverage/partial_eq.rs
@@ -0,0 +1,46 @@
+// This test confirms an earlier problem was resolved, supporting the MIR graph generated by the
+// structure of this test.
+
+#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+pub struct Version {
+ major: usize,
+ minor: usize,
+ patch: usize,
+}
+
+impl Version {
+ pub fn new(major: usize, minor: usize, patch: usize) -> Self {
+ Self {
+ major,
+ minor,
+ patch,
+ }
+ }
+}
+
+fn main() {
+ let version_3_2_1 = Version::new(3, 2, 1);
+ let version_3_3_0 = Version::new(3, 3, 0);
+
+ println!("{:?} < {:?} = {}", version_3_2_1, version_3_3_0, version_3_2_1 < version_3_3_0);
+}
+
+/*
+
+This test verifies a bug was fixed that otherwise generated this error:
+
+thread 'rustc' panicked at 'No counters provided the source_hash for function:
+ Instance {
+ def: Item(WithOptConstParam {
+ did: DefId(0:101 ~ autocfg[c44a]::version::{impl#2}::partial_cmp),
+ const_param_did: None
+ }),
+ substs: []
+ }'
+The `PartialOrd` derived by `Version` happened to generate a MIR that generated coverage
+without a code region associated with any `Counter`. Code regions were associated with at least
+one expression, which is allowed, but the `function_source_hash` was only passed to the codegen
+(coverage mapgen) phase from a `Counter`s code region. A new method was added to pass the
+`function_source_hash` without a code region, if necessary.
+
+*/
diff --git a/src/test/run-make/coverage/simple_loop.rs b/src/test/run-make/coverage/simple_loop.rs
new file mode 100644
index 000000000..6f7f23475
--- /dev/null
+++ b/src/test/run-make/coverage/simple_loop.rs
@@ -0,0 +1,35 @@
+#![allow(unused_assignments)]
+
+fn main() {
+ // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ // dependent conditions.
+ let is_true = std::env::args().len() == 1;
+
+ let mut countdown = 0;
+
+ if
+ is_true
+ {
+ countdown
+ =
+ 10
+ ;
+ }
+
+ loop
+ {
+ if
+ countdown
+ ==
+ 0
+ {
+ break
+ ;
+ }
+ countdown
+ -=
+ 1
+ ;
+ }
+}
diff --git a/src/test/run-make/coverage/simple_match.rs b/src/test/run-make/coverage/simple_match.rs
new file mode 100644
index 000000000..be99e59a8
--- /dev/null
+++ b/src/test/run-make/coverage/simple_match.rs
@@ -0,0 +1,43 @@
+#![allow(unused_assignments, unused_variables)]
+
+fn main() {
+ // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ // dependent conditions.
+ let is_true = std::env::args().len() == 1;
+
+ let mut countdown = 1;
+ if is_true {
+ countdown = 0;
+ }
+
+ for
+ _
+ in
+ 0..2
+ {
+ let z
+ ;
+ match
+ countdown
+ {
+ x
+ if
+ x
+ <
+ 1
+ =>
+ {
+ z = countdown
+ ;
+ let y = countdown
+ ;
+ countdown = 10
+ ;
+ }
+ _
+ =>
+ {}
+ }
+ }
+}
diff --git a/src/test/run-make/coverage/tight_inf_loop.rs b/src/test/run-make/coverage/tight_inf_loop.rs
new file mode 100644
index 000000000..cef99027a
--- /dev/null
+++ b/src/test/run-make/coverage/tight_inf_loop.rs
@@ -0,0 +1,5 @@
+fn main() {
+ if false {
+ loop {}
+ }
+}
diff --git a/src/test/run-make/coverage/try_error_result.rs b/src/test/run-make/coverage/try_error_result.rs
new file mode 100644
index 000000000..cd0acf723
--- /dev/null
+++ b/src/test/run-make/coverage/try_error_result.rs
@@ -0,0 +1,118 @@
+#![allow(unused_assignments)]
+// expect-exit-status-1
+
+fn call(return_error: bool) -> Result<(),()> {
+ if return_error {
+ Err(())
+ } else {
+ Ok(())
+ }
+}
+
+fn test1() -> Result<(),()> {
+ let mut
+ countdown = 10
+ ;
+ for
+ _
+ in
+ 0..10
+ {
+ countdown
+ -= 1
+ ;
+ if
+ countdown < 5
+ {
+ call(/*return_error=*/ true)?;
+ call(/*return_error=*/ false)?;
+ }
+ else
+ {
+ call(/*return_error=*/ false)?;
+ }
+ }
+ Ok(())
+}
+
+struct Thing1;
+impl Thing1 {
+ fn get_thing_2(&self, return_error: bool) -> Result<Thing2,()> {
+ if return_error {
+ Err(())
+ } else {
+ Ok(Thing2{})
+ }
+ }
+}
+
+struct Thing2;
+impl Thing2 {
+ fn call(&self, return_error: bool) -> Result<u32,()> {
+ if return_error {
+ Err(())
+ } else {
+ Ok(57)
+ }
+ }
+}
+
+fn test2() -> Result<(),()> {
+ let thing1 = Thing1{};
+ let mut
+ countdown = 10
+ ;
+ for
+ _
+ in
+ 0..10
+ {
+ countdown
+ -= 1
+ ;
+ if
+ countdown < 5
+ {
+ thing1.get_thing_2(/*err=*/ false)?.call(/*err=*/ true).expect_err("call should fail");
+ thing1
+ .
+ get_thing_2(/*return_error=*/ false)
+ ?
+ .
+ call(/*return_error=*/ true)
+ .
+ expect_err(
+ "call should fail"
+ );
+ let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ true)?;
+ assert_eq!(val, 57);
+ let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ false)?;
+ assert_eq!(val, 57);
+ }
+ else
+ {
+ let val = thing1.get_thing_2(/*return_error=*/ false)?.call(/*return_error=*/ false)?;
+ assert_eq!(val, 57);
+ let val = thing1
+ .get_thing_2(/*return_error=*/ false)?
+ .call(/*return_error=*/ false)?;
+ assert_eq!(val, 57);
+ let val = thing1
+ .get_thing_2(/*return_error=*/ false)
+ ?
+ .call(/*return_error=*/ false)
+ ?
+ ;
+ assert_eq!(val, 57);
+ }
+ }
+ Ok(())
+}
+
+fn main() -> Result<(),()> {
+ test1().expect_err("test1 should fail");
+ test2()
+ ?
+ ;
+ Ok(())
+}
diff --git a/src/test/run-make/coverage/unused.rs b/src/test/run-make/coverage/unused.rs
new file mode 100644
index 000000000..fb6113eb0
--- /dev/null
+++ b/src/test/run-make/coverage/unused.rs
@@ -0,0 +1,39 @@
+fn foo<T>(x: T) {
+ let mut i = 0;
+ while i < 10 {
+ i != 0 || i != 0;
+ i += 1;
+ }
+}
+
+fn unused_template_func<T>(x: T) {
+ let mut i = 0;
+ while i < 10 {
+ i != 0 || i != 0;
+ i += 1;
+ }
+}
+
+fn unused_func(mut a: u32) {
+ if a != 0 {
+ a += 1;
+ }
+}
+
+fn unused_func2(mut a: u32) {
+ if a != 0 {
+ a += 1;
+ }
+}
+
+fn unused_func3(mut a: u32) {
+ if a != 0 {
+ a += 1;
+ }
+}
+
+fn main() -> Result<(), u8> {
+ foo::<u32>(0);
+ foo::<f32>(0.0);
+ Ok(())
+}
diff --git a/src/test/run-make/coverage/unused_mod.rs b/src/test/run-make/coverage/unused_mod.rs
new file mode 100644
index 000000000..679b4e531
--- /dev/null
+++ b/src/test/run-make/coverage/unused_mod.rs
@@ -0,0 +1,6 @@
+#[path = "lib/unused_mod_helper.rs"]
+mod unused_module;
+
+fn main() {
+ println!("hello world!");
+}
diff --git a/src/test/run-make/coverage/uses_crate.rs b/src/test/run-make/coverage/uses_crate.rs
new file mode 100644
index 000000000..20cb05fe5
--- /dev/null
+++ b/src/test/run-make/coverage/uses_crate.rs
@@ -0,0 +1,12 @@
+#![allow(unused_assignments, unused_variables)]
+// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
+extern crate used_crate;
+
+fn main() {
+ used_crate::used_function();
+ let some_vec = vec![1, 2, 3, 4];
+ used_crate::used_only_from_bin_crate_generic_function(&some_vec);
+ used_crate::used_only_from_bin_crate_generic_function("used from bin uses_crate.rs");
+ used_crate::used_from_bin_crate_and_lib_crate_generic_function(some_vec);
+ used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function("interesting?");
+}
diff --git a/src/test/run-make/coverage/uses_inline_crate.rs b/src/test/run-make/coverage/uses_inline_crate.rs
new file mode 100644
index 000000000..a7fe8532b
--- /dev/null
+++ b/src/test/run-make/coverage/uses_inline_crate.rs
@@ -0,0 +1,17 @@
+#![allow(unused_assignments, unused_variables)]
+
+// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
+
+extern crate used_inline_crate;
+
+fn main() {
+ used_inline_crate::used_function();
+ used_inline_crate::used_inline_function();
+ let some_vec = vec![1, 2, 3, 4];
+ used_inline_crate::used_only_from_bin_crate_generic_function(&some_vec);
+ used_inline_crate::used_only_from_bin_crate_generic_function("used from bin uses_crate.rs");
+ used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function(some_vec);
+ used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function(
+ "interesting?",
+ );
+}
diff --git a/src/test/run-make/coverage/while.rs b/src/test/run-make/coverage/while.rs
new file mode 100644
index 000000000..781b90b35
--- /dev/null
+++ b/src/test/run-make/coverage/while.rs
@@ -0,0 +1,5 @@
+fn main() {
+ let num = 9;
+ while num >= 10 {
+ }
+}
diff --git a/src/test/run-make/coverage/while_early_ret.rs b/src/test/run-make/coverage/while_early_ret.rs
new file mode 100644
index 000000000..1fcea9c85
--- /dev/null
+++ b/src/test/run-make/coverage/while_early_ret.rs
@@ -0,0 +1,42 @@
+#![allow(unused_assignments)]
+// expect-exit-status-1
+
+fn main() -> Result<(),u8> {
+ let mut countdown = 10;
+ while
+ countdown
+ >
+ 0
+ {
+ if
+ countdown
+ <
+ 5
+ {
+ return
+ if
+ countdown
+ >
+ 8
+ {
+ Ok(())
+ }
+ else
+ {
+ Err(1)
+ }
+ ;
+ }
+ countdown
+ -=
+ 1
+ ;
+ }
+ Ok(())
+}
+
+// ISSUE(77553): Originally, this test had `Err(1)` on line 22 (instead of `Ok(())`) and
+// `std::process::exit(2)` on line 26 (instead of `Err(1)`); and this worked as expected on Linux
+// and MacOS. But on Windows (MSVC, at least), the call to `std::process::exit()` exits the program
+// without saving the InstrProf coverage counters. The use of `std::process:exit()` is not critical
+// to the coverage test for early returns, but this is a limitation that should be fixed.
diff --git a/src/test/run-make/coverage/yield.rs b/src/test/run-make/coverage/yield.rs
new file mode 100644
index 000000000..ff7616656
--- /dev/null
+++ b/src/test/run-make/coverage/yield.rs
@@ -0,0 +1,37 @@
+#![feature(generators, generator_trait)]
+#![allow(unused_assignments)]
+
+use std::ops::{Generator, GeneratorState};
+use std::pin::Pin;
+
+fn main() {
+ let mut generator = || {
+ yield 1;
+ return "foo"
+ };
+
+ match Pin::new(&mut generator).resume(()) {
+ GeneratorState::Yielded(1) => {}
+ _ => panic!("unexpected value from resume"),
+ }
+ match Pin::new(&mut generator).resume(()) {
+ GeneratorState::Complete("foo") => {}
+ _ => panic!("unexpected value from resume"),
+ }
+
+ let mut generator = || {
+ yield 1;
+ yield 2;
+ yield 3;
+ return "foo"
+ };
+
+ match Pin::new(&mut generator).resume(()) {
+ GeneratorState::Yielded(1) => {}
+ _ => panic!("unexpected value from resume"),
+ }
+ match Pin::new(&mut generator).resume(()) {
+ GeneratorState::Yielded(2) => {}
+ _ => panic!("unexpected value from resume"),
+ }
+}
diff --git a/src/test/run-make/dep-graph/Makefile b/src/test/run-make/dep-graph/Makefile
new file mode 100644
index 000000000..88916022c
--- /dev/null
+++ b/src/test/run-make/dep-graph/Makefile
@@ -0,0 +1,12 @@
+-include ../../run-make-fulldeps/tools.mk
+
+# ignore-cross-compile
+
+# Just verify that we successfully run and produce dep graphs when requested.
+
+all:
+ RUST_DEP_GRAPH=$(TMPDIR)/dep-graph $(RUSTC) \
+ -Cincremental=$(TMPDIR)/incr \
+ -Zquery-dep-graph -Zdump-dep-graph foo.rs
+ test -f $(TMPDIR)/dep-graph.txt
+ test -f $(TMPDIR)/dep-graph.dot
diff --git a/src/test/run-make/dep-graph/foo.rs b/src/test/run-make/dep-graph/foo.rs
new file mode 100644
index 000000000..f328e4d9d
--- /dev/null
+++ b/src/test/run-make/dep-graph/foo.rs
@@ -0,0 +1 @@
+fn main() {}
diff --git a/src/test/run-make/emit-named-files/Makefile b/src/test/run-make/emit-named-files/Makefile
new file mode 100644
index 000000000..03eb83b97
--- /dev/null
+++ b/src/test/run-make/emit-named-files/Makefile
@@ -0,0 +1,33 @@
+-include ../../run-make-fulldeps/tools.mk
+
+OUT=$(TMPDIR)/emit
+
+all: asm llvm-bc llvm-ir obj metadata link dep-info mir
+
+asm: $(OUT)
+ $(RUSTC) --emit asm=$(OUT)/libfoo.s foo.rs
+ test -f $(OUT)/libfoo.s
+llvm-bc: $(OUT)
+ $(RUSTC) --emit llvm-bc=$(OUT)/libfoo.bc foo.rs
+ test -f $(OUT)/libfoo.bc
+llvm-ir: $(OUT)
+ $(RUSTC) --emit llvm-ir=$(OUT)/libfoo.ll foo.rs
+ test -f $(OUT)/libfoo.ll
+obj: $(OUT)
+ $(RUSTC) --emit obj=$(OUT)/libfoo.o foo.rs
+ test -f $(OUT)/libfoo.o
+metadata: $(OUT)
+ $(RUSTC) --emit metadata=$(OUT)/libfoo.rmeta foo.rs
+ test -f $(OUT)/libfoo.rmeta
+link: $(OUT)
+ $(RUSTC) --emit link=$(OUT)/libfoo.rlib foo.rs
+ test -f $(OUT)/libfoo.rlib
+dep-info: $(OUT)
+ $(RUSTC) --emit dep-info=$(OUT)/libfoo.d foo.rs
+ test -f $(OUT)/libfoo.d
+mir: $(OUT)
+ $(RUSTC) --emit mir=$(OUT)/libfoo.mir foo.rs
+ test -f $(OUT)/libfoo.mir
+
+$(OUT):
+ mkdir -p $(OUT)
diff --git a/src/test/run-make/emit-named-files/foo.rs b/src/test/run-make/emit-named-files/foo.rs
new file mode 100644
index 000000000..c1bfaa6ca
--- /dev/null
+++ b/src/test/run-make/emit-named-files/foo.rs
@@ -0,0 +1 @@
+#![crate_type = "rlib"]
diff --git a/src/test/run-make/emit-path-unhashed/Makefile b/src/test/run-make/emit-path-unhashed/Makefile
new file mode 100644
index 000000000..b6b2d8af6
--- /dev/null
+++ b/src/test/run-make/emit-path-unhashed/Makefile
@@ -0,0 +1,37 @@
+-include ../../run-make-fulldeps/tools.mk
+
+OUT=$(TMPDIR)/emit
+
+# --emit KIND=PATH should not affect crate hash vs --emit KIND
+all: $(OUT)/a/libfoo.rlib $(OUT)/b/libfoo.rlib $(OUT)/c/libfoo.rlib \
+ $(TMPDIR)/libfoo.rlib
+ $(RUSTC) -Zls $(TMPDIR)/libfoo.rlib > $(TMPDIR)/base.txt
+ $(RUSTC) -Zls $(OUT)/a/libfoo.rlib > $(TMPDIR)/a.txt
+ $(RUSTC) -Zls $(OUT)/b/libfoo.rlib > $(TMPDIR)/b.txt
+ $(RUSTC) -Zls $(OUT)/c/libfoo.rlib > $(TMPDIR)/c.txt
+
+ diff $(TMPDIR)/base.txt $(TMPDIR)/a.txt
+ diff $(TMPDIR)/base.txt $(TMPDIR)/b.txt
+
+ # Different KIND parameters do affect hash.
+ # diff exits 1 on difference, 2 on trouble
+ diff $(TMPDIR)/base.txt $(TMPDIR)/c.txt ; test "$$?" -eq 1
+
+# Default output name
+$(TMPDIR)/libfoo.rlib: foo.rs
+ $(RUSTC) --emit link foo.rs
+
+# Output named with -o
+$(OUT)/a/libfoo.rlib: foo.rs
+ mkdir -p $(OUT)/a
+ $(RUSTC) --emit link -o $@ foo.rs
+
+# Output named with KIND=PATH
+$(OUT)/b/libfoo.rlib: foo.rs
+ mkdir -p $(OUT)/b
+ $(RUSTC) --emit link=$@ foo.rs
+
+# Output multiple kinds
+$(OUT)/c/libfoo.rlib: foo.rs
+ mkdir -p $(OUT)/c
+ $(RUSTC) --emit link=$@,metadata foo.rs
diff --git a/src/test/run-make/emit-path-unhashed/foo.rs b/src/test/run-make/emit-path-unhashed/foo.rs
new file mode 100644
index 000000000..c1bfaa6ca
--- /dev/null
+++ b/src/test/run-make/emit-path-unhashed/foo.rs
@@ -0,0 +1 @@
+#![crate_type = "rlib"]
diff --git a/src/test/run-make/emit-shared-files/Makefile b/src/test/run-make/emit-shared-files/Makefile
new file mode 100644
index 000000000..9f46883be
--- /dev/null
+++ b/src/test/run-make/emit-shared-files/Makefile
@@ -0,0 +1,46 @@
+-include ../../run-make-fulldeps/tools.mk
+
+INVOCATION_ONLY = $(TMPDIR)/invocation-only
+TOOLCHAIN_ONLY = $(TMPDIR)/toolchain-only
+ALL_SHARED = $(TMPDIR)/all-shared
+
+all: invocation-only toolchain-only all-shared
+
+invocation-only:
+ $(RUSTDOC) -Z unstable-options --emit=invocation-specific --output $(INVOCATION_ONLY) --resource-suffix=-xxx --theme y.css --extend-css z.css x.rs
+ [ -e $(INVOCATION_ONLY)/search-index-xxx.js ]
+ [ -e $(INVOCATION_ONLY)/settings.html ]
+ [ -e $(INVOCATION_ONLY)/x/all.html ]
+ [ -e $(INVOCATION_ONLY)/x/index.html ]
+ [ -e $(INVOCATION_ONLY)/theme-xxx.css ] # generated from z.css
+ ! [ -e $(INVOCATION_ONLY)/storage-xxx.js ]
+ ! [ -e $(INVOCATION_ONLY)/SourceSerif4-It.ttf.woff2 ]
+
+ # FIXME: this probably shouldn't have a suffix
+ [ -e $(INVOCATION_ONLY)/y-xxx.css ]
+ # FIXME: this is technically incorrect (see `write_shared`)
+ ! [ -e $(INVOCATION_ONLY)/main-xxx.js ]
+
+toolchain-only:
+ $(RUSTDOC) -Z unstable-options --emit=toolchain-shared-resources --output $(TOOLCHAIN_ONLY) --resource-suffix=-xxx --extend-css z.css x.rs
+ [ -e $(TOOLCHAIN_ONLY)/storage-xxx.js ]
+ ! [ -e $(TOOLCHAIN_ONLY)/SourceSerif4-It.ttf.woff2 ]
+ ! [ -e $(TOOLCHAIN_ONLY)/search-index-xxx.js ]
+ ! [ -e $(TOOLCHAIN_ONLY)/x/index.html ]
+ ! [ -e $(TOOLCHAIN_ONLY)/theme.css ]
+
+ [ -e $(TOOLCHAIN_ONLY)/main-xxx.js ]
+ ! [ -e $(TOOLCHAIN_ONLY)/y-xxx.css ]
+
+all-shared:
+ $(RUSTDOC) -Z unstable-options --emit=toolchain-shared-resources,unversioned-shared-resources --output $(ALL_SHARED) --resource-suffix=-xxx --extend-css z.css x.rs
+ [ -e $(ALL_SHARED)/storage-xxx.js ]
+ [ -e $(ALL_SHARED)/SourceSerif4-It.ttf.woff2 ]
+ ! [ -e $(ALL_SHARED)/search-index-xxx.js ]
+ ! [ -e $(ALL_SHARED)/settings.html ]
+ ! [ -e $(ALL_SHARED)/x ]
+ ! [ -e $(ALL_SHARED)/src ]
+ ! [ -e $(ALL_SHARED)/theme.css ]
+
+ [ -e $(ALL_SHARED)/main-xxx.js ]
+ ! [ -e $(ALL_SHARED)/y-xxx.css ]
diff --git a/src/test/run-make/emit-shared-files/x.rs b/src/test/run-make/emit-shared-files/x.rs
new file mode 100644
index 000000000..5df757613
--- /dev/null
+++ b/src/test/run-make/emit-shared-files/x.rs
@@ -0,0 +1 @@
+// nothing to see here
diff --git a/src/test/run-make/emit-shared-files/y.css b/src/test/run-make/emit-shared-files/y.css
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/test/run-make/emit-shared-files/y.css
diff --git a/src/test/run-make/emit-shared-files/z.css b/src/test/run-make/emit-shared-files/z.css
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/test/run-make/emit-shared-files/z.css
diff --git a/src/test/run-make/env-dep-info/Makefile b/src/test/run-make/env-dep-info/Makefile
new file mode 100644
index 000000000..25d9a31c2
--- /dev/null
+++ b/src/test/run-make/env-dep-info/Makefile
@@ -0,0 +1,19 @@
+-include ../../run-make-fulldeps/tools.mk
+
+# FIXME(eddyb) provide `HOST_RUSTC` and `TARGET_RUSTC`
+# instead of hardcoding them everywhere they're needed.
+ifeq ($(IS_MUSL_HOST),1)
+ADDITIONAL_ARGS := $(RUSTFLAGS)
+endif
+
+all:
+ EXISTING_ENV=1 EXISTING_OPT_ENV=1 $(RUSTC) --emit dep-info main.rs
+ $(CGREP) "# env-dep:EXISTING_ENV=1" < $(TMPDIR)/main.d
+ $(CGREP) "# env-dep:EXISTING_OPT_ENV=1" < $(TMPDIR)/main.d
+ $(CGREP) "# env-dep:NONEXISTENT_OPT_ENV" < $(TMPDIR)/main.d
+ $(CGREP) "# env-dep:ESCAPE\nESCAPE\\" < $(TMPDIR)/main.d
+ # Proc macro
+ $(BARE_RUSTC) $(ADDITIONAL_ARGS) --out-dir $(TMPDIR) macro_def.rs
+ EXISTING_PROC_MACRO_ENV=1 $(RUSTC) --emit dep-info macro_use.rs
+ $(CGREP) "# env-dep:EXISTING_PROC_MACRO_ENV=1" < $(TMPDIR)/macro_use.d
+ $(CGREP) "# env-dep:NONEXISTENT_PROC_MACEO_ENV" < $(TMPDIR)/macro_use.d
diff --git a/src/test/run-make/env-dep-info/macro_def.rs b/src/test/run-make/env-dep-info/macro_def.rs
new file mode 100644
index 000000000..e328eae48
--- /dev/null
+++ b/src/test/run-make/env-dep-info/macro_def.rs
@@ -0,0 +1,12 @@
+#![feature(proc_macro_tracked_env)]
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro]
+pub fn access_env_vars(_: TokenStream) -> TokenStream {
+ let _ = tracked_env::var("EXISTING_PROC_MACRO_ENV");
+ let _ = tracked_env::var("NONEXISTENT_PROC_MACEO_ENV");
+ TokenStream::new()
+}
diff --git a/src/test/run-make/env-dep-info/macro_use.rs b/src/test/run-make/env-dep-info/macro_use.rs
new file mode 100644
index 000000000..2f5267471
--- /dev/null
+++ b/src/test/run-make/env-dep-info/macro_use.rs
@@ -0,0 +1,6 @@
+#[macro_use]
+extern crate macro_def;
+
+access_env_vars!();
+
+fn main() {}
diff --git a/src/test/run-make/env-dep-info/main.rs b/src/test/run-make/env-dep-info/main.rs
new file mode 100644
index 000000000..a25246bac
--- /dev/null
+++ b/src/test/run-make/env-dep-info/main.rs
@@ -0,0 +1,6 @@
+fn main() {
+ env!("EXISTING_ENV");
+ option_env!("EXISTING_OPT_ENV");
+ option_env!("NONEXISTENT_OPT_ENV");
+ option_env!("ESCAPE\nESCAPE\\");
+}
diff --git a/src/test/run-make/export-executable-symbols/Makefile b/src/test/run-make/export-executable-symbols/Makefile
new file mode 100644
index 000000000..5006f9cb8
--- /dev/null
+++ b/src/test/run-make/export-executable-symbols/Makefile
@@ -0,0 +1,11 @@
+-include ../../run-make-fulldeps/tools.mk
+
+# ignore-wasm32
+# ignore-wasm64
+# ignore-none no-std is not supported
+# only-linux
+
+all:
+ $(RUSTC) -Zexport-executable-symbols main.rs --target $(TARGET) --crate-type=bin
+ nm $(TMPDIR)/main | $(CGREP) exported_symbol
+
diff --git a/src/test/run-make/export-executable-symbols/main.rs b/src/test/run-make/export-executable-symbols/main.rs
new file mode 100644
index 000000000..c498381a3
--- /dev/null
+++ b/src/test/run-make/export-executable-symbols/main.rs
@@ -0,0 +1,8 @@
+// edition:2018
+
+fn main() {}
+
+#[no_mangle]
+pub fn exported_symbol() -> i8 {
+ 42
+}
diff --git a/src/test/run-make/fmt-write-bloat/Makefile b/src/test/run-make/fmt-write-bloat/Makefile
new file mode 100644
index 000000000..26e08086a
--- /dev/null
+++ b/src/test/run-make/fmt-write-bloat/Makefile
@@ -0,0 +1,25 @@
+-include ../../run-make-fulldeps/tools.mk
+
+# ignore-windows
+
+ifeq ($(shell $(RUSTC) -vV | grep 'host: $(TARGET)'),)
+
+# Don't run this test when cross compiling.
+all:
+
+else
+
+NM = nm
+
+PANIC_SYMS = panic_bounds_check pad_integral Display Debug
+
+# Allow for debug_assert!() in debug builds of std.
+ifdef NO_DEBUG_ASSERTIONS
+PANIC_SYMS += panicking panic_fmt
+endif
+
+all: main.rs
+ $(RUSTC) $< -O
+ $(NM) $(call RUN_BINFILE,main) | $(CGREP) -v $(PANIC_SYMS)
+
+endif
diff --git a/src/test/run-make/fmt-write-bloat/main.rs b/src/test/run-make/fmt-write-bloat/main.rs
new file mode 100644
index 000000000..e86c48014
--- /dev/null
+++ b/src/test/run-make/fmt-write-bloat/main.rs
@@ -0,0 +1,32 @@
+#![feature(lang_items)]
+#![feature(start)]
+#![no_std]
+
+use core::fmt;
+use core::fmt::Write;
+
+#[link(name = "c")]
+extern "C" {}
+
+struct Dummy;
+
+impl fmt::Write for Dummy {
+ #[inline(never)]
+ fn write_str(&mut self, _: &str) -> fmt::Result {
+ Ok(())
+ }
+}
+
+#[start]
+fn main(_: isize, _: *const *const u8) -> isize {
+ let _ = writeln!(Dummy, "Hello World");
+ 0
+}
+
+#[lang = "eh_personality"]
+fn eh_personality() {}
+
+#[panic_handler]
+fn panic(_: &core::panic::PanicInfo) -> ! {
+ loop {}
+}
diff --git a/src/test/run-make/git_clone_sha1.sh b/src/test/run-make/git_clone_sha1.sh
new file mode 100644
index 000000000..626e4e427
--- /dev/null
+++ b/src/test/run-make/git_clone_sha1.sh
@@ -0,0 +1,23 @@
+#!/bin/bash -x
+
+# Usage: $0 project_name url sha1
+# Get the crate with the specified sha1.
+#
+# all arguments are required.
+#
+# See below link for git usage:
+# https://stackoverflow.com/questions/3489173#14091182
+
+# Mandatory arguments:
+PROJECT_NAME=$1
+URL=$2
+SHA1=$3
+
+function err_exit() {
+ echo "ERROR:" $*
+ exit 1
+}
+
+git clone $URL $PROJECT_NAME || err_exit
+cd $PROJECT_NAME || err_exit
+git reset --hard $SHA1 || err_exit
diff --git a/src/test/run-make/incr-foreign-head-span/Makefile b/src/test/run-make/incr-foreign-head-span/Makefile
new file mode 100644
index 000000000..712965eaa
--- /dev/null
+++ b/src/test/run-make/incr-foreign-head-span/Makefile
@@ -0,0 +1,21 @@
+include ../../run-make-fulldeps/tools.mk
+
+# ignore-none no-std is not supported
+# ignore-nvptx64-nvidia-cuda FIXME: can't find crate for 'std'
+
+# Ensure that modifying a crate on disk (without recompiling it)
+# does not cause ICEs in downstream crates.
+# Previously, we would call `SourceMap.guess_head_span` on a span
+# from an external crate, which would cause us to read an upstream
+# source file from disk during compilation of a downstream crate
+# See #86480 for more details
+
+INCR=$(TMPDIR)/incr
+
+all:
+ cp first_crate.rs second_crate.rs $(TMPDIR)
+ $(RUSTC) $(TMPDIR)/first_crate.rs -C incremental=$(INCR) --target $(TARGET) --crate-type lib
+ $(RUSTC) $(TMPDIR)/second_crate.rs -C incremental=$(INCR) --target $(TARGET) --extern first-crate=$(TMPDIR) --crate-type lib
+ rm $(TMPDIR)/first_crate.rs
+ $(RUSTC) $(TMPDIR)/second_crate.rs -C incremental=$(INCR) --target $(TARGET) --cfg second_run --crate-type lib
+
diff --git a/src/test/run-make/incr-foreign-head-span/first_crate.rs b/src/test/run-make/incr-foreign-head-span/first_crate.rs
new file mode 100644
index 000000000..69dd103bf
--- /dev/null
+++ b/src/test/run-make/incr-foreign-head-span/first_crate.rs
@@ -0,0 +1 @@
+pub trait OtherTrait {}
diff --git a/src/test/run-make/incr-foreign-head-span/second_crate.rs b/src/test/run-make/incr-foreign-head-span/second_crate.rs
new file mode 100644
index 000000000..102f6b26c
--- /dev/null
+++ b/src/test/run-make/incr-foreign-head-span/second_crate.rs
@@ -0,0 +1,8 @@
+extern crate first_crate;
+use first_crate::OtherTrait;
+
+#[cfg(not(second_run))]
+trait Foo: OtherTrait {}
+
+#[cfg(second_run)]
+trait Bar: OtherTrait {}
diff --git a/src/test/run-make/incr-prev-body-beyond-eof/Makefile b/src/test/run-make/incr-prev-body-beyond-eof/Makefile
new file mode 100644
index 000000000..24eea3aca
--- /dev/null
+++ b/src/test/run-make/incr-prev-body-beyond-eof/Makefile
@@ -0,0 +1,19 @@
+# ignore-none no-std is not supported
+# ignore-nvptx64-nvidia-cuda FIXME: can't find crate for `std`
+
+include ../../run-make-fulldeps/tools.mk
+
+# Tests that we don't ICE during incremental compilation after modifying a
+# function span such that its previous end line exceeds the number of lines
+# in the new file, but its start line/column and length remain the same.
+
+SRC=$(TMPDIR)/src
+INCR=$(TMPDIR)/incr
+
+all:
+ mkdir $(SRC)
+ mkdir $(INCR)
+ cp a.rs $(SRC)/main.rs
+ $(RUSTC) -C incremental=$(INCR) $(SRC)/main.rs --target $(TARGET)
+ cp b.rs $(SRC)/main.rs
+ $(RUSTC) -C incremental=$(INCR) $(SRC)/main.rs --target $(TARGET)
diff --git a/src/test/run-make/incr-prev-body-beyond-eof/a.rs b/src/test/run-make/incr-prev-body-beyond-eof/a.rs
new file mode 100644
index 000000000..ca70fb563
--- /dev/null
+++ b/src/test/run-make/incr-prev-body-beyond-eof/a.rs
@@ -0,0 +1,16 @@
+fn main() {
+ // foo must be used.
+ foo();
+}
+
+// For this test to operate correctly, foo's body must start on exactly the same
+// line and column and have the exact same length in bytes in a.rs and b.rs. In
+// a.rs, the body must end on a line number which does not exist in b.rs.
+// Basically, avoid modifying this file, including adding or removing whitespace!
+fn foo() {
+ assert_eq!(1, 1);
+
+
+
+
+}
diff --git a/src/test/run-make/incr-prev-body-beyond-eof/b.rs b/src/test/run-make/incr-prev-body-beyond-eof/b.rs
new file mode 100644
index 000000000..a272e44a6
--- /dev/null
+++ b/src/test/run-make/incr-prev-body-beyond-eof/b.rs
@@ -0,0 +1,12 @@
+fn main() {
+ // foo must be used.
+ foo();
+}
+
+// For this test to operate correctly, foo's body must start on exactly the same
+// line and column and have the exact same length in bytes in a.rs and b.rs. In
+// a.rs, the body must end on a line number which does not exist in b.rs.
+// Basically, avoid modifying this file, including adding or removing whitespace!
+fn foo() {
+ assert_eq!(1, 1);////
+}
diff --git a/src/test/run-make/incremental-session-fail/Makefile b/src/test/run-make/incremental-session-fail/Makefile
new file mode 100644
index 000000000..0461bb926
--- /dev/null
+++ b/src/test/run-make/incremental-session-fail/Makefile
@@ -0,0 +1,14 @@
+include ../../run-make-fulldeps/tools.mk
+
+SESSION_DIR := $(TMPDIR)/session
+OUTPUT_FILE := $(TMPDIR)/build-output
+
+all:
+ echo $(TMPDIR)
+ # Make it so that rustc will fail to create a session directory.
+ touch $(SESSION_DIR)
+ # Check exit code is 1 for an error, and not 101 for ICE.
+ $(RUSTC) foo.rs --crate-type=rlib -C incremental=$(SESSION_DIR) > $(OUTPUT_FILE) 2>&1; [ $$? -eq 1 ]
+ $(CGREP) "Could not create incremental compilation crate directory" < $(OUTPUT_FILE)
+ # -v tests are fragile, hopefully this text won't change
+ $(CGREP) -v "internal compiler error" < $(OUTPUT_FILE)
diff --git a/src/test/run-make/incremental-session-fail/foo.rs b/src/test/run-make/incremental-session-fail/foo.rs
new file mode 100644
index 000000000..d11c69f81
--- /dev/null
+++ b/src/test/run-make/incremental-session-fail/foo.rs
@@ -0,0 +1 @@
+// intentionally empty
diff --git a/src/test/run-make/invalid-so/Makefile b/src/test/run-make/invalid-so/Makefile
new file mode 100644
index 000000000..5b82ecd20
--- /dev/null
+++ b/src/test/run-make/invalid-so/Makefile
@@ -0,0 +1,7 @@
+include ../../run-make-fulldeps/tools.mk
+
+DYLIB_NAME := $(shell echo | $(RUSTC) --crate-name foo --crate-type dylib --print file-names -)
+
+all:
+ echo >> $(TMPDIR)/$(DYLIB_NAME)
+ $(RUSTC) --crate-type lib --extern foo=$(TMPDIR)/$(DYLIB_NAME) bar.rs 2>&1 | $(CGREP) 'invalid metadata files for crate `foo`'
diff --git a/src/test/run-make/invalid-so/bar.rs b/src/test/run-make/invalid-so/bar.rs
new file mode 100644
index 000000000..49af74e1b
--- /dev/null
+++ b/src/test/run-make/invalid-so/bar.rs
@@ -0,0 +1 @@
+extern crate foo;
diff --git a/src/test/run-make/issue-10971-temps-dir/Makefile b/src/test/run-make/issue-10971-temps-dir/Makefile
new file mode 100644
index 000000000..5ce271926
--- /dev/null
+++ b/src/test/run-make/issue-10971-temps-dir/Makefile
@@ -0,0 +1,10 @@
+-include ../../run-make-fulldeps/tools.mk
+
+# Regression test for issue #10971
+# Running two invocations in parallel would overwrite each other's temp files.
+
+all:
+ touch $(TMPDIR)/lib.rs
+
+ $(RUSTC) --crate-type=lib -Z temps-dir=$(TMPDIR)/temp1 $(TMPDIR)/lib.rs & \
+ $(RUSTC) --crate-type=staticlib -Z temps-dir=$(TMPDIR)/temp2 $(TMPDIR)/lib.rs
diff --git a/src/test/run-make/issue-36710/Makefile b/src/test/run-make/issue-36710/Makefile
new file mode 100644
index 000000000..b5270ad2b
--- /dev/null
+++ b/src/test/run-make/issue-36710/Makefile
@@ -0,0 +1,20 @@
+# ignore-riscv64 $(call RUN,foo) expects to run the target executable natively
+# so it won't work with remote-test-server
+# ignore-arm Another build using remote-test-server
+# ignore-none no-std is not supported
+# ignore-wasm32 FIXME: don't attempt to compile C++ to WASM
+# ignore-wasm64 FIXME: don't attempt to compile C++ to WASM
+# ignore-nvptx64-nvidia-cuda FIXME: can't find crate for `std`
+# ignore-musl FIXME: this makefile needs teaching how to use a musl toolchain
+# (see dist-i586-gnu-i586-i686-musl Dockerfile)
+
+include ../../run-make-fulldeps/tools.mk
+
+all: foo
+ $(call RUN,foo)
+
+foo: foo.rs $(call NATIVE_STATICLIB,foo)
+ $(RUSTC) $< -lfoo $(EXTRARSCXXFLAGS) --target $(TARGET)
+
+$(TMPDIR)/libfoo.o: foo.cpp
+ $(call COMPILE_OBJ_CXX,$@,$<)
diff --git a/src/test/run-make/issue-36710/foo.cpp b/src/test/run-make/issue-36710/foo.cpp
new file mode 100644
index 000000000..8f878c2c2
--- /dev/null
+++ b/src/test/run-make/issue-36710/foo.cpp
@@ -0,0 +1,15 @@
+#include <stdint.h>
+
+struct A {
+ A() { v = 1234; }
+ ~A() { v = 1; }
+ uint32_t v;
+};
+
+A a;
+
+extern "C" {
+ uint32_t get() {
+ return a.v;
+ }
+}
diff --git a/src/test/run-make/issue-36710/foo.rs b/src/test/run-make/issue-36710/foo.rs
new file mode 100644
index 000000000..f30a35e27
--- /dev/null
+++ b/src/test/run-make/issue-36710/foo.rs
@@ -0,0 +1,10 @@
+// Tests that linking to C++ code with global destructors works.
+
+extern "C" {
+ fn get() -> u32;
+}
+
+fn main() {
+ let i = unsafe { get() };
+ assert_eq!(i, 1234);
+}
diff --git a/src/test/run-make/issue-47384/Makefile b/src/test/run-make/issue-47384/Makefile
new file mode 100644
index 000000000..f10365f8c
--- /dev/null
+++ b/src/test/run-make/issue-47384/Makefile
@@ -0,0 +1,12 @@
+-include ../../run-make-fulldeps/tools.mk
+
+# only-linux
+# ignore-cross-compile
+
+all: main.rs
+ $(RUSTC) --crate-type lib lib.rs
+ $(RUSTC) --crate-type cdylib -Clink-args="-Tlinker.ld" main.rs
+ # Ensure `#[used]` and `KEEP`-ed section is there
+ objdump -s -j".static" $(TMPDIR)/libmain.so
+ # Ensure `#[no_mangle]` symbol is there
+ nm $(TMPDIR)/libmain.so | $(CGREP) bar
diff --git a/src/test/run-make/issue-47384/lib.rs b/src/test/run-make/issue-47384/lib.rs
new file mode 100644
index 000000000..99508bcda
--- /dev/null
+++ b/src/test/run-make/issue-47384/lib.rs
@@ -0,0 +1,12 @@
+mod foo {
+ #[link_section = ".rodata.STATIC"]
+ #[used]
+ static STATIC: [u32; 10] = [1; 10];
+}
+
+mod bar {
+ #[no_mangle]
+ extern "C" fn bar() -> i32 {
+ 0
+ }
+}
diff --git a/src/test/run-make/issue-47384/linker.ld b/src/test/run-make/issue-47384/linker.ld
new file mode 100644
index 000000000..2e70acab3
--- /dev/null
+++ b/src/test/run-make/issue-47384/linker.ld
@@ -0,0 +1,7 @@
+SECTIONS
+{
+ .static : ALIGN(4)
+ {
+ KEEP(*(.rodata.STATIC));
+ }
+}
diff --git a/src/test/run-make/issue-47384/main.rs b/src/test/run-make/issue-47384/main.rs
new file mode 100644
index 000000000..025726325
--- /dev/null
+++ b/src/test/run-make/issue-47384/main.rs
@@ -0,0 +1 @@
+extern crate lib;
diff --git a/src/test/run-make/issue-71519/Makefile b/src/test/run-make/issue-71519/Makefile
new file mode 100644
index 000000000..636665ec1
--- /dev/null
+++ b/src/test/run-make/issue-71519/Makefile
@@ -0,0 +1,6 @@
+-include ../../run-make-fulldeps/tools.mk
+
+# needs-rust-lld
+all:
+ RUSTC_LOG=rustc_codegen_ssa::back::link=info $(RUSTC) -Z gcc-ld=lld -C link-args=-Wl,-v main.rs 2> $(TMPDIR)/output.txt
+ $(CGREP) -e "^LLD [0-9]+\.[0-9]+\.[0-9]+" < $(TMPDIR)/output.txt
diff --git a/src/test/run-make/issue-71519/main.rs b/src/test/run-make/issue-71519/main.rs
new file mode 100644
index 000000000..f8d09e897
--- /dev/null
+++ b/src/test/run-make/issue-71519/main.rs
@@ -0,0 +1,4 @@
+// test linking using cc with rust-lld injected into search path as ld
+// see rust-lang/rust#71519 for more info
+
+fn main() {}
diff --git a/src/test/run-make/issue-83112-incr-test-moved-file/Makefile b/src/test/run-make/issue-83112-incr-test-moved-file/Makefile
new file mode 100644
index 000000000..2f796e5b2
--- /dev/null
+++ b/src/test/run-make/issue-83112-incr-test-moved-file/Makefile
@@ -0,0 +1,25 @@
+include ../../run-make-fulldeps/tools.mk
+
+# ignore-none no-std is not supported
+# ignore-nvptx64-nvidia-cuda FIXME: can't find crate for 'std'
+
+# Regression test for issue #83112
+# The generated test harness code contains spans with a dummy location,
+# but a non-dummy SyntaxContext. Previously, the incremental cache was encoding
+# these spans as a full span (with a source file index), instead of skipping
+# the encoding of the location information. If the file gest moved, the hash
+# of the span will be unchanged (since it has a dummy location), so the incr
+# cache would end up try to load a non-existent file using the previously
+# enccoded source file id.
+
+SRC=$(TMPDIR)/src
+INCR=$(TMPDIR)/incr
+
+all:
+ mkdir $(SRC)
+ mkdir $(SRC)/mydir
+ mkdir $(INCR)
+ cp main.rs $(SRC)/main.rs
+ $(RUSTC) --test -C incremental=$(INCR) $(SRC)/main.rs --target $(TARGET)
+ mv $(SRC)/main.rs $(SRC)/mydir/main.rs
+ $(RUSTC) --test -C incremental=$(INCR) $(SRC)/mydir/main.rs --target $(TARGET)
diff --git a/src/test/run-make/issue-83112-incr-test-moved-file/main.rs b/src/test/run-make/issue-83112-incr-test-moved-file/main.rs
new file mode 100644
index 000000000..f328e4d9d
--- /dev/null
+++ b/src/test/run-make/issue-83112-incr-test-moved-file/main.rs
@@ -0,0 +1 @@
+fn main() {}
diff --git a/src/test/run-make/issue-85019-moved-src-dir/Makefile b/src/test/run-make/issue-85019-moved-src-dir/Makefile
new file mode 100644
index 000000000..3606d4fdf
--- /dev/null
+++ b/src/test/run-make/issue-85019-moved-src-dir/Makefile
@@ -0,0 +1,28 @@
+include ../../run-make-fulldeps/tools.mk
+
+INCR=$(TMPDIR)/incr
+FIRST_SRC=$(TMPDIR)/first_src
+SECOND_SRC=$(TMPDIR)/second_src
+
+# ignore-none no-std is not supported
+# ignore-nvptx64-nvidia-cuda FIXME: can't find crate for 'std'
+
+# Tests that we don't get an ICE when the working directory
+# (but not the build directory!) changes between compilation
+# sessions
+
+all:
+ mkdir $(INCR)
+ # Build from 'FIRST_SRC'
+ mkdir $(FIRST_SRC)
+ cp my_lib.rs $(FIRST_SRC)/my_lib.rs
+ cp main.rs $(FIRST_SRC)/main.rs
+ cd $(FIRST_SRC) && \
+ $(RUSTC) -C incremental=$(INCR) --crate-type lib my_lib.rs --target $(TARGET) && \
+ $(RUSTC) -C incremental=$(INCR) --extern my_lib=$(TMPDIR)/libmy_lib.rlib main.rs --target $(TARGET)
+ # Build from 'SECOND_SRC', keeping the output directory and incremental directory
+ # the same
+ mv $(FIRST_SRC) $(SECOND_SRC)
+ cd $(SECOND_SRC) && \
+ $(RUSTC) -C incremental=$(INCR) --crate-type lib my_lib.rs --target $(TARGET) && \
+ $(RUSTC) -C incremental=$(INCR) --extern my_lib=$(TMPDIR)/libmy_lib.rlib main.rs --target $(TARGET)
diff --git a/src/test/run-make/issue-85019-moved-src-dir/main.rs b/src/test/run-make/issue-85019-moved-src-dir/main.rs
new file mode 100644
index 000000000..543559a5c
--- /dev/null
+++ b/src/test/run-make/issue-85019-moved-src-dir/main.rs
@@ -0,0 +1,5 @@
+extern crate my_lib;
+
+fn main() {
+ my_lib::my_fn("hi");
+}
diff --git a/src/test/run-make/issue-85019-moved-src-dir/my_lib.rs b/src/test/run-make/issue-85019-moved-src-dir/my_lib.rs
new file mode 100644
index 000000000..432875739
--- /dev/null
+++ b/src/test/run-make/issue-85019-moved-src-dir/my_lib.rs
@@ -0,0 +1 @@
+pub fn my_fn<T: Copy>(_val: T) {}
diff --git a/src/test/run-make/issue-85441/Makefile b/src/test/run-make/issue-85441/Makefile
new file mode 100644
index 000000000..c7ae708c1
--- /dev/null
+++ b/src/test/run-make/issue-85441/Makefile
@@ -0,0 +1,9 @@
+# only-windows-msvc
+
+-include ../../run-make-fulldeps/tools.mk
+
+# Tests that WS2_32.dll is not unnecessarily linked, see issue #85441
+
+all:
+ $(RUSTC) empty.rs
+ objdump -p $(TMPDIR)/empty.exe | $(CGREP) -v -i "WS2_32.dll"
diff --git a/src/test/run-make/issue-85441/empty.rs b/src/test/run-make/issue-85441/empty.rs
new file mode 100644
index 000000000..f328e4d9d
--- /dev/null
+++ b/src/test/run-make/issue-85441/empty.rs
@@ -0,0 +1 @@
+fn main() {}
diff --git a/src/test/run-make/issue-88756-default-output/Makefile b/src/test/run-make/issue-88756-default-output/Makefile
new file mode 100644
index 000000000..cacbcbf39
--- /dev/null
+++ b/src/test/run-make/issue-88756-default-output/Makefile
@@ -0,0 +1,4 @@
+-include ../../run-make-fulldeps/tools.mk
+
+all:
+ $(BARE_RUSTDOC) 2>&1 | sed -E 's@/nightly/|/beta/|/stable/|/1\.[0-9]+\.[0-9]+/@/$$CHANNEL/@g' | diff - output-default.stdout
diff --git a/src/test/run-make/issue-88756-default-output/README.md b/src/test/run-make/issue-88756-default-output/README.md
new file mode 100644
index 000000000..8cbfac4f7
--- /dev/null
+++ b/src/test/run-make/issue-88756-default-output/README.md
@@ -0,0 +1 @@
+This is a test to verify that the default behavior of `rustdoc` is printing out help output instead of erroring out (#88756).
diff --git a/src/test/run-make/issue-88756-default-output/output-default.stdout b/src/test/run-make/issue-88756-default-output/output-default.stdout
new file mode 100644
index 000000000..80cd08ee1
--- /dev/null
+++ b/src/test/run-make/issue-88756-default-output/output-default.stdout
@@ -0,0 +1,197 @@
+rustdoc [options] <input>
+
+Options:
+ -h, --help show this help message
+ -V, --version print rustdoc's version
+ -v, --verbose use verbose output
+ -w, --output-format [html]
+ the output type to write
+ --output PATH Which directory to place the output. This option is
+ deprecated, use --out-dir instead.
+ -o, --out-dir PATH which directory to place the output
+ --crate-name NAME
+ specify the name of this crate
+ --crate-type [bin|lib|rlib|dylib|cdylib|staticlib|proc-macro]
+ Comma separated list of types of crates
+ for the compiler to emit
+ -L, --library-path DIR
+ directory to add to crate search path
+ --cfg pass a --cfg to rustc
+ --check-cfg pass a --check-cfg to rustc
+ --extern NAME[=PATH]
+ pass an --extern to rustc
+ --extern-html-root-url NAME=URL
+ base URL to use for dependencies; for example,
+ "std=/doc" links std::vec::Vec to
+ /doc/std/vec/struct.Vec.html
+ --extern-html-root-takes-precedence
+ give precedence to `--extern-html-root-url`, not
+ `html_root_url`
+ -C, --codegen OPT[=VALUE]
+ pass a codegen option to rustc
+ --document-private-items
+ document private items
+ --document-hidden-items
+ document items that have doc(hidden)
+ --test run code examples as tests
+ --test-args ARGS
+ arguments to pass to the test runner
+ --test-run-directory PATH
+ The working directory in which to run tests
+ --target TRIPLE target triple to document
+ --markdown-css FILES
+ CSS files to include via <link> in a rendered Markdown
+ file
+ --html-in-header FILES
+ files to include inline in the <head> section of a
+ rendered Markdown file or generated documentation
+ --html-before-content FILES
+ files to include inline between <body> and the content
+ of a rendered Markdown file or generated documentation
+ --html-after-content FILES
+ files to include inline between the content and
+ </body> of a rendered Markdown file or generated
+ documentation
+ --markdown-before-content FILES
+ files to include inline between <body> and the content
+ of a rendered Markdown file or generated documentation
+ --markdown-after-content FILES
+ files to include inline between the content and
+ </body> of a rendered Markdown file or generated
+ documentation
+ --markdown-playground-url URL
+ URL to send code snippets to
+ --markdown-no-toc
+ don't include table of contents
+ -e, --extend-css PATH
+ To add some CSS rules with a given file to generate
+ doc with your own theme. However, your theme might
+ break if the rustdoc's generated HTML changes, so be
+ careful!
+ -Z FLAG unstable / perma-unstable options (only on nightly
+ build)
+ --sysroot PATH Override the system root
+ --playground-url URL
+ URL to send code snippets to, may be reset by
+ --markdown-playground-url or
+ `#![doc(html_playground_url=...)]`
+ --display-doctest-warnings
+ show warnings that originate in doctests
+ --crate-version VERSION
+ crate version to print into documentation
+ --sort-modules-by-appearance
+ sort modules by where they appear in the program,
+ rather than alphabetically
+ --default-theme THEME
+ Set the default theme. THEME should be the theme name,
+ generally lowercase. If an unknown default theme is
+ specified, the builtin default is used. The set of
+ themes, and the rustdoc built-in default, are not
+ stable.
+ --default-setting SETTING[=VALUE]
+ Default value for a rustdoc setting (used when
+ "rustdoc-SETTING" is absent from web browser Local
+ Storage). If VALUE is not supplied, "true" is used.
+ Supported SETTINGs and VALUEs are not documented and
+ not stable.
+ --theme FILES additional themes which will be added to the generated
+ docs
+ --check-theme FILES
+ check if given theme is valid
+ --resource-suffix PATH
+ suffix to add to CSS and JavaScript files, e.g.,
+ "light.css" will become "light-suffix.css"
+ --edition EDITION
+ edition to use when compiling rust code (default:
+ 2015)
+ --color auto|always|never
+ Configure coloring of output:
+ auto = colorize, if output goes to a tty (default);
+ always = always colorize output;
+ never = never colorize output
+ --error-format human|json|short
+ How errors and other messages are produced
+ --diagnostic-width WIDTH
+ Provide width of the output for truncated error
+ messages
+ --json CONFIG Configure the structure of JSON diagnostics
+ --disable-minification
+ Disable minification applied on JS files
+ -A, --allow LINT Set lint allowed
+ -W, --warn LINT Set lint warnings
+ --force-warn LINT
+ Set lint force-warn
+ -D, --deny LINT Set lint denied
+ -F, --forbid LINT Set lint forbidden
+ --cap-lints LEVEL
+ Set the most restrictive lint level. More restrictive
+ lints are capped at this level. By default, it is at
+ `forbid` level.
+ --index-page PATH
+ Markdown file to be used as index page
+ --enable-index-page
+ To enable generation of the index page
+ --static-root-path PATH
+ Path string to force loading static files from in
+ output pages. If not set, uses combinations of '../'
+ to reach the documentation root.
+ --disable-per-crate-search
+ disables generating the crate selector on the search
+ box
+ --persist-doctests PATH
+ Directory to persist doctest executables into
+ --show-coverage
+ calculate percentage of public items with
+ documentation
+ --enable-per-target-ignores
+ parse ignore-foo for ignoring doctests on a per-target
+ basis
+ --runtool The tool to run tests with when building for a different target than host
+
+ --runtool-arg One (of possibly many) arguments to pass to the runtool
+
+ --test-builder PATH
+ The rustc-like binary to use as the test builder
+ --check Run rustdoc checks
+ --generate-redirect-map
+ Generate JSON file at the top level instead of
+ generating HTML redirection files
+ --emit [unversioned-shared-resources,toolchain-shared-resources,invocation-specific]
+ Comma separated list of types of output for rustdoc to
+ emit
+ --no-run Compile doctests without running them
+ --show-type-layout
+ Include the memory layout of types in the docs
+ --nocapture Don't capture stdout and stderr of tests
+ --generate-link-to-definition
+ Make the identifiers in the HTML source code pages
+ navigable
+ --scrape-examples-output-path collect function call information and output at the given path
+
+ --scrape-examples-target-crate collect function call information for functions from the target crate
+
+ --scrape-tests Include test code when scraping examples
+ --with-examples path to function call information (for displaying examples in the documentation)
+
+ --plugin-path DIR
+ removed, see issue #44136
+ <https://github.com/rust-lang/rust/issues/44136> for
+ more information
+ --passes PASSES removed, see issue #44136
+ <https://github.com/rust-lang/rust/issues/44136> for
+ more information
+ --plugins PLUGINS
+ removed, see issue #44136
+ <https://github.com/rust-lang/rust/issues/44136> for
+ more information
+ --no-defaults removed, see issue #44136
+ <https://github.com/rust-lang/rust/issues/44136> for
+ more information
+ -r, --input-format [rust]
+ removed, see issue #44136
+ <https://github.com/rust-lang/rust/issues/44136> for
+ more information
+
+ @path Read newline separated options from `path`
+
+More information available at https://doc.rust-lang.org/$CHANNEL/rustdoc/what-is-rustdoc.html
diff --git a/src/test/run-make/issue-88756-default-output/x.rs b/src/test/run-make/issue-88756-default-output/x.rs
new file mode 100644
index 000000000..5df757613
--- /dev/null
+++ b/src/test/run-make/issue-88756-default-output/x.rs
@@ -0,0 +1 @@
+// nothing to see here
diff --git a/src/test/run-make/issue-96498/Makefile b/src/test/run-make/issue-96498/Makefile
new file mode 100644
index 000000000..eae6400ae
--- /dev/null
+++ b/src/test/run-make/issue-96498/Makefile
@@ -0,0 +1,8 @@
+# only-windows
+# needs-rust-lld
+
+-include ../../run-make-fulldeps/tools.mk
+
+# Ensure that LLD can link
+all:
+ $(RUSTC) -C linker=rust-lld foo.rs
diff --git a/src/test/run-make/issue-96498/foo.rs b/src/test/run-make/issue-96498/foo.rs
new file mode 100644
index 000000000..93ac3641b
--- /dev/null
+++ b/src/test/run-make/issue-96498/foo.rs
@@ -0,0 +1,4 @@
+#![crate_type = "cdylib"]
+
+#[no_mangle]
+extern "C" fn foo() {}
diff --git a/src/test/run-make/libtest-thread-limit/Makefile b/src/test/run-make/libtest-thread-limit/Makefile
new file mode 100644
index 000000000..29c1bc71d
--- /dev/null
+++ b/src/test/run-make/libtest-thread-limit/Makefile
@@ -0,0 +1,7 @@
+-include ../../run-make-fulldeps/tools.mk
+
+# only-linux
+
+all:
+ $(RUSTC) test.rs --test --target $(TARGET)
+ $(shell ulimit -p 0 && $(call RUN,test))
diff --git a/src/test/run-make/libtest-thread-limit/test.rs b/src/test/run-make/libtest-thread-limit/test.rs
new file mode 100644
index 000000000..26bc29216
--- /dev/null
+++ b/src/test/run-make/libtest-thread-limit/test.rs
@@ -0,0 +1,20 @@
+#![feature(once_cell)]
+
+use std::{
+ io::ErrorKind,
+ sync::OnceLock,
+ thread::{self, Builder, ThreadId},
+};
+
+static THREAD_ID: OnceLock<ThreadId> = OnceLock::new();
+
+#[test]
+fn spawn_thread_would_block() {
+ assert_eq!(Builder::new().spawn(|| unreachable!()).unwrap_err().kind(), ErrorKind::WouldBlock);
+ THREAD_ID.set(thread::current().id()).unwrap();
+}
+
+#[test]
+fn run_in_same_thread() {
+ assert_eq!(*THREAD_ID.get().unwrap(), thread::current().id());
+}
diff --git a/src/test/run-make/llvm-outputs/Makefile b/src/test/run-make/llvm-outputs/Makefile
new file mode 100644
index 000000000..d7f67577b
--- /dev/null
+++ b/src/test/run-make/llvm-outputs/Makefile
@@ -0,0 +1,5 @@
+-include ../../run-make-fulldeps/tools.mk
+
+all:
+ echo 'fn main() {}' | $(BARE_RUSTC) - --out-dir=$(TMPDIR)/random_directory_that_does_not_exist_ir/ --emit=llvm-ir
+ echo 'fn main() {}' | $(BARE_RUSTC) - --out-dir=$(TMPDIR)/random_directory_that_does_not_exist_bc/ --emit=llvm-bc
diff --git a/src/test/run-make/native-link-modifier-bundle/Makefile b/src/test/run-make/native-link-modifier-bundle/Makefile
new file mode 100644
index 000000000..e4b0f74ac
--- /dev/null
+++ b/src/test/run-make/native-link-modifier-bundle/Makefile
@@ -0,0 +1,33 @@
+# ignore-cross-compile
+# ignore-windows-msvc
+
+-include ../../run-make-fulldeps/tools.mk
+
+# We're using the llvm-nm instead of the system nm to ensure it is compatible
+# with the LLVM bitcode generated by rustc.
+NM = "$(LLVM_BIN_DIR)"/llvm-nm
+
+all: $(call NATIVE_STATICLIB,native-staticlib)
+ # Build a staticlib and a rlib, the `native_func` symbol will be bundled into them
+ $(RUSTC) bundled.rs --crate-type=staticlib --crate-type=rlib
+ $(NM) $(TMPDIR)/libbundled.a | $(CGREP) -e "T _*native_func"
+ $(NM) $(TMPDIR)/libbundled.a | $(CGREP) -e "U _*native_func"
+ $(NM) $(TMPDIR)/libbundled.rlib | $(CGREP) -e "T _*native_func"
+ $(NM) $(TMPDIR)/libbundled.rlib | $(CGREP) -e "U _*native_func"
+
+ # Build a staticlib and a rlib, the `native_func` symbol will not be bundled into it
+ $(RUSTC) non-bundled.rs --crate-type=staticlib --crate-type=rlib
+ $(NM) $(TMPDIR)/libnon_bundled.a | $(CGREP) -ve "T _*native_func"
+ $(NM) $(TMPDIR)/libnon_bundled.a | $(CGREP) -e "U _*native_func"
+ $(NM) $(TMPDIR)/libnon_bundled.rlib | $(CGREP) -ve "T _*native_func"
+ $(NM) $(TMPDIR)/libnon_bundled.rlib | $(CGREP) -e "U _*native_func"
+
+ # Build a cdylib, `native-staticlib` will not appear on the linker line because it was bundled previously
+ # The cdylib will contain the `native_func` symbol in the end
+ $(RUSTC) cdylib-bundled.rs --crate-type=cdylib --print link-args | $(CGREP) -ve '-l[" ]*native-staticlib'
+ $(NM) $(call DYLIB,cdylib_bundled) | $(CGREP) -e "[Tt] _*native_func"
+
+ # Build a cdylib, `native-staticlib` will appear on the linker line because it was not bundled previously
+ # The cdylib will contain the `native_func` symbol in the end
+ $(RUSTC) cdylib-non-bundled.rs --crate-type=cdylib --print link-args | $(CGREP) -e '-l[" ]*native-staticlib'
+ $(NM) $(call DYLIB,cdylib_non_bundled) | $(CGREP) -e "[Tt] _*native_func"
diff --git a/src/test/run-make/native-link-modifier-bundle/bundled.rs b/src/test/run-make/native-link-modifier-bundle/bundled.rs
new file mode 100644
index 000000000..0bbae8752
--- /dev/null
+++ b/src/test/run-make/native-link-modifier-bundle/bundled.rs
@@ -0,0 +1,11 @@
+#[link(name = "native-staticlib", kind = "static", modifiers = "+bundle")]
+extern "C" {
+ pub fn native_func();
+}
+
+#[no_mangle]
+pub extern "C" fn wrapped_func() {
+ unsafe {
+ native_func();
+ }
+}
diff --git a/src/test/run-make/native-link-modifier-bundle/cdylib-bundled.rs b/src/test/run-make/native-link-modifier-bundle/cdylib-bundled.rs
new file mode 100644
index 000000000..729130916
--- /dev/null
+++ b/src/test/run-make/native-link-modifier-bundle/cdylib-bundled.rs
@@ -0,0 +1 @@
+extern crate bundled;
diff --git a/src/test/run-make/native-link-modifier-bundle/cdylib-non-bundled.rs b/src/test/run-make/native-link-modifier-bundle/cdylib-non-bundled.rs
new file mode 100644
index 000000000..1df81fd10
--- /dev/null
+++ b/src/test/run-make/native-link-modifier-bundle/cdylib-non-bundled.rs
@@ -0,0 +1 @@
+extern crate non_bundled;
diff --git a/src/test/run-make/native-link-modifier-bundle/native-staticlib.c b/src/test/run-make/native-link-modifier-bundle/native-staticlib.c
new file mode 100644
index 000000000..d300fdf1c
--- /dev/null
+++ b/src/test/run-make/native-link-modifier-bundle/native-staticlib.c
@@ -0,0 +1 @@
+void native_func() {}
diff --git a/src/test/run-make/native-link-modifier-bundle/non-bundled.rs b/src/test/run-make/native-link-modifier-bundle/non-bundled.rs
new file mode 100644
index 000000000..8181e6387
--- /dev/null
+++ b/src/test/run-make/native-link-modifier-bundle/non-bundled.rs
@@ -0,0 +1,11 @@
+#[link(name = "native-staticlib", kind = "static", modifiers = "-bundle")]
+extern "C" {
+ pub fn native_func();
+}
+
+#[no_mangle]
+pub extern "C" fn wrapped_func() {
+ unsafe {
+ native_func();
+ }
+}
diff --git a/src/test/run-make/native-link-modifier-whole-archive/Makefile b/src/test/run-make/native-link-modifier-whole-archive/Makefile
new file mode 100644
index 000000000..967cb065c
--- /dev/null
+++ b/src/test/run-make/native-link-modifier-whole-archive/Makefile
@@ -0,0 +1,52 @@
+# ignore-cross-compile -- compiling C++ code does not work well when cross-compiling
+
+# This test case makes sure that native libraries are linked with appropriate semantics
+# when the `[+-]bundle,[+-]whole-archive` modifiers are applied to them.
+#
+# The test works by checking that the resulting executables produce the expected output,
+# part of which is emitted by otherwise unreferenced C code. If +whole-archive didn't work
+# that code would never make it into the final executable and we'd thus be missing some
+# of the output.
+
+-include ../../run-make-fulldeps/tools.mk
+
+all: $(TMPDIR)/$(call BIN,directly_linked) \
+ $(TMPDIR)/$(call BIN,directly_linked_test_plus_whole_archive) \
+ $(TMPDIR)/$(call BIN,directly_linked_test_minus_whole_archive) \
+ $(TMPDIR)/$(call BIN,indirectly_linked) \
+ $(TMPDIR)/$(call BIN,indirectly_linked_via_attr)
+ $(call RUN,directly_linked) | $(CGREP) 'static-initializer.directly_linked.'
+ $(call RUN,directly_linked_test_plus_whole_archive) --nocapture | $(CGREP) 'static-initializer.'
+ $(call RUN,directly_linked_test_minus_whole_archive) --nocapture | $(CGREP) -v 'static-initializer.'
+ $(call RUN,indirectly_linked) | $(CGREP) 'static-initializer.indirectly_linked.'
+ $(call RUN,indirectly_linked_via_attr) | $(CGREP) 'static-initializer.native_lib_in_src.'
+
+# Native lib linked directly into executable
+$(TMPDIR)/$(call BIN,directly_linked): $(call NATIVE_STATICLIB,c_static_lib_with_constructor)
+ $(RUSTC) directly_linked.rs -l static:+whole-archive=c_static_lib_with_constructor
+
+# Native lib linked into test executable, +whole-archive
+$(TMPDIR)/$(call BIN,directly_linked_test_plus_whole_archive): $(call NATIVE_STATICLIB,c_static_lib_with_constructor)
+ $(RUSTC) directly_linked_test_plus_whole_archive.rs --test -l static:+whole-archive=c_static_lib_with_constructor
+# Native lib linked into test executable, -whole-archive
+$(TMPDIR)/$(call BIN,directly_linked_test_minus_whole_archive): $(call NATIVE_STATICLIB,c_static_lib_with_constructor)
+ $(RUSTC) directly_linked_test_minus_whole_archive.rs --test -l static:-whole-archive=c_static_lib_with_constructor
+
+# Native lib linked into RLIB via `-l static:-bundle,+whole-archive`, RLIB linked into executable
+$(TMPDIR)/$(call BIN,indirectly_linked): $(TMPDIR)/librlib_with_cmdline_native_lib.rlib
+ $(RUSTC) indirectly_linked.rs
+
+# Native lib linked into RLIB via #[link] attribute, RLIB linked into executable
+$(TMPDIR)/$(call BIN,indirectly_linked_via_attr): $(TMPDIR)/libnative_lib_in_src.rlib
+ $(RUSTC) indirectly_linked_via_attr.rs
+
+# Native lib linked into rlib with via commandline
+$(TMPDIR)/librlib_with_cmdline_native_lib.rlib: $(call NATIVE_STATICLIB,c_static_lib_with_constructor)
+ $(RUSTC) rlib_with_cmdline_native_lib.rs --crate-type=rlib -l static:-bundle,+whole-archive=c_static_lib_with_constructor
+
+# Native lib linked into rlib via `#[link()]` attribute on extern block.
+$(TMPDIR)/libnative_lib_in_src.rlib: $(call NATIVE_STATICLIB,c_static_lib_with_constructor)
+ $(RUSTC) native_lib_in_src.rs --crate-type=rlib
+
+$(TMPDIR)/libc_static_lib_with_constructor.o: c_static_lib_with_constructor.cpp
+ $(call COMPILE_OBJ_CXX,$@,$<)
diff --git a/src/test/run-make/native-link-modifier-whole-archive/c_static_lib_with_constructor.cpp b/src/test/run-make/native-link-modifier-whole-archive/c_static_lib_with_constructor.cpp
new file mode 100644
index 000000000..c687eb0f0
--- /dev/null
+++ b/src/test/run-make/native-link-modifier-whole-archive/c_static_lib_with_constructor.cpp
@@ -0,0 +1,11 @@
+#include <cstdio>
+
+// Since this is a global variable, its constructor will be called before
+// main() is executed. But only if the object file containing it actually
+// gets linked into the executable.
+struct Foo {
+ Foo() {
+ printf("static-initializer.");
+ fflush(stdout);
+ }
+} FOO;
diff --git a/src/test/run-make/native-link-modifier-whole-archive/directly_linked.rs b/src/test/run-make/native-link-modifier-whole-archive/directly_linked.rs
new file mode 100644
index 000000000..17518e8b2
--- /dev/null
+++ b/src/test/run-make/native-link-modifier-whole-archive/directly_linked.rs
@@ -0,0 +1,6 @@
+use std::io::Write;
+
+fn main() {
+ print!("directly_linked.");
+ std::io::stdout().flush().unwrap();
+}
diff --git a/src/test/run-make/native-link-modifier-whole-archive/directly_linked_test_minus_whole_archive.rs b/src/test/run-make/native-link-modifier-whole-archive/directly_linked_test_minus_whole_archive.rs
new file mode 100644
index 000000000..20ed8d9d4
--- /dev/null
+++ b/src/test/run-make/native-link-modifier-whole-archive/directly_linked_test_minus_whole_archive.rs
@@ -0,0 +1,7 @@
+use std::io::Write;
+
+#[test]
+fn test_thing() {
+ print!("ran the test");
+ std::io::stdout().flush().unwrap();
+}
diff --git a/src/test/run-make/native-link-modifier-whole-archive/directly_linked_test_plus_whole_archive.rs b/src/test/run-make/native-link-modifier-whole-archive/directly_linked_test_plus_whole_archive.rs
new file mode 100644
index 000000000..20ed8d9d4
--- /dev/null
+++ b/src/test/run-make/native-link-modifier-whole-archive/directly_linked_test_plus_whole_archive.rs
@@ -0,0 +1,7 @@
+use std::io::Write;
+
+#[test]
+fn test_thing() {
+ print!("ran the test");
+ std::io::stdout().flush().unwrap();
+}
diff --git a/src/test/run-make/native-link-modifier-whole-archive/indirectly_linked.rs b/src/test/run-make/native-link-modifier-whole-archive/indirectly_linked.rs
new file mode 100644
index 000000000..c8b83fcfe
--- /dev/null
+++ b/src/test/run-make/native-link-modifier-whole-archive/indirectly_linked.rs
@@ -0,0 +1,5 @@
+extern crate rlib_with_cmdline_native_lib;
+
+fn main() {
+ rlib_with_cmdline_native_lib::hello();
+}
diff --git a/src/test/run-make/native-link-modifier-whole-archive/indirectly_linked_via_attr.rs b/src/test/run-make/native-link-modifier-whole-archive/indirectly_linked_via_attr.rs
new file mode 100644
index 000000000..b9e347609
--- /dev/null
+++ b/src/test/run-make/native-link-modifier-whole-archive/indirectly_linked_via_attr.rs
@@ -0,0 +1,5 @@
+extern crate native_lib_in_src;
+
+fn main() {
+ native_lib_in_src::hello();
+}
diff --git a/src/test/run-make/native-link-modifier-whole-archive/native_lib_in_src.rs b/src/test/run-make/native-link-modifier-whole-archive/native_lib_in_src.rs
new file mode 100644
index 000000000..971f3be7a
--- /dev/null
+++ b/src/test/run-make/native-link-modifier-whole-archive/native_lib_in_src.rs
@@ -0,0 +1,11 @@
+use std::io::Write;
+
+#[link(name = "c_static_lib_with_constructor",
+ kind = "static",
+ modifiers = "-bundle,+whole-archive")]
+extern {}
+
+pub fn hello() {
+ print!("native_lib_in_src.");
+ std::io::stdout().flush().unwrap();
+}
diff --git a/src/test/run-make/native-link-modifier-whole-archive/rlib_with_cmdline_native_lib.rs b/src/test/run-make/native-link-modifier-whole-archive/rlib_with_cmdline_native_lib.rs
new file mode 100644
index 000000000..ef2b702dd
--- /dev/null
+++ b/src/test/run-make/native-link-modifier-whole-archive/rlib_with_cmdline_native_lib.rs
@@ -0,0 +1,6 @@
+use std::io::Write;
+
+pub fn hello() {
+ print!("indirectly_linked.");
+ std::io::stdout().flush().unwrap();
+}
diff --git a/src/test/run-make/pass-linker-flags-from-dep/Makefile b/src/test/run-make/pass-linker-flags-from-dep/Makefile
new file mode 100644
index 000000000..365216b4c
--- /dev/null
+++ b/src/test/run-make/pass-linker-flags-from-dep/Makefile
@@ -0,0 +1,10 @@
+-include ../../run-make-fulldeps/tools.mk
+
+all:
+ # Build deps
+ $(RUSTC) native_dep_1.rs --crate-type=staticlib
+ $(RUSTC) native_dep_2.rs --crate-type=staticlib
+ $(RUSTC) rust_dep.rs -l static:-bundle=native_dep_1 -l link-arg=some_flag -l static:-bundle=native_dep_2 --crate-type=lib -Z unstable-options
+
+ # Check sequence of linker args
+ $(RUSTC) main.rs --extern lib=$(TMPDIR)/librust_dep.rlib --crate-type=bin --print link-args | $(CGREP) -e 'native_dep_1.*some_flag.*native_dep_2'
diff --git a/src/test/run-make/pass-linker-flags-from-dep/main.rs b/src/test/run-make/pass-linker-flags-from-dep/main.rs
new file mode 100644
index 000000000..40952fb22
--- /dev/null
+++ b/src/test/run-make/pass-linker-flags-from-dep/main.rs
@@ -0,0 +1,3 @@
+fn main() {
+ lib::f();
+}
diff --git a/src/test/run-make/pass-linker-flags-from-dep/native_dep_1.rs b/src/test/run-make/pass-linker-flags-from-dep/native_dep_1.rs
new file mode 100644
index 000000000..fdb2d9ca6
--- /dev/null
+++ b/src/test/run-make/pass-linker-flags-from-dep/native_dep_1.rs
@@ -0,0 +1 @@
+pub fn f1() {}
diff --git a/src/test/run-make/pass-linker-flags-from-dep/native_dep_2.rs b/src/test/run-make/pass-linker-flags-from-dep/native_dep_2.rs
new file mode 100644
index 000000000..f788b7711
--- /dev/null
+++ b/src/test/run-make/pass-linker-flags-from-dep/native_dep_2.rs
@@ -0,0 +1 @@
+pub fn f2() {}
diff --git a/src/test/run-make/pass-linker-flags-from-dep/rust_dep.rs b/src/test/run-make/pass-linker-flags-from-dep/rust_dep.rs
new file mode 100644
index 000000000..7f5df1139
--- /dev/null
+++ b/src/test/run-make/pass-linker-flags-from-dep/rust_dep.rs
@@ -0,0 +1,9 @@
+extern "C" {
+ pub fn foo();
+}
+
+pub fn f() {
+ unsafe {
+ foo();
+ }
+}
diff --git a/src/test/run-make/pass-linker-flags/Makefile b/src/test/run-make/pass-linker-flags/Makefile
new file mode 100644
index 000000000..02b1e2179
--- /dev/null
+++ b/src/test/run-make/pass-linker-flags/Makefile
@@ -0,0 +1,4 @@
+-include ../../run-make-fulldeps/tools.mk
+
+all:
+ $(RUSTC) rs.rs -Z unstable-options -l static=l1 -l link-arg=a1 -l static=l2 -l link-arg=a2 -l dylib=d1 -l link-arg=a3 --print link-args | $(CGREP) -e 'l1.*a1.*l2.*a2.*d1.*a3'
diff --git a/src/test/run-make/pass-linker-flags/rs.rs b/src/test/run-make/pass-linker-flags/rs.rs
new file mode 100644
index 000000000..f328e4d9d
--- /dev/null
+++ b/src/test/run-make/pass-linker-flags/rs.rs
@@ -0,0 +1 @@
+fn main() {}
diff --git a/src/test/run-make/raw-dylib-alt-calling-convention/Makefile b/src/test/run-make/raw-dylib-alt-calling-convention/Makefile
new file mode 100644
index 000000000..a254285ab
--- /dev/null
+++ b/src/test/run-make/raw-dylib-alt-calling-convention/Makefile
@@ -0,0 +1,32 @@
+# Test the behavior of #[link(.., kind = "raw-dylib")] with alternative calling conventions.
+
+# only-x86
+# only-windows
+
+-include ../../run-make-fulldeps/tools.mk
+
+all:
+ $(RUSTC) --crate-type lib --crate-name raw_dylib_alt_calling_convention_test lib.rs
+ $(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
+ $(call COMPILE_OBJ,"$(TMPDIR)"/extern.obj,extern.c)
+ifdef IS_MSVC
+ $(CC) "$(TMPDIR)"/extern.obj -link -dll -out:"$(TMPDIR)"/extern.dll -noimplib
+else
+ $(CC) "$(TMPDIR)"/extern.obj -shared -o "$(TMPDIR)"/extern.dll
+endif
+
+ "$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt
+ifdef RUSTC_BLESS_TEST
+ cp "$(TMPDIR)"/output.txt output.txt
+else
+ $(DIFF) output.txt "$(TMPDIR)"/output.txt
+endif
+
+ifdef IS_MSVC
+ "$(TMPDIR)"/driver true > "$(TMPDIR)"/output.msvc.txt
+ifdef RUSTC_BLESS_TEST
+ cp "$(TMPDIR)"/output.msvc.txt output.msvc.txt
+else
+ $(DIFF) output.msvc.txt "$(TMPDIR)"/output.msvc.txt
+endif
+endif
diff --git a/src/test/run-make/raw-dylib-alt-calling-convention/driver.rs b/src/test/run-make/raw-dylib-alt-calling-convention/driver.rs
new file mode 100644
index 000000000..b7f372c6b
--- /dev/null
+++ b/src/test/run-make/raw-dylib-alt-calling-convention/driver.rs
@@ -0,0 +1,8 @@
+extern crate raw_dylib_alt_calling_convention_test;
+
+fn main() {
+ raw_dylib_alt_calling_convention_test::library_function(
+ std::env::args().skip(1).next().map_or(
+ false,
+ |s| std::str::FromStr::from_str(&s).unwrap()));
+}
diff --git a/src/test/run-make/raw-dylib-alt-calling-convention/extern.c b/src/test/run-make/raw-dylib-alt-calling-convention/extern.c
new file mode 100644
index 000000000..0c4d12af9
--- /dev/null
+++ b/src/test/run-make/raw-dylib-alt-calling-convention/extern.c
@@ -0,0 +1,178 @@
+#include <stdio.h>
+#include <stdint.h>
+
+struct S {
+ uint8_t x;
+ int32_t y;
+};
+
+struct S2 {
+ int32_t x;
+ uint8_t y;
+};
+
+struct S3 {
+ uint8_t x[5];
+};
+
+__declspec(dllexport) void __stdcall stdcall_fn_1(int i) {
+ printf("stdcall_fn_1(%d)\n", i);
+ fflush(stdout);
+}
+
+__declspec(dllexport) void __stdcall stdcall_fn_2(uint8_t i, float f) {
+ printf("stdcall_fn_2(%d, %.1f)\n", i, f);
+ fflush(stdout);
+}
+
+__declspec(dllexport) void __stdcall stdcall_fn_3(double d) {
+ printf("stdcall_fn_3(%.1f)\n", d);
+ fflush(stdout);
+}
+
+__declspec(dllexport) void __stdcall stdcall_fn_4(uint8_t i, uint8_t j, float f) {
+ printf("stdcall_fn_4(%d, %d, %.1f)\n", i, j, f);
+ fflush(stdout);
+}
+
+__declspec(dllexport) void __stdcall stdcall_fn_5(struct S s, int i) {
+ printf("stdcall_fn_5(S { x: %d, y: %d }, %d)\n", s.x, s.y, i);
+ fflush(stdout);
+}
+
+// Test that stdcall support works correctly with the nullable pointer optimization.
+__declspec(dllexport) void __stdcall stdcall_fn_6(struct S* s) {
+ if (s) {
+ printf("stdcall_fn_6(S { x: %d, y: %d })\n", s->x, s->y);
+ } else {
+ printf("stdcall_fn_6(null)\n");
+ }
+ fflush(stdout);
+}
+
+__declspec(dllexport) void __stdcall stdcall_fn_7(struct S2 s, int i) {
+ printf("stdcall_fn_7(S2 { x: %d, y: %d }, %d)\n", s.x, s.y, i);
+ fflush(stdout);
+}
+
+// Verify that we compute the correct amount of space in the argument list for a 5-byte struct.
+__declspec(dllexport) void __stdcall stdcall_fn_8(struct S3 s, struct S3 t) {
+ printf("stdcall_fn_8(S3 { x: [%d, %d, %d, %d, %d] }, S3 { x: [%d, %d, %d, %d, %d] })\n",
+ s.x[0], s.x[1], s.x[2], s.x[3], s.x[4],
+ t.x[0], t.x[1], t.x[2], t.x[3], t.x[4]
+ );
+ fflush(stdout);
+}
+
+// test whether f64/double values are aligned on 4-byte or 8-byte boundaries.
+__declspec(dllexport) void __stdcall stdcall_fn_9(uint8_t x, double y) {
+ printf("stdcall_fn_9(%d, %.1f)\n", x, y);
+ fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_1(int i) {
+ printf("fastcall_fn_1(%d)\n", i);
+ fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_2(uint8_t i, float f) {
+ printf("fastcall_fn_2(%d, %.1f)\n", i, f);
+ fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_3(double d) {
+ printf("fastcall_fn_3(%.1f)\n", d);
+ fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_4(uint8_t i, uint8_t j, float f) {
+ printf("fastcall_fn_4(%d, %d, %.1f)\n", i, j, f);
+ fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_5(struct S s, int i) {
+ printf("fastcall_fn_5(S { x: %d, y: %d }, %d)\n", s.x, s.y, i);
+ fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_6(struct S* s) {
+ if (s) {
+ printf("fastcall_fn_6(S { x: %d, y: %d })\n", s->x, s->y);
+ } else {
+ printf("fastcall_fn_6(null)\n");
+ }
+ fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_7(struct S2 s, int i) {
+ printf("fastcall_fn_7(S2 { x: %d, y: %d }, %d)\n", s.x, s.y, i);
+ fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_8(struct S3 s, struct S3 t) {
+ printf("fastcall_fn_8(S3 { x: [%d, %d, %d, %d, %d] }, S3 { x: [%d, %d, %d, %d, %d] })\n",
+ s.x[0], s.x[1], s.x[2], s.x[3], s.x[4],
+ t.x[0], t.x[1], t.x[2], t.x[3], t.x[4]
+ );
+ fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_9(uint8_t x, double y) {
+ printf("fastcall_fn_9(%d, %.1f)\n", x, y);
+ fflush(stdout);
+}
+
+// GCC doesn't support vectorcall: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89485
+#ifdef _MSC_VER
+__declspec(dllexport) void __vectorcall vectorcall_fn_1(int i) {
+ printf("vectorcall_fn_1(%d)\n", i);
+ fflush(stdout);
+}
+
+__declspec(dllexport) void __vectorcall vectorcall_fn_2(uint8_t i, float f) {
+ printf("vectorcall_fn_2(%d, %.1f)\n", i, f);
+ fflush(stdout);
+}
+
+__declspec(dllexport) void __vectorcall vectorcall_fn_3(double d) {
+ printf("vectorcall_fn_3(%.1f)\n", d);
+ fflush(stdout);
+}
+
+__declspec(dllexport) void __vectorcall vectorcall_fn_4(uint8_t i, uint8_t j, float f) {
+ printf("vectorcall_fn_4(%d, %d, %.1f)\n", i, j, f);
+ fflush(stdout);
+}
+
+__declspec(dllexport) void __vectorcall vectorcall_fn_5(struct S s, int i) {
+ printf("vectorcall_fn_5(S { x: %d, y: %d }, %d)\n", s.x, s.y, i);
+ fflush(stdout);
+}
+
+__declspec(dllexport) void __vectorcall vectorcall_fn_6(struct S* s) {
+ if (s) {
+ printf("vectorcall_fn_6(S { x: %d, y: %d })\n", s->x, s->y);
+ } else {
+ printf("vectorcall_fn_6(null)\n");
+ }
+ fflush(stdout);
+}
+
+__declspec(dllexport) void __vectorcall vectorcall_fn_7(struct S2 s, int i) {
+ printf("vectorcall_fn_7(S2 { x: %d, y: %d }, %d)\n", s.x, s.y, i);
+ fflush(stdout);
+}
+
+__declspec(dllexport) void __vectorcall vectorcall_fn_8(struct S3 s, struct S3 t) {
+ printf("vectorcall_fn_8(S3 { x: [%d, %d, %d, %d, %d] }, S3 { x: [%d, %d, %d, %d, %d] })\n",
+ s.x[0], s.x[1], s.x[2], s.x[3], s.x[4],
+ t.x[0], t.x[1], t.x[2], t.x[3], t.x[4]
+ );
+ fflush(stdout);
+}
+
+__declspec(dllexport) void __vectorcall vectorcall_fn_9(uint8_t x, double y) {
+ printf("vectorcall_fn_9(%d, %.1f)\n", x, y);
+ fflush(stdout);
+}
+#endif
diff --git a/src/test/run-make/raw-dylib-alt-calling-convention/lib.rs b/src/test/run-make/raw-dylib-alt-calling-convention/lib.rs
new file mode 100644
index 000000000..b5e9415b2
--- /dev/null
+++ b/src/test/run-make/raw-dylib-alt-calling-convention/lib.rs
@@ -0,0 +1,106 @@
+#![feature(raw_dylib)]
+#![feature(abi_vectorcall)]
+
+#[repr(C)]
+#[derive(Clone)]
+struct S {
+ x: u8,
+ y: i32,
+}
+
+#[repr(C)]
+#[derive(Clone)]
+struct S2 {
+ x: i32,
+ y: u8,
+}
+
+#[repr(C)]
+#[derive(Clone)]
+struct S3 {
+ x: [u8; 5],
+}
+
+#[link(name = "extern", kind = "raw-dylib")]
+extern "stdcall" {
+ fn stdcall_fn_1(i: i32);
+ fn stdcall_fn_2(c: u8, f: f32);
+ fn stdcall_fn_3(d: f64);
+ fn stdcall_fn_4(i: u8, j: u8, f: f32);
+ fn stdcall_fn_5(a: S, b: i32);
+ fn stdcall_fn_6(a: Option<&S>);
+ fn stdcall_fn_7(a: S2, b: i32);
+ fn stdcall_fn_8(a: S3, b: S3);
+ fn stdcall_fn_9(x: u8, y: f64);
+}
+
+#[link(name = "extern", kind = "raw-dylib")]
+extern "fastcall" {
+ fn fastcall_fn_1(i: i32);
+ fn fastcall_fn_2(c: u8, f: f32);
+ fn fastcall_fn_3(d: f64);
+ fn fastcall_fn_4(i: u8, j: u8, f: f32);
+ fn fastcall_fn_5(a: S, b: i32);
+ fn fastcall_fn_6(a: Option<&S>);
+ fn fastcall_fn_7(a: S2, b: i32);
+ fn fastcall_fn_8(a: S3, b: S3);
+ fn fastcall_fn_9(x: u8, y: f64);
+}
+
+#[cfg(target_env = "msvc")]
+#[link(name = "extern", kind = "raw-dylib")]
+extern "vectorcall" {
+ fn vectorcall_fn_1(i: i32);
+ fn vectorcall_fn_2(c: u8, f: f32);
+ fn vectorcall_fn_3(d: f64);
+ fn vectorcall_fn_4(i: u8, j: u8, f: f32);
+ fn vectorcall_fn_5(a: S, b: i32);
+ fn vectorcall_fn_6(a: Option<&S>);
+ fn vectorcall_fn_7(a: S2, b: i32);
+ fn vectorcall_fn_8(a: S3, b: S3);
+ fn vectorcall_fn_9(x: u8, y: f64);
+}
+
+pub fn library_function(run_msvc_only: bool) {
+ unsafe {
+ if !run_msvc_only {
+ stdcall_fn_1(14);
+ stdcall_fn_2(16, 3.5);
+ stdcall_fn_3(3.5);
+ stdcall_fn_4(1, 2, 3.0);
+ stdcall_fn_5(S { x: 1, y: 2 }, 16);
+ stdcall_fn_6(Some(&S { x: 10, y: 12 }));
+ stdcall_fn_7(S2 { x: 15, y: 16 }, 3);
+ stdcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] });
+ stdcall_fn_9(1, 3.0);
+
+ fastcall_fn_1(14);
+ fastcall_fn_2(16, 3.5);
+ fastcall_fn_3(3.5);
+ fastcall_fn_4(1, 2, 3.0);
+ fastcall_fn_6(Some(&S { x: 10, y: 12 }));
+ fastcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] });
+ fastcall_fn_9(1, 3.0);
+ } else {
+ // FIXME: 91167
+ // rustc generates incorrect code for the calls to fastcall_fn_5 and fastcall_fn_7
+ // on i686-pc-windows-gnu; disabling these until the indicated issue is fixed.
+ fastcall_fn_5(S { x: 1, y: 2 }, 16);
+ fastcall_fn_7(S2 { x: 15, y: 16 }, 3);
+
+ // GCC doesn't support vectorcall: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89485
+ #[cfg(target_env = "msvc")]
+ {
+ vectorcall_fn_1(14);
+ vectorcall_fn_2(16, 3.5);
+ vectorcall_fn_3(3.5);
+ vectorcall_fn_4(1, 2, 3.0);
+ vectorcall_fn_5(S { x: 1, y: 2 }, 16);
+ vectorcall_fn_6(Some(&S { x: 10, y: 12 }));
+ vectorcall_fn_7(S2 { x: 15, y: 16 }, 3);
+ vectorcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] });
+ vectorcall_fn_9(1, 3.0);
+ }
+ }
+ }
+}
diff --git a/src/test/run-make/raw-dylib-alt-calling-convention/output.msvc.txt b/src/test/run-make/raw-dylib-alt-calling-convention/output.msvc.txt
new file mode 100644
index 000000000..9ddd1b110
--- /dev/null
+++ b/src/test/run-make/raw-dylib-alt-calling-convention/output.msvc.txt
@@ -0,0 +1,11 @@
+fastcall_fn_5(S { x: 1, y: 2 }, 16)
+fastcall_fn_7(S2 { x: 15, y: 16 }, 3)
+vectorcall_fn_1(14)
+vectorcall_fn_2(16, 3.5)
+vectorcall_fn_3(3.5)
+vectorcall_fn_4(1, 2, 3.0)
+vectorcall_fn_5(S { x: 1, y: 2 }, 16)
+vectorcall_fn_6(S { x: 10, y: 12 })
+vectorcall_fn_7(S2 { x: 15, y: 16 }, 3)
+vectorcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] })
+vectorcall_fn_9(1, 3.0)
diff --git a/src/test/run-make/raw-dylib-alt-calling-convention/output.txt b/src/test/run-make/raw-dylib-alt-calling-convention/output.txt
new file mode 100644
index 000000000..348bad63e
--- /dev/null
+++ b/src/test/run-make/raw-dylib-alt-calling-convention/output.txt
@@ -0,0 +1,16 @@
+stdcall_fn_1(14)
+stdcall_fn_2(16, 3.5)
+stdcall_fn_3(3.5)
+stdcall_fn_4(1, 2, 3.0)
+stdcall_fn_5(S { x: 1, y: 2 }, 16)
+stdcall_fn_6(S { x: 10, y: 12 })
+stdcall_fn_7(S2 { x: 15, y: 16 }, 3)
+stdcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] })
+stdcall_fn_9(1, 3.0)
+fastcall_fn_1(14)
+fastcall_fn_2(16, 3.5)
+fastcall_fn_3(3.5)
+fastcall_fn_4(1, 2, 3.0)
+fastcall_fn_6(S { x: 10, y: 12 })
+fastcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] })
+fastcall_fn_9(1, 3.0)
diff --git a/src/test/run-make/raw-dylib-c/Makefile b/src/test/run-make/raw-dylib-c/Makefile
new file mode 100644
index 000000000..713f66507
--- /dev/null
+++ b/src/test/run-make/raw-dylib-c/Makefile
@@ -0,0 +1,28 @@
+# Test the behavior of #[link(.., kind = "raw-dylib")] on windows-msvc
+
+# only-windows
+
+-include ../../run-make-fulldeps/tools.mk
+
+all:
+ $(RUSTC) --crate-type lib --crate-name raw_dylib_test lib.rs
+ $(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
+ $(RUSTC) --crate-type bin --crate-name raw_dylib_test_bin lib.rs
+ $(call COMPILE_OBJ,"$(TMPDIR)"/extern_1.obj,extern_1.c)
+ $(call COMPILE_OBJ,"$(TMPDIR)"/extern_2.obj,extern_2.c)
+ifdef IS_MSVC
+ $(CC) "$(TMPDIR)"/extern_1.obj -link -dll -out:"$(TMPDIR)"/extern_1.dll -noimplib
+ $(CC) "$(TMPDIR)"/extern_2.obj -link -dll -out:"$(TMPDIR)"/extern_2.dll -noimplib
+else
+ $(CC) "$(TMPDIR)"/extern_1.obj -shared -o "$(TMPDIR)"/extern_1.dll
+ $(CC) "$(TMPDIR)"/extern_2.obj -shared -o "$(TMPDIR)"/extern_2.dll
+endif
+ "$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt
+ "$(TMPDIR)"/raw_dylib_test_bin > "$(TMPDIR)"/output_bin.txt
+
+ifdef RUSTC_BLESS_TEST
+ cp "$(TMPDIR)"/output.txt output.txt
+else
+ $(DIFF) output.txt "$(TMPDIR)"/output.txt
+ $(DIFF) output.txt "$(TMPDIR)"/output_bin.txt
+endif
diff --git a/src/test/run-make/raw-dylib-c/driver.rs b/src/test/run-make/raw-dylib-c/driver.rs
new file mode 100644
index 000000000..4059ede11
--- /dev/null
+++ b/src/test/run-make/raw-dylib-c/driver.rs
@@ -0,0 +1,5 @@
+extern crate raw_dylib_test;
+
+fn main() {
+ raw_dylib_test::library_function();
+}
diff --git a/src/test/run-make/raw-dylib-c/extern_1.c b/src/test/run-make/raw-dylib-c/extern_1.c
new file mode 100644
index 000000000..72737c086
--- /dev/null
+++ b/src/test/run-make/raw-dylib-c/extern_1.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+__declspec(dllexport) void extern_fn_1() {
+ printf("extern_fn_1\n");
+ fflush(stdout);
+}
+
+__declspec(dllexport) void extern_fn_2() {
+ printf("extern_fn_2; didn't get the rename\n");
+ fflush(stdout);
+}
+
+__declspec(dllexport) void extern_fn_with_long_name() {
+ printf("extern_fn_with_long_name; got the rename\n");
+ fflush(stdout);
+}
diff --git a/src/test/run-make/raw-dylib-c/extern_2.c b/src/test/run-make/raw-dylib-c/extern_2.c
new file mode 100644
index 000000000..ae87fc3f8
--- /dev/null
+++ b/src/test/run-make/raw-dylib-c/extern_2.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+__declspec(dllexport) void extern_fn_3() {
+ printf("extern_fn_3\n");
+ fflush(stdout);
+}
diff --git a/src/test/run-make/raw-dylib-c/lib.rs b/src/test/run-make/raw-dylib-c/lib.rs
new file mode 100644
index 000000000..58f7ccb38
--- /dev/null
+++ b/src/test/run-make/raw-dylib-c/lib.rs
@@ -0,0 +1,26 @@
+#![feature(raw_dylib, native_link_modifiers_verbatim)]
+
+#[link(name = "extern_1.dll", kind = "raw-dylib", modifiers = "+verbatim")]
+extern {
+ fn extern_fn_1();
+}
+
+#[link(name = "extern_2", kind = "raw-dylib")]
+extern {
+ fn extern_fn_3();
+}
+
+pub fn library_function() {
+ #[link(name = "extern_1", kind = "raw-dylib")]
+ extern { fn extern_fn_2(); }
+
+ unsafe {
+ extern_fn_1();
+ extern_fn_2();
+ extern_fn_3();
+ }
+}
+
+fn main() {
+ library_function();
+}
diff --git a/src/test/run-make/raw-dylib-c/output.txt b/src/test/run-make/raw-dylib-c/output.txt
new file mode 100644
index 000000000..7800cba18
--- /dev/null
+++ b/src/test/run-make/raw-dylib-c/output.txt
@@ -0,0 +1,3 @@
+extern_fn_1
+extern_fn_2; didn't get the rename
+extern_fn_3
diff --git a/src/test/run-make/raw-dylib-link-ordinal/Makefile b/src/test/run-make/raw-dylib-link-ordinal/Makefile
new file mode 100644
index 000000000..c9baa3c1e
--- /dev/null
+++ b/src/test/run-make/raw-dylib-link-ordinal/Makefile
@@ -0,0 +1,22 @@
+# Test the behavior of #[link(.., kind = "raw-dylib")] and #[link_ordinal] on windows-msvc
+
+# only-windows
+
+-include ../../run-make-fulldeps/tools.mk
+
+all:
+ $(RUSTC) --crate-type lib --crate-name raw_dylib_test lib.rs
+ $(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
+ $(call COMPILE_OBJ,"$(TMPDIR)"/exporter.obj,exporter.c)
+ifdef IS_MSVC
+ $(CC) "$(TMPDIR)"/exporter.obj exporter.def -link -dll -out:"$(TMPDIR)"/exporter.dll -noimplib
+else
+ $(CC) "$(TMPDIR)"/exporter.obj exporter.def -shared -o "$(TMPDIR)"/exporter.dll
+endif
+ "$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt
+
+ifdef RUSTC_BLESS_TEST
+ cp "$(TMPDIR)"/output.txt output.txt
+else
+ $(DIFF) output.txt "$(TMPDIR)"/output.txt
+endif
diff --git a/src/test/run-make/raw-dylib-link-ordinal/driver.rs b/src/test/run-make/raw-dylib-link-ordinal/driver.rs
new file mode 100644
index 000000000..4059ede11
--- /dev/null
+++ b/src/test/run-make/raw-dylib-link-ordinal/driver.rs
@@ -0,0 +1,5 @@
+extern crate raw_dylib_test;
+
+fn main() {
+ raw_dylib_test::library_function();
+}
diff --git a/src/test/run-make/raw-dylib-link-ordinal/exporter.c b/src/test/run-make/raw-dylib-link-ordinal/exporter.c
new file mode 100644
index 000000000..a9dd6da66
--- /dev/null
+++ b/src/test/run-make/raw-dylib-link-ordinal/exporter.c
@@ -0,0 +1,5 @@
+#include <stdio.h>
+
+void exported_function() {
+ printf("exported_function\n");
+}
diff --git a/src/test/run-make/raw-dylib-link-ordinal/exporter.def b/src/test/run-make/raw-dylib-link-ordinal/exporter.def
new file mode 100644
index 000000000..1a4b4c941
--- /dev/null
+++ b/src/test/run-make/raw-dylib-link-ordinal/exporter.def
@@ -0,0 +1,3 @@
+LIBRARY exporter
+EXPORTS
+ exported_function @13 NONAME
diff --git a/src/test/run-make/raw-dylib-link-ordinal/lib.rs b/src/test/run-make/raw-dylib-link-ordinal/lib.rs
new file mode 100644
index 000000000..20609caa5
--- /dev/null
+++ b/src/test/run-make/raw-dylib-link-ordinal/lib.rs
@@ -0,0 +1,13 @@
+#![feature(raw_dylib)]
+
+#[link(name = "exporter", kind = "raw-dylib")]
+extern {
+ #[link_ordinal(13)]
+ fn imported_function();
+}
+
+pub fn library_function() {
+ unsafe {
+ imported_function();
+ }
+}
diff --git a/src/test/run-make/raw-dylib-link-ordinal/output.txt b/src/test/run-make/raw-dylib-link-ordinal/output.txt
new file mode 100644
index 000000000..2d0ed60f2
--- /dev/null
+++ b/src/test/run-make/raw-dylib-link-ordinal/output.txt
@@ -0,0 +1 @@
+exported_function
diff --git a/src/test/run-make/raw-dylib-stdcall-ordinal/Makefile b/src/test/run-make/raw-dylib-stdcall-ordinal/Makefile
new file mode 100644
index 000000000..3360a97b5
--- /dev/null
+++ b/src/test/run-make/raw-dylib-stdcall-ordinal/Makefile
@@ -0,0 +1,23 @@
+# Test the behavior of #[link(.., kind = "raw-dylib")], #[link_ordinal], and alternative calling conventions on i686 windows.
+
+# only-x86
+# only-windows
+
+-include ../../run-make-fulldeps/tools.mk
+
+all:
+ $(RUSTC) --crate-type lib --crate-name raw_dylib_test lib.rs
+ $(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
+ $(call COMPILE_OBJ,"$(TMPDIR)"/exporter.obj,exporter.c)
+ifdef IS_MSVC
+ $(CC) "$(TMPDIR)"/exporter.obj exporter-msvc.def -link -dll -out:"$(TMPDIR)"/exporter.dll -noimplib
+else
+ $(CC) "$(TMPDIR)"/exporter.obj exporter-gnu.def -shared -o "$(TMPDIR)"/exporter.dll
+endif
+ "$(TMPDIR)"/driver > "$(TMPDIR)"/actual_output.txt
+
+ifdef RUSTC_BLESS_TEST
+ cp "$(TMPDIR)"/actual_output.txt expected_output.txt
+else
+ $(DIFF) expected_output.txt "$(TMPDIR)"/actual_output.txt
+endif
diff --git a/src/test/run-make/raw-dylib-stdcall-ordinal/driver.rs b/src/test/run-make/raw-dylib-stdcall-ordinal/driver.rs
new file mode 100644
index 000000000..4059ede11
--- /dev/null
+++ b/src/test/run-make/raw-dylib-stdcall-ordinal/driver.rs
@@ -0,0 +1,5 @@
+extern crate raw_dylib_test;
+
+fn main() {
+ raw_dylib_test::library_function();
+}
diff --git a/src/test/run-make/raw-dylib-stdcall-ordinal/expected_output.txt b/src/test/run-make/raw-dylib-stdcall-ordinal/expected_output.txt
new file mode 100644
index 000000000..201577637
--- /dev/null
+++ b/src/test/run-make/raw-dylib-stdcall-ordinal/expected_output.txt
@@ -0,0 +1,2 @@
+exported_function_stdcall(6)
+exported_function_fastcall(125)
diff --git a/src/test/run-make/raw-dylib-stdcall-ordinal/exporter-gnu.def b/src/test/run-make/raw-dylib-stdcall-ordinal/exporter-gnu.def
new file mode 100644
index 000000000..8d28d714b
--- /dev/null
+++ b/src/test/run-make/raw-dylib-stdcall-ordinal/exporter-gnu.def
@@ -0,0 +1,4 @@
+LIBRARY exporter
+EXPORTS
+ exported_function_stdcall@4 @15 NONAME
+ @exported_function_fastcall@4 @18 NONAME \ No newline at end of file
diff --git a/src/test/run-make/raw-dylib-stdcall-ordinal/exporter-msvc.def b/src/test/run-make/raw-dylib-stdcall-ordinal/exporter-msvc.def
new file mode 100644
index 000000000..5a4c79a58
--- /dev/null
+++ b/src/test/run-make/raw-dylib-stdcall-ordinal/exporter-msvc.def
@@ -0,0 +1,4 @@
+LIBRARY exporter
+EXPORTS
+ _exported_function_stdcall@4 @15 NONAME
+ @exported_function_fastcall@4 @18 NONAME \ No newline at end of file
diff --git a/src/test/run-make/raw-dylib-stdcall-ordinal/exporter.c b/src/test/run-make/raw-dylib-stdcall-ordinal/exporter.c
new file mode 100644
index 000000000..1fb45bf01
--- /dev/null
+++ b/src/test/run-make/raw-dylib-stdcall-ordinal/exporter.c
@@ -0,0 +1,11 @@
+#include <stdio.h>
+
+void __stdcall exported_function_stdcall(int i) {
+ printf("exported_function_stdcall(%d)\n", i);
+ fflush(stdout);
+}
+
+void __fastcall exported_function_fastcall(int i) {
+ printf("exported_function_fastcall(%d)\n", i);
+ fflush(stdout);
+}
diff --git a/src/test/run-make/raw-dylib-stdcall-ordinal/lib.rs b/src/test/run-make/raw-dylib-stdcall-ordinal/lib.rs
new file mode 100644
index 000000000..07dd3d7be
--- /dev/null
+++ b/src/test/run-make/raw-dylib-stdcall-ordinal/lib.rs
@@ -0,0 +1,20 @@
+#![feature(raw_dylib)]
+
+#[link(name = "exporter", kind = "raw-dylib")]
+extern "stdcall" {
+ #[link_ordinal(15)]
+ fn imported_function_stdcall(i: i32);
+}
+
+#[link(name = "exporter", kind = "raw-dylib")]
+extern "fastcall" {
+ #[link_ordinal(18)]
+ fn imported_function_fastcall(i: i32);
+}
+
+pub fn library_function() {
+ unsafe {
+ imported_function_stdcall(6);
+ imported_function_fastcall(125);
+ }
+}
diff --git a/src/test/run-make/remap-path-prefix-dwarf/Makefile b/src/test/run-make/remap-path-prefix-dwarf/Makefile
new file mode 100644
index 000000000..561a343d6
--- /dev/null
+++ b/src/test/run-make/remap-path-prefix-dwarf/Makefile
@@ -0,0 +1,77 @@
+# This test makes sure that --remap-path-prefix has the expected effects on paths in debuginfo.
+# It tests several cases, each of them has a detailed description attached to it.
+
+# ignore-windows
+
+SRC_DIR := $(abspath .)
+SRC_DIR_PARENT := $(abspath ..)
+
+-include ../../run-make-fulldeps/tools.mk
+
+all: \
+ abs_input_outside_working_dir \
+ rel_input_remap_working_dir \
+ rel_input_remap_working_dir_parent \
+ rel_input_remap_working_dir_child \
+ abs_input_inside_working_dir \
+ abs_input_outside_working_dir
+
+# The compiler is called with an *ABSOLUTE PATH* as input, and that absolute path *is* within
+# the working directory of the compiler. We are remapping the path that contains `src`.
+abs_input_inside_working_dir:
+ # We explicitly switch to a directory that *is* a prefix of the directory our
+ # source code is contained in.
+ cd $(SRC_DIR) && $(RUSTC) $(SRC_DIR)/src/quux.rs -o "$(TMPDIR)/abs_input_inside_working_dir.rlib" -Cdebuginfo=2 --remap-path-prefix $(SRC_DIR)=REMAPPED
+ # We expect the path to the main source file to be remapped.
+ "$(LLVM_BIN_DIR)"/llvm-dwarfdump $(TMPDIR)/abs_input_inside_working_dir.rlib | $(CGREP) "REMAPPED/src/quux.rs"
+ # No weird duplication of remapped components (see #78479)
+ "$(LLVM_BIN_DIR)"/llvm-dwarfdump $(TMPDIR)/abs_input_inside_working_dir.rlib | $(CGREP) -v "REMAPPED/REMAPPED"
+
+# The compiler is called with an *ABSOLUTE PATH* as input, and that absolute path is *not* within
+# the working directory of the compiler. We are remapping both the path that contains `src` and
+# the working directory to the same thing. This setup corresponds to a workaround that is needed
+# when trying to remap everything to something that looks like a local path.
+# Relative paths are interpreted as relative to the compiler's working directory (e.g. in
+# debuginfo). If we also remap the working directory, the compiler strip it from other paths so
+# that the final outcome is the desired one again.
+abs_input_outside_working_dir:
+ # We explicitly switch to a directory that is *not* a prefix of the directory our
+ # source code is contained in.
+ cd $(TMPDIR) && $(RUSTC) $(SRC_DIR)/src/quux.rs -o "$(TMPDIR)/abs_input_outside_working_dir.rlib" -Cdebuginfo=2 --remap-path-prefix $(SRC_DIR)=REMAPPED --remap-path-prefix $(TMPDIR)=REMAPPED
+ "$(LLVM_BIN_DIR)"/llvm-dwarfdump $(TMPDIR)/abs_input_outside_working_dir.rlib | $(CGREP) "REMAPPED/src/quux.rs"
+ # No weird duplication of remapped components (see #78479)
+ "$(LLVM_BIN_DIR)"/llvm-dwarfdump $(TMPDIR)/abs_input_outside_working_dir.rlib | $(CGREP) -v "REMAPPED/REMAPPED"
+
+# The compiler is called with a *RELATIVE PATH* as input. We are remapping the working directory of
+# the compiler, which naturally is an implicit prefix of our relative input path. Debuginfo will
+# expand the relative path to an absolute path and we expect the working directory to be remapped
+# in that expansion.
+rel_input_remap_working_dir:
+ cd $(SRC_DIR) && $(RUSTC) src/quux.rs -o "$(TMPDIR)/rel_input_remap_working_dir.rlib" -Cdebuginfo=2 --remap-path-prefix "$(SRC_DIR)=REMAPPED"
+ "$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir.rlib" | $(CGREP) "REMAPPED/src/quux.rs"
+ # No weird duplication of remapped components (see #78479)
+ "$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir.rlib" | $(CGREP) -v "REMAPPED/REMAPPED"
+
+# The compiler is called with a *RELATIVE PATH* as input. We are remapping a *SUB-DIRECTORY* of the
+# compiler's working directory. This test makes sure that that directory is remapped even though it
+# won't actually show up in this form in the compiler's SourceMap and instead is only constructed
+# on demand during debuginfo generation.
+rel_input_remap_working_dir_child:
+ cd $(SRC_DIR) && $(RUSTC) src/quux.rs -o "$(TMPDIR)/rel_input_remap_working_dir_child.rlib" -Cdebuginfo=2 --remap-path-prefix "$(SRC_DIR)/src=REMAPPED"
+ # We expect `src/quux.rs` to have been remapped to `REMAPPED/quux.rs`.
+ "$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir_child.rlib" | $(CGREP) "REMAPPED/quux.rs"
+ # We don't want to find the path that we just remapped anywhere in the DWARF
+ "$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir_child.rlib" | $(CGREP) -v "$(SRC_DIR)/src"
+ # No weird duplication of remapped components (see #78479)
+ "$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir_child.rlib" | $(CGREP) -v "REMAPPED/REMAPPED"
+
+# The compiler is called with a *RELATIVE PATH* as input. We are remapping a *PARENT DIRECTORY* of
+# the compiler's working directory.
+rel_input_remap_working_dir_parent:
+ cd $(SRC_DIR) && $(RUSTC) src/quux.rs -o "$(TMPDIR)/rel_input_remap_working_dir_parent.rlib" -Cdebuginfo=2 --remap-path-prefix "$(SRC_DIR_PARENT)=REMAPPED"
+ # We expect `src/quux.rs` to have been remapped to `REMAPPED/remap-path-prefix-dwarf/src/quux.rs`.
+ "$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir_parent.rlib" | $(CGREP) "REMAPPED/remap-path-prefix-dwarf/src/quux.rs"
+ # We don't want to find the path that we just remapped anywhere in the DWARF
+ "$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir_parent.rlib" | $(CGREP) -v "$(SRC_DIR_PARENT)"
+ # No weird duplication of remapped components (see #78479)
+ "$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir_parent.rlib" | $(CGREP) -v "REMAPPED/REMAPPED"
diff --git a/src/test/run-make/remap-path-prefix-dwarf/src/quux.rs b/src/test/run-make/remap-path-prefix-dwarf/src/quux.rs
new file mode 100644
index 000000000..38d5ef619
--- /dev/null
+++ b/src/test/run-make/remap-path-prefix-dwarf/src/quux.rs
@@ -0,0 +1,5 @@
+#![crate_type = "rlib"]
+
+pub fn foo() {
+ println!("foo");
+}
diff --git a/src/test/run-make/rustc-macro-dep-files/Makefile b/src/test/run-make/rustc-macro-dep-files/Makefile
new file mode 100644
index 000000000..a08a63fb4
--- /dev/null
+++ b/src/test/run-make/rustc-macro-dep-files/Makefile
@@ -0,0 +1,11 @@
+-include ../../run-make-fulldeps/tools.mk
+
+# FIXME(eddyb) provide `HOST_RUSTC` and `TARGET_RUSTC`
+# instead of hardcoding them everywhere they're needed.
+ifeq ($(IS_MUSL_HOST),1)
+ADDITIONAL_ARGS := $(RUSTFLAGS)
+endif
+all:
+ $(BARE_RUSTC) $(ADDITIONAL_ARGS) foo.rs --out-dir $(TMPDIR)
+ $(RUSTC) bar.rs --target $(TARGET) --emit dep-info
+ $(CGREP) -v "proc-macro source" < $(TMPDIR)/bar.d
diff --git a/src/test/run-make/rustc-macro-dep-files/bar.rs b/src/test/run-make/rustc-macro-dep-files/bar.rs
new file mode 100644
index 000000000..4a3b3364b
--- /dev/null
+++ b/src/test/run-make/rustc-macro-dep-files/bar.rs
@@ -0,0 +1,8 @@
+#![no_std]
+#![crate_type = "lib"]
+
+#[macro_use]
+extern crate foo;
+
+#[derive(A)]
+struct A;
diff --git a/src/test/run-make/rustc-macro-dep-files/foo.rs b/src/test/run-make/rustc-macro-dep-files/foo.rs
new file mode 100644
index 000000000..66db1a217
--- /dev/null
+++ b/src/test/run-make/rustc-macro-dep-files/foo.rs
@@ -0,0 +1,12 @@
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(A)]
+pub fn derive(input: TokenStream) -> TokenStream {
+ let input = input.to_string();
+ assert!(input.contains("struct A ;"));
+ "struct B;".parse().unwrap()
+}
diff --git a/src/test/run-make/rustdoc-scrape-examples-invalid-expr/Makefile b/src/test/run-make/rustdoc-scrape-examples-invalid-expr/Makefile
new file mode 100644
index 000000000..dce8b83ee
--- /dev/null
+++ b/src/test/run-make/rustdoc-scrape-examples-invalid-expr/Makefile
@@ -0,0 +1,5 @@
+deps := ex
+
+-include ../rustdoc-scrape-examples-multiple/scrape.mk
+
+all: scrape
diff --git a/src/test/run-make/rustdoc-scrape-examples-invalid-expr/examples/ex.rs b/src/test/run-make/rustdoc-scrape-examples-invalid-expr/examples/ex.rs
new file mode 100644
index 000000000..b342b5b0a
--- /dev/null
+++ b/src/test/run-make/rustdoc-scrape-examples-invalid-expr/examples/ex.rs
@@ -0,0 +1,2 @@
+pub struct Foo([usize; foobar::f()]);
+fn main() {}
diff --git a/src/test/run-make/rustdoc-scrape-examples-invalid-expr/src/lib.rs b/src/test/run-make/rustdoc-scrape-examples-invalid-expr/src/lib.rs
new file mode 100644
index 000000000..c30c99dec
--- /dev/null
+++ b/src/test/run-make/rustdoc-scrape-examples-invalid-expr/src/lib.rs
@@ -0,0 +1 @@
+pub const fn f() -> usize { 5 }
diff --git a/src/test/run-make/rustdoc-scrape-examples-multiple/Makefile b/src/test/run-make/rustdoc-scrape-examples-multiple/Makefile
new file mode 100644
index 000000000..897805e44
--- /dev/null
+++ b/src/test/run-make/rustdoc-scrape-examples-multiple/Makefile
@@ -0,0 +1,5 @@
+deps := ex ex2
+
+-include ./scrape.mk
+
+all: scrape
diff --git a/src/test/run-make/rustdoc-scrape-examples-multiple/examples/ex.rs b/src/test/run-make/rustdoc-scrape-examples-multiple/examples/ex.rs
new file mode 100644
index 000000000..01b730c61
--- /dev/null
+++ b/src/test/run-make/rustdoc-scrape-examples-multiple/examples/ex.rs
@@ -0,0 +1,4 @@
+fn main() {
+ foobar::ok();
+ foobar::ok();
+}
diff --git a/src/test/run-make/rustdoc-scrape-examples-multiple/examples/ex2.rs b/src/test/run-make/rustdoc-scrape-examples-multiple/examples/ex2.rs
new file mode 100644
index 000000000..f83cf2f27
--- /dev/null
+++ b/src/test/run-make/rustdoc-scrape-examples-multiple/examples/ex2.rs
@@ -0,0 +1,3 @@
+fn main() {
+ foobar::ok();
+}
diff --git a/src/test/run-make/rustdoc-scrape-examples-multiple/scrape.mk b/src/test/run-make/rustdoc-scrape-examples-multiple/scrape.mk
new file mode 100644
index 000000000..d49b6c1f2
--- /dev/null
+++ b/src/test/run-make/rustdoc-scrape-examples-multiple/scrape.mk
@@ -0,0 +1,21 @@
+-include ../../run-make-fulldeps/tools.mk
+
+OUTPUT_DIR := "$(TMPDIR)/rustdoc"
+
+$(TMPDIR)/%.calls: $(TMPDIR)/libfoobar.rmeta
+ $(RUSTDOC) examples/$*.rs --crate-name $* --crate-type bin --output $(OUTPUT_DIR) \
+ --extern foobar=$(TMPDIR)/libfoobar.rmeta \
+ -Z unstable-options \
+ --scrape-examples-output-path $@ \
+ --scrape-examples-target-crate foobar \
+ $(extra_flags)
+
+$(TMPDIR)/lib%.rmeta: src/lib.rs
+ $(RUSTC) src/lib.rs --crate-name $* --crate-type lib --emit=metadata
+
+scrape: $(foreach d,$(deps),$(TMPDIR)/$(d).calls)
+ $(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --output $(OUTPUT_DIR) \
+ -Z unstable-options \
+ $(foreach d,$(deps),--with-examples $(TMPDIR)/$(d).calls)
+
+ $(HTMLDOCCK) $(OUTPUT_DIR) src/lib.rs
diff --git a/src/test/run-make/rustdoc-scrape-examples-multiple/src/lib.rs b/src/test/run-make/rustdoc-scrape-examples-multiple/src/lib.rs
new file mode 100644
index 000000000..bdfeda92d
--- /dev/null
+++ b/src/test/run-make/rustdoc-scrape-examples-multiple/src/lib.rs
@@ -0,0 +1,6 @@
+// @has foobar/fn.ok.html '//*[@class="docblock scraped-example-list"]//*[@class="prev"]' ''
+// @has foobar/fn.ok.html '//*[@class="more-scraped-examples"]' ''
+// @has src/ex/ex.rs.html
+// @has foobar/fn.ok.html '//a[@href="../src/ex/ex.rs.html#2"]' ''
+
+pub fn ok() {}
diff --git a/src/test/run-make/rustdoc-scrape-examples-ordering/Makefile b/src/test/run-make/rustdoc-scrape-examples-ordering/Makefile
new file mode 100644
index 000000000..339d539bf
--- /dev/null
+++ b/src/test/run-make/rustdoc-scrape-examples-ordering/Makefile
@@ -0,0 +1,5 @@
+deps := ex1 ex2
+
+-include ../rustdoc-scrape-examples-multiple/scrape.mk
+
+all: scrape
diff --git a/src/test/run-make/rustdoc-scrape-examples-ordering/examples/ex1.rs b/src/test/run-make/rustdoc-scrape-examples-ordering/examples/ex1.rs
new file mode 100644
index 000000000..05c18007b
--- /dev/null
+++ b/src/test/run-make/rustdoc-scrape-examples-ordering/examples/ex1.rs
@@ -0,0 +1,11 @@
+fn main() {
+ foobar::ok(0);
+
+ // this is a
+
+ // ..
+
+ // BIG
+
+ // item
+}
diff --git a/src/test/run-make/rustdoc-scrape-examples-ordering/examples/ex2.rs b/src/test/run-make/rustdoc-scrape-examples-ordering/examples/ex2.rs
new file mode 100644
index 000000000..de21d9061
--- /dev/null
+++ b/src/test/run-make/rustdoc-scrape-examples-ordering/examples/ex2.rs
@@ -0,0 +1,8 @@
+fn main() {
+ foobar::ok(1);
+ // small item
+}
+
+fn f() {
+ foobar::ok(2);
+}
diff --git a/src/test/run-make/rustdoc-scrape-examples-ordering/src/lib.rs b/src/test/run-make/rustdoc-scrape-examples-ordering/src/lib.rs
new file mode 100644
index 000000000..c53c987a7
--- /dev/null
+++ b/src/test/run-make/rustdoc-scrape-examples-ordering/src/lib.rs
@@ -0,0 +1,6 @@
+// @has foobar/fn.ok.html '//*[@class="docblock scraped-example-list"]' 'ex2'
+// @has foobar/fn.ok.html '//*[@class="more-scraped-examples"]' 'ex1'
+// @has foobar/fn.ok.html '//*[@class="highlight focus"]' 'ok'
+// @has foobar/fn.ok.html '//*[@class="highlight"]' 'ok'
+
+pub fn ok(_x: i32) {}
diff --git a/src/test/run-make/rustdoc-scrape-examples-remap/Makefile b/src/test/run-make/rustdoc-scrape-examples-remap/Makefile
new file mode 100644
index 000000000..dce8b83ee
--- /dev/null
+++ b/src/test/run-make/rustdoc-scrape-examples-remap/Makefile
@@ -0,0 +1,5 @@
+deps := ex
+
+-include ../rustdoc-scrape-examples-multiple/scrape.mk
+
+all: scrape
diff --git a/src/test/run-make/rustdoc-scrape-examples-remap/examples/ex.rs b/src/test/run-make/rustdoc-scrape-examples-remap/examples/ex.rs
new file mode 100644
index 000000000..1438fdba7
--- /dev/null
+++ b/src/test/run-make/rustdoc-scrape-examples-remap/examples/ex.rs
@@ -0,0 +1,4 @@
+fn main() {
+ foobar::b::foo();
+ foobar::c::foo();
+}
diff --git a/src/test/run-make/rustdoc-scrape-examples-remap/src/a.rs b/src/test/run-make/rustdoc-scrape-examples-remap/src/a.rs
new file mode 100644
index 000000000..b76b4321d
--- /dev/null
+++ b/src/test/run-make/rustdoc-scrape-examples-remap/src/a.rs
@@ -0,0 +1 @@
+pub fn foo() {}
diff --git a/src/test/run-make/rustdoc-scrape-examples-remap/src/lib.rs b/src/test/run-make/rustdoc-scrape-examples-remap/src/lib.rs
new file mode 100644
index 000000000..f525a4270
--- /dev/null
+++ b/src/test/run-make/rustdoc-scrape-examples-remap/src/lib.rs
@@ -0,0 +1,8 @@
+// @has foobar/b/fn.foo.html '//*[@class="scraped-example expanded"]' 'ex.rs'
+// @has foobar/c/fn.foo.html '//*[@class="scraped-example expanded"]' 'ex.rs'
+
+#[path = "a.rs"]
+pub mod b;
+
+#[path = "a.rs"]
+pub mod c;
diff --git a/src/test/run-make/rustdoc-scrape-examples-test/Makefile b/src/test/run-make/rustdoc-scrape-examples-test/Makefile
new file mode 100644
index 000000000..9f80a8d96
--- /dev/null
+++ b/src/test/run-make/rustdoc-scrape-examples-test/Makefile
@@ -0,0 +1,6 @@
+extra_flags := --scrape-tests
+deps := ex
+
+-include ../rustdoc-scrape-examples-multiple/scrape.mk
+
+all: scrape
diff --git a/src/test/run-make/rustdoc-scrape-examples-test/examples/ex.rs b/src/test/run-make/rustdoc-scrape-examples-test/examples/ex.rs
new file mode 100644
index 000000000..d1a9a74e7
--- /dev/null
+++ b/src/test/run-make/rustdoc-scrape-examples-test/examples/ex.rs
@@ -0,0 +1,6 @@
+fn main() {}
+
+#[test]
+fn a_test() {
+ foobar::ok();
+}
diff --git a/src/test/run-make/rustdoc-scrape-examples-test/src/lib.rs b/src/test/run-make/rustdoc-scrape-examples-test/src/lib.rs
new file mode 100644
index 000000000..22be1ad41
--- /dev/null
+++ b/src/test/run-make/rustdoc-scrape-examples-test/src/lib.rs
@@ -0,0 +1,3 @@
+// @has foobar/fn.ok.html '//*[@class="docblock scraped-example-list"]' ''
+
+pub fn ok() {}
diff --git a/src/test/run-make/rustdoc-scrape-examples-whitespace/Makefile b/src/test/run-make/rustdoc-scrape-examples-whitespace/Makefile
new file mode 100644
index 000000000..dce8b83ee
--- /dev/null
+++ b/src/test/run-make/rustdoc-scrape-examples-whitespace/Makefile
@@ -0,0 +1,5 @@
+deps := ex
+
+-include ../rustdoc-scrape-examples-multiple/scrape.mk
+
+all: scrape
diff --git a/src/test/run-make/rustdoc-scrape-examples-whitespace/examples/ex.rs b/src/test/run-make/rustdoc-scrape-examples-whitespace/examples/ex.rs
new file mode 100644
index 000000000..44ff689df
--- /dev/null
+++ b/src/test/run-make/rustdoc-scrape-examples-whitespace/examples/ex.rs
@@ -0,0 +1,8 @@
+struct Foo;
+impl Foo {
+ fn bar() { foobar::ok(); }
+}
+
+fn main() {
+ Foo::bar();
+}
diff --git a/src/test/run-make/rustdoc-scrape-examples-whitespace/src/lib.rs b/src/test/run-make/rustdoc-scrape-examples-whitespace/src/lib.rs
new file mode 100644
index 000000000..28c34716c
--- /dev/null
+++ b/src/test/run-make/rustdoc-scrape-examples-whitespace/src/lib.rs
@@ -0,0 +1,3 @@
+// @has foobar/fn.ok.html '//*[@class="docblock scraped-example-list"]//code' ' '
+
+pub fn ok() {}
diff --git a/src/test/run-make/rustdoc-with-out-dir-option/Makefile b/src/test/run-make/rustdoc-with-out-dir-option/Makefile
new file mode 100644
index 000000000..f79fce8ee
--- /dev/null
+++ b/src/test/run-make/rustdoc-with-out-dir-option/Makefile
@@ -0,0 +1,8 @@
+-include ../../run-make-fulldeps/tools.mk
+
+OUTPUT_DIR := "$(TMPDIR)/rustdoc"
+
+all:
+ $(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --out-dir $(OUTPUT_DIR)
+
+ $(HTMLDOCCK) $(OUTPUT_DIR) src/lib.rs
diff --git a/src/test/run-make/rustdoc-with-out-dir-option/src/lib.rs b/src/test/run-make/rustdoc-with-out-dir-option/src/lib.rs
new file mode 100644
index 000000000..044bb6acb
--- /dev/null
+++ b/src/test/run-make/rustdoc-with-out-dir-option/src/lib.rs
@@ -0,0 +1,2 @@
+// @has foobar/fn.ok.html
+pub fn ok() {}
diff --git a/src/test/run-make/rustdoc-with-output-option/Makefile b/src/test/run-make/rustdoc-with-output-option/Makefile
new file mode 100644
index 000000000..654f96725
--- /dev/null
+++ b/src/test/run-make/rustdoc-with-output-option/Makefile
@@ -0,0 +1,8 @@
+-include ../../run-make-fulldeps/tools.mk
+
+OUTPUT_DIR := "$(TMPDIR)/rustdoc"
+
+all:
+ $(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --output $(OUTPUT_DIR)
+
+ $(HTMLDOCCK) $(OUTPUT_DIR) src/lib.rs
diff --git a/src/test/run-make/rustdoc-with-output-option/src/lib.rs b/src/test/run-make/rustdoc-with-output-option/src/lib.rs
new file mode 100644
index 000000000..044bb6acb
--- /dev/null
+++ b/src/test/run-make/rustdoc-with-output-option/src/lib.rs
@@ -0,0 +1,2 @@
+// @has foobar/fn.ok.html
+pub fn ok() {}
diff --git a/src/test/run-make/rustdoc-with-short-out-dir-option/Makefile b/src/test/run-make/rustdoc-with-short-out-dir-option/Makefile
new file mode 100644
index 000000000..1e9ba71de
--- /dev/null
+++ b/src/test/run-make/rustdoc-with-short-out-dir-option/Makefile
@@ -0,0 +1,8 @@
+-include ../../run-make-fulldeps/tools.mk
+
+OUTPUT_DIR := "$(TMPDIR)/rustdoc"
+
+all:
+ $(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib -o $(OUTPUT_DIR)
+
+ $(HTMLDOCCK) $(OUTPUT_DIR) src/lib.rs
diff --git a/src/test/run-make/rustdoc-with-short-out-dir-option/src/lib.rs b/src/test/run-make/rustdoc-with-short-out-dir-option/src/lib.rs
new file mode 100644
index 000000000..044bb6acb
--- /dev/null
+++ b/src/test/run-make/rustdoc-with-short-out-dir-option/src/lib.rs
@@ -0,0 +1,2 @@
+// @has foobar/fn.ok.html
+pub fn ok() {}
diff --git a/src/test/run-make/static-pie/Makefile b/src/test/run-make/static-pie/Makefile
new file mode 100644
index 000000000..945ec1724
--- /dev/null
+++ b/src/test/run-make/static-pie/Makefile
@@ -0,0 +1,18 @@
+-include ../../run-make-fulldeps/tools.mk
+
+# only-x86_64
+# only-linux
+# ignore-gnux32
+
+# How to manually run this
+# $ ./x.py test --target x86_64-unknown-linux-[musl,gnu] src/test/run-make/static-pie
+
+all: test-clang test-gcc
+
+test-%:
+ if ./check_$*_version.sh; then\
+ ${RUSTC} -Clinker=$* -Clinker-flavor=gcc --target ${TARGET} -C target-feature=+crt-static test-aslr.rs; \
+ ! readelf -l $(call RUN_BINFILE,test-aslr) | $(CGREP) INTERP; \
+ readelf -l $(call RUN_BINFILE,test-aslr) | $(CGREP) DYNAMIC; \
+ $(call RUN,test-aslr) --test-aslr; \
+ fi
diff --git a/src/test/run-make/static-pie/check_clang_version.sh b/src/test/run-make/static-pie/check_clang_version.sh
new file mode 100755
index 000000000..b8e97c3da
--- /dev/null
+++ b/src/test/run-make/static-pie/check_clang_version.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+set -euo pipefail
+
+if command -v clang > /dev/null
+then
+ CLANG_VERSION=$(echo __clang_major__ | clang -E -x c - | grep -v -e '^#' )
+ echo "clang version $CLANG_VERSION detected"
+ if (( $CLANG_VERSION >= 9 ))
+ then
+ echo "clang supports -static-pie"
+ exit 0
+ else
+ echo "clang too old to support -static-pie, skipping test"
+ exit 1
+ fi
+else
+ echo "No clang version detected"
+ exit 2
+fi
diff --git a/src/test/run-make/static-pie/check_gcc_version.sh b/src/test/run-make/static-pie/check_gcc_version.sh
new file mode 100755
index 000000000..d07e1d151
--- /dev/null
+++ b/src/test/run-make/static-pie/check_gcc_version.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+set -euo pipefail
+
+if command -v gcc > /dev/null
+then
+ GCC_VERSION=$(echo __GNUC__ | gcc -E -x c - | grep -v -e '^#' )
+ echo "gcc version $GCC_VERSION detected"
+ if (( $GCC_VERSION >= 8 ))
+ then
+ echo "gcc supports -static-pie"
+ exit 0
+ else
+ echo "gcc too old to support -static-pie, skipping test"
+ exit 1
+ fi
+else
+ echo "No gcc version detected"
+ exit 2
+fi
diff --git a/src/test/run-make/static-pie/test-aslr.rs b/src/test/run-make/static-pie/test-aslr.rs
new file mode 100644
index 000000000..96b17af46
--- /dev/null
+++ b/src/test/run-make/static-pie/test-aslr.rs
@@ -0,0 +1,43 @@
+const NUM_RUNS: usize = 10;
+
+fn run_self(exe: &str) -> usize {
+ use std::process::Command;
+ let mut set = std::collections::HashSet::new();
+
+ let mut cmd = Command::new(exe);
+ cmd.arg("--report");
+ (0..NUM_RUNS).for_each(|_| {
+ set.insert(cmd.output().expect("failed to execute process").stdout);
+ });
+ set.len()
+}
+
+fn main() {
+ let mut args = std::env::args();
+ let arg0 = args.next().unwrap();
+ match args.next() {
+ Some(s) if s.eq("--report") => {
+ println!("main = {:#?}", &main as *const _);
+ }
+ Some(s) if s.eq("--test-no-aslr") => {
+ let cnt = run_self(&arg0);
+ if cnt != 1 {
+ eprintln!("FAIL: {} most likely ASLR", arg0);
+ std::process::exit(1);
+ }
+ println!("PASS: {} does no ASLR", arg0);
+ }
+ Some(s) if s.eq("--test-aslr") => {
+ let cnt = run_self(&arg0);
+ if cnt == 1 {
+ eprintln!("FAIL: {} most likely no ASLR", arg0);
+ std::process::exit(1);
+ }
+ println!("PASS: {} does ASLR", arg0);
+ }
+ Some(_) | None => {
+ println!("Usage: {} --test-no-aslr | --test-aslr", arg0);
+ std::process::exit(1);
+ }
+ }
+}
diff --git a/src/test/run-make/thumb-none-cortex-m/Makefile b/src/test/run-make/thumb-none-cortex-m/Makefile
new file mode 100644
index 000000000..13385369e
--- /dev/null
+++ b/src/test/run-make/thumb-none-cortex-m/Makefile
@@ -0,0 +1,38 @@
+-include ../../run-make-fulldeps/tools.mk
+
+# How to run this
+# $ ./x.py clean
+# $ ./x.py test --target thumbv6m-none-eabi,thumbv7m-none-eabi src/test/run-make
+
+# Supported targets:
+# - thumbv6m-none-eabi (Bare Cortex-M0, M0+, M1)
+# - thumbv7em-none-eabi (Bare Cortex-M4, M7)
+# - thumbv7em-none-eabihf (Bare Cortex-M4F, M7F, FPU, hardfloat)
+# - thumbv7m-none-eabi (Bare Cortex-M3)
+
+# only-thumb
+
+# For cargo setting
+RUSTC := $(RUSTC_ORIGINAL)
+LD_LIBRARY_PATH := $(HOST_RPATH_DIR)
+# We need to be outside of 'src' dir in order to run cargo
+WORK_DIR := $(TMPDIR)
+
+HERE := $(shell pwd)
+
+CRATE := cortex-m
+CRATE_URL := https://github.com/rust-embedded/cortex-m
+CRATE_SHA1 := a448e9156e2cb1e556e5441fd65426952ef4b927 # 0.5.0
+
+# Don't make lints fatal, but they need to at least warn or they break Cargo's target info parsing.
+export RUSTFLAGS := --cap-lints=warn
+
+all:
+ env
+ mkdir -p $(WORK_DIR)
+ -cd $(WORK_DIR) && rm -rf $(CRATE)
+ cd $(WORK_DIR) && bash -x $(HERE)/../git_clone_sha1.sh $(CRATE) $(CRATE_URL) $(CRATE_SHA1)
+ # HACK(eddyb) sets `RUSTC_BOOTSTRAP=1` so Cargo can accept nightly features.
+ # These come from the top-level Rust workspace, that this crate is not a
+ # member of, but Cargo tries to load the workspace `Cargo.toml` anyway.
+ cd $(WORK_DIR) && cd $(CRATE) && env RUSTC_BOOTSTRAP=1 $(BOOTSTRAP_CARGO) build --target $(TARGET) -v
diff --git a/src/test/run-make/thumb-none-qemu/Makefile b/src/test/run-make/thumb-none-qemu/Makefile
new file mode 100644
index 000000000..ab8b90e15
--- /dev/null
+++ b/src/test/run-make/thumb-none-qemu/Makefile
@@ -0,0 +1,27 @@
+-include ../../run-make-fulldeps/tools.mk
+
+# only-thumb
+
+# How to run this
+# $ ./x.py clean
+# $ ./x.py test --target thumbv7m-none-eabi src/test/run-make
+
+# For cargo setting
+export RUSTC := $(RUSTC_ORIGINAL)
+export LD_LIBRARY_PATH := $(HOST_RPATH_DIR)
+# We need to be outside of 'src' dir in order to run cargo
+export WORK_DIR := $(TMPDIR)
+export HERE := $(shell pwd)
+
+## clean up unused env variables which might cause harm.
+unexport RUSTC_LINKER
+unexport RUSTC_BOOTSTRAP
+unexport RUST_BUILD_STAGE
+unexport RUST_TEST_THREADS
+unexport RUST_TEST_TMPDIR
+unexport AR
+unexport CC
+unexport CXX
+
+all:
+ bash script.sh
diff --git a/src/test/run-make/thumb-none-qemu/example/.cargo/config b/src/test/run-make/thumb-none-qemu/example/.cargo/config
new file mode 100644
index 000000000..8b30310e7
--- /dev/null
+++ b/src/test/run-make/thumb-none-qemu/example/.cargo/config
@@ -0,0 +1,45 @@
+[target.thumbv6m-none-eabi]
+# FIXME: Should be Cortex-M0, but Qemu used by CI is too old
+runner = "qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel"
+
+[target.thumbv7m-none-eabi]
+runner = "qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel"
+
+[target.thumbv7em-none-eabi]
+runner = "qemu-system-arm -cpu cortex-m4 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel"
+
+[target.thumbv7em-none-eabihf]
+runner = "qemu-system-arm -cpu cortex-m4 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel"
+
+[target.thumbv8m.base-none-eabi]
+# FIXME: Should be the Cortex-M23, bt Qemu does not currently support it
+runner = "qemu-system-arm -cpu cortex-m33 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel"
+
+[target.thumbv8m.main-none-eabi]
+runner = "qemu-system-arm -cpu cortex-m33 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel"
+
+[target.thumbv8m.main-none-eabihf]
+runner = "qemu-system-arm -cpu cortex-m33 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel"
+
+[target.'cfg(all(target_arch = "arm", target_os = "none"))']
+# uncomment ONE of these three option to make `cargo run` start a GDB session
+# which option to pick depends on your system
+# runner = "arm-none-eabi-gdb -q -x openocd.gdb"
+# runner = "gdb-multiarch -q -x openocd.gdb"
+# runner = "gdb -q -x openocd.gdb"
+
+rustflags = [
+ # LLD (shipped with the Rust toolchain) is used as the default linker
+ "-C", "link-arg=-Tlink.x",
+
+ # if you run into problems with LLD switch to the GNU linker by commenting out
+ # this line
+ # "-C", "linker=arm-none-eabi-ld",
+
+ # if you need to link to pre-compiled C libraries provided by a C toolchain
+ # use GCC as the linker by commenting out both lines above and then
+ # uncommenting the three lines below
+ # "-C", "linker=arm-none-eabi-gcc",
+ # "-C", "link-arg=-Wl,-Tlink.x",
+ # "-C", "link-arg=-nostartfiles",
+]
diff --git a/src/test/run-make/thumb-none-qemu/example/Cargo.lock b/src/test/run-make/thumb-none-qemu/example/Cargo.lock
new file mode 100644
index 000000000..687b962a8
--- /dev/null
+++ b/src/test/run-make/thumb-none-qemu/example/Cargo.lock
@@ -0,0 +1,199 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "aligned"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "as-slice 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "as-slice"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "generic-array 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "bare-metal"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "cortex-m"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "aligned 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bare-metal 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "volatile-register 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "cortex-m-rt"
+version = "0.6.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cortex-m-rt-macros 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "cortex-m-rt-macros"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "cortex-m-semihosting"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cortex-m 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "example"
+version = "0.1.0"
+dependencies = [
+ "cortex-m 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cortex-m-rt 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cortex-m-semihosting 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "panic-halt 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "generic-array"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "generic-array"
+version = "0.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "panic-halt"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "r0"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "rustc_version"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "semver"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "semver-parser"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "stable_deref_trait"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "syn"
+version = "1.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "typenum"
+version = "1.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "vcell"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "volatile-register"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "vcell 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[metadata]
+"checksum aligned 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eb1ce8b3382016136ab1d31a1b5ce807144f8b7eb2d5f16b2108f0f07edceb94"
+"checksum as-slice 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "be6b7e95ac49d753f19cab5a825dea99a1149a04e4e3230b33ae16e120954c04"
+"checksum bare-metal 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3"
+"checksum cortex-m 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2954942fbbdd49996704e6f048ce57567c3e1a4e2dc59b41ae9fde06a01fc763"
+"checksum cortex-m-rt 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "33a716cd7d8627fae3892c2eede9249e50d2d79aedfb43ca28dad9a2b23876d9"
+"checksum cortex-m-rt-macros 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "72b1073338d1e691b3b7aaf6bd61993e589ececce9242a02dfa5453e1b98918d"
+"checksum cortex-m-semihosting 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "113ef0ecffee2b62b58f9380f4469099b30e9f9cbee2804771b4203ba1762cfa"
+"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
+"checksum generic-array 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0ed1e761351b56f54eb9dcd0cfaca9fd0daecf93918e1cfc01c8a3d26ee7adcd"
+"checksum panic-halt 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de96540e0ebde571dc55c73d60ef407c653844e6f9a1e2fdbd40c07b9252d812"
+"checksum proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3acb317c6ff86a4e579dfa00fc5e6cca91ecbb4e7eb2df0468805b674eb88548"
+"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
+"checksum r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2a38df5b15c8d5c7e8654189744d8e396bddc18ad48041a500ce52d6948941f"
+"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
+"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
+"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
+"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
+"checksum syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "af6f3550d8dff9ef7dc34d384ac6f107e5d31c8f57d9f28e0081503f547ac8f5"
+"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9"
+"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
+"checksum vcell 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "876e32dcadfe563a4289e994f7cb391197f362b6315dc45e8ba4aa6f564a4b3c"
+"checksum volatile-register 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d67cb4616d99b940db1d6bd28844ff97108b498a6ca850e5b6191a532063286"
diff --git a/src/test/run-make/thumb-none-qemu/example/Cargo.toml b/src/test/run-make/thumb-none-qemu/example/Cargo.toml
new file mode 100644
index 000000000..63eb5f90a
--- /dev/null
+++ b/src/test/run-make/thumb-none-qemu/example/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "example"
+version = "0.1.0"
+edition = "2018"
+
+[dependencies]
+cortex-m = "0.6.2"
+cortex-m-rt = "0.6.11"
+panic-halt = "0.2.0"
+cortex-m-semihosting = "0.3.1"
diff --git a/src/test/run-make/thumb-none-qemu/example/memory.x b/src/test/run-make/thumb-none-qemu/example/memory.x
new file mode 100644
index 000000000..dc7ad967a
--- /dev/null
+++ b/src/test/run-make/thumb-none-qemu/example/memory.x
@@ -0,0 +1,23 @@
+/* Device specific memory layout */
+
+/* This file is used to build the cortex-m-rt examples,
+ but not other applications using cortex-m-rt. */
+
+MEMORY
+{
+ /* FLASH and RAM are mandatory memory regions */
+ /* Update examples/data_overflow.rs if you change these sizes. */
+ FLASH : ORIGIN = 0x00000000, LENGTH = 256K
+ RAM : ORIGIN = 0x20000000, LENGTH = 64K
+
+ /* More memory regions can declared: for example this is a second RAM region */
+ /* CCRAM : ORIGIN = 0x10000000, LENGTH = 8K */
+}
+
+/* The location of the stack can be overridden using the `_stack_start` symbol.
+ By default it will be placed at the end of the RAM region */
+/* _stack_start = ORIGIN(CCRAM) + LENGTH(CCRAM); */
+
+/* The location of the .text section can be overridden using the `_stext` symbol.
+ By default it will place after .vector_table */
+/* _stext = ORIGIN(FLASH) + 0x40c; */ \ No newline at end of file
diff --git a/src/test/run-make/thumb-none-qemu/example/src/main.rs b/src/test/run-make/thumb-none-qemu/example/src/main.rs
new file mode 100644
index 000000000..2abfde8e7
--- /dev/null
+++ b/src/test/run-make/thumb-none-qemu/example/src/main.rs
@@ -0,0 +1,24 @@
+#![no_main]
+#![no_std]
+use core::fmt::Write;
+use cortex_m::asm;
+use cortex_m_rt::entry;
+use cortex_m_semihosting as semihosting;
+
+use panic_halt as _;
+
+#[entry]
+fn main() -> ! {
+ let x = 42;
+
+ loop {
+ asm::nop();
+
+ // write something through semihosting interface
+ let mut hstdout = semihosting::hio::hstdout().unwrap();
+ let _ = write!(hstdout, "x = {}\n", x);
+
+ // exit from qemu
+ semihosting::debug::exit(semihosting::debug::EXIT_SUCCESS);
+ }
+}
diff --git a/src/test/run-make/thumb-none-qemu/script.sh b/src/test/run-make/thumb-none-qemu/script.sh
new file mode 100644
index 000000000..a8aa72af1
--- /dev/null
+++ b/src/test/run-make/thumb-none-qemu/script.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+set -exuo pipefail
+
+CRATE=example
+
+env | sort
+mkdir -p $WORK_DIR
+pushd $WORK_DIR
+ rm -rf $CRATE || echo OK
+ cp -a $HERE/example .
+ pushd $CRATE
+ # HACK(eddyb) sets `RUSTC_BOOTSTRAP=1` so Cargo can accept nightly features.
+ # These come from the top-level Rust workspace, that this crate is not a
+ # member of, but Cargo tries to load the workspace `Cargo.toml` anyway.
+ env RUSTC_BOOTSTRAP=1 RUSTFLAGS="-C linker=arm-none-eabi-ld -C link-arg=-Tlink.x" \
+ $BOOTSTRAP_CARGO run --target $TARGET | grep "x = 42"
+ env RUSTC_BOOTSTRAP=1 RUSTFLAGS="-C linker=arm-none-eabi-ld -C link-arg=-Tlink.x" \
+ $BOOTSTRAP_CARGO run --target $TARGET --release | grep "x = 42"
+ popd
+popd
diff --git a/src/test/run-make/track-path-dep-info/Makefile b/src/test/run-make/track-path-dep-info/Makefile
new file mode 100644
index 000000000..465d37447
--- /dev/null
+++ b/src/test/run-make/track-path-dep-info/Makefile
@@ -0,0 +1,13 @@
+-include ../../run-make-fulldeps/tools.mk
+
+# FIXME(eddyb) provide `HOST_RUSTC` and `TARGET_RUSTC`
+# instead of hardcoding them everywhere they're needed.
+ifeq ($(IS_MUSL_HOST),1)
+ADDITIONAL_ARGS := $(RUSTFLAGS)
+endif
+
+all:
+ # Proc macro
+ $(BARE_RUSTC) $(ADDITIONAL_ARGS) --out-dir $(TMPDIR) macro_def.rs
+ EXISTING_PROC_MACRO_ENV=1 $(RUSTC) --emit dep-info macro_use.rs
+ $(CGREP) "emojis.txt:" < $(TMPDIR)/macro_use.d
diff --git a/src/test/run-make/track-path-dep-info/emojis.txt b/src/test/run-make/track-path-dep-info/emojis.txt
new file mode 100644
index 000000000..e1a728461
--- /dev/null
+++ b/src/test/run-make/track-path-dep-info/emojis.txt
@@ -0,0 +1 @@
+👾👾👾👾👾👾
diff --git a/src/test/run-make/track-path-dep-info/macro_def.rs b/src/test/run-make/track-path-dep-info/macro_def.rs
new file mode 100644
index 000000000..8777ce21f
--- /dev/null
+++ b/src/test/run-make/track-path-dep-info/macro_def.rs
@@ -0,0 +1,11 @@
+#![feature(track_path)]
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro]
+pub fn access_tracked_paths(_: TokenStream) -> TokenStream {
+ tracked_path::path("emojis.txt");
+ TokenStream::new()
+}
diff --git a/src/test/run-make/track-path-dep-info/macro_use.rs b/src/test/run-make/track-path-dep-info/macro_use.rs
new file mode 100644
index 000000000..3c49fd05d
--- /dev/null
+++ b/src/test/run-make/track-path-dep-info/macro_use.rs
@@ -0,0 +1,6 @@
+#[macro_use]
+extern crate macro_def;
+
+access_tracked_paths!();
+
+fn main() {}
diff --git a/src/test/run-make/translation/Makefile b/src/test/run-make/translation/Makefile
new file mode 100644
index 000000000..bfff75e7a
--- /dev/null
+++ b/src/test/run-make/translation/Makefile
@@ -0,0 +1,59 @@
+include ../../run-make-fulldeps/tools.mk
+
+# This test uses `ln -s` rather than copying to save testing time, but its
+# usage doesn't work on Windows.
+# ignore-windows
+
+SYSROOT:=$(shell $(RUSTC) --print sysroot)
+FAKEROOT=$(TMPDIR)/fakeroot
+
+all: normal custom sysroot
+
+normal: basic-translation.rs
+ $(RUSTC) $< 2>&1 | grep "struct literal body without path"
+
+custom: basic-translation.rs basic-translation.ftl
+ $(RUSTC) $< -Ztranslate-additional-ftl=$(CURDIR)/basic-translation.ftl 2>&1 | grep "this is a test message"
+
+# Check that a locale can be loaded from the sysroot given a language
+# identifier by making a local copy of the sysroot and adding the custom locale
+# to it.
+sysroot: basic-translation.rs basic-translation.ftl
+ 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
+ mkdir -p $(FAKEROOT)/share/locale/zh-CN/
+ ln -s $(CURDIR)/basic-translation.ftl $(FAKEROOT)/share/locale/zh-CN/basic-translation.ftl
+ $(RUSTC) $< --sysroot $(FAKEROOT) -Ztranslate-lang=zh-CN 2>&1 | grep "this is a test message"
+
+# Check that the compiler errors out when the sysroot requested cannot be
+# found. This test might start failing if there actually exists a Klingon
+# translation of rustc's error messages.
+sysroot-missing:
+ $(RUSTC) $< -Ztranslate-lang=tlh 2>&1 || grep "missing locale directory"
+
+# Check that the compiler errors out when the sysroot requested cannot be
+# found. This test might start failing if there actually exists a Klingon
+# translation of rustc's error messages.
+sysroot-invalid: basic-translation.rs basic-translation.ftl
+ 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
+ touch $(FAKEROOT)/share/locale/zh-CN/
+ $(RUSTC) $< --sysroot $(FAKEROOT) -Ztranslate-lang=zh-CN 2>&1 || grep "`\$sysroot/share/locales/\$locale` is not a directory"
diff --git a/src/test/run-make/translation/basic-translation.ftl b/src/test/run-make/translation/basic-translation.ftl
new file mode 100644
index 000000000..4681b879c
--- /dev/null
+++ b/src/test/run-make/translation/basic-translation.ftl
@@ -0,0 +1,2 @@
+parser-struct-literal-body-without-path = this is a test message
+ .suggestion = this is a test suggestion
diff --git a/src/test/run-make/translation/basic-translation.rs b/src/test/run-make/translation/basic-translation.rs
new file mode 100644
index 000000000..b8f5bff31
--- /dev/null
+++ b/src/test/run-make/translation/basic-translation.rs
@@ -0,0 +1,18 @@
+// Exact error being tested isn't relevant, it just needs to be known that it uses Fluent-backed
+// diagnostics.
+
+struct Foo {
+ val: (),
+}
+
+fn foo() -> Foo {
+ val: (),
+}
+
+fn main() {
+ let x = foo();
+ x.val == 42;
+ let x = {
+ val: (),
+ };
+}
diff --git a/src/test/run-make/unstable-flag-required/Makefile b/src/test/run-make/unstable-flag-required/Makefile
new file mode 100644
index 000000000..b8769d5f6
--- /dev/null
+++ b/src/test/run-make/unstable-flag-required/Makefile
@@ -0,0 +1,4 @@
+-include ../../run-make-fulldeps/tools.mk
+
+all:
+ $(RUSTDOC) --output-format=json x.html 2>&1 | diff - output-format-json.stderr
diff --git a/src/test/run-make/unstable-flag-required/README.md b/src/test/run-make/unstable-flag-required/README.md
new file mode 100644
index 000000000..e5251fdf9
--- /dev/null
+++ b/src/test/run-make/unstable-flag-required/README.md
@@ -0,0 +1,3 @@
+This is a collection of tests that verify `--unstable-options` is required.
+It should eventually be removed in favor of UI tests once compiletest stops
+passing --unstable-options by default (#82639).
diff --git a/src/test/run-make/unstable-flag-required/output-format-json.stderr b/src/test/run-make/unstable-flag-required/output-format-json.stderr
new file mode 100644
index 000000000..fb4079beb
--- /dev/null
+++ b/src/test/run-make/unstable-flag-required/output-format-json.stderr
@@ -0,0 +1,2 @@
+error: the -Z unstable-options flag must be passed to enable --output-format for documentation generation (see https://github.com/rust-lang/rust/issues/76578)
+
diff --git a/src/test/run-make/unstable-flag-required/x.rs b/src/test/run-make/unstable-flag-required/x.rs
new file mode 100644
index 000000000..5df757613
--- /dev/null
+++ b/src/test/run-make/unstable-flag-required/x.rs
@@ -0,0 +1 @@
+// nothing to see here
diff --git a/src/test/run-make/wasm-abi/Makefile b/src/test/run-make/wasm-abi/Makefile
new file mode 100644
index 000000000..61fc4e8f5
--- /dev/null
+++ b/src/test/run-make/wasm-abi/Makefile
@@ -0,0 +1,7 @@
+-include ../../run-make-fulldeps/tools.mk
+
+# only-wasm32-bare
+
+all:
+ $(RUSTC) foo.rs --target wasm32-unknown-unknown
+ $(NODE) foo.js $(TMPDIR)/foo.wasm
diff --git a/src/test/run-make/wasm-abi/foo.js b/src/test/run-make/wasm-abi/foo.js
new file mode 100644
index 000000000..9e9a65401
--- /dev/null
+++ b/src/test/run-make/wasm-abi/foo.js
@@ -0,0 +1,22 @@
+const fs = require('fs');
+const process = require('process');
+const assert = require('assert');
+const buffer = fs.readFileSync(process.argv[2]);
+
+const m = new WebAssembly.Module(buffer);
+const i = new WebAssembly.Instance(m, {
+ host: {
+ two_i32: () => [100, 101],
+ two_i64: () => [102n, 103n],
+ two_f32: () => [104, 105],
+ two_f64: () => [106, 107],
+ mishmash: () => [108, 109, 110, 111n, 112, 113],
+ }
+});
+
+assert.deepEqual(i.exports.return_two_i32(), [1, 2])
+assert.deepEqual(i.exports.return_two_i64(), [3, 4])
+assert.deepEqual(i.exports.return_two_f32(), [5, 6])
+assert.deepEqual(i.exports.return_two_f64(), [7, 8])
+assert.deepEqual(i.exports.return_mishmash(), [9, 10, 11, 12, 13, 14])
+i.exports.call_imports();
diff --git a/src/test/run-make/wasm-abi/foo.rs b/src/test/run-make/wasm-abi/foo.rs
new file mode 100644
index 000000000..0678eb3ff
--- /dev/null
+++ b/src/test/run-make/wasm-abi/foo.rs
@@ -0,0 +1,87 @@
+#![crate_type = "cdylib"]
+#![deny(warnings)]
+#![feature(wasm_abi)]
+
+#[repr(C)]
+#[derive(PartialEq, Debug)]
+pub struct TwoI32 {
+ pub a: i32,
+ pub b: i32,
+}
+
+#[no_mangle]
+pub extern "wasm" fn return_two_i32() -> TwoI32 {
+ TwoI32 { a: 1, b: 2 }
+}
+
+#[repr(C)]
+#[derive(PartialEq, Debug)]
+pub struct TwoI64 {
+ pub a: i64,
+ pub b: i64,
+}
+
+#[no_mangle]
+pub extern "wasm" fn return_two_i64() -> TwoI64 {
+ TwoI64 { a: 3, b: 4 }
+}
+
+#[repr(C)]
+#[derive(PartialEq, Debug)]
+pub struct TwoF32 {
+ pub a: f32,
+ pub b: f32,
+}
+
+#[no_mangle]
+pub extern "wasm" fn return_two_f32() -> TwoF32 {
+ TwoF32 { a: 5., b: 6. }
+}
+
+#[repr(C)]
+#[derive(PartialEq, Debug)]
+pub struct TwoF64 {
+ pub a: f64,
+ pub b: f64,
+}
+
+#[no_mangle]
+pub extern "wasm" fn return_two_f64() -> TwoF64 {
+ TwoF64 { a: 7., b: 8. }
+}
+
+#[repr(C)]
+#[derive(PartialEq, Debug)]
+pub struct Mishmash {
+ pub a: f64,
+ pub b: f32,
+ pub c: i32,
+ pub d: i64,
+ pub e: TwoI32,
+}
+
+#[no_mangle]
+pub extern "wasm" fn return_mishmash() -> Mishmash {
+ Mishmash { a: 9., b: 10., c: 11, d: 12, e: TwoI32 { a: 13, b: 14 } }
+}
+
+#[link(wasm_import_module = "host")]
+extern "wasm" {
+ fn two_i32() -> TwoI32;
+ fn two_i64() -> TwoI64;
+ fn two_f32() -> TwoF32;
+ fn two_f64() -> TwoF64;
+ fn mishmash() -> Mishmash;
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn call_imports() {
+ assert_eq!(two_i32(), TwoI32 { a: 100, b: 101 });
+ assert_eq!(two_i64(), TwoI64 { a: 102, b: 103 });
+ assert_eq!(two_f32(), TwoF32 { a: 104., b: 105. });
+ assert_eq!(two_f64(), TwoF64 { a: 106., b: 107. });
+ assert_eq!(
+ mishmash(),
+ Mishmash { a: 108., b: 109., c: 110, d: 111, e: TwoI32 { a: 112, b: 113 } }
+ );
+}
diff --git a/src/test/run-make/wasm-custom-section/Makefile b/src/test/run-make/wasm-custom-section/Makefile
new file mode 100644
index 000000000..2f48b8525
--- /dev/null
+++ b/src/test/run-make/wasm-custom-section/Makefile
@@ -0,0 +1,8 @@
+-include ../../run-make-fulldeps/tools.mk
+
+# only-wasm32-bare
+
+all:
+ $(RUSTC) foo.rs --target wasm32-unknown-unknown
+ $(RUSTC) bar.rs -C lto -O --target wasm32-unknown-unknown
+ $(NODE) foo.js $(TMPDIR)/bar.wasm
diff --git a/src/test/run-make/wasm-custom-section/bar.rs b/src/test/run-make/wasm-custom-section/bar.rs
new file mode 100644
index 000000000..c95f3e143
--- /dev/null
+++ b/src/test/run-make/wasm-custom-section/bar.rs
@@ -0,0 +1,13 @@
+#![crate_type = "cdylib"]
+#![deny(warnings)]
+
+extern crate foo;
+
+#[link_section = "foo"]
+pub static A: [u8; 2] = [5, 6];
+
+#[link_section = "baz"]
+pub static B: [u8; 2] = [7, 8];
+
+#[no_mangle]
+pub extern fn foo() {}
diff --git a/src/test/run-make/wasm-custom-section/foo.js b/src/test/run-make/wasm-custom-section/foo.js
new file mode 100644
index 000000000..57a0f5073
--- /dev/null
+++ b/src/test/run-make/wasm-custom-section/foo.js
@@ -0,0 +1,36 @@
+const fs = require('fs');
+const process = require('process');
+const assert = require('assert');
+const buffer = fs.readFileSync(process.argv[2]);
+
+let m = new WebAssembly.Module(buffer);
+let sections = WebAssembly.Module.customSections(m, "baz");
+console.log('section baz', sections);
+assert.strictEqual(sections.length, 1);
+let section = new Uint8Array(sections[0]);
+console.log('contents', section);
+assert.strictEqual(section.length, 2);
+assert.strictEqual(section[0], 7);
+assert.strictEqual(section[1], 8);
+
+sections = WebAssembly.Module.customSections(m, "bar");
+console.log('section bar', sections);
+assert.strictEqual(sections.length, 1, "didn't pick up `bar` section from dependency");
+section = new Uint8Array(sections[0]);
+console.log('contents', section);
+assert.strictEqual(section.length, 2);
+assert.strictEqual(section[0], 3);
+assert.strictEqual(section[1], 4);
+
+sections = WebAssembly.Module.customSections(m, "foo");
+console.log('section foo', sections);
+assert.strictEqual(sections.length, 1, "didn't create `foo` section");
+section = new Uint8Array(sections[0]);
+console.log('contents', section);
+assert.strictEqual(section.length, 4, "didn't concatenate `foo` sections");
+assert.strictEqual(section[0], 5);
+assert.strictEqual(section[1], 6);
+assert.strictEqual(section[2], 1);
+assert.strictEqual(section[3], 2);
+
+process.exit(0);
diff --git a/src/test/run-make/wasm-custom-section/foo.rs b/src/test/run-make/wasm-custom-section/foo.rs
new file mode 100644
index 000000000..61f81f024
--- /dev/null
+++ b/src/test/run-make/wasm-custom-section/foo.rs
@@ -0,0 +1,8 @@
+#![crate_type = "rlib"]
+#![deny(warnings)]
+
+#[link_section = "foo"]
+pub static A: [u8; 2] = [1, 2];
+
+#[link_section = "bar"]
+pub static B: [u8; 2] = [3, 4];
diff --git a/src/test/run-make/wasm-custom-sections-opt/Makefile b/src/test/run-make/wasm-custom-sections-opt/Makefile
new file mode 100644
index 000000000..76698c0aa
--- /dev/null
+++ b/src/test/run-make/wasm-custom-sections-opt/Makefile
@@ -0,0 +1,7 @@
+-include ../../run-make-fulldeps/tools.mk
+
+# only-wasm32-bare
+
+all:
+ $(RUSTC) foo.rs -O --target wasm32-unknown-unknown
+ $(NODE) foo.js $(TMPDIR)/foo.wasm
diff --git a/src/test/run-make/wasm-custom-sections-opt/foo.js b/src/test/run-make/wasm-custom-sections-opt/foo.js
new file mode 100644
index 000000000..9663f377e
--- /dev/null
+++ b/src/test/run-make/wasm-custom-sections-opt/foo.js
@@ -0,0 +1,15 @@
+const fs = require('fs');
+const process = require('process');
+const assert = require('assert');
+const buffer = fs.readFileSync(process.argv[2]);
+
+let m = new WebAssembly.Module(buffer);
+
+sections = WebAssembly.Module.customSections(m, "foo");
+console.log('section foo', sections);
+assert.strictEqual(sections.length, 1, "didn't create `foo` section");
+section = new Uint8Array(sections[0]);
+console.log('contents', section);
+assert.strictEqual(section.length, 4, "didn't concatenate `foo` sections");
+
+process.exit(0);
diff --git a/src/test/run-make/wasm-custom-sections-opt/foo.rs b/src/test/run-make/wasm-custom-sections-opt/foo.rs
new file mode 100644
index 000000000..9af7728b7
--- /dev/null
+++ b/src/test/run-make/wasm-custom-sections-opt/foo.rs
@@ -0,0 +1,21 @@
+#![crate_type = "cdylib"]
+#![deny(warnings)]
+
+#[link_section = "foo"]
+pub static A: [u8; 2] = [1, 2];
+
+// make sure this is in another CGU
+pub mod another {
+ #[link_section = "foo"]
+ pub static FOO: [u8; 2] = [3, 4];
+
+ pub fn foo() {}
+}
+
+#[no_mangle]
+pub extern fn foo() {
+ // This will import `another::foo` through ThinLTO passes, and it better not
+ // also accidentally import the `FOO` custom section into this module as
+ // well
+ another::foo();
+}
diff --git a/src/test/run-make/wasm-export-all-symbols/Makefile b/src/test/run-make/wasm-export-all-symbols/Makefile
new file mode 100644
index 000000000..7e47ba485
--- /dev/null
+++ b/src/test/run-make/wasm-export-all-symbols/Makefile
@@ -0,0 +1,19 @@
+-include ../../run-make-fulldeps/tools.mk
+
+# only-wasm32-bare
+
+all:
+ $(RUSTC) bar.rs --target wasm32-unknown-unknown
+ $(RUSTC) foo.rs --target wasm32-unknown-unknown
+ $(NODE) verify.js $(TMPDIR)/foo.wasm
+ $(RUSTC) main.rs --target wasm32-unknown-unknown
+ $(NODE) verify.js $(TMPDIR)/main.wasm
+ $(RUSTC) bar.rs --target wasm32-unknown-unknown -O
+ $(RUSTC) foo.rs --target wasm32-unknown-unknown -O
+ $(NODE) verify.js $(TMPDIR)/foo.wasm
+ $(RUSTC) main.rs --target wasm32-unknown-unknown -O
+ $(NODE) verify.js $(TMPDIR)/main.wasm
+ $(RUSTC) foo.rs --target wasm32-unknown-unknown -C lto
+ $(NODE) verify.js $(TMPDIR)/foo.wasm
+ $(RUSTC) main.rs --target wasm32-unknown-unknown -C lto
+ $(NODE) verify.js $(TMPDIR)/main.wasm
diff --git a/src/test/run-make/wasm-export-all-symbols/bar.rs b/src/test/run-make/wasm-export-all-symbols/bar.rs
new file mode 100644
index 000000000..ac9c20a57
--- /dev/null
+++ b/src/test/run-make/wasm-export-all-symbols/bar.rs
@@ -0,0 +1,7 @@
+#![crate_type = "rlib"]
+
+#[no_mangle]
+pub extern fn foo() {}
+
+#[no_mangle]
+pub static FOO: u64 = 42;
diff --git a/src/test/run-make/wasm-export-all-symbols/foo.rs b/src/test/run-make/wasm-export-all-symbols/foo.rs
new file mode 100644
index 000000000..4811b24bc
--- /dev/null
+++ b/src/test/run-make/wasm-export-all-symbols/foo.rs
@@ -0,0 +1,3 @@
+#![crate_type = "cdylib"]
+
+extern crate bar;
diff --git a/src/test/run-make/wasm-export-all-symbols/main.rs b/src/test/run-make/wasm-export-all-symbols/main.rs
new file mode 100644
index 000000000..0edda7d7b
--- /dev/null
+++ b/src/test/run-make/wasm-export-all-symbols/main.rs
@@ -0,0 +1,3 @@
+extern crate bar;
+
+fn main() {}
diff --git a/src/test/run-make/wasm-export-all-symbols/verify.js b/src/test/run-make/wasm-export-all-symbols/verify.js
new file mode 100644
index 000000000..72db3356f
--- /dev/null
+++ b/src/test/run-make/wasm-export-all-symbols/verify.js
@@ -0,0 +1,32 @@
+const fs = require('fs');
+const process = require('process');
+const assert = require('assert');
+const buffer = fs.readFileSync(process.argv[2]);
+
+let m = new WebAssembly.Module(buffer);
+let list = WebAssembly.Module.exports(m);
+console.log('exports', list);
+
+const my_exports = {};
+let nexports = 0;
+
+for (const entry of list) {
+ if (entry.kind == 'function'){
+ nexports += 1;
+ }
+ my_exports[entry.name] = entry.kind;
+}
+
+if (my_exports.foo != "function")
+ throw new Error("`foo` wasn't defined");
+
+if (my_exports.FOO != "global")
+ throw new Error("`FOO` wasn't defined");
+
+if (my_exports.main === undefined) {
+ if (nexports != 1)
+ throw new Error("should only have one function export");
+} else {
+ if (nexports != 2)
+ throw new Error("should only have two function exports");
+}
diff --git a/src/test/run-make/wasm-import-module/Makefile b/src/test/run-make/wasm-import-module/Makefile
new file mode 100644
index 000000000..fe63e66f2
--- /dev/null
+++ b/src/test/run-make/wasm-import-module/Makefile
@@ -0,0 +1,8 @@
+-include ../../run-make-fulldeps/tools.mk
+
+ # only-wasm32-bare
+
+all:
+ $(RUSTC) foo.rs --target wasm32-unknown-unknown
+ $(RUSTC) bar.rs -C lto -O --target wasm32-unknown-unknown
+ $(NODE) foo.js $(TMPDIR)/bar.wasm
diff --git a/src/test/run-make/wasm-import-module/bar.rs b/src/test/run-make/wasm-import-module/bar.rs
new file mode 100644
index 000000000..1b988c783
--- /dev/null
+++ b/src/test/run-make/wasm-import-module/bar.rs
@@ -0,0 +1,18 @@
+#![crate_type = "cdylib"]
+#![deny(warnings)]
+
+extern crate foo;
+
+#[link(wasm_import_module = "./me")]
+extern "C" {
+ #[link_name = "me_in_dep"]
+ fn dep();
+}
+
+#[no_mangle]
+pub extern "C" fn foo() {
+ unsafe {
+ foo::dep();
+ dep();
+ }
+}
diff --git a/src/test/run-make/wasm-import-module/foo.js b/src/test/run-make/wasm-import-module/foo.js
new file mode 100644
index 000000000..3ea47fcc9
--- /dev/null
+++ b/src/test/run-make/wasm-import-module/foo.js
@@ -0,0 +1,18 @@
+const fs = require('fs');
+const process = require('process');
+const assert = require('assert');
+const buffer = fs.readFileSync(process.argv[2]);
+
+let m = new WebAssembly.Module(buffer);
+let imports = WebAssembly.Module.imports(m);
+console.log('imports', imports);
+assert.strictEqual(imports.length, 2);
+
+assert.strictEqual(imports[0].kind, 'function');
+assert.strictEqual(imports[1].kind, 'function');
+
+let modules = [imports[0].module, imports[1].module];
+modules.sort();
+
+assert.strictEqual(modules[0], './dep');
+assert.strictEqual(modules[1], './me');
diff --git a/src/test/run-make/wasm-import-module/foo.rs b/src/test/run-make/wasm-import-module/foo.rs
new file mode 100644
index 000000000..bbeaf99bc
--- /dev/null
+++ b/src/test/run-make/wasm-import-module/foo.rs
@@ -0,0 +1,7 @@
+#![crate_type = "rlib"]
+#![deny(warnings)]
+
+#[link(wasm_import_module = "./dep")]
+extern "C" {
+ pub fn dep();
+}
diff --git a/src/test/run-make/wasm-panic-small/Makefile b/src/test/run-make/wasm-panic-small/Makefile
new file mode 100644
index 000000000..68397e4bc
--- /dev/null
+++ b/src/test/run-make/wasm-panic-small/Makefile
@@ -0,0 +1,17 @@
+-include ../../run-make-fulldeps/tools.mk
+
+# only-wasm32-bare
+
+all:
+ $(RUSTC) foo.rs -C lto -O --target wasm32-unknown-unknown --cfg a
+ wc -c < $(TMPDIR)/foo.wasm
+ [ "`wc -c < $(TMPDIR)/foo.wasm`" -lt "1024" ]
+ $(RUSTC) foo.rs -C lto -O --target wasm32-unknown-unknown --cfg b
+ wc -c < $(TMPDIR)/foo.wasm
+ [ "`wc -c < $(TMPDIR)/foo.wasm`" -lt "5120" ]
+ $(RUSTC) foo.rs -C lto -O --target wasm32-unknown-unknown --cfg c
+ wc -c < $(TMPDIR)/foo.wasm
+ [ "`wc -c < $(TMPDIR)/foo.wasm`" -lt "5120" ]
+ $(RUSTC) foo.rs -C lto -O --target wasm32-unknown-unknown --cfg d
+ wc -c < $(TMPDIR)/foo.wasm
+ [ "`wc -c < $(TMPDIR)/foo.wasm`" -lt "5120" ]
diff --git a/src/test/run-make/wasm-panic-small/foo.rs b/src/test/run-make/wasm-panic-small/foo.rs
new file mode 100644
index 000000000..6df52affe
--- /dev/null
+++ b/src/test/run-make/wasm-panic-small/foo.rs
@@ -0,0 +1,27 @@
+#![crate_type = "cdylib"]
+
+#[no_mangle]
+#[cfg(a)]
+pub fn foo() {
+ panic!("test");
+}
+
+#[no_mangle]
+#[cfg(b)]
+pub fn foo() {
+ panic!("{}", 1);
+}
+
+#[no_mangle]
+#[cfg(c)]
+pub fn foo() {
+ panic!("{}", "a");
+}
+
+#[no_mangle]
+#[cfg(d)]
+pub fn foo() -> usize {
+ use std::cell::Cell;
+ thread_local!(static A: Cell<Vec<u32>> = Cell::new(Vec::new()));
+ A.try_with(|x| x.take().len()).unwrap_or(0)
+}
diff --git a/src/test/run-make/wasm-spurious-import/Makefile b/src/test/run-make/wasm-spurious-import/Makefile
new file mode 100644
index 000000000..1bb59dc1b
--- /dev/null
+++ b/src/test/run-make/wasm-spurious-import/Makefile
@@ -0,0 +1,7 @@
+-include ../../run-make-fulldeps/tools.mk
+
+# only-wasm32-bare
+
+all:
+ $(RUSTC) main.rs -C overflow-checks=yes -C panic=abort -C lto -C opt-level=z --target wasm32-unknown-unknown
+ $(NODE) verify.js $(TMPDIR)/main.wasm
diff --git a/src/test/run-make/wasm-spurious-import/main.rs b/src/test/run-make/wasm-spurious-import/main.rs
new file mode 100644
index 000000000..fcbead5e2
--- /dev/null
+++ b/src/test/run-make/wasm-spurious-import/main.rs
@@ -0,0 +1,14 @@
+#![crate_type = "cdylib"]
+#![no_std]
+
+#[panic_handler]
+fn my_panic(_info: &core::panic::PanicInfo) -> ! {
+ loop {}
+}
+
+#[no_mangle]
+pub fn multer(a: i128, b: i128) -> i128 {
+ // Trigger usage of the __multi3 compiler intrinsic which then leads to an imported
+ // panic function in case of a bug. We verify that no imports exist in our verifier.
+ a * b
+}
diff --git a/src/test/run-make/wasm-spurious-import/verify.js b/src/test/run-make/wasm-spurious-import/verify.js
new file mode 100644
index 000000000..d3b2101b6
--- /dev/null
+++ b/src/test/run-make/wasm-spurious-import/verify.js
@@ -0,0 +1,9 @@
+const fs = require('fs');
+const process = require('process');
+const assert = require('assert');
+const buffer = fs.readFileSync(process.argv[2]);
+
+let m = new WebAssembly.Module(buffer);
+let imports = WebAssembly.Module.imports(m);
+console.log('imports', imports);
+assert.strictEqual(imports.length, 0);
diff --git a/src/test/run-make/wasm-stringify-ints-small/Makefile b/src/test/run-make/wasm-stringify-ints-small/Makefile
new file mode 100644
index 000000000..01e1c6b0c
--- /dev/null
+++ b/src/test/run-make/wasm-stringify-ints-small/Makefile
@@ -0,0 +1,10 @@
+-include ../../run-make-fulldeps/tools.mk
+
+ifeq ($(TARGET),wasm32-unknown-unknown)
+all:
+ $(RUSTC) foo.rs -C lto -O --target wasm32-unknown-unknown
+ wc -c < $(TMPDIR)/foo.wasm
+ [ "`wc -c < $(TMPDIR)/foo.wasm`" -lt "25000" ]
+else
+all:
+endif
diff --git a/src/test/run-make/wasm-stringify-ints-small/foo.rs b/src/test/run-make/wasm-stringify-ints-small/foo.rs
new file mode 100644
index 000000000..7a947f013
--- /dev/null
+++ b/src/test/run-make/wasm-stringify-ints-small/foo.rs
@@ -0,0 +1,33 @@
+#![crate_type = "cdylib"]
+
+extern "C" {
+ fn observe(ptr: *const u8, len: usize);
+}
+
+macro_rules! s {
+ ( $( $f:ident -> $t:ty );* $(;)* ) => {
+ $(
+ extern "C" {
+ fn $f() -> $t;
+ }
+ let s = $f().to_string();
+ observe(s.as_ptr(), s.len());
+ )*
+ };
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn foo() {
+ s! {
+ get_u8 -> u8;
+ get_i8 -> i8;
+ get_u16 -> u16;
+ get_i16 -> i16;
+ get_u32 -> u32;
+ get_i32 -> i32;
+ get_u64 -> u64;
+ get_i64 -> i64;
+ get_usize -> usize;
+ get_isize -> isize;
+ }
+}
diff --git a/src/test/run-make/wasm-symbols-different-module/Makefile b/src/test/run-make/wasm-symbols-different-module/Makefile
new file mode 100644
index 000000000..bb6a5d3c9
--- /dev/null
+++ b/src/test/run-make/wasm-symbols-different-module/Makefile
@@ -0,0 +1,28 @@
+-include ../../run-make-fulldeps/tools.mk
+
+# only-wasm32-bare
+
+all:
+ $(RUSTC) foo.rs --target wasm32-unknown-unknown
+ $(NODE) verify-imports.js $(TMPDIR)/foo.wasm a/foo b/foo
+ $(RUSTC) foo.rs --target wasm32-unknown-unknown -C lto
+ $(NODE) verify-imports.js $(TMPDIR)/foo.wasm a/foo b/foo
+ $(RUSTC) foo.rs --target wasm32-unknown-unknown -O
+ $(NODE) verify-imports.js $(TMPDIR)/foo.wasm a/foo b/foo
+ $(RUSTC) foo.rs --target wasm32-unknown-unknown -O -C lto
+ $(NODE) verify-imports.js $(TMPDIR)/foo.wasm a/foo b/foo
+
+ $(RUSTC) bar.rs --target wasm32-unknown-unknown
+ $(NODE) verify-imports.js $(TMPDIR)/bar.wasm m1/f m1/g m2/f
+ $(RUSTC) bar.rs --target wasm32-unknown-unknown -C lto
+ $(NODE) verify-imports.js $(TMPDIR)/bar.wasm m1/f m1/g m2/f
+ $(RUSTC) bar.rs --target wasm32-unknown-unknown -O
+ $(NODE) verify-imports.js $(TMPDIR)/bar.wasm m1/f m1/g m2/f
+ $(RUSTC) bar.rs --target wasm32-unknown-unknown -O -C lto
+ $(NODE) verify-imports.js $(TMPDIR)/bar.wasm m1/f m1/g m2/f
+
+ $(RUSTC) baz.rs --target wasm32-unknown-unknown
+ $(NODE) verify-imports.js $(TMPDIR)/baz.wasm sqlite/allocate sqlite/deallocate
+
+ $(RUSTC) log.rs --target wasm32-unknown-unknown
+ $(NODE) verify-imports.js $(TMPDIR)/log.wasm test/log
diff --git a/src/test/run-make/wasm-symbols-different-module/bar.rs b/src/test/run-make/wasm-symbols-different-module/bar.rs
new file mode 100644
index 000000000..7567060d7
--- /dev/null
+++ b/src/test/run-make/wasm-symbols-different-module/bar.rs
@@ -0,0 +1,33 @@
+//! Issue #50021
+
+#![crate_type = "cdylib"]
+
+mod m1 {
+ #[link(wasm_import_module = "m1")]
+ extern "C" {
+ pub fn f();
+ }
+ #[link(wasm_import_module = "m1")]
+ extern "C" {
+ pub fn g();
+ }
+}
+
+mod m2 {
+ #[link(wasm_import_module = "m2")]
+ extern "C" {
+ pub fn f(_: i32);
+ }
+}
+
+#[no_mangle]
+pub unsafe fn run() {
+ m1::f();
+ m1::g();
+
+ // In generated code, expected:
+ // (import "m2" "f" (func $f (param i32)))
+ // but got:
+ // (import "m1" "f" (func $f (param i32)))
+ m2::f(0);
+}
diff --git a/src/test/run-make/wasm-symbols-different-module/baz.rs b/src/test/run-make/wasm-symbols-different-module/baz.rs
new file mode 100644
index 000000000..fbb78619b
--- /dev/null
+++ b/src/test/run-make/wasm-symbols-different-module/baz.rs
@@ -0,0 +1,22 @@
+//! Issue #63562
+
+#![crate_type = "cdylib"]
+
+mod foo {
+ #[link(wasm_import_module = "sqlite")]
+ extern "C" {
+ pub fn allocate(size: usize) -> i32;
+ pub fn deallocate(ptr: i32, size: usize);
+ }
+}
+
+#[no_mangle]
+pub extern "C" fn allocate() {
+ unsafe {
+ foo::allocate(1);
+ foo::deallocate(1, 2);
+ }
+}
+
+#[no_mangle]
+pub extern "C" fn deallocate() {}
diff --git a/src/test/run-make/wasm-symbols-different-module/foo.rs b/src/test/run-make/wasm-symbols-different-module/foo.rs
new file mode 100644
index 000000000..a4ba7e714
--- /dev/null
+++ b/src/test/run-make/wasm-symbols-different-module/foo.rs
@@ -0,0 +1,23 @@
+#![crate_type = "cdylib"]
+
+mod a {
+ #[link(wasm_import_module = "a")]
+ extern "C" {
+ pub fn foo();
+ }
+}
+
+mod b {
+ #[link(wasm_import_module = "b")]
+ extern "C" {
+ pub fn foo();
+ }
+}
+
+#[no_mangle]
+pub fn start() {
+ unsafe {
+ a::foo();
+ b::foo();
+ }
+}
diff --git a/src/test/run-make/wasm-symbols-different-module/log.rs b/src/test/run-make/wasm-symbols-different-module/log.rs
new file mode 100644
index 000000000..ea3e0b4b2
--- /dev/null
+++ b/src/test/run-make/wasm-symbols-different-module/log.rs
@@ -0,0 +1,16 @@
+//! Issue #56309
+
+#![crate_type = "cdylib"]
+
+#[link(wasm_import_module = "test")]
+extern "C" {
+ fn log(message_data: u32, message_size: u32);
+}
+
+#[no_mangle]
+pub fn main() {
+ let message = "Hello, world!";
+ unsafe {
+ log(message.as_ptr() as u32, message.len() as u32);
+ }
+}
diff --git a/src/test/run-make/wasm-symbols-different-module/verify-imports.js b/src/test/run-make/wasm-symbols-different-module/verify-imports.js
new file mode 100644
index 000000000..7e9f90cf8
--- /dev/null
+++ b/src/test/run-make/wasm-symbols-different-module/verify-imports.js
@@ -0,0 +1,32 @@
+const fs = require('fs');
+const process = require('process');
+const assert = require('assert');
+const buffer = fs.readFileSync(process.argv[2]);
+
+let m = new WebAssembly.Module(buffer);
+let list = WebAssembly.Module.imports(m);
+console.log('imports', list);
+if (list.length !== process.argv.length - 3)
+ throw new Error("wrong number of imports")
+
+const imports = new Map();
+for (let i = 3; i < process.argv.length; i++) {
+ const [module, name] = process.argv[i].split('/');
+ if (!imports.has(module))
+ imports.set(module, new Map());
+ imports.get(module).set(name, true);
+}
+
+for (let i of list) {
+ if (imports.get(i.module) === undefined || imports.get(i.module).get(i.name) === undefined)
+ throw new Error(`didn't find import of ${i.module}::${i.name}`);
+ imports.get(i.module).delete(i.name);
+
+ if (imports.get(i.module).size === 0)
+ imports.delete(i.module);
+}
+
+console.log(imports);
+if (imports.size !== 0) {
+ throw new Error('extra imports');
+}
diff --git a/src/test/run-make/wasm-symbols-not-exported/Makefile b/src/test/run-make/wasm-symbols-not-exported/Makefile
new file mode 100644
index 000000000..62bd0f087
--- /dev/null
+++ b/src/test/run-make/wasm-symbols-not-exported/Makefile
@@ -0,0 +1,13 @@
+-include ../../run-make-fulldeps/tools.mk
+
+# only-wasm32-bare
+
+all:
+ $(RUSTC) foo.rs --target wasm32-unknown-unknown
+ $(NODE) verify-exported-symbols.js $(TMPDIR)/foo.wasm
+ $(RUSTC) foo.rs --target wasm32-unknown-unknown -O
+ $(NODE) verify-exported-symbols.js $(TMPDIR)/foo.wasm
+ $(RUSTC) bar.rs --target wasm32-unknown-unknown
+ $(NODE) verify-exported-symbols.js $(TMPDIR)/bar.wasm
+ $(RUSTC) bar.rs --target wasm32-unknown-unknown -O
+ $(NODE) verify-exported-symbols.js $(TMPDIR)/bar.wasm
diff --git a/src/test/run-make/wasm-symbols-not-exported/bar.rs b/src/test/run-make/wasm-symbols-not-exported/bar.rs
new file mode 100644
index 000000000..6ffbd3ec6
--- /dev/null
+++ b/src/test/run-make/wasm-symbols-not-exported/bar.rs
@@ -0,0 +1,35 @@
+#![feature(panic_handler, alloc_error_handler)]
+#![crate_type = "cdylib"]
+#![no_std]
+
+use core::alloc::*;
+
+struct B;
+
+unsafe impl GlobalAlloc for B {
+ unsafe fn alloc(&self, x: Layout) -> *mut u8 {
+ 1 as *mut u8
+ }
+
+ unsafe fn dealloc(&self, ptr: *mut u8, x: Layout) {
+ }
+}
+
+#[global_allocator]
+static A: B = B;
+
+#[no_mangle]
+pub extern fn foo(a: u32) -> u32 {
+ assert_eq!(a, 3);
+ a * 2
+}
+
+#[alloc_error_handler]
+fn a(_: core::alloc::Layout) -> ! {
+ loop {}
+}
+
+#[panic_handler]
+fn b(_: &core::panic::PanicInfo) -> ! {
+ loop {}
+}
diff --git a/src/test/run-make/wasm-symbols-not-exported/foo.rs b/src/test/run-make/wasm-symbols-not-exported/foo.rs
new file mode 100644
index 000000000..d46baee01
--- /dev/null
+++ b/src/test/run-make/wasm-symbols-not-exported/foo.rs
@@ -0,0 +1,7 @@
+#![crate_type = "cdylib"]
+
+#[no_mangle]
+pub extern fn foo() {
+ println!("foo");
+ panic!("test");
+}
diff --git a/src/test/run-make/wasm-symbols-not-exported/verify-exported-symbols.js b/src/test/run-make/wasm-symbols-not-exported/verify-exported-symbols.js
new file mode 100644
index 000000000..afc8a7241
--- /dev/null
+++ b/src/test/run-make/wasm-symbols-not-exported/verify-exported-symbols.js
@@ -0,0 +1,21 @@
+const fs = require('fs');
+const process = require('process');
+const assert = require('assert');
+const buffer = fs.readFileSync(process.argv[2]);
+
+let m = new WebAssembly.Module(buffer);
+let list = WebAssembly.Module.exports(m);
+console.log('exports', list);
+
+let bad = false;
+for (let i = 0; i < list.length; i++) {
+ const e = list[i];
+ if (e.name == "foo" || e.kind != "function")
+ continue;
+
+ console.log('unexpected exported symbol:', e.name);
+ bad = true;
+}
+
+if (bad)
+ process.exit(1);
diff --git a/src/test/run-make/wasm-symbols-not-imported/Makefile b/src/test/run-make/wasm-symbols-not-imported/Makefile
new file mode 100644
index 000000000..7a923375c
--- /dev/null
+++ b/src/test/run-make/wasm-symbols-not-imported/Makefile
@@ -0,0 +1,13 @@
+-include ../../run-make-fulldeps/tools.mk
+
+# only-wasm32-bare
+
+all:
+ $(RUSTC) foo.rs --target wasm32-unknown-unknown
+ $(NODE) verify-no-imports.js $(TMPDIR)/foo.wasm
+ $(RUSTC) foo.rs --target wasm32-unknown-unknown -C lto
+ $(NODE) verify-no-imports.js $(TMPDIR)/foo.wasm
+ $(RUSTC) foo.rs --target wasm32-unknown-unknown -O
+ $(NODE) verify-no-imports.js $(TMPDIR)/foo.wasm
+ $(RUSTC) foo.rs --target wasm32-unknown-unknown -O -C lto
+ $(NODE) verify-no-imports.js $(TMPDIR)/foo.wasm
diff --git a/src/test/run-make/wasm-symbols-not-imported/foo.rs b/src/test/run-make/wasm-symbols-not-imported/foo.rs
new file mode 100644
index 000000000..b25bdc980
--- /dev/null
+++ b/src/test/run-make/wasm-symbols-not-imported/foo.rs
@@ -0,0 +1,14 @@
+#![crate_type = "cdylib"]
+#![no_std]
+
+use core::panic::PanicInfo;
+
+#[no_mangle]
+pub extern fn foo() {
+ panic!()
+}
+
+#[panic_handler]
+fn panic(_info: &PanicInfo) -> ! {
+ loop {}
+}
diff --git a/src/test/run-make/wasm-symbols-not-imported/verify-no-imports.js b/src/test/run-make/wasm-symbols-not-imported/verify-no-imports.js
new file mode 100644
index 000000000..90e3df1d9
--- /dev/null
+++ b/src/test/run-make/wasm-symbols-not-imported/verify-no-imports.js
@@ -0,0 +1,10 @@
+const fs = require('fs');
+const process = require('process');
+const assert = require('assert');
+const buffer = fs.readFileSync(process.argv[2]);
+
+let m = new WebAssembly.Module(buffer);
+let list = WebAssembly.Module.imports(m);
+console.log('imports', list);
+if (list.length !== 0)
+ throw new Error("there are some imports");
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/Makefile b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/Makefile
new file mode 100644
index 000000000..6a04d3439
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/Makefile
@@ -0,0 +1,23 @@
+-include ../../run-make-fulldeps/tools.mk
+
+#only-x86_64-fortanix-unknown-sgx
+
+# For cargo setting
+export RUSTC := $(RUSTC_ORIGINAL)
+export LD_LIBRARY_PATH := $(HOST_RPATH_DIR)
+# We need to be outside of 'src' dir in order to run cargo
+export WORK_DIR := $(TMPDIR)
+export TEST_DIR := $(shell pwd)
+
+## clean up unused env variables which might cause harm.
+unexport RUSTC_LINKER
+unexport RUSTC_BOOTSTRAP
+unexport RUST_BUILD_STAGE
+unexport RUST_TEST_THREADS
+unexport RUST_TEST_TMPDIR
+unexport AR
+unexport CC
+unexport CXX
+
+all:
+ bash script.sh
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_asm.checks b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_asm.checks
new file mode 100644
index 000000000..e839c200b
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_asm.checks
@@ -0,0 +1,8 @@
+CHECK: cc_plus_one_asm
+CHECK-NEXT: movl
+CHECK-NEXT: lfence
+CHECK-NEXT: inc
+CHECK-NEXT: notq (%rsp)
+CHECK-NEXT: notq (%rsp)
+CHECK-NEXT: lfence
+CHECK-NEXT: retq
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_c.checks b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_c.checks
new file mode 100644
index 000000000..b93b33afb
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_c.checks
@@ -0,0 +1,6 @@
+CHECK: cc_plus_one_c
+CHECK: lfence
+CHECK: popq
+CHECK-NEXT: popq [[REGISTER:%[a-z]+]]
+CHECK-NEXT: lfence
+CHECK-NEXT: jmpq *[[REGISTER]]
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_c_asm.checks b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_c_asm.checks
new file mode 100644
index 000000000..d1fae3d49
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_c_asm.checks
@@ -0,0 +1,15 @@
+CHECK: cc_plus_one_c_asm
+CHECK: lfence
+CHECK: lfence
+CHECK: lfence
+CHECK: lfence
+CHECK: lfence
+CHECK-NEXT: incl
+CHECK-NEXT: jmp
+CHECK-NEXT: shlq $0, (%rsp)
+CHECK-NEXT: lfence
+CHECK-NEXT: retq
+CHECK: popq
+CHECK-NEXT: popq [[REGISTER:%[a-z]+]]
+CHECK-NEXT: lfence
+CHECK-NEXT: jmpq *[[REGISTER]]
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_cxx.checks b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_cxx.checks
new file mode 100644
index 000000000..f96f152c0
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_cxx.checks
@@ -0,0 +1,6 @@
+CHECK: cc_plus_one_cxx
+CHECK: lfence
+CHECK: popq
+CHECK-NEXT: popq [[REGISTER:%[a-z]+]]
+CHECK-NEXT: lfence
+CHECK-NEXT: jmpq *[[REGISTER]]
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_cxx_asm.checks b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_cxx_asm.checks
new file mode 100644
index 000000000..e704bf417
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_cxx_asm.checks
@@ -0,0 +1,16 @@
+CHECK: cc_plus_one_cxx_asm
+CHECK: lfence
+CHECK: lfence
+CHECK: lfence
+CHECK: movl
+CHECK: lfence
+CHECK: lfence
+CHECK-NEXT: incl
+CHECK-NEXT: jmp 0x{{[[:xdigit:]]+}} <cc_plus_one_cxx_asm+0x{{[[:xdigit:]]+}}>
+CHECK-NEXT: shlq $0, (%rsp)
+CHECK-NEXT: lfence
+CHECK-NEXT: retq
+CHECK: popq
+CHECK-NEXT: popq [[REGISTER:%[a-z]+]]
+CHECK-NEXT: lfence
+CHECK-NEXT: jmpq *[[REGISTER]]
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_asm.checks b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_asm.checks
new file mode 100644
index 000000000..78b18ccbf
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_asm.checks
@@ -0,0 +1,7 @@
+CHECK: cmake_plus_one_asm
+CHECK-NEXT: movl
+CHECK-NEXT: lfence
+CHECK-NEXT: incl
+CHECK-NEXT: shlq $0, (%rsp)
+CHECK-NEXT: lfence
+CHECK-NEXT: retq
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c.checks b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c.checks
new file mode 100644
index 000000000..f551356b2
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c.checks
@@ -0,0 +1,6 @@
+CHECK: cmake_plus_one_c
+CHECK: lfence
+CHECK: popq
+CHECK-NEXT: popq [[REGISTER:%[a-z]+]]
+CHECK-NEXT: lfence
+CHECK-NEXT: jmpq *[[REGISTER]]
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c_asm.checks b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c_asm.checks
new file mode 100644
index 000000000..87c806f13
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c_asm.checks
@@ -0,0 +1,16 @@
+CHECK: cmake_plus_one_c_asm
+CHECK: lfence
+CHECK: lfence
+CHECK: lfence
+CHECK: lfence
+CHECK: movl
+CHECK: lfence
+CHECK-NEXT: incl
+CHECK-NEXT: jmp 0x{{[[:xdigit:]]+}} <cmake_plus_one_c_asm+0x{{[[:xdigit:]]+}}>
+CHECK-NEXT: shlq $0, (%rsp)
+CHECK-NEXT: lfence
+CHECK-NEXT: retq
+CHECK: popq
+CHECK-NEXT: popq [[REGISTER:%[a-z]+]]
+CHECK-NEXT: lfence
+CHECK-NEXT: jmpq *[[REGISTER]]
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c_global_asm.checks b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c_global_asm.checks
new file mode 100644
index 000000000..4b66cc5bc
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c_global_asm.checks
@@ -0,0 +1,2 @@
+CHECK: cmake_plus_one_c_global_asm
+CHECK: lfence
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx.checks b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx.checks
new file mode 100644
index 000000000..0f403e020
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx.checks
@@ -0,0 +1,6 @@
+CHECK: cmake_plus_one_cxx
+CHECK: lfence
+CHECK: popq
+CHECK-NEXT: popq [[REGISTER:%[a-z]+]]
+CHECK-NEXT: lfence
+CHECK-NEXT: jmpq *[[REGISTER]]
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx_asm.checks b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx_asm.checks
new file mode 100644
index 000000000..9cac8711e
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx_asm.checks
@@ -0,0 +1,16 @@
+CHECK: cmake_plus_one_cxx_asm
+CHECK: lfence
+CHECK: lfence
+CHECK: lfence
+CHECK: lfence
+CHECK: movl
+CHECK: lfence
+CHECK-NEXT: incl
+CHECK-NEXT: jmp 0x{{[[:xdigit:]]+}} <cmake_plus_one_cxx_asm+0x{{[[:xdigit:]]+}}>
+CHECK-NEXT: shlq $0, (%rsp)
+CHECK-NEXT: lfence
+CHECK-NEXT: retq
+CHECK: popq
+CHECK-NEXT: popq [[REGISTER:%[a-z]+]]
+CHECK-NEXT: lfence
+CHECK-NEXT: jmpq *[[REGISTER]]
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx_global_asm.checks b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx_global_asm.checks
new file mode 100644
index 000000000..d4a3d4479
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx_global_asm.checks
@@ -0,0 +1,2 @@
+CHECK: cmake_plus_one_cxx_global_asm
+CHECK: lfence
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/Cargo.toml b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/Cargo.toml
new file mode 100644
index 000000000..3a97c37e9
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/Cargo.toml
@@ -0,0 +1,12 @@
+[package]
+name = "enclave"
+version = "0.1.0"
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+
+[build-dependencies]
+cc = "1.0"
+cmake = "0.1"
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/build.rs b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/build.rs
new file mode 100644
index 000000000..3a7aa1be8
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/build.rs
@@ -0,0 +1,30 @@
+fn main() {
+ cc::Build::new()
+ .file("foo.c")
+ .compile("foo_c");
+
+ cc::Build::new()
+ .file("foo_asm.s")
+ .compile("foo_asm");
+
+ cc::Build::new()
+ .cpp(true)
+ .cpp_set_stdlib(None)
+ .file("foo_cxx.cpp")
+ .compile("foo_cxx");
+
+ // When the cmake crate detects the clang compiler, it passes the
+ // "--target" argument to the linker which subsequently fails. The
+ // `CMAKE_C_COMPILER_FORCED` option makes sure that `cmake` does not
+ // tries to test the compiler. From version 3.6 the option
+ // `CMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY` can be used
+ // https://cmake.org/cmake/help/v3.5/module/CMakeForceCompiler.html
+ let dst = cmake::Config::new("libcmake_foo")
+ .build_target("cmake_foo")
+ .define("CMAKE_C_COMPILER_FORCED", "1")
+ .define("CMAKE_CXX_COMPILER_FORCED", "1")
+ .define("CMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY", "1")
+ .build();
+ println!("cargo:rustc-link-search=native={}/build/", dst.display());
+ println!("cargo:rustc-link-lib=static=cmake_foo");
+}
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/foo.c b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/foo.c
new file mode 100644
index 000000000..dd76d4f30
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/foo.c
@@ -0,0 +1,18 @@
+int cc_plus_one_c(int *arg) {
+ return *arg + 1;
+}
+
+int cc_plus_one_c_asm(int *arg) {
+ int value = 0;
+
+ asm volatile ( " movl (%1), %0\n"
+ " inc %0\n"
+ " jmp 1f\n"
+ " retq\n" // never executed, but a shortcut to determine how
+ // the assembler deals with `ret` instructions
+ "1:\n"
+ : "=r"(value)
+ : "r"(arg) );
+
+ return value;
+}
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/foo_asm.s b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/foo_asm.s
new file mode 100644
index 000000000..6d56214e8
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/foo_asm.s
@@ -0,0 +1,7 @@
+ .text
+ .global cc_plus_one_asm
+ .type cc_plus_one_asm, @function
+cc_plus_one_asm:
+ movl (%rdi), %eax
+ inc %eax
+ retq
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/foo_cxx.cpp b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/foo_cxx.cpp
new file mode 100644
index 000000000..ac6f64ac4
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/foo_cxx.cpp
@@ -0,0 +1,21 @@
+extern "C" int cc_plus_one_cxx(int *arg);
+extern "C" int cc_plus_one_cxx_asm(int *arg);
+
+int cc_plus_one_cxx(int *arg) {
+ return *arg + 1;
+}
+
+int cc_plus_one_cxx_asm(int *arg) {
+ int value = 0;
+
+ asm volatile ( " movl (%1), %0\n"
+ " inc %0\n"
+ " jmp 1f\n"
+ " retq\n" // never executed, but a shortcut to determine how
+ // the assembler deals with `ret` instructions
+ "1:\n"
+ : "=r"(value)
+ : "r"(arg) );
+
+ return value;
+}
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/CMakeLists.txt b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/CMakeLists.txt
new file mode 100644
index 000000000..27cdf2ecf
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/CMakeLists.txt
@@ -0,0 +1,33 @@
+enable_language(C CXX ASM)
+
+set(C_SOURCES
+ src/foo.c
+ )
+
+set_source_files_properties(${C_SOURCES}
+ PROPERTIES
+ LANGUAGE C)
+
+set(CXX_SOURCES
+ src/foo_cxx.cpp
+ )
+
+set_source_files_properties(${CXX_SOURCES}
+ PROPERTIES
+ LANGUAGE CXX)
+
+set(ASM_SOURCES
+ src/foo_asm.s
+ )
+
+set_source_files_properties(${ASM_SOURCES}
+ PROPERTIES
+ LANGUAGE ASM)
+
+set(SOURCES
+ ${C_SOURCES}
+ ${CXX_SOURCES}
+ ${ASM_SOURCES})
+
+add_library(cmake_foo STATIC
+ ${SOURCES})
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo.c b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo.c
new file mode 100644
index 000000000..c3b731a2d
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo.c
@@ -0,0 +1,26 @@
+int cmake_plus_one_c(int *arg) {
+ return *arg + 1;
+}
+
+int cmake_plus_one_c_asm(int *arg) {
+ int value = 0;
+
+ asm volatile ( " movl (%1), %0\n"
+ " inc %0\n"
+ " jmp 1f\n"
+ " retq\n" // never executed, but a shortcut to determine how
+ // the assembler deals with `ret` instructions
+ "1:\n"
+ : "=r"(value)
+ : "r"(arg) );
+
+ return value;
+}
+
+asm(".text\n"
+" .global cmake_plus_one_c_global_asm\n"
+" .type cmake_plus_one_c_global_asm, @function\n"
+"cmake_plus_one_c_global_asm:\n"
+" movl (%rdi), %eax\n"
+" inc %eax\n"
+" retq\n" );
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo_asm.s b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo_asm.s
new file mode 100644
index 000000000..64b6b430e
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo_asm.s
@@ -0,0 +1,7 @@
+ .text
+ .global cmake_plus_one_asm
+ .type cmake_plus_one_asm, @function
+cmake_plus_one_asm:
+ movl (%rdi), %eax
+ inc %eax
+ retq
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo_cxx.cpp b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo_cxx.cpp
new file mode 100644
index 000000000..824e2afeb
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo_cxx.cpp
@@ -0,0 +1,29 @@
+extern "C" int cmake_plus_one_cxx(int *arg);
+extern "C" int cmake_plus_one_cxx_asm(int *arg);
+
+int cmake_plus_one_cxx(int *arg) {
+ return *arg + 1;
+}
+
+int cmake_plus_one_cxx_asm(int *arg) {
+ int value = 0;
+
+ asm volatile ( " movl (%1), %0\n"
+ " inc %0\n"
+ " jmp 1f\n"
+ " retq\n" // never executed, but a shortcut to determine how
+ // the assembler deals with `ret` instructions
+ "1:\n"
+ : "=r"(value)
+ : "r"(arg) );
+
+ return value;
+}
+
+asm(".text\n"
+" .global cmake_plus_one_cxx_global_asm\n"
+" .type cmake_plus_one_cxx_global_asm, @function\n"
+"cmake_plus_one_cxx_global_asm:\n"
+" movl (%rdi), %eax\n"
+" inc %eax\n"
+" retq\n" );
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/src/main.rs b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/src/main.rs
new file mode 100644
index 000000000..cde38aacf
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/src/main.rs
@@ -0,0 +1,49 @@
+std::arch::global_asm!(
+ r#"
+ .text
+ .global rust_plus_one_global_asm
+ .type rust_plus_one_global_asm, @function
+rust_plus_one_global_asm:
+ movl (%rdi), %eax
+ inc %eax
+ retq
+"#,
+ options(att_syntax)
+);
+
+extern "C" {
+ fn cc_plus_one_c(arg: &u32) -> u32;
+ fn cc_plus_one_c_asm(arg: &u32) -> u32;
+ fn cc_plus_one_cxx(arg: &u32) -> u32;
+ fn cc_plus_one_cxx_asm(arg: &u32) -> u32;
+ fn cc_plus_one_asm(arg: &u32) -> u32;
+ fn cmake_plus_one_c(arg: &u32) -> u32;
+ fn cmake_plus_one_c_asm(arg: &u32) -> u32;
+ fn cmake_plus_one_cxx(arg: &u32) -> u32;
+ fn cmake_plus_one_cxx_asm(arg: &u32) -> u32;
+ fn cmake_plus_one_c_global_asm(arg: &u32) -> u32;
+ fn cmake_plus_one_cxx_global_asm(arg: &u32) -> u32;
+ fn cmake_plus_one_asm(arg: &u32) -> u32;
+ fn rust_plus_one_global_asm(arg: &u32) -> u32;
+}
+
+fn main() {
+ let value: u32 = 41;
+ let question = "Answer to the Ultimate Question of Life, the Universe, and Everything:";
+
+ unsafe {
+ println!("{}: {}!", question, rust_plus_one_global_asm(&value));
+ println!("{}: {}!", question, cc_plus_one_c(&value));
+ println!("{}: {}!", question, cc_plus_one_c_asm(&value));
+ println!("{}: {}!", question, cc_plus_one_cxx(&value));
+ println!("{}: {}!", question, cc_plus_one_cxx_asm(&value));
+ println!("{}: {}!", question, cc_plus_one_asm(&value));
+ println!("{}: {}!", question, cmake_plus_one_c(&value));
+ println!("{}: {}!", question, cmake_plus_one_c_asm(&value));
+ println!("{}: {}!", question, cmake_plus_one_cxx(&value));
+ println!("{}: {}!", question, cmake_plus_one_cxx_asm(&value));
+ println!("{}: {}!", question, cmake_plus_one_c_global_asm(&value));
+ println!("{}: {}!", question, cmake_plus_one_cxx_global_asm(&value));
+ println!("{}: {}!", question, cmake_plus_one_asm(&value));
+ }
+}
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/jumpto.checks b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/jumpto.checks
new file mode 100644
index 000000000..15211e3ad
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/jumpto.checks
@@ -0,0 +1,8 @@
+CHECK: libunwind::Registers_x86_64::jumpto
+CHECK: lfence
+CHECK: lfence
+CHECK: lfence
+CHECK: lfence
+CHECK: shlq $0, (%rsp)
+CHECK-NEXT: lfence
+CHECK-NEXT: retq
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/print.checks b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/print.checks
new file mode 100644
index 000000000..0fe88141b
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/print.checks
@@ -0,0 +1,7 @@
+CHECK: print
+CHECK: lfence
+CHECK: lfence
+CHECK: lfence
+CHECK: popq
+CHECK: callq 0x{{[[:xdigit:]]*}} <_Unwind_Resume>
+CHECK-NEXT: ud2
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/rust_plus_one_global_asm.checks b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/rust_plus_one_global_asm.checks
new file mode 100644
index 000000000..fe6777537
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/rust_plus_one_global_asm.checks
@@ -0,0 +1,2 @@
+CHECK: rust_plus_one_global_asm
+CHECK: lfence
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh
new file mode 100644
index 000000000..54645e9e2
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh
@@ -0,0 +1,58 @@
+#!/bin/sh
+set -exuo pipefail
+
+function build {
+ CRATE=enclave
+
+ mkdir -p $WORK_DIR
+ pushd $WORK_DIR
+ rm -rf $CRATE
+ cp -a $TEST_DIR/enclave .
+ pushd $CRATE
+ echo ${WORK_DIR}
+ # HACK(eddyb) sets `RUSTC_BOOTSTRAP=1` so Cargo can accept nightly features.
+ # These come from the top-level Rust workspace, that this crate is not a
+ # member of, but Cargo tries to load the workspace `Cargo.toml` anyway.
+ env RUSTC_BOOTSTRAP=1
+ cargo -v run --target $TARGET
+ popd
+ popd
+}
+
+function check {
+ local func=$1
+ local checks="${TEST_DIR}/$2"
+ local asm=$(mktemp)
+ local objdump="${BUILD_DIR}/x86_64-unknown-linux-gnu/llvm/build/bin/llvm-objdump"
+ local filecheck="${BUILD_DIR}/x86_64-unknown-linux-gnu/llvm/build/bin/FileCheck"
+
+ ${objdump} --disassemble-symbols=${func} --demangle \
+ ${WORK_DIR}/enclave/target/x86_64-fortanix-unknown-sgx/debug/enclave > ${asm}
+ ${filecheck} --input-file ${asm} ${checks}
+}
+
+build
+
+check unw_getcontext unw_getcontext.checks
+check "libunwind::Registers_x86_64::jumpto()" jumpto.checks
+check "std::io::stdio::_print::h87f0c238421c45bc" print.checks
+check rust_plus_one_global_asm rust_plus_one_global_asm.checks \
+ || echo "warning: module level assembly currently not hardened"
+
+check cc_plus_one_c cc_plus_one_c.checks
+check cc_plus_one_c_asm cc_plus_one_c_asm.checks
+check cc_plus_one_cxx cc_plus_one_cxx.checks
+check cc_plus_one_cxx_asm cc_plus_one_cxx_asm.checks
+check cc_plus_one_asm cc_plus_one_asm.checks \
+ || echo "warning: the cc crate forwards assembly files to the CC compiler." \
+ "Clang uses its own intergrated assembler, which does not include the LVI passes."
+
+check cmake_plus_one_c cmake_plus_one_c.checks
+check cmake_plus_one_c_asm cmake_plus_one_c_asm.checks
+check cmake_plus_one_c_global_asm cmake_plus_one_c_global_asm.checks \
+ || echo "warning: module level assembly currently not hardened"
+check cmake_plus_one_cxx cmake_plus_one_cxx.checks
+check cmake_plus_one_cxx_asm cmake_plus_one_cxx_asm.checks
+check cmake_plus_one_cxx_global_asm cmake_plus_one_cxx_global_asm.checks \
+ || echo "warning: module level assembly currently not hardened"
+check cmake_plus_one_asm cmake_plus_one_asm.checks
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/unw_getcontext.checks b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/unw_getcontext.checks
new file mode 100644
index 000000000..4b7615b11
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/unw_getcontext.checks
@@ -0,0 +1,6 @@
+CHECK: unw_getcontext
+CHECK: lfence
+CHECK: lfence
+CHECK: shlq $0, (%rsp)
+CHECK-NEXT: lfence
+CHECK-NEXT: retq