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();