// Copyright 2003-2008 Novell, Inc.
//
-//
-// We will eventually remove the SIMPLE_SPEEDUP, and should never change
-// the behavior of the compilation. This can be removed if we rework
-// the code to get a list of namespaces available.
-//
-#define SIMPLE_SPEEDUP
-
using System;
-using System.IO;
using System.Globalization;
-using System.Collections;
-using System.Reflection;
-using System.Reflection.Emit;
+using System.Collections.Generic;
using System.Text;
-using System.Runtime.CompilerServices;
-using System.Diagnostics;
-namespace Mono.CSharp {
+namespace Mono.CSharp
+{
+ //
+ // All compiler build-in types (they have to exist otherwise the compile will not work)
+ //
+ public class BuildinTypes
+ {
+ public readonly BuildinTypeSpec Object;
+ public readonly BuildinTypeSpec ValueType;
+ public readonly BuildinTypeSpec Attribute;
+
+ public readonly BuildinTypeSpec Int;
+ public readonly BuildinTypeSpec UInt;
+ public readonly BuildinTypeSpec Long;
+ public readonly BuildinTypeSpec ULong;
+ public readonly BuildinTypeSpec Float;
+ public readonly BuildinTypeSpec Double;
+ public readonly BuildinTypeSpec Char;
+ public readonly BuildinTypeSpec Short;
+ public readonly BuildinTypeSpec Decimal;
+ public readonly BuildinTypeSpec Bool;
+ public readonly BuildinTypeSpec SByte;
+ public readonly BuildinTypeSpec Byte;
+ public readonly BuildinTypeSpec UShort;
+ public readonly BuildinTypeSpec String;
+
+ public readonly BuildinTypeSpec Enum;
+ public readonly BuildinTypeSpec Delegate;
+ public readonly BuildinTypeSpec MulticastDelegate;
+ public readonly BuildinTypeSpec Void;
+ public readonly BuildinTypeSpec Array;
+ public readonly BuildinTypeSpec Type;
+ public readonly BuildinTypeSpec IEnumerator;
+ public readonly BuildinTypeSpec IEnumerable;
+ public readonly BuildinTypeSpec IDisposable;
+ public readonly BuildinTypeSpec IntPtr;
+ public readonly BuildinTypeSpec UIntPtr;
+ public readonly BuildinTypeSpec RuntimeFieldHandle;
+ public readonly BuildinTypeSpec RuntimeTypeHandle;
+ public readonly BuildinTypeSpec Exception;
+
+ //
+ // These are internal buil-in types which depend on other
+ // build-in type (mostly object)
+ //
+ public readonly BuildinTypeSpec Dynamic;
+ public readonly BuildinTypeSpec Null;
+
+ readonly BuildinTypeSpec[] types;
+
+ public BuildinTypes ()
+ {
+ Object = new BuildinTypeSpec (MemberKind.Class, "System", "Object", BuildinTypeSpec.Type.Object);
+ ValueType = new BuildinTypeSpec (MemberKind.Class, "System", "ValueType", BuildinTypeSpec.Type.ValueType);
+ Attribute = new BuildinTypeSpec (MemberKind.Class, "System", "Attribute", BuildinTypeSpec.Type.Attribute);
+
+ Int = new BuildinTypeSpec (MemberKind.Struct, "System", "Int32", BuildinTypeSpec.Type.Int);
+ Long = new BuildinTypeSpec (MemberKind.Struct, "System", "Int64", BuildinTypeSpec.Type.Long);
+ UInt = new BuildinTypeSpec (MemberKind.Struct, "System", "UInt32", BuildinTypeSpec.Type.UInt);
+ ULong = new BuildinTypeSpec (MemberKind.Struct, "System", "UInt64", BuildinTypeSpec.Type.ULong);
+ Byte = new BuildinTypeSpec (MemberKind.Struct, "System", "Byte", BuildinTypeSpec.Type.Byte);
+ SByte = new BuildinTypeSpec (MemberKind.Struct, "System", "SByte", BuildinTypeSpec.Type.SByte);
+ Short = new BuildinTypeSpec (MemberKind.Struct, "System", "Int16", BuildinTypeSpec.Type.Short);
+ UShort = new BuildinTypeSpec (MemberKind.Struct, "System", "UInt16", BuildinTypeSpec.Type.UShort);
+
+ IEnumerator = new BuildinTypeSpec (MemberKind.Interface, "System.Collections", "IEnumerator", BuildinTypeSpec.Type.IEnumerator);
+ IEnumerable = new BuildinTypeSpec (MemberKind.Interface, "System.Collections", "IEnumerable", BuildinTypeSpec.Type.IEnumerable);
+ IDisposable = new BuildinTypeSpec (MemberKind.Interface, "System", "IDisposable", BuildinTypeSpec.Type.IDisposable);
+
+ Char = new BuildinTypeSpec (MemberKind.Struct, "System", "Char", BuildinTypeSpec.Type.Char);
+ String = new BuildinTypeSpec (MemberKind.Class, "System", "String", BuildinTypeSpec.Type.String);
+ Float = new BuildinTypeSpec (MemberKind.Struct, "System", "Single", BuildinTypeSpec.Type.Float);
+ Double = new BuildinTypeSpec (MemberKind.Struct, "System", "Double", BuildinTypeSpec.Type.Double);
+ Decimal = new BuildinTypeSpec (MemberKind.Struct, "System", "Decimal", BuildinTypeSpec.Type.Decimal);
+ Bool = new BuildinTypeSpec (MemberKind.Struct, "System", "Boolean", BuildinTypeSpec.Type.Bool);
+ IntPtr = new BuildinTypeSpec (MemberKind.Struct, "System", "IntPtr", BuildinTypeSpec.Type.IntPtr);
+ UIntPtr = new BuildinTypeSpec (MemberKind.Struct, "System", "UIntPtr", BuildinTypeSpec.Type.UIntPtr);
+
+ MulticastDelegate = new BuildinTypeSpec (MemberKind.Class, "System", "MulticastDelegate", BuildinTypeSpec.Type.MulticastDelegate);
+ Delegate = new BuildinTypeSpec (MemberKind.Class, "System", "Delegate", BuildinTypeSpec.Type.Delegate);
+ Enum = new BuildinTypeSpec (MemberKind.Class, "System", "Enum", BuildinTypeSpec.Type.Enum);
+ Array = new BuildinTypeSpec (MemberKind.Class, "System", "Array", BuildinTypeSpec.Type.Array);
+ Void = new BuildinTypeSpec (MemberKind.Struct, "System", "Void", BuildinTypeSpec.Type.Void);
+ Type = new BuildinTypeSpec (MemberKind.Class, "System", "Type", BuildinTypeSpec.Type.Type);
+ Exception = new BuildinTypeSpec (MemberKind.Class, "System", "Exception", BuildinTypeSpec.Type.Exception);
+ RuntimeFieldHandle = new BuildinTypeSpec (MemberKind.Struct, "System", "RuntimeFieldHandle", BuildinTypeSpec.Type.RuntimeFieldHandle);
+ RuntimeTypeHandle = new BuildinTypeSpec (MemberKind.Struct, "System", "RuntimeTypeHandle", BuildinTypeSpec.Type.RuntimeTypeHandle);
+
+ Dynamic = new BuildinTypeSpec ("dynamic", BuildinTypeSpec.Type.Dynamic);
+ Null = new BuildinTypeSpec ("null", BuildinTypeSpec.Type.Null);
+ Null.MemberCache = MemberCache.Empty;
+
+ types = new BuildinTypeSpec[] {
+ Object, ValueType, Attribute,
+ Int, UInt, Long, ULong, Float, Double, Char, Short, Decimal, Bool, SByte, Byte, UShort, String,
+ Enum, Delegate, MulticastDelegate, Void, Array, Type, IEnumerator, IEnumerable, IDisposable,
+ IntPtr, UIntPtr, RuntimeFieldHandle, RuntimeTypeHandle, Exception };
+
+ // Deal with obsolete static types
+ // TODO: remove
+ TypeManager.object_type = Object;
+ TypeManager.value_type = ValueType;
+ TypeManager.string_type = String;
+ TypeManager.int32_type = Int;
+ TypeManager.uint32_type = UInt;
+ TypeManager.int64_type = Long;
+ TypeManager.uint64_type = ULong;
+ TypeManager.float_type = Float;
+ TypeManager.double_type = Double;
+ TypeManager.char_type = Char;
+ TypeManager.short_type = Short;
+ TypeManager.decimal_type = Decimal;
+ TypeManager.bool_type = Bool;
+ TypeManager.sbyte_type = SByte;
+ TypeManager.byte_type = Byte;
+ TypeManager.ushort_type = UShort;
+ TypeManager.enum_type = Enum;
+ TypeManager.delegate_type = Delegate;
+ TypeManager.multicast_delegate_type = MulticastDelegate; ;
+ TypeManager.void_type = Void;
+ TypeManager.array_type = Array; ;
+ TypeManager.runtime_handle_type = RuntimeTypeHandle;
+ TypeManager.type_type = Type;
+ TypeManager.ienumerator_type = IEnumerator;
+ TypeManager.ienumerable_type = IEnumerable;
+ TypeManager.idisposable_type = IDisposable;
+ TypeManager.intptr_type = IntPtr;
+ TypeManager.uintptr_type = UIntPtr;
+ TypeManager.runtime_field_handle_type = RuntimeFieldHandle;
+ TypeManager.attribute_type = Attribute;
+ TypeManager.exception_type = Exception;
+
+ InternalType.Dynamic = Dynamic;
+ InternalType.Null = Null;
+ }
+
+ public BuildinTypeSpec[] AllTypes {
+ get {
+ return types;
+ }
+ }
+
+ public bool CheckDefinitions (ModuleContainer module)
+ {
+ var ctx = module.Compiler;
+ foreach (var p in types) {
+ var found = PredefinedType.Resolve (module, p.Kind, p.Namespace, p.Name, p.Arity, Location.Null);
+ if (found == null || found == p)
+ continue;
- partial class TypeManager {
- //
- // A list of core types that the compiler requires or uses
- //
- static public Type object_type;
- static public Type value_type;
- static public Type string_type;
- static public Type int32_type;
- static public Type uint32_type;
- static public Type int64_type;
- static public Type uint64_type;
- static public Type float_type;
- static public Type double_type;
- static public Type char_type;
- static public Type short_type;
- static public Type decimal_type;
- static public Type bool_type;
- static public Type sbyte_type;
- static public Type byte_type;
- static public Type ushort_type;
- static public Type enum_type;
- static public Type delegate_type;
- static public Type multicast_delegate_type;
- static public Type void_type;
- static public Type null_type;
- static public Type array_type;
- static public Type runtime_handle_type;
- static public Type type_type;
- static public Type ienumerator_type;
- static public Type ienumerable_type;
- static public Type idisposable_type;
- static public Type iasyncresult_type;
- static public Type asynccallback_type;
- static public Type intptr_type;
- static public Type uintptr_type;
- static public Type runtime_field_handle_type;
- static public Type runtime_argument_handle_type;
- static public Type attribute_type;
- static public Type void_ptr_type;
- static public Type exception_type;
-
- static public Type typed_reference_type;
- static public Type arg_iterator_type;
- static public Type mbr_type;
- public static Type runtime_helpers_type;
+ var tc = found.MemberDefinition as TypeContainer;
+ if (tc != null) {
+ var ns = module.GlobalRootNamespace.GetNamespace (p.Namespace, false);
+ ns.ReplaceTypeWithPredefined (found, p);
- //
- // C# 2.0
- //
- static internal Type isvolatile_type;
- static public Type generic_ilist_type;
- static public Type generic_icollection_type;
- static public Type generic_ienumerator_type;
- static public Type generic_ienumerable_type;
- static public Type generic_nullable_type;
+ tc.SetPredefinedSpec (p);
+ p.SetDefinition (found);
+ }
+ }
- //
- // C# 3.0
- //
- static internal Type expression_type;
- public static Type parameter_expression_type;
- public static Type fieldinfo_type;
- public static Type methodinfo_type;
- public static Type ctorinfo_type;
+ if (ctx.Report.Errors != 0)
+ return false;
+
+ // Set internal build-in types
+ Dynamic.SetDefinition (Object);
+ Null.SetDefinition (Object);
+
+ return true;
+ }
+ }
//
- // C# 4.0
+ // Compiler predefined types. Usually used for compiler generated
+ // code or for comparison against well known framework type
//
- public static Type call_site_type;
- public static Type generic_call_site_type;
+ class PredefinedTypes
+ {
+ // TODO: These two exist only to reject type comparison
+ public readonly PredefinedType TypedReference;
+ public readonly PredefinedType ArgIterator;
- //
- // 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;
- static public TypeExpr system_intptr_expr;
- public static TypeExpr expression_type_expr;
+ public readonly PredefinedType MarshalByRefObject;
+ public readonly PredefinedType RuntimeHelpers;
+ public readonly PredefinedType IAsyncResult;
+ public readonly PredefinedType AsyncCallback;
+ public readonly PredefinedType RuntimeArgumentHandle;
+ public readonly PredefinedType CharSet;
+ public readonly PredefinedType IsVolatile;
+ public readonly PredefinedType IEnumeratorGeneric;
+ public readonly PredefinedType IListGeneric;
+ public readonly PredefinedType ICollectionGeneric;
+ public readonly PredefinedType IEnumerableGeneric;
+ public readonly PredefinedType Nullable;
+ public readonly PredefinedType Activator;
+ public readonly PredefinedType Interlocked;
+ public readonly PredefinedType Monitor;
+ public readonly PredefinedType NotSupportedException;
+ public readonly PredefinedType RuntimeFieldHandle;
+ public readonly PredefinedType RuntimeMethodHandle;
+ public readonly PredefinedType SecurityAction;
+ //
+ // C# 3.0
+ //
+ public readonly PredefinedType Expression;
+ public readonly PredefinedType ExpressionGeneric;
+ public readonly PredefinedType ParameterExpression;
+ public readonly PredefinedType FieldInfo;
+ public readonly PredefinedType MethodBase;
+ public readonly PredefinedType MethodInfo;
+ public readonly PredefinedType ConstructorInfo;
- //
- // These methods are called by code generated by the compiler
- //
- static public FieldInfo string_empty;
- static public MethodInfo system_type_get_type_from_handle;
- static public MethodInfo bool_movenext_void;
- static public MethodInfo void_dispose_void;
- static public MethodInfo void_monitor_enter_object;
- static public MethodInfo void_monitor_exit_object;
- static public MethodInfo void_initializearray_array_fieldhandle;
- static public MethodInfo delegate_combine_delegate_delegate;
- static public MethodInfo delegate_remove_delegate_delegate;
- static public PropertyInfo int_get_offset_to_string_data;
- static public MethodInfo int_interlocked_compare_exchange;
- static public PropertyInfo ienumerator_getcurrent;
- public static MethodInfo methodbase_get_type_from_handle;
- public static MethodInfo methodbase_get_type_from_handle_generic;
- public static MethodInfo fieldinfo_get_field_from_handle;
- public static MethodInfo fieldinfo_get_field_from_handle_generic;
- static public MethodInfo activator_create_instance;
+ //
+ // C# 4.0
+ //
+ public readonly PredefinedType Binder;
+ public readonly PredefinedType CallSite;
+ public readonly PredefinedType CallSiteGeneric;
+ public readonly PredefinedType BinderFlags;
- //
- // The constructors.
- //
- static public ConstructorInfo void_decimal_ctor_five_args;
- static public ConstructorInfo void_decimal_ctor_int_arg;
- public static ConstructorInfo void_decimal_ctor_long_arg;
+ public PredefinedTypes (ModuleContainer module)
+ {
+ TypedReference = new PredefinedType (module, MemberKind.Struct, "System", "TypedReference");
+ ArgIterator = new PredefinedType (module, MemberKind.Struct, "System", "ArgIterator");
+ MarshalByRefObject = new PredefinedType (module, MemberKind.Class, "System", "MarshalByRefObject");
+ RuntimeHelpers = new PredefinedType (module, MemberKind.Class, "System.Runtime.CompilerServices", "RuntimeHelpers");
+ IAsyncResult = new PredefinedType (module, MemberKind.Interface, "System", "IAsyncResult");
+ AsyncCallback = new PredefinedType (module, MemberKind.Delegate, "System", "AsyncCallback");
+ RuntimeArgumentHandle = new PredefinedType (module, MemberKind.Struct, "System", "RuntimeArgumentHandle");
+ CharSet = new PredefinedType (module, MemberKind.Enum, "System.Runtime.InteropServices", "CharSet");
+ IsVolatile = new PredefinedType (module, MemberKind.Class, "System.Runtime.CompilerServices", "IsVolatile");
+ IEnumeratorGeneric = new PredefinedType (module, MemberKind.Interface, "System.Collections.Generic", "IEnumerator", 1);
+ IListGeneric = new PredefinedType (module, MemberKind.Interface, "System.Collections.Generic", "IList", 1);
+ ICollectionGeneric = new PredefinedType (module, MemberKind.Interface, "System.Collections.Generic", "ICollection", 1);
+ IEnumerableGeneric = new PredefinedType (module, MemberKind.Interface, "System.Collections.Generic", "IEnumerable", 1);
+ Nullable = new PredefinedType (module, MemberKind.Struct, "System", "Nullable", 1);
+ Activator = new PredefinedType (module, MemberKind.Class, "System", "Activator");
+ Interlocked = new PredefinedType (module, MemberKind.Class, "System.Threading", "Interlocked");
+ Monitor = new PredefinedType (module, MemberKind.Class, "System.Threading", "Monitor");
+ NotSupportedException = new PredefinedType (module, MemberKind.Class, "System", "NotSupportedException");
+ RuntimeFieldHandle = new PredefinedType (module, MemberKind.Struct, "System", "RuntimeFieldHandle");
+ RuntimeMethodHandle = new PredefinedType (module, MemberKind.Struct, "System", "RuntimeMethodHandle");
+ SecurityAction = new PredefinedType (module, MemberKind.Enum, "System.Security.Permissions", "SecurityAction");
+
+ Expression = new PredefinedType (module, MemberKind.Class, "System.Linq.Expressions", "Expression");
+ ExpressionGeneric = new PredefinedType (module, MemberKind.Class, "System.Linq.Expressions", "Expression", 1);
+ ParameterExpression = new PredefinedType (module, MemberKind.Class, "System.Linq.Expressions", "ParameterExpression");
+ FieldInfo = new PredefinedType (module, MemberKind.Class, "System.Reflection", "FieldInfo");
+ MethodBase = new PredefinedType (module, MemberKind.Class, "System.Reflection", "MethodBase");
+ MethodInfo = new PredefinedType (module, MemberKind.Class, "System.Reflection", "MethodInfo");
+ ConstructorInfo = new PredefinedType (module, MemberKind.Class, "System.Reflection", "ConstructorInfo");
+
+ CallSite = new PredefinedType (module, MemberKind.Class, "System.Runtime.CompilerServices", "CallSite");
+ CallSiteGeneric = new PredefinedType (module, MemberKind.Class, "System.Runtime.CompilerServices", "CallSite", 1);
+ Binder = new PredefinedType (module, MemberKind.Class, "Microsoft.CSharp.RuntimeBinder", "Binder");
+ BinderFlags = new PredefinedType (module, MemberKind.Enum, "Microsoft.CSharp.RuntimeBinder", "CSharpBinderFlags");
+
+ //
+ // Define types which are used for comparison. It does not matter
+ // if they don't exist as no error report is needed
+ //
+ TypedReference.Define ();
+ ArgIterator.Define ();
+ MarshalByRefObject.Define ();
+ CharSet.Define ();
+
+ IEnumerableGeneric.Define ();
+ IListGeneric.Define ();
+ ICollectionGeneric.Define ();
+ IEnumerableGeneric.Define ();
+ IEnumeratorGeneric.Define ();
+ Nullable.Define ();
+ ExpressionGeneric.Define ();
+
+ // Deal with obsolete static types
+ // TODO: remove
+ TypeManager.typed_reference_type = TypedReference.TypeSpec;
+ TypeManager.arg_iterator_type = ArgIterator.TypeSpec;
+ TypeManager.mbr_type = MarshalByRefObject.TypeSpec;
+ TypeManager.generic_ilist_type = IListGeneric.TypeSpec;
+ TypeManager.generic_icollection_type = ICollectionGeneric.TypeSpec;
+ TypeManager.generic_ienumerator_type = IEnumeratorGeneric.TypeSpec;
+ TypeManager.generic_ienumerable_type = IEnumerableGeneric.TypeSpec;
+ TypeManager.generic_nullable_type = Nullable.TypeSpec;
+ TypeManager.expression_type = ExpressionGeneric.TypeSpec;
+ }
+ }
+
+ public class PredefinedType
+ {
+ string name;
+ string ns;
+ int arity;
+ MemberKind kind;
+ ModuleContainer module;
+ protected TypeSpec type;
+
+ public PredefinedType (ModuleContainer module, MemberKind kind, string ns, string name, int arity)
+ : this (module, kind, ns, name)
+ {
+ this.arity = arity;
+ }
+
+ public PredefinedType (ModuleContainer module, MemberKind kind, string ns, string name)
+ {
+ this.module = module;
+ this.kind = kind;
+ this.name = name;
+ this.ns = ns;
+ }
- static PtrHashtable builder_to_declspace;
+ #region Properties
- static PtrHashtable builder_to_member_cache;
+ public int Arity {
+ get {
+ return arity;
+ }
+ }
+
+ public bool IsDefined {
+ get {
+ return type != null;
+ }
+ }
- // <remarks>
- // Tracks the interfaces implemented by typebuilders. We only
- // enter those who do implement or or more interfaces
- // </remarks>
- static PtrHashtable builder_to_ifaces;
+ public string Name {
+ get {
+ return name;
+ }
+ }
- // <remarks>
- // Maps a MethodBase to its ParameterData (either InternalParameters or ReflectionParameters)
- // <remarks>
- static Hashtable method_params;
+ public string Namespace {
+ get {
+ return ns;
+ }
+ }
- // <remarks>
- // A hash table from override methods to their base virtual method.
- // <remarks>
- static Hashtable method_overrides;
+ public TypeSpec TypeSpec {
+ get {
+ return type;
+ }
+ }
- // <remarks>
- // Keeps track of methods
- // </remarks>
+ #endregion
- static Hashtable builder_to_method;
+ public bool Define ()
+ {
+ if (type != null)
+ return true;
- // <remarks>
- // Contains all public types from referenced assemblies.
- // This member is used only if CLS Compliance verification is required.
- // </remarks>
- public static Hashtable AllClsTopLevelTypes;
+ Namespace type_ns = module.GlobalRootNamespace.GetNamespace (ns, true);
+ var te = type_ns.LookupType (module.Compiler, name, arity, true, Location.Null);
+ if (te == null)
+ return false;
- static Hashtable fieldbuilders_to_fields;
- static Hashtable propertybuilder_to_property;
- static Hashtable fields;
- static Hashtable events;
- static PtrHashtable assembly_internals_vis_attrs;
+ if (te.Type.Kind != kind)
+ return false;
- public static void CleanUp ()
- {
- // Lets get everything clean so that we can collect before generating code
- builder_to_declspace = null;
- builder_to_member_cache = null;
- builder_to_ifaces = null;
- builder_to_type_param = null;
- method_params = null;
- builder_to_method = null;
-
- fields = null;
- events = null;
- type_hash = null;
- propertybuilder_to_property = null;
+ type = te.Type;
+ return true;
+ }
- TypeHandle.CleanUp ();
+ public FieldSpec GetField (string name, TypeSpec memberType, Location loc)
+ {
+ return TypeManager.GetPredefinedField (type, name, loc, memberType);
+ }
+
+ public string GetSignatureForError ()
+ {
+ return ns + "." + name;
+ }
+
+ public static TypeSpec Resolve (ModuleContainer module, MemberKind kind, string ns, string name, int arity, Location loc)
+ {
+ Namespace type_ns = module.GlobalRootNamespace.GetNamespace (ns, true);
+ var te = type_ns.LookupType (module.Compiler, name, arity, false, Location.Null);
+ if (te == null) {
+ module.Compiler.Report.Error (518, loc, "The predefined type `{0}.{1}' is not defined or imported", ns, name);
+ return null;
+ }
+
+ var type = te.Type;
+ if (type.Kind != kind) {
+ module.Compiler.Report.Error (520, loc, "The predefined type `{0}.{1}' is not declared correctly", ns, name);
+ return null;
+ }
+
+ return type;
+ }
+
+ public TypeSpec Resolve (Location loc)
+ {
+ if (type == null)
+ type = Resolve (module, kind, ns, name, arity, loc);
+
+ return type;
+ }
}
+ partial class TypeManager {
//
- // These are expressions that represent some of the internal data types, used
- // elsewhere
+ // A list of core types that the compiler requires or uses
//
- static void InitExpressionTypes ()
- {
- system_object_expr = new TypeLookupExpression ("System", "Object");
- system_string_expr = new TypeLookupExpression ("System", "String");
- system_boolean_expr = new TypeLookupExpression ("System", "Boolean");
- system_decimal_expr = new TypeLookupExpression ("System", "Decimal");
- system_single_expr = new TypeLookupExpression ("System", "Single");
- system_double_expr = new TypeLookupExpression ("System", "Double");
- system_sbyte_expr = new TypeLookupExpression ("System", "SByte");
- system_byte_expr = new TypeLookupExpression ("System", "Byte");
- system_int16_expr = new TypeLookupExpression ("System", "Int16");
- system_uint16_expr = new TypeLookupExpression ("System", "UInt16");
- system_int32_expr = new TypeLookupExpression ("System", "Int32");
- system_uint32_expr = new TypeLookupExpression ("System", "UInt32");
- system_int64_expr = new TypeLookupExpression ("System", "Int64");
- system_uint64_expr = new TypeLookupExpression ("System", "UInt64");
- system_char_expr = new TypeLookupExpression ("System", "Char");
- system_void_expr = new TypeLookupExpression ("System", "Void");
- system_valuetype_expr = new TypeLookupExpression ("System", "ValueType");
- system_intptr_expr = new TypeLookupExpression ("System", "IntPtr");
- }
+ static public BuildinTypeSpec object_type;
+ static public BuildinTypeSpec value_type;
+ static public BuildinTypeSpec string_type;
+ static public BuildinTypeSpec int32_type;
+ static public BuildinTypeSpec uint32_type;
+ static public BuildinTypeSpec int64_type;
+ static public BuildinTypeSpec uint64_type;
+ static public BuildinTypeSpec float_type;
+ static public BuildinTypeSpec double_type;
+ static public BuildinTypeSpec char_type;
+ static public BuildinTypeSpec short_type;
+ static public BuildinTypeSpec decimal_type;
+ static public BuildinTypeSpec bool_type;
+ static public BuildinTypeSpec sbyte_type;
+ static public BuildinTypeSpec byte_type;
+ static public BuildinTypeSpec ushort_type;
+ static public BuildinTypeSpec enum_type;
+ static public BuildinTypeSpec delegate_type;
+ static public BuildinTypeSpec multicast_delegate_type;
+ static public BuildinTypeSpec void_type;
+ static public BuildinTypeSpec array_type;
+ static public BuildinTypeSpec runtime_handle_type;
+ static public BuildinTypeSpec type_type;
+ static public BuildinTypeSpec ienumerator_type;
+ static public BuildinTypeSpec ienumerable_type;
+ static public BuildinTypeSpec idisposable_type;
+ static public BuildinTypeSpec intptr_type;
+ static public BuildinTypeSpec uintptr_type;
+ static public BuildinTypeSpec runtime_field_handle_type;
+ static public BuildinTypeSpec attribute_type;
+ static public BuildinTypeSpec exception_type;
+
+
+ static public TypeSpec typed_reference_type;
+ static public TypeSpec arg_iterator_type;
+ static public TypeSpec mbr_type;
+ static public TypeSpec generic_ilist_type;
+ static public TypeSpec generic_icollection_type;
+ static public TypeSpec generic_ienumerator_type;
+ static public TypeSpec generic_ienumerable_type;
+ static public TypeSpec generic_nullable_type;
+ static internal TypeSpec expression_type;
+
+ //
+ // These methods are called by code generated by the compiler
+ //
+ static public FieldSpec string_empty;
+ static public MethodSpec system_type_get_type_from_handle;
+ static public MethodSpec bool_movenext_void;
+ static public MethodSpec void_dispose_void;
+ static public MethodSpec void_monitor_enter_object;
+ static public MethodSpec void_monitor_exit_object;
+ static public MethodSpec void_initializearray_array_fieldhandle;
+ static public MethodSpec delegate_combine_delegate_delegate;
+ 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;
+ public static MethodSpec activator_create_instance;
+
+ //
+ // The constructors.
+ //
+ static public MethodSpec void_decimal_ctor_five_args;
+ static public MethodSpec void_decimal_ctor_int_arg;
+ public static MethodSpec void_decimal_ctor_long_arg;
static TypeManager ()
{
static public void Reset ()
{
- object_type = null;
-
- InitExpressionTypes ();
-
- builder_to_declspace = new PtrHashtable ();
- builder_to_member_cache = new PtrHashtable ();
- builder_to_method = new PtrHashtable ();
- builder_to_type_param = new PtrHashtable ();
- method_params = new PtrHashtable ();
- method_overrides = new PtrHashtable ();
- builder_to_ifaces = new PtrHashtable ();
-
- fieldbuilders_to_fields = new Hashtable ();
- propertybuilder_to_property = new Hashtable ();
- fields = new Hashtable ();
- type_hash = new DoubleHash ();
- assembly_internals_vis_attrs = new PtrHashtable ();
- iface_cache = new PtrHashtable ();
-
- closure = new Closure ();
- FilterWithClosure_delegate = new MemberFilter (closure.Filter);
-
+// object_type = null;
+
// TODO: I am really bored by all this static stuff
system_type_get_type_from_handle =
bool_movenext_void =
void_monitor_enter_object =
void_monitor_exit_object =
void_initializearray_array_fieldhandle =
- delegate_combine_delegate_delegate =
- delegate_remove_delegate_delegate =
int_interlocked_compare_exchange =
+ gen_interlocked_compare_exchange =
methodbase_get_type_from_handle =
methodbase_get_type_from_handle_generic =
fieldinfo_get_field_from_handle =
fieldinfo_get_field_from_handle_generic =
- activator_create_instance = null;
+ activator_create_instance =
+ delegate_combine_delegate_delegate =
+ delegate_remove_delegate_delegate = null;
int_get_offset_to_string_data =
ienumerator_getcurrent = null;
void_decimal_ctor_int_arg =
void_decimal_ctor_long_arg = null;
- isvolatile_type = null;
-
- // to uncover regressions
- AllClsTopLevelTypes = null;
+ string_empty = null;
+
+ typed_reference_type = arg_iterator_type = mbr_type =
+ generic_ilist_type = generic_icollection_type = generic_ienumerator_type =
+ generic_ienumerable_type = generic_nullable_type = expression_type = null;
}
- public static void AddUserType (DeclSpace ds)
+ /// <summary>
+ /// Returns the C# name of a type if possible, or the full type name otherwise
+ /// </summary>
+ static public string CSharpName (TypeSpec t)
{
- builder_to_declspace.Add (ds.TypeBuilder, ds);
+ return t.GetSignatureForError ();
}
- //
- // This entry point is used by types that we define under the covers
- //
- public static void RegisterBuilder (Type tb, Type [] ifaces)
+ static public string CSharpName (IList<TypeSpec> types)
{
- if (ifaces != null)
- builder_to_ifaces [tb] = ifaces;
- }
+ if (types.Count == 0)
+ return string.Empty;
- public static void AddMethod (MethodBase builder, IMethodData method)
- {
- builder_to_method.Add (builder, method);
- method_params.Add (builder, method.ParameterInfo);
- }
+ StringBuilder sb = new StringBuilder ();
+ for (int i = 0; i < types.Count; ++i) {
+ if (i > 0)
+ sb.Append (",");
- public static IMethodData GetMethod (MethodBase builder)
- {
- return (IMethodData) builder_to_method [builder];
+ sb.Append (CSharpName (types [i]));
+ }
+ return sb.ToString ();
}
- /// <summary>
- /// Returns the DeclSpace whose Type is `t' or null if there is no
- /// DeclSpace for `t' (ie, the Type comes from a library)
- /// </summary>
- public static DeclSpace LookupDeclSpace (Type t)
+ static public string GetFullNameSignature (MemberSpec mi)
{
- return builder_to_declspace [t] as DeclSpace;
+ return mi.GetSignatureForError ();
}
- /// <summary>
- /// Returns the TypeContainer whose Type is `t' or null if there is no
- /// TypeContainer for `t' (ie, the Type comes from a library)
- /// </summary>
- public static TypeContainer LookupTypeContainer (Type t)
+ static public string CSharpSignature (MemberSpec mb)
{
- return builder_to_declspace [t] as TypeContainer;
+ return mb.GetSignatureForError ();
}
- public static MemberCache LookupMemberCache (Type t)
+ static MemberSpec GetPredefinedMember (TypeSpec t, MemberFilter filter, bool optional, Location loc)
{
- if (t.Module == RootContext.ToplevelTypes.Builder) {
- DeclSpace container = (DeclSpace)builder_to_declspace [t];
- if (container != null)
- return container.MemberCache;
- }
+ var member = MemberCache.FindMember (t, filter, BindingRestriction.DeclaredOnly);
- if (t is GenericTypeParameterBuilder) {
- TypeParameter container = builder_to_type_param [t] as TypeParameter;
+ if (member != null && member.IsAccessible (InternalType.FakeInternalType))
+ return member;
- if (container != null)
- return container.MemberCache;
- }
-
- return TypeHandle.GetMemberCache (t);
- }
+ if (optional)
+ return member;
- public static MemberCache LookupBaseInterfacesCache (Type t)
- {
- Type [] ifaces = GetInterfaces (t);
+ string method_args = null;
+ if (filter.Parameters != null)
+ method_args = filter.Parameters.GetSignatureForError ();
- if (ifaces != null && ifaces.Length == 1)
- return LookupMemberCache (ifaces [0]);
+ RootContext.ToplevelTypes.Compiler.Report.Error (656, loc, "The compiler required member `{0}.{1}{2}' could not be found or is inaccessible",
+ TypeManager.CSharpName (t), filter.Name, method_args);
- // TODO: the builder_to_member_cache should be indexed by 'ifaces', not 't'
- MemberCache cache = builder_to_member_cache [t] as MemberCache;
- if (cache != null)
- return cache;
+ return null;
+ }
- cache = new MemberCache (ifaces);
- builder_to_member_cache.Add (t, cache);
- return cache;
+ //
+ // Returns the ConstructorInfo for "args"
+ //
+ public static MethodSpec GetPredefinedConstructor (TypeSpec t, Location loc, params TypeSpec [] args)
+ {
+ var pc = ParametersCompiled.CreateFullyResolved (args);
+ return GetPredefinedMember (t, MemberFilter.Constructor (pc), false, loc) as MethodSpec;
}
- public static TypeContainer LookupInterface (Type t)
+ //
+ // Returns the method specification for a method named `name' defined
+ // in type `t' which takes arguments of types `args'
+ //
+ public static MethodSpec GetPredefinedMethod (TypeSpec t, string name, Location loc, params TypeSpec [] args)
{
- TypeContainer tc = (TypeContainer) builder_to_declspace [t];
- if ((tc == null) || (tc.Kind != Kind.Interface))
- return null;
+ var pc = ParametersCompiled.CreateFullyResolved (args);
+ return GetPredefinedMethod (t, MemberFilter.Method (name, 0, pc, null), false, loc);
+ }
- return tc;
+ public static MethodSpec GetPredefinedMethod (TypeSpec t, MemberFilter filter, Location loc)
+ {
+ return GetPredefinedMethod (t, filter, false, loc);
}
- public static Delegate LookupDelegate (Type t)
+ public static MethodSpec GetPredefinedMethod (TypeSpec t, MemberFilter filter, bool optional, Location loc)
{
- return builder_to_declspace [t] as Delegate;
+ return GetPredefinedMember (t, filter, optional, loc) as MethodSpec;
}
- public static Class LookupClass (Type t)
+ public static FieldSpec GetPredefinedField (TypeSpec t, string name, Location loc, TypeSpec type)
{
- return (Class) builder_to_declspace [t];
+ return GetPredefinedMember (t, MemberFilter.Field (name, type), false, loc) as FieldSpec;
}
- //
- // 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 ();
+ public static PropertySpec GetPredefinedProperty (TypeSpec t, string name, Location loc, TypeSpec type)
+ {
+ return GetPredefinedMember (t, MemberFilter.Property (name, type), false, loc) as PropertySpec;
+ }
- //
- // Gets the reference to T version of the Type (T&)
- //
- public static Type GetReferenceType (Type t)
+ public static bool IsBuiltinType (TypeSpec t)
{
- return t.MakeByRefType ();
+ 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;
}
//
- // Gets the pointer to T version of the Type (T*)
- //
- public static Type GetPointerType (Type t)
+ // 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 (TypeSpec t)
{
- return GetConstructedType (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 Type GetConstructedType (Type t, string dim)
+ // Obsolete
+ public static bool IsDelegateType (TypeSpec t)
{
- object ret = null;
- if (type_hash.Lookup (t, dim, out ret))
- return (Type) ret;
-
- if (IsDynamicType (t)) {
- // FIXME: this is more like not supported with SRE
- // An example: var v = new [] { d, 1 }; int i = v [0];
- throw new NotImplementedException ("dynamic arrays");
- }
-
- ret = t.Module.GetType (t.ToString () + dim);
- if (ret != null) {
- type_hash.Insert (t, dim, ret);
- return (Type) ret;
- }
+ return t.IsDelegate;
+ }
+
+ // Obsolete
+ public static bool IsEnumType (TypeSpec t)
+ {
+ return t.IsEnum;
+ }
- if (dim == "&") {
- ret = GetReferenceType (t);
- type_hash.Insert (t, dim, ret);
- return (Type) ret;
- }
+ public static bool IsBuiltinOrEnum (TypeSpec t)
+ {
+ if (IsBuiltinType (t))
+ return true;
+
+ if (IsEnumType (t))
+ return true;
- if (t.IsGenericParameter || t.IsGenericType) {
- int pos = 0;
- Type result = t;
- while ((pos < dim.Length) && (dim [pos] == '[')) {
- pos++;
+ return false;
+ }
- if (dim [pos] == ']') {
- result = result.MakeArrayType ();
- pos++;
+ //
+ // Whether a type is unmanaged. This is used by the unsafe code (25.2)
+ //
+ public static bool IsUnmanagedType (TypeSpec t)
+ {
+ var ds = t.MemberDefinition as DeclSpace;
+ if (ds != null)
+ return ds.IsUnmanagedType ();
- if (pos < dim.Length)
- continue;
+ // some builtins that are not unmanaged types
+ if (t == TypeManager.object_type || t == TypeManager.string_type)
+ return false;
- type_hash.Insert (t, dim, result);
- return result;
- }
+ if (IsBuiltinOrEnum (t))
+ return true;
- int rank = 0;
- while (dim [pos] == ',') {
- pos++; rank++;
- }
+ // 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));
- if ((dim [pos] != ']') || (pos != dim.Length-1))
- break;
+ if (!IsValueType (t))
+ return false;
- result = result.MakeArrayType (rank + 1);
- type_hash.Insert (t, dim, result);
- return result;
- }
- }
+ if (t.IsNested && t.DeclaringType.IsGenericOrParentIsGeneric)
+ return false;
- type_hash.Insert (t, dim, null);
- return null;
+ return true;
}
- public static Type GetNestedType (Type t, string name)
+ //
+ // Null is considered to be a reference type
+ //
+ public static bool IsReferenceType (TypeSpec t)
{
- object ret = null;
- if (!type_hash.Lookup (t, name, out ret)) {
- ret = t.GetNestedType (name,
- BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
- type_hash.Insert (t, name, ret);
- }
- return (Type) ret;
+ if (t.IsGenericParameter)
+ return ((TypeParameterSpec) t).IsReferenceType;
+
+ return !t.IsStruct && !IsEnumType (t);
+ }
+
+ public static bool IsValueType (TypeSpec t)
+ {
+ if (t.IsGenericParameter)
+ return ((TypeParameterSpec) t).IsValueType;
+
+ return t.IsStruct || IsEnumType (t);
}
- /// <summary>
- /// Fills static table with exported types from all referenced assemblies.
- /// This information is required for CLS Compliance tests.
- /// </summary>
- public static void LoadAllImportedTypes ()
+ public static bool IsStruct (TypeSpec t)
{
- AllClsTopLevelTypes = new Hashtable (1500);
- foreach (Assembly a in GlobalRootNamespace.Instance.Assemblies) {
- foreach (Type t in a.GetExportedTypes ()) {
- AllClsTopLevelTypes [t.FullName.ToLower (System.Globalization.CultureInfo.InvariantCulture)] = null;
- }
- }
+ return t.IsStruct;
}
- /// <summary>
- /// Returns the C# name of a type if possible, or the full type name otherwise
- /// </summary>
- static public string CSharpName (Type t)
+ public static bool IsFamilyAccessible (TypeSpec type, TypeSpec parent)
{
- if (t == null_type)
- return "null";
+// TypeParameter tparam = LookupTypeParameter (type);
+// TypeParameter pparam = LookupTypeParameter (parent);
- if (t == typeof (ArglistAccess))
- return "__arglist";
-
- if (t == typeof (AnonymousMethodBody))
- return "anonymous method";
+ if (type.Kind == MemberKind.TypeParameter && parent.Kind == MemberKind.TypeParameter) { // (tparam != null) && (pparam != null)) {
+ if (type == parent)
+ return true;
- if (t == typeof (MethodGroupExpr))
- return "method group";
+ throw new NotImplementedException ("net");
+// return tparam.IsSubclassOf (parent);
+ }
- if (IsDynamicType (t))
- return "dynamic";
+ do {
+ if (IsInstantiationOfSameGenericType (type, parent))
+ return true;
- if (t == null)
- return "internal error";
+ type = type.BaseType;
+ } while (type != null);
- return CSharpName (GetFullName (t), t);
+ return false;
}
- static readonly char [] elements = new char [] { '*', '[' };
-
- public static string CSharpName (string name, Type type)
+ //
+ // Checks whether `type' is a subclass or nested child of `base_type'.
+ //
+ public static bool IsNestedFamilyAccessible (TypeSpec type, TypeSpec base_type)
{
- if (name.Length > 10) {
- string s;
- switch (name) {
- case "System.Int32": s = "int"; break;
- case "System.Int64": s = "long"; break;
- case "System.String": s = "string"; break;
- case "System.Boolean": s = "bool"; break;
- case "System.Void": s = "void"; break;
- case "System.Object": s = "object"; break;
- case "System.UInt32": s = "uint"; break;
- case "System.Int16": s = "short"; break;
- case "System.UInt16": s = "ushort"; break;
- case "System.UInt64": s = "ulong"; break;
- case "System.Single": s = "float"; break;
- case "System.Double": s = "double"; break;
- case "System.Decimal": s = "decimal"; break;
- case "System.Char": s = "char"; break;
- case "System.Byte": s = "byte"; break;
- case "System.SByte": s = "sbyte"; break;
- default: s = null; break;
- }
-
- if (s != null) {
- //
- // Predefined names can come from mscorlib only
- //
- if (type == null || type.Module.Name == "mscorlib.dll" || !RootContext.StdLib)
- return s;
-
- return name;
- }
-
- if (name [0] == AnonymousTypeClass.ClassNamePrefix [0] && name.StartsWith (AnonymousTypeClass.ClassNamePrefix))
- return AnonymousTypeClass.SignatureForError;
+ do {
+ if (IsFamilyAccessible (type, base_type))
+ return true;
- int idx = name.IndexOfAny (elements, 10);
- if (idx > 0)
- return CSharpName (name.Substring (0, idx), type) + name.Substring (idx);
- }
+ // Handle nested types.
+ type = type.DeclaringType;
+ } while (type != null);
- return name.Replace ('+', '.');
+ return false;
}
- static public string CSharpName (Type[] types)
+ //
+ // Checks whether `type' is a nested child of `parent'.
+ //
+ public static bool IsNestedChildOf (TypeSpec type, ITypeDefinition parent)
{
- if (types.Length == 0)
- return string.Empty;
+ if (type == null)
+ return false;
- StringBuilder sb = new StringBuilder ();
- for (int i = 0; i < types.Length; ++i) {
- if (i > 0)
- sb.Append (", ");
+ if (type.MemberDefinition == parent)
+ return false;
- sb.Append (CSharpName (types [i]));
- }
- return sb.ToString ();
- }
-
- /// <summary>
- /// Returns the signature of the method with full namespace classification
- /// </summary>
- static public string GetFullNameSignature (MemberInfo mi)
- {
- PropertyInfo pi = mi as PropertyInfo;
- if (pi != null) {
- MethodBase pmi = pi.GetGetMethod (true);
- if (pmi == null)
- pmi = pi.GetSetMethod (true);
- if (GetParameterData (pmi).Count > 0)
- mi = pmi;
- }
- return (mi is MethodBase)
- ? CSharpSignature (mi as MethodBase)
- : CSharpName (mi.DeclaringType) + '.' + mi.Name;
- }
-
- private static int GetFullName (Type t, StringBuilder sb)
- {
- int pos = 0;
-
- if (!t.IsGenericType) {
- sb.Append (t.FullName);
- return 0;
- }
-
- if (t.DeclaringType != null) {
- pos = GetFullName (t.DeclaringType, sb);
- sb.Append ('.');
- } else if (t.Namespace != null && t.Namespace.Length != 0) {
- sb.Append (t.Namespace);
- sb.Append ('.');
- }
- sb.Append (RemoveGenericArity (t.Name));
-
- Type[] this_args = GetTypeArguments (t);
-
- if (this_args.Length < pos)
- throw new InternalErrorException (
- "Enclosing class " + t.DeclaringType + " has more type arguments than " + t);
- if (this_args.Length == pos)
- return pos;
-
- sb.Append ('<');
- for (;;) {
- sb.Append (CSharpName (this_args [pos++]));
- if (pos == this_args.Length)
- break;
- sb.Append (',');
- }
- sb.Append ('>');
- return pos;
- }
-
- static string GetFullName (Type t)
- {
- if (t.IsArray) {
- string dimension = t.Name.Substring (t.Name.LastIndexOf ('['));
- return GetFullName (GetElementType (t)) + dimension;
- }
+ type = type.DeclaringType;
+ while (type != null) {
+ if (type.MemberDefinition == parent)
+ return true;
- if (IsNullableType (t) && !t.IsGenericTypeDefinition) {
- t = TypeToCoreType (GetTypeArguments (t)[0]);
- return CSharpName (t) + "?";
+ type = type.DeclaringType;
}
- if (t.IsGenericParameter)
- return t.Name;
- if (!t.IsGenericType)
- return t.FullName;
-
- StringBuilder sb = new StringBuilder ();
- int pos = GetFullName (t, sb);
- if (pos <= 0)
- throw new InternalErrorException ("Generic Type " + t + " doesn't have type arguments");
- return sb.ToString ();
+ return false;
}
- public static string RemoveGenericArity (string from)
+ public static bool IsSpecialType (TypeSpec t)
{
- int i = from.IndexOf ('`');
- if (i > 0)
- return from.Substring (0, i);
- return from;
+ return t == arg_iterator_type || t == typed_reference_type;
}
- /// <summary>
- /// When we need to report accessors as well
- /// </summary>
- static public string CSharpSignature (MethodBase mb)
+ public static TypeSpec GetElementType (TypeSpec t)
{
- return CSharpSignature (mb, false);
+ return ((ElementTypeSpec)t).Element;
}
/// <summary>
- /// Returns the signature of the method
+ /// This method is not implemented by MS runtime for dynamic types
/// </summary>
- static public string CSharpSignature (MethodBase mb, bool show_accessor)
- {
- StringBuilder sig = new StringBuilder (CSharpName (mb.DeclaringType));
- sig.Append ('.');
-
- AParametersCollection iparams = GetParameterData (mb);
- string parameters = iparams.GetSignatureForError ();
- int accessor_end = 0;
-
- if (!mb.IsConstructor && TypeManager.IsSpecialMethod (mb)) {
- string op_name = Operator.GetName (mb.Name);
- if (op_name != null) {
- if (op_name == "explicit" || op_name == "implicit") {
- sig.Append (op_name);
- sig.Append (" operator ");
- sig.Append (CSharpName (((MethodInfo)mb).ReturnType));
- } else {
- sig.Append ("operator ");
- sig.Append (op_name);
- }
- sig.Append (parameters);
- return sig.ToString ();
- }
-
- bool is_getter = mb.Name.StartsWith ("get_");
- bool is_setter = mb.Name.StartsWith ("set_");
- if (is_getter || is_setter || mb.Name.StartsWith ("add_")) {
- accessor_end = 3;
- } else if (mb.Name.StartsWith ("remove_")) {
- accessor_end = 6;
- }
-
- // Is indexer
- if (iparams.Count > (is_getter ? 0 : 1)) {
- sig.Append ("this[");
- if (is_getter)
- sig.Append (parameters.Substring (1, parameters.Length - 2));
- else
- sig.Append (parameters.Substring (1, parameters.LastIndexOf (',') - 1));
- sig.Append (']');
- } else {
- sig.Append (mb.Name.Substring (accessor_end + 1));
- }
- } else {
- if (mb.Name == ".ctor")
- sig.Append (RemoveGenericArity (mb.DeclaringType.Name));
- else {
- sig.Append (mb.Name);
-
- if (IsGenericMethod (mb)) {
- Type[] args = GetGenericArguments (mb);
- sig.Append ('<');
- for (int i = 0; i < args.Length; i++) {
- if (i > 0)
- sig.Append (',');
- sig.Append (CSharpName (args [i]));
- }
- sig.Append ('>');
- }
- }
-
- sig.Append (parameters);
- }
-
- if (show_accessor && accessor_end > 0) {
- sig.Append ('.');
- sig.Append (mb.Name.Substring (0, accessor_end));
- }
-
- return sig.ToString ();
- }
-
- public static string GetMethodName (MethodInfo m)
+ public static bool HasElementType (TypeSpec t)
{
- if (!IsGenericMethodDefinition (m) && !IsGenericMethod (m))
- return m.Name;
-
- return MemberName.MakeName (m.Name, TypeManager.GetGenericArguments (m).Length);
+ return t is ElementTypeSpec;
}
- static public string CSharpSignature (EventInfo ei)
- {
- return CSharpName (ei.DeclaringType) + "." + ei.Name;
- }
+ static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat;
- //
- // Looks up a type, and aborts if it is not found. This is used
- // by predefined types required by the compiler
- //
- public static Type CoreLookupType (CompilerContext ctx, string ns_name, string name, Kind type_kind, bool required)
+ // This is a custom version of Convert.ChangeType() which works
+ // with the TypeBuilder defined types when compiling corlib.
+ public static object ChangeType (object value, TypeSpec targetType, out bool error)
{
- Namespace ns = GlobalRootNamespace.Instance.GetNamespace (ns_name, true);
- Expression expr = ns.Lookup (ctx, name, Location.Null);
-
- if (expr == null) {
- if (required) {
- ctx.Report.Error (518, "The predefined type `{0}.{1}' is not defined or imported",
- ns_name, name);
- }
+ IConvertible convert_value = value as IConvertible;
+
+ if (convert_value == null){
+ error = true;
return null;
}
-
- Type t = expr.Type;
- if (RootContext.StdLib || t == null || !required)
- return t;
-
- // TODO: All predefined imported types have to have correct signature
- if (t.Module != RootContext.ToplevelTypes.Builder)
- return t;
-
- DeclSpace ds = (DeclSpace)RootContext.ToplevelTypes.GetDefinition (t.FullName);
- if (ds is Delegate) {
- if (type_kind == Kind.Delegate)
- return t;
- } else {
- TypeContainer tc = (TypeContainer)ds;
- if (tc.Kind == type_kind)
- return t;
- }
-
- ctx.Report.Error (520, ds.Location, "The predefined type `{0}.{1}' is not declared correctly",
- ns_name, name);
- return null;
- }
-
- static MemberInfo GetPredefinedMember (Type t, string name, MemberTypes mt, Location loc, params Type [] args)
- {
- const BindingFlags flags = instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly;
-
- MemberInfo [] members = MemberLookup (null, null, t, mt, flags, name, null);
- if (members != null) {
- for (int i = 0; i < members.Length; ++i) {
- MemberInfo member = members [i];
- if (mt == MemberTypes.Method || mt == MemberTypes.Constructor) {
- MethodBase mb = member as MethodBase;
- if (mb == null)
- continue;
-
- AParametersCollection pd = TypeManager.GetParameterData (mb);
- if (IsEqual (pd.Types, args))
- return member;
- }
- if (mt == MemberTypes.Field) {
- FieldInfo fi = member as FieldInfo;
- if (fi == null)
- continue;
-
- if (args.Length >= 1 && !IsEqual (TypeToCoreType (fi.FieldType), args [0]))
- continue;
-
- return member;
- }
-
- if (mt == MemberTypes.Property) {
- PropertyInfo pi = member as PropertyInfo;
- if (pi == null)
- continue;
-
- if (args.Length >= 1 && !IsEqual (TypeToCoreType (pi.PropertyType), args [0]))
- continue;
-
- return member;
- }
- }
- }
-
- string method_args = null;
- if (mt == MemberTypes.Method || mt == MemberTypes.Constructor)
- method_args = "(" + TypeManager.CSharpName (args) + ")";
-
- RootContext.ToplevelTypes.Compiler.Report.Error (656, loc, "The compiler required member `{0}.{1}{2}' could not be found or is inaccessible",
- TypeManager.CSharpName (t), name, method_args);
-
- return null;
- }
-
- //
- // Returns the ConstructorInfo for "args"
- //
- public static ConstructorInfo GetPredefinedConstructor (Type t, Location loc, params Type [] args)
- {
- return (ConstructorInfo) GetPredefinedMember (t, ConstructorInfo.ConstructorName, MemberTypes.Constructor, loc, args);
- }
-
- //
- // Returns the MethodInfo for a method named `name' defined
- // in type `t' which takes arguments of types `args'
- //
- public static MethodInfo GetPredefinedMethod (Type t, string name, Location loc, params Type [] args)
- {
- return (MethodInfo)GetPredefinedMember (t, name, MemberTypes.Method, loc, args);
- }
-
- public static FieldInfo GetPredefinedField (Type t, string name, Location loc, params Type [] args)
- {
- return (FieldInfo) GetPredefinedMember (t, name, MemberTypes.Field, loc, args);
- }
-
- public static PropertyInfo GetPredefinedProperty (Type t, string name, Location loc, params Type [] args)
- {
- return (PropertyInfo) GetPredefinedMember (t, name, MemberTypes.Property, loc, args);
- }
-
- /// <remarks>
- /// The types have to be initialized after the initial
- /// population of the type has happened (for example, to
- /// bootstrap the corlib.dll
- /// </remarks>
- public static bool InitCoreTypes (CompilerContext ctx)
- {
- object_type = CoreLookupType (ctx, "System", "Object", Kind.Class, true);
- system_object_expr.Type = object_type;
- value_type = CoreLookupType (ctx, "System", "ValueType", Kind.Class, true);
- system_valuetype_expr.Type = value_type;
- attribute_type = CoreLookupType (ctx, "System", "Attribute", Kind.Class, true);
-
- int32_type = CoreLookupType (ctx, "System", "Int32", Kind.Struct, true);
- system_int32_expr.Type = int32_type;
- int64_type = CoreLookupType (ctx, "System", "Int64", Kind.Struct, true);
- system_int64_expr.Type = int64_type;
- uint32_type = CoreLookupType (ctx, "System", "UInt32", Kind.Struct, true);
- system_uint32_expr.Type = uint32_type;
- uint64_type = CoreLookupType (ctx, "System", "UInt64", Kind.Struct, true);
- system_uint64_expr.Type = uint64_type;
- byte_type = CoreLookupType (ctx, "System", "Byte", Kind.Struct, true);
- system_byte_expr.Type = byte_type;
- sbyte_type = CoreLookupType (ctx, "System", "SByte", Kind.Struct, true);
- system_sbyte_expr.Type = sbyte_type;
- short_type = CoreLookupType (ctx, "System", "Int16", Kind.Struct, true);
- system_int16_expr.Type = short_type;
- ushort_type = CoreLookupType (ctx, "System", "UInt16", Kind.Struct, true);
- system_uint16_expr.Type = ushort_type;
-
- ienumerator_type = CoreLookupType (ctx, "System.Collections", "IEnumerator", Kind.Interface, true);
- ienumerable_type = CoreLookupType (ctx, "System.Collections", "IEnumerable", Kind.Interface, true);
- idisposable_type = CoreLookupType (ctx, "System", "IDisposable", Kind.Interface, true);
-
- // HACK: DefineType immediately resolves iterators (very wrong)
- generic_ienumerator_type = CoreLookupType (ctx, "System.Collections.Generic", "IEnumerator`1", Kind.Interface, false);
-
- char_type = CoreLookupType (ctx, "System", "Char", Kind.Struct, true);
- system_char_expr.Type = char_type;
- string_type = CoreLookupType (ctx, "System", "String", Kind.Class, true);
- system_string_expr.Type = string_type;
- float_type = CoreLookupType (ctx, "System", "Single", Kind.Struct, true);
- system_single_expr.Type = float_type;
- double_type = CoreLookupType (ctx, "System", "Double", Kind.Struct, true);
- system_double_expr.Type = double_type;
- decimal_type = CoreLookupType (ctx, "System", "Decimal", Kind.Struct, true);
- system_decimal_expr.Type = decimal_type;
- bool_type = CoreLookupType (ctx, "System", "Boolean", Kind.Struct, true);
- system_boolean_expr.Type = bool_type;
- intptr_type = CoreLookupType (ctx, "System", "IntPtr", Kind.Struct, true);
- system_intptr_expr.Type = intptr_type;
- uintptr_type = CoreLookupType (ctx, "System", "UIntPtr", Kind.Struct, true);
-
- multicast_delegate_type = CoreLookupType (ctx, "System", "MulticastDelegate", Kind.Class, true);
- delegate_type = CoreLookupType (ctx, "System", "Delegate", Kind.Class, true);
-
- enum_type = CoreLookupType (ctx, "System", "Enum", Kind.Class, true);
- array_type = CoreLookupType (ctx, "System", "Array", Kind.Class, true);
- void_type = CoreLookupType (ctx, "System", "Void", Kind.Struct, true);
- system_void_expr.Type = void_type;
- type_type = CoreLookupType (ctx, "System", "Type", Kind.Class, true);
- exception_type = CoreLookupType (ctx, "System", "Exception", Kind.Class, true);
-
- runtime_field_handle_type = CoreLookupType (ctx, "System", "RuntimeFieldHandle", Kind.Struct, true);
- runtime_handle_type = CoreLookupType (ctx, "System", "RuntimeTypeHandle", Kind.Struct, true);
-
- PredefinedAttributes.Get.ParamArray.Resolve (false);
- PredefinedAttributes.Get.Out.Resolve (false);
-
- return ctx.Report.Errors == 0;
- }
-
- //
- // Initializes optional core types
- //
- public static void InitOptionalCoreTypes (CompilerContext ctx)
- {
- //
- // 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 ();
-
- 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
+ // We cannot rely on build-in type conversions as they are
+ // more limited than what C# supports.
+ // See char -> float/decimal/double conversion
//
- 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));
+ error = false;
+ try {
+ if (targetType == TypeManager.bool_type)
+ return convert_value.ToBoolean (nf_provider);
+ if (targetType == TypeManager.byte_type)
+ return convert_value.ToByte (nf_provider);
+ if (targetType == TypeManager.char_type)
+ return convert_value.ToChar (nf_provider);
+ if (targetType == TypeManager.short_type)
+ return convert_value.ToInt16 (nf_provider);
+ if (targetType == TypeManager.int32_type)
+ return convert_value.ToInt32 (nf_provider);
+ if (targetType == TypeManager.int64_type)
+ return convert_value.ToInt64 (nf_provider);
+ if (targetType == TypeManager.sbyte_type)
+ return convert_value.ToSByte (nf_provider);
+
+ if (targetType == TypeManager.decimal_type) {
+ if (convert_value.GetType () == typeof (char))
+ return (decimal) convert_value.ToInt32 (nf_provider);
+ return convert_value.ToDecimal (nf_provider);
}
- }
- }
- 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];
+ if (targetType == TypeManager.double_type) {
+ if (convert_value.GetType () == typeof (char))
+ return (double) convert_value.ToInt32 (nf_provider);
+ return convert_value.ToDouble (nf_provider);
+ }
- //
- // `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;
- }
+ if (targetType == TypeManager.float_type) {
+ if (convert_value.GetType () == typeof (char))
+ return (float)convert_value.ToInt32 (nf_provider);
+ return convert_value.ToSingle (nf_provider);
+ }
- //
- // 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;
- }
+ if (targetType == TypeManager.string_type)
+ return convert_value.ToString (nf_provider);
+ if (targetType == TypeManager.ushort_type)
+ return convert_value.ToUInt16 (nf_provider);
+ if (targetType == TypeManager.uint32_type)
+ return convert_value.ToUInt32 (nf_provider);
+ if (targetType == TypeManager.uint64_type)
+ return convert_value.ToUInt64 (nf_provider);
+ if (targetType == TypeManager.object_type)
+ return value;
- //
- // 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);
- }
+ error = true;
+ } catch {
+ error = true;
}
-
- return new MemberList (t.FindMembers (mt, bf, filter, criteria));
+ return null;
}
-
/// <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.
+ /// Utility function that can be used to probe whether a type
+ /// is managed or not.
/// </summary>
- private static MemberInfo [] MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
- string name, out bool used_cache)
+ public static bool VerifyUnmanaged (CompilerContext ctx, TypeSpec t, Location loc)
{
- 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);
- }
+ while (t.IsPointer)
+ t = GetElementType (t);
- 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;
- }
+ if (IsUnmanagedType (t))
+ return true;
- //
- // 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);
+ 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));
- used_cache = true;
- return cache.FindMembers (mt, bf, name, FilterWithClosure_delegate, null);
+ return false;
}
-
- public static bool IsBuiltinType (Type t)
+#region Generics
+ // This method always return false for non-generic compiler,
+ // while Type.IsGenericParameter is returned if it is supported.
+ public static bool IsGenericParameter (TypeSpec type)
{
- 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;
+ return type.IsGenericParameter;
}
- //
- // 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)
+ public static bool IsGenericType (TypeSpec type)
{
- return (t == int32_type || t == uint32_type ||
- t == int64_type || t == uint64_type || t == float_type || t == double_type ||
- t == char_type || t == short_type || t == bool_type ||
- t == sbyte_type || t == byte_type || t == ushort_type);
+ return type.IsGeneric;
}
- public static bool IsDelegateType (Type t)
+ public static TypeSpec[] GetTypeArguments (TypeSpec 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);
+ // TODO: return empty array !!
+ return t.TypeArguments;
}
- //
- // Is a type of dynamic type
- //
- public static bool IsDynamicType (Type t)
- {
- if (t == InternalType.Dynamic)
- return true;
-
- if (t != object_type)
- return false;
-
- if (t.Module == RootContext.ToplevelTypes.Builder)
- 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;
- }
-
- public static bool IsEnumType (Type t)
+ /// <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 (TypeSpec type, TypeSpec parent)
{
- t = DropGenericTypeArguments (t);
- return t.BaseType == TypeManager.enum_type;
+ return type == parent || type.MemberDefinition == parent.MemberDefinition;
}
- public static bool IsBuiltinOrEnum (Type t)
+ public static bool IsNullableType (TypeSpec t)
{
- if (IsBuiltinType (t))
- return true;
-
- if (IsEnumType (t))
- return true;
-
- return false;
+ return generic_nullable_type == t.GetDefinition ();
}
+#endregion
+}
- 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)) {
- RootContext.ToplevelTypes.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
- return IsDynamicType (type) ? object_type : type;
- }
-
- /// <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;
-
- while (t.IsPointer)
- t = GetElementType (t);
-
- RootContext.ToplevelTypes.Compiler.Report.SymbolRelatedToPreviousError (t);
- RootContext.ToplevelTypes.Compiler.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;
- }
-
- 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){
- RootContext.ToplevelTypes.Compiler.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 (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 ();
- }
-
- public static MethodBase DropGenericMethodArguments (MethodBase m)
- {
- 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;
- }
-
- return m;
- }
-
- public static Type[] GetGenericArguments (MethodBase mi)
- {
- return mi.GetGenericArguments () ?? Type.EmptyTypes;
- }
-
- public static Type[] GetTypeArguments (Type t)
- {
- 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 ();
- }
-
- public static GenericConstraints GetTypeParameterConstraints (Type t)
- {
- if (!t.IsGenericParameter)
- throw new InvalidOperationException ();
-
- TypeParameter tparam = LookupTypeParameter (t);
- if (tparam != null)
- return tparam.GenericConstraints;
-
- return ReflectionConstraints.GetConstraints (t);
- }
-
- public static bool HasGenericArguments (Type t)
- {
- return GetNumberOfTypeArguments (t) > 0;
- }
-
- public static int GetNumberOfTypeArguments (Type t)
- {
- 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;
- }
-
- /// <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 (mb.DeclaringType is TypeBuilder) {
- IMethodData method = (IMethodData) builder_to_method [mb];
- if (method == null)
- return false;
-
- return method.GenericMethod != null;
- }
-
- return mb.IsGenericMethodDefinition;
- }
-
- /// <summary>
- /// Whether `mb' is a generic method.
- /// </summary>
- public static bool IsGenericMethod (MethodBase mb)
- {
- return mb.IsGenericMethod;
- }
-
- public static bool IsNullableType (Type t)
- {
- return generic_nullable_type == DropGenericTypeArguments (t);
- }
-#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 (invocation_assembly, 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 (invocation_assembly, 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;
- static MemberFilter FilterWithClosure_delegate;
-
- //
- // 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 MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type,
- Type queried_type, MemberTypes mt,
- BindingFlags original_bf, string name, IList almost_match)
- {
- Timer.StartTimer (TimerType.MemberLookup);
-
- MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type,
- queried_type, mt, original_bf, name, almost_match);
-
- Timer.StopTimer (TimerType.MemberLookup);
-
- return retval;
- }
-
- static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type,
- Type queried_type, MemberTypes mt,
- BindingFlags original_bf, string name, IList almost_match)
- {
- BindingFlags bf = original_bf;
-
- ArrayList method_list = null;
- Type current_type = queried_type;
- bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
- bool skip_iface_check = true, used_cache = false;
- bool always_ok_flag = invocation_type != null && IsNestedChildOf (invocation_type, queried_type);
-
- closure.invocation_type = invocation_type;
- closure.invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
- closure.qualifier_type = qualifier_type;
- closure.almost_match = almost_match;
-
- // This is from the first time we find a method
- // in most cases, we do not actually find a method in the base class
- // so we can just ignore it, and save the arraylist allocation
- MemberInfo [] first_members_list = null;
- bool use_first_members_list = false;
-
- do {
- MemberInfo [] list;
-
- //
- // `NonPublic' is lame, because it includes both protected and
- // private methods, so we need to control this behavior by
- // explicitly tracking if a private method is ok or not.
- //
- // The possible cases are:
- // public, private and protected (internal does not come into the
- // equation)
- //
- if ((invocation_type != null) &&
- ((invocation_type == current_type) ||
- IsNestedChildOf (invocation_type, current_type)) ||
- always_ok_flag)
- bf = original_bf | BindingFlags.NonPublic;
- else
- bf = original_bf;
-
- closure.private_ok = (original_bf & BindingFlags.NonPublic) != 0;
-
- Timer.StopTimer (TimerType.MemberLookup);
-
- list = MemberLookup_FindMembers (current_type, mt, bf, name, out used_cache);
-
- Timer.StartTimer (TimerType.MemberLookup);
-
- //
- // When queried for an interface type, the cache will automatically check all
- // inherited members, so we don't need to do this here. However, this only
- // works if we already used the cache in the first iteration of this loop.
- //
- // If we used the cache in any further iteration, we can still terminate the
- // loop since the cache always looks in all base classes.
- //
-
- if (used_cache)
- searching = false;
- else
- skip_iface_check = false;
-
- if (current_type == TypeManager.object_type)
- searching = false;
- else {
- current_type = current_type.BaseType;
-
- //
- // This happens with interfaces, they have a null
- // basetype. Look members up in the Object class.
- //
- if (current_type == null) {
- current_type = TypeManager.object_type;
- searching = true;
- }
- }
-
- if (list.Length == 0)
- continue;
-
- //
- // Events and types are returned by both `static' and `instance'
- // searches, which means that our above FindMembers will
- // return two copies of the same.
- //
- if (list.Length == 1 && !(list [0] is MethodBase)){
- return list;
- }
-
- //
- // Multiple properties: we query those just to find out the indexer
- // name
- //
- if (list [0] is PropertyInfo)
- return list;
-
- //
- // We found an event: the cache lookup returns both the event and
- // its private field.
- //
- if (list [0] is EventInfo) {
- if ((list.Length == 2) && (list [1] is FieldInfo))
- return new MemberInfo [] { list [0] };
-
- return list;
- }
-
- //
- // We found methods, turn the search into "method scan"
- // mode.
- //
-
- if (first_members_list != null) {
- if (use_first_members_list) {
- method_list = CopyNewMethods (method_list, first_members_list);
- use_first_members_list = false;
- }
-
- method_list = CopyNewMethods (method_list, list);
- } else {
- first_members_list = list;
- use_first_members_list = true;
- mt &= (MemberTypes.Method | MemberTypes.Constructor);
- }
- } while (searching);
-
- if (use_first_members_list)
- return first_members_list;
-
- if (method_list != null && method_list.Count > 0) {
- return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
- }
- //
- // This happens if we already used the cache in the first iteration, in this case
- // the cache already looked in all interfaces.
- //
- if (skip_iface_check)
- return null;
-
- //
- // Interfaces do not list members they inherit, so we have to
- // scan those.
- //
- if (!queried_type.IsInterface)
- return null;
-
- if (queried_type.IsArray)
- queried_type = TypeManager.array_type;
-
- Type [] ifaces = GetInterfaces (queried_type);
- if (ifaces == null)
- return null;
-
- foreach (Type itype in ifaces){
- MemberInfo [] x;
-
- x = MemberLookup (null, null, itype, mt, bf, name, null);
- if (x != null)
- return x;
- }
-
- return null;
- }
-
- public const BindingFlags AllMembers = BindingFlags.Public | BindingFlags.NonPublic |
- BindingFlags.Static | BindingFlags.Instance |
- BindingFlags.DeclaredOnly;
-
- // Currently is designed to work with external types only
- public static PropertyInfo GetPropertyFromAccessor (MethodBase mb)
- {
- if (!mb.IsSpecialName)
- return null;
-
- string name = mb.Name;
- if (name.Length < 5)
- return null;
-
- if (name [3] != '_')
- return null;
-
- if (name.StartsWith ("get") || name.StartsWith ("set")) {
- MemberInfo[] pi = mb.DeclaringType.FindMembers (MemberTypes.Property, AllMembers,
- Type.FilterName, name.Substring (4));
-
- if (pi == null)
- return null;
-
- // This can happen when property is indexer (it can have same name but different parameters)
- foreach (PropertyInfo p in pi) {
- foreach (MethodInfo p_mi in p.GetAccessors (true)) {
- if (p_mi == mb || TypeManager.GetParameterData (p_mi).Equals (TypeManager.GetParameterData (mb)))
- return p;
- }
- }
- }
-
- return null;
- }
-
- // Currently is designed to work with external types only
- public static MemberInfo GetEventFromAccessor (MethodBase mb)
- {
- if (!mb.IsSpecialName)
- return null;
-
- string name = mb.Name;
- if (name.Length < 5)
- return null;
-
- if (name.StartsWith ("add_"))
- return mb.DeclaringType.GetEvent (name.Substring (4), AllMembers);
-
- if (name.StartsWith ("remove_"))
- return mb.DeclaringType.GetEvent (name.Substring (7), AllMembers);
-
- return null;
- }
-
- // Tests whether external method is really special
- public static bool IsSpecialMethod (MethodBase mb)
- {
- if (!mb.IsSpecialName)
- return false;
-
- IMethodData md = TypeManager.GetMethod (mb);
- if (md != null)
- return (md is AbstractPropertyEventMethod || md is Operator);
-
- PropertyInfo pi = GetPropertyFromAccessor (mb);
- if (pi != null)
- return IsValidProperty (pi);
-
- if (GetEventFromAccessor (mb) != null)
- return true;
-
- string name = mb.Name;
- if (name.StartsWith ("op_"))
- return Operator.GetName (name) != null;
-
- return false;
- }
-
- // Tests whether imported property is valid C# property.
- // TODO: It seems to me that we should do a lot of sanity tests before
- // we accept property as C# property
- static bool IsValidProperty (PropertyInfo pi)
- {
- MethodInfo get_method = pi.GetGetMethod (true);
- MethodInfo set_method = pi.GetSetMethod (true);
- int g_count = 0;
- int s_count = 0;
- if (get_method != null && set_method != null) {
- g_count = get_method.GetParameters ().Length;
- s_count = set_method.GetParameters ().Length;
- if (g_count + 1 != s_count)
- return false;
- } else if (get_method != null) {
- g_count = get_method.GetParameters ().Length;
- } else if (set_method != null) {
- s_count = set_method.GetParameters ().Length;
- }
-
- //
- // DefaultMemberName and indexer name has to match to identify valid C# indexer
- //
- PredefinedAttribute pa = PredefinedAttributes.Get.DefaultMember;
- if ((s_count > 1 || g_count > 0) && pa.IsDefined) {
- object[] o = pi.DeclaringType.GetCustomAttributes (pa.Type, false);
- if (o.Length == 0)
- return false;
-
- DefaultMemberAttribute dma = (DefaultMemberAttribute) o [0];
- if (dma.MemberName != pi.Name)
- return false;
- if (get_method != null && "get_" + dma.MemberName != get_method.Name)
- return false;
- if (set_method != null && "set_" + dma.MemberName != set_method.Name)
- return false;
- }
-
- return true;
- }
-
-#endregion
-
-}
-
- class InternalType
- {
- public static readonly Type AnonymousMethod = typeof (AnonymousMethodBody);
- public static readonly Type Arglist = typeof (ArglistAccess);
- public static readonly Type Dynamic = new DynamicType ();
- public static readonly Type MethodGroup = typeof (MethodGroupExpr);
- }
-
-/// <summary>
-/// There is exactly one instance of this class per type.
-/// </summary>
-public sealed class TypeHandle : IMemberContainer {
- public readonly IMemberContainer BaseType;
-
- readonly int id = ++next_id;
- static int next_id = 0;
-
- static TypeHandle ()
- {
- Reset ();
- }
-
- /// <summary>
- /// Lookup a TypeHandle instance for the given type. If the type doesn't have
- /// a TypeHandle yet, a new instance of it is created. This static method
- /// ensures that we'll only have one TypeHandle instance per type.
- /// </summary>
- private static TypeHandle GetTypeHandle (Type t)
- {
- TypeHandle handle = (TypeHandle) type_hash [t];
- if (handle != null)
- return handle;
-
- handle = new TypeHandle (t);
- type_hash.Add (t, handle);
- return handle;
- }
-
- public static MemberCache GetMemberCache (Type t)
- {
- return GetTypeHandle (t).MemberCache;
- }
-
- public static void CleanUp ()
- {
- type_hash = null;
- }
-
- public static void Reset ()
- {
- type_hash = new PtrHashtable ();
- }
-
- /// <summary>
- /// Returns the TypeHandle for TypeManager.object_type.
- /// </summary>
- public static IMemberContainer ObjectType {
- get {
- if (object_type != null)
- return object_type;
-
- object_type = GetTypeHandle (TypeManager.object_type);
-
- return object_type;
- }
- }
-
- /// <summary>
- /// Returns the TypeHandle for TypeManager.array_type.
- /// </summary>
- public static TypeHandle ArrayType {
- get {
- if (array_type != null)
- return array_type;
-
- array_type = GetTypeHandle (TypeManager.array_type);
-
- return array_type;
- }
- }
-
- private static PtrHashtable type_hash;
-
- private static TypeHandle object_type = null;
- private static TypeHandle array_type = null;
-
- private Type type;
- private string full_name;
- private bool is_interface;
- private MemberCache member_cache;
- private MemberCache base_cache;
-
- private TypeHandle (Type type)
- {
- this.type = type;
- full_name = type.FullName != null ? type.FullName : type.Name;
- if (type.BaseType != null) {
- base_cache = TypeManager.LookupMemberCache (type.BaseType);
- BaseType = base_cache.Container;
- } else if (type.IsInterface)
- base_cache = TypeManager.LookupBaseInterfacesCache (type);
- this.is_interface = type.IsInterface || TypeManager.IsGenericParameter (type);
- this.member_cache = new MemberCache (this);
- }
-
- // IMemberContainer methods
-
- public string Name {
- get {
- return full_name;
- }
- }
-
- public Type Type {
- get {
- return type;
- }
- }
-
- public MemberCache BaseCache {
- get {
- return base_cache;
- }
- }
-
- public bool IsInterface {
- get {
- return is_interface;
- }
- }
-
- public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
- {
- MemberInfo [] members;
-
- if (type is GenericTypeParameterBuilder)
- return MemberList.Empty;
-
-#if MS_COMPATIBLE
- type = TypeManager.DropGenericTypeArguments (type);
-#endif
- if (mt == MemberTypes.Event)
- members = type.GetEvents (bf | BindingFlags.DeclaredOnly);
- else
- members = type.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
- null, null);
-
- if (members.Length == 0)
- return MemberList.Empty;
-
- Array.Reverse (members);
- return new MemberList (members);
- }
-
- // IMemberFinder methods
-
- public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
- MemberFilter filter, object criteria)
- {
- return new MemberList (member_cache.FindMembers (mt, bf, name, filter, criteria));
- }
-
- public MemberCache MemberCache {
- get {
- return member_cache;
- }
- }
-
- public override string ToString ()
- {
- if (BaseType != null)
- return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")";
- else
- return "TypeHandle (" + id + "," + Name + ")";
- }
-}
}