diff --git a/changelog/dmd.in-externd.dd b/changelog/dmd.in-externd.dd new file mode 100644 index 0000000000..b0d2ef8b17 --- /dev/null +++ b/changelog/dmd.in-externd.dd @@ -0,0 +1,7 @@ +Using `in` parameters with non `extern(D)`/`extern(C++)` functions is deprecated + +In preparation for enabling `-preview=in` by default, +using `in` parameters on function that have neither D nor C++ linkage is deprecated. +Users can replace instances of `in` with either `const` or `scope const`. +Refer to [v2.101.0 changelog's](https://dlang.org/changelog/2.101.0.html#dmd.previewInLink) +for a full rationale. diff --git a/compiler/src/dmd/typesem.d b/compiler/src/dmd/typesem.d index aed7ccbd5a..71f80f7f87 100644 --- a/compiler/src/dmd/typesem.d +++ b/compiler/src/dmd/typesem.d @@ -1185,19 +1185,31 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc) // -preview=in: Always add `ref` when used with `extern(C++)` functions // Done here to allow passing opaque types with `in` - if (global.params.previewIn && (fparam.storageClass & (STC.in_ | STC.ref_)) == STC.in_) + if ((fparam.storageClass & (STC.in_ | STC.ref_)) == STC.in_) { switch (tf.linkage) { case LINK.cpp: - fparam.storageClass |= STC.ref_; + if (global.params.previewIn) + fparam.storageClass |= STC.ref_; break; case LINK.default_, LINK.d: break; default: - .error(loc, "cannot use `in` parameters with `extern(%s)` functions", - linkageToChars(tf.linkage)); - .errorSupplemental(loc, "parameter `%s` declared as `in` here", fparam.toChars()); + if (global.params.previewIn) + { + .error(loc, "cannot use `in` parameters with `extern(%s)` functions", + linkageToChars(tf.linkage)); + .errorSupplemental(loc, "parameter `%s` declared as `in` here", fparam.toChars()); + } + else + { + // Note that this deprecation will not trigger on `in ref` / `ref in` + // parameters, however the parser will trigger a deprecation on them. + .deprecation(loc, "using `in` parameters with `extern(%s)` functions is deprecated", + linkageToChars(tf.linkage)); + .deprecationSupplemental(loc, "parameter `%s` declared as `in` here", fparam.toChars()); + } break; } } diff --git a/compiler/test/compilable/warn3882.d b/compiler/test/compilable/warn3882.d index af7aed9059..0474315be5 100644 --- a/compiler/test/compilable/warn3882.d +++ b/compiler/test/compilable/warn3882.d @@ -12,7 +12,7 @@ void test3882() /******************************************/ // https://issues.dlang.org/show_bug.cgi?id=12619 -extern (C) @system nothrow pure void* memcpy(void* s1, in void* s2, size_t n); +extern (C) @system nothrow pure void* memcpy(void* s1, const void* s2, size_t n); // -> weakly pure void test12619() pure diff --git a/compiler/test/fail_compilation/deprecations_preview_in.d b/compiler/test/fail_compilation/deprecations_preview_in.d new file mode 100644 index 0000000000..33cc904e4b --- /dev/null +++ b/compiler/test/fail_compilation/deprecations_preview_in.d @@ -0,0 +1,11 @@ +/* +REQUIRED_ARGS: -de +TEST_OUTPUT: +--- +fail_compilation/deprecations_preview_in.d(1): Deprecation: using `in` parameters with `extern(C)` functions is deprecated +fail_compilation/deprecations_preview_in.d(1): parameter `__anonymous_param` declared as `in` here +--- +*/ + +#line 1 +extern(C) void fun1(in char*); diff --git a/compiler/test/runnable/debug_info.d b/compiler/test/runnable/debug_info.d index 902f2e569e..7853d9a3d9 100644 --- a/compiler/test/runnable/debug_info.d +++ b/compiler/test/runnable/debug_info.d @@ -27,8 +27,8 @@ else extern (C) { MachHeader* _dyld_get_image_header(uint image_index); - const(section)* getsectbynamefromheader(in mach_header* mhp, in char* segname, in char* sectname); - const(section_64)* getsectbynamefromheader_64(in mach_header_64* mhp, in char* segname, in char* sectname); + const(section)* getsectbynamefromheader(scope const mach_header* mhp, scope const char* segname, scope const char* sectname); + const(section_64)* getsectbynamefromheader_64(scope const mach_header_64* mhp, scope const char* segname, scope const char* sectname); } const(Section)* getSectByNameFromHeader(MachHeader* mhp, in char* segname, in char* sectname) diff --git a/compiler/test/runnable/imports/link13415a.d b/compiler/test/runnable/imports/link13415a.d index de3bbe2ac9..077671b01c 100644 --- a/compiler/test/runnable/imports/link13415a.d +++ b/compiler/test/runnable/imports/link13415a.d @@ -7,7 +7,7 @@ struct S(alias func) } } -extern(C) int printf(in char*, ...); +extern(C) int printf(const char*, ...); void f(int i = 77) { diff --git a/compiler/test/runnable/objc_call.d b/compiler/test/runnable/objc_call.d index 1463ac34ba..98199a0abb 100644 --- a/compiler/test/runnable/objc_call.d +++ b/compiler/test/runnable/objc_call.d @@ -12,12 +12,12 @@ extern class Class extern (Objective-C) extern class NSObject { - NSObject initWithUTF8String(in char* str) @selector("initWithUTF8String:"); + NSObject initWithUTF8String(scope const char* str) @selector("initWithUTF8String:"); void release() @selector("release"); } extern (C) void NSLog(NSObject, ...); -extern (C) Class objc_lookUpClass(in char* name); +extern (C) Class objc_lookUpClass(scope const char* name); void main() { diff --git a/compiler/test/runnable/objc_objc_msgSend.d b/compiler/test/runnable/objc_objc_msgSend.d index 21fe95cbda..8b7e8ab5c4 100644 --- a/compiler/test/runnable/objc_objc_msgSend.d +++ b/compiler/test/runnable/objc_objc_msgSend.d @@ -3,7 +3,7 @@ import core.attribute : selector; -extern (C) Class objc_lookUpClass(in char* name); +extern (C) Class objc_lookUpClass(scope const char* name); struct Struct { diff --git a/compiler/test/runnable/objc_protocol_sections.d b/compiler/test/runnable/objc_protocol_sections.d index b2869d204d..89790c1cfc 100644 --- a/compiler/test/runnable/objc_protocol_sections.d +++ b/compiler/test/runnable/objc_protocol_sections.d @@ -31,8 +31,8 @@ struct objc_method_description } } -SEL sel_registerName(in char* str); -Protocol* objc_getProtocol(in char* name); +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 );