In mcs:
[mono.git] / mcs / gmcs / iterators.cs
index 69b7d9c426fb56e62946c7dfc252cf56197ef831..82250f6bb91c6a674bb7c893de85283e02c8d181 100644 (file)
@@ -39,7 +39,7 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
-               public static bool CheckContext (EmitContext ec, Location loc)
+               public static bool CheckContext (EmitContext ec, Location loc, bool isYieldBreak)
                {
                        if (ec.InFinally) {
                                Report.Error (1625, loc, "Cannot yield in the body of a " +
@@ -51,10 +51,6 @@ namespace Mono.CSharp {
                                Report.Error (1629, loc, "Unsafe code may not appear in iterators");
                                return false;
                        }
-                       if (ec.InCatch){
-                               Report.Error (1631, loc, "Cannot yield a value in the body of a catch clause");
-                               return false;
-                       }
 
                        AnonymousContainer am = ec.CurrentAnonymousMethod;
                        if ((am != null) && !am.IsIterator){
@@ -62,9 +58,12 @@ namespace Mono.CSharp {
                                return false;
                        }
 
-                       if (ec.CurrentBranching.InTryWithCatch ()) {
-                               Report.Error (1626, loc, "Cannot yield a value in the body of a " +
+                       if (ec.CurrentBranching.InTryWithCatch () && (!isYieldBreak || !ec.InCatch)) {
+                               if (!ec.InCatch)
+                                       Report.Error (1626, loc, "Cannot yield a value in the body of a " +
                                        "try block with a catch clause");
+                               else
+                                       Report.Error (1631, loc, "Cannot yield a value in the body of a catch clause");
                                return false;
                        }
                        return true;
@@ -76,7 +75,7 @@ namespace Mono.CSharp {
                        if (expr == null)
                                return false;
 
-                       if (!CheckContext (ec, loc))
+                       if (!CheckContext (ec, loc, false))
                                return false;
 
                        Iterator iterator = ec.CurrentIterator;
@@ -107,7 +106,7 @@ namespace Mono.CSharp {
 
                public override bool Resolve (EmitContext ec)
                {
-                       if (!Yield.CheckContext (ec, loc))
+                       if (!Yield.CheckContext (ec, loc, true))
                                return false;
 
                        ec.CurrentBranching.CurrentUsageVector.Goto ();
@@ -157,6 +156,7 @@ namespace Mono.CSharp {
                Expression generic_enumerator_type;
                Expression generic_enumerable_type;
                TypeArguments generic_args;
+               EmitContext ec;
 
                protected enum State {
                        Uninitialized   = -2,
@@ -356,16 +356,16 @@ namespace Mono.CSharp {
                //
                // Our constructor
                //
-               public Iterator (IMethodData m_container, TypeContainer container, GenericMethod generic,
+               public Iterator (IMethodData m_container, DeclSpace parent, GenericMethod generic,
                                 int modifiers)
-                       : base (container.NamespaceEntry, container,
+                       : base (parent.NamespaceEntry, parent,
                                MakeProxyName (m_container.MethodName.Name, generic, m_container.Location),
                                (modifiers & Modifiers.UNSAFE) | Modifiers.PRIVATE, null)
                {
                        this.orig_method = m_container;
 
                        this.generic_method = generic;
-                       this.container = container;
+                       this.container = parent.PartialContainer;
                        this.original_parameters = m_container.ParameterInfo;
                        this.original_block = orig_method.Block;
                        this.block = new ToplevelBlock (orig_method.Block, parameters, orig_method.Location);
@@ -387,7 +387,7 @@ namespace Mono.CSharp {
 
                public bool DefineIterator ()
                {
-                       ec = new EmitContext (this, Location, null, null, ModFlags);
+                       ec = new EmitContext (this, this, Location, null, null, ModFlags);
                        ec.CurrentAnonymousMethod = move_next_method;
                        ec.InIterator = true;
 
@@ -504,7 +504,7 @@ namespace Mono.CSharp {
                        if (it.IsGenericParameter && (it.DeclaringMethod != null)) {
                                int pos = it.GenericParameterPosition;
                                it = CurrentTypeParameters [pos].Type;
-                       } else if (it.IsGenericInstance) {
+                       } else if (it.IsGenericType) {
                                Type[] args = it.GetGenericArguments ();
 
                                TypeArguments inflated = new TypeArguments (Location);
@@ -516,7 +516,7 @@ namespace Mono.CSharp {
                                TypeExpr et_expr = InflateType (it.GetElementType ());
                                int rank = it.GetArrayRank ();
 
-                               Type et = et_expr.ResolveAsTypeTerminal (ec).Type;
+                               Type et = et_expr.ResolveAsTypeTerminal (ec, false).Type;
                                it = et.MakeArrayType (rank);
                        }
 
@@ -542,7 +542,7 @@ namespace Mono.CSharp {
                        return new Parameters (fixed_params, parameters.HasArglist);
                }
 
-               protected override TypeExpr [] GetClassBases (out TypeExpr base_class)
+               public override TypeExpr [] GetClassBases (out TypeExpr base_class)
                {
                        iterator_type_expr = InflateType (original_iterator_type);
 
@@ -587,6 +587,11 @@ namespace Mono.CSharp {
                        else
                                current_type = new TypeExpression (TypeBuilder, Location);
 
+                       if (IsGeneric) {
+                               foreach (TypeParameter tparam in TypeParameters)
+                                       tparam.InflateConstraints (current_type.Type);
+                       }
+
                        parameters = InflateParameters (original_parameters, ec);
                        if (!parameters.Resolve (ec)) {
                                // TODO:
@@ -655,7 +660,7 @@ namespace Mono.CSharp {
                                foreach (TypeParameter tparam in generic_method.TypeParameters)
                                        new_args.Add (new TypeParameterExpr (tparam, Location));
                                ConstructedType ct = new ConstructedType (CurrentType, new_args, Location);
-                               proxy_type = ct.ResolveAsTypeTerminal (ec);
+                               proxy_type = ct.ResolveAsTypeTerminal (ec, false);
                        } else
                                proxy_type = current_type;
 
@@ -803,7 +808,14 @@ namespace Mono.CSharp {
                        Method get_enumerator = new Method (
                                this, null, type, 0, false, name,
                                Parameters.EmptyReadOnlyParameters, null);
-                       AddMethod (get_enumerator);
+
+                       //
+                       // We call append instead of add, as we need to make sure that
+                       // this method is resolved after the MoveNext method, as that one
+                       // triggers the computation of the AnonymousMethod Scope, which is
+                       // required during the code generation of the enumerator
+                       //
+                       AppendMethod (get_enumerator);
 
                        get_enumerator.Block = new ToplevelBlock (
                                block, parameters, Location);
@@ -812,7 +824,7 @@ namespace Mono.CSharp {
 
                        Expression ce = new MemberAccess (
                                new SimpleName ("System.Threading.Interlocked", Location),
-                               "CompareExchange", Location);
+                               "CompareExchange");
 
                        Expression pc = new FieldExpression (this, pc_field);
                        Expression before = new IntLiteral ((int) State.Running, Location);
@@ -946,7 +958,7 @@ namespace Mono.CSharp {
 
                        public override void Emit (EmitContext ec)
                        {
-                               ec.EmitThis ();
+                               ec.EmitThis (false);
                        }
                }
 
@@ -1018,6 +1030,11 @@ namespace Mono.CSharp {
                                get { return iterator; }
                        }
 
+                       public void ComputeHost ()
+                       {
+                               ComputeMethodHost ();
+                       }
+                       
                        public override bool IsIterator {
                                get { return true; }
                        }
@@ -1050,6 +1067,7 @@ namespace Mono.CSharp {
 
                        protected override void DoEmit (EmitContext ec)
                        {
+                               iterator.move_next_method.ComputeHost ();
                                ec.CurrentAnonymousMethod = iterator.move_next_method;
                                ec.InIterator = true;
 
@@ -1233,7 +1251,7 @@ namespace Mono.CSharp {
                                return true;
                        }
 
-                       if (!ret.IsGenericInstance)
+                       if (!ret.IsGenericType)
                                return false;
 
                        Type[] args = TypeManager.GetTypeArguments (ret);