diff options
Diffstat (limited to 'src/test/ui/asm/named-asm-labels.rs')
-rw-r--r-- | src/test/ui/asm/named-asm-labels.rs | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/src/test/ui/asm/named-asm-labels.rs b/src/test/ui/asm/named-asm-labels.rs new file mode 100644 index 000000000..160dbf617 --- /dev/null +++ b/src/test/ui/asm/named-asm-labels.rs @@ -0,0 +1,196 @@ +// needs-asm-support +// ignore-nvptx64 +// ignore-spirv +// ignore-wasm32 + +// Tests that the use of named labels in the `asm!` macro are linted against +// except for in `#[naked]` fns. +// Using a named label is incorrect as per the RFC because for most cases +// the compiler cannot ensure that inline asm is emitted exactly once per +// codegen unit (except for naked fns) and so the label could be duplicated +// which causes less readable LLVM errors and in the worst cases causes ICEs +// or segfaults based on system dependent behavior and codegen flags. + +#![feature(naked_functions, asm_const)] + +use std::arch::{asm, global_asm}; + +#[no_mangle] +pub static FOO: usize = 42; + +fn main() { + unsafe { + // Basic usage + asm!("bar: nop"); //~ ERROR avoid using named labels + + // No following asm + asm!("abcd:"); //~ ERROR avoid using named labels + + // Multiple labels on one line + asm!("foo: bar1: nop"); + //~^ ERROR avoid using named labels + + // Multiple lines + asm!("foo1: nop", "nop"); //~ ERROR avoid using named labels + asm!("foo2: foo3: nop", "nop"); + //~^ ERROR avoid using named labels + asm!("nop", "foo4: nop"); //~ ERROR avoid using named labels + asm!("foo5: nop", "foo6: nop"); + //~^ ERROR avoid using named labels + //~| ERROR avoid using named labels + + // Statement separator + asm!("foo7: nop; foo8: nop"); + //~^ ERROR avoid using named labels + asm!("foo9: nop; nop"); //~ ERROR avoid using named labels + asm!("nop; foo10: nop"); //~ ERROR avoid using named labels + + // Escaped newline + asm!("bar2: nop\n bar3: nop"); + //~^ ERROR avoid using named labels + asm!("bar4: nop\n nop"); //~ ERROR avoid using named labels + asm!("nop\n bar5: nop"); //~ ERROR avoid using named labels + asm!("nop\n bar6: bar7: nop"); + //~^ ERROR avoid using named labels + + // Raw strings + asm!( + r" + blah2: nop + blah3: nop + " + ); + //~^^^^ ERROR avoid using named labels + + asm!( + r###" + nop + nop ; blah4: nop + "### + ); + //~^^^ ERROR avoid using named labels + + // Non-labels + // should not trigger lint, but may be invalid asm + asm!("ab cd: nop"); + + // `blah:` does not trigger because labels need to be at the start + // of the statement, and there was already a non-label + asm!("1bar: blah: nop"); + + // Only `blah1:` should trigger + asm!("blah1: 2bar: nop"); //~ ERROR avoid using named labels + + // Duplicate labels + asm!("def: def: nop"); //~ ERROR avoid using named labels + asm!("def: nop\ndef: nop"); //~ ERROR avoid using named labels + asm!("def: nop; def: nop"); //~ ERROR avoid using named labels + + // Trying to break parsing + asm!(":"); + asm!("\n:\n"); + asm!("::::"); + + // 0x3A is a ':' + asm!("fooo\u{003A} nop"); //~ ERROR avoid using named labels + asm!("foooo\x3A nop"); //~ ERROR avoid using named labels + + // 0x0A is a newline + asm!("fooooo:\u{000A} nop"); //~ ERROR avoid using named labels + asm!("foooooo:\x0A nop"); //~ ERROR avoid using named labels + + // Intentionally breaking span finding + // equivalent to "ABC: nop" + asm!("\x41\x42\x43\x3A\x20\x6E\x6F\x70"); //~ ERROR avoid using named labels + + // Non-label colons - should pass + asm!("mov rax, qword ptr fs:[0]"); + + // Comments + asm!( + r" + ab: nop // ab: does foo + // cd: nop + " + ); + //~^^^^ ERROR avoid using named labels + + // Tests usage of colons in non-label positions + asm!(":lo12:FOO"); // this is apparently valid aarch64 + // is there an example that is valid x86 for this test? + asm!(":bbb nop"); + + // Test include_str in asm + asm!(include_str!("named-asm-labels.s")); //~ ERROR avoid using named labels + + // Test allowing or warning on the lint instead + #[allow(named_asm_labels)] + { + asm!("allowed: nop"); // Should not emit anything + } + + #[warn(named_asm_labels)] + { + asm!("warned: nop"); //~ WARNING avoid using named labels + } + } +} + +// Trigger on naked fns too, even though they can't be inlined, reusing a +// label or LTO can cause labels to break +#[naked] +pub extern "C" fn foo() -> i32 { + unsafe { asm!(".Lfoo: mov rax, {}; ret;", "nop", const 1, options(noreturn)) } //~ ERROR avoid using named labels +} + +// Make sure that non-naked attributes *do* still let the lint happen +#[no_mangle] +pub extern "C" fn bar() { + unsafe { asm!(".Lbar: mov rax, {}; ret;", "nop", const 1, options(noreturn)) } + //~^ ERROR avoid using named labels +} + +#[naked] +pub extern "C" fn aaa() { + fn _local() {} + + unsafe { asm!(".Laaa: nop; ret;", options(noreturn)) } //~ ERROR avoid using named labels +} + +pub fn normal() { + fn _local1() {} + + #[naked] + pub extern "C" fn bbb() { + fn _very_local() {} + + unsafe { asm!(".Lbbb: nop; ret;", options(noreturn)) } //~ ERROR avoid using named labels + } + + fn _local2() {} +} + +// Make sure that the lint happens within closures +fn closures() { + || unsafe { + asm!("closure1: nop"); //~ ERROR avoid using named labels + }; + + move || unsafe { + asm!("closure2: nop"); //~ ERROR avoid using named labels + }; + + || { + #[naked] + unsafe extern "C" fn _nested() { + asm!("ret;", options(noreturn)); + } + + unsafe { + asm!("closure3: nop"); //~ ERROR avoid using named labels + } + }; +} + +// Don't trigger on global asm +global_asm!("aaaaaaaa: nop"); |