summaryrefslogtreecommitdiffstats
path: root/src/test/ui/asm/named-asm-labels.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/ui/asm/named-asm-labels.rs')
-rw-r--r--src/test/ui/asm/named-asm-labels.rs196
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");