**** Merged r36189 from MCS ****
authorMartin Baulig <martin@novell.com>
Thu, 18 Nov 2004 06:40:39 +0000 (06:40 -0000)
committerMartin Baulig <martin@novell.com>
Thu, 18 Nov 2004 06:40:39 +0000 (06:40 -0000)
2004-11-15  Miguel de Icaza  <miguel@ximian.com>

* anonymous.cs (AnonymousMethod.Error_AddressOfCapturedVar): New
routine that is used to report the use of a captured variable
whose address has been taken.

There are two checks: one when variables are being captured and
the other check is when the address of a variable is taken.

(because an anonymous methods might be resolved before *or* after
the address has been taken) and

* expression.cs (Conditional.DoResolve): Remove the special
casing that Martin added to trueExpr and falseExpr being both
NullLiteral.  We get the right behavior now just by introducing
the null_type into the compiler.

* convert.cs (ExplicitConversion): Change the code to use
null_type instead of testing `expr is NullLiteral'.
(ImplicitConversionStandard): use null_type too.
(ImplicitReferenceConversionExists): use null_type too.
(ImplicitReferenceConversion): use null_type too.

* literal.cs: The type of `NullLiteral' is now null_type instead
of object_type.
(Resolve): Set the type here.

* typemanager.cs: Introduce null_type.

svn path=/trunk/mcs/; revision=36250

mcs/gmcs/ChangeLog
mcs/gmcs/anonymous.cs
mcs/gmcs/const.cs
mcs/gmcs/convert.cs
mcs/gmcs/expression.cs
mcs/gmcs/literal.cs
mcs/gmcs/namespace.cs
mcs/gmcs/statement.cs
mcs/gmcs/typemanager.cs

index 9091ef6fa1724e74e5371f3872c1522826b3e424..f7bbd8b08185de090842938e85e03945e018f4ca 100755 (executable)
@@ -1,3 +1,32 @@
+2004-11-15  Miguel de Icaza  <miguel@ximian.com>
+
+       * anonymous.cs (AnonymousMethod.Error_AddressOfCapturedVar): New
+       routine that is used to report the use of a captured variable
+       whose address has been taken.
+
+       There are two checks: one when variables are being captured and
+       the other check is when the address of a variable is taken. 
+       
+       (because an anonymous methods might be resolved before *or* after
+       the address has been taken) and 
+
+       * expression.cs (Conditional.DoResolve): Remove the special
+       casing that Martin added to trueExpr and falseExpr being both
+       NullLiteral.  We get the right behavior now just by introducing
+       the null_type into the compiler. 
+
+       * convert.cs (ExplicitConversion): Change the code to use
+       null_type instead of testing `expr is NullLiteral'.
+       (ImplicitConversionStandard): use null_type too.
+       (ImplicitReferenceConversionExists): use null_type too.
+       (ImplicitReferenceConversion): use null_type too.
+
+       * literal.cs: The type of `NullLiteral' is now null_type instead
+       of object_type. 
+       (Resolve): Set the type here.
+
+       * typemanager.cs: Introduce null_type.
+
 2004-11-18  Martin Baulig  <martin@ximian.com>
 
        * rootcontext.cs
index d13a2093abeecc7fec89013bccabe2f04dd7e450..d0fa55e555d3de659e730d9e56f16e73ba4c43a8 100644 (file)
@@ -314,6 +314,12 @@ namespace Mono.CSharp {
                        aec.EmitMeta (Block, amp);
                        aec.EmitResolvedTopBlock (Block, unreachable);
                }
+
+               public static void Error_AddressOfCapturedVar (string name, Location loc)
+               {
+                       Report.Error (1686, loc,
+                                     "Variable {0} is captured in an anonymous method and its address is also being taken: they are exclusive", name);
+               }
        }
 
        //
index fbab41568ecf0ae6ca93c517a0ccc785b121ad9f..199dd5c3e45678542a94d547517dd6e4d5883755 100755 (executable)
@@ -82,7 +82,7 @@ namespace Mono.CSharp {
                        while (ttype.IsArray)
                            ttype = TypeManager.GetElementType (ttype);
                        
-                       if (!TypeManager.IsBuiltinType (ttype) && (!ttype.IsSubclassOf (TypeManager.enum_type)) && !(Expr is NullLiteral)) {
+                       if (!TypeManager.IsBuiltinType(ttype) && (!ttype.IsSubclassOf(TypeManager.enum_type)) && !(Expr is NullLiteral)){
                                Report.Error (
                                        -3, Location,
                                        "Constant type is not valid (only system types are allowed)");
@@ -108,7 +108,7 @@ namespace Mono.CSharp {
                        bool fail;
 
                        // from the null type to any reference-type.
-                       if (expr is NullLiteral && !type.IsValueType && !TypeManager.IsEnumType (type))
+                       if (expr.Type == TypeManager.null_type && !type.IsValueType && !TypeManager.IsEnumType (type))
                                return NullLiteral.Null;
 
                        if (!Convert.ImplicitStandardConversionExists (Convert.ConstantEC, expr, type)){
index dc3bd4ee5da15d275cf6ca5ad4745d5b82a2f414..d95cefc32f4bda960092fad117432a5644a454c4 100644 (file)
@@ -173,7 +173,7 @@ namespace Mono.CSharp {
                        } else if (target_type == TypeManager.value_type) {
                                if (TypeManager.IsValueType (expr_type))
                                        return new BoxedCast (expr);
-                               if (expr is NullLiteral)
+                               if (expr_type == TypeManager.null_type)
                                        return new NullCast (expr, target_type);
 
                                return null;
@@ -195,7 +195,7 @@ namespace Mono.CSharp {
                        // Always ensure that the code here and there is in sync
 
                        // from the null type to any reference-type.
-                       if (expr is NullLiteral){
+                       if (expr_type == TypeManager.null_type){
                                if (target_type.IsPointer)
                                        return NullPointer.Null;
                                        
@@ -346,7 +346,7 @@ namespace Mono.CSharp {
                                        return true;
                                
                        // from the null type to any reference-type.
-                       if (expr is NullLiteral && !target_type.IsValueType && !TypeManager.IsEnumType (target_type))
+                       if (expr_type == TypeManager.null_type && !target_type.IsValueType && !TypeManager.IsEnumType (target_type))
                                return true;
 
                        // from a generic type definition to a generic instance.
@@ -1197,7 +1197,7 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       if (expr_type.Equals (target_type) && !(expr is NullLiteral))
+                       if (expr_type.Equals (target_type) && !TypeManager.IsNullType (expr_type))
                                return expr;
 
                        e = ImplicitNumericConversion (ec, expr, target_type, loc);
@@ -1233,7 +1233,7 @@ namespace Mono.CSharp {
                                }
                                
                                if (target_type.IsPointer) {
-                                       if (expr is NullLiteral)
+                                       if (expr_type == TypeManager.null_type)
                                                return new EmptyCast (expr, target_type);
 
                                        if (expr_type == TypeManager.void_ptr_type)
@@ -1846,23 +1846,20 @@ namespace Mono.CSharp {
                        //
                        // Unboxing conversion.
                        //
-                       if (expr_type == TypeManager.object_type && target_type.IsValueType){
-                               if (expr is NullLiteral){
-                                       //
-                                       // Skip the ExplicitReferenceConversion because we can not convert
-                                       // from Null to a ValueType, and ExplicitReference wont check against
-                                       // null literal explicitly
-                                       //
-                                       goto skip_explicit;
-                               }
+                       if (expr_type == TypeManager.object_type && target_type.IsValueType)
                                return new UnboxCast (expr, target_type);
 
+                       //
+                       // Skip the ExplicitReferenceConversion because we can not convert
+                       // from Null to a ValueType, and ExplicitReference wont check against
+                       // null literal explicitly
+                       //
+                       if (expr_type != TypeManager.null_type){
+                               ne = ExplicitReferenceConversion (expr, target_type);
+                               if (ne != null)
+                                       return ne;
                        }
 
-                       ne = ExplicitReferenceConversion (expr, target_type);
-                       if (ne != null)
-                               return ne;
-
                skip_explicit:
                        if (ec.InUnsafe){
                                if (target_type.IsPointer){
index d613402d55486aea6c6414bff5d1aaf329ec4e4e..cd9bc2d94bacc5a3df7849da1b6f39299770f857 100755 (executable)
@@ -439,6 +439,15 @@ namespace Mono.CSharp {
                                        return null;
                                }
 
+                               LocalVariableReference lr = Expr as LocalVariableReference;
+                               if (lr != null){
+                                       if (lr.local_info.IsCaptured){
+                                               AnonymousMethod.Error_AddressOfCapturedVar (lr.Name, loc);
+                                               return null;
+                                       }
+                                       lr.local_info.AddressTaken = true;
+                               }
+
                                // According to the specs, a variable is considered definitely assigned if you take
                                // its address.
                                if ((variable != null) && (variable.VariableInfo != null))
@@ -2236,8 +2245,8 @@ namespace Mono.CSharp {
                        // Special cases: string or type parameter comapred to null
                        //
                        if (oper == Operator.Equality || oper == Operator.Inequality){
-                               if ((!TypeManager.IsValueType (l) && (right is NullLiteral)) ||
-                                   (!TypeManager.IsValueType (r) && (left is NullLiteral))) {
+                               if ((!TypeManager.IsValueType (l) && r == TypeManager.null_type) ||
+                                   (!TypeManager.IsValueType (r) && l == TypeManager.null_type)) {
                                        Type = TypeManager.bool_type;
                                        
                                        return this;
@@ -3487,9 +3496,6 @@ namespace Mono.CSharp {
                        if (trueExpr == null || falseExpr == null)
                                return null;
 
-                       if ((trueExpr is NullLiteral) && (falseExpr is NullLiteral))
-                               return trueExpr;
-
                        eclass = ExprClass.Value;
                        if (trueExpr.Type == falseExpr.Type)
                                type = trueExpr.Type;
@@ -3639,8 +3645,11 @@ namespace Mono.CSharp {
                                // flag it for capturing
                                //
                                if (local_info.Block.Toplevel != ec.CurrentBlock.Toplevel){
+                                       if (local_info.AddressTaken){
+                                               AnonymousMethod.Error_AddressOfCapturedVar (local_info.Name, loc);
+                                               return null;
+                                       }
                                        ec.CaptureVariable (local_info);
-                                       //Console.WriteLine ("Capturing at " + loc);
                                }
                        }
                        
@@ -4316,9 +4325,9 @@ namespace Mono.CSharp {
                                //   * There is no implicit conversion from type 'object' to other reference types
                                //  => Conversion of 'null' to a reference type is better than conversion to 'object'
                                //
-                               //  FIXME: This probably isn't necessary, since the type of a NullLiteral is 'System.Null'.
-                               //         I think it used to be 'object' and thus needed a special case to avoid the
-                               //         immediately following two checks.
+                               //  FIXME: This probably isn't necessary, since the type of a NullLiteral is the 
+                               //         null type. I think it used to be 'object' and thus needed a special 
+                               //         case to avoid the immediately following two checks.
                                //
                                if (!p.IsValueType && q == TypeManager.object_type)
                                        return p;
index 7e65784a0272f5e5a1a7ec0141208b3a765ca247..0a97d502b5046af510de45853feb4e18fba29e99 100755 (executable)
@@ -36,6 +36,16 @@ namespace System {
        
 namespace Mono.CSharp {
 
+       //
+       // The NullType just exists to compare type equality, and for
+       // expressions that might have the `null type'
+       //
+       public class NullType {
+       }
+
+       //
+       // The null Literal constant
+       //
        public class NullLiteral : Constant {
                public static readonly NullLiteral Null;
 
@@ -61,7 +71,7 @@ namespace Mono.CSharp {
 
                public override Expression DoResolve (EmitContext ec)
                {
-                       type = typeof (System.Null); 
+                       type = TypeManager.null_type;
                        return this;
                }
 
index a778000c7a74fb44c66cb26742e4315bc9e2fb04..cd94d61ae8405b88187f38eabc6e4c31b66be0b5 100755 (executable)
@@ -545,10 +545,15 @@ namespace Mono.CSharp {
                        }
                }
 
-               static void Msgtry (string s)
+               static void MsgtryRef (string s)
                {
                        Console.WriteLine ("    Try using -r:" + s);
                }
+               
+               static void MsgtryPkg (string s)
+               {
+                       Console.WriteLine ("    Try using -pkg:" + s);
+               }
 
                protected void error246 (Location loc, string name)
                {
@@ -561,35 +566,35 @@ namespace Mono.CSharp {
 
                                switch (name){
                                case "Gtk": case "GtkSharp":
-                                       Msgtry ("gtk-sharp");
+                                       MsgtryPkg ("gtk-sharp");
                                        break;
 
                                case "Gdk": case "GdkSharp":
-                                       Msgtry ("gdk-sharp");
+                                       MsgtryPkg ("gdk-sharp");
                                        break;
 
                                case "Glade": case "GladeSharp":
-                                       Msgtry ("glade-sharp");
+                                       MsgtryPkg ("glade-sharp");
                                        break;
                                                        
                                case "System.Drawing":
-                                       Msgtry ("System.Drawing");
+                                       MsgtryRef ("System.Drawing");
                                        break;
                                                        
                                case "System.Web.Services":
-                                       Msgtry ("System.Web.Services");
+                                       MsgtryRef ("System.Web.Services");
                                        break;
 
                                case "System.Web":
-                                       Msgtry ("System.Web");
+                                       MsgtryRef ("System.Web");
                                        break;
                                                        
                                case "System.Data":
-                                       Msgtry ("System.Data");
+                                       MsgtryRef ("System.Data");
                                        break;
 
                                case "System.Windows.Forms":
-                                       Msgtry ("System.Windows.Forms");
+                                       MsgtryRef ("System.Windows.Forms");
                                        break;
                                }
                        }
index ca011abcb7dd46fb2276ec1e5f2672b269f2418d..b0eb18b159f06a9003a69111c9eba016ac11ba74 100755 (executable)
@@ -981,7 +981,8 @@ namespace Mono.CSharp {
                        ReadOnly = 2,
                        Pinned = 4,
                        IsThis = 8,
-                       Captured = 16
+                       Captured = 16,
+                       AddressTaken = 32
                }
 
                Flags flags;
@@ -1069,6 +1070,16 @@ namespace Mono.CSharp {
                        }
                }
 
+               public bool AddressTaken {
+                       get {
+                               return (flags & Flags.AddressTaken) != 0;
+                       }
+
+                       set {
+                               flags |= Flags.AddressTaken;
+                       }
+               }
+
                public override string ToString ()
                {
                        return String.Format ("LocalInfo ({0},{1},{2},{3})",
index 8f3f9b6020ac2b16a1c234e2338ed66607c8cc04..745855437c67467db5b733c79d874d1bfe74f32b 100755 (executable)
@@ -55,6 +55,7 @@ public class TypeManager {
        static public Type delegate_type;
        static public Type multicast_delegate_type;
        static public Type void_type;
+       static public Type null_type;
        static public Type enumeration_type;
        static public Type array_type;
        static public Type runtime_handle_type;
@@ -1303,6 +1304,7 @@ public class TypeManager {
                // These are only used for compare purposes
                //
                anonymous_method_type = typeof (AnonymousMethod);
+               null_type = typeof (NullType);
        }
 
        //
@@ -1657,6 +1659,11 @@ public class TypeManager {
                return false;
        }
 
+       public static bool IsNullType (Type t)
+       {
+               return t == null_type;
+       }
+
        //
        // Only a quick hack to get things moving, while real runtime support appears
        //