Multiple fixes for Windows x86 p/invoke test failures. (#3186)
[mono.git] / mono / tests / libtest.c
index aeb95e5579c4fcf95f7b8e66d657239b74efd4fc..8f1cef273f40075165310ad858c344b9fb71324f 100644 (file)
@@ -889,12 +889,12 @@ mono_test_marshal_return_delegate (SimpleDelegate delegate)
        return delegate;
 }
 
-typedef int DelegateByrefDelegate (void *);
+typedef int (STDCALL *DelegateByrefDelegate) (void *);
 
 LIBTEST_API int STDCALL
 mono_test_marshal_delegate_ref_delegate (DelegateByrefDelegate del)
 {
-       int (*ptr) (int i);
+       int (STDCALL *ptr) (int i);
 
        del (&ptr);
 
@@ -1067,7 +1067,7 @@ typedef int (STDCALL *SimpleDelegate9) (return_int_fnt d);
 LIBTEST_API int STDCALL 
 mono_test_marshal_delegate9 (SimpleDelegate9 delegate, gpointer ftn)
 {
-       return delegate ((int (*)(int))ftn);
+       return delegate ((return_int_fnt)ftn);
 }
 
 static int STDCALL 
@@ -1109,6 +1109,22 @@ mono_test_marshal_return_delegate_delegate (ReturnDelegateDelegate d)
        return (d ()) (55);
 }
 
+typedef int (STDCALL *VirtualDelegate) (int);
+
+LIBTEST_API int STDCALL
+mono_test_marshal_virtual_delegate (VirtualDelegate del)
+{
+       return del (42);
+}
+
+typedef char* (STDCALL *IcallDelegate) (const char *);
+LIBTEST_API int STDCALL
+mono_test_marshal_icall_delegate (IcallDelegate del)
+{
+       char *res = del ("ABC");
+       return strcmp (res, "ABC") == 0 ? 0 : 1;
+}
+
 LIBTEST_API int STDCALL  
 mono_test_marshal_stringbuilder (char *s, int n)
 {
@@ -1212,14 +1228,29 @@ mono_test_marshal_stringbuilder_ref (char **s)
        return 0;
 }
 
+#ifdef __GNUC__
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wc++-compat"
+#endif
+
+/*
+* Standard C and C++ doesn't allow empty structs, empty structs will always have a size of 1 byte.
+* GCC have an extension to allow empty structs, https://gcc.gnu.org/onlinedocs/gcc/Empty-Structures.html.
+* This cause a little dilemma since runtime build using none GCC compiler will not be compatible with
+* GCC build C libraries and the other way around. On platforms where empty structs has size of 1 byte
+* it must be represented in call and cannot be dropped. On Windows x64 structs will always be represented in the call
+* meaning that an empty struct must have a representation in the callee in order to correctly follow the ABI used by the
+* C/C++ standard and the runtime.
+*/
 typedef struct {
-#ifndef __GNUC__
+#if !defined(__GNUC__) || defined(TARGET_WIN32)
     char a;
 #endif
 } EmptyStruct;
+
+#ifdef __GNUC__
 #pragma GCC diagnostic pop
+#endif
 
 LIBTEST_API int STDCALL 
 mono_test_marshal_empty_string_array (char **array)
@@ -1323,6 +1354,8 @@ mono_test_return_empty_struct (int a)
 {
        EmptyStruct s;
 
+       memset (&s, 0, sizeof (s));
+
        g_assert (a == 42);
 
        return s;
@@ -3624,7 +3657,7 @@ test_method_thunk (int test_id, gpointer test_method_handle, gpointer create_obj
                goto done;
        }
 
-       CreateObject = (gpointer (*)(gpointer *))mono_method_get_unmanaged_thunk (create_object_method_handle);
+       CreateObject = (gpointer (STDCALL *)(gpointer *))mono_method_get_unmanaged_thunk (create_object_method_handle);
        if (!CreateObject) {
                ret = 3;
                goto done;