mirror of
https://github.com/dlang/dmd.git
synced 2025-04-26 13:10:12 +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;
|
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)
|
if (t.ty == Tfunction)
|
||||||
{
|
{
|
||||||
.error(loc, "cannot have parameter of function type `%s`", fparam.type.toChars());
|
.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
|
// PERMUTE_ARGS: -g
|
||||||
// EXTRA_CPP_SOURCES: cppb.cpp
|
// EXTRA_CPP_SOURCES: cppb.cpp
|
||||||
// EXTRA_FILES: extra-files/cppb.h
|
// EXTRA_FILES: extra-files/cppb.h
|
||||||
|
@ -1637,7 +1638,13 @@ void test19134()
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://issues.dlang.org/show_bug.cgi?id=18955
|
// 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)
|
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()
|
void main()
|
||||||
{
|
{
|
||||||
test1();
|
test1();
|
||||||
|
@ -1695,6 +1712,7 @@ void main()
|
||||||
test18966();
|
test18966();
|
||||||
test19134();
|
test19134();
|
||||||
test18955();
|
test18955();
|
||||||
|
testPreviewIn();
|
||||||
|
|
||||||
printf("Success\n");
|
printf("Success\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,30 +4,8 @@
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <cstdarg>
|
#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>
|
#include <string>
|
||||||
|
|
||||||
#endif // _WIN32
|
|
||||||
|
|
||||||
#include "cppb.h"
|
#include "cppb.h"
|
||||||
|
|
||||||
/**************************************/
|
/**************************************/
|
||||||
|
@ -936,3 +914,11 @@ void test18955()
|
||||||
callback18955(s);
|
callback18955(s);
|
||||||
#endif
|
#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