X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fecore.cs;h=26d88130ad84bd63e665004339c1e700409e43c4;hb=25f808006ab037e1c36f844b01268a34c9d40601;hp=f9d7ee165cd0ded6c19c766f4d659d998c960d84;hpb=93986018bde38a267cf3c8ff69ae6f1fc526a699;p=mono.git diff --git a/mcs/mcs/ecore.cs b/mcs/mcs/ecore.cs index f9d7ee165cd..26d88130ad8 100755 --- a/mcs/mcs/ecore.cs +++ b/mcs/mcs/ecore.cs @@ -36,6 +36,34 @@ namespace Mono.CSharp { Nothing, } + /// + /// This is used to tell Resolve in which types of expressions we're + /// interested. + /// + [Flags] + public enum ResolveFlags { + // Returns Value, Variable, PropertyAccess, EventAccess or IndexerAccess. + VariableOrValue = 1, + + // Returns a type expression. + Type = 2, + + // Returns a method group. + MethodGroup = 4, + + // Allows SimpleNames to be returned. + // This is used by MemberAccess to construct long names that can not be + // partially resolved (namespace-qualified names for example). + SimpleName = 8, + + // Mask of all the expression class flags. + MaskExprClass = 15, + + // Disable control flow analysis while resolving the expression. + // This is used when resolving the instance expression of a field expression. + DisableFlowAnalysis = 16 + } + // // This is just as a hint to AddressOf of what will be done with the // address. @@ -64,12 +92,103 @@ namespace Mono.CSharp { void AddressOf (EmitContext ec, AddressOp mode); } + /// + /// This interface is implemented by variables + /// + public interface IVariable { + /// + /// Checks whether the variable has already been assigned at + /// the current position of the method's control flow and + /// reports an appropriate error message if not. + /// + /// If the variable is a struct, then this call checks whether + /// all of its fields (including all private ones) have been + /// assigned. + /// + bool IsAssigned (EmitContext ec, Location loc); + + /// + /// Checks whether field `name' in this struct has been assigned. + /// + bool IsFieldAssigned (EmitContext ec, string name, Location loc); + + /// + /// Tells the flow analysis code that the variable has already + /// been assigned at the current code position. + /// + /// If the variable is a struct, this call marks all its fields + /// (including private fields) as being assigned. + /// + void SetAssigned (EmitContext ec); + + /// + /// Tells the flow analysis code that field `name' in this struct + /// has already been assigned atthe current code position. + /// + void SetFieldAssigned (EmitContext ec, string name); + } + + /// + /// This interface denotes an expression which evaluates to a member + /// of a struct or a class. + /// + public interface IMemberExpr + { + /// + /// The name of this member. + /// + string Name { + get; + } + + /// + /// Whether this is an instance member. + /// + bool IsInstance { + get; + } + + /// + /// Whether this is a static member. + /// + bool IsStatic { + get; + } + + /// + /// The type which declares this member. + /// + Type DeclaringType { + get; + } + + /// + /// The instance expression associated with this member, if it's a + /// non-static member. + /// + Expression InstanceExpression { + get; set; + } + } + + /// + /// Expression which resolves to a type. + /// + public interface ITypeExpression + { + /// + /// Resolve the expression, but only lookup types. + /// + Expression DoResolveType (EmitContext ec); + } + /// /// Base class for expressions /// public abstract class Expression { public ExprClass eclass; - protected Type type; + protected Type type; + protected Location loc; public Type Type { get { @@ -81,25 +200,42 @@ namespace Mono.CSharp { } } + public Location Location { + get { + return loc; + } + } + /// /// Utility wrapper routine for Error, just to beautify the code /// - static protected void Error (int error, string s) + public void Error (int error, string s) { - Report.Error (error, s); + if (!Location.IsNull (loc)) + Report.Error (error, loc, s); + else + Report.Error (error, s); } - static protected void Error (int error, Location loc, string s) + /// + /// Utility wrapper routine for Warning, just to beautify the code + /// + public void Warning (int warning, string s) { - Report.Error (error, loc, s); + if (!Location.IsNull (loc)) + Report.Warning (warning, loc, s); + else + Report.Warning (warning, s); } - + /// - /// Utility wrapper routine for Warning, just to beautify the code + /// Utility wrapper routine for Warning, only prints the warning if + /// warnings of level `level' are enabled. /// - static protected void Warning (int warning, string s) + public void Warning (int warning, int level, string s) { - Report.Warning (warning, s); + if (level <= RootContext.WarningLevel) + Warning (warning, s); } static public void Error_CannotConvertType (Location loc, Type source, Type target) @@ -151,72 +287,110 @@ namespace Mono.CSharp { /// Currently Resolve wraps DoResolve to perform sanity /// checking and assertion checking on what we expect from Resolve. /// - public Expression Resolve (EmitContext ec) + public Expression Resolve (EmitContext ec, ResolveFlags flags) { - Expression e = DoResolve (ec); - - if (e != null){ - - if (e is SimpleName){ - SimpleName s = (SimpleName) e; + // Are we doing a types-only search ? + if ((flags & ResolveFlags.MaskExprClass) == ResolveFlags.Type) { + ITypeExpression type_expr = this as ITypeExpression; - Report.Error ( - 103, s.Location, - "The name `" + s.Name + "' could not be found in `" + - ec.DeclSpace.Name + "'"); + if (type_expr == null) return null; - } - - if (e.eclass == ExprClass.Invalid) - throw new Exception ("Expression " + e.GetType () + - " ExprClass is Invalid after resolve"); - if (e.eclass != ExprClass.MethodGroup) - if (e.type == null) - throw new Exception ( - "Expression " + e.GetType () + - " did not set its type after Resolve\n" + - "called from: " + this.GetType ()); + return type_expr.DoResolveType (ec); } - return e; - } + bool old_do_flow_analysis = ec.DoFlowAnalysis; + if ((flags & ResolveFlags.DisableFlowAnalysis) != 0) + ec.DoFlowAnalysis = false; - /// - /// Performs expression resolution and semantic analysis, but - /// allows SimpleNames to be returned. - /// - /// - /// - /// This is used by MemberAccess to construct long names that can not be - /// partially resolved (namespace-qualified names for example). - /// - public Expression ResolveWithSimpleName (EmitContext ec) - { Expression e; - if (this is SimpleName) e = ((SimpleName) this).DoResolveAllowStatic (ec); else e = DoResolve (ec); - if (e != null){ - if (e is SimpleName) - return e; + ec.DoFlowAnalysis = old_do_flow_analysis; - if (e.eclass == ExprClass.Invalid) - throw new Exception ("Expression " + e + - " ExprClass is Invalid after resolve"); + if (e == null) + return null; + + if (e is SimpleName){ + SimpleName s = (SimpleName) e; + + if ((flags & ResolveFlags.SimpleName) == 0) { + + object lookup = TypeManager.MemberLookup ( + ec.ContainerType, ec.ContainerType, AllMemberTypes, + AllBindingFlags | BindingFlags.NonPublic, s.Name); + if (lookup != null) + Error (122, "`" + s.Name + "' " + + "is inaccessible because of its protection level"); + else + Error (103, "The name `" + s.Name + "' could not be " + + "found in `" + ec.DeclSpace.Name + "'"); + return null; + } + + return s; + } + + if ((e is TypeExpr) || (e is ComposedCast)) { + if ((flags & ResolveFlags.Type) == 0) { + e.Error118 (flags); + return null; + } + + return e; + } + + switch (e.eclass) { + case ExprClass.Type: + if ((flags & ResolveFlags.VariableOrValue) == 0) { + e.Error118 (flags); + return null; + } + break; + + case ExprClass.MethodGroup: + if ((flags & ResolveFlags.MethodGroup) == 0) { + ((MethodGroupExpr) e).ReportUsageError (); + return null; + } + break; + + case ExprClass.Value: + case ExprClass.Variable: + case ExprClass.PropertyAccess: + case ExprClass.EventAccess: + case ExprClass.IndexerAccess: + if ((flags & ResolveFlags.VariableOrValue) == 0) { + e.Error118 (flags); + return null; + } + break; - if (e.eclass != ExprClass.MethodGroup) - if (e.type == null) - throw new Exception ("Expression " + e + - " did not set its type after Resolve"); + default: + throw new Exception ("Expression " + e.GetType () + + " ExprClass is Invalid after resolve"); } + if (e.type == null) + throw new Exception ( + "Expression " + e.GetType () + + " did not set its type after Resolve\n" + + "called from: " + this.GetType ()); + return e; } - + + /// + /// Resolves an expression and performs semantic analysis on it. + /// + public Expression Resolve (EmitContext ec) + { + return Resolve (ec, ResolveFlags.VariableOrValue); + } + /// /// Resolves an expression for LValue assignment /// @@ -234,7 +408,7 @@ namespace Mono.CSharp { SimpleName s = (SimpleName) e; Report.Error ( - 103, s.Location, + 103, loc, "The name `" + s.Name + "' could not be found in `" + ec.DeclSpace.Name + "'"); return null; @@ -244,10 +418,14 @@ namespace Mono.CSharp { throw new Exception ("Expression " + e + " ExprClass is Invalid after resolve"); - if (e.eclass != ExprClass.MethodGroup) - if (e.type == null) - throw new Exception ("Expression " + e + - " did not set its type after Resolve"); + if (e.eclass == ExprClass.MethodGroup) { + ((MethodGroupExpr) e).ReportUsageError (); + return null; + } + + if (e.type == null) + throw new Exception ("Expression " + e + + " did not set its type after Resolve"); } return e; @@ -316,7 +494,7 @@ namespace Mono.CSharp { else if (t == TypeManager.bool_type) return new BoolConstant ((bool) v); else if (TypeManager.IsEnumType (t)){ - Constant e = Constantify (v, v.GetType ()); + Constant e = Constantify (v, TypeManager.TypeToCoreType (v.GetType ())); return new EnumConstant (e, t); } else @@ -336,7 +514,7 @@ namespace Mono.CSharp { else if (mi is PropertyInfo) return new PropertyExpr ((PropertyInfo) mi, loc); else if (mi is Type){ - return new TypeExpr ((System.Type) mi); + return new TypeExpr ((System.Type) mi, loc); } return null; @@ -373,7 +551,23 @@ namespace Mono.CSharp { public static Expression MemberLookup (EmitContext ec, Type t, string name, MemberTypes mt, BindingFlags bf, Location loc) { - MemberInfo [] mi = TypeManager.MemberLookup (ec.ContainerType, t, mt, bf, name); + return MemberLookup (ec, ec.ContainerType, t, name, mt, bf, loc); + } + + // + // Lookup type `t' for code in class `invocation_type'. Note that it's important + // to set `invocation_type' correctly since this method also checks whether the + // invoking class is allowed to access the member in class `t'. When you want to + // explicitly do a lookup in the base class, you must set both `t' and `invocation_type' + // to the base class (although a derived class can access protected members of its base + // class it cannot do so through an instance of the base class (error CS1540)). + // + + public static Expression MemberLookup (EmitContext ec, Type invocation_type, Type t, + string name, MemberTypes mt, BindingFlags bf, + Location loc) + { + MemberInfo [] mi = TypeManager.MemberLookup (invocation_type, t, mt, bf, name); if (mi == null) return null; @@ -404,12 +598,14 @@ namespace Mono.CSharp { public static Expression MemberLookup (EmitContext ec, Type t, string name, Location loc) { - return MemberLookup (ec, t, name, AllMemberTypes, AllBindingFlags, loc); + return MemberLookup (ec, ec.ContainerType, t, name, + AllMemberTypes, AllBindingFlags, loc); } public static Expression MethodLookup (EmitContext ec, Type t, string name, Location loc) { - return MemberLookup (ec, t, name, MemberTypes.Method, AllBindingFlags, loc); + return MemberLookup (ec, ec.ContainerType, t, name, + MemberTypes.Method, AllBindingFlags, loc); } /// @@ -429,10 +625,16 @@ namespace Mono.CSharp { { Expression e; - e = MemberLookup (ec, t, name, mt, bf, loc); + int errors = Report.Errors; + + e = MemberLookup (ec, ec.ContainerType, t, name, mt, bf, loc); if (e != null) return e; + + // Error has already been reported. + if (errors < Report.Errors) + return null; e = MemberLookup (ec, t, name, AllMemberTypes, AllBindingFlags | BindingFlags.NonPublic, loc); @@ -447,7 +649,14 @@ namespace Mono.CSharp { } return null; - } + } + + static public MemberInfo GetFieldFromEvent (EventExpr event_expr) + { + EventInfo ei = event_expr.EventInfo; + + return TypeManager.GetPrivateFieldOfEvent (ei); + } static EmptyExpression MyEmptyExpr; static public Expression ImplicitReferenceConversion (Expression expr, Type target_type) @@ -552,8 +761,7 @@ namespace Mono.CSharp { args.Add (new Argument (expr, Argument.AType.Expression)); - Expression ne = new New (target.FullName, args, - new Location (-1)); + Expression ne = new New (new TypeExpr (target, Location.Null), args, Location.Null); return ne.Resolve (ec); } @@ -590,19 +798,8 @@ namespace Mono.CSharp { return new ULongConstant ((ulong) v); } - // - // If we have an enumeration, extract the underlying type, - // use this during the comparission, but wrap around the original - // target_type - // - Type real_target_type = target_type; - - if (TypeManager.IsEnumType (real_target_type)) - real_target_type = TypeManager.EnumToUnderlying (real_target_type); + Type real_target_type = target_type; - if (expr_type == real_target_type) - return new EmptyCast (expr, target_type); - if (expr_type == TypeManager.sbyte_type){ // // From sbyte to short, int, long, float, double. @@ -700,11 +897,20 @@ namespace Mono.CSharp { OpCodes.Conv_R4); if (real_target_type == TypeManager.decimal_type) return InternalTypeConstructor (ec, expr, target_type); - } else if ((expr_type == TypeManager.uint64_type) || - (expr_type == TypeManager.int64_type)){ + } else if (expr_type == TypeManager.int64_type){ // // From long/ulong to float, double // + if (real_target_type == TypeManager.double_type) + return new OpcodeCast (expr, target_type, OpCodes.Conv_R8); + if (real_target_type == TypeManager.float_type) + return new OpcodeCast (expr, target_type, OpCodes.Conv_R4); + if (real_target_type == TypeManager.decimal_type) + return InternalTypeConstructor (ec, expr, target_type); + } else if (expr_type == TypeManager.uint64_type){ + // + // From ulong to float, double + // if (real_target_type == TypeManager.double_type) return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un, OpCodes.Conv_R8); @@ -797,7 +1003,7 @@ namespace Mono.CSharp { } // from an array-type to System.Array - if (expr_type.IsArray && target_type.IsAssignableFrom (expr_type)) + if (expr_type.IsArray && (target_type == TypeManager.array_type)) return true; // from any delegate type to System.Delegate @@ -812,7 +1018,8 @@ namespace Mono.CSharp { return true; // from the null type to any reference-type. - if (expr is NullLiteral && !target_type.IsValueType) + if (expr is NullLiteral && !target_type.IsValueType && + !TypeManager.IsEnumType (target_type)) return true; } @@ -836,7 +1043,7 @@ namespace Mono.CSharp { return false; } - + /// /// Determines if a standard implicit conversion exists from /// expr_type to target_type @@ -844,6 +1051,9 @@ namespace Mono.CSharp { public static bool StandardConversionExists (Expression expr, Type target_type) { Type expr_type = expr.Type; + + if (expr_type == TypeManager.void_type) + return false; if (expr_type == target_type) return true; @@ -1006,6 +1216,7 @@ namespace Mono.CSharp { if (i.Value == 0) return true; } + return false; } @@ -1085,7 +1296,7 @@ namespace Mono.CSharp { /// by making use of FindMostEncomp* methods. Applies the correct rules separately /// for explicit and implicit conversion operators. /// - static public Type FindMostSpecificSource (MethodGroupExpr me, Type source_type, + static public Type FindMostSpecificSource (MethodGroupExpr me, Expression source, bool apply_explicit_conv_rules, Location loc) { @@ -1093,10 +1304,11 @@ namespace Mono.CSharp { if (priv_fms_expr == null) priv_fms_expr = new EmptyExpression (); - + // // If any operator converts from S then Sx = S // + Type source_type = source.Type; foreach (MethodBase mb in me.Methods){ ParameterData pd = Invocation.GetParameterData (mb); Type param_type = pd.ParameterType (0); @@ -1117,16 +1329,14 @@ namespace Mono.CSharp { if (StandardConversionExists (priv_fms_expr, source_type)) src_types_set.Add (param_type); else { - priv_fms_expr.SetType (source_type); - if (StandardConversionExists (priv_fms_expr, param_type)) + if (StandardConversionExists (source, param_type)) src_types_set.Add (param_type); } } else { // // Only if S is encompassed by param_type // - priv_fms_expr.SetType (source_type); - if (StandardConversionExists (priv_fms_expr, param_type)) + if (StandardConversionExists (source, param_type)) src_types_set.Add (param_type); } } @@ -1138,9 +1348,7 @@ namespace Mono.CSharp { ArrayList candidate_set = new ArrayList (); foreach (Type param_type in src_types_set){ - priv_fms_expr.SetType (source_type); - - if (StandardConversionExists (priv_fms_expr, param_type)) + if (StandardConversionExists (source, param_type)) candidate_set.Add (param_type); } @@ -1233,8 +1441,10 @@ namespace Mono.CSharp { // if (apply_explicit_conv_rules) return FindMostEncompassedType (tgt_types_set); - else + else { + Console.WriteLine ("Here with: " + tgt_types_set.Count); return FindMostEncompassingType (tgt_types_set); + } } /// @@ -1355,14 +1565,14 @@ namespace Mono.CSharp { } #endif - most_specific_source = FindMostSpecificSource (union, source_type, look_for_explicit, loc); + most_specific_source = FindMostSpecificSource (union, source, look_for_explicit, loc); if (most_specific_source == null) return null; most_specific_target = FindMostSpecificTarget (union, target, look_for_explicit, loc); if (most_specific_target == null) return null; - + int count = 0; foreach (MethodBase mb in union.Methods){ @@ -1396,7 +1606,7 @@ namespace Mono.CSharp { return null; Expression e; - e = new UserCast ((MethodInfo) method, source); + e = new UserCast ((MethodInfo) method, source, loc); if (e.Type != target){ if (!look_for_explicit) e = ConvertImplicitStandard (ec, e, target, loc); @@ -1542,7 +1752,7 @@ namespace Mono.CSharp { TypeManager.CSharpName (source) + "' to `" + TypeManager.CSharpName (target) + "'"; - Error (29, loc, msg); + Report.Error (29, loc, msg); } /// @@ -1560,9 +1770,9 @@ namespace Mono.CSharp { return e; if (source is DoubleLiteral && target_type == TypeManager.float_type){ - Error (664, loc, - "Double literal cannot be implicitly converted to " + - "float type, use F suffix to create a float literal"); + Report.Error (664, loc, + "Double literal cannot be implicitly converted to " + + "float type, use F suffix to create a float literal"); } Error_CannotConvertImplicit (loc, source.Type, target_type); @@ -1573,14 +1783,13 @@ namespace Mono.CSharp { /// /// Performs the explicit numeric conversions /// - static Expression ConvertNumericExplicit (EmitContext ec, Expression expr, - Type target_type) + static Expression ConvertNumericExplicit (EmitContext ec, Expression expr, Type target_type) { Type expr_type = expr.Type; // // If we have an enumeration, extract the underlying type, - // use this during the comparission, but wrap around the original + // use this during the comparison, but wrap around the original // target_type // Type real_target_type = target_type; @@ -1588,6 +1797,9 @@ namespace Mono.CSharp { if (TypeManager.IsEnumType (real_target_type)) real_target_type = TypeManager.EnumToUnderlying (real_target_type); + if (StandardConversionExists (expr, real_target_type)) + return new EmptyCast (expr, target_type); + if (expr_type == TypeManager.sbyte_type){ // // From sbyte to byte, ushort, uint, ulong, char @@ -1854,7 +2066,7 @@ namespace Mono.CSharp { // From System.Array to any array-type if (source_type == TypeManager.array_type && - target_type.IsSubclassOf (TypeManager.array_type)){ + target_type.IsArray){ return true; } @@ -1953,7 +2165,7 @@ namespace Mono.CSharp { // From System.Array to any array-type if (source_type == TypeManager.array_type && - target_type.IsSubclassOf (TypeManager.array_type)){ + target_type.IsArray) { return new ClassCast (source, target_type); } @@ -2132,17 +2344,52 @@ namespace Mono.CSharp { /// /// Reports that we were expecting `expr' to be of class `expected' /// - protected void report118 (Location loc, Expression expr, string expected) + public void Error118 (string expected) { string kind = "Unknown"; - if (expr != null) - kind = ExprClassName (expr.eclass); + kind = ExprClassName (eclass); - Error (118, loc, "Expression denotes a `" + kind + + Error (118, "Expression denotes a `" + kind + "' where a `" + expected + "' was expected"); } + public void Error118 (ResolveFlags flags) + { + ArrayList valid = new ArrayList (10); + + if ((flags & ResolveFlags.VariableOrValue) != 0) { + valid.Add ("variable"); + valid.Add ("value"); + } + + if ((flags & ResolveFlags.Type) != 0) + valid.Add ("type"); + + if ((flags & ResolveFlags.MethodGroup) != 0) + valid.Add ("method group"); + + if ((flags & ResolveFlags.SimpleName) != 0) + valid.Add ("simple name"); + + if (valid.Count == 0) + valid.Add ("unknown"); + + StringBuilder sb = new StringBuilder (); + for (int i = 0; i < valid.Count; i++) { + if (i > 0) + sb.Append (", "); + else if (i == valid.Count) + sb.Append (" or "); + sb.Append (valid [i]); + } + + string kind = ExprClassName (eclass); + + Error (119, "Expression denotes a `" + kind + "' where " + + "a `" + sb.ToString () + "' was expected"); + } + static void Error_ConstantValueCannotBeConverted (Location l, string val, Type t) { Report.Error (31, l, "Constant value `" + val + "' cannot be converted to " + @@ -2454,9 +2701,12 @@ namespace Mono.CSharp { ig.Emit (OpCodes.Ldind_I1); else if (t == TypeManager.intptr_type) ig.Emit (OpCodes.Ldind_I); - else if (TypeManager.IsEnumType (t)) - LoadFromPtr (ig, TypeManager.EnumToUnderlying (t)); - else if (t.IsValueType) + else if (TypeManager.IsEnumType (t)) { + if (t == TypeManager.enum_type) + ig.Emit (OpCodes.Ldind_Ref); + else + LoadFromPtr (ig, TypeManager.EnumToUnderlying (t)); + } else if (t.IsValueType) ig.Emit (OpCodes.Ldobj, t); else ig.Emit (OpCodes.Ldind_Ref); @@ -2467,6 +2717,8 @@ namespace Mono.CSharp { // public static void StoreFromPtr (ILGenerator ig, Type type) { + if (type.IsEnum) + type = TypeManager.EnumToUnderlying (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) @@ -2484,7 +2736,7 @@ namespace Mono.CSharp { else if (type == TypeManager.intptr_type) ig.Emit (OpCodes.Stind_I); else if (type.IsValueType) - ig.Emit (OpCodes.Stobj); + ig.Emit (OpCodes.Stobj, type); else ig.Emit (OpCodes.Stind_Ref); } @@ -2494,6 +2746,7 @@ namespace Mono.CSharp { // public static int GetTypeSize (Type t) { + t = TypeManager.TypeToCoreType (t); if (t == TypeManager.int32_type || t == TypeManager.uint32_type || t == TypeManager.float_type) @@ -2520,6 +2773,59 @@ namespace Mono.CSharp { public void CacheTemporaries (EmitContext ec) { } + + static void Error_NegativeArrayIndex (Location loc) + { + Report.Error (284, loc, "Can not create array with a negative size"); + } + + // + // Converts `source' to an int, uint, long or ulong. + // + public Expression ExpressionToArrayArgument (EmitContext ec, Expression source, Location loc) + { + Expression target; + + bool old_checked = ec.CheckState; + ec.CheckState = true; + + target = ConvertImplicit (ec, source, TypeManager.int32_type, loc); + if (target == null){ + target = ConvertImplicit (ec, source, TypeManager.uint32_type, loc); + if (target == null){ + target = ConvertImplicit (ec, source, TypeManager.int64_type, loc); + if (target == null){ + target = ConvertImplicit (ec, source, TypeManager.uint64_type, loc); + if (target == null) + Expression.Error_CannotConvertImplicit (loc, source.Type, TypeManager.int32_type); + } + } + } + ec.CheckState = old_checked; + + // + // Only positive constants are allowed at compile time + // + if (target is Constant){ + if (target is IntConstant){ + if (((IntConstant) target).Value < 0){ + Error_NegativeArrayIndex (loc); + return null; + } + } + + if (target is LongConstant){ + if (((LongConstant) target).Value < 0){ + Error_NegativeArrayIndex (loc); + return null; + } + } + + } + + return target; + } + } /// @@ -2784,8 +3090,8 @@ namespace Mono.CSharp { public ConvCast (EmitContext ec, Expression child, Type return_type, Mode m) : base (child, return_type) { - mode = m; checked_state = ec.CheckState; + mode = m; } public override Expression DoResolve (EmitContext ec) @@ -3063,53 +3369,40 @@ namespace Mono.CSharp { /// The downside of this is that we might be hitting `LookupType' too many /// times with this scheme. /// - public class SimpleName : Expression { + public class SimpleName : Expression, ITypeExpression { public readonly string Name; - public readonly Location Location; public SimpleName (string name, Location l) { Name = name; - Location = l; + loc = l; } - public static void Error120 (Location l, string name) + public static void Error_ObjectRefRequired (EmitContext ec, Location l, string name) { - Report.Error ( - 120, l, - "An object reference is required " + - "for the non-static field `"+name+"'"); + if (ec.IsFieldInitializer) + Report.Error ( + 236, l, + "A field initializer cannot reference the non-static field, " + + "method or property `"+name+"'"); + else + Report.Error ( + 120, l, + "An object reference is required " + + "for the non-static field `"+name+"'"); } // // Checks whether we are trying to access an instance // property, method or field from a static body. // - Expression MemberStaticCheck (Expression e) + Expression MemberStaticCheck (EmitContext ec, Expression e) { - if (e is FieldExpr){ - FieldInfo fi = ((FieldExpr) e).FieldInfo; + if (e is IMemberExpr){ + IMemberExpr member = (IMemberExpr) e; - if (!fi.IsStatic){ - Error120 (Location, Name); - return null; - } - } else if (e is MethodGroupExpr){ - MethodGroupExpr mg = (MethodGroupExpr) e; - - if (!mg.RemoveInstanceMethods ()){ - Error120 (Location, mg.Methods [0].Name); - return null; - } - return e; - } else if (e is PropertyExpr){ - if (!((PropertyExpr) e).IsStatic){ - Error120 (Location, Name); - return null; - } - } else if (e is EventExpr) { - if (!((EventExpr) e).IsStatic) { - Error120 (Location, Name); + if (!member.IsStatic){ + Error_ObjectRefRequired (ec, loc, Name); return null; } } @@ -3133,15 +3426,56 @@ namespace Mono.CSharp { return SimpleNameResolve (ec, null, true); } - /// - /// 7.5.2: Simple Names. - /// - /// Local Variables and Parameters are handled at - /// parse time, so they never occur as SimpleNames. - /// - /// The `allow_static' flag is used by MemberAccess only - /// and it is used to inform us that it is ok for us to - /// avoid the static check, because MemberAccess might end + public Expression DoResolveType (EmitContext ec) + { + // + // Stage 3: Lookup symbol in the various namespaces. + // + DeclSpace ds = ec.DeclSpace; + Type t; + string alias_value; + + if ((t = RootContext.LookupType (ds, Name, true, loc)) != null) + return new TypeExpr (t, loc); + + // + // Stage 2 part b: Lookup up if we are an alias to a type + // or a namespace. + // + // Since we are cheating: we only do the Alias lookup for + // namespaces if the name does not include any dots in it + // + + alias_value = ec.DeclSpace.LookupAlias (Name); + + if (Name.IndexOf ('.') == -1 && alias_value != null) { + if ((t = RootContext.LookupType (ds, alias_value, true, loc)) != null) + return new TypeExpr (t, loc); + + // we have alias value, but it isn't Type, so try if it's namespace + return new SimpleName (alias_value, loc); + } + + if (ec.ResolvingTypeTree){ + Type dt = ec.DeclSpace.FindType (Name); + if (dt != null) + return new TypeExpr (dt, loc); + } + + // No match, maybe our parent can compose us + // into something meaningful. + return this; + } + + /// + /// 7.5.2: Simple Names. + /// + /// Local Variables and Parameters are handled at + /// parse time, so they never occur as SimpleNames. + /// + /// The `allow_static' flag is used by MemberAccess only + /// and it is used to inform us that it is ok for us to + /// avoid the static check, because MemberAccess might end /// up resolving the Name as a Type name and the access as /// a static type access. /// @@ -3157,214 +3491,112 @@ namespace Mono.CSharp { // // Stage 1: Performed by the parser (binding to locals or parameters). // - if (!ec.OnlyLookupTypes){ - Block current_block = ec.CurrentBlock; - if (current_block != null && current_block.IsVariableDefined (Name)){ - LocalVariableReference var; - - var = new LocalVariableReference (ec.CurrentBlock, Name, Location); + Block current_block = ec.CurrentBlock; + if (current_block != null && current_block.IsVariableDefined (Name)){ + LocalVariableReference var; - if (right_side != null) - return var.ResolveLValue (ec, right_side); - else - return var.Resolve (ec); - } - - // - // Stage 2: Lookup members - // + var = new LocalVariableReference (ec.CurrentBlock, Name, loc); - // - // For enums, the TypeBuilder is not ec.DeclSpace.TypeBuilder - // Hence we have two different cases - // - - DeclSpace lookup_ds = ec.DeclSpace; - do { - if (lookup_ds.TypeBuilder == null) - break; - - e = MemberLookup (ec, lookup_ds.TypeBuilder, Name, Location); - if (e != null) - break; - - // - // Classes/structs keep looking, enums break - // - if (lookup_ds is TypeContainer) - lookup_ds = ((TypeContainer) lookup_ds).Parent; - else - break; - } while (lookup_ds != null); - - if (e == null && ec.ContainerType != null) - e = MemberLookup (ec, ec.ContainerType, Name, Location); + if (right_side != null) + return var.ResolveLValue (ec, right_side); + else + return var.Resolve (ec); } - // Continuation of stage 2 - if (e == null){ - // - // Stage 3: Lookup symbol in the various namespaces. - // - DeclSpace ds = ec.DeclSpace; - Type t; - string alias_value; + if (current_block != null){ + int idx = -1; + Parameter par = null; + Parameters pars = current_block.Parameters; + if (pars != null) + par = pars.GetParameterByName (Name, out idx); - if ((t = RootContext.LookupType (ds, Name, true, Location)) != null) - return new TypeExpr (t); - - // - // Stage 2 part b: Lookup up if we are an alias to a type - // or a namespace. - // - // Since we are cheating: we only do the Alias lookup for - // namespaces if the name does not include any dots in it - // - - if (Name.IndexOf ('.') == -1 && (alias_value = ec.TypeContainer.LookupAlias (Name)) != null) { - // System.Console.WriteLine (Name + " --> " + alias_value); - if ((t = RootContext.LookupType (ds, alias_value, true, Location)) - != null) - return new TypeExpr (t); + if (par != null) { + ParameterReference param; - // we have alias value, but it isn't Type, so try if it's namespace - return new SimpleName (alias_value, Location); + param = new ParameterReference (pars, idx, Name, loc); + + if (right_side != null) + return param.ResolveLValue (ec, right_side); + else + return param.Resolve (ec); } - - // No match, maybe our parent can compose us - // into something meaningful. - return this; } - + + // + // Stage 2: Lookup members // - // Stage 2 continues here. - // - if (e is TypeExpr) - return e; - if (ec.OnlyLookupTypes) - return null; - - if (e is FieldExpr){ - FieldExpr fe = (FieldExpr) e; - FieldInfo fi = fe.FieldInfo; + // + // For enums, the TypeBuilder is not ec.DeclSpace.TypeBuilder + // Hence we have two different cases + // - if (fi.FieldType.IsPointer && !ec.InUnsafe){ - UnsafeError (Location); - } - - if (ec.IsStatic){ - if (!allow_static && !fi.IsStatic){ - Error120 (Location, Name); - return null; - } - } else { - // If we are not in static code and this - // field is not static, set the instance to `this'. + DeclSpace lookup_ds = ec.DeclSpace; + do { + if (lookup_ds.TypeBuilder == null) + break; - if (!fi.IsStatic) - fe.InstanceExpression = ec.This; - } + e = MemberLookup (ec, lookup_ds.TypeBuilder, Name, loc); + if (e != null) + break; + // + // Classes/structs keep looking, enums break + // + if (lookup_ds is TypeContainer) + lookup_ds = ((TypeContainer) lookup_ds).Parent; + else + break; + } while (lookup_ds != null); - if (fi is FieldBuilder) { - Const c = TypeManager.LookupConstant ((FieldBuilder) fi); - - if (c != null) { - object o = c.LookupConstantValue (ec); - object real_value = ((Constant)c.Expr).GetValue (); - return Constantify (real_value, fi.FieldType); - } - } + if (e == null && ec.ContainerType != null) + e = MemberLookup (ec, ec.ContainerType, Name, loc); - if (fi.IsLiteral) { - Type t = fi.FieldType; - Type decl_type = fi.DeclaringType; - object o; + if (e == null) + return DoResolveType (ec); - if (fi is FieldBuilder) - o = TypeManager.GetValue ((FieldBuilder) fi); - else - o = fi.GetValue (fi); - - if (decl_type.IsSubclassOf (TypeManager.enum_type)) { - Expression enum_member = MemberLookup ( - ec, decl_type, "value__", MemberTypes.Field, - AllBindingFlags, Location); - - Enum en = TypeManager.LookupEnum (decl_type); - - Constant c; - if (en != null) - c = Constantify (o, en.UnderlyingType); - else - c = Constantify (o, enum_member.Type); - - return new EnumConstant (c, decl_type); - } - - Expression exp = Constantify (o, t); - } - + if (e is TypeExpr) return e; - } - if (e is EventExpr) { - // - // If the event is local to this class, we transform ourselves into - // a FieldExpr - // - EventExpr ee = (EventExpr) e; - - Expression ml = MemberLookup ( - ec, ec.DeclSpace.TypeBuilder, ee.EventInfo.Name, - MemberTypes.Event, AllBindingFlags, Location); + if (e is IMemberExpr) { + e = MemberAccess.ResolveMemberAccess (ec, e, null, loc, this); + if (e == null) + return null; - if (ml != null) { - MemberInfo mi = ec.TypeContainer.GetFieldFromEvent ((EventExpr) ml); + IMemberExpr me = e as IMemberExpr; + if (me == null) + return e; - if (mi == null) { - // - // If this happens, then we have an event with its own - // accessors and private field etc so there's no need - // to transform ourselves : we should instead flag an error - // - Assign.error70 (ee.EventInfo, Location); - return null; - } + // This fails if ResolveMemberAccess() was unable to decide whether + // it's a field or a type of the same name. + if (!me.IsStatic && (me.InstanceExpression == null)) + return e; - ml = ExprClassFromMemberInfo (ec, mi, Location); - - if (ml == null) { - Report.Error (-200, Location, "Internal error!!"); - return null; - } + if (!me.IsStatic && + TypeManager.IsNestedChildOf (me.InstanceExpression.Type, me.DeclaringType)) { + Error (38, "Cannot access nonstatic member `" + me.Name + "' of " + + "outer type `" + me.DeclaringType + "' via nested type `" + + me.InstanceExpression.Type + "'"); + return null; + } - Expression instance_expr; - - FieldInfo fi = ((FieldExpr) ml).FieldInfo; + if (right_side != null) + e = e.DoResolveLValue (ec, right_side); + else + e = e.DoResolve (ec); - if (fi.IsStatic) - instance_expr = null; - else { - instance_expr = ec.This; - instance_expr = instance_expr.Resolve (ec); - } - - return MemberAccess.ResolveMemberAccess (ec, ml, instance_expr, Location, null); - } + return e; } - - - if (ec.IsStatic){ + + if (ec.IsStatic || ec.IsFieldInitializer){ if (allow_static) return e; - return MemberStaticCheck (e); + return MemberStaticCheck (ec, e); } else return e; } - + public override void Emit (EmitContext ec) { // @@ -3372,20 +3604,31 @@ namespace Mono.CSharp { // find the name as a namespace // - Error (103, Location, "The name `" + Name + + Error (103, "The name `" + Name + "' does not exist in the class `" + ec.DeclSpace.Name + "'"); } + + public override string ToString () + { + return Name; + } } /// /// Fully resolved expression that evaluates to a type /// - public class TypeExpr : Expression { - public TypeExpr (Type t) + public class TypeExpr : Expression, ITypeExpression { + public TypeExpr (Type t, Location l) { Type = t; eclass = ExprClass.Type; + loc = l; + } + + public virtual Expression DoResolveType (EmitContext ec) + { + return this; } override public Expression DoResolve (EmitContext ec) @@ -3395,7 +3638,48 @@ namespace Mono.CSharp { override public void Emit (EmitContext ec) { - throw new Exception ("Implement me"); + throw new Exception ("Should never be called"); + } + + public override string ToString () + { + return Type.ToString (); + } + } + + /// + /// Used to create types from a fully qualified name. These are just used + /// by the parser to setup the core types. A TypeLookupExpression is always + /// classified as a type. + /// + public class TypeLookupExpression : TypeExpr { + string name; + + public TypeLookupExpression (string name) : base (null, Location.Null) + { + this.name = name; + } + + public override Expression DoResolveType (EmitContext ec) + { + if (type == null) + type = RootContext.LookupType (ec.DeclSpace, name, false, Location.Null); + return this; + } + + public override Expression DoResolve (EmitContext ec) + { + return DoResolveType (ec); + } + + public override void Emit (EmitContext ec) + { + throw new Exception ("Should never be called"); + } + + public override string ToString () + { + return name; } } @@ -3404,10 +3688,10 @@ namespace Mono.CSharp { /// /// This is a fully resolved expression that evaluates to a type /// - public class MethodGroupExpr : Expression { + public class MethodGroupExpr : Expression, IMemberExpr { public MethodBase [] Methods; - Location loc; Expression instance_expression = null; + bool is_explicit_impl = false; public MethodGroupExpr (MemberInfo [] mi, Location l) { @@ -3437,6 +3721,12 @@ namespace Mono.CSharp { eclass = ExprClass.MethodGroup; type = TypeManager.object_type; } + + public Type DeclaringType { + get { + return Methods [0].DeclaringType; + } + } // // `A method group may have associated an instance expression' @@ -3450,9 +3740,51 @@ namespace Mono.CSharp { instance_expression = value; } } + + public bool IsExplicitImpl { + get { + return is_explicit_impl; + } + + set { + is_explicit_impl = value; + } + } + + public string Name { + get { + return Methods [0].Name; + } + } + + public bool IsInstance { + get { + foreach (MethodBase mb in Methods) + if (!mb.IsStatic) + return true; + + return false; + } + } + + public bool IsStatic { + get { + foreach (MethodBase mb in Methods) + if (mb.IsStatic) + return true; + + return false; + } + } override public Expression DoResolve (EmitContext ec) { + if (instance_expression != null) { + instance_expression = instance_expression.DoResolve (ec); + if (instance_expression == null) + return null; + } + return this; } @@ -3507,10 +3839,9 @@ namespace Mono.CSharp { /// /// Fully resolved expression that evaluates to a Field /// - public class FieldExpr : Expression, IAssignMethod, IMemoryLocation { + public class FieldExpr : Expression, IAssignMethod, IMemoryLocation, IMemberExpr { public readonly FieldInfo FieldInfo; - public Expression InstanceExpression; - Location loc; + Expression instance_expr; public FieldExpr (FieldInfo fi, Location l) { @@ -3520,20 +3851,63 @@ namespace Mono.CSharp { loc = l; } + public string Name { + get { + return FieldInfo.Name; + } + } + + public bool IsInstance { + get { + return !FieldInfo.IsStatic; + } + } + + public bool IsStatic { + get { + return FieldInfo.IsStatic; + } + } + + public Type DeclaringType { + get { + return FieldInfo.DeclaringType; + } + } + + public Expression InstanceExpression { + get { + return instance_expr; + } + + set { + instance_expr = value; + } + } + override public Expression DoResolve (EmitContext ec) { if (!FieldInfo.IsStatic){ - if (InstanceExpression == null){ + if (instance_expr == null){ throw new Exception ("non-static FieldExpr without instance var\n" + "You have to assign the Instance variable\n" + "Of the FieldExpr to set this\n"); } - InstanceExpression = InstanceExpression.Resolve (ec); - if (InstanceExpression == null) + // Resolve the field's instance expression while flow analysis is turned + // off: when accessing a field "a.b", we must check whether the field + // "a.b" is initialized, not whether the whole struct "a" is initialized. + instance_expr = instance_expr.Resolve (ec, ResolveFlags.VariableOrValue | + ResolveFlags.DisableFlowAnalysis); + if (instance_expr == null) return null; } + // If the instance expression is a local variable or parameter. + IVariable var = instance_expr as IVariable; + if ((var != null) && !var.IsFieldAssigned (ec, FieldInfo.Name, loc)) + return null; + return this; } @@ -3553,6 +3927,10 @@ namespace Mono.CSharp { override public Expression DoResolveLValue (EmitContext ec, Expression right_side) { + IVariable var = instance_expr as IVariable; + if (var != null) + var.SetFieldAssigned (ec, FieldInfo.Name); + Expression e = DoResolve (ec); if (e == null) @@ -3577,7 +3955,7 @@ namespace Mono.CSharp { { ILGenerator ig = ec.ig; bool is_volatile = false; - + if (FieldInfo is FieldBuilder){ FieldBase f = TypeManager.GetField (FieldInfo); @@ -3593,23 +3971,23 @@ namespace Mono.CSharp { ig.Emit (OpCodes.Ldsfld, FieldInfo); } else { - if (InstanceExpression.Type.IsValueType){ + if (instance_expr.Type.IsValueType){ IMemoryLocation ml; LocalTemporary tempo = null; - if (!(InstanceExpression is IMemoryLocation)){ + if (!(instance_expr is IMemoryLocation)){ tempo = new LocalTemporary ( - ec, InstanceExpression.Type); + ec, instance_expr.Type); InstanceExpression.Emit (ec); tempo.Store (ec); ml = tempo; } else - ml = (IMemoryLocation) InstanceExpression; + ml = (IMemoryLocation) instance_expr; ml.AddressOf (ec, AddressOp.Load); } else - InstanceExpression.Emit (ec); + instance_expr.Emit (ec); if (is_volatile) ig.Emit (OpCodes.Volatile); @@ -3631,7 +4009,7 @@ namespace Mono.CSharp { } if (!is_static){ - Expression instance = InstanceExpression; + Expression instance = instance_expr; if (instance.Type.IsValueType){ if (instance is IMemoryLocation){ @@ -3691,19 +4069,26 @@ namespace Mono.CSharp { // get the address of the copy. // if (FieldInfo.IsInitOnly){ - LocalBuilder local; + if (ec.IsConstructor) { + ig.Emit (OpCodes.Ldsflda, FieldInfo); + } else { + LocalBuilder local; - Emit (ec); - local = ig.DeclareLocal (type); - ig.Emit (OpCodes.Stloc, local); - ig.Emit (OpCodes.Ldloca, local); + Emit (ec); + local = ig.DeclareLocal (type); + ig.Emit (OpCodes.Stloc, local); + ig.Emit (OpCodes.Ldloca, local); + } return; - } + } if (FieldInfo.IsStatic) ig.Emit (OpCodes.Ldsflda, FieldInfo); else { - InstanceExpression.Emit (ec); + if (instance_expr is IMemoryLocation) + ((IMemoryLocation)instance_expr).AddressOf (ec, AddressOp.LoadStore); + else + instance_expr.Emit (ec); ig.Emit (OpCodes.Ldflda, FieldInfo); } } @@ -3716,20 +4101,19 @@ namespace Mono.CSharp { /// This is not an LValue because we need to re-write the expression, we /// can not take data from the stack and store it. /// - public class PropertyExpr : ExpressionStatement, IAssignMethod { + public class PropertyExpr : ExpressionStatement, IAssignMethod, IMemberExpr { public readonly PropertyInfo PropertyInfo; - public readonly bool IsStatic; public bool IsBase; MethodInfo [] Accessors; - Location loc; + bool is_static; Expression instance_expr; - + public PropertyExpr (PropertyInfo pi, Location l) { PropertyInfo = pi; eclass = ExprClass.PropertyAccess; - IsStatic = false; + is_static = false; loc = l; Accessors = TypeManager.GetAccessors (pi); @@ -3737,12 +4121,36 @@ namespace Mono.CSharp { foreach (MethodInfo mi in Accessors){ if (mi != null) if (mi.IsStatic) - IsStatic = true; + is_static = true; } else Accessors = new MethodInfo [2]; - type = pi.PropertyType; + type = TypeManager.TypeToCoreType (pi.PropertyType); + } + + public string Name { + get { + return PropertyInfo.Name; + } + } + + public bool IsInstance { + get { + return !is_static; + } + } + + public bool IsStatic { + get { + return is_static; + } + } + + public Type DeclaringType { + get { + return PropertyInfo.DeclaringType; + } } // @@ -3780,7 +4188,35 @@ namespace Mono.CSharp { return null; } - type = PropertyInfo.PropertyType; + if ((instance_expr == null) && ec.IsStatic && !is_static) { + SimpleName.Error_ObjectRefRequired (ec, loc, PropertyInfo.Name); + return null; + } + + if (instance_expr != null) { + instance_expr = instance_expr.DoResolve (ec); + if (instance_expr == null) + return null; + } + + return this; + } + + override public Expression DoResolveLValue (EmitContext ec, Expression right_side) + { + if (!PropertyInfo.CanWrite){ + Report.Error (154, loc, + "The property `" + PropertyInfo.Name + + "' can not be used in " + + "this context because it lacks a set accessor"); + return null; + } + + if (instance_expr != null) { + instance_expr = instance_expr.DoResolve (ec); + if (instance_expr == null) + return null; + } return this; } @@ -3792,21 +4228,22 @@ namespace Mono.CSharp { // // Special case: length of single dimension array is turned into ldlen // - if (method == TypeManager.int_array_get_length){ + if ((method == TypeManager.system_int_array_get_length) || + (method == TypeManager.int_array_get_length)){ Type iet = instance_expr.Type; // // 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)){ + if (iet != TypeManager.array_type && (iet.GetArrayRank () == 1)){ instance_expr.Emit (ec); ec.ig.Emit (OpCodes.Ldlen); return; } } - Invocation.EmitCall (ec, IsBase, IsStatic, instance_expr, method, null); + Invocation.EmitCall (ec, IsBase, IsStatic, instance_expr, method, null, loc); } @@ -3819,7 +4256,7 @@ namespace Mono.CSharp { ArrayList args = new ArrayList (); args.Add (arg); - Invocation.EmitCall (ec, false, IsStatic, instance_expr, Accessors [1], args); + Invocation.EmitCall (ec, false, IsStatic, instance_expr, Accessors [1], args, loc); } override public void EmitStatement (EmitContext ec) @@ -3832,13 +4269,11 @@ namespace Mono.CSharp { /// /// Fully resolved expression that evaluates to an Event /// - public class EventExpr : Expression { + public class EventExpr : Expression, IMemberExpr { public readonly EventInfo EventInfo; - Location loc; - public Expression InstanceExpression; - - public readonly bool IsStatic; + public Expression instance_expr; + bool is_static; MethodInfo add_accessor, remove_accessor; public EventExpr (EventInfo ei, Location loc) @@ -3851,7 +4286,7 @@ namespace Mono.CSharp { remove_accessor = TypeManager.GetRemoveMethod (ei); if (add_accessor.IsStatic || remove_accessor.IsStatic) - IsStatic = true; + is_static = true; if (EventInfo is MyEventBuilder) type = ((MyEventBuilder) EventInfo).EventType; @@ -3859,13 +4294,52 @@ namespace Mono.CSharp { type = EventInfo.EventHandlerType; } - override public Expression DoResolve (EmitContext ec) + public string Name { + get { + return EventInfo.Name; + } + } + + public bool IsInstance { + get { + return !is_static; + } + } + + public bool IsStatic { + get { + return is_static; + } + } + + public Type DeclaringType { + get { + return EventInfo.DeclaringType; + } + } + + public Expression InstanceExpression { + get { + return instance_expr; + } + + set { + instance_expr = value; + } + } + + public override Expression DoResolve (EmitContext ec) { - // We are born fully resolved + if (instance_expr != null) { + instance_expr = instance_expr.DoResolve (ec); + if (instance_expr == null) + return null; + } + return this; } - override public void Emit (EmitContext ec) + public override void Emit (EmitContext ec) { throw new Exception ("Should not happen I think"); } @@ -3881,10 +4355,10 @@ namespace Mono.CSharp { if (((Binary) source).Oper == Binary.Operator.Addition) Invocation.EmitCall ( - ec, false, IsStatic, InstanceExpression, add_accessor, args); + ec, false, IsStatic, instance_expr, add_accessor, args, loc); else Invocation.EmitCall ( - ec, false, IsStatic, InstanceExpression, remove_accessor, args); + ec, false, IsStatic, instance_expr, remove_accessor, args, loc); } } }