static public Type unverifiable_code_type;
static public Type methodimpl_attr_type;
static public Type marshal_as_attr_type;
+ static public Type new_constraint_attr_type;
static public Type param_array_type;
static public Type guid_attr_type;
static public Type void_ptr_type;
static public Type indexer_name_type;
static public Type exception_type;
+ static public Type activator_type;
static public Type invalid_operation_exception_type;
static public object obsolete_attribute_type;
static public object conditional_attribute_type;
static public Type in_attribute_type;
+ static public Type cls_compliant_attribute_type;
+ static public Type typed_reference_type;
+ static public Type arg_iterator_type;
//
// An empty array of types
static public MethodInfo string_concat_string_string;
static public MethodInfo string_concat_string_string_string;
static public MethodInfo string_concat_string_string_string_string;
+ static public MethodInfo string_concat_string_dot_dot_dot;
static public MethodInfo string_concat_object_object;
+ static public MethodInfo string_concat_object_object_object;
+ static public MethodInfo string_concat_object_dot_dot_dot;
static public MethodInfo string_isinterneted_string;
static public MethodInfo system_type_get_type_from_handle;
static public MethodInfo object_getcurrent_void;
static public MethodInfo int_array_get_lower_bound_int;
static public MethodInfo int_array_get_upper_bound_int;
static public MethodInfo void_array_copyto_array_int;
+ static public MethodInfo activator_create_instance;
//
// The attribute constructors.
static Assembly [] assemblies;
// <remarks>
- // Keeps a list of module builders. We used this to do lookups
- // on the modulebuilder using GetType -- needed for arrays
+ // Keeps a list of modules. We used this to do lookups
+ // on the module using GetType -- needed for arrays
// </remarks>
- static ModuleBuilder [] modules;
+ static Module [] modules;
// <remarks>
// This is the type_cache from the assemblies to avoid
// </remarks>
static PtrHashtable builder_to_ifaces;
+ // <remarks>
+ // Tracks the generic parameters.
+ // </remarks>
+ static PtrHashtable builder_to_type_param;
+
// <remarks>
// Maps MethodBase.RuntimeTypeHandle to a Type array that contains
// the arguments to the method
static Hashtable builder_to_method;
+ // <remarks>
+ // Contains all public types from referenced assemblies.
+ // This member is used only if CLS Compliance verification is required.
+ // </remarks>
+ public static Hashtable all_imported_types;
+
struct Signature {
public string name;
public Type [] args;
}
+ public static void CleanUp ()
+ {
+ // Lets get everything clean so that we can collect before generating code
+ assemblies = null;
+ modules = null;
+ types = null;
+ typecontainers = null;
+ user_types = null;
+ builder_to_declspace = null;
+ builder_to_ifaces = null;
+ method_arguments = null;
+ indexer_arguments = null;
+ method_internal_params = null;
+ builder_to_attr = null;
+ builder_to_method = null;
+ builder_to_type_param = null;
+
+ fields = null;
+ references = null;
+ negative_hits = null;
+ attr_to_allowmult = null;
+ builder_to_constant = null;
+ fieldbuilders_to_fields = null;
+ events = null;
+ priv_fields_events = null;
+ properties = null;
+
+ TypeHandle.CleanUp ();
+ }
+
/// <summary>
/// A filter for Findmembers that uses the Signature object to
/// extract objects
method_internal_params = new PtrHashtable ();
indexer_arguments = new PtrHashtable ();
builder_to_ifaces = new PtrHashtable ();
+ builder_to_type_param = new PtrHashtable ();
NoTypes = new Type [0];
NoTypeExprs = new TypeExpr [0];
return;
}
- Location l;
tc = builder_to_declspace [t] as TypeContainer;
if (tc != null){
Report.Warning (
builder_to_attr.Add (t, tc);
}
+ public static void AddTypeParameter (Type t, TypeParameter tparam, TypeExpr[] ifaces)
+ {
+ if (!builder_to_type_param.Contains (t)) {
+ builder_to_type_param.Add (t, tparam);
+
+ if (ifaces != null)
+ builder_to_ifaces [t] = ifaces;
+ }
+ }
+
/// <summary>
/// Returns the DeclSpace whose Type is `t' or null if there is no
/// DeclSpace for `t' (ie, the Type comes from a library)
return container;
}
+ if (t is GenericTypeParameterBuilder) {
+ IMemberContainer container = builder_to_type_param [t] as IMemberContainer;
+
+ if (container != null)
+ return container;
+ }
+
return TypeHandle.GetTypeHandle (t);
}
{
return (TypeContainer) builder_to_attr [t];
}
+
+ public static TypeParameter LookupTypeParameter (Type t)
+ {
+ return (TypeParameter) builder_to_type_param [t];
+ }
+
+ public static bool HasConstructorConstraint (Type t)
+ {
+ if (!t.IsGenericParameter)
+ throw new InvalidOperationException ();
+
+ TypeParameter tparam = LookupTypeParameter (t);
+ if (tparam != null)
+ return tparam.HasConstructorConstraint;
+ else {
+ object[] attrs = t.GetCustomAttributes (
+ TypeManager.new_constraint_attr_type, false);
+
+ return attrs.Length > 0;
+ }
+ }
/// <summary>
/// Registers an assembly to load types from.
/// </summary>
public static void AddAssembly (Assembly a)
{
+ foreach (Assembly assembly in assemblies) {
+ if (a == assembly)
+ return;
+ }
+
int top = assemblies.Length;
Assembly [] n = new Assembly [top + 1];
/// <summary>
/// Registers a module builder to lookup types from
/// </summary>
- public static void AddModule (ModuleBuilder mb)
+ public static void AddModule (Module mb)
{
int top = modules != null ? modules.Length : 0;
- ModuleBuilder [] n = new ModuleBuilder [top + 1];
+ Module [] n = new Module [top + 1];
if (modules != null)
modules.CopyTo (n, 0);
modules = n;
}
+ public static Module[] Modules {
+ get {
+ return modules;
+ }
+ }
+
static Hashtable references = new Hashtable ();
//
//
if (ret == null){
if (pointers [t] == null)
- pointers [t] = CodeGen.ModuleBuilder.GetType (tname);
+ pointers [t] = CodeGen.Module.Builder.GetType (tname);
ret = (Type) pointers [t];
}
} while (t != null);
}
- foreach (ModuleBuilder mb in modules) {
+ foreach (Module mb in modules) {
t = mb.GetType (name);
if (t != null)
return t;
return t;
}
+ static readonly char [] dot_array = { '.' };
+
/// <summary>
/// Returns the Type associated with @name, takes care of the fact that
/// reflection expects nested types to be separated from the main type
if (negative_hits.Contains (name))
return null;
- string [] elements = name.Split ('.');
+ // Sadly, split takes a param array, so this ends up allocating *EVERY TIME*
+ string [] elements = name.Split (dot_array);
int count = elements.Length;
for (int n = 1; n <= count; n++){
if (t == null){
t = LookupTypeReflection (top_level_type);
if (t == null){
- negative_hits [top_level_type] = true;
+ negative_hits [top_level_type] = null;
continue;
}
}
//Console.WriteLine ("Looking up: " + newt + " " + name);
t = LookupTypeReflection (newt);
if (t == null)
- negative_hits [name] = true;
+ negative_hits [name] = null;
else
types [name] = t;
return t;
}
- negative_hits [name] = true;
+ negative_hits [name] = null;
return null;
}
/// </summary>
public static void ComputeNamespaces ()
{
- MethodInfo assembly_get_namespaces = typeof (Assembly).GetMethod ("GetNamespaces");
+ MethodInfo assembly_get_namespaces = typeof (Assembly).GetMethod ("GetNamespaces", BindingFlags.Instance|BindingFlags.NonPublic);
//
// First add the assembly namespaces
//
if (assembly_get_namespaces != null){
int count = assemblies.Length;
- int total;
for (int i = 0; i < count; i++){
Assembly a = assemblies [i];
}
}
+ /// <summary>
+ /// Fills static table with exported types from all referenced assemblies.
+ /// This information is required for CLS Compliance tests.
+ /// </summary>
+ public static void LoadAllImportedTypes ()
+ {
+ if (!CodeGen.Assembly.IsClsCompliant)
+ return;
+
+ all_imported_types = new Hashtable ();
+ foreach (Assembly a in assemblies) {
+ foreach (Type t in a.GetExportedTypes ()) {
+ all_imported_types [t.FullName] = t;
+ }
+ }
+ }
+
public static bool NamespaceClash (string name, Location loc)
{
if (Namespace.LookupNamespace (name, false) == null)
/// </summary>
static public string CSharpName (Type t)
{
+ if (t.FullName == null)
+ return t.Name;
+
return Regex.Replace (t.FullName,
@"^System\." +
@"(Int32|UInt32|Int16|UInt16|Int64|UInt64|" +
+ match.Groups [2].Captures [0].Value;
}
+ /// <summary>
+ /// Returns the signature of the method with full namespace classification
+ /// </summary>
+ static public string GetFullNameSignature (MemberInfo mi)
+ {
+ string n = mi.Name;
+ if (n == ".ctor")
+ n = mi.DeclaringType.Name;
+
+ return mi.DeclaringType.FullName.Replace ('+', '.') + '.' + n;
+ }
+
+ static public string GetFullName (Type t)
+ {
+ if (t.FullName == null)
+ return t.Name;
+
+ string name = t.FullName.Replace ('+', '.');
+
+ DeclSpace tc = LookupDeclSpace (t);
+ if ((tc != null) && tc.IsGeneric) {
+ TypeParameter[] tparam = tc.TypeParameters;
+
+ StringBuilder sb = new StringBuilder (name);
+ sb.Append ("<");
+ for (int i = 0; i < tparam.Length; i++) {
+ if (i > 0)
+ sb.Append (",");
+ sb.Append (tparam [i].Name);
+ }
+ sb.Append (">");
+ return sb.ToString ();
+ } else if (t.HasGenericArguments && !t.IsGenericInstance) {
+ Type[] tparam = t.GetGenericArguments ();
+
+ StringBuilder sb = new StringBuilder (name);
+ sb.Append ("<");
+ for (int i = 0; i < tparam.Length; i++) {
+ if (i > 0)
+ sb.Append (",");
+ sb.Append (tparam [i].Name);
+ }
+ sb.Append (">");
+ return sb.ToString ();
+ }
+
+ return name;
+ }
+
+ /// <summary>
+ /// Returns the signature of the property and indexer
+ /// </summary>
+ static public string CSharpSignature (PropertyBuilder pb, bool is_indexer)
+ {
+ if (!is_indexer) {
+ return GetFullNameSignature (pb);
+ }
+
+ MethodBase mb = pb.GetSetMethod (true) != null ? pb.GetSetMethod (true) : pb.GetGetMethod (true);
+ string signature = GetFullNameSignature (mb);
+ string arg = TypeManager.LookupParametersByBuilder (mb).ParameterDesc (0);
+ return String.Format ("{0}.this[{1}]", signature.Substring (0, signature.LastIndexOf ('.')), arg);
+ }
+
/// <summary>
/// Returns the signature of the method
/// </summary>
//
ParameterData iparams = LookupParametersByBuilder (mb);
- if (iparams == null){
- ParameterInfo [] pi = mb.GetParameters ();
- iparams = new ReflectionParameters (pi);
- }
+ if (iparams == null)
+ iparams = new ReflectionParameters (mb);
for (int i = 0; i < iparams.Count; i++) {
if (i > 0) {
}
sig += ")";
- return mb.DeclaringType.Name + "." + mb.Name + sig;
+ return GetFullNameSignature (mb) + sig;
}
/// <summary>
/// Returns the MethodInfo for a method named `name' defined
/// in type `t' which takes arguments of types `args'
/// </summary>
- static MethodInfo GetMethod (Type t, string name, Type [] args, bool report_errors)
+ static MethodInfo GetMethod (Type t, string name, Type [] args, bool is_private, bool report_errors)
{
MemberList list;
Signature sig;
+ BindingFlags flags = instance_and_static | BindingFlags.Public;
sig.name = name;
sig.args = args;
- list = FindMembers (t, MemberTypes.Method, instance_and_static | BindingFlags.Public,
- signature_filter, sig);
+ if (is_private)
+ flags |= BindingFlags.NonPublic;
+
+ list = FindMembers (t, MemberTypes.Method, flags, signature_filter, sig);
if (list.Count == 0) {
if (report_errors)
Report.Error (-19, "Can not find the core function `" + name + "'");
return mi;
}
+ static MethodInfo GetMethod (Type t, string name, Type [] args, bool report_errors)
+ {
+ return GetMethod (t, name, args, false, report_errors);
+ }
+
static MethodInfo GetMethod (Type t, string name, Type [] args)
{
return GetMethod (t, name, args, true);
dllimport_type = CoreLookupType ("System.Runtime.InteropServices.DllImportAttribute");
methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices.MethodImplAttribute");
marshal_as_attr_type = CoreLookupType ("System.Runtime.InteropServices.MarshalAsAttribute");
+ new_constraint_attr_type = CoreLookupType ("System.Runtime.CompilerServices.NewConstraintAttribute");
param_array_type = CoreLookupType ("System.ParamArrayAttribute");
in_attribute_type = CoreLookupType ("System.Runtime.InteropServices.InAttribute");
+ typed_reference_type = CoreLookupType ("System.TypedReference");
+ arg_iterator_type = CoreLookupType ("System.ArgIterator");
//
// Sigh. Remove this before the release. Wonder what versions of Mono
indexer_name_type = CoreLookupType ("System.Runtime.CompilerServices.IndexerNameAttribute");
exception_type = CoreLookupType ("System.Exception");
+ activator_type = CoreLookupType ("System.Activator");
invalid_operation_exception_type = CoreLookupType ("System.InvalidOperationException");
//
//
obsolete_attribute_type = CoreLookupType ("System.ObsoleteAttribute");
conditional_attribute_type = CoreLookupType ("System.Diagnostics.ConditionalAttribute");
+ cls_compliant_attribute_type = CoreLookupType ("System.CLSCompliantAttribute");
//
// When compiling corlib, store the "real" types here.
MethodInfo set_corlib_type_builders = GetMethod (
system_assemblybuilder_type, "SetCorlibTypeBuilders",
- system_4_type_arg, false);
+ system_4_type_arg, true, false);
if (set_corlib_type_builders != null) {
object[] args = new object [4];
args [2] = enum_type;
args [3] = void_type;
- set_corlib_type_builders.Invoke (CodeGen.AssemblyBuilder, args);
+ set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
} else {
// Compatibility for an older version of the class libs.
set_corlib_type_builders = GetMethod (
system_assemblybuilder_type, "SetCorlibTypeBuilders",
- system_3_type_arg, true);
+ system_3_type_arg, true, true);
if (set_corlib_type_builders == null) {
Report.Error (-26, "Corlib compilation is not supported in Microsoft.NET due to bugs in it");
args [1] = value_type;
args [2] = enum_type;
- set_corlib_type_builders.Invoke (CodeGen.AssemblyBuilder, args);
+ set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
}
}
Type [] string_string_string_string = { string_type, string_type, string_type, string_type };
string_concat_string_string_string_string = GetMethod (
string_type, "Concat", string_string_string_string);
+ Type[] params_string = { TypeManager.LookupType ("System.String[]") };
+ string_concat_string_dot_dot_dot = GetMethod (
+ string_type, "Concat", params_string);
Type [] object_object = { object_type, object_type };
string_concat_object_object = GetMethod (
string_type, "Concat", object_object);
+ Type [] object_object_object = { object_type, object_type, object_type };
+ string_concat_object_object_object = GetMethod (
+ string_type, "Concat", object_object_object);
+ Type[] params_object = { TypeManager.LookupType ("System.Object[]") };
+ string_concat_object_dot_dot_dot = GetMethod (
+ string_type, "Concat", params_object);
Type [] string_ = { string_type };
string_isinterneted_string = GetMethod (
// Object
object_ctor = GetConstructor (object_type, void_arg);
+ // Activator
+ Type [] type_arg = { type_type };
+ activator_create_instance = GetMethod (
+ activator_type, "CreateInstance", type_arg);
}
const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
- static Hashtable type_hash = new Hashtable ();
-
/// <remarks>
/// This is the "old", non-cache based FindMembers() function. We cannot use
/// the cache here because there is no member name argument.
/// our return value will already contain all inherited members and the caller don't need
/// to check base classes and interfaces anymore.
/// </summary>
- private static MemberList MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
+ private static MemberInfo [] MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
string name, out bool used_cache)
{
- bool not_loaded_corlib = (t.Assembly == CodeGen.AssemblyBuilder);
-
//
// We have to take care of arrays specially, because GetType on
// a TypeBuilder array will return a Type, not a TypeBuilder,
}
// 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);
FilterWithClosure_delegate, name);
Timer.StopTimer (TimerType.FindMembers);
used_cache = false;
- return list;
+ return (MemberInfo []) list;
+ }
+
+ if (t is GenericTypeParameterBuilder) {
+ TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
+
+ MemberList list;
+ Timer.StartTimer (TimerType.FindMembers);
+ list = tparam.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
+ FilterWithClosure_delegate, name);
+ Timer.StopTimer (TimerType.FindMembers);
+ used_cache = false;
+ return (MemberInfo []) list;
}
//
public static bool IsDelegateType (Type t)
{
+ if (t.IsGenericInstance)
+ t = t.GetGenericTypeDefinition ();
+
if (t.IsSubclassOf (TypeManager.delegate_type))
return true;
else
return ds.IsGeneric;
}
+
+ public static bool HasGenericArguments (Type t)
+ {
+ return GetNumberOfTypeArguments (t) > 0;
+ }
+
+ public static int GetNumberOfTypeArguments (Type t)
+ {
+ DeclSpace tc = LookupDeclSpace (t);
+ if (tc != null)
+ return tc.IsGeneric ? tc.CountTypeParameters : 0;
+ else
+ return t.HasGenericArguments ? t.GetGenericArguments ().Length : 0;
+ }
+
+ public static Type[] GetTypeArguments (Type t)
+ {
+ DeclSpace tc = LookupDeclSpace (t);
+ if (tc != null) {
+ if (!tc.IsGeneric)
+ throw new InvalidOperationException ();
+
+ TypeParameter[] tparam = tc.TypeParameters;
+ Type[] ret = new Type [tparam.Length];
+ for (int i = 0; i < tparam.Length; i++) {
+ ret [i] = tparam [i].Type;
+ if (ret [i] == null)
+ throw new InternalErrorException ();
+ }
+
+ return ret;
+ } else
+ return t.GetGenericArguments ();
+ }
//
// Whether a type is unmanaged. This is used by the unsafe code (25.2)
if (t is TypeBuilder){
TypeContainer tc = LookupTypeContainer (t);
+ if (tc.Fields != null){
foreach (Field f in tc.Fields){
if (f.FieldBuilder.IsStatic)
continue;
if (!IsUnmanagedType (f.FieldBuilder.FieldType))
return false;
}
+ } else
+ return true;
} else {
FieldInfo [] fields = t.GetFields ();
return false;
for (int i = 0; i < aparams.Length; i++)
- if (aparams [i] != bparams [i])
+ if (!aparams [i].Equals (bparams [i]))
return false;
return true;
return false;
}
+ public static bool IsEqual (Type a, Type b)
+ {
+ if (a.Equals (b))
+ return true;
+ else
+ return IsEqualGenericType (a, b);
+ }
+
+ public static bool MayBecomeEqualGenericTypes (Type a, Type b)
+ {
+ if (a.IsGenericParameter) {
+ //
+ // If a is an array of a's type, they may never
+ // become equal.
+ //
+ while (b.IsArray) {
+ b = b.GetElementType ();
+ if (a.Equals (b))
+ return false;
+ }
+
+ //
+ // If b is a generic parameter or an actual type,
+ // they may become equal:
+ //
+ // class X<T,U> : I<T>, I<U>
+ // class X<T> : I<T>, I<float>
+ //
+ if (b.IsGenericParameter || !b.IsGenericInstance)
+ return true;
+
+ //
+ // We're now comparing a type parameter with a
+ // generic instance. They may become equal unless
+ // the type parameter appears anywhere in the
+ // generic instance:
+ //
+ // class X<T,U> : I<T>, I<X<U>>
+ // -> error because you could instanciate it as
+ // X<X<int>,int>
+ //
+ // class X<T> : I<T>, I<X<T>> -> ok
+ //
+
+ Type[] bargs = GetTypeArguments (b);
+ for (int i = 0; i < bargs.Length; i++) {
+ if (a.Equals (bargs [i]))
+ return false;
+ }
+
+ return true;
+ }
+
+ if (b.IsGenericParameter)
+ return MayBecomeEqualGenericTypes (b, a);
+
+ //
+ // At this point, neither a nor b are a type parameter.
+ //
+ // If one of them is a generic instance, let
+ // MayBecomeEqualGenericInstances() compare them (if the
+ // other one is not a generic instance, they can never
+ // become equal).
+ //
+
+ if (a.IsGenericInstance || b.IsGenericInstance)
+ return MayBecomeEqualGenericInstances (a, b);
+
+ //
+ // If both of them are arrays.
+ //
+
+ if (a.IsArray && b.IsArray) {
+ if (a.GetArrayRank () != b.GetArrayRank ())
+ return false;
+
+ a = a.GetElementType ();
+ b = b.GetElementType ();
+
+ return MayBecomeEqualGenericTypes (a, b);
+ }
+
+ //
+ // Ok, two ordinary types.
+ //
+
+ return a.Equals (b);
+ }
+
+ //
+ // Checks whether two generic instances may become equal for some
+ // particular instantiation (26.3.1).
+ //
+ public static bool MayBecomeEqualGenericInstances (Type a, Type b)
+ {
+ if (!a.IsGenericInstance || !b.IsGenericInstance)
+ return false;
+ if (a.GetGenericTypeDefinition () != b.GetGenericTypeDefinition ())
+ return false;
+
+ Type[] aargs = GetTypeArguments (a);
+ Type[] bargs = GetTypeArguments (b);
+
+ if (aargs.Length != bargs.Length)
+ return false;
+
+ for (int i = 0; i < aargs.Length; i++) {
+ if (MayBecomeEqualGenericTypes (aargs [i], bargs [i]))
+ return true;
+ }
+
+ return false;
+ }
+
+ public static bool IsSubclassOf (Type type, Type parent)
+ {
+ if (type.IsGenericInstance && !parent.IsGenericInstance)
+ type = type.GetGenericTypeDefinition ();
+
+ return type.IsSubclassOf (parent);
+ }
+
//
// Checks whether `type' is a subclass or nested child of `parent'.
//
return ret;
}
+ static PtrHashtable iface_cache = new PtrHashtable ();
+
/// <summary>
/// This function returns the interfaces in the type `t'. Works with
/// both types and TypeBuilders.
/// </summary>
public static TypeExpr [] GetInterfaces (Type t)
{
+
+ TypeExpr [] cached = iface_cache [t] as TypeExpr [];
+ 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,
parent_ifaces.CopyTo (result, 0);
type_ifaces.CopyTo (result, parent_count);
+ iface_cache [t] = result;
return result;
+ } else if (t is GenericTypeParameterBuilder){
+ TypeExpr[] type_ifaces = (TypeExpr []) builder_to_ifaces [t];
+ if (type_ifaces == null)
+ type_ifaces = NoTypeExprs;
+
+ iface_cache [t] = type_ifaces;
+ return type_ifaces;
} else {
Type [] ifaces = t.GetInterfaces ();
+ if (ifaces.Length == 0)
+ return NoTypeExprs;
TypeExpr [] result = new TypeExpr [ifaces.Length];
for (int i = 0; i < ifaces.Length; i++)
result [i] = new TypeExpression (ifaces [i], Location.Null);
+
+ iface_cache [t] = result;
return result;
}
}
+ //
+ // gets the interfaces that are declared explicitly on t
+ //
+ public static TypeExpr [] GetExplicitInterfaces (TypeBuilder t)
+ {
+ return (TypeExpr []) 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 string IndexerPropertyName (Type t)
{
+ if (t.IsGenericInstance)
+ t = t.GetGenericTypeDefinition ();
+
if (t is TypeBuilder) {
if (t.IsInterface) {
Interface i = LookupInterface (t);
return "Item";
}
+ static MethodInfo pinned_method = null;
public static void MakePinned (LocalBuilder builder)
{
- //
- // FIXME: Flag the "LocalBuilder" type as being
- // pinned. Figure out API.
- //
+ if (pinned_method == null) {
+ pinned_method = typeof (LocalBuilder).GetMethod ("MakePinned", BindingFlags.Instance | BindingFlags.NonPublic);
+ if (pinned_method == null) {
+ Report.Warning (-24, new Location (-1), "Microsoft.NET does not support making pinned variables." +
+ "This code may cause errors on a runtime with a moving GC");
+
+ return;
+ }
+ }
+
+ pinned_method.Invoke (builder, null);
}
//
// The name is assumed to be the same.
//
- public static ArrayList CopyNewMethods (ArrayList target_list, MemberList new_members)
+ public static ArrayList CopyNewMethods (ArrayList target_list, IList new_members)
{
if (target_list == null){
target_list = new ArrayList ();
IsObsoleteError = 1 << 1,
ShouldIgnore = 1 << 2
}
+
+ static public bool IsGenericMethod (MethodBase mb)
+ {
+ if (mb.DeclaringType is TypeBuilder) {
+ MethodData method = (MethodData) builder_to_method [mb];
+ if (method == null)
+ return false;
+
+ return method.GenericMethod != null;
+ }
+
+ return mb.IsGenericMethodDefinition;
+ }
//
// Returns the TypeManager.MethodFlags for this method.
static public MethodFlags GetMethodFlags (MethodBase mb, Location loc)
{
MethodFlags flags = 0;
-
+
+ if (mb.Mono_IsInflatedMethod)
+ mb = mb.GetGenericMethodDefinition ();
+
if (mb.DeclaringType is TypeBuilder){
MethodData method = (MethodData) builder_to_method [mb];
if (method == null) {
return method.GetMethodFlags (loc);
}
-#if FIXME
- if (mb.IsInflatedGeneric) {
- MethodBase generic = mb.GetGenericMethodDefinition ();
-
- return GetMethodFlags (generic, loc);
- }
-#endif
-
object [] attrs = mb.GetCustomAttributes (true);
foreach (object ta in attrs){
if (!(ta is System.Attribute)){
#region MemberLookup implementation
- //
- // Name of the member
- //
- static string closure_name;
-
//
// Whether we allow private members in the result (since FindMembers
// uses NonPublic for both protected and private), we need to distinguish.
// Who is invoking us and which type is being queried currently.
//
static Type closure_invocation_type;
- static Type closure_queried_type;
static Type closure_qualifier_type;
//
return false;
if (((closure_qualifier_type == null) || (closure_qualifier_type == closure_invocation_type)) &&
- (m.DeclaringType == closure_invocation_type))
+ (closure_invocation_type != null) && IsEqual (m.DeclaringType, closure_invocation_type))
return true;
//
MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
if (ma == MethodAttributes.Private)
- return closure_private_ok || (closure_invocation_type == m.DeclaringType) ||
+ return closure_private_ok ||
+ IsEqual (closure_invocation_type, m.DeclaringType) ||
IsNestedChildOf (closure_invocation_type, m.DeclaringType);
//
FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
if (fa == FieldAttributes.Private)
- return closure_private_ok || (closure_invocation_type == m.DeclaringType) ||
+ return closure_private_ok ||
+ IsEqual (closure_invocation_type, m.DeclaringType) ||
IsNestedChildOf (closure_invocation_type, m.DeclaringType);
//
// that might return multiple matches.
//
public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type,
- Type queried_type, MemberTypes mt,
+ Type queried_type, MemberTypes mt,
BindingFlags original_bf, string name)
{
Timer.StartTimer (TimerType.MemberLookup);
bool skip_iface_check = true, used_cache = false;
bool always_ok_flag = false;
- closure_name = name;
closure_invocation_type = invocation_type;
closure_invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
closure_qualifier_type = qualifier_type;
//
if (invocation_type != null){
string invocation_name = invocation_type.FullName;
- if (invocation_name.IndexOf ('+') != -1){
+ if ((invocation_name != null) && (invocation_name.IndexOf ('+') != -1)){
string container = queried_type.FullName + "+";
int container_length = container.Length;
}
}
+ // This is from the first time we find a method
+ // in most cases, we do not actually find a method in the base class
+ // so we can just ignore it, and save the arraylist allocation
+ MemberInfo [] first_members_list = null;
+ bool use_first_members_list = false;
+
do {
- MemberList list;
+ MemberInfo [] list;
//
// `NonPublic' is lame, because it includes both protected and
bf = original_bf;
closure_private_ok = (original_bf & BindingFlags.NonPublic) != 0;
- closure_queried_type = current_type;
Timer.StopTimer (TimerType.MemberLookup);
- list = MemberLookup_FindMembers (current_type, mt, bf, name, out used_cache);
+ list = MemberLookup_FindMembers (
+ current_type, mt, bf, name, out used_cache);
Timer.StartTimer (TimerType.MemberLookup);
current_type = TypeManager.object_type;
}
- if (list.Count == 0)
+ if (list.Length == 0)
continue;
//
// searches, which means that our above FindMembers will
// return two copies of the same.
//
- if (list.Count == 1 && !(list [0] is MethodBase)){
- return (MemberInfo []) list;
+ if (list.Length == 1 && !(list [0] is MethodBase)){
+ return list;
}
//
// name
//
if (list [0] is PropertyInfo)
- return (MemberInfo []) list;
+ return list;
//
// We found an event: the cache lookup returns both the event and
// its private field.
//
if (list [0] is EventInfo) {
- if ((list.Count == 2) && (list [1] is FieldInfo))
+ if ((list.Length == 2) && (list [1] is FieldInfo))
return new MemberInfo [] { list [0] };
// Oooops
// mode.
//
- method_list = CopyNewMethods (method_list, list);
- mt &= (MemberTypes.Method | MemberTypes.Constructor);
+ if (first_members_list != null) {
+ if (use_first_members_list) {
+ method_list = CopyNewMethods (method_list, first_members_list);
+ use_first_members_list = false;
+ }
+
+ method_list = CopyNewMethods (method_list, list);
+ } else {
+ first_members_list = list;
+ use_first_members_list = true;
+
+ mt &= (MemberTypes.Method | MemberTypes.Constructor);
+ }
} while (searching);
+ if (use_first_members_list) {
+ foreach (MemberInfo mi in first_members_list) {
+ if (! (mi is MethodBase)) {
+ method_list = CopyNewMethods (method_list, first_members_list);
+ return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
+ }
+ }
+ return (MemberInfo []) first_members_list;
+ }
+
if (method_list != null && method_list.Count > 0) {
return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
}
type_hash.Add (t, handle);
return handle;
}
+
+ public static void CleanUp ()
+ {
+ type_hash = null;
+ }
/// <summary>
/// Returns the TypeHandle for TypeManager.object_type.
private static TypeHandle array_type = null;
private Type type;
+ private string full_name;
private bool is_interface;
private MemberCache member_cache;
private TypeHandle (Type type)
{
this.type = type;
+ full_name = type.FullName != null ? type.FullName : type.Name;
if (type.BaseType != null)
BaseType = GetTypeHandle (type.BaseType);
- this.is_interface = type.IsInterface;
+ this.is_interface = type.IsInterface || type.IsGenericParameter;
this.member_cache = new MemberCache (this);
}
public string Name {
get {
- return type.FullName;
+ return full_name;
}
}
public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
{
MemberInfo [] members;
+ if (type is GenericTypeParameterBuilder)
+ return MemberList.Empty;
if (mt == MemberTypes.Event)
members = type.GetEvents (bf | BindingFlags.DeclaredOnly);
else
public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
MemberFilter filter, object criteria)
{
- return member_cache.FindMembers (mt, bf, name, filter, criteria);
+ return new MemberList (member_cache.FindMembers (mt, bf, name, filter, criteria));
}
public MemberCache MemberCache {