X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fecore.cs;h=9470b01ac6fc4efaa1107081a56d21971bbb060b;hb=d8aae4dd7b6bf2a72a12a62e5359fe76b6567435;hp=5a0888205c9430a5763a4f45653219f79db8127a;hpb=332221c6213b7ad580be6eb78c51ee265b660c2b;p=mono.git diff --git a/mcs/mcs/ecore.cs b/mcs/mcs/ecore.cs index 5a0888205c9..9470b01ac6f 100644 --- a/mcs/mcs/ecore.cs +++ b/mcs/mcs/ecore.cs @@ -5,7 +5,8 @@ // Miguel de Icaza (miguel@ximian.com) // Marek Safar (marek.safar@seznam.cz) // -// (C) 2001, 2002, 2003 Ximian, Inc. +// Copyright 2001, 2002, 2003 Ximian, Inc. +// Copyright 2003-2008 Novell, Inc. // // @@ -96,15 +97,10 @@ namespace Mono.CSharp { void AddressOf (EmitContext ec, AddressOp mode); } - /// - /// This interface is implemented by variables - /// + // TODO: Rename to something meaningful, this is flow-analysis interface only public interface IVariable { - VariableInfo VariableInfo { - get; - } - - bool VerifyFixed (); + VariableInfo VariableInfo { get; } + bool IsFixed { get; } } /// @@ -165,8 +161,7 @@ namespace Mono.CSharp { return TypeManager.IsPrivateAccessible (invocation_type, mi.DeclaringType) || TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType); - if (mi.DeclaringType.Assembly == invocation_type.Assembly || - TypeManager.IsFriendAssembly (mi.DeclaringType.Assembly)) { + if (TypeManager.IsThisOrFriendAssembly (mi.DeclaringType.Assembly)) { if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem) return true; } else { @@ -229,8 +224,16 @@ namespace Mono.CSharp { // This is used if the expression should be resolved as a type or namespace name. // the default implementation fails. // - public virtual FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent) + public virtual FullNamedExpression ResolveAsTypeStep (IResolveContext rc, bool silent) { + if (!silent) { + Expression e = this; + EmitContext ec = rc as EmitContext; + if (ec != null) + e = e.Resolve (ec); + if (e != null) + e.Error_UnexpectedKind (ResolveFlags.Type, loc); + } return null; } @@ -347,9 +350,9 @@ namespace Mono.CSharp { if (TypeManager.IsGenericParameter (Type) && TypeManager.IsGenericParameter (target) && type.Name == target.Name) { #if GMCS_SOURCE - string sig1 = Type.DeclaringMethod == null ? - TypeManager.CSharpName (Type.DeclaringType) : - TypeManager.CSharpSignature (Type.DeclaringMethod); + string sig1 = type.DeclaringMethod == null ? + TypeManager.CSharpName (type.DeclaringType) : + TypeManager.CSharpSignature (type.DeclaringMethod); string sig2 = target.DeclaringMethod == null ? TypeManager.CSharpName (target.DeclaringType) : TypeManager.CSharpSignature (target.DeclaringMethod); @@ -377,7 +380,7 @@ namespace Mono.CSharp { if (b || Convert.ExplicitReferenceConversionExists (Type, target) || Convert.ExplicitUnsafe (e, target) != null || - (ec != null && Convert.UserDefinedConversion (ec, this, target, Location.Null, true) != null)) + (ec != null && Convert.ExplicitUserConversion (ec, this, target, Location.Null) != null)) { Report.Error (266, loc, "Cannot implicitly convert type `{0}' to `{1}'. " + "An explicit conversion exists (are you missing a cast?)", @@ -385,12 +388,6 @@ namespace Mono.CSharp { return; } - if (Type != TypeManager.string_type && this is Constant && !(this is EmptyConstantCast)) { - Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'", - ((Constant)(this)).GetValue ().ToString (), TypeManager.CSharpName (target)); - return; - } - Report.Error (29, loc, "Cannot implicitly convert type `{0}' to `{1}'", TypeManager.CSharpName (type), TypeManager.CSharpName (target)); @@ -577,12 +574,25 @@ namespace Mono.CSharp { /// public abstract void Emit (EmitContext ec); + // Emit code to branch to @target if this expression is equivalent to @on_true. + // The default implementation is to emit the value, and then emit a brtrue or brfalse. + // Subclasses can provide more efficient implementations, but those MUST be equivalent, + // including the use of conditional branches. Note also that a branch MUST be emitted public virtual void EmitBranchable (EmitContext ec, Label target, bool on_true) { Emit (ec); ec.ig.Emit (on_true ? OpCodes.Brtrue : OpCodes.Brfalse, target); } + // Emit this expression for its side effects, not for its value. + // The default implementation is to emit the value, and then throw it away. + // Subclasses can provide more efficient implementations, but those MUST be equivalent + public virtual void EmitSideEffect (EmitContext ec) + { + Emit (ec); + ec.ig.Emit (OpCodes.Pop); + } + /// /// Protected constructor. Only derivate types should /// be able to be created @@ -893,6 +903,11 @@ namespace Mono.CSharp { throw new NotImplementedException (); } + protected void Error_PointerInsideExpressionTree () + { + Report.Error (1944, loc, "An expression tree cannot contain an unsafe pointer operation"); + } + /// /// Returns an expression that can be used to invoke operator true /// on the expression if it exists. @@ -914,7 +929,8 @@ namespace Mono.CSharp { static Expression GetOperatorTrueOrFalse (EmitContext ec, Expression e, bool is_true, Location loc) { MethodGroupExpr operator_group; - operator_group = MethodLookup (ec.ContainerType, e.Type, is_true ? "op_True" : "op_False", loc) as MethodGroupExpr; + string mname = Operator.GetMetadataName (is_true ? Operator.OpType.True : Operator.OpType.False); + operator_group = MethodLookup (ec.ContainerType, e.Type, mname, loc) as MethodGroupExpr; if (operator_group == null) return null; @@ -926,7 +942,7 @@ namespace Mono.CSharp { if (operator_group == null) return null; - return new StaticCallExpr ((MethodInfo) operator_group, arguments, loc); + return new UserOperatorCall (operator_group, arguments, null, loc); } /// @@ -1078,7 +1094,7 @@ namespace Mono.CSharp { if (t == TypeManager.enum_type) ig.Emit (OpCodes.Ldind_Ref); else - LoadFromPtr (ig, TypeManager.EnumToUnderlying (t)); + LoadFromPtr (ig, TypeManager.GetEnumUnderlyingType (t)); } else if (t.IsValueType || TypeManager.IsGenericParameter (t)) ig.Emit (OpCodes.Ldobj, t); else if (t.IsPointer) @@ -1093,7 +1109,7 @@ namespace Mono.CSharp { public static void StoreFromPtr (ILGenerator ig, Type type) { if (TypeManager.IsEnumType (type)) - type = TypeManager.EnumToUnderlying (type); + type = TypeManager.GetEnumUnderlyingType (type); if (type == TypeManager.int32_type || type == TypeManager.uint32_type) ig.Emit (OpCodes.Stind_I4); else if (type == TypeManager.int64_type || type == TypeManager.uint64_type) @@ -1230,11 +1246,10 @@ namespace Mono.CSharp { return cloned; } - public virtual Expression CreateExpressionTree (EmitContext ec) - { - throw new NotImplementedException ( - "Expression tree conversion not implemented for " + GetType ()); - } + // + // Implementation of expression to expression tree conversion + // + public abstract Expression CreateExpressionTree (EmitContext ec); protected Expression CreateExpressionFactoryCall (string name, ArrayList args) { @@ -1248,8 +1263,21 @@ namespace Mono.CSharp { public static Expression CreateExpressionFactoryCall (string name, TypeArguments typeArguments, ArrayList args, Location loc) { - TypeExpression texpr = new TypeExpression (LinqExpression.expression_type, loc); - return new Invocation (new MemberAccess (texpr, name, typeArguments, loc), args); + return new Invocation (new MemberAccess (CreateExpressionTypeExpression (loc), name, typeArguments, loc), args); + } + + protected static TypeExpr CreateExpressionTypeExpression (Location loc) + { + TypeExpr texpr = TypeManager.expression_type_expr; + if (texpr == null) { + Type t = TypeManager.CoreLookupType ("System.Linq.Expressions", "Expression", Kind.Class, true); + if (t == null) + return null; + + TypeManager.expression_type_expr = texpr = new TypeExpression (t, Location.Null); + } + + return texpr; } } @@ -1282,6 +1310,11 @@ namespace Mono.CSharp { /// Emit that will always leave a value on the stack). /// public abstract void EmitStatement (EmitContext ec); + + public override void EmitSideEffect (EmitContext ec) + { + EmitStatement (ec); + } } /// @@ -1296,33 +1329,28 @@ namespace Mono.CSharp { /// would be "unsigned int". /// /// - public class EmptyCast : Expression + public abstract class TypeCast : Expression { protected Expression child; - protected EmptyCast (Expression child, Type return_type) + protected TypeCast (Expression child, Type return_type) { eclass = child.eclass; loc = child.Location; type = return_type; this.child = child; } - - public static Expression Create (Expression child, Type type) - { - Constant c = child as Constant; - if (c != null) - return new EmptyConstantCast (c, type); - - return new EmptyCast (child, type); - } public override Expression CreateExpressionTree (EmitContext ec) { ArrayList args = new ArrayList (2); args.Add (new Argument (child.CreateExpressionTree (ec))); args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc))); - return CreateExpressionFactoryCall ("Convert", args); + + if (type.IsPointer || child.Type.IsPointer) + Error_PointerInsideExpressionTree (); + + return CreateExpressionFactoryCall (ec.CheckState ? "ConvertChecked" : "Convert", args); } public override Expression DoResolve (EmitContext ec) @@ -1345,16 +1373,50 @@ namespace Mono.CSharp { protected override void CloneTo (CloneContext clonectx, Expression t) { - EmptyCast target = (EmptyCast) t; + TypeCast target = (TypeCast) t; target.child = child.Clone (clonectx); } + + public override bool IsNull { + get { return child.IsNull; } + } + } + + public class EmptyCast : TypeCast { + EmptyCast (Expression child, Type target_type) + : base (child, target_type) + { + } + + public static Expression Create (Expression child, Type type) + { + Constant c = child as Constant; + if (c != null) + return new EmptyConstantCast (c, type); + + EmptyCast e = child as EmptyCast; + if (e != null) + return new EmptyCast (e.child, type); + + return new EmptyCast (child, type); + } + + public override void EmitBranchable (EmitContext ec, Label label, bool on_true) + { + child.EmitBranchable (ec, label, on_true); + } + + public override void EmitSideEffect (EmitContext ec) + { + child.EmitSideEffect (ec); + } } /// /// Performs a cast using an operator (op_Explicit or op_Implicit) /// - public class OperatorCast : EmptyCast { + public class OperatorCast : TypeCast { MethodInfo conversion_operator; bool find_explicit; @@ -1385,7 +1447,7 @@ namespace Mono.CSharp { foreach (MethodInfo oper in mi) { ParameterData pd = TypeManager.GetParameterData (oper); - if (pd.ParameterType (0) == child.Type && oper.ReturnType == type) + if (pd.ParameterType (0) == child.Type && TypeManager.TypeToCoreType (oper.ReturnType) == type) return oper; } @@ -1411,7 +1473,7 @@ namespace Mono.CSharp { /// /// This is a numeric cast to a Decimal /// - public class CastToDecimal : EmptyCast { + public class CastToDecimal : TypeCast { MethodInfo conversion_operator; public CastToDecimal (Expression child) @@ -1440,7 +1502,7 @@ namespace Mono.CSharp { foreach (MethodInfo oper in mi) { ParameterData pd = TypeManager.GetParameterData (oper); - if (pd.ParameterType (0) == child.Type && oper.ReturnType == type) + if (pd.ParameterType (0) == child.Type && TypeManager.TypeToCoreType (oper.ReturnType) == type) return oper; } @@ -1458,7 +1520,7 @@ namespace Mono.CSharp { /// /// This is an explicit numeric cast from a Decimal /// - public class CastFromDecimal : EmptyCast + public class CastFromDecimal : TypeCast { static IDictionary operators; @@ -1483,7 +1545,7 @@ namespace Mono.CSharp { foreach (MethodInfo oper in all_oper) { ParameterData pd = TypeManager.GetParameterData (oper); if (pd.ParameterType (0) == TypeManager.decimal_type) - operators.Add (oper.ReturnType, oper); + operators.Add (TypeManager.TypeToCoreType (oper.ReturnType), oper); } } @@ -1533,6 +1595,17 @@ namespace Mono.CSharp { return child.ConvertExplicitly (in_checked_context, target_type); } + public override Expression CreateExpressionTree (EmitContext ec) + { + ArrayList args = new ArrayList (2); + args.Add (new Argument (child.CreateExpressionTree (ec))); + args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc))); + if (type.IsPointer) + Error_PointerInsideExpressionTree (); + + return CreateExpressionFactoryCall ("Convert", args); + } + public override Constant Increment () { return child.Increment (); @@ -1552,13 +1625,23 @@ namespace Mono.CSharp { public override bool IsZeroInteger { get { return child.IsZeroInteger; } - } + } public override void Emit (EmitContext ec) { child.Emit (ec); } + public override void EmitBranchable (EmitContext ec, Label label, bool on_true) + { + child.EmitBranchable (ec, label, on_true); + } + + public override void EmitSideEffect (EmitContext ec) + { + child.EmitSideEffect (ec); + } + public override Constant ConvertImplicitly (Type target_type) { // FIXME: Do we need to check user conversions? @@ -1596,6 +1679,16 @@ namespace Mono.CSharp { Child.Emit (ec); } + public override void EmitBranchable (EmitContext ec, Label label, bool on_true) + { + Child.EmitBranchable (ec, label, on_true); + } + + public override void EmitSideEffect (EmitContext ec) + { + Child.EmitSideEffect (ec); + } + public override bool GetAttributableValue (Type value_type, out object value) { value = GetTypedValue (); @@ -1687,7 +1780,7 @@ namespace Mono.CSharp { /// The effect of it is to box the value type emitted by the previous /// operation. /// - public class BoxedCast : EmptyCast { + public class BoxedCast : TypeCast { public BoxedCast (Expression expr, Type target_type) : base (expr, target_type) @@ -1709,9 +1802,20 @@ namespace Mono.CSharp { ec.ig.Emit (OpCodes.Box, child.Type); } + + public override void EmitSideEffect (EmitContext ec) + { + // boxing is side-effectful, since it involves runtime checks, except when boxing to Object or ValueType + // so, we need to emit the box+pop instructions in most cases + if (child.Type.IsValueType && + (type == TypeManager.object_type || type == TypeManager.value_type)) + child.EmitSideEffect (ec); + else + base.EmitSideEffect (ec); + } } - public class UnboxCast : EmptyCast { + public class UnboxCast : TypeCast { public UnboxCast (Expression expr, Type return_type) : base (expr, return_type) { @@ -1758,7 +1862,7 @@ namespace Mono.CSharp { /// context, so they should generate the conv.ovf opcodes instead of /// conv opcodes. /// - public class ConvCast : EmptyCast { + public class ConvCast : TypeCast { public enum Mode : byte { I1_U1, I1_U2, I1_U4, I1_U8, I1_CH, U1_I1, U1_CH, @@ -1966,7 +2070,7 @@ namespace Mono.CSharp { } } - public class OpcodeCast : EmptyCast { + public class OpcodeCast : TypeCast { OpCode op, op2; bool second_valid; @@ -2002,14 +2106,18 @@ namespace Mono.CSharp { if (second_valid) ec.ig.Emit (op2); - } + } + + public Type UnderlyingType { + get { return child.Type; } + } } /// /// This kind of cast is used to encapsulate a child and cast it /// to the class requested /// - public class ClassCast : EmptyCast { + public class ClassCast : TypeCast { public ClassCast (Expression child, Type return_type) : base (child, return_type) @@ -2039,37 +2147,182 @@ namespace Mono.CSharp { ec.ig.Emit (OpCodes.Castclass, type); } } + + // + // Used when resolved expression has different representations for + // expression trees and emit phase + // + public class ReducedExpression : Expression + { + class ReducedConstantExpression : Constant + { + readonly Constant expr; + readonly Expression orig_expr; + + public ReducedConstantExpression (Constant expr, Expression orig_expr) + : base (expr.Location) + { + this.expr = expr; + this.orig_expr = orig_expr; + eclass = expr.eclass; + type = expr.Type; + } + + public override string AsString () + { + return expr.AsString (); + } + + public override Expression CreateExpressionTree (EmitContext ec) + { + return orig_expr.CreateExpressionTree (ec); + } + + public override object GetValue () + { + return expr.GetValue (); + } + + public override Constant ConvertExplicitly (bool in_checked_context, Type target_type) + { + throw new NotImplementedException (); + } + + public override Expression DoResolve (EmitContext ec) + { + return this; + } + + public override Constant Increment () + { + throw new NotImplementedException (); + } + + public override bool IsDefaultValue { + get { + return expr.IsDefaultValue; + } + } + + public override bool IsNegative { + get { + return expr.IsNegative; + } + } + + public override void Emit (EmitContext ec) + { + expr.Emit (ec); + } + } + + readonly Expression expr, orig_expr; + + private ReducedExpression (Expression expr, Expression orig_expr) + { + this.expr = expr; + this.orig_expr = orig_expr; + this.loc = orig_expr.Location; + } + + public static Expression Create (Constant expr, Expression original_expr) + { + return new ReducedConstantExpression (expr, original_expr); + } + + public static Expression Create (Expression expr, Expression original_expr) + { + Constant c = expr as Constant; + if (c != null) + return Create (c, original_expr); + + return new ReducedExpression (expr, original_expr); + } + + public override Expression CreateExpressionTree (EmitContext ec) + { + return orig_expr.CreateExpressionTree (ec); + } + + public override Expression DoResolve (EmitContext ec) + { + eclass = expr.eclass; + type = expr.Type; + return this; + } + + public override void Emit (EmitContext ec) + { + expr.Emit (ec); + } + + public override void EmitBranchable (EmitContext ec, Label target, bool on_true) + { + expr.EmitBranchable (ec, target, on_true); + } + } + + // + // Unresolved type name expressions + // + public abstract class ATypeNameExpression : FullNamedExpression + { + public readonly string Name; + protected TypeArguments targs; + + protected ATypeNameExpression (string name, Location l) + { + Name = name; + loc = l; + } + + protected ATypeNameExpression (string name, TypeArguments targs, Location l) + { + Name = name; + this.targs = targs; + loc = l; + } + + public bool HasTypeArguments { + get { + return targs != null; + } + } + + public override string GetSignatureForError () + { + if (targs != null) { + return TypeManager.RemoveGenericArity (Name) + "<" + + targs.GetSignatureForError () + ">"; + } + + return Name; + } + } /// /// SimpleName expressions are formed of a single word and only happen at the beginning /// of a dotted-name. /// - public class SimpleName : Expression { - public readonly string Name; - public readonly TypeArguments Arguments; + public class SimpleName : ATypeNameExpression { bool in_transit; public SimpleName (string name, Location l) + : base (name, l) { - Name = name; - loc = l; } public SimpleName (string name, TypeArguments args, Location l) + : base (name, args, l) { - Name = name; - Arguments = args; - loc = l; } public SimpleName (string name, TypeParameter[] type_params, Location l) + : base (name, l) { - Name = name; - loc = l; - - Arguments = new TypeArguments (l); + targs = new TypeArguments (l); foreach (TypeParameter type_param in type_params) - Arguments.Add (new TypeParameterExpr (type_param, l)); + targs.Add (new TypeParameterExpr (type_param, l)); } public static string RemoveGenericArity (string name) @@ -2102,7 +2355,7 @@ namespace Mono.CSharp { public SimpleName GetMethodGroup () { - return new SimpleName (RemoveGenericArity (Name), Arguments, loc); + return new SimpleName (RemoveGenericArity (Name), targs, loc); } public static void Error_ObjectRefRequired (EmitContext ec, Location l, string name) @@ -2166,7 +2419,7 @@ namespace Mono.CSharp { Type[] gen_params = TypeManager.GetTypeArguments (t); - int arg_count = Arguments != null ? Arguments.Count : 0; + int arg_count = targs != null ? targs.Count : 0; for (; (ds != null) && ds.IsGeneric; ds = ds.Parent) { if (arg_count + ds.CountTypeParameters == gen_params.Length) { @@ -2174,8 +2427,8 @@ namespace Mono.CSharp { foreach (TypeParameter param in ds.TypeParameters) new_args.Add (new TypeParameterExpr (param, loc)); - if (Arguments != null) - new_args.Add (Arguments); + if (targs != null) + new_args.Add (targs); return new ConstructedType (t, new_args, loc); } @@ -2201,8 +2454,8 @@ namespace Mono.CSharp { if (nested != null) return nested.ResolveAsTypeStep (ec, false); - if (Arguments != null) { - ConstructedType ct = new ConstructedType (fne, Arguments, loc); + if (targs != null) { + ConstructedType ct = new ConstructedType (fne, targs, loc); return ct.ResolveAsTypeStep (ec, false); } @@ -2241,7 +2494,7 @@ namespace Mono.CSharp { return; } - if (Arguments != null) { + if (targs != null) { FullNamedExpression retval = ec.DeclContainer.LookupNamespaceOrType (SimpleName.RemoveGenericArity (Name), loc, true); if (retval != null) { Namespace.Error_TypeArgumentsCannotBeUsed (retval.Type, loc); @@ -2318,7 +2571,7 @@ namespace Mono.CSharp { if (current_block != null){ LocalInfo vi = current_block.GetLocalInfo (Name); if (vi != null){ - if (Arguments != null) { + if (targs != null) { Report.Error (307, loc, "The variable `{0}' cannot be used with type arguments", Name); @@ -2338,7 +2591,7 @@ namespace Mono.CSharp { ParameterReference pref = current_block.Toplevel.GetParameterReference (Name, loc); if (pref != null) { - if (Arguments != null) { + if (targs != null) { Report.Error (307, loc, "The variable `{0}' cannot be used with type arguments", Name); @@ -2424,11 +2677,11 @@ namespace Mono.CSharp { } if (e is TypeExpr) { - if (Arguments == null) + if (targs == null) return e; ConstructedType ct = new ConstructedType ( - (FullNamedExpression) e, Arguments, loc); + e.Type, targs, loc); return ct.ResolveAsTypeStep (ec, false); } @@ -2448,7 +2701,7 @@ namespace Mono.CSharp { if (!me.IsStatic && (!intermediate || !IdenticalNameAndTypeName (ec, me, loc))) { Error_ObjectRefRequired (ec, loc, me.GetSignatureForError ()); - return EmptyExpression.Null; + return null; } // @@ -2466,9 +2719,9 @@ namespace Mono.CSharp { if (me == null) return null; - if (Arguments != null) { - Arguments.Resolve (ec); - me.SetTypeArguments (Arguments); + if (targs != null) { + targs.Resolve (ec); + me.SetTypeArguments (targs); } if (!me.IsStatic && (me.InstanceExpression != null) && @@ -2489,26 +2742,6 @@ namespace Mono.CSharp { return e; } - public override void Emit (EmitContext ec) - { - throw new InternalErrorException ("The resolve phase was not executed"); - } - - public override string ToString () - { - return Name; - } - - public override string GetSignatureForError () - { - if (Arguments != null) { - return TypeManager.RemoveGenericArity (Name) + "<" + - Arguments.GetSignatureForError () + ">"; - } - - return Name; - } - protected override void CloneTo (CloneContext clonectx, Expression target) { // CloneTo: Nothing, we do not keep any state on this expression @@ -2520,13 +2753,21 @@ namespace Mono.CSharp { /// section 10.8.1 (Fully Qualified Names). /// public abstract class FullNamedExpression : Expression { + + public override Expression CreateExpressionTree (EmitContext ec) + { + throw new NotSupportedException ("ET"); + } + public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent) { return this; } - public abstract string FullName { - get; + public override void Emit (EmitContext ec) + { + throw new InternalErrorException ("FullNamedExpression `{0}' found in resolved tree", + GetSignatureForError ()); } } @@ -2549,19 +2790,14 @@ namespace Mono.CSharp { return ResolveAsTypeTerminal (ec, false); } - override public void Emit (EmitContext ec) - { - throw new Exception ("Should never be called"); - } - public virtual bool CheckAccessLevel (DeclSpace ds) { return ds.CheckAccessLevel (Type); } - public virtual bool AsAccessible (DeclSpace ds, int flags) + public virtual bool AsAccessible (DeclSpace ds) { - return ds.AsAccessible (Type, flags); + return ds.IsAccessibleAs (Type); } public virtual bool IsClass { @@ -2594,10 +2830,6 @@ namespace Mono.CSharp { protected abstract TypeExpr DoResolveAsTypeStep (IResolveContext ec); - public abstract string Name { - get; - } - public override bool Equals (object obj) { TypeExpr tobj = obj as TypeExpr; @@ -2611,11 +2843,6 @@ namespace Mono.CSharp { { return Type.GetHashCode (); } - - public override string ToString () - { - return Name; - } } /// @@ -2638,14 +2865,6 @@ namespace Mono.CSharp { { return this; } - - public override string Name { - get { return Type.ToString (); } - } - - public override string FullName { - get { return Type.FullName; } - } } /// @@ -2779,14 +2998,6 @@ namespace Mono.CSharp { return this; } - public override string Name { - get { return name; } - } - - public override string FullName { - get { return name; } - } - protected override void CloneTo (CloneContext clonectx, Expression target) { // CloneTo: Nothing, we do not keep any state on this expression @@ -2815,6 +3026,11 @@ namespace Mono.CSharp { loc = l; } + protected override void CloneTo (CloneContext clonectx, Expression target) + { + // Nothing to clone + } + protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec) { Expression expr; @@ -2832,99 +3048,6 @@ namespace Mono.CSharp { type = fne.Type; return new TypeExpression (type, loc); } - - public override string Name { - get { return name.FullName; } - } - - public override string FullName { - get { return name.FullName; } - } - } - - public class TypeAliasExpression : TypeExpr { - FullNamedExpression alias; - TypeExpr texpr; - TypeArguments args; - string name; - - public TypeAliasExpression (FullNamedExpression alias, TypeArguments args, Location l) - { - this.alias = alias; - this.args = args; - loc = l; - - eclass = ExprClass.Type; - if (args != null) - name = alias.FullName + "<" + args.ToString () + ">"; - else - name = alias.FullName; - } - - public override string Name { - get { return alias.FullName; } - } - - public override string FullName { - get { return name; } - } - - protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec) - { - texpr = alias.ResolveAsTypeTerminal (ec, false); - if (texpr == null) - return null; - - Type type = texpr.Type; - int num_args = TypeManager.GetNumberOfTypeArguments (type); - - if (args != null) { - if (num_args == 0) { - Report.Error (308, loc, - "The non-generic type `{0}' cannot " + - "be used with type arguments.", - TypeManager.CSharpName (type)); - return null; - } - - ConstructedType ctype = new ConstructedType (type, args, loc); - return ctype.ResolveAsTypeTerminal (ec, false); - } else if (num_args > 0) { - Report.Error (305, loc, - "Using the generic type `{0}' " + - "requires {1} type arguments", - TypeManager.CSharpName (type), num_args.ToString ()); - return null; - } - - return texpr; - } - - public override bool CheckAccessLevel (DeclSpace ds) - { - return texpr.CheckAccessLevel (ds); - } - - public override bool AsAccessible (DeclSpace ds, int flags) - { - return texpr.AsAccessible (ds, flags); - } - - public override bool IsClass { - get { return texpr.IsClass; } - } - - public override bool IsValueType { - get { return texpr.IsValueType; } - } - - public override bool IsInterface { - get { return texpr.IsInterface; } - } - - public override bool IsSealed { - get { return texpr.IsSealed; } - } } /// @@ -2983,6 +3106,11 @@ namespace Mono.CSharp { "with an instance reference, qualify it with a type name instead", name); } + public static void Error_BaseAccessInExpressionTree (Location loc) + { + Report.Error (831, loc, "An expression tree may not contain a base access"); + } + // TODO: possible optimalization // Cache resolved constant result in FieldBuilder <-> expression map public virtual MemberExpr ResolveMemberAccess (EmitContext ec, Expression left, Location loc, @@ -3123,7 +3251,7 @@ namespace Mono.CSharp { return null; // Search continues - ExtensionMethodGroupExpr e = ns.LookupExtensionMethod (type, null, Name); + ExtensionMethodGroupExpr e = ns.LookupExtensionMethod (type, null, Name, loc); if (e == null) return base.OverloadResolve (ec, ref arguments, false, loc); @@ -3259,57 +3387,80 @@ namespace Mono.CSharp { return (MethodInfo)mg.best_candidate; } - /// - /// Determines "better conversion" as specified in 14.4.2.3 - /// - /// Returns : p if a->p is better, - /// q if a->q is better, - /// null if neither is better - /// - static Type BetterConversion (EmitContext ec, Argument a, Type p, Type q) + // + // 7.4.3.3 Better conversion from expression + // Returns : 1 if a->p is better, + // 2 if a->q is better, + // 0 if neither is better + // + static int BetterExpressionConversion (EmitContext ec, Argument a, Type p, Type q) { Type argument_type = TypeManager.TypeToCoreType (a.Type); - Expression argument_expr = a.Expr; + if (argument_type == TypeManager.anonymous_method_type && RootContext.Version > LanguageVersion.ISO_2) { + // + // Uwrap delegate from Expression + // + if (TypeManager.DropGenericTypeArguments (p) == TypeManager.expression_type) { + p = TypeManager.GetTypeArguments (p) [0]; + } + if (TypeManager.DropGenericTypeArguments (q) == TypeManager.expression_type) { + q = TypeManager.GetTypeArguments (q) [0]; + } + + p = Delegate.GetInvokeMethod (null, p).ReturnType; + q = Delegate.GetInvokeMethod (null, q).ReturnType; + } else { + if (argument_type == p) + return 1; - if (argument_type == null) - throw new Exception ("Expression of type " + a.Expr + - " does not resolve its type"); + if (argument_type == q) + return 2; + } - if (p == null || q == null) - throw new InternalErrorException ("BetterConversion Got a null conversion"); + return BetterTypeConversion (ec, p, q); + } - if (p == q) - return null; + // + // 7.4.3.4 Better conversion from type + // + public static int BetterTypeConversion (EmitContext ec, Type p, Type q) + { + if (p == null || q == null) + throw new InternalErrorException ("BetterTypeConversion got a null conversion"); - if (argument_expr is NullLiteral) - { - // - // If the argument is null and one of the types to compare is 'object' and - // the other is a reference type, we prefer the other. - // - // This follows from the usual rules: - // * There is an implicit conversion from 'null' to type 'object' - // * There is an implicit conversion from 'null' to any reference type - // * There is an implicit conversion from any reference type to type 'object' - // * 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 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; - if (!q.IsValueType && p == TypeManager.object_type) - return q; + if (p == TypeManager.int32_type) { + if (q == TypeManager.uint32_type || q == TypeManager.uint64_type) + return 1; + } else if (p == TypeManager.int64_type) { + if (q == TypeManager.uint64_type) + return 1; + } else if (p == TypeManager.sbyte_type) { + if (q == TypeManager.byte_type || q == TypeManager.ushort_type || + q == TypeManager.uint32_type || q == TypeManager.uint64_type) + return 1; + } else if (p == TypeManager.short_type) { + if (q == TypeManager.ushort_type || q == TypeManager.uint32_type || + q == TypeManager.uint64_type) + return 1; } - - if (argument_type == p) - return p; - if (argument_type == q) - return q; + if (q == TypeManager.int32_type) { + if (p == TypeManager.uint32_type || p == TypeManager.uint64_type) + return 2; + } if (q == TypeManager.int64_type) { + if (p == TypeManager.uint64_type) + return 2; + } else if (q == TypeManager.sbyte_type) { + if (p == TypeManager.byte_type || p == TypeManager.ushort_type || + p == TypeManager.uint32_type || p == TypeManager.uint64_type) + return 2; + } if (q == TypeManager.short_type) { + if (p == TypeManager.ushort_type || p == TypeManager.uint32_type || + p == TypeManager.uint64_type) + return 2; + } + // TODO: this is expensive Expression p_tmp = new EmptyExpression (p); Expression q_tmp = new EmptyExpression (q); @@ -3317,44 +3468,12 @@ namespace Mono.CSharp { bool q_to_p = Convert.ImplicitConversionExists (ec, q_tmp, p); if (p_to_q && !q_to_p) - return p; + return 1; if (q_to_p && !p_to_q) - return q; - - if (p == TypeManager.sbyte_type) - if (q == TypeManager.byte_type || q == TypeManager.ushort_type || - q == TypeManager.uint32_type || q == TypeManager.uint64_type) - return p; - if (q == TypeManager.sbyte_type) - if (p == TypeManager.byte_type || p == TypeManager.ushort_type || - p == TypeManager.uint32_type || p == TypeManager.uint64_type) - return q; - - if (p == TypeManager.short_type) - if (q == TypeManager.ushort_type || q == TypeManager.uint32_type || - q == TypeManager.uint64_type) - return p; - if (q == TypeManager.short_type) - if (p == TypeManager.ushort_type || p == TypeManager.uint32_type || - p == TypeManager.uint64_type) - return q; - - if (p == TypeManager.int32_type) - if (q == TypeManager.uint32_type || q == TypeManager.uint64_type) - return p; - if (q == TypeManager.int32_type) - if (p == TypeManager.uint32_type || p == TypeManager.uint64_type) - return q; - - if (p == TypeManager.int64_type) - if (q == TypeManager.uint64_type) - return p; - if (q == TypeManager.int64_type) - if (p == TypeManager.uint64_type) - return q; + return 2; - return null; + return 0; } /// @@ -3398,16 +3517,16 @@ namespace Mono.CSharp { continue; same = false; - Type better = BetterConversion (ec, a, ct, bt); + int result = BetterExpressionConversion (ec, a, ct, bt); // for each argument, the conversion to 'ct' should be no worse than // the conversion to 'bt'. - if (better == bt) + if (result == 2) return false; // for at least one argument, the conversion to 'ct' should be better than // the conversion to 'bt'. - if (better == ct) + if (result != 0) better_at_least_one = true; } @@ -3513,7 +3632,20 @@ namespace Mono.CSharp { public override Expression CreateExpressionTree (EmitContext ec) { - return new Cast (new TypeExpression (typeof (MethodInfo), loc), new TypeOfMethod (this)); + if (best_candidate == null) { + Report.Error (1953, loc, "An expression tree cannot contain an expression with method group"); + return null; + } + + if (best_candidate.IsConstructor) + return new TypeOfConstructorInfo (best_candidate, loc); + + IMethodData md = TypeManager.GetMethod (best_candidate); + if (md != null && md.IsExcluded ()) + Report.Error (765, loc, + "Partial methods with only a defining declaration or removed conditional methods cannot be used in an expression tree"); + + return new TypeOfMethodInfo (best_candidate, loc); } override public Expression DoResolve (EmitContext ec) @@ -3591,6 +3723,12 @@ namespace Mono.CSharp { Report.Error (1503, loc, "Argument {0}: Cannot convert type `{1}' to `{2}'", index, p1, p2); } } + + public override void Error_ValueCannotBeConverted (EmitContext ec, Location loc, Type target, bool expl) + { + Report.Error (428, loc, "Cannot convert method group `{0}' to non-delegate type `{1}'. Consider using parentheses to invoke the method", + Name, TypeManager.CSharpName (target)); + } protected virtual int GetApplicableParametersCount (MethodBase method, ParameterData parameters) { @@ -3645,7 +3783,8 @@ namespace Mono.CSharp { return score - 20000; if (TypeManager.IsGenericMethodDefinition (candidate)) - throw new InternalErrorException ("a generic method definition took part in overload resolution"); + throw new InternalErrorException ("A generic method `{0}' definition took part in overload resolution", + TypeManager.CSharpSignature (candidate)); pd = TypeManager.GetParameterData (candidate); } @@ -3692,8 +3831,11 @@ namespace Mono.CSharp { params_expanded_form = true; } - if (score != 0) + if (score != 0) { + if (params_expanded_form) + ++score; return (arg_count - i) * 2 + score; + } } if (arg_count != param_count) @@ -3721,21 +3863,13 @@ namespace Mono.CSharp { return 0; } - // FIXME: Kill this abomination (EmitContext.TempEc) - EmitContext prevec = EmitContext.TempEc; - EmitContext.TempEc = ec; - try { - if (delegate_type != null ? - !Delegate.IsTypeCovariant (argument.Expr, parameter) : - !Convert.ImplicitConversionExists (ec, argument.Expr, parameter)) - return 2; - - if (arg_mod != param_mod) - return 1; + if (delegate_type != null ? + !Delegate.IsTypeCovariant (argument.Expr, parameter) : + !Convert.ImplicitConversionExists (ec, argument.Expr, parameter)) + return 2; - } finally { - EmitContext.TempEc = prevec; - } + if (arg_mod != param_mod) + return 1; return 0; } @@ -3993,7 +4127,7 @@ namespace Mono.CSharp { // not an extension method. We start extension methods lookup from here // if (InstanceExpression != null) { - ExtensionMethodGroupExpr ex_method_lookup = ec.TypeContainer.LookupExtensionMethod (type, Name); + ExtensionMethodGroupExpr ex_method_lookup = ec.TypeContainer.LookupExtensionMethod (type, Name, loc); if (ex_method_lookup != null) { ex_method_lookup.ExtensionExpression = InstanceExpression; ex_method_lookup.SetTypeArguments (type_arguments); @@ -4041,9 +4175,8 @@ namespace Mono.CSharp { } } - if (VerifyArgumentsCompat (ec, ref Arguments, arg_count, best_candidate, cand_params, may_fail, loc)) - throw new InternalErrorException ("Overload verification expected failure"); - return null; + if (!VerifyArgumentsCompat (ec, ref Arguments, arg_count, best_candidate, cand_params, may_fail, loc)) + return null; } } @@ -4148,7 +4281,7 @@ namespace Mono.CSharp { // should be better than all the others // MethodBase ambiguous = null; - for (int ix = 0; ix < candidate_top; ix++) { + for (int ix = 1; ix < candidate_top; ix++) { MethodBase candidate = (MethodBase) candidates [ix]; if (candidate == best_candidate) @@ -4299,7 +4432,7 @@ namespace Mono.CSharp { continue; } - + Expression conv; if (TypeManager.IsEqual (a.Type, pt)) { conv = a.Expr; @@ -4313,12 +4446,14 @@ namespace Mono.CSharp { // Convert params arguments to an array initializer // if (params_initializers != null) { - params_initializers.Add (conv); + // we choose to use 'a.Expr' rather than 'conv' so that + // we don't hide the kind of expression we have (esp. CompoundAssign.Helper) + params_initializers.Add (a.Expr); arguments.RemoveAt (a_idx--); --arg_count; continue; } - + // Update the argument with the implicit conversion a.Expr = conv; } @@ -4326,7 +4461,7 @@ namespace Mono.CSharp { // // Fill not provided arguments required by params modifier // - if (params_initializers == null && pd.HasParams && arg_count < pd.Count) { + if (params_initializers == null && pd.HasParams && arg_count < pd.Count && a_idx + 1 == pd.Count) { if (arguments == null) arguments = new ArrayList (1); @@ -4403,6 +4538,11 @@ namespace Mono.CSharp { return base.ResolveMemberAccess (ec, left, loc, original); } + public override Expression CreateExpressionTree (EmitContext ec) + { + throw new NotSupportedException ("ET"); + } + public override Expression DoResolve (EmitContext ec) { IConstant ic = TypeManager.GetConstant (constant); @@ -4498,6 +4638,26 @@ namespace Mono.CSharp { return base.ResolveMemberAccess (ec, left, loc, original); } + public override Expression CreateExpressionTree (EmitContext ec) + { + Expression instance; + if (InstanceExpression == null) { + instance = new NullLiteral (loc); + } else { + instance = InstanceExpression.CreateExpressionTree (ec); + } + + ArrayList args = new ArrayList (2); + args.Add (new Argument (instance)); + args.Add (new Argument (CreateTypeOfExpression ())); + return CreateExpressionFactoryCall ("Field", args); + } + + public Expression CreateTypeOfExpression () + { + return new TypeOfField (FieldInfo, loc); + } + override public Expression DoResolve (EmitContext ec) { return DoResolve (ec, false, false); @@ -4582,7 +4742,7 @@ namespace Mono.CSharp { // If the instance expression is a local variable or parameter. IVariable var = InstanceExpression as IVariable; - if ((var == null) || (var.VariableInfo == null)) + if (var == null || var.VariableInfo == null) return this; VariableInfo vi = var.VariableInfo; @@ -4633,7 +4793,7 @@ namespace Mono.CSharp { override public Expression DoResolveLValue (EmitContext ec, Expression right_side) { IVariable var = InstanceExpression as IVariable; - if ((var != null) && (var.VariableInfo != null)) + if (var != null && var.VariableInfo != null) var.VariableInfo.SetFieldAssigned (ec, FieldInfo.Name); bool lvalue_instance = !FieldInfo.IsStatic && FieldInfo.DeclaringType.IsValueType; @@ -4671,7 +4831,7 @@ namespace Mono.CSharp { } if (right_side == EmptyExpression.OutAccess && - !IsStatic && !(InstanceExpression is This) && DeclaringType.IsSubclassOf (TypeManager.mbr_type)) { + !IsStatic && !(InstanceExpression is This) && TypeManager.mbr_type != null && TypeManager.IsSubclassOf (DeclaringType, TypeManager.mbr_type)) { Report.SymbolRelatedToPreviousError (DeclaringType); Report.Warning (197, 1, loc, "Passing `{0}' as ref or out or taking its address may cause a runtime exception because it is a field of a marshal-by-reference class", @@ -4681,28 +4841,34 @@ namespace Mono.CSharp { return this; } + bool is_marshal_by_ref () + { + return !IsStatic && Type.IsValueType && TypeManager.mbr_type != null && TypeManager.IsSubclassOf (DeclaringType, TypeManager.mbr_type); + } + public override void CheckMarshalByRefAccess (EmitContext ec) { - if (!IsStatic && Type.IsValueType && !(InstanceExpression is This) && DeclaringType.IsSubclassOf (TypeManager.mbr_type)) { + if (is_marshal_by_ref () && !(InstanceExpression is This)) { Report.SymbolRelatedToPreviousError (DeclaringType); Report.Warning (1690, 1, loc, "Cannot call methods, properties, or indexers on `{0}' because it is a value type member of a marshal-by-reference class", GetSignatureForError ()); } } - public bool VerifyFixed () - { - IVariable variable = InstanceExpression as IVariable; - // A variable of the form V.I is fixed when V is a fixed variable of a struct type. - // We defer the InstanceExpression check after the variable check to avoid a - // separate null check on InstanceExpression. - return variable != null && InstanceExpression.Type.IsValueType && variable.VerifyFixed (); - } - public override int GetHashCode () { return FieldInfo.GetHashCode (); } + + public bool IsFixed { + get { + IVariable variable = InstanceExpression as IVariable; + // A variable of the form V.I is fixed when V is a fixed variable of a struct type. + // We defer the InstanceExpression check after the variable check to avoid a + // separate null check on InstanceExpression. + return variable != null && InstanceExpression.Type.IsValueType && variable.IsFixed; + } + } public override bool Equals (object obj) { @@ -4774,10 +4940,7 @@ namespace Mono.CSharp { return; } - // - // String concatenation creates a new string instance - // - prepared = prepare_for_load && !(source is StringConcat); + prepared = prepare_for_load; EmitInstance (ec, prepared); source.Emit (ec); @@ -4813,6 +4976,15 @@ namespace Mono.CSharp { Emit (ec, false); } + public override void EmitSideEffect (EmitContext ec) + { + FieldBase f = TypeManager.GetField (FieldInfo); + bool is_volatile = f != null && (f.ModFlags & Modifiers.VOLATILE) != 0; + + if (is_volatile || is_marshal_by_ref ()) + base.EmitSideEffect (ec); + } + public void AddressOf (EmitContext ec, AddressOp mode) { ILGenerator ig = ec.ig; @@ -4917,18 +5089,30 @@ namespace Mono.CSharp { public override Expression CreateExpressionTree (EmitContext ec) { + ArrayList args; if (IsSingleDimensionalArrayLength ()) { - ArrayList args = new ArrayList (1); + args = new ArrayList (1); args.Add (new Argument (InstanceExpression.CreateExpressionTree (ec))); return CreateExpressionFactoryCall ("ArrayLength", args); } - // TODO: it's waiting for PropertyExpr refactoring - //ArrayList args = new ArrayList (2); - //args.Add (new Argument (InstanceExpression.CreateExpressionTree (ec))); - //args.Add (getter expression); - //return CreateExpressionFactoryCall ("Property", args); - return base.CreateExpressionTree (ec); + if (is_base) { + Error_BaseAccessInExpressionTree (loc); + return null; + } + + args = new ArrayList (2); + if (InstanceExpression == null) + args.Add (new Argument (new NullLiteral (loc))); + else + args.Add (new Argument (InstanceExpression.CreateExpressionTree (ec))); + args.Add (new Argument (new TypeOfMethodInfo (getter, loc))); + return CreateExpressionFactoryCall ("Property", args); + } + + public Expression CreateSetterTypeOfExpression () + { + return new TypeOfMethodInfo (setter, loc); } public override Type DeclaringType { @@ -5044,7 +5228,7 @@ namespace Mono.CSharp { Error_TypeDoesNotContainDefinition (loc, PropertyInfo.DeclaringType, Name); return; } - + StringBuilder sig = new StringBuilder (TypeManager.CSharpName (mi.DeclaringType)); sig.Append ('.'); ParameterData iparams = TypeManager.GetParameterData (mi); @@ -5068,18 +5252,12 @@ namespace Mono.CSharp { bool IsSingleDimensionalArrayLength () { - if (getter == TypeManager.system_int_array_get_length || - getter == TypeManager.int_array_get_length) { - Type iet = InstanceExpression.Type; - - // - // System.Array.Length can be called, but the Type does not - // support invoking GetArrayRank, so test for that case first - // - return iet != TypeManager.array_type && (iet.GetArrayRank () == 1); - } + if (DeclaringType != TypeManager.array_type || getter == null || Name != "Length") + return false; - return false; + string t_name = InstanceExpression.Type.Name; + int t_name_len = t_name.Length; + return t_name_len > 2 && t_name [t_name_len - 2] == '['; } override public Expression DoResolve (EmitContext ec) @@ -5250,14 +5428,9 @@ namespace Mono.CSharp { Expression my_source = source; if (prepare_for_load) { - if (source is StringConcat) - EmitInstance (ec, false); - else - prepared = true; - + prepared = true; source.Emit (ec); - prepared = true; if (leave_copy) { ec.ig.Emit (OpCodes.Dup); if (!is_static) { @@ -5374,7 +5547,6 @@ namespace Mono.CSharp { return base.ResolveMemberAccess (ec, left, loc, original); } - bool InstanceResolve (EmitContext ec, bool must_do_cs1540_check) { if (is_static) { @@ -5402,7 +5574,7 @@ namespace Mono.CSharp { // if (must_do_cs1540_check && InstanceExpression != EmptyExpression.Null && InstanceExpression.Type != ec.ContainerType && - ec.ContainerType.IsSubclassOf (InstanceExpression.Type)) { + TypeManager.IsSubclassOf (ec.ContainerType, InstanceExpression.Type)) { Report.SymbolRelatedToPreviousError (EventInfo); ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo)); return false; @@ -5418,9 +5590,16 @@ namespace Mono.CSharp { IsAccessorAccessible (invocation_type, remove_accessor, out dummy); } + public override Expression CreateExpressionTree (EmitContext ec) + { + throw new NotSupportedException ("ET"); + } + public override Expression DoResolveLValue (EmitContext ec, Expression right_side) { - return DoResolve (ec); + // contexts where an LValue is valid have already devolved to FieldExprs + Error_CannotAssign (); + return null; } public override Expression DoResolve (EmitContext ec) @@ -5435,14 +5614,25 @@ namespace Mono.CSharp { if (!InstanceResolve (ec, must_do_cs1540_check)) return null; + + if (!ec.IsInCompoundAssignment) { + Error_CannotAssign (); + return null; + } return this; } public override void Emit (EmitContext ec) { - Report.Error (70, loc, "The event `{0}' can only appear on the left hand side of += or -= "+ - "(except on the defining type)", GetSignatureForError ()); + Error_CannotAssign (); + } + + public void Error_CannotAssign () + { + Report.Error (70, loc, + "The event `{0}' can only appear on the left hand side of += or -= when used outside of the type `{1}'", + GetSignatureForError (), TypeManager.CSharpName (EventInfo.DeclaringType)); } public override string GetSignatureForError () @@ -5450,46 +5640,36 @@ namespace Mono.CSharp { return TypeManager.CSharpSignature (EventInfo); } - public void EmitAddOrRemove (EmitContext ec, Expression source) + public void EmitAddOrRemove (EmitContext ec, bool is_add, Expression source) { - BinaryDelegate source_del = source as BinaryDelegate; - if (source_del == null) { - Emit (ec); - return; - } - Expression handler = source_del.Right; - - Argument arg = new Argument (handler, Argument.AType.Expression); - ArrayList args = new ArrayList (); - - args.Add (arg); - - if (source_del.IsAddition) - Invocation.EmitCall ( - ec, IsBase, InstanceExpression, add_accessor, args, loc); - else - Invocation.EmitCall ( - ec, IsBase, InstanceExpression, remove_accessor, args, loc); + ArrayList args = new ArrayList (1); + args.Add (new Argument (source, Argument.AType.Expression)); + Invocation.EmitCall (ec, IsBase, InstanceExpression, is_add ? add_accessor : remove_accessor, args, loc); } } - public class TemporaryVariable : Expression, IMemoryLocation + public class TemporaryVariable : VariableReference { LocalInfo li; Variable var; - + public TemporaryVariable (Type type, Location loc) { this.type = type; this.loc = loc; - eclass = ExprClass.Value; + eclass = ExprClass.Variable; } - + + public override Expression CreateExpressionTree (EmitContext ec) + { + throw new NotSupportedException ("ET"); + } + public override Expression DoResolve (EmitContext ec) { if (li != null) return this; - + TypeExpr te = new TypeExpression (type, loc); li = ec.CurrentBlock.AddTemporaryVariable (te, loc); if (!li.Resolve (ec)) @@ -5500,46 +5680,34 @@ namespace Mono.CSharp { var = scope.AddLocal (li); type = var.Type; } - + return this; } - public Variable Variable { - get { return var != null ? var : li.Variable; } - } - public override void Emit (EmitContext ec) { - Variable.EmitInstance (ec); - Variable.Emit (ec); + Emit (ec, false); } - - public void EmitLoadAddress (EmitContext ec) + + public void EmitAssign (EmitContext ec, Expression source) { - Variable.EmitInstance (ec); - Variable.EmitAddressOf (ec); + EmitAssign (ec, source, false, false); } - - public void Store (EmitContext ec, Expression right_side) - { - Variable.EmitInstance (ec); - right_side.Emit (ec); - Variable.EmitAssign (ec); + + public override bool IsFixed { + get { return true; } } - - public void EmitThis (EmitContext ec) - { - Variable.EmitInstance (ec); + + public override bool IsRef { + get { return false; } } - - public void EmitStore (EmitContext ec) - { - Variable.EmitAssign (ec); + + public override Variable Variable { + get { return var != null ? var : li.Variable; } } - - public void AddressOf (EmitContext ec, AddressOp mode) - { - EmitLoadAddress (ec); + + public override VariableInfo VariableInfo { + get { throw new NotImplementedException (); } } } @@ -5563,7 +5731,7 @@ namespace Mono.CSharp { } } - public override Expression DoResolveLValue (EmitContext ec, Expression right_side) + public bool InferType (EmitContext ec, Expression right_side) { if (type != null) throw new InternalErrorException ("An implicitly typed local variable could not be redefined"); @@ -5572,11 +5740,11 @@ namespace Mono.CSharp { if (type == TypeManager.null_type || type == TypeManager.void_type || type == TypeManager.anonymous_method_type) { Report.Error (815, loc, "An implicitly typed local variable declaration cannot be initialized with `{0}'", right_side.GetSignatureForError ()); - return null; + return false; } eclass = ExprClass.Variable; - return this; + return true; } protected override void Error_TypeOrNamespaceNotFound (IResolveContext ec)