X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fgmcs%2Ftypemanager.cs;h=7e08cc98e869e2dc961c620cfd63933cef7e337e;hb=2ce246b7a6ce1690c9c866a59b098c82442c0841;hp=3b58e641c870fdfcb98dbfcdbcd7c5585c27ab21;hpb=76716bfa3aef87dbf324016eaad111a7a4e74171;p=mono.git diff --git a/mcs/gmcs/typemanager.cs b/mcs/gmcs/typemanager.cs index 3b58e641c87..7e08cc98e86 100755 --- a/mcs/gmcs/typemanager.cs +++ b/mcs/gmcs/typemanager.cs @@ -63,48 +63,65 @@ public class TypeManager { static public Type ienumerator_type; static public Type ienumerable_type; static public Type idisposable_type; + static public Type iconvertible_type; static public Type default_member_type; static public Type iasyncresult_type; static public Type asynccallback_type; static public Type intptr_type; static public Type monitor_type; static public Type runtime_field_handle_type; + static public Type runtime_argument_handle_type; static public Type attribute_type; static public Type attribute_usage_type; static public Type dllimport_type; static public Type unverifiable_code_type; static public Type methodimpl_attr_type; static public Type marshal_as_attr_type; + static public Type new_constraint_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; + 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 not_supported_exception_type; + static public Type obsolete_attribute_type; + static public Type 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; + + static public Type generic_ienumerator_type; + static public Type generic_ienumerable_type; // // An empty array of types // static public Type [] NoTypes; + static public TypeExpr [] NoTypeExprs; // // Expressions representing the internal types. Used during declaration // definition. // - static public Expression system_object_expr, system_string_expr; - static public Expression system_boolean_expr, system_decimal_expr; - static public Expression system_single_expr, system_double_expr; - static public Expression system_sbyte_expr, system_byte_expr; - static public Expression system_int16_expr, system_uint16_expr; - static public Expression system_int32_expr, system_uint32_expr; - static public Expression system_int64_expr, system_uint64_expr; - static public Expression system_char_expr, system_void_expr; - static public Expression system_asynccallback_expr; - static public Expression system_iasyncresult_expr; + static public TypeExpr system_object_expr, system_string_expr; + static public TypeExpr system_boolean_expr, system_decimal_expr; + static public TypeExpr system_single_expr, system_double_expr; + static public TypeExpr system_sbyte_expr, system_byte_expr; + static public TypeExpr system_int16_expr, system_uint16_expr; + static public TypeExpr system_int32_expr, system_uint32_expr; + static public TypeExpr system_int64_expr, system_uint64_expr; + static public TypeExpr system_char_expr, system_void_expr; + 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 @@ -133,7 +150,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; @@ -155,6 +175,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. @@ -164,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; // // Holds the Array of Assemblies that have been loaded @@ -173,10 +195,10 @@ public class TypeManager { static Assembly [] assemblies; // - // Keeps a list of module builders. We used this to do lookups - // on the modulebuilder using GetType -- needed for arrays + // Keeps a list of modules. We used this to do lookups + // on the module using GetType -- needed for arrays // - static ModuleBuilder [] modules; + static Module [] modules; // // This is the type_cache from the assemblies to avoid @@ -204,6 +226,11 @@ public class TypeManager { // static PtrHashtable builder_to_ifaces; + // + // Tracks the generic parameters. + // + static PtrHashtable builder_to_type_param; + // // Maps MethodBase.RuntimeTypeHandle to a Type array that contains // the arguments to the method @@ -223,22 +250,50 @@ public class TypeManager { static Hashtable method_internal_params; // - // Keeps track of attribute types + // Keeps track of methods // - static Hashtable builder_to_attr; + static Hashtable builder_to_method; // - // Keeps track of methods + // Contains all public types from referenced assemblies. + // This member is used only if CLS Compliance verification is required. // - - static Hashtable builder_to_method; + public static Hashtable all_imported_types; struct Signature { public string name; public Type [] args; } + public static void CleanUp () + { + // Lets get everything clean so that we can collect before generating code + assemblies = null; + modules = null; + types = null; + typecontainers = null; + user_types = null; + builder_to_declspace = null; + builder_to_ifaces = null; + method_arguments = null; + indexer_arguments = null; + method_internal_params = null; + builder_to_method = null; + builder_to_type_param = null; + + fields = null; + references = null; + negative_hits = null; + builder_to_constant = null; + fieldbuilders_to_fields = null; + events = null; + priv_fields_events = null; + properties = null; + + TypeHandle.CleanUp (); + } + /// /// A filter for Findmembers that uses the Signature object to /// extract objects @@ -306,8 +361,10 @@ public class TypeManager { system_void_expr = new TypeLookupExpression ("System.Void"); 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 () { assemblies = new Assembly [0]; @@ -318,14 +375,15 @@ public class TypeManager { typecontainers = new Hashtable (); builder_to_declspace = new PtrHashtable (); - builder_to_attr = new PtrHashtable (); builder_to_method = new PtrHashtable (); method_arguments = new PtrHashtable (); method_internal_params = new PtrHashtable (); indexer_arguments = new PtrHashtable (); builder_to_ifaces = new PtrHashtable (); + builder_to_type_param = new PtrHashtable (); NoTypes = new Type [0]; + NoTypeExprs = new TypeExpr [0]; signature_filter = new MemberFilter (SignatureFilter); InitExpressionTypes (); @@ -344,7 +402,6 @@ public class TypeManager { return; } - Location l; tc = builder_to_declspace [t] as TypeContainer; if (tc != null){ Report.Warning ( @@ -361,7 +418,7 @@ public class TypeManager { types.Add (name, t); } - public static void AddUserType (string name, TypeBuilder t, Type [] ifaces) + public static void AddUserType (string name, TypeBuilder t) { try { types.Add (name, t); @@ -369,25 +426,22 @@ public class TypeManager { HandleDuplicate (name, t); } user_types.Add (t); - - if (ifaces != null) - builder_to_ifaces [t] = ifaces; } // // This entry point is used by types that we define under the covers // - public static void RegisterBuilder (TypeBuilder tb, Type [] ifaces) + public static void RegisterBuilder (Type tb, Type [] ifaces) { if (ifaces != null) builder_to_ifaces [tb] = ifaces; } - public static void AddUserType (string name, TypeBuilder t, TypeContainer tc, Type [] ifaces) + public static void AddUserType (string name, TypeBuilder t, TypeContainer tc) { builder_to_declspace.Add (t, tc); typecontainers.Add (name, tc); - AddUserType (name, t, ifaces); + AddUserType (name, t); } public static void AddDelegateType (string name, TypeBuilder t, Delegate del) @@ -411,20 +465,20 @@ public class TypeManager { builder_to_declspace.Add (t, en); } - public static void AddUserInterface (string name, TypeBuilder t, Interface i, Type [] ifaces) + public static void AddMethod (MethodBase builder, IMethodData method) { - AddUserType (name, t, ifaces); - builder_to_declspace.Add (t, i); + builder_to_method.Add (builder, method); } - public static void AddMethod (MethodBuilder builder, MethodData method) + public static IMethodData GetMethod (MethodBase builder) { - builder_to_method.Add (builder, method); + return (IMethodData) builder_to_method [builder]; } - public static void RegisterAttrType (Type t, TypeContainer tc) + public static void AddTypeParameter (Type t, TypeParameter tparam) { - builder_to_attr.Add (t, tc); + if (!builder_to_type_param.Contains (t)) + builder_to_type_param.Add (t, tparam); } /// @@ -444,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) { @@ -453,12 +515,23 @@ 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); } - public static Interface LookupInterface (Type t) + public static TypeContainer LookupInterface (Type t) { - return builder_to_declspace [t] as Interface; + TypeContainer tc = (TypeContainer) builder_to_declspace [t]; + if ((tc == null) || (tc.Kind != Kind.Interface)) + return null; + + return tc; } public static Delegate LookupDelegate (Type t) @@ -471,9 +544,35 @@ 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]; + } + + public static TypeParameter LookupTypeParameter (Type t) + { + return (TypeParameter) builder_to_type_param [t]; + } + + 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.GenericConstraints; + + return new ReflectionConstraints (t); } /// @@ -481,6 +580,11 @@ public class TypeManager { /// public static void AddAssembly (Assembly a) { + foreach (Assembly assembly in assemblies) { + if (a == assembly) + return; + } + int top = assemblies.Length; Assembly [] n = new Assembly [top + 1]; @@ -490,13 +594,18 @@ public class TypeManager { assemblies = n; } + public static Assembly [] GetAssemblies () + { + return assemblies; + } + /// /// Registers a module builder to lookup types from /// - public static void AddModule (ModuleBuilder mb) + public static void AddModule (Module mb) { int top = modules != null ? modules.Length : 0; - ModuleBuilder [] n = new ModuleBuilder [top + 1]; + Module [] n = new Module [top + 1]; if (modules != null) modules.CopyTo (n, 0); @@ -504,6 +613,12 @@ public class TypeManager { modules = n; } + public static Module[] Modules { + get { + return modules; + } + } + static Hashtable references = new Hashtable (); // @@ -511,22 +626,7 @@ public class TypeManager { // public static Type GetReferenceType (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 (references [t] == null) - references [t] = CodeGen.ModuleBuilder.GetType (tname); - ret = (Type) references [t]; - } - - return ret; + return t.MakeByRefType (); } static Hashtable pointers = new Hashtable (); @@ -547,7 +647,7 @@ public class TypeManager { // if (ret == null){ if (pointers [t] == null) - pointers [t] = CodeGen.ModuleBuilder.GetType (tname); + pointers [t] = CodeGen.Module.Builder.GetType (tname); ret = (Type) pointers [t]; } @@ -589,7 +689,7 @@ public class TypeManager { } while (t != null); } - foreach (ModuleBuilder mb in modules) { + foreach (Module mb in modules) { t = mb.GetType (name); if (t != null) return t; @@ -622,6 +722,8 @@ public class TypeManager { 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 @@ -643,7 +745,8 @@ public class TypeManager { if (negative_hits.Contains (name)) return null; - string [] elements = name.Split ('.'); + // 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++){ @@ -657,7 +760,7 @@ public class TypeManager { if (t == null){ t = LookupTypeReflection (top_level_type); if (t == null){ - negative_hits [top_level_type] = true; + negative_hits [top_level_type] = null; continue; } } @@ -678,12 +781,12 @@ public class TypeManager { //Console.WriteLine ("Looking up: " + newt + " " + name); t = LookupTypeReflection (newt); if (t == null) - negative_hits [name] = true; + negative_hits [name] = null; else types [name] = t; return t; } - negative_hits [name] = true; + negative_hits [name] = null; return null; } @@ -692,14 +795,13 @@ public class TypeManager { /// public static void ComputeNamespaces () { - MethodInfo assembly_get_namespaces = typeof (Assembly).GetMethod ("GetNamespaces"); + MethodInfo assembly_get_namespaces = typeof (Assembly).GetMethod ("GetNamespaces", BindingFlags.Instance|BindingFlags.NonPublic); // // First add the assembly namespaces // if (assembly_get_namespaces != null){ int count = assemblies.Length; - int total; for (int i = 0; i < count; i++){ Assembly a = assemblies [i]; @@ -711,19 +813,35 @@ 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 - if (ns == ""|| ns == null) + if (ns == null || cache.Contains (ns)) continue; + Namespace.LookupNamespace (ns, true); + cache.Add (ns, null); } } } } + /// + /// Fills static table with exported types from all referenced assemblies. + /// This information is required for CLS Compliance tests. + /// + public static void LoadAllImportedTypes () + { + 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) @@ -738,11 +856,14 @@ public class TypeManager { /// 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|" + @"Single|Double|Char|Decimal|Byte|SByte|Object|" + - @"Boolean|String|Void)" + + @"Boolean|String|Void|Null)" + @"(\W+|\b)", new MatchEvaluator (CSharpNameMatch)); } @@ -762,12 +883,90 @@ public class TypeManager { + match.Groups [2].Captures [0].Value; } + /// + /// Returns the signature of the method with full namespace classification + /// + static public string GetFullNameSignature (MemberInfo mi) + { + return mi.DeclaringType.FullName.Replace ('+', '.') + '.' + mi.Name; + } + + static public string GetFullNameSignature (MethodBase mb) + { + string name = mb.Name; + if (name == ".ctor") + name = mb.DeclaringType.Name; + + if (mb.IsSpecialName) { + if (name.StartsWith ("get_") || name.StartsWith ("set_")) { + name = name.Remove (0, 4); + } + + if (name == "Item") + name = "this"; + } + + return mb.DeclaringType.FullName.Replace ('+', '.') + '.' + name; + } + + static public string GetFullName (Type t) + { + if (t.FullName == null) + return t.Name; + + string name = t.FullName.Replace ('+', '.'); + + DeclSpace tc = LookupDeclSpace (t); + if ((tc != null) && tc.IsGeneric) { + TypeParameter[] tparam = tc.TypeParameters; + + 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); + } + sb.Append (">"); + return sb.ToString (); + } else if (t.HasGenericArguments && !t.IsGenericInstance) { + Type[] tparam = t.GetGenericArguments (); + + 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); + } + sb.Append (">"); + return sb.ToString (); + } + + return name; + } + + /// + /// Returns the signature of the property and indexer + /// + static public string CSharpSignature (PropertyBuilder pb, bool is_indexer) + { + if (!is_indexer) { + return GetFullNameSignature (pb); + } + + MethodBase mb = pb.GetSetMethod (true) != null ? pb.GetSetMethod (true) : pb.GetGetMethod (true); + string signature = GetFullNameSignature (mb); + string arg = TypeManager.LookupParametersByBuilder (mb).ParameterDesc (0); + return String.Format ("{0}.this[{1}]", signature.Substring (0, signature.LastIndexOf ('.')), arg); + } + /// /// Returns the signature of the method /// static public string CSharpSignature (MethodBase mb) { - string sig = "("; + StringBuilder sig = new StringBuilder ("("); // // FIXME: We should really have a single function to do @@ -775,20 +974,28 @@ public class TypeManager { // ParameterData iparams = LookupParametersByBuilder (mb); - if (iparams == null){ - ParameterInfo [] pi = mb.GetParameters (); - iparams = new ReflectionParameters (pi); - } + if (iparams == null) + iparams = new ReflectionParameters (mb); + + // Is property + if (mb.IsSpecialName && iparams.Count == 0 && !mb.IsConstructor) + return GetFullNameSignature (mb); for (int i = 0; i < iparams.Count; i++) { if (i > 0) { - sig += ", "; + sig.Append (", "); } - sig += iparams.ParameterDesc(i); + sig.Append (iparams.ParameterDesc (i)); } - sig += ")"; + sig.Append (")"); + + // Is indexer + if (mb.IsSpecialName && iparams.Count == 1 && !mb.IsConstructor) { + sig.Replace ('(', '['); + sig.Replace (')', ']'); + } - return mb.DeclaringType.Name + "." + mb.Name + sig; + return GetFullNameSignature (mb) + sig.ToString (); } /// @@ -801,7 +1008,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; @@ -811,16 +1018,19 @@ public class TypeManager { /// Returns the MethodInfo for a method named `name' defined /// in type `t' which takes arguments of types `args' /// - static MethodInfo GetMethod (Type t, string name, Type [] args, bool report_errors) + static MethodInfo GetMethod (Type t, string name, Type [] args, bool is_private, bool report_errors) { MemberList list; Signature sig; + BindingFlags flags = instance_and_static | BindingFlags.Public; sig.name = name; sig.args = args; - list = FindMembers (t, MemberTypes.Method, instance_and_static | BindingFlags.Public, - signature_filter, sig); + if (is_private) + flags |= BindingFlags.NonPublic; + + list = FindMembers (t, MemberTypes.Method, flags, signature_filter, sig); if (list.Count == 0) { if (report_errors) Report.Error (-19, "Can not find the core function `" + name + "'"); @@ -837,6 +1047,11 @@ public class TypeManager { return mi; } + static MethodInfo GetMethod (Type t, string name, Type [] args, bool report_errors) + { + return GetMethod (t, name, args, false, report_errors); + } + static MethodInfo GetMethod (Type t, string name, Type [] args) { return GetMethod (t, name, args, true); @@ -913,6 +1128,7 @@ public class TypeManager { type_type = CoreLookupType ("System.Type"); runtime_field_handle_type = CoreLookupType ("System.RuntimeFieldHandle"); + runtime_argument_handle_type = CoreLookupType ("System.RuntimeArgumentHandle"); runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices.RuntimeHelpers"); default_member_type = CoreLookupType ("System.Reflection.DefaultMemberAttribute"); runtime_handle_type = CoreLookupType ("System.RuntimeTypeHandle"); @@ -922,6 +1138,7 @@ public class TypeManager { ienumerable_type = CoreLookupType ("System.Collections.IEnumerable"); idisposable_type = CoreLookupType ("System.IDisposable"); icloneable_type = CoreLookupType ("System.ICloneable"); + iconvertible_type = CoreLookupType ("System.IConvertible"); monitor_type = CoreLookupType ("System.Threading.Monitor"); intptr_type = CoreLookupType ("System.IntPtr"); @@ -930,8 +1147,12 @@ public class TypeManager { dllimport_type = CoreLookupType ("System.Runtime.InteropServices.DllImportAttribute"); methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices.MethodImplAttribute"); marshal_as_attr_type = CoreLookupType ("System.Runtime.InteropServices.MarshalAsAttribute"); + 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"); + mbr_type = CoreLookupType ("System.MarshalByRefObject"); // // Sigh. Remove this before the release. Wonder what versions of Mono @@ -946,13 +1167,25 @@ 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"); + not_supported_exception_type = CoreLookupType ("System.NotSupportedException"); // // Attribute types // 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"); + + // + // Generic types + // + generic_ienumerator_type = CoreLookupType (MemberName.MakeName ("System.Collections.Generic.IEnumerator", 1)); + generic_ienumerable_type = CoreLookupType (MemberName.MakeName ("System.Collections.Generic.IEnumerable", 1)); + // // When compiling corlib, store the "real" types here. @@ -990,7 +1223,7 @@ public class TypeManager { MethodInfo set_corlib_type_builders = GetMethod ( system_assemblybuilder_type, "SetCorlibTypeBuilders", - system_4_type_arg, false); + system_4_type_arg, true, false); if (set_corlib_type_builders != null) { object[] args = new object [4]; @@ -999,12 +1232,12 @@ public class TypeManager { args [2] = enum_type; args [3] = void_type; - set_corlib_type_builders.Invoke (CodeGen.AssemblyBuilder, args); + set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args); } else { // Compatibility for an older version of the class libs. set_corlib_type_builders = GetMethod ( system_assemblybuilder_type, "SetCorlibTypeBuilders", - system_3_type_arg, true); + system_3_type_arg, true, true); if (set_corlib_type_builders == null) { Report.Error (-26, "Corlib compilation is not supported in Microsoft.NET due to bugs in it"); @@ -1016,9 +1249,29 @@ public class TypeManager { args [1] = value_type; args [2] = enum_type; - set_corlib_type_builders.Invoke (CodeGen.AssemblyBuilder, args); + set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args); } } + + system_object_expr.Type = object_type; + system_string_expr.Type = string_type; + system_boolean_expr.Type = bool_type; + system_decimal_expr.Type = decimal_type; + system_single_expr.Type = float_type; + system_double_expr.Type = double_type; + system_sbyte_expr.Type = sbyte_type; + system_byte_expr.Type = byte_type; + system_int16_expr.Type = short_type; + system_uint16_expr.Type = ushort_type; + system_int32_expr.Type = int32_type; + system_uint32_expr.Type = uint32_type; + system_int64_expr.Type = int64_type; + system_uint64_expr.Type = uint64_type; + system_char_expr.Type = char_type; + system_void_expr.Type = void_type; + system_asynccallback_expr.Type = asynccallback_type; + system_iasyncresult_expr.Type = iasyncresult_type; + system_valuetype_expr.Type = value_type; } // @@ -1038,10 +1291,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 ( @@ -1135,6 +1397,8 @@ public class TypeManager { unverifiable_code_ctor = GetConstructor ( unverifiable_code_type, void_arg); + default_member_ctor = GetConstructor (default_member_type, string_); + // // InvalidOperationException // @@ -1145,12 +1409,14 @@ 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; - static Hashtable type_hash = new Hashtable (); - /// /// This is the "old", non-cache based FindMembers() function. We cannot use /// the cache here because there is no member name argument. @@ -1179,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. @@ -1223,11 +1499,9 @@ 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. /// - private static MemberList MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf, + private static MemberInfo [] MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf, string name, out bool used_cache) { - bool not_loaded_corlib = (t.Assembly == CodeGen.AssemblyBuilder); - // // We have to take care of arrays specially, because GetType on // a TypeBuilder array will return a Type, not a TypeBuilder, @@ -1258,6 +1532,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); @@ -1265,7 +1540,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; } // @@ -1290,6 +1577,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. @@ -1307,6 +1599,9 @@ public class TypeManager { public static bool IsDelegateType (Type t) { + if (t.IsGenericInstance) + t = t.GetGenericTypeDefinition (); + if (t.IsSubclassOf (TypeManager.delegate_type)) return true; else @@ -1315,7 +1610,7 @@ public class TypeManager { public static bool IsEnumType (Type t) { - if (t == TypeManager.enum_type || t.IsSubclassOf (TypeManager.enum_type)) + if (t.IsSubclassOf (TypeManager.enum_type)) return true; else return false; @@ -1340,6 +1635,40 @@ 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); + if (tc != null) + return tc.IsGeneric ? tc.CountTypeParameters : 0; + else + return t.HasGenericArguments ? t.GetGenericArguments ().Length : 0; + } + + public static Type[] GetTypeArguments (Type t) + { + DeclSpace tc = LookupDeclSpace (t); + if (tc != null) { + if (!tc.IsGeneric) + throw new InvalidOperationException (); + + TypeParameter[] tparam = tc.TypeParameters; + Type[] ret = new Type [tparam.Length]; + for (int i = 0; i < tparam.Length; i++) { + ret [i] = tparam [i].Type; + if (ret [i] == null) + throw new InternalErrorException (); + } + + return ret; + } else + return t.GetGenericArguments (); + } // // Whether a type is unmanaged. This is used by the unsafe code (25.2) @@ -1359,12 +1688,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 (); @@ -1388,121 +1720,370 @@ public class TypeManager { public static bool IsInterfaceType (Type t) { - Interface iface = builder_to_declspace [t] as Interface; - - if (iface != null) - return true; - else + TypeContainer tc = (TypeContainer) builder_to_declspace [t]; + if (tc == null) return false; - } - - // - // Checks whether `type' is a subclass or nested child of `parent'. - // - public static bool IsSubclassOrNestedChildOf (Type type, Type parent) - { - do { - if ((type == parent) || type.IsSubclassOf (parent)) - return true; - - // Handle nested types. - type = type.DeclaringType; - } while (type != null); - return false; + return tc.Kind == Kind.Interface; } - // - // Checks whether `type' is a nested child of `parent'. - // - public static bool IsNestedChildOf (Type type, Type parent) + public static bool IsEqual (Type a, Type b) { - if (type == parent) - return false; + if (a.Equals (b)) + return true; - type = type.DeclaringType; - while (type != null) { - if (type == parent) - return true; + if ((a is TypeBuilder) && a.IsGenericTypeDefinition && b.IsGenericInstance) { + // + // `a' is a generic type definition's TypeBuilder and `b' is a + // generic instance of the same type. + // + // Example: + // + // class Stack + // { + // void Test (Stack stack) { } + // } + // + // The first argument of `Test' will be the generic instance + // "Stack" - 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; - type = type.DeclaringType; - } + Type[] aparams = a.GetGenericArguments (); + Type[] bparams = b.GetGenericArguments (); - return false; - } + if (aparams.Length != bparams.Length) + return false; - // - // Do the right thing when returning the element type of an - // array type based on whether we are compiling corlib or not - // - public static Type GetElementType (Type t) - { - if (RootContext.StdLib) - return t.GetElementType (); - else - return TypeToCoreType (t.GetElementType ()); - } + for (int i = 0; i < aparams.Length; i++) + if (!IsEqual (aparams [i], bparams [i])) + return false; - /// - /// Returns the User Defined Types - /// - public static ArrayList UserTypes { - get { - return user_types; + return true; } - } - public static Hashtable TypeContainers { - get { - return typecontainers; + if (a.IsGenericParameter && b.IsGenericParameter) { + if ((a.DeclaringMethod == null) || (b.DeclaringMethod == null)) + return false; + return a.GenericParameterPosition == b.GenericParameterPosition; } - } - static Hashtable attr_to_allowmult; + if (a.IsArray && b.IsArray) { + if (a.GetArrayRank () != b.GetArrayRank ()) + return false; + return IsEqual (a.GetElementType (), b.GetElementType ()); + } - public static void RegisterAttributeAllowMultiple (Type attr_type, bool allow) - { - if (attr_to_allowmult == null) - attr_to_allowmult = new PtrHashtable (); + if (a.IsGenericInstance && b.IsGenericInstance) { + Type at = a.GetGenericTypeDefinition (); + Type bt = b.GetGenericTypeDefinition (); - if (attr_to_allowmult.Contains (attr_type)) - return; + if (a.GetGenericTypeDefinition () != b.GetGenericTypeDefinition ()) + return false; - attr_to_allowmult.Add (attr_type, allow); - - } + Type[] aargs = a.GetGenericArguments (); + Type[] bargs = b.GetGenericArguments (); - public static bool AreMultipleAllowed (Type attr_type) - { - if (!(attr_type is TypeBuilder)) { - System.Attribute [] attrs = System.Attribute.GetCustomAttributes (attr_type); + if (aargs.Length != bargs.Length) + return false; - foreach (System.Attribute tmp in attrs) - if (tmp is AttributeUsageAttribute) { - return ((AttributeUsageAttribute) tmp).AllowMultiple; - } + for (int i = 0; i < aargs.Length; i++) { + if (!IsEqual (aargs [i], bargs [i])) + return false; + } - return false; + return true; } - - if (attr_to_allowmult == null) - return false; - return (bool) attr_to_allowmult [attr_type]; + return false; } - static Hashtable builder_to_constant; - - public static void RegisterConstant (FieldBuilder fb, Const c) + public static bool MayBecomeEqualGenericTypes (Type a, Type b) { - if (builder_to_constant == null) - builder_to_constant = new PtrHashtable (); - - if (builder_to_constant.Contains (fb)) - return; + if (a.IsGenericParameter) { + // + // If a is an array of a's type, they may never + // become equal. + // + while (b.IsArray) { + b = b.GetElementType (); + if (a.Equals (b)) + return false; + } - builder_to_constant.Add (fb, c); - } + // + // If b is a generic parameter or an actual type, + // they may become equal: + // + // class X : I, I + // class X : I, I + // + if (b.IsGenericParameter || !b.IsGenericInstance) + return true; + + // + // We're now comparing a type parameter with a + // generic instance. They may become equal unless + // the type parameter appears anywhere in the + // generic instance: + // + // class X : I, I> + // -> error because you could instanciate it as + // X,int> + // + // class X : I, I> -> ok + // + + Type[] bargs = GetTypeArguments (b); + for (int i = 0; i < bargs.Length; i++) { + if (a.Equals (bargs [i])) + return false; + } + + return true; + } + + if (b.IsGenericParameter) + return MayBecomeEqualGenericTypes (b, a); + + // + // At this point, neither a nor b are a type parameter. + // + // If one of them is a generic instance, let + // MayBecomeEqualGenericInstances() compare them (if the + // other one is not a generic instance, they can never + // become equal). + // + + if (a.IsGenericInstance || b.IsGenericInstance) + return MayBecomeEqualGenericInstances (a, b); + + // + // If both of them are arrays. + // + + if (a.IsArray && b.IsArray) { + if (a.GetArrayRank () != b.GetArrayRank ()) + return false; + + a = a.GetElementType (); + b = b.GetElementType (); + + return MayBecomeEqualGenericTypes (a, b); + } + + // + // Ok, two ordinary types. + // + + return a.Equals (b); + } + + // + // Checks whether two generic instances may become equal for some + // particular instantiation (26.3.1). + // + public static bool MayBecomeEqualGenericInstances (Type a, Type b) + { + if (!a.IsGenericInstance || !b.IsGenericInstance) + return false; + if (a.GetGenericTypeDefinition () != b.GetGenericTypeDefinition ()) + return false; + + Type[] aargs = GetTypeArguments (a); + Type[] bargs = GetTypeArguments (b); + + if (aargs.Length != bargs.Length) + return false; + + for (int i = 0; i < aargs.Length; i++) { + if (MayBecomeEqualGenericTypes (aargs [i], bargs [i])) + return true; + } + + return false; + } + + public static bool IsEqualGenericInstance (Type type, Type parent) + { + int tcount = GetNumberOfTypeArguments (type); + int pcount = GetNumberOfTypeArguments (parent); + + if (type.IsGenericInstance) + type = type.GetGenericTypeDefinition (); + if (parent.IsGenericInstance) + parent = parent.GetGenericTypeDefinition (); + + if (tcount != pcount) + return false; + + return type.Equals (parent); + } + + 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 + // { + // void Test (Stack stack) { } + // } + // + // The first argument of `Test' will be the generic instance + // "Stack" - 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; + + type = type.BaseType; + } while (type != null); + + return false; + } + + // + // Checks whether `type' is a subclass or nested child of `parent'. + // + public static bool IsNestedFamilyAccessible (Type type, Type parent) + { + do { + if (IsFamilyAccessible (type, parent)) + return true; + + // Handle nested types. + type = type.DeclaringType; + } while (type != null); + + return false; + } + + // + // Checks whether `type' is a nested child of `parent'. + // + public static bool IsNestedChildOf (Type type, Type parent) + { + if (IsEqual (type, parent)) + return false; + + type = type.DeclaringType; + while (type != null) { + if (IsEqual (type, parent)) + return true; + + type = type.DeclaringType; + } + + return false; + } + + // + // Do the right thing when returning the element type of an + // array type based on whether we are compiling corlib or not + // + public static Type GetElementType (Type t) + { + if (RootContext.StdLib) + return t.GetElementType (); + else + return TypeToCoreType (t.GetElementType ()); + } + + /// + /// Returns the User Defined Types + /// + public static ArrayList UserTypes { + get { + return user_types; + } + } + + public static Hashtable TypeContainers { + get { + return typecontainers; + } + } + + static Hashtable builder_to_constant; + + public static void RegisterConstant (FieldBuilder fb, Const c) + { + if (builder_to_constant == null) + builder_to_constant = new PtrHashtable (); + + if (builder_to_constant.Contains (fb)) + return; + + builder_to_constant.Add (fb, c); + } public static Const LookupConstant (FieldBuilder fb) { @@ -1521,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. /// - 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) @@ -1552,20 +2131,24 @@ public class TypeManager { /// static public Type [] GetArgumentTypes (MethodBase mb) { - if (method_arguments.Contains (mb)) - return (Type []) method_arguments [mb]; - else { + object t = method_arguments [mb]; + if (t != null) + return (Type []) t; + ParameterInfo [] pi = mb.GetParameters (); int c = pi.Length; - Type [] types = new Type [c]; + Type [] types; + if (c == 0) { + types = NoTypes; + } else { + types = new Type [c]; for (int i = 0; i < c; i++) types [i] = pi [i].ParameterType; - + } method_arguments.Add (mb, types); return types; } - } /// /// Returns the argument types for an indexer based on its PropertyInfo @@ -1641,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) @@ -1660,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) @@ -1670,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; @@ -1723,6 +2303,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.Kind != Kind.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; + } + /// /// Given an array of interface types, expand and eliminate repeated ocurrences /// of an interface. @@ -1732,15 +2370,19 @@ public class TypeManager { /// This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to /// be IA, IB, IC. /// - public static Type [] ExpandInterfaces (Type [] base_interfaces) + public static Type[] ExpandInterfaces (EmitContext ec, TypeExpr [] base_interfaces) { ArrayList new_ifaces = new ArrayList (); - foreach (Type iface in base_interfaces){ - if (!new_ifaces.Contains (iface)) - new_ifaces.Add (iface); + foreach (TypeExpr iface in base_interfaces){ + Type itype = iface.ResolveType (ec); + if (itype == null) + return null; + + if (!new_ifaces.Contains (itype)) + new_ifaces.Add (itype); - Type [] implementing = TypeManager.GetInterfaces (iface); + Type [] implementing = itype.GetInterfaces (); foreach (Type imp in implementing){ if (!new_ifaces.Contains (imp)) @@ -1752,12 +2394,19 @@ public class TypeManager { return ret; } + static PtrHashtable iface_cache = new PtrHashtable (); + /// /// This function returns the interfaces in the type `t'. Works with /// both types and TypeBuilders. /// public static Type [] GetInterfaces (Type t) { + + Type [] cached = iface_cache [t] as Type []; + if (cached != null) + return cached; + // // The reason for catching the Array case is that Reflection.Emit // will not return a TypeBuilder for Array types of TypeBuilder types, @@ -1772,24 +2421,43 @@ public class TypeManager { t = TypeManager.array_type; if (t is TypeBuilder){ - Type [] parent_ifaces; + Type[] parent_ifaces; if (t.BaseType == null) parent_ifaces = NoTypes; else parent_ifaces = GetInterfaces (t.BaseType); - Type [] type_ifaces = (Type []) builder_to_ifaces [t]; + Type[] type_ifaces = (Type []) builder_to_ifaces [t]; if (type_ifaces == null) type_ifaces = NoTypes; int parent_count = parent_ifaces.Length; - Type [] result = new Type [parent_count + type_ifaces.Length]; + Type[] result = new Type [parent_count + type_ifaces.Length]; parent_ifaces.CopyTo (result, 0); type_ifaces.CopyTo (result, parent_count); + iface_cache [t] = result; return result; - } else - return t.GetInterfaces (); + } else if (t is GenericTypeParameterBuilder){ + Type[] type_ifaces = (Type []) builder_to_ifaces [t]; + if (type_ifaces == null) + type_ifaces = NoTypes; + + iface_cache [t] = type_ifaces; + return type_ifaces; + } else { + Type[] ifaces = t.GetInterfaces (); + iface_cache [t] = ifaces; + return ifaces; + } + } + + // + // gets the interfaces that are declared explicitly on t + // + public static Type [] GetExplicitInterfaces (TypeBuilder t) + { + return (Type []) builder_to_ifaces [t]; } /// @@ -1985,6 +2653,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; } } @@ -2021,28 +2691,18 @@ public class TypeManager { /// /// /// 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' /// public static string IndexerPropertyName (Type t) { - if (t is TypeBuilder) { - if (t.IsInterface) { - Interface 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"; + if (t.IsGenericInstance) + t = t.GetGenericTypeDefinition (); - return tc.IndexerName; - } + if (t is TypeBuilder) { + TypeContainer tc = t.IsInterface ? LookupInterface (t) : LookupTypeContainer (t); + return tc == null ? TypeContainer.DefaultIndexerName : tc.IndexerName; } System.Attribute attr = System.Attribute.GetCustomAttribute ( @@ -2052,18 +2712,30 @@ public class TypeManager { return dma.MemberName; } - return "Item"; + return TypeContainer.DefaultIndexerName; } - public static void MakePinned (LocalBuilder builder) - { - // - // FIXME: Flag the "LocalBuilder" type as being - // pinned. Figure out API. - // + static MethodInfo declare_local_method = null; + + public static LocalBuilder DeclareLocalPinned (ILGenerator ig, Type t) + { + if (declare_local_method == null){ + declare_local_method = typeof (ILGenerator).GetMethod ( + "DeclareLocal", + BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, + null, + new Type [] { typeof (Type), typeof (bool)}, + null); + if (declare_local_method == null){ + Report.Warning (-24, 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); + } + } + return (LocalBuilder) declare_local_method.Invoke (ig, new object [] { t, true }); } - // // Returns whether the array of memberinfos contains the given method // @@ -2106,7 +2778,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 (); @@ -2130,152 +2802,95 @@ public class TypeManager { return target_list; } - [Flags] - public enum MethodFlags { - IsObsolete = 1, - IsObsoleteError = 1 << 1, - ShouldIgnore = 1 << 2 - } - - // - // Returns the TypeManager.MethodFlags for this method. - // This emits an error 619 / warning 618 if the method is obsolete. - // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned. - // - static public MethodFlags GetMethodFlags (MethodBase mb, Location loc) + static public bool IsGenericMethod (MethodBase mb) { - MethodFlags flags = 0; - - if (mb.DeclaringType is TypeBuilder){ - MethodData method = (MethodData) builder_to_method [mb]; - if (method == null) { - // FIXME: implement Obsolete attribute on Property, - // Indexer and Event. - return 0; - } - - return method.GetMethodFlags (loc); - } - -#if FIXME - if (mb.IsInflatedGeneric) { - MethodBase generic = mb.GetGenericMethodDefinition (); - - return GetMethodFlags (generic, loc); - } -#endif - - object [] attrs = mb.GetCustomAttributes (true); - foreach (object ta in attrs){ - if (!(ta is System.Attribute)){ - Console.WriteLine ("Unknown type in GetMethodFlags: " + ta); - 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. - // - if (a.TypeId == TypeManager.conditional_attribute_type){ - ConditionalAttribute ca = (ConditionalAttribute) a; + if (mb.DeclaringType is TypeBuilder) { + IMethodData method = (IMethodData) builder_to_method [mb]; + if (method == null) + return false; - if (RootContext.AllDefines [ca.ConditionString] == null) - flags |= MethodFlags.ShouldIgnore; - } + return method.GenericMethod != null; } - return flags; + return mb.IsGenericMethodDefinition; } #region MemberLookup implementation - // - // Name of the member - // - static string closure_name; - // // Whether we allow private members in the result (since FindMembers // uses NonPublic for both protected and private), we need to distinguish. // - static bool closure_private_ok; - - // - // Who is invoking us and which type is being queried currently. - // - static Type closure_invocation_type; - static Type closure_queried_type; - static Type closure_qualifier_type; - - // - // The assembly that defines the type is that is calling us - // - static Assembly closure_invocation_assembly; static internal bool FilterNone (MemberInfo m, object filter_criteria) { return true; } - - // - // This filter filters by name + whether it is ok to include private - // members in the search - // - static internal bool FilterWithClosure (MemberInfo m, object filter_criteria) - { - // - // Hack: we know that the filter criteria will always be in the `closure' - // fields. - // - if ((filter_criteria != null) && (m.Name != (string) filter_criteria)) - return false; + internal class Closure { + internal bool private_ok; - if (((closure_qualifier_type == null) || (closure_qualifier_type == closure_invocation_type)) && - (m.DeclaringType == closure_invocation_type)) - return true; + // Who is invoking us and which type is being queried currently. + internal Type invocation_type; + internal Type qualifier_type; - // - // Ugly: we need to find out the type of `m', and depending - // on this, tell whether we accept or not - // - if (m is MethodBase){ - MethodBase mb = (MethodBase) m; + // The assembly that defines the type is that is calling us + internal Assembly invocation_assembly; + internal IList almost_match; + + private bool CheckValidFamilyAccess (bool is_static, MemberInfo m) + { + if (invocation_type == null) + return false; + + 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; if (ma == MethodAttributes.Private) - return closure_private_ok || (closure_invocation_type == m.DeclaringType) || - IsNestedChildOf (closure_invocation_type, m.DeclaringType); + return private_ok || + IsPrivateAccessible (invocation_type, mb.DeclaringType) || + IsNestedChildOf (invocation_type, mb.DeclaringType); // // FamAndAssem requires that we not only derivate, but we are on the // same assembly. // if (ma == MethodAttributes.FamANDAssem){ - if (closure_invocation_assembly != mb.DeclaringType.Assembly) + if (invocation_assembly != mb.DeclaringType.Assembly) return false; } // Assembly and FamORAssem succeed if we're in the same assembly. if ((ma == MethodAttributes.Assembly) || (ma == MethodAttributes.FamORAssem)){ - if (closure_invocation_assembly == mb.DeclaringType.Assembly) + if (invocation_assembly == mb.DeclaringType.Assembly) return true; } @@ -2285,17 +2900,18 @@ public class TypeManager { // Family and FamANDAssem require that we derive. if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem)){ - if (closure_invocation_type == null) + if (invocation_type == null) return false; - if (!IsSubclassOrNestedChildOf (closure_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 && (closure_invocation_type != closure_qualifier_type) && - (closure_qualifier_type != null) && - closure_invocation_type.IsSubclassOf (closure_qualifier_type)) + if (!mb.IsStatic && (qualifier_type != null) && + !IsEqualGenericInstance (invocation_type, qualifier_type) && + TypeManager.IsFamilyAccessible (invocation_type, qualifier_type) && + !TypeManager.IsNestedChildOf (invocation_type, qualifier_type)) return false; return true; @@ -2305,26 +2921,27 @@ public class TypeManager { return true; } - if (m is FieldInfo){ - FieldInfo fi = (FieldInfo) m; + bool Filter (FieldInfo fi, object filter_criteria) + { FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask; if (fa == FieldAttributes.Private) - return closure_private_ok || (closure_invocation_type == m.DeclaringType) || - IsNestedChildOf (closure_invocation_type, m.DeclaringType); + return private_ok || + IsPrivateAccessible (invocation_type, fi.DeclaringType) || + IsNestedChildOf (invocation_type, fi.DeclaringType); // // FamAndAssem requires that we not only derivate, but we are on the // same assembly. // if (fa == FieldAttributes.FamANDAssem){ - if (closure_invocation_assembly != fi.DeclaringType.Assembly) + if (invocation_assembly != fi.DeclaringType.Assembly) return false; } // Assembly and FamORAssem succeed if we're in the same assembly. if ((fa == FieldAttributes.Assembly) || (fa == FieldAttributes.FamORAssem)){ - if (closure_invocation_assembly == fi.DeclaringType.Assembly) + if (invocation_assembly == fi.DeclaringType.Assembly) return true; } @@ -2334,17 +2951,18 @@ public class TypeManager { // Family and FamANDAssem require that we derive. if ((fa == FieldAttributes.Family) || (fa == FieldAttributes.FamANDAssem)){ - if (closure_invocation_type == null) + if (invocation_type == null) return false; - if (!IsSubclassOrNestedChildOf (closure_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 && (closure_invocation_type != closure_qualifier_type) && - (closure_qualifier_type != null) && - closure_invocation_type.IsSubclassOf (closure_qualifier_type)) + if (!fi.IsStatic && (qualifier_type != null) && + !IsEqualGenericInstance (invocation_type, qualifier_type) && + TypeManager.IsFamilyAccessible (invocation_type, qualifier_type) && + !TypeManager.IsNestedChildOf (invocation_type, qualifier_type)) return false; return true; @@ -2353,16 +2971,46 @@ public class TypeManager { // Public. return true; } - + // - // EventInfos and PropertyInfos, return true because they lack permission - // informaiton, so we need to check later on the methods. + // This filter filters by name + whether it is ok to include private + // members in the search // - return true; + internal bool Filter (MemberInfo m, object filter_criteria) + { + // + // Hack: we know that the filter criteria will always be in the + // `closure' // fields. + // + + if ((filter_criteria != null) && (m.Name != (string) filter_criteria)) + return false; + + if (((qualifier_type == null) || (qualifier_type == invocation_type)) && + (invocation_type != null) && + IsPrivateAccessible (m.DeclaringType, invocation_type)) + return true; + + // + // Ugly: we need to find out the type of `m', and depending + // on this, tell whether we accept or not + // + if (m is MethodBase) + return Filter ((MethodBase) m, filter_criteria); + + if (m is FieldInfo) + return Filter ((FieldInfo) m, filter_criteria); + + // + // EventInfos and PropertyInfos, return true because they lack + // permission information, so we need to check later on the methods. + // + return true; + } } - static MemberFilter FilterWithClosure_delegate = new MemberFilter (FilterWithClosure); - static MemberFilter FilterNone_delegate = new MemberFilter (FilterNone); + static Closure closure = new Closure (); + static MemberFilter FilterWithClosure_delegate = new MemberFilter (closure.Filter); // // Looks up a member called `name' in the `queried_type'. This lookup @@ -2389,17 +3037,19 @@ public class TypeManager { // is allowed to access (using the specified `qualifier_type' if given); only use // BindingFlags.NonPublic to bypass the permission check. // + // The 'almost_match' argument is used for reporting error CS1540. + // // Returns an array of a single element for everything but Methods/Constructors // that might return multiple matches. // public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type, - Type queried_type, MemberTypes mt, - BindingFlags original_bf, string name) + Type queried_type, MemberTypes mt, + BindingFlags original_bf, string name, IList almost_match) { Timer.StartTimer (TimerType.MemberLookup); MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type, - queried_type, mt, original_bf, name); + queried_type, mt, original_bf, name, almost_match); Timer.StopTimer (TimerType.MemberLookup); @@ -2408,7 +3058,7 @@ public class TypeManager { static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type, Type queried_type, MemberTypes mt, - BindingFlags original_bf, string name) + BindingFlags original_bf, string name, IList almost_match) { BindingFlags bf = original_bf; @@ -2418,10 +3068,10 @@ public class TypeManager { bool skip_iface_check = true, used_cache = false; bool always_ok_flag = false; - closure_name = name; - closure_invocation_type = invocation_type; - closure_invocation_assembly = invocation_type != null ? invocation_type.Assembly : null; - closure_qualifier_type = qualifier_type; + closure.invocation_type = invocation_type; + closure.invocation_assembly = invocation_type != null ? invocation_type.Assembly : null; + closure.qualifier_type = qualifier_type; + closure.almost_match = almost_match; // // If we are a nested class, we always have access to our container @@ -2429,7 +3079,7 @@ public class TypeManager { // 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; @@ -2442,8 +3092,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 @@ -2462,12 +3118,12 @@ public class TypeManager { else bf = original_bf; - closure_private_ok = (original_bf & BindingFlags.NonPublic) != 0; - closure_queried_type = current_type; + closure.private_ok = (original_bf & BindingFlags.NonPublic) != 0; Timer.StopTimer (TimerType.MemberLookup); - list = MemberLookup_FindMembers (current_type, mt, bf, name, out used_cache); + list = MemberLookup_FindMembers ( + current_type, mt, bf, name, out used_cache); Timer.StartTimer (TimerType.MemberLookup); @@ -2498,7 +3154,7 @@ public class TypeManager { current_type = TypeManager.object_type; } - if (list.Count == 0) + if (list.Length == 0) continue; // @@ -2506,8 +3162,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; } // @@ -2515,14 +3171,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 @@ -2534,10 +3190,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)); } @@ -2565,7 +3242,7 @@ public class TypeManager { foreach (Type itype in ifaces){ MemberInfo [] x; - x = MemberLookup (null, null, itype, mt, bf, name); + x = MemberLookup (null, null, itype, mt, bf, name, null); if (x != null) return x; } @@ -2573,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); + string name = mb.Name; + if (name.StartsWith ("get_") || name.StartsWith ("set_")) + return mb.DeclaringType.GetProperty (name.Substring (4)) != null; - foreach (MethodInfo m in methods){ - if (m == mb) - return true; - } - } else if (mi is MyEventBuilder){ - Pair p = (Pair) events [mi]; + if (name.StartsWith ("add_")) + return mb.DeclaringType.GetEvent (name.Substring (4)) != null; - 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; - - if (ei.GetRaiseMethod (true) == mb) - return true; - } - } + if (name.StartsWith ("remove_")) + return mb.DeclaringType.GetEvent (name.Substring (7)) != null; - // - // Now check if it is an operator method - // - string s = mb.Name; - - 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; } @@ -2683,6 +3305,11 @@ public sealed class TypeHandle : IMemberContainer { type_hash.Add (t, handle); return handle; } + + public static void CleanUp () + { + type_hash = null; + } /// /// Returns the TypeHandle for TypeManager.object_type. @@ -2718,15 +3345,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); } @@ -2734,7 +3363,7 @@ public sealed class TypeHandle : IMemberContainer { public string Name { get { - return type.FullName; + return full_name; } } @@ -2744,7 +3373,7 @@ public sealed class TypeHandle : IMemberContainer { } } - public IMemberContainer Parent { + public IMemberContainer ParentContainer { get { return BaseType; } @@ -2759,6 +3388,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 @@ -2774,7 +3405,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 {