Merge pull request #4065 from akoeplinger/add-mcs-lane
authorAlexander Köplinger <alex.koeplinger@outlook.com>
Thu, 1 Dec 2016 15:53:37 +0000 (16:53 +0100)
committerGitHub <noreply@github.com>
Thu, 1 Dec 2016 15:53:37 +0000 (16:53 +0100)
[ci] Add job configuration for testing Mono with mcs as compiler

README.md
mcs/class/corlib/Microsoft.Win32/Win32RegistryApi.cs
mcs/class/corlib/Test/System.Reflection.Emit/TypeBuilderTest.cs
mono/io-layer/wapi-remap.h
mono/io-layer/wapi.c
mono/io-layer/wapi.h
mono/metadata/file-io.c
mono/metadata/reflection.c
mono/metadata/sre.c

index 99e99427cc179696fd4672d883991a62bc136b47..c530d4a18bb485b86434447498efe899b984a1c2 100644 (file)
--- a/README.md
+++ b/README.md
@@ -462,7 +462,7 @@ disable it.
   * There are a number of runtime options to control this
 also, see the man page.
 
-* `--with-csc={roslyn,mcs,default}'
+* `--with-csc=roslyn,mcs,default`
 
   * Use this option to configure which C# compiler to use.  By default
     the configure script will pick Roslyn, except on platforms where
@@ -472,8 +472,8 @@ also, see the man page.
     also allows for a complete bootstrap of Mono's core compiler and
     core libraries from source.
 
   If you specify "roslyn", then Roslyn's C# compiler will be used.
-    This uses currently uses Roslyn binaries.
   If you specify "roslyn", then Roslyn's C# compiler will be used.
+    This currently uses Roslyn binaries.
   
 * `--enable-nacl`
 
index 220967e09e4b157c1bd72f731002968cff817139..033572799dfcbd5ecb6e9fca79f3280d286edfeb 100644 (file)
@@ -92,14 +92,17 @@ namespace Microsoft.Win32
                [DllImport ("advapi32.dll", CharSet=CharSet.Unicode, EntryPoint="RegDeleteValue")]
                private static extern int RegDeleteValue (IntPtr keyHandle, string valueName);
 
-               [DllImport ("advapi32.dll", CharSet=CharSet.Unicode, EntryPoint="RegEnumKey")]
-               private static extern int RegEnumKey (IntPtr keyBase, int index, StringBuilder nameBuffer, int bufferLength);
+               [DllImport ("advapi32.dll", CharSet=CharSet.Unicode, EntryPoint="RegEnumKeyExW")]
+               internal unsafe static extern int RegEnumKeyEx (IntPtr keyHandle, int dwIndex,
+                                       char* lpName, ref int lpcbName, int[] lpReserved,
+                                       [Out]StringBuilder lpClass, int[] lpcbClass,
+                                       long[] lpftLastWriteTime);
 
                [DllImport ("advapi32.dll", CharSet=CharSet.Unicode, EntryPoint="RegEnumValue")]
-               private static extern int RegEnumValue (IntPtr keyBase, 
-                               int index, StringBuilder nameBuffer, 
-                               ref int nameLength, IntPtr reserved, 
-                               ref RegistryValueKind type, IntPtr data, IntPtr dataLength);
+               internal unsafe static extern int RegEnumValue (IntPtr hKey, int dwIndex,
+                                       char* lpValueName, ref int lpcbValueName,
+                                       IntPtr lpReserved_MustBeZero, int[] lpType, byte[] lpData,
+                                       int[] lpcbData);
 
 //             [DllImport ("advapi32.dll", CharSet=CharSet.Unicode, EntryPoint="RegSetValueEx")]
 //             private static extern int RegSetValueEx (IntPtr keyBase, 
@@ -146,6 +149,14 @@ namespace Microsoft.Win32
                                string valueName, IntPtr reserved, ref RegistryValueKind type,
                                ref long data, ref int dataSize);
 
+               [DllImport ("advapi32.dll", CharSet = CharSet.Unicode, EntryPoint="RegQueryInfoKeyW")]
+               internal static extern int RegQueryInfoKey (IntPtr hKey, [Out]StringBuilder lpClass,
+                       int[] lpcbClass, IntPtr lpReserved_MustBeZero, ref int lpcSubKeys,
+                       int[] lpcbMaxSubKeyLen, int[] lpcbMaxClassLen,
+                       ref int lpcValues, int[] lpcbMaxValueNameLen,
+                       int[] lpcbMaxValueLen, int[] lpcbSecurityDescriptor,
+                       int[] lpftLastWriteTime);
+
                // Returns our handle from the RegistryKey
                public IntPtr GetHandle (RegistryKey key)
                {
@@ -355,59 +366,54 @@ namespace Microsoft.Win32
                        return result;
                }
 
-               
-               // Arbitrary max size for key/values names that can be fetched.
-               // .NET framework SDK docs say that the max name length that can 
-               // be used is 255 characters, we'll allow for a bit more.
-               const int BufferMaxLength = 1024;
+               // MSDN defines the following limits for registry key names & values:
+               // Key Name: 255 characters
+               // Value name:  16,383 Unicode characters
+               // Value: either 1 MB or current available memory, depending on registry format.
+               private const int MaxKeyLength = 255;
+               private const int MaxValueLength = 16383;
                
                public int SubKeyCount (RegistryKey rkey)
                {
-                       int index;
-                       StringBuilder stringBuffer = new StringBuilder (BufferMaxLength);
-                       IntPtr handle = GetHandle (rkey);
-                       
-                       for (index = 0; true; index ++) {
-                               int result = RegEnumKey (handle, index, stringBuffer,
-                                       stringBuffer.Capacity);
-
-                               if (result == Win32ResultCode.Success)
-                                       continue;
-                               
-                               if (result == Win32ResultCode.NoMoreEntries)
-                                       break;
-                               
-                               // something is wrong!!
-                               GenerateException (result);
-                       }
-                       return index;
+                       int subkeys = 0;
+                       int junk = 0;
+                       int ret = RegQueryInfoKey (GetHandle (rkey),
+                                                                          null,
+                                                                          null,
+                                                                          IntPtr.Zero,
+                                                                          ref subkeys,  // subkeys
+                                                                          null,
+                                                                          null,
+                                                                          ref junk,     // values
+                                                                          null,
+                                                                          null,
+                                                                          null,
+                                                                          null);
+
+                       if (ret != Win32ResultCode.Success)
+                               GenerateException (ret);
+                       return subkeys;
                }
 
                public int ValueCount (RegistryKey rkey)
                {
-                       int index, result, bufferCapacity;
-                       RegistryValueKind type;
-                       StringBuilder buffer = new StringBuilder (BufferMaxLength);
-                       
-                       IntPtr handle = GetHandle (rkey);
-                       for (index = 0; true; index ++) {
-                               type = 0;
-                               bufferCapacity = buffer.Capacity;
-                               result = RegEnumValue (handle, index, 
-                                                      buffer, ref bufferCapacity,
-                                                      IntPtr.Zero, ref type, 
-                                                      IntPtr.Zero, IntPtr.Zero);
-
-                               if (result == Win32ResultCode.Success || result == Win32ResultCode.MoreData)
-                                       continue;
-                               
-                               if (result == Win32ResultCode.NoMoreEntries)
-                                       break;
-                               
-                               // something is wrong
-                               GenerateException (result);
-                       }
-                       return index;
+                       int values = 0;
+                       int junk = 0;
+                       int ret = RegQueryInfoKey (GetHandle (rkey),
+                                                                          null,
+                                                                          null,
+                                                                          IntPtr.Zero,
+                                                                          ref junk,     // subkeys
+                                                                          null,
+                                                                          null,
+                                                                          ref values,   // values
+                                                                          null,
+                                                                          null,
+                                                                          null,
+                                                                          null);
+                       if (ret != Win32ResultCode.Success)
+                               GenerateException (ret);
+                       return values;
                }
 
                public RegistryKey OpenRemoteBaseKey (RegistryHive hKey, string machineName)
@@ -536,57 +542,70 @@ namespace Microsoft.Win32
                                GenerateException (result);
                }
 
-               public string [] GetSubKeyNames (RegistryKey rkey)
+               public unsafe string [] GetSubKeyNames (RegistryKey rkey)
                {
-                       IntPtr handle = GetHandle (rkey);
-                       StringBuilder buffer = new StringBuilder (BufferMaxLength);
-                       var keys = new List<string> ();
-                               
-                       for (int index = 0; true; index ++) {
-                               int result = RegEnumKey (handle, index, buffer, buffer.Capacity);
-
-                               if (result == Win32ResultCode.Success) {
-                                       keys.Add (buffer.ToString ());
-                                       buffer.Length = 0;
-                                       continue;
+                       int subkeys = SubKeyCount (rkey);
+                       var names = new string [subkeys];  // Returns 0-length array if empty.
+
+                       if (subkeys > 0) {
+                               var hkey = GetHandle (rkey);
+                               char[] name = new char [MaxKeyLength + 1];
+                               int namelen;
+
+                               fixed (char* namePtr = &name [0]) {
+                                       for (int i = 0; i < subkeys; i++) {
+                                               namelen = name.Length; // Don't remove this. The API's doesn't work if this is not properly initialised.
+                                               int ret = RegEnumKeyEx (hkey,
+                                                       i,
+                                                       namePtr,
+                                                       ref namelen,
+                                                       null,
+                                                       null,
+                                                       null,
+                                                       null);
+
+                                               if (ret != 0)
+                                                       GenerateException (ret);
+                                               names [i] = new String (namePtr);
+                                       }
                                }
-
-                               if (result == Win32ResultCode.NoMoreEntries)
-                                       break;
-
-                               // should not be here!
-                               GenerateException (result);
                        }
-                       return keys.ToArray ();
-               }
 
+                       return names;
+               }
 
-               public string [] GetValueNames (RegistryKey rkey)
+               public unsafe string [] GetValueNames (RegistryKey rkey)
                {
-                       IntPtr handle = GetHandle (rkey);
-                       var values = new List<string> ();
-                       
-                       for (int index = 0; true; index ++)
-                       {
-                               StringBuilder buffer = new StringBuilder (BufferMaxLength);
-                               int bufferCapacity = buffer.Capacity;
-                               RegistryValueKind type = 0;
-                               
-                               int result = RegEnumValue (handle, index, buffer, ref bufferCapacity,
-                                                       IntPtr.Zero, ref type, IntPtr.Zero, IntPtr.Zero);
-
-                               if (result == Win32ResultCode.Success || result == Win32ResultCode.MoreData) {
-                                       values.Add (buffer.ToString ());
-                                       continue;
+                       int values = ValueCount (rkey);
+                       String[] names = new String [values];
+
+                       if (values > 0) {
+                               IntPtr hkey = GetHandle (rkey);
+                               char[] name = new char [MaxValueLength + 1];
+                               int namelen;
+
+                               fixed (char* namePtr = &name [0]) {
+                                       for (int i = 0; i < values; i++) {
+                                               namelen = name.Length;
+
+                                               int ret = RegEnumValue (hkey,
+                                                       i,
+                                                       namePtr,
+                                                       ref namelen,
+                                                       IntPtr.Zero,
+                                                       null,
+                                                       null,
+                                                       null);
+
+                                               if (ret != Win32ResultCode.Success && ret != Win32Native.ERROR_MORE_DATA)
+                                                       GenerateException (ret);
+
+                                               names [i] = new String (namePtr);
+                                       }
                                }
-                               
-                               if (result == Win32ResultCode.NoMoreEntries)
-                                       break;
-
-                               GenerateException (result);
                        }
 
-                       return values.ToArray ();
+                       return names;
                }
 
                private void CheckResult (int result)
index ac3b1f149fa3d8e587cb8cf5a691fcc62eef46a5..6d056da47a33590723a552c93aeef3711b577dd9 100644 (file)
@@ -11190,5 +11190,63 @@ namespace MonoTests.System.Reflection.Emit
 
                interface IFoo {
                }
+
+               [Test]
+               public void GenericFieldInCreatedType () {
+                       /*
+                        * Regression test for #47867.
+                        * We construct the following, but only call CreateType on R.
+                        *
+                        * public class S<T> {
+                        *   public T t;
+                        * }
+                        * public class R {
+                        *   public static S<R> sr;
+                        * }
+                        */
+                       var aname = new AssemblyName ("example1");
+                       var ab = AppDomain.CurrentDomain.DefineDynamicAssembly (aname, AssemblyBuilderAccess.Run);
+                       var mb = ab.DefineDynamicModule (aname.Name);
+                       var tbS = mb.DefineType ("S", TypeAttributes.Public);
+                       tbS.DefineGenericParameters (new String [] { "T" });
+                       var tbR = mb.DefineType ("R", TypeAttributes.Public);
+                       tbR.DefineField ("sr", tbS.MakeGenericType(new Type[] { tbR }), FieldAttributes.Public | FieldAttributes.Static);
+
+                       Type r = tbR.CreateType ();
+
+                       Assert.IsNotNull  (r);
+               }
+
+               [Test]
+               public void GenericFieldInCreatedTypeIncompleteTypeTLE () {
+                       /*
+                        * Regression test for #47867.
+                        * We construct the following, but only call CreateType on R.
+                        * Then we try to use R.sr which is expected throw a
+                        * TLE because S hasn't been created yet.
+                        *
+                        * public class S<T> {
+                        *   public T t;
+                        * }
+                        * public class R {
+                        *   public static S<R> sr;
+                        * }
+                        */
+                       var aname = new AssemblyName ("example1");
+                       var ab = AppDomain.CurrentDomain.DefineDynamicAssembly (aname, AssemblyBuilderAccess.Run);
+                       var mb = ab.DefineDynamicModule (aname.Name);
+                       var tbS = mb.DefineType ("S", TypeAttributes.Public);
+                       tbS.DefineGenericParameters (new String [] { "T" });
+                       var tbR = mb.DefineType ("R", TypeAttributes.Public);
+                       tbR.DefineField ("sr", tbS.MakeGenericType(new Type[] { tbR }), FieldAttributes.Public | FieldAttributes.Static);
+
+                       Type r = tbR.CreateType ();
+
+                       Assert.IsNotNull  (r);
+
+                       // N.B.  tbS has not had CreateType called yet, so expect this to fail.
+                       Assert.Throws<TypeLoadException> (delegate { var ft = r.GetField("sr").FieldType; });
+               }
+               
        }
 }
index c106ee767c1b00784944eb15a8b603d25fa71d97..e14881a2988eff440e43d703d10b697197ca38d7 100644 (file)
@@ -16,7 +16,6 @@
 #define SetLastError wapi_SetLastError
 #define TransmitFile wapi_TransmitFile
 #define CloseHandle wapi_CloseHandle 
-#define DuplicateHandle wapi_DuplicateHandle 
 #define CreateFile wapi_CreateFile
 #define DeleteFile wapi_DeleteFile
 #define GetStdHandle wapi_GetStdHandle
index f162b0bb45cad926593816f8e28366fcfd034dd7..fc9c00ccd909b7462b40556820b8848a2e666e5b 100644 (file)
@@ -46,16 +46,6 @@ wapi_getpid (void)
        return _wapi_pid;
 }
 
-/* Lots more to implement here, but this is all we need at the moment */
-gboolean
-DuplicateHandle (gpointer srcprocess, gpointer src, gpointer targetprocess, gpointer *target,
-       guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, guint32 options G_GNUC_UNUSED)
-{
-       mono_w32handle_ref (src);
-       *target = src;
-       return TRUE;
-}
-
 /**
  * CloseHandle:
  * @handle: The handle to release
index 1ae5cc835438cddaa63d0b0cd7e28540087bfa15..8a7ef1f77daa6a2600f919220a45bc2b0c268cb2 100644 (file)
@@ -44,10 +44,6 @@ wapi_cleanup (void);
 gboolean
 CloseHandle (gpointer handle);
 
-gboolean
-DuplicateHandle (gpointer srcprocess, gpointer src, gpointer targetprocess, gpointer *target,
-       guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, guint32 options G_GNUC_UNUSED);
-
 pid_t
 wapi_getpid (void);
 
index 0b001db668921cde759f8d3dbc434bc30aedf43f..17db2725b1d13c6171cf299b12b4bdb7f8ce9687 100644 (file)
@@ -1158,7 +1158,13 @@ ves_icall_System_IO_MonoIO_DuplicateHandle (HANDLE source_process_handle, HANDLE
        gboolean ret;
        
        MONO_ENTER_GC_SAFE;
+#ifdef HOST_WIN32
        ret=DuplicateHandle (source_process_handle, source_handle, target_process_handle, target_handle, access, inherit, options);
+#else
+       mono_w32handle_ref (source_handle);
+       *target_handle = source_handle;
+       ret = TRUE;
+#endif
        MONO_EXIT_GC_SAFE;
 
        if(ret==FALSE) {
index 28817a3311438815a1a8583fd60ae57dcc7b9452..6c856c6683f532a0d5ab4d3db5a9e9051a4b9c79 100644 (file)
@@ -501,9 +501,28 @@ mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *err
                return res;
        }
 
-       /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
-       if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
-               g_assert (0);
+       if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) {
+               /* This can happen if a TypeBuilder for a generic class K<T,U>
+                * had reflection_create_generic_class) called on it, but not
+                * ves_icall_TypeBuilder_create_runtime_class.  This can happen
+                * if the K`2 is refernced from a generic instantiation
+                * (e.g. K<int,string>) that appears as type argument
+                * (e.g. Dict<string,K<int,string>>), field (e.g. K<int,string>
+                * Foo) or method signature, parent class or any of the above
+                * in a nested class of some other TypeBuilder.  Such an
+                * occurrence caused mono_reflection_type_get_handle to be
+                * called on the sre generic instance (K<int,string>) which
+                * required the container_class for the generic class K`2 to be
+                * set up, but the remainder of class construction for K`2 has
+                * not been done. */
+               char * full_name = mono_type_get_full_name (klass);
+               /* I would have expected ReflectionTypeLoadException, but evidently .NET throws TLE in this case. */
+               mono_error_set_type_load_class (error, klass, "TypeBuilder.CreateType() not called for generic class %s", full_name);
+               g_free (full_name);
+               mono_domain_unlock (domain);
+               mono_loader_unlock ();
+               return NULL;
+       }
 
        if (mono_class_get_ref_info (klass) && !klass->wastypebuilder && !type->byref) {
                mono_domain_unlock (domain);
@@ -2245,6 +2264,8 @@ mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc
        if (mono_is_sre_type_builder (mono_object_class (type))) {
                is_dynamic = TRUE;
        } else if (mono_is_sre_generic_instance (mono_object_class (type))) {
+               /* Does this ever make sense?  what does instantiating a generic instance even mean? */
+               g_assert_not_reached ();
                MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
                MonoReflectionType *gtd = rgi->generic_type;
 
index d189c4a03172d91d46dddf26aa2586bb676e703f..041a2ba6f4859f38494cd49ea37422e4e4f3a8aa 100644 (file)
@@ -44,6 +44,8 @@ static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoR
 static gboolean ensure_runtime_vtable (MonoClass *klass, MonoError  *error);
 static void reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb);
 static gboolean reflection_setup_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error);
+static gboolean reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error);
+
 
 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
 #endif
@@ -1547,7 +1549,21 @@ mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
                                return NULL;
                        }
                }
-
+               /* Need to resolve the generic_type in order for it to create its generic context. */
+               MonoType *gtd = mono_reflection_type_get_handle (gclass->generic_type, error);
+               if (!is_ok (error)) {
+                       g_free (types);
+                       return NULL;
+               }
+               MonoClass *gtd_klass = mono_class_from_mono_type (gtd);
+               if (is_sre_type_builder (mono_object_class (gclass->generic_type))) {
+                       reflection_create_generic_class ((MonoReflectionTypeBuilder*)gclass->generic_type, error);
+                       if (!is_ok (error)) {
+                               g_free (types);
+                               return NULL;
+                       }
+               }
+               g_assert (count == 0 || mono_class_is_gtd (gtd_klass));
                res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types, error);
                g_free (types);
                g_assert (res);
@@ -2408,6 +2424,7 @@ reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error
        mono_error_init (error);
 
        reflection_setup_internal_class (tb, error);
+       return_val_if_nok (error, FALSE);
 
        klass = mono_class_from_mono_type (tb->type.type);
 
@@ -2416,6 +2433,9 @@ reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error
        if (count == 0)
                return TRUE;
 
+       if (mono_class_try_get_generic_container (klass) != NULL)
+               return TRUE; /* already setup */
+
        MonoGenericContainer *generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
 
        generic_container->owner.klass = klass;