X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Ftypemanager.cs;h=ef1a806073e195c6677067be9ad0bf24d36fcf62;hb=740b5e1ef4f9b44ecf9cb10a905cad26a6306551;hp=50e504c5165a64fbc9734a5d43e89d1b20f22290;hpb=e0e4acf1ab210a00104a038ba206073b8ad47f63;p=mono.git
diff --git a/mcs/mcs/typemanager.cs b/mcs/mcs/typemanager.cs
index 50e504c5165..ef1a806073e 100644
--- a/mcs/mcs/typemanager.cs
+++ b/mcs/mcs/typemanager.cs
@@ -31,7 +31,10 @@ using System.Diagnostics;
namespace Mono.CSharp {
-public class TypeManager {
+#if GMCS_SOURCE
+ partial
+#endif
+ class TypeManager {
//
// A list of core types that the compiler requires or uses
//
@@ -57,7 +60,6 @@ public class TypeManager {
static public Type multicast_delegate_type;
static public Type void_type;
static public Type null_type;
- static public Type enumeration_type;
static public Type array_type;
static public Type runtime_handle_type;
static public Type icloneable_type;
@@ -70,7 +72,9 @@ public class TypeManager {
static public Type iasyncresult_type;
static public Type asynccallback_type;
static public Type intptr_type;
+ static public Type uintptr_type;
static public Type monitor_type;
+ static public Type interlocked_type;
static public Type runtime_field_handle_type;
static public Type runtime_argument_handle_type;
static public Type attribute_type;
@@ -90,6 +94,8 @@ public class TypeManager {
static public Type conditional_attribute_type;
static public Type in_attribute_type;
static public Type out_attribute_type;
+ static public Type default_parameter_value_attribute_type;
+
static public Type anonymous_method_type;
static public Type cls_compliant_attribute_type;
static public Type typed_reference_type;
@@ -112,15 +118,10 @@ public class TypeManager {
static internal Type compiler_generated_attr_type;
static internal Type fixed_buffer_attr_type;
static internal Type default_charset_type;
+ static internal Type internals_visible_attr_type;
+ static internal Type type_forwarder_attr_type;
#endif
- //
- // An empty array of types
- //
- static public Type [] NoTypes;
- static public TypeExpr [] NoTypeExprs;
-
-
//
// Expressions representing the internal types. Used during declaration
// definition.
@@ -169,7 +170,7 @@ public class TypeManager {
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 string_isinterned_string;
static public MethodInfo system_type_get_type_from_handle;
static public MethodInfo bool_movenext_void;
static public MethodInfo ienumerable_getenumerator_void;
@@ -189,13 +190,14 @@ public class TypeManager {
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 int_interlocked_compare_exchange;
static public PropertyInfo ienumerator_getcurrent;
//
// The attribute constructors.
//
static public ConstructorInfo object_ctor;
- static public ConstructorInfo cons_param_array_attribute;
+ static private ConstructorInfo cons_param_array_attribute;
static public ConstructorInfo void_decimal_ctor_five_args;
static public ConstructorInfo void_decimal_ctor_int_arg;
static public ConstructorInfo unverifiable_code_ctor;
@@ -251,7 +253,13 @@ public class TypeManager {
public static Hashtable AllClsTopLevelTypes;
static Hashtable fieldbuilders_to_fields;
+ static Hashtable propertybuilder_to_property;
static Hashtable fields;
+ static Hashtable events;
+
+#if GMCS_SOURCE
+ static PtrHashtable assembly_internals_vis_attrs;
+#endif
struct Signature {
public string name;
@@ -264,16 +272,20 @@ public class TypeManager {
builder_to_declspace = null;
builder_to_member_cache = null;
builder_to_ifaces = null;
+ builder_to_type_param = null;
indexer_arguments = null;
method_params = null;
builder_to_method = null;
fields = null;
- fieldbuilders_to_fields = null;
events = null;
- priv_fields_events = null;
type_hash = null;
-
+ propertybuilder_to_property = null;
+
+#if GMCS_SOURCE
+ assembly_internals_vis_attrs = null;
+#endif
+
TypeHandle.CleanUp ();
}
@@ -287,7 +299,7 @@ public class TypeManager {
if (!(mi is MethodBase))
return false;
-
+
if (mi.Name != sig.name)
return false;
@@ -361,17 +373,24 @@ public class TypeManager {
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 ();
indexer_arguments = new PtrHashtable ();
builder_to_ifaces = new PtrHashtable ();
- NoTypes = new Type [0];
- NoTypeExprs = new TypeExpr [0];
-
fieldbuilders_to_fields = new Hashtable ();
+ propertybuilder_to_property = new Hashtable ();
fields = new Hashtable ();
type_hash = new DoubleHash ();
+
+#if GMCS_SOURCE
+ assembly_internals_vis_attrs = new PtrHashtable ();
+#endif
+
+ // to uncover regressions
+ AllClsTopLevelTypes = null;
+ cons_param_array_attribute = null;
}
public static void AddUserType (DeclSpace ds)
@@ -425,12 +444,21 @@ public class TypeManager {
return container.MemberCache;
}
+#if GMCS_SOURCE
+ if (t is GenericTypeParameterBuilder) {
+ IMemberContainer container = builder_to_type_param [t] as IMemberContainer;
+
+ if (container != null)
+ return container.MemberCache;
+ }
+#endif
+
return TypeHandle.GetMemberCache (t);
}
public static MemberCache LookupBaseInterfacesCache (Type t)
{
- Type [] ifaces = t.GetInterfaces ();
+ Type [] ifaces = GetInterfaces (t);
if (ifaces != null && ifaces.Length == 1)
return LookupMemberCache (ifaces [0]);
@@ -481,7 +509,11 @@ public class TypeManager {
//
public static Type GetReferenceType (Type t)
{
+#if GMCS_SOURCE
+ return t.MakeByRefType ();
+#else
return GetConstructedType (t, "&");
+#endif
}
//
@@ -495,11 +527,56 @@ public class TypeManager {
public static Type GetConstructedType (Type t, string dim)
{
object ret = null;
- if (!type_hash.Lookup (t, dim, out ret)) {
- ret = t.Module.GetType (t.ToString () + dim);
+ if (type_hash.Lookup (t, dim, out ret))
+ return (Type) ret;
+
+ ret = t.Module.GetType (t.ToString () + dim);
+ if (ret != null) {
type_hash.Insert (t, dim, ret);
+ return (Type) ret;
}
- return (Type) ret;
+
+ if (dim == "&") {
+ ret = GetReferenceType (t);
+ type_hash.Insert (t, dim, ret);
+ return (Type) ret;
+ }
+
+#if GMCS_SOURCE
+ if (t.IsGenericParameter || t.IsGenericType) {
+ int pos = 0;
+ Type result = t;
+ while ((pos < dim.Length) && (dim [pos] == '[')) {
+ pos++;
+
+ if (dim [pos] == ']') {
+ result = result.MakeArrayType ();
+ pos++;
+
+ if (pos < dim.Length)
+ continue;
+
+ type_hash.Insert (t, dim, result);
+ return result;
+ }
+
+ int rank = 0;
+ while (dim [pos] == ',') {
+ pos++; rank++;
+ }
+
+ if ((dim [pos] != ']') || (pos != dim.Length-1))
+ break;
+
+ result = result.MakeArrayType (rank + 1);
+ type_hash.Insert (t, dim, result);
+ return result;
+ }
+ }
+#endif
+
+ type_hash.Insert (t, dim, null);
+ return null;
}
public static Type GetNestedType (Type t, string name)
@@ -541,7 +618,19 @@ public class TypeManager {
///
static public string CSharpName (Type t)
{
- return Regex.Replace (t.FullName,
+ if (t == typeof(NullType))
+ return "null";
+
+#if GMCS_SOURCE
+ if (IsNullableType (t) && !t.IsGenericTypeDefinition) {
+ t = GetTypeArguments (t) [0];
+ return CSharpName (t) + "?";
+ }
+#endif
+
+ string name = GetFullName (t);
+
+ return Regex.Replace (name,
@"^System\." +
@"(Int32|UInt32|Int16|UInt16|Int64|UInt64|" +
@"Single|Double|Char|Decimal|Byte|SByte|Object|" +
@@ -576,6 +665,16 @@ public class TypeManager {
+ match.Groups [2].Captures [0].Value;
}
+ // Used for error reporting to show symbolic name instead of underlying value
+ public static string CSharpEnumValue (Type t, object value)
+ {
+ Enum e = LookupDeclSpace (t) as Enum;
+ if (e == null)
+ return System.Enum.GetName (t, value);
+
+ return e.GetDefinition (value).GetSignatureForError ();
+ }
+
///
/// Returns the signature of the method with full namespace classification
///
@@ -583,9 +682,9 @@ public class TypeManager {
{
PropertyInfo pi = mi as PropertyInfo;
if (pi != null) {
- MethodBase pmi = pi.GetGetMethod ();
+ MethodBase pmi = pi.GetGetMethod (true);
if (pmi == null)
- pmi = pi.GetSetMethod ();
+ pmi = pi.GetSetMethod (true);
if (GetParameterData (pmi).Count > 0)
mi = pmi;
}
@@ -594,6 +693,71 @@ public class TypeManager {
: CSharpName (mi.DeclaringType) + '.' + mi.Name;
}
+#if GMCS_SOURCE
+ 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 ('.');
+ sb.Append (RemoveGenericArity (t.Name));
+ } else {
+ sb.Append (RemoveGenericArity (t.FullName));
+ }
+
+ 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;
+ }
+
+ public static string GetFullName (Type t)
+ {
+ 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 ();
+ }
+#else
+ public static string GetFullName (Type t)
+ {
+ return t.FullName;
+ }
+#endif
+
+ public static string RemoveGenericArity (string from)
+ {
+ int i = from.IndexOf ('`');
+ if (i > 0)
+ return from.Substring (0, i);
+ return from;
+ }
+
///
/// When we need to report accessors as well
///
@@ -612,10 +776,9 @@ public class TypeManager {
ParameterData iparams = GetParameterData (mb);
string parameters = iparams.GetSignatureForError ();
- string accessor = "";
+ int accessor_end = 0;
- // Is property
- if (mb.IsSpecialName) {
+ if (!mb.IsConstructor && TypeManager.IsSpecialMethod (mb)) {
Operator.OpType ot = Operator.GetOperatorType (mb.Name);
if (ot != Operator.OpType.TOP) {
sig.Append ("operator ");
@@ -624,49 +787,71 @@ public class TypeManager {
return sig.ToString ();
}
- if (mb.Name.StartsWith ("get_") || mb.Name.StartsWith ("set_")) {
- accessor = mb.Name.Substring (0, 3);
+ 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 (mb.IsSpecialName && !mb.IsConstructor) {
- if (iparams.Count > (mb.Name.StartsWith ("get_") ? 0 : 1)) {
+ // Is indexer
+ if (iparams.Count > (is_getter ? 0 : 1)) {
sig.Append ("this[");
- if (show_accessor) {
+ if (is_getter)
sig.Append (parameters.Substring (1, parameters.Length - 2));
- }
- else {
- int before_ret_val = parameters.LastIndexOf (',');
- if (before_ret_val < 0)
- sig.Append (parameters.Substring (1, parameters.Length - 2));
- else
- sig.Append (parameters.Substring (1, before_ret_val - 1));
- }
+ else
+ sig.Append (parameters.Substring (1, parameters.LastIndexOf (',') - 1));
sig.Append (']');
} else {
- sig.Append (mb.Name.Substring (4));
+ sig.Append (mb.Name.Substring (accessor_end + 1));
}
} else {
if (mb.Name == ".ctor")
sig.Append (mb.DeclaringType.Name);
- else
+ else {
sig.Append (mb.Name);
+#if GMCS_SOURCE
+ if (TypeManager.IsGenericMethod (mb)) {
+ Type[] args = mb.GetGenericArguments ();
+ sig.Append ('<');
+ for (int i = 0; i < args.Length; i++) {
+ if (i > 0)
+ sig.Append (',');
+ sig.Append (args [i].Name);
+ }
+ sig.Append ('>');
+ }
+#endif
+ }
+
sig.Append (parameters);
}
- if (show_accessor && accessor.Length > 0) {
+ if (show_accessor && accessor_end > 0) {
sig.Append ('.');
- sig.Append (accessor);
+ sig.Append (mb.Name.Substring (0, accessor_end));
}
return sig.ToString ();
}
+ public static string GetMethodName (MethodInfo m)
+ {
+#if GMCS_SOURCE
+ if (!IsGenericMethodDefinition (m) && !IsGenericMethod (m))
+ return m.Name;
+
+ return MemberName.MakeName (m.Name, m.GetGenericArguments ().Length);
+#else
+ return m.Name;
+#endif
+ }
+
static public string CSharpSignature (EventInfo ei)
{
- return CSharpName (ei.DeclaringType) + '.' + ei.Name;
+ return CSharpName (ei.DeclaringType) + "." + ei.Name;
}
///
@@ -676,10 +861,14 @@ public class TypeManager {
static Type CoreLookupType (string ns_name, string name)
{
Namespace ns = RootNamespace.Global.GetNamespace (ns_name, true);
- FullNamedExpression fne = ns.Lookup (RootContext.Tree.Types, name, Location.Null);
+ FullNamedExpression fne = ns.Lookup (RootContext.ToplevelTypes, name, Location.Null);
Type t = fne == null ? null : fne.Type;
- if (t == null)
+ if (t == null) {
Report.Error (518, "The predefined type `" + name + "' is not defined or imported");
+ return null;
+ }
+
+ AttributeTester.RegisterNonObsoleteType (t);
return t;
}
@@ -721,7 +910,7 @@ public class TypeManager {
return GetMethod (t, name, args, false, report_errors);
}
- static MethodInfo GetMethod (Type t, string name, Type [] args)
+ public static MethodInfo GetMethod (Type t, string name, Type [] args)
{
return GetMethod (t, name, args, true);
}
@@ -730,10 +919,10 @@ public class TypeManager {
/// Returns the PropertyInfo for a property named `name' defined
/// in type `t'
///
- static PropertyInfo GetProperty (Type t, string name)
+ public static PropertyInfo GetProperty (Type t, string name)
{
MemberList list = FindMembers (t, MemberTypes.Property, BindingFlags.Public |
- BindingFlags.Instance, Type.FilterName, name);
+ BindingFlags.Instance, Type.FilterName, name);
if (list.Count == 0) {
Report.Error (-19, "Can not find the core property `" + name + "'");
return null;
@@ -758,6 +947,9 @@ public class TypeManager {
sig.name = ".ctor";
sig.args = args;
+
+ if (t == null)
+ throw new InternalErrorException ("Core types haven't been initialized yet?");
list = FindMembers (t, MemberTypes.Constructor,
instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly,
@@ -778,7 +970,6 @@ public class TypeManager {
public static void InitEnumUnderlyingTypes ()
{
-
int32_type = CoreLookupType ("System", "Int32");
int64_type = CoreLookupType ("System", "Int64");
uint32_type = CoreLookupType ("System", "UInt32");
@@ -787,6 +978,15 @@ public class TypeManager {
sbyte_type = CoreLookupType ("System", "SByte");
short_type = CoreLookupType ("System", "Int16");
ushort_type = CoreLookupType ("System", "UInt16");
+
+ ienumerator_type = CoreLookupType ("System.Collections", "IEnumerator");
+ ienumerable_type = CoreLookupType ("System.Collections", "IEnumerable");
+
+ idisposable_type = CoreLookupType ("System", "IDisposable");
+
+#if GMCS_SOURCE
+ InitGenericCoreTypes ();
+#endif
}
///
@@ -797,7 +997,9 @@ public class TypeManager {
public static void InitCoreTypes ()
{
object_type = CoreLookupType ("System", "Object");
+ system_object_expr.Type = object_type;
value_type = CoreLookupType ("System", "ValueType");
+ system_valuetype_expr.Type = value_type;
InitEnumUnderlyingTypes ();
@@ -824,13 +1026,12 @@ public class TypeManager {
runtime_handle_type = CoreLookupType ("System", "RuntimeTypeHandle");
asynccallback_type = CoreLookupType ("System", "AsyncCallback");
iasyncresult_type = CoreLookupType ("System", "IAsyncResult");
- ienumerator_type = CoreLookupType ("System.Collections", "IEnumerator");
- ienumerable_type = CoreLookupType ("System.Collections", "IEnumerable");
- idisposable_type = CoreLookupType ("System", "IDisposable");
icloneable_type = CoreLookupType ("System", "ICloneable");
iconvertible_type = CoreLookupType ("System", "IConvertible");
+ interlocked_type = CoreLookupType ("System.Threading", "Interlocked");
monitor_type = CoreLookupType ("System.Threading", "Monitor");
intptr_type = CoreLookupType ("System", "IntPtr");
+ uintptr_type = CoreLookupType ("System", "UIntPtr");
attribute_type = CoreLookupType ("System", "Attribute");
attribute_usage_type = CoreLookupType ("System", "AttributeUsageAttribute");
@@ -840,6 +1041,9 @@ public class TypeManager {
param_array_type = CoreLookupType ("System", "ParamArrayAttribute");
in_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "InAttribute");
out_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "OutAttribute");
+#if NET_2_0
+ default_parameter_value_attribute_type = CoreLookupType ("System.Runtime.InteropServices", "DefaultParameterValueAttribute");
+#endif
typed_reference_type = CoreLookupType ("System", "TypedReference");
arg_iterator_type = CoreLookupType ("System", "ArgIterator");
mbr_type = CoreLookupType ("System", "MarshalByRefObject");
@@ -877,7 +1081,9 @@ public class TypeManager {
compiler_generated_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "CompilerGeneratedAttribute");
fixed_buffer_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "FixedBufferAttribute");
default_charset_type = CoreLookupType ("System.Runtime.InteropServices", "DefaultCharSetAttribute");
+ internals_visible_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
runtime_compatibility_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "RuntimeCompatibilityAttribute");
+ type_forwarder_attr_type = CoreLookupType ("System.Runtime.CompilerServices", "TypeForwardedToAttribute");
#endif
//
// When compiling corlib, store the "real" types here.
@@ -888,13 +1094,12 @@ public class TypeManager {
system_type_type = typeof (System.Type);
system_assemblybuilder_type = typeof (System.Reflection.Emit.AssemblyBuilder);
- Type [] void_arg = { };
system_int_array_get_length = GetMethod (
- system_array_type, "get_Length", void_arg);
+ system_array_type, "get_Length", Type.EmptyTypes);
system_int_array_get_rank = GetMethod (
- system_array_type, "get_Rank", void_arg);
+ system_array_type, "get_Rank", Type.EmptyTypes);
system_object_array_clone = GetMethod (
- system_array_type, "Clone", void_arg);
+ system_array_type, "Clone", Type.EmptyTypes);
Type [] system_int_arg = { system_int32_type };
system_int_array_get_length_int = GetMethod (
@@ -945,7 +1150,6 @@ public class TypeManager {
}
}
- system_object_expr.Type = object_type;
system_string_expr.Type = string_type;
system_boolean_expr.Type = bool_type;
system_decimal_expr.Type = decimal_type;
@@ -963,7 +1167,6 @@ public class TypeManager {
system_void_expr.Type = void_type;
system_asynccallback_expr.Type = asynccallback_type;
system_iasyncresult_expr.Type = iasyncresult_type;
- system_valuetype_expr.Type = value_type;
//
// These are only used for compare purposes
@@ -1004,7 +1207,7 @@ public class TypeManager {
string_type, "Concat", params_object);
Type [] string_ = { string_type };
- string_isinterneted_string = GetMethod (
+ string_isinterned_string = GetMethod (
string_type, "IsInterned", string_);
Type [] runtime_type_handle = { runtime_handle_type };
@@ -1021,23 +1224,22 @@ public class TypeManager {
//
// Void arguments
//
- Type [] void_arg = { };
ienumerator_getcurrent = GetProperty (
ienumerator_type, "Current");
bool_movenext_void = GetMethod (
- ienumerator_type, "MoveNext", void_arg);
+ ienumerator_type, "MoveNext", Type.EmptyTypes);
void_reset_void = GetMethod (
- ienumerator_type, "Reset", void_arg);
+ ienumerator_type, "Reset", Type.EmptyTypes);
void_dispose_void = GetMethod (
- idisposable_type, "Dispose", void_arg);
+ idisposable_type, "Dispose", Type.EmptyTypes);
int_get_offset_to_string_data = GetMethod (
- runtime_helpers_type, "get_OffsetToStringData", void_arg);
+ runtime_helpers_type, "get_OffsetToStringData", Type.EmptyTypes);
int_array_get_length = GetMethod (
- array_type, "get_Length", void_arg);
+ array_type, "get_Length", Type.EmptyTypes);
int_array_get_rank = GetMethod (
- array_type, "get_Rank", void_arg);
+ array_type, "get_Rank", Type.EmptyTypes);
ienumerable_getenumerator_void = GetMethod (
- ienumerable_type, "GetEnumerator", void_arg);
+ ienumerable_type, "GetEnumerator", Type.EmptyTypes);
//
// Int32 arguments
@@ -1054,7 +1256,7 @@ public class TypeManager {
// System.Array methods
//
object_array_clone = GetMethod (
- array_type, "Clone", void_arg);
+ array_type, "Clone", Type.EmptyTypes);
Type [] array_int_arg = { array_type, int32_type };
void_array_copyto_array_int = GetMethod (
array_type, "CopyTo", array_int_arg);
@@ -1091,8 +1293,7 @@ public class TypeManager {
//
// Attributes
//
- cons_param_array_attribute = GetConstructor (param_array_type, void_arg);
- unverifiable_code_ctor = GetConstructor (unverifiable_code_type, void_arg);
+ unverifiable_code_ctor = GetConstructor (unverifiable_code_type, Type.EmptyTypes);
default_member_ctor = GetConstructor (default_member_type, string_);
Type[] short_arg = { short_type };
@@ -1104,20 +1305,39 @@ public class TypeManager {
field_offset_attribute_ctor = GetConstructor (field_offset_attribute_type, new Type []
{ int32_type });
+ //
+ // System.Threading.CompareExchange
+ //
+ Type[] compare_exchange_types = {
+ GetReferenceType (int32_type), int32_type, int32_type };
+ int_interlocked_compare_exchange = GetMethod (
+ interlocked_type, "CompareExchange", compare_exchange_types);
+
//
// .NET 2.0 types
//
#if NET_2_0
compiler_generated_attr = new CustomAttributeBuilder (
- GetConstructor (compiler_generated_attr_type, void_arg), new object[0]);
+ GetConstructor (compiler_generated_attr_type, Type.EmptyTypes), new object[0]);
Type[] type_int_arg = { type_type, int32_type };
fixed_buffer_attr_ctor = GetConstructor (fixed_buffer_attr_type, type_int_arg);
#endif
// Object
- object_ctor = GetConstructor (object_type, void_arg);
+ object_ctor = GetConstructor (object_type, Type.EmptyTypes);
+
+#if GMCS_SOURCE
+ InitGenericCodeHelpers ();
+#endif
+ }
+ static public ConstructorInfo ConsParamArrayAttribute {
+ get {
+ if (cons_param_array_attribute == null)
+ cons_param_array_attribute = GetConstructor (param_array_type, Type.EmptyTypes);
+ return cons_param_array_attribute;
+ }
}
const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
@@ -1129,6 +1349,11 @@ public class TypeManager {
public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
MemberFilter filter, object criteria)
{
+#if MS_COMPATIBLE && GMCS_SOURCE
+ if (t.IsGenericType)
+ t = t.GetGenericTypeDefinition ();
+#endif
+
DeclSpace decl = (DeclSpace) builder_to_declspace [t];
//
@@ -1147,9 +1372,25 @@ public class TypeManager {
// a TypeBuilder array will return a Type, not a TypeBuilder,
// and we can not call FindMembers on this type.
//
- if (TypeManager.IsSubclassOf (t, TypeManager.array_type))
+ if (
+#if MS_COMPATIBLE && GMCS_SOURCE
+ !t.IsGenericType &&
+#endif
+ t.IsSubclassOf (TypeManager.array_type))
return new MemberList (TypeManager.array_type.FindMembers (mt, bf, filter, criteria));
+#if GMCS_SOURCE
+ 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;
+ }
+#endif
+
//
// Since FindMembers will not lookup both static and instance
// members, we emulate this behaviour here.
@@ -1195,20 +1436,14 @@ public class TypeManager {
/// to check base classes and interfaces anymore.
///
private static MemberInfo [] MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
- string name, out bool used_cache)
+ string name, out bool used_cache)
{
MemberCache cache;
- //
- // 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 == TypeManager.array_type || t.IsSubclassOf (TypeManager.array_type)) {
- used_cache = true;
- return TypeHandle.ArrayType.MemberCache.FindMembers (
- mt, bf, name, FilterWithClosure_delegate, null);
- }
+#if GMCS_SOURCE && MS_COMPATIBLE
+ if (t.IsGenericType && !t.IsGenericTypeDefinition)
+ t = t.GetGenericTypeDefinition();
+#endif
//
// If this is a dynamic type, it's always in the `builder_to_declspace' hash table
@@ -1230,17 +1465,53 @@ public class TypeManager {
// 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) { // == TypeManager.array_type || t.IsSubclassOf (TypeManager.array_type)) {
+ used_cache = true;
+ return TypeHandle.ArrayType.MemberCache.FindMembers (
+ mt, bf, name, FilterWithClosure_delegate, null);
+ }
+
+#if GMCS_SOURCE
+ 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 = true;
+ return (MemberInfo []) list;
+ }
+#endif
+
+ if (IsGenericType (t) && (mt == MemberTypes.NestedType)) {
+ //
+ // This happens if we're resolving a class'es base class and interfaces
+ // in TypeContainer.DefineType(). At this time, the types aren't
+ // populated yet, so we can't use the cache.
+ //
+ MemberInfo[] info = t.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
+ FilterWithClosure_delegate, name);
+ used_cache = false;
+ return info;
+ }
+
//
// This call will always succeed. There is exactly one TypeHandle instance per
// type, TypeHandle.GetMemberCache() will, if necessary, create a new one, and return
@@ -1254,6 +1525,7 @@ public class TypeManager {
public static bool IsBuiltinType (Type t)
{
+ t = TypeToCoreType (t);
if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
t == int64_type || t == uint64_type || t == float_type || t == double_type ||
t == char_type || t == short_type || t == decimal_type || t == bool_type ||
@@ -1282,6 +1554,7 @@ public class TypeManager {
public static bool IsDelegateType (Type t)
{
+ t = DropGenericTypeArguments (t);
if (t.IsSubclassOf (TypeManager.delegate_type))
return true;
else
@@ -1293,6 +1566,10 @@ public class TypeManager {
if (builder_to_declspace [t] is Enum)
return true;
+#if MS_COMPATIBLE && GMCS_SOURCE
+ if (t.IsGenericParameter || t.IsGenericType)
+ return false;
+#endif
return t.IsEnum;
}
@@ -1307,6 +1584,16 @@ public class TypeManager {
return false;
}
+ public static bool IsNullType (Type t)
+ {
+ return t == null_type;
+ }
+
+ public static bool IsAttributeType (Type t)
+ {
+ return t == attribute_type && t.BaseType != null || IsSubclassOf (t, attribute_type);
+ }
+
static Stack unmanaged_enclosing_types = new Stack (4);
//
@@ -1322,6 +1609,9 @@ public class TypeManager {
if (t == TypeManager.object_type || t == TypeManager.string_type)
return false;
+ if (IsGenericType (t) || IsGenericParameter (t))
+ return false;
+
if (IsBuiltinOrEnum (t))
return true;
@@ -1336,14 +1626,21 @@ public class TypeManager {
if (!IsValueType (t))
return false;
+#if GMCS_SOURCE
+ for (Type p = t.DeclaringType; p != null; p = p.DeclaringType) {
+ if (p.IsGenericTypeDefinition)
+ return false;
+ }
+#endif
+
unmanaged_enclosing_types.Push (t);
bool retval = true;
- if (t is TypeBuilder){
+ if (t is TypeBuilder) {
TypeContainer tc = LookupTypeContainer (t);
if (tc.Fields != null){
- foreach (FieldMember f in tc.Fields){
+ foreach (FieldBase f in tc.Fields){
// Avoid using f.FieldBuilder: f.Define () may not yet have been invoked.
if ((f.ModFlags & Modifiers.STATIC) != 0)
continue;
@@ -1373,10 +1670,7 @@ public class TypeManager {
public static bool IsValueType (Type t)
{
- if (t.IsSubclassOf (TypeManager.value_type) && (t != TypeManager.enum_type))
- return true;
- else
- return false;
+ return t.IsValueType || IsGenericParameter (t);
}
public static bool IsInterfaceType (Type t)
@@ -1390,8 +1684,26 @@ public class TypeManager {
public static bool IsSubclassOf (Type type, Type base_type)
{
+ TypeParameter tparam = LookupTypeParameter (type);
+ TypeParameter pparam = LookupTypeParameter (base_type);
+
+ if ((tparam != null) && (pparam != null)) {
+ if (tparam == pparam)
+ return true;
+
+ return tparam.IsSubclassOf (base_type);
+ }
+
+#if MS_COMPATIBLE && GMCS_SOURCE
+ if (type.IsGenericType)
+ type = type.GetGenericTypeDefinition ();
+#endif
+
+ if (type.IsSubclassOf (base_type))
+ return true;
+
do {
- if (type.Equals (base_type))
+ if (IsEqual (type, base_type))
return true;
type = type.BaseType;
@@ -1400,9 +1712,37 @@ public class TypeManager {
return false;
}
- public static bool IsFamilyAccessible (Type type, Type base_type)
+ 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)
{
- return IsSubclassOf (type, base_type);
+ 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;
}
//
@@ -1411,7 +1751,7 @@ public class TypeManager {
public static bool IsNestedFamilyAccessible (Type type, Type base_type)
{
do {
- if ((type == base_type) || type.IsSubclassOf (base_type))
+ if (IsFamilyAccessible (type, base_type))
return true;
// Handle nested types.
@@ -1426,12 +1766,18 @@ public class TypeManager {
//
public static bool IsNestedChildOf (Type type, Type parent)
{
- if (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 (type == parent)
+ if (IsEqual (type, parent))
return true;
type = type.DeclaringType;
@@ -1440,36 +1786,111 @@ public class TypeManager {
return false;
}
- //
- // 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 ());
- }
-
- ///
- /// This method is not implemented by MS runtime for dynamic types
- ///
- public static bool HasElementType (Type t)
- {
- return t.IsArray || t.IsPointer || t.IsByRef;
- }
-
- ///
- /// Gigantic work around for missing features in System.Reflection.Emit follows.
- ///
- ///
- ///
- /// 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.
- ///
- static public void RegisterMethod (MethodBase mb, Parameters ip)
+#if GMCS_SOURCE
+ //
+ // Checks whether `extern_type' is friend of the output assembly
+ //
+ public static bool IsFriendAssembly (Assembly assembly)
+ {
+ if (assembly_internals_vis_attrs.Contains (assembly))
+ return (bool)(assembly_internals_vis_attrs [assembly]);
+
+ object [] attrs = assembly.GetCustomAttributes (internals_visible_attr_type, false);
+ if (attrs.Length == 0) {
+ assembly_internals_vis_attrs.Add (assembly, false);
+ return false;
+ }
+
+ AssemblyName this_name = CodeGen.Assembly.Name;
+ byte [] this_token = this_name.GetPublicKeyToken ();
+ bool is_friend = false;
+ 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 == null) {
+ // Same name, but key token is null
+ Error_FriendAccessNameNotMatching (aname.FullName);
+ 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.Error (281, "Friend access was granted to `" + other_name +
+ "', but the output assembly is named `" + CodeGen.Assembly.Name.FullName +
+ "'. Try adding a reference to `" + other_name +
+ "' or change the output assembly name to match it");
+ }
+#else
+ public static bool IsFriendAssembly (Assembly assembly)
+ {
+ return false;
+ }
+#endif
+
+ //
+ // Do the right thing when returning the element type of an
+ // array type based on whether we are compiling corlib or not
+ //
+ public static Type GetElementType (Type t)
+ {
+ if (RootContext.StdLib)
+ return t.GetElementType ();
+ else
+ return TypeToCoreType (t.GetElementType ());
+ }
+
+ ///
+ /// This method is not implemented by MS runtime for dynamic types
+ ///
+ public static bool HasElementType (Type t)
+ {
+ return t.IsArray || t.IsPointer || t.IsByRef;
+ }
+
+ ///
+ /// Gigantic work around for missing features in System.Reflection.Emit follows.
+ ///
+ ///
+ ///
+ /// 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.
+ ///
+ static public void RegisterMethod (MethodBase mb, Parameters ip)
{
method_params.Add (mb, ip);
}
@@ -1489,21 +1910,28 @@ public class TypeManager {
static public void RegisterOverride (MethodBase override_method, MethodBase base_method)
{
- if (method_overrides.Contains (override_method)) {
- if (method_overrides [override_method] != base_method)
- throw new InternalErrorException ("Override mismatch: " + override_method);
- return;
- }
- method_overrides [override_method] = 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];
+ }
+
///
/// Returns the argument types for an indexer based on its PropertyInfo
///
@@ -1519,12 +1947,12 @@ public class TypeManager {
// If we're a PropertyBuilder and not in the
// `indexer_arguments' hash, then we're a property and
// not an indexer.
- return NoTypes;
+ return Type.EmptyTypes;
else {
ParameterInfo [] pi = indexer.GetIndexParameters ();
// Property, not an indexer.
if (pi == null)
- return NoTypes;
+ return Type.EmptyTypes;
int c = pi.Length;
Type [] types = new Type [c];
@@ -1549,13 +1977,19 @@ public class TypeManager {
return (IConstant)fields [fb];
}
- static public bool RegisterFieldBase (FieldBuilder fb, FieldBase f)
+ public static void RegisterProperty (PropertyInfo pi, PropertyBase pb)
{
- if (fieldbuilders_to_fields.Contains (fb))
- return false;
+ 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);
- return true;
}
//
@@ -1565,27 +1999,16 @@ public class TypeManager {
//
static public FieldBase GetField (FieldInfo fb)
{
+#if GMCS_SOURCE
+ fb = GetGenericFieldDefinition (fb);
+#endif
return (FieldBase) fieldbuilders_to_fields [fb];
}
-
- static Hashtable events;
-
- static public void RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove)
- {
- if (events == null)
- events = new Hashtable ();
-
- if (!events.Contains (eb)) {
- events.Add (eb, new Pair (add, remove));
- }
- }
static public MethodInfo GetAddMethod (EventInfo ei)
{
if (ei is MyEventBuilder) {
- Pair pair = (Pair) events [ei];
-
- return (MethodInfo) pair.First;
+ return ((MyEventBuilder)ei).GetAddMethod (true);
}
return ei.GetAddMethod (true);
}
@@ -1593,36 +2016,27 @@ public class TypeManager {
static public MethodInfo GetRemoveMethod (EventInfo ei)
{
if (ei is MyEventBuilder) {
- Pair pair = (Pair) events [ei];
-
- return (MethodInfo) pair.Second;
+ return ((MyEventBuilder)ei).GetRemoveMethod (true);
}
return ei.GetRemoveMethod (true);
}
- static Hashtable priv_fields_events;
-
- static public bool RegisterPrivateFieldOfEvent (EventInfo einfo, FieldBuilder builder)
+ static public void RegisterEventField (EventInfo einfo, EventField e)
{
- if (priv_fields_events == null)
- priv_fields_events = new Hashtable ();
-
- if (priv_fields_events.Contains (einfo))
- return false;
-
- priv_fields_events.Add (einfo, builder);
+ if (events == null)
+ events = new Hashtable ();
- return true;
+ events.Add (einfo, e);
}
- static public MemberInfo GetPrivateFieldOfEvent (EventInfo ei)
+ static public EventField GetEventField (EventInfo ei)
{
- if (priv_fields_events == null)
+ if (events == null)
return null;
- else
- return (MemberInfo) priv_fields_events [ei];
+
+ return (EventField) events [ei];
}
-
+
static public bool RegisterIndexer (PropertyBuilder pb, MethodBase get,
MethodBase set, Type[] args)
{
@@ -1653,7 +2067,7 @@ public class TypeManager {
if (tc.Fields == null)
return true;
- foreach (FieldMember field in tc.Fields) {
+ foreach (FieldBase field in tc.Fields) {
if (field.FieldBuilder == null || field.FieldBuilder.IsStatic)
continue;
@@ -1698,20 +2112,42 @@ public class TypeManager {
/// This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
/// be IA, IB, IC.
///
- public static Type[] ExpandInterfaces (EmitContext ec, TypeExpr [] base_interfaces)
+ public static Type[] ExpandInterfaces (TypeExpr [] base_interfaces)
{
ArrayList new_ifaces = new ArrayList ();
foreach (TypeExpr iface in base_interfaces){
- Type itype = iface.ResolveType (ec);
- if (itype == null)
- return null;
+ Type itype = iface.Type;
- if (!new_ifaces.Contains (itype))
- new_ifaces.Add (itype);
+ if (new_ifaces.Contains (itype))
+ continue;
+
+ new_ifaces.Add (itype);
- Type [] implementing = itype.GetInterfaces ();
+ 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);
@@ -1721,7 +2157,7 @@ public class TypeManager {
new_ifaces.CopyTo (ret, 0);
return ret;
}
-
+
static PtrHashtable iface_cache = new PtrHashtable ();
///
@@ -1730,7 +2166,6 @@ public class TypeManager {
///
public static Type [] GetInterfaces (Type t)
{
-
Type [] cached = iface_cache [t] as Type [];
if (cached != null)
return cached;
@@ -1748,16 +2183,24 @@ public class TypeManager {
if (t.IsArray)
t = TypeManager.array_type;
- if (t is TypeBuilder){
+ if ((t is TypeBuilder) || IsGenericType (t)) {
Type [] base_ifaces;
if (t.BaseType == null)
- base_ifaces = NoTypes;
+ base_ifaces = Type.EmptyTypes;
else
base_ifaces = GetInterfaces (t.BaseType);
- Type [] type_ifaces = (Type []) builder_to_ifaces [t];
- if (type_ifaces == null)
- type_ifaces = NoTypes;
+ Type[] type_ifaces;
+ if (IsGenericType (t))
+#if MS_COMPATIBLE && GMCS_SOURCE
+ type_ifaces = t.GetGenericTypeDefinition().GetInterfaces ();
+#else
+ type_ifaces = t.GetInterfaces ();
+#endif
+ else
+ type_ifaces = (Type []) builder_to_ifaces [t];
+ if (type_ifaces == null || type_ifaces.Length == 0)
+ type_ifaces = Type.EmptyTypes;
int base_count = base_ifaces.Length;
Type [] result = new Type [base_count + type_ifaces.Length];
@@ -1766,6 +2209,15 @@ public class TypeManager {
iface_cache [t] = result;
return result;
+#if GMCS_SOURCE
+ } else if (t is GenericTypeParameterBuilder){
+ Type[] type_ifaces = (Type []) builder_to_ifaces [t];
+ if (type_ifaces == null || type_ifaces.Length == 0)
+ type_ifaces = Type.EmptyTypes;
+
+ iface_cache [t] = type_ifaces;
+ return type_ifaces;
+#endif
} else {
Type[] ifaces = t.GetInterfaces ();
iface_cache [t] = ifaces;
@@ -2006,6 +2458,7 @@ public class TypeManager {
///
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;
@@ -2039,7 +2492,72 @@ public class TypeManager {
}
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 ();
+ /// }
+ ///
+ /// public abstract class B : A
+ /// {
+ /// public override U Foo ()
+ /// { return default (U); }
+ /// }
+ ///
+ /// Here, `T' and `U' are method type parameters from different methods
+ /// (A.Foo and B.Foo), so both `==' and Equals() will fail.
+ ///
+ /// However, since we're determining whether B.Foo() overrides A.Foo(),
+ /// we need to do a signature based comparision and consider them equal.
+
+ if (a == b)
+ return true;
+
+#if GMCS_SOURCE
+ if (a.IsGenericParameter && b.IsGenericParameter &&
+ (a.DeclaringMethod != null) && (b.DeclaringMethod != null)) {
+ return a.GenericParameterPosition == b.GenericParameterPosition;
+ }
+#endif
+
+ if (a.IsArray && b.IsArray) {
+ if (a.GetArrayRank () != b.GetArrayRank ())
+ return false;
+
+ return IsSignatureEqual (a.GetElementType (), b.GetElementType ());
+ }
+
+ if (a.IsByRef && b.IsByRef)
+ return IsSignatureEqual (a.GetElementType (), b.GetElementType ());
+
+#if GMCS_SOURCE
+ if (a.IsGenericType && b.IsGenericType) {
+ if (a.GetGenericTypeDefinition () != b.GetGenericTypeDefinition ())
+ return false;
+
+ Type[] aargs = a.GetGenericArguments ();
+ Type[] bargs = b.GetGenericArguments ();
+
+ if (aargs.Length != bargs.Length)
+ return false;
+
+ for (int i = 0; i < aargs.Length; i++) {
+ if (!IsSignatureEqual (aargs [i], bargs [i]))
+ return false;
+ }
+
+ return true;
+ }
+#endif
+
+ return false;
+ }
+
//
// Returns whether the array of memberinfos contains the given method
//
@@ -2052,7 +2570,8 @@ public class TypeManager {
continue;
if (method is MethodInfo && new_method is MethodInfo)
- if (((MethodInfo) method).ReturnType != ((MethodInfo) new_method).ReturnType)
+ if (!IsSignatureEqual (((MethodInfo) method).ReturnType,
+ ((MethodInfo) new_method).ReturnType))
continue;
@@ -2064,7 +2583,7 @@ public class TypeManager {
continue;
for (i = 0; i < old_count; i++){
- if (old_args [i] != new_args [i])
+ if (!IsSignatureEqual (old_args [i], new_args [i]))
break;
}
if (i != old_count)
@@ -2106,6 +2625,328 @@ public class TypeManager {
return target_list;
}
+#region Generics
+ //
+ // Tracks the generic parameters.
+ //
+ static PtrHashtable builder_to_type_param;
+
+ public static void AddTypeParameter (Type t, TypeParameter tparam)
+ {
+ if (!builder_to_type_param.Contains (t))
+ builder_to_type_param.Add (t, tparam);
+ }
+
+ public static TypeParameter LookupTypeParameter (Type t)
+ {
+ return (TypeParameter) builder_to_type_param [t];
+ }
+
+ // This method always return false for non-generic compiler,
+ // while Type.IsGenericParameter is returned if it is supported.
+ public static bool IsGenericParameter (Type type)
+ {
+#if GMCS_SOURCE
+ return type.IsGenericParameter;
+#else
+ return false;
+#endif
+ }
+
+ public static int GenericParameterPosition (Type type)
+ {
+#if GMCS_SOURCE
+ return type.GenericParameterPosition;
+#else
+ throw new InternalErrorException ("should not be called");
+#endif
+ }
+
+ public static bool IsGenericType (Type type)
+ {
+#if GMCS_SOURCE
+ return type.IsGenericType;
+#else
+ return false;
+#endif
+ }
+
+ public static bool IsGenericTypeDefinition (Type type)
+ {
+#if GMCS_SOURCE
+ return type.IsGenericTypeDefinition;
+#else
+ return false;
+#endif
+ }
+
+ public static bool ContainsGenericParameters (Type type)
+ {
+#if GMCS_SOURCE
+ return type.ContainsGenericParameters;
+#else
+ return false;
+#endif
+ }
+
+ public static FieldInfo GetGenericFieldDefinition (FieldInfo fi)
+ {
+#if GMCS_SOURCE
+ if (fi.DeclaringType.IsGenericTypeDefinition ||
+ !fi.DeclaringType.IsGenericType)
+ return fi;
+
+ Type t = fi.DeclaringType.GetGenericTypeDefinition ();
+ BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic |
+ BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
+
+ foreach (FieldInfo f in t.GetFields (bf))
+ if (f.MetadataToken == fi.MetadataToken)
+ return f;
+#endif
+
+ return fi;
+ }
+
+ public static bool IsEqual (Type a, Type b)
+ {
+ if (a.Equals (b)) {
+ // MS BCL returns true even if enum types are different
+ if (a.BaseType == TypeManager.enum_type || b.BaseType == TypeManager.enum_type)
+ return a.FullName == b.FullName;
+
+ return true;
+ }
+
+#if GMCS_SOURCE
+ if (a.IsGenericParameter && b.IsGenericParameter) {
+ if (a.DeclaringMethod != b.DeclaringMethod &&
+ (a.DeclaringMethod == null || b.DeclaringMethod == null))
+ return false;
+ return a.GenericParameterPosition == b.GenericParameterPosition;
+ }
+
+ if (a.IsArray && b.IsArray) {
+ if (a.GetArrayRank () != b.GetArrayRank ())
+ return false;
+ return IsEqual (a.GetElementType (), b.GetElementType ());
+ }
+
+ if (a.IsByRef && b.IsByRef)
+ return IsEqual (a.GetElementType (), b.GetElementType ());
+
+ if (a.IsGenericType && b.IsGenericType) {
+ if (a.GetGenericTypeDefinition () != b.GetGenericTypeDefinition ())
+ return false;
+
+ Type[] aargs = a.GetGenericArguments ();
+ Type[] bargs = b.GetGenericArguments ();
+
+ if (aargs.Length != bargs.Length)
+ return false;
+
+ for (int i = 0; i < aargs.Length; i++) {
+ if (!IsEqual (aargs [i], bargs [i]))
+ return false;
+ }
+
+ return true;
+ }
+#endif
+
+ return false;
+ }
+
+ public static Type DropGenericTypeArguments (Type t)
+ {
+#if GMCS_SOURCE
+ if (!t.IsGenericType)
+ return t;
+ // Micro-optimization: a generic typebuilder is always a generic type definition
+ if (t is TypeBuilder)
+ return t;
+ return t.GetGenericTypeDefinition ();
+#else
+ return t;
+#endif
+ }
+
+ public static MethodBase DropGenericMethodArguments (MethodBase m)
+ {
+#if GMCS_SOURCE
+ if (m.IsGenericMethodDefinition)
+ return m;
+ if (m.IsGenericMethod)
+ return ((MethodInfo) m).GetGenericMethodDefinition ();
+ if (!m.DeclaringType.IsGenericType)
+ return m;
+
+ Type t = m.DeclaringType.GetGenericTypeDefinition ();
+ BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic |
+ BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
+
+#if MS_COMPATIBLE
+ return m;
+#endif
+
+ if (m is ConstructorInfo) {
+ foreach (ConstructorInfo c in t.GetConstructors (bf))
+ if (c.MetadataToken == m.MetadataToken)
+ return c;
+ } else {
+ foreach (MethodBase mb in t.GetMethods (bf))
+ if (mb.MetadataToken == m.MetadataToken)
+ return mb;
+ }
+#endif
+
+ return m;
+ }
+
+ public static Type[] GetGenericArguments (MethodInfo mi)
+ {
+#if GMCS_SOURCE
+ return mi.GetGenericArguments ();
+#else
+ return Type.EmptyTypes;
+#endif
+ }
+
+ public static Type[] GetTypeArguments (Type t)
+ {
+#if GMCS_SOURCE
+ DeclSpace tc = LookupDeclSpace (t);
+ if (tc != null) {
+ if (!tc.IsGeneric)
+ return Type.EmptyTypes;
+
+ TypeParameter[] tparam = tc.TypeParameters;
+ Type[] ret = new Type [tparam.Length];
+ for (int i = 0; i < tparam.Length; i++) {
+ ret [i] = tparam [i].Type;
+ if (ret [i] == null)
+ throw new InternalErrorException ();
+ }
+
+ return ret;
+ } else
+ return t.GetGenericArguments ();
+#else
+ throw new InternalErrorException ();
+#endif
+ }
+
+ public static bool HasGenericArguments (Type t)
+ {
+ return GetNumberOfTypeArguments (t) > 0;
+ }
+
+ public static int GetNumberOfTypeArguments (Type t)
+ {
+#if GMCS_SOURCE
+ if (t.IsGenericParameter)
+ return 0;
+ DeclSpace tc = LookupDeclSpace (t);
+ if (tc != null)
+ return tc.IsGeneric ? tc.CountTypeParameters : 0;
+ else
+ return t.IsGenericType ? t.GetGenericArguments ().Length : 0;
+#else
+ return 0;
+#endif
+ }
+
+ ///
+ /// Check whether `type' and `parent' are both instantiations of the same
+ /// generic type. Note that we do not check the type parameters here.
+ ///
+ 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);
+ }
+
+ ///
+ /// Whether `mb' is a generic method definition.
+ ///
+ public static bool IsGenericMethodDefinition (MethodBase mb)
+ {
+#if GMCS_SOURCE
+ if (mb.DeclaringType is TypeBuilder) {
+ IMethodData method = (IMethodData) builder_to_method [mb];
+ if (method == null)
+ return false;
+
+ return method.GenericMethod != null;
+ }
+
+ return mb.IsGenericMethodDefinition;
+#else
+ return false;
+#endif
+ }
+
+ ///
+ /// Whether `mb' is a generic method.
+ ///
+ public static bool IsGenericMethod (MethodBase mb)
+ {
+#if GMCS_SOURCE
+ if (mb.DeclaringType is TypeBuilder) {
+ IMethodData method = (IMethodData) builder_to_method [mb];
+ if (method == null)
+ return false;
+
+ return method.GenericMethod != null;
+ }
+
+ return mb.IsGenericMethod;
+#else
+ return false;
+#endif
+ }
+
+ public static bool IsNullableType (Type t)
+ {
+#if GMCS_SOURCE
+ return generic_nullable_type == DropGenericTypeArguments (t);
+#else
+ return false;
+#endif
+ }
+
+ public static bool IsNullableTypeOf (Type t, Type nullable)
+ {
+#if GMCS_SOURCE
+ if (!IsNullableType (t))
+ return false;
+
+ return GetTypeArguments (t) [0] == nullable;
+#else
+ return false;
+#endif
+ }
+
+ public static bool IsNullableValueType (Type t)
+ {
+#if GMCS_SOURCE
+ if (!IsNullableType (t))
+ return false;
+
+ return GetTypeArguments (t) [0].IsValueType;
+#else
+ return false;
+#endif
+ }
+#endregion
#region MemberLookup implementation
@@ -2114,11 +2955,6 @@ public class TypeManager {
// uses NonPublic for both protected and private), we need to distinguish.
//
- static internal bool FilterNone (MemberInfo m, object filter_criteria)
- {
- return true;
- }
-
internal class Closure {
internal bool private_ok;
@@ -2139,18 +2975,19 @@ public class TypeManager {
// It resolved from a simple name, so it should be visible.
return true;
- // A nested class has access to all the protected members visible to its parent.
- if (qualifier_type != null && TypeManager.IsNestedChildOf (invocation_type, qualifier_type))
+ if (IsNestedChildOf (invocation_type, m.DeclaringType))
return true;
- if (invocation_type == m.DeclaringType || invocation_type.IsSubclassOf (m.DeclaringType)) {
+ 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 ||
- qualifier_type == invocation_type ||
- qualifier_type.IsSubclassOf (invocation_type))
+ if (is_static || qualifier_type == null ||
+ IsInstantiationOfSameGenericType (t, qualifier_type) ||
+ IsFamilyAccessible (qualifier_type, t))
return true;
}
@@ -2167,17 +3004,18 @@ public class TypeManager {
internal bool Filter (MemberInfo m, object filter_criteria)
{
//
- // Hack: we know that the filter criteria will always be in the `closure'
- // fields.
+ // 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)) &&
- (m.DeclaringType == 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
@@ -2186,11 +3024,19 @@ public class TypeManager {
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 || invocation_type == m.DeclaringType ||
+ return private_ok ||
+ IsPrivateAccessible (invocation_type, m.DeclaringType) ||
IsNestedChildOf (invocation_type, m.DeclaringType);
- if (invocation_assembly == mb.DeclaringType.Assembly) {
+ if (invocation_assembly == mb.DeclaringType.Assembly ||
+ TypeManager.IsFriendAssembly (mb.DeclaringType.Assembly)) {
if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem)
return true;
} else {
@@ -2198,43 +3044,44 @@ public class TypeManager {
return false;
}
- if (ma == MethodAttributes.Family ||
- ma == MethodAttributes.FamANDAssem ||
- ma == MethodAttributes.FamORAssem)
- return CheckValidFamilyAccess (mb.IsStatic, m);
-
- // Public.
- return true;
+ // 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 || (invocation_type == m.DeclaringType) ||
+ return private_ok ||
+ IsPrivateAccessible (invocation_type, m.DeclaringType) ||
IsNestedChildOf (invocation_type, m.DeclaringType);
- if (invocation_assembly == fi.DeclaringType.Assembly) {
- if (fa == FieldAttributes.Assembly || fa == FieldAttributes.FamORAssem)
+ if ((invocation_assembly == fi.DeclaringType.Assembly) ||
+ (invocation_assembly == null) ||
+ TypeManager.IsFriendAssembly (fi.DeclaringType.Assembly)) {
+ if ((fa == FieldAttributes.Assembly) ||
+ (fa == FieldAttributes.FamORAssem))
return true;
} else {
- if (fa == FieldAttributes.Assembly || fa == FieldAttributes.FamANDAssem)
+ if ((fa == FieldAttributes.Assembly) ||
+ (fa == FieldAttributes.FamANDAssem))
return false;
}
- if (fa == FieldAttributes.Family ||
- fa == FieldAttributes.FamANDAssem ||
- fa == FieldAttributes.FamORAssem)
- return CheckValidFamilyAccess (fi.IsStatic, m);
-
- // Public.
- return true;
+ // 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.
+ // EventInfos and PropertyInfos, return true because they lack
+ // permission information, so we need to check later on the methods.
//
return true;
}
@@ -2274,7 +3121,7 @@ public class TypeManager {
// 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, IList almost_match)
{
Timer.StartTimer (TimerType.MemberLookup);
@@ -2394,8 +3241,7 @@ public class TypeManager {
if ((list.Length == 2) && (list [1] is FieldInfo))
return new MemberInfo [] { list [0] };
- // Oooops
- return null;
+ return list;
}
//
@@ -2416,20 +3262,13 @@ public class TypeManager {
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));
-
+ 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.
@@ -2462,25 +3301,85 @@ public class TypeManager {
return null;
}
- // Tests whether external method is really special
- public static bool IsSpecialMethod (MethodBase mb)
+ 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.StartsWith ("get_") || name.StartsWith ("set_"))
- return mb.DeclaringType.GetProperty (name.Substring (4)) != null;
+ 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)) != null;
+ return mb.DeclaringType.GetEvent (name.Substring (4), AllMembers);
if (name.StartsWith ("remove_"))
- return mb.DeclaringType.GetEvent (name.Substring (7)) != null;
+ 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_")){
foreach (string oname in Unary.oper_names) {
if (oname == name)
return true;
}
-
+
foreach (string oname in Binary.oper_names) {
if (oname == name)
return true;
@@ -2488,7 +3387,23 @@ public class TypeManager {
}
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);
+ if (get_method != null && set_method != null) {
+ int g_count = get_method.GetParameters ().Length;
+ int s_count = set_method.GetParameters ().Length;
+ if (g_count + 1 != s_count)
+ return false;
+ }
+ return true;
+ }
+
#endregion
}
@@ -2572,6 +3487,7 @@ public sealed class TypeHandle : IMemberContainer {
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;
@@ -2579,12 +3495,17 @@ public sealed class TypeHandle : IMemberContainer {
private TypeHandle (Type type)
{
this.type = type;
+#if MS_COMPATIBLE && GMCS_SOURCE
+ if (type.IsGenericType)
+ this.type = this.type.GetGenericTypeDefinition ();
+#endif
+ 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;
+ this.is_interface = type.IsInterface || TypeManager.IsGenericParameter (type);
this.member_cache = new MemberCache (this);
}
@@ -2592,7 +3513,7 @@ public sealed class TypeHandle : IMemberContainer {
public string Name {
get {
- return type.FullName;
+ return full_name;
}
}
@@ -2617,6 +3538,12 @@ public sealed class TypeHandle : IMemberContainer {
public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
{
MemberInfo [] members;
+
+#if GMCS_SOURCE
+ if (type is GenericTypeParameterBuilder)
+ return MemberList.Empty;
+#endif
+
if (mt == MemberTypes.Event)
members = type.GetEvents (bf | BindingFlags.DeclaredOnly);
else