- //
- // These are only used for compare purposes
- //
- null_type = typeof (NullLiteral);
-
- void_ptr_type = GetPointerType (void_type);
-
- //
- // Initialize InternalsVisibleTo as the very first optional type. Otherwise we would populate
- // types cache with incorrect accessiblity when any of optional types is internal.
- //
- PredefinedAttributes.Get.Initialize (ctx);
-
- runtime_argument_handle_type = CoreLookupType (ctx, "System", "RuntimeArgumentHandle", Kind.Struct, false);
- asynccallback_type = CoreLookupType (ctx, "System", "AsyncCallback", Kind.Delegate, false);
- iasyncresult_type = CoreLookupType (ctx, "System", "IAsyncResult", Kind.Interface, false);
- typed_reference_type = CoreLookupType (ctx, "System", "TypedReference", Kind.Struct, false);
- arg_iterator_type = CoreLookupType (ctx, "System", "ArgIterator", Kind.Struct, false);
- mbr_type = CoreLookupType (ctx, "System", "MarshalByRefObject", Kind.Class, false);
-
- //
- // Optional attributes, used for error reporting only
- //
- //if (PredefinedAttributes.Get.Obsolete.IsDefined) {
- // Class c = TypeManager.LookupClass (PredefinedAttributes.Get.Obsolete.Type);
- // if (c != null)
- // c.Define ();
- //}
-
- generic_ilist_type = CoreLookupType (ctx, "System.Collections.Generic", "IList`1", Kind.Interface, false);
- generic_icollection_type = CoreLookupType (ctx, "System.Collections.Generic", "ICollection`1", Kind.Interface, false);
- generic_ienumerable_type = CoreLookupType (ctx, "System.Collections.Generic", "IEnumerable`1", Kind.Interface, false);
- generic_nullable_type = CoreLookupType (ctx, "System", "Nullable`1", Kind.Struct, false);
-
- //
- // Optional types which are used as types and for member lookup
- //
- runtime_helpers_type = CoreLookupType (ctx, "System.Runtime.CompilerServices", "RuntimeHelpers", Kind.Class, false);
-
- // New in .NET 3.5
- // Note: extension_attribute_type is already loaded
- expression_type = CoreLookupType (ctx, "System.Linq.Expressions", "Expression`1", Kind.Class, false);
-
- if (!RootContext.StdLib) {
- //
- // HACK: When building Mono corlib mcs uses loaded mscorlib which
- // has different predefined types and this method sets mscorlib types
- // to be same to avoid any type check errors.
- //
-
- Type type = typeof (Type);
- Type [] system_4_type_arg = { type, type, type, type };
-
- MethodInfo set_corlib_type_builders =
- typeof (System.Reflection.Emit.AssemblyBuilder).GetMethod (
- "SetCorlibTypeBuilders", BindingFlags.NonPublic | BindingFlags.Instance, null,
- system_4_type_arg, null);
-
- if (set_corlib_type_builders != null) {
- object[] args = new object [4];
- args [0] = object_type;
- args [1] = value_type;
- args [2] = enum_type;
- args [3] = void_type;
-
- set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
- } else {
- ctx.Report.Warning (-26, 3, "The compilation may fail due to missing `{0}.SetCorlibTypeBuilders({1})' method",
- TypeManager.CSharpName (typeof (System.Reflection.Emit.AssemblyBuilder)),
- TypeManager.CSharpName (system_4_type_arg));
- }
- }
- }
-
- const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
-
- /// <remarks>
- /// This is the "old", non-cache based FindMembers() function. We cannot use
- /// the cache here because there is no member name argument.
- /// </remarks>
- public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
- MemberFilter filter, object criteria)
- {
-#if MS_COMPATIBLE
- if (t.IsGenericType)
- t = t.GetGenericTypeDefinition ();
-#endif
-
- DeclSpace decl = (DeclSpace) builder_to_declspace [t];
-
- //
- // `builder_to_declspace' contains all dynamic types.
- //
- if (decl != null) {
- MemberList list;
- Timer.StartTimer (TimerType.FindMembers);
- list = decl.FindMembers (mt, bf, filter, criteria);
- Timer.StopTimer (TimerType.FindMembers);
- return list;
- }
-
- //
- // We have to take care of arrays specially, because GetType on
- // a TypeBuilder array will return a Type, not a TypeBuilder,
- // and we can not call FindMembers on this type.
- //
- if (
-#if MS_COMPATIBLE
- !t.IsGenericType &&
-#endif
- 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.
- //
- if ((bf & instance_and_static) == instance_and_static){
- MemberInfo [] i_members = t.FindMembers (
- mt, bf & ~BindingFlags.Static, filter, criteria);
-
- int i_len = i_members.Length;
- if (i_len == 1){
- MemberInfo one = i_members [0];
-
- //
- // If any of these are present, we are done!
- //
- if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
- return new MemberList (i_members);
- }
-
- MemberInfo [] s_members = t.FindMembers (
- mt, bf & ~BindingFlags.Instance, filter, criteria);
-
- int s_len = s_members.Length;
- if (i_len > 0 || s_len > 0)
- return new MemberList (i_members, s_members);
- else {
- if (i_len > 0)
- return new MemberList (i_members);
- else
- return new MemberList (s_members);
- }
- }
-
- return new MemberList (t.FindMembers (mt, bf, filter, criteria));
- }
-
-
- /// <summary>
- /// This method is only called from within MemberLookup. It tries to use the member
- /// cache if possible and falls back to the normal FindMembers if not. The `used_cache'
- /// flag tells the caller whether we used the cache or not. If we used the cache, then
- /// our return value will already contain all inherited members and the caller don't need
- /// to check base classes and interfaces anymore.
- /// </summary>
- private static MemberInfo [] MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
- string name, out bool used_cache)
- {
- MemberCache cache;
-
- //
- // If this is a dynamic type, it's always in the `builder_to_declspace' hash table
- // and we can ask the DeclSpace for the MemberCache.
- //
-#if MS_COMPATIBLE
- if (t.Assembly == CodeGen.Assembly.Builder) {
- if (t.IsGenericParameter) {
- TypeParameter tparam = (TypeParameter) builder_to_type_param[t];
-
- used_cache = true;
- if (tparam.MemberCache == null)
- return new MemberInfo[0];
-
- return tparam.MemberCache.FindMembers (
- mt, bf, name, FilterWithClosure_delegate, null);
- }
-
- //
- // We have to take care of arrays specially, because GetType on
- // a TypeBuilder array will return a Type, not a TypeBuilder,
- // and we can not call FindMembers on this type.
- //
- if (t.IsArray) {
- used_cache = true;
- return TypeHandle.ArrayType.MemberCache.FindMembers (
- mt, bf, name, FilterWithClosure_delegate, null);
- }
-
- if (t.IsGenericType && !t.IsGenericTypeDefinition)
- t = t.GetGenericTypeDefinition ();
-#else
- if (t is TypeBuilder) {
-#endif
- DeclSpace decl = (DeclSpace) builder_to_declspace [t];
- cache = decl.MemberCache;
-
- //
- // If this DeclSpace has a MemberCache, use it.
- //
-
- if (cache != null) {
- used_cache = true;
- return cache.FindMembers (
- mt, bf, name, FilterWithClosure_delegate, null);
- }
-
- // 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);
- list = decl.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
- FilterWithClosure_delegate, name);
- Timer.StopTimer (TimerType.FindMembers);
- used_cache = false;
- return (MemberInfo []) list;
- }
-
- //
- // We have to take care of arrays specially, because GetType on
- // a TypeBuilder array will return a Type, not a TypeBuilder,
- // and we can not call FindMembers on this type.
- //
- if (t.IsArray) {
- used_cache = true;
- return TypeHandle.ArrayType.MemberCache.FindMembers (
- mt, bf, name, FilterWithClosure_delegate, null);
- }
-
- if (t is GenericTypeParameterBuilder) {
- TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
-
- used_cache = true;
- if (tparam.MemberCache == null)
- return new MemberInfo [0];
-
- return tparam.MemberCache.FindMembers (
- mt, bf, name, FilterWithClosure_delegate, null);
- }
-
- if (IsGenericType (t) && (mt == MemberTypes.NestedType)) {
- //
- // This happens if we're resolving a class'es base class and interfaces
- // in TypeContainer.DefineType(). At this time, the types aren't
- // populated yet, so we can't use the cache.
- //
- MemberInfo[] info = t.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
- FilterWithClosure_delegate, name);
- used_cache = false;
- return info;
- }
-
- //
- // This call will always succeed. There is exactly one TypeHandle instance per
- // type, TypeHandle.GetMemberCache() will, if necessary, create a new one, and return
- // the corresponding MemberCache.
- //
- cache = TypeHandle.GetMemberCache (t);
-
- used_cache = true;
- return cache.FindMembers (mt, bf, name, FilterWithClosure_delegate, null);
- }
-
- //
- // Return true for SRE dynamic/unclosed members
- //
- public static bool IsBeingCompiled (MemberInfo mi)
- {
- return mi.Module.Assembly == CodeGen.Assembly.Builder;
- }
-
- public static bool IsBuiltinType (Type t)
- {
- t = TypeToCoreType (t);
- if (t == object_type || t == string_type || 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 == decimal_type || t == bool_type ||
- t == sbyte_type || t == byte_type || t == ushort_type || t == void_type)
- return true;
- else
- return false;
- }
-
- //
- // 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 IsPrimitiveType (Type t)
- {
- 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);
- }
-
- public static bool IsDelegateType (Type t)
- {
- if (TypeManager.IsGenericParameter (t))
- return false;
-
- if (t == TypeManager.delegate_type || t == TypeManager.multicast_delegate_type)
- return false;
-
- t = DropGenericTypeArguments (t);
- return IsSubclassOf (t, TypeManager.delegate_type);
- }
-
- //
- // Is a type of dynamic type
- //
- public static bool IsDynamicType (Type t)
- {
- if (object.ReferenceEquals (InternalType.Dynamic, t))
- return true;
-
- if (t != object_type)
- return false;
-
- if (IsBeingCompiled (t))
- return false;
-
- PredefinedAttribute pa = PredefinedAttributes.Get.Dynamic;
- if (pa == null)
- return false;
-
- object[] res = t.GetCustomAttributes (pa.Type, false);
- return res != null && res.Length != 0;
- }
-
- //
- // When any element of the type is a dynamic type
- //
- // This method builds a transformation array for dynamic types
- // used in places where DynamicAttribute cannnot be applied to.
- // It uses bool flag when type is of dynamic type and each
- // section always starts with "false" for some reason.
- //
- // LAMESPEC: This should be part of C# specification !
- //
- // Example: Func<dynamic, int, dynamic[]>
- // Transformation: { false, true, false, false, true }
- //
- public static bool[] HasDynamicTypeUsed (Type t)
- {
- if (t is DynamicArrayType)
- return new bool[] { false, true };
-
- if (t == null)
- return null;
-
- if (IsGenericType (t)) {
- List<bool> transform = null;
- var targs = GetTypeArguments (t);
- for (int i = 0; i < targs.Length; ++i) {
- var element = HasDynamicTypeUsed (targs [i]);
- if (element != null) {
- if (transform == null) {
- transform = new List<bool> ();
- for (int ii = 0; ii <= i; ++ii)
- transform.Add (false);
- }
-
- transform.AddRange (element);
- } else if (transform != null) {
- transform.Add (false);
- }
- }
-
- if (transform != null)
- return transform.ToArray ();
- }
-
- if (object.ReferenceEquals (InternalType.Dynamic, t))
- return new bool [] { true };
-
- return null;
- }
-
- public static bool IsEnumType (Type t)
- {
- t = DropGenericTypeArguments (t);
- return t.BaseType == TypeManager.enum_type;
- }
-
- public static bool IsBuiltinOrEnum (Type t)
- {
- if (IsBuiltinType (t))
- return true;
-
- if (IsEnumType (t))
- return true;
-
- return false;
- }
-
- public static bool IsAttributeType (Type t)
- {
- return t == attribute_type && t.BaseType != null || IsSubclassOf (t, attribute_type);
- }
-
- //
- // Whether a type is unmanaged. This is used by the unsafe code (25.2)
- //
- // mcs4: delete, DeclSpace.IsUnmanagedType is replacement
- public static bool IsUnmanagedType (Type t)
- {
- DeclSpace ds = TypeManager.LookupDeclSpace (t);
- if (ds != null)
- return ds.IsUnmanagedType ();
-
- // builtins that are not unmanaged types
- if (t == TypeManager.object_type || t == TypeManager.string_type)
- return false;
-
- if (IsGenericType (t) || IsGenericParameter (t))
- return false;
-
- 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 IsUnmanagedType (GetElementType (t));
-
- // Arrays are disallowed, even if we mark them with [MarshalAs(UnmanagedType.ByValArray, ...)]
- if (t.IsArray)
- return false;
-
- if (!IsValueType (t))
- return false;
-
- for (Type p = t.DeclaringType; p != null; p = p.DeclaringType) {
- if (IsGenericTypeDefinition (p))
- return false;
- }
-
- bool retval = true;
- {
- FieldInfo [] fields = t.GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
-
- foreach (FieldInfo f in fields){
- if (!IsUnmanagedType (f.FieldType)){
- retval = false;
- }
- }
- }
-
- return retval;
- }
-
- //
- // Null is considered to be a reference type
- //
- public static bool IsReferenceType (Type t)
- {
- if (TypeManager.IsGenericParameter (t)) {
- GenericConstraints constraints = TypeManager.GetTypeParameterConstraints (t);
- if (constraints == null)
- return false;
-
- return constraints.IsReferenceType;
- }
-
- return !IsStruct (t) && !IsEnumType (t);
- }
-
- public static bool IsValueType (Type t)
- {
- if (TypeManager.IsGenericParameter (t)) {
- GenericConstraints constraints = TypeManager.GetTypeParameterConstraints (t);
- if (constraints == null)
- return false;
-
- return constraints.IsValueType;
- }
-
- return IsStruct (t) || IsEnumType (t);
- }
-
- public static bool IsStruct (Type t)
- {
- return t.BaseType == value_type && t != enum_type && t.IsSealed;
- }
-
- public static bool IsInterfaceType (Type t)
- {
- TypeContainer tc = (TypeContainer) builder_to_declspace [t];
- if (tc == null)
- return false;
-
- return tc.Kind == Kind.Interface;
- }
-
- public static bool IsSubclassOf (Type type, Type base_type)
- {
- TypeParameter tparam = LookupTypeParameter (type);
- TypeParameter pparam = LookupTypeParameter (base_type);
-
- if ((tparam != null) && (pparam != null)) {
- if (tparam == pparam)
- return true;
-
- return tparam.IsSubclassOf (base_type);
- }
-
-#if MS_COMPATIBLE
- if (tparam != pparam)
- return false;
-
- if (type.IsGenericType)
- type = type.GetGenericTypeDefinition ();
-#endif
-
- if (type.IsSubclassOf (base_type))
- return true;
-
- do {
- if (IsEqual (type, base_type))
- return true;
-
- type = type.BaseType;
- } while (type != null);
-
- return false;
- }
-
- public static bool IsPrivateAccessible (Type type, Type parent)
- {
- if (type == null)
- return false;
-
- if (type.Equals (parent))
- return true;
-
- return DropGenericTypeArguments (type) == DropGenericTypeArguments (parent);
- }
-
- 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 (IsInstantiationOfSameGenericType (type, parent))
- return true;
-
- type = type.BaseType;
- } while (type != null);
-
- return false;
- }
-
- //
- // Checks whether `type' is a subclass or nested child of `base_type'.
- //
- public static bool IsNestedFamilyAccessible (Type type, Type base_type)
- {
- do {
- if (IsFamilyAccessible (type, base_type))
- 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 (type == null)
- return false;
-
- type = DropGenericTypeArguments (type);
- parent = DropGenericTypeArguments (parent);
-
- if (IsEqual (type, parent))
- return false;
-
- type = type.DeclaringType;
- while (type != null) {
- if (IsEqual (type, parent))
- return true;
-
- type = type.DeclaringType;
- }
-
- return false;
- }
-
- public static bool IsSpecialType (Type t)
- {
- return t == arg_iterator_type || t == typed_reference_type;
- }
-
- //
- // Checks whether `invocationAssembly' is same or a friend of the assembly
- //
- public static bool IsThisOrFriendAssembly (Assembly invocationAssembly, Assembly assembly)
- {
- if (assembly == null)
- throw new ArgumentNullException ("assembly");
-
- // TODO: This can happen for constants used at assembly level and
- // predefined members
- // But there is no way to test for it for now, so it could be abused
- // elsewhere too.
- if (invocationAssembly == null)
- invocationAssembly = CodeGen.Assembly.Builder;
-
- if (invocationAssembly == assembly)
- return true;
-
- if (assembly_internals_vis_attrs.Contains (assembly))
- return (bool)(assembly_internals_vis_attrs [assembly]);
-
- PredefinedAttribute pa = PredefinedAttributes.Get.InternalsVisibleTo;
- // HACK: Do very early resolve of SRE type checking
- if (pa.Type == null)
- pa.Resolve (true);
-
- if (!pa.IsDefined)
- return false;
-
- object [] attrs = assembly.GetCustomAttributes (pa.Type, false);
- if (attrs.Length == 0) {
- assembly_internals_vis_attrs.Add (assembly, false);
- return false;
- }
-
- bool is_friend = false;
-
- AssemblyName this_name = CodeGen.Assembly.Name;
- byte [] this_token = this_name.GetPublicKeyToken ();
- foreach (InternalsVisibleToAttribute attr in attrs) {
- if (attr.AssemblyName == null || attr.AssemblyName.Length == 0)
- continue;
-
- AssemblyName aname = null;
- try {
- aname = new AssemblyName (attr.AssemblyName);
- } catch (FileLoadException) {
- } catch (ArgumentException) {
- }
-
- if (aname == null || aname.Name != this_name.Name)
- continue;
-
- byte [] key_token = aname.GetPublicKeyToken ();
- if (key_token != null) {
- if (this_token.Length == 0) {
- // Same name, but assembly is not strongnamed
- Error_FriendAccessNameNotMatching (aname.FullName, RootContext.ToplevelTypes.Compiler.Report);
- break;
- }
-
- if (!CompareKeyTokens (this_token, key_token))
- continue;
- }
-
- is_friend = true;
- break;
- }
-
- assembly_internals_vis_attrs.Add (assembly, is_friend);
- return is_friend;
- }
-
- static bool CompareKeyTokens (byte [] token1, byte [] token2)
- {
- for (int i = 0; i < token1.Length; i++)
- if (token1 [i] != token2 [i])
- return false;
-
- return true;
- }
-
- static void Error_FriendAccessNameNotMatching (string other_name, Report Report)
- {
- Report.Error (281,
- "Friend access was granted to `{0}', but the output assembly is named `{1}'. Try adding a reference to `{0}' or change the output assembly name to match it",
- other_name, CodeGen.Assembly.Name.FullName);
- }
-
- //
- // 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 ());
- }
-
- /// <summary>
- /// This method is not implemented by MS runtime for dynamic types
- /// </summary>
- public static bool HasElementType (Type t)
- {
- return t.IsArray || t.IsPointer || t.IsByRef;
- }
-
- public static Type GetEnumUnderlyingType (Type t)
- {
- t = DropGenericTypeArguments (t);
- Enum e = LookupTypeContainer (t) as Enum;
- if (e != null)
- return e.UnderlyingType;
-
- // TODO: cache it ?
- FieldInfo fi = GetPredefinedField (t, Enum.UnderlyingValueField, Location.Null, Type.EmptyTypes);
- if (fi == null)
- return TypeManager.int32_type;
-
- return TypeToCoreType (fi.FieldType);
- }
-
- /// <summary>
- /// Gigantic work around for missing features in System.Reflection.Emit follows.
- /// </summary>
- ///
- /// <remarks>
- /// Since System.Reflection.Emit can not return MethodBase.GetParameters
- /// for anything which is dynamic, and we need this in a number of places,
- /// we register this information here, and use it afterwards.
- /// </remarks>
- static public void RegisterMethod (MethodBase mb, AParametersCollection ip)
- {
- method_params.Add (mb, ip);
- }
-
- static public void RegisterIndexer (PropertyBuilder pb, AParametersCollection p)
- {
- method_params.Add (pb, p);
- }
-
- static public AParametersCollection GetParameterData (MethodBase mb)
- {
- AParametersCollection pd = (AParametersCollection) method_params [mb];
- if (pd == null) {
-#if MS_COMPATIBLE
- if (mb.IsGenericMethod && !mb.IsGenericMethodDefinition) {
- MethodInfo mi = ((MethodInfo) mb).GetGenericMethodDefinition ();
- pd = GetParameterData (mi);
- /*
- if (mi.IsGenericMethod)
- pd = pd.InflateTypes (mi.GetGenericArguments (), mb.GetGenericArguments ());
- else
- pd = pd.InflateTypes (mi.DeclaringType.GetGenericArguments (), mb.GetGenericArguments ());
- */
- method_params.Add (mb, pd);
- return pd;
- }
-
- if (mb.DeclaringType.Assembly == CodeGen.Assembly.Builder) {
- throw new InternalErrorException ("Parameters are not registered for method `{0}'",
- TypeManager.CSharpName (mb.DeclaringType) + "." + mb.Name);
- }
-
- pd = ParametersImported.Create (mb);
-#else
- MethodBase generic = TypeManager.DropGenericMethodArguments (mb);
- if (generic != mb) {
- pd = TypeManager.GetParameterData (generic);
- pd = ParametersImported.Create (pd, mb);
- } else {
- pd = ParametersImported.Create (mb);
- }
-#endif
- method_params.Add (mb, pd);
- }
- return pd;
- }
-
- public static AParametersCollection GetParameterData (PropertyInfo pi)
- {
- AParametersCollection pd = (AParametersCollection)method_params [pi];
- if (pd == null) {
- if (pi is PropertyBuilder)
- return ParametersCompiled.EmptyReadOnlyParameters;
-
- ParameterInfo [] p = pi.GetIndexParameters ();
- if (p == null)
- return ParametersCompiled.EmptyReadOnlyParameters;
-
- pd = ParametersImported.Create (p, null);
- method_params.Add (pi, pd);
- }
-
- return pd;
- }
-
- public static AParametersCollection GetDelegateParameters (ResolveContext ec, Type t)
- {
- Delegate d = builder_to_declspace [t] as Delegate;
- if (d != null)
- return d.Parameters;
-
- MethodInfo invoke_mb = Delegate.GetInvokeMethod (ec.Compiler, t, t);
- return GetParameterData (invoke_mb);
- }
-
- static public void RegisterOverride (MethodBase override_method, MethodBase base_method)
- {
- if (!method_overrides.Contains (override_method))
- method_overrides [override_method] = base_method;
- if (method_overrides [override_method] != base_method)
- throw new InternalErrorException ("Override mismatch: " + override_method);
- }
-
- static public bool IsOverride (MethodBase m)
- {
- m = DropGenericMethodArguments (m);
-
- return m.IsVirtual &&
- (m.Attributes & MethodAttributes.NewSlot) == 0 &&
- (m is MethodBuilder || method_overrides.Contains (m));
- }
-
- static public MethodBase TryGetBaseDefinition (MethodBase m)
- {
- m = DropGenericMethodArguments (m);
-
- return (MethodBase) method_overrides [m];
- }
-
- public static void RegisterConstant (FieldInfo fb, IConstant ic)
- {
- fields.Add (fb, ic);
- }
-
- public static IConstant GetConstant (FieldInfo fb)
- {
- if (fb == null)
- return null;
-
- return (IConstant)fields [fb];
- }
-
- public static void RegisterProperty (PropertyInfo pi, PropertyBase pb)
- {
- propertybuilder_to_property.Add (pi, pb);
- }
-
- public static PropertyBase GetProperty (PropertyInfo pi)
- {
- return (PropertyBase)propertybuilder_to_property [pi];
- }
-
- static public void RegisterFieldBase (FieldBuilder fb, FieldBase f)
- {
- fieldbuilders_to_fields.Add (fb, f);
- }
-
- //
- // The return value can be null; This will be the case for
- // auxiliary FieldBuilders created by the compiler that have no
- // real field being declared on the source code
- //
- static public FieldBase GetField (FieldInfo fb)
- {
- fb = GetGenericFieldDefinition (fb);
- return (FieldBase) fieldbuilders_to_fields [fb];
- }
-
- static public MethodInfo GetAddMethod (EventInfo ei)
- {
- if (ei is MyEventBuilder) {
- return ((MyEventBuilder)ei).GetAddMethod (true);
- }
- return ei.GetAddMethod (true);
- }
-
- static public MethodInfo GetRemoveMethod (EventInfo ei)
- {
- if (ei is MyEventBuilder) {
- return ((MyEventBuilder)ei).GetRemoveMethod (true);
- }
- return ei.GetRemoveMethod (true);
- }
-
- static public void RegisterEventField (EventInfo einfo, EventField e)
- {
- if (events == null)
- events = new Hashtable ();
-
- events.Add (einfo, e);
- }
-
- static public EventField GetEventField (EventInfo ei)
- {
- if (events == null)
- return null;
-
- return (EventField) events [ei];
- }
-
- 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.TypeBuilder))
- 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 (FieldBase field in tc.Fields) {
- if (field.FieldBuilder == null || field.FieldBuilder.IsStatic)
- continue;
-
- Type ftype = field.FieldBuilder.FieldType;
- TypeContainer ftc = LookupTypeContainer (ftype);
- if (ftc == null)
- continue;
-
- if (hash.Contains (ftc)) {
- tc.Compiler.Report.Error (523, tc.Location,
- "Struct member `{0}.{1}' of type `{2}' " +
- "causes a cycle in the struct layout",
- tc.Name, field.Name, ftc.Name);
- return false;
- }
-
- //
- // `hash' contains all types in the current path.
- //
- hash.Add (tc, null);
-
- bool ok = CheckStructCycles (ftc, seen, hash);
-
- hash.Remove (tc);
-
- if (!ok)
- return false;
-
- if (!seen.Contains (ftc))
- seen.Add (ftc, null);
- }
-
- return true;
- }
-
- /// <summary>
- /// Given an array of interface types, expand and eliminate repeated ocurrences
- /// of an interface.
- /// </summary>
- ///
- /// <remarks>
- /// This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
- /// be IA, IB, IC.
- /// </remarks>
- public static Type[] ExpandInterfaces (TypeExpr [] base_interfaces)
- {
- ArrayList new_ifaces = new ArrayList ();
-
- foreach (TypeExpr iface in base_interfaces){
- Type itype = iface.Type;
-
- if (new_ifaces.Contains (itype))
- continue;
-
- new_ifaces.Add (itype);
-
- Type [] implementing = GetInterfaces (itype);
-
- foreach (Type imp in implementing){
- if (!new_ifaces.Contains (imp))
- new_ifaces.Add (imp);
- }
- }
- Type [] ret = new Type [new_ifaces.Count];
- new_ifaces.CopyTo (ret, 0);
- return ret;
- }
-
- public static Type[] ExpandInterfaces (Type [] base_interfaces)
- {
- ArrayList new_ifaces = new ArrayList ();
-
- foreach (Type itype in base_interfaces){
- if (new_ifaces.Contains (itype))
- continue;
-
- new_ifaces.Add (itype);
-
- Type [] implementing = GetInterfaces (itype);
-
- foreach (Type imp in implementing){
- if (!new_ifaces.Contains (imp))
- new_ifaces.Add (imp);
- }
- }
- Type [] ret = new Type [new_ifaces.Count];
- new_ifaces.CopyTo (ret, 0);
- return ret;
- }
-
- static PtrHashtable iface_cache;
-
- /// <summary>
- /// This function returns the interfaces in the type `t'. Works with
- /// both types and TypeBuilders.
- /// </summary>
- 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,
- // but will still throw an exception if we try to call GetInterfaces
- // on the type.
- //
- // Since the array interfaces are always constant, we return those for
- // the System.Array
- //
-
- if (t.IsArray)
- t = TypeManager.array_type;
-
- if ((t is TypeBuilder) || IsGenericType (t)) {
- Type [] base_ifaces;
-
- if (t.BaseType == null)
- base_ifaces = Type.EmptyTypes;
- else
- base_ifaces = GetInterfaces (t.BaseType);
- Type[] type_ifaces;
- if (IsGenericType (t))
-#if MS_COMPATIBLE
- type_ifaces = t.GetGenericTypeDefinition().GetInterfaces ();
-#else
- type_ifaces = t.GetInterfaces ();
-#endif
- else
- type_ifaces = (Type []) builder_to_ifaces [t];
- if (type_ifaces == null || type_ifaces.Length == 0)
- type_ifaces = Type.EmptyTypes;
-
- int base_count = base_ifaces.Length;
- Type [] result = new Type [base_count + type_ifaces.Length];
- base_ifaces.CopyTo (result, 0);
- type_ifaces.CopyTo (result, base_count);
-
- iface_cache [t] = result;
- return result;
- } else if (t is GenericTypeParameterBuilder){
- Type[] type_ifaces = (Type []) builder_to_ifaces [t];
- if (type_ifaces == null || type_ifaces.Length == 0)
- type_ifaces = Type.EmptyTypes;
-
- 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];
- }
-
- /// <remarks>
- /// The following is used to check if a given type implements an interface.
- /// The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
- /// </remarks>
- public static bool ImplementsInterface (Type t, Type iface)
- {
- Type [] interfaces;
-
- //
- // FIXME OPTIMIZATION:
- // as soon as we hit a non-TypeBuiler in the interface
- // chain, we could return, as the `Type.GetInterfaces'
- // will return all the interfaces implement by the type
- // or its bases.
- //
- do {
- interfaces = GetInterfaces (t);
-
- if (interfaces != null){
- foreach (Type i in interfaces){
- if (i == iface || IsVariantOf (i, iface))
- return true;
- }
- }
-
- t = t.BaseType;
- } while (t != null);
-
- return false;
- }
-
- static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat;
-
- // This is a custom version of Convert.ChangeType() which works
- // with the TypeBuilder defined types when compiling corlib.
- public static object ChangeType (object value, Type conversionType, out bool error)
- {
- IConvertible convert_value = value as IConvertible;
-
- if (convert_value == null){
- error = true;
- return null;
- }
-
- //
- // NOTE 1:
- // We must use Type.Equals() here since `conversionType' is
- // the TypeBuilder created version of a system type and not
- // the system type itself. You cannot use Type.GetTypeCode()
- // on such a type - it'd always return TypeCode.Object.
- //
- // NOTE 2:
- // We cannot rely on build-in type conversions as they are
- // more limited than what C# supports.
- // See char -> float/decimal/double conversion
- //
-
- error = false;
- try {
- if (conversionType.Equals (typeof (Boolean)))
- return (object)(convert_value.ToBoolean (nf_provider));
- if (conversionType.Equals (typeof (Byte)))
- return (object)(convert_value.ToByte (nf_provider));
- if (conversionType.Equals (typeof (Char)))
- return (object)(convert_value.ToChar (nf_provider));
- if (conversionType.Equals (typeof (DateTime)))
- return (object)(convert_value.ToDateTime (nf_provider));
-
- if (conversionType.Equals (decimal_type)) {
- if (convert_value.GetType () == TypeManager.char_type)
- return (decimal)convert_value.ToInt32 (nf_provider);
- return convert_value.ToDecimal (nf_provider);
- }
-
- if (conversionType.Equals (typeof (Double))) {
- if (convert_value.GetType () == TypeManager.char_type)
- return (double)convert_value.ToInt32 (nf_provider);
- return convert_value.ToDouble (nf_provider);
- }
-
- if (conversionType.Equals (typeof (Int16)))
- return (object)(convert_value.ToInt16 (nf_provider));
- if (conversionType.Equals (int32_type))
- return (object)(convert_value.ToInt32 (nf_provider));
- if (conversionType.Equals (int64_type))
- return (object)(convert_value.ToInt64 (nf_provider));
- if (conversionType.Equals (typeof (SByte)))
- return (object)(convert_value.ToSByte (nf_provider));
-
- if (conversionType.Equals (typeof (Single))) {
- if (convert_value.GetType () == TypeManager.char_type)
- return (float)convert_value.ToInt32 (nf_provider);
- return convert_value.ToSingle (nf_provider);
- }
-
- if (conversionType.Equals (typeof (String)))
- return (object)(convert_value.ToString (nf_provider));
- if (conversionType.Equals (typeof (UInt16)))
- return (object)(convert_value.ToUInt16 (nf_provider));
- if (conversionType.Equals (typeof (UInt32)))
- return (object)(convert_value.ToUInt32 (nf_provider));
- if (conversionType.Equals (typeof (UInt64)))
- return (object)(convert_value.ToUInt64 (nf_provider));
- if (conversionType.Equals (typeof (Object)))
- return (object)(value);
- else
- error = true;
- } catch {
- error = true;
- }
- return null;
- }
-
- //
- // When compiling with -nostdlib and the type is imported from an external assembly
- // SRE uses "wrong" type and we have to convert it to the right compiler instance.
- //
- public static Type TypeToCoreType (Type t)
- {
- if (RootContext.StdLib || t.Module != typeof (object).Module)
- return t;
-
- // TODO: GetTypeCode returns underlying type for enums !!
- TypeCode tc = Type.GetTypeCode (t);
-
- switch (tc){
- case TypeCode.Boolean:
- return TypeManager.bool_type;
- case TypeCode.Byte:
- return TypeManager.byte_type;
- case TypeCode.SByte:
- return TypeManager.sbyte_type;
- case TypeCode.Char:
- return TypeManager.char_type;
- case TypeCode.Int16:
- return TypeManager.short_type;
- case TypeCode.UInt16:
- return TypeManager.ushort_type;
- case TypeCode.Int32:
- return TypeManager.int32_type;
- case TypeCode.UInt32:
- return TypeManager.uint32_type;
- case TypeCode.Int64:
- return TypeManager.int64_type;
- case TypeCode.UInt64:
- return TypeManager.uint64_type;
- case TypeCode.Single:
- return TypeManager.float_type;
- case TypeCode.Double:
- return TypeManager.double_type;
- case TypeCode.String:
- return TypeManager.string_type;
- case TypeCode.Decimal:
- return TypeManager.decimal_type;
- }
-
- if (t == typeof (void))
- return TypeManager.void_type;
- if (t == typeof (object))
- return TypeManager.object_type;
- if (t == typeof (System.Type))
- return TypeManager.type_type;
- if (t == typeof (System.IntPtr))
- return TypeManager.intptr_type;
- if (t == typeof (System.UIntPtr))
- return TypeManager.uintptr_type;
-
- if (t.IsArray) {
- int dim = t.GetArrayRank ();
- t = GetElementType (t);
- return t.MakeArrayType (dim);
- }
- if (t.IsByRef) {
- t = GetElementType (t);
- return t.MakeByRefType ();
- }
- if (t.IsPointer) {
- t = GetElementType (t);
- return t.MakePointerType ();
- }
-
- return t;
- }
-
- //
- // Converts any type to reflection supported type
- //
- public static Type TypeToReflectionType (Type type)
- {
- // TODO: Very lame and painful, GetReference () is enough for mcs-cecil
- if (IsDynamicType (type))
- return object_type;
-
- if (type is DynamicArrayType)
- return type.UnderlyingSystemType;
-
- return type;
- }
-
- /// <summary>
- /// Utility function that can be used to probe whether a type
- /// is managed or not.
- /// </summary>
- public static bool VerifyUnmanaged (CompilerContext ctx, Type t, Location loc)
- {
- if (IsUnmanagedType (t))
- return true;
-
- while (t.IsPointer)
- t = GetElementType (t);
-
- ctx.Report.SymbolRelatedToPreviousError (t);
- ctx.Report.Error (208, loc,
- "Cannot take the address of, get the size of, or declare a pointer to a managed type `{0}'",
- CSharpName (t));
-
- return false;
- }
-
- /// <summary>
- /// Returns the name of the indexer in a given type.
- /// </summary>
- /// <remarks>
- /// The default is not always `Item'. The user can change this behaviour by
- /// using the IndexerNameAttribute in the container.
- /// For example, the String class indexer is named `Chars' not `Item'
- /// </remarks>
- public static string IndexerPropertyName (Type t)
- {
- t = DropGenericTypeArguments (t);
- if (t is TypeBuilder) {
- TypeContainer tc = t.IsInterface ? LookupInterface (t) : LookupTypeContainer (t);
- return tc == null ? TypeContainer.DefaultIndexerName : tc.IndexerName;
- }
-
- PredefinedAttribute pa = PredefinedAttributes.Get.DefaultMember;
- if (pa.IsDefined) {
- System.Attribute attr = System.Attribute.GetCustomAttribute (
- t, pa.Type);
- if (attr != null) {
- DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
- return dma.MemberName;
- }
- }
-
- return TypeContainer.DefaultIndexerName;
- }
-
- private static bool IsSignatureEqual (Type a, Type b)
- {
- ///
- /// Consider the following example (bug #77674):
- ///
- /// public abstract class A
- /// {
- /// public abstract T Foo<T> ();
- /// }
- ///
- /// public abstract class B : A
- /// {
- /// public override U Foo<T> ()
- /// { return default (U); }
- /// }
- ///
- /// Here, `T' and `U' are method type parameters from different methods
- /// (A.Foo and B.Foo), so both `==' and Equals() will fail.
- ///
- /// However, since we're determining whether B.Foo() overrides A.Foo(),
- /// we need to do a signature based comparision and consider them equal.
-
- if (a == b)
- return true;
-
- if (a.IsGenericParameter && b.IsGenericParameter &&
- (a.DeclaringMethod != null) && (b.DeclaringMethod != null)) {
- return a.GenericParameterPosition == b.GenericParameterPosition;
- }
-
- if (a.IsArray && b.IsArray) {
- if (a.GetArrayRank () != b.GetArrayRank ())
- return false;
-
- return IsSignatureEqual (GetElementType (a), GetElementType (b));
- }
-
- if (a.IsByRef && b.IsByRef)
- return IsSignatureEqual (GetElementType (a), GetElementType (b));
-
- if (IsGenericType (a) && IsGenericType (b)) {
- if (DropGenericTypeArguments (a) != DropGenericTypeArguments (b))
- 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 (!IsSignatureEqual (aargs [i], bargs [i]))
- return false;
- }
-
- return true;
- }
-
- return false;
- }
-
- //
- // Returns whether the array of memberinfos contains the given method
- //
- public static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method, bool ignoreDeclType)
- {
- Type [] new_args = TypeManager.GetParameterData (new_method).Types;
-
- foreach (MethodBase method in array) {
- if (!ignoreDeclType && method.DeclaringType != new_method.DeclaringType)
- continue;
-
- if (method.Name != new_method.Name)
- continue;
-
- if (method is MethodInfo && new_method is MethodInfo &&
- !IsSignatureEqual (
- TypeToCoreType (((MethodInfo) method).ReturnType),
- TypeToCoreType (((MethodInfo) new_method).ReturnType)))
- continue;
-
- Type [] old_args = TypeManager.GetParameterData (method).Types;
- int old_count = old_args.Length;
- int i;
-
- if (new_args.Length != old_count)
- continue;
-
- for (i = 0; i < old_count; i++){
- if (!IsSignatureEqual (old_args [i], new_args [i]))
- break;
- }
- if (i != old_count)
- continue;
-
- return true;
- }
-
- return false;
- }
-
- //
- // We copy methods from `new_members' into `target_list' if the signature
- // for the method from in the new list does not exist in the target_list
- //
- // The name is assumed to be the same.
- //
- public static ArrayList CopyNewMethods (ArrayList target_list, IList new_members)
- {
- if (target_list == null){
- target_list = new ArrayList ();
-
- foreach (MemberInfo mi in new_members){
- if (mi is MethodBase)
- target_list.Add (mi);
- }
- return target_list;
- }
-
- MemberInfo [] target_array = new MemberInfo [target_list.Count];
- target_list.CopyTo (target_array, 0);
-
- foreach (MemberInfo mi in new_members){
- MethodBase new_method = (MethodBase) mi;
-
- if (!ArrayContainsMethod (target_array, new_method, true))
- target_list.Add (new_method);
- }
- return target_list;
- }
-
-#region Generics
- // <remarks>
- // Tracks the generic parameters.
- // </remarks>
- static PtrHashtable builder_to_type_param;
-
- public static void AddTypeParameter (Type t, TypeParameter tparam)
- {
- if (!builder_to_type_param.Contains (t))
- builder_to_type_param.Add (t, tparam);
- }
-
- public static TypeParameter LookupTypeParameter (Type t)
- {
- return (TypeParameter) builder_to_type_param [t];
- }
-
- // This method always return false for non-generic compiler,
- // while Type.IsGenericParameter is returned if it is supported.
- public static bool IsGenericParameter (Type type)
- {
- return type.IsGenericParameter;
- }
-
- public static int GenericParameterPosition (Type type)
- {
- return type.GenericParameterPosition;
- }
-
- public static bool IsGenericType (Type type)
- {
- return type.IsGenericType;
- }
-
- public static bool IsGenericTypeDefinition (Type type)
- {
- return type.IsGenericTypeDefinition;
- }
-
- public static bool ContainsGenericParameters (Type type)
- {
- return type.ContainsGenericParameters;
- }
-
- public static FieldInfo GetGenericFieldDefinition (FieldInfo fi)
- {
- if (fi.DeclaringType.IsGenericTypeDefinition ||
- !fi.DeclaringType.IsGenericType)
- return fi;
-
- Type t = fi.DeclaringType.GetGenericTypeDefinition ();
- BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic |
- BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
-
- // TODO: use CodeGen.Module.Builder.ResolveField (fi.MetadataToken);
- foreach (FieldInfo f in t.GetFields (bf))
- if (f.MetadataToken == fi.MetadataToken)
- return f;
-
- return fi;
- }
-
- public static bool IsEqual (Type a, Type b)
- {
- if (a.Equals (b)) {
- // MS BCL returns true even if enum types are different
- if (a.BaseType == TypeManager.enum_type || b.BaseType == TypeManager.enum_type)
- return a.FullName == b.FullName;
-
- // Some types are never equal
- if (a == TypeManager.null_type || a == InternalType.AnonymousMethod)
- return false;
-
- return true;
- }
-
- if (IsGenericParameter (a) && IsGenericParameter (b)) {
- // TODO: needs more testing before cleaning up
- //if (a.DeclaringMethod != b.DeclaringMethod &&
- // (a.DeclaringMethod == null || b.DeclaringMethod == null))
- // return false;
- return a.GenericParameterPosition == b.GenericParameterPosition;
- }
-
- if (a.IsArray && b.IsArray) {
- if (a.GetArrayRank () != b.GetArrayRank ())
- return false;
- return IsEqual (GetElementType (a), GetElementType (b));
- }
-
- if (a.IsByRef && b.IsByRef)
- return IsEqual (a.GetElementType (), b.GetElementType ());
-
- if (IsGenericType (a) && IsGenericType (b)) {
- Type adef = DropGenericTypeArguments (a);
- Type bdef = DropGenericTypeArguments (b);
-
- if (adef != bdef)
- return false;
-
- if (adef.IsEnum && bdef.IsEnum)
- return true;
-
- Type[] aargs = GetTypeArguments (a);
- Type[] bargs = GetTypeArguments (b);
-
- if (aargs.Length != bargs.Length)
- return false;
-
- for (int i = 0; i < aargs.Length; i++) {
- if (!IsEqual (aargs [i], bargs [i]))
- return false;
- }
-
- return true;
- }
-
- return false;
- }
-
- public static bool IsEqual (Type[] a, Type[] b)
- {
- if (a == null || b == null || a.Length != b.Length)
- return false;
-
- for (int i = 0; i < a.Length; ++i) {
- if (a [i] == null || b [i] == null) {
- if (a [i] == b [i])
- continue;
-
- return false;
- }
-
- if (!IsEqual (a [i], b [i]))
- return false;
- }
-
- return true;
- }
-
- public static Type DropGenericTypeArguments (Type t)
- {
- if (!t.IsGenericType)
- return t;
- // Micro-optimization: a generic typebuilder is always a generic type definition
- if (t is TypeBuilder)
- return t;
- return t.GetGenericTypeDefinition ();
- }