2004-05-24 Martin Baulig <martin@ximian.com>
[mono.git] / mcs / mcs / statement.cs
index f9dbfa79d18773031a404eda5b6ba3689cb54861..203e61d58bf9c0fc51f3aeecf25aaeace77b483e 100755 (executable)
@@ -171,7 +171,7 @@ namespace Mono.CSharp {
 
                        is_true_ret = ec.CurrentBranching.CurrentUsageVector.Reachability.IsUnreachable;
 
-                       ec.CurrentBranching.CreateSibling (FlowBranching.SiblingType.Conditional);
+                       ec.CurrentBranching.CreateSibling ();
 
                        if ((FalseStatement != null) && !FalseStatement.Resolve (ec))
                                ok = false;
@@ -440,7 +440,7 @@ namespace Mono.CSharp {
 
                        ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc);
                        if (!infinite)
-                               ec.CurrentBranching.CreateSibling (FlowBranching.SiblingType.Conditional);
+                               ec.CurrentBranching.CreateSibling ();
 
                        if (!Statement.Resolve (ec))
                                ok = false;
@@ -598,22 +598,15 @@ namespace Mono.CSharp {
                        if (Expr != null) {
                                Expr.Emit (ec);
 
-                               if (in_exc || !ec.IsLastStatement)
+                               if (in_exc)
                                        ec.ig.Emit (OpCodes.Stloc, ec.TemporaryReturn ());
                        }
 
                        if (in_exc) {
                                ec.NeedReturnLabel ();
                                ec.ig.Emit (OpCodes.Leave, ec.ReturnLabel);
-                       } else if (ec.IsLastStatement) {
-                               // If we are the last statement in a top-level block, simply
-                               // emit a `ret'.
-                               ec.ig.Emit (OpCodes.Ret);
                        } else {
-                               // Otherwise, we always create a return label and jump to
-                               // it.
-                               ec.NeedReturnLabel ();
-                               ec.ig.Emit (OpCodes.Br, ec.ReturnLabel);
+                               ec.ig.Emit (OpCodes.Ret);
                        }
                }
        }
@@ -625,13 +618,9 @@ namespace Mono.CSharp {
                
                public override bool Resolve (EmitContext ec)
                {
-                       label = block.LookupLabel (target);
-                       if (label == null){
-                               Report.Error (
-                                       159, loc,
-                                       "No such label `" + target + "' in this scope");
+                       label = ec.CurrentBranching.LookupLabel (target, loc);
+                       if (label == null)
                                return false;
-                       }
 
                        // If this is a forward goto.
                        if (!label.IsDefined)
@@ -1014,6 +1003,12 @@ namespace Mono.CSharp {
                        if (VariableType == null)
                                VariableType = decl.ResolveType (Type, false, Location);
 
+                       if (VariableType == TypeManager.void_type) {
+                               Report.Error (1547, Location,
+                                             "Keyword 'void' cannot be used in this context");
+                               return false;
+                       }
+
                        if (VariableType == null)
                                return false;
 
@@ -1235,19 +1230,22 @@ namespace Mono.CSharp {
                                return switch_block.AddLabel (name, target, loc);
 
                        Block cur = this;
-                       while (cur != null && cur.Implicit) {
-                               if (cur.LookupLabel (name) != null) {
+                       while (cur != null) {
+                               if (cur.DoLookupLabel (name) != null) {
                                        Report.Error (
                                                140, loc, "The label '{0}' is a duplicate",
                                                name);
                                        return false;
                                }
 
+                               if (!Implicit)
+                                       break;
+
                                cur = cur.Parent;
                        }
 
                        while (cur != null) {
-                               if (cur.LookupLabel (name) != null) {
+                               if (cur.DoLookupLabel (name) != null) {
                                        Report.Error (
                                                158, loc,
                                                "The label '{0}' shadows another label " +
@@ -1256,6 +1254,23 @@ namespace Mono.CSharp {
                                        return false;
                                }
 
+                               if (children != null) {
+                                       foreach (Block b in children) {
+                                               LabeledStatement s = b.DoLookupLabel (name);
+                                               if (s == null)
+                                                       continue;
+
+                                               Report.Error (
+                                                       158, s.Location,
+                                                       "The label '{0}' shadows another " +
+                                                       "label by the same name in a " +
+                                                       "containing scope.",
+                                                       name);
+                                               return false;
+                                       }
+                               }
+
+
                                cur = cur.Parent;
                        }
 
@@ -1268,40 +1283,34 @@ namespace Mono.CSharp {
 
                public LabeledStatement LookupLabel (string name)
                {
-                       Hashtable l = new Hashtable ();
-                       
-                       return LookupLabel (name, l);
+                       LabeledStatement s = DoLookupLabel (name);
+                       if (s != null)
+                               return s;
+
+                       if (children == null)
+                               return null;
+
+                       foreach (Block child in children) {
+                               if (!child.Implicit)
+                                       continue;
+
+                               s = child.LookupLabel (name);
+                               if (s != null)
+                                       return s;
+                       }
+
+                       return null;
                }
 
-               //
-               // Lookups a label in the current block, parents and children.
-               // It skips during child recurssion on `source'
-               //
-               LabeledStatement LookupLabel (string name, Hashtable seen)
+               LabeledStatement DoLookupLabel (string name)
                {
                        if (switch_block != null)
-                               return switch_block.LookupLabel (name, seen);
+                               return switch_block.LookupLabel (name);
 
-                       if (seen [this] != null)
-                               return null;
-
-                       seen [this] = this;
-                       
                        if (labels != null)
                                if (labels.Contains (name))
                                        return ((LabeledStatement) labels [name]);
 
-                       if (children != null){
-                               foreach (Block b in children){
-                                       LabeledStatement s = b.LookupLabel (name, seen);
-                                       if (s != null)
-                                               return s;
-                               }
-                       }
-
-                       if (Parent != null)
-                               return Parent.LookupLabel (name, seen);
-
                        return null;
                }
 
@@ -1496,15 +1505,6 @@ namespace Mono.CSharp {
                        return e != null;
                }
                
-               /// <summary>
-               ///   Use to fetch the statement associated with this label
-               /// </summary>
-               public Statement this [string name] {
-                       get {
-                               return (Statement) labels [name];
-                       }
-               }
-
                Parameters parameters = null;
                public Parameters Parameters {
                        get {
@@ -1739,11 +1739,16 @@ namespace Mono.CSharp {
                                Statement s = (Statement) statements [ix];
 
                                if (unreachable && !(s is LabeledStatement)) {
+                                       if (s == EmptyStatement.Value)
+                                               s.loc = EndLocation;
+
                                        if (!s.ResolveUnreachable (ec, !warning_shown))
                                                ok = false;
 
                                        if (s != EmptyStatement.Value)
                                                warning_shown = true;
+                                       else
+                                               s.loc = Location.Null;
 
                                        statements [ix] = EmptyStatement.Value;
                                        continue;
@@ -2617,7 +2622,8 @@ namespace Mono.CSharp {
                        bool first = true;
                        foreach (SwitchSection ss in Sections){
                                if (!first)
-                                       ec.CurrentBranching.CreateSibling (FlowBranching.SiblingType.SwitchSection);
+                                       ec.CurrentBranching.CreateSibling (
+                                               null, FlowBranching.SiblingType.SwitchSection);
                                else
                                        first = false;
 
@@ -2627,7 +2633,8 @@ namespace Mono.CSharp {
 
 
                        if (!got_default)
-                               ec.CurrentBranching.CreateSibling (FlowBranching.SiblingType.SwitchSection);
+                               ec.CurrentBranching.CreateSibling (
+                                       null, FlowBranching.SiblingType.SwitchSection);
 
                        FlowBranching.Reachability reachability = ec.EndFlowBranching ();
                        ec.Switch = old_switch;
@@ -3191,7 +3198,9 @@ namespace Mono.CSharp {
                        Report.Debug (1, "START OF CATCH BLOCKS", vector);
 
                        foreach (Catch c in Specific){
-                               ec.CurrentBranching.CreateSibling (FlowBranching.SiblingType.Catch);
+                               ec.CurrentBranching.CreateSibling (
+                                       c.Block, FlowBranching.SiblingType.Catch);
+
                                Report.Debug (1, "STARTED SIBLING FOR CATCH", ec.CurrentBranching);
 
                                if (c.Name != null) {
@@ -3209,7 +3218,9 @@ namespace Mono.CSharp {
                        Report.Debug (1, "END OF CATCH BLOCKS", ec.CurrentBranching);
 
                        if (General != null){
-                               ec.CurrentBranching.CreateSibling (FlowBranching.SiblingType.Catch);
+                               ec.CurrentBranching.CreateSibling (
+                                       General.Block, FlowBranching.SiblingType.Catch);
+
                                Report.Debug (1, "STARTED SIBLING FOR GENERAL", ec.CurrentBranching);
 
                                if (!General.Resolve (ec))
@@ -3220,7 +3231,9 @@ namespace Mono.CSharp {
 
                        if (Fini != null) {
                                if (ok)
-                                       ec.CurrentBranching.CreateSibling (FlowBranching.SiblingType.Finally);
+                                       ec.CurrentBranching.CreateSibling (
+                                               Fini, FlowBranching.SiblingType.Finally);
+
                                Report.Debug (1, "STARTED SIBLING FOR FINALLY", ec.CurrentBranching, vector);
 
                                if (!Fini.Resolve (ec))
@@ -3404,7 +3417,7 @@ namespace Mono.CSharp {
                                        converted_vars [i].Emit (ec);
                                        ig.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void);
                                } else {
-                                       Expression ml = Expression.MemberLookup(ec, typeof(IDisposable), var.Type, "Dispose", Mono.CSharp.Location.Null);
+                                       Expression ml = Expression.MemberLookup(ec, TypeManager.idisposable_type, var.Type, "Dispose", Mono.CSharp.Location.Null);
 
                                        if (!(ml is MethodGroupExpr)) {
                                                var.Emit (ec);
@@ -3585,7 +3598,7 @@ namespace Mono.CSharp {
                        bool ok = true;
 
                        ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc);
-                       ec.CurrentBranching.CreateSibling (FlowBranching.SiblingType.Conditional);
+                       ec.CurrentBranching.CreateSibling ();
 
                        //
                        //
@@ -3902,11 +3915,18 @@ namespace Mono.CSharp {
                                if (expr is IMemoryLocation){
                                        IMemoryLocation ml = (IMemoryLocation) expr;
 
-                                       ml.AddressOf (ec, AddressOp.Load);
+                                       Expression ml1 = Expression.MemberLookup(ec, TypeManager.ienumerator_type, expr.Type, "GetEnumerator", Mono.CSharp.Location.Null);
+
+                                       if (!(ml1 is MethodGroupExpr)) {
+                                               expr.Emit(ec);
+                                               ec.ig.Emit(OpCodes.Box, expr.Type);
+                                       } else {
+                                               ml.AddressOf (ec, AddressOp.Load);
+                                       }
                                } else
                                        throw new Exception ("Expr " + expr + " of type " + expr.Type +
                                                             " does not implement IMemoryLocation");
-                               ig.Emit (OpCodes.Call, hm.get_enumerator);
+                               ig.Emit (OpCodes.Callvirt, hm.get_enumerator);
                        } else {
                                expr.Emit (ec);
                                ig.Emit (OpCodes.Callvirt, hm.get_enumerator);