Merge pull request #160 from garuma/tpl-dataflow-plumbing
[mono.git] / mcs / mcs / decl.cs
index bfc256094ec90020034a0453f2150708c5113a42..27f4879aedc092fb3cb589ae8723db9d219c2fa1 100644 (file)
@@ -13,8 +13,7 @@
 
 using System;
 using System.Collections.Generic;
-using System.Reflection.Emit;
-using System.Reflection;
+using System.Diagnostics;
 
 #if NET_2_1
 using XmlElement = System.Object;
@@ -22,11 +21,20 @@ using XmlElement = System.Object;
 using System.Xml;
 #endif
 
+#if STATIC
+using IKVM.Reflection;
+using IKVM.Reflection.Emit;
+#else
+using System.Reflection;
+using System.Reflection.Emit;
+#endif
+
 namespace Mono.CSharp {
 
        //
        // Better name would be DottenName
        //
+       [DebuggerDisplay ("{GetSignatureForError()}")]
        public class MemberName {
                public readonly string Name;
                public TypeArguments TypeArguments;
@@ -379,7 +387,7 @@ namespace Mono.CSharp {
                                }
                        } else {
                                if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN | Modifiers.PARTIAL)) == 0 && !(Parent is Delegate)) {
-                                       if (RootContext.Version >= LanguageVersion.V_3) {
+                                       if (Compiler.Settings.Version >= LanguageVersion.V_3) {
                                                Property.PropertyMethod pm = this as Property.PropertyMethod;
                                                if (pm is Indexer.GetIndexerMethod || pm is Indexer.SetIndexerMethod)
                                                        pm = null;
@@ -453,7 +461,7 @@ namespace Mono.CSharp {
                /// </summary>
                public virtual void Emit ()
                {
-                       if (!RootContext.VerifyClsCompliance)
+                       if (!Compiler.Settings.VerifyClsCompliance)
                                return;
 
                        VerifyClsCompliance ();
@@ -678,9 +686,9 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               public virtual IList<MethodSpec> LookupExtensionMethod (TypeSpec extensionType, string name, int arity, ref NamespaceEntry scope)
+               public virtual ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity)
                {
-                       return Parent.LookupExtensionMethod (extensionType, name, arity, ref scope);
+                       return Parent.LookupExtensionMethod (extensionType, name, arity);
                }
 
                public virtual FullNamedExpression LookupNamespaceAlias (string name)
@@ -688,35 +696,40 @@ namespace Mono.CSharp {
                        return Parent.NamespaceEntry.LookupNamespaceAlias (name);
                }
 
-               public virtual FullNamedExpression LookupNamespaceOrType (string name, int arity, Location loc, bool ignore_cs0104)
+               public virtual FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
                {
-                       return Parent.LookupNamespaceOrType (name, arity, loc, ignore_cs0104);
+                       return Parent.LookupNamespaceOrType (name, arity, mode, loc);
                }
 
                /// <summary>
                /// Goes through class hierarchy and gets value of first found CLSCompliantAttribute.
                /// If no is attribute exists then assembly CLSCompliantAttribute is returned.
                /// </summary>
-               public bool IsNotCLSCompliant ()
-               {
-                       if ((caching_flags & Flags.HasCompliantAttribute_Undetected) == 0)
-                               return (caching_flags & Flags.ClsCompliantAttributeFalse) != 0;
+               public bool? CLSAttributeValue {
+                       get {
+                               if ((caching_flags & Flags.HasCompliantAttribute_Undetected) == 0) {
+                                       if ((caching_flags & Flags.HasClsCompliantAttribute) == 0)
+                                               return null;
 
-                       caching_flags &= ~Flags.HasCompliantAttribute_Undetected;
+                                       return (caching_flags & Flags.ClsCompliantAttributeFalse) == 0;
+                               }
 
-                       if (OptAttributes != null) {
-                               Attribute cls_attribute = OptAttributes.Search (Module.PredefinedAttributes.CLSCompliant);
-                               if (cls_attribute != null) {
-                                       caching_flags |= Flags.HasClsCompliantAttribute;
-                                       if (cls_attribute.GetClsCompliantAttributeValue ())
-                                               return false;
+                               caching_flags &= ~Flags.HasCompliantAttribute_Undetected;
 
-                                       caching_flags |= Flags.ClsCompliantAttributeFalse;
-                                       return true;
+                               if (OptAttributes != null) {
+                                       Attribute cls_attribute = OptAttributes.Search (Module.PredefinedAttributes.CLSCompliant);
+                                       if (cls_attribute != null) {
+                                               caching_flags |= Flags.HasClsCompliantAttribute;
+                                               if (cls_attribute.GetClsCompliantAttributeValue ())
+                                                       return true;
+
+                                               caching_flags |= Flags.ClsCompliantAttributeFalse;
+                                               return false;
+                                       }
                                }
-                       }
 
-                       return false;
+                               return null;
+                       }
                }
 
                /// <summary>
@@ -724,10 +737,7 @@ namespace Mono.CSharp {
                /// </summary>
                protected bool HasClsCompliantAttribute {
                        get {
-                               if ((caching_flags & Flags.HasCompliantAttribute_Undetected) != 0)
-                                       IsNotCLSCompliant ();
-                               
-                               return (caching_flags & Flags.HasClsCompliantAttribute) != 0;
+                               return CLSAttributeValue.HasValue;
                        }
                }
 
@@ -799,34 +809,31 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               //
-               // Raised (and passed an XmlElement that contains the comment)
-               // when GenerateDocComment is writing documentation expectedly.
-               //
-               internal virtual void OnGenerateDocComment (XmlElement intermediateNode)
-               {
-               }
-
                //
                // Returns a string that represents the signature for this 
                // member which should be used in XML documentation.
                //
-               public virtual string GetDocCommentName (DeclSpace ds)
-               {
-                       if (ds == null || this is DeclSpace)
-                               return DocCommentHeader + Name;
-                       else
-                               return String.Concat (DocCommentHeader, ds.Name, ".", Name);
-               }
+               public abstract string GetSignatureForDocumentation ();
 
                //
                // Generates xml doc comments (if any), and if required,
                // handle warning report.
                //
-               internal virtual void GenerateDocComment (DeclSpace ds)
+               internal virtual void GenerateDocComment (DocumentationBuilder builder)
                {
+                       if (DocComment == null) {
+                               if (IsExposedFromAssembly ()) {
+                                       Constructor c = this as Constructor;
+                                       if (c == null || !c.IsDefault ())
+                                               Report.Warning (1591, 4, Location,
+                                                       "Missing XML comment for publicly visible type or member `{0}'", GetSignatureForError ());
+                               }
+
+                               return;
+                       }
+
                        try {
-                               DocUtil.GenerateDocComment (this, ds, Report);
+                               builder.GenerateDocumentationForMember (this);
                        } catch (Exception e) {
                                throw new InternalErrorException (this, e);
                        }
@@ -850,10 +857,6 @@ namespace Mono.CSharp {
                        get { return null; }
                }
 
-               public virtual bool HasUnresolvedConstraints {
-                       get { return false; }
-               }
-
                public bool IsObsolete {
                        get {
                                if (GetAttributeObsolete () != null)
@@ -892,9 +895,12 @@ namespace Mono.CSharp {
                {
                        Obsolete_Undetected = 1,        // Obsolete attribute has not been detected yet
                        Obsolete = 1 << 1,                      // Member has obsolete attribute
-                       CLSCompliant_Undetected = 1 << 3,       // CLSCompliant attribute has not been detected yet
-                       CLSCompliant = 1 << 4,          // Member is CLS Compliant
-                       HasDynamicElement = 1 << 5,
+                       CLSCompliant_Undetected = 1 << 2,       // CLSCompliant attribute has not been detected yet
+                       CLSCompliant = 1 << 3,          // Member is CLS Compliant
+                       MissingDependency_Undetected = 1 << 4,
+                       MissingDependency = 1 << 5,
+                       HasDynamicElement = 1 << 6,
+                       ConstraintsChecked = 1 << 7,
 
                        IsAccessor = 1 << 9,            // Method is an accessor
                        IsGeneric = 1 << 10,            // Member contains type arguments
@@ -904,7 +910,12 @@ namespace Mono.CSharp {
                        PendingMemberCacheMembers = 1 << 14,
                        PendingBaseTypeInflate = 1 << 15,
                        InterfacesExpanded = 1 << 16,
-                       IsNotRealProperty = 1 << 17,
+                       IsNotCSharpCompatible = 1 << 17,
+                       SpecialRuntimeType = 1 << 18,
+                       InflatedExpressionType = 1 << 19,
+                       InflatedNullableType = 1 << 20,
+                       GenericIterateInterface = 1 << 21,
+                       GenericTask = 1 << 22
                }
 
                protected Modifiers modifiers;
@@ -925,7 +936,7 @@ namespace Mono.CSharp {
                        this.definition = definition;
                        this.modifiers = modifiers;
 
-                       state = StateFlags.Obsolete_Undetected | StateFlags.CLSCompliant_Undetected;
+                       state = StateFlags.Obsolete_Undetected | StateFlags.CLSCompliant_Undetected | StateFlags.MissingDependency_Undetected;
                }
 
                #region Properties
@@ -992,6 +1003,18 @@ namespace Mono.CSharp {
                        }
                }
 
+               //
+               // Returns true for imported members which are not compatible with C# language
+               //
+               public bool IsNotCSharpCompatible {
+                       get {
+                               return (state & StateFlags.IsNotCSharpCompatible) != 0;
+                       }
+                       set {
+                               state = value ? state | StateFlags.IsNotCSharpCompatible : state & ~StateFlags.IsNotCSharpCompatible;
+                       }
+               }
+
                public bool IsPrivate {
                        get { return (modifiers & Modifiers.PRIVATE) != 0; }
                }
@@ -1022,9 +1045,47 @@ namespace Mono.CSharp {
                        return oa;
                }
 
-               protected virtual bool IsNotCLSCompliant ()
+               //
+               // Returns a list of missing dependencies of this member. The list
+               // will contain types only but it can have numerous values for members
+               // like methods where both return type and all parameters are checked
+               //
+               public List<TypeSpec> GetMissingDependencies ()
                {
-                       return MemberDefinition.IsNotCLSCompliant ();
+                       if ((state & (StateFlags.MissingDependency | StateFlags.MissingDependency_Undetected)) == 0)
+                               return null;
+
+                       state &= ~StateFlags.MissingDependency_Undetected;
+
+                       var imported = definition as ImportedDefinition;
+                       List<TypeSpec> missing;
+                       if (imported != null) {
+                               missing = ResolveMissingDependencies ();
+                       } else if (this is ElementTypeSpec) {
+                               missing = ((ElementTypeSpec) this).Element.GetMissingDependencies ();
+                       } else {
+                               missing = null;
+                       }
+
+                       if (missing != null) {
+                               state |= StateFlags.MissingDependency;
+                       }
+
+                       return missing;
+               }
+
+               public abstract List<TypeSpec> ResolveMissingDependencies ();
+
+               protected virtual bool IsNotCLSCompliant (out bool attrValue)
+               {
+                       var cls = MemberDefinition.CLSAttributeValue;
+                       attrValue = cls ?? false;
+                       return cls == false;
+               }
+
+               public virtual string GetSignatureForDocumentation ()
+               {
+                       return DeclaringType.GetSignatureForDocumentation () + "." + Name;
                }
 
                public virtual string GetSignatureForError ()
@@ -1038,41 +1099,41 @@ namespace Mono.CSharp {
                {
                        var inflated = (MemberSpec) MemberwiseClone ();
                        inflated.declaringType = inflator.TypeInstance;
-                       inflated.state |= StateFlags.PendingMetaInflate;
+                       if (DeclaringType.IsGenericOrParentIsGeneric)
+                               inflated.state |= StateFlags.PendingMetaInflate;
 #if DEBUG
-                       if (inflated.ID > 0)
-                               inflated.ID = -inflated.ID;
+                       inflated.ID += 1000000;
 #endif
                        return inflated;
                }
 
                //
-               // Is this member accessible from invocationType
+               // Is this member accessible from invocation context
                //
-               public bool IsAccessible (TypeSpec invocationType)
+               public bool IsAccessible (IMemberContext ctx)
                {
                        var ma = Modifiers & Modifiers.AccessibilityMask;
                        if (ma == Modifiers.PUBLIC)
                                return true;
 
                        var parentType = /* this as TypeSpec ?? */ DeclaringType;
+                       var ctype = ctx.CurrentType;
 
-                       // It's null for module context
-                       if (invocationType == null)
-                               invocationType = InternalType.FakeInternalType;
-               
-                       //
-                       // If only accessible to the current class or children
-                       //
-                       if (ma == Modifiers.PRIVATE)
-                               return invocationType.MemberDefinition == parentType.MemberDefinition ||
-                                       TypeManager.IsNestedChildOf (invocationType, parentType);
+                       if (ma == Modifiers.PRIVATE) {
+                               if (ctype == null)
+                                       return false;
+                               //
+                               // It's only accessible to the current class or children
+                               //
+                               if (parentType.MemberDefinition == ctype.MemberDefinition)
+                                       return true;
+
+                               return TypeManager.IsNestedChildOf (ctype, parentType.MemberDefinition);
+                       }
 
                        if ((ma & Modifiers.INTERNAL) != 0) {
                                bool b;
-                               var assembly = invocationType == InternalType.FakeInternalType ?
-                                       RootContext.ToplevelTypes.DeclaringAssembly :
-                                       invocationType.MemberDefinition.DeclaringAssembly;
+                               var assembly = ctype == null ? ctx.Module.DeclaringAssembly : ctype.MemberDefinition.DeclaringAssembly;
 
                                if (parentType == null) {
                                        b = ((ITypeDefinition) MemberDefinition).IsInternalAsPublic (assembly);
@@ -1084,11 +1145,18 @@ namespace Mono.CSharp {
                                        return b;
                        }
 
-                       // PROTECTED
-                       if (!TypeManager.IsNestedFamilyAccessible (invocationType, parentType))
-                               return false;
+                       //
+                       // Checks whether `ctype' is a subclass or nested child of `parentType'.
+                       //
+                       while (ctype != null) {
+                               if (TypeManager.IsFamilyAccessible (ctype, parentType))
+                                       return true;
 
-                       return true;
+                               // Handle nested types.
+                               ctype = ctype.DeclaringType;    // TODO: Untested ???
+                       }
+
+                       return false;
                }
 
                //
@@ -1099,14 +1167,16 @@ namespace Mono.CSharp {
                        if ((state & StateFlags.CLSCompliant_Undetected) != 0) {
                                state &= ~StateFlags.CLSCompliant_Undetected;
 
-                               if (IsNotCLSCompliant ())
+                               bool compliant;
+                               if (IsNotCLSCompliant (out compliant))
                                        return false;
 
-                               bool compliant;
-                               if (DeclaringType != null) {
-                                       compliant = DeclaringType.IsCLSCompliant ();
-                               } else {
-                                       compliant = ((ITypeDefinition) MemberDefinition).DeclaringAssembly.IsCLSCompliant;
+                               if (!compliant) {
+                                       if (DeclaringType != null) {
+                                               compliant = DeclaringType.IsCLSCompliant ();
+                                       } else {
+                                               compliant = ((ITypeDefinition) MemberDefinition).DeclaringAssembly.IsCLSCompliant;
+                                       }
                                }
 
                                if (compliant)
@@ -1116,7 +1186,7 @@ namespace Mono.CSharp {
                        return (state & StateFlags.CLSCompliant) != 0;
                }
 
-               public bool IsConditionallyExcluded (Location loc)
+               public bool IsConditionallyExcluded (CompilerContext ctx, Location loc)
                {
                        if ((Kind & (MemberKind.Class | MemberKind.Method)) == 0)
                                return false;
@@ -1126,7 +1196,7 @@ namespace Mono.CSharp {
                                return false;
 
                        foreach (var condition in conditions) {
-                               if (loc.CompilationUnit.IsConditionalDefined (condition))
+                               if (loc.CompilationUnit.IsConditionalDefined (ctx, condition))
                                        return false;
                        }
 
@@ -1145,12 +1215,12 @@ namespace Mono.CSharp {
        //
        public interface IMemberDefinition
        {
+               bool? CLSAttributeValue { get; }
                string Name { get; }
                bool IsImported { get; }
 
                string[] ConditionalConditions ();
                ObsoleteAttribute GetAttributeObsolete ();
-               bool IsNotCLSCompliant ();
                void SetIsAssigned ();
                void SetIsUsed ();
        }
@@ -1181,7 +1251,7 @@ namespace Mono.CSharp {
                // This is the namespace in which this typecontainer
                // was declared.  We use this to resolve names.
                //
-               public NamespaceEntry NamespaceEntry;
+               public NamespaceContainer NamespaceEntry;
 
                public readonly string Basename;
                
@@ -1208,9 +1278,9 @@ namespace Mono.CSharp {
                        }
                }
 
-               static string[] attribute_targets = new string [] { "type" };
+               static readonly string[] attribute_targets = new string [] { "type" };
 
-               public DeclSpace (NamespaceEntry ns, DeclSpace parent, MemberName name,
+               public DeclSpace (NamespaceContainer ns, DeclSpace parent, MemberName name,
                                  Attributes attrs)
                        : base (parent, name, attrs)
                {
@@ -1253,17 +1323,13 @@ namespace Mono.CSharp {
                                return false;
                        }
 
-                       if (this is ModuleContainer) {
-                               Report.Error (101, symbol.Location, 
-                                       "The namespace `{0}' already contains a definition for `{1}'",
-                                       ((DeclSpace)symbol).NamespaceEntry.GetSignatureForError (), symbol.MemberName.Name);
-                       } else if (symbol is TypeParameter) {
+                       if (symbol is TypeParameter) {
                                Report.Error (692, symbol.Location,
                                        "Duplicate type parameter `{0}'", symbol.GetSignatureForError ());
                        } else {
                                Report.Error (102, symbol.Location,
-                                             "The type `{0}' already contains a definition for `{1}'",
-                                             GetSignatureForError (), symbol.MemberName.Name);
+                                       "The type `{0}' already contains a definition for `{1}'",
+                                       GetSignatureForError (), symbol.MemberName.Name);
                        }
 
                        return false;
@@ -1300,9 +1366,7 @@ namespace Mono.CSharp {
                        return false;
                }
 
-               protected virtual TypeAttributes TypeAttr {
-                       get { return Module.DefaultCharSetType; }
-               }
+               protected abstract TypeAttributes TypeAttr { get; }
 
                /// <remarks>
                ///  Should be overriten by the appropriate declaration space
@@ -1316,6 +1380,11 @@ namespace Mono.CSharp {
                                type.GetSignatureForError ());
                }
 
+               public override string GetSignatureForDocumentation ()
+               {
+                       return Name;
+               }
+
                public override string GetSignatureForError ()
                {
                        return MemberName.GetSignatureForError ();