X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Ftypespec.cs;h=8337ce59b8d91eb89391baa3908d53184c1b6659;hb=490a86b6ecc02fbe31445ad201f01e90678e2c21;hp=5940c0ecf9634ec4f06f7bced455bc1f084c7000;hpb=7699434f00845ba4291c9d8a32cd62304ea0da86;p=mono.git diff --git a/mcs/mcs/typespec.cs b/mcs/mcs/typespec.cs index 5940c0ecf96..8337ce59b8d 100644 --- a/mcs/mcs/typespec.cs +++ b/mcs/mcs/typespec.cs @@ -6,6 +6,7 @@ // Dual licensed under the terms of the MIT X11 or GNU GPL // // Copyright 2010 Novell, Inc +// Copyright 2011 Xamarin, Inc (http://www.xamarin.com) // using System; @@ -22,6 +23,9 @@ using System.Reflection; namespace Mono.CSharp { + // + // Inflated or non-inflated representation of any type. + // public class TypeSpec : MemberSpec { protected MetaType info; @@ -109,11 +113,11 @@ namespace Mono.CSharp var type = this; do { - if (type.IsGeneric) - return false; - if (type.BuiltinType == BuiltinTypeSpec.Type.Attribute) return true; + + if (type.IsGeneric) + return false; type = type.base_type; } while (type != null); @@ -197,6 +201,18 @@ namespace Mono.CSharp } } + // + // Returns true for instances of System.Threading.Tasks.Task + // + public virtual bool IsGenericTask { + get { + return false; + } + set { + state = value ? state | StateFlags.GenericTask : state & ~StateFlags.GenericTask; + } + } + // TODO: Should probably do // IsGenericType -- recursive // HasTypeParameter -- non-recursive @@ -271,6 +287,31 @@ namespace Mono.CSharp } } + // + // Whether a type is unmanaged. This is used by the unsafe code + // + public bool IsUnmanaged { + get { + if (IsPointer) + return ((ElementTypeSpec) this).Element.IsUnmanaged; + + var ds = MemberDefinition as TypeDefinition; + if (ds != null) + return ds.IsUnmanagedType (); + + if (Kind == MemberKind.Void) + return true; + + if (IsNested && DeclaringType.IsGenericOrParentIsGeneric) + return false; + + return IsValueType (this); + } + } + + // + // A cache of all type members (including nested types) + // public MemberCache MemberCache { get { if (cache == null || (state & StateFlags.PendingMemberCacheMembers) != 0) @@ -327,6 +368,58 @@ namespace Mono.CSharp return false; } + // + // Special version used during type definition + // + public bool AddInterfaceDefined (TypeSpec iface) + { + if (!AddInterface (iface)) + return false; + + // + // We can get into a situation where a type is inflated before + // its interfaces are resoved. Consider this situation + // + // class A : X>, IFoo {} + // + // When resolving base class of X`1 we inflate context type A`1 + // All this happens before we even hit IFoo resolve. Without + // additional expansion any inside usage of A would miss IFoo + // interface because it comes from early inflated TypeSpec + // + if (inflated_instances != null) { + foreach (var inflated in inflated_instances) { + inflated.Value.AddInterface (iface); + } + } + + return true; + } + + // + // Returns all type arguments, usefull for nested types + // + public static TypeSpec[] GetAllTypeArguments (TypeSpec type) + { + IList targs = TypeSpec.EmptyTypes; + + do { + if (type.Arity > 0) { + if (targs.Count == 0) { + targs = type.TypeArguments; + } else { + var list = targs as List ?? new List (targs); + list.AddRange (type.TypeArguments); + targs = list; + } + } + + type = type.declaringType; + } while (type != null); + + return targs as TypeSpec[] ?? ((List) targs).ToArray (); + } + public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa) { if (Kind != MemberKind.Class) @@ -348,6 +441,9 @@ namespace Mono.CSharp return aua; } + // + // Return metadata information used during emit to describe the type + // public virtual MetaType GetMetaInfo () { return info; @@ -358,6 +454,9 @@ namespace Mono.CSharp return this; } + // + // Text representation of type used by documentation writer + // public override string GetSignatureForDocumentation () { StringBuilder sb = new StringBuilder (); @@ -452,12 +551,13 @@ namespace Mono.CSharp { var t = this; do { - if (t.Interfaces != null) { - foreach (TypeSpec i in t.Interfaces) { - if (i == iface || TypeSpecComparer.IsEqual (i, iface)) + var ifaces = t.Interfaces; + if (ifaces != null) { + for (int i = 0; i < ifaces.Count; ++i) { + if (TypeSpecComparer.IsEqual (ifaces[i], iface)) return true; - if (variantly && TypeSpecComparer.Variant.IsEqual (i, iface)) + if (variantly && TypeSpecComparer.Variant.IsEqual (ifaces[i], iface)) return true; } } @@ -516,6 +616,38 @@ namespace Mono.CSharp return false; } + public static bool IsReferenceType (TypeSpec t) + { + switch (t.Kind) { + case MemberKind.TypeParameter: + return ((TypeParameterSpec) t).IsReferenceType; + case MemberKind.Struct: + case MemberKind.Enum: + case MemberKind.Void: + return false; + case MemberKind.InternalCompilerType: + // + // Null is considered to be a reference type + // + return t == InternalType.NullLiteral || t.BuiltinType == BuiltinTypeSpec.Type.Dynamic; + default: + return true; + } + } + + public static bool IsValueType (TypeSpec t) + { + switch (t.Kind) { + case MemberKind.TypeParameter: + return ((TypeParameterSpec) t).IsValueType; + case MemberKind.Struct: + case MemberKind.Enum: + return true; + default: + return false; + } + } + public override MemberSpec InflateMember (TypeParameterInflator inflator) { var targs = IsGeneric ? MemberDefinition.TypeParameters : TypeSpec.EmptyTypes; @@ -531,6 +663,9 @@ namespace Mono.CSharp return new InflatedTypeSpec (inflator.Context, this, inflator.TypeInstance, targs); } + // + // Inflates current type using specific type arguments + // public InflatedTypeSpec MakeGenericType (IModuleContext context, TypeSpec[] targs) { if (targs.Length == 0 && !IsNested) @@ -601,6 +736,18 @@ namespace Mono.CSharp } } + if (MemberDefinition.TypeParametersCount > 0) { + foreach (var tp in MemberDefinition.TypeParameters) { + var tp_missing = tp.GetMissingDependencies (); + if (tp_missing != null) { + if (missing == null) + missing = new List (); + + missing.AddRange (tp_missing); + } + } + } + if (missing != null || BaseType == null) return missing; @@ -621,6 +768,10 @@ namespace Mono.CSharp } } + // + // Special version used for types which must exist in corlib or + // the compiler cannot work + // public sealed class BuiltinTypeSpec : TypeSpec { public enum Type @@ -664,8 +815,6 @@ namespace Mono.CSharp Exception, Attribute, Other, - - Null, } readonly Type type; @@ -804,6 +953,9 @@ namespace Mono.CSharp } } + // + // Various type comparers used by compiler + // static class TypeSpecComparer { // @@ -943,8 +1095,7 @@ namespace Mono.CSharp if (!IsEqual (a.Types[i], b.Types[i])) return false; - const Parameter.Modifier ref_out = Parameter.Modifier.REF | Parameter.Modifier.OUT; - if ((a.FixedParameters[i].ModFlags & ref_out) != (b.FixedParameters[i].ModFlags & ref_out)) + if ((a.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask) != (b.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask)) return false; } @@ -975,10 +1126,11 @@ namespace Mono.CSharp } for (int i = 0; i < targs_definition.Length; ++i) { + if (TypeSpecComparer.IsEqual (t1_targs[i], t2_targs[i])) + continue; + Variance v = targs_definition[i].Variance; if (v == Variance.None) { - if (t1_targs[i] == t2_targs[i]) - continue; return false; } @@ -1005,8 +1157,17 @@ namespace Mono.CSharp // public static bool IsEqual (TypeSpec a, TypeSpec b) { - if (a.MemberDefinition != b.MemberDefinition) + if (a.MemberDefinition != b.MemberDefinition) { + var base_ifaces = a.Interfaces; + if (base_ifaces != null) { + foreach (var base_iface in base_ifaces) { + if (base_iface.Arity > 0 && IsEqual (base_iface, b)) + return true; + } + } + return false; + } var ta = a.TypeArguments; var tb = b.TypeArguments; @@ -1054,7 +1215,7 @@ namespace Mono.CSharp // class X : I, I // if (b.IsGenericParameter) - return a.DeclaringType == b.DeclaringType; + return a != b && a.DeclaringType == b.DeclaringType; // // We're now comparing a type parameter with a @@ -1141,7 +1302,7 @@ namespace Mono.CSharp if (b_a == null) return false; - return IsEqual (a_a.Element, b_a.Element) && a_a.Rank == b_a.Rank; + return a_a.Rank == b_a.Rank && IsEqual (a_a.Element, b_a.Element); } if (!a.IsGeneric || !b.IsGeneric) { @@ -1175,6 +1336,7 @@ namespace Mono.CSharp { IAssemblyDefinition DeclaringAssembly { get; } string Namespace { get; } + bool IsPartial { get; } int TypeParametersCount { get; } TypeParameterSpec[] TypeParameters { get; } @@ -1193,15 +1355,10 @@ namespace Mono.CSharp public static readonly InternalType NullLiteral = new InternalType ("null"); public static readonly InternalType FakeInternalType = new InternalType (""); public static readonly InternalType Namespace = new InternalType (""); + public static readonly InternalType ErrorType = new InternalType (""); readonly string name; - InternalType (string name, MemberCache cache) - : this (name) - { - this.cache = cache; - } - InternalType (string name) : base (MemberKind.InternalCompilerType, null, null, null, Modifiers.PUBLIC) { @@ -1210,7 +1367,7 @@ namespace Mono.CSharp cache = MemberCache.Empty; // Make all internal types CLS-compliant, non-obsolete - state = (state & ~(StateFlags.CLSCompliant_Undetected | StateFlags.Obsolete_Undetected)) | StateFlags.CLSCompliant; + state = (state & ~(StateFlags.CLSCompliant_Undetected | StateFlags.Obsolete_Undetected | StateFlags.MissingDependency_Undetected)) | StateFlags.CLSCompliant; } #region Properties @@ -1233,6 +1390,12 @@ namespace Mono.CSharp } } + bool ITypeDefinition.IsPartial { + get { + return false; + } + } + public override string Name { get { return name; @@ -1318,6 +1481,9 @@ namespace Mono.CSharp #endregion } + // + // Common base class for composite types + // public abstract class ElementTypeSpec : TypeSpec, ITypeDefinition { protected ElementTypeSpec (MemberKind kind, TypeSpec element, MetaType info) @@ -1325,11 +1491,8 @@ namespace Mono.CSharp { this.Element = element; - // Some flags can be copied directly from the element - const StateFlags shared_flags = StateFlags.CLSCompliant | StateFlags.CLSCompliant_Undetected - | StateFlags.Obsolete | StateFlags.Obsolete_Undetected | StateFlags.HasDynamicElement; - state &= ~shared_flags; - state |= (element.state & shared_flags); + state &= ~SharedStateFlags; + state |= (element.state & SharedStateFlags); if (element.BuiltinType == BuiltinTypeSpec.Type.Dynamic) state |= StateFlags.HasDynamicElement; @@ -1345,6 +1508,12 @@ namespace Mono.CSharp public TypeSpec Element { get; private set; } + bool ITypeDefinition.IsPartial { + get { + return false; + } + } + public override string Name { get { throw new NotSupportedException (); @@ -1600,29 +1769,27 @@ namespace Mono.CSharp public override string GetSignatureForDocumentation () { - var e = Element; - List ranks = new List (2); - ranks.Add (rank); + StringBuilder sb = new StringBuilder (); + GetElementSignatureForDocumentation (sb); + return sb.ToString (); + } - while (e is ArrayContainer) { - var ac = (ArrayContainer) e; - ranks.Add (ac.rank); - e = ac.Element; - } + void GetElementSignatureForDocumentation (StringBuilder sb) + { + var ac = Element as ArrayContainer; + if (ac == null) + sb.Append (Element.GetSignatureForDocumentation ()); + else + ac.GetElementSignatureForDocumentation (sb); - StringBuilder sb = new StringBuilder (e.GetSignatureForDocumentation ()); - for (int r = 0; r < ranks.Count; ++r) { - sb.Append ("["); - for (int i = 1; i < ranks[r]; i++) { - if (i == 1) - sb.Append ("0:"); + sb.Append ("["); + for (int i = 1; i < rank; i++) { + if (i == 1) + sb.Append ("0:"); - sb.Append (",0:"); - } - sb.Append ("]"); + sb.Append (",0:"); } - - return sb.ToString (); + sb.Append ("]"); } public static ArrayContainer MakeType (ModuleContainer module, TypeSpec element)