Add initial reflection dependant code
[mono.git] / mcs / mcs / typemanager.cs
index a41f4d742e095353d0fe94942cece224fde4cf67..ea699d34d6192d44a863aff8411f96e3e02e9e32 100644 (file)
 //
 
 using System;
-using System.IO;
 using System.Globalization;
 using System.Collections.Generic;
-using System.Reflection;
-using System.Reflection.Emit;
 using System.Text;
-using System.Runtime.CompilerServices;
-using System.Diagnostics;
-using System.Linq;
 
 namespace Mono.CSharp {
 
@@ -61,7 +55,6 @@ namespace Mono.CSharp {
        static public PredefinedTypeSpec exception_type;
 
 
-       static public TypeSpec null_type;
        static public TypeSpec typed_reference_type;
        static public TypeSpec arg_iterator_type;
        static public TypeSpec mbr_type;
@@ -70,6 +63,7 @@ namespace Mono.CSharp {
        static public TypeSpec asynccallback_type;
        static public TypeSpec runtime_argument_handle_type;
        static public TypeSpec void_ptr_type;
+       static public TypeSpec interop_charset;
 
        // 
        // C# 2.0
@@ -98,19 +92,6 @@ namespace Mono.CSharp {
        public static TypeExpr binder_type;
        public static TypeSpec binder_flags;
 
-       // 
-       // Expressions representing the internal types.  Used during declaration
-       // definition.
-       //
-       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_valuetype_expr;
        public static TypeExpr expression_type_expr;
 
 
@@ -128,12 +109,13 @@ namespace Mono.CSharp {
        static public MethodSpec delegate_remove_delegate_delegate;
        static public PropertySpec int_get_offset_to_string_data;
        static public MethodSpec int_interlocked_compare_exchange;
+       public static MethodSpec gen_interlocked_compare_exchange;
        static public PropertySpec ienumerator_getcurrent;
        public static MethodSpec methodbase_get_type_from_handle;
        public static MethodSpec methodbase_get_type_from_handle_generic;
        public static MethodSpec fieldinfo_get_field_from_handle;
        public static MethodSpec fieldinfo_get_field_from_handle_generic;
-       static public MethodSpec activator_create_instance;
+       public static MethodSpec activator_create_instance;
 
        //
        // The constructors.
@@ -142,33 +124,6 @@ namespace Mono.CSharp {
        static public MethodSpec void_decimal_ctor_int_arg;
        public static MethodSpec void_decimal_ctor_long_arg;
 
-       static Dictionary<Assembly, bool> assembly_internals_vis_attrs;
-
-       //
-       // These are expressions that represent some of the internal data types, used
-       // elsewhere
-       //
-       public static void InitExpressionTypes ()
-       {
-               system_object_expr  = new TypeLookupExpression (object_type);
-               system_string_expr  = new TypeLookupExpression (string_type);
-               system_boolean_expr = new TypeLookupExpression (bool_type);
-               system_decimal_expr = new TypeLookupExpression (decimal_type);
-               system_single_expr  = new TypeLookupExpression (float_type);
-               system_double_expr  = new TypeLookupExpression (double_type);
-               system_sbyte_expr   = new TypeLookupExpression (sbyte_type);
-               system_byte_expr    = new TypeLookupExpression (byte_type);
-               system_int16_expr   = new TypeLookupExpression (short_type);
-               system_uint16_expr  = new TypeLookupExpression (ushort_type);
-               system_int32_expr   = new TypeLookupExpression (int32_type);
-               system_uint32_expr  = new TypeLookupExpression (uint32_type);
-               system_int64_expr   = new TypeLookupExpression (int64_type);
-               system_uint64_expr  = new TypeLookupExpression (uint64_type);
-               system_char_expr    = new TypeLookupExpression (char_type);
-               system_void_expr    = new TypeLookupExpression (void_type);
-               system_valuetype_expr  = new TypeLookupExpression (value_type);
-       }
-
        static TypeManager ()
        {
                Reset ();
@@ -178,9 +133,6 @@ namespace Mono.CSharp {
        {
 //             object_type = null;
        
-               type_hash = new DoubleHash ();
-               assembly_internals_vis_attrs = new Dictionary<Assembly, bool> ();
-               
                // TODO: I am really bored by all this static stuff
                system_type_get_type_from_handle =
                bool_movenext_void =
@@ -189,6 +141,7 @@ namespace Mono.CSharp {
                void_monitor_exit_object =
                void_initializearray_array_fieldhandle =
                int_interlocked_compare_exchange =
+               gen_interlocked_compare_exchange =
                methodbase_get_type_from_handle =
                methodbase_get_type_from_handle_generic =
                fieldinfo_get_field_from_handle =
@@ -216,61 +169,12 @@ namespace Mono.CSharp {
                runtime_helpers_type = iasyncresult_type = asynccallback_type =
                runtime_argument_handle_type = void_ptr_type = isvolatile_type =
                generic_ilist_type = generic_icollection_type = generic_ienumerator_type =
-               generic_ienumerable_type = generic_nullable_type = expression_type =
+               generic_ienumerable_type = generic_nullable_type = expression_type = interop_charset =
                parameter_expression_type = fieldinfo_type = methodinfo_type = ctorinfo_type = null;
 
                expression_type_expr = null;
        }
 
-       //
-       // We use this hash for multiple kinds of constructed types:
-       //
-       //    (T, "&")  Given T, get T &
-       //    (T, "*")  Given T, get T *
-       //    (T, "[]") Given T and a array dimension, get T []
-       //    (T, X)    Given a type T and a simple name X, get the type T+X
-       //
-       // Accessibility tests, if necessary, should be done by the user
-       //
-       static DoubleHash type_hash = new DoubleHash ();
-
-       //
-       // Gets the reference to T version of the Type (T&)
-       //
-       public static Type GetReferenceType (TypeSpec t)
-       {
-               return t.GetMetaInfo ().MakeByRefType ();
-       }
-
-       public static TypeSpec GetConstructedType (TypeSpec t, string dim)
-       {
-               object ret = null;
-               if (type_hash.Lookup (t, dim, out ret))
-                       return (TypeSpec) ret;
-
-               TypeSpec ds;
-               if (dim.Length == 1) {
-                       if (dim[0] == '*') {
-                               ds = PointerContainer.MakeType (t);
-                       } else if (dim[0] == '&') {
-                               ds = ReferenceContainer.MakeType (t);
-                       } else {
-                               throw new NotImplementedException ("net");
-                       }
-               } else if (dim.Length == 2) {   // optimizes common "[]"
-                       ds = ArrayContainer.MakeType (t);
-               } else {
-                       int rank = dim.IndexOf (']');
-                       if (rank + 1 != dim.Length)
-                               t = GetConstructedType (t, dim.Substring (rank + 1));
-
-                       ds = ArrayContainer.MakeType (t, rank);
-               }
-
-               type_hash.Insert (t, dim, ds);
-               return ds;
-       }
-
        /// <summary>
        ///   Returns the C# name of a type if possible, or the full type name otherwise
        /// </summary>
@@ -315,8 +219,8 @@ namespace Mono.CSharp {
 
        public static TypeSpec CoreLookupType (CompilerContext ctx, string ns_name, string name, int arity, MemberKind kind, bool required)
        {
-               Namespace ns = GlobalRootNamespace.Instance.GetNamespace (ns_name, true);
-               var te = ns.Lookup (ctx, name, arity, Location.Null);
+               Namespace ns = ctx.GlobalRootNamespace.GetNamespace (ns_name, true);
+               var te = ns.LookupType (ctx, name, arity, !required, Location.Null);
                var ts = te == null ? null : te.Type;
 
                if (!required)
@@ -337,12 +241,14 @@ namespace Mono.CSharp {
                return ts;
        }
 
-       static MemberSpec GetPredefinedMember (TypeSpec t, MemberFilter filter, Location loc)
+       static MemberSpec GetPredefinedMember (TypeSpec t, MemberFilter filter, bool optional, Location loc)
        {
-               const BindingRestriction restrictions = BindingRestriction.AccessibleOnly | BindingRestriction.DeclaredOnly;
-               var member = MemberCache.FindMember (t, filter, restrictions);
+               var member = MemberCache.FindMember (t, filter, BindingRestriction.DeclaredOnly);
+
+               if (member != null && member.IsAccessible (InternalType.FakeInternalType))
+                       return member;
 
-               if (member != null)
+               if (optional)
                        return member;
 
                string method_args = null;
@@ -361,7 +267,7 @@ namespace Mono.CSharp {
        public static MethodSpec GetPredefinedConstructor (TypeSpec t, Location loc, params TypeSpec [] args)
        {
                var pc = ParametersCompiled.CreateFullyResolved (args);
-               return GetPredefinedMember (t, MemberFilter.Constructor (pc), loc) as MethodSpec;
+               return GetPredefinedMember (t, MemberFilter.Constructor (pc), false, loc) as MethodSpec;
        }
 
        //
@@ -371,22 +277,27 @@ namespace Mono.CSharp {
        public static MethodSpec GetPredefinedMethod (TypeSpec t, string name, Location loc, params TypeSpec [] args)
        {
                var pc = ParametersCompiled.CreateFullyResolved (args);
-               return GetPredefinedMethod (t, MemberFilter.Method (name, 0, pc, null), loc);
+               return GetPredefinedMethod (t, MemberFilter.Method (name, 0, pc, null), false, loc);
        }
 
        public static MethodSpec GetPredefinedMethod (TypeSpec t, MemberFilter filter, Location loc)
        {
-               return GetPredefinedMember (t, filter, loc) as MethodSpec;
+               return GetPredefinedMethod (t, filter, false, loc);
+       }
+
+       public static MethodSpec GetPredefinedMethod (TypeSpec t, MemberFilter filter, bool optional, Location loc)
+       {
+               return GetPredefinedMember (t, filter, optional, loc) as MethodSpec;
        }
 
        public static FieldSpec GetPredefinedField (TypeSpec t, string name, Location loc, TypeSpec type)
        {
-               return GetPredefinedMember (t, MemberFilter.Field (name, type), loc) as FieldSpec;
+               return GetPredefinedMember (t, MemberFilter.Field (name, type), false, loc) as FieldSpec;
        }
 
        public static PropertySpec GetPredefinedProperty (TypeSpec t, string name, Location loc, TypeSpec type)
        {
-               return GetPredefinedMember (t, MemberFilter.Property (name, type), loc) as PropertySpec;
+               return GetPredefinedMember (t, MemberFilter.Property (name, type), false, loc) as PropertySpec;
        }
 
        public static IList<PredefinedTypeSpec> InitCoreTypes ()
@@ -437,15 +348,16 @@ namespace Mono.CSharp {
        ///   population of the type has happened (for example, to
        ///   bootstrap the corlib.dll
        /// </remarks>
-       public static bool InitCoreTypes (CompilerContext ctx, IList<PredefinedTypeSpec> predefined)
+       public static bool InitCoreTypes (ModuleContainer module, IList<PredefinedTypeSpec> predefined)
        {
+               var ctx = module.Compiler;
                foreach (var p in predefined) {
                        var found = CoreLookupType (ctx, p.Namespace, p.Name, p.Kind, true);
                        if (found == null || found == p)
                                continue;
 
                        if (!RootContext.StdLib) {
-                               var ns = GlobalRootNamespace.Instance.GetNamespace (p.Namespace, false);
+                               var ns = module.GlobalRootNamespace.GetNamespace (p.Namespace, false);
                                ns.ReplaceTypeWithPredefined (found, p);
 
                                var tc = found.MemberDefinition as TypeContainer;
@@ -454,8 +366,17 @@ namespace Mono.CSharp {
                        }
                }
 
-               PredefinedAttributes.Get.ParamArray.Initialize (ctx, false);
-               PredefinedAttributes.Get.Out.Initialize (ctx, false);
+               ctx.PredefinedAttributes.ParamArray.Initialize (ctx, false);
+               ctx.PredefinedAttributes.Out.Initialize (ctx, false);
+
+               if (InternalType.Dynamic.GetMetaInfo () == null) {
+                       InternalType.Dynamic.SetMetaInfo (object_type.GetMetaInfo ());
+
+                       if (object_type.MemberDefinition.IsImported)
+                               InternalType.Dynamic.MemberCache = object_type.MemberCache;
+
+                       InternalType.Null.SetMetaInfo (object_type.GetMetaInfo ());
+               }
 
                return ctx.Report.Errors == 0;
        }
@@ -465,18 +386,13 @@ namespace Mono.CSharp {
        //
        public static void InitOptionalCoreTypes (CompilerContext ctx)
        {
-               //
-               // These are only used for compare purposes
-               //
-               null_type = InternalType.Null;
-
                void_ptr_type = PointerContainer.MakeType (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);
+               ctx.PredefinedAttributes.Initialize (ctx);
 
                runtime_argument_handle_type = CoreLookupType (ctx, "System", "RuntimeArgumentHandle", MemberKind.Struct, false);
                asynccallback_type = CoreLookupType (ctx, "System", "AsyncCallback", MemberKind.Delegate, false);
@@ -491,6 +407,8 @@ namespace Mono.CSharp {
                generic_ienumerable_type = CoreLookupType (ctx, "System.Collections.Generic", "IEnumerable", 1, MemberKind.Interface, false);
                generic_nullable_type = CoreLookupType (ctx, "System", "Nullable", 1, MemberKind.Struct, false);
 
+               isvolatile_type = CoreLookupType (ctx, "System.Runtime.CompilerServices", "IsVolatile", MemberKind.Class, false);
+
                //
                // Optional types which are used as types and for member lookup
                //
@@ -529,60 +447,6 @@ namespace Mono.CSharp {
        {
                return t.IsDelegate;
        }
-
-       //
-       // When any element of the type is a dynamic type
-       //
-       // This method builds a transformation array for dynamic types
-       // used in places where DynamicAttribute cannot 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 (TypeSpec t)
-       {
-               var ac = t as ArrayContainer;
-               if (ac != null) {
-                       if (HasDynamicTypeUsed (ac.Element) != null)
-                               return new bool[] { false, true };
-
-                       return null;
-               }
-
-               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;
-       }
        
        // Obsolete
        public static bool IsEnumType (TypeSpec t)
@@ -654,18 +518,6 @@ namespace Mono.CSharp {
                return t.IsStruct;
        }
 
-       public static bool IsSubclassOf (TypeSpec type, TypeSpec base_type)
-       {
-               do {
-                       if (type == base_type)
-                               return true;
-
-                       type = type.BaseType;
-               } while (type != null);
-
-               return false;
-       }
-
        public static bool IsFamilyAccessible (TypeSpec type, TypeSpec parent)
        {
 //             TypeParameter tparam = LookupTypeParameter (type);
@@ -716,12 +568,12 @@ namespace Mono.CSharp {
                type = type.GetDefinition (); // DropGenericTypeArguments (type);
                parent = parent.GetDefinition (); // DropGenericTypeArguments (parent);
 
-               if (IsEqual (type, parent))
+               if (type == parent)
                        return false;
 
                type = type.DeclaringType;
                while (type != null) {
-                       if (IsEqual (type.GetDefinition (), parent))
+                       if (type.GetDefinition () == parent)
                                return true;
 
                        type = type.DeclaringType;
@@ -735,91 +587,6 @@ namespace Mono.CSharp {
                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;
-
-               bool value;
-               if (assembly_internals_vis_attrs.TryGetValue (assembly, out value))
-                       return value;
-
-               object[] attrs = assembly.GetCustomAttributes (typeof (InternalsVisibleToAttribute), false);
-               if (attrs.Length == 0) {
-                       assembly_internals_vis_attrs.Add (assembly, false);
-                       return false;
-               }
-
-               bool is_friend = false;
-
-               AssemblyName this_name = CodeGen.Assembly.Name;
-               if (this_name == null)
-                       return false;
-
-               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);
-       }
-
        public static TypeSpec GetElementType (TypeSpec t)
        {
                return ((ElementTypeSpec)t).Element;
@@ -923,43 +690,6 @@ namespace Mono.CSharp {
 
                return false;   
        }
-       
-       //
-       // Returns whether the array of memberinfos contains the given method
-       //
-       public static bool ArrayContainsMethod (List<MemberSpec> array, MethodSpec new_method, bool ignoreDeclType)
-       {
-               AParametersCollection new_args = new_method.Parameters;
-
-               foreach (MethodSpec method in array) {
-                       if (!ignoreDeclType && method.DeclaringType != new_method.DeclaringType)
-                               continue;
-
-                       if (method.Name != new_method.Name)
-                               continue;
-
-                       if (!TypeSpecComparer.Override.IsEqual (method.ReturnType, new_method.ReturnType))
-                               continue;
-
-                       AParametersCollection old_args = method.Parameters;
-                       int old_count = old_args.Count;
-                       int i;
-
-                       if (new_args.Count != old_count)
-                               continue;
-
-                       for (i = 0; i < old_count; i++) {
-                               if (!TypeSpecComparer.Override.IsEqual (old_args.Types[i], new_args.Types[i]))
-                                       break;
-                       }
-                       if (i != old_count)
-                               continue;
-
-                       return true;
-               }
-
-               return false;
-       }
 #region Generics
        // This method always return false for non-generic compiler,
        // while Type.IsGenericParameter is returned if it is supported.
@@ -979,11 +709,6 @@ namespace Mono.CSharp {
                return type.GetMetaInfo ().ContainsGenericParameters;
        }
 
-       public static bool IsEqual (TypeSpec a, TypeSpec b)
-       {
-               return a == b && !(a is InternalType);
-       }
-
        public static TypeSpec[] GetTypeArguments (TypeSpec t)
        {
                // TODO: return empty array !!
@@ -1004,62 +729,6 @@ namespace Mono.CSharp {
                return generic_nullable_type == t.GetDefinition ();
        }
 #endregion
-
-       //
-       // Looks up a member called `name' in the `queried_type'.  This lookup
-       // is done by code that is contained in the definition for `invocation_type'
-       // through a qualifier of type `qualifier_type' (or null if there is no qualifier).
-       //
-       // `invocation_type' is used to check whether we're allowed to access the requested
-       // member wrt its protection level.
-       //
-       // When called from MemberAccess, `qualifier_type' is the type which is used to access
-       // the requested member (`class B { A a = new A (); a.foo = 5; }'; here invocation_type
-       // is B and qualifier_type is A).  This is used to do the CS1540 check.
-       //
-       // When resolving a SimpleName, `qualifier_type' is null.
-       //
-       // The `qualifier_type' is used for the CS1540 check; it's normally either null or
-       // the same than `queried_type' - except when we're being called from BaseAccess;
-       // in this case, `invocation_type' is the current type and `queried_type' the base
-       // type, so this'd normally trigger a CS1540.
-       //
-       // The binding flags are `bf' and the kind of members being looked up are `mt'
-       //
-       // The return value always includes private members which code in `invocation_type'
-       // 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 IList<MemberSpec> MemberLookup (TypeSpec invocation_type, TypeSpec qualifier_type,
-                                                 TypeSpec queried_type, MemberKind mt,
-                                                 BindingRestriction opt, string name, int arity, IList<MemberSpec> almost_match)
-       {
-               Timer.StartTimer (TimerType.MemberLookup);
-
-               var retval = RealMemberLookup (invocation_type, qualifier_type,
-                                                       queried_type, mt, opt, name, arity, almost_match);
-
-               Timer.StopTimer (TimerType.MemberLookup);
-
-               return retval;
-       }
-
-       static IList<MemberSpec> RealMemberLookup (TypeSpec invocation_type, TypeSpec qualifier_type,
-                                                  TypeSpec queried_type, MemberKind mt,
-                                                  BindingRestriction bf, string name, int arity, IList<MemberSpec> almost_match)
-       {
-               MemberFilter filter = new MemberFilter (name, arity, mt, null, null);
-               if ((bf & BindingRestriction.AccessibleOnly) != 0) {
-                       filter.InvocationType = invocation_type ?? InternalType.FakeInternalType;
-               }
-
-               return MemberCache.FindMembers (queried_type, filter, bf);
-       }       
 }
 
 }