Merge pull request #409 from Alkarex/patch-1
[mono.git] / mcs / mcs / typespec.cs
index d25de6614b542229baafd2d26c9cc0fab0ca3fbe..d1e1b709d1d17027443723e76bd265ae80133350 100644 (file)
@@ -23,6 +23,9 @@ using System.Reflection;
 
 namespace Mono.CSharp
 {
+       //
+       // Inflated or non-inflated representation of any type. 
+       //
        public class TypeSpec : MemberSpec
        {
                protected MetaType info;
@@ -284,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)
@@ -368,6 +396,30 @@ namespace Mono.CSharp
                        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)
@@ -389,6 +441,9 @@ namespace Mono.CSharp
                        return aua;
                }
 
+               //
+               // Return metadata information used during emit to describe the type
+               //
                public virtual MetaType GetMetaInfo ()
                {
                        return info;
@@ -399,6 +454,9 @@ namespace Mono.CSharp
                        return this;
                }
 
+               //
+               // Text representation of type used by documentation writer
+               //
                public override string GetSignatureForDocumentation ()
                {
                        StringBuilder sb = new StringBuilder ();
@@ -605,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)
@@ -675,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;
 
@@ -695,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
@@ -876,6 +953,9 @@ namespace Mono.CSharp
                }
        }
 
+       //
+       // Various type comparers used by compiler
+       //
        static class TypeSpecComparer
        {
                //
@@ -976,6 +1056,23 @@ namespace Mono.CSharp
                                return true;
                        }
 
+                       public static bool IsEqual (TypeSpec[] a, TypeSpec[] b)
+                       {
+                               if (a == b)
+                                       return true;
+
+                               if (a.Length != b.Length)
+                                       return false;
+
+                               for (int i = 0; i < a.Length; ++i) {
+                                       if (!IsEqual (a[i], b[i]))
+                                               return false;
+                               }
+
+                               return true;
+                       }
+
+
                        //
                        // Compares unordered arrays
                        //
@@ -1015,8 +1112,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;
                                }
 
@@ -1257,6 +1353,9 @@ namespace Mono.CSharp
        {
                IAssemblyDefinition DeclaringAssembly { get; }
                string Namespace { get; }
+               bool IsPartial { get; }
+               bool IsComImport { get; }
+               bool IsTypeForwarder { get; }
                int TypeParametersCount { get; }
                TypeParameterSpec[] TypeParameters { get; }
 
@@ -1275,15 +1374,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)
                {
@@ -1292,7 +1386,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
@@ -1309,12 +1403,30 @@ namespace Mono.CSharp
                        }
                }
 
+               bool ITypeDefinition.IsComImport {
+                       get {
+                               return false;
+                       }
+               }
+
                bool IMemberDefinition.IsImported {
                        get {
                                return false;
                        }
                }
 
+               bool ITypeDefinition.IsPartial {
+                       get {
+                               return false;
+                       }
+               }
+
+               bool ITypeDefinition.IsTypeForwarder {
+                       get {
+                               return false;
+                       }
+               }
+
                public override string Name {
                        get {
                                return name;
@@ -1400,6 +1512,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)
@@ -1407,11 +1522,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;
@@ -1427,6 +1539,24 @@ namespace Mono.CSharp
 
                public TypeSpec Element { get; private set; }
 
+               bool ITypeDefinition.IsComImport {
+                       get {
+                               return false;
+                       }
+               }
+
+               bool ITypeDefinition.IsPartial {
+                       get {
+                               return false;
+                       }
+               }
+
+               bool ITypeDefinition.IsTypeForwarder {
+                       get {
+                               return false;
+                       }
+               }
+
                public override string Name {
                        get {
                                throw new NotSupportedException ();