oops.
[mono.git] / mcs / mcs / statement.cs
old mode 100755 (executable)
new mode 100644 (file)
index 8936d25..e050e8f
@@ -3,7 +3,7 @@
 //
 // Author:
 //   Miguel de Icaza (miguel@ximian.com)
-//   Martin Baulig (martin@gnome.org)
+//   Martin Baulig (martin@ximian.com)
 //
 // (C) 2001, 2002, 2003 Ximian, Inc.
 // (C) 2003, 2004 Novell, Inc.
@@ -46,16 +46,14 @@ namespace Mono.CSharp {
                        // in unreachable code, for instance.
                        //
 
+                       if (warn && (RootContext.WarningLevel >= 2))
+                               Report.Warning (162, loc, "Unreachable code detected");
+
                        ec.StartFlowBranching (FlowBranching.BranchingType.Block, loc);
                        bool ok = Resolve (ec);
                        ec.KillFlowBranching ();
 
-                       if (!ok)
-                               return false;
-
-                       if (warn && (RootContext.WarningLevel >= 2))
-                               Report.Warning (162, loc, "Unreachable code detected");
-                       return true;
+                       return ok;
                }
                
                protected void CheckObsolete (Type type)
@@ -148,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
                        //
@@ -672,6 +675,7 @@ namespace Mono.CSharp {
                bool defined;
                bool referenced;
                Label label;
+               ILGenerator ig;
 
                FlowBranching.UsageVector vectors;
                
@@ -684,6 +688,7 @@ namespace Mono.CSharp {
                {
                        if (defined)
                                return label;
+                       ig = ec.ig;
                        label = ec.ig.DefineLabel ();
                        defined = true;
 
@@ -720,6 +725,10 @@ namespace Mono.CSharp {
 
                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);
                }
@@ -822,7 +831,6 @@ namespace Mono.CSharp {
 
                public override bool Resolve (EmitContext ec)
                {
-                       bool in_catch = ec.CurrentBranching.InCatch ();
                        ec.CurrentBranching.CurrentUsageVector.Throw ();
 
                        if (expr != null){
@@ -833,7 +841,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;
                                }
@@ -841,20 +849,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;
                }
                        
@@ -1420,12 +1433,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;
                        }
                }
 
@@ -1747,8 +1760,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
@@ -2117,8 +2128,6 @@ namespace Mono.CSharp {
 
                static int did = 0;
                
-               int my_id = did++;
-
                        
                public void RegisterCaptureContext (CaptureContext cc)
                {
@@ -2347,12 +2356,12 @@ namespace Mono.CSharp {
 
                        if (allowed_types == null){
                                allowed_types = new Type [] {
+                                       TypeManager.int32_type,
+                                       TypeManager.uint32_type,
                                        TypeManager.sbyte_type,
                                        TypeManager.byte_type,
                                        TypeManager.short_type,
                                        TypeManager.ushort_type,
-                                       TypeManager.int32_type,
-                                       TypeManager.uint32_type,
                                        TypeManager.int64_type,
                                        TypeManager.uint64_type,
                                        TypeManager.char_type,
@@ -2375,13 +2384,26 @@ namespace Mono.CSharp {
                                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.Error (-12, loc, "More than one conversion to an integral " +
-                                                     " type exists for type `" +
-                                                     TypeManager.CSharpName (Expr.Type)+"'");
+                                       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
+                               } else {
                                        converted = e;
+                               }
                        }
                        return converted;
                }
@@ -3871,7 +3893,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 ();
 
@@ -3945,12 +3967,39 @@ namespace Mono.CSharp {
                void EmitExpressionFinally (EmitContext ec)
                {
                        ILGenerator ig = ec.ig;
-                       Label skip = ig.DefineLabel ();
-                       ig.Emit (OpCodes.Ldloc, local_copy);
-                       ig.Emit (OpCodes.Brfalse, skip);
-                       ig.Emit (OpCodes.Ldloc, local_copy);
-                       ig.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void);
-                       ig.MarkLabel (skip);
+                       if (!local_copy.LocalType.IsValueType) {
+                               Label skip = ig.DefineLabel ();
+                               ig.Emit (OpCodes.Ldloc, local_copy);
+                               ig.Emit (OpCodes.Brfalse, skip);
+                               ig.Emit (OpCodes.Ldloc, local_copy);
+                               ig.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void);
+                               ig.MarkLabel (skip);
+                       } else {
+                               Expression ml = Expression.MemberLookup(ec, TypeManager.idisposable_type, local_copy.LocalType, "Dispose", Mono.CSharp.Location.Null);
+
+                               if (!(ml is MethodGroupExpr)) {
+                                       ig.Emit (OpCodes.Ldloc, local_copy);
+                                       ig.Emit (OpCodes.Box, local_copy.LocalType);
+                                       ig.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void);
+                               } else {
+                                       MethodInfo mi = null;
+
+                                       foreach (MethodInfo mk in ((MethodGroupExpr) ml).Methods) {
+                                               if (TypeManager.GetArgumentTypes (mk).Length == 0) {
+                                                       mi = mk;
+                                                       break;
+                                               }
+                                       }
+
+                                       if (mi == null) {
+                                               Report.Error(-100, Mono.CSharp.Location.Null, "Internal error: No Dispose method which takes 0 parameters.");
+                                               return;
+                                       }
+
+                                       ig.Emit (OpCodes.Ldloca, local_copy);
+                                       ig.Emit (OpCodes.Call, mi);
+                               }
+                       }
                }
                
                public override bool Resolve (EmitContext ec)
@@ -4045,6 +4094,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, false);
                        if (texpr == null)
                                return false;
@@ -4074,8 +4128,12 @@ namespace Mono.CSharp {
                                if (hm == null){
                                        error1579 (expr.Type);
                                        return false;
-                               }                       
+                               }
 
+                               // When ProbeCollection reported error
+                               if (hm.move_next == null)
+                                       return false;
+       
                                array_type = expr.Type;
                                element_type = hm.element_type;
 
@@ -4212,10 +4270,12 @@ namespace Mono.CSharp {
                        public Type element_type;
                        public Type enumerator_type;
                        public bool is_disposable;
+                       public readonly Location Location;
 
-                       public ForeachHelperMethods (EmitContext ec)
+                       public ForeachHelperMethods (EmitContext ec, Location loc)
                        {
                                this.ec = ec;
+                               this.Location = loc;
                                this.element_type = TypeManager.object_type;
                                this.enumerator_type = TypeManager.ienumerator_type;
                                this.is_disposable = true;
@@ -4240,7 +4300,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)
@@ -4290,6 +4349,16 @@ namespace Mono.CSharp {
 
                        } else {
 
+                               if (return_type.IsPointer || return_type.IsArray) {
+                                       Report.SymbolRelatedToPreviousError (mi);
+                                       Type t = return_type.GetElementType ();
+                                       Report.SymbolRelatedToPreviousError (t);
+                                       Report.Error (202, hm.Location, "foreach requires that the return type '{0}' of '{1}' must have a suitable public MoveNext method and public Current property", 
+                                               TypeManager.CSharpName (return_type), TypeManager.GetFullNameSignature (m));
+                                       hm.get_enumerator = mi;
+                                       return false;
+                               }
+
                                //
                                // Ok, so they dont return an IEnumerable, we will have to
                                // find if they support the GetEnumerator pattern.
@@ -4354,7 +4423,7 @@ namespace Mono.CSharp {
                //
                ForeachHelperMethods ProbeCollectionType (EmitContext ec, Type t)
                {
-                       ForeachHelperMethods hm = new ForeachHelperMethods (ec);
+                       ForeachHelperMethods hm = new ForeachHelperMethods (ec, loc);
 
                        for (Type tt = t; tt != null && tt != TypeManager.object_type;){
                                if (TryType (tt, hm))
@@ -4447,7 +4516,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){
@@ -4544,7 +4614,7 @@ namespace Mono.CSharp {
                                ig.MarkLabel (loop);
 
                                if (ec.InIterator)
-                                       ec.EmitThis ();
+                                       ig.Emit (OpCodes.Ldarg_0);
                                
                                copy.EmitThis (ig);
                                copy.EmitLoad (ig);
@@ -4613,7 +4683,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++){