//
// 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;
// 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;
}
return this;
}
- best_candidate = CandidateToBaseOverride (best_candidate);
+ best_candidate = CandidateToBaseOverride (ec, best_candidate);
//
// And now check if the arguments are all
UnsafeError (ec, loc);
}
- getter = CandidateToBaseOverride (spec.Get);
+ getter = CandidateToBaseOverride (ec, spec.Get);
//
// Only base will allow this invocation to happen.
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.
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; }
}
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)
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))
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;
am.SetHasThisAccess ();
}
}
-
- return true;
+
+ eclass = ExprClass.Variable;
+ type = ec.CurrentType;
}
//
override public Expression DoResolveLValue (ResolveContext ec, Expression right_side)
{
- if (!ResolveBase (ec))
- return null;
+ ResolveBase (ec);
if (variable_info != null)
variable_info.SetAssigned (ec);
throw new NotImplementedException ();
}
- public override string Name {
- get { return "this"; }
- }
-
public override bool Equals (object obj)
{
This t = obj as This;
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 " +
//
// 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>