diff options
| author | Stuart Cook <Zalathar@users.noreply.github.com> | 2025-09-17 14:56:44 +1000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-09-17 14:56:44 +1000 |
| commit | 6ad98750e0d2261aa123806c69a133b2fbd18d88 (patch) | |
| tree | 53152bd7a544941557844f85b18cc1a1ba9ee527 /tests | |
| parent | f21a9c94cf39cdb26a15ea0967501629f3156958 (diff) | |
| parent | 1ebf69d1b1a94e99c01680514571c41d0b864c15 (diff) | |
| download | rust-6ad98750e0d2261aa123806c69a133b2fbd18d88.tar.gz rust-6ad98750e0d2261aa123806c69a133b2fbd18d88.zip | |
Rollup merge of #145660 - jbatez:darwin_objc, r=jdonszelmann,madsmtm,tmandry
initial implementation of the darwin_objc unstable feature Tracking issue: https://github.com/rust-lang/rust/issues/145496 This feature makes it possible to reference Objective-C classes and selectors using the same ABI used by native Objective-C on Apple/Darwin platforms. Without it, Rust code interacting with Objective-C must resort to loading classes and selectors using costly string-based lookups at runtime. With it, these references can be loaded efficiently at dynamic load time. r? ```@tmandry``` try-job: `*apple*` try-job: `x86_64-gnu-nopt`
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/codegen-llvm/auxiliary/darwin_objc_aux.rs | 27 | ||||
| -rw-r--r-- | tests/codegen-llvm/darwin-no-objc.rs | 52 | ||||
| -rw-r--r-- | tests/codegen-llvm/darwin-objc-abi-v1.rs | 100 | ||||
| -rw-r--r-- | tests/codegen-llvm/darwin-objc-abi-v2.rs | 185 | ||||
| -rw-r--r-- | tests/codegen-llvm/darwin-objc-cross-crate.rs | 58 | ||||
| -rw-r--r-- | tests/ui/README.md | 6 | ||||
| -rw-r--r-- | tests/ui/darwin-objc/darwin-objc-bad-arg.rs | 36 | ||||
| -rw-r--r-- | tests/ui/darwin-objc/darwin-objc-bad-arg.stderr | 50 | ||||
| -rw-r--r-- | tests/ui/darwin-objc/darwin-objc-bad-const.rs | 17 | ||||
| -rw-r--r-- | tests/ui/darwin-objc/darwin-objc-bad-const.stderr | 19 | ||||
| -rw-r--r-- | tests/ui/darwin-objc/darwin-objc-bad-ref.rs | 31 | ||||
| -rw-r--r-- | tests/ui/darwin-objc/darwin-objc-bad-ref.stderr | 39 | ||||
| -rw-r--r-- | tests/ui/darwin-objc/darwin-objc-class-selector.rs | 31 | ||||
| -rw-r--r-- | tests/ui/darwin-objc/darwin-objc-class.rs | 39 | ||||
| -rw-r--r-- | tests/ui/darwin-objc/darwin-objc-selector.rs | 36 |
15 files changed, 726 insertions, 0 deletions
diff --git a/tests/codegen-llvm/auxiliary/darwin_objc_aux.rs b/tests/codegen-llvm/auxiliary/darwin_objc_aux.rs new file mode 100644 index 00000000000..3c35d003c8a --- /dev/null +++ b/tests/codegen-llvm/auxiliary/darwin_objc_aux.rs @@ -0,0 +1,27 @@ +#![crate_type = "lib"] +#![feature(darwin_objc)] + +use std::os::darwin::objc; + +#[link(name = "Foundation", kind = "framework")] +unsafe extern "C" {} + +#[inline(always)] +pub fn inline_get_object_class() -> objc::Class { + objc::class!("NSObject") +} + +#[inline(always)] +pub fn inline_get_alloc_selector() -> objc::SEL { + objc::selector!("alloc") +} + +#[inline(never)] +pub fn never_inline_get_string_class() -> objc::Class { + objc::class!("NSString") +} + +#[inline(never)] +pub fn never_inline_get_init_selector() -> objc::SEL { + objc::selector!("init") +} diff --git a/tests/codegen-llvm/darwin-no-objc.rs b/tests/codegen-llvm/darwin-no-objc.rs new file mode 100644 index 00000000000..fda3671fb6d --- /dev/null +++ b/tests/codegen-llvm/darwin-no-objc.rs @@ -0,0 +1,52 @@ +// Test that we don't generate Objective-C definitions or image info unnecessarily. + +//@ add-core-stubs +//@ revisions: i686_apple_darwin +//@ [i686_apple_darwin] compile-flags: --target i686-apple-darwin +//@ [i686_apple_darwin] needs-llvm-components: x86 +//@ revisions: x86_64_macos +//@ [x86_64_macos] compile-flags: --target x86_64-apple-darwin +//@ [x86_64_macos] needs-llvm-components: x86 +//@ revisions: aarch64_macos +//@ [aarch64_macos] compile-flags: --target aarch64-apple-darwin +//@ [aarch64_macos] needs-llvm-components: aarch64 +//@ revisions: i386_ios +//@ [i386_ios] compile-flags: --target i386-apple-ios +//@ [i386_ios] needs-llvm-components: x86 +//@ revisions: x86_64_ios +//@ [x86_64_ios] compile-flags: --target x86_64-apple-ios +//@ [x86_64_ios] needs-llvm-components: x86 +//@ revisions: armv7s_ios +//@ [armv7s_ios] compile-flags: --target armv7s-apple-ios +//@ [armv7s_ios] needs-llvm-components: arm +//@ revisions: aarch64_ios +//@ [aarch64_ios] compile-flags: --target aarch64-apple-ios +//@ [aarch64_ios] needs-llvm-components: aarch64 +//@ revisions: aarch64_ios_sim +//@ [aarch64_ios_sim] compile-flags: --target aarch64-apple-ios-sim +//@ [aarch64_ios_sim] needs-llvm-components: aarch64 + +#![crate_type = "lib"] +#![feature(no_core, lang_items)] +#![no_core] + +extern crate minicore; +use minicore::*; + +#[no_mangle] +pub fn foo() {} + +// CHECK-NOT: %struct._class_t +// CHECK-NOT: %struct._objc_module +// CHECK-NOT: @OBJC_CLASS_NAME_ +// CHECK-NOT: @"OBJC_CLASS_$_{{[0-9A-Z_a-z]+}}" +// CHECK-NOT: @"OBJC_CLASSLIST_REFERENCES_$_.{{[0-9]+}}" +// CHECK-NOT: @OBJC_METH_VAR_NAME_ +// CHECK-NOT: @OBJC_SELECTOR_REFERENCES_ +// CHECK-NOT: @OBJC_MODULES + +// CHECK-NOT: !"Objective-C Version" +// CHECK-NOT: !"Objective-C Image Info Version" +// CHECK-NOT: !"Objective-C Image Info Section" +// CHECK-NOT: !"Objective-C Is Simulated" +// CHECK-NOT: !"Objective-C Class Properties" diff --git a/tests/codegen-llvm/darwin-objc-abi-v1.rs b/tests/codegen-llvm/darwin-objc-abi-v1.rs new file mode 100644 index 00000000000..0fc1de9332a --- /dev/null +++ b/tests/codegen-llvm/darwin-objc-abi-v1.rs @@ -0,0 +1,100 @@ +// ignore-tidy-linelength +//@ add-core-stubs +//@ revisions: i686_apple_darwin +//@ [i686_apple_darwin] compile-flags: --target i686-apple-darwin +//@ [i686_apple_darwin] needs-llvm-components: x86 + +#![crate_type = "lib"] +#![feature(no_core, lang_items, rustc_attrs)] +#![no_core] + +extern crate minicore; +use minicore::*; + +#[no_mangle] +pub fn get_class() -> *mut () { + unsafe extern "C" { + #[rustc_objc_class = "MyClass"] + safe static VAL: *mut (); + } + VAL +} + +#[no_mangle] +pub fn get_class_again() -> *mut () { + // Codegen should de-duplicate this class with the one from get_class above. + unsafe extern "C" { + #[rustc_objc_class = "MyClass"] + safe static VAL: *mut (); + } + VAL +} + +#[no_mangle] +pub fn get_selector() -> *mut () { + unsafe extern "C" { + #[rustc_objc_selector = "myMethod"] + safe static VAL: *mut (); + } + VAL +} + +#[no_mangle] +pub fn get_selector_again() -> *mut () { + // Codegen should de-duplicate this selector with the one from get_selector above. + unsafe extern "C" { + #[rustc_objc_selector = "myMethod"] + safe static VAL: *mut (); + } + VAL +} + +#[no_mangle] +pub fn get_other_class() -> *mut () { + unsafe extern "C" { + #[rustc_objc_class = "OtherClass"] + safe static VAL: *mut (); + } + VAL +} + +#[no_mangle] +pub fn get_other_selector() -> *mut () { + unsafe extern "C" { + #[rustc_objc_selector = "otherMethod"] + safe static VAL: *mut (); + } + VAL +} + +// CHECK: %struct._objc_module = type { i32, i32, ptr, ptr } + +// CHECK: @OBJC_CLASS_NAME_.{{[0-9]+}} = private unnamed_addr constant [8 x i8] c"MyClass\00", section "__TEXT,__cstring,cstring_literals", align 1 +// CHECK: @OBJC_CLASS_REFERENCES_.{{[0-9]+}} = private global ptr @OBJC_CLASS_NAME_.{{[0-9]+}}, section "__OBJC,__cls_refs,literal_pointers,no_dead_strip", align 4 +// CHECK-NOT: @OBJC_CLASS_NAME_ +// CHECK-NOT: @OBJC_CLASS_REFERENCES_ + +// CHECK: @OBJC_METH_VAR_NAME_.{{[0-9]+}} = private unnamed_addr constant [9 x i8] c"myMethod\00", section "__TEXT,__cstring,cstring_literals", align 1 +// CHECK: @OBJC_SELECTOR_REFERENCES_.{{[0-9]+}} = private externally_initialized global ptr @OBJC_METH_VAR_NAME_.{{[0-9]+}}, section "__OBJC,__message_refs,literal_pointers,no_dead_strip", align 4 +// CHECK-NOT: @OBJC_METH_VAR_NAME_ +// CHECK-NOT: @OBJC_SELECTOR_REFERENCES_ + +// CHECK: @OBJC_CLASS_NAME_.{{[0-9]+}} = private unnamed_addr constant [11 x i8] c"OtherClass\00", section "__TEXT,__cstring,cstring_literals", align 1 +// CHECK: @OBJC_CLASS_REFERENCES_.{{[0-9]+}} = private global ptr @OBJC_CLASS_NAME_.{{[0-9]+}}, section "__OBJC,__cls_refs,literal_pointers,no_dead_strip", align 4 + +// CHECK: @OBJC_METH_VAR_NAME_.{{[0-9]+}} = private unnamed_addr constant [12 x i8] c"otherMethod\00", section "__TEXT,__cstring,cstring_literals", align 1 +// CHECK: @OBJC_SELECTOR_REFERENCES_.{{[0-9]+}} = private externally_initialized global ptr @OBJC_METH_VAR_NAME_.{{[0-9]+}}, section "__OBJC,__message_refs,literal_pointers,no_dead_strip", align 4 + +// CHECK: @OBJC_CLASS_NAME_.{{[0-9]+}} = private unnamed_addr constant [1 x i8] zeroinitializer, section "__TEXT,__cstring,cstring_literals", align 1 +// CHECK: @OBJC_MODULES = private global %struct._objc_module { i32 7, i32 16, ptr @OBJC_CLASS_NAME_.{{[0-9]+}}, ptr null }, section "__OBJC,__module_info,regular,no_dead_strip", align 4 + +// CHECK: load ptr, ptr @OBJC_CLASS_REFERENCES_.{{[0-9]+}}, align 4 +// CHECK: load ptr, ptr @OBJC_SELECTOR_REFERENCES_.{{[0-9]+}}, align 4 +// CHECK: load ptr, ptr @OBJC_CLASS_REFERENCES_.{{[0-9]+}}, align 4 +// CHECK: load ptr, ptr @OBJC_SELECTOR_REFERENCES_.{{[0-9]+}}, align 4 + +// CHECK: !{{[0-9]+}} = !{i32 1, !"Objective-C Version", i32 1} +// CHECK: !{{[0-9]+}} = !{i32 1, !"Objective-C Image Info Version", i32 0} +// CHECK: !{{[0-9]+}} = !{i32 1, !"Objective-C Image Info Section", !"__OBJC,__image_info,regular"} +// CHECK-NOT: !{{[0-9]+}} = !{i32 1, !"Objective-C Is Simulated", i32 32} +// CHECK: !{{[0-9]+}} = !{i32 1, !"Objective-C Class Properties", i32 64} diff --git a/tests/codegen-llvm/darwin-objc-abi-v2.rs b/tests/codegen-llvm/darwin-objc-abi-v2.rs new file mode 100644 index 00000000000..f142371d582 --- /dev/null +++ b/tests/codegen-llvm/darwin-objc-abi-v2.rs @@ -0,0 +1,185 @@ +// ignore-tidy-linelength +//@ add-core-stubs +//@ revisions: x86_64_macos +//@ [x86_64_macos] compile-flags: --target x86_64-apple-darwin +//@ [x86_64_macos] needs-llvm-components: x86 +//@ revisions: aarch64_macos +//@ [aarch64_macos] compile-flags: --target aarch64-apple-darwin +//@ [aarch64_macos] needs-llvm-components: aarch64 +//@ revisions: i386_ios +//@ [i386_ios] compile-flags: --target i386-apple-ios +//@ [i386_ios] needs-llvm-components: x86 +//@ revisions: x86_64_ios +//@ [x86_64_ios] compile-flags: --target x86_64-apple-ios +//@ [x86_64_ios] needs-llvm-components: x86 +//@ revisions: armv7s_ios +//@ [armv7s_ios] compile-flags: --target armv7s-apple-ios +//@ [armv7s_ios] needs-llvm-components: arm +//@ revisions: aarch64_ios +//@ [aarch64_ios] compile-flags: --target aarch64-apple-ios +//@ [aarch64_ios] needs-llvm-components: aarch64 +//@ revisions: aarch64_ios_sim +//@ [aarch64_ios_sim] compile-flags: --target aarch64-apple-ios-sim +//@ [aarch64_ios_sim] needs-llvm-components: aarch64 + +#![crate_type = "lib"] +#![feature(no_core, lang_items, rustc_attrs)] +#![no_core] + +extern crate minicore; +use minicore::*; + +#[no_mangle] +pub fn get_class() -> *mut () { + unsafe extern "C" { + #[rustc_objc_class = "MyClass"] + safe static VAL: *mut (); + } + VAL +} + +#[no_mangle] +pub fn get_class_again() -> *mut () { + // Codegen should de-duplicate this class with the one from get_class above. + unsafe extern "C" { + #[rustc_objc_class = "MyClass"] + safe static VAL: *mut (); + } + VAL +} + +#[no_mangle] +pub fn get_selector() -> *mut () { + unsafe extern "C" { + #[rustc_objc_selector = "myMethod"] + safe static VAL: *mut (); + } + VAL +} + +#[no_mangle] +pub fn get_selector_again() -> *mut () { + // Codegen should de-duplicate this selector with the one from get_selector above. + unsafe extern "C" { + #[rustc_objc_selector = "myMethod"] + safe static VAL: *mut (); + } + VAL +} + +#[no_mangle] +pub fn get_other_class() -> *mut () { + unsafe extern "C" { + #[rustc_objc_class = "OtherClass"] + safe static VAL: *mut (); + } + VAL +} + +#[no_mangle] +pub fn get_other_selector() -> *mut () { + unsafe extern "C" { + #[rustc_objc_selector = "otherMethod"] + safe static VAL: *mut (); + } + VAL +} + +// CHECK: %struct._class_t = type { ptr, ptr, ptr, ptr, ptr } + +// CHECK: @"OBJC_CLASS_$_MyClass" = external global %struct._class_t +// CHECK: @"OBJC_CLASSLIST_REFERENCES_$_.{{[0-9]+}}" = internal global ptr @"OBJC_CLASS_$_MyClass", section "__DATA,__objc_classrefs,regular,no_dead_strip", +// x86_64_macos-SAME: align 8 +// aarch64_macos-SAME: align 8 +// i386_ios-SAME: align 4 +// x86_64_ios-SAME: align 8 +// armv7s_ios-SAME: align 4 +// aarch64_ios-SAME: align 8 +// aarch64_ios_sim-SAME: align 8 +// CHECK-NOT: @"OBJC_CLASS_$_MyClass" +// CHECK-NOT: @"OBJC_CLASSLIST_REFERENCES_$_ + +// CHECK: @OBJC_METH_VAR_NAME_.{{[0-9]+}} = private unnamed_addr constant [9 x i8] c"myMethod\00", section "__TEXT,__objc_methname,cstring_literals", align 1 +// CHECK: @OBJC_SELECTOR_REFERENCES_.{{[0-9]+}} = internal externally_initialized global ptr @OBJC_METH_VAR_NAME_.{{[0-9]+}}, section "__DATA,__objc_selrefs,literal_pointers,no_dead_strip", +// x86_64_macos-SAME: align 8 +// aarch64_macos-SAME: align 8 +// i386_ios-SAME: align 4 +// x86_64_ios-SAME: align 8 +// armv7s_ios-SAME: align 4 +// aarch64_ios-SAME: align 8 +// aarch64_ios_sim-SAME: align 8 +// CHECK-NOT: @OBJC_METH_VAR_NAME_ +// CHECK-NOT: @OBJC_SELECTOR_REFERENCES_ + +// CHECK: @"OBJC_CLASS_$_OtherClass" = external global %struct._class_t +// CHECK: @"OBJC_CLASSLIST_REFERENCES_$_.{{[0-9]+}}" = internal global ptr @"OBJC_CLASS_$_OtherClass", section "__DATA,__objc_classrefs,regular,no_dead_strip", +// x86_64_macos-SAME: align 8 +// aarch64_macos-SAME: align 8 +// i386_ios-SAME: align 4 +// x86_64_ios-SAME: align 8 +// armv7s_ios-SAME: align 4 +// aarch64_ios-SAME: align 8 +// aarch64_ios_sim-SAME: align 8 + +// CHECK: @OBJC_METH_VAR_NAME_.{{[0-9]+}} = private unnamed_addr constant [12 x i8] c"otherMethod\00", section "__TEXT,__objc_methname,cstring_literals", align 1 +// CHECK: @OBJC_SELECTOR_REFERENCES_.{{[0-9]+}} = internal externally_initialized global ptr @OBJC_METH_VAR_NAME_.{{[0-9]+}}, section "__DATA,__objc_selrefs,literal_pointers,no_dead_strip", +// x86_64_macos-SAME: align 8 +// aarch64_macos-SAME: align 8 +// i386_ios-SAME: align 4 +// x86_64_ios-SAME: align 8 +// armv7s_ios-SAME: align 4 +// aarch64_ios-SAME: align 8 +// aarch64_ios_sim-SAME: align 8 + +// CHECK-NOT: @OBJC_CLASS_NAME_ +// CHECK-NOT: @OBJC_MODULES + +// CHECK: load ptr, ptr @"OBJC_CLASSLIST_REFERENCES_$_.{{[0-9]+}}", +// x86_64_macos-SAME: align 8 +// aarch64_macos-SAME: align 8 +// i386_ios-SAME: align 4 +// x86_64_ios-SAME: align 8 +// armv7s_ios-SAME: align 4 +// aarch64_ios-SAME: align 8 +// aarch64_ios_sim-SAME: align 8 + +// CHECK: load ptr, ptr @OBJC_SELECTOR_REFERENCES_.{{[0-9]+}}, +// x86_64_macos-SAME: align 8 +// aarch64_macos-SAME: align 8 +// i386_ios-SAME: align 4 +// x86_64_ios-SAME: align 8 +// armv7s_ios-SAME: align 4 +// aarch64_ios-SAME: align 8 +// aarch64_ios_sim-SAME: align 8 + +// CHECK: load ptr, ptr @"OBJC_CLASSLIST_REFERENCES_$_.{{[0-9]+}}", +// x86_64_macos-SAME: align 8 +// aarch64_macos-SAME: align 8 +// i386_ios-SAME: align 4 +// x86_64_ios-SAME: align 8 +// armv7s_ios-SAME: align 4 +// aarch64_ios-SAME: align 8 +// aarch64_ios_sim-SAME: align 8 + +// CHECK: load ptr, ptr @OBJC_SELECTOR_REFERENCES_.{{[0-9]+}}, +// x86_64_macos-SAME: align 8 +// aarch64_macos-SAME: align 8 +// i386_ios-SAME: align 4 +// x86_64_ios-SAME: align 8 +// armv7s_ios-SAME: align 4 +// aarch64_ios-SAME: align 8 +// aarch64_ios_sim-SAME: align 8 + +// CHECK: !{{[0-9]+}} = !{i32 1, !"Objective-C Version", i32 2} +// CHECK: !{{[0-9]+}} = !{i32 1, !"Objective-C Image Info Version", i32 0} +// CHECK: !{{[0-9]+}} = !{i32 1, !"Objective-C Image Info Section", !"__DATA,__objc_imageinfo,regular,no_dead_strip"} + +// x86_64_macos-NOT: !{{[0-9]+}} = !{i32 1, !"Objective-C Is Simulated", i32 32} +// aarch64_macos-NOT: !{{[0-9]+}} = !{i32 1, !"Objective-C Is Simulated", i32 32} +// i386_ios: !{{[0-9]+}} = !{i32 1, !"Objective-C Is Simulated", i32 32} +// x86_64_ios: !{{[0-9]+}} = !{i32 1, !"Objective-C Is Simulated", i32 32} +// armv7s_ios-NOT: !{{[0-9]+}} = !{i32 1, !"Objective-C Is Simulated", i32 32} +// aarch64_ios-NOT: !{{[0-9]+}} = !{i32 1, !"Objective-C Is Simulated", i32 32} +// aarch64_ios_sim: !{{[0-9]+}} = !{i32 1, !"Objective-C Is Simulated", i32 32} + +// CHECK: !{{[0-9]+}} = !{i32 1, !"Objective-C Class Properties", i32 64} diff --git a/tests/codegen-llvm/darwin-objc-cross-crate.rs b/tests/codegen-llvm/darwin-objc-cross-crate.rs new file mode 100644 index 00000000000..74ad9a27346 --- /dev/null +++ b/tests/codegen-llvm/darwin-objc-cross-crate.rs @@ -0,0 +1,58 @@ +// Test that Objective-C class and selector references inlined across crates +// get defined in this CGU but non-inline references don't. + +// ignore-tidy-linelength +//@ aux-build: darwin_objc_aux.rs +//@ revisions: x86_64_macos aarch64_macos +//@ [x86_64_macos] only-x86_64-apple-darwin +//@ [aarch64_macos] only-aarch64-apple-darwin + +#![crate_type = "lib"] +#![feature(darwin_objc)] + +use std::os::darwin::objc; + +extern crate darwin_objc_aux as aux; + +#[no_mangle] +pub fn get_object_class() -> objc::Class { + aux::inline_get_object_class() +} + +#[no_mangle] +pub fn get_alloc_selector() -> objc::SEL { + aux::inline_get_alloc_selector() +} + +#[no_mangle] +pub fn get_string_class() -> objc::Class { + aux::never_inline_get_string_class() +} + +#[no_mangle] +pub fn get_init_selector() -> objc::SEL { + aux::never_inline_get_init_selector() +} + +// CHECK: %struct._class_t = type { ptr, ptr, ptr, ptr, ptr } + +// CHECK: @"OBJC_CLASS_$_NSObject" = external global %struct._class_t +// CHECK: @"OBJC_CLASSLIST_REFERENCES_$_.{{[0-9]+}}" = internal global ptr @"OBJC_CLASS_$_NSObject", section "__DATA,__objc_classrefs,regular,no_dead_strip", align 8 + +// CHECK: @OBJC_METH_VAR_NAME_.{{[0-9]+}} = private unnamed_addr constant [6 x i8] c"alloc\00", section "__TEXT,__objc_methname,cstring_literals", align 1 +// CHECK: @OBJC_SELECTOR_REFERENCES_.{{[0-9]+}} = internal externally_initialized global ptr @OBJC_METH_VAR_NAME_.{{[0-9]+}}, section "__DATA,__objc_selrefs,literal_pointers,no_dead_strip", align 8 + +// CHECK-NOT: @"OBJC_CLASS_$_NSString" = external global %struct._class_t +// CHECK-NOT: @"OBJC_CLASSLIST_REFERENCES_$_.{{[0-9]+}}" = internal global ptr @"OBJC_CLASS_$_NSString" + +// CHECK-NOT: @OBJC_METH_VAR_NAME_.{{[0-9]+}} = private unnamed_addr constant [5 x i8] c"init\00" +// CHECK-NOT: @OBJC_SELECTOR_REFERENCES_.{{[0-9]+}} = internal externally_initialized global ptr @OBJC_METH_VAR_NAME_.{{[0-9]+}} + +// CHECK: load ptr, ptr @"OBJC_CLASSLIST_REFERENCES_$_.{{[0-9]+}}", align 8 +// CHECK: load ptr, ptr @OBJC_SELECTOR_REFERENCES_.{{[0-9]+}}, align 8 + +// CHECK: !{{[0-9]+}} = !{i32 1, !"Objective-C Version", i32 2} +// CHECK: !{{[0-9]+}} = !{i32 1, !"Objective-C Image Info Version", i32 0} +// CHECK: !{{[0-9]+}} = !{i32 1, !"Objective-C Image Info Section", !"__DATA,__objc_imageinfo,regular,no_dead_strip"} +// CHECK-NOT: !{{[0-9]+}} = !{i32 1, !"Objective-C Is Simulated", i32 32} +// CHECK: !{{[0-9]+}} = !{i32 1, !"Objective-C Class Properties", i32 64} diff --git a/tests/ui/README.md b/tests/ui/README.md index 66c1bb905a7..3b28ef694dd 100644 --- a/tests/ui/README.md +++ b/tests/ui/README.md @@ -350,6 +350,12 @@ Tests for FFI with C varargs (`va_list`). Tests for detection and handling of cyclic trait dependencies. +## `tests/ui/darwin-objc/`: Darwin Objective-C + +Tests exercising `#![feature(darwin_objc)]`. + +See [Tracking Issue for `darwin_objc` #145496](https://github.com/rust-lang/rust/issues/145496). + ## `tests/ui/dataflow_const_prop/` Contains a single regression test for const prop in `SwitchInt` pass crashing when `ptr2int` transmute is involved. diff --git a/tests/ui/darwin-objc/darwin-objc-bad-arg.rs b/tests/ui/darwin-objc/darwin-objc-bad-arg.rs new file mode 100644 index 00000000000..70eb83aa052 --- /dev/null +++ b/tests/ui/darwin-objc/darwin-objc-bad-arg.rs @@ -0,0 +1,36 @@ +// Test that `objc::class!` and `objc::selector!` only take string literals. + +//@ edition: 2024 +//@ only-apple + +#![feature(darwin_objc)] + +use std::os::darwin::objc; + +pub fn main() { + let s = "NSObject"; + objc::class!(s); + //~^ ERROR attribute value must be a literal + + objc::class!(NSObject); + //~^ ERROR attribute value must be a literal + + objc::class!(123); + //~^ ERROR `objc::class!` expected a string literal + + objc::class!("NSObject\0"); + //~^ ERROR `objc::class!` may not contain null characters + + let s = "alloc"; + objc::selector!(s); + //~^ ERROR attribute value must be a literal + + objc::selector!(alloc); + //~^ ERROR attribute value must be a literal + + objc::selector!(123); + //~^ ERROR `objc::selector!` expected a string literal + + objc::selector!("alloc\0"); + //~^ ERROR `objc::selector!` may not contain null characters +} diff --git a/tests/ui/darwin-objc/darwin-objc-bad-arg.stderr b/tests/ui/darwin-objc/darwin-objc-bad-arg.stderr new file mode 100644 index 00000000000..99eeb27e30c --- /dev/null +++ b/tests/ui/darwin-objc/darwin-objc-bad-arg.stderr @@ -0,0 +1,50 @@ +error: attribute value must be a literal + --> $DIR/darwin-objc-bad-arg.rs:12:18 + | +LL | objc::class!(s); + | ^ + +error: attribute value must be a literal + --> $DIR/darwin-objc-bad-arg.rs:15:18 + | +LL | objc::class!(NSObject); + | ^^^^^^^^ + +error: `objc::class!` expected a string literal + --> $DIR/darwin-objc-bad-arg.rs:18:18 + | +LL | objc::class!(123); + | ^^^ + +error: `objc::class!` may not contain null characters + --> $DIR/darwin-objc-bad-arg.rs:21:18 + | +LL | objc::class!("NSObject\0"); + | ^^^^^^^^^^^^ + +error: attribute value must be a literal + --> $DIR/darwin-objc-bad-arg.rs:25:21 + | +LL | objc::selector!(s); + | ^ + +error: attribute value must be a literal + --> $DIR/darwin-objc-bad-arg.rs:28:21 + | +LL | objc::selector!(alloc); + | ^^^^^ + +error: `objc::selector!` expected a string literal + --> $DIR/darwin-objc-bad-arg.rs:31:21 + | +LL | objc::selector!(123); + | ^^^ + +error: `objc::selector!` may not contain null characters + --> $DIR/darwin-objc-bad-arg.rs:34:21 + | +LL | objc::selector!("alloc\0"); + | ^^^^^^^^^ + +error: aborting due to 8 previous errors + diff --git a/tests/ui/darwin-objc/darwin-objc-bad-const.rs b/tests/ui/darwin-objc/darwin-objc-bad-const.rs new file mode 100644 index 00000000000..ccf28697b48 --- /dev/null +++ b/tests/ui/darwin-objc/darwin-objc-bad-const.rs @@ -0,0 +1,17 @@ +// Test that `objc::class!` and `objc::selector!` aren't `const` expressions. +// The system gives them their final values at dynamic load time. + +//@ edition: 2024 +//@ only-apple + +#![feature(darwin_objc)] + +use std::os::darwin::objc; + +pub const CLASS: objc::Class = objc::class!("NSObject"); +//~^ ERROR cannot access extern static `CLASS::VAL` [E0080] + +pub const SELECTOR: objc::SEL = objc::selector!("alloc"); +//~^ ERROR cannot access extern static `SELECTOR::VAL` [E0080] + +pub fn main() {} diff --git a/tests/ui/darwin-objc/darwin-objc-bad-const.stderr b/tests/ui/darwin-objc/darwin-objc-bad-const.stderr new file mode 100644 index 00000000000..43d0b7d761f --- /dev/null +++ b/tests/ui/darwin-objc/darwin-objc-bad-const.stderr @@ -0,0 +1,19 @@ +error[E0080]: cannot access extern static `CLASS::VAL` + --> $DIR/darwin-objc-bad-const.rs:11:32 + | +LL | pub const CLASS: objc::Class = objc::class!("NSObject"); + | ^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `CLASS` failed here + | + = note: this error originates in the macro `objc::class` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: cannot access extern static `SELECTOR::VAL` + --> $DIR/darwin-objc-bad-const.rs:14:33 + | +LL | pub const SELECTOR: objc::SEL = objc::selector!("alloc"); + | ^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `SELECTOR` failed here + | + = note: this error originates in the macro `objc::selector` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/darwin-objc/darwin-objc-bad-ref.rs b/tests/ui/darwin-objc/darwin-objc-bad-ref.rs new file mode 100644 index 00000000000..fb1437366dd --- /dev/null +++ b/tests/ui/darwin-objc/darwin-objc-bad-ref.rs @@ -0,0 +1,31 @@ +// Test that `objc::class!` and `objc::selector!` can't be returned by reference. +// A single instance may have multiple addresses (e.g. across dylib boundaries). + +//@ edition: 2024 +//@ only-apple + +#![feature(darwin_objc)] + +use std::os::darwin::objc; + +pub fn class_ref<'a>() -> &'a objc::Class { + &objc::class!("NSObject") + //~^ ERROR cannot return reference to temporary value [E0515] +} + +pub fn class_ref_static() -> &'static objc::Class { + &objc::class!("NSObject") + //~^ ERROR cannot return reference to temporary value [E0515] +} + +pub fn selector_ref<'a>() -> &'a objc::SEL { + &objc::selector!("alloc") + //~^ ERROR cannot return reference to temporary value [E0515] +} + +pub fn selector_ref_static() -> &'static objc::SEL { + &objc::selector!("alloc") + //~^ ERROR cannot return reference to temporary value [E0515] +} + +pub fn main() {} diff --git a/tests/ui/darwin-objc/darwin-objc-bad-ref.stderr b/tests/ui/darwin-objc/darwin-objc-bad-ref.stderr new file mode 100644 index 00000000000..b09e6a75c84 --- /dev/null +++ b/tests/ui/darwin-objc/darwin-objc-bad-ref.stderr @@ -0,0 +1,39 @@ +error[E0515]: cannot return reference to temporary value + --> $DIR/darwin-objc-bad-ref.rs:12:5 + | +LL | &objc::class!("NSObject") + | ^------------------------ + | || + | |temporary value created here + | returns a reference to data owned by the current function + +error[E0515]: cannot return reference to temporary value + --> $DIR/darwin-objc-bad-ref.rs:17:5 + | +LL | &objc::class!("NSObject") + | ^------------------------ + | || + | |temporary value created here + | returns a reference to data owned by the current function + +error[E0515]: cannot return reference to temporary value + --> $DIR/darwin-objc-bad-ref.rs:22:5 + | +LL | &objc::selector!("alloc") + | ^------------------------ + | || + | |temporary value created here + | returns a reference to data owned by the current function + +error[E0515]: cannot return reference to temporary value + --> $DIR/darwin-objc-bad-ref.rs:27:5 + | +LL | &objc::selector!("alloc") + | ^------------------------ + | || + | |temporary value created here + | returns a reference to data owned by the current function + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/darwin-objc/darwin-objc-class-selector.rs b/tests/ui/darwin-objc/darwin-objc-class-selector.rs new file mode 100644 index 00000000000..b9a2fc3634f --- /dev/null +++ b/tests/ui/darwin-objc/darwin-objc-class-selector.rs @@ -0,0 +1,31 @@ +// Call `[NSObject class]` using `objc::class!` and `objc::selector!`. + +//@ edition: 2024 +//@ only-apple +//@ run-pass + +#![feature(darwin_objc)] + +use std::mem::transmute; +use std::os::darwin::objc; + +#[link(name = "Foundation", kind = "framework")] +unsafe extern "C" {} + +#[link(name = "objc", kind = "dylib")] +unsafe extern "C" { + unsafe fn objc_msgSend(); +} + +fn main() { + let msg_send_fn = unsafe { + transmute::< + unsafe extern "C" fn(), + unsafe extern "C" fn(objc::Class, objc::SEL) -> objc::Class, + >(objc_msgSend) + }; + let static_sel = objc::selector!("class"); + let static_class = objc::class!("NSObject"); + let runtime_class = unsafe { msg_send_fn(static_class, static_sel) }; + assert_eq!(static_class, runtime_class); +} diff --git a/tests/ui/darwin-objc/darwin-objc-class.rs b/tests/ui/darwin-objc/darwin-objc-class.rs new file mode 100644 index 00000000000..851149d8726 --- /dev/null +++ b/tests/ui/darwin-objc/darwin-objc-class.rs @@ -0,0 +1,39 @@ +// Test that `objc::class!` returns the same thing as `objc_lookUpClass`. + +//@ edition: 2024 +//@ only-apple +//@ run-pass + +#![feature(darwin_objc)] + +use std::ffi::c_char; +use std::os::darwin::objc; + +#[link(name = "Foundation", kind = "framework")] +unsafe extern "C" {} + +#[link(name = "objc")] +unsafe extern "C" { + fn objc_lookUpClass(methname: *const c_char) -> objc::Class; +} + +fn get_object_class() -> objc::Class { + objc::class!("NSObject") +} + +fn lookup_object_class() -> objc::Class { + unsafe { objc_lookUpClass(c"NSObject".as_ptr()) } +} + +fn get_string_class() -> objc::Class { + objc::class!("NSString") +} + +fn lookup_string_class() -> objc::Class { + unsafe { objc_lookUpClass(c"NSString".as_ptr()) } +} + +fn main() { + assert_eq!(get_object_class(), lookup_object_class()); + assert_eq!(get_string_class(), lookup_string_class()); +} diff --git a/tests/ui/darwin-objc/darwin-objc-selector.rs b/tests/ui/darwin-objc/darwin-objc-selector.rs new file mode 100644 index 00000000000..008ae4c4ca4 --- /dev/null +++ b/tests/ui/darwin-objc/darwin-objc-selector.rs @@ -0,0 +1,36 @@ +// Test that `objc::selector!` returns the same thing as `sel_registerName`. + +//@ edition: 2024 +//@ only-apple +//@ run-pass + +#![feature(darwin_objc)] + +use std::ffi::c_char; +use std::os::darwin::objc; + +#[link(name = "objc")] +unsafe extern "C" { + fn sel_registerName(methname: *const c_char) -> objc::SEL; +} + +fn get_alloc_selector() -> objc::SEL { + objc::selector!("alloc") +} + +fn register_alloc_selector() -> objc::SEL { + unsafe { sel_registerName(c"alloc".as_ptr()) } +} + +fn get_init_selector() -> objc::SEL { + objc::selector!("initWithCString:encoding:") +} + +fn register_init_selector() -> objc::SEL { + unsafe { sel_registerName(c"initWithCString:encoding:".as_ptr()) } +} + +fn main() { + assert_eq!(get_alloc_selector(), register_alloc_selector()); + assert_eq!(get_init_selector(), register_init_selector()); +} |
