X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fgmcs%2Ftypemanager.cs;h=6fa5127dbe0a066c3309ff3a1668d2375a957174;hb=215c1cd77483d5c0018469905265023f3f8df7ee;hp=9bb772c08bb70d9cef01c7486a4a063ac0c5c210;hpb=6fb01373c53422257ae42c9129e1d76a0c841663;p=mono.git diff --git a/mcs/gmcs/typemanager.cs b/mcs/gmcs/typemanager.cs index 9bb772c08bb..6fa5127dbe0 100644 --- a/mcs/gmcs/typemanager.cs +++ b/mcs/gmcs/typemanager.cs @@ -80,7 +80,6 @@ public partial class TypeManager { static public Type methodimpl_attr_type; static public Type marshal_as_attr_type; static public Type param_array_type; - static public Type guid_attr_type; static public Type void_ptr_type; static public Type indexer_name_type; static public Type exception_type; @@ -98,12 +97,14 @@ public partial class TypeManager { static public Type struct_layout_attribute_type; static public Type field_offset_attribute_type; static public Type security_attr_type; + static public Type required_attr_type; /// /// .NET 2.0 /// static internal Type compiler_generated_attr_type; static internal Type fixed_buffer_attr_type; + static internal Type default_charset_type; // // An empty array of types @@ -193,7 +194,8 @@ public partial class TypeManager { static public ConstructorInfo default_member_ctor; static public ConstructorInfo decimal_constant_attribute_ctor; static internal ConstructorInfo struct_layout_attribute_ctor; - + static public ConstructorInfo field_offset_attribute_ctor; + /// /// A new in C# 2.0 /// @@ -270,6 +272,9 @@ public partial class TypeManager { // public static Hashtable all_imported_types; + static Hashtable fieldbuilders_to_fields; + static Hashtable fields; + struct Signature { public string name; public Type [] args; @@ -292,15 +297,15 @@ public partial class TypeManager { builder_to_method = null; fields = null; - references = null; - negative_hits = null; builder_to_constant = null; fieldbuilders_to_fields = null; events = null; priv_fields_events = null; properties = null; - CleanUpGenerics (); + type_hash = null; + + CleanUpGenerics (); TypeHandle.CleanUp (); } @@ -376,6 +381,15 @@ public partial class TypeManager { } static TypeManager () + { + Reset (); + + signature_filter = new MemberFilter (SignatureFilter); + InitExpressionTypes (); + InitGenerics (); + } + + static public void Reset () { assemblies = new Assembly [0]; modules = null; @@ -395,9 +409,9 @@ public partial class TypeManager { NoTypes = new Type [0]; NoTypeExprs = new TypeExpr [0]; - signature_filter = new MemberFilter (SignatureFilter); - InitGenerics (); - InitExpressionTypes (); + fieldbuilders_to_fields = new Hashtable (); + fields = new Hashtable (); + type_hash = new DoubleHash (); } public static void HandleDuplicate (string name, Type t) @@ -436,6 +450,7 @@ public partial class TypeManager { } catch { HandleDuplicate (name, t); } + user_types.Add (t); } @@ -607,8 +622,18 @@ public partial class TypeManager { } } - static Hashtable references = new Hashtable (); - + // + // We use this hash for multiple kinds of constructed types: + // + // (T, "&") Given T, get T & + // (T, "*") Given T, get T * + // (T, "[]") Given T and a array dimension, get T [] + // (T, X) Given a type T and a simple name X, get the type T+X + // + // Accessibility tests, if necessary, should be done by the user + // + static DoubleHash type_hash = new DoubleHash (); + // // Gets the reference to T version of the Type (T&) // @@ -617,36 +642,82 @@ public partial class TypeManager { return t.MakeByRefType (); } - static Hashtable pointers = new Hashtable (); - // // Gets the pointer to T version of the Type (T*) // public static Type GetPointerType (Type t) { - string tname = t.FullName + "*"; - - Type ret = t.Assembly.GetType (tname); - - // - // If the type comes from the assembly we are building - // We need the Hashtable, because .NET 1.1 will return different instance types - // every time we call ModuleBuilder.GetType. - // - if (ret == null){ - if (pointers [t] == null) - pointers [t] = CodeGen.Module.Builder.GetType (tname); - - ret = (Type) pointers [t]; + return GetConstructedType (t, "*"); + } + + public static Type GetConstructedType (Type t, string dim) + { + object ret = null; + if (type_hash.Lookup (t, dim, out ret)) + return (Type) ret; + + ret = t.Module.GetType (t.ToString () + dim); + if (ret != null) { + type_hash.Insert (t, dim, ret); + return (Type) ret; } - return ret; + if (dim == "&") { + ret = GetReferenceType (t); + type_hash.Insert (t, dim, ret); + return (Type) ret; + } + + if (t.IsGenericParameter || t.IsGenericInstance) { + int pos = 0; + Type result = t; + while ((pos < dim.Length) && (dim [pos] == '[')) { + pos++; + + if (dim [pos] == ']') { + result = result.MakeArrayType (); + pos++; + + if (pos < dim.Length) + continue; + + type_hash.Insert (t, dim, result); + return result; + } + + int rank = 0; + while (dim [pos] == ',') { + pos++; rank++; + } + + if ((dim [pos] != ']') || (pos != dim.Length-1)) + break; + + result = result.MakeArrayType (rank + 1); + type_hash.Insert (t, dim, result); + return result; + } + } + + type_hash.Insert (t, dim, null); + return null; + } + + public static Type GetNestedType (Type t, string name) + { + object ret = null; + if (!type_hash.Lookup (t, name, out ret)) { + string lookup = t.FullName + "+" + name; + ret = t.Module.GetType (lookup); + type_hash.Insert (t, name, ret); + } + return (Type) ret; } // // Low-level lookup, cache-less // - static Type LookupTypeReflection (string name) + public static Type LookupTypeReflection (string name) { Type t; @@ -686,98 +757,6 @@ public partial class TypeManager { return null; } - static Hashtable negative_hits = new Hashtable (); - - // - // 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; - } - - static readonly char [] dot_array = { '.' }; - - /// - /// 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 "." - /// - public static Type LookupType (string name) - { - Type t; - - // - // First lookup in user defined and cached values - // - - t = (Type) types [name]; - if (t != null) - return t; - - // Two thirds of the failures are caught here. - if (negative_hits.Contains (name)) - return null; - - // Sadly, split takes a param array, so this ends up allocating *EVERY TIME* - string [] elements = name.Split (dot_array); - int count = elements.Length; - - for (int n = 1; n <= count; n++){ - string top_level_type = String.Join (".", elements, 0, n); - - // One third of the failures are caught here. - if (negative_hits.Contains (top_level_type)) - continue; - - t = (Type) types [top_level_type]; - if (t == null){ - t = LookupTypeReflection (top_level_type); - if (t == null){ - negative_hits [top_level_type] = null; - continue; - } - } - - if (count == n){ - types [name] = t; - return t; - } - - // - // We know that System.Object does not have children, and since its the base of - // all the objects, it always gets probbed for inner classes. - // - if (top_level_type == "System.Object") - return null; - - string newt = top_level_type + "+" + String.Join ("+", elements, n, count - n); - //Console.WriteLine ("Looking up: " + newt + " " + name); - t = LookupTypeReflection (newt); - if (t == null) - negative_hits [name] = null; - else - types [name] = t; - return t; - } - negative_hits [name] = null; - return null; - } - /// /// Computes the namespaces that we import from the assemblies we reference. /// @@ -785,6 +764,8 @@ public partial class TypeManager { { MethodInfo assembly_get_namespaces = typeof (Assembly).GetMethod ("GetNamespaces", BindingFlags.Instance|BindingFlags.NonPublic); + Hashtable cache = null; + // // First add the assembly namespaces // @@ -801,7 +782,7 @@ public partial class TypeManager { } } } else { - Hashtable cache = new Hashtable (); + cache = new Hashtable (); cache.Add ("", null); foreach (Assembly a in assemblies) { foreach (Type t in a.GetExportedTypes ()) { @@ -814,6 +795,25 @@ public partial class TypeManager { } } } + + // + // Then add module namespaces + // + foreach (Module m in modules) { + if (m == CodeGen.Module.Builder) + continue; + if (cache == null) { + cache = new Hashtable (); + cache.Add ("", null); + } + foreach (Type t in m.GetTypes ()) { + string ns = t.Namespace; + if (ns == null || cache.Contains (ns)) + continue; + Namespace.LookupNamespace (ns, true); + cache.Add (ns, null); + } + } } /// @@ -855,6 +855,17 @@ public partial class TypeManager { @"(\W+|\b)", new MatchEvaluator (CSharpNameMatch)).Replace ('+', '.'); } + + static public string CSharpName (Type[] types) + { + StringBuilder sb = new StringBuilder (); + foreach (Type t in types) { + sb.Append (CSharpName (t)); + sb.Append (','); + } + sb.Remove (sb.Length - 1, 1); + return sb.ToString (); + } static String CSharpNameMatch (Match match) { @@ -900,41 +911,45 @@ public partial class TypeManager { return mb.DeclaringType.FullName.Replace ('+', '.') + '.' + name; } - static public string GetFullName (Type t) + private static void GetFullName_recursed (StringBuilder sb, Type t, bool recursed) { - if (t.FullName == null) - return t.Name; - - string name = t.FullName.Replace ('+', '.'); + if (t.IsGenericParameter) { + sb.Append (t.Name); + return; + } - DeclSpace tc = LookupDeclSpace (t); - if ((tc != null) && tc.IsGeneric) { - TypeParameter[] tparam = tc.TypeParameters; + if (t.DeclaringType != null) { + GetFullName_recursed (sb, t.DeclaringType, true); + sb.Append ("."); + } - StringBuilder sb = new StringBuilder (name); - sb.Append ("<"); - for (int i = 0; i < tparam.Length; i++) { - if (i > 0) - sb.Append (","); - sb.Append (tparam [i].Name); + if (!recursed) { + string ns = t.Namespace; + if ((ns != null) && (ns != "")) { + sb.Append (ns); + sb.Append ("."); } - sb.Append (">"); - return sb.ToString (); - } else if (t.HasGenericArguments && !t.IsGenericInstance) { - Type[] tparam = t.GetGenericArguments (); + } - StringBuilder sb = new StringBuilder (name); + sb.Append (SimpleName.RemoveGenericArity (t.Name)); + + Type[] args = GetTypeArguments (t); + if (args.Length > 0) { sb.Append ("<"); - for (int i = 0; i < tparam.Length; i++) { + for (int i = 0; i < args.Length; i++) { if (i > 0) sb.Append (","); - sb.Append (tparam [i].Name); + sb.Append (GetFullName (args [i])); } sb.Append (">"); - return sb.ToString (); } + } - return name; + static public string GetFullName (Type t) + { + StringBuilder sb = new StringBuilder (); + GetFullName_recursed (sb, t, false); + return sb.ToString (); } /// @@ -996,13 +1011,16 @@ public partial class TypeManager { /// static Type CoreLookupType (string name) { - Type t = LookupTypeDirect (name); + Type t = null; + if (types.Contains (name)) + t = (Type) types [name]; + else + t = LookupTypeReflection (name); - if (t == null){ + if (t == null) Report.Error (518, "The predefined type `" + name + "' is not defined or imported"); - Environment.Exit (1); - } + types [name] = t; return t; } @@ -1053,7 +1071,7 @@ public partial class TypeManager { /// /// Returns the ConstructorInfo for "args" /// - static ConstructorInfo GetConstructor (Type t, Type [] args) + public static ConstructorInfo GetConstructor (Type t, Type [] args) { MemberList list; Signature sig; @@ -1147,12 +1165,6 @@ public partial class TypeManager { mbr_type = CoreLookupType ("System.MarshalByRefObject"); decimal_constant_attribute_type = CoreLookupType ("System.Runtime.CompilerServices.DecimalConstantAttribute"); - // - // Sigh. Remove this before the release. Wonder what versions of Mono - // people are running. - // - guid_attr_type = LookupType ("System.Runtime.InteropServices.GuidAttribute"); - unverifiable_code_type= CoreLookupType ("System.Security.UnverifiableCodeAttribute"); void_ptr_type = CoreLookupType ("System.Void*"); @@ -1172,6 +1184,7 @@ public partial class TypeManager { struct_layout_attribute_type = CoreLookupType ("System.Runtime.InteropServices.StructLayoutAttribute"); field_offset_attribute_type = CoreLookupType ("System.Runtime.InteropServices.FieldOffsetAttribute"); security_attr_type = CoreLookupType ("System.Security.Permissions.SecurityAttribute"); + required_attr_type = CoreLookupType ("System.Runtime.CompilerServices.RequiredAttributeAttribute"); InitGenericCoreTypes (); @@ -1180,6 +1193,7 @@ public partial class TypeManager { // compiler_generated_attr_type = CoreLookupType ("System.Runtime.CompilerServices.CompilerGeneratedAttribute"); fixed_buffer_attr_type = CoreLookupType ("System.Runtime.CompilerServices.FixedBufferAttribute"); + default_charset_type = CoreLookupType ("System.Runtime.InteropServices.DefaultCharSetAttribute"); // // When compiling corlib, store the "real" types here. // @@ -1290,7 +1304,7 @@ public partial 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[]") }; + Type[] params_string = { GetConstructedType (string_type, "[]") }; string_concat_string_dot_dot_dot = GetMethod ( string_type, "Concat", params_string); @@ -1300,7 +1314,7 @@ public partial class TypeManager { 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[]") }; + Type[] params_object = { GetConstructedType (object_type, "[]") }; string_concat_object_dot_dot_dot = GetMethod ( string_type, "Concat", params_object); @@ -1402,6 +1416,8 @@ public partial class TypeManager { decimal_constant_attribute_ctor = GetConstructor (decimal_constant_attribute_type, new Type [] { byte_type, byte_type, uint32_type, uint32_type, uint32_type } ); + field_offset_attribute_ctor = GetConstructor (field_offset_attribute_type, new Type [] + { int32_type }); // // .NET 2.0 types @@ -1503,7 +1519,7 @@ public partial class TypeManager { /// to check base classes and interfaces anymore. /// private static MemberInfo [] MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf, - string name, out bool used_cache) + string name, out bool used_cache) { MemberCache cache; @@ -1591,15 +1607,12 @@ public partial class TypeManager { // 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. // - public static bool IsCLRType (Type t) + public static bool IsPrimitiveType (Type t) { - if (t == object_type || t == int32_type || t == uint32_type || + return (t == int32_type || t == uint32_type || t == int64_type || t == uint64_type || t == float_type || t == double_type || t == char_type || t == short_type || t == bool_type || - t == sbyte_type || t == byte_type || t == ushort_type) - return true; - else - return false; + t == sbyte_type || t == byte_type || t == ushort_type); } public static bool IsDelegateType (Type t) @@ -1641,42 +1654,52 @@ public partial class TypeManager { // public static bool IsUnmanagedType (Type t) { - if (IsBuiltinType (t) && t != TypeManager.string_type) - return true; + // builtins that are not unmanaged types + if (t == TypeManager.object_type || t == TypeManager.string_type) + return false; - if (IsEnumType (t)) + if (IsBuiltinOrEnum (t)) return true; + // Someone did the work of checking if the ElementType of t is unmanaged. Let's not repeat it. if (t.IsPointer) return true; - if (IsValueType (t)){ - if (t is TypeBuilder){ - TypeContainer tc = LookupTypeContainer (t); + // Arrays are disallowed, even if we mark them with [MarshalAs(UnmanagedType.ByValArray, ...)] + if (t.IsArray) + return false; - 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 (); + if (!IsValueType (t)) + return false; - foreach (FieldInfo f in fields){ - if (f.IsStatic) - continue; - if (!IsUnmanagedType (f.FieldType)) - return false; + if (t is TypeBuilder){ + TypeContainer tc = LookupTypeContainer (t); + if (tc.Fields == null) + return true; + foreach (Field f in tc.Fields){ + // Avoid using f.FieldBuilder: f.Define () may not yet have been invoked. + if ((f.ModFlags & Modifiers.STATIC) != 0) + continue; + if (f.MemberType == null) + continue; + if (!IsUnmanagedType (f.MemberType)){ + Report.SymbolRelatedToPreviousError (f.Location, CSharpName (t) + "." + f.Name); + return false; } } return true; } + + FieldInfo [] fields = t.GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); - return false; + foreach (FieldInfo f in fields){ + if (!IsUnmanagedType (f.FieldType)){ + Report.SymbolRelatedToPreviousError (f); + return false; + } + } + + return true; } public static bool IsValueType (Type t) @@ -1962,7 +1985,6 @@ public partial class TypeManager { // This is a workaround the fact that GetValue is not // supported for dynamic types // - static Hashtable fields = new Hashtable (); static public bool RegisterFieldValue (FieldBuilder fb, object value) { if (fields.Contains (fb)) @@ -1978,7 +2000,6 @@ public partial class TypeManager { return fields [fb]; } - static Hashtable fieldbuilders_to_fields = new Hashtable (); static public bool RegisterFieldBase (FieldBuilder fb, FieldBase f) { if (fieldbuilders_to_fields.Contains (fb)) @@ -2158,11 +2179,13 @@ public partial class TypeManager { if (texpr == null) return null; - if (!new_ifaces.Contains (texpr.Type)) - new_ifaces.Add (texpr.Type); + if (new_ifaces.Contains (texpr.Type)) + continue; + + new_ifaces.Add (texpr.Type); Type [] implementing = texpr.Type.GetInterfaces (); - + foreach (Type imp in implementing){ if (!new_ifaces.Contains (imp)) new_ifaces.Add (imp); @@ -2181,7 +2204,6 @@ public partial class TypeManager { /// public static Type [] GetInterfaces (Type t) { - Type [] cached = iface_cache [t] as Type []; if (cached != null) return cached; @@ -2199,14 +2221,18 @@ public partial class TypeManager { if (t.IsArray) t = TypeManager.array_type; - if (t is TypeBuilder){ + if ((t is TypeBuilder) || t.IsGenericInstance) { Type [] base_ifaces; if (t.BaseType == null) base_ifaces = NoTypes; else base_ifaces = GetInterfaces (t.BaseType); - Type[] type_ifaces = (Type []) builder_to_ifaces [t]; + Type[] type_ifaces; + if (t.IsGenericInstance) + type_ifaces = t.GetInterfaces (); + else + type_ifaces = (Type []) builder_to_ifaces [t]; if (type_ifaces == null) type_ifaces = NoTypes; @@ -2446,18 +2472,7 @@ public partial class TypeManager { /// public static bool VerifyUnManaged (Type t, Location loc) { - if (t.IsValueType || t.IsPointer){ - // - // FIXME: this is more complex, we actually need to - // make sure that the type does not contain any - // classes itself - // - return true; - } - - if (!RootContext.StdLib && (t == TypeManager.decimal_type)) - // We need this explicit check here to make it work when - // compiling corlib. + if (IsUnmanagedType (t)) return true; Report.Error ( @@ -2508,7 +2523,7 @@ public partial class TypeManager { new Type [] { typeof (Type), typeof (bool)}, null); if (declare_local_method == null){ - Report.Warning (-24, new Location (-1), + Report.Warning (-30, new Location (-1), "This version of the runtime does not support making pinned local variables. " + "This code may cause errors on a runtime with a moving GC"); return ig.DeclareLocal (t); @@ -2606,40 +2621,6 @@ public partial class TypeManager { internal Assembly invocation_assembly; internal IList almost_match; - private bool CheckValidFamilyAccess (bool is_static, MemberInfo m) - { - if (invocation_type == null) - return false; - - Debug.Assert (IsNestedFamilyAccessible (invocation_type, m.DeclaringType)); - - if (is_static) - return true; - - // A nested class has access to all the protected members visible - // to its parent. - if (qualifier_type != null - && TypeManager.IsNestedChildOf (invocation_type, qualifier_type)) - return true; - - if (invocation_type == m.DeclaringType - || invocation_type.IsSubclassOf (m.DeclaringType)) { - // Although a derived class can access protected members of - // its base class it cannot do so through an instance of the - // base class (CS1540). - // => Ancestry should be: declaring_type ->* invocation_type - // ->* qualified_type - if (qualifier_type == null - || qualifier_type == invocation_type - || qualifier_type.IsSubclassOf (invocation_type)) - return true; - } - - if (almost_match != null) - almost_match.Add (m); - return false; - } - bool Filter (MethodBase mb, object filter_criteria) { MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask; @@ -3057,11 +3038,16 @@ public partial class TypeManager { /// There is exactly one instance of this class per type. /// public sealed class TypeHandle : IMemberContainer { - public readonly TypeHandle BaseType; + public readonly IMemberContainer BaseType; readonly int id = ++next_id; static int next_id = 0; + static TypeHandle () + { + Reset (); + } + /// /// Lookup a TypeHandle instance for the given type. If the type doesn't have /// a TypeHandle yet, a new instance of it is created. This static method @@ -3088,6 +3074,11 @@ public sealed class TypeHandle : IMemberContainer { type_hash = null; } + public static void Reset () + { + type_hash = new PtrHashtable (); + } + /// /// Returns the TypeHandle for TypeManager.object_type. /// @@ -3116,7 +3107,7 @@ public sealed class TypeHandle : IMemberContainer { } } - private static PtrHashtable type_hash = new PtrHashtable (); + private static PtrHashtable type_hash; private static TypeHandle object_type = null; private static TypeHandle array_type = null; @@ -3132,8 +3123,8 @@ public sealed class TypeHandle : IMemberContainer { this.type = type; full_name = type.FullName != null ? type.FullName : type.Name; if (type.BaseType != null) { - BaseType = GetTypeHandle (type.BaseType); - base_cache = BaseType.MemberCache; + base_cache = TypeManager.LookupMemberCache (type.BaseType); + BaseType = base_cache.Container; } else if (type.IsInterface) base_cache = TypeManager.LookupBaseInterfacesCache (type); this.is_interface = type.IsInterface || type.IsGenericParameter;