2004-05-29 Martin Baulig <martin@ximian.com>
[mono.git] / mcs / mcs / typemanager.cs
index 1839450c58df7c363eae24754e59b36e64e1e387..83184f36821f7112365fdd3d121c2e14882b5d57 100755 (executable)
@@ -81,10 +81,15 @@ public class TypeManager {
        static public Type indexer_name_type;
        static public Type exception_type;
        static public Type invalid_operation_exception_type;
-       static public object obsolete_attribute_type;
+       static public Type 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;
+       static public Type mbr_type;
+       static public Type struct_layout_attribute_type;
+       static public Type field_offset_attribute_type;
 
        //
        // An empty array of types
@@ -228,17 +233,12 @@ public class TypeManager {
        // <remarks>
        static Hashtable method_internal_params;
 
-       // <remarks>
-       //  Keeps track of attribute types
-       // </remarks>
-
-       static Hashtable builder_to_attr;
-
        // <remarks>
        //  Keeps track of methods
        // </remarks>
 
        static Hashtable builder_to_method;
+       static Hashtable builder_to_method_2;
 
        // <remarks>
        //  Contains all public types from referenced assemblies.
@@ -264,13 +264,11 @@ public class TypeManager {
                method_arguments = null;
                indexer_arguments = null;
                method_internal_params = null;
-               builder_to_attr = null;
                builder_to_method = null;
                
                fields = null;
                references = null;
                negative_hits = null;
-               attr_to_allowmult = null;
                builder_to_constant = null;
                fieldbuilders_to_fields = null;
                events = null;
@@ -360,8 +358,8 @@ public class TypeManager {
                typecontainers = new Hashtable ();
                
                builder_to_declspace = new PtrHashtable ();
-               builder_to_attr = new PtrHashtable ();
                builder_to_method = new PtrHashtable ();
+               builder_to_method_2 = new PtrHashtable ();
                method_arguments = new PtrHashtable ();
                method_internal_params = new PtrHashtable ();
                indexer_arguments = new PtrHashtable ();
@@ -459,14 +457,21 @@ public class TypeManager {
                builder_to_declspace.Add (t, i);
        }
 
+
+       [Obsolete("Will be removed very soon")]
        public static void AddMethod (MethodBuilder builder, MethodData method)
        {
                builder_to_method.Add (builder, method);
        }
 
-       public static void RegisterAttrType (Type t, TypeContainer tc)
+       public static void AddMethod2 (MethodBase builder, IMethodData method)
        {
-               builder_to_attr.Add (t, tc);
+               builder_to_method_2.Add (builder, method);
+       }
+
+       public static IMethodData GetMethod (MethodBase builder)
+       {
+               return (IMethodData) builder_to_method_2 [builder];
        }
 
        /// <summary>
@@ -512,10 +517,10 @@ public class TypeManager {
        {
                return builder_to_declspace [t] as Enum;
        }
-       
-       public static TypeContainer LookupAttr (Type t)
+
+       public static Class LookupClass (Type t)
        {
-               return (TypeContainer) builder_to_attr [t];
+               return (Class) builder_to_declspace [t];
        }
        
        /// <summary>
@@ -766,14 +771,16 @@ public class TypeManager {
                                }
                        }
                } else {
-                       foreach (Assembly a in assemblies){
-                               foreach (Type t in a.GetTypes ()){
+                       Hashtable cache = new Hashtable ();
+                       cache.Add ("", null);
+                       foreach (Assembly a in assemblies) {
+                               foreach (Type t in a.GetExportedTypes ()) {
                                        string ns = t.Namespace;
-
-                                       // t.Namespace returns null for <PrivateImplDetails>
-                                       if (ns == ""|| ns == null)
+                                       if (ns == null || cache.Contains (ns))
                                                continue;
+
                                        Namespace.LookupNamespace (ns, true);
+                                       cache.Add (ns, null);
                                }
                        }
                }
@@ -900,7 +907,7 @@ public class TypeManager {
 
                if (t == null){
                        Report.Error (518, "The predefined type `" + name + "' is not defined or imported");
-                       Environment.Exit (0);
+                       Environment.Exit (1);
                }
 
                return t;
@@ -1039,6 +1046,9 @@ public class TypeManager {
                marshal_as_attr_type = CoreLookupType ("System.Runtime.InteropServices.MarshalAsAttribute");
                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");
+               mbr_type             = CoreLookupType ("System.MarshalByRefObject");
 
                //
                // Sigh. Remove this before the release.  Wonder what versions of Mono
@@ -1061,6 +1071,8 @@ public class TypeManager {
                obsolete_attribute_type = CoreLookupType ("System.ObsoleteAttribute");
                conditional_attribute_type = CoreLookupType ("System.Diagnostics.ConditionalAttribute");
                cls_compliant_attribute_type = CoreLookupType ("System.CLSCompliantAttribute");
+               struct_layout_attribute_type = CoreLookupType ("System.Runtime.InteropServices.StructLayoutAttribute");
+               field_offset_attribute_type = CoreLookupType ("System.Runtime.InteropServices.FieldOffsetAttribute");
 
                //
                // When compiling corlib, store the "real" types here.
@@ -1425,6 +1437,11 @@ public class TypeManager {
                        return false;
        }
 
+       public static bool IsBuiltinType (TypeContainer tc)
+       {
+               return IsBuiltinType (tc.TypeBuilder);
+       }
+
        //
        // This is like IsBuiltinType, but lacks decimal_type, we should also clean up
        // the pieces in the code where we use IsBuiltinType and special case decimal_type.
@@ -1589,39 +1606,6 @@ public class TypeManager {
                }
        }
 
-       static Hashtable attr_to_allowmult;
-
-       public static void RegisterAttributeAllowMultiple (Type attr_type, bool allow)
-       {
-               if (attr_to_allowmult == null)
-                       attr_to_allowmult = new PtrHashtable ();
-
-               if (attr_to_allowmult.Contains (attr_type))
-                       return;
-
-               attr_to_allowmult.Add (attr_type, allow);
-                              
-       }
-
-       public static bool AreMultipleAllowed (Type attr_type)
-       {
-               if (!(attr_type is TypeBuilder)) {
-                       System.Attribute [] attrs = System.Attribute.GetCustomAttributes (attr_type);
-
-                       foreach (System.Attribute tmp in attrs)
-                               if (tmp is AttributeUsageAttribute) {
-                                        return ((AttributeUsageAttribute) tmp).AllowMultiple;
-                                }
-
-                       return false;
-               }
-               
-               if (attr_to_allowmult == null)
-                       return false;
-
-               return (bool) attr_to_allowmult [attr_type];
-       }
-
        static Hashtable builder_to_constant;
 
        public static void RegisterConstant (FieldBuilder fb, Const c)
@@ -1854,6 +1838,64 @@ public class TypeManager {
                return true;
        }
 
+       public static bool CheckStructCycles (TypeContainer tc, Hashtable seen)
+       {
+               Hashtable hash = new Hashtable ();
+               return CheckStructCycles (tc, seen, hash);
+       }
+
+       public static bool CheckStructCycles (TypeContainer tc, Hashtable seen,
+                                             Hashtable hash)
+       {
+               if (!(tc is Struct) || IsBuiltinType (tc))
+                       return true;
+
+               //
+               // `seen' contains all types we've already visited.
+               //
+               if (seen.Contains (tc))
+                       return true;
+               seen.Add (tc, null);
+
+               if (tc.Fields == null)
+                       return true;
+
+               foreach (Field field in tc.Fields) {
+                       if (field.FieldBuilder.IsStatic)
+                               continue;
+
+                       Type ftype = field.FieldBuilder.FieldType;
+                       TypeContainer ftc = LookupTypeContainer (ftype);
+                       if (ftc == null)
+                               continue;
+
+                       if (hash.Contains (ftc)) {
+                               Report.Error (523, tc.Location,
+                                             "Struct member `{0}.{1}' of type `{2}' " +
+                                             "causes a cycle in the struct layout",
+                                             tc.Name, field.Name, ftc.Name);
+                               return false;
+                       }
+
+                       //
+                       // `hash' contains all types in the current path.
+                       //
+                       hash.Add (tc, null);
+
+                       bool ok = CheckStructCycles (ftc, seen, hash);
+
+                       hash.Remove (tc);
+
+                       if (!ok)
+                               return false;
+
+                       if (!seen.Contains (ftc))
+                               seen.Add (ftc, null);
+               }
+
+               return true;
+       }
+
        /// <summary>
        ///   Given an array of interface types, expand and eliminate repeated ocurrences
        ///   of an interface.  
@@ -2142,6 +2184,8 @@ public class TypeManager {
                                return TypeManager.object_type;
                        if (t == typeof (System.Type))
                                return TypeManager.type_type;
+                       if (t == typeof (System.IntPtr))
+                               return TypeManager.intptr_type;
                        return t;
                }
        }
@@ -2297,8 +2341,6 @@ public class TypeManager {
 
        [Flags]
        public enum MethodFlags {
-               IsObsolete = 1,
-               IsObsoleteError = 1 << 1,
                ShouldIgnore = 1 << 2
        }
        
@@ -2329,23 +2371,6 @@ public class TypeManager {
                                continue;
                        }
                        System.Attribute a = (System.Attribute) ta;
-                       if (a.TypeId == TypeManager.obsolete_attribute_type){
-                               ObsoleteAttribute oa = (ObsoleteAttribute) a;
-
-                               string method_desc = TypeManager.CSharpSignature (mb);
-
-                               if (oa.IsError) {
-                                       Report.Error (619, loc, "Method `" + method_desc +
-                                                     "' is obsolete: `" + oa.Message + "'");
-                                       return MethodFlags.IsObsoleteError;
-                               } else
-                                       Report.Warning (618, loc, "Method `" + method_desc +
-                                                       "' is obsolete: `" + oa.Message + "'");
-
-                               flags |= MethodFlags.IsObsolete;
-
-                               continue;
-                       }
                        
                        //
                        // Skip over conditional code.
@@ -2446,7 +2471,8 @@ public class TypeManager {
                                // it cannot do so through an instance of the base class (CS1540).
                                if (!mb.IsStatic && (closure_invocation_type != closure_qualifier_type) &&
                                    (closure_qualifier_type != null) &&
-                                   closure_invocation_type.IsSubclassOf (closure_qualifier_type))
+                                   closure_invocation_type.IsSubclassOf (closure_qualifier_type) &&
+                                   !TypeManager.IsNestedChildOf (closure_invocation_type, closure_qualifier_type))
                                        return false;
 
                                return true;
@@ -2495,7 +2521,8 @@ public class TypeManager {
                                // it cannot do so through an instance of the base class (CS1540).
                                if (!fi.IsStatic && (closure_invocation_type != closure_qualifier_type) &&
                                    (closure_qualifier_type != null) &&
-                                   closure_invocation_type.IsSubclassOf (closure_qualifier_type))
+                                   closure_invocation_type.IsSubclassOf (closure_qualifier_type) &&
+                                   !TypeManager.IsNestedChildOf (closure_invocation_type, closure_qualifier_type))
                                        return false;
 
                                return true;