2005-05-31 Sebastien Pouliot <sebastien@ximian.com>
[mono.git] / mcs / mcs / iterators.cs
index e6c7ed754bdb8f76c6dcc1960218eee6b55b1fa0..62bb473c9a5862a4849d7f0ca0e0e5d87920a48a 100644 (file)
@@ -8,7 +8,7 @@
 //
 // TODO:
 //    Flow analysis for Yield.
-//    Emit calls to parent object constructor.
+//    Emit calls to base object constructor.
 //
 // Generics note:
 //    Current should be defined to return T, and IEnumerator.Current returns object
@@ -41,24 +41,31 @@ namespace Mono.CSharp {
 
                public static bool CheckContext (EmitContext ec, Location loc)
                {
-                       if (ec.CurrentBranching.InFinally (true)){
+                       if (ec.InFinally) {
                                Report.Error (1625, loc, "Cannot yield in the body of a " +
                                              "finally clause");
                                return false;
+                       } 
+                       
+                       if (ec.InUnsafe) {
+                               Report.Error (1629, loc, "Unsafe code may not appear in iterators");
+                               return false;
                        }
-                       if (ec.CurrentBranching.InCatch ()){
+                       if (ec.InCatch){
                                Report.Error (1631, loc, "Cannot yield in the body of a " +
                                              "catch clause");
                                return false;
                        }
                        if (ec.CurrentAnonymousMethod != null){
-                               Report.Error (1621, loc, "yield statement can not appear inside an anonymoud method");
+                               Report.Error (1621, loc, "The yield statement cannot be used inside anonymous method blocks");
                                return false;
                        }
 
-                       //
-                       // FIXME: Missing check for Yield inside try block that contains catch clauses
-                       //
+                       if (ec.CurrentBranching.InTryWithCatch ()) {
+                               Report.Error (1626, loc, "Cannot yield a value in the body of a " +
+                                       "try block with a catch clause");
+                               return false;
+                       }
                        return true;
                }
                
@@ -134,7 +141,6 @@ namespace Mono.CSharp {
                //
                TypeContainer container;
                Type return_type;
-               Type [] param_types;
                InternalParameters parameters;
 
                protected enum State {
@@ -349,14 +355,13 @@ namespace Mono.CSharp {
                // Our constructor
                //
                public Iterator (TypeContainer container, string name, Type return_type,
-                                Type [] param_types, InternalParameters parameters,
+                                InternalParameters parameters,
                                 int modifiers, ToplevelBlock block, Location loc)
                        : base (container.NamespaceEntry, container, MakeProxyName (name),
-                               Modifiers.PRIVATE, null, loc)
+                               (modifiers & Modifiers.UNSAFE) | Modifiers.PRIVATE, null, loc)
                {
                        this.container = container;
                        this.return_type = return_type;
-                       this.param_types = param_types;
                        this.parameters = parameters;
                        this.original_name = name;
                        this.original_block = block;
@@ -388,6 +393,16 @@ namespace Mono.CSharp {
                                                "Iterators cannot have ref or out parameters");
                                        return false;
                                }
+
+                               if ((mod & Parameter.Modifier.ARGLIST) != 0) {
+                                       Report.Error (1636, Location, "__arglist is not allowed in parameter list of iterators");
+                                       return false;
+                               }
+
+                               if (parameters.ParameterType (i).IsPointer) {
+                                       Report.Error (1637, Location, "Iterators cannot have unsafe parameters or yield types");
+                                       return false;
+                               }
                        }
 
                        ArrayList list = new ArrayList ();
@@ -502,10 +517,11 @@ namespace Mono.CSharp {
                        if (!is_static)
                                list.Add (new Parameter (
                                        new TypeExpression (container.TypeBuilder, Location),
-                                       "this", Parameter.Modifier.NONE, null));
+                                       "this", Parameter.Modifier.NONE,
+                                       null, Location));
                        list.Add (new Parameter (
                                TypeManager.system_boolean_expr, "initialized",
-                               Parameter.Modifier.NONE, null));
+                               Parameter.Modifier.NONE, null, Location));
 
                        Parameter[] old_fixed = parameters.Parameters.FixedParameters;
                        if (old_fixed != null)
@@ -515,8 +531,7 @@ namespace Mono.CSharp {
                        list.CopyTo (fixed_params);
 
                        ctor_params = new Parameters (
-                               fixed_params, parameters.Parameters.ArrayParameter,
-                               Location);
+                               fixed_params, parameters.Parameters.ArrayParameter);
 
                        Constructor ctor = new Constructor (
                                this, Name, Modifiers.PUBLIC, ctor_params,
@@ -718,6 +733,11 @@ namespace Mono.CSharp {
                                this.field = field;
                        }
 
+                       public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
+                       {
+                               return DoResolve (ec);
+                       }
+
                        public override Expression DoResolve (EmitContext ec)
                        {
                                FieldExpr fexpr = new FieldExpr (field.FieldBuilder, loc);
@@ -752,6 +772,8 @@ namespace Mono.CSharp {
                                if (iterator.is_static)
                                        code_flags |= Modifiers.STATIC;
 
+                               code_flags |= iterator.ModFlags & Modifiers.UNSAFE;
+
                                EmitContext new_ec = new EmitContext (
                                        iterator.container, loc, ec.ig,
                                        TypeManager.int32_type, code_flags);