X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fecore.cs;h=46a3c677a1a5e01ad9ecd576180fd6d508ca82b8;hb=c5118cc145a60dccbb8247b9f4917d286056b54e;hp=d7fa1d0196aeb976127636f9229e5e7fec0f5d62;hpb=76f71ea43b0b8eff5e09c36db31c4be6cd28af27;p=mono.git diff --git a/mcs/mcs/ecore.cs b/mcs/mcs/ecore.cs index d7fa1d0196a..46a3c677a1a 100755 --- a/mcs/mcs/ecore.cs +++ b/mcs/mcs/ecore.cs @@ -171,17 +171,6 @@ namespace Mono.CSharp { } } - /// - /// Expression which resolves to a type. - /// - public interface ITypeExpression - { - /// - /// Resolve the expression, but only lookup types. - /// - Expression DoResolveType (EmitContext ec); - } - /// /// Base class for expressions /// @@ -278,7 +267,33 @@ namespace Mono.CSharp { { return DoResolve (ec); } - + + // + // This is used if the expression should be resolved as a type. + // the default implementation fails. Use this method in + // those participants in the SimpleName chain system. + // + public virtual Expression ResolveAsTypeStep (EmitContext ec) + { + return null; + } + + // + // This is used to resolve the expression as a type, a null + // value will be returned if the expression is not a type + // reference + // + public Expression ResolveAsTypeTerminal (EmitContext ec) + { + Expression e = ResolveAsTypeStep (ec); + + if (e == null) + return null; + if (e is SimpleName) + return null; + return e; + } + /// /// Resolves an expression and performs semantic analysis on it. /// @@ -289,15 +304,8 @@ namespace Mono.CSharp { /// public Expression Resolve (EmitContext ec, ResolveFlags flags) { - // Are we doing a types-only search ? - if ((flags & ResolveFlags.MaskExprClass) == ResolveFlags.Type) { - ITypeExpression type_expr = this as ITypeExpression; - - if (type_expr == null) - return null; - - return type_expr.DoResolveType (ec); - } + if ((flags & ResolveFlags.MaskExprClass) == ResolveFlags.Type) + return ResolveAsTypeStep (ec); bool old_do_flow_analysis = ec.DoFlowAnalysis; if ((flags & ResolveFlags.DisableFlowAnalysis) != 0) @@ -318,16 +326,8 @@ namespace Mono.CSharp { 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 + "'"); + MemberLookupFailed (ec, null, ec.ContainerType, s.Name, + ec.DeclSpace.Name, loc); return null; } @@ -336,7 +336,7 @@ namespace Mono.CSharp { if ((e is TypeExpr) || (e is ComposedCast)) { if ((flags & ResolveFlags.Type) == 0) { - e.Error118 (flags); + e.Error_UnexpectedKind (flags); return null; } @@ -346,7 +346,7 @@ namespace Mono.CSharp { switch (e.eclass) { case ExprClass.Type: if ((flags & ResolveFlags.VariableOrValue) == 0) { - e.Error118 (flags); + e.Error_UnexpectedKind (flags); return null; } break; @@ -364,7 +364,12 @@ namespace Mono.CSharp { case ExprClass.EventAccess: case ExprClass.IndexerAccess: if ((flags & ResolveFlags.VariableOrValue) == 0) { - e.Error118 (flags); + Console.WriteLine ("I got: {0} and {1}", e.GetType (), e); + Console.WriteLine ("I am {0} and {1}", this.GetType (), this); + FieldInfo fi = ((FieldExpr) e).FieldInfo; + + Console.WriteLine ("{0} and {1}", fi.DeclaringType, fi.Name); + e.Error_UnexpectedKind (flags); return null; } break; @@ -406,11 +411,8 @@ namespace Mono.CSharp { if (e != null){ if (e is SimpleName){ SimpleName s = (SimpleName) e; - - Report.Error ( - 103, loc, - "The name `" + s.Name + "' could not be found in `" + - ec.DeclSpace.Name + "'"); + MemberLookupFailed (ec, null, ec.ContainerType, s.Name, + ec.DeclSpace.Name, loc); return null; } @@ -512,7 +514,7 @@ namespace Mono.CSharp { else if (mi is FieldInfo) return new FieldExpr ((FieldInfo) mi, loc); else if (mi is PropertyInfo) - return new PropertyExpr ((PropertyInfo) mi, loc); + return new PropertyExpr (ec, (PropertyInfo) mi, loc); else if (mi is Type){ return new TypeExpr ((System.Type) mi, loc); } @@ -548,38 +550,36 @@ namespace Mono.CSharp { // FIXME: Potential optimization, have a static ArrayList // - public static Expression MemberLookup (EmitContext ec, Type t, string name, + public static Expression MemberLookup (EmitContext ec, Type queried_type, string name, MemberTypes mt, BindingFlags bf, Location loc) { - return MemberLookup (ec, ec.ContainerType, t, name, mt, bf, loc); + return MemberLookup (ec, ec.ContainerType, null, queried_type, 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)). - // + // Lookup type `queried_type' for code in class `container_type' with a qualifier of + // `qualifier_type' or null to lookup members in the current class. + // - public static Expression MemberLookup (EmitContext ec, Type invocation_type, Type t, - string name, MemberTypes mt, BindingFlags bf, - Location loc) + public static Expression MemberLookup (EmitContext ec, Type container_type, + Type qualifier_type, Type queried_type, + string name, MemberTypes mt, + BindingFlags bf, Location loc) { - MemberInfo [] mi = TypeManager.MemberLookup (invocation_type, t, mt, bf, name); + MemberInfo [] mi = TypeManager.MemberLookup (container_type, qualifier_type, + queried_type, mt, bf, name); if (mi == null) return null; int count = mi.Length; - if (count > 1) - return new MethodGroupExpr (mi, loc); - if (mi [0] is MethodBase) return new MethodGroupExpr (mi, loc); + if (count > 1) + return null; + return ExprClassFromMemberInfo (ec, mi [0], loc); } @@ -596,15 +596,24 @@ namespace Mono.CSharp { BindingFlags.Static | BindingFlags.Instance; - public static Expression MemberLookup (EmitContext ec, Type t, string name, Location loc) + public static Expression MemberLookup (EmitContext ec, Type queried_type, + string name, Location loc) { - return MemberLookup (ec, ec.ContainerType, t, name, + return MemberLookup (ec, ec.ContainerType, null, queried_type, name, AllMemberTypes, AllBindingFlags, loc); } - public static Expression MethodLookup (EmitContext ec, Type t, string name, Location loc) + public static Expression MemberLookup (EmitContext ec, Type qualifier_type, + Type queried_type, string name, Location loc) { - return MemberLookup (ec, ec.ContainerType, t, name, + return MemberLookup (ec, ec.ContainerType, qualifier_type, queried_type, + name, AllMemberTypes, AllBindingFlags, loc); + } + + public static Expression MethodLookup (EmitContext ec, Type queried_type, + string name, Location loc) + { + return MemberLookup (ec, ec.ContainerType, null, queried_type, name, MemberTypes.Method, AllBindingFlags, loc); } @@ -614,20 +623,24 @@ namespace Mono.CSharp { /// look for private members and display a useful debugging message if we /// find it. /// - public static Expression MemberLookupFinal (EmitContext ec, Type t, string name, - Location loc) + public static Expression MemberLookupFinal (EmitContext ec, Type qualifier_type, + Type queried_type, string name, Location loc) { - return MemberLookupFinal (ec, t, name, MemberTypes.Method, AllBindingFlags, loc); + return MemberLookupFinal (ec, qualifier_type, queried_type, name, + AllMemberTypes, AllBindingFlags, loc); } - public static Expression MemberLookupFinal (EmitContext ec, Type t, string name, - MemberTypes mt, BindingFlags bf, Location loc) + public static Expression MemberLookupFinal (EmitContext ec, Type qualifier_type, + Type queried_type, string name, + MemberTypes mt, BindingFlags bf, + Location loc) { Expression e; int errors = Report.Errors; - e = MemberLookup (ec, ec.ContainerType, t, name, mt, bf, loc); + e = MemberLookup (ec, ec.ContainerType, qualifier_type, queried_type, + name, mt, bf, loc); if (e != null) return e; @@ -635,20 +648,63 @@ namespace Mono.CSharp { // Error has already been reported. if (errors < Report.Errors) return null; - - e = MemberLookup (ec, t, name, AllMemberTypes, - AllBindingFlags | BindingFlags.NonPublic, loc); - if (e == null){ + + MemberLookupFailed (ec, qualifier_type, queried_type, name, null, loc); + return null; + } + + public static void MemberLookupFailed (EmitContext ec, Type qualifier_type, + Type queried_type, string name, + string class_name, Location loc) + { + object lookup = TypeManager.MemberLookup (queried_type, null, queried_type, + AllMemberTypes, AllBindingFlags | + BindingFlags.NonPublic, name); + + if (lookup == null) { + if (class_name != null) + Report.Error (103, loc, "The name `" + name + "' could not be " + + "found in `" + class_name + "'"); + else + Report.Error ( + 117, loc, "`" + queried_type + "' does not contain a " + + "definition for `" + name + "'"); + return; + } + + if ((qualifier_type != null) && (qualifier_type != ec.ContainerType) && + ec.ContainerType.IsSubclassOf (qualifier_type)) { + // Although a derived class can access protected members of + // its base class it cannot do so through an instance of the + // base class (CS1540). If the qualifier_type is a parent of the + // ec.ContainerType and the lookup succeeds with the latter one, + // then we are in this situation. + + lookup = TypeManager.MemberLookup ( + ec.ContainerType, ec.ContainerType, ec.ContainerType, + AllMemberTypes, AllBindingFlags, name); + + if (lookup != null) { + Report.Error ( + 1540, loc, "Cannot access protected member `" + + TypeManager.CSharpName (qualifier_type) + "." + + name + "' " + "via a qualifier of type `" + + TypeManager.CSharpName (qualifier_type) + "'; the " + + "qualifier must be of type `" + + TypeManager.CSharpName (ec.ContainerType) + "' " + + "(or derived from it)"); + return; + } + } + + if (qualifier_type != null) Report.Error ( - 117, loc, "`" + t + "' does not contain a definition " + - "for `" + name + "'"); - } else { + 122, loc, "`" + TypeManager.CSharpName (qualifier_type) + "." + + name + "' is inaccessible due to its protection level"); + else Report.Error ( - 122, loc, "`" + t + "." + name + - "' is inaccessible due to its protection level"); - } - - return null; + 122, loc, "`" + name + "' is inaccessible due to its " + + "protection level"); } static public MemberInfo GetFieldFromEvent (EventExpr event_expr) @@ -668,7 +724,11 @@ namespace Mono.CSharp { expr.Emit (null); } - + + // + // notice that it is possible to write "ValueType v = 1", the ValueType here + // is an abstract class, and not really a value type, so we apply the same rules. + // if (target_type == TypeManager.object_type) { // // A pointer type cannot be converted to object @@ -678,9 +738,22 @@ namespace Mono.CSharp { if (expr_type.IsValueType) return new BoxedCast (expr); - if (expr_type.IsClass || expr_type.IsInterface) + if (expr_type.IsClass || expr_type.IsInterface || expr_type == TypeManager.enum_type) return new EmptyCast (expr, target_type); + } else if (target_type == TypeManager.value_type) { + if (expr_type.IsValueType) + return new BoxedCast (expr); + if (expr is NullLiteral) + return new BoxedCast (expr); } else if (expr_type.IsSubclassOf (target_type)) { + // + // Special case: enumeration to System.Enum. + // System.Enum is not a value type, it is a class, so we need + // a boxing conversion + // + if (expr_type.IsEnum) + return new BoxedCast (expr); + return new EmptyCast (expr, target_type); } else { @@ -691,19 +764,20 @@ namespace Mono.CSharp { // from the null type to any reference-type. if (expr is NullLiteral && !target_type.IsValueType) - return new EmptyCast (expr, target_type); + return new NullLiteralTyped (target_type); // from any class-type S to any interface-type T. - if (expr_type.IsClass && target_type.IsInterface) { - if (TypeManager.ImplementsInterface (expr_type, target_type)) - return new EmptyCast (expr, target_type); - else - return null; + if (target_type.IsInterface) { + if (TypeManager.ImplementsInterface (expr_type, target_type)){ + if (expr_type.IsClass) + return new EmptyCast (expr, target_type); + else if (expr_type.IsValueType) + return new BoxedCast (expr); + } } // from any interface type S to interface-type T. if (expr_type.IsInterface && target_type.IsInterface) { - if (TypeManager.ImplementsInterface (expr_type, target_type)) return new EmptyCast (expr, target_type); else @@ -735,12 +809,15 @@ namespace Mono.CSharp { return new EmptyCast (expr, target_type); // from any delegate type to System.Delegate - if (expr_type.IsSubclassOf (TypeManager.delegate_type) && + if ((expr_type == TypeManager.delegate_type || + expr_type.IsSubclassOf (TypeManager.delegate_type)) && target_type == TypeManager.delegate_type) return new EmptyCast (expr, target_type); // from any array-type or delegate type into System.ICloneable. - if (expr_type.IsArray || expr_type.IsSubclassOf (TypeManager.delegate_type)) + if (expr_type.IsArray || + expr_type == TypeManager.delegate_type || + expr_type.IsSubclassOf (TypeManager.delegate_type)) if (target_type == TypeManager.icloneable_type) return new EmptyCast (expr, target_type); @@ -751,21 +828,6 @@ namespace Mono.CSharp { return null; } - /// - /// Handles expressions like this: decimal d; d = 1; - /// and changes them into: decimal d; d = new System.Decimal (1); - /// - static Expression InternalTypeConstructor (EmitContext ec, Expression expr, Type target) - { - ArrayList args = new ArrayList (); - - args.Add (new Argument (expr, Argument.AType.Expression)); - - Expression ne = new New (new TypeExpr (target, Location.Null), args, Location.Null); - - return ne.Resolve (ec); - } - /// /// Implicit Numeric Conversions. /// @@ -780,24 +842,27 @@ namespace Mono.CSharp { // // Attempt to do the implicit constant expression conversions - if (expr is IntConstant){ - Expression e; + if (expr is Constant){ - e = TryImplicitIntConversion (target_type, (IntConstant) expr); - - if (e != null) - return e; - } else if (expr is LongConstant && target_type == TypeManager.uint64_type){ - // - // Try the implicit constant expression conversion - // from long to ulong, instead of a nice routine, - // we just inline it - // - long v = ((LongConstant) expr).Value; - if (v > 0) - return new ULongConstant ((ulong) v); + if (expr is IntConstant){ + Expression e; + + e = TryImplicitIntConversion (target_type, (IntConstant) expr); + + if (e != null) + return e; + } else if (expr is LongConstant && target_type == TypeManager.uint64_type){ + // + // Try the implicit constant expression conversion + // from long to ulong, instead of a nice routine, + // we just inline it + // + long v = ((LongConstant) expr).Value; + if (v > 0) + return new ULongConstant ((ulong) v); + } } - + Type real_target_type = target_type; if (expr_type == TypeManager.sbyte_type){ @@ -814,8 +879,6 @@ namespace Mono.CSharp { return new OpcodeCast (expr, target_type, OpCodes.Conv_R4); if (real_target_type == TypeManager.short_type) return new OpcodeCast (expr, target_type, OpCodes.Conv_I2); - if (real_target_type == TypeManager.decimal_type) - return InternalTypeConstructor (ec, expr, target_type); } else if (expr_type == TypeManager.byte_type){ // // From byte to short, ushort, int, uint, long, ulong, float, double @@ -834,8 +897,6 @@ namespace Mono.CSharp { return new OpcodeCast (expr, target_type, OpCodes.Conv_R4); if (real_target_type == TypeManager.double_type) return new OpcodeCast (expr, target_type, OpCodes.Conv_R8); - if (real_target_type == TypeManager.decimal_type) - return InternalTypeConstructor (ec, expr, target_type); } else if (expr_type == TypeManager.short_type){ // // From short to int, long, float, double @@ -848,8 +909,6 @@ namespace Mono.CSharp { 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.ushort_type){ // // From ushort to int, uint, long, ulong, float, double @@ -867,8 +926,6 @@ namespace Mono.CSharp { 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.int32_type){ // // From int to long, float, double @@ -879,8 +936,6 @@ namespace Mono.CSharp { 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.uint32_type){ // // From uint to long, ulong, float, double @@ -895,8 +950,6 @@ namespace Mono.CSharp { if (real_target_type == TypeManager.float_type) return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un, OpCodes.Conv_R4); - if (real_target_type == TypeManager.decimal_type) - return InternalTypeConstructor (ec, expr, target_type); } else if (expr_type == TypeManager.int64_type){ // // From long/ulong to float, double @@ -905,8 +958,6 @@ namespace Mono.CSharp { 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 @@ -917,8 +968,6 @@ namespace Mono.CSharp { if (real_target_type == TypeManager.float_type) return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un, OpCodes.Conv_R4); - if (real_target_type == TypeManager.decimal_type) - return InternalTypeConstructor (ec, expr, target_type); } else if (expr_type == TypeManager.char_type){ // // From char to ushort, int, uint, long, ulong, float, double @@ -935,8 +984,6 @@ namespace Mono.CSharp { return new OpcodeCast (expr, target_type, OpCodes.Conv_R4); if (real_target_type == TypeManager.double_type) return new OpcodeCast (expr, target_type, OpCodes.Conv_R8); - if (real_target_type == TypeManager.decimal_type) - return InternalTypeConstructor (ec, expr, target_type); } else if (expr_type == TypeManager.float_type){ // // float to double @@ -960,20 +1007,17 @@ namespace Mono.CSharp { // This is the boxed case. // if (target_type == TypeManager.object_type) { - if ((expr_type.IsClass) || - (expr_type.IsValueType) || - (expr_type.IsInterface)) + if (expr_type.IsClass || expr_type.IsValueType || + expr_type.IsInterface || expr_type == TypeManager.enum_type) return true; - } else if (expr_type.IsSubclassOf (target_type)) { return true; - } else { // Please remember that all code below actually comes // from ImplicitReferenceConversion so make sure code remains in sync // from any class-type S to any interface-type T. - if (expr_type.IsClass && target_type.IsInterface) { + if (target_type.IsInterface) { if (TypeManager.ImplementsInterface (expr_type, target_type)) return true; } @@ -1007,13 +1051,16 @@ namespace Mono.CSharp { return true; // from any delegate type to System.Delegate - if (expr_type.IsSubclassOf (TypeManager.delegate_type) && + if ((expr_type == TypeManager.delegate_type || + expr_type.IsSubclassOf (TypeManager.delegate_type)) && target_type == TypeManager.delegate_type) if (target_type.IsAssignableFrom (expr_type)) return true; // from any array-type or delegate type into System.ICloneable. - if (expr_type.IsArray || expr_type.IsSubclassOf (TypeManager.delegate_type)) + if (expr_type.IsArray || + expr_type == TypeManager.delegate_type || + expr_type.IsSubclassOf (TypeManager.delegate_type)) if (target_type == TypeManager.icloneable_type) return true; @@ -1044,6 +1091,13 @@ namespace Mono.CSharp { return false; } + public static bool ImplicitUserConversionExists (EmitContext ec, Type source, Type target) + { + Expression dummy = ImplicitUserConversion ( + ec, new EmptyExpression (source), target, Location.Null); + return dummy != null; + } + /// /// Determines if a standard implicit conversion exists from /// expr_type to target_type @@ -1210,7 +1264,9 @@ namespace Mono.CSharp { return true; } - if (target_type.IsSubclassOf (TypeManager.enum_type) && expr is IntLiteral){ + if ((target_type == TypeManager.enum_type || + target_type.IsSubclassOf (TypeManager.enum_type)) && + expr is IntLiteral){ IntLiteral i = (IntLiteral) expr; if (i.Value == 0) @@ -1466,6 +1522,60 @@ namespace Mono.CSharp { return UserDefinedConversion (ec, source, target, loc, true); } + /// + /// Returns an expression that can be used to invoke operator true + /// on the expression if it exists. + /// + static public StaticCallExpr GetOperatorTrue (EmitContext ec, Expression e, Location loc) + { + MethodBase method; + Expression operator_group; + + operator_group = MethodLookup (ec, e.Type, "op_True", loc); + if (operator_group == null) + return null; + + ArrayList arguments = new ArrayList (); + arguments.Add (new Argument (e, Argument.AType.Expression)); + method = Invocation.OverloadResolve (ec, (MethodGroupExpr) operator_group, arguments, loc); + + if (method == null) + return null; + + return new StaticCallExpr ((MethodInfo) method, arguments, loc); + } + + /// + /// Resolves the expression `e' into a boolean expression: either through + /// an implicit conversion, or through an `operator true' invocation + /// + public static Expression ResolveBoolean (EmitContext ec, Expression e, Location loc) + { + e = e.Resolve (ec); + if (e == null) + return null; + + Expression converted = e; + if (e.Type != TypeManager.bool_type) + converted = Expression.ConvertImplicit (ec, e, TypeManager.bool_type, new Location (-1)); + + // + // If no implicit conversion to bool exists, try using `operator true' + // + if (converted == null){ + Expression operator_true = Expression.GetOperatorTrue (ec, e, loc); + if (operator_true == null){ + Report.Error ( + 31, loc, "Can not convert the expression to a boolean"); + return null; + } + e = operator_true; + } else + e = converted; + + return e; + } + /// /// Computes the MethodGroup for the user-defined conversion /// operators from source_type to target_type. `look_for_explicit' @@ -1480,17 +1590,10 @@ namespace Mono.CSharp { Expression mg5 = null, mg6 = null, mg7 = null, mg8 = null; string op_name; - // - // FIXME : How does the False operator come into the picture ? - // This doesn't look complete and very correct ! - // - if (target_type == TypeManager.bool_type && !look_for_explicit) - op_name = "op_True"; - else - op_name = "op_Implicit"; + op_name = "op_Implicit"; MethodGroupExpr union3; - + mg1 = MethodLookup (ec, source_type, op_name, loc); if (source_type.BaseType != null) mg2 = MethodLookup (ec, source_type.BaseType, op_name, loc); @@ -1552,13 +1655,12 @@ namespace Mono.CSharp { MethodGroupExpr union; Type source_type = source.Type; MethodBase method = null; - + union = GetConversionOperators (ec, source_type, target, loc, look_for_explicit); if (union == null) return null; Type most_specific_source, most_specific_target; - #if BLAH foreach (MethodBase m in union.Methods){ Console.WriteLine ("Name: " + m.Name); @@ -1576,6 +1678,7 @@ namespace Mono.CSharp { int count = 0; + foreach (MethodBase mb in union.Methods){ ParameterData pd = Invocation.GetParameterData (mb); MethodInfo mi = (MethodInfo) mb; @@ -1587,10 +1690,9 @@ namespace Mono.CSharp { } } - if (method == null || count > 1) { - Report.Error (-11, loc, "Ambiguous user defined conversion"); + if (method == null || count > 1) return null; - } + // // This will do the conversion to the best match that we @@ -1613,7 +1715,8 @@ namespace Mono.CSharp { e = ConvertImplicitStandard (ec, e, target, loc); else e = ConvertExplicitStandard (ec, e, target, loc); - } + } + return e; } @@ -1672,12 +1775,14 @@ namespace Mono.CSharp { e = ImplicitReferenceConversion (expr, target_type); if (e != null) return e; - - if (target_type.IsSubclassOf (TypeManager.enum_type) && expr is IntLiteral){ + + if ((target_type == TypeManager.enum_type || + target_type.IsSubclassOf (TypeManager.enum_type)) && + expr is IntLiteral){ IntLiteral i = (IntLiteral) expr; if (i.Value == 0) - return new EmptyCast (expr, target_type); + return new EnumConstant ((Constant) expr, target_type); } if (ec.InUnsafe) { @@ -1690,14 +1795,17 @@ namespace Mono.CSharp { // t1 == t2, we have to compare their element types. // if (target_type.IsPointer){ - if (target_type.GetElementType()==expr_type.GetElementType()) + if (target_type.GetElementType() == expr_type.GetElementType()) return expr; } } - if (target_type.IsPointer){ + if (target_type.IsPointer) { if (expr is NullLiteral) return new EmptyCast (expr, target_type); + + if (expr_type == TypeManager.void_ptr_type) + return new EmptyCast (expr, target_type); } } @@ -1713,9 +1821,6 @@ namespace Mono.CSharp { { int value = ic.Value; - // - // FIXME: This could return constants instead of EmptyCasts - // if (target_type == TypeManager.sbyte_type){ if (value >= SByte.MinValue && value <= SByte.MaxValue) return new SByteConstant ((sbyte) value); @@ -1739,11 +1844,26 @@ namespace Mono.CSharp { // if (value >= 0) return new ULongConstant ((ulong) value); - } + } else if (target_type == TypeManager.double_type) + return new DoubleConstant ((double) value); + else if (target_type == TypeManager.float_type) + return new FloatConstant ((float) value); - if (value == 0 && ic is IntLiteral && TypeManager.IsEnumType (target_type)) - return new EnumConstant (ic, target_type); - + if (value == 0 && ic is IntLiteral && TypeManager.IsEnumType (target_type)){ + Type underlying = TypeManager.EnumToUnderlying (target_type); + Constant e = (Constant) ic; + + // + // Possibly, we need to create a different 0 literal before passing + // to EnumConstant + //n + if (underlying == TypeManager.int64_type) + e = new LongLiteral (0); + else if (underlying == TypeManager.uint64_type) + e = new ULongLiteral (0); + + return new EnumConstant (e, target_type); + } return null; } @@ -1775,7 +1895,7 @@ namespace Mono.CSharp { "Double literal cannot be implicitly converted to " + "float type, use F suffix to create a float literal"); } - + Error_CannotConvertImplicit (loc, source.Type, target_type); return null; @@ -1784,7 +1904,7 @@ 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, Location loc) { Type expr_type = expr.Type; @@ -1798,8 +1918,13 @@ 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 (StandardConversionExists (expr, real_target_type)){ + Expression ce = ConvertImplicitStandard (ec, expr, real_target_type, loc); + + if (real_target_type != target_type) + return new EmptyCast (ce, target_type); + return ce; + } if (expr_type == TypeManager.sbyte_type){ // @@ -1959,8 +2084,6 @@ namespace Mono.CSharp { return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_U8); if (real_target_type == TypeManager.char_type) return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_CH); - if (real_target_type == TypeManager.decimal_type) - return InternalTypeConstructor (ec, expr, target_type); } else if (expr_type == TypeManager.double_type){ // // From double to byte, byte, short, @@ -1987,8 +2110,6 @@ namespace Mono.CSharp { return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_CH); if (real_target_type == TypeManager.float_type) return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_R4); - if (real_target_type == TypeManager.decimal_type) - return InternalTypeConstructor (ec, expr, target_type); } // decimal is taken care of by the op_Explicit methods. @@ -2196,44 +2317,50 @@ namespace Mono.CSharp { Type target_type, Location loc) { Type expr_type = expr.Type; + Type original_expr_type = expr_type; + + if (expr_type.IsSubclassOf (TypeManager.enum_type)){ + if (target_type == TypeManager.enum_type || + target_type == TypeManager.object_type) { + if (expr is EnumConstant) + expr = ((EnumConstant) expr).Child; + // We really need all these casts here .... :-( + expr = new BoxedCast (new EmptyCast (expr, expr_type)); + return new EmptyCast (expr, target_type); + } else if ((expr_type == TypeManager.enum_type) && target_type.IsValueType && + target_type.IsSubclassOf (TypeManager.enum_type)) + return new UnboxCast (expr, target_type); + + // + // Notice that we have kept the expr_type unmodified, which is only + // used later on to + if (expr is EnumConstant) + expr = ((EnumConstant) expr).Child; + else + expr = new EmptyCast (expr, TypeManager.EnumToUnderlying (expr_type)); + expr_type = expr.Type; + } + Expression ne = ConvertImplicitStandard (ec, expr, target_type, loc); if (ne != null) return ne; - ne = ConvertNumericExplicit (ec, expr, target_type); + ne = ConvertNumericExplicit (ec, expr, target_type, loc); if (ne != null) return ne; // // Unboxing conversion. // - if (expr_type == TypeManager.object_type && target_type.IsValueType) - return new UnboxCast (expr, target_type); - - // - // Enum types - // - if (expr_type.IsSubclassOf (TypeManager.enum_type)) { - Expression e; - - // - // FIXME: Is there any reason we should have EnumConstant - // dealt with here instead of just using always the - // UnderlyingSystemType to wrap the type? - // - if (expr is EnumConstant) - e = ((EnumConstant) expr).Child; - else { - e = new EmptyCast (expr, TypeManager.EnumToUnderlying (expr_type)); + if (expr_type == TypeManager.object_type && target_type.IsValueType){ + if (expr is NullLiteral){ + Report.Error (37, "Cannot convert null to value type `" + TypeManager.CSharpName (expr_type) + "'"); + return null; } - - Expression t = ConvertImplicit (ec, e, target_type, loc); - if (t != null) - return t; - - return ConvertNumericExplicit (ec, e, target_type); + return new UnboxCast (expr, target_type); } + ne = ConvertReferenceExplicit (expr, target_type); if (ne != null) @@ -2271,7 +2398,7 @@ namespace Mono.CSharp { if (ci != null) return ci; - ce = ConvertNumericExplicit (ec, e, target_type); + ce = ConvertNumericExplicit (ec, e, target_type, loc); if (ce != null) return ce; // @@ -2288,7 +2415,7 @@ namespace Mono.CSharp { if (ne != null) return ne; - Error_CannotConvertType (loc, expr_type, target_type); + Error_CannotConvertType (loc, original_expr_type, target_type); return null; } @@ -2303,7 +2430,7 @@ namespace Mono.CSharp { if (ne != null) return ne; - ne = ConvertNumericExplicit (ec, expr, target_type); + ne = ConvertNumericExplicit (ec, expr, target_type, l); if (ne != null) return ne; @@ -2345,7 +2472,7 @@ namespace Mono.CSharp { /// /// Reports that we were expecting `expr' to be of class `expected' /// - public void Error118 (string expected) + public void Error_UnexpectedKind (string expected) { string kind = "Unknown"; @@ -2355,7 +2482,7 @@ namespace Mono.CSharp { "' where a `" + expected + "' was expected"); } - public void Error118 (ResolveFlags flags) + public void Error_UnexpectedKind (ResolveFlags flags) { ArrayList valid = new ArrayList (10); @@ -2718,7 +2845,7 @@ namespace Mono.CSharp { // public static void StoreFromPtr (ILGenerator ig, Type type) { - if (type.IsEnum) + if (TypeManager.IsEnumType (type)) type = TypeManager.EnumToUnderlying (type); if (type == TypeManager.int32_type || type == TypeManager.uint32_type) ig.Emit (OpCodes.Stind_I4); @@ -2863,7 +2990,7 @@ namespace Mono.CSharp { /// public class EmptyCast : Expression { protected Expression child; - + public EmptyCast (Expression child, Type return_type) { eclass = child.eclass; @@ -3019,10 +3146,10 @@ namespace Mono.CSharp { public class BoxedCast : EmptyCast { public BoxedCast (Expression expr) - : base (expr, TypeManager.object_type) + : base (expr, TypeManager.object_type) { } - + public override Expression DoResolve (EmitContext ec) { // This should never be invoked, we are born in fully @@ -3105,6 +3232,11 @@ namespace Mono.CSharp { return this; } + public override string ToString () + { + return String.Format ("ConvCast ({0}, {1})", mode, child); + } + public override void Emit (EmitContext ec) { ILGenerator ig = ec.ig; @@ -3372,13 +3504,26 @@ namespace Mono.CSharp { /// The downside of this is that we might be hitting `LookupType' too many /// times with this scheme. /// - public class SimpleName : Expression, ITypeExpression { + public class SimpleName : Expression { public readonly string Name; + + // + // If true, then we are a simple name, not composed with a ". + // + bool is_base; + + public SimpleName (string a, string b, Location l) + { + Name = String.Concat (a, ".", b); + loc = l; + is_base = false; + } public SimpleName (string name, Location l) { Name = name; loc = l; + is_base = true; } public static void Error_ObjectRefRequired (EmitContext ec, Location l, string name) @@ -3429,42 +3574,56 @@ namespace Mono.CSharp { return SimpleNameResolve (ec, null, true); } - public Expression DoResolveType (EmitContext ec) + public override Expression ResolveAsTypeStep (EmitContext ec) { - // - // Stage 3: Lookup symbol in the various namespaces. - // DeclSpace ds = ec.DeclSpace; + Namespace ns = ds.Namespace; 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 // + if (ns != null && is_base) + alias_value = ns.LookupAlias (Name); + else + alias_value = null; - alias_value = ec.DeclSpace.LookupAlias (Name); + if (ec.ResolvingTypeTree){ + if (alias_value != null){ + if ((t = RootContext.LookupType (ds, alias_value, true, loc)) != null) + return new TypeExpr (t, loc); + } + + int errors = Report.Errors; + Type dt = ec.DeclSpace.FindType (loc, Name); + if (Report.Errors != errors) + return null; - if (Name.IndexOf ('.') == -1 && alias_value != null) { + if (dt != null) + return new TypeExpr (dt, loc); + } + + // + // First, the using aliases + // + if (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); } + + // + // Stage 2: Lookup up if we are an alias to a type + // or a namespace. + // + + if ((t = RootContext.LookupType (ds, Name, true, loc)) != null) + return new TypeExpr (t, 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; @@ -3495,7 +3654,7 @@ namespace Mono.CSharp { // Stage 1: Performed by the parser (binding to locals or parameters). // Block current_block = ec.CurrentBlock; - if (current_block != null && current_block.IsVariableDefined (Name)){ + if (current_block != null && current_block.GetVariableInfo (Name) != null){ LocalVariableReference var; var = new LocalVariableReference (ec.CurrentBlock, Name, loc); @@ -3529,11 +3688,6 @@ namespace Mono.CSharp { // Stage 2: Lookup members // - // - // 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) @@ -3543,20 +3697,14 @@ namespace Mono.CSharp { if (e != null) break; - // - // Classes/structs keep looking, enums break - // - if (lookup_ds is TypeContainer) - lookup_ds = ((TypeContainer) lookup_ds).Parent; - else - break; + lookup_ds =lookup_ds.Parent; } while (lookup_ds != null); if (e == null && ec.ContainerType != null) e = MemberLookup (ec, ec.ContainerType, Name, loc); if (e == null) - return DoResolveType (ec); + return ResolveAsTypeStep (ec); if (e is TypeExpr) return e; @@ -3576,7 +3724,8 @@ namespace Mono.CSharp { return e; if (!me.IsStatic && - TypeManager.IsNestedChildOf (me.InstanceExpression.Type, me.DeclaringType)) { + TypeManager.IsNestedChildOf (me.InstanceExpression.Type, me.DeclaringType) && + !me.InstanceExpression.Type.IsSubclassOf (me.DeclaringType)) { Error (38, "Cannot access nonstatic member `" + me.Name + "' of " + "outer type `" + me.DeclaringType + "' via nested type `" + me.InstanceExpression.Type + "'"); @@ -3621,7 +3770,7 @@ namespace Mono.CSharp { /// /// Fully resolved expression that evaluates to a type /// - public class TypeExpr : Expression, ITypeExpression { + public class TypeExpr : Expression { public TypeExpr (Type t, Location l) { Type = t; @@ -3629,7 +3778,7 @@ namespace Mono.CSharp { loc = l; } - public virtual Expression DoResolveType (EmitContext ec) + public override Expression ResolveAsTypeStep (EmitContext ec) { return this; } @@ -3663,7 +3812,7 @@ namespace Mono.CSharp { this.name = name; } - public override Expression DoResolveType (EmitContext ec) + public override Expression ResolveAsTypeStep (EmitContext ec) { if (type == null) type = RootContext.LookupType (ec.DeclSpace, name, false, Location.Null); @@ -3672,7 +3821,7 @@ namespace Mono.CSharp { public override Expression DoResolve (EmitContext ec) { - return DoResolveType (ec); + return ResolveAsTypeStep (ec); } public override void Emit (EmitContext ec) @@ -3892,9 +4041,12 @@ namespace Mono.CSharp { { if (!FieldInfo.IsStatic){ 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"); + // + // This can happen when referencing an instance field using + // a fully qualified type expression: TypeName.InstanceField = xxx + // + SimpleName.Error_ObjectRefRequired (ec, loc, FieldInfo.Name); + return null; } // Resolve the field's instance expression while flow analysis is turned @@ -3946,8 +4098,10 @@ namespace Mono.CSharp { // InitOnly fields can only be assigned in constructors // - if (ec.IsConstructor) - return this; + if (ec.IsConstructor){ + if (ec.ContainerType == FieldInfo.DeclaringType) + return this; + } Report_AssignToReadonly (true); @@ -3977,7 +4131,7 @@ namespace Mono.CSharp { if (instance_expr.Type.IsValueType){ IMemoryLocation ml; LocalTemporary tempo = null; - + if (!(instance_expr is IMemoryLocation)){ tempo = new LocalTemporary ( ec, instance_expr.Type); @@ -4071,26 +4225,31 @@ namespace Mono.CSharp { // Handle initonly fields specially: make a copy and then // get the address of the copy. // - if (FieldInfo.IsInitOnly){ - if (ec.IsConstructor) { - ig.Emit (OpCodes.Ldsflda, FieldInfo); - } else { - LocalBuilder local; + if (FieldInfo.IsInitOnly && !ec.IsConstructor){ + 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 { - if (instance_expr is IMemoryLocation) - ((IMemoryLocation)instance_expr).AddressOf (ec, AddressOp.LoadStore); - else + // + // In the case of `This', we call the AddressOf method, which will + // only load the pointer, and not perform an Ldobj immediately after + // the value has been loaded into the stack. + // + if (instance_expr is This) + ((This)instance_expr).AddressOf (ec, AddressOp.LoadStore); + else if (instance_expr.Type.IsValueType && instance_expr is IMemoryLocation){ + IMemoryLocation ml = (IMemoryLocation) instance_expr; + + ml.AddressOf (ec, AddressOp.LoadStore); + } else instance_expr.Emit (ec); ig.Emit (OpCodes.Ldflda, FieldInfo); } @@ -4106,30 +4265,27 @@ namespace Mono.CSharp { /// public class PropertyExpr : ExpressionStatement, IAssignMethod, IMemberExpr { public readonly PropertyInfo PropertyInfo; + + // + // This is set externally by the `BaseAccess' class + // public bool IsBase; - MethodInfo [] Accessors; + MethodInfo getter, setter; bool is_static; + bool must_do_cs1540_check; Expression instance_expr; - public PropertyExpr (PropertyInfo pi, Location l) + public PropertyExpr (EmitContext ec, PropertyInfo pi, Location l) { PropertyInfo = pi; eclass = ExprClass.PropertyAccess; is_static = false; loc = l; - Accessors = TypeManager.GetAccessors (pi); - if (Accessors != null) - foreach (MethodInfo mi in Accessors){ - if (mi != null) - if (mi.IsStatic) - is_static = true; - } - else - Accessors = new MethodInfo [2]; - type = TypeManager.TypeToCoreType (pi.PropertyType); + + ResolveAccessors (ec); } public string Name { @@ -4171,7 +4327,7 @@ namespace Mono.CSharp { public bool VerifyAssignable () { - if (!PropertyInfo.CanWrite){ + if (setter == null) { Report.Error (200, loc, "The property `" + PropertyInfo.Name + "' can not be assigned to, as it has not set accessor"); @@ -4181,25 +4337,159 @@ namespace Mono.CSharp { return true; } - override public Expression DoResolve (EmitContext ec) + MethodInfo GetAccessor (Type invocation_type, string accessor_name) { - if (!PropertyInfo.CanRead){ - Report.Error (154, loc, - "The property `" + PropertyInfo.Name + - "' can not be used in " + - "this context because it lacks a get accessor"); + BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | + BindingFlags.Static | BindingFlags.Instance; + MemberInfo[] group; + + group = TypeManager.MemberLookup ( + invocation_type, invocation_type, PropertyInfo.DeclaringType, + MemberTypes.Method, flags, accessor_name + "_" + PropertyInfo.Name); + + // + // The first method is the closest to us + // + if (group == null) return null; + + foreach (MethodInfo mi in group) { + MethodAttributes ma = mi.Attributes & MethodAttributes.MemberAccessMask; + + // + // If only accessible to the current class or children + // + if (ma == MethodAttributes.Private) { + Type declaring_type = mi.DeclaringType; + + if (invocation_type != declaring_type){ + if (TypeManager.IsSubclassOrNestedChildOf (invocation_type, mi.DeclaringType)) + return mi; + else + continue; + } else + return mi; + } + // + // FamAndAssem requires that we not only derivate, but we are on the + // same assembly. + // + if (ma == MethodAttributes.FamANDAssem){ + if (mi.DeclaringType.Assembly != invocation_type.Assembly) + continue; + else + return mi; + } + + // Assembly and FamORAssem succeed if we're in the same assembly. + if ((ma == MethodAttributes.Assembly) || (ma == MethodAttributes.FamORAssem)){ + if (mi.DeclaringType.Assembly != invocation_type.Assembly) + continue; + else + return mi; + } + + // We already know that we aren't in the same assembly. + if (ma == MethodAttributes.Assembly) + continue; + + // Family and FamANDAssem require that we derive. + if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem)){ + if (!TypeManager.IsSubclassOrNestedChildOf (invocation_type, mi.DeclaringType)) + continue; + else { + must_do_cs1540_check = true; + + return mi; + } + } + + return mi; } + return null; + } + + // + // We also perform the permission checking here, as the PropertyInfo does not + // hold the information for the accessibility of its setter/getter + // + void ResolveAccessors (EmitContext ec) + { + getter = GetAccessor (ec.ContainerType, "get"); + if ((getter != null) && getter.IsStatic) + is_static = true; + + setter = GetAccessor (ec.ContainerType, "set"); + if ((setter != null) && setter.IsStatic) + is_static = true; + + if (setter == null && getter == null){ + Error (122, "`" + PropertyInfo.Name + "' " + + "is inaccessible because of its protection level"); + + } + } + + bool InstanceResolve (EmitContext ec) + { if ((instance_expr == null) && ec.IsStatic && !is_static) { SimpleName.Error_ObjectRefRequired (ec, loc, PropertyInfo.Name); - return null; + return false; } if (instance_expr != null) { instance_expr = instance_expr.DoResolve (ec); if (instance_expr == null) + return false; + } + + if (must_do_cs1540_check && (instance_expr != null)) { + if ((instance_expr.Type != ec.ContainerType) && + ec.ContainerType.IsSubclassOf (instance_expr.Type)) { + Report.Error (1540, loc, "Cannot access protected member `" + + PropertyInfo.DeclaringType + "." + PropertyInfo.Name + + "' via a qualifier of type `" + + TypeManager.CSharpName (instance_expr.Type) + + "'; the qualifier must be of type `" + + TypeManager.CSharpName (ec.ContainerType) + + "' (or derived from it)"); + return false; + } + } + + return true; + } + + override public Expression DoResolve (EmitContext ec) + { + if (getter == null){ + // + // The following condition happens if the PropertyExpr was + // created, but is invalid (ie, the property is inaccessible), + // and we did not want to embed the knowledge about this in + // the caller routine. This only avoids double error reporting. + // + if (setter == null) return null; + + Report.Error (154, loc, + "The property `" + PropertyInfo.Name + + "' can not be used in " + + "this context because it lacks a get accessor"); + return null; + } + + if (!InstanceResolve (ec)) + return null; + + // + // Only base will allow this invocation to happen. + // + if (IsBase && getter.IsAbstract){ + Report.Error (205, loc, "Cannot call an abstract base property: " + + PropertyInfo.DeclaringType + "." +PropertyInfo.Name); + return null; } return this; @@ -4207,7 +4497,16 @@ namespace Mono.CSharp { override public Expression DoResolveLValue (EmitContext ec, Expression right_side) { - if (!PropertyInfo.CanWrite){ + if (setter == null){ + // + // The following condition happens if the PropertyExpr was + // created, but is invalid (ie, the property is inaccessible), + // and we did not want to embed the knowledge about this in + // the caller routine. This only avoids double error reporting. + // + if (getter == null) + return null; + Report.Error (154, loc, "The property `" + PropertyInfo.Name + "' can not be used in " + @@ -4215,24 +4514,27 @@ namespace Mono.CSharp { return null; } - if (instance_expr != null) { - instance_expr = instance_expr.DoResolve (ec); - if (instance_expr == null) - return null; + if (!InstanceResolve (ec)) + return null; + + // + // Only base will allow this invocation to happen. + // + if (IsBase && setter.IsAbstract){ + Report.Error (205, loc, "Cannot call an abstract base property: " + + PropertyInfo.DeclaringType + "." +PropertyInfo.Name); + return null; } - return this; } override public void Emit (EmitContext ec) { - MethodInfo method = Accessors [0]; - // - // Special case: length of single dimension array is turned into ldlen + // Special case: length of single dimension array property is turned into ldlen // - if ((method == TypeManager.system_int_array_get_length) || - (method == TypeManager.int_array_get_length)){ + if ((getter == TypeManager.system_int_array_get_length) || + (getter == TypeManager.int_array_get_length)){ Type iet = instance_expr.Type; // @@ -4246,7 +4548,7 @@ namespace Mono.CSharp { } } - Invocation.EmitCall (ec, IsBase, IsStatic, instance_expr, method, null, loc); + Invocation.EmitCall (ec, IsBase, IsStatic, instance_expr, getter, null, loc); } @@ -4259,7 +4561,7 @@ namespace Mono.CSharp { ArrayList args = new ArrayList (); args.Add (arg); - Invocation.EmitCall (ec, false, IsStatic, instance_expr, Accessors [1], args, loc); + Invocation.EmitCall (ec, IsBase, IsStatic, instance_expr, setter, args, loc); } override public void EmitStatement (EmitContext ec) @@ -4291,9 +4593,11 @@ namespace Mono.CSharp { if (add_accessor.IsStatic || remove_accessor.IsStatic) is_static = true; - if (EventInfo is MyEventBuilder) - type = ((MyEventBuilder) EventInfo).EventType; - else + if (EventInfo is MyEventBuilder){ + MyEventBuilder eb = (MyEventBuilder) EventInfo; + type = eb.EventType; + eb.SetUsed (); + } else type = EventInfo.EventHandlerType; } @@ -4339,12 +4643,13 @@ namespace Mono.CSharp { return null; } + return this; } public override void Emit (EmitContext ec) { - throw new Exception ("Should not happen I think"); + Report.Error (70, loc, "The event `" + Name + "' can only appear on the left hand side of += or -= (except on the defining type)"); } public void EmitAddOrRemove (EmitContext ec, Expression source)