mirror of
https://github.com/dlang/dmd.git
synced 2025-04-26 21:21:48 +03:00

This error was introduced in `-preview=in` in v2.101.0. In order to make `-preview=in` the default, we add a deprecation even if `-preview=in` is not used.
104 lines
2.7 KiB
D
104 lines
2.7 KiB
D
// EXTRA_OBJC_SOURCES:
|
|
// REQUIRED_ARGS: -L-lobjc
|
|
|
|
// This file verifies that Objective-C protocols are put in the correct segments
|
|
// and sections in the binary. If not, functions from the Objective-C runtime
|
|
// won't find the protocol data and the below functions will return `null`.
|
|
|
|
import core.attribute : selector, optional;
|
|
|
|
extern (Objective-C):
|
|
|
|
struct Protocol;
|
|
struct objc_selector;
|
|
alias SEL = objc_selector*;
|
|
|
|
struct objc_method_description
|
|
{
|
|
SEL name;
|
|
char* types;
|
|
|
|
/**
|
|
* Returns `true` if the method description is valid.
|
|
*
|
|
* That means that the Objective-C runtime was able to find the method. That
|
|
* implicitly means that the protocol data has been laid out correctly in the
|
|
* binary.
|
|
*/
|
|
bool isValid()
|
|
{
|
|
return name && types;
|
|
}
|
|
}
|
|
|
|
SEL sel_registerName(scope const char* str);
|
|
Protocol* objc_getProtocol(scope const char* name);
|
|
objc_method_description protocol_getMethodDescription(
|
|
Protocol* proto, SEL aSel, bool isRequiredMethod, bool isInstanceMethod
|
|
);
|
|
|
|
interface Foo
|
|
{
|
|
void foo1() @selector("foo1");
|
|
static void foo2() @selector("foo2");
|
|
@optional void foo3() @selector("foo3");
|
|
@optional static void foo4() @selector("foo4");
|
|
}
|
|
|
|
// A class that implements an Objective-C interface is required for the
|
|
// protocol data to be put into the binary.
|
|
class TestObject : Foo
|
|
{
|
|
void foo1() @selector("foo1") {}
|
|
static void foo2() @selector("foo2") {}
|
|
void foo3() @selector("foo3") {}
|
|
static void foo4() @selector("foo4") {}
|
|
}
|
|
|
|
extern (D):
|
|
|
|
/// Used to indicate if a method is an instance method or a class (static) method.
|
|
enum MethodType : bool
|
|
{
|
|
class_,
|
|
instance
|
|
}
|
|
|
|
/// Used to indicate if a method is required or optional.
|
|
enum MethodFlag : bool
|
|
{
|
|
optional,
|
|
required
|
|
}
|
|
|
|
/**
|
|
* Returns the method description for the method with the given selector.
|
|
*
|
|
* The protocol the methods will be looked up in is always `Foo`.
|
|
*
|
|
* Params:
|
|
* selector = the selector of the method
|
|
* flag = indicates if the method is required or optional
|
|
* type = indicates if the method is an instance method or a class method
|
|
*/
|
|
objc_method_description methodDescription(in char* selector, MethodFlag flag, MethodType type)
|
|
{
|
|
auto protocol = objc_getProtocol("Foo");
|
|
assert(protocol);
|
|
|
|
auto sel = sel_registerName(selector);
|
|
assert(sel);
|
|
|
|
return protocol_getMethodDescription(protocol, sel, flag, type);
|
|
}
|
|
|
|
void main()
|
|
{
|
|
with (MethodFlag) with (MethodType)
|
|
{
|
|
assert(methodDescription("foo1", required, instance).isValid);
|
|
assert(methodDescription("foo2", required, class_).isValid);
|
|
assert(methodDescription("foo3", optional, instance).isValid);
|
|
assert(methodDescription("foo4", optional, class_).isValid);
|
|
}
|
|
}
|