about summary refs log tree commit diff
path: root/tests/ui/asm/named-asm-labels.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ui/asm/named-asm-labels.rs')
-rw-r--r--tests/ui/asm/named-asm-labels.rs196
1 files changed, 196 insertions, 0 deletions
diff --git a/tests/ui/asm/named-asm-labels.rs b/tests/ui/asm/named-asm-labels.rs
new file mode 100644
index 00000000000..160dbf617c4
--- /dev/null
+++ b/tests/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");