**** Merged from MCS ****
[mono.git] / mcs / gmcs / ecore.cs
index 02265965487956672f017ee00a61261a8b317aef..743b255c62697aaa352b5ec0018ebccd130bb2b8 100755 (executable)
@@ -206,22 +206,9 @@ namespace Mono.CSharp {
                /// <summary>
                ///   Utility wrapper routine for Warning, just to beautify the code
                /// </summary>
-               public void Warning (int warning, string s)
+               public void Warning (int code, string format, params object[] args)
                {
-                       if (!Location.IsNull (loc))
-                               Report.Warning (warning, loc, s);
-                       else
-                               Report.Warning (warning, s);
-               }
-
-               /// <summary>
-               ///   Utility wrapper routine for Warning, only prints the warning if
-               ///   warnings of level `level' are enabled.
-               /// </summary>
-               public void Warning (int warning, int level, string s)
-               {
-                       if (level <= RootContext.WarningLevel)
-                               Warning (warning, s);
+                       Report.Warning (code, loc, format, args);
                }
 
                /// <summary>
@@ -733,12 +720,12 @@ namespace Mono.CSharp {
 
 
                        if (qualifier_type != null)
-                               Report.Error_T (122, loc, TypeManager.CSharpName (qualifier_type) + "." + name);
+                               Report.Error (122, loc, "'{0}' is inaccessible due to its protection level", TypeManager.CSharpName (qualifier_type) + "." + name);
                        else if (name == ".ctor") {
                                Report.Error (143, loc, String.Format ("The type {0} has no constructors defined",
                                                                       TypeManager.CSharpName (queried_type)));
                        } else {
-                               Report.Error_T (122, loc, name);
+                               Report.Error (122, loc, "'{0}' is inaccessible due to its protection level", name);
                }
                }
 
@@ -1280,13 +1267,6 @@ namespace Mono.CSharp {
                                return 0;
                }
 
-               //
-               // Default implementation of IAssignMethod.CacheTemporaries
-               //
-               public virtual void CacheTemporaries (EmitContext ec)
-               {
-               }
-
                static void Error_NegativeArrayIndex (Location loc)
                {
                        Report.Error (284, loc, "Can not create array with a negative size");
@@ -2269,7 +2249,7 @@ namespace Mono.CSharp {
                                if (!me.IsStatic &&
                                    TypeManager.IsSubclassOrNestedChildOf (me.InstanceExpression.Type, me.DeclaringType) &&
                                    me.InstanceExpression.Type != me.DeclaringType &&
-                                   !me.InstanceExpression.Type.IsSubclassOf (me.DeclaringType) &&
+                                   !TypeManager.IsSubclassOf (me.InstanceExpression.Type, me.DeclaringType) &&
                                    (!intermediate || !MemberAccess.IdenticalNameAndTypeName (ec, this, e, loc))) {
                                        Error (38, "Cannot access nonstatic member `" + me.Name + "' of " +
                                               "outer type `" + me.DeclaringType + "' via nested type `" +
@@ -2378,11 +2358,6 @@ namespace Mono.CSharp {
                        }
                }
 
-               public virtual TypeExpr[] GetInterfaces ()
-               {
-                       return TypeManager.GetInterfaces (Type);
-               }
-
                public abstract TypeExpr DoResolveAsTypeStep (EmitContext ec);
 
                public virtual Type ResolveType (EmitContext ec)
@@ -2490,6 +2465,16 @@ namespace Mono.CSharp {
                }
        }
 
+       /// <summary>
+       ///   Represents an "unbound generic type", ie. typeof (Foo<>).
+       ///   See 14.5.11.
+       /// </summary>
+       public class UnboundTypeExpression : TypeLookupExpression {
+               public UnboundTypeExpression (string name)
+                       : base (name)
+               { }
+       }
+
        public class TypeAliasExpression : TypeExpr, IAlias {
                TypeExpr texpr;
                TypeArguments args;
@@ -2594,6 +2579,7 @@ namespace Mono.CSharp {
                bool is_explicit_impl = false;
                bool has_type_arguments = false;
                bool identical_type_name = false;
+               bool is_base;
                
                public MethodGroupExpr (MemberInfo [] mi, Location l)
                {
@@ -2678,6 +2664,15 @@ namespace Mono.CSharp {
                        }
                }
 
+               public bool IsBase {
+                       get {
+                               return is_base;
+                       }
+                       set {
+                               is_base = value;
+                       }
+               }
+
                public string Name {
                        get {
                                //return Methods [0].Name;
@@ -2824,9 +2819,9 @@ namespace Mono.CSharp {
                Expression instance_expr;
                VariableInfo variable_info;
                
-               LocalTemporary temporary;
-               IMemoryLocation instance_ml;
-               bool have_temporary;
+               LocalTemporary temp;
+               bool prepared;
+               bool is_field_initializer;
                
                public FieldExpr (FieldInfo fi, Location l)
                {
@@ -2870,6 +2865,16 @@ namespace Mono.CSharp {
                        }
                }
 
+               public bool IsFieldInitializer {
+                       get {
+                               return is_field_initializer;
+                       }
+
+                       set {
+                               is_field_initializer = value;
+                       }
+               }
+
                public VariableInfo VariableInfo {
                        get {
                                return variable_info;
@@ -2970,7 +2975,8 @@ namespace Mono.CSharp {
                                        Report_AssignToReadonly (false);
 
                                Type ctype;
-                               if (ec.TypeContainer.CurrentType != null)
+                               if (!is_field_initializer &&
+                                   (ec.TypeContainer.CurrentType != null))
                                        ctype = ec.TypeContainer.CurrentType.ResolveType (ec);
                                else
                                        ctype = ec.ContainerType;
@@ -2992,37 +2998,8 @@ namespace Mono.CSharp {
 
                        return true;
                }
-
-               public override void CacheTemporaries (EmitContext ec)
-               {
-                       if (!FieldInfo.IsStatic && (temporary == null))
-                               temporary = new LocalTemporary (ec, instance_expr.Type);
-               }
-
-               void EmitInstance (EmitContext ec)
-               {
-                       if (instance_expr.Type.IsValueType)
-                               CacheTemporaries (ec);
-
-                       if ((temporary == null) || have_temporary)
-                               return;
-
-                       if (instance_expr.Type.IsValueType) {
-                               instance_ml = instance_expr as IMemoryLocation;
-                               if (instance_ml == null) {
-                                       instance_expr.Emit (ec);
-                                       temporary.Store (ec);
-                                       instance_ml = temporary;
-                               }
-                       } else {
-                               instance_expr.Emit (ec);
-                               temporary.Store (ec);
-                       }
-
-                       have_temporary = true;
-               }
-
-               override public void Emit (EmitContext ec)
+               
+               public void Emit (EmitContext ec, bool leave_copy)
                {
                        ILGenerator ig = ec.ig;
                        bool is_volatile = false;
@@ -3042,46 +3019,52 @@ namespace Mono.CSharp {
                                        ig.Emit (OpCodes.Volatile);
                                
                                ig.Emit (OpCodes.Ldsfld, FieldInfo);
-                               return;
+                       } else {
+                               if (!prepared)
+                                       EmitInstance (ec);
+
+                               if (is_volatile)
+                                       ig.Emit (OpCodes.Volatile);
+
+                               ig.Emit (OpCodes.Ldfld, FieldInfo);
                        }
-                       
-                       EmitInstance (ec);
-                       if (instance_ml != null)
-                               instance_ml.AddressOf (ec, AddressOp.Load);
-                       else if (temporary != null)
-                               temporary.Emit (ec);
-                       else
-                               instance_expr.Emit (ec);
 
-                       if (is_volatile)
-                               ig.Emit (OpCodes.Volatile);
-                       
-                       ig.Emit (OpCodes.Ldfld, FieldInfo);
+                       if (leave_copy) {
+                               ec.ig.Emit (OpCodes.Dup);
+                               if (!FieldInfo.IsStatic) {
+                                       temp = new LocalTemporary (ec, this.Type);
+                                       temp.Store (ec);
+                               }
+                       }
                }
 
-               public void EmitAssign (EmitContext ec, Expression source)
+               public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
                {
                        FieldAttributes fa = FieldInfo.Attributes;
                        bool is_static = (fa & FieldAttributes.Static) != 0;
                        bool is_readonly = (fa & FieldAttributes.InitOnly) != 0;
                        ILGenerator ig = ec.ig;
+                       prepared = prepare_for_load;
 
                        if (is_readonly && !ec.IsConstructor){
                                Report_AssignToReadonly (!is_static);
                                return;
                        }
 
-                       if (!is_static){
+                       if (!is_static) {
                                EmitInstance (ec);
-                               if (instance_ml != null)
-                                       instance_ml.AddressOf (ec, AddressOp.Store);
-                               else if (temporary != null)
-                                       temporary.Emit (ec);
-                               else
-                                       instance_expr.Emit (ec);
+                               if (prepare_for_load)
+                                       ig.Emit (OpCodes.Dup);
                        }
 
                        source.Emit (ec);
+                       if (leave_copy) {
+                               ec.ig.Emit (OpCodes.Dup);
+                               if (!FieldInfo.IsStatic) {
+                                       temp = new LocalTemporary (ec, this.Type);
+                                       temp.Store (ec);
+                               }
+                       }
 
                        if (FieldInfo is FieldBuilder){
                                FieldBase f = TypeManager.GetField (FieldInfo);
@@ -3097,6 +3080,29 @@ namespace Mono.CSharp {
                                ig.Emit (OpCodes.Stsfld, FieldInfo);
                        else 
                                ig.Emit (OpCodes.Stfld, FieldInfo);
+                       
+                       if (temp != null)
+                               temp.Emit (ec);
+               }
+
+               void EmitInstance (EmitContext ec)
+               {
+                       if (instance_expr.Type.IsValueType) {
+                               if (instance_expr is IMemoryLocation) {
+                                       ((IMemoryLocation) instance_expr).AddressOf (ec, AddressOp.LoadStore);
+                               } else {
+                                       LocalTemporary t = new LocalTemporary (ec, instance_expr.Type);
+                                       instance_expr.Emit (ec);
+                                       t.Store (ec);
+                                       t.AddressOf (ec, AddressOp.Store);
+                               }
+                       } else
+                               instance_expr.Emit (ec);
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       Emit (ec, false);
                }
                
                public void AddressOf (EmitContext ec, AddressOp mode)
@@ -3148,20 +3154,7 @@ namespace Mono.CSharp {
                        if (FieldInfo.IsStatic){
                                ig.Emit (OpCodes.Ldsflda, FieldInfo);
                        } else {
-                               //
-                               // In the case of `This', we call the AddressOf method, which will
-                               // only load the pointer, and not perform an Ldobj immediately after
-                               // the value has been loaded into the stack.
-                               //
                                EmitInstance (ec);
-                               if (instance_ml != null)
-                                       instance_ml.AddressOf (ec, AddressOp.LoadStore);
-                               else if (temporary != null)
-                                       temporary.Emit (ec);
-                               else if (instance_expr is This)
-                                       ((This)instance_expr).AddressOf (ec, AddressOp.LoadStore);
-                               else
-                                       instance_expr.Emit (ec);
                                ig.Emit (OpCodes.Ldflda, FieldInfo);
                        }
                }
@@ -3200,8 +3193,8 @@ namespace Mono.CSharp {
                bool must_do_cs1540_check;
                
                Expression instance_expr;
-               LocalTemporary temporary;
-               bool have_temporary;
+               LocalTemporary temp;
+               bool prepared;
 
                public PropertyExpr (EmitContext ec, PropertyInfo pi, Location l)
                {
@@ -3379,7 +3372,7 @@ namespace Mono.CSharp {
                                is_static = true;
 
                        if (setter == null && getter == null){
-                               Report.Error_T (122, loc, PropertyInfo.Name);
+                               Report.Error (122, loc, "'{0}' is inaccessible due to its protection level", PropertyInfo.Name);
                        }
                }
 
@@ -3495,32 +3488,53 @@ namespace Mono.CSharp {
                                              PropertyInfo.DeclaringType + "." +PropertyInfo.Name);
                                return null;
                        }
+
+                       //
+                       // Check that we are not making changes to a temporary memory location
+                       //
+                       if (instance_expr != null && instance_expr.Type.IsValueType && !(instance_expr is IMemoryLocation)) {
+                               // FIXME: Provide better error reporting.
+                               Error (1612, "Cannot modify expression because it is not a variable.");
+                               return null;
+                       }
+
                        return this;
                }
 
-               public override void CacheTemporaries (EmitContext ec)
+
+               
+               public override void Emit (EmitContext ec)
                {
-                       if (!is_static)
-                               temporary = new LocalTemporary (ec, instance_expr.Type);
+                       Emit (ec, false);
                }
-
-               Expression EmitInstance (EmitContext ec)
+               
+               void EmitInstance (EmitContext ec)
                {
-                       if (temporary != null){
-                               if (!have_temporary){
+                       if (is_static)
+                               return;
+
+                       if (instance_expr.Type.IsValueType) {
+                               if (instance_expr is IMemoryLocation) {
+                                       ((IMemoryLocation) instance_expr).AddressOf (ec, AddressOp.LoadStore);
+                               } else {
+                                       LocalTemporary t = new LocalTemporary (ec, instance_expr.Type);
                                        instance_expr.Emit (ec);
-                                       temporary.Store (ec);
-                                       have_temporary = true;
+                                       t.Store (ec);
+                                       t.AddressOf (ec, AddressOp.Store);
                                }
-                               return temporary;
                        } else
-                               return instance_expr;
+                               instance_expr.Emit (ec);
+                       
+                       if (prepared)
+                               ec.ig.Emit (OpCodes.Dup);
                }
 
-               override public void Emit (EmitContext ec)
+               
+               public void Emit (EmitContext ec, bool leave_copy)
                {
-                       Expression expr = EmitInstance (ec);
-
+                       if (!prepared)
+                               EmitInstance (ec);
+                       
                        //
                        // Special case: length of single dimension array property is turned into ldlen
                        //
@@ -3532,30 +3546,50 @@ namespace Mono.CSharp {
                                // System.Array.Length can be called, but the Type does not
                                // support invoking GetArrayRank, so test for that case first
                                //
-                               if (iet != TypeManager.array_type && (iet.GetArrayRank () == 1)){
-                                       expr.Emit (ec);
+                               if (iet != TypeManager.array_type && (iet.GetArrayRank () == 1)) {
                                        ec.ig.Emit (OpCodes.Ldlen);
                                        ec.ig.Emit (OpCodes.Conv_I4);
                                        return;
                                }
                        }
 
-                       Invocation.EmitCall (ec, IsBase, IsStatic, expr, getter, null, loc);
+                       Invocation.EmitCall (ec, IsBase, IsStatic, new EmptyAddressOf (), getter, null, loc);
+                       
+                       if (!leave_copy)
+                               return;
                        
+                       ec.ig.Emit (OpCodes.Dup);
+                       if (!is_static) {
+                               temp = new LocalTemporary (ec, this.Type);
+                               temp.Store (ec);
+                       }
                }
 
                //
                // Implements the IAssignMethod interface for assignments
                //
-               public void EmitAssign (EmitContext ec, Expression source)
+               public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
                {
-                       Expression expr = EmitInstance (ec);
-
-                       Argument arg = new Argument (source, Argument.AType.Expression);
-                       ArrayList args = new ArrayList ();
+                       prepared = prepare_for_load;
+                       
+                       EmitInstance (ec);
 
-                       args.Add (arg);
-                       Invocation.EmitCall (ec, IsBase, IsStatic, expr, setter, args, loc);
+                       source.Emit (ec);
+                       if (leave_copy) {
+                               ec.ig.Emit (OpCodes.Dup);
+                               if (!is_static) {
+                                       temp = new LocalTemporary (ec, this.Type);
+                                       temp.Store (ec);
+                               }
+                       }
+                       
+                       ArrayList args = new ArrayList (1);
+                       args.Add (new Argument (new EmptyAddressOf (), Argument.AType.Expression));
+                       
+                       Invocation.EmitCall (ec, IsBase, IsStatic, new EmptyAddressOf (), setter, args, loc);
+                       
+                       if (temp != null)
+                               temp.Emit (ec);
                }
 
                override public void EmitStatement (EmitContext ec)