mirror of
https://github.com/dlang/dmd.git
synced 2025-04-26 13:10:12 +03:00
1676 lines
31 KiB
D
1676 lines
31 KiB
D
// REQUIRED_ARGS: -preview=in
|
|
// PERMUTE_ARGS: -g
|
|
// EXTRA_CPP_SOURCES: cppb.cpp
|
|
// EXTRA_FILES: extra-files/cppb.h
|
|
// CXXFLAGS(linux freebsd osx openbsd netbsd dragonflybsd): -std=c++11
|
|
// druntime isn't linked, this prevents missing symbols '_d_arraybounds_slicep':
|
|
// REQUIRED_ARGS: -checkaction=C
|
|
// TRANSFORM_OUTPUT: remove_lines("warning: vsprintf\(\) is often misused")
|
|
|
|
// N.B MSVC doesn't have a C++11 switch, but it defaults to the latest fully-supported standard
|
|
|
|
import core.stdc.stdio;
|
|
import core.stdc.stdarg;
|
|
import core.stdc.config;
|
|
import core.stdc.stdint;
|
|
|
|
extern (C++)
|
|
int foob(int i, int j, int k);
|
|
|
|
class C
|
|
{
|
|
extern (C++) int bar(int i, int j, int k)
|
|
{
|
|
printf("this = %p\n", this);
|
|
printf("i = %d\n", i);
|
|
printf("j = %d\n", j);
|
|
printf("k = %d\n", k);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
extern (C++)
|
|
int foo(int i, int j, int k)
|
|
{
|
|
printf("i = %d\n", i);
|
|
printf("j = %d\n", j);
|
|
printf("k = %d\n", k);
|
|
assert(i == 1);
|
|
assert(j == 2);
|
|
assert(k == 3);
|
|
return 1;
|
|
}
|
|
|
|
void test1()
|
|
{
|
|
foo(1, 2, 3);
|
|
|
|
auto i = foob(1, 2, 3);
|
|
assert(i == 7);
|
|
|
|
C c = new C();
|
|
c.bar(4, 5, 6);
|
|
}
|
|
|
|
/****************************************/
|
|
|
|
extern (C++) interface D
|
|
{
|
|
int bar(int i, int j, int k);
|
|
}
|
|
|
|
extern (C++) D getD();
|
|
|
|
void test2()
|
|
{
|
|
D d = getD();
|
|
int i = d.bar(9,10,11);
|
|
assert(i == 8);
|
|
}
|
|
|
|
/****************************************/
|
|
|
|
extern (C++) int callE(E);
|
|
|
|
extern (C++) interface E
|
|
{
|
|
int bar(int i, int j, int k);
|
|
}
|
|
|
|
class F : E
|
|
{
|
|
extern (C++) int bar(int i, int j, int k)
|
|
{
|
|
printf("F.bar: i = %d\n", i);
|
|
printf("F.bar: j = %d\n", j);
|
|
printf("F.bar: k = %d\n", k);
|
|
assert(i == 11);
|
|
assert(j == 12);
|
|
assert(k == 13);
|
|
return 8;
|
|
}
|
|
}
|
|
|
|
void test3()
|
|
{
|
|
F f = new F();
|
|
int i = callE(f);
|
|
assert(i == 8);
|
|
}
|
|
|
|
/****************************************/
|
|
|
|
extern (C++) void foo4(char* p);
|
|
|
|
void test4()
|
|
{
|
|
foo4(null);
|
|
}
|
|
|
|
/****************************************/
|
|
|
|
extern(C++)
|
|
{
|
|
struct foo5 { int i; int j; void* p; }
|
|
|
|
interface bar5{
|
|
foo5 getFoo(int i);
|
|
}
|
|
|
|
bar5 newBar();
|
|
}
|
|
|
|
void test5()
|
|
{
|
|
bar5 b = newBar();
|
|
foo5 f = b.getFoo(4);
|
|
printf("f.p = %p, b = %p\n", f.p, cast(void*)b);
|
|
assert(f.p == cast(void*)b);
|
|
}
|
|
|
|
|
|
/****************************************/
|
|
|
|
extern(C++)
|
|
{
|
|
struct S6
|
|
{
|
|
int i;
|
|
double d;
|
|
}
|
|
|
|
union S6_2
|
|
{
|
|
int i;
|
|
double d;
|
|
}
|
|
|
|
enum S6_3
|
|
{
|
|
A, B
|
|
}
|
|
|
|
S6 foo6();
|
|
S6_2 foo6_2();
|
|
S6_3 foo6_3();
|
|
}
|
|
|
|
extern (C) int foosize6();
|
|
|
|
void test6()
|
|
{
|
|
S6 f = foo6();
|
|
printf("%d %zd\n", foosize6(), S6.sizeof);
|
|
assert(foosize6() == S6.sizeof);
|
|
version (X86)
|
|
{
|
|
assert(f.i == 42);
|
|
printf("f.d = %g\n", f.d);
|
|
assert(f.d == 2.5);
|
|
assert(foo6_2().i == 42);
|
|
assert(foo6_3() == S6_3.A);
|
|
}
|
|
}
|
|
|
|
/****************************************/
|
|
|
|
extern (C) int foo7();
|
|
|
|
struct S
|
|
{
|
|
int i;
|
|
long l;
|
|
}
|
|
|
|
void test7()
|
|
{
|
|
printf("%d %zd\n", foo7(), S.sizeof);
|
|
assert(foo7() == S.sizeof);
|
|
}
|
|
|
|
/****************************************/
|
|
|
|
extern (C++) void foo8(const(char)*);
|
|
|
|
void test8()
|
|
{
|
|
char c;
|
|
foo8(&c);
|
|
}
|
|
|
|
/****************************************/
|
|
// https://issues.dlang.org/show_bug.cgi?id=4059
|
|
|
|
struct elem9 { }
|
|
|
|
extern(C++) void foobar9(elem9*, elem9*);
|
|
|
|
void test9()
|
|
{
|
|
elem9 *a;
|
|
foobar9(a, a);
|
|
}
|
|
|
|
/****************************************/
|
|
|
|
|
|
struct A11802;
|
|
struct B11802;
|
|
|
|
extern(C++) class C11802
|
|
{
|
|
int x;
|
|
void fun(A11802*) { x += 2; }
|
|
void fun(B11802*) { x *= 2; }
|
|
}
|
|
|
|
extern(C++) class D11802 : C11802
|
|
{
|
|
override void fun(A11802*) { x += 3; }
|
|
override void fun(B11802*) { x *= 3; }
|
|
}
|
|
|
|
extern(C++) void test11802x(D11802);
|
|
|
|
void test11802()
|
|
{
|
|
auto x = new D11802();
|
|
x.x = 0;
|
|
test11802x(x);
|
|
assert(x.x == 9);
|
|
}
|
|
|
|
|
|
/****************************************/
|
|
|
|
struct S13956
|
|
{
|
|
}
|
|
|
|
extern(C++) void func13956(S13956 arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6);
|
|
|
|
extern(C++) void check13956(S13956 arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6)
|
|
{
|
|
assert(arg0 == S13956());
|
|
assert(arg1 == 1);
|
|
assert(arg2 == 2);
|
|
assert(arg3 == 3);
|
|
assert(arg4 == 4);
|
|
assert(arg5 == 5);
|
|
assert(arg6 == 6);
|
|
}
|
|
|
|
void test13956()
|
|
{
|
|
func13956(S13956(), 1, 2, 3, 4, 5, 6);
|
|
}
|
|
|
|
/****************************************/
|
|
// https://issues.dlang.org/show_bug.cgi?id=5148
|
|
|
|
extern (C++)
|
|
{
|
|
void foo10(const(char)*, const(char)*);
|
|
void foo10(const int, const int);
|
|
void foo10(const char, const char);
|
|
void foo10(bool, bool);
|
|
|
|
struct MyStructType { }
|
|
void foo10(const MyStructType s, const MyStructType t);
|
|
|
|
enum MyEnumType { onemember }
|
|
void foo10(const MyEnumType s, const MyEnumType t);
|
|
}
|
|
|
|
void test10()
|
|
{
|
|
char* p;
|
|
foo10(p, p);
|
|
foo10(1,2);
|
|
foo10('c','d');
|
|
MyStructType s;
|
|
foo10(s,s);
|
|
MyEnumType e;
|
|
foo10(e,e);
|
|
}
|
|
|
|
/****************************************/
|
|
|
|
extern (C++, N11.M) { void bar11(); }
|
|
|
|
extern (C++, A11.B) { extern (C++, C) { void bar(); }}
|
|
|
|
void test11()
|
|
{
|
|
bar11();
|
|
A11.B.C.bar();
|
|
}
|
|
/****************************************/
|
|
|
|
struct Struct10071
|
|
{
|
|
void *p;
|
|
c_long_double r;
|
|
}
|
|
|
|
extern(C++) size_t offset10071();
|
|
void test10071()
|
|
{
|
|
assert(offset10071() == Struct10071.r.offsetof);
|
|
}
|
|
|
|
/****************************************/
|
|
|
|
char[100] valistbuffer;
|
|
|
|
extern(C++) void myvprintfx(const(char)* format, va_list va)
|
|
{
|
|
vsprintf(valistbuffer.ptr, format, va);
|
|
}
|
|
extern(C++) void myvprintf(const(char)*, va_list);
|
|
extern(C++) void myprintf(const(char)* format, ...)
|
|
{
|
|
va_list ap;
|
|
va_start(ap, format);
|
|
myvprintf(format, ap);
|
|
va_end(ap);
|
|
}
|
|
|
|
void testvalist()
|
|
{
|
|
myprintf("hello %d", 999);
|
|
assert(valistbuffer[0..9] == "hello 999");
|
|
}
|
|
|
|
/****************************************/
|
|
// https://issues.dlang.org/show_bug.cgi?id=12825
|
|
|
|
extern(C++) class C12825
|
|
{
|
|
uint a = 0x12345678;
|
|
}
|
|
|
|
void test12825()
|
|
{
|
|
auto c = new C12825();
|
|
}
|
|
|
|
/****************************************/
|
|
|
|
struct S13955a
|
|
{
|
|
float a;
|
|
double b;
|
|
}
|
|
|
|
struct S13955b
|
|
{
|
|
double a;
|
|
float b;
|
|
}
|
|
|
|
struct S13955c
|
|
{
|
|
float a;
|
|
float b;
|
|
}
|
|
|
|
struct S13955d
|
|
{
|
|
double a;
|
|
double b;
|
|
}
|
|
|
|
extern(C++) void check13955(S13955a a, S13955b b, S13955c c, S13955d d)
|
|
{
|
|
assert(a.a == 2);
|
|
assert(a.b == 4);
|
|
assert(b.a == 8);
|
|
assert(b.b == 16);
|
|
assert(c.a == 32);
|
|
assert(c.b == 64);
|
|
assert(d.a == 128);
|
|
assert(d.b == 256);
|
|
}
|
|
|
|
extern(C++) void func13955(S13955a a, S13955b b, S13955c c, S13955d d);
|
|
|
|
void test13955()
|
|
{
|
|
func13955(S13955a(2, 4), S13955b(8, 16), S13955c(32, 64), S13955d(128, 256));
|
|
}
|
|
|
|
/****************************************/
|
|
|
|
extern(C++) class C13161
|
|
{
|
|
void dummyfunc();
|
|
long val_5;
|
|
uint val_9;
|
|
}
|
|
|
|
extern(C++) class Test : C13161
|
|
{
|
|
uint val_0;
|
|
long val_1;
|
|
}
|
|
|
|
extern(C++) size_t getoffset13161();
|
|
|
|
extern(C++) class C13161a
|
|
{
|
|
void dummyfunc();
|
|
c_long_double val_5;
|
|
uint val_9;
|
|
}
|
|
|
|
extern(C++) class Testa : C13161a
|
|
{
|
|
bool val_0;
|
|
}
|
|
|
|
extern(C++) size_t getoffset13161a();
|
|
|
|
void test13161()
|
|
{
|
|
assert(getoffset13161() == Test.val_0.offsetof);
|
|
assert(getoffset13161a() == Testa.val_0.offsetof);
|
|
}
|
|
|
|
/****************************************/
|
|
|
|
extern (C++, std)
|
|
{
|
|
extern (C++, class) struct allocator(T)
|
|
{
|
|
}
|
|
|
|
class vector(T, A = allocator!T)
|
|
{
|
|
final void push_back(ref const T);
|
|
}
|
|
|
|
struct char_traits(T)
|
|
{
|
|
}
|
|
|
|
version (CppRuntime_GNU)
|
|
{
|
|
// https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html
|
|
static if (__traits(getTargetInfo, "cppStd") >= 201103)
|
|
{
|
|
extern (C++, __cxx11)
|
|
{
|
|
struct basic_string(T, C = char_traits!T, A = allocator!T)
|
|
{
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
extern (C++, class) struct basic_string(T, C = char_traits!T, A = allocator!T)
|
|
{
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
extern (C++, class) struct basic_string(T, C = char_traits!T, A = allocator!T)
|
|
{
|
|
}
|
|
}
|
|
|
|
struct basic_istream(T, C = char_traits!T)
|
|
{
|
|
}
|
|
|
|
struct basic_ostream(T, C = char_traits!T)
|
|
{
|
|
}
|
|
|
|
struct basic_iostream(T, C = char_traits!T)
|
|
{
|
|
}
|
|
|
|
class exception { }
|
|
|
|
// https://issues.dlang.org/show_bug.cgi?id=14956
|
|
extern(C++, N14956)
|
|
{
|
|
struct S14956 { }
|
|
}
|
|
}
|
|
|
|
extern (C++)
|
|
{
|
|
version (linux)
|
|
{
|
|
void foo14(std.vector!(int) p);
|
|
void foo14a(std.basic_string!(char) *p);
|
|
void foo14b(std.basic_string!(int) *p);
|
|
void foo14c(std.basic_istream!(char) *p);
|
|
void foo14d(std.basic_ostream!(char) *p);
|
|
void foo14e(std.basic_iostream!(char) *p);
|
|
|
|
void foo14f(std.char_traits!char* x, std.basic_string!char* p, std.basic_string!char* q);
|
|
}
|
|
}
|
|
|
|
void test14()
|
|
{
|
|
version (linux)
|
|
{
|
|
std.vector!int p;
|
|
foo14(p);
|
|
|
|
foo14a(null);
|
|
foo14b(null);
|
|
foo14c(null);
|
|
foo14d(null);
|
|
foo14e(null);
|
|
foo14f(null, null, null);
|
|
}
|
|
}
|
|
|
|
version (linux)
|
|
{
|
|
void gun(std.vector!int pa)
|
|
{
|
|
int x = 42;
|
|
pa.push_back(x);
|
|
}
|
|
}
|
|
|
|
void test13289()
|
|
{
|
|
assert(f13289_cpp_wchar_t('a') == 'A');
|
|
assert(f13289_cpp_wchar_t('B') == 'B');
|
|
assert(f13289_d_wchar('c') == 'C');
|
|
assert(f13289_d_wchar('D') == 'D');
|
|
assert(f13289_d_dchar('e') == 'E');
|
|
assert(f13289_d_dchar('F') == 'F');
|
|
assert(f13289_cpp_test());
|
|
}
|
|
|
|
version(Posix)
|
|
{
|
|
enum __c_wchar_t : dchar;
|
|
}
|
|
else version(Windows)
|
|
{
|
|
enum __c_wchar_t : wchar;
|
|
}
|
|
alias wchar_t = __c_wchar_t;
|
|
extern(C++)
|
|
{
|
|
bool f13289_cpp_test();
|
|
|
|
|
|
wchar_t f13289_cpp_wchar_t(wchar_t);
|
|
|
|
|
|
wchar f13289_d_wchar(wchar ch)
|
|
{
|
|
if (ch <= 'z' && ch >= 'a')
|
|
{
|
|
return cast(wchar)(ch - ('a' - 'A'));
|
|
}
|
|
else
|
|
{
|
|
return ch;
|
|
}
|
|
}
|
|
dchar f13289_d_dchar(dchar ch)
|
|
{
|
|
if (ch <= 'z' && ch >= 'a')
|
|
{
|
|
return ch - ('a' - 'A');
|
|
}
|
|
else
|
|
{
|
|
return ch;
|
|
}
|
|
}
|
|
wchar_t f13289_d_wchar_t(wchar_t ch)
|
|
{
|
|
if (ch <= 'z' && ch >= 'a')
|
|
{
|
|
return cast(wchar_t)(ch - ('a' - 'A'));
|
|
}
|
|
else
|
|
{
|
|
return ch;
|
|
}
|
|
}
|
|
}
|
|
|
|
/****************************************/
|
|
|
|
version (CRuntime_Microsoft)
|
|
{
|
|
enum __c_long_double : double;
|
|
alias __c_long_double myld;
|
|
}
|
|
else
|
|
alias c_long_double myld;
|
|
|
|
extern (C++) myld testld(myld);
|
|
extern (C++) myld testldld(myld, myld);
|
|
|
|
|
|
void test15()
|
|
{
|
|
myld ld = 5.0;
|
|
ld = testld(ld);
|
|
assert(ld == 6.0);
|
|
|
|
myld ld2 = 5.0;
|
|
ld2 = testldld(ld2, ld2);
|
|
assert(ld2 == 6.0);
|
|
}
|
|
|
|
/****************************************/
|
|
|
|
version( Windows )
|
|
{
|
|
alias int x_long;
|
|
alias uint x_ulong;
|
|
}
|
|
else
|
|
{
|
|
static if( (void*).sizeof > int.sizeof )
|
|
{
|
|
alias long x_long;
|
|
alias ulong x_ulong;
|
|
}
|
|
else
|
|
{
|
|
alias int x_long;
|
|
alias uint x_ulong;
|
|
}
|
|
}
|
|
|
|
enum __c_long : x_long;
|
|
enum __c_ulong : x_ulong;
|
|
alias __c_long mylong;
|
|
alias __c_ulong myulong;
|
|
|
|
extern (C++) mylong testl(mylong);
|
|
extern (C++) myulong testul(myulong);
|
|
|
|
|
|
void test16()
|
|
{
|
|
{
|
|
mylong ld = 5;
|
|
ld = testl(ld);
|
|
printf("ld = %lld, mylong.sizeof = %lld\n", cast(long)ld, cast(long)mylong.sizeof);
|
|
assert(ld == 5 + mylong.sizeof);
|
|
}
|
|
{
|
|
myulong ld = 5;
|
|
ld = testul(ld);
|
|
assert(ld == 5 + myulong.sizeof);
|
|
}
|
|
|
|
static if (__c_long.sizeof == long.sizeof)
|
|
{
|
|
static assert(__c_long.max == long.max);
|
|
static assert(__c_long.min == long.min);
|
|
static assert(__c_long.init == long.init);
|
|
|
|
static assert(__c_ulong.max == ulong.max);
|
|
static assert(__c_ulong.min == ulong.min);
|
|
static assert(__c_ulong.init == ulong.init);
|
|
|
|
__c_long cl = 0;
|
|
cl = cl + 1;
|
|
long l = cl;
|
|
cl = l;
|
|
|
|
__c_ulong cul = 0;
|
|
cul = cul + 1;
|
|
ulong ul = cul;
|
|
cul = ul;
|
|
}
|
|
else static if (__c_long.sizeof == int.sizeof)
|
|
{
|
|
static assert(__c_long.max == int.max);
|
|
static assert(__c_long.min == int.min);
|
|
static assert(__c_long.init == int.init);
|
|
|
|
static assert(__c_ulong.max == uint.max);
|
|
static assert(__c_ulong.min == uint.min);
|
|
static assert(__c_ulong.init == uint.init);
|
|
|
|
__c_long cl = 0;
|
|
cl = cl + 1;
|
|
int i = cl;
|
|
cl = i;
|
|
|
|
__c_ulong cul = 0;
|
|
cul = cul + 1;
|
|
uint u = cul;
|
|
cul = u;
|
|
}
|
|
else
|
|
static assert(0);
|
|
}
|
|
|
|
/****************************************/
|
|
|
|
struct S13707
|
|
{
|
|
void* a;
|
|
void* b;
|
|
this(void* a, void* b)
|
|
{
|
|
this.a = a;
|
|
this.b = b;
|
|
}
|
|
}
|
|
|
|
extern(C++) S13707 func13707();
|
|
|
|
void test13707()
|
|
{
|
|
auto p = func13707();
|
|
assert(p.a == null);
|
|
assert(p.b == null);
|
|
}
|
|
|
|
/****************************************/
|
|
|
|
struct S13932(int x)
|
|
{
|
|
int member;
|
|
}
|
|
|
|
extern(C++) void func13932(S13932!(-1) s);
|
|
|
|
/****************************************/
|
|
|
|
extern(C++, N13337.M13337)
|
|
{
|
|
struct S13337{}
|
|
void foo13337(S13337 s);
|
|
}
|
|
|
|
/****************************************/
|
|
// https://issues.dlang.org/show_bug.cgi?id=14195
|
|
|
|
struct Delegate1(T) {}
|
|
struct Delegate2(T1, T2) {}
|
|
|
|
template Signature(T)
|
|
{
|
|
alias Signature = typeof(*(T.init));
|
|
}
|
|
|
|
extern(C++)
|
|
{
|
|
alias del1_t = Delegate1!(Signature!(void function()));
|
|
alias del2_t = Delegate2!(Signature!(int function(float, double)), Signature!(int function(float, double)));
|
|
void test14195a(del1_t);
|
|
void test14195b(del2_t);
|
|
}
|
|
|
|
void test14195()
|
|
{
|
|
test14195a(del1_t());
|
|
test14195b(del2_t());
|
|
}
|
|
|
|
|
|
/****************************************/
|
|
// https://issues.dlang.org/show_bug.cgi?id=14200
|
|
|
|
template Tuple14200(T...)
|
|
{
|
|
alias Tuple14200 = T;
|
|
}
|
|
|
|
extern(C++) void test14200a(Tuple14200!(int));
|
|
extern(C++) void test14200b(float, Tuple14200!(int, double));
|
|
|
|
void test14200()
|
|
{
|
|
test14200a(1);
|
|
test14200b(1.0f, 1, 1.0);
|
|
}
|
|
|
|
/****************************************/
|
|
// https://issues.dlang.org/show_bug.cgi?id=14956
|
|
|
|
extern(C++) void test14956(S14956 s);
|
|
|
|
/****************************************/
|
|
// check order of overloads in vtable
|
|
|
|
extern (C++) class Statement {}
|
|
extern (C++) class ErrorStatement {}
|
|
extern (C++) class PeelStatement {}
|
|
extern (C++) class ExpStatement {}
|
|
extern (C++) class DtorExpStatement {}
|
|
|
|
extern (C++) class Visitor
|
|
{
|
|
public:
|
|
int visit(Statement) { return 1; }
|
|
int visit(ErrorStatement) { return 2; }
|
|
int visit(PeelStatement) { return 3; }
|
|
}
|
|
|
|
extern (C++) class Visitor2 : Visitor
|
|
{
|
|
int visit2(ExpStatement) { return 4; }
|
|
int visit2(DtorExpStatement) { return 5; }
|
|
}
|
|
|
|
extern(C++) bool testVtableCpp(Visitor2 sv);
|
|
extern(C++) Visitor2 getVisitor2();
|
|
|
|
bool testVtableD(Visitor2 sv)
|
|
{
|
|
Statement s1;
|
|
ErrorStatement s2;
|
|
PeelStatement s3;
|
|
ExpStatement s4;
|
|
DtorExpStatement s5;
|
|
|
|
if (sv.visit(s1) != 1) return false;
|
|
if (sv.visit(s2) != 2) return false;
|
|
if (sv.visit(s3) != 3) return false;
|
|
if (sv.visit2(s4) != 4) return false;
|
|
if (sv.visit2(s5) != 5) return false;
|
|
return true;
|
|
}
|
|
|
|
void testVtable()
|
|
{
|
|
Visitor2 dinst = new Visitor2;
|
|
if (!testVtableCpp(dinst))
|
|
assert(0);
|
|
|
|
Visitor2 cppinst = getVisitor2();
|
|
if (!testVtableD(cppinst))
|
|
assert(0);
|
|
}
|
|
|
|
/****************************************/
|
|
/* problems detected by fuzzer */
|
|
extern(C++) void fuzz1_cppvararg(int64_t arg10, int64_t arg11, bool arg12);
|
|
extern(C++) void fuzz1_dvararg(int64_t arg10, int64_t arg11, bool arg12)
|
|
{
|
|
fuzz1_checkValues(arg10, arg11, arg12);
|
|
}
|
|
|
|
extern(C++) void fuzz1_checkValues(int64_t arg10, int64_t arg11, bool arg12)
|
|
{
|
|
assert(arg10 == 103);
|
|
assert(arg11 == 104);
|
|
assert(arg12 == false);
|
|
}
|
|
|
|
void fuzz1()
|
|
{
|
|
long arg10 = 103;
|
|
long arg11 = 104;
|
|
bool arg12 = false;
|
|
fuzz1_dvararg(arg10, arg11, arg12);
|
|
fuzz1_cppvararg(arg10, arg11, arg12);
|
|
}
|
|
|
|
////////
|
|
extern(C++) void fuzz2_cppvararg(uint64_t arg10, uint64_t arg11, bool arg12);
|
|
extern(C++) void fuzz2_dvararg(uint64_t arg10, uint64_t arg11, bool arg12)
|
|
{
|
|
fuzz2_checkValues(arg10, arg11, arg12);
|
|
}
|
|
|
|
extern(C++) void fuzz2_checkValues(uint64_t arg10, uint64_t arg11, bool arg12)
|
|
{
|
|
assert(arg10 == 103);
|
|
assert(arg11 == 104);
|
|
assert(arg12 == false);
|
|
}
|
|
|
|
void fuzz2()
|
|
{
|
|
ulong arg10 = 103;
|
|
ulong arg11 = 104;
|
|
bool arg12 = false;
|
|
fuzz2_dvararg(arg10, arg11, arg12);
|
|
fuzz2_cppvararg(arg10, arg11, arg12);
|
|
}
|
|
|
|
////////
|
|
version(CppRuntime_Microsoft)
|
|
enum UNICODE = false; //VS2013 doesn't support them
|
|
else
|
|
enum UNICODE = true;
|
|
|
|
static if (UNICODE)
|
|
{
|
|
extern(C++) void fuzz3_cppvararg(wchar arg10, dchar arg11, bool arg12);
|
|
extern(C++) void fuzz3_dvararg(wchar arg10, dchar arg11, bool arg12)
|
|
{
|
|
fuzz2_checkValues(arg10, arg11, arg12);
|
|
}
|
|
|
|
extern(C++) void fuzz3_checkValues(wchar arg10, dchar arg11, bool arg12)
|
|
{
|
|
assert(arg10 == 103);
|
|
assert(arg11 == 104);
|
|
assert(arg12 == false);
|
|
}
|
|
|
|
void fuzz3()
|
|
{
|
|
wchar arg10 = 103;
|
|
dchar arg11 = 104;
|
|
bool arg12 = false;
|
|
fuzz3_dvararg(arg10, arg11, arg12);
|
|
fuzz3_cppvararg(arg10, arg11, arg12);
|
|
}
|
|
}
|
|
|
|
void fuzz()
|
|
{
|
|
fuzz1();
|
|
fuzz2();
|
|
static if (UNICODE) fuzz3();
|
|
}
|
|
|
|
/****************************************/
|
|
|
|
extern (C++)
|
|
{
|
|
void throwit();
|
|
}
|
|
|
|
void testeh()
|
|
{
|
|
printf("testeh()\n");
|
|
version (linux)
|
|
{
|
|
version (X86_64)
|
|
{
|
|
bool caught;
|
|
try
|
|
{
|
|
throwit();
|
|
}
|
|
catch (std.exception e)
|
|
{
|
|
caught = true;
|
|
}
|
|
assert(caught);
|
|
}
|
|
}
|
|
}
|
|
|
|
/****************************************/
|
|
|
|
version (linux)
|
|
{
|
|
version (X86_64)
|
|
{
|
|
bool raii_works = false;
|
|
struct RAIITest
|
|
{
|
|
~this()
|
|
{
|
|
raii_works = true;
|
|
}
|
|
}
|
|
|
|
void dFunction()
|
|
{
|
|
RAIITest rt;
|
|
throwit();
|
|
}
|
|
|
|
void testeh2()
|
|
{
|
|
printf("testeh2()\n");
|
|
try
|
|
{
|
|
dFunction();
|
|
}
|
|
catch(std.exception e)
|
|
{
|
|
assert(raii_works);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
void testeh2() { }
|
|
}
|
|
else
|
|
void testeh2() { }
|
|
|
|
/****************************************/
|
|
|
|
extern (C++) { void throwle(); void throwpe(); }
|
|
|
|
void testeh3()
|
|
{
|
|
printf("testeh3()\n");
|
|
version (linux)
|
|
{
|
|
version (X86_64)
|
|
{
|
|
bool caught = false;
|
|
try
|
|
{
|
|
throwle();
|
|
}
|
|
catch (std.exception e) //polymorphism test.
|
|
{
|
|
caught = true;
|
|
}
|
|
assert(caught);
|
|
}
|
|
}
|
|
}
|
|
|
|
/****************************************/
|
|
// https://issues.dlang.org/show_bug.cgi?id=15576
|
|
|
|
extern (C++, ns15576)
|
|
{
|
|
extern __gshared int global15576;
|
|
|
|
extern (C++, ns)
|
|
{
|
|
extern __gshared int n_global15576;
|
|
}
|
|
}
|
|
|
|
void test15576()
|
|
{
|
|
global15576 = n_global15576 = 123;
|
|
}
|
|
|
|
/****************************************/
|
|
// https://issues.dlang.org/show_bug.cgi?id=15579
|
|
|
|
version (DigitalMars)
|
|
{
|
|
version (linux)
|
|
{
|
|
// Test removed for DMD/linux-only.
|
|
// https://issues.dlang.org/show_bug.cgi?id=23660
|
|
}
|
|
else
|
|
version = TEST15579;
|
|
}
|
|
else
|
|
version = TEST15579;
|
|
|
|
version (TEST15579)
|
|
{
|
|
extern (C++)
|
|
{
|
|
class Base
|
|
{
|
|
//~this() {}
|
|
void based() { }
|
|
ubyte x = 4;
|
|
}
|
|
|
|
interface Interface
|
|
{
|
|
int MethodCPP();
|
|
int MethodD();
|
|
}
|
|
|
|
class Derived : Base, Interface
|
|
{
|
|
short y = 5;
|
|
int MethodCPP();
|
|
int MethodD() {
|
|
printf("Derived.MethodD(): this = %p, x = %d, y = %d\n", this, x, y);
|
|
Derived p = this;
|
|
//p = cast(Derived)(cast(void*)p - 16);
|
|
assert(p.x == 4 || p.x == 7);
|
|
assert(p.y == 5 || p.y == 8);
|
|
return 3;
|
|
}
|
|
int Method() { return 6; }
|
|
}
|
|
|
|
Derived cppfoo(Derived);
|
|
Interface cppfooi(Interface);
|
|
}
|
|
|
|
void test15579()
|
|
{
|
|
Derived d = new Derived();
|
|
printf("d = %p\n", d);
|
|
assert(d.x == 4);
|
|
assert(d.y == 5);
|
|
assert((cast(Interface)d).MethodCPP() == 30);
|
|
assert((cast(Interface)d).MethodD() == 3);
|
|
assert(d.MethodCPP() == 30);
|
|
assert(d.MethodD() == 3);
|
|
assert(d.Method() == 6);
|
|
|
|
d = cppfoo(d);
|
|
assert(d.x == 7);
|
|
assert(d.y == 8);
|
|
|
|
printf("d2 = %p\n", d);
|
|
|
|
/* Casting to an interface involves thunks in the vtbl[].
|
|
* g++ puts the thunks for MethodD in the same COMDAT as MethodD.
|
|
* But D doesn't, so when the linker "picks one" of the D generated MethodD
|
|
* or the g++ generated MethodD, it may wind up with a messed up thunk,
|
|
* resulting in a seg fault. The solution is to not expect objects of the same
|
|
* type to be constructed on both sides of the D/C++ divide if the same member
|
|
* function (in this case, MethodD) is also defined on both sides.
|
|
*/
|
|
version (Windows)
|
|
{
|
|
assert((cast(Interface)d).MethodD() == 3);
|
|
}
|
|
assert((cast(Interface)d).MethodCPP() == 30);
|
|
|
|
assert(d.Method() == 6);
|
|
|
|
printf("d = %p, i = %p\n", d, cast(Interface)d);
|
|
version (Windows)
|
|
{
|
|
Interface i = cppfooi(d);
|
|
printf("i2: %p\n", i);
|
|
assert(i.MethodD() == 3);
|
|
assert(i.MethodCPP() == 30);
|
|
}
|
|
printf("test15579() done\n");
|
|
}
|
|
}
|
|
|
|
/****************************************/
|
|
// https://issues.dlang.org/show_bug.cgi?id=15610
|
|
|
|
extern(C++) class Base2
|
|
{
|
|
int i;
|
|
void baser() { }
|
|
}
|
|
|
|
extern(C++) interface Interface2 { abstract void f(); }
|
|
|
|
extern(C++) class Derived2 : Base2, Interface2
|
|
{
|
|
final
|
|
override void f();
|
|
}
|
|
|
|
|
|
void test15610()
|
|
{
|
|
auto c = new Derived2();
|
|
printf("test15610(): c = %p\n", c);
|
|
c.i = 3;
|
|
c.f();
|
|
}
|
|
|
|
/******************************************/
|
|
// https://issues.dlang.org/show_bug.cgi?id=15455
|
|
|
|
struct X6
|
|
{
|
|
ushort a;
|
|
ushort b;
|
|
ubyte c;
|
|
ubyte d;
|
|
}
|
|
|
|
static assert(X6.sizeof == 6);
|
|
|
|
struct X8
|
|
{
|
|
ushort a;
|
|
X6 b;
|
|
}
|
|
|
|
static assert(X8.sizeof == 8);
|
|
|
|
void test15455a(X8 s)
|
|
{
|
|
assert(s.a == 1);
|
|
assert(s.b.a == 2);
|
|
assert(s.b.b == 3);
|
|
assert(s.b.c == 4);
|
|
assert(s.b.d == 5);
|
|
}
|
|
|
|
extern (C++) void test15455b(X8 s);
|
|
|
|
void test15455()
|
|
{
|
|
X8 s;
|
|
|
|
s.a = 1;
|
|
s.b.a = 2;
|
|
s.b.b = 3;
|
|
s.b.c = 4;
|
|
s.b.d = 5;
|
|
test15455a(s);
|
|
test15455b(s);
|
|
}
|
|
|
|
/****************************************/
|
|
// https://issues.dlang.org/show_bug.cgi?id=15372
|
|
|
|
extern(C++) int foo15372(T)(int v);
|
|
|
|
void test15372()
|
|
{
|
|
version(Windows){}
|
|
else
|
|
assert(foo15372!int(1) == 1);
|
|
}
|
|
|
|
/****************************************/
|
|
// https://issues.dlang.org/show_bug.cgi?id=15802
|
|
|
|
extern(C++) {
|
|
template Foo15802(T) {
|
|
static int boo(T v);
|
|
}
|
|
}
|
|
|
|
void test15802()
|
|
{
|
|
version(Windows){}
|
|
else
|
|
assert(Foo15802!(int).boo(1) == 1);
|
|
}
|
|
|
|
/****************************************/
|
|
// https://issues.dlang.org/show_bug.cgi?id=16536
|
|
// mangling mismatch on OSX
|
|
|
|
version(OSX) extern(C++) uint64_t pass16536(uint64_t);
|
|
|
|
void test16536()
|
|
{
|
|
version(OSX) assert(pass16536(123) == 123);
|
|
}
|
|
|
|
/****************************************/
|
|
// https://issues.dlang.org/show_bug.cgi?id=15589
|
|
// extern(C++) virtual destructors are not put in vtbl[]
|
|
|
|
extern(C++)
|
|
{
|
|
class A15589
|
|
{
|
|
extern(D) static int[] dtorSeq;
|
|
struct S
|
|
{
|
|
this(int x) { this.x = x; }
|
|
~this() { dtorSeq ~= x; }
|
|
int x;
|
|
}
|
|
int foo() { return 100; } // shift dtor to slot 1
|
|
~this() { dtorSeq ~= 10; }
|
|
S s1 = S(1);
|
|
S s2 = S(2);
|
|
}
|
|
class B15589 : A15589
|
|
{
|
|
int bar() { return 200;} // add an additional function AFTER the dtor at slot 2
|
|
~this() { dtorSeq ~= 20; }
|
|
S s3 = S(3);
|
|
}
|
|
|
|
void test15589b(A15589 p);
|
|
}
|
|
|
|
void test15589()
|
|
{
|
|
A15589 c = new B15589;
|
|
assert(A15589.dtorSeq == null);
|
|
assert(c.foo() == 100);
|
|
assert((cast(B15589)c).bar() == 200);
|
|
c.__xdtor(); // virtual dtor call
|
|
assert(A15589.dtorSeq[] == [ 20, 3, 10, 2, 1 ]); // destroyed full hierarchy!
|
|
|
|
A15589.dtorSeq = null;
|
|
test15589b(c);
|
|
assert(A15589.dtorSeq[] == [ 20, 3, 10, 2, 1 ]); // destroyed full hierarchy!
|
|
}
|
|
|
|
extern(C++)
|
|
{
|
|
class Cpp15589Base
|
|
{
|
|
public:
|
|
final ~this();
|
|
|
|
void nonVirtual();
|
|
int a;
|
|
}
|
|
|
|
class Cpp15589Derived : Cpp15589Base
|
|
{
|
|
public:
|
|
this() scope;
|
|
final ~this();
|
|
int b;
|
|
}
|
|
|
|
class Cpp15589BaseVirtual
|
|
{
|
|
public:
|
|
void beforeDtor();
|
|
|
|
this() scope;
|
|
~this();
|
|
|
|
void afterDtor();
|
|
int c = 1;
|
|
}
|
|
|
|
class Cpp15589DerivedVirtual : Cpp15589BaseVirtual
|
|
{
|
|
public:
|
|
this() scope;
|
|
~this();
|
|
|
|
override void afterDtor();
|
|
|
|
int d;
|
|
}
|
|
|
|
class Cpp15589IntroducingVirtual : Cpp15589Base
|
|
{
|
|
public:
|
|
this() scope;
|
|
void beforeIntroducedVirtual();
|
|
~this();
|
|
void afterIntroducedVirtual(int);
|
|
|
|
int e;
|
|
}
|
|
|
|
struct Cpp15589Struct
|
|
{
|
|
~this();
|
|
int s;
|
|
}
|
|
|
|
void trace15589(int ch)
|
|
{
|
|
traceBuf[traceBufPos++] = cast(char) ch;
|
|
}
|
|
}
|
|
|
|
__gshared char[32] traceBuf;
|
|
__gshared size_t traceBufPos;
|
|
|
|
// workaround for https://issues.dlang.org/show_bug.cgi?id=18986
|
|
version(OSX)
|
|
enum cppCtorReturnsThis = false;
|
|
else version(FreeBSD)
|
|
enum cppCtorReturnsThis = false;
|
|
else
|
|
enum cppCtorReturnsThis = true;
|
|
|
|
mixin template scopeAllocCpp(C)
|
|
{
|
|
static if (cppCtorReturnsThis)
|
|
scope C ptr = new C;
|
|
else
|
|
{
|
|
ubyte[__traits(classInstanceSize, C)] data;
|
|
C ptr = (){ auto p = cast(C) data.ptr; p.__ctor(); return p; }();
|
|
}
|
|
}
|
|
|
|
void test15589b()
|
|
{
|
|
traceBufPos = 0;
|
|
{
|
|
Cpp15589Struct struc = Cpp15589Struct();
|
|
mixin scopeAllocCpp!Cpp15589Derived derived;
|
|
mixin scopeAllocCpp!Cpp15589DerivedVirtual derivedVirtual;
|
|
mixin scopeAllocCpp!Cpp15589IntroducingVirtual introducingVirtual;
|
|
|
|
// `scope` instances are destroyed automatically
|
|
static if (!cppCtorReturnsThis)
|
|
{
|
|
introducingVirtual.ptr.destroy();
|
|
derivedVirtual.ptr.destroy();
|
|
derived.ptr.destroy();
|
|
}
|
|
}
|
|
printf("traceBuf15589 %.*s\n", cast(int)traceBufPos, traceBuf.ptr);
|
|
assert(traceBuf[0..traceBufPos] == "IbVvBbs");
|
|
}
|
|
|
|
/****************************************/
|
|
|
|
// https://issues.dlang.org/show_bug.cgi?id=18928
|
|
// Win64: extern(C++) bad codegen, wrong calling convention
|
|
|
|
extern(C++) struct Small18928
|
|
{
|
|
int x;
|
|
}
|
|
|
|
extern(C++) class CC18928
|
|
{
|
|
Small18928 getVirtual(); // { return S(3); }
|
|
final Small18928 getFinal(); // { return S(4); }
|
|
static Small18928 getStatic(); // { return S(5); }
|
|
}
|
|
|
|
extern(C++) CC18928 newCC18928();
|
|
|
|
void test18928()
|
|
{
|
|
auto cc = newCC18928();
|
|
Small18928 v = cc.getVirtual();
|
|
assert(v.x == 3);
|
|
Small18928 f = cc.getFinal();
|
|
assert(f.x == 4);
|
|
Small18928 s = cc.getStatic();
|
|
assert(s.x == 5);
|
|
}
|
|
|
|
/****************************************/
|
|
// https://issues.dlang.org/show_bug.cgi?id=18953
|
|
// Win32: extern(C++) struct destructor not called correctly through runtime
|
|
|
|
extern(C++)
|
|
struct S18953
|
|
{
|
|
char x;
|
|
~this() nothrow @nogc { traceBuf[traceBufPos++] = x; }
|
|
}
|
|
|
|
void test18953()
|
|
{
|
|
traceBufPos = 0;
|
|
S18953[] arr = new S18953[3];
|
|
arr[1].x = '1';
|
|
arr[2].x = '2';
|
|
arr.length = 1;
|
|
assumeSafeAppend(arr); // destroys arr[1] and arr[2]
|
|
printf("traceBuf18953 %.*s\n", cast(int)traceBufPos, traceBuf.ptr);
|
|
assert(traceBuf[0..traceBufPos] == "21");
|
|
}
|
|
|
|
/****************************************/
|
|
|
|
// https://issues.dlang.org/show_bug.cgi?id=18966
|
|
|
|
extern(C++):
|
|
class Base18966
|
|
{
|
|
this() @safe nothrow;
|
|
~this() @safe;
|
|
void vf();
|
|
int x;
|
|
}
|
|
|
|
class Derived18966 : Base18966
|
|
{
|
|
override void vf() { x = 200; }
|
|
}
|
|
|
|
class Explicit18966 : Base18966
|
|
{
|
|
this() @safe { super(); }
|
|
override void vf() { x = 250; }
|
|
}
|
|
|
|
class Implicit18966 : Base18966
|
|
{
|
|
this() nothrow {}
|
|
override void vf() { x = 300; }
|
|
}
|
|
|
|
// test vptr in full ctor chain of mixed D/C++ class hierarchies
|
|
|
|
// TODO: Make this a D class and let C++ derive from it. This works on Windows,
|
|
// but results in linker errors on Posix due to extra base ctor (`C2`
|
|
// mangling) being called by the B ctor.
|
|
class A18966 // in C++
|
|
{
|
|
char[8] calledOverloads = 0;
|
|
int i;
|
|
this();
|
|
void foo();
|
|
}
|
|
|
|
class B18966 : A18966 // in C++
|
|
{
|
|
this();
|
|
override void foo();
|
|
}
|
|
|
|
class C18966 : B18966
|
|
{
|
|
this() { foo(); }
|
|
override void foo() { calledOverloads[i++] = 'C'; }
|
|
}
|
|
|
|
class D18966 : C18966
|
|
{
|
|
this() { foo(); }
|
|
override void foo() { calledOverloads[i++] = 'D'; }
|
|
}
|
|
|
|
void test18966()
|
|
{
|
|
Derived18966 d = new Derived18966;
|
|
assert(d.x == 10);
|
|
d.vf();
|
|
assert(d.x == 200);
|
|
|
|
Explicit18966 e = new Explicit18966;
|
|
assert(e.x == 10);
|
|
e.vf();
|
|
assert(e.x == 250);
|
|
|
|
Implicit18966 i = new Implicit18966;
|
|
assert(i.x == 10);
|
|
i.vf();
|
|
assert(i.x == 300);
|
|
|
|
// TODO: Allocating + constructing a C++ class with the D GC is not
|
|
// supported on Posix. The returned pointer (probably from C++ ctor)
|
|
// seems to be an offset and not the actual object address.
|
|
version (Windows)
|
|
{
|
|
auto a = new A18966;
|
|
assert(a.calledOverloads[0..2] == "A\0");
|
|
|
|
auto b = new B18966;
|
|
assert(b.calledOverloads[0..3] == "AB\0");
|
|
}
|
|
|
|
auto c = new C18966;
|
|
assert(c.calledOverloads[0..4] == "ABC\0");
|
|
|
|
auto d2 = new D18966;
|
|
// note: the vptr semantics in ctors of extern(C++) classes may be revised (to "ABCD")
|
|
assert(d2.calledOverloads[0..5] == "ABDD\0");
|
|
}
|
|
|
|
/****************************************/
|
|
|
|
// https://issues.dlang.org/show_bug.cgi?id=19134
|
|
|
|
class Base19134
|
|
{
|
|
int a = 123;
|
|
this() { a += 42; }
|
|
int foo() const { return a; }
|
|
}
|
|
|
|
class Derived19134 : Base19134
|
|
{
|
|
int b = 666;
|
|
this()
|
|
{
|
|
a *= 2;
|
|
b -= 6;
|
|
}
|
|
override int foo() const { return b; }
|
|
}
|
|
|
|
void test19134()
|
|
{
|
|
static const d = new Derived19134;
|
|
assert(d.a == (123 + 42) * 2);
|
|
assert(d.b == 666 - 6);
|
|
assert(d.foo() == 660);
|
|
}
|
|
|
|
// https://issues.dlang.org/show_bug.cgi?id=18955
|
|
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 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();
|
|
test2();
|
|
test3();
|
|
test4();
|
|
test13956();
|
|
test5();
|
|
test6();
|
|
test10071();
|
|
test7();
|
|
test8();
|
|
test11802();
|
|
test9();
|
|
test10();
|
|
test13955();
|
|
test11();
|
|
testvalist();
|
|
test12825();
|
|
test13161();
|
|
test14();
|
|
test13289();
|
|
test15();
|
|
test16();
|
|
func13707();
|
|
func13932(S13932!(-1)(0));
|
|
foo13337(S13337());
|
|
test14195();
|
|
test14200();
|
|
test14956(S14956());
|
|
testVtable();
|
|
fuzz();
|
|
testeh();
|
|
testeh2();
|
|
testeh3();
|
|
test15576();
|
|
version (TEST15579) test15579();
|
|
test15610();
|
|
test15455();
|
|
test15372();
|
|
test15802();
|
|
test16536();
|
|
test15589();
|
|
test15589b();
|
|
test18928();
|
|
test18953();
|
|
test18966();
|
|
test19134();
|
|
test18955();
|
|
testPreviewIn();
|
|
|
|
printf("Success\n");
|
|
}
|