Added file cs0230.cs
[mono.git] / mcs / mbas / typemanager.cs
index 2f7413c9e5a9fcf165b6928c2cff4f46c61ac4e7..b144bce45cf8a572bc237eee96924e8780c9b107 100644 (file)
@@ -456,8 +456,54 @@ public class TypeManager {
                modules = n;
        }
 
+       //
+       // Low-level lookup, cache-less
+       //
+       static Type LookupTypeReflection (string name)
+       {
+               Type t;
+
+               foreach (Assembly a in assemblies){
+                       t = a.GetType (name);
+                       if (t != null)
+                               return t;
+               }
+
+               foreach (ModuleBuilder mb in modules) {
+                       t = mb.GetType (name);
+                       if (t != null){
+                               return t;
+                       }
+               }
+               return null;
+       }
+
+       //
+       // This function is used when you want to avoid the lookups, and want to go
+       // directly to the source.  This will use the cache.
+       //
+       // Notice that bypassing the cache is bad, because on Microsoft.NET runtime
+       // GetType ("DynamicType[]") != GetType ("DynamicType[]"), and there is no
+       // way to test things other than doing a fullname compare
+       //
+       public static Type LookupTypeDirect (string name)
+       {
+               Type t = (Type) types [name];
+               if (t != null)
+                       return t;
+
+               t = LookupTypeReflection (name);
+               if (t == null)
+                       return null;
+
+               types [name] = t;
+               return t;
+       }
+       
        /// <summary>
-       ///   Returns the Type associated with @name
+       ///   Returns the Type associated with @name, takes care of the fact that
+       ///   reflection expects nested types to be separated from the main type
+       ///   with a "+" instead of a "."
        /// </summary>
        public static Type LookupType (string name)
        {
@@ -471,23 +517,35 @@ public class TypeManager {
                if (t != null)
                        return t;
 
-               foreach (Assembly a in assemblies){
-                       t = a.GetType (name);
-                       if (t != null){
-                               types [name] = t;
+               //
+               // Optimization: ComposedCast will work with an existing type, and might already have the
+               // full name of the type, so the full system lookup can probably be avoided.
+               //
+               
+               string [] elements = name.Split ('.');
+               int count = elements.Length;
 
-                               return t;
-                       }
-               }
+               for (int n = 1; n <= count; n++){
+                       string top_level_type = String.Join (".", elements, 0, n);
 
-               foreach (ModuleBuilder mb in modules) {
-                       t = mb.GetType (name);
-                       if (t != null) {
+                       t = (Type) types [top_level_type];
+                       if (t == null){
+                               t = LookupTypeReflection (top_level_type);
+                               if (t == null)
+                                       continue;
+                       }
+                       
+                       if (count == n){
                                types [name] = t;
                                return t;
-                       }
+                       } 
+                       
+                       string newt = top_level_type + "+" + String.Join ("+", elements, n, count - n);
+                       t = LookupTypeDirect (newt);
+                       if (t != null)
+                               types [newt] = t;
+                       return t;
                }
-               
                return null;
        }
 
@@ -1034,7 +1092,47 @@ public class TypeManager {
                else
                        return false;
        }
-       
+
+       //
+       // Whether a type is unmanaged.  This is used by the unsafe code (25.2)
+       //
+       public static bool IsUnmanagedType (Type t)
+       {
+               if (IsBuiltinType (t) && t != TypeManager.string_type)
+                       return true;
+
+               if (IsEnumType (t))
+                       return true;
+
+               if (t.IsPointer)
+                       return true;
+
+               if (IsValueType (t)){
+                       if (t is TypeBuilder){
+                               TypeContainer tc = LookupTypeContainer (t);
+
+                               foreach (Field f in tc.Fields){
+                                       if (f.FieldBuilder.IsStatic)
+                                               continue;
+                                       if (!IsUnmanagedType (f.FieldBuilder.FieldType))
+                                               return false;
+                               }
+                       } else {
+                               FieldInfo [] fields = t.GetFields ();
+
+                               foreach (FieldInfo f in fields){
+                                       if (f.IsStatic)
+                                               continue;
+                                       if (!IsUnmanagedType (f.FieldType))
+                                               return false;
+                               }
+                       }
+                       return true;
+               }
+
+               return false;
+       }
+               
        public static bool IsValueType (Type t)
        {
                if (t.IsSubclassOf (TypeManager.value_type))
@@ -1074,7 +1172,10 @@ public class TypeManager {
        //
        public static bool IsNestedChildOf (Type type, Type parent)
        {
-               return IsSubclassOrNestedChildOf (type, parent) && !type.IsSubclassOf (parent);
+               if ((type == parent) || type.IsSubclassOf (parent))
+                       return false;
+               else
+                       return IsSubclassOrNestedChildOf (type, parent);
        }
 
        /// <summary>
@@ -1315,37 +1416,6 @@ public class TypeManager {
                return true;
        }
 
-       //
-       // FIXME: we need to return the accessors depending on whether
-       // they are visible or not.
-       //
-       static public MethodInfo [] GetAccessors (PropertyInfo pi)
-       {
-               MethodInfo [] ret;
-
-               if (pi is PropertyBuilder){
-                       Pair pair = (Pair) properties [pi];
-
-                       ret = new MethodInfo [2];
-                       ret [0] = (MethodInfo) pair.First;
-                       ret [1] = (MethodInfo) pair.Second;
-
-                       return ret;
-               } else {
-                       MethodInfo [] mi = new MethodInfo [2];
-
-                       //
-                       // Why this and not pi.GetAccessors?
-                       // Because sometimes index 0 is the getter
-                       // sometimes it is 1
-                       //
-                       mi [0] = pi.GetGetMethod (true);
-                       mi [1] = pi.GetSetMethod (true);
-
-                       return mi;
-               }
-       }
-
        static public MethodInfo GetPropertyGetter (PropertyInfo pi)
        {
                if (pi is PropertyBuilder){
@@ -1902,12 +1972,6 @@ public class TypeManager {
                                if (!IsSubclassOrNestedChildOf (closure_invocation_type, mb.DeclaringType))
                                        return false;
 
-                               // Although a derived class can access protected members of its base class
-                               // it cannot do so through an instance of the base class (CS1540).
-                               if ((closure_invocation_type != closure_start_type) &&
-                                   closure_invocation_type.IsSubclassOf (closure_start_type))
-                                       return false;
-
                                return true;
                        }
 
@@ -2046,7 +2110,10 @@ public class TypeManager {
                                } else
                                        private_ok = always_ok_flag;
 
-                               if (private_ok || invocation_type.IsSubclassOf (current_type))
+                               if (invocation_type.IsSubclassOf (current_type))
+                                       private_ok = true;
+                               
+                               if (private_ok)
                                        bf = original_bf | BindingFlags.NonPublic;
                        } else {
                                private_ok = false;