Also update this
[mono.git] / mcs / gmcs / typemanager.cs
index 77a69076f5e972589ec79821b92945c5ced9b90a..93ebe7209ceb619ccd59adff2f82dad5b8378e61 100755 (executable)
@@ -81,10 +81,14 @@ public class TypeManager {
        static public Type void_ptr_type;
        static public Type indexer_name_type;
        static public Type exception_type;
+       static public Type activator_type;
        static public Type invalid_operation_exception_type;
        static public object obsolete_attribute_type;
        static public object conditional_attribute_type;
        static public Type in_attribute_type;
+       static public Type cls_compliant_attribute_type;
+       static public Type typed_reference_type;
+       static public Type arg_iterator_type;
 
        //
        // An empty array of types
@@ -136,7 +140,10 @@ public class TypeManager {
        static public MethodInfo string_concat_string_string;
        static public MethodInfo string_concat_string_string_string;
        static public MethodInfo string_concat_string_string_string_string;
+       static public MethodInfo string_concat_string_dot_dot_dot;
        static public MethodInfo string_concat_object_object;
+       static public MethodInfo string_concat_object_object_object;
+       static public MethodInfo string_concat_object_dot_dot_dot;
        static public MethodInfo string_isinterneted_string;
        static public MethodInfo system_type_get_type_from_handle;
        static public MethodInfo object_getcurrent_void;
@@ -158,6 +165,7 @@ public class TypeManager {
        static public MethodInfo int_array_get_lower_bound_int;
        static public MethodInfo int_array_get_upper_bound_int;
        static public MethodInfo void_array_copyto_array_int;
+       static public MethodInfo activator_create_instance;
        
        //
        // The attribute constructors.
@@ -242,6 +250,12 @@ public class TypeManager {
 
        static Hashtable builder_to_method;
 
+       // <remarks>
+       //  Contains all public types from referenced assemblies.
+       //  This member is used only if CLS Compliance verification is required.
+       // </remarks>
+       public static Hashtable all_imported_types;
+
        struct Signature {
                public string name;
                public Type [] args;
@@ -467,9 +481,14 @@ public class TypeManager {
                builder_to_attr.Add (t, tc);
        }
 
-       public static void AddTypeParameter (Type t, TypeParameter tparam)
+       public static void AddTypeParameter (Type t, TypeParameter tparam, TypeExpr[] ifaces)
        {
-               builder_to_type_param.Add (t, tparam);
+               if (!builder_to_type_param.Contains (t)) {
+                       builder_to_type_param.Add (t, tparam);
+
+                       if (ifaces != null)
+                               builder_to_ifaces [t] = ifaces;
+               }
        }
 
        /// <summary>
@@ -498,6 +517,13 @@ public class TypeManager {
                                return container;
                }
 
+               if (t is GenericTypeParameterBuilder) {
+                       IMemberContainer container = builder_to_type_param [t] as IMemberContainer;
+
+                       if (container != null)
+                               return container;
+               }
+
                return TypeHandle.GetTypeHandle (t);
        }
 
@@ -575,6 +601,12 @@ public class TypeManager {
                modules = n;
        }
 
+       public static Module[] Modules {
+               get {
+                       return modules;
+               }
+       }
+
        static Hashtable references = new Hashtable ();
        
        //
@@ -782,6 +814,23 @@ public class TypeManager {
                }
        }
 
+       /// <summary>
+       /// Fills static table with exported types from all referenced assemblies.
+       /// This information is required for CLS Compliance tests.
+       /// </summary>
+       public static void LoadAllImportedTypes ()
+       {
+               if (!CodeGen.Assembly.IsClsCompliant)
+                       return;
+
+               all_imported_types = new Hashtable ();
+               foreach (Assembly a in assemblies) {
+                       foreach (Type t in a.GetExportedTypes ()) {
+                               all_imported_types [t.FullName] = t;
+                       }
+               }
+       }
+
        public static bool NamespaceClash (string name, Location loc)
        {
                if (Namespace.LookupNamespace (name, false) == null)
@@ -796,6 +845,9 @@ public class TypeManager {
        /// </summary>
        static public string CSharpName (Type t)
        {
+               if (t.FullName == null)
+                       return t.Name;
+
                return Regex.Replace (t.FullName, 
                        @"^System\." +
                        @"(Int32|UInt32|Int16|UInt16|Int64|UInt64|" +
@@ -834,6 +886,9 @@ public class TypeManager {
 
        static public string GetFullName (Type t)
        {
+               if (t.FullName == null)
+                       return t.Name;
+
                string name = t.FullName.Replace ('+', '.');
 
                DeclSpace tc = LookupDeclSpace (t);
@@ -1058,6 +1113,8 @@ public class TypeManager {
                new_constraint_attr_type = CoreLookupType ("System.Runtime.CompilerServices.NewConstraintAttribute");
                param_array_type     = CoreLookupType ("System.ParamArrayAttribute");
                in_attribute_type    = CoreLookupType ("System.Runtime.InteropServices.InAttribute");
+               typed_reference_type = CoreLookupType ("System.TypedReference");
+               arg_iterator_type    = CoreLookupType ("System.ArgIterator");
 
                //
                // Sigh. Remove this before the release.  Wonder what versions of Mono
@@ -1072,6 +1129,7 @@ public class TypeManager {
                indexer_name_type     = CoreLookupType ("System.Runtime.CompilerServices.IndexerNameAttribute");
 
                exception_type        = CoreLookupType ("System.Exception");
+               activator_type        = CoreLookupType ("System.Activator");
                invalid_operation_exception_type = CoreLookupType ("System.InvalidOperationException");
 
                //
@@ -1079,6 +1137,7 @@ public class TypeManager {
                //
                obsolete_attribute_type = CoreLookupType ("System.ObsoleteAttribute");
                conditional_attribute_type = CoreLookupType ("System.Diagnostics.ConditionalAttribute");
+               cls_compliant_attribute_type = CoreLookupType ("System.CLSCompliantAttribute");
 
                //
                // When compiling corlib, store the "real" types here.
@@ -1184,10 +1243,19 @@ public class TypeManager {
                Type [] string_string_string_string = { string_type, string_type, string_type, string_type };
                string_concat_string_string_string_string = GetMethod (
                        string_type, "Concat", string_string_string_string);
+               Type[] params_string = { TypeManager.LookupType ("System.String[]") };
+               string_concat_string_dot_dot_dot = GetMethod (
+                       string_type, "Concat", params_string);
 
                Type [] object_object = { object_type, object_type };
                string_concat_object_object = GetMethod (
                        string_type, "Concat", object_object);
+               Type [] object_object_object = { object_type, object_type, object_type };
+               string_concat_object_object_object = GetMethod (
+                       string_type, "Concat", object_object_object);
+               Type[] params_object = { TypeManager.LookupType ("System.Object[]") };
+               string_concat_object_dot_dot_dot = GetMethod (
+                       string_type, "Concat", params_object);
 
                Type [] string_ = { string_type };
                string_isinterneted_string = GetMethod (
@@ -1291,6 +1359,10 @@ public class TypeManager {
                // Object
                object_ctor = GetConstructor (object_type, void_arg);
 
+               // Activator
+               Type [] type_arg = { type_type };
+               activator_create_instance = GetMethod (
+                       activator_type, "CreateInstance", type_arg);
        }
 
        const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
@@ -1367,9 +1439,8 @@ public class TypeManager {
        ///   our return value will already contain all inherited members and the caller don't need
        ///   to check base classes and interfaces anymore.
        /// </summary>
-       private static MemberList MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
-                                                           string name, int num_type_arguments,
-                                                           out bool used_cache)
+       private static MemberInfo [] MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
+                                                           string name, out bool used_cache)
        {
                //
                // We have to take care of arrays specially, because GetType on
@@ -1401,6 +1472,7 @@ public class TypeManager {
                        }
 
                        // If there is no MemberCache, we need to use the "normal" FindMembers.
+                       // Note, this is a VERY uncommon route!
 
                        MemberList list;
                        Timer.StartTimer (TimerType.FindMembers);
@@ -1408,7 +1480,19 @@ public class TypeManager {
                                                 FilterWithClosure_delegate, name);
                        Timer.StopTimer (TimerType.FindMembers);
                        used_cache = false;
-                       return list;
+                       return (MemberInfo []) list;
+               }
+
+               if (t is GenericTypeParameterBuilder) {
+                       TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
+
+                       MemberList list;
+                       Timer.StartTimer (TimerType.FindMembers);
+                       list = tparam.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
+                                                  FilterWithClosure_delegate, name);
+                       Timer.StopTimer (TimerType.FindMembers);
+                       used_cache = false;
+                       return (MemberInfo []) list;
                }
 
                //
@@ -1487,6 +1571,11 @@ public class TypeManager {
                return ds.IsGeneric;
        }
 
+       public static bool HasGenericArguments (Type t)
+       {
+               return GetNumberOfTypeArguments (t) > 0;
+       }
+
        public static int GetNumberOfTypeArguments (Type t)
        {
                DeclSpace tc = LookupDeclSpace (t);
@@ -1515,36 +1604,6 @@ public class TypeManager {
                } else
                        return t.GetGenericArguments ();
        }
-
-       public static bool CheckGeneric (Type t, int num_type_arguments)
-       {
-               if (num_type_arguments < 0)
-                       return true;
-
-               DeclSpace tc = LookupDeclSpace (t);
-
-               if (tc != null) {
-                       if (!tc.IsGeneric)
-                               return num_type_arguments == 0;
-
-                       if (num_type_arguments == 0)
-                               return false;
-
-                       if (num_type_arguments != tc.CountTypeParameters)
-                               return false;
-               } else {
-                       if (!t.HasGenericArguments)
-                               return num_type_arguments == 0;
-
-                       if (num_type_arguments == 0)
-                               return false;
-
-                       if (num_type_arguments != t.GetGenericArguments ().Length)
-                               return false;
-               }
-
-               return true;
-       }
        
        //
        // Whether a type is unmanaged.  This is used by the unsafe code (25.2)
@@ -1564,12 +1623,15 @@ public class TypeManager {
                        if (t is TypeBuilder){
                                TypeContainer tc = LookupTypeContainer (t);
 
+                               if (tc.Fields != null){
                                foreach (Field f in tc.Fields){
                                        if (f.FieldBuilder.IsStatic)
                                                continue;
                                        if (!IsUnmanagedType (f.FieldBuilder.FieldType))
                                                return false;
                                }
+                               } else
+                                       return true;
                        } else {
                                FieldInfo [] fields = t.GetFields ();
 
@@ -2160,6 +2222,13 @@ public class TypeManager {
 
                        iface_cache [t] = result;
                        return result;
+               } else if (t is GenericTypeParameterBuilder){
+                       TypeExpr[] type_ifaces = (TypeExpr []) builder_to_ifaces [t];
+                       if (type_ifaces == null)
+                               type_ifaces = NoTypeExprs;
+
+                       iface_cache [t] = type_ifaces;
+                       return type_ifaces;
                } else {
                        Type [] ifaces = t.GetInterfaces ();
                        if (ifaces.Length == 0)
@@ -2448,12 +2517,20 @@ public class TypeManager {
                return "Item";
        }
 
+       static MethodInfo pinned_method = null;
        public static void MakePinned (LocalBuilder builder)
        {
-               //
-               // FIXME: Flag the "LocalBuilder" type as being
-               // pinned.  Figure out API.
-               //
+               if (pinned_method == null) {
+                       pinned_method = typeof (LocalBuilder).GetMethod ("MakePinned", BindingFlags.Instance | BindingFlags.NonPublic);
+                       if (pinned_method == null) {
+                               Report.Warning (-24, new Location (-1), "Microsoft.NET does not support making pinned variables." +
+                                       "This code may cause errors on a runtime with a moving GC");
+                               
+                               return;
+                       }
+               }
+               
+               pinned_method.Invoke (builder, null);
        }
 
 
@@ -2499,7 +2576,7 @@ public class TypeManager {
        //
        // The name is assumed to be the same.
        //
-       public static ArrayList CopyNewMethods (ArrayList target_list, MemberList new_members)
+       public static ArrayList CopyNewMethods (ArrayList target_list, IList new_members)
        {
                if (target_list == null){
                        target_list = new ArrayList ();
@@ -2618,7 +2695,6 @@ public class TypeManager {
        //
        static Type     closure_invocation_type;
        static Type     closure_qualifier_type;
-       static int      closure_num_type_arguments;
 
        //
        // The assembly that defines the type is that is calling us
@@ -2644,9 +2720,6 @@ public class TypeManager {
                if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
                        return false;
 
-               if (m is Type)
-                       return TypeManager.CheckGeneric ((Type) m, closure_num_type_arguments);
-
                if (((closure_qualifier_type == null) || (closure_qualifier_type == closure_invocation_type)) &&
                    (closure_invocation_type != null) && IsEqual (m.DeclaringType, closure_invocation_type))
                        return true;
@@ -2794,15 +2867,13 @@ public class TypeManager {
        // that might return multiple matches.
        //
        public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type,
-                                                 Type queried_type, int num_type_arguments,
-                                                 MemberTypes mt, BindingFlags original_bf,
-                                                 string name)
+                                                 Type queried_type, MemberTypes mt,
+                                                 BindingFlags original_bf, string name)
        {
                Timer.StartTimer (TimerType.MemberLookup);
 
                MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type,
-                                                       queried_type, num_type_arguments,
-                                                       mt, original_bf, name);
+                                                       queried_type, mt, original_bf, name);
 
                Timer.StopTimer (TimerType.MemberLookup);
 
@@ -2810,9 +2881,8 @@ public class TypeManager {
        }
 
        static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type,
-                                              Type queried_type, int num_type_arguments,
-                                              MemberTypes mt, BindingFlags original_bf,
-                                              string name)
+                                              Type queried_type, MemberTypes mt,
+                                              BindingFlags original_bf, string name)
        {
                BindingFlags bf = original_bf;
                
@@ -2826,15 +2896,13 @@ public class TypeManager {
                closure_invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
                closure_qualifier_type = qualifier_type;
 
-               closure_num_type_arguments = num_type_arguments;
-
                //
                // If we are a nested class, we always have access to our container
                // type names
                //
                if (invocation_type != null){
                        string invocation_name = invocation_type.FullName;
-                       if (invocation_name.IndexOf ('+') != -1){
+                       if ((invocation_name != null) && (invocation_name.IndexOf ('+') != -1)){
                                string container = queried_type.FullName + "+";
                                int container_length = container.Length;
 
@@ -2847,8 +2915,14 @@ public class TypeManager {
                        }
                }
                
+               // This is from the first time we find a method
+               // in most cases, we do not actually find a method in the base class
+               // so we can just ignore it, and save the arraylist allocation
+               MemberInfo [] first_members_list = null;
+               bool use_first_members_list = false;
+               
                do {
-                       MemberList list;
+                       MemberInfo [] list;
 
                        //
                        // `NonPublic' is lame, because it includes both protected and
@@ -2871,8 +2945,8 @@ public class TypeManager {
 
                        Timer.StopTimer (TimerType.MemberLookup);
 
-                       list = MemberLookup_FindMembers (current_type, mt, bf, name,
-                                                        num_type_arguments, out used_cache);
+                       list = MemberLookup_FindMembers (
+                               current_type, mt, bf, name, out used_cache);
 
                        Timer.StartTimer (TimerType.MemberLookup);
 
@@ -2903,7 +2977,7 @@ public class TypeManager {
                                        current_type = TypeManager.object_type;
                        }
                        
-                       if (list.Count == 0)
+                       if (list.Length == 0)
                                continue;
 
                        //
@@ -2911,8 +2985,8 @@ public class TypeManager {
                        // searches, which means that our above FindMembers will
                        // return two copies of the same.
                        //
-                       if (list.Count == 1 && !(list [0] is MethodBase)){
-                               return (MemberInfo []) list;
+                       if (list.Length == 1 && !(list [0] is MethodBase)){
+                               return list;
                        }
 
                        //
@@ -2920,14 +2994,14 @@ public class TypeManager {
                        // name
                        //
                        if (list [0] is PropertyInfo)
-                               return (MemberInfo []) list;
+                               return list;
 
                        //
                        // We found an event: the cache lookup returns both the event and
                        // its private field.
                        //
                        if (list [0] is EventInfo) {
-                               if ((list.Count == 2) && (list [1] is FieldInfo))
+                               if ((list.Length == 2) && (list [1] is FieldInfo))
                                        return new MemberInfo [] { list [0] };
 
                                // Oooops
@@ -2939,10 +3013,31 @@ public class TypeManager {
                        // mode.
                        //
 
-                       method_list = CopyNewMethods (method_list, list);
-                       mt &= (MemberTypes.Method | MemberTypes.Constructor);
+                       if (first_members_list != null) {
+                               if (use_first_members_list) {
+                                       method_list = CopyNewMethods (method_list, first_members_list);
+                                       use_first_members_list = false;
+                               }
+                               
+                               method_list = CopyNewMethods (method_list, list);
+                       } else {
+                               first_members_list = list;
+                               use_first_members_list = true;
+
+                               mt &= (MemberTypes.Method | MemberTypes.Constructor);
+                       }
                } while (searching);
 
+               if (use_first_members_list) {
+                       foreach (MemberInfo mi in first_members_list) {
+                               if (! (mi is MethodBase)) {
+                                       method_list = CopyNewMethods (method_list, first_members_list);
+                                       return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
+                               }
+                       }
+                       return (MemberInfo []) first_members_list;
+               }
+
                if (method_list != null && method_list.Count > 0) {
                         return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
                 }
@@ -2970,8 +3065,7 @@ public class TypeManager {
                foreach (TypeExpr itype in ifaces){
                        MemberInfo [] x;
 
-                       x = MemberLookup (null, null, itype.Type, num_type_arguments,
-                                         mt, bf, name);
+                       x = MemberLookup (null, null, itype.Type, mt, bf, name);
                        if (x != null)
                                return x;
                }
@@ -3129,15 +3223,17 @@ public sealed class TypeHandle : IMemberContainer {
        private static TypeHandle array_type = null;
 
        private Type type;
+       private string full_name;
        private bool is_interface;
        private MemberCache member_cache;
 
        private TypeHandle (Type type)
        {
                this.type = type;
+               full_name = type.FullName != null ? type.FullName : type.Name;
                if (type.BaseType != null)
                        BaseType = GetTypeHandle (type.BaseType);
-               this.is_interface = type.IsInterface;
+               this.is_interface = type.IsInterface || type.IsGenericParameter;
                this.member_cache = new MemberCache (this);
        }
 
@@ -3145,7 +3241,7 @@ public sealed class TypeHandle : IMemberContainer {
 
        public string Name {
                get {
-                       return type.FullName;
+                       return full_name;
                }
        }
 
@@ -3170,6 +3266,8 @@ public sealed class TypeHandle : IMemberContainer {
        public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
        {
                 MemberInfo [] members;
+               if (type is GenericTypeParameterBuilder)
+                       return MemberList.Empty;
                if (mt == MemberTypes.Event)
                         members = type.GetEvents (bf | BindingFlags.DeclaredOnly);
                 else
@@ -3185,7 +3283,7 @@ public sealed class TypeHandle : IMemberContainer {
        public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
                                       MemberFilter filter, object criteria)
        {
-               return member_cache.FindMembers (mt, bf, name, filter, criteria);
+               return new MemberList (member_cache.FindMembers (mt, bf, name, filter, criteria));
        }
 
        public MemberCache MemberCache {