mirror of
https://github.com/dlang/dmd.git
synced 2025-04-26 21:21:48 +03:00
Allow -preview=in
only with extern(D|C++)
The intent of `-preview=in` is to make `in` the go-to storage class for input parameters in D. However it is D centric, as it is an enhanced version of `scope const ref`. As non-`extern(D)` functions usually are expected to match a specific ABI, using `in` is hardly a good idea. However, as C++, also have a "go to" storage class for input parameters (`const T&`), `in` can also be applied on `extern(C++)` function in order to bind to `const T&` parameters. This also allows to expose a closer API for a function than via `const ref`, as `in` will allow to bind rvalues to `const T&`, as in C++.
This commit is contained in:
parent
37436a4446
commit
b3cc517966
5 changed files with 75 additions and 23 deletions
11
changelog/previewInLink.dd
Normal file
11
changelog/previewInLink.dd
Normal file
|
@ -0,0 +1,11 @@
|
|||
`-preview=in` can now be used with `extern(C++)`, disabled for other non-D linkage
|
||||
|
||||
The intent of `-preview=in` is to make `in` the go-to storage class for input parameters in D.
|
||||
However, it is D centric, as it is an enhanced version of `scope const ref`.
|
||||
As non-`extern(D)` functions usually are expected to match a specific ABI,
|
||||
using `in` is hardly a good idea.
|
||||
|
||||
As C++ also has a "go to" storage class for input parameters (`const T&`),
|
||||
`in` can also be applied on `extern(C++)` function in order to bind to `const T&` parameters.
|
||||
This also allows to expose a closer API for a function than via `const ref`,
|
||||
as `in` will allow to bind rvalues to `const T&`, as in C++.
|
|
@ -1224,6 +1224,25 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
|
|||
continue;
|
||||
}
|
||||
|
||||
// -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_)
|
||||
{
|
||||
switch (tf.linkage)
|
||||
{
|
||||
case LINK.cpp:
|
||||
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());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (t.ty == Tfunction)
|
||||
{
|
||||
.error(loc, "cannot have parameter of function type `%s`", fparam.type.toChars());
|
||||
|
|
18
test/fail_compilation/previewin2.d
Normal file
18
test/fail_compilation/previewin2.d
Normal file
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
REQUIRED_ARGS: -preview=in -preview=dip1000
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/previewin2.d(1): Error: cannot use `in` parameters with `extern(C)` functions
|
||||
fail_compilation/previewin2.d(1): parameter `a` declared as `in` here
|
||||
fail_compilation/previewin2.d(2): Error: cannot use `in` parameters with `extern(Windows)` functions
|
||||
fail_compilation/previewin2.d(2): parameter `a` declared as `in` here
|
||||
fail_compilation/previewin2.d(4): Error: cannot use `in` parameters with `extern(C)` functions
|
||||
fail_compilation/previewin2.d(4): parameter `__anonymous_param` declared as `in` here
|
||||
---
|
||||
*/
|
||||
|
||||
#line 1
|
||||
extern(C) void wrongLink1 (in int a);
|
||||
extern(Windows) void wrongLink2 (in void* a);
|
||||
struct Large { ulong[64] data; }
|
||||
extern(C) void wrongLink3 (in Large);
|
|
@ -1,3 +1,4 @@
|
|||
// REQUIRED_ARGS: -preview=in
|
||||
// PERMUTE_ARGS: -g
|
||||
// EXTRA_CPP_SOURCES: cppb.cpp
|
||||
// EXTRA_FILES: extra-files/cppb.h
|
||||
|
@ -1637,7 +1638,13 @@ void test19134()
|
|||
}
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=18955
|
||||
alias std_string = std.basic_string!(char);
|
||||
version (linux)
|
||||
alias std_string = std.basic_string!(char);
|
||||
else
|
||||
{
|
||||
import core.stdcpp.string : core_basic_string = basic_string;
|
||||
alias std_string = core_basic_string!(char);
|
||||
}
|
||||
|
||||
extern(C++) void callback18955(ref const(std_string) str)
|
||||
{
|
||||
|
@ -1646,6 +1653,16 @@ extern(C++) void test18955();
|
|||
|
||||
/****************************************/
|
||||
|
||||
extern(C++) void testPreviewIn();
|
||||
|
||||
extern(C++) void previewInFunction(in int a, in std_string b, ref const(std_string) c)
|
||||
{
|
||||
assert(a == 42);
|
||||
assert(&b is &c);
|
||||
}
|
||||
|
||||
/****************************************/
|
||||
|
||||
void main()
|
||||
{
|
||||
test1();
|
||||
|
@ -1695,6 +1712,7 @@ void main()
|
|||
test18966();
|
||||
test19134();
|
||||
test18955();
|
||||
testPreviewIn();
|
||||
|
||||
printf("Success\n");
|
||||
}
|
||||
|
|
|
@ -4,30 +4,8 @@
|
|||
#include <exception>
|
||||
#include <cstdarg>
|
||||
|
||||
#if _WIN32 // otherwise defined in C header files!
|
||||
// https://issues.dlang.org/show_bug.cgi?id=18955
|
||||
namespace std
|
||||
{
|
||||
template<typename Char>
|
||||
struct char_traits
|
||||
{
|
||||
};
|
||||
template<typename Char>
|
||||
class allocator
|
||||
{
|
||||
};
|
||||
template<typename Char, typename Traits, typename Alloc>
|
||||
class basic_string
|
||||
{
|
||||
};
|
||||
typedef basic_string<char, char_traits<char>, allocator<char> > string;
|
||||
}
|
||||
#else // if POSIX
|
||||
|
||||
#include <string>
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
#include "cppb.h"
|
||||
|
||||
/**************************************/
|
||||
|
@ -936,3 +914,11 @@ void test18955()
|
|||
callback18955(s);
|
||||
#endif
|
||||
}
|
||||
|
||||
void previewInFunction(const int& a, const std::string& b, const std::string& c);
|
||||
|
||||
void testPreviewIn()
|
||||
{
|
||||
std::string s = "Hello World";
|
||||
previewInFunction(42, s, s);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue