2010-07-05 Marek Safar <marek.safar@gmail.com>
authorMarek Safar <marek.safar@gmail.com>
Mon, 5 Jul 2010 17:28:32 +0000 (17:28 -0000)
committerMarek Safar <marek.safar@gmail.com>
Mon, 5 Jul 2010 17:28:32 +0000 (17:28 -0000)
* context.cs, expression.cs, ecore.cs: BaseThis is fully based on
this expression (Fixes #619904).

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

mcs/mcs/ChangeLog
mcs/mcs/context.cs
mcs/mcs/ecore.cs
mcs/mcs/expression.cs

index 4e813fc4e5635a0aa0f8b2cad1c6d387fd4641a7..6ea22d7e8b4cbc49873c634c39170d9bc26bee8e 100644 (file)
@@ -1,3 +1,8 @@
+2010-07-05  Marek Safar  <marek.safar@gmail.com>
+
+       * context.cs, expression.cs, ecore.cs: BaseThis is fully based on
+       this expression (Fixes #619904).
+
 2010-07-05  Marek Safar  <marek.safar@gmail.com>
 
        * membercache.cs, class.cs: Don't use base member to check for
index 89db3023bd067ddbbea54fa502efd056c3665c06..2d89d2b9a2eb03d42c3c9c42e6982e38deb9fb95 100644 (file)
@@ -403,10 +403,7 @@ namespace Mono.CSharp
                public Expression GetThis (Location loc)
                {
                        This my_this = new This (loc);
-
-                       if (!my_this.ResolveBase (this))
-                               my_this = null;
-
+                       my_this.ResolveBase (this);
                        return my_this;
                }
 
index 1f9f4998a57074d022913f2de08ba8b7fe158708..137709384656bda5e69b617bacef2f511a70501a 100644 (file)
@@ -2700,10 +2700,10 @@ namespace Mono.CSharp {
                //
                // Converts best base candidate for virtual method starting from QueriedBaseType
                //
-               protected MethodSpec CandidateToBaseOverride (MethodSpec method)
+               protected MethodSpec CandidateToBaseOverride (ResolveContext rc, MethodSpec method)
                {
                        //
-                       // Only when base.member is used
+                       // Only when base.member is used and method is virtual
                        //
                        if (!IsBase || method.DeclaringType == InstanceExpression.Type)
                                return method;
@@ -2712,11 +2712,14 @@ namespace Mono.CSharp {
                        // Overload resulution works on virtual or non-virtual members only (no overrides). That
                        // means for base.member access we have to find the closest match after we found best candidate
                        //
-                       if ((method.Modifiers & Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.STATIC) != Modifiers.STATIC) {
+                       if ((method.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.STATIC)) != Modifiers.STATIC) {
                                var base_override = MemberCache.FindMember (InstanceExpression.Type, new MemberFilter (method), BindingRestriction.InstanceOnly) as MethodSpec;
                                if (base_override != null && base_override.DeclaringType != method.DeclaringType) {
                                        if (base_override.IsGeneric)
-                                               return base_override.MakeGenericMethod (method.TypeArguments);
+                                               base_override = base_override.MakeGenericMethod (method.TypeArguments);
+
+                                       if (rc.CurrentAnonymousMethod != null)
+                                               throw new NotImplementedException ("base call hoisting");
 
                                        return base_override;
                                }
@@ -3888,7 +3891,7 @@ namespace Mono.CSharp {
                                return this;
                        }
 
-                       best_candidate = CandidateToBaseOverride (best_candidate);
+                       best_candidate = CandidateToBaseOverride (ec, best_candidate);
 
                        //
                        // And now check if the arguments are all
@@ -4840,7 +4843,7 @@ namespace Mono.CSharp {
                                UnsafeError (ec, loc);
                        }
 
-                       getter = CandidateToBaseOverride (spec.Get);
+                       getter = CandidateToBaseOverride (ec, spec.Get);
 
                        //
                        // Only base will allow this invocation to happen.
@@ -4913,7 +4916,7 @@ namespace Mono.CSharp {
                        if (!InstanceResolve (ec, TypeManager.IsStruct (spec.DeclaringType), must_do_cs1540_check))
                                return null;
 
-                       setter = CandidateToBaseOverride (spec.Set);
+                       setter = CandidateToBaseOverride (ec, spec.Set);
                        
                        //
                        // Only base will allow this invocation to happen.
index 63cdbce18be73466dc31cd9dad2d6a666b7a5d47..0a18b8f49c72fa57d3b34ce7dd23a91a11cabf32 100644 (file)
@@ -6505,6 +6505,20 @@ namespace Mono.CSharp {
                        this.loc = loc;
                }
 
+               #region Properties
+
+               public override string Name {
+                       get { return "this"; }
+               }
+
+               public override bool IsRef {
+                       get { return type.IsStruct; }
+               }
+
+               protected override ILocalVariable Variable {
+                       get { return ThisVariable.Instance; }
+               }
+
                public override VariableInfo VariableInfo {
                        get { return variable_info; }
                }
@@ -6513,6 +6527,21 @@ namespace Mono.CSharp {
                        get { return false; }
                }
 
+               #endregion
+
+               protected virtual void Error_ThisNotAvailable (ResolveContext ec)
+               {
+                       if (ec.IsStatic && !ec.HasSet (ResolveContext.Options.ConstantScope)) {
+                               ec.Report.Error (26, loc, "Keyword `this' is not valid in a static property, static method, or static field initializer");
+                       } else if (ec.CurrentAnonymousMethod != null) {
+                               ec.Report.Error (1673, loc,
+                                       "Anonymous methods inside structs cannot access instance members of `this'. " +
+                                       "Consider copying `this' to a local variable outside the anonymous method and using the local instead");
+                       } else {
+                               ec.Report.Error (27, loc, "Keyword `this' is not available in the current context");
+                       }
+               }
+
                public override HoistedVariable GetHoistedVariable (AnonymousExpression ae)
                {
                        if (ae == null)
@@ -6530,14 +6559,6 @@ namespace Mono.CSharp {
                        return null;
                }
 
-               public override bool IsRef {
-                       get { return type.IsStruct; }
-               }
-
-               protected override ILocalVariable Variable {
-                       get { return ThisVariable.Instance; }
-               }
-
                public static bool IsThisAvailable (ResolveContext ec, bool ignoreAnonymous)
                {
                        if (ec.IsStatic || ec.HasAny (ResolveContext.Options.FieldInitializerScope | ResolveContext.Options.BaseInitializer | ResolveContext.Options.ConstantScope))
@@ -6552,21 +6573,10 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               public bool ResolveBase (ResolveContext ec)
+               public virtual void ResolveBase (ResolveContext ec)
                {
-                       eclass = ExprClass.Variable;
-                       type = ec.CurrentType;
-
                        if (!IsThisAvailable (ec, false)) {
-                               if (ec.IsStatic && !ec.HasSet (ResolveContext.Options.ConstantScope)) {
-                                       ec.Report.Error (26, loc, "Keyword `this' is not valid in a static property, static method, or static field initializer");
-                               } else if (ec.CurrentAnonymousMethod != null) {
-                                       ec.Report.Error (1673, loc,
-                                               "Anonymous methods inside structs cannot access instance members of `this'. " +
-                                               "Consider copying `this' to a local variable outside the anonymous method and using the local instead");
-                               } else {
-                                       ec.Report.Error (27, loc, "Keyword `this' is not available in the current context");
-                               }
+                               Error_ThisNotAvailable (ec);
                        }
 
                        var block = ec.CurrentBlock;
@@ -6579,8 +6589,9 @@ namespace Mono.CSharp {
                                        am.SetHasThisAccess ();
                                }
                        }
-                       
-                       return true;
+
+                       eclass = ExprClass.Variable;
+                       type = ec.CurrentType;
                }
 
                //
@@ -6614,8 +6625,7 @@ namespace Mono.CSharp {
 
                override public Expression DoResolveLValue (ResolveContext ec, Expression right_side)
                {
-                       if (!ResolveBase (ec))
-                               return null;
+                       ResolveBase (ec);
 
                        if (variable_info != null)
                                variable_info.SetAssigned (ec);
@@ -6637,10 +6647,6 @@ namespace Mono.CSharp {
                        throw new NotImplementedException ();
                }
 
-               public override string Name {
-                       get { return "this"; }
-               }
-
                public override bool Equals (object obj)
                {
                        This t = obj as This;
@@ -7499,7 +7505,7 @@ namespace Mono.CSharp {
 
                protected override void Error_TypeDoesNotContainDefinition (ResolveContext ec, TypeSpec type, string name)
                {
-                       if (RootContext.Version > LanguageVersion.ISO_2 && !ec.Compiler.IsRuntimeBinder &&
+                       if (RootContext.Version > LanguageVersion.ISO_2 && !ec.Compiler.IsRuntimeBinder && !(expr is BaseThis) &&
                                ((expr.eclass & (ExprClass.Value | ExprClass.Variable)) != 0)) {
                                ec.Report.Error (1061, loc, "Type `{0}' does not contain a definition for `{1}' and no " +
                                        "extension method `{1}' of type `{0}' could be found " +
@@ -8270,59 +8276,50 @@ namespace Mono.CSharp {
        //
        // A base access expression
        //
-       public class BaseThis : Expression
+       public class BaseThis : This
        {
                public BaseThis (Location loc)
+                       : base (loc)
                {
-                       this.loc = loc;
                }
 
                public BaseThis (TypeSpec type, Location loc)
+                       : base (loc)
                {
                        this.type = type;
                        eclass = ExprClass.Variable;
-                       this.loc = loc;
                }
 
                public override Expression CreateExpressionTree (ResolveContext ec)
                {
                        ec.Report.Error (831, loc, "An expression tree may not contain a base access");
-
-                       Arguments args = new Arguments (1);
-                       args.Add (new Argument (this));
-                       return CreateExpressionFactoryCall (ec, "Constant", args);
-               }
-
-               protected override void CloneTo (CloneContext clonectx, Expression target)
-               {
-                       // Nothing to clone
+                       return base.CreateExpressionTree (ec);
                }
 
-               protected override Expression DoResolve (ResolveContext rc)
+               public override void ResolveBase (ResolveContext ec)
                {
-                       type = rc.CurrentType.BaseType;
-
-                       if (!This.IsThisAvailable (rc, false)) {
-                               if (rc.IsStatic) {
-                                       rc.Report.Error (1511, loc, "Keyword `base' is not available in a static method");
-                               } else {
-                                       rc.Report.Error (1512, loc, "Keyword `base' is not available in the current context");
-                               }
-                       }
-
-                       eclass = ExprClass.Variable;
-                       return this;
+                       base.ResolveBase (ec);
+                       type = ec.CurrentType.BaseType;
                }
 
                public override void Emit (EmitContext ec)
                {
-                       ec.Emit (OpCodes.Ldarg_0);
+                       base.Emit (ec);
 
                        if (ec.CurrentType.IsStruct) {
                                ec.Emit (OpCodes.Ldobj, ec.CurrentType);
                                ec.Emit (OpCodes.Box, ec.CurrentType);
                        }
                }
+
+               protected override void Error_ThisNotAvailable (ResolveContext ec)
+               {
+                       if (ec.IsStatic) {
+                               ec.Report.Error (1511, loc, "Keyword `base' is not available in a static method");
+                       } else {
+                               ec.Report.Error (1512, loc, "Keyword `base' is not available in the current context");
+                       }
+               }
        }
 
        /// <summary>