//
// typemanager.cs: C# type manager
//
// Author: Miguel de Icaza (miguel@gnu.org)
// Ravi Pratap (ravi@ximian.com)
// Marek Safar (marek.safar@seznam.cz)
//
// Dual licensed under the terms of the MIT X11 or GNU GPL
//
// Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
// Copyright 2003-2008 Novell, Inc.
//
using System;
using System.Globalization;
using System.Collections.Generic;
using System.Text;
namespace Mono.CSharp
{
//
// All compiler build-in types (they have to exist otherwise the compile will not work)
//
public class BuildinTypes
{
public readonly BuildinTypeSpec Object;
public readonly BuildinTypeSpec ValueType;
public readonly BuildinTypeSpec Attribute;
public readonly BuildinTypeSpec Int;
public readonly BuildinTypeSpec UInt;
public readonly BuildinTypeSpec Long;
public readonly BuildinTypeSpec ULong;
public readonly BuildinTypeSpec Float;
public readonly BuildinTypeSpec Double;
public readonly BuildinTypeSpec Char;
public readonly BuildinTypeSpec Short;
public readonly BuildinTypeSpec Decimal;
public readonly BuildinTypeSpec Bool;
public readonly BuildinTypeSpec SByte;
public readonly BuildinTypeSpec Byte;
public readonly BuildinTypeSpec UShort;
public readonly BuildinTypeSpec String;
public readonly BuildinTypeSpec Enum;
public readonly BuildinTypeSpec Delegate;
public readonly BuildinTypeSpec MulticastDelegate;
public readonly BuildinTypeSpec Void;
public readonly BuildinTypeSpec Array;
public readonly BuildinTypeSpec Type;
public readonly BuildinTypeSpec IEnumerator;
public readonly BuildinTypeSpec IEnumerable;
public readonly BuildinTypeSpec IDisposable;
public readonly BuildinTypeSpec IntPtr;
public readonly BuildinTypeSpec UIntPtr;
public readonly BuildinTypeSpec RuntimeFieldHandle;
public readonly BuildinTypeSpec RuntimeTypeHandle;
public readonly BuildinTypeSpec Exception;
//
// These are internal buil-in types which depend on other
// build-in type (mostly object)
//
public readonly BuildinTypeSpec Dynamic;
// Predefined operators tables
public readonly Binary.PredefinedOperator[] OperatorsBinaryStandard;
public readonly Binary.PredefinedOperator[] OperatorsBinaryEquality;
public readonly Binary.PredefinedOperator[] OperatorsBinaryUnsafe;
public readonly TypeSpec[][] OperatorsUnary;
public readonly TypeSpec[] OperatorsUnaryMutator;
public readonly TypeSpec[] BinaryPromotionsTypes;
public readonly TypeSpec[] SwitchUserTypes;
readonly BuildinTypeSpec[] types;
public BuildinTypes ()
{
Object = new BuildinTypeSpec (MemberKind.Class, "System", "Object", BuildinTypeSpec.Type.Object);
ValueType = new BuildinTypeSpec (MemberKind.Class, "System", "ValueType", BuildinTypeSpec.Type.ValueType);
Attribute = new BuildinTypeSpec (MemberKind.Class, "System", "Attribute", BuildinTypeSpec.Type.Attribute);
Int = new BuildinTypeSpec (MemberKind.Struct, "System", "Int32", BuildinTypeSpec.Type.Int);
Long = new BuildinTypeSpec (MemberKind.Struct, "System", "Int64", BuildinTypeSpec.Type.Long);
UInt = new BuildinTypeSpec (MemberKind.Struct, "System", "UInt32", BuildinTypeSpec.Type.UInt);
ULong = new BuildinTypeSpec (MemberKind.Struct, "System", "UInt64", BuildinTypeSpec.Type.ULong);
Byte = new BuildinTypeSpec (MemberKind.Struct, "System", "Byte", BuildinTypeSpec.Type.Byte);
SByte = new BuildinTypeSpec (MemberKind.Struct, "System", "SByte", BuildinTypeSpec.Type.SByte);
Short = new BuildinTypeSpec (MemberKind.Struct, "System", "Int16", BuildinTypeSpec.Type.Short);
UShort = new BuildinTypeSpec (MemberKind.Struct, "System", "UInt16", BuildinTypeSpec.Type.UShort);
IEnumerator = new BuildinTypeSpec (MemberKind.Interface, "System.Collections", "IEnumerator", BuildinTypeSpec.Type.IEnumerator);
IEnumerable = new BuildinTypeSpec (MemberKind.Interface, "System.Collections", "IEnumerable", BuildinTypeSpec.Type.IEnumerable);
IDisposable = new BuildinTypeSpec (MemberKind.Interface, "System", "IDisposable", BuildinTypeSpec.Type.IDisposable);
Char = new BuildinTypeSpec (MemberKind.Struct, "System", "Char", BuildinTypeSpec.Type.Char);
String = new BuildinTypeSpec (MemberKind.Class, "System", "String", BuildinTypeSpec.Type.String);
Float = new BuildinTypeSpec (MemberKind.Struct, "System", "Single", BuildinTypeSpec.Type.Float);
Double = new BuildinTypeSpec (MemberKind.Struct, "System", "Double", BuildinTypeSpec.Type.Double);
Decimal = new BuildinTypeSpec (MemberKind.Struct, "System", "Decimal", BuildinTypeSpec.Type.Decimal);
Bool = new BuildinTypeSpec (MemberKind.Struct, "System", "Boolean", BuildinTypeSpec.Type.Bool);
IntPtr = new BuildinTypeSpec (MemberKind.Struct, "System", "IntPtr", BuildinTypeSpec.Type.IntPtr);
UIntPtr = new BuildinTypeSpec (MemberKind.Struct, "System", "UIntPtr", BuildinTypeSpec.Type.UIntPtr);
MulticastDelegate = new BuildinTypeSpec (MemberKind.Class, "System", "MulticastDelegate", BuildinTypeSpec.Type.MulticastDelegate);
Delegate = new BuildinTypeSpec (MemberKind.Class, "System", "Delegate", BuildinTypeSpec.Type.Delegate);
Enum = new BuildinTypeSpec (MemberKind.Class, "System", "Enum", BuildinTypeSpec.Type.Enum);
Array = new BuildinTypeSpec (MemberKind.Class, "System", "Array", BuildinTypeSpec.Type.Array);
Void = new BuildinTypeSpec (MemberKind.Void, "System", "Void", BuildinTypeSpec.Type.Other);
Type = new BuildinTypeSpec (MemberKind.Class, "System", "Type", BuildinTypeSpec.Type.Type);
Exception = new BuildinTypeSpec (MemberKind.Class, "System", "Exception", BuildinTypeSpec.Type.Exception);
RuntimeFieldHandle = new BuildinTypeSpec (MemberKind.Struct, "System", "RuntimeFieldHandle", BuildinTypeSpec.Type.Other);
RuntimeTypeHandle = new BuildinTypeSpec (MemberKind.Struct, "System", "RuntimeTypeHandle", BuildinTypeSpec.Type.Other);
// TODO: Maybe I should promote it to different kind for faster compares
Dynamic = new BuildinTypeSpec ("dynamic", BuildinTypeSpec.Type.Dynamic);
OperatorsBinaryStandard = Binary.CreateStandardOperatorsTable (this);
OperatorsBinaryEquality = Binary.CreateEqualityOperatorsTable (this);
OperatorsBinaryUnsafe = Binary.CreatePointerOperatorsTable (this);
OperatorsUnary = Unary.CreatePredefinedOperatorsTable (this);
OperatorsUnaryMutator = UnaryMutator.CreatePredefinedOperatorsTable (this);
BinaryPromotionsTypes = ConstantFold.CreateBinaryPromotionsTypes (this);
SwitchUserTypes = Switch.CreateSwitchUserTypes (this);
types = new BuildinTypeSpec[] {
Object, ValueType, Attribute,
Int, UInt, Long, ULong, Float, Double, Char, Short, Decimal, Bool, SByte, Byte, UShort, String,
Enum, Delegate, MulticastDelegate, Void, Array, Type, IEnumerator, IEnumerable, IDisposable,
IntPtr, UIntPtr, RuntimeFieldHandle, RuntimeTypeHandle, Exception };
// Deal with obsolete static types
// TODO: remove
TypeManager.object_type = Object;
TypeManager.value_type = ValueType;
}
public BuildinTypeSpec[] AllTypes {
get {
return types;
}
}
public bool CheckDefinitions (ModuleContainer module)
{
var ctx = module.Compiler;
foreach (var p in types) {
var found = PredefinedType.Resolve (module, p.Kind, p.Namespace, p.Name, p.Arity, Location.Null);
if (found == null || found == p)
continue;
var tc = found.MemberDefinition as TypeContainer;
if (tc != null) {
var ns = module.GlobalRootNamespace.GetNamespace (p.Namespace, false);
ns.ReplaceTypeWithPredefined (found, p);
tc.SetPredefinedSpec (p);
p.SetDefinition (found);
}
}
if (ctx.Report.Errors != 0)
return false;
// Set internal build-in types
Dynamic.SetDefinition (Object);
return true;
}
}
//
// Compiler predefined types. Usually used for compiler generated
// code or for comparison against well known framework type. They
// may not exist as they are optional
//
class PredefinedTypes
{
public readonly PredefinedType ArgIterator;
public readonly PredefinedType MarshalByRefObject;
public readonly PredefinedType RuntimeHelpers;
public readonly PredefinedType IAsyncResult;
public readonly PredefinedType AsyncCallback;
public readonly PredefinedType RuntimeArgumentHandle;
public readonly PredefinedType CharSet;
public readonly PredefinedType IsVolatile;
public readonly PredefinedType IEnumeratorGeneric;
public readonly PredefinedType IListGeneric;
public readonly PredefinedType ICollectionGeneric;
public readonly PredefinedType IEnumerableGeneric;
public readonly PredefinedType Nullable;
public readonly PredefinedType Activator;
public readonly PredefinedType Interlocked;
public readonly PredefinedType Monitor;
public readonly PredefinedType NotSupportedException;
public readonly PredefinedType RuntimeFieldHandle;
public readonly PredefinedType RuntimeMethodHandle;
public readonly PredefinedType SecurityAction;
//
// C# 3.0
//
public readonly PredefinedType Expression;
public readonly PredefinedType ExpressionGeneric;
public readonly PredefinedType ParameterExpression;
public readonly PredefinedType FieldInfo;
public readonly PredefinedType MethodBase;
public readonly PredefinedType MethodInfo;
public readonly PredefinedType ConstructorInfo;
//
// C# 4.0
//
public readonly PredefinedType Binder;
public readonly PredefinedType CallSite;
public readonly PredefinedType CallSiteGeneric;
public readonly PredefinedType BinderFlags;
public PredefinedTypes (ModuleContainer module)
{
var TypedReference = new PredefinedType (module, MemberKind.Struct, "System", "TypedReference");
ArgIterator = new PredefinedType (module, MemberKind.Struct, "System", "ArgIterator");
MarshalByRefObject = new PredefinedType (module, MemberKind.Class, "System", "MarshalByRefObject");
RuntimeHelpers = new PredefinedType (module, MemberKind.Class, "System.Runtime.CompilerServices", "RuntimeHelpers");
IAsyncResult = new PredefinedType (module, MemberKind.Interface, "System", "IAsyncResult");
AsyncCallback = new PredefinedType (module, MemberKind.Delegate, "System", "AsyncCallback");
RuntimeArgumentHandle = new PredefinedType (module, MemberKind.Struct, "System", "RuntimeArgumentHandle");
CharSet = new PredefinedType (module, MemberKind.Enum, "System.Runtime.InteropServices", "CharSet");
IsVolatile = new PredefinedType (module, MemberKind.Class, "System.Runtime.CompilerServices", "IsVolatile");
IEnumeratorGeneric = new PredefinedType (module, MemberKind.Interface, "System.Collections.Generic", "IEnumerator", 1);
IListGeneric = new PredefinedType (module, MemberKind.Interface, "System.Collections.Generic", "IList", 1);
ICollectionGeneric = new PredefinedType (module, MemberKind.Interface, "System.Collections.Generic", "ICollection", 1);
IEnumerableGeneric = new PredefinedType (module, MemberKind.Interface, "System.Collections.Generic", "IEnumerable", 1);
Nullable = new PredefinedType (module, MemberKind.Struct, "System", "Nullable", 1);
Activator = new PredefinedType (module, MemberKind.Class, "System", "Activator");
Interlocked = new PredefinedType (module, MemberKind.Class, "System.Threading", "Interlocked");
Monitor = new PredefinedType (module, MemberKind.Class, "System.Threading", "Monitor");
NotSupportedException = new PredefinedType (module, MemberKind.Class, "System", "NotSupportedException");
RuntimeFieldHandle = new PredefinedType (module, MemberKind.Struct, "System", "RuntimeFieldHandle");
RuntimeMethodHandle = new PredefinedType (module, MemberKind.Struct, "System", "RuntimeMethodHandle");
SecurityAction = new PredefinedType (module, MemberKind.Enum, "System.Security.Permissions", "SecurityAction");
Expression = new PredefinedType (module, MemberKind.Class, "System.Linq.Expressions", "Expression");
ExpressionGeneric = new PredefinedType (module, MemberKind.Class, "System.Linq.Expressions", "Expression", 1);
ParameterExpression = new PredefinedType (module, MemberKind.Class, "System.Linq.Expressions", "ParameterExpression");
FieldInfo = new PredefinedType (module, MemberKind.Class, "System.Reflection", "FieldInfo");
MethodBase = new PredefinedType (module, MemberKind.Class, "System.Reflection", "MethodBase");
MethodInfo = new PredefinedType (module, MemberKind.Class, "System.Reflection", "MethodInfo");
ConstructorInfo = new PredefinedType (module, MemberKind.Class, "System.Reflection", "ConstructorInfo");
CallSite = new PredefinedType (module, MemberKind.Class, "System.Runtime.CompilerServices", "CallSite");
CallSiteGeneric = new PredefinedType (module, MemberKind.Class, "System.Runtime.CompilerServices", "CallSite", 1);
Binder = new PredefinedType (module, MemberKind.Class, "Microsoft.CSharp.RuntimeBinder", "Binder");
BinderFlags = new PredefinedType (module, MemberKind.Enum, "Microsoft.CSharp.RuntimeBinder", "CSharpBinderFlags");
//
// Define types which are used for comparison. It does not matter
// if they don't exist as no error report is needed
//
if (TypedReference.Define ())
TypedReference.TypeSpec.IsSpecialRuntimeType = true;
if (ArgIterator.Define ())
ArgIterator.TypeSpec.IsSpecialRuntimeType = true;
MarshalByRefObject.Define ();
CharSet.Define ();
IEnumerableGeneric.Define ();
IListGeneric.Define ();
ICollectionGeneric.Define ();
IEnumerableGeneric.Define ();
IEnumeratorGeneric.Define ();
Nullable.Define ();
ExpressionGeneric.Define ();
// Deal with obsolete static types
// TODO: remove
TypeManager.generic_ilist_type = IListGeneric.TypeSpec;
TypeManager.generic_icollection_type = ICollectionGeneric.TypeSpec;
TypeManager.generic_ienumerator_type = IEnumeratorGeneric.TypeSpec;
TypeManager.generic_ienumerable_type = IEnumerableGeneric.TypeSpec;
TypeManager.generic_nullable_type = Nullable.TypeSpec;
TypeManager.expression_type = ExpressionGeneric.TypeSpec;
}
}
public class PredefinedType
{
string name;
string ns;
int arity;
MemberKind kind;
protected readonly ModuleContainer module;
protected TypeSpec type;
public PredefinedType (ModuleContainer module, MemberKind kind, string ns, string name, int arity)
: this (module, kind, ns, name)
{
this.arity = arity;
}
public PredefinedType (ModuleContainer module, MemberKind kind, string ns, string name)
{
this.module = module;
this.kind = kind;
this.name = name;
this.ns = ns;
}
#region Properties
public int Arity {
get {
return arity;
}
}
public bool IsDefined {
get {
return type != null;
}
}
public string Name {
get {
return name;
}
}
public string Namespace {
get {
return ns;
}
}
public TypeSpec TypeSpec {
get {
return type;
}
}
#endregion
public bool Define ()
{
if (type != null)
return true;
Namespace type_ns = module.GlobalRootNamespace.GetNamespace (ns, true);
var te = type_ns.LookupType (module, name, arity, true, Location.Null);
if (te == null || te.Type.Kind != kind) {
return false;
}
type = te.Type;
return true;
}
public FieldSpec GetField (string name, TypeSpec memberType, Location loc)
{
return TypeManager.GetPredefinedField (type, name, loc, memberType);
}
public string GetSignatureForError ()
{
return ns + "." + name;
}
public static TypeSpec Resolve (ModuleContainer module, MemberKind kind, string ns, string name, int arity, Location loc)
{
Namespace type_ns = module.GlobalRootNamespace.GetNamespace (ns, true);
var te = type_ns.LookupType (module, name, arity, false, Location.Null);
if (te == null) {
module.Compiler.Report.Error (518, loc, "The predefined type `{0}.{1}' is not defined or imported", ns, name);
return null;
}
var type = te.Type;
if (type.Kind != kind) {
if (type.Kind == MemberKind.Struct && kind == MemberKind.Void && type.MemberDefinition is TypeContainer) {
// Void is declared as struct but we keep it internally as
// special kind, the swap will be done by caller
} else {
module.Compiler.Report.Error (520, loc, "The predefined type `{0}.{1}' is not declared correctly", ns, name);
return null;
}
}
return type;
}
public TypeSpec Resolve (Location loc)
{
if (type == null)
type = Resolve (module, kind, ns, name, arity, loc);
return type;
}
}
partial class TypeManager {
//
// A list of core types that the compiler requires or uses
//
static public BuildinTypeSpec object_type;
static public BuildinTypeSpec value_type;
static public TypeSpec generic_ilist_type;
static public TypeSpec generic_icollection_type;
static public TypeSpec generic_ienumerator_type;
static public TypeSpec generic_ienumerable_type;
static public TypeSpec generic_nullable_type;
static internal TypeSpec expression_type;
//
// These methods are called by code generated by the compiler
//
static public FieldSpec string_empty;
static public MethodSpec system_type_get_type_from_handle;
static public MethodSpec bool_movenext_void;
static public MethodSpec void_dispose_void;
static public MethodSpec void_monitor_enter_object;
static public MethodSpec void_monitor_exit_object;
static public MethodSpec void_initializearray_array_fieldhandle;
static public MethodSpec delegate_combine_delegate_delegate;
static public MethodSpec delegate_remove_delegate_delegate;
static public PropertySpec int_get_offset_to_string_data;
static public MethodSpec int_interlocked_compare_exchange;
public static MethodSpec gen_interlocked_compare_exchange;
static public PropertySpec ienumerator_getcurrent;
public static MethodSpec methodbase_get_type_from_handle;
public static MethodSpec methodbase_get_type_from_handle_generic;
public static MethodSpec fieldinfo_get_field_from_handle;
public static MethodSpec fieldinfo_get_field_from_handle_generic;
public static MethodSpec activator_create_instance;
//
// The constructors.
//
static public MethodSpec void_decimal_ctor_five_args;
static public MethodSpec void_decimal_ctor_int_arg;
public static MethodSpec void_decimal_ctor_long_arg;
static TypeManager ()
{
Reset ();
}
static public void Reset ()
{
// object_type = null;
// TODO: I am really bored by all this static stuff
system_type_get_type_from_handle =
bool_movenext_void =
void_dispose_void =
void_monitor_enter_object =
void_monitor_exit_object =
void_initializearray_array_fieldhandle =
int_interlocked_compare_exchange =
gen_interlocked_compare_exchange =
methodbase_get_type_from_handle =
methodbase_get_type_from_handle_generic =
fieldinfo_get_field_from_handle =
fieldinfo_get_field_from_handle_generic =
activator_create_instance =
delegate_combine_delegate_delegate =
delegate_remove_delegate_delegate = null;
int_get_offset_to_string_data =
ienumerator_getcurrent = null;
void_decimal_ctor_five_args =
void_decimal_ctor_int_arg =
void_decimal_ctor_long_arg = null;
string_empty = null;
generic_ilist_type = generic_icollection_type = generic_ienumerator_type =
generic_ienumerable_type = generic_nullable_type = expression_type = null;
}
///
/// Returns the C# name of a type if possible, or the full type name otherwise
///
static public string CSharpName (TypeSpec t)
{
return t.GetSignatureForError ();
}
static public string CSharpName (IList types)
{
if (types.Count == 0)
return string.Empty;
StringBuilder sb = new StringBuilder ();
for (int i = 0; i < types.Count; ++i) {
if (i > 0)
sb.Append (",");
sb.Append (CSharpName (types [i]));
}
return sb.ToString ();
}
static public string GetFullNameSignature (MemberSpec mi)
{
return mi.GetSignatureForError ();
}
static public string CSharpSignature (MemberSpec mb)
{
return mb.GetSignatureForError ();
}
static MemberSpec GetPredefinedMember (TypeSpec t, MemberFilter filter, bool optional, Location loc)
{
var member = MemberCache.FindMember (t, filter, BindingRestriction.DeclaredOnly);
if (member != null && member.IsAccessible (InternalType.FakeInternalType))
return member;
if (optional)
return member;
string method_args = null;
if (filter.Parameters != null)
method_args = filter.Parameters.GetSignatureForError ();
RootContext.ToplevelTypes.Compiler.Report.Error (656, loc, "The compiler required member `{0}.{1}{2}' could not be found or is inaccessible",
TypeManager.CSharpName (t), filter.Name, method_args);
return null;
}
//
// Returns the ConstructorInfo for "args"
//
public static MethodSpec GetPredefinedConstructor (TypeSpec t, Location loc, params TypeSpec [] args)
{
var pc = ParametersCompiled.CreateFullyResolved (args);
return GetPredefinedMember (t, MemberFilter.Constructor (pc), false, loc) as MethodSpec;
}
//
// Returns the method specification for a method named `name' defined
// in type `t' which takes arguments of types `args'
//
public static MethodSpec GetPredefinedMethod (TypeSpec t, string name, Location loc, params TypeSpec [] args)
{
var pc = ParametersCompiled.CreateFullyResolved (args);
return GetPredefinedMethod (t, MemberFilter.Method (name, 0, pc, null), false, loc);
}
public static MethodSpec GetPredefinedMethod (TypeSpec t, MemberFilter filter, Location loc)
{
return GetPredefinedMethod (t, filter, false, loc);
}
public static MethodSpec GetPredefinedMethod (TypeSpec t, MemberFilter filter, bool optional, Location loc)
{
return GetPredefinedMember (t, filter, optional, loc) as MethodSpec;
}
public static FieldSpec GetPredefinedField (TypeSpec t, string name, Location loc, TypeSpec type)
{
return GetPredefinedMember (t, MemberFilter.Field (name, type), false, loc) as FieldSpec;
}
public static PropertySpec GetPredefinedProperty (TypeSpec t, string name, Location loc, TypeSpec type)
{
return GetPredefinedMember (t, MemberFilter.Property (name, type), false, loc) as PropertySpec;
}
// Obsolete
public static bool IsDelegateType (TypeSpec t)
{
return t.IsDelegate;
}
// Obsolete
public static bool IsEnumType (TypeSpec t)
{
return t.IsEnum;
}
//
// Whether a type is unmanaged. This is used by the unsafe code (25.2)
//
public static bool IsUnmanagedType (TypeSpec t)
{
var ds = t.MemberDefinition as DeclSpace;
if (ds != null)
return ds.IsUnmanagedType ();
if (t.Kind == MemberKind.Void)
return true;
// Someone did the work of checking if the ElementType of t is unmanaged. Let's not repeat it.
if (t.IsPointer)
return IsUnmanagedType (GetElementType (t));
if (!IsValueType (t))
return false;
if (t.IsNested && t.DeclaringType.IsGenericOrParentIsGeneric)
return false;
return true;
}
//
// Null is considered to be a reference type
//
public static bool IsReferenceType (TypeSpec t)
{
if (t.IsGenericParameter)
return ((TypeParameterSpec) t).IsReferenceType;
return !t.IsStruct && !IsEnumType (t);
}
public static bool IsValueType (TypeSpec t)
{
if (t.IsGenericParameter)
return ((TypeParameterSpec) t).IsValueType;
return t.IsStruct || IsEnumType (t);
}
public static bool IsStruct (TypeSpec t)
{
return t.IsStruct;
}
public static bool IsFamilyAccessible (TypeSpec type, TypeSpec parent)
{
// TypeParameter tparam = LookupTypeParameter (type);
// TypeParameter pparam = LookupTypeParameter (parent);
if (type.Kind == MemberKind.TypeParameter && parent.Kind == MemberKind.TypeParameter) { // (tparam != null) && (pparam != null)) {
if (type == parent)
return true;
throw new NotImplementedException ("net");
// return tparam.IsSubclassOf (parent);
}
do {
if (IsInstantiationOfSameGenericType (type, parent))
return true;
type = type.BaseType;
} while (type != null);
return false;
}
//
// Checks whether `type' is a subclass or nested child of `base_type'.
//
public static bool IsNestedFamilyAccessible (TypeSpec type, TypeSpec base_type)
{
do {
if (IsFamilyAccessible (type, base_type))
return true;
// Handle nested types.
type = type.DeclaringType;
} while (type != null);
return false;
}
//
// Checks whether `type' is a nested child of `parent'.
//
public static bool IsNestedChildOf (TypeSpec type, ITypeDefinition parent)
{
if (type == null)
return false;
if (type.MemberDefinition == parent)
return false;
type = type.DeclaringType;
while (type != null) {
if (type.MemberDefinition == parent)
return true;
type = type.DeclaringType;
}
return false;
}
public static TypeSpec GetElementType (TypeSpec t)
{
return ((ElementTypeSpec)t).Element;
}
///
/// This method is not implemented by MS runtime for dynamic types
///
public static bool HasElementType (TypeSpec t)
{
return t is ElementTypeSpec;
}
///
/// Utility function that can be used to probe whether a type
/// is managed or not.
///
public static bool VerifyUnmanaged (ModuleContainer rc, TypeSpec t, Location loc)
{
while (t.IsPointer)
t = GetElementType (t);
if (IsUnmanagedType (t))
return true;
rc.Compiler.Report.SymbolRelatedToPreviousError (t);
rc.Compiler.Report.Error (208, loc,
"Cannot take the address of, get the size of, or declare a pointer to a managed type `{0}'",
CSharpName (t));
return false;
}
#region Generics
// This method always return false for non-generic compiler,
// while Type.IsGenericParameter is returned if it is supported.
public static bool IsGenericParameter (TypeSpec type)
{
return type.IsGenericParameter;
}
public static bool IsGenericType (TypeSpec type)
{
return type.IsGeneric;
}
public static TypeSpec[] GetTypeArguments (TypeSpec t)
{
// TODO: return empty array !!
return t.TypeArguments;
}
///
/// 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 (TypeSpec type, TypeSpec parent)
{
return type == parent || type.MemberDefinition == parent.MemberDefinition;
}
public static bool IsNullableType (TypeSpec t)
{
return generic_nullable_type == t.GetDefinition ();
}
#endregion
}
}