- // Whether a type is unmanaged. This is used by the unsafe code (25.2)
- //
- public static bool IsUnmanagedType (Type t)
- {
- // Avoid infloops in the case of: unsafe struct Foo { Foo *x; }
- if (unmanaged_enclosing_types.Contains (t))
- return true;
-
- // 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 true;
-
- // Arrays are disallowed, even if we mark them with [MarshalAs(UnmanagedType.ByValArray, ...)]
- if (t.IsArray)
- return false;
-
- if (!IsValueType (t))
- return false;
-
-#if GMCS_SOURCE
- for (Type p = t.DeclaringType; p != null; p = p.DeclaringType) {
- if (p.IsGenericTypeDefinition)
- return false;
- }
-#endif
-
- unmanaged_enclosing_types.Push (t);
-
- bool retval = true;
-
- if (t is TypeBuilder) {
- TypeContainer tc = LookupTypeContainer (t);
- if (tc.Fields != null){
- foreach (FieldBase f in tc.Fields){
- // Avoid using f.FieldBuilder: f.Define () may not yet have been invoked.
- if ((f.ModFlags & Modifiers.STATIC) != 0)
- continue;
- if (f.MemberType == null)
- continue;
- if (!IsUnmanagedType (f.MemberType)){
- Report.SymbolRelatedToPreviousError (f.Location, CSharpName (t) + "." + f.Name);
- retval = false;
- }
- }
- }
- } else {
- FieldInfo [] fields = t.GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
-
- foreach (FieldInfo f in fields){
- if (!IsUnmanagedType (f.FieldType)){
- Report.SymbolRelatedToPreviousError (f);
- retval = false;
- }
- }
- }
-
- unmanaged_enclosing_types.Pop ();
-
- 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 !t.IsValueType;
- }
-
- public static bool IsValueType (Type t)
- {
- return t.IsValueType || IsGenericParameter (t);
- }
-
- 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 && GMCS_SOURCE
- 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 `extern_type' is friend of the output assembly
- //
- public static bool IsThisOrFriendAssembly (Assembly assembly)
- {
- if (assembly == CodeGen.Assembly.Builder)
- return true;
-
- if (assembly_internals_vis_attrs.Contains (assembly))
- return (bool)(assembly_internals_vis_attrs [assembly]);
-
- if (internals_visible_attr_type == null)
- return false;
-
- object [] attrs = assembly.GetCustomAttributes (internals_visible_attr_type, false);
- if (attrs.Length == 0) {
- assembly_internals_vis_attrs.Add (assembly, false);
- return false;
- }
-
- bool is_friend = false;
-#if GMCS_SOURCE
- 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);
- break;
- }
-
- if (!CompareKeyTokens (this_token, key_token))
- continue;
- }
-
- is_friend = true;
- break;
- }
-#endif
- assembly_internals_vis_attrs.Add (assembly, is_friend);
- return is_friend;
- }
-
-#if GMCS_SOURCE
- 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.Error (281, "Friend access was granted to `" + other_name +
- "', but the output assembly is named `" + CodeGen.Assembly.Name.FullName +
- "'. Try adding a reference to `" + other_name +
- "' or change the output assembly name to match it");
- }
-#endif
-
- //
- // 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 = ParametersCollection.Create (mb);
-#else
- MethodBase generic = TypeManager.DropGenericMethodArguments (mb);
- if (generic != mb) {
- pd = TypeManager.GetParameterData (generic);
- pd = ParametersCollection.Create (pd, mb);
- } else {
- pd = ParametersCollection.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 Parameters.EmptyReadOnlyParameters;
-
- ParameterInfo [] p = pi.GetIndexParameters ();
- if (p == null)
- return Parameters.EmptyReadOnlyParameters;
-
- pd = ParametersCollection.Create (p, null);
- method_params.Add (pi, pd);
- }
-
- return pd;
- }
-
- public static AParametersCollection GetDelegateParameters (Type t)
- {
- Delegate d = builder_to_declspace [t] as Delegate;
- if (d != null)
- return d.Parameters;
-
- MethodInfo invoke_mb = Delegate.GetInvokeMethod (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)
- {
-#if GMCS_SOURCE
- fb = GetGenericFieldDefinition (fb);
-#endif
- 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)) {
- 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 = new PtrHashtable ();
-
- /// <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 && GMCS_SOURCE
- 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;
-#if GMCS_SOURCE
- } 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;
-#endif
- } 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)
- 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;
-
- 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 GMCS_SOURCE
- 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 ();
- }
-#endif
- return t;
- }
-
- /// <summary>
- /// Utility function that can be used to probe whether a type
- /// is managed or not.
- /// </summary>
- public static bool VerifyUnManaged (Type t, Location loc)
- {
- if (IsUnmanagedType (t))
- return true;
-
- 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;
- }
-
- System.Attribute attr = System.Attribute.GetCustomAttribute (
- t, TypeManager.default_member_type);
- if (attr != null){
- DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
- return dma.MemberName;
- }
-
- return TypeContainer.DefaultIndexerName;
- }
-
- 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.RuntimeMissingSupport (Location.Null, "pinned local variables");
- return ig.DeclareLocal (t);
- }
- }
- return (LocalBuilder) declare_local_method.Invoke (ig, new object [] { t, true });
- }
-
- 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 GMCS_SOURCE
- if (a.IsGenericParameter && b.IsGenericParameter &&
- (a.DeclaringMethod != null) && (b.DeclaringMethod != null)) {
- return a.GenericParameterPosition == b.GenericParameterPosition;
- }
-#endif
-
- if (a.IsArray && b.IsArray) {
- if (a.GetArrayRank () != b.GetArrayRank ())
- return false;
-
- return IsSignatureEqual (a.GetElementType (), b.GetElementType ());
- }
-
- if (a.IsByRef && b.IsByRef)
- return IsSignatureEqual (a.GetElementType (), b.GetElementType ());
-
-#if GMCS_SOURCE
- if (a.IsGenericType && b.IsGenericType) {
- if (a.GetGenericTypeDefinition () != b.GetGenericTypeDefinition ())
- return false;
-
- Type[] aargs = a.GetGenericArguments ();
- Type[] bargs = b.GetGenericArguments ();
-
- 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;
- }
-#endif
-
- 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)
- {
-#if GMCS_SOURCE
- return type.IsGenericParameter;
-#else
- return false;
-#endif
- }
-
- public static int GenericParameterPosition (Type type)
- {
-#if GMCS_SOURCE
- return type.GenericParameterPosition;
-#else
- throw new InternalErrorException ("should not be called");
-#endif
- }
-
- public static bool IsGenericType (Type type)
- {
-#if GMCS_SOURCE
- return type.IsGenericType;
-#else
- return false;
-#endif
- }
-
- public static bool IsGenericTypeDefinition (Type type)
- {
-#if GMCS_SOURCE
- return type.IsGenericTypeDefinition;
-#else
- return false;
-#endif
- }
-
- public static bool ContainsGenericParameters (Type type)
- {
-#if GMCS_SOURCE
- return type.ContainsGenericParameters;
-#else
- return false;
-#endif
- }
-
- public static FieldInfo GetGenericFieldDefinition (FieldInfo fi)
- {
-#if GMCS_SOURCE
- 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;
-#endif
-
- 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 == TypeManager.anonymous_method_type)
- return false;
-
- return true;
- }
-
-#if GMCS_SOURCE
- if (a.IsGenericParameter && b.IsGenericParameter) {
- // 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 (a.GetElementType (), b.GetElementType ());
- }
-
- if (a.IsByRef && b.IsByRef)
- return IsEqual (a.GetElementType (), b.GetElementType ());
-
- if (a.IsGenericType && b.IsGenericType) {
- Type adef = a.GetGenericTypeDefinition ();
- Type bdef = b.GetGenericTypeDefinition ();
-
- if (adef != bdef)
- return false;
-
- if (adef.IsEnum && bdef.IsEnum)
- return true;
-
- Type[] aargs = a.GetGenericArguments ();
- Type[] bargs = b.GetGenericArguments ();
-
- 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;
- }
-#endif
-
- 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 GMCS_SOURCE
- 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 ();
-#else
- return t;
-#endif
- }
-
- public static MethodBase DropGenericMethodArguments (MethodBase m)
- {
-#if GMCS_SOURCE
- if (m.IsGenericMethod)
- m = ((MethodInfo) m).GetGenericMethodDefinition ();
-
- Type t = m.DeclaringType;
- if (!t.IsGenericType || t.IsGenericTypeDefinition)
- return m;
-
- t = t.GetGenericTypeDefinition ();
- BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic |
- BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
-
-#if MS_COMPATIBLE
- // TODO: use CodeGen.Module.Builder.ResolveMethod ()
- return m;
-#endif
-
- if (m is ConstructorInfo) {
- foreach (ConstructorInfo c in t.GetConstructors (bf))
- if (c.MetadataToken == m.MetadataToken)
- return c;
- } else {
- foreach (MethodBase mb in t.GetMethods (bf))
- if (mb.MetadataToken == m.MetadataToken)
- return mb;
- }
-#endif
-
- return m;
- }
-
- public static Type[] GetGenericArguments (MethodBase mi)
- {
-#if GMCS_SOURCE
- return mi.GetGenericArguments ();
-#else
- return Type.EmptyTypes;
-#endif
- }
-
- public static Type[] GetTypeArguments (Type t)
- {
-#if GMCS_SOURCE
- DeclSpace tc = LookupDeclSpace (t);
- if (tc != null) {
- if (!tc.IsGeneric)
- return Type.EmptyTypes;
-
- 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 ();
-#else
- throw new InternalErrorException ();
-#endif
- }
-
- public static GenericConstraints GetTypeParameterConstraints (Type t)
- {
-#if GMCS_SOURCE
- if (!t.IsGenericParameter)
- throw new InvalidOperationException ();
-
- TypeParameter tparam = LookupTypeParameter (t);
- if (tparam != null)
- return tparam.GenericConstraints;
-
- return ReflectionConstraints.GetConstraints (t);
-#else
- throw new InternalErrorException ();
-#endif
- }
-
- public static bool HasGenericArguments (Type t)
- {
- return GetNumberOfTypeArguments (t) > 0;
- }
-
- public static int GetNumberOfTypeArguments (Type t)
- {
-#if GMCS_SOURCE
- if (t.IsGenericParameter)
- return 0;
- DeclSpace tc = LookupDeclSpace (t);
- if (tc != null)
- return tc.IsGeneric ? tc.CountTypeParameters : 0;
- else
- return t.IsGenericType ? t.GetGenericArguments ().Length : 0;
-#else
- return 0;
-#endif
- }
-
- /// <summary>
- /// Check whether `type' and `parent' are both instantiations of the same
- /// generic type. Note that we do not check the type parameters here.
- /// </summary>
- public static bool IsInstantiationOfSameGenericType (Type type, Type parent)
- {
- int tcount = GetNumberOfTypeArguments (type);
- int pcount = GetNumberOfTypeArguments (parent);
-
- if (tcount != pcount)
- return false;
-
- type = DropGenericTypeArguments (type);
- parent = DropGenericTypeArguments (parent);
-
- return type.Equals (parent);
- }
-
- /// <summary>
- /// Whether `mb' is a generic method definition.
- /// </summary>
- public static bool IsGenericMethodDefinition (MethodBase mb)
- {
-#if GMCS_SOURCE
- if (mb.DeclaringType is TypeBuilder) {
- IMethodData method = (IMethodData) builder_to_method [mb];
- if (method == null)
- return false;
-
- return method.GenericMethod != null;
- }
-
- return mb.IsGenericMethodDefinition;
-#else
- return false;
-#endif
- }
-
- /// <summary>
- /// Whether `mb' is a generic method.
- /// </summary>
- public static bool IsGenericMethod (MethodBase mb)
- {
-#if GMCS_SOURCE
- return mb.IsGenericMethod;
-#else
- return false;
-#endif
- }
-
- public static bool IsNullableType (Type t)
- {
-#if GMCS_SOURCE
- return generic_nullable_type == DropGenericTypeArguments (t);
-#else
- return false;
-#endif
- }
-
- public static bool IsNullableTypeOf (Type t, Type nullable)
- {
-#if GMCS_SOURCE
- if (!IsNullableType (t))
- return false;
-
- return GetTypeArguments (t) [0] == nullable;
-#else
- return false;
-#endif
- }
-
- public static bool IsNullableValueType (Type t)
- {
-#if GMCS_SOURCE
- if (!IsNullableType (t))
- return false;
-
- return GetTypeArguments (t) [0].IsValueType;
-#else
- return false;
-#endif
- }
-#endregion
-
-#region MemberLookup implementation
-
- //
- // Whether we allow private members in the result (since FindMembers
- // uses NonPublic for both protected and private), we need to distinguish.
- //
-
- internal class Closure {
- internal bool private_ok;
-
- // Who is invoking us and which type is being queried currently.
- internal Type invocation_type;
- internal Type qualifier_type;
-
- // 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 && qualifier_type == null)
- // It resolved from a simple name, so it should be visible.
- return true;
-
- if (IsNestedChildOf (invocation_type, m.DeclaringType))
- return true;
-
- for (Type t = invocation_type; t != null; t = t.DeclaringType) {
- if (!IsFamilyAccessible (t, m.DeclaringType))
- continue;
-
- // 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 (is_static || qualifier_type == null ||
- IsInstantiationOfSameGenericType (t, qualifier_type) ||
- IsFamilyAccessible (qualifier_type, t))
- return true;
- }
-
- if (almost_match != null)
- almost_match.Add (m);
-
- return false;
- }
-
- //
- // This filter filters by name + whether it is ok to include private
- // members in the search
- //
- 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){
- MethodBase mb = (MethodBase) m;
- MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
-
- if (ma == MethodAttributes.Public)
- return true;
-
- if (ma == MethodAttributes.PrivateScope)
- return false;
-
- if (ma == MethodAttributes.Private)
- return private_ok ||
- IsPrivateAccessible (invocation_type, m.DeclaringType) ||
- IsNestedChildOf (invocation_type, m.DeclaringType);
-
- if (TypeManager.IsThisOrFriendAssembly (mb.DeclaringType.Assembly)) {
- if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem)
- return true;
- } else {
- if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamANDAssem)
- return false;
- }
-
- // Family, FamORAssem or FamANDAssem
- return CheckValidFamilyAccess (mb.IsStatic, m);
- }
-
- if (m is FieldInfo){
- FieldInfo fi = (FieldInfo) m;
- FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
-
- if (fa == FieldAttributes.Public)
- return true;
-
- if (fa == FieldAttributes.PrivateScope)
- return false;
-
- if (fa == FieldAttributes.Private)
- return private_ok ||
- IsPrivateAccessible (invocation_type, m.DeclaringType) ||
- IsNestedChildOf (invocation_type, m.DeclaringType);
-
- if (TypeManager.IsThisOrFriendAssembly (fi.DeclaringType.Assembly)) {
- if ((fa == FieldAttributes.Assembly) ||
- (fa == FieldAttributes.FamORAssem))
- return true;
- } else {
- if ((fa == FieldAttributes.Assembly) ||
- (fa == FieldAttributes.FamANDAssem))
- return false;
- }
-
- // Family, FamORAssem or FamANDAssem
- return CheckValidFamilyAccess (fi.IsStatic, m);
- }
-
- //
- // EventInfos and PropertyInfos, return true because they lack
- // permission information, so we need to check later on the methods.
- //
- return true;
- }
- }
-
- 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
- // 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).