**** Merged r44746 from MCS ****
[mono.git] / mcs / gmcs / statement.cs
index 49c3ce7e26212ec185a592be866332b95972e8da..9332dd8543b25adf3b99c2cb4d187bc2d71888d8 100644 (file)
@@ -175,8 +175,8 @@ namespace Mono.CSharp {
                        
                                        if ((FalseStatement != null) &&
                                            !FalseStatement.Resolve (ec))
-                               return false;
-                       }
+                                               return false;
+                               }
 
                                return true;
                        }
@@ -355,8 +355,8 @@ namespace Mono.CSharp {
                        if (!Statement.Resolve (ec))
                                ok = false;
 
-                               ec.CurrentBranching.Infinite = infinite;
-                               ec.EndFlowBranching ();
+                       ec.CurrentBranching.Infinite = infinite;
+                       ec.EndFlowBranching ();
 
                        return ok;
                }
@@ -568,7 +568,7 @@ namespace Mono.CSharp {
                public override bool Resolve (EmitContext ec)
                {
                        if (ec.ReturnType == null){
-                       if (Expr != null){
+                               if (Expr != null){
                                        if (ec.CurrentAnonymousMethod != null){
                                                Report.Error (1662, loc, String.Format (
                                                        "Anonymous method could not be converted to delegate " +
@@ -917,7 +917,7 @@ namespace Mono.CSharp {
                        } else if (ec.CurrentBranching.InTryOrCatch (false))
                                ec.CurrentBranching.AddFinallyVector (
                                        ec.CurrentBranching.CurrentUsageVector);
-                       else if (ec.CurrentBranching.InLoop ())
+                       else if (ec.CurrentBranching.InLoop () || ec.CurrentBranching.InSwitch ())
                                ec.CurrentBranching.AddBreakVector (
                                        ec.CurrentBranching.CurrentUsageVector);
 
@@ -1012,8 +1012,15 @@ namespace Mono.CSharp {
                        AddressTaken = 32
                }
 
-               Flags flags;
+               public enum ReadOnlyContext: byte {
+                       Using,
+                       Foreach,
+                       Fixed
+               }
 
+               Flags flags;
+               ReadOnlyContext ro_context;
+               
                public LocalInfo (Expression type, string name, Block block, Location l)
                {
                        Type = type;
@@ -1126,9 +1133,28 @@ namespace Mono.CSharp {
                        get {
                                return (flags & Flags.ReadOnly) != 0;
                        }
-                       set {
-                               flags = value ? (flags | Flags.ReadOnly) : (unchecked (flags & ~Flags.ReadOnly));
+               }
+
+               public void SetReadOnlyContext (ReadOnlyContext context)
+               {
+                       flags |= Flags.ReadOnly;
+                       ro_context = context;
+               }
+
+               public string GetReadOnlyContext ()
+               {
+                       if (!ReadOnly)
+                               throw new InternalErrorException ("Variable is not readonly");
+
+                       switch (ro_context) {
+                               case ReadOnlyContext.Fixed:
+                                       return "fixed variable";
+                               case ReadOnlyContext.Foreach:
+                                       return "foreach iteration variable";
+                               case ReadOnlyContext.Using:
+                                       return "using variable";
                        }
+                       throw new NotImplementedException ();
                }
 
                //
@@ -1631,49 +1657,6 @@ namespace Mono.CSharp {
                        return e != null;
                }
                
-               //
-               // Returns a `ParameterReference' for the given name, or null if there
-               // is no such parameter
-               //
-               public ParameterReference GetParameterReference (string name, Location loc)
-               {
-                       Parameter par;
-                       int idx;
-
-                       for (Block b = this; b != null; b = b.Toplevel.Parent) {
-                               Parameters pars = b.Toplevel.Parameters;
-                               par = pars.GetParameterByName (name, out idx);
-                               if (par != null)
-                                       return new ParameterReference (pars, this, idx, name, loc);
-                       }
-                       return null;
-               }
-
-               //
-               // Whether the parameter named `name' is local to this block, 
-               // or false, if the parameter belongs to an encompassing block.
-               //
-               public bool IsLocalParameter (string name)
-               {
-                       return Toplevel.Parameters.GetParameterByName (name) != null;
-               }
-               
-               //
-               // Whether the `name' is a parameter reference
-               //
-               public bool IsParameterReference (string name)
-               {
-                       Parameter par;
-                       int idx;
-
-                       for (Block b = this; b != null; b = b.Toplevel.Parent) {
-                               par = b.Toplevel.Parameters.GetParameterByName (name, out idx);
-                               if (par != null)
-                                       return true;
-                       }
-                       return false;
-               }
-
                /// <returns>
                ///   A list of labels that were not used within this block
                /// </returns>
@@ -1941,32 +1924,27 @@ namespace Mono.CSharp {
                        for (int ix = 0; ix < statement_count; ix++){
                                Statement s = (Statement) statements [ix];
 
-                               if (unreachable && !(s is LabeledStatement)) {
-                                       if (s == EmptyStatement.Value)
-                                               s.loc = EndLocation;
+                               if (unreachable) {
+                                       if (s is Block)
+                                               ((Block) s).unreachable = true;
 
-                                       if (!s.ResolveUnreachable (ec, !unreachable_shown))
-                                               ok = false;
-
-                                       if (s != EmptyStatement.Value)
+                                       if (!unreachable_shown && (RootContext.WarningLevel >= 2)) {
+                                               Report.Warning (
+                                                       162, loc, "Unreachable code detected");
                                                unreachable_shown = true;
-                                       else
-                                               s.loc = Location.Null;
-
-                                       if (ok && !(s is Block)) {
-                                               statements [ix] = EmptyStatement.Value;
-                                               continue;
                                        }
                                }
 
-                               if (s.Resolve (ec) == false) {
-                                       ok = false;
+                               if (!s.Resolve (ec)) {
+                                       ok = false;
                                        statements [ix] = EmptyStatement.Value;
                                        continue;
                                }
 
-                               num_statements = ix + 1;
+                               if (unreachable && !(s is LabeledStatement) && !(s is Block))
+                                       statements [ix] = EmptyStatement.Value;
 
+                               num_statements = ix + 1;
                                if (s is LabeledStatement)
                                        unreachable = false;
                                else
@@ -2013,15 +1991,11 @@ namespace Mono.CSharp {
                public override bool ResolveUnreachable (EmitContext ec, bool warn)
                {
                        unreachable_shown = true;
+                       unreachable = true;
 
                        if (warn && (RootContext.WarningLevel >= 2))
                                Report.Warning (162, loc, "Unreachable code detected");
 
-                       if (Implicit)
-                               return Resolve (ec);
-
-                       unreachable = true;
-
                        ec.StartFlowBranching (FlowBranching.BranchingType.Block, loc);
                        bool ok = Resolve (ec);
                        ec.KillFlowBranching ();
@@ -2198,6 +2172,48 @@ namespace Mono.CSharp {
                        }
                }
 
+               //
+               // Returns a `ParameterReference' for the given name, or null if there
+               // is no such parameter
+               //
+               public ParameterReference GetParameterReference (string name, Location loc)
+               {
+                       Parameter par;
+                       int idx;
+
+                       for (ToplevelBlock t = this; t != null; t = t.Container) {
+                               Parameters pars = t.Parameters;
+                               par = pars.GetParameterByName (name, out idx);
+                               if (par != null)
+                                       return new ParameterReference (pars, this, idx, name, loc);
+                       }
+                       return null;
+               }
+
+               //
+               // Whether the parameter named `name' is local to this block, 
+               // or false, if the parameter belongs to an encompassing block.
+               //
+               public bool IsLocalParameter (string name)
+               {
+                       return Parameters.GetParameterByName (name) != null;
+               }
+               
+               //
+               // Whether the `name' is a parameter reference
+               //
+               public bool IsParameterReference (string name)
+               {
+                       Parameter par;
+                       int idx;
+
+                       for (ToplevelBlock t = this; t != null; t = t.Container) {
+                               if (t.IsLocalParameter (name))
+                                       return true;
+                       }
+                       return false;
+               }
+
                public bool ResolveMeta (EmitContext ec, InternalParameters ip)
                {
                        int errors = Report.Errors;
@@ -3417,7 +3433,7 @@ namespace Mono.CSharp {
                                Expression e = (Expression) p.Second;
 
                                vi.VariableInfo.SetAssigned (ec);
-                               vi.ReadOnly = true;
+                               vi.SetReadOnlyContext (LocalInfo.ReadOnlyContext.Fixed);
 
                                //
                                // The rules for the possible declarators are pretty wise,