2006-03-13 Peter Dennis Bartok <pbartok@novell.com>
[mono.git] / mcs / bmcs / statement.cs
index 44fd3cc326f55863b61f8281240af78ca4c7f57a..8dce0ad24f979bcae4d5045790ff2904b14f0580 100644 (file)
@@ -146,6 +146,11 @@ namespace Mono.CSharp {
                                return false;
                        }
                        
+                       Assign ass = expr as Assign;
+                       if (ass != null && ass.Source is Constant) {
+                               Report.Warning (665, 3, loc, "Assignment in conditional expression is always constant; did you mean to use == instead of = ?");
+                       }
+
                        //
                        // Dead code elimination
                        //
@@ -579,7 +584,7 @@ namespace Mono.CSharp {
                                        return false;
 
                                if (Expr.Type != ec.ReturnType) {
-                                       Expr = Convert.ImplicitConversionRequired (
+                                       Expr = Convert.WideningConversionRequired (
                                                ec, Expr, ec.ReturnType, loc);
                                        if (Expr == null)
                                                return false;
@@ -641,6 +646,7 @@ namespace Mono.CSharp {
                                label.AddUsageVector (ec.CurrentBranching.CurrentUsageVector);
 
                        ec.CurrentBranching.CurrentUsageVector.Goto ();
+                       label.AddReference ();
 
                        return true;
                }
@@ -670,6 +676,7 @@ namespace Mono.CSharp {
                bool defined;
                bool referenced;
                Label label;
+               ILGenerator ig;
 
                FlowBranching.UsageVector vectors;
                
@@ -682,6 +689,7 @@ namespace Mono.CSharp {
                {
                        if (defined)
                                return label;
+                       ig = ec.ig;
                        label = ec.ig.DefineLabel ();
                        defined = true;
 
@@ -711,16 +719,23 @@ namespace Mono.CSharp {
                {
                        ec.CurrentBranching.Label (vectors);
 
-                       referenced = true;
-
                        return true;
                }
 
                protected override void DoEmit (EmitContext ec)
                {
+                       if (ig != null && ig != ec.ig) {
+                               Report.Error (1632, "Control cannot leave body of anonymous method");
+                               return;
+                       }
                        LabelTarget (ec);
                        ec.ig.MarkLabel (label);
                }
+
+               public void AddReference ()
+               {
+                       referenced = true;
+               }
        }
        
 
@@ -820,7 +835,6 @@ namespace Mono.CSharp {
 
                public override bool Resolve (EmitContext ec)
                {
-                       bool in_catch = ec.CurrentBranching.InCatch ();
                        ec.CurrentBranching.CurrentUsageVector.Throw ();
 
                        if (expr != null){
@@ -831,7 +845,7 @@ namespace Mono.CSharp {
                                ExprClass eclass = expr.eclass;
 
                                if (!(eclass == ExprClass.Variable || eclass == ExprClass.PropertyAccess ||
-                                     eclass == ExprClass.Value || eclass == ExprClass.IndexerAccess)) {
+                                       eclass == ExprClass.Value || eclass == ExprClass.IndexerAccess)) {
                                        expr.Error_UnexpectedKind ("value, variable, property or indexer access ", loc);
                                        return false;
                                }
@@ -839,20 +853,25 @@ namespace Mono.CSharp {
                                Type t = expr.Type;
                                
                                if ((t != TypeManager.exception_type) &&
-                                   !t.IsSubclassOf (TypeManager.exception_type) &&
-                                   !(expr is NullLiteral)) {
+                                       !t.IsSubclassOf (TypeManager.exception_type) &&
+                                       !(expr is NullLiteral)) {
                                        Error (155,
-                                                     "The type caught or thrown must be derived " +
-                                                     "from System.Exception");
+                                               "The type caught or thrown must be derived " +
+                                               "from System.Exception");
                                        return false;
                                }
-                       } else if (!in_catch) {
-                               Error (156,
-                                      "A throw statement with no argument is only " +
-                                      "allowed in a catch clause");
+                               return true;
+                       }
+
+                       if (ec.CurrentBranching.InFinally (true)) {
+                               Error (724, "A throw statement with no argument is only allowed in a catch clause nested inside of the innermost catch clause");
                                return false;
                        }
 
+                       if (!ec.CurrentBranching.InCatch ()) {
+                               Error (156, "A throw statement with no argument is only allowed in a catch clause");
+                               return false;
+                       }
                        return true;
                }
                        
@@ -1418,12 +1437,12 @@ namespace Mono.CSharp {
                // </summary>
                public LocalInfo ThisVariable {
                        get {
-                               if (this_variable != null)
-                                       return this_variable;
-                               else if (Parent != null)
-                                       return Parent.ThisVariable;
-                               else
-                                       return null;
+                               for (Block b = this; b != null; b = b.Parent) {
+                                       if (b.this_variable != null)
+                                               return b.this_variable;
+                               }
+                               
+                               return null;
                        }
                }
 
@@ -1745,8 +1764,6 @@ namespace Mono.CSharp {
                /// </remarks>
                public void ResolveMeta (ToplevelBlock toplevel, EmitContext ec, InternalParameters ip)
                {
-                       ILGenerator ig = ec.ig;
-
                        bool old_unsafe = ec.InUnsafe;
 
                        // If some parent block was unsafe, we remain unsafe even if this block
@@ -1934,7 +1951,7 @@ namespace Mono.CSharp {
 
                        Report.Debug (4, "RESOLVE BLOCK", StartLocation, ec.CurrentBranching);
 
-                       bool unreachable = false;
+                       bool unreachable = unreachable_shown;
 
                        int statement_count = statements.Count;
                        for (int ix = 0; ix < statement_count; ix++){
@@ -1952,8 +1969,10 @@ namespace Mono.CSharp {
                                        else
                                                s.loc = Location.Null;
 
-                                       statements [ix] = EmptyStatement.Value;
-                                       continue;
+                                       if (ok && !(s is Block)) {
+                                               statements [ix] = EmptyStatement.Value;
+                                               continue;
+                                       }
                                }
 
                                if (s.Resolve (ec) == false) {
@@ -2010,7 +2029,18 @@ namespace Mono.CSharp {
                public override bool ResolveUnreachable (EmitContext ec, bool warn)
                {
                        unreachable_shown = true;
-                       return base.ResolveUnreachable (ec, warn);
+
+                       if (warn && (RootContext.WarningLevel >= 2))
+                               Report.Warning (162, loc, "Unreachable code detected");
+
+                       if (Implicit)
+                               return Resolve (ec);
+
+                       ec.StartFlowBranching (FlowBranching.BranchingType.Block, loc);
+                       bool ok = Resolve (ec);
+                       ec.KillFlowBranching ();
+
+                       return ok;
                }
                
                protected override void DoEmit (EmitContext ec)
@@ -2021,7 +2051,7 @@ namespace Mono.CSharp {
                                // Check whether we are the last statement in a
                                // top-level block.
 
-                               if ((Parent == null) && (ix+1 == num_statements))
+                               if (((Parent == null) || Implicit) && (ix+1 == num_statements) && !(s is Block))
                                        ec.IsLastStatement = true;
                                else
                                        ec.IsLastStatement = false;
@@ -2115,8 +2145,6 @@ namespace Mono.CSharp {
 
                static int did = 0;
                
-               int my_id = did++;
-
                        
                public void RegisterCaptureContext (CaptureContext cc)
                {
@@ -2366,34 +2394,39 @@ namespace Mono.CSharp {
                        // conversions, we have to report an error
                        //
                        Expression converted = null;
-                       foreach (Type tt in allowed_types){
-                               Expression e;
-                               
-                               e = Convert.ImplicitUserConversion (ec, Expr, tt, loc);
-                               if (e == null)
-                                       continue;
 
-                               //
-                               // Ignore over-worked ImplicitUserConversions that do
-                               // an implicit conversion in addition to the user conversion.
-                               // 
-                               if (e is UserCast){
-                                       UserCast ue = e as UserCast;
-
-                                       if (ue.Source != Expr)
-                                               e = null;
-                               }
+                       //
+                       // VB.NET has no notion of User defined conversions
+                       //
+
+//                     foreach (Type tt in allowed_types){
+//                             Expression e;
                                
-                               if (converted != null){
-                                       Report.ExtraInformation (
-                                               loc,
-                                               String.Format ("reason: more than one conversion to an integral type exist for type {0}",
-                                                              TypeManager.CSharpName (Expr.Type)));
-                                       return null;
-                               } else {
-                                       converted = e;
-                               }
-                       }
+//                             e = Convert.ImplicitUserConversion (ec, Expr, tt, loc);
+//                             if (e == null)
+//                                     continue;
+
+//                             //
+//                             // Ignore over-worked ImplicitUserConversions that do
+//                             // an implicit conversion in addition to the user conversion.
+//                             // 
+//                             if (e is UserCast){
+//                                     UserCast ue = e as UserCast;
+
+//                                     if (ue.Source != Expr)
+//                                             e = null;
+//                             }
+                               
+//                             if (converted != null){
+//                                     Report.ExtraInformation (
+//                                             loc,
+//                                             String.Format ("reason: more than one conversion to an integral type exist for type {0}",
+//                                                            TypeManager.CSharpName (Expr.Type)));
+//                                     return null;
+//                             } else {
+//                                     converted = e;
+//                             }
+//                     }
                        return converted;
                }
 
@@ -3412,7 +3445,7 @@ namespace Mono.CSharp {
                                        //
                                        ArrayPtr array_ptr = new ArrayPtr (e, loc);
                                        
-                                       Expression converted = Convert.ImplicitConversionRequired (
+                                       Expression converted = Convert.WideningConversionRequired (
                                                ec, array_ptr, vi.VariableType, loc);
                                        if (converted == null)
                                                return false;
@@ -3442,7 +3475,7 @@ namespace Mono.CSharp {
                                // For other cases, flag a `this is already fixed expression'
                                //
                                if (e is LocalVariableReference || e is ParameterReference ||
-                                   Convert.ImplicitConversionExists (ec, e, vi.VariableType)){
+                                   Convert.WideningConversionExists (ec, e, vi.VariableType)){
                                    
                                        Report.Error (245, loc, "right hand expression is already fixed, no need to use fixed statement ");
                                        return false;
@@ -3512,7 +3545,7 @@ namespace Mono.CSharp {
                                        ig.Emit (OpCodes.Stloc, pinned_string);
 
                                        Expression sptr = new StringPtr (pinned_string, loc);
-                                       Expression converted = Convert.ImplicitConversionRequired (
+                                       Expression converted = Convert.WideningConversionRequired (
                                                ec, sptr, vi.VariableType, loc);
                                        
                                        if (converted == null)
@@ -3815,7 +3848,7 @@ namespace Mono.CSharp {
                                        continue;
                                }
 
-                               converted_vars [i] = Convert.ImplicitConversionRequired (
+                               converted_vars [i] = Convert.WideningConversionRequired (
                                        ec, var, TypeManager.idisposable_type, loc);
 
                                if (converted_vars [i] == null)
@@ -3847,7 +3880,7 @@ namespace Mono.CSharp {
                bool ResolveExpression (EmitContext ec)
                {
                        if (!TypeManager.ImplementsInterface (expr_type, TypeManager.idisposable_type)){
-                               conv = Convert.ImplicitConversionRequired (
+                               conv = Convert.WideningConversionRequired (
                                        ec, expr, TypeManager.idisposable_type, loc);
 
                                if (conv == null)
@@ -3883,7 +3916,7 @@ namespace Mono.CSharp {
                        ILGenerator ig = ec.ig;
 
                        int i = assign.Length;
-                       foreach (DictionaryEntry e in var_list){
+                       for (int ii = 0; ii < var_list.Count; ++ii){
                                Expression var = resolved_vars [--i];
                                Label skip = ig.DefineLabel ();
                                
@@ -4086,6 +4119,11 @@ namespace Mono.CSharp {
                        if (expr == null)
                                return false;
 
+                       if (expr is NullLiteral) {
+                               Report.Error (186, expr.Location, "Use of null is not valid in this context");
+                               return false;
+                       }
+
                        TypeExpr texpr = type.ResolveAsTypeTerminal (ec);
                        if (texpr == null)
                                return false;
@@ -4136,7 +4174,7 @@ namespace Mono.CSharp {
                        // Although it is not as important in this case, as the type
                        // will not likely be object (what the enumerator will return).
                        //
-                       conv = Convert.ExplicitConversion (ec, empty, var_type, loc);
+                       conv = Convert.WideningAndNarrowingConversion (ec, empty, var_type, loc);
                        if (conv == null)
                                ok = false;
 
@@ -4281,7 +4319,6 @@ namespace Mono.CSharp {
                                        return false;
                        }
                        ForeachHelperMethods hm = (ForeachHelperMethods) criteria;
-                       EmitContext ec = hm.ec;
 
                        // Check whether GetEnumerator is public
                        if ((mi.Attributes & MethodAttributes.Public) != MethodAttributes.Public)
@@ -4488,7 +4525,8 @@ namespace Mono.CSharp {
                        ig.Emit (OpCodes.Brfalse, end_try);
 
                        if (ec.InIterator)
-                               enumerator.EmitThis (ig);
+                               ig.Emit (OpCodes.Ldarg_0);
+                       
                        enumerator.EmitCall (ig, hm.get_current);
 
                        if (ec.InIterator){
@@ -4588,7 +4626,7 @@ namespace Mono.CSharp {
                                ig.MarkLabel (loop);
 
                                if (ec.InIterator)
-                                       ec.EmitThis ();
+                                       ig.Emit (OpCodes.Ldarg_0);
                                
                                copy.EmitThis (ig);
                                copy.EmitLoad (ig);
@@ -4657,7 +4695,8 @@ namespace Mono.CSharp {
                                }
 
                                if (ec.InIterator)
-                                       ec.EmitThis ();
+                                       ig.Emit (OpCodes.Ldarg_0);
+                               
                                copy.EmitThis (ig);
                                copy.EmitLoad (ig);
                                for (dim = 0; dim < rank; dim++){