2005-09-19 Chris Toshok <toshok@ximian.com>
[mono.git] / mcs / mcs / statement.cs
index a5ebed1ce98510f6084def2593b459651b8b96da..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,
@@ -812,7 +812,7 @@ namespace Mono.CSharp {
 
                        object val = c.GetValue ();
                        if (val == null)
-                               val = c;
+                               val = SwitchLabel.NullStringCase;
                                        
                        sl = (SwitchLabel) ec.Switch.Elements [val];
 
@@ -950,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) {
@@ -1512,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;
                }
 
@@ -1857,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;
@@ -1872,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.
@@ -1882,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;
                                        }
                                }
@@ -2266,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.
                //
@@ -2323,7 +2360,7 @@ namespace Mono.CSharp {
                        }
 
                        if (required_type == TypeManager.string_type && e is NullLiteral) {
-                               converted = e;
+                               converted = NullStringCase;
                                return true;
                        }
 
@@ -2821,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);
@@ -2860,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);
@@ -3051,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)
@@ -3322,6 +3359,10 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
+               public Statement Statement {
+                       get { return statement; }
+               }
+
                public override bool Resolve (EmitContext ec)
                {
                        if (!ec.InUnsafe){
@@ -3754,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;
@@ -3842,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;
                                }
@@ -4067,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);