Implemented PipeSecurity. GetAccessControl, SetAccessControl, and ACL-containing...
[mono.git] / mcs / mcs / typespec.cs
index 5940c0ecf9634ec4f06f7bced455bc1f084c7000..8337ce59b8d91eb89391baa3908d53184c1b6659 100644 (file)
@@ -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<T>
+               //
+               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<T> : X<A<int>>, 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<T> 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<TypeSpec> targs = TypeSpec.EmptyTypes;
+
+                       do {
+                               if (type.Arity > 0) {
+                                       if (targs.Count == 0) {
+                                               targs = type.TypeArguments;
+                                       } else {
+                                               var list = targs as List<TypeSpec> ?? new List<TypeSpec> (targs);
+                                               list.AddRange (type.TypeArguments);
+                                               targs = list;
+                                       }
+                               }
+
+                               type = type.declaringType;
+                       } while (type != null);
+
+                       return targs as TypeSpec[] ?? ((List<TypeSpec>) 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<TypeSpec> ();
+
+                                               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<T> : I<T>, I<float>
                                        // 
                                        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 ("<fake$type>");
                public static readonly InternalType Namespace = new InternalType ("<namespace>");
+               public static readonly InternalType ErrorType = new InternalType ("<error>");
 
                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<int> ranks = new List<int> (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)