Merge pull request #900 from Blewzman/FixAggregateExceptionGetBaseException
[mono.git] / mcs / mcs / class.cs
index 8343e82f2c70b01e417a979421c86ae94c695775..d450030d747ebc686eec4f757f2b8882983df7d1 100644 (file)
@@ -13,6 +13,7 @@
 //
 
 using System;
+using System.Linq;
 using System.Collections.Generic;
 using System.Runtime.InteropServices;
 using System.Security;
@@ -53,7 +54,11 @@ namespace Mono.CSharp
 
                protected bool is_defined;
 
-               public TypeContainer (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
+               public int CounterAnonymousMethods { get; set; }
+               public int CounterAnonymousContainers { get; set; }
+               public int CounterSwitchTypes { get; set; }
+
+               protected TypeContainer (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
                        : base (parent, name, attrs)
                {
                        this.Kind = kind;
@@ -98,9 +103,9 @@ namespace Mono.CSharp
                        get; set;
                }
 
-               public virtual void AddCompilerGeneratedClass (CompilerGeneratedContainer c)
+               public void AddCompilerGeneratedClass (CompilerGeneratedContainer c)
                {
-                       containers.Add (c);
+                       AddTypeContainerMember (c);
                }
 
                public virtual void AddPartial (TypeDefinition next_part)
@@ -187,15 +192,14 @@ namespace Mono.CSharp
 
                        next_part.PartialContainer = existing;
 
-                       if (containers == null)
-                               containers = new List<TypeContainer> ();
+                       existing.AddPartialPart (next_part);
 
-                       containers.Add (next_part);
+                       AddTypeContainerMember (next_part);
                }
 
                public virtual void AddTypeContainer (TypeContainer tc)
                {
-                       containers.Add (tc);
+                       AddTypeContainerMember (tc);
 
                        var tparams = tc.MemberName.TypeParameters;
                        if (tparams != null && tc.PartialContainer != null) {
@@ -210,6 +214,11 @@ namespace Mono.CSharp
                        }
                }
 
+               protected virtual void AddTypeContainerMember (TypeContainer tc)
+               {
+                       containers.Add (tc);
+               }
+
                public virtual void CloseContainer ()
                {
                        if (containers != null) {
@@ -512,6 +521,9 @@ namespace Mono.CSharp
 
                protected List<FullNamedExpression> type_bases;
 
+               // Partial parts for classes only
+               List<TypeDefinition> class_partial_parts;
+
                TypeDefinition InTransit;
 
                public TypeBuilder TypeBuilder;
@@ -549,7 +561,7 @@ namespace Mono.CSharp
                /// </remarks>
                PendingImplementation pending;
 
-               public TypeDefinition (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
+               protected TypeDefinition (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
                        : base (parent, name, attrs, kind)
                {
                        PartialContainer = this;
@@ -681,6 +693,12 @@ namespace Mono.CSharp
                        }
                }
 
+               bool ITypeDefinition.IsCyclicTypeForwarder {
+                       get {
+                               return false;
+                       }
+               }
+
                //
                // Returns true for secondary partial containers
                //
@@ -741,7 +759,7 @@ namespace Mono.CSharp
                                }
                        }
 
-                       AddNameToContainer (symbol, symbol.MemberName.Basename);
+                       AddNameToContainer (symbol, symbol.MemberName.Name);
                        members.Add (symbol);
                }
 
@@ -749,21 +767,17 @@ namespace Mono.CSharp
                {
                        AddNameToContainer (tc, tc.Basename);
 
-                       if (containers == null)
-                               containers = new List<TypeContainer> ();
-
-                       members.Add (tc);
                        base.AddTypeContainer (tc);
                }
 
-               public override void AddCompilerGeneratedClass (CompilerGeneratedContainer c)
+               protected override void AddTypeContainerMember (TypeContainer tc)
                {
-                       members.Add (c);
+                       members.Add (tc);
 
                        if (containers == null)
                                containers = new List<TypeContainer> ();
 
-                       base.AddCompilerGeneratedClass (c);
+                       base.AddTypeContainerMember (tc);
                }
 
                //
@@ -861,6 +875,17 @@ namespace Mono.CSharp
                        AddMember (op);
                }
 
+               public void AddPartialPart (TypeDefinition part)
+               {
+                       if (Kind != MemberKind.Class)
+                               return;
+
+                       if (class_partial_parts == null)
+                               class_partial_parts = new List<TypeDefinition> ();
+
+                       class_partial_parts.Add (part);
+               }
+
                public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
                {
                        if (has_normal_indexers && a.Type == pa.DefaultMember) {
@@ -957,7 +982,7 @@ namespace Mono.CSharp
                                        if (s == null) {
                                                s = EmptyExpressionStatement.Instance;
                                        } else if (!fi.IsSideEffectFree) {
-                                               has_complex_initializer |= true;
+                                               has_complex_initializer = true;
                                        }
 
                                        init [i] = s;
@@ -973,6 +998,7 @@ namespace Mono.CSharp
                                        if (!has_complex_initializer && fi.IsDefaultInitializer)
                                                continue;
 
+                                       ec.AssignmentInfoOffset += fi.AssignmentOffset;
                                        ec.CurrentBlock.AddScopeStatement (new StatementExpression (init [i]));
                                }
 
@@ -994,6 +1020,7 @@ namespace Mono.CSharp
                                if (fi.IsDefaultInitializer && ec.Module.Compiler.Settings.Optimize)
                                        continue;
 
+                               ec.AssignmentInfoOffset += fi.AssignmentOffset;
                                ec.CurrentBlock.AddScopeStatement (new StatementExpression (s));
                        }
                }
@@ -1428,6 +1455,14 @@ namespace Mono.CSharp
                }
 
                protected bool DefineBaseTypes ()
+               {
+                       if (IsPartialPart && Kind == MemberKind.Class)
+                               return true;
+
+                       return DoDefineBaseType ();
+               }
+
+               bool DoDefineBaseType ()
                {
                        iface_exprs = ResolveBaseTypes (out base_type_expr);
                        bool set_base_type;
@@ -1517,19 +1552,43 @@ namespace Mono.CSharp
                        }
 
                        if (set_base_type) {
-                               if (base_type != null) {
-                                       spec.BaseType = base_type;
+                               SetBaseType ();
+                       }
+
+                       //
+                       // Base type of partial container has to be resolved before we
+                       // resolve any nested types of the container. We need to know
+                       // partial parts because the base type can be specified in file
+                       // defined after current container
+                       //
+                       if (class_partial_parts != null) {
+                               foreach (var pp in class_partial_parts)
+                                       pp.DoDefineBaseType ();
 
-                                       // Set base type after type creation
-                                       TypeBuilder.SetParent (base_type.GetMetaInfo ());
-                               } else {
-                                       TypeBuilder.SetParent (null);
-                               }
                        }
 
                        return true;
                }
 
+               void SetBaseType ()
+               {
+                       if (base_type == null) {
+                               TypeBuilder.SetParent (null);
+                               return;
+                       }
+
+                       if (spec.BaseType == base_type)
+                               return;
+
+                       spec.BaseType = base_type;
+
+                       if (IsPartialPart)
+                               spec.UpdateInflatedInstancesBaseType ();
+
+                       // Set base type after type creation
+                       TypeBuilder.SetParent (base_type.GetMetaInfo ());
+               }
+
                public override void ExpandBaseInterfaces ()
                {
                        if (!IsPartialPart)
@@ -1774,7 +1833,7 @@ namespace Mono.CSharp
 
                                        if (iface_type.Arity > 0) {
                                                // TODO: passing `this' is wrong, should be base type iface instead
-                                               TypeManager.CheckTypeVariance (iface_type, Variance.Covariant, this);
+                                               VarianceDecl.CheckTypeVariance (iface_type, Variance.Covariant, this);
 
                                                if (((InflatedTypeSpec) iface_type).HasDynamicArgument () && !IsCompilerGenerated) {
                                                        Report.Error (1966, Location,
@@ -2081,8 +2140,13 @@ namespace Mono.CSharp
 
                        base.Emit ();
 
-                       for (int i = 0; i < members.Count; i++)
-                               members[i].Emit ();
+                       for (int i = 0; i < members.Count; i++) {
+                               var m = members[i];
+                               if ((m.caching_flags & Flags.CloseTypeCreated) != 0)
+                                       continue;
+
+                               m.Emit ();
+                       }
 
                        EmitIndexerName ();
                        CheckAttributeClsCompliance ();
@@ -2252,11 +2316,20 @@ namespace Mono.CSharp
                /// </summary>
                public bool VerifyImplements (InterfaceMemberBase mb)
                {
-                       var ifaces = spec.Interfaces;
+                       var ifaces = PartialContainer.Interfaces;
                        if (ifaces != null) {
                                foreach (TypeSpec t in ifaces){
                                        if (t == mb.InterfaceType)
                                                return true;
+
+                                       var expanded_base = t.Interfaces;
+                                       if (expanded_base == null)
+                                               continue;
+
+                                       foreach (var bt in expanded_base) {
+                                               if (bt == mb.InterfaceType)
+                                                       return true;
+                                       }
                                }
                        }
                        
@@ -2313,8 +2386,6 @@ namespace Mono.CSharp
                //
                // Public function used to locate types.
                //
-               // Set 'ignore_cs0104' to true if you want to ignore cs0104 errors.
-               //
                // Returns: Type or null if they type can not be found.
                //
                public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
@@ -2340,7 +2411,13 @@ namespace Mono.CSharp
                                if (t != null && (t.IsAccessible (this) || mode == LookupMode.IgnoreAccessibility))
                                        e = new TypeExpression (t, Location.Null);
                                else {
+                                       var errors = Compiler.Report.Errors;
                                        e = Parent.LookupNamespaceOrType (name, arity, mode, loc);
+
+                                       // TODO: LookupNamespaceOrType does more than just lookup. The result
+                                       // cannot be cached or the error reporting won't happen
+                                       if (errors != Compiler.Report.Errors)
+                                               return e;
                                }
                        }
 
@@ -2423,7 +2500,7 @@ namespace Mono.CSharp
 
                SecurityType declarative_security;
 
-               public ClassOrStruct (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
+               protected ClassOrStruct (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
                        : base (parent, name, attrs, kind)
                {
                }
@@ -2606,7 +2683,7 @@ namespace Mono.CSharp
                                return;
                        }
 
-                       if (a.Type.IsConditionallyExcluded (this, Location))
+                       if (a.Type.IsConditionallyExcluded (this))
                                return;
 
                        base.ApplyAttributeBuilder (a, ctor, cdata, pa);
@@ -2675,6 +2752,17 @@ namespace Mono.CSharp
                        }
                }
 
+               public override void GetCompletionStartingWith (string prefix, List<string> results)
+               {
+                       base.GetCompletionStartingWith (prefix, results);
+
+                       var bt = base_type;
+                       while (bt != null) {
+                               results.AddRange (MemberCache.GetCompletitionMembers (this, bt, prefix).Where (l => l.IsStatic).Select (l => l.Name));
+                               bt = bt.BaseType;
+                       }
+               }
+
                protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
                {
                        var ifaces = base.ResolveBaseTypes (out base_class);
@@ -3086,7 +3174,7 @@ namespace Mono.CSharp
                readonly Modifiers explicit_mod_flags;
                public MethodAttributes flags;
 
-               public InterfaceMemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, MemberName name, Attributes attrs)
+               protected InterfaceMemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, MemberName name, Attributes attrs)
                        : base (parent, type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs)
                {
                        IsInterface = parent.Kind == MemberKind.Interface;
@@ -3204,7 +3292,7 @@ namespace Mono.CSharp
                                        }
                                }
 
-                               if (!IsInterface && base_member.IsAbstract && !overrides) {
+                               if (!IsInterface && base_member.IsAbstract && !overrides && !IsStatic) {
                                        Report.SymbolRelatedToPreviousError (base_member);
                                        Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
                                                GetSignatureForError (), base_member.GetSignatureForError ());
@@ -3330,7 +3418,11 @@ namespace Mono.CSharp
                                        Parent.PartialContainer.VerifyImplements (this);
                                }
 
-                               ModifiersExtensions.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location, Report);
+                               Modifiers allowed_explicit = Modifiers.AllowedExplicitImplFlags;
+                               if (this is Method)
+                                       allowed_explicit |= Modifiers.ASYNC;
+
+                               ModifiersExtensions.Check (allowed_explicit, explicit_mod_flags, 0, Location, Report);
                        }
 
                        return base.Define ();
@@ -3374,7 +3466,7 @@ namespace Mono.CSharp
                {
                        base.DoMemberTypeDependentChecks ();
 
-                       TypeManager.CheckTypeVariance (MemberType, ExpectedMemberTypeVariance, this);
+                       VarianceDecl.CheckTypeVariance (MemberType, ExpectedMemberTypeVariance, this);
                }
 
                public override void Emit()