2005-09-19 Chris Toshok <toshok@ximian.com>
[mono.git] / mcs / mcs / statement.cs
index b1aa97561c3a96c551e9788b77e6c659ff4f8996..d717fba709339e2335e66f816595c62d231f2b4e 100644 (file)
@@ -410,7 +410,7 @@ namespace Mono.CSharp {
                Expression Test;
                readonly Statement InitStatement;
                readonly Statement Increment;
-               readonly Statement Statement;
+               public readonly Statement Statement;
                bool infinite, empty;
                
                public For (Statement initStatement,
@@ -800,21 +800,24 @@ namespace Mono.CSharp {
                        if (expr == null)
                                return false;
 
-                       if (!(expr is Constant)){
+                       Constant c = expr as Constant;
+                       if (c == null) {
                                Error (150, "A constant value is expected");
                                return false;
                        }
 
-                       object val = Expression.ConvertIntLiteral (
-                               (Constant) expr, ec.Switch.SwitchType, loc);
+                       c = c.ToType (ec.Switch.SwitchType, loc);
+                       if (c == null)
+                               return false;
 
+                       object val = c.GetValue ();
                        if (val == null)
-                               return false;
+                               val = SwitchLabel.NullStringCase;
                                        
                        sl = (SwitchLabel) ec.Switch.Elements [val];
 
                        if (sl == null){
-                               Report.Error (159, loc, "No such label `case {0}:' within the scope of the goto statement", val);
+                               Report.Error (159, loc, "No such label `case {0}:' within the scope of the goto statement", c.GetValue () == null ? "null" : val);
                                return false;
                        }
 
@@ -947,7 +950,7 @@ namespace Mono.CSharp {
 
                public override bool Resolve (EmitContext ec)
                {
-                       if (!ec.CurrentBranching.InLoop () && !ec.CurrentBranching.InSwitch ()){
+                       if (!ec.CurrentBranching.InLoop ()){
                                Error (139, "No enclosing loop out of which to break or continue");
                                return false;
                        } else if (ec.InFinally) {
@@ -1509,7 +1512,7 @@ namespace Mono.CSharp {
                        // treat it as if the variable declaration was in error.
                        //
                        Report.SymbolRelatedToPreviousError (loc, name);
-                       Error_AlreadyDeclared (kvi.Location, name, "child");
+                       Error_AlreadyDeclared (kvi.Location, name, "parent or current");
                        return false;
                }
 
@@ -1758,11 +1761,9 @@ namespace Mono.CSharp {
                                                continue;
                                        }
 
-                                       if (e.Type != variable_type){
-                                               e = Const.ChangeType (vi.Location, ce, variable_type);
-                                               if (e == null)
-                                                       continue;
-                                       }
+                                       e = ce.ToType (variable_type, vi.Location);
+                                       if (e == null)
+                                               continue;
 
                                        constants.Remove (name);
                                        constants.Add (name, e);
@@ -1856,6 +1857,36 @@ namespace Mono.CSharp {
                bool unreachable_shown;
                bool unreachable;
 
+               private void CheckPossibleMistakenEmptyStatement (Statement s)
+               {
+                       Statement body;
+
+                       // Some statements are wrapped by a Block. Since
+                       // others' internal could be changed, here I treat
+                       // them as possibly wrapped by Block equally.
+                       Block b = s as Block;
+                       if (b != null && b.statements.Count == 1)
+                               s = (Statement) b.statements [0];
+
+                       if (s is Lock)
+                               body = ((Lock) s).Statement;
+                       else if (s is For)
+                               body = ((For) s).Statement;
+                       else if (s is Foreach)
+                               body = ((Foreach) s).Statement;
+                       else if (s is While)
+                               body = ((While) s).Statement;
+                       else if (s is Using)
+                               body = ((Using) s).Statement;
+                       else if (s is Fixed)
+                               body = ((Fixed) s).Statement;
+                       else
+                               return;
+
+                       if (body == null || body is EmptyStatement)
+                               Report.Warning (642, 3, s.loc, "Possible mistaken empty statement");
+               }
+
                public override bool Resolve (EmitContext ec)
                {
                        Block prev_block = ec.CurrentBlock;
@@ -1871,6 +1902,11 @@ namespace Mono.CSharp {
                        int statement_count = statements.Count;
                        for (int ix = 0; ix < statement_count; ix++){
                                Statement s = (Statement) statements [ix];
+                               // Check possible empty statement (CS0642)
+                               if (RootContext.WarningLevel >= 3 &&
+                                       ix + 1 < statement_count &&
+                                               statements [ix + 1] is Block)
+                                       CheckPossibleMistakenEmptyStatement (s);
 
                                //
                                // Warn if we detect unreachable code.
@@ -1881,7 +1917,7 @@ namespace Mono.CSharp {
 
                                        if (!unreachable_shown && (RootContext.WarningLevel >= 2)) {
                                                Report.Warning (
-                                                       162, loc, "Unreachable code detected");
+                                                       162, s.loc, "Unreachable code detected");
                                                unreachable_shown = true;
                                        }
                                }
@@ -2265,6 +2301,8 @@ namespace Mono.CSharp {
                Label il_label_code;
                bool  il_label_code_set;
 
+               public static readonly object NullStringCase = new object ();
+
                //
                // if expr == null, then it is the default case.
                //
@@ -2321,20 +2359,17 @@ namespace Mono.CSharp {
                                return false;
                        }
 
-                       if (required_type == TypeManager.string_type) {
-                               if (c.Type == TypeManager.string_type) {
-                                       converted = c.GetValue ();
-                                       return true;
-                               }
-
-                               if (e is NullLiteral) {
-                                       converted = e;
-                                       return true;
-                               }
+                       if (required_type == TypeManager.string_type && e is NullLiteral) {
+                               converted = NullStringCase;
+                               return true;
                        }
 
-                       converted = Expression.ConvertIntLiteral (c, required_type, loc);
-                       return converted != null;
+                       c = c.ToType (required_type, loc);
+                       if (c == null)
+                               return false;
+
+                       converted = c.GetValue ();
+                       return true;
                }
 
                public void Erorr_AlreadyOccurs ()
@@ -2823,7 +2858,7 @@ namespace Mono.CSharp {
 
                        ig.Emit (OpCodes.Ldloc, val);
                        
-                       if (Elements.Contains (NullLiteral.Null)){
+                       if (Elements.Contains (SwitchLabel.NullStringCase)){
                                ig.Emit (OpCodes.Brfalse, null_target);
                        } else
                                ig.Emit (OpCodes.Brfalse, default_target);
@@ -2862,7 +2897,7 @@ namespace Mono.CSharp {
                                        if (sl.Label != null){
                                                object lit = sl.Converted;
 
-                                               if (lit is NullLiteral){
+                                               if (lit == SwitchLabel.NullStringCase){
                                                        null_found = true;
                                                        if (label_count == 1)
                                                                ig.Emit (OpCodes.Br, next_test);
@@ -3053,7 +3088,7 @@ namespace Mono.CSharp {
 
        public class Lock : ExceptionStatement {
                Expression expr;
-               Statement Statement;
+               public Statement Statement;
                LocalBuilder temp;
                        
                public Lock (Expression expr, Statement stmt, Location l)
@@ -3324,6 +3359,10 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
+               public Statement Statement {
+                       get { return statement; }
+               }
+
                public override bool Resolve (EmitContext ec)
                {
                        if (!ec.InUnsafe){
@@ -3756,7 +3795,7 @@ namespace Mono.CSharp {
 
        public class Using : ExceptionStatement {
                object expression_or_block;
-               Statement Statement;
+               public Statement Statement;
                ArrayList var_list;
                Expression expr;
                Type expr_type;
@@ -3844,7 +3883,7 @@ namespace Mono.CSharp {
                {
                        if (!TypeManager.ImplementsInterface (expr_type, TypeManager.idisposable_type)){
                                if (Convert.ImplicitConversion (ec, expr, TypeManager.idisposable_type, loc) == null) {
-                                       Report.Error (1674, loc, "`{0}': type used in a using statement must be implicitly convertible to 'System.IDisposable'",
+                                       Report.Error (1674, loc, "`{0}': type used in a using statement must be implicitly convertible to `System.IDisposable'",
                                                TypeManager.CSharpName (expr_type));
                                        return false;
                                }
@@ -4069,7 +4108,11 @@ namespace Mono.CSharp {
                        statement = stmt;
                        loc = l;
                }
-               
+
+               public Statement Statement {
+                       get { return statement; }
+               }
+
                public override bool Resolve (EmitContext ec)
                {
                        expr = expr.Resolve (ec);