2004-11-10 Martin Baulig <martin@localhost>
[mono.git] / mcs / gmcs / typemanager.cs
index 8bb5b151b955e3b927a7e800d291cf91c3125a51..7e08cc98e869e2dc961c620cfd63933cef7e337e 100755 (executable)
@@ -121,6 +121,7 @@ public class TypeManager {
        static public TypeExpr system_asynccallback_expr;
        static public TypeExpr system_iasyncresult_expr;
        static public TypeExpr system_valuetype_expr;
+       static public TypeExpr system_intptr_expr;
 
        //
        // This is only used when compiling corlib
@@ -184,6 +185,7 @@ public class TypeManager {
        static public ConstructorInfo void_decimal_ctor_five_args;
        static public ConstructorInfo unverifiable_code_ctor;
        static public ConstructorInfo invalid_operation_ctor;
+       static public ConstructorInfo default_member_ctor;
        
        // <remarks>
        //   Holds the Array of Assemblies that have been loaded
@@ -360,6 +362,7 @@ public class TypeManager {
                system_asynccallback_expr = new TypeLookupExpression ("System.AsyncCallback");
                system_iasyncresult_expr = new TypeLookupExpression ("System.IAsyncResult");
                system_valuetype_expr  = new TypeLookupExpression ("System.ValueType");
+               system_intptr_expr  = new TypeLookupExpression ("System.IntPtr");
        }
 
        static TypeManager ()
@@ -495,6 +498,14 @@ public class TypeManager {
        {
                return builder_to_declspace [t] as TypeContainer;
        }
+
+       public static TypeContainer LookupGenericTypeContainer (Type t)
+       {
+               while (t.IsGenericInstance)
+                       t = t.GetGenericTypeDefinition ();
+
+               return LookupTypeContainer (t);
+       }
        
        public static IMemberContainer LookupMemberContainer (Type t)
        {
@@ -544,19 +555,24 @@ public class TypeManager {
        }
 
        public static bool HasConstructorConstraint (Type t)
+       {
+               GenericConstraints gc = GetTypeParameterConstraints (t);
+               if (gc == null)
+                       return false;
+
+               return (gc.Attributes & GenericParameterAttributes.DefaultConstructorConstraint) != 0;
+       }
+
+       public static GenericConstraints GetTypeParameterConstraints (Type t)
        {
                if (!t.IsGenericParameter)
                        throw new InvalidOperationException ();
 
                TypeParameter tparam = LookupTypeParameter (t);
                if (tparam != null)
-                       return tparam.HasConstructorConstraint;
-               else {
-                       object[] attrs = t.GetCustomAttributes (
-                               TypeManager.new_constraint_attr_type, false);
+                       return tparam.GenericConstraints;
 
-                       return attrs.Length > 0;
-               }
+               return new ReflectionConstraints (t);
        }
        
        /// <summary>
@@ -818,9 +834,6 @@ public class TypeManager {
        /// </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 ()) {
@@ -850,7 +863,7 @@ public class TypeManager {
                        @"^System\." +
                        @"(Int32|UInt32|Int16|UInt16|Int64|UInt64|" +
                        @"Single|Double|Char|Decimal|Byte|SByte|Object|" +
-                       @"Boolean|String|Void)" +
+                       @"Boolean|String|Void|Null)" +
                        @"(\W+|\b)", 
                        new MatchEvaluator (CSharpNameMatch));
        }       
@@ -965,7 +978,7 @@ public class TypeManager {
                        iparams = new ReflectionParameters (mb);
                
                // Is property
-               if (mb.IsSpecialName && iparams.Count == 0)
+               if (mb.IsSpecialName && iparams.Count == 0 && !mb.IsConstructor)
                        return GetFullNameSignature (mb);
                
                 for (int i = 0; i < iparams.Count; i++) {
@@ -977,7 +990,7 @@ public class TypeManager {
                sig.Append (")");
 
                // Is indexer
-               if (mb.IsSpecialName && iparams.Count == 1) {
+               if (mb.IsSpecialName && iparams.Count == 1 && !mb.IsConstructor) {
                        sig.Replace ('(', '[');
                        sig.Replace (')', ']');
                }
@@ -1384,6 +1397,8 @@ public class TypeManager {
                unverifiable_code_ctor = GetConstructor (
                        unverifiable_code_type, void_arg);
 
+               default_member_ctor = GetConstructor (default_member_type, string_);
+
                //
                // InvalidOperationException
                //
@@ -1430,6 +1445,16 @@ public class TypeManager {
                if (t.IsSubclassOf (TypeManager.array_type))
                        return new MemberList (TypeManager.array_type.FindMembers (mt, bf, filter, criteria));
 
+               if (t is GenericTypeParameterBuilder) {
+                       TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
+
+                       Timer.StartTimer (TimerType.FindMembers);
+                       MemberList list = tparam.FindMembers (
+                               mt, bf | BindingFlags.DeclaredOnly, filter, criteria);
+                       Timer.StopTimer (TimerType.FindMembers);
+                       return list;
+               }
+
                //
                // Since FindMembers will not lookup both static and instance
                // members, we emulate this behaviour here.
@@ -1702,8 +1727,11 @@ public class TypeManager {
                return tc.Kind == Kind.Interface;
        }
 
-       public static bool IsEqualGenericType (Type a, Type b)
+       public static bool IsEqual (Type a, Type b)
        {
+               if (a.Equals (b))
+                       return true;
+
                if ((a is TypeBuilder) && a.IsGenericTypeDefinition && b.IsGenericInstance) {
                        //
                        // `a' is a generic type definition's TypeBuilder and `b' is a
@@ -1719,6 +1747,9 @@ public class TypeManager {
                        // The first argument of `Test' will be the generic instance
                        // "Stack<!0>" - which is the same type than the "Stack" TypeBuilder.
                        //
+                       //
+                       // We hit this via Closure.Filter() for gen-82.cs.
+                       //
                        if (a != b.GetGenericTypeDefinition ())
                                return false;
 
@@ -1729,21 +1760,46 @@ public class TypeManager {
                                return false;
 
                        for (int i = 0; i < aparams.Length; i++)
-                               if (!aparams [i].Equals (bparams [i]))
+                               if (!IsEqual (aparams [i], bparams [i]))
                                        return false;
 
                        return true;
                }
 
-               return false;
-       }
+               if (a.IsGenericParameter && b.IsGenericParameter) {
+                       if ((a.DeclaringMethod == null) || (b.DeclaringMethod == null))
+                               return false;
+                       return a.GenericParameterPosition == b.GenericParameterPosition;
+               }
+
+               if (a.IsArray && b.IsArray) {
+                       if (a.GetArrayRank () != b.GetArrayRank ())
+                               return false;
+                       return IsEqual (a.GetElementType (), b.GetElementType ());
+               }
+
+               if (a.IsGenericInstance && b.IsGenericInstance) {
+                       Type at = a.GetGenericTypeDefinition ();
+                       Type bt = b.GetGenericTypeDefinition ();
+
+                       if (a.GetGenericTypeDefinition () != b.GetGenericTypeDefinition ())
+                               return false;
+
+                       Type[] aargs = a.GetGenericArguments ();
+                       Type[] bargs = b.GetGenericArguments ();
+
+                       if (aargs.Length != bargs.Length)
+                               return false;
+
+                       for (int i = 0; i < aargs.Length; i++) {
+                               if (!IsEqual (aargs [i], bargs [i]))
+                                       return false;
+                       }
 
-       public static bool IsEqual (Type a, Type b)
-       {
-               if (a.Equals (b))
                        return true;
-               else
-                       return IsEqualGenericType (a, b);
+               }
+
+               return false;
        }
 
        public static bool MayBecomeEqualGenericTypes (Type a, Type b)
@@ -1870,6 +1926,80 @@ public class TypeManager {
 
        public static bool IsSubclassOf (Type type, Type parent)
        {
+               TypeParameter tparam = LookupTypeParameter (type);
+               TypeParameter pparam = LookupTypeParameter (parent);
+
+               if ((tparam != null) && (pparam != null)) {
+                       if (tparam == pparam)
+                               return true;
+
+                       return tparam.IsSubclassOf (parent);
+               }
+
+               do {
+                       if (type.Equals (parent))
+                               return true;
+
+                       type = type.BaseType;
+               } while (type != null);
+
+               return false;
+       }
+
+       public static bool IsPrivateAccessible (Type type, Type parent)
+       {
+               if (type.Equals (parent))
+                       return true;
+
+               if ((type is TypeBuilder) && type.IsGenericTypeDefinition && parent.IsGenericInstance) {
+                       //
+                       // `a' is a generic type definition's TypeBuilder and `b' is a
+                       // generic instance of the same type.
+                       //
+                       // Example:
+                       //
+                       // class Stack<T>
+                       // {
+                       //     void Test (Stack<T> stack) { }
+                       // }
+                       //
+                       // The first argument of `Test' will be the generic instance
+                       // "Stack<!0>" - which is the same type than the "Stack" TypeBuilder.
+                       //
+                       //
+                       // We hit this via Closure.Filter() for gen-82.cs.
+                       //
+                       if (type != parent.GetGenericTypeDefinition ())
+                               return false;
+
+                       return true;
+               }
+
+               if (type.IsGenericInstance && parent.IsGenericInstance) {
+                       Type tdef = type.GetGenericTypeDefinition ();
+                       Type pdef = parent.GetGenericTypeDefinition ();
+
+                       if (type.GetGenericTypeDefinition () != parent.GetGenericTypeDefinition ())
+                               return false;
+
+                       return true;
+               }
+
+               return false;
+       }
+
+       public static bool IsFamilyAccessible (Type type, Type parent)
+       {
+               TypeParameter tparam = LookupTypeParameter (type);
+               TypeParameter pparam = LookupTypeParameter (parent);
+
+               if ((tparam != null) && (pparam != null)) {
+                       if (tparam == pparam)
+                               return true;
+
+                       return tparam.IsSubclassOf (parent);
+               }
+
                do {
                        if (IsEqualGenericInstance (type, parent))
                                return true;
@@ -1883,10 +2013,10 @@ public class TypeManager {
        //
        // Checks whether `type' is a subclass or nested child of `parent'.
        //
-       public static bool IsSubclassOrNestedChildOf (Type type, Type parent)
+       public static bool IsNestedFamilyAccessible (Type type, Type parent)
        {
                do {
-                       if (IsSubclassOf (type, parent))
+                       if (IsFamilyAccessible (type, parent))
                                return true;
 
                        // Handle nested types.
@@ -1972,15 +2102,13 @@ public class TypeManager {
        ///   for anything which is dynamic, and we need this in a number of places,
        ///   we register this information here, and use it afterwards.
        /// </remarks>
-       static public bool RegisterMethod (MethodBase mb, InternalParameters ip, Type [] args)
+       static public void RegisterMethod (MethodBase mb, InternalParameters ip, Type [] args)
        {
                if (args == null)
                        args = NoTypes;
                                
                method_arguments.Add (mb, args);
                method_internal_params.Add (mb, ip);
-               
-               return true;
        }
        
        static public InternalParameters LookupParametersByBuilder (MethodBase mb)
@@ -2096,17 +2224,14 @@ public class TypeManager {
        
        static Hashtable events;
 
-       static public bool RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove)
+       static public void RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove)
        {
                if (events == null)
                        events = new Hashtable ();
 
-               if (events.Contains (eb))
-                       return false;
-
+               if (!events.Contains (eb)) {
                events.Add (eb, new Pair (add, remove));
-
-               return true;
+               }
        }
 
        static public MethodInfo GetAddMethod (EventInfo ei)
@@ -2115,8 +2240,8 @@ public class TypeManager {
                        Pair pair = (Pair) events [ei];
 
                        return (MethodInfo) pair.First;
-               } else
-                       return ei.GetAddMethod ();
+               }
+               return ei.GetAddMethod (true);
        }
 
        static public MethodInfo GetRemoveMethod (EventInfo ei)
@@ -2125,8 +2250,8 @@ public class TypeManager {
                        Pair pair = (Pair) events [ei];
 
                        return (MethodInfo) pair.Second;
-               } else
-                       return ei.GetRemoveMethod ();
+               }
+               return ei.GetRemoveMethod (true);
        }
 
        static Hashtable priv_fields_events;
@@ -2566,7 +2691,7 @@ public class TypeManager {
        /// </summary>
        /// <remarks>
        ///   The default is not always `Item'.  The user can change this behaviour by
-       ///   using the DefaultMemberAttribute in the class.
+       ///   using the IndexerNameAttribute in the container.
        ///
        ///   For example, the String class indexer is named `Chars' not `Item' 
        /// </remarks>
@@ -2576,21 +2701,8 @@ public class TypeManager {
                        t = t.GetGenericTypeDefinition ();
 
                if (t is TypeBuilder) {
-                       if (t.IsInterface) {
-                               TypeContainer i = LookupInterface (t);
-
-                               if ((i == null) || (i.IndexerName == null))
-                                       return "Item";
-
-                               return i.IndexerName;
-                       } else {
-                               TypeContainer tc = LookupTypeContainer (t);
-
-                               if ((tc == null) || (tc.IndexerName == null))
-                                       return "Item";
-
-                               return tc.IndexerName;
-                       }
+                       TypeContainer tc = t.IsInterface ? LookupInterface (t) : LookupTypeContainer (t);
+                       return tc == null ? TypeContainer.DefaultIndexerName : tc.IndexerName;
                }
                
                System.Attribute attr = System.Attribute.GetCustomAttribute (
@@ -2600,7 +2712,7 @@ public class TypeManager {
                        return dma.MemberName;
                }
 
-               return "Item";
+               return TypeContainer.DefaultIndexerName;
        }
 
        static MethodInfo declare_local_method = null;
@@ -2764,7 +2876,7 @@ public class TypeManager {
 
                        if (ma == MethodAttributes.Private)
                                return private_ok ||
-                                       IsEqual (invocation_type, mb.DeclaringType) ||
+                                       IsPrivateAccessible (invocation_type, mb.DeclaringType) ||
                                        IsNestedChildOf (invocation_type, mb.DeclaringType);
 
                        //
@@ -2791,14 +2903,14 @@ public class TypeManager {
                                if (invocation_type == null)
                                        return false;
 
-                               if (!IsSubclassOrNestedChildOf (invocation_type, mb.DeclaringType))
+                               if (!IsNestedFamilyAccessible (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 (!mb.IsStatic && (qualifier_type != null) &&
                                    !IsEqualGenericInstance (invocation_type, qualifier_type) &&
-                                   TypeManager.IsSubclassOf (invocation_type, qualifier_type) &&
+                                   TypeManager.IsFamilyAccessible (invocation_type, qualifier_type) &&
                                    !TypeManager.IsNestedChildOf (invocation_type, qualifier_type))
                                        return false;
 
@@ -2815,7 +2927,7 @@ public class TypeManager {
 
                        if (fa == FieldAttributes.Private)
                                return private_ok ||
-                                       IsEqual (invocation_type, fi.DeclaringType) ||
+                                       IsPrivateAccessible (invocation_type, fi.DeclaringType) ||
                                        IsNestedChildOf (invocation_type, fi.DeclaringType);
 
                        //
@@ -2842,14 +2954,14 @@ public class TypeManager {
                                if (invocation_type == null)
                                        return false;
 
-                               if (!IsSubclassOrNestedChildOf (invocation_type, fi.DeclaringType))
+                               if (!IsNestedFamilyAccessible (invocation_type, fi.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 (!fi.IsStatic && (qualifier_type != null) &&
                                    !IsEqualGenericInstance (invocation_type, qualifier_type) &&
-                                   TypeManager.IsSubclassOf (invocation_type, qualifier_type) &&
+                                   TypeManager.IsFamilyAccessible (invocation_type, qualifier_type) &&
                                    !TypeManager.IsNestedChildOf (invocation_type, qualifier_type))
                                        return false;
 
@@ -2876,7 +2988,7 @@ public class TypeManager {
 
                        if (((qualifier_type == null) || (qualifier_type == invocation_type)) &&
                            (invocation_type != null) &&
-                           IsEqual (m.DeclaringType, invocation_type))
+                           IsPrivateAccessible (m.DeclaringType, invocation_type))
                                return true;
 
                        //
@@ -2899,7 +3011,6 @@ public class TypeManager {
 
        static Closure closure = new Closure ();
        static MemberFilter FilterWithClosure_delegate = new MemberFilter (closure.Filter);
-       static MemberFilter FilterNone_delegate = new MemberFilter (FilterNone);
 
        //
        // Looks up a member called `name' in the `queried_type'.  This lookup
@@ -3139,85 +3250,30 @@ public class TypeManager {
                return null;
        }
 
-       //
-       // This is used to extract properties and event declarations from a type
-       //
-       static MemberInfo [] SpecialContainerLookup (Type t, bool is_static)
-       {
-               BindingFlags bf = BindingFlags.DeclaredOnly | (is_static ? BindingFlags.Static : BindingFlags.Instance);
-
-               bf |= BindingFlags.Public | BindingFlags.NonPublic;
-               
-               if (t is TypeBuilder) {
-                       DeclSpace decl = (DeclSpace) builder_to_declspace [t];
-
-                       return (MemberInfo []) decl.FindMembers (
-                               MemberTypes.Property | MemberTypes.Event,
-                               bf, FilterNone_delegate, null);
-               } else {
-                       return t.FindMembers (MemberTypes.Property | MemberTypes.Event,
-                                             bf, FilterNone_delegate, null);
-
-               }
-       }
-       
+       // Tests whether external method is really special
        public static bool IsSpecialMethod (MethodBase mb)
        {
-               Type t = mb.DeclaringType;
-               
-               MemberInfo [] matches = TypeManager.SpecialContainerLookup (t, mb.IsStatic);
-               if (matches == null)
-                       return false;
-               
-               foreach (MemberInfo mi in matches){
-                       if (mi is PropertyBuilder){
-                               Pair p = (Pair) properties [mi];
-
-                               if (p.First == mb || p.Second == mb)
-                                       return true;
-                       } else if (mi is PropertyInfo){
-                               MethodInfo [] methods = ((PropertyInfo) mi).GetAccessors (true);
-                               
-                               foreach (MethodInfo m in methods){
-                                       if (m == mb)
-                                               return true;
-                               }
-                       } else if (mi is MyEventBuilder){
-                               Pair p = (Pair) events [mi];
-
-                               if (p.First == mb || p.Second == mb)
-                                       return true;
-                       } else if (mi is EventInfo){
-                               EventInfo ei = ((EventInfo) mi);
-                               
-                               if (ei.GetAddMethod (true) == mb)
-                                       return true;
-                               
-                               if (ei.GetRemoveMethod (true) == mb)
-                                       return true;
+               string name = mb.Name;
+               if (name.StartsWith ("get_") || name.StartsWith ("set_"))
+                       return mb.DeclaringType.GetProperty (name.Substring (4)) != null;
                                
-                               if (ei.GetRaiseMethod (true) == mb)
-                                       return true;
-                       }
-               }
+               if (name.StartsWith ("add_"))
+                       return mb.DeclaringType.GetEvent (name.Substring (4)) != null;
 
-               //
-               // Now check if it is an operator method
-               //
-               string s = mb.Name;
+               if (name.StartsWith ("remove_"))
+                       return mb.DeclaringType.GetEvent (name.Substring (7)) != null;
 
-               if (s.StartsWith ("op_")){
-                       foreach (string name in Unary.oper_names){
-                               if (s == name)
+               if (name.StartsWith ("op_")){
+                       foreach (string oname in Unary.oper_names) {
+                               if (oname == name)
                                        return true;
                        }
 
-                       foreach (string name in Binary.oper_names){
-                               if (s == name)
+                       foreach (string oname in Binary.oper_names) {
+                               if (oname == name)
                                        return true;
                        }
                }
-               
                return false;
        }
                
@@ -3317,7 +3373,7 @@ public sealed class TypeHandle : IMemberContainer {
                }
        }
 
-       public IMemberContainer Parent {
+       public IMemberContainer ParentContainer {
                get {
                        return BaseType;
                }