namespace Mono.CSharp {
-public class TypeManager {
+#if GMCS_SOURCE
+ partial
+#endif
+ class TypeManager {
//
// A list of core types that the compiler requires or uses
//
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;
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;
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;
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
//
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;
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;
//
static Hashtable fields;
static Hashtable events;
+#if GMCS_SOURCE
+ static PtrHashtable assembly_internals_vis_attrs;
+#endif
+
struct Signature {
public string name;
public Type [] args;
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 ();
}
if (!(mi is MethodBase))
return false;
-
+
if (mi.Name != sig.name)
return false;
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 ();
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;
}
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]);
//
public static Type GetReferenceType (Type t)
{
+#if GMCS_SOURCE
+ return t.MakeByRefType ();
+#else
return GetConstructedType (t, "&");
+#endif
}
//
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)
/// </summary>
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|" +
+ 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 ();
+ }
+
/// <summary>
/// Returns the signature of the method with full namespace classification
/// </summary>
{
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;
}
: 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;
+ }
+
/// <summary>
/// When we need to report accessors as well
/// </summary>
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 ");
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;
}
/// <summary>
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;
}
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);
}
/// Returns the PropertyInfo for a property named `name' defined
/// in type `t'
/// </summary>
- 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;
/// <summary>
/// Returns the ConstructorInfo for "args"
/// </summary>
- private static ConstructorInfo GetConstructor (Type t, Type [] args)
+ public static ConstructorInfo GetConstructor (Type t, Type [] args)
{
MemberList list;
Signature sig;
public static void InitEnumUnderlyingTypes ()
{
-
int32_type = CoreLookupType ("System", "Int32");
int64_type = CoreLookupType ("System", "Int64");
uint32_type = CoreLookupType ("System", "UInt32");
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
}
/// <remarks>
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 ();
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");
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");
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.
}
}
- system_object_expr.Type = object_type;
system_string_expr.Type = string_type;
system_boolean_expr.Type = bool_type;
system_decimal_expr.Type = decimal_type;
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
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 };
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
//
// Object
object_ctor = GetConstructor (object_type, Type.EmptyTypes);
+#if GMCS_SOURCE
+ InitGenericCodeHelpers ();
+#endif
}
static public ConstructorInfo ConsParamArrayAttribute {
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];
//
// 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.
/// to check base classes and interfaces anymore.
/// </summary>
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
// 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
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 ||
public static bool IsDelegateType (Type t)
{
+ t = DropGenericTypeArguments (t);
if (t.IsSubclassOf (TypeManager.delegate_type))
return true;
else
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;
}
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);
//
if (t == TypeManager.object_type || t == TypeManager.string_type)
return false;
+ if (IsGenericType (t) || IsGenericParameter (t))
+ return false;
+
if (IsBuiltinOrEnum (t))
return true;
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;
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)
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;
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;
}
//
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.
//
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;
return false;
}
+#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
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];
}
return (PropertyBase)propertybuilder_to_property [pi];
}
- static public bool RegisterFieldBase (FieldBuilder fb, FieldBase f)
+ static public void RegisterFieldBase (FieldBuilder fb, FieldBase f)
{
- if (fieldbuilders_to_fields.Contains (fb))
- return false;
-
fieldbuilders_to_fields.Add (fb, f);
- return true;
}
//
//
static public FieldBase GetField (FieldInfo fb)
{
+#if GMCS_SOURCE
+ fb = GetGenericFieldDefinition (fb);
+#endif
return (FieldBase) fieldbuilders_to_fields [fb];
}
-
- 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);
}
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)
{
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;
/// This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
/// be IA, IB, IC.
/// </remarks>
- public static Type[] ExpandInterfaces (IResolveContext 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))
+ continue;
- if (!new_ifaces.Contains (itype))
- new_ifaces.Add (itype);
+ 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);
new_ifaces.CopyTo (ret, 0);
return ret;
}
-
+
static PtrHashtable iface_cache = new PtrHashtable ();
/// <summary>
/// </summary>
public static Type [] GetInterfaces (Type t)
{
-
Type [] cached = iface_cache [t] as Type [];
if (cached != null)
return cached;
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 = Type.EmptyTypes;
else
base_ifaces = GetInterfaces (t.BaseType);
- Type [] type_ifaces = (Type []) builder_to_ifaces [t];
- if (type_ifaces == null)
+ 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;
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;
/// </remarks>
public static string IndexerPropertyName (Type t)
{
+ t = DropGenericTypeArguments (t);
if (t is TypeBuilder) {
TypeContainer tc = t.IsInterface ? LookupInterface (t) : LookupTypeContainer (t);
return tc == null ? TypeContainer.DefaultIndexerName : tc.IndexerName;
}
return (LocalBuilder) declare_local_method.Invoke (ig, new object [] { t, true });
}
-
+
+ private static bool IsSignatureEqual (Type a, Type b)
+ {
+ ///
+ /// Consider the following example (bug #77674):
+ ///
+ /// public abstract class A
+ /// {
+ /// public abstract T Foo<T> ();
+ /// }
+ ///
+ /// public abstract class B : A
+ /// {
+ /// public override U Foo<T> ()
+ /// { return default (U); }
+ /// }
+ ///
+ /// Here, `T' and `U' are method type parameters from different methods
+ /// (A.Foo and B.Foo), so both `==' and Equals() will fail.
+ ///
+ /// However, since we're determining whether B.Foo() overrides A.Foo(),
+ /// we need to do a signature based comparision and consider them equal.
+
+ if (a == b)
+ return true;
+
+#if GMCS_SOURCE
+ if (a.IsGenericParameter && b.IsGenericParameter &&
+ (a.DeclaringMethod != null) && (b.DeclaringMethod != null)) {
+ return a.GenericParameterPosition == b.GenericParameterPosition;
+ }
+#endif
+
+ if (a.IsArray && b.IsArray) {
+ if (a.GetArrayRank () != b.GetArrayRank ())
+ return false;
+
+ return IsSignatureEqual (a.GetElementType (), b.GetElementType ());
+ }
+
+ if (a.IsByRef && b.IsByRef)
+ return IsSignatureEqual (a.GetElementType (), b.GetElementType ());
+
+#if GMCS_SOURCE
+ if (a.IsGenericType && b.IsGenericType) {
+ if (a.GetGenericTypeDefinition () != b.GetGenericTypeDefinition ())
+ return false;
+
+ Type[] aargs = a.GetGenericArguments ();
+ Type[] bargs = b.GetGenericArguments ();
+
+ if (aargs.Length != bargs.Length)
+ return false;
+
+ for (int i = 0; i < aargs.Length; i++) {
+ if (!IsSignatureEqual (aargs [i], bargs [i]))
+ return false;
+ }
+
+ return true;
+ }
+#endif
+
+ return false;
+ }
+
//
// Returns whether the array of memberinfos contains the given method
//
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;
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)
return target_list;
}
+#region Generics
+ // <remarks>
+ // Tracks the generic parameters.
+ // </remarks>
+ static PtrHashtable builder_to_type_param;
+
+ public static void AddTypeParameter (Type t, TypeParameter tparam)
+ {
+ if (!builder_to_type_param.Contains (t))
+ builder_to_type_param.Add (t, tparam);
+ }
+
+ public static TypeParameter LookupTypeParameter (Type t)
+ {
+ return (TypeParameter) builder_to_type_param [t];
+ }
// This method always return false for non-generic compiler,
// while Type.IsGenericParameter is returned if it is supported.
public static bool IsGenericParameter (Type type)
{
+#if GMCS_SOURCE
+ return type.IsGenericParameter;
+#else
return false;
+#endif
}
public static int GenericParameterPosition (Type type)
{
+#if GMCS_SOURCE
+ return type.GenericParameterPosition;
+#else
throw new InternalErrorException ("should not be called");
+#endif
+ }
+
+ public static bool IsGenericType (Type type)
+ {
+#if GMCS_SOURCE
+ return type.IsGenericType;
+#else
+ return false;
+#endif
+ }
+
+ public static bool IsGenericTypeDefinition (Type type)
+ {
+#if GMCS_SOURCE
+ return type.IsGenericTypeDefinition;
+#else
+ return false;
+#endif
+ }
+
+ public static bool ContainsGenericParameters (Type type)
+ {
+#if GMCS_SOURCE
+ return type.ContainsGenericParameters;
+#else
+ return false;
+#endif
+ }
+
+ public static FieldInfo GetGenericFieldDefinition (FieldInfo fi)
+ {
+#if GMCS_SOURCE
+ if (fi.DeclaringType.IsGenericTypeDefinition ||
+ !fi.DeclaringType.IsGenericType)
+ return fi;
+
+ Type t = fi.DeclaringType.GetGenericTypeDefinition ();
+ BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic |
+ BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
+
+ 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
+ }
+
+ /// <summary>
+ /// Check whether `type' and `parent' are both instantiations of the same
+ /// generic type. Note that we do not check the type parameters here.
+ /// </summary>
+ public static bool IsInstantiationOfSameGenericType (Type type, Type parent)
+ {
+ int tcount = GetNumberOfTypeArguments (type);
+ int pcount = GetNumberOfTypeArguments (parent);
+
+ if (tcount != pcount)
+ return false;
+
+ type = DropGenericTypeArguments (type);
+ parent = DropGenericTypeArguments (parent);
+
+ return type.Equals (parent);
+ }
+
+ /// <summary>
+ /// Whether `mb' is a generic method definition.
+ /// </summary>
+ public static bool IsGenericMethodDefinition (MethodBase mb)
+ {
+#if GMCS_SOURCE
+ if (mb.DeclaringType is TypeBuilder) {
+ IMethodData method = (IMethodData) builder_to_method [mb];
+ if (method == null)
+ return false;
+
+ return method.GenericMethod != null;
+ }
+
+ return mb.IsGenericMethodDefinition;
+#else
+ return false;
+#endif
+ }
+
+ /// <summary>
+ /// Whether `mb' is a generic method.
+ /// </summary>
+ public static bool IsGenericMethod (MethodBase mb)
+ {
+#if GMCS_SOURCE
+ 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
//
// 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;
// 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;
}
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
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 {
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;
}
// 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);
if ((list.Length == 2) && (list [1] is FieldInfo))
return new MemberInfo [] { list [0] };
- // Oooops
- return null;
+ return list;
}
//
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.
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.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.StartsWith ("get_") || name.StartsWith ("set_"))
- return mb.DeclaringType.GetProperty (name.Substring (4)) != null;
+ 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;
}
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
}
private static TypeHandle array_type = null;
private Type type;
+ private string full_name;
private bool is_interface;
private MemberCache member_cache;
private MemberCache base_cache;
private TypeHandle (Type type)
{
this.type = type;
+#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);
}
public string Name {
get {
- return type.FullName;
+ return full_name;
}
}
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