Mercurial > pub > dyncall > dyncall
comparison test/plain_c++/test_main.cc @ 611:d94b053311a7
test/plain_c++:
- refactored to share code
- extended to treat default this calls and explicitly as cdecl declared ones, separately
- prev point fixes implicitly on x86 a wrong dcMode setting (assumed that cdecl for methods would default to the native this call convention, but actually does not, applies cdecl verbatim)
- extended aggr tests to also test explicit cdecl as well as MS thiscalls on x86
- simplified
author | Tassilo Philipp |
---|---|
date | Thu, 29 Sep 2022 11:47:54 +0200 |
parents | b26a2a4e1daa |
children | 086362f4ae3f |
comparison
equal
deleted
inserted
replaced
610:fea865cd1305 | 611:d94b053311a7 |
---|---|
41 | 41 |
42 void segv_handler(int sig) | 42 void segv_handler(int sig) |
43 { | 43 { |
44 longjmp(jbuf, 1); | 44 longjmp(jbuf, 1); |
45 } | 45 } |
46 | |
47 | |
48 /* ------------------------------------------------------------------------- | |
49 * test: identity function calls | |
50 * ------------------------------------------------------------------------- */ | |
51 | |
52 #define DEF_FUNCS(API,NAME) \ | |
53 void API fun_##NAME##_v() { } \ | |
54 DCbool API fun_##NAME##_b(DCbool x) { return x; } \ | |
55 DCint API fun_##NAME##_i(DCint x) { return x; } \ | |
56 DClong API fun_##NAME##_j(DClong x) { return x; } \ | |
57 DClonglong API fun_##NAME##_l(DClonglong x) { return x; } \ | |
58 DCfloat API fun_##NAME##_f(DCfloat x) { return x; } \ | |
59 DCdouble API fun_##NAME##_d(DCdouble x) { return x; } \ | |
60 DCpointer API fun_##NAME##_p(DCpointer x) { return x; } | |
61 | |
62 /* __cdecl */ | |
63 | |
64 #if !defined(DC__OS_Win32) | |
65 # define __cdecl | |
66 #endif | |
67 | 46 |
68 | 47 |
69 /* ------------------------------------------------------------------------- | 48 /* ------------------------------------------------------------------------- |
70 * test: identity this calls | 49 * test: identity this calls |
71 * ------------------------------------------------------------------------- */ | 50 * ------------------------------------------------------------------------- */ |
79 DCfloat f; | 58 DCfloat f; |
80 DCdouble d; | 59 DCdouble d; |
81 DCpointer p; | 60 DCpointer p; |
82 }; | 61 }; |
83 | 62 |
84 /* C++ class using __cdecl this call */ | |
85 | |
86 // #define VTBI_DESTRUCTOR 0 | |
87 | 63 |
88 /* | 64 /* |
89 * the layout of the VTable is non-standard and it is not clear what is the initial real first method index. | 65 * the layout of the VTable is non-standard and it is not clear what is the |
66 * initial real first method index. | |
90 * so far it turns out, *iff* dtor is defined, that: | 67 * so far it turns out, *iff* dtor is defined, that: |
91 * on msvc/x86 : 1 | 68 * on msvc/x86 : 1 |
92 * on msvc/x64 : 1 | 69 * on msvc/x64 : 1 |
93 * on gcc/x86 : 2 | 70 * on gcc/x86 : 2 |
94 * on gcc/x64 : 2 | 71 * on gcc/x64 : 2 |
117 #define VTBI_GET_DOUBLE VTBI_BASE+11 | 94 #define VTBI_GET_DOUBLE VTBI_BASE+11 |
118 #define VTBI_SET_POINTER VTBI_BASE+12 | 95 #define VTBI_SET_POINTER VTBI_BASE+12 |
119 #define VTBI_GET_POINTER VTBI_BASE+13 | 96 #define VTBI_GET_POINTER VTBI_BASE+13 |
120 #define VTBI_SUM_3_INTS VTBI_BASE+14 | 97 #define VTBI_SUM_3_INTS VTBI_BASE+14 |
121 | 98 |
122 class Value | 99 #define TEST_CLASS(NAME, CCONV) \ |
123 { | 100 class NAME \ |
124 public: | 101 { \ |
125 virtual ~Value() {} | 102 public: \ |
126 | 103 virtual ~NAME() { } \ |
127 virtual void __cdecl setBool(DCbool x) { mValue.B = x; } | 104 \ |
128 virtual DCbool __cdecl getBool() { return mValue.B; } | 105 virtual void CCONV setBool(DCbool x) { mValue.B = x; } \ |
129 virtual void __cdecl setInt(DCint x) { mValue.i = x; } | 106 virtual DCbool CCONV getBool() { return mValue.B; } \ |
130 virtual DCint __cdecl getInt() { return mValue.i; } | 107 virtual void CCONV setInt(DCint x) { mValue.i = x; } \ |
131 virtual void __cdecl setLong(DClong x) { mValue.j = x; } | 108 virtual DCint CCONV getInt() { return mValue.i; } \ |
132 virtual DClong __cdecl getLong() { return mValue.j; } | 109 virtual void CCONV setLong(DClong x) { mValue.j = x; } \ |
133 virtual void __cdecl setLongLong(DClonglong x) { mValue.l = x; } | 110 virtual DClong CCONV getLong() { return mValue.j; } \ |
134 virtual DClonglong __cdecl getLongLong() { return mValue.l; } | 111 virtual void CCONV setLongLong(DClonglong x) { mValue.l = x; } \ |
135 virtual void __cdecl setFloat(DCfloat x) { mValue.f = x; } | 112 virtual DClonglong CCONV getLongLong() { return mValue.l; } \ |
136 virtual DCfloat __cdecl getFloat() { return mValue.f; } | 113 virtual void CCONV setFloat(DCfloat x) { mValue.f = x; } \ |
137 virtual void __cdecl setDouble(DCdouble x) { mValue.d = x; } | 114 virtual DCfloat CCONV getFloat() { return mValue.f; } \ |
138 virtual DCdouble __cdecl getDouble() { return mValue.d; } | 115 virtual void CCONV setDouble(DCdouble x) { mValue.d = x; } \ |
139 virtual void __cdecl setPtr(DCpointer x) { mValue.p = x; } | 116 virtual DCdouble CCONV getDouble() { return mValue.d; } \ |
140 virtual DCpointer __cdecl getPtr() { return mValue.p; } | 117 virtual void CCONV setPtr(DCpointer x) { mValue.p = x; } \ |
141 | 118 virtual DCpointer CCONV getPtr() { return mValue.p; } \ |
142 /* ellipsis test w/ this ptr */ | 119 \ |
143 virtual int __cdecl sum3Ints(DCint x, ...) { va_list va; va_start(va,x); x += va_arg(va,int); x += va_arg(va,int); va_end(va); return x; } | 120 /* ellipsis test w/ this ptr */ \ |
144 | 121 virtual int CCONV sum3Ints(DCint x, ...) { va_list va; va_start(va,x); x += va_arg(va,int); x += va_arg(va,int); va_end(va); return x; } \ |
145 private: | 122 \ |
146 ValueUnion mValue; | 123 private: \ |
124 ValueUnion mValue; \ | |
147 }; | 125 }; |
126 | |
127 TEST_CLASS(ValueThisDef, /*empty/default*/) /* default */ | |
128 #if defined(DC__Arch_Intel_x86) | |
129 TEST_CLASS(ValueThisCdecl, __cdecl) /* methods explicitly declared as cdecl */ | |
130 #if defined(DC__OS_Win32) && defined(DC__C_MSVC) | |
131 TEST_CLASS(ValueThisMS, /*empty/default*/) /* microsoft this call */ | |
132 #endif | |
133 #endif | |
134 | |
135 | |
136 | |
148 | 137 |
149 template<typename T> | 138 template<typename T> |
150 bool testCallValue(DCCallVM* pc, const char* name) | 139 bool testCallValue(DCCallVM* pc, const char* name) |
151 { | 140 { |
152 bool r = true, b; | 141 bool r = true, b; |
266 | 255 |
267 return r; | 256 return r; |
268 } | 257 } |
269 | 258 |
270 | 259 |
271 #if defined(DC__OS_Win32) && defined(DC__C_MSVC) | 260 template<class T> |
272 | 261 static bool testCallThis(DCint mode, const char* str) |
273 /* C++ class using (on win32: microsoft) this call */ | |
274 | |
275 class ValueMS | |
276 { | |
277 public: | |
278 virtual ~ValueMS() {} | |
279 | |
280 virtual void setBool(DCbool x) { mValue.B = x; } | |
281 virtual DCbool getBool() { return mValue.B; } | |
282 virtual void setInt(DCint x) { mValue.i = x; } | |
283 virtual DCint getInt() { return mValue.i; } | |
284 virtual void setLong(DClong x) { mValue.j = x; } | |
285 virtual DClong getLong() { return mValue.j; } | |
286 virtual void setLongLong(DClonglong x) { mValue.l = x; } | |
287 virtual DClonglong getLongLong() { return mValue.l; } | |
288 virtual void setFloat(DCfloat x) { mValue.f = x; } | |
289 virtual DCfloat getFloat() { return mValue.f; } | |
290 virtual void setDouble(DCdouble x) { mValue.d = x; } | |
291 virtual DCdouble getDouble() { return mValue.d; } | |
292 virtual void setPtr(DCpointer x) { mValue.p = x; } | |
293 virtual DCpointer getPtr() { return mValue.p; } | |
294 private: | |
295 ValueUnion mValue; | |
296 }; | |
297 | |
298 static bool testCallThisMS() | |
299 { | 262 { |
300 bool r = false; | 263 bool r = false; |
301 DCCallVM* pc = dcNewCallVM(4096); | 264 DCCallVM* pc = dcNewCallVM(4096); |
302 dcMode(pc, DC_CALL_C_X86_WIN32_THIS_MS); | 265 dcMode(pc, mode); |
303 dcReset(pc); | 266 dcReset(pc); |
304 if(setjmp(jbuf) != 0) | 267 if(setjmp(jbuf) != 0) |
305 printf("sigsegv\n"), r=false; | 268 printf("sigsegv\n"), r=false; |
306 else | 269 else |
307 r = testCallValue<ValueMS>(pc, "MS"); | 270 r = testCallValue<T>(pc, str); |
308 dcFree(pc); | 271 dcFree(pc); |
309 return r; | 272 return r; |
310 } | 273 } |
311 | 274 |
312 #endif | 275 |
313 | 276 #if defined(DC__Feature_AggrByVal) |
314 | 277 |
315 static bool testCallThisC() | 278 #define TEST_CLASS_AGGR(NAME, CCONV) \ |
279 class NAME \ | |
280 { \ | |
281 public: \ | |
282 struct S { int i, j, k, l, m; }; \ | |
283 \ | |
284 virtual ~NAME() { } \ | |
285 \ | |
286 virtual void CCONV setAggr(S x) { mS.i = x.i; mS.j = x.j; mS.k = x.k; mS.l = x.l; mS.m = x.m; } \ | |
287 virtual S CCONV getAggr() { return mS; } \ | |
288 \ | |
289 /* ellipsis test w/ this ptr and big (!) aggregate return */ \ | |
290 struct Big { int sum; long long dummy[50]; /*dummy to make it not fit in any regs*/ }; \ | |
291 virtual struct Big CCONV sum3RetAggr(DCint x, ...) { va_list va; va_start(va,x); struct Big r = { x + va_arg(va,int) + va_arg(va,int) }; va_end(va); return r; } \ | |
292 \ | |
293 /* non-trivial aggregate */ \ | |
294 struct NonTriv { \ | |
295 int i, j; \ | |
296 NonTriv(int a, int b) : i(a),j(b) { } \ | |
297 NonTriv(const NonTriv& rhs) { static int a=13, b=37; i = a++; j = b++; } \ | |
298 }; \ | |
299 /* by value, so on first invocation a = 13,37, b = 14,38 and retval = 13*14,37*38, no matter the contents of the instances as copy ctor is called */ \ | |
300 /* NOTE: copy of return value is subject to C++ "copy elision", so it is *not* calling the copy ctor for the return value */ \ | |
301 virtual struct NonTriv CCONV squareFields(NonTriv a, NonTriv b) { return NonTriv(a.i*b.i, a.j*b.j); } \ | |
302 \ | |
303 private: \ | |
304 struct S mS; \ | |
305 }; | |
306 | |
307 TEST_CLASS_AGGR(ValueAggrThisDef, /*empty/default*/) /* default */ | |
308 #if defined(DC__Arch_Intel_x86) | |
309 TEST_CLASS_AGGR(ValueAggrThisCdecl, __cdecl) /* methods explicitly declared as cdecl */ | |
310 #if defined(DC__OS_Win32) && defined(DC__C_MSVC) | |
311 TEST_CLASS_AGGR(ValueAggrThisMS, /*empty/default*/) /* microsoft this call */ | |
312 #endif | |
313 #endif | |
314 | |
315 | |
316 #if (__cplusplus >= 201103L) | |
317 # include <type_traits> | |
318 #endif | |
319 | |
320 /* special case w/ e.g. MS x64 C++ calling cconf: struct return ptr is passed as *2nd* arg */ | |
321 template<class T> | |
322 static bool testCallThisAggr(DCint mode, const char* str) | |
316 { | 323 { |
317 bool r = false; | 324 bool r = false; |
318 DCCallVM* pc = dcNewCallVM(4096); | 325 DCCallVM* pc = dcNewCallVM(4096); |
319 dcMode(pc, DC_CALL_C_DEFAULT_THIS); | 326 dcMode(pc, mode); |
320 dcReset(pc); | |
321 if(setjmp(jbuf) != 0) | |
322 printf("sigsegv\n"), r=false; | |
323 else | |
324 r = testCallValue<Value>(pc, "c"); | |
325 dcFree(pc); | |
326 return r; | |
327 } | |
328 | |
329 | |
330 #if defined(DC__Feature_AggrByVal) | |
331 | |
332 class ValueAggr | |
333 { | |
334 public: | |
335 struct S { int i, j, k, l, m; }; | |
336 | |
337 virtual ~ValueAggr() {} | |
338 | |
339 virtual void __cdecl setAggr(S x) { mS.i = x.i; mS.j = x.j; mS.k = x.k; mS.l = x.l; mS.m = x.m; } | |
340 virtual S __cdecl getAggr() { return mS; } | |
341 | |
342 /* ellipsis test w/ this ptr and big (!) aggregate return */ | |
343 struct Big { int sum; long long dummy[50]; /*dummy to make it not fit in any regs*/ }; | |
344 virtual struct Big __cdecl sum3RetAggr(DCint x, ...) { va_list va; va_start(va,x); struct Big r = { x + va_arg(va,int) + va_arg(va,int) }; va_end(va); return r; } | |
345 | |
346 /* non-trivial aggregate */ | |
347 struct NonTriv { | |
348 int i, j; | |
349 NonTriv(int a, int b) : i(a),j(b) { } | |
350 NonTriv(const NonTriv& rhs) { static int a=13, b=37; i = a++; j = b++; } | |
351 }; | |
352 /* by value, so on first invocation a = 13,37, b = 14,38 and retval = 13*14,37*38, no matter the contents of the instances as copy ctor is called */ | |
353 /* NOTE: copy of return value is subject to C++ "copy elision", so it is *not* calling the copy ctor for the return value */ | |
354 virtual struct NonTriv __cdecl squareFields(NonTriv a, NonTriv b) { return NonTriv(a.i*b.i, a.j*b.j); } | |
355 | |
356 private: | |
357 struct S mS; | |
358 }; | |
359 | |
360 #if (__cplusplus >= 201103L) | |
361 # include <type_traits> | |
362 #endif | |
363 | |
364 /* special case w/ e.g. MS x64 C++ calling cconf: struct return ptr is passed as *2nd* arg */ | |
365 static bool testCallThisAggr() | |
366 { | |
367 bool r = false; | |
368 DCCallVM* pc = dcNewCallVM(4096); | |
369 dcMode(pc, DC_CALL_C_DEFAULT_THIS); | |
370 | 327 |
371 if(setjmp(jbuf) != 0) | 328 if(setjmp(jbuf) != 0) |
372 printf("sigsegv\n"), r=false; | 329 printf("sigsegv\n"), r=false; |
373 else | 330 else |
374 { | 331 { |
375 ValueAggr o; | 332 T o; |
376 | 333 |
377 DCpointer* vtbl = *( (DCpointer**) &o ); /* vtbl is located at beginning of class */ | 334 DCpointer* vtbl = *( (DCpointer**) &o ); /* vtbl is located at beginning of class */ |
378 ValueAggr::S st = { 124, -12, 434, 20202, -99999 }, returned; | 335 typename T::S st = { 124, -12, 434, 20202, -99999 }, returned; |
379 | 336 |
380 #if (__cplusplus >= 201103L) | 337 #if (__cplusplus >= 201103L) |
381 bool istriv = std::is_trivial<ValueAggr::S>::value; | 338 bool istriv = std::is_trivial<typename T::S>::value; |
382 #else | 339 #else |
383 bool istriv = true; /* own deduction as no type trait */ | 340 bool istriv = true; /* own deduction as no type trait */ |
384 #endif | 341 #endif |
385 DCaggr *s = dcNewAggr(5, sizeof(ValueAggr::S)); | 342 DCaggr *s = dcNewAggr(5, sizeof(typename T::S)); |
386 dcAggrField(s, DC_SIGCHAR_INT, offsetof(ValueAggr::S, i), 1); | 343 dcAggrField(s, DC_SIGCHAR_INT, offsetof(typename T::S, i), 1); |
387 dcAggrField(s, DC_SIGCHAR_INT, offsetof(ValueAggr::S, j), 1); | 344 dcAggrField(s, DC_SIGCHAR_INT, offsetof(typename T::S, j), 1); |
388 dcAggrField(s, DC_SIGCHAR_INT, offsetof(ValueAggr::S, k), 1); | 345 dcAggrField(s, DC_SIGCHAR_INT, offsetof(typename T::S, k), 1); |
389 dcAggrField(s, DC_SIGCHAR_INT, offsetof(ValueAggr::S, l), 1); | 346 dcAggrField(s, DC_SIGCHAR_INT, offsetof(typename T::S, l), 1); |
390 dcAggrField(s, DC_SIGCHAR_INT, offsetof(ValueAggr::S, m), 1); | 347 dcAggrField(s, DC_SIGCHAR_INT, offsetof(typename T::S, m), 1); |
391 dcCloseAggr(s); | 348 dcCloseAggr(s); |
392 | 349 |
393 // set S::mS | 350 // set S::mS |
394 dcReset(pc); | 351 dcReset(pc); |
395 dcArgPointer(pc, &o); // this ptr | 352 dcArgPointer(pc, &o); // this ptr |
403 dcCallAggr(pc, vtbl[VTBI_BASE+1], s, &returned); | 360 dcCallAggr(pc, vtbl[VTBI_BASE+1], s, &returned); |
404 | 361 |
405 dcFreeAggr(s); | 362 dcFreeAggr(s); |
406 | 363 |
407 r = returned.i == st.i && returned.j == st.j && returned.k == st.k && returned.l == st.l && returned.m == st.m && istriv; | 364 r = returned.i == st.i && returned.j == st.j && returned.k == st.k && returned.l == st.l && returned.m == st.m && istriv; |
408 printf("r:{iiiii} (this/trivial): %d\n", r); | 365 printf("r:{iiiii} (%s/trivial): %d\n", str, r); |
409 | 366 |
410 | 367 |
411 | 368 |
412 /* ellipsis test w/ this pointer returning big aggregate (quite an edge | 369 /* ellipsis test w/ this pointer returning big aggregate (quite an edge |
413 * case) by value (won't fit in regs, so hidden pointer is is used to write | 370 * case) by value (won't fit in regs, so hidden pointer is is used to write |
414 * return values to), showing the need to use the DC_CALL_C_DEFAULT_THIS | 371 * return values to), showing the need to use the DC_CALL_C_DEFAULT_THIS |
415 * mode first, for the this ptr alone, then DC_CALL_C_ELLIPSIS, then | 372 * mode first, for the this ptr alone, then DC_CALL_C_ELLIPSIS, then |
416 * DC_CALL_C_ELLIPSIS_VARARGS (test is useful on win64 where thisptr is | 373 * DC_CALL_C_ELLIPSIS_VARARGS (test is useful on win64 where thisptr is |
417 * passed *after* return aggregate's hidden ptr) */ | 374 * passed *after* return aggregate's hidden ptr) */ |
418 #if (__cplusplus >= 201103L) | 375 #if (__cplusplus >= 201103L) |
419 istriv = std::is_trivial<ValueAggr::Big>::value; | 376 istriv = std::is_trivial<typename T::Big>::value; |
420 #else | 377 #else |
421 istriv = true; /* own deduction as no type trait */ | 378 istriv = true; /* own deduction as no type trait */ |
422 #endif | 379 #endif |
423 s = dcNewAggr(2, sizeof(struct ValueAggr::Big)); | 380 s = dcNewAggr(2, sizeof(struct T::Big)); |
424 dcAggrField(s, DC_SIGCHAR_INT, offsetof(struct ValueAggr::Big, sum), 1); | 381 dcAggrField(s, DC_SIGCHAR_INT, offsetof(struct T::Big, sum), 1); |
425 dcAggrField(s, DC_SIGCHAR_LONGLONG, offsetof(struct ValueAggr::Big, dummy), 50); | 382 dcAggrField(s, DC_SIGCHAR_LONGLONG, offsetof(struct T::Big, dummy), 50); |
426 dcCloseAggr(s); | 383 dcCloseAggr(s); |
427 dcReset(pc); | 384 dcReset(pc); |
428 dcMode(pc, DC_CALL_C_DEFAULT_THIS); /* <-- needed on x64/win64 */ | 385 dcMode(pc, mode); |
429 | 386 |
430 dcBeginCallAggr(pc, s); | 387 dcBeginCallAggr(pc, s); |
431 dcArgPointer(pc, &o); | 388 dcArgPointer(pc, &o); |
432 dcMode(pc, DC_CALL_C_ELLIPSIS); | 389 dcMode(pc, DC_CALL_C_ELLIPSIS); |
433 dcArgInt(pc, 89); | 390 dcArgInt(pc, 89); |
434 dcMode(pc, DC_CALL_C_ELLIPSIS_VARARGS); | 391 dcMode(pc, DC_CALL_C_ELLIPSIS_VARARGS); |
435 dcArgInt(pc, -157); | 392 dcArgInt(pc, -157); |
436 dcArgInt(pc, 888); | 393 dcArgInt(pc, 888); |
437 struct ValueAggr::Big big; | 394 struct T::Big big; |
438 dcCallAggr(pc, vtbl[VTBI_BASE+2], s, &big); | 395 dcCallAggr(pc, vtbl[VTBI_BASE+2], s, &big); |
439 | 396 |
440 dcFreeAggr(s); | 397 dcFreeAggr(s); |
441 | 398 |
442 bool b = (big.sum == 820) && istriv; | 399 bool b = (big.sum == 820) && istriv; |
443 r = r && b; | 400 r = r && b; |
444 printf("r:{il[50]} (this/trivial/ellipsis): %d\n", b); | 401 printf("r:{il[50]} (%s/trivial/ellipsis): %d\n", str, b); |
445 | 402 |
446 | 403 |
447 | 404 |
448 /* non-trivial test ----------------------------------------------------------- */ | 405 /* non-trivial test ----------------------------------------------------------- */ |
449 | 406 |
450 #if (__cplusplus >= 201103L) | 407 #if (__cplusplus >= 201103L) |
451 istriv = std::is_trivial<ValueAggr::NonTriv>::value; | 408 istriv = std::is_trivial<typename T::NonTriv>::value; |
452 #else | 409 #else |
453 istriv = false; /* own deduction as no type trait */ | 410 istriv = false; /* own deduction as no type trait */ |
454 #endif | 411 #endif |
455 dcReset(pc); | 412 dcReset(pc); |
456 dcMode(pc, DC_CALL_C_DEFAULT_THIS); | 413 dcMode(pc, mode); |
457 | 414 |
458 /* non trivial aggregates: pass NULL for DCaggr* and do copy on our own (see doc) */ | 415 /* non trivial aggregates: pass NULL for DCaggr* and do copy on our own (see doc) */ |
459 dcBeginCallAggr(pc, NULL); | 416 dcBeginCallAggr(pc, NULL); |
460 | 417 |
461 ValueAggr::NonTriv nt0(5, 6), nt1(7, 8), ntr(0, 0); | 418 typename T::NonTriv nt0(5, 6), nt1(7, 8), ntr(0, 0); |
462 dcArgAggr(pc, NULL, &o); // this ptr | 419 dcArgAggr(pc, NULL, &o); // this ptr |
463 /* make *own* copies, as dyncall cannot know how to call copy ctor */ //@@@ put into doc | 420 /* make *own* copies, as dyncall cannot know how to call copy ctor */ //@@@ put into doc |
464 ValueAggr::NonTriv nt0_ = nt0, nt1_ = nt1; | 421 typename T::NonTriv nt0_ = nt0, nt1_ = nt1; |
465 dcArgAggr(pc, NULL, &nt0_); /* use *own* copy */ | 422 dcArgAggr(pc, NULL, &nt0_); /* use *own* copy */ |
466 dcArgAggr(pc, NULL, &nt1_); /* use *own* copy */ | 423 dcArgAggr(pc, NULL, &nt1_); /* use *own* copy */ |
467 | 424 |
468 dcCallAggr(pc, vtbl[VTBI_BASE+3], NULL, &ntr); /* note: "copy elision", so retval might *not* call copy ctor */ | 425 dcCallAggr(pc, vtbl[VTBI_BASE+3], NULL, &ntr); /* note: "copy elision", so retval might *not* call copy ctor */ |
469 | 426 |
470 | 427 |
471 b = ntr.i == 13*14 && ntr.j == 37*38 && !istriv; | 428 b = ntr.i == 13*14 && ntr.j == 37*38 && !istriv; |
472 r = r && b; | 429 r = r && b; |
473 printf("r:{ii} (this/nontrivial/retval_copy_elision): %d\n", b); | 430 printf("r:{ii} (%s/nontrivial/retval_copy_elision): %d\n", str, b); |
474 } | 431 } |
475 | 432 |
476 dcFree(pc); | 433 dcFree(pc); |
477 return r; | 434 return r; |
478 } | 435 } |
488 | 445 |
489 signal(SIGSEGV, segv_handler); | 446 signal(SIGSEGV, segv_handler); |
490 | 447 |
491 bool r = true; | 448 bool r = true; |
492 | 449 |
493 r = testCallThisC() && r; | 450 r = testCallThis<ValueThisDef>(DC_CALL_C_DEFAULT_THIS, "thisDef") && r; |
451 #if defined(DC__Arch_Intel_x86) | |
452 r = testCallThis<ValueThisCdecl>(DC_CALL_C_X86_CDECL, "thisCdecl") && r; | |
494 #if defined(DC__OS_Win32) && defined(DC__C_MSVC) | 453 #if defined(DC__OS_Win32) && defined(DC__C_MSVC) |
495 r = testCallThisMS() && r; | 454 r = testCallThis<ValueThisMS>(DC_CALL_C_X86_WIN32_THIS_MS, "thisMS") && r; |
496 #endif | 455 #endif |
456 #endif | |
457 | |
497 #if defined(DC__Feature_AggrByVal) | 458 #if defined(DC__Feature_AggrByVal) |
498 r = testCallThisAggr() && r; | 459 r = testCallThisAggr<ValueAggrThisDef>(DC_CALL_C_DEFAULT_THIS, "thisDef") && r; |
460 #if defined(DC__Arch_Intel_x86) | |
461 r = testCallThisAggr<ValueAggrThisCdecl>(DC_CALL_C_X86_CDECL, "thisCdecl") && r; | |
462 #if defined(DC__OS_Win32) && defined(DC__C_MSVC) | |
463 r = testCallThisAggr<ValueAggrThisMS>(DC_CALL_C_X86_WIN32_THIS_MS, "thisMS") && r; | |
464 #endif | |
465 #endif | |
499 #endif | 466 #endif |
500 | 467 |
501 printf("result: plain_c++: %d\n", r); | 468 printf("result: plain_c++: %d\n", r); |
502 | 469 |
503 dcTest_deInitPlatform(); | 470 dcTest_deInitPlatform(); |