X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fexpression.cs;h=c537b1421892eb9be2d178fe5aa698dde7d8391b;hb=ab7a1d6bb8802e143d2acdb8d4a71e0e99e26296;hp=d406c698b420fd031b5b06601e01824a0dc26661;hpb=ed08cc90885fed60521bb942d05f00e0b6791060;p=mono.git diff --git a/mcs/mcs/expression.cs b/mcs/mcs/expression.cs index d406c698b42..c537b142189 100644 --- a/mcs/mcs/expression.cs +++ b/mcs/mcs/expression.cs @@ -12,16 +12,12 @@ namespace Mono.CSharp { using System; - using System.Collections; using System.Collections.Generic; using System.Reflection; using System.Reflection.Emit; using System.Text; - -#if NET_4_0 using System.Linq; using SLE = System.Linq.Expressions; -#endif // // This is an user operator expression, automatically created during @@ -40,7 +36,7 @@ namespace Mono.CSharp { this.arguments = args; this.expr_tree = expr_tree; - type = TypeManager.TypeToCoreType (((MethodInfo) mg).ReturnType); + type = mg.BestCandidate.ReturnType; eclass = ExprClass.Value; this.loc = loc; } @@ -75,22 +71,15 @@ namespace Mono.CSharp { mg.EmitCall (ec, arguments); } -#if NET_4_0 public override SLE.Expression MakeExpression (BuilderContext ctx) { - return SLE.Expression.Call ((MethodInfo) mg, Arguments.MakeExpression (arguments, ctx)); + var method = mg.BestCandidate.GetMetaInfo () as MethodInfo; + return SLE.Expression.Call (method, Arguments.MakeExpression (arguments, ctx)); } -#endif public MethodGroupExpr Method { get { return mg; } } - - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) - { - arguments.MutateHoistedGenericType (storey); - mg.MutateHoistedGenericType (storey); - } } public class ParenthesizedExpression : ShimExpression @@ -122,17 +111,17 @@ namespace Mono.CSharp { AddressOf, TOP } - static Type [] [] predefined_operators; + static TypeSpec[][] predefined_operators; public readonly Operator Oper; public Expression Expr; Expression enum_conversion; - public Unary (Operator op, Expression expr) + public Unary (Operator op, Expression expr, Location loc) { Oper = op; Expr = expr; - loc = expr.Location; + this.loc = loc; } // @@ -149,7 +138,7 @@ namespace Mono.CSharp { return r == null ? null : new SideEffectConstant (r, e, r.Location); } - Type expr_type = e.Type; + TypeSpec expr_type = e.Type; switch (Oper){ case Operator.UnaryPlus: @@ -215,7 +204,7 @@ namespace Mono.CSharp { if (expr_type == TypeManager.uint32_type) { UIntLiteral uil = e as UIntLiteral; if (uil != null) { - if (uil.Value == 2147483648) + if (uil.Value == int.MaxValue + (uint) 1) return new IntLiteral (int.MinValue, e.Location); return new LongLiteral (-uil.Value, e.Location); } @@ -298,7 +287,7 @@ namespace Mono.CSharp { if (predefined_operators == null) CreatePredefinedOperatorsTable (); - Type expr_type = expr.Type; + TypeSpec expr_type = expr.Type; Expression best_expr; // @@ -325,7 +314,7 @@ namespace Mono.CSharp { protected virtual Expression ResolveEnumOperator (ResolveContext ec, Expression expr) { - Type underlying_type = TypeManager.GetEnumUnderlyingType (expr.Type); + TypeSpec underlying_type = EnumSpec.GetUnderlyingType (expr.Type); Expression best_expr = ResolvePrimitivePredefinedType (EmptyCast.Create (expr, underlying_type)); if (best_expr == null) return null; @@ -374,12 +363,12 @@ namespace Mono.CSharp { static void CreatePredefinedOperatorsTable () { - predefined_operators = new Type [(int) Operator.TOP] []; + predefined_operators = new TypeSpec [(int) Operator.TOP] []; // // 7.6.1 Unary plus operator // - predefined_operators [(int) Operator.UnaryPlus] = new Type [] { + predefined_operators [(int) Operator.UnaryPlus] = new TypeSpec [] { TypeManager.int32_type, TypeManager.uint32_type, TypeManager.int64_type, TypeManager.uint64_type, TypeManager.float_type, TypeManager.double_type, @@ -389,7 +378,7 @@ namespace Mono.CSharp { // // 7.6.2 Unary minus operator // - predefined_operators [(int) Operator.UnaryNegation] = new Type [] { + predefined_operators [(int) Operator.UnaryNegation] = new TypeSpec [] { TypeManager.int32_type, TypeManager.int64_type, TypeManager.float_type, TypeManager.double_type, @@ -399,14 +388,14 @@ namespace Mono.CSharp { // // 7.6.3 Logical negation operator // - predefined_operators [(int) Operator.LogicalNot] = new Type [] { + predefined_operators [(int) Operator.LogicalNot] = new TypeSpec [] { TypeManager.bool_type }; // // 7.6.4 Bitwise complement operator // - predefined_operators [(int) Operator.OnesComplement] = new Type [] { + predefined_operators [(int) Operator.OnesComplement] = new TypeSpec [] { TypeManager.int32_type, TypeManager.uint32_type, TypeManager.int64_type, TypeManager.uint64_type }; @@ -417,7 +406,7 @@ namespace Mono.CSharp { // static Expression DoNumericPromotion (Operator op, Expression expr) { - Type expr_type = expr.Type; + TypeSpec expr_type = expr.Type; if ((op == Operator.UnaryPlus || op == Operator.UnaryNegation || op == Operator.OnesComplement) && expr_type == TypeManager.byte_type || expr_type == TypeManager.sbyte_type || expr_type == TypeManager.short_type || expr_type == TypeManager.ushort_type || @@ -440,14 +429,14 @@ namespace Mono.CSharp { if (Expr == null) return null; - if (TypeManager.IsDynamicType (Expr.Type)) { + if (Expr.Type == InternalType.Dynamic) { Arguments args = new Arguments (1); args.Add (new Argument (Expr)); return new DynamicUnaryConversion (GetOperatorExpressionTypeName (), args, loc).Resolve (ec); } if (TypeManager.IsNullableType (Expr.Type)) - return new Nullable.LiftedUnaryOperator (Oper, Expr).Resolve (ec); + return new Nullable.LiftedUnaryOperator (Oper, Expr, loc).Resolve (ec); // // Attempt to use a constant folding operation. @@ -482,10 +471,8 @@ namespace Mono.CSharp { EmitOperator (ec, type); } - protected void EmitOperator (EmitContext ec, Type type) + protected void EmitOperator (EmitContext ec, TypeSpec type) { - ILGenerator ig = ec.ig; - switch (Oper) { case Operator.UnaryPlus: Expr.Emit (ec); @@ -493,27 +480,27 @@ namespace Mono.CSharp { case Operator.UnaryNegation: if (ec.HasSet (EmitContext.Options.CheckedScope) && !IsFloat (type)) { - ig.Emit (OpCodes.Ldc_I4_0); + ec.Emit (OpCodes.Ldc_I4_0); if (type == TypeManager.int64_type) - ig.Emit (OpCodes.Conv_U8); + ec.Emit (OpCodes.Conv_U8); Expr.Emit (ec); - ig.Emit (OpCodes.Sub_Ovf); + ec.Emit (OpCodes.Sub_Ovf); } else { Expr.Emit (ec); - ig.Emit (OpCodes.Neg); + ec.Emit (OpCodes.Neg); } break; case Operator.LogicalNot: Expr.Emit (ec); - ig.Emit (OpCodes.Ldc_I4_0); - ig.Emit (OpCodes.Ceq); + ec.Emit (OpCodes.Ldc_I4_0); + ec.Emit (OpCodes.Ceq); break; case Operator.OnesComplement: Expr.Emit (ec); - ig.Emit (OpCodes.Not); + ec.Emit (OpCodes.Not); break; case Operator.AddressOf: @@ -545,7 +532,7 @@ namespace Mono.CSharp { Expr.EmitSideEffect (ec); } - public static void Error_OperatorCannotBeApplied (ResolveContext ec, Location loc, string oper, Type t) + public static void Error_OperatorCannotBeApplied (ResolveContext ec, Location loc, string oper, TypeSpec t) { ec.Report.Error (23, loc, "The `{0}' operator cannot be applied to operand of type `{1}'", oper, TypeManager.CSharpName (t)); @@ -570,7 +557,7 @@ namespace Mono.CSharp { } } - static bool IsFloat (Type t) + static bool IsFloat (TypeSpec t) { return t == TypeManager.float_type || t == TypeManager.double_type; } @@ -596,7 +583,6 @@ namespace Mono.CSharp { throw new NotImplementedException (oper.ToString ()); } -#if NET_4_0 public override SLE.Expression MakeExpression (BuilderContext ctx) { var expr = Expr.MakeExpression (ctx); @@ -607,18 +593,18 @@ namespace Mono.CSharp { return is_checked ? SLE.Expression.NegateChecked (expr) : SLE.Expression.Negate (expr); case Operator.LogicalNot: return SLE.Expression.Not (expr); +#if NET_4_0 case Operator.OnesComplement: return SLE.Expression.OnesComplement (expr); +#endif default: throw new NotImplementedException (Oper.ToString ()); } } -#endif - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + public static void Reset () { - type = storey.MutateType (type); - Expr.MutateHoistedGenericType (storey); + predefined_operators = null; } Expression ResolveAddressOf (ResolveContext ec) @@ -665,7 +651,7 @@ namespace Mono.CSharp { ec.Report.Error (212, loc, "You can only take the address of unfixed expression inside of a fixed statement initializer"); } - type = TypeManager.GetPointerType (Expr.Type); + type = PointerContainer.MakeType (Expr.Type); eclass = ExprClass.Value; return this; } @@ -673,9 +659,9 @@ namespace Mono.CSharp { Expression ResolvePrimitivePredefinedType (Expression expr) { expr = DoNumericPromotion (Oper, expr); - Type expr_type = expr.Type; - Type[] predefined = predefined_operators [(int) Oper]; - foreach (Type t in predefined) { + TypeSpec expr_type = expr.Type; + TypeSpec[] predefined = predefined_operators [(int) Oper]; + foreach (TypeSpec t in predefined) { if (t == expr_type) return expr; } @@ -702,7 +688,7 @@ namespace Mono.CSharp { } string op_name = CSharp.Operator.GetMetadataName (op_type); - MethodGroupExpr user_op = MemberLookup (ec.Compiler, ec.CurrentType, expr.Type, op_name, MemberTypes.Method, AllBindingFlags, expr.Location) as MethodGroupExpr; + MethodGroupExpr user_op = MethodLookup (ec.Compiler, ec.CurrentType, expr.Type, MemberKind.Operator, op_name, 0, expr.Location); if (user_op == null) return null; @@ -726,9 +712,9 @@ namespace Mono.CSharp { if (best_expr != null) return best_expr; - Type[] predefined = predefined_operators [(int) Oper]; - foreach (Type t in predefined) { - Expression oper_expr = Convert.UserDefinedConversion (ec, expr, t, expr.Location, false, false); + TypeSpec[] predefined = predefined_operators [(int) Oper]; + foreach (TypeSpec t in predefined) { + Expression oper_expr = Convert.ImplicitUserConversion (ec, expr, t, expr.Location); if (oper_expr == null) continue; @@ -814,14 +800,14 @@ namespace Mono.CSharp { if (!prepared) expr.Emit (ec); - LoadFromPtr (ec.ig, Type); + ec.EmitLoadFromPtr (Type); } public void Emit (EmitContext ec, bool leave_copy) { Emit (ec); if (leave_copy) { - ec.ig.Emit (OpCodes.Dup); + ec.Emit (OpCodes.Dup); temporary = new LocalTemporary (expr.Type); temporary.Store (ec); } @@ -834,16 +820,16 @@ namespace Mono.CSharp { expr.Emit (ec); if (prepare_for_load) - ec.ig.Emit (OpCodes.Dup); + ec.Emit (OpCodes.Dup); source.Emit (ec); if (leave_copy) { - ec.ig.Emit (OpCodes.Dup); + ec.Emit (OpCodes.Dup); temporary = new LocalTemporary (expr.Type); temporary.Store (ec); } - StoreFromPtr (ec.ig, type); + ec.EmitStoreFromPtr (type); if (temporary != null) { temporary.Emit (ec); @@ -993,10 +979,10 @@ namespace Mono.CSharp { // Holds the real operation Expression operation; - public UnaryMutator (Mode m, Expression e) + public UnaryMutator (Mode m, Expression e, Location loc) { mode = m; - loc = e.Location; + this.loc = loc; expr = e; } @@ -1012,7 +998,7 @@ namespace Mono.CSharp { if (expr == null) return null; - if (TypeManager.IsDynamicType (expr.Type)) { + if (expr.Type == InternalType.Dynamic) { // // Handle postfix unary operators using local // temporary variable @@ -1082,7 +1068,7 @@ namespace Mono.CSharp { // use pre-post incr-decr operations on it, but it is not a // System.Decimal, which we require operator overloading to catch) // - static bool IsPredefinedOperator (Type t) + static bool IsPredefinedOperator (TypeSpec t) { return (TypeManager.IsPrimitiveType (t) && t != TypeManager.bool_type) || TypeManager.IsEnumType (t) || @@ -1135,7 +1121,7 @@ namespace Mono.CSharp { // TODO: Cache this based on type when using EmptyExpression in // context cache Binary.Operator op = IsDecrement ? Binary.Operator.Subtraction : Binary.Operator.Addition; - operation = new Binary (op, operation, one); + operation = new Binary (op, operation, one, loc); operation = operation.Resolve (ec); if (operation != null && operation.Type != type) operation = Convert.ExplicitNumericConversion (operation, type); @@ -1146,7 +1132,6 @@ namespace Mono.CSharp { // // Step 2: Perform Operator Overload location // - MethodGroupExpr mg; string op_name; if (IsDecrement) @@ -1154,7 +1139,7 @@ namespace Mono.CSharp { else op_name = Operator.GetMetadataName (Operator.OpType.Increment); - mg = MemberLookup (ec.Compiler, ec.CurrentType, type, op_name, MemberTypes.Method, AllBindingFlags, loc) as MethodGroupExpr; + var mg = MethodLookup (ec.Compiler, ec.CurrentType, type, MemberKind.Operator, op_name, 0, loc); if (mg != null) { Arguments args = new Arguments (1); @@ -1214,7 +1199,7 @@ namespace Mono.CSharp { if (expr == null) return null; - if ((probe_type_expr.Type.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) { + if (probe_type_expr.Type.IsStatic) { ec.Report.Error (-244, loc, "The `{0}' operator cannot be applied to an operand of a static type", OperatorName); } @@ -1234,12 +1219,6 @@ namespace Mono.CSharp { return this; } - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) - { - expr.MutateHoistedGenericType (storey); - probe_type_expr.MutateHoistedGenericType (storey); - } - protected abstract string OperatorName { get; } protected override void CloneTo (CloneContext clonectx, Expression t) @@ -1274,28 +1253,26 @@ namespace Mono.CSharp { public override void Emit (EmitContext ec) { - ILGenerator ig = ec.ig; if (expr_unwrap != null) { expr_unwrap.EmitCheck (ec); return; } expr.Emit (ec); - ig.Emit (OpCodes.Isinst, probe_type_expr.Type); - ig.Emit (OpCodes.Ldnull); - ig.Emit (OpCodes.Cgt_Un); + ec.Emit (OpCodes.Isinst, probe_type_expr.Type); + ec.Emit (OpCodes.Ldnull); + ec.Emit (OpCodes.Cgt_Un); } public override void EmitBranchable (EmitContext ec, Label target, bool on_true) { - ILGenerator ig = ec.ig; if (expr_unwrap != null) { expr_unwrap.EmitCheck (ec); } else { expr.Emit (ec); - ig.Emit (OpCodes.Isinst, probe_type_expr.Type); + ec.Emit (OpCodes.Isinst, probe_type_expr.Type); } - ig.Emit (on_true ? OpCodes.Brtrue : OpCodes.Brfalse, target); + ec.Emit (on_true ? OpCodes.Brtrue : OpCodes.Brfalse, target); } Expression CreateConstantResult (ResolveContext ec, bool result) @@ -1315,7 +1292,7 @@ namespace Mono.CSharp { if (base.DoResolve (ec) == null) return null; - Type d = expr.Type; + TypeSpec d = expr.Type; bool d_is_nullable = false; // @@ -1325,18 +1302,24 @@ namespace Mono.CSharp { if (expr.IsNull || expr.eclass == ExprClass.MethodGroup) return CreateConstantResult (ec, false); - if (TypeManager.IsNullableType (d) && !TypeManager.ContainsGenericParameters (d)) { - d = TypeManager.TypeToCoreType (TypeManager.GetTypeArguments (d) [0]); - d_is_nullable = true; + if (TypeManager.IsNullableType (d)) { + var ut = Nullable.NullableInfo.GetUnderlyingType (d); + if (!ut.IsGenericParameter) { + d = ut; + d_is_nullable = true; + } } type = TypeManager.bool_type; eclass = ExprClass.Value; - Type t = probe_type_expr.Type; + TypeSpec t = probe_type_expr.Type; bool t_is_nullable = false; - if (TypeManager.IsNullableType (t) && !TypeManager.ContainsGenericParameters (t)) { - t = TypeManager.TypeToCoreType (TypeManager.GetTypeArguments (t) [0]); - t_is_nullable = true; + if (TypeManager.IsNullableType (t)) { + var ut = Nullable.NullableInfo.GetUnderlyingType (t); + if (!ut.IsGenericParameter) { + t = ut; + t_is_nullable = true; + } } if (TypeManager.IsStruct (t)) { @@ -1355,8 +1338,9 @@ namespace Mono.CSharp { return CreateConstantResult (ec, true); } - if (TypeManager.IsGenericParameter (d)) - return ResolveGenericParameter (ec, t, d); + var tp = d as TypeParameterSpec; + if (tp != null) + return ResolveGenericParameter (ec, t, tp); // // An unboxing conversion exists @@ -1365,15 +1349,14 @@ namespace Mono.CSharp { return this; } else { if (TypeManager.IsGenericParameter (t)) - return ResolveGenericParameter (ec, d, t); + return ResolveGenericParameter (ec, d, (TypeParameterSpec) t); if (TypeManager.IsStruct (d)) { - bool temp; - if (Convert.ImplicitBoxingConversionExists (expr, t, out temp)) + if (Convert.ImplicitBoxingConversion (null, d, t) != null) return CreateConstantResult (ec, true); } else { if (TypeManager.IsGenericParameter (d)) - return ResolveGenericParameter (ec, t, d); + return ResolveGenericParameter (ec, t, (TypeParameterSpec) d); if (TypeManager.ContainsGenericParameters (d)) return this; @@ -1388,16 +1371,15 @@ namespace Mono.CSharp { return CreateConstantResult (ec, false); } - Expression ResolveGenericParameter (ResolveContext ec, Type d, Type t) + Expression ResolveGenericParameter (ResolveContext ec, TypeSpec d, TypeParameterSpec t) { - GenericConstraints constraints = TypeManager.GetTypeParameterConstraints (t); - if (constraints != null) { - if (constraints.IsReferenceType && TypeManager.IsStruct (d)) + if (t.IsReferenceType) { + if (TypeManager.IsStruct (d)) return CreateConstantResult (ec, false); } if (TypeManager.IsGenericParameter (expr.Type)) { - if (constraints != null && constraints.IsValueType && expr.Type == t) + if (t.IsValueType && expr.Type == t) return CreateConstantResult (ec, true); expr = new BoxedCast (expr, d); @@ -1434,15 +1416,13 @@ namespace Mono.CSharp { public override void Emit (EmitContext ec) { - ILGenerator ig = ec.ig; - expr.Emit (ec); if (do_isinst) - ig.Emit (OpCodes.Isinst, type); + ec.Emit (OpCodes.Isinst, type); if (TypeManager.IsGenericParameter (type) || TypeManager.IsNullableType (type)) - ig.Emit (OpCodes.Unbox_Any, type); + ec.Emit (OpCodes.Unbox_Any, type); } protected override Expression DoResolve (ResolveContext ec) @@ -1456,7 +1436,7 @@ namespace Mono.CSharp { type = probe_type_expr.Type; eclass = ExprClass.Value; - Type etype = expr.Type; + TypeSpec etype = expr.Type; if (!TypeManager.IsReferenceType (type) && !TypeManager.IsNullableType (type)) { if (TypeManager.IsGenericParameter (type)) { @@ -1506,32 +1486,13 @@ namespace Mono.CSharp { protected override string OperatorName { get { return "as"; } } - - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) - { - type = storey.MutateType (type); - base.MutateHoistedGenericType (storey); - } - - public override bool GetAttributableValue (ResolveContext ec, Type value_type, out object value) - { - return expr.GetAttributableValue (ec, value_type, out value); - } } - /// - /// This represents a typecast in the source language. - /// - /// FIXME: Cast expressions have an unusual set of parsing - /// rules, we need to figure those out. - /// + // + // This represents a typecast in the source language. + // public class Cast : ShimExpression { Expression target_type; - - public Cast (Expression cast_type, Expression expr) - : this (cast_type, expr, cast_type.Location) - { - } public Cast (Expression cast_type, Expression expr, Location loc) : base (expr) @@ -1556,7 +1517,7 @@ namespace Mono.CSharp { type = target.Type; - if (type.IsAbstract && type.IsSealed) { + if (type.IsStatic) { ec.Report.Error (716, loc, "Cannot convert to static type `{0}'", TypeManager.CSharpName (type)); return null; } @@ -1572,14 +1533,17 @@ namespace Mono.CSharp { if (type.IsPointer && !ec.IsUnsafe) { UnsafeError (ec, loc); - } else if (TypeManager.IsDynamicType (expr.Type)) { + } else if (expr.Type == InternalType.Dynamic) { Arguments arg = new Arguments (1); arg.Add (new Argument (expr)); return new DynamicConversion (type, CSharpBinderFlags.ConvertExplicit, arg, loc).Resolve (ec); } - expr = Convert.ExplicitConversion (ec, expr, type, loc); - return expr; + var res = Convert.ExplicitConversion (ec, expr, type, loc); + if (res == expr) + return EmptyCast.Create (res, type); + + return res; } protected override void CloneTo (CloneContext clonectx, Expression t) @@ -1595,7 +1559,7 @@ namespace Mono.CSharp { { bool arrayAccess; - public ImplicitCast (Expression expr, Type target, bool arrayAccess) + public ImplicitCast (Expression expr, TypeSpec target, bool arrayAccess) : base (expr) { this.loc = expr.Location; @@ -1647,7 +1611,7 @@ namespace Mono.CSharp { type = texpr.Type; - if ((type.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) { + if (type.IsStatic) { ec.Report.Error (-244, loc, "The `default value' operator cannot be applied to an operand of a static type"); } @@ -1670,15 +1634,10 @@ namespace Mono.CSharp { LocalTemporary temp_storage = new LocalTemporary(type); temp_storage.AddressOf(ec, AddressOp.LoadStore); - ec.ig.Emit(OpCodes.Initobj, type); + ec.Emit(OpCodes.Initobj, type); temp_storage.Emit(ec); } - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) - { - type = storey.MutateType (type); - } - protected override void CloneTo (CloneContext clonectx, Expression t) { DefaultValueExpression target = (DefaultValueExpression) t; @@ -1692,29 +1651,28 @@ namespace Mono.CSharp { /// public class Binary : Expression, IDynamicBinder { - protected class PredefinedOperator { - protected readonly Type left; - protected readonly Type right; + protected readonly TypeSpec left; + protected readonly TypeSpec right; public readonly Operator OperatorsMask; - public Type ReturnType; + public TypeSpec ReturnType; - public PredefinedOperator (Type ltype, Type rtype, Operator op_mask) + public PredefinedOperator (TypeSpec ltype, TypeSpec rtype, Operator op_mask) : this (ltype, rtype, op_mask, ltype) { } - public PredefinedOperator (Type type, Operator op_mask, Type return_type) + public PredefinedOperator (TypeSpec type, Operator op_mask, TypeSpec return_type) : this (type, type, op_mask, return_type) { } - public PredefinedOperator (Type type, Operator op_mask) + public PredefinedOperator (TypeSpec type, Operator op_mask) : this (type, type, op_mask, type) { } - public PredefinedOperator (Type ltype, Type rtype, Operator op_mask, Type return_type) + public PredefinedOperator (TypeSpec ltype, TypeSpec rtype, Operator op_mask, TypeSpec return_type) { if ((op_mask & Operator.ValuesOnlyMask) != 0) throw new InternalErrorException ("Only masked values can be used"); @@ -1740,10 +1698,28 @@ namespace Mono.CSharp { if (left == TypeManager.decimal_type) return b.ResolveUserOperator (ec, b.left.Type, b.right.Type); + var c = b.right as Constant; + if (c != null) { + if (c.IsDefaultValue && (b.oper == Operator.Addition || b.oper == Operator.BitwiseOr || b.oper == Operator.Subtraction)) + return ReducedExpression.Create (b.left, b).Resolve (ec); + if ((b.oper == Operator.Multiply || b.oper == Operator.Division) && c.IsOneInteger) + return ReducedExpression.Create (b.left, b).Resolve (ec); + return b; + } + + c = b.left as Constant; + if (c != null) { + if (c.IsDefaultValue && (b.oper == Operator.Addition || b.oper == Operator.BitwiseOr)) + return ReducedExpression.Create (b.right, b).Resolve (ec); + if (b.oper == Operator.Multiply && c.IsOneInteger) + return ReducedExpression.Create (b.right, b).Resolve (ec); + return b; + } + return b; } - public bool IsPrimitiveApplicable (Type ltype, Type rtype) + public bool IsPrimitiveApplicable (TypeSpec ltype, TypeSpec rtype) { // // We are dealing with primitive types only @@ -1783,13 +1759,13 @@ namespace Mono.CSharp { } class PredefinedStringOperator : PredefinedOperator { - public PredefinedStringOperator (Type type, Operator op_mask) + public PredefinedStringOperator (TypeSpec type, Operator op_mask) : base (type, op_mask, type) { ReturnType = TypeManager.string_type; } - public PredefinedStringOperator (Type ltype, Type rtype, Operator op_mask) + public PredefinedStringOperator (TypeSpec ltype, TypeSpec rtype, Operator op_mask) : base (ltype, rtype, op_mask) { ReturnType = TypeManager.string_type; @@ -1819,7 +1795,7 @@ namespace Mono.CSharp { } class PredefinedShiftOperator : PredefinedOperator { - public PredefinedShiftOperator (Type ltype, Operator op_mask) : + public PredefinedShiftOperator (TypeSpec ltype, Operator op_mask) : base (ltype, TypeManager.int32_type, op_mask) { } @@ -1836,29 +1812,37 @@ namespace Mono.CSharp { // b = b.left >> b.right & (0x1f|0x3f) // b.right = new Binary (Operator.BitwiseAnd, - b.right, new IntConstant (right_mask, b.right.Location)).Resolve (ec); + b.right, new IntConstant (right_mask, b.right.Location), b.loc).Resolve (ec); // // Expression tree representation does not use & mask // - b.right = ReducedExpression.Create (b.right, expr_tree_expr); + b.right = ReducedExpression.Create (b.right, expr_tree_expr).Resolve (ec); b.type = ReturnType; + + // + // Optimize shift by 0 + // + var c = b.right as Constant; + if (c != null && c.IsDefaultValue) + return ReducedExpression.Create (b.left, b).Resolve (ec); + return b; } } class PredefinedPointerOperator : PredefinedOperator { - public PredefinedPointerOperator (Type ltype, Type rtype, Operator op_mask) + public PredefinedPointerOperator (TypeSpec ltype, TypeSpec rtype, Operator op_mask) : base (ltype, rtype, op_mask) { } - public PredefinedPointerOperator (Type ltype, Type rtype, Operator op_mask, Type retType) + public PredefinedPointerOperator (TypeSpec ltype, TypeSpec rtype, Operator op_mask, TypeSpec retType) : base (ltype, rtype, op_mask, retType) { } - public PredefinedPointerOperator (Type type, Operator op_mask, Type return_type) + public PredefinedPointerOperator (TypeSpec type, Operator op_mask, TypeSpec return_type) : base (type, op_mask, return_type) { } @@ -1892,7 +1876,7 @@ namespace Mono.CSharp { b.right = EmptyCast.Create (b.right, right); } - Type r_type = ReturnType; + TypeSpec r_type = ReturnType; Expression left_arg, right_arg; if (r_type == null) { if (left == null) { @@ -1958,21 +1942,21 @@ namespace Mono.CSharp { readonly bool is_compound; Expression enum_conversion; - static PredefinedOperator [] standard_operators; - static PredefinedOperator [] pointer_operators; + static PredefinedOperator[] standard_operators; + static PredefinedOperator[] pointer_operators; - public Binary (Operator oper, Expression left, Expression right, bool isCompound) - : this (oper, left, right) + public Binary (Operator oper, Expression left, Expression right, bool isCompound, Location loc) + : this (oper, left, right, loc) { this.is_compound = isCompound; } - public Binary (Operator oper, Expression left, Expression right) + public Binary (Operator oper, Expression left, Expression right, Location loc) { this.oper = oper; this.left = left; this.right = right; - this.loc = left.Location; + this.loc = loc; } public Operator Oper { @@ -2055,7 +2039,7 @@ namespace Mono.CSharp { public static void Error_OperatorCannotBeApplied (ResolveContext ec, Expression left, Expression right, Operator oper, Location loc) { - new Binary (oper, left, right).Error_OperatorCannotBeApplied (ec, left, right); + new Binary (oper, left, right, loc).Error_OperatorCannotBeApplied (ec, left, right); } public static void Error_OperatorCannotBeApplied (ResolveContext ec, Expression left, Expression right, string oper, Location loc) @@ -2163,10 +2147,9 @@ namespace Mono.CSharp { return CSharp.Operator.GetMetadataName (op_type); } - public static void EmitOperatorOpcode (EmitContext ec, Operator oper, Type l) + public static void EmitOperatorOpcode (EmitContext ec, Operator oper, TypeSpec l) { OpCode opcode; - ILGenerator ig = ec.ig; switch (oper){ case Operator.Multiply: @@ -2236,8 +2219,8 @@ namespace Mono.CSharp { break; case Operator.Inequality: - ig.Emit (OpCodes.Ceq); - ig.Emit (OpCodes.Ldc_I4_0); + ec.Emit (OpCodes.Ceq); + ec.Emit (OpCodes.Ldc_I4_0); opcode = OpCodes.Ceq; break; @@ -2258,21 +2241,21 @@ namespace Mono.CSharp { case Operator.LessThanOrEqual: if (IsUnsigned (l) || IsFloat (l)) - ig.Emit (OpCodes.Cgt_Un); + ec.Emit (OpCodes.Cgt_Un); else - ig.Emit (OpCodes.Cgt); - ig.Emit (OpCodes.Ldc_I4_0); + ec.Emit (OpCodes.Cgt); + ec.Emit (OpCodes.Ldc_I4_0); opcode = OpCodes.Ceq; break; case Operator.GreaterThanOrEqual: if (IsUnsigned (l) || IsFloat (l)) - ig.Emit (OpCodes.Clt_Un); + ec.Emit (OpCodes.Clt_Un); else - ig.Emit (OpCodes.Clt); + ec.Emit (OpCodes.Clt); - ig.Emit (OpCodes.Ldc_I4_0); + ec.Emit (OpCodes.Ldc_I4_0); opcode = OpCodes.Ceq; break; @@ -2293,10 +2276,10 @@ namespace Mono.CSharp { throw new InternalErrorException (oper.ToString ()); } - ig.Emit (opcode); + ec.Emit (opcode); } - static bool IsUnsigned (Type t) + static bool IsUnsigned (TypeSpec t) { if (t.IsPointer) return true; @@ -2305,15 +2288,20 @@ namespace Mono.CSharp { t == TypeManager.ushort_type || t == TypeManager.byte_type); } - static bool IsFloat (Type t) + static bool IsFloat (TypeSpec t) { return t == TypeManager.float_type || t == TypeManager.double_type; } + public static void Reset () + { + pointer_operators = standard_operators = null; + } + Expression ResolveOperator (ResolveContext ec) { - Type l = left.Type; - Type r = right.Type; + TypeSpec l = left.Type; + TypeSpec r = right.Type; Expression expr; bool primitives_only = false; @@ -2441,7 +2429,7 @@ namespace Mono.CSharp { static void CreatePointerOperatorsTable () { - ArrayList temp = new ArrayList (); + var temp = new List (); // // Pointer arithmetic: @@ -2472,13 +2460,13 @@ namespace Mono.CSharp { // temp.Add (new PredefinedPointerOperator (null, Operator.SubtractionMask, TypeManager.int64_type)); - pointer_operators = (PredefinedOperator []) temp.ToArray (typeof (PredefinedOperator)); + pointer_operators = temp.ToArray (); } static void CreateStandardOperatorsTable () { - ArrayList temp = new ArrayList (); - Type bool_type = TypeManager.bool_type; + var temp = new List (); + TypeSpec bool_type = TypeManager.bool_type; temp.Add (new PredefinedOperator (TypeManager.int32_type, Operator.ArithmeticMask | Operator.BitwiseMask)); temp.Add (new PredefinedOperator (TypeManager.uint32_type, Operator.ArithmeticMask | Operator.BitwiseMask)); @@ -2510,16 +2498,16 @@ namespace Mono.CSharp { temp.Add (new PredefinedShiftOperator (TypeManager.int64_type, Operator.ShiftMask)); temp.Add (new PredefinedShiftOperator (TypeManager.uint64_type, Operator.ShiftMask)); - standard_operators = (PredefinedOperator []) temp.ToArray (typeof (PredefinedOperator)); + standard_operators = temp.ToArray (); } // // Rules used during binary numeric promotion // - static bool DoNumericPromotion (ResolveContext rc, ref Expression prim_expr, ref Expression second_expr, Type type) + static bool DoNumericPromotion (ResolveContext rc, ref Expression prim_expr, ref Expression second_expr, TypeSpec type) { Expression temp; - Type etype; + TypeSpec etype; Constant c = prim_expr as Constant; if (c != null) { @@ -2551,7 +2539,7 @@ namespace Mono.CSharp { // A compile-time error occurs if the other operand is of type sbyte, short, int, or long // if (type == TypeManager.int32_type || type == TypeManager.int64_type || - type == TypeManager.sbyte_type || type == TypeManager.sbyte_type) + type == TypeManager.short_type || type == TypeManager.sbyte_type) return false; } @@ -2568,11 +2556,11 @@ namespace Mono.CSharp { // public bool DoBinaryOperatorPromotion (ResolveContext ec) { - Type ltype = left.Type; - Type rtype = right.Type; + TypeSpec ltype = left.Type; + TypeSpec rtype = right.Type; Expression temp; - foreach (Type t in ConstantFold.binary_promotions) { + foreach (TypeSpec t in ConstantFold.BinaryPromotionsTypes) { if (t == ltype) return t == rtype || DoNumericPromotion (ec, ref right, ref left, t); @@ -2580,7 +2568,7 @@ namespace Mono.CSharp { return t == ltype || DoNumericPromotion (ec, ref left, ref right, t); } - Type int32 = TypeManager.int32_type; + TypeSpec int32 = TypeManager.int32_type; if (ltype != int32) { Constant c = left as Constant; if (c != null) @@ -2675,7 +2663,7 @@ namespace Mono.CSharp { CheckUselessComparison (ec, rc, left.Type); } - if (TypeManager.IsDynamicType (left.Type) || TypeManager.IsDynamicType (right.Type)) { + if (left.Type == InternalType.Dynamic || right.Type == InternalType.Dynamic) { Arguments args = new Arguments (2); args.Add (new Argument (left)); args.Add (new Argument (right)); @@ -2707,7 +2695,6 @@ namespace Mono.CSharp { return expr; } -#if NET_4_0 public override SLE.Expression MakeExpression (BuilderContext ctx) { var le = left.MakeExpression (ctx); @@ -2755,13 +2742,6 @@ namespace Mono.CSharp { throw new NotImplementedException (oper.ToString ()); } } -#endif - - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) - { - left.MutateHoistedGenericType (storey); - right.MutateHoistedGenericType (storey); - } // // D operator + (D x, D y) @@ -2769,10 +2749,10 @@ namespace Mono.CSharp { // bool operator == (D x, D y) // bool operator != (D x, D y) // - Expression ResolveOperatorDelegate (ResolveContext ec, Type l, Type r) + Expression ResolveOperatorDelegate (ResolveContext ec, TypeSpec l, TypeSpec r) { bool is_equality = (oper & Operator.EqualityMask) != 0; - if (!TypeManager.IsEqual (l, r) && !TypeManager.IsVariantOf (r, l)) { + if (!TypeManager.IsEqual (l, r) && !TypeSpecComparer.Variant.IsEqual (r, l)) { Expression tmp; if (right.eclass == ExprClass.MethodGroup || (r == InternalType.AnonymousMethod && !is_equality)) { tmp = Convert.ImplicitConversionRequired (ec, right, l, loc); @@ -2797,7 +2777,7 @@ namespace Mono.CSharp { if (is_equality) return ResolveUserOperator (ec, l, r); - MethodInfo method; + MethodSpec method; Arguments args = new Arguments (2); args.Add (new Argument (left)); args.Add (new Argument (right)); @@ -2818,7 +2798,10 @@ namespace Mono.CSharp { method = TypeManager.delegate_remove_delegate_delegate; } - MethodGroupExpr mg = new MethodGroupExpr (new MemberInfo [] { method }, TypeManager.delegate_type, loc); + if (method == null) + return new EmptyExpression (TypeManager.decimal_type); + + MethodGroupExpr mg = new MethodGroupExpr (method, TypeManager.delegate_type, loc); mg = mg.OverloadResolve (ec, ref args, false, loc); return new ClassCast (new UserOperatorCall (mg, args, CreateExpressionTree, loc), l); @@ -2827,7 +2810,7 @@ namespace Mono.CSharp { // // Enumeration operators // - Expression ResolveOperatorEnum (ResolveContext ec, bool lenum, bool renum, Type ltype, Type rtype) + Expression ResolveOperatorEnum (ResolveContext ec, bool lenum, bool renum, TypeSpec ltype, TypeSpec rtype) { // // bool operator == (E x, E y); @@ -2854,7 +2837,7 @@ namespace Mono.CSharp { Expression ltemp = left; Expression rtemp = right; - Type underlying_type; + TypeSpec underlying_type; Expression expr; if ((oper & (Operator.ComparisonMask | Operator.BitwiseMask)) != 0) { @@ -2874,7 +2857,7 @@ namespace Mono.CSharp { } if (TypeManager.IsEqual (ltype, rtype)) { - underlying_type = TypeManager.GetEnumUnderlyingType (ltype); + underlying_type = EnumSpec.GetUnderlyingType (ltype); if (left is Constant) left = ((Constant) left).ConvertExplicitly (false, underlying_type).Resolve (ec); @@ -2886,7 +2869,7 @@ namespace Mono.CSharp { else right = EmptyCast.Create (right, underlying_type); } else if (lenum) { - underlying_type = TypeManager.GetEnumUnderlyingType (ltype); + underlying_type = EnumSpec.GetUnderlyingType (ltype); if (oper != Operator.Subtraction && oper != Operator.Addition) { Constant c = right as Constant; @@ -2905,7 +2888,7 @@ namespace Mono.CSharp { left = EmptyCast.Create (left, underlying_type); } else if (renum) { - underlying_type = TypeManager.GetEnumUnderlyingType (rtype); + underlying_type = EnumSpec.GetUnderlyingType (rtype); if (oper != Operator.Addition) { Constant c = left as Constant; @@ -2937,9 +2920,9 @@ namespace Mono.CSharp { return null; } - Type res_type = null; + TypeSpec res_type = null; if ((oper & Operator.BitwiseMask) != 0 || oper == Operator.Subtraction || oper == Operator.Addition) { - Type promoted_type = lenum ? left.Type : right.Type; + TypeSpec promoted_type = lenum ? left.Type : right.Type; enum_conversion = Convert.ExplicitNumericConversion ( new EmptyExpression (promoted_type), underlying_type); @@ -2984,7 +2967,7 @@ namespace Mono.CSharp { // // 7.9.6 Reference type equality operators // - Binary ResolveOperatorEqualityRerefence (ResolveContext ec, Type l, Type r) + Binary ResolveOperatorEqualityRerefence (ResolveContext ec, TypeSpec l, TypeSpec r) { // // operator != (object a, object b) @@ -2997,12 +2980,14 @@ namespace Mono.CSharp { return null; type = TypeManager.bool_type; - GenericConstraints constraints; - bool lgen = TypeManager.IsGenericParameter (l); + var lgen = l as TypeParameterSpec; + + if (l == r) { + if (l is InternalType) + return null; - if (TypeManager.IsEqual (l, r)) { - if (lgen) { + if (lgen != null) { // // Only allow to compare same reference type parameter // @@ -3015,16 +3000,13 @@ namespace Mono.CSharp { return null; } - if (l == InternalType.AnonymousMethod) - return null; - if (TypeManager.IsValueType (l)) return null; return this; } - bool rgen = TypeManager.IsGenericParameter (r); + var rgen = r as TypeParameterSpec; // // a, Both operands are reference-type values or the value null @@ -3033,18 +3015,16 @@ namespace Mono.CSharp { // value type constrain // if (left is NullLiteral || right is NullLiteral) { - if (lgen) { - constraints = TypeManager.GetTypeParameterConstraints (l); - if (constraints != null && constraints.HasValueTypeConstraint) + if (lgen != null) { + if (lgen.HasSpecialStruct) return null; left = new BoxedCast (left, TypeManager.object_type); return this; } - if (rgen) { - constraints = TypeManager.GetTypeParameterConstraints (r); - if (constraints != null && constraints.HasValueTypeConstraint) + if (rgen != null) { + if (rgen.HasSpecialStruct) return null; right = new BoxedCast (right, TypeManager.object_type); @@ -3057,7 +3037,7 @@ namespace Mono.CSharp { // standard conversion is applied. It's not clear from the // standard but it looks like it works like that. // - if (lgen) { + if (lgen != null) { if (!TypeManager.IsReferenceType (l)) return null; @@ -3069,7 +3049,7 @@ namespace Mono.CSharp { return null; } - if (rgen) { + if (rgen != null) { if (!TypeManager.IsReferenceType (r)) return null; @@ -3107,7 +3087,7 @@ namespace Mono.CSharp { } - Expression ResolveOperatorPointer (ResolveContext ec, Type l, Type r) + Expression ResolveOperatorPointer (ResolveContext ec, TypeSpec l, TypeSpec r) { // // bool operator == (void* x, void* y); @@ -3146,11 +3126,11 @@ namespace Mono.CSharp { // // Build-in operators method overloading // - protected virtual Expression ResolveOperatorPredefined (ResolveContext ec, PredefinedOperator [] operators, bool primitives_only, Type enum_type) + protected virtual Expression ResolveOperatorPredefined (ResolveContext ec, PredefinedOperator [] operators, bool primitives_only, TypeSpec enum_type) { PredefinedOperator best_operator = null; - Type l = left.Type; - Type r = right.Type; + TypeSpec l = left.Type; + TypeSpec r = right.Type; Operator oper_mask = oper & ~Operator.ValuesOnlyMask; foreach (PredefinedOperator po in operators) { @@ -3220,7 +3200,7 @@ namespace Mono.CSharp { // // Performs user-operator overloading // - protected virtual Expression ResolveUserOperator (ResolveContext ec, Type l, Type r) + protected virtual Expression ResolveUserOperator (ResolveContext ec, TypeSpec l, TypeSpec r) { Operator user_oper; if (oper == Operator.LogicalAnd) @@ -3232,11 +3212,11 @@ namespace Mono.CSharp { string op = GetOperatorMetadataName (user_oper); - MethodGroupExpr left_operators = MemberLookup (ec.Compiler, ec.CurrentType, l, op, MemberTypes.Method, AllBindingFlags, loc) as MethodGroupExpr; + MethodGroupExpr left_operators = MethodLookup (ec.Compiler, ec.CurrentType, l, MemberKind.Operator, op, 0, loc); MethodGroupExpr right_operators = null; if (!TypeManager.IsEqual (r, l)) { - right_operators = MemberLookup (ec.Compiler, ec.CurrentType, r, op, MemberTypes.Method, AllBindingFlags, loc) as MethodGroupExpr; + right_operators = MethodLookup (ec.Compiler, ec.CurrentType, r, MemberKind.Operator, op, 0, loc); if (right_operators == null && left_operators == null) return null; } else if (left_operators == null) { @@ -3297,7 +3277,7 @@ namespace Mono.CSharp { if (left is NullLiteral || right is NullLiteral) oper_expr = ReducedExpression.Create (this, oper_expr); } else if (l != r) { - MethodInfo mi = (MethodInfo) union; + var mi = union.BestCandidate; // // Two System.Delegate(s) are never equal @@ -3318,7 +3298,7 @@ namespace Mono.CSharp { return null; } - private void CheckUselessComparison (ResolveContext ec, Constant c, Type type) + private void CheckUselessComparison (ResolveContext ec, Constant c, TypeSpec type) { if (c == null || !IsTypeIntegral (type) || c is StringConstant @@ -3371,7 +3351,7 @@ namespace Mono.CSharp { WarnUselessComparison (ec, type); } - static bool IsValueOutOfRange (long value, Type type) + static bool IsValueOutOfRange (long value, TypeSpec type) { if (IsTypeUnsigned (type) && value < 0) return true; @@ -3383,13 +3363,13 @@ namespace Mono.CSharp { type == TypeManager.uint32_type && value >= 0x100000000; } - static bool IsBuildInEqualityOperator (Type t) + static bool IsBuildInEqualityOperator (TypeSpec t) { return t == TypeManager.object_type || t == TypeManager.string_type || t == TypeManager.delegate_type || TypeManager.IsDelegateType (t); } - static bool IsPredefinedUserOperator (Type t, Operator op) + static bool IsPredefinedUserOperator (TypeSpec t, Operator op) { // // Some predefined types have user operators @@ -3397,7 +3377,7 @@ namespace Mono.CSharp { return (op & Operator.EqualityMask) != 0 && (t == TypeManager.string_type || t == TypeManager.decimal_type); } - private static bool IsTypeIntegral (Type type) + private static bool IsTypeIntegral (TypeSpec type) { return type == TypeManager.uint64_type || type == TypeManager.int64_type || @@ -3410,7 +3390,7 @@ namespace Mono.CSharp { type == TypeManager.char_type; } - private static bool IsTypeUnsigned (Type type) + private static bool IsTypeUnsigned (TypeSpec type) { return type == TypeManager.uint64_type || type == TypeManager.uint32_type || @@ -3419,7 +3399,7 @@ namespace Mono.CSharp { type == TypeManager.char_type; } - private void WarnUselessComparison (ResolveContext ec, Type type) + private void WarnUselessComparison (ResolveContext ec, TypeSpec type) { ec.Report.Warning (652, 2, loc, "A comparison between a constant and a variable is useless. The constant is out of the range of the variable type `{0}'", TypeManager.CSharpName (type)); @@ -3435,15 +3415,13 @@ namespace Mono.CSharp { /// public override void EmitBranchable (EmitContext ec, Label target, bool on_true) { - ILGenerator ig = ec.ig; - // // This is more complicated than it looks, but its just to avoid // duplicated tests: basically, we allow ==, !=, >, <, >= and <= // but on top of that we want for == and != to use a special path // if we are comparing against null // - if ((oper == Operator.Equality || oper == Operator.Inequality) && (left is Constant || right is Constant)) { + if ((oper & Operator.EqualityMask) != 0 && (left is Constant || right is Constant)) { bool my_on_true = oper == Operator.Inequality ? on_true : !on_true; // @@ -3455,7 +3433,10 @@ namespace Mono.CSharp { left = swap; } - if (((Constant) right).IsZeroInteger) { + // + // brtrue/brfalse works with native int only + // + if (((Constant) right).IsZeroInteger && right.Type != TypeManager.int64_type && right.Type != TypeManager.uint64_type) { left.EmitBranchable (ec, target, my_on_true); return; } @@ -3468,11 +3449,11 @@ namespace Mono.CSharp { } else if (oper == Operator.LogicalAnd) { if (on_true) { - Label tests_end = ig.DefineLabel (); + Label tests_end = ec.DefineLabel (); left.EmitBranchable (ec, tests_end, false); right.EmitBranchable (ec, target, true); - ig.MarkLabel (tests_end); + ec.MarkLabel (tests_end); } else { // // This optimizes code like this @@ -3493,17 +3474,15 @@ namespace Mono.CSharp { right.EmitBranchable (ec, target, true); } else { - Label tests_end = ig.DefineLabel (); + Label tests_end = ec.DefineLabel (); left.EmitBranchable (ec, tests_end, true); right.EmitBranchable (ec, target, false); - ig.MarkLabel (tests_end); + ec.MarkLabel (tests_end); } return; - - } else if (!(oper == Operator.LessThan || oper == Operator.GreaterThan || - oper == Operator.LessThanOrEqual || oper == Operator.GreaterThanOrEqual || - oper == Operator.Equality || oper == Operator.Inequality)) { + + } else if ((oper & Operator.ComparisonMask) == 0) { base.EmitBranchable (ec, target, on_true); return; } @@ -3511,76 +3490,76 @@ namespace Mono.CSharp { left.Emit (ec); right.Emit (ec); - Type t = left.Type; + TypeSpec t = left.Type; bool is_float = IsFloat (t); bool is_unsigned = is_float || IsUnsigned (t); switch (oper){ case Operator.Equality: if (on_true) - ig.Emit (OpCodes.Beq, target); + ec.Emit (OpCodes.Beq, target); else - ig.Emit (OpCodes.Bne_Un, target); + ec.Emit (OpCodes.Bne_Un, target); break; case Operator.Inequality: if (on_true) - ig.Emit (OpCodes.Bne_Un, target); + ec.Emit (OpCodes.Bne_Un, target); else - ig.Emit (OpCodes.Beq, target); + ec.Emit (OpCodes.Beq, target); break; case Operator.LessThan: if (on_true) if (is_unsigned && !is_float) - ig.Emit (OpCodes.Blt_Un, target); + ec.Emit (OpCodes.Blt_Un, target); else - ig.Emit (OpCodes.Blt, target); + ec.Emit (OpCodes.Blt, target); else if (is_unsigned) - ig.Emit (OpCodes.Bge_Un, target); + ec.Emit (OpCodes.Bge_Un, target); else - ig.Emit (OpCodes.Bge, target); + ec.Emit (OpCodes.Bge, target); break; case Operator.GreaterThan: if (on_true) if (is_unsigned && !is_float) - ig.Emit (OpCodes.Bgt_Un, target); + ec.Emit (OpCodes.Bgt_Un, target); else - ig.Emit (OpCodes.Bgt, target); + ec.Emit (OpCodes.Bgt, target); else if (is_unsigned) - ig.Emit (OpCodes.Ble_Un, target); + ec.Emit (OpCodes.Ble_Un, target); else - ig.Emit (OpCodes.Ble, target); + ec.Emit (OpCodes.Ble, target); break; case Operator.LessThanOrEqual: if (on_true) if (is_unsigned && !is_float) - ig.Emit (OpCodes.Ble_Un, target); + ec.Emit (OpCodes.Ble_Un, target); else - ig.Emit (OpCodes.Ble, target); + ec.Emit (OpCodes.Ble, target); else if (is_unsigned) - ig.Emit (OpCodes.Bgt_Un, target); + ec.Emit (OpCodes.Bgt_Un, target); else - ig.Emit (OpCodes.Bgt, target); + ec.Emit (OpCodes.Bgt, target); break; case Operator.GreaterThanOrEqual: if (on_true) if (is_unsigned && !is_float) - ig.Emit (OpCodes.Bge_Un, target); + ec.Emit (OpCodes.Bge_Un, target); else - ig.Emit (OpCodes.Bge, target); + ec.Emit (OpCodes.Bge, target); else if (is_unsigned) - ig.Emit (OpCodes.Blt_Un, target); + ec.Emit (OpCodes.Blt_Un, target); else - ig.Emit (OpCodes.Blt, target); + ec.Emit (OpCodes.Blt, target); break; default: throw new InternalErrorException (oper.ToString ()); @@ -3592,43 +3571,40 @@ namespace Mono.CSharp { EmitOperator (ec, left.Type); } - protected virtual void EmitOperator (EmitContext ec, Type l) + protected virtual void EmitOperator (EmitContext ec, TypeSpec l) { - ILGenerator ig = ec.ig; - // // Handle short-circuit operators differently // than the rest // if ((oper & Operator.LogicalMask) != 0) { - Label load_result = ig.DefineLabel (); - Label end = ig.DefineLabel (); + Label load_result = ec.DefineLabel (); + Label end = ec.DefineLabel (); bool is_or = oper == Operator.LogicalOr; left.EmitBranchable (ec, load_result, is_or); right.Emit (ec); - ig.Emit (OpCodes.Br_S, end); + ec.Emit (OpCodes.Br_S, end); - ig.MarkLabel (load_result); - ig.Emit (is_or ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0); - ig.MarkLabel (end); + ec.MarkLabel (load_result); + ec.Emit (is_or ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0); + ec.MarkLabel (end); return; } - left.Emit (ec); - - // - // Optimize zero-based operations // - // TODO: Implement more optimizations, but it should probably go to PredefinedOperators + // Optimize zero-based operations which cannot be optimized at expression level // - if ((oper & Operator.ShiftMask) != 0 || oper == Operator.Addition || oper == Operator.Subtraction) { - Constant rc = right as Constant; - if (rc != null && rc.IsDefaultValue) { + if (oper == Operator.Subtraction) { + var lc = left as IntegralConstant; + if (lc != null && lc.IsDefaultValue) { + right.Emit (ec); + ec.Emit (OpCodes.Neg); return; } } + left.Emit (ec); right.Emit (ec); EmitOperatorOpcode (ec, oper, l); @@ -3661,7 +3637,7 @@ namespace Mono.CSharp { public Expression CreateCallSiteBinder (ResolveContext ec, Arguments args) { - Arguments binder_args = new Arguments (3); + Arguments binder_args = new Arguments (4); MemberAccess sle = new MemberAccess (new MemberAccess ( new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "System", loc), "Linq", loc), "Expressions", loc); @@ -3675,7 +3651,8 @@ namespace Mono.CSharp { binder_args.Add (new Argument (new EnumConstant (new IntLiteral ((int) flags, loc), TypeManager.binder_flags))); binder_args.Add (new Argument (new MemberAccess (new MemberAccess (sle, "ExpressionType", loc), GetOperatorExpressionTypeName (), loc))); - binder_args.Add (new Argument (new ImplicitlyTypedArrayCreation ("[]", args.CreateDynamicBinderArguments (ec), loc))); + binder_args.Add (new Argument (new TypeOf (new TypeExpression (ec.CurrentType, loc), loc))); + binder_args.Add (new Argument (new ImplicitlyTypedArrayCreation (args.CreateDynamicBinderArguments (ec), loc))); return new Invocation (DynamicExpressionStatement.GetBinder ("BinaryOperation", loc), binder_args); } @@ -3840,7 +3817,7 @@ namespace Mono.CSharp { if (++pos == arguments.Count) return expr; - left = new Argument (new EmptyExpression (((MethodInfo)method).ReturnType)); + left = new Argument (new EmptyExpression (method.BestCandidate.ReturnType)); return CreateExpressionAddCall (ec, left, expr, pos); } @@ -3892,21 +3869,14 @@ namespace Mono.CSharp { concat.Emit (ec); } -#if NET_4_0 public override SLE.Expression MakeExpression (BuilderContext ctx) { if (arguments.Count != 2) throw new NotImplementedException ("arguments.Count != 2"); - var concat = TypeManager.string_type.GetMethod ("Concat", new[] { typeof (object), typeof (object) }); + var concat = typeof (string).GetMethod ("Concat", new[] { typeof (object), typeof (object) }); return SLE.Expression.Add (arguments[0].Expr.MakeExpression (ctx), arguments[1].Expr.MakeExpression (ctx), concat); } -#endif - - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) - { - arguments.MutateHoistedGenericType (storey); - } } // @@ -3926,9 +3896,9 @@ namespace Mono.CSharp { protected override Expression DoResolve (ResolveContext ec) { - MethodInfo method = (MethodInfo)mg; - type = TypeManager.TypeToCoreType (method.ReturnType); - AParametersCollection pd = TypeManager.GetParameterData (method); + var method = mg.BestCandidate; + type = method.ReturnType; + AParametersCollection pd = method.Parameters; if (!TypeManager.IsEqual (type, type) || !TypeManager.IsEqual (type, pd.Types [0]) || !TypeManager.IsEqual (type, pd.Types [1])) { ec.Report.Error (217, loc, "A user-defined operator `{0}' must have parameters and return values of the same type in order to be applicable as a short circuit operator", @@ -3953,19 +3923,18 @@ namespace Mono.CSharp { public override void Emit (EmitContext ec) { - ILGenerator ig = ec.ig; - Label end_target = ig.DefineLabel (); + Label end_target = ec.DefineLabel (); // // Emit and duplicate left argument // arguments [0].Expr.Emit (ec); - ig.Emit (OpCodes.Dup); + ec.Emit (OpCodes.Dup); arguments.RemoveAt (0); oper.EmitBranchable (ec, end_target, true); base.Emit (ec); - ig.MarkLabel (end_target); + ec.MarkLabel (end_target); } } @@ -3976,7 +3945,7 @@ namespace Mono.CSharp { // // We assume that `l' is always a pointer // - public PointerArithmetic (Binary.Operator op, Expression l, Expression r, Type t, Location loc) + public PointerArithmetic (Binary.Operator op, Expression l, Expression r, TypeSpec t, Location loc) { type = t; this.loc = loc; @@ -4005,23 +3974,22 @@ namespace Mono.CSharp { public override void Emit (EmitContext ec) { - Type op_type = left.Type; - ILGenerator ig = ec.ig; + TypeSpec op_type = left.Type; // It must be either array or fixed buffer - Type element; + TypeSpec element; if (TypeManager.HasElementType (op_type)) { element = TypeManager.GetElementType (op_type); } else { FieldExpr fe = left as FieldExpr; if (fe != null) - element = AttributeTester.GetFixedBuffer (fe.FieldInfo).ElementType; + element = ((FixedFieldSpec) (fe.Spec)).ElementType; else element = op_type; } int size = GetTypeSize (element); - Type rtype = right.Type; + TypeSpec rtype = right.Type; if ((op & Binary.Operator.SubtractionMask) != 0 && rtype.IsPointer){ // @@ -4029,16 +3997,16 @@ namespace Mono.CSharp { // left.Emit (ec); right.Emit (ec); - ig.Emit (OpCodes.Sub); + ec.Emit (OpCodes.Sub); if (size != 1){ if (size == 0) - ig.Emit (OpCodes.Sizeof, element); + ec.Emit (OpCodes.Sizeof, element); else - IntLiteral.EmitInt (ig, size); - ig.Emit (OpCodes.Div); + ec.EmitInt (size); + ec.Emit (OpCodes.Div); } - ig.Emit (OpCodes.Conv_I8); + ec.Emit (OpCodes.Conv_I8); } else { // // handle + and - on (pointer op int) @@ -4057,7 +4025,7 @@ namespace Mono.CSharp { left.Emit (ec); - Constant right_const = right as Constant; + var right_const = right as Constant; if (right_const != null) { // // Optimize 0-based arithmetic @@ -4065,42 +4033,42 @@ namespace Mono.CSharp { if (right_const.IsDefaultValue) return; - if (size != 0) { - // TODO: Should be the checks resolve context sensitive? - ResolveContext rc = new ResolveContext (ec.MemberContext); - right = ConstantFold.BinaryFold (rc, Binary.Operator.Multiply, new IntConstant (size, right.Location).Resolve (rc), right_const, loc); - if (right == null) - return; - } else { - ig.Emit (OpCodes.Sizeof, element); - right = EmptyExpression.Null; - } + if (size != 0) + right = new IntConstant (size, right.Location); + else + right = new SizeOf (new TypeExpression (element, right.Location), right.Location); + + // TODO: Should be the checks resolve context sensitive? + ResolveContext rc = new ResolveContext (ec.MemberContext, ResolveContext.Options.UnsafeScope); + right = new Binary (Binary.Operator.Multiply, right, right_const, loc).Resolve (rc); + if (right == null) + return; } right.Emit (ec); if (rtype == TypeManager.sbyte_type || rtype == TypeManager.byte_type || rtype == TypeManager.short_type || rtype == TypeManager.ushort_type) { - ig.Emit (OpCodes.Conv_I); + ec.Emit (OpCodes.Conv_I); } else if (rtype == TypeManager.uint32_type) { - ig.Emit (OpCodes.Conv_U); + ec.Emit (OpCodes.Conv_U); } if (right_const == null && size != 1){ if (size == 0) - ig.Emit (OpCodes.Sizeof, element); + ec.Emit (OpCodes.Sizeof, element); else - IntLiteral.EmitInt (ig, size); + ec.EmitInt (size); if (rtype == TypeManager.int64_type || rtype == TypeManager.uint64_type) - ig.Emit (OpCodes.Conv_I8); + ec.Emit (OpCodes.Conv_I8); Binary.EmitOperatorOpcode (ec, Binary.Operator.Multiply, rtype); } if (left_const == null) { if (rtype == TypeManager.int64_type) - ig.Emit (OpCodes.Conv_I); + ec.Emit (OpCodes.Conv_I); else if (rtype == TypeManager.uint64_type) - ig.Emit (OpCodes.Conv_U); + ec.Emit (OpCodes.Conv_U); Binary.EmitOperatorOpcode (ec, op, op_type); } @@ -4146,7 +4114,7 @@ namespace Mono.CSharp { if (expr.Type == TypeManager.bool_type) return expr; - if (TypeManager.IsDynamicType (expr.Type)) { + if (expr.Type == InternalType.Dynamic) { Arguments args = new Arguments (1); args.Add (new Argument (expr)); return new DynamicUnaryConversion ("IsTrue", args, loc).Resolve (ec); @@ -4221,8 +4189,8 @@ namespace Mono.CSharp { return null; eclass = ExprClass.Value; - Type true_type = true_expr.Type; - Type false_type = false_expr.Type; + TypeSpec true_type = true_expr.Type; + TypeSpec false_type = false_expr.Type; type = true_type; // @@ -4233,14 +4201,12 @@ namespace Mono.CSharp { Expression conv = Convert.ImplicitConversion (ec, true_expr, false_type, loc); if (conv != null) { // - // Check if both can convert implicitl to each other's type + // Check if both can convert implicitly to each other's type // if (Convert.ImplicitConversion (ec, false_expr, true_type, loc) != null) { - ec.Report.Error (172, loc, - "Can not compute type of conditional expression " + - "as `" + TypeManager.CSharpName (true_expr.Type) + - "' and `" + TypeManager.CSharpName (false_expr.Type) + - "' convert implicitly to each other"); + ec.Report.Error (172, true_expr.Location, + "Type of conditional expression cannot be determined as `{0}' and `{1}' convert implicitly to each other", + TypeManager.CSharpName (true_type), TypeManager.CSharpName (false_type)); return null; } type = false_type; @@ -4248,7 +4214,7 @@ namespace Mono.CSharp { } else if ((conv = Convert.ImplicitConversion (ec, false_expr, true_type, loc)) != null) { false_expr = conv; } else { - ec.Report.Error (173, loc, + ec.Report.Error (173, true_expr.Location, "Type of conditional expression cannot be determined because there is no implicit conversion between `{0}' and `{1}'", TypeManager.CSharpName (true_type), TypeManager.CSharpName (false_type)); return null; @@ -4260,20 +4226,12 @@ namespace Mono.CSharp { if (c != null){ bool is_false = c.IsDefaultValue; ec.Report.Warning (429, 4, is_false ? true_expr.Location : false_expr.Location, "Unreachable expression code detected"); - return ReducedExpression.Create (is_false ? false_expr : true_expr, this); + return ReducedExpression.Create (is_false ? false_expr : true_expr, this).Resolve (ec); } return this; } - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) - { - expr.MutateHoistedGenericType (storey); - true_expr.MutateHoistedGenericType (storey); - false_expr.MutateHoistedGenericType (storey); - type = storey.MutateType (type); - } - public override TypeExpr ResolveAsTypeTerminal (IMemberContext ec, bool silent) { return null; @@ -4281,24 +4239,23 @@ namespace Mono.CSharp { public override void Emit (EmitContext ec) { - ILGenerator ig = ec.ig; - Label false_target = ig.DefineLabel (); - Label end_target = ig.DefineLabel (); + Label false_target = ec.DefineLabel (); + Label end_target = ec.DefineLabel (); expr.EmitBranchable (ec, false_target, false); true_expr.Emit (ec); if (type.IsInterface) { LocalBuilder temp = ec.GetTemporaryLocal (type); - ig.Emit (OpCodes.Stloc, temp); - ig.Emit (OpCodes.Ldloc, temp); + ec.Emit (OpCodes.Stloc, temp); + ec.Emit (OpCodes.Ldloc, temp); ec.FreeTemporaryLocal (temp, type); } - ig.Emit (OpCodes.Br, end_target); - ig.MarkLabel (false_target); + ec.Emit (OpCodes.Br, end_target); + ec.MarkLabel (false_target); false_expr.Emit (ec); - ig.MarkLabel (end_target); + ec.MarkLabel (end_target); } protected override void CloneTo (CloneContext clonectx, Expression t) @@ -4332,7 +4289,7 @@ namespace Mono.CSharp { public abstract VariableInfo VariableInfo { get; } #endregion - public void AddressOf (EmitContext ec, AddressOp mode) + public virtual void AddressOf (EmitContext ec, AddressOp mode) { HoistedVariable hv = GetHoistedVariable (ec); if (hv != null) { @@ -4396,11 +4353,11 @@ namespace Mono.CSharp { // If we are a reference, we loaded on the stack a pointer // Now lets load the real value // - LoadFromPtr (ec.ig, type); + ec.EmitLoadFromPtr (type); } if (leave_copy) { - ec.ig.Emit (OpCodes.Dup); + ec.Emit (OpCodes.Dup); if (IsRef) { temp = new LocalTemporary (Type); @@ -4433,7 +4390,7 @@ namespace Mono.CSharp { } if (leave_copy) { - ec.ig.Emit (OpCodes.Dup); + ec.Emit (OpCodes.Dup); if (IsRef) { temp = new LocalTemporary (Type); temp.Store (ec); @@ -4441,7 +4398,7 @@ namespace Mono.CSharp { } if (IsRef) - StoreFromPtr (ec.ig, type); + ec.EmitStoreFromPtr (type); else Variable.EmitAssign (ec); @@ -4454,11 +4411,6 @@ namespace Mono.CSharp { public bool IsHoisted { get { return GetHoistedVariable ((AnonymousExpression) null) != null; } } - - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) - { - type = storey.MutateType (type); - } } /// @@ -4795,6 +4747,19 @@ namespace Mono.CSharp { return Name == pr.Name; } + + public override void AddressOf (EmitContext ec, AddressOp mode) + { + // + // ParameterReferences might already be a reference + // + if (IsRef) { + EmitLoad (ec); + return; + } + + base.AddressOf (ec, mode); + } protected override void CloneTo (CloneContext clonectx, Expression target) { @@ -4843,25 +4808,22 @@ namespace Mono.CSharp { if (!DoResolveBase (ec)) return null; - // HACK: parameters are not captured when probing is on - if (!ec.IsInProbingMode) - SetAssigned (ec); - + SetAssigned (ec); return this; } - static public void EmitLdArg (ILGenerator ig, int x) + static public void EmitLdArg (EmitContext ec, int x) { switch (x) { - case 0: ig.Emit (OpCodes.Ldarg_0); break; - case 1: ig.Emit (OpCodes.Ldarg_1); break; - case 2: ig.Emit (OpCodes.Ldarg_2); break; - case 3: ig.Emit (OpCodes.Ldarg_3); break; + case 0: ec.Emit (OpCodes.Ldarg_0); break; + case 1: ec.Emit (OpCodes.Ldarg_1); break; + case 2: ec.Emit (OpCodes.Ldarg_2); break; + case 3: ec.Emit (OpCodes.Ldarg_3); break; default: if (x > byte.MaxValue) - ig.Emit (OpCodes.Ldarg, x); + ec.Emit (OpCodes.Ldarg, x); else - ig.Emit (OpCodes.Ldarg_S, (byte) x); + ec.Emit (OpCodes.Ldarg_S, (byte) x); break; } } @@ -4929,10 +4891,10 @@ namespace Mono.CSharp { if (arguments != null && !arguments_resolved) arguments.Resolve (ec, out dynamic_arg); - Type expr_type = member_expr.Type; + TypeSpec expr_type = member_expr.Type; mg = member_expr as MethodGroupExpr; - bool dynamic_member = TypeManager.IsDynamicType (expr_type); + bool dynamic_member = expr_type == InternalType.Dynamic; if (!dynamic_member) { Expression invoke = null; @@ -4950,7 +4912,7 @@ namespace Mono.CSharp { return null; } - mg = ec.LookupExtensionMethod (me.Type, me.Name, loc); + mg = ec.LookupExtensionMethod (me.Type, me.Name, -1, loc); if (mg == null) { ec.Report.Error (1955, loc, "The member `{0}' cannot be used as method or delegate", member_expr.GetSignatureForError ()); @@ -4971,26 +4933,9 @@ namespace Mono.CSharp { if (dynamic_arg || dynamic_member) return DoResolveDynamic (ec, member_expr); - MethodInfo method = (MethodInfo)mg; + var method = mg.BestCandidate; if (method != null) { - type = TypeManager.TypeToCoreType (method.ReturnType); - - // TODO: this is a copy of mg.ResolveMemberAccess method - Expression iexpr = mg.InstanceExpression; - if (method.IsStatic) { - if (iexpr == null || - iexpr is This || iexpr is EmptyExpression || - mg.IdenticalTypeName) { - mg.InstanceExpression = null; - } else { - MemberExpr.error176 (ec, loc, mg.GetSignatureForError ()); - return null; - } - } else { - if (iexpr == null || iexpr == EmptyExpression.Null) { - SimpleName.Error_ObjectRefRequired (ec, loc, mg.GetSignatureForError ()); - } - } + type = method.ReturnType; } // @@ -5042,20 +4987,24 @@ namespace Mono.CSharp { return null; } - args = arguments; - - if (mg.IsStatic != mg.IsInstance) { - if (args == null) - args = new Arguments (1); + if (arguments == null) + args = new Arguments (1); + else + args = arguments; - if (mg.IsStatic) { - args.Insert (0, new Argument (new TypeOf (new TypeExpression (mg.DeclaringType, loc), loc).Resolve (ec), Argument.AType.DynamicTypeName)); + MemberAccess ma = expr as MemberAccess; + if (ma != null) { + var left_type = ma.Left as TypeExpr; + if (left_type != null) { + args.Insert (0, new Argument (new TypeOf (left_type, loc).Resolve (ec), Argument.AType.DynamicTypeName)); } else { - MemberAccess ma = expr as MemberAccess; - if (ma != null) - args.Insert (0, new Argument (ma.Left.Resolve (ec))); - else - args.Insert (0, new Argument (new This (loc).Resolve (ec))); + args.Insert (0, new Argument (ma.Left)); + } + } else { // is SimpleName + if (ec.IsStatic) { + args.Insert (0, new Argument (new TypeOf (new TypeExpression (ec.CurrentType, loc), loc).Resolve (ec), Argument.AType.DynamicTypeName)); + } else { + args.Insert (0, new Argument (new This (loc).Resolve (ec))); } } } @@ -5068,9 +5017,9 @@ namespace Mono.CSharp { return mg.OverloadResolve (ec, ref arguments, false, loc); } - public static bool IsSpecialMethodInvocation (ResolveContext ec, MethodBase method, Location loc) + public static bool IsSpecialMethodInvocation (ResolveContext ec, MethodSpec method, Location loc) { - if (!TypeManager.IsSpecialMethod (method)) + if (!method.IsReservedMethod) return false; if (ec.HasSet (ResolveContext.Options.InvokeSpecialName)) @@ -5078,14 +5027,14 @@ namespace Mono.CSharp { ec.Report.SymbolRelatedToPreviousError (method); ec.Report.Error (571, loc, "`{0}': cannot explicitly call operator or accessor", - TypeManager.CSharpSignature (method, true)); + method.GetSignatureForError ()); return true; } - static Type[] GetVarargsTypes (MethodBase mb, Arguments arguments) + static Type[] GetVarargsTypes (MethodSpec mb, Arguments arguments) { - AParametersCollection pd = TypeManager.GetParameterData (mb); + AParametersCollection pd = mb.Parameters; Argument a = arguments [pd.Count - 1]; Arglist list = (Arglist) a.Expr; @@ -5093,28 +5042,6 @@ namespace Mono.CSharp { return list.ArgumentTypes; } - /// - /// This checks the ConditionalAttribute on the method - /// - public static bool IsMethodExcluded (MethodBase method, Location loc) - { - if (method.IsConstructor) - return false; - - method = TypeManager.DropGenericMethodArguments (method); - if (TypeManager.IsBeingCompiled (method)) { - IMethodData md = TypeManager.GetMethod (method); - if (md != null) - return md.IsExcluded (); - - // For some methods (generated by delegate class) GetMethod returns null - // because they are not included in builder_to_method table - return false; - } - - return AttributeTester.IsConditionalMethodExcluded (method, loc); - } - /// /// is_base tells whether we want to force the use of the `call' /// opcode instead of using callvirt. Call is required to call @@ -5132,7 +5059,7 @@ namespace Mono.CSharp { /// public static void EmitCall (EmitContext ec, bool is_base, Expression instance_expr, - MethodBase method, Arguments Arguments, Location loc) + MethodSpec method, Arguments Arguments, Location loc) { EmitCall (ec, is_base, instance_expr, method, Arguments, loc, false, false); } @@ -5145,77 +5072,73 @@ namespace Mono.CSharp { // only have been evaluated once. public static void EmitCall (EmitContext ec, bool is_base, Expression instance_expr, - MethodBase method, Arguments Arguments, Location loc, + MethodSpec method, Arguments Arguments, Location loc, bool dup_args, bool omit_args) { - ILGenerator ig = ec.ig; - bool struct_call = false; - bool this_call = false; LocalTemporary this_arg = null; - Type decl_type = method.DeclaringType; + TypeSpec decl_type = method.DeclaringType; - if (IsMethodExcluded (method, loc)) + // Speed up the check by not doing it on not allowed targets + if (method.ReturnType == TypeManager.void_type && method.IsConditionallyExcluded (loc)) return; - - bool is_static = method.IsStatic; - if (!is_static){ - this_call = instance_expr is This; - if (TypeManager.IsStruct (decl_type) || TypeManager.IsEnumType (decl_type)) - struct_call = true; + + OpCode call_op; + TypeSpec iexpr_type; + + if (method.IsStatic) { + iexpr_type = null; + call_op = OpCodes.Call; + } else { + iexpr_type = instance_expr.Type; + + if (is_base || decl_type.IsStruct || decl_type.IsEnum || (instance_expr is This && !method.IsVirtual)) { + call_op = OpCodes.Call; + } else { + call_op = OpCodes.Callvirt; + } // // If this is ourselves, push "this" // if (!omit_args) { - Type t = null; - Type iexpr_type = instance_expr.Type; + TypeSpec t = iexpr_type; // // Push the instance expression // - if (TypeManager.IsValueType (iexpr_type) || TypeManager.IsGenericParameter (iexpr_type)) { + if ((iexpr_type.IsStruct && (call_op == OpCodes.Callvirt || (call_op == OpCodes.Call && decl_type == iexpr_type))) || + iexpr_type.IsGenericParameter || TypeManager.IsNullableType (decl_type)) { + // + // If the expression implements IMemoryLocation, then + // we can optimize and use AddressOf on the + // return. // - // Special case: calls to a function declared in a - // reference-type with a value-type argument need - // to have their value boxed. - if (TypeManager.IsStruct (decl_type) || - TypeManager.IsGenericParameter (iexpr_type)) { - // - // If the expression implements IMemoryLocation, then - // we can optimize and use AddressOf on the - // return. - // - // If not we have to use some temporary storage for - // it. - if (instance_expr is IMemoryLocation) { - ((IMemoryLocation)instance_expr). - AddressOf (ec, AddressOp.LoadStore); - } else { - LocalTemporary temp = new LocalTemporary (iexpr_type); - instance_expr.Emit (ec); - temp.Store (ec); - temp.AddressOf (ec, AddressOp.Load); - } - - // avoid the overhead of doing this all the time. - if (dup_args) - t = TypeManager.GetReferenceType (iexpr_type); + // If not we have to use some temporary storage for + // it. + var iml = instance_expr as IMemoryLocation; + if (iml != null) { + iml.AddressOf (ec, AddressOp.LoadStore); } else { + LocalTemporary temp = new LocalTemporary (iexpr_type); instance_expr.Emit (ec); - - // FIXME: should use instance_expr is IMemoryLocation + constraint. - // to help JIT to produce better code - ig.Emit (OpCodes.Box, instance_expr.Type); - t = TypeManager.object_type; + temp.Store (ec); + temp.AddressOf (ec, AddressOp.Load); } + + // avoid the overhead of doing this all the time. + if (dup_args) + t = ReferenceContainer.MakeType (iexpr_type); + } else if (iexpr_type.IsEnum || iexpr_type.IsStruct) { + instance_expr.Emit (ec); + ec.Emit (OpCodes.Box, iexpr_type); + t = iexpr_type = TypeManager.object_type; } else { instance_expr.Emit (ec); - t = instance_expr.Type; } if (dup_args) { - ig.Emit (OpCodes.Dup); + ec.Emit (OpCodes.Dup); if (Arguments != null && Arguments.Count != 0) { this_arg = new LocalTemporary (t); this_arg.Store (ec); @@ -5227,19 +5150,13 @@ namespace Mono.CSharp { if (!omit_args && Arguments != null) Arguments.Emit (ec, dup_args, this_arg); - OpCode call_op; - if (is_static || struct_call || is_base || (this_call && !method.IsVirtual)) { - call_op = OpCodes.Call; - } else { - call_op = OpCodes.Callvirt; - - if ((instance_expr != null) && (instance_expr.Type.IsGenericParameter)) - ig.Emit (OpCodes.Constrained, instance_expr.Type); + if (call_op == OpCodes.Callvirt && (iexpr_type.IsGenericParameter || iexpr_type.IsStruct)) { + ec.Emit (OpCodes.Constrained, iexpr_type); } - if ((method.CallingConvention & CallingConventions.VarArgs) != 0) { + if (method.Parameters.HasArglist) { Type[] varargs_types = GetVarargsTypes (method, Arguments); - ig.EmitCall (call_op, (MethodInfo) method, varargs_types); + ec.Emit (call_op, method, varargs_types); return; } @@ -5249,10 +5166,7 @@ namespace Mono.CSharp { // and DoFoo is not virtual, you can omit the callvirt, // because you don't need the null checking behavior. // - if (method is MethodInfo) - ig.Emit (call_op, (MethodInfo) method); - else - ig.Emit (call_op, (ConstructorInfo) method); + ec.Emit (call_op, method); } public override void Emit (EmitContext ec) @@ -5267,8 +5181,8 @@ namespace Mono.CSharp { // // Pop the return value if there is one // - if (TypeManager.TypeToCoreType (type) != TypeManager.void_type) - ec.ig.Emit (OpCodes.Pop); + if (type != TypeManager.void_type) + ec.Emit (OpCodes.Pop); } protected override void CloneTo (CloneContext clonectx, Expression t) @@ -5281,26 +5195,15 @@ namespace Mono.CSharp { target.expr = expr.Clone (clonectx); } -#if NET_4_0 public override SLE.Expression MakeExpression (BuilderContext ctx) { - return MakeExpression (ctx, mg.InstanceExpression, (MethodInfo) mg, arguments); + return MakeExpression (ctx, mg.InstanceExpression, (MethodSpec) mg, arguments); } - public static SLE.Expression MakeExpression (BuilderContext ctx, Expression instance, MethodInfo mi, Arguments args) + public static SLE.Expression MakeExpression (BuilderContext ctx, Expression instance, MethodSpec mi, Arguments args) { var instance_expr = instance == null ? null : instance.MakeExpression (ctx); - return SLE.Expression.Call (instance_expr, mi, Arguments.MakeExpression (args, ctx)); - } -#endif - - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) - { - mg.MutateHoistedGenericType (storey); - type = storey.MutateType (type); - if (arguments != null) { - arguments.MutateHoistedGenericType (storey); - } + return SLE.Expression.Call (instance_expr, (MethodInfo) mi.GetMetaInfo (), Arguments.MakeExpression (args, ctx)); } } @@ -5319,8 +5222,6 @@ namespace Mono.CSharp { protected MethodGroupExpr method; - bool is_type_parameter; - public New (Expression requested_type, Arguments arguments, Location l) { RequestedType = requested_type; @@ -5331,7 +5232,7 @@ namespace Mono.CSharp { /// /// Converts complex core type syntax like 'new int ()' to simple constant /// - public static Constant Constantify (Type t) + public static Constant Constantify (TypeSpec t) { if (t == TypeManager.int32_type) return new IntConstant (0, Location.Null); @@ -5360,7 +5261,7 @@ namespace Mono.CSharp { if (t == TypeManager.decimal_type) return new DecimalConstant (0, Location.Null); if (TypeManager.IsEnumType (t)) - return new EnumConstant (Constantify (TypeManager.GetEnumUnderlyingType (t)), t); + return new EnumConstant (Constantify (EnumSpec.GetUnderlyingType (t)), t); if (TypeManager.IsNullableType (t)) return Nullable.LiftedNull.Create (t, Location.Null); @@ -5381,7 +5282,7 @@ namespace Mono.CSharp { // Turn the call into: // (the-interface-stated) (new class-referenced-in-coclassattribute ()) // - Type real_class = AttributeTester.GetCoClassAttribute (type); + var real_class = type.MemberDefinition.GetAttributeCoClass (); if (real_class == null) return null; @@ -5407,20 +5308,6 @@ namespace Mono.CSharp { protected override Expression DoResolve (ResolveContext ec) { - // - // The New DoResolve might be called twice when initializing field - // expressions (see EmitFieldInitializers, the call to - // GetInitializerExpression will perform a resolve on the expression, - // and later the assign will trigger another resolution - // - // This leads to bugs (#37014) - // - if (type != null){ - if (RequestedType is NewDelegate) - return RequestedType; - return this; - } - TypeExpr texpr = RequestedType.ResolveAsTypeTerminal (ec, false); if (texpr == null) return null; @@ -5443,37 +5330,33 @@ namespace Mono.CSharp { return (new NewDelegate (type, Arguments, loc)).Resolve (ec); } - if (TypeManager.IsGenericParameter (type)) { - GenericConstraints gc = TypeManager.GetTypeParameterConstraints (type); - - if ((gc == null) || (!gc.HasConstructorConstraint && !gc.IsValueType)) { + var tparam = type as TypeParameterSpec; + if (tparam != null) { + if (!tparam.HasSpecialConstructor && !tparam.HasSpecialStruct) { ec.Report.Error (304, loc, - "Cannot create an instance of the variable type '{0}' because it doesn't have the new() constraint", + "Cannot create an instance of the variable type `{0}' because it does not have the new() constraint", TypeManager.CSharpName (type)); - return null; } if ((Arguments != null) && (Arguments.Count != 0)) { ec.Report.Error (417, loc, "`{0}': cannot provide arguments when creating an instance of a variable type", TypeManager.CSharpName (type)); - return null; } if (TypeManager.activator_create_instance == null) { - Type activator_type = TypeManager.CoreLookupType (ec.Compiler, "System", "Activator", Kind.Class, true); + TypeSpec activator_type = TypeManager.CoreLookupType (ec.Compiler, "System", "Activator", MemberKind.Class, true); if (activator_type != null) { TypeManager.activator_create_instance = TypeManager.GetPredefinedMethod ( - activator_type, "CreateInstance", loc, Type.EmptyTypes); + activator_type, MemberFilter.Method ("CreateInstance", 1, ParametersCompiled.EmptyReadOnlyParameters, null), loc); } } - is_type_parameter = true; eclass = ExprClass.Value; return this; } - if (type.IsAbstract && type.IsSealed) { + if (type.IsStatic) { ec.Report.SymbolRelatedToPreviousError (type); ec.Report.Error (712, loc, "Cannot create an instance of the static class `{0}'", TypeManager.CSharpName (type)); return null; @@ -5502,8 +5385,8 @@ namespace Mono.CSharp { return this; // For member-lookup, treat 'new Foo (bar)' as call to 'foo.ctor (bar)', where 'foo' is of type 'Foo'. - Expression ml = MemberLookupFinal (ec, type, type, ConstructorInfo.ConstructorName, - MemberTypes.Constructor, AllBindingFlags | BindingFlags.DeclaredOnly, loc); + Expression ml = MemberLookupFinal (ec, type, type, ConstructorInfo.ConstructorName, 0, + MemberKind.Constructor, BindingRestriction.AccessibleOnly | BindingRestriction.DeclaredOnly, loc); bool dynamic; if (Arguments != null) { @@ -5535,14 +5418,11 @@ namespace Mono.CSharp { bool DoEmitTypeParameter (EmitContext ec) { - ILGenerator ig = ec.ig; - - MethodInfo ci = TypeManager.activator_create_instance.MakeGenericMethod ( - new Type [] { type }); + var ctor_factory = TypeManager.activator_create_instance.MakeGenericMethod (type); + var tparam = (TypeParameterSpec) type; - GenericConstraints gc = TypeManager.GetTypeParameterConstraints (type); - if (gc.HasReferenceTypeConstraint || gc.HasClassConstraint) { - ig.Emit (OpCodes.Call, ci); + if (tparam.IsReferenceType) { + ec.Emit (OpCodes.Call, ctor_factory); return true; } @@ -5551,25 +5431,25 @@ namespace Mono.CSharp { // you can't share LocalBuilders among ILGeneators. LocalTemporary temp = new LocalTemporary (type); - Label label_activator = ig.DefineLabel (); - Label label_end = ig.DefineLabel (); + Label label_activator = ec.DefineLabel (); + Label label_end = ec.DefineLabel (); temp.AddressOf (ec, AddressOp.Store); - ig.Emit (OpCodes.Initobj, type); + ec.Emit (OpCodes.Initobj, type); temp.Emit (ec); - ig.Emit (OpCodes.Box, type); - ig.Emit (OpCodes.Brfalse, label_activator); + ec.Emit (OpCodes.Box, type); + ec.Emit (OpCodes.Brfalse, label_activator); temp.AddressOf (ec, AddressOp.Store); - ig.Emit (OpCodes.Initobj, type); + ec.Emit (OpCodes.Initobj, type); temp.Emit (ec); - ig.Emit (OpCodes.Br_S, label_end); + ec.Emit (OpCodes.Br_S, label_end); - ig.MarkLabel (label_activator); + ec.MarkLabel (label_activator); - ig.Emit (OpCodes.Call, ci); - ig.MarkLabel (label_end); + ec.Emit (OpCodes.Call, ctor_factory); + ec.MarkLabel (label_end); return true; } @@ -5603,7 +5483,6 @@ namespace Mono.CSharp { public virtual bool Emit (EmitContext ec, IMemoryLocation target) { bool is_value_type = TypeManager.IsValueType (type); - ILGenerator ig = ec.ig; VariableReference vr = target as VariableReference; if (target != null && is_value_type && (vr != null || method == null)) { @@ -5617,26 +5496,20 @@ namespace Mono.CSharp { if (is_value_type) { if (method == null) { - ig.Emit (OpCodes.Initobj, type); + ec.Emit (OpCodes.Initobj, type); return false; } if (vr != null) { - ig.Emit (OpCodes.Call, (ConstructorInfo) method); + ec.Emit (OpCodes.Call, method.BestCandidate); return false; } } - if (is_type_parameter) + if (type is TypeParameterSpec) return DoEmitTypeParameter (ec); - ConstructorInfo ci = (ConstructorInfo) method; -#if MS_COMPATIBLE - if (TypeManager.IsGenericType (type) && type.IsGenericTypeDefinition) - ci = TypeBuilder.GetConstructor (type, ci); -#endif - - ig.Emit (OpCodes.Newobj, ci); + ec.Emit (OpCodes.Newobj, method.BestCandidate); return true; } @@ -5661,7 +5534,7 @@ namespace Mono.CSharp { } if (Emit (ec, v)) - ec.ig.Emit (OpCodes.Pop); + ec.Emit (OpCodes.Pop); } public virtual bool HasInitializer { @@ -5679,7 +5552,7 @@ namespace Mono.CSharp { { LocalTemporary value_target = new LocalTemporary (type); - if (is_type_parameter) { + if (type is TypeParameterSpec) { DoEmitTypeParameter (ec); value_target.Store (ec); value_target.AddressOf (ec, mode); @@ -5699,12 +5572,12 @@ namespace Mono.CSharp { value_target.AddressOf (ec, AddressOp.Store); if (method == null) { - ec.ig.Emit (OpCodes.Initobj, type); + ec.Emit (OpCodes.Initobj, type); } else { if (Arguments != null) Arguments.Emit (ec); - ec.ig.Emit (OpCodes.Call, (ConstructorInfo) method); + ec.Emit (OpCodes.Call, method.BestCandidate); } value_target.AddressOf (ec, mode); @@ -5721,23 +5594,68 @@ namespace Mono.CSharp { } } -#if NET_4_0 public override SLE.Expression MakeExpression (BuilderContext ctx) { - return SLE.Expression.New ((ConstructorInfo) method, Arguments.MakeExpression (Arguments, ctx)); + return SLE.Expression.New ((ConstructorInfo) method.BestCandidate.GetMetaInfo (), Arguments.MakeExpression (Arguments, ctx)); } -#endif + } + + public class ArrayInitializer : Expression + { + List elements; - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + public ArrayInitializer (List init, Location loc) { - if (method != null) { - method.MutateHoistedGenericType (storey); - if (Arguments != null) { - Arguments.MutateHoistedGenericType (storey); - } - } + elements = init; + this.loc = loc; + } + + public ArrayInitializer (int count, Location loc) + { + elements = new List (count); + this.loc = loc; + } + + public ArrayInitializer (Location loc) + : this (4, loc) + { + } + + public void Add (Expression expr) + { + elements.Add (expr); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotSupportedException ("ET"); + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + var target = (ArrayInitializer) t; + + target.elements = new List (elements.Count); + foreach (var element in elements) + target.elements.Add (element.Clone (clonectx)); + } + + public int Count { + get { return elements.Count; } + } + + protected override Expression DoResolve (ResolveContext rc) + { + throw new NotImplementedException (); + } + + public override void Emit (EmitContext ec) + { + throw new InternalErrorException ("Missing Resolve call"); + } - type = storey.MutateType (type); + public Expression this [int index] { + get { return elements [index]; } } } @@ -5751,60 +5669,67 @@ namespace Mono.CSharp { /// initialization data and the other which does not need dimensions /// specified but where initialization data is mandatory. /// - public class ArrayCreation : Expression { + public class ArrayCreation : Expression + { FullNamedExpression requested_base_type; - ArrayList initializers; + ArrayInitializer initializers; // // The list of Argument types. // This is used to construct the `newarray' or constructor signature // - protected ArrayList arguments; + protected List arguments; - protected Type array_element_type; - bool expect_initializers = false; + protected TypeSpec array_element_type; int num_arguments = 0; protected int dimensions; - protected readonly string rank; + protected readonly ComposedTypeSpecifier rank; Expression first_emit; LocalTemporary first_emit_temp; protected List array_data; - IDictionary bounds; + Dictionary bounds; // The number of constants in array initializers int const_initializers_count; bool only_constant_initializers; - - public ArrayCreation (FullNamedExpression requested_base_type, ArrayList exprs, string rank, ArrayList initializers, Location l) + + public ArrayCreation (FullNamedExpression requested_base_type, List exprs, ComposedTypeSpecifier rank, ArrayInitializer initializers, Location l) + : this (requested_base_type, rank, initializers, l) + { + arguments = new List (exprs); + num_arguments = arguments.Count; + } + + // + // For expressions like int[] foo = new int[] { 1, 2, 3 }; + // + public ArrayCreation (FullNamedExpression requested_base_type, ComposedTypeSpecifier rank, ArrayInitializer initializers, Location loc) { this.requested_base_type = requested_base_type; - this.initializers = initializers; this.rank = rank; - loc = l; - - arguments = new ArrayList (exprs.Count); + this.initializers = initializers; + this.loc = loc; - foreach (Expression e in exprs) { - arguments.Add (e); - num_arguments++; - } + if (rank != null) + num_arguments = rank.Dimension; } - public ArrayCreation (FullNamedExpression requested_base_type, string rank, ArrayList initializers, Location l) + // + // For compiler generated single dimensional arrays only + // + public ArrayCreation (FullNamedExpression requested_base_type, ArrayInitializer initializers, Location loc) + : this (requested_base_type, ComposedTypeSpecifier.SingleDimension, initializers, loc) { - this.requested_base_type = requested_base_type; - this.initializers = initializers; - this.rank = rank; - loc = l; + } - //this.rank = rank.Substring (0, rank.LastIndexOf ('[')); - // - //string tmp = rank.Substring (rank.LastIndexOf ('[')); - // - //dimensions = tmp.Length - 1; - expect_initializers = true; + // + // For expressions like int[] foo = { 1, 2, 3 }; + // + public ArrayCreation (FullNamedExpression requested_base_type, ArrayInitializer initializers) + : this (requested_base_type, null, initializers, initializers.Location) + { } protected override void Error_NegativeArrayIndex (ResolveContext ec, Location loc) @@ -5812,61 +5737,84 @@ namespace Mono.CSharp { ec.Report.Error (248, loc, "Cannot create an array with a negative size"); } - bool CheckIndices (ResolveContext ec, ArrayList probe, int idx, bool specified_dims, int child_bounds) + bool CheckIndices (ResolveContext ec, ArrayInitializer probe, int idx, bool specified_dims, int child_bounds) { + if (initializers != null && bounds == null) { + // + // We use this to store all the date values in the order in which we + // will need to store them in the byte blob later + // + array_data = new List (); + bounds = new Dictionary (); + } + if (specified_dims) { - Expression a = (Expression) arguments [idx]; + Expression a = arguments [idx]; a = a.Resolve (ec); if (a == null) return false; - Constant c = a as Constant; - if (c != null) { - c = c.ImplicitConversionRequired (ec, TypeManager.int32_type, a.Location); - } - - if (c == null) { - ec.Report.Error (150, a.Location, "A constant value is expected"); + a = ConvertExpressionToArrayIndex (ec, a); + if (a == null) return false; - } - int value = (int) c.GetValue (); - - if (value != probe.Count) { - ec.Report.Error (847, loc, "An array initializer of length `{0}' was expected", value); - return false; - } - - bounds [idx] = value; - } + arguments[idx] = a; - only_constant_initializers = true; - for (int i = 0; i < probe.Count; ++i) { - object o = probe [i]; - if (o is ArrayList) { - ArrayList sub_probe = o as ArrayList; - if (idx + 1 >= dimensions){ - ec.Report.Error (623, loc, "Array initializers can only be used in a variable or field initializer. Try using a new expression instead"); + if (initializers != null) { + Constant c = a as Constant; + if (c == null && a is ArrayIndexCast) + c = ((ArrayIndexCast) a).Child as Constant; + + if (c == null) { + ec.Report.Error (150, a.Location, "A constant value is expected"); return false; } - - bool ret = CheckIndices (ec, sub_probe, idx + 1, specified_dims, child_bounds - 1); - if (!ret) + + int value; + try { + value = System.Convert.ToInt32 (c.GetValue ()); + } catch { + ec.Report.Error (150, a.Location, "A constant value is expected"); + return false; + } + + // TODO: probe.Count does not fit ulong in + if (value != probe.Count) { + ec.Report.Error (847, loc, "An array initializer of length `{0}' was expected", value.ToString ()); + return false; + } + + bounds[idx] = value; + } + } + + if (initializers == null) + return true; + + only_constant_initializers = true; + for (int i = 0; i < probe.Count; ++i) { + var o = probe [i]; + if (o is ArrayInitializer) { + var sub_probe = o as ArrayInitializer; + if (idx + 1 >= dimensions){ + ec.Report.Error (623, loc, "Array initializers can only be used in a variable or field initializer. Try using a new expression instead"); + return false; + } + + bool ret = CheckIndices (ec, sub_probe, idx + 1, specified_dims, child_bounds - 1); + if (!ret) return false; } else if (child_bounds > 1) { - ec.Report.Error (846, ((Expression) o).Location, "A nested array initializer was expected"); + ec.Report.Error (846, o.Location, "A nested array initializer was expected"); } else { - Expression element = ResolveArrayElement (ec, (Expression) o); + Expression element = ResolveArrayElement (ec, o); if (element == null) continue; // Initializers with the default values can be ignored Constant c = element as Constant; if (c != null) { - if (c.IsDefaultInitializer (array_element_type)) { - element = null; - } - else { + if (!c.IsDefaultInitializer (array_element_type)) { ++const_initializers_count; } } else { @@ -5903,9 +5851,6 @@ namespace Mono.CSharp { if (array_data != null) { for (int i = 0; i < array_data.Count; ++i) { Expression e = array_data [i]; - if (e == null) - e = Convert.ImplicitConversion (ec, (Expression) initializers [i], array_element_type, loc); - args.Add (new Argument (e.CreateExpressionTree (ec))); } } @@ -5916,14 +5861,14 @@ namespace Mono.CSharp { public void UpdateIndices () { int i = 0; - for (ArrayList probe = initializers; probe != null;) { - if (probe.Count > 0 && probe [0] is ArrayList) { + for (var probe = initializers; probe != null;) { + if (probe.Count > 0 && probe [0] is ArrayInitializer) { Expression e = new IntConstant (probe.Count, Location.Null); arguments.Add (e); - bounds [i++] = probe.Count; - - probe = (ArrayList) probe [0]; + bounds [i++] = probe.Count; + + probe = (ArrayInitializer) probe[0]; } else { Expression e = new IntConstant (probe.Count, Location.Null); @@ -5954,21 +5899,18 @@ namespace Mono.CSharp { protected bool ResolveInitializers (ResolveContext ec) { - if (initializers == null) { - return !expect_initializers; + if (arguments != null) { + bool res = true; + for (int i = 0; i < arguments.Count; ++i) { + res &= CheckIndices (ec, initializers, i, true, dimensions); + if (initializers != null) + break; + } + + return res; } - - // - // We use this to store all the date values in the order in which we - // will need to store them in the byte blob later - // - array_data = new List (); - bounds = new System.Collections.Specialized.HybridDictionary (); - - if (arguments != null) - return CheckIndices (ec, initializers, 0, true, dimensions); - arguments = new ArrayList (); + arguments = new List (); if (!CheckIndices (ec, initializers, 0, false, dimensions)) return false; @@ -5983,41 +5925,34 @@ namespace Mono.CSharp { // bool ResolveArrayType (ResolveContext ec) { - if (requested_base_type == null) { - ec.Report.Error (622, loc, "Can only use array initializer expressions to assign to array types. Try using a new expression instead"); - return false; - } - if (requested_base_type is VarExpr) { ec.Report.Error (820, loc, "An implicitly typed local variable declarator cannot use an array initializer"); return false; } - StringBuilder array_qualifier = new StringBuilder (rank); - // - // `In the first form allocates an array instace of the type that results - // from deleting each of the individual expression from the expression list' + // Lookup the type // + FullNamedExpression array_type_expr; if (num_arguments > 0) { - array_qualifier.Append ("["); - for (int i = num_arguments-1; i > 0; i--) - array_qualifier.Append (","); - array_qualifier.Append ("]"); + array_type_expr = new ComposedCast (requested_base_type, rank); + } else { + array_type_expr = requested_base_type; } - // - // Lookup the type - // - TypeExpr array_type_expr; - array_type_expr = new ComposedCast (requested_base_type, array_qualifier.ToString (), loc); array_type_expr = array_type_expr.ResolveAsTypeTerminal (ec, false); if (array_type_expr == null) return false; type = array_type_expr.Type; - array_element_type = TypeManager.GetElementType (type); - dimensions = type.GetArrayRank (); + var ac = type as ArrayContainer; + if (ac == null) { + ec.Report.Error (622, loc, "Can only use array initializer expressions to assign to array types. Try using a new expression instead"); + return false; + } + + array_element_type = ac.Element; + dimensions = ac.Rank; return true; } @@ -6031,44 +5966,15 @@ namespace Mono.CSharp { return null; // - // First step is to validate the initializers and fill - // in any missing bits + // validate the initializers and fill in any missing bits // if (!ResolveInitializers (ec)) return null; - for (int i = 0; i < arguments.Count; ++i) { - Expression e = ((Expression) arguments[i]).Resolve (ec); - if (e == null) - continue; - - arguments [i] = ConvertExpressionToArrayIndex (ec, e); - } - eclass = ExprClass.Value; return this; } - MethodInfo GetArrayMethod (EmitContext ec, int arguments) - { - ModuleBuilder mb = RootContext.ToplevelTypes.Builder; - - Type[] arg_types = new Type[arguments]; - for (int i = 0; i < arguments; i++) - arg_types[i] = TypeManager.int32_type; - - MethodInfo mi = mb.GetArrayMethod (type, ".ctor", CallingConventions.HasThis, null, - arg_types); - - if (mi == null) { - ec.Report.Error (-6, "New invocation: Can not find a constructor for " + - "this argument list"); - return null; - } - - return mi; - } - byte [] MakeByteBlob () { int factor; @@ -6076,9 +5982,9 @@ namespace Mono.CSharp { byte [] element; int count = array_data.Count; - Type element_type = array_element_type; + TypeSpec element_type = array_element_type; if (TypeManager.IsEnumType (element_type)) - element_type = TypeManager.GetEnumUnderlyingType (element_type); + element_type = EnumSpec.GetUnderlyingType (element_type); factor = GetTypeSize (element_type); if (factor == 0) @@ -6227,35 +6133,14 @@ namespace Mono.CSharp { var initializers = new SLE.Expression [array_data.Count]; for (var i = 0; i < initializers.Length; i++) { if (array_data [i] == null) - initializers [i] = SLE.Expression.Default (array_element_type); + initializers [i] = SLE.Expression.Default (array_element_type.GetMetaInfo ()); else initializers [i] = array_data [i].MakeExpression (ctx); } - return SLE.Expression.NewArrayInit (array_element_type, initializers); + return SLE.Expression.NewArrayInit (array_element_type.GetMetaInfo (), initializers); } #endif - - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) - { - array_element_type = storey.MutateType (array_element_type); - type = storey.MutateType (type); - if (arguments != null) { - foreach (Expression e in arguments) - e.MutateHoistedGenericType (storey); - } - - if (array_data != null) { - foreach (Expression e in array_data) { - // Don't mutate values optimized away - if (e == null) - continue; - - e.MutateHoistedGenericType (storey); - } - } - } - // // Emits the initializers for the array // @@ -6274,16 +6159,14 @@ namespace Mono.CSharp { // First, the static data // FieldBuilder fb; - ILGenerator ig = ec.ig; byte [] data = MakeByteBlob (); fb = RootContext.MakeStaticData (data); - ig.Emit (OpCodes.Dup); - ig.Emit (OpCodes.Ldtoken, fb); - ig.Emit (OpCodes.Call, - TypeManager.void_initializearray_array_fieldhandle); + ec.Emit (OpCodes.Dup); + ec.Emit (OpCodes.Ldtoken, fb); + ec.Emit (OpCodes.Call, TypeManager.void_initializearray_array_fieldhandle); } // @@ -6294,37 +6177,22 @@ namespace Mono.CSharp { // void EmitDynamicInitializers (EmitContext ec, bool emitConstants) { - ILGenerator ig = ec.ig; int dims = bounds.Count; - int [] current_pos = new int [dims]; - - MethodInfo set = null; - - if (dims != 1){ - Type [] args = new Type [dims + 1]; - - for (int j = 0; j < dims; j++) - args [j] = TypeManager.int32_type; - args [dims] = array_element_type; - - set = RootContext.ToplevelTypes.Builder.GetArrayMethod ( - type, "Set", - CallingConventions.HasThis | CallingConventions.Standard, - TypeManager.void_type, args); - } + var current_pos = new int [dims]; for (int i = 0; i < array_data.Count; i++){ - Expression e = (Expression)array_data [i]; + Expression e = array_data [i]; + var c = e as Constant; // Constant can be initialized via StaticInitializer - if (e != null && !(!emitConstants && e is Constant)) { - Type etype = e.Type; + if (c == null || (c != null && emitConstants && !c.IsDefaultInitializer (array_element_type))) { + TypeSpec etype = e.Type; - ig.Emit (OpCodes.Dup); + ec.Emit (OpCodes.Dup); for (int idx = 0; idx < dims; idx++) - IntConstant.EmitInt (ig, current_pos [idx]); + ec.EmitInt (current_pos [idx]); // // If we are dealing with a struct, get the @@ -6334,23 +6202,12 @@ namespace Mono.CSharp { (!TypeManager.IsBuiltinOrEnum (etype) || etype == TypeManager.decimal_type)) { - ig.Emit (OpCodes.Ldelema, etype); + ec.Emit (OpCodes.Ldelema, etype); } e.Emit (ec); - if (dims == 1) { - bool is_stobj, has_type_arg; - OpCode op = ArrayAccess.GetStoreOpcode (etype, out is_stobj, out has_type_arg); - if (is_stobj) - ig.Emit (OpCodes.Stobj, etype); - else if (has_type_arg) - ig.Emit (op, etype); - else - ig.Emit (op); - } else - ig.Emit (OpCodes.Call, set); - + ec.EmitArrayStore ((ArrayContainer) type); } // @@ -6358,7 +6215,7 @@ namespace Mono.CSharp { // for (int j = dims - 1; j >= 0; j--){ current_pos [j]++; - if (current_pos [j] < (int) bounds [j]) + if (current_pos [j] < bounds [j]) break; current_pos [j] = 0; } @@ -6367,8 +6224,6 @@ namespace Mono.CSharp { public override void Emit (EmitContext ec) { - ILGenerator ig = ec.ig; - if (first_emit != null) { first_emit.Emit (ec); first_emit_temp.Store (ec); @@ -6377,19 +6232,15 @@ namespace Mono.CSharp { foreach (Expression e in arguments) e.Emit (ec); - if (arguments.Count == 1) - ig.Emit (OpCodes.Newarr, TypeManager.TypeToReflectionType (array_element_type)); - else { - ig.Emit (OpCodes.Newobj, GetArrayMethod (ec, arguments.Count)); - } + ec.EmitArrayNew ((ArrayContainer) type); if (initializers == null) return; - // Emit static initializer for arrays which have contain more than 4 items and + // Emit static initializer for arrays which have contain more than 2 items and // the static initializer will initialize at least 25% of array values. // NOTE: const_initializers_count does not contain default constant values. - if (const_initializers_count >= 4 && const_initializers_count * 4 > (array_data.Count) && + if (const_initializers_count > 2 && const_initializers_count * 4 > (array_data.Count) && (TypeManager.IsPrimitiveType (array_element_type) || TypeManager.IsEnumType (array_element_type))) { EmitStaticInitializers (ec); @@ -6403,43 +6254,40 @@ namespace Mono.CSharp { first_emit_temp.Release (ec); } - public override bool GetAttributableValue (ResolveContext ec, Type value_type, out object value) + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) { - if (arguments.Count != 1) { - // ec.Report.Error (-211, Location, "attribute can not encode multi-dimensional arrays"); - return base.GetAttributableValue (ec, null, out value); + // no multi dimensional or jagged arrays + if (arguments.Count != 1 || array_element_type.IsArray) { + base.EncodeAttributeValue (rc, enc, targetType); + return; } - if (array_data == null) { - Expression arg = (Expression) arguments[0]; - object arg_value; - if (arg.GetAttributableValue (ec, arg.Type, out arg_value) && arg_value is int && (int)arg_value == 0) { - value = Array.CreateInstance (array_element_type, 0); - return true; + // No array covariance, except for array -> object + if (type != targetType) { + if (targetType != TypeManager.object_type) { + base.EncodeAttributeValue (rc, enc, targetType); + return; } - // ec.Report.Error (-212, Location, "array should be initialized when passing it to an attribute"); - return base.GetAttributableValue (ec, null, out value); + enc.Encode (type); } - - Array ret = Array.CreateInstance (array_element_type, array_data.Count); - object element_value; - for (int i = 0; i < ret.Length; ++i) - { - Expression e = (Expression)array_data [i]; - - // Is null when an initializer is optimized (value == predefined value) - if (e == null) - continue; - if (!e.GetAttributableValue (ec, array_element_type, out element_value)) { - value = null; - return false; + // Single dimensional array of 0 size + if (array_data == null) { + IntConstant ic = arguments[0] as IntConstant; + if (ic == null || !ic.IsDefaultValue) { + base.EncodeAttributeValue (rc, enc, targetType); + } else { + enc.Stream.Write (0); } - ret.SetValue (element_value, i); + + return; + } + + enc.Stream.Write ((int) array_data.Count); + foreach (var element in array_data) { + element.EncodeAttributeValue (rc, enc, array_element_type); } - value = ret; - return true; } protected override void CloneTo (CloneContext clonectx, Expression t) @@ -6450,40 +6298,29 @@ namespace Mono.CSharp { target.requested_base_type = (FullNamedExpression)requested_base_type.Clone (clonectx); if (arguments != null){ - target.arguments = new ArrayList (arguments.Count); + target.arguments = new List (arguments.Count); foreach (Expression e in arguments) target.arguments.Add (e.Clone (clonectx)); } - if (initializers != null){ - target.initializers = new ArrayList (initializers.Count); - foreach (object initializer in initializers) - if (initializer is ArrayList) { - ArrayList this_al = (ArrayList)initializer; - ArrayList al = new ArrayList (this_al.Count); - target.initializers.Add (al); - foreach (Expression e in this_al) - al.Add (e.Clone (clonectx)); - } else { - target.initializers.Add (((Expression)initializer).Clone (clonectx)); - } - } + if (initializers != null) + target.initializers = (ArrayInitializer) initializers.Clone (clonectx); } } // // Represents an implicitly typed array epxression // - public class ImplicitlyTypedArrayCreation : ArrayCreation + class ImplicitlyTypedArrayCreation : ArrayCreation { - public ImplicitlyTypedArrayCreation (string rank, ArrayList initializers, Location loc) + public ImplicitlyTypedArrayCreation (ComposedTypeSpecifier rank, ArrayInitializer initializers, Location loc) : base (null, rank, initializers, loc) { - if (rank.Length > 2) { - while (rank [++dimensions] == ','); - } else { - dimensions = 1; - } + } + + public ImplicitlyTypedArrayCreation (ArrayInitializer initializers, Location loc) + : base (null, initializers, loc) + { } protected override Expression DoResolve (ResolveContext ec) @@ -6491,13 +6328,15 @@ namespace Mono.CSharp { if (type != null) return this; + dimensions = rank.Dimension; + if (!ResolveInitializers (ec)) return null; if (array_element_type == null || array_element_type == TypeManager.null_type || array_element_type == TypeManager.void_type || array_element_type == InternalType.AnonymousMethod || array_element_type == InternalType.MethodGroup || - arguments.Count != dimensions) { + arguments.Count != rank.Dimension) { Error_NoBestType (ec); return null; } @@ -6509,7 +6348,7 @@ namespace Mono.CSharp { // UnifyInitializerElement (ec); - type = TypeManager.GetConstructedType (array_element_type, rank); + type = ArrayContainer.MakeType (array_element_type, dimensions); eclass = ExprClass.Value; return this; } @@ -6568,7 +6407,7 @@ namespace Mono.CSharp { { } - public CompilerGeneratedThis (Type type, Location loc) + public CompilerGeneratedThis (TypeSpec type, Location loc) : base (loc) { this.type = type; @@ -6580,7 +6419,6 @@ namespace Mono.CSharp { if (type == null) type = ec.CurrentType; - is_struct = type.IsValueType; return this; } @@ -6602,7 +6440,7 @@ namespace Mono.CSharp { public void Emit (EmitContext ec) { - ec.ig.Emit (OpCodes.Ldarg_0); + ec.Emit (OpCodes.Ldarg_0); } public void EmitAssign (EmitContext ec) @@ -6612,19 +6450,11 @@ namespace Mono.CSharp { public void EmitAddressOf (EmitContext ec) { - ec.ig.Emit (OpCodes.Ldarg_0); + ec.Emit (OpCodes.Ldarg_0); } } - Block block; VariableInfo variable_info; - protected bool is_struct; - - public This (Block block, Location loc) - { - this.loc = loc; - this.block = block; - } public This (Location loc) { @@ -6657,22 +6487,22 @@ namespace Mono.CSharp { } public override bool IsRef { - get { return is_struct; } + get { return type.IsStruct; } } protected override ILocalVariable Variable { get { return ThisVariable.Instance; } } - public static bool IsThisAvailable (ResolveContext ec) + public static bool IsThisAvailable (ResolveContext ec, bool ignoreAnonymous) { if (ec.IsStatic || ec.HasAny (ResolveContext.Options.FieldInitializerScope | ResolveContext.Options.BaseInitializer | ResolveContext.Options.ConstantScope)) return false; - if (ec.CurrentAnonymousMethod == null) + if (ignoreAnonymous || ec.CurrentAnonymousMethod == null) return true; - if (ec.CurrentType.IsValueType && ec.CurrentIterator == null) + if (TypeManager.IsStruct (ec.CurrentType) && ec.CurrentIterator == null) return false; return true; @@ -6683,7 +6513,7 @@ namespace Mono.CSharp { eclass = ExprClass.Variable; type = ec.CurrentType; - if (!IsThisAvailable (ec)) { + if (!IsThisAvailable (ec, false)) { if (ec.IsStatic && !ec.HasSet (ResolveContext.Options.ConstantScope)) { ec.Report.Error (26, loc, "Keyword `this' is not valid in a static property, static method, or static field initializer"); } else if (ec.CurrentAnonymousMethod != null) { @@ -6695,8 +6525,7 @@ namespace Mono.CSharp { } } - is_struct = type.IsValueType; - + var block = ec.CurrentBlock; if (block != null) { if (block.Toplevel.ThisVariable != null) variable_info = block.Toplevel.ThisVariable.VariableInfo; @@ -6761,7 +6590,7 @@ namespace Mono.CSharp { public override int GetHashCode() { - return block.GetHashCode (); + throw new NotImplementedException (); } public override string Name { @@ -6774,14 +6603,12 @@ namespace Mono.CSharp { if (t == null) return false; - return block == t.block; + return true; } protected override void CloneTo (CloneContext clonectx, Expression t) { - This target = (This) t; - - target.block = clonectx.LookupBlock (block); + // Nothing } public override void SetHasAddressTaken () @@ -6820,7 +6647,7 @@ namespace Mono.CSharp { public override void Emit (EmitContext ec) { - ec.ig.Emit (OpCodes.Arglist); + ec.Emit (OpCodes.Arglist); } protected override void CloneTo (CloneContext clonectx, Expression target) @@ -6832,7 +6659,7 @@ namespace Mono.CSharp { /// /// Represents the `__arglist (....)' construct /// - class Arglist : Expression + public class Arglist : Expression { Arguments Arguments; @@ -6850,11 +6677,11 @@ namespace Mono.CSharp { public Type[] ArgumentTypes { get { if (Arguments == null) - return Type.EmptyTypes; + return System.Type.EmptyTypes; - Type[] retval = new Type [Arguments.Count]; + var retval = new Type [Arguments.Count]; for (int i = 0; i < retval.Length; i++) - retval [i] = Arguments [i].Expr.Type; + retval[i] = Arguments[i].Expr.Type.GetMetaInfo (); return retval; } @@ -6884,12 +6711,6 @@ namespace Mono.CSharp { Arguments.Emit (ec); } - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) - { - if (Arguments != null) - Arguments.MutateHoistedGenericType (storey); - } - protected override void CloneTo (CloneContext clonectx, Expression t) { Arglist target = (Arglist) t; @@ -6903,15 +6724,30 @@ namespace Mono.CSharp { /// Implements the typeof operator /// public class TypeOf : Expression { - Expression QueriedType; - protected Type typearg; - - public TypeOf (Expression queried_type, Location l) + FullNamedExpression QueriedType; + TypeSpec typearg; + + public TypeOf (FullNamedExpression queried_type, Location l) { QueriedType = queried_type; loc = l; } + #region Properties + public TypeSpec TypeArgument { + get { + return typearg; + } + } + + public FullNamedExpression TypeExpression { + get { + return QueriedType; + } + } + + #endregion + public override Expression CreateExpressionTree (ResolveContext ec) { Arguments args = new Arguments (2); @@ -6928,7 +6764,14 @@ namespace Mono.CSharp { typearg = texpr.Type; - if (typearg == TypeManager.void_type) { + // + // Get generic type definition for unbounded type arguments + // + var tne = QueriedType as ATypeNameExpression; + if (tne != null && typearg.IsGeneric && !tne.HasTypeArguments) + typearg = typearg.GetDefinition (); + + if (typearg == TypeManager.void_type && !(QueriedType is TypeExpression)) { ec.Report.Error (673, loc, "System.Void cannot be used from C#. Use typeof (void) to get the void type object"); } else if (typearg.IsPointer && !ec.IsUnsafe){ UnsafeError (ec, loc); @@ -6955,85 +6798,71 @@ namespace Mono.CSharp { return this; } - public override void Emit (EmitContext ec) + static bool ContainsTypeParameter (TypeSpec type) { - ec.ig.Emit (OpCodes.Ldtoken, TypeManager.TypeToReflectionType (typearg)); - ec.ig.Emit (OpCodes.Call, TypeManager.system_type_get_type_from_handle); - } + if (type.Kind == MemberKind.TypeParameter) + return true; - public override bool GetAttributableValue (ResolveContext ec, Type value_type, out object value) - { - if (TypeManager.ContainsGenericParameters (typearg) && - !TypeManager.IsGenericTypeDefinition (typearg)) { - ec.Report.SymbolRelatedToPreviousError (typearg); - ec.Report.Error (416, loc, "`{0}': an attribute argument cannot use type parameters", - TypeManager.CSharpName (typearg)); - value = null; - return false; - } + var element_container = type as ElementTypeSpec; + if (element_container != null) + return ContainsTypeParameter (element_container.Element); - if (value_type == TypeManager.object_type) { - value = (object)typearg; - return true; + foreach (var t in type.TypeArguments) { + if (ContainsTypeParameter (t)) { + return true; + } } - value = typearg; - return true; + + return false; } - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) { - typearg = storey.MutateType (typearg); - } + // Target type is not System.Type therefore must be object + // and we need to use different encoding sequence + if (targetType != type) + enc.Encode (type); - public Type TypeArgument { - get { - return typearg; + if (ContainsTypeParameter (typearg)) { + rc.Compiler.Report.Error (416, loc, "`{0}': an attribute argument cannot use type parameters", + TypeManager.CSharpName (typearg)); + return; } - } - protected override void CloneTo (CloneContext clonectx, Expression t) - { - TypeOf target = (TypeOf) t; - if (QueriedType != null) - target.QueriedType = QueriedType.Clone (clonectx); + enc.EncodeTypeName (typearg); } - } - /// - /// Implements the `typeof (void)' operator - /// - public class TypeOfVoid : TypeOf { - public TypeOfVoid (Location l) : base (null, l) + public override void Emit (EmitContext ec) { - loc = l; + ec.Emit (OpCodes.Ldtoken, typearg); + ec.Emit (OpCodes.Call, TypeManager.system_type_get_type_from_handle); } - protected override Expression DoResolve (ResolveContext ec) + protected override void CloneTo (CloneContext clonectx, Expression t) { - type = TypeManager.type_type; - typearg = TypeManager.void_type; - - return DoResolveBase (); + TypeOf target = (TypeOf) t; + if (QueriedType != null) + target.QueriedType = (FullNamedExpression) QueriedType.Clone (clonectx); } } - class TypeOfMethod : TypeOfMember + class TypeOfMethod : TypeOfMember { - public TypeOfMethod (MethodBase method, Location loc) + public TypeOfMethod (MethodSpec method, Location loc) : base (method, loc) { } protected override Expression DoResolve (ResolveContext ec) { - if (member is MethodInfo) { - type = TypeManager.methodinfo_type; + if (member.IsConstructor) { + type = TypeManager.ctorinfo_type; if (type == null) - type = TypeManager.methodinfo_type = TypeManager.CoreLookupType (ec.Compiler, "System.Reflection", "MethodInfo", Kind.Class, true); + type = TypeManager.ctorinfo_type = TypeManager.CoreLookupType (ec.Compiler, "System.Reflection", "ConstructorInfo", MemberKind.Class, true); } else { - type = TypeManager.ctorinfo_type; + type = TypeManager.methodinfo_type; if (type == null) - type = TypeManager.ctorinfo_type = TypeManager.CoreLookupType (ec.Compiler, "System.Reflection", "ConstructorInfo", Kind.Class, true); + type = TypeManager.methodinfo_type = TypeManager.CoreLookupType (ec.Compiler, "System.Reflection", "MethodInfo", MemberKind.Class, true); } return base.DoResolve (ec); @@ -7041,13 +6870,10 @@ namespace Mono.CSharp { public override void Emit (EmitContext ec) { - if (member is ConstructorInfo) - ec.ig.Emit (OpCodes.Ldtoken, (ConstructorInfo) member); - else - ec.ig.Emit (OpCodes.Ldtoken, (MethodInfo) member); + ec.Emit (OpCodes.Ldtoken, member); base.Emit (ec); - ec.ig.Emit (OpCodes.Castclass, type); + ec.Emit (OpCodes.Castclass, type); } protected override string GetMethodName { @@ -7058,7 +6884,7 @@ namespace Mono.CSharp { get { return "RuntimeMethodHandle"; } } - protected override MethodInfo TypeFromHandle { + protected override MethodSpec TypeFromHandle { get { return TypeManager.methodbase_get_type_from_handle; } @@ -7067,7 +6893,7 @@ namespace Mono.CSharp { } } - protected override MethodInfo TypeFromHandleGeneric { + protected override MethodSpec TypeFromHandleGeneric { get { return TypeManager.methodbase_get_type_from_handle_generic; } @@ -7081,11 +6907,11 @@ namespace Mono.CSharp { } } - abstract class TypeOfMember : Expression + abstract class TypeOfMember : Expression where T : MemberSpec { - protected readonly MemberInfo member; + protected readonly T member; - protected TypeOfMember (MemberInfo member, Location loc) + protected TypeOfMember (T member, Location loc) { this.member = member; this.loc = loc; @@ -7101,20 +6927,20 @@ namespace Mono.CSharp { protected override Expression DoResolve (ResolveContext ec) { - bool is_generic = TypeManager.IsGenericType (member.DeclaringType); - MethodInfo mi = is_generic ? TypeFromHandleGeneric : TypeFromHandle; + bool is_generic = member.DeclaringType.IsGenericOrParentIsGeneric; + var mi = is_generic ? TypeFromHandleGeneric : TypeFromHandle; if (mi == null) { - Type t = TypeManager.CoreLookupType (ec.Compiler, "System.Reflection", TypeName, Kind.Class, true); - Type handle_type = TypeManager.CoreLookupType (ec.Compiler, "System", RuntimeHandleName, Kind.Class, true); + TypeSpec t = TypeManager.CoreLookupType (ec.Compiler, "System.Reflection", TypeName, MemberKind.Class, true); + TypeSpec handle_type = TypeManager.CoreLookupType (ec.Compiler, "System", RuntimeHandleName, MemberKind.Struct, true); if (t == null || handle_type == null) return null; mi = TypeManager.GetPredefinedMethod (t, GetMethodName, loc, is_generic ? - new Type[] { handle_type, TypeManager.runtime_handle_type } : - new Type[] { handle_type } ); + new TypeSpec[] { handle_type, TypeManager.runtime_handle_type } : + new TypeSpec[] { handle_type } ); if (is_generic) TypeFromHandleGeneric = mi; @@ -7128,28 +6954,28 @@ namespace Mono.CSharp { public override void Emit (EmitContext ec) { - bool is_generic = TypeManager.IsGenericType (member.DeclaringType); - MethodInfo mi; + bool is_generic = member.DeclaringType.IsGenericOrParentIsGeneric; + MethodSpec mi; if (is_generic) { mi = TypeFromHandleGeneric; - ec.ig.Emit (OpCodes.Ldtoken, member.DeclaringType); + ec.Emit (OpCodes.Ldtoken, member.DeclaringType); } else { mi = TypeFromHandle; } - ec.ig.Emit (OpCodes.Call, mi); + ec.Emit (OpCodes.Call, mi); } protected abstract string GetMethodName { get; } protected abstract string RuntimeHandleName { get; } - protected abstract MethodInfo TypeFromHandle { get; set; } - protected abstract MethodInfo TypeFromHandleGeneric { get; set; } + protected abstract MethodSpec TypeFromHandle { get; set; } + protected abstract MethodSpec TypeFromHandleGeneric { get; set; } protected abstract string TypeName { get; } } - class TypeOfField : TypeOfMember + class TypeOfField : TypeOfMember { - public TypeOfField (FieldInfo field, Location loc) + public TypeOfField (FieldSpec field, Location loc) : base (field, loc) { } @@ -7157,7 +6983,7 @@ namespace Mono.CSharp { protected override Expression DoResolve (ResolveContext ec) { if (TypeManager.fieldinfo_type == null) - TypeManager.fieldinfo_type = TypeManager.CoreLookupType (ec.Compiler, "System.Reflection", TypeName, Kind.Class, true); + TypeManager.fieldinfo_type = TypeManager.CoreLookupType (ec.Compiler, "System.Reflection", TypeName, MemberKind.Class, true); type = TypeManager.fieldinfo_type; return base.DoResolve (ec); @@ -7165,7 +6991,7 @@ namespace Mono.CSharp { public override void Emit (EmitContext ec) { - ec.ig.Emit (OpCodes.Ldtoken, (FieldInfo) member); + ec.Emit (OpCodes.Ldtoken, member); base.Emit (ec); } @@ -7177,7 +7003,7 @@ namespace Mono.CSharp { get { return "RuntimeFieldHandle"; } } - protected override MethodInfo TypeFromHandle { + protected override MethodSpec TypeFromHandle { get { return TypeManager.fieldinfo_get_field_from_handle; } @@ -7186,7 +7012,7 @@ namespace Mono.CSharp { } } - protected override MethodInfo TypeFromHandleGeneric { + protected override MethodSpec TypeFromHandleGeneric { get { return TypeManager.fieldinfo_get_field_from_handle_generic; } @@ -7205,7 +7031,7 @@ namespace Mono.CSharp { /// public class SizeOf : Expression { readonly Expression QueriedType; - Type type_queried; + TypeSpec type_queried; public SizeOf (Expression queried_type, Location l) { @@ -7227,7 +7053,7 @@ namespace Mono.CSharp { type_queried = texpr.Type; if (TypeManager.IsEnumType (type_queried)) - type_queried = TypeManager.GetEnumUnderlyingType (type_queried); + type_queried = EnumSpec.GetUnderlyingType (type_queried); int size_of = GetTypeSize (type_queried); if (size_of > 0) { @@ -7251,7 +7077,7 @@ namespace Mono.CSharp { public override void Emit (EmitContext ec) { - ec.ig.Emit (OpCodes.Sizeof, type_queried); + ec.Emit (OpCodes.Sizeof, type_queried); } protected override void CloneTo (CloneContext clonectx, Expression t) @@ -7267,14 +7093,20 @@ namespace Mono.CSharp { readonly string alias; public static readonly string GlobalAlias = "global"; + public QualifiedAliasMember (string alias, string identifier, Location l) + : base (null, identifier, l) + { + this.alias = alias; + } + public QualifiedAliasMember (string alias, string identifier, TypeArguments targs, Location l) : base (null, identifier, targs, l) { this.alias = alias; } - public QualifiedAliasMember (string alias, string identifier, Location l) - : base (null, identifier, l) + public QualifiedAliasMember (string alias, string identifier, int arity, Location l) + : base (null, identifier, arity, l) { this.alias = alias; } @@ -7314,7 +7146,7 @@ namespace Mono.CSharp { return ResolveAsTypeStep (ec, false); } - protected override void Error_IdentifierNotFound (IMemberContext rc, FullNamedExpression expr_type, string identifier) + protected override void Error_IdentifierNotFound (IMemberContext rc, TypeSpec expr_type, string identifier) { rc.Compiler.Report.Error (687, loc, "A namespace alias qualifier `{0}' did not resolve to a namespace or a type", @@ -7325,8 +7157,7 @@ namespace Mono.CSharp { { string name = Name; if (targs != null) { - name = TypeManager.RemoveGenericArity (Name) + "<" + - targs.GetSignatureForError () + ">"; + name = Name + "<" + targs.GetSignatureForError () + ">"; } return alias + "::" + name; @@ -7362,6 +7193,12 @@ namespace Mono.CSharp { this.expr = expr; } + public MemberAccess (Expression expr, string identifier, int arity, Location loc) + : base (identifier, arity, loc) + { + this.expr = expr; + } + Expression DoResolve (ResolveContext ec, Expression right_side) { if (type != null) @@ -7376,29 +7213,45 @@ namespace Mono.CSharp { SimpleName original = expr as SimpleName; Expression expr_resolved; + const ResolveFlags flags = ResolveFlags.VariableOrValue | ResolveFlags.Type; + using (ec.Set (ResolveContext.Options.OmitStructFlowAnalysis)) { - expr_resolved = expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.Type | ResolveFlags.Intermediate); + if (original != null) { + expr_resolved = original.DoResolve (ec, true); + if (expr_resolved != null) { + // Ugly, simulate skipped Resolve + if (expr_resolved is ConstantExpr) { + expr_resolved = expr_resolved.Resolve (ec); + } else if (expr_resolved is FieldExpr || expr_resolved is PropertyExpr) { + // nothing yet + } else if ((flags & expr_resolved.ExprClassToResolveFlags) == 0) { + expr_resolved.Error_UnexpectedKind (ec, flags, expr.Location); + expr_resolved = null; + } + } + } else { + expr_resolved = expr.Resolve (ec, flags); + } } if (expr_resolved == null) return null; - string LookupIdentifier = MemberName.MakeName (Name, targs); - Namespace ns = expr_resolved as Namespace; if (ns != null) { - FullNamedExpression retval = ns.Lookup (ec.Compiler, LookupIdentifier, loc); + FullNamedExpression retval = ns.Lookup (ec.Compiler, Name, Arity, loc); if (retval == null) - ns.Error_NamespaceDoesNotExist (loc, LookupIdentifier, ec); - else if (targs != null) + ns.Error_NamespaceDoesNotExist (loc, Name, Arity, ec); + else if (HasTypeArguments) retval = new GenericTypeExpr (retval.Type, targs, loc).ResolveAsTypeStep (ec, false); + expr = expr_resolved; return retval; } - Type expr_type = expr_resolved.Type; - if (TypeManager.IsDynamicType (expr_type)) { + TypeSpec expr_type = expr_resolved.Type; + if (expr_type == InternalType.Dynamic) { Arguments args = new Arguments (1); args.Add (new Argument (expr_resolved.Resolve (ec))); expr = new DynamicMemberBinder (Name, args, loc); @@ -7408,34 +7261,24 @@ namespace Mono.CSharp { return expr.Resolve (ec); } - if (expr_type.IsPointer || expr_type == TypeManager.void_type || - expr_type == TypeManager.null_type || expr_type == InternalType.AnonymousMethod) { - Unary.Error_OperatorCannotBeApplied (ec, loc, ".", expr_type); - return null; - } - Constant c = expr_resolved as Constant; - if (c != null && c.GetValue () == null) { - ec.Report.Warning (1720, 1, loc, "Expression will always cause a `{0}'", - "System.NullReferenceException"); - } + const MemberKind dot_kinds = MemberKind.Class | MemberKind.Struct | MemberKind.Delegate | MemberKind.Enum | + MemberKind.Interface | MemberKind.TypeParameter | MemberKind.ArrayType; - if (targs != null) { - if (!targs.Resolve (ec)) - return null; + if ((expr_type.Kind & dot_kinds) == 0 || expr_type == TypeManager.void_type) { + Unary.Error_OperatorCannotBeApplied (ec, loc, ".", expr_type); + return null; } - Expression member_lookup; - member_lookup = MemberLookup (ec.Compiler, - ec.CurrentType, expr_type, expr_type, Name, loc); + var arity = HasTypeArguments ? targs.Count : -1; - if (member_lookup == null && targs != null) { - member_lookup = MemberLookup (ec.Compiler, - ec.CurrentType, expr_type, expr_type, LookupIdentifier, loc); - } + var member_lookup = MemberLookup (ec.Compiler, + ec.CurrentType, expr_type, expr_type, Name, arity, BindingRestriction.NoOverrides, loc); if (member_lookup == null) { - ExprClass expr_eclass = expr_resolved.eclass; + expr = expr_resolved.Resolve (ec); + + ExprClass expr_eclass = expr.eclass; // // Extension methods are not allowed on all expression types @@ -7443,11 +7286,14 @@ namespace Mono.CSharp { if (expr_eclass == ExprClass.Value || expr_eclass == ExprClass.Variable || expr_eclass == ExprClass.IndexerAccess || expr_eclass == ExprClass.PropertyAccess || expr_eclass == ExprClass.EventAccess) { - ExtensionMethodGroupExpr ex_method_lookup = ec.LookupExtensionMethod (expr_type, Name, loc); + ExtensionMethodGroupExpr ex_method_lookup = ec.LookupExtensionMethod (expr_type, Name, arity, loc); if (ex_method_lookup != null) { - ex_method_lookup.ExtensionExpression = expr_resolved; + ex_method_lookup.ExtensionExpression = expr; + + if (HasTypeArguments) { + if (!targs.Resolve (ec)) + return null; - if (targs != null) { ex_method_lookup.SetTypeArguments (ec, targs); } @@ -7455,21 +7301,25 @@ namespace Mono.CSharp { } } - expr = expr_resolved; member_lookup = Error_MemberLookupFailed (ec, - ec.CurrentType, expr_type, expr_type, Name, null, - AllMemberTypes, AllBindingFlags); + ec.CurrentType, expr_type, expr_type, Name, arity, null, + MemberKind.All, BindingRestriction.AccessibleOnly); if (member_lookup == null) return null; } + expr = expr_resolved; + + MemberExpr me; TypeExpr texpr = member_lookup as TypeExpr; if (texpr != null) { - if (!(expr_resolved is TypeExpr) && - (original == null || !original.IdenticalNameAndTypeName (ec, expr_resolved, loc))) { - ec.Report.Error (572, loc, "`{0}': cannot reference a type through an expression; try `{1}' instead", - Name, member_lookup.GetSignatureForError ()); - return null; + if (!(expr_resolved is TypeExpr)) { + me = expr_resolved as MemberExpr; + if (me == null || me.ProbeIdenticalTypeName (ec, expr_resolved, original) == expr_resolved) { + ec.Report.Error (572, loc, "`{0}': cannot reference a type through an expression; try `{1}' instead", + Name, member_lookup.GetSignatureForError ()); + return null; + } } if (!texpr.CheckAccessLevel (ec.MemberContext)) { @@ -7478,38 +7328,25 @@ namespace Mono.CSharp { return null; } - GenericTypeExpr ct = expr_resolved as GenericTypeExpr; - if (ct != null) { - // - // When looking up a nested type in a generic instance - // via reflection, we always get a generic type definition - // and not a generic instance - so we have to do this here. - // - // See gtest-172-lib.cs and gtest-172.cs for an example. - // - - TypeArguments nested_targs; - if (HasTypeArguments) { - nested_targs = ct.TypeArguments.Clone (); - nested_targs.Add (targs); - } else { - nested_targs = ct.TypeArguments; - } - - ct = new GenericTypeExpr (member_lookup.Type, nested_targs, loc); - + if (HasTypeArguments) { + var ct = new GenericTypeExpr (member_lookup.Type, targs, loc); return ct.ResolveAsTypeStep (ec, false); } return member_lookup; } - MemberExpr me = (MemberExpr) member_lookup; - me = me.ResolveMemberAccess (ec, expr_resolved, loc, original); - if (me == null) - return null; + me = (MemberExpr) member_lookup; + + if (original != null && me.IsStatic) + expr_resolved = me.ProbeIdenticalTypeName (ec, expr_resolved, original); + + me = me.ResolveMemberAccess (ec, expr_resolved, original); + + if (HasTypeArguments) { + if (!targs.Resolve (ec)) + return null; - if (targs != null) { me.SetTypeArguments (ec, targs); } @@ -7552,16 +7389,16 @@ namespace Mono.CSharp { if (expr_resolved == null) return null; - string LookupIdentifier = MemberName.MakeName (Name, targs); - Namespace ns = expr_resolved as Namespace; if (ns != null) { - FullNamedExpression retval = ns.Lookup (rc.Compiler, LookupIdentifier, loc); + FullNamedExpression retval = ns.Lookup (rc.Compiler, Name, Arity, loc); - if (retval == null && !silent) - ns.Error_NamespaceDoesNotExist (loc, LookupIdentifier, rc); - else if (targs != null) + if (retval == null) { + if (!silent) + ns.Error_NamespaceDoesNotExist (loc, Name, Arity, rc); + } else if (HasTypeArguments) { retval = new GenericTypeExpr (retval.Type, targs, loc).ResolveAsTypeStep (rc, silent); + } return retval; } @@ -7570,71 +7407,49 @@ namespace Mono.CSharp { if (tnew_expr == null) return null; - Type expr_type = tnew_expr.Type; + TypeSpec expr_type = tnew_expr.Type; if (TypeManager.IsGenericParameter (expr_type)) { rc.Compiler.Report.Error (704, loc, "A nested type cannot be specified through a type parameter `{0}'", tnew_expr.GetSignatureForError ()); return null; } - Expression member_lookup = MemberLookup (rc.Compiler, - rc.CurrentType, expr_type, expr_type, LookupIdentifier, - MemberTypes.NestedType, BindingFlags.Public | BindingFlags.NonPublic, loc); - if (member_lookup == null) { + var nested = MemberCache.FindNestedType (expr_type, Name, Arity); + if (nested == null) { if (silent) return null; - Error_IdentifierNotFound (rc, expr_resolved, LookupIdentifier); + Error_IdentifierNotFound (rc, expr_type, Name); return null; } - TypeExpr texpr = member_lookup.ResolveAsTypeTerminal (rc, false); - if (texpr == null) - return null; - - TypeArguments the_args = targs; - Type declaring_type = texpr.Type.DeclaringType; - if (TypeManager.HasGenericArguments (declaring_type) && !TypeManager.IsGenericTypeDefinition (expr_type)) { - while (!TypeManager.IsEqual (TypeManager.DropGenericTypeArguments (expr_type), declaring_type)) { - expr_type = expr_type.BaseType; - } - - TypeArguments new_args = new TypeArguments (); - foreach (Type decl in TypeManager.GetTypeArguments (expr_type)) - new_args.Add (new TypeExpression (TypeManager.TypeToCoreType (decl), loc)); - - if (targs != null) - new_args.Add (targs); - - the_args = new_args; + bool extra_check; + if (!IsMemberAccessible (rc.CurrentType ?? InternalType.FakeInternalType, nested, out extra_check)) { + ErrorIsInaccesible (loc, nested.GetSignatureForError (), rc.Compiler.Report); } - - if (the_args != null) { - GenericTypeExpr ctype = new GenericTypeExpr (texpr.Type, the_args, loc); - return ctype.ResolveAsTypeStep (rc, false); + + TypeExpr texpr; + if (HasTypeArguments) { + texpr = new GenericTypeExpr (nested, targs, loc); + } else { + texpr = new TypeExpression (nested, loc); } - return texpr; + return texpr.ResolveAsTypeStep (rc, false); } - protected virtual void Error_IdentifierNotFound (IMemberContext rc, FullNamedExpression expr_type, string identifier) + protected virtual void Error_IdentifierNotFound (IMemberContext rc, TypeSpec expr_type, string identifier) { - Expression member_lookup = MemberLookup (rc.Compiler, - rc.CurrentType, expr_type.Type, expr_type.Type, SimpleName.RemoveGenericArity (identifier), - MemberTypes.NestedType, BindingFlags.Public | BindingFlags.NonPublic, loc); + var nested = MemberCache.FindNestedType (expr_type, Name, -System.Math.Max (1, Arity)); - if (member_lookup != null) { - expr_type = member_lookup.ResolveAsTypeTerminal (rc, false); - if (expr_type == null) - return; - - expr_type.Error_TypeArgumentsCannotBeUsed (rc.Compiler.Report, loc); + if (nested != null) { + Error_TypeArgumentsCannotBeUsed (rc.Compiler.Report, expr.Location, nested, Arity); return; } - member_lookup = MemberLookup (rc.Compiler, - rc.CurrentType, expr_type.Type, expr_type.Type, identifier, - MemberTypes.All, BindingFlags.Public | BindingFlags.NonPublic, loc); + var member_lookup = MemberLookup (rc.Compiler, + rc.CurrentType, expr_type, expr_type, identifier, -1, + MemberKind.All, BindingRestriction.None, loc); if (member_lookup == null) { rc.Compiler.Report.Error (426, loc, "The nested type `{0}' does not exist in the type `{1}'", @@ -7645,7 +7460,7 @@ namespace Mono.CSharp { } } - protected override void Error_TypeDoesNotContainDefinition (ResolveContext ec, Type type, string name) + protected override void Error_TypeDoesNotContainDefinition (ResolveContext ec, TypeSpec type, string name) { if (RootContext.Version > LanguageVersion.ISO_2 && !ec.Compiler.IsRuntimeBinder && ((expr.eclass & (ExprClass.Value | ExprClass.Variable)) != 0)) { @@ -7725,19 +7540,12 @@ namespace Mono.CSharp { Expr.EmitBranchable (ec, target, on_true); } -#if NET_4_0 public override SLE.Expression MakeExpression (BuilderContext ctx) { using (ctx.With (BuilderContext.Options.AllCheckStateFlags, true)) { return Expr.MakeExpression (ctx); } } -#endif - - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) - { - Expr.MutateHoistedGenericType (storey); - } protected override void CloneTo (CloneContext clonectx, Expression t) { @@ -7794,11 +7602,6 @@ namespace Mono.CSharp { Expr.EmitBranchable (ec, target, on_true); } - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) - { - Expr.MutateHoistedGenericType (storey); - } - protected override void CloneTo (CloneContext clonectx, Expression t) { UnCheckedExpr target = (UnCheckedExpr) t; @@ -7817,10 +7620,10 @@ namespace Mono.CSharp { public Arguments Arguments; public Expression Expr; - public ElementAccess (Expression e, Arguments args) + public ElementAccess (Expression e, Arguments args, Location loc) { Expr = e; - loc = e.Location; + this.loc = loc; this.Arguments = args; } @@ -7832,7 +7635,7 @@ namespace Mono.CSharp { return CreateExpressionFactoryCall (ec, "ArrayIndex", args); } - Expression MakePointerAccess (ResolveContext ec, Type t) + Expression MakePointerAccess (ResolveContext ec, TypeSpec t) { if (Arguments.Count != 1){ ec.Report.Error (196, loc, "A pointer must be indexed by only one value"); @@ -7858,7 +7661,7 @@ namespace Mono.CSharp { // // I am experimenting with this pattern. // - Type t = Expr.Type; + TypeSpec t = Expr.Type; if (t == TypeManager.array_type){ ec.Report.Error (21, loc, "Cannot apply indexing with [] to an expression of type `System.Array'"); @@ -7872,7 +7675,7 @@ namespace Mono.CSharp { FieldExpr fe = Expr as FieldExpr; if (fe != null) { - IFixedBuffer ff = AttributeTester.GetFixedBuffer (fe.FieldInfo); + var ff = fe.Spec as FixedFieldSpec; if (ff != null) { return MakePointerAccess (ec, ff.ElementType); } @@ -7906,7 +7709,7 @@ namespace Mono.CSharp { public static void Error_NamedArgument (NamedArgument na, Report Report) { - Report.Error (1742, na.Name.Location, "An element access expression cannot use named argument"); + Report.Error (1742, na.Location, "An element access expression cannot use named argument"); } public override string GetSignatureForError () @@ -7959,15 +7762,15 @@ namespace Mono.CSharp { bool dynamic; ea.Arguments.Resolve (ec, out dynamic); - Type t = ea.Expr.Type; + var ac = ea.Expr.Type as ArrayContainer; int rank = ea.Arguments.Count; - if (t.GetArrayRank () != rank) { + if (ac.Rank != rank) { ec.Report.Error (22, ea.Location, "Wrong number of indexes `{0}' inside [], expected `{1}'", - ea.Arguments.Count.ToString (), t.GetArrayRank ().ToString ()); + rank.ToString (), ac.Rank.ToString ()); return null; } - type = TypeManager.GetElementType (t); + type = ac.Element; if (type.IsPointer && !ec.IsUnsafe) { UnsafeError (ec, ea.Location); } @@ -7984,144 +7787,11 @@ namespace Mono.CSharp { return this; } - /// - /// Emits the right opcode to load an object of Type `t' - /// from an array of T - /// - void EmitLoadOpcode (ILGenerator ig, Type type, int rank) - { - if (rank > 1) { - MethodInfo get = FetchGetMethod (); - ig.Emit (OpCodes.Call, get); - return; - } - - if (type == TypeManager.byte_type || type == TypeManager.bool_type) - ig.Emit (OpCodes.Ldelem_U1); - else if (type == TypeManager.sbyte_type) - ig.Emit (OpCodes.Ldelem_I1); - else if (type == TypeManager.short_type) - ig.Emit (OpCodes.Ldelem_I2); - else if (type == TypeManager.ushort_type || type == TypeManager.char_type) - ig.Emit (OpCodes.Ldelem_U2); - else if (type == TypeManager.int32_type) - ig.Emit (OpCodes.Ldelem_I4); - else if (type == TypeManager.uint32_type) - ig.Emit (OpCodes.Ldelem_U4); - else if (type == TypeManager.uint64_type) - ig.Emit (OpCodes.Ldelem_I8); - else if (type == TypeManager.int64_type) - ig.Emit (OpCodes.Ldelem_I8); - else if (type == TypeManager.float_type) - ig.Emit (OpCodes.Ldelem_R4); - else if (type == TypeManager.double_type) - ig.Emit (OpCodes.Ldelem_R8); - else if (type == TypeManager.intptr_type) - ig.Emit (OpCodes.Ldelem_I); - else if (TypeManager.IsEnumType (type)){ - EmitLoadOpcode (ig, TypeManager.GetEnumUnderlyingType (type), rank); - } else if (TypeManager.IsStruct (type)){ - ig.Emit (OpCodes.Ldelema, type); - ig.Emit (OpCodes.Ldobj, type); - } else if (type.IsGenericParameter) { - ig.Emit (OpCodes.Ldelem, type); - } else if (type.IsPointer) - ig.Emit (OpCodes.Ldelem_I); - else - ig.Emit (OpCodes.Ldelem_Ref); - } - protected override void Error_NegativeArrayIndex (ResolveContext ec, Location loc) { ec.Report.Warning (251, 2, loc, "Indexing an array with a negative index (array indices always start at zero)"); } - /// - /// Returns the right opcode to store an object of Type `t' - /// from an array of T. - /// - static public OpCode GetStoreOpcode (Type t, out bool is_stobj, out bool has_type_arg) - { - has_type_arg = false; is_stobj = false; - t = TypeManager.TypeToCoreType (t); - if (TypeManager.IsEnumType (t)) - t = TypeManager.GetEnumUnderlyingType (t); - if (t == TypeManager.byte_type || t == TypeManager.sbyte_type || - t == TypeManager.bool_type) - return OpCodes.Stelem_I1; - else if (t == TypeManager.short_type || t == TypeManager.ushort_type || - t == TypeManager.char_type) - return OpCodes.Stelem_I2; - else if (t == TypeManager.int32_type || t == TypeManager.uint32_type) - return OpCodes.Stelem_I4; - else if (t == TypeManager.int64_type || t == TypeManager.uint64_type) - return OpCodes.Stelem_I8; - else if (t == TypeManager.float_type) - return OpCodes.Stelem_R4; - else if (t == TypeManager.double_type) - return OpCodes.Stelem_R8; - else if (t == TypeManager.intptr_type) { - has_type_arg = true; - is_stobj = true; - return OpCodes.Stobj; - } else if (TypeManager.IsStruct (t)) { - has_type_arg = true; - is_stobj = true; - return OpCodes.Stobj; - } else if (t.IsGenericParameter) { - has_type_arg = true; - return OpCodes.Stelem; - } else if (t.IsPointer) - return OpCodes.Stelem_I; - else - return OpCodes.Stelem_Ref; - } - - MethodInfo FetchGetMethod () - { - ModuleBuilder mb = RootContext.ToplevelTypes.Builder; - int arg_count = ea.Arguments.Count; - Type [] args = new Type [arg_count]; - MethodInfo get; - - for (int i = 0; i < arg_count; i++){ - //args [i++] = a.Type; - args [i] = TypeManager.int32_type; - } - - get = mb.GetArrayMethod ( - ea.Expr.Type, "Get", - CallingConventions.HasThis | - CallingConventions.Standard, - type, args); - return get; - } - - - MethodInfo FetchAddressMethod () - { - ModuleBuilder mb = RootContext.ToplevelTypes.Builder; - int arg_count = ea.Arguments.Count; - Type [] args = new Type [arg_count]; - MethodInfo address; - Type ret_type; - - ret_type = TypeManager.GetReferenceType (type); - - for (int i = 0; i < arg_count; i++){ - //args [i++] = a.Type; - args [i] = TypeManager.int32_type; - } - - address = mb.GetArrayMethod ( - ea.Expr.Type, "Address", - CallingConventions.HasThis | - CallingConventions.Standard, - ret_type, args); - - return address; - } - // // Load the array arguments into the stack. // @@ -8136,18 +7806,17 @@ namespace Mono.CSharp { public void Emit (EmitContext ec, bool leave_copy) { - int rank = ea.Expr.Type.GetArrayRank (); - ILGenerator ig = ec.ig; + var ac = ea.Expr.Type as ArrayContainer; if (prepared) { - LoadFromPtr (ig, this.type); + ec.EmitLoadFromPtr (type); } else { LoadArrayAndArguments (ec); - EmitLoadOpcode (ig, type, rank); + ec.EmitArrayLoad (ac); } if (leave_copy) { - ig.Emit (OpCodes.Dup); + ec.Emit (OpCodes.Dup); temp = new LocalTemporary (this.type); temp.Store (ec); } @@ -8160,74 +7829,43 @@ namespace Mono.CSharp { public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) { - int rank = ea.Expr.Type.GetArrayRank (); - ILGenerator ig = ec.ig; - Type t = source.Type; + var ac = (ArrayContainer) ea.Expr.Type; + TypeSpec t = source.Type; prepared = prepare_for_load; if (prepared) { AddressOf (ec, AddressOp.LoadStore); - ec.ig.Emit (OpCodes.Dup); + ec.Emit (OpCodes.Dup); } else { LoadArrayAndArguments (ec); - } - if (rank == 1) { - bool is_stobj, has_type_arg; - OpCode op = GetStoreOpcode (t, out is_stobj, out has_type_arg); + // + // If we are dealing with a struct, get the + // address of it, so we can store it. + // + // The stobj opcode used by value types will need + // an address on the stack, not really an array/array + // pair + // + if (ac.Rank == 1 && TypeManager.IsStruct (t) && + (!TypeManager.IsBuiltinOrEnum (t) || + t == TypeManager.decimal_type)) { - if (!prepared) { - // - // The stobj opcode used by value types will need - // an address on the stack, not really an array/array - // pair - // - if (is_stobj) - ig.Emit (OpCodes.Ldelema, t); - } - - source.Emit (ec); - if (leave_copy) { - ec.ig.Emit (OpCodes.Dup); - temp = new LocalTemporary (this.type); - temp.Store (ec); - } - - if (prepared) - StoreFromPtr (ig, t); - else if (is_stobj) - ig.Emit (OpCodes.Stobj, t); - else if (has_type_arg) - ig.Emit (op, t); - else - ig.Emit (op); - } else { - source.Emit (ec); - if (leave_copy) { - ec.ig.Emit (OpCodes.Dup); - temp = new LocalTemporary (this.type); - temp.Store (ec); + ec.Emit (OpCodes.Ldelema, t); } + } - if (prepared) { - StoreFromPtr (ig, t); - } else { - int arg_count = ea.Arguments.Count; - Type [] args = new Type [arg_count + 1]; - for (int i = 0; i < arg_count; i++) { - //args [i++] = a.Type; - args [i] = TypeManager.int32_type; - } - args [arg_count] = type; - - MethodInfo set = RootContext.ToplevelTypes.Builder.GetArrayMethod ( - ea.Expr.Type, "Set", - CallingConventions.HasThis | - CallingConventions.Standard, - TypeManager.void_type, args); + source.Emit (ec); + if (leave_copy) { + ec.Emit (OpCodes.Dup); + temp = new LocalTemporary (this.type); + temp.Store (ec); + } - ig.Emit (OpCodes.Call, set); - } + if (prepared) { + ec.EmitStoreFromPtr (t); + } else { + ec.EmitArrayStore (ac); } if (temp != null) { @@ -8250,17 +7888,10 @@ namespace Mono.CSharp { public void AddressOf (EmitContext ec, AddressOp mode) { - int rank = ea.Expr.Type.GetArrayRank (); - ILGenerator ig = ec.ig; + var ac = (ArrayContainer) ea.Expr.Type; LoadArrayAndArguments (ec); - - if (rank == 1){ - ig.Emit (OpCodes.Ldelema, type); - } else { - MethodInfo address = FetchAddressMethod (); - ig.Emit (OpCodes.Call, address); - } + ec.EmitArrayAddress (ac); } #if NET_4_0 @@ -8270,6 +7901,7 @@ namespace Mono.CSharp { ea.Expr.MakeExpression (ctx), Arguments.MakeExpression (ea.Arguments, ctx)); } +#endif public override SLE.Expression MakeExpression (BuilderContext ctx) { @@ -8277,13 +7909,6 @@ namespace Mono.CSharp { ea.Expr.MakeExpression (ctx), Arguments.MakeExpression (ea.Arguments, ctx)); } -#endif - - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) - { - type = storey.MutateType (type); - ea.Expr.Type = storey.MutateType (ea.Expr.Type); - } } /// @@ -8293,10 +7918,39 @@ namespace Mono.CSharp { { class IndexerMethodGroupExpr : MethodGroupExpr { - public IndexerMethodGroupExpr (Indexers indexers, Location loc) - : base (null, loc) + IEnumerable candidates; + + public IndexerMethodGroupExpr (IEnumerable indexers, Location loc) + : base (FilterAccessors (indexers).ToList (), null, loc) { - Methods = (MethodBase []) indexers.Methods.ToArray (typeof (MethodBase)); + candidates = indexers; + } + + public IndexerSpec BestIndexer () + { + return MemberCache.FindIndexers (BestCandidate.DeclaringType, BindingRestriction.None). + Where (l => + (l.HasGet && l.Get.MemberDefinition == BestCandidate.MemberDefinition) || + (l.HasSet && l.Set.MemberDefinition == BestCandidate.MemberDefinition)).First (); + } + + static IEnumerable FilterAccessors (IEnumerable indexers) + { + foreach (IndexerSpec i in indexers) { + if (i.HasGet) + yield return i.Get; + else + yield return i.Set; + } + } + + protected override IList GetBaseTypeMethods (ResolveContext rc, TypeSpec type) + { + candidates = GetIndexersForType (type); + if (candidates == null) + return null; + + return FilterAccessors (candidates).ToList (); } public override string Name { @@ -8305,7 +7959,7 @@ namespace Mono.CSharp { } } - protected override int GetApplicableParametersCount (MethodBase method, AParametersCollection parameters) + protected override int GetApplicableParametersCount (MethodSpec method, AParametersCollection parameters) { // // Here is the trick, decrease number of arguments by 1 when only @@ -8320,100 +7974,18 @@ namespace Mono.CSharp { } } - class Indexers - { - // Contains either property getter or setter - public ArrayList Methods; - public ArrayList Properties; - - Indexers () - { - } - - void Append (Type caller_type, MemberInfo [] mi) - { - if (mi == null) - return; - - foreach (PropertyInfo property in mi) { - MethodInfo accessor = property.GetGetMethod (true); - if (accessor == null) - accessor = property.GetSetMethod (true); - - if (Methods == null) { - Methods = new ArrayList (); - Properties = new ArrayList (); - } - - Methods.Add (accessor); - Properties.Add (property); - } - } - - static MemberInfo [] GetIndexersForTypeOrInterface (Type caller_type, Type lookup_type) - { - string p_name = TypeManager.IndexerPropertyName (lookup_type); - - return TypeManager.MemberLookup ( - caller_type, caller_type, lookup_type, MemberTypes.Property, - BindingFlags.Public | BindingFlags.Instance | - BindingFlags.DeclaredOnly, p_name, null); - } - - public static Indexers GetIndexersForType (Type caller_type, Type lookup_type) - { - Indexers ix = new Indexers (); - - if (TypeManager.IsGenericParameter (lookup_type)) { - GenericConstraints gc = TypeManager.GetTypeParameterConstraints (lookup_type); - if (gc == null) - return ix; - - if (gc.HasClassConstraint) { - Type class_contraint = gc.ClassConstraint; - while (class_contraint != TypeManager.object_type && class_contraint != null) { - ix.Append (caller_type, GetIndexersForTypeOrInterface (caller_type, class_contraint)); - class_contraint = class_contraint.BaseType; - } - } - - Type[] ifaces = gc.InterfaceConstraints; - foreach (Type itype in ifaces) - ix.Append (caller_type, GetIndexersForTypeOrInterface (caller_type, itype)); - - return ix; - } - - Type copy = lookup_type; - while (copy != TypeManager.object_type && copy != null){ - ix.Append (caller_type, GetIndexersForTypeOrInterface (caller_type, copy)); - copy = copy.BaseType; - } - - if (lookup_type.IsInterface) { - Type [] ifaces = TypeManager.GetInterfaces (lookup_type); - if (ifaces != null) { - foreach (Type itype in ifaces) - ix.Append (caller_type, GetIndexersForTypeOrInterface (caller_type, itype)); - } - } - - return ix; - } - } - // // Points to our "data" repository // - MethodInfo get, set; + IndexerSpec spec; bool is_base_indexer; bool prepared; LocalTemporary temp; LocalTemporary prepared_value; Expression set_expr; - protected Type indexer_type; - protected Type current_type; + protected TypeSpec indexer_type; + protected TypeSpec current_type; protected Expression instance_expr; protected Arguments arguments; @@ -8440,11 +8012,16 @@ namespace Mono.CSharp { { Arguments args = Arguments.CreateForExpressionTree (ec, arguments, instance_expr.CreateExpressionTree (ec), - new TypeOfMethod (get, loc)); + new TypeOfMethod (spec.Get, loc)); return CreateExpressionFactoryCall (ec, "Call", args); } + static IEnumerable GetIndexersForType (TypeSpec lookup_type) + { + return MemberCache.FindIndexers (lookup_type, BindingRestriction.AccessibleOnly | BindingRestriction.NoOverrides); + } + protected virtual void CommonResolve (ResolveContext ec) { indexer_type = instance_expr.Type; @@ -8475,28 +8052,33 @@ namespace Mono.CSharp { { CommonResolve (ec); - MethodGroupExpr mg; - Indexers ilist; bool dynamic; arguments.Resolve (ec, out dynamic); - if (TypeManager.IsDynamicType (indexer_type)) { + if (indexer_type == InternalType.Dynamic) { dynamic = true; - mg = null; - ilist = null; } else { - ilist = Indexers.GetIndexersForType (current_type, indexer_type); - if (ilist.Methods == null) { + var ilist = GetIndexersForType (indexer_type); + if (ilist == null) { ec.Report.Error (21, loc, "Cannot apply indexing with [] to an expression of type `{0}'", TypeManager.CSharpName (indexer_type)); return null; } - mg = new IndexerMethodGroupExpr (ilist, loc); - mg = mg.OverloadResolve (ec, ref arguments, false, loc); + var mg = new IndexerMethodGroupExpr (ilist, loc) { + InstanceExpression = instance_expr + }; + + if (is_base_indexer) + mg.QueriedBaseType = current_type; + + mg = mg.OverloadResolve (ec, ref arguments, false, loc) as IndexerMethodGroupExpr; if (mg == null) return null; + + if (!dynamic) + spec = mg.BestIndexer (); } if (dynamic) { @@ -8515,28 +8097,19 @@ namespace Mono.CSharp { return expr.Resolve (ec); } - MethodInfo mi = (MethodInfo) mg; - PropertyInfo pi = null; - for (int i = 0; i < ilist.Methods.Count; ++i) { - if (ilist.Methods [i] == mi) { - pi = (PropertyInfo) ilist.Properties [i]; - break; - } - } - - type = TypeManager.TypeToCoreType (pi.PropertyType); + type = spec.MemberType; if (type.IsPointer && !ec.IsUnsafe) UnsafeError (ec, loc); - MethodInfo accessor; + MethodSpec accessor; if (right_side == null) { - accessor = get = pi.GetGetMethod (true); + accessor = spec.Get; } else { - accessor = set = pi.GetSetMethod (true); - if (accessor == null && pi.GetGetMethod (true) != null) { - ec.Report.SymbolRelatedToPreviousError (pi); + accessor = spec.Set; + if (!spec.HasSet && spec.HasGet) { + ec.Report.SymbolRelatedToPreviousError (spec); ec.Report.Error (200, loc, "The read only property or indexer `{0}' cannot be assigned to", - TypeManager.GetFullNameSignature (pi)); + spec.GetSignatureForError ()); return null; } @@ -8544,38 +8117,42 @@ namespace Mono.CSharp { } if (accessor == null) { - ec.Report.SymbolRelatedToPreviousError (pi); + ec.Report.SymbolRelatedToPreviousError (spec); ec.Report.Error (154, loc, "The property or indexer `{0}' cannot be used in this context because it lacks a `{1}' accessor", - TypeManager.GetFullNameSignature (pi), GetAccessorName (right_side != null)); + spec.GetSignatureForError (), GetAccessorName (right_side != null)); return null; } // // Only base will allow this invocation to happen. // - if (accessor.IsAbstract && this is BaseIndexerAccess) { - Error_CannotCallAbstractBase (ec, TypeManager.GetFullNameSignature (pi)); + if (spec.IsAbstract && this is BaseIndexerAccess) { + Error_CannotCallAbstractBase (ec, spec.GetSignatureForError ()); } bool must_do_cs1540_check; - if (!IsAccessorAccessible (ec.CurrentType, accessor, out must_do_cs1540_check)) { - if (set == null) - set = pi.GetSetMethod (true); - else - get = pi.GetGetMethod (true); - - if (set != null && get != null && - (set.Attributes & MethodAttributes.MemberAccessMask) != (get.Attributes & MethodAttributes.MemberAccessMask)) { + if (!IsMemberAccessible (ec.CurrentType, accessor, out must_do_cs1540_check)) { + if (spec.HasDifferentAccessibility) { ec.Report.SymbolRelatedToPreviousError (accessor); ec.Report.Error (271, loc, "The property or indexer `{0}' cannot be used in this context because a `{1}' accessor is inaccessible", - TypeManager.GetFullNameSignature (pi), GetAccessorName (right_side != null)); + TypeManager.GetFullNameSignature (spec), GetAccessorName (right_side != null)); } else { - ec.Report.SymbolRelatedToPreviousError (pi); - ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (pi), ec.Report); + ec.Report.SymbolRelatedToPreviousError (spec); + ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (spec), ec.Report); } } instance_expr.CheckMarshalByRefAccess (ec); + + if (must_do_cs1540_check && (instance_expr != EmptyExpression.Null) && + !TypeManager.IsInstantiationOfSameGenericType (instance_expr.Type, ec.CurrentType) && + !TypeManager.IsNestedChildOf (ec.CurrentType, instance_expr.Type) && + !TypeManager.IsSubclassOf (instance_expr.Type, ec.CurrentType)) { + ec.Report.SymbolRelatedToPreviousError (accessor); + Error_CannotAccessProtected (ec, loc, spec, instance_expr.Type, ec.CurrentType); + return null; + } + eclass = ExprClass.IndexerAccess; return this; } @@ -8590,12 +8167,12 @@ namespace Mono.CSharp { if (prepared) { prepared_value.Emit (ec); } else { - Invocation.EmitCall (ec, is_base_indexer, instance_expr, get, + Invocation.EmitCall (ec, is_base_indexer, instance_expr, spec.Get, arguments, loc, false, false); } if (leave_copy) { - ec.ig.Emit (OpCodes.Dup); + ec.Emit (OpCodes.Dup); temp = new LocalTemporary (Type); temp.Store (ec); } @@ -8612,7 +8189,7 @@ namespace Mono.CSharp { Expression value = set_expr; if (prepared) { - Invocation.EmitCall (ec, is_base_indexer, instance_expr, get, + Invocation.EmitCall (ec, is_base_indexer, instance_expr, spec.Get, arguments, loc, true, false); prepared_value = new LocalTemporary (type); @@ -8621,7 +8198,7 @@ namespace Mono.CSharp { prepared_value.Release (ec); if (leave_copy) { - ec.ig.Emit (OpCodes.Dup); + ec.Emit (OpCodes.Dup); temp = new LocalTemporary (Type); temp.Store (ec); } @@ -8635,7 +8212,7 @@ namespace Mono.CSharp { if (!prepared) arguments.Add (new Argument (value)); - Invocation.EmitCall (ec, is_base_indexer, instance_expr, set, arguments, loc, false, prepared); + Invocation.EmitCall (ec, is_base_indexer, instance_expr, spec.Set, arguments, loc, false, prepared); if (temp != null) { temp.Emit (ec); @@ -8645,7 +8222,7 @@ namespace Mono.CSharp { public override string GetSignatureForError () { - return TypeManager.CSharpSignature (get != null ? get : set, false); + return spec.GetSignatureForError (); } #if NET_4_0 @@ -8655,29 +8232,15 @@ namespace Mono.CSharp { var args = Arguments.MakeExpression (arguments, ctx).Concat (value); return SLE.Expression.Block ( - SLE.Expression.Call (instance_expr.MakeExpression (ctx), set, args), + SLE.Expression.Call (instance_expr.MakeExpression (ctx), (MethodInfo) spec.Set.GetMetaInfo (), args), value [0]); } +#endif public override SLE.Expression MakeExpression (BuilderContext ctx) { var args = Arguments.MakeExpression (arguments, ctx); - return SLE.Expression.Call (instance_expr.MakeExpression (ctx), get, args); - } -#endif - - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) - { - if (get != null) - get = storey.MutateGenericMethod (get); - if (set != null) - set = storey.MutateGenericMethod (set); - - instance_expr.MutateHoistedGenericType (storey); - if (arguments != null) - arguments.MutateHoistedGenericType (storey); - - type = storey.MutateType (type); + return SLE.Expression.Call (instance_expr.MakeExpression (ctx), (MethodInfo) spec.Get.GetMetaInfo (), args); } protected override void CloneTo (CloneContext clonectx, Expression t) @@ -8750,10 +8313,10 @@ namespace Mono.CSharp { Expression CommonResolve (ResolveContext ec) { Expression member_lookup; - Type current_type = ec.CurrentType; - Type base_type = current_type.BaseType; + TypeSpec current_type = ec.CurrentType; + TypeSpec base_type = current_type.BaseType; - if (!This.IsThisAvailable (ec)) { + if (!This.IsThisAvailable (ec, false)) { if (ec.IsStatic) { ec.Report.Error (1511, loc, "Keyword `base' is not available in a static method"); } else { @@ -8761,22 +8324,16 @@ namespace Mono.CSharp { } return null; } - - member_lookup = MemberLookup (ec.Compiler, ec.CurrentType, null, base_type, Identifier, - AllMemberTypes, AllBindingFlags, loc); + + var arity = args == null ? -1 : args.Count; + member_lookup = MemberLookup (ec.Compiler, ec.CurrentType, null, base_type, Identifier, arity, + MemberKind.All, BindingRestriction.AccessibleOnly | BindingRestriction.NoOverrides, loc); if (member_lookup == null) { - Error_MemberLookupFailed (ec, ec.CurrentType, base_type, base_type, Identifier, - null, AllMemberTypes, AllBindingFlags); + Error_MemberLookupFailed (ec, ec.CurrentType, base_type, base_type, Identifier, arity, + null, MemberKind.All, BindingRestriction.AccessibleOnly); return null; } - Expression left; - - if (ec.IsStatic) - left = new TypeExpression (base_type, loc); - else - left = ec.GetThis (loc); - MemberExpr me = member_lookup as MemberExpr; if (me == null){ if (member_lookup is TypeExpression){ @@ -8790,11 +8347,8 @@ namespace Mono.CSharp { return null; } - me = me.ResolveMemberAccess (ec, left, loc, null); - if (me == null) - return null; + me.QueriedBaseType = base_type; - me.IsBase = true; if (args != null) { args.Resolve (ec); me.SetTypeArguments (ec, args); @@ -8893,7 +8447,7 @@ namespace Mono.CSharp { loc = Location.Null; } - public EmptyExpression (Type t) + public EmptyExpression (TypeSpec t) { type = t; eclass = ExprClass.Value; @@ -8924,7 +8478,7 @@ namespace Mono.CSharp { // instead of creating gazillions of EmptyExpressions. // (CanImplicitConversion uses it) // - public void SetType (Type t) + public void SetType (TypeSpec t) { type = t; } @@ -8966,14 +8520,14 @@ namespace Mono.CSharp { } public class UserCast : Expression { - MethodInfo method; + MethodSpec method; Expression source; - public UserCast (MethodInfo method, Expression source, Location l) + public UserCast (MethodSpec method, Expression source, Location l) { this.method = method; this.source = source; - type = TypeManager.TypeToCoreType (method.ReturnType); + type = method.ReturnType; loc = l; } @@ -8994,7 +8548,7 @@ namespace Mono.CSharp { protected override Expression DoResolve (ResolveContext ec) { - ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (method); + ObsoleteAttribute oa = method.GetAttributeObsolete (); if (oa != null) AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc, ec.Report); @@ -9005,7 +8559,7 @@ namespace Mono.CSharp { public override void Emit (EmitContext ec) { source.Emit (ec); - ec.ig.Emit (OpCodes.Call, method); + ec.Emit (OpCodes.Call, method); } public override string GetSignatureForError () @@ -9013,17 +8567,68 @@ namespace Mono.CSharp { return TypeManager.CSharpSignature (method); } -#if NET_4_0 public override SLE.Expression MakeExpression (BuilderContext ctx) { - return SLE.Expression.Convert (source.MakeExpression (ctx), type, method); + return SLE.Expression.Convert (source.MakeExpression (ctx), type.GetMetaInfo (), (MethodInfo) method.GetMetaInfo ()); + } + } + + // + // Holds additional type specifiers like ?, *, [] + // + public class ComposedTypeSpecifier + { + public static readonly ComposedTypeSpecifier SingleDimension = new ComposedTypeSpecifier (1, Location.Null); + + public readonly int Dimension; + public readonly Location Location; + + public ComposedTypeSpecifier (int specifier, Location loc) + { + this.Dimension = specifier; + this.Location = loc; + } + + #region Properties + public bool IsNullable { + get { + return Dimension == -1; + } + } + + public bool IsPointer { + get { + return Dimension == -2; + } + } + + public ComposedTypeSpecifier Next { get; set; } + + #endregion + + public static ComposedTypeSpecifier CreateArrayDimension (int dimension, Location loc) + { + return new ComposedTypeSpecifier (dimension, loc); + } + + public static ComposedTypeSpecifier CreateNullable (Location loc) + { + return new ComposedTypeSpecifier (-1, loc); + } + + public static ComposedTypeSpecifier CreatePointer (Location loc) + { + return new ComposedTypeSpecifier (-2, loc); } -#endif - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + public string GetSignatureForError () { - source.MutateHoistedGenericType (storey); - method = storey.MutateGenericMethod (method); + string s = + IsPointer ? "*" : + IsNullable ? "?" : + ArrayContainer.GetPostfixSignature (Dimension); + + return Next != null ? s + Next.GetSignatureForError () : s; } } @@ -9035,18 +8640,16 @@ namespace Mono.CSharp { // public class ComposedCast : TypeExpr { FullNamedExpression left; - string dim; + ComposedTypeSpecifier spec; - public ComposedCast (FullNamedExpression left, string dim) - : this (left, dim, left.Location) + public ComposedCast (FullNamedExpression left, ComposedTypeSpecifier spec) { - } + if (spec == null) + throw new ArgumentNullException ("spec"); - public ComposedCast (FullNamedExpression left, string dim, Location l) - { this.left = left; - this.dim = dim; - loc = l; + this.spec = spec; + this.loc = spec.Location; } protected override TypeExpr DoResolveAsTypeStep (IMemberContext ec) @@ -9055,66 +8658,68 @@ namespace Mono.CSharp { if (lexpr == null) return null; - Type ltype = lexpr.Type; - if ((dim.Length > 0) && (dim [0] == '?')) { - TypeExpr nullable = new Nullable.NullableType (lexpr, loc); - if (dim.Length > 1) - nullable = new ComposedCast (nullable, dim.Substring (1), loc); - return nullable.ResolveAsTypeTerminal (ec, false); - } + type = lexpr.Type; + eclass = ExprClass.Type; - if (dim == "*" && !TypeManager.VerifyUnmanaged (ec.Compiler, ltype, loc)) - return null; + var single_spec = spec; + + if (single_spec.IsNullable) { + lexpr = new Nullable.NullableType (lexpr, loc); + lexpr = lexpr.ResolveAsTypeTerminal (ec, false); + if (lexpr != null) + type = lexpr.Type; - if (dim.Length != 0 && dim [0] == '[') { - if (TypeManager.IsSpecialType (ltype)) { - ec.Compiler.Report.Error (611, loc, "Array elements cannot be of type `{0}'", TypeManager.CSharpName (ltype)); + single_spec = single_spec.Next; + } else if (single_spec.IsPointer) { + if (!TypeManager.VerifyUnmanaged (ec.Compiler, type, loc)) return null; - } - if ((ltype.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) { - ec.Compiler.Report.SymbolRelatedToPreviousError (ltype); - ec.Compiler.Report.Error (719, loc, "Array elements cannot be of static type `{0}'", - TypeManager.CSharpName (ltype)); + if (!ec.IsUnsafe) { + UnsafeError (ec.Compiler.Report, loc); } - } - if (dim != "") - type = TypeManager.GetConstructedType (ltype, dim); - else - type = ltype; - - if (type == null) - throw new InternalErrorException ("Couldn't create computed type " + ltype + dim); + type = PointerContainer.MakeType (type); + single_spec = single_spec.Next; + } - if (type.IsPointer && !ec.IsUnsafe){ - UnsafeError (ec.Compiler.Report, loc); + if (single_spec != null && single_spec.Dimension > 0) { + if (TypeManager.IsSpecialType (type)) { + ec.Compiler.Report.Error (611, loc, "Array elements cannot be of type `{0}'", type.GetSignatureForError ()); + } else if (type.IsStatic) { + ec.Compiler.Report.SymbolRelatedToPreviousError (type); + ec.Compiler.Report.Error (719, loc, "Array elements cannot be of static type `{0}'", + type.GetSignatureForError ()); + } else { + MakeArray (single_spec); + } } - eclass = ExprClass.Type; return this; } - public override string GetSignatureForError () + void MakeArray (ComposedTypeSpecifier spec) { - return left.GetSignatureForError () + dim; + if (spec.Next != null) + MakeArray (spec.Next); + + type = ArrayContainer.MakeType (type, spec.Dimension); } - public override TypeExpr ResolveAsTypeTerminal (IMemberContext ec, bool silent) + public override string GetSignatureForError () { - return ResolveAsBaseTerminal (ec, silent); - } + return left.GetSignatureForError () + spec.GetSignatureForError (); + } } public class FixedBufferPtr : Expression { Expression array; - public FixedBufferPtr (Expression array, Type array_type, Location l) + public FixedBufferPtr (Expression array, TypeSpec array_type, Location l) { this.array = array; this.loc = l; - type = TypeManager.GetPointerType (array_type); + type = PointerContainer.MakeType (array_type); eclass = ExprClass.Value; } @@ -9145,9 +8750,9 @@ namespace Mono.CSharp { // for fixed (char *pa = a) // public class ArrayPtr : FixedBufferPtr { - Type array_type; + TypeSpec array_type; - public ArrayPtr (Expression array, Type array_type, Location l): + public ArrayPtr (Expression array, TypeSpec array_type, Location l): base (array, array_type, l) { this.array_type = array_type; @@ -9157,9 +8762,8 @@ namespace Mono.CSharp { { base.Emit (ec); - ILGenerator ig = ec.ig; - IntLiteral.EmitInt (ig, 0); - ig.Emit (OpCodes.Ldelema, array_type); + ec.EmitInt (0); + ec.Emit (OpCodes.Ldelema, array_type); } } @@ -9189,26 +8793,21 @@ namespace Mono.CSharp { var expr_type = child.Type; if (expr_type == TypeManager.uint32_type) - ec.ig.Emit (OpCodes.Conv_U); + ec.Emit (OpCodes.Conv_U); else if (expr_type == TypeManager.int64_type) - ec.ig.Emit (OpCodes.Conv_Ovf_I); + ec.Emit (OpCodes.Conv_Ovf_I); else if (expr_type == TypeManager.uint64_type) - ec.ig.Emit (OpCodes.Conv_Ovf_I_Un); + ec.Emit (OpCodes.Conv_Ovf_I_Un); else throw new InternalErrorException ("Cannot emit cast to unknown array element type", type); } - - public override bool GetAttributableValue (ResolveContext ec, Type value_type, out object value) - { - return child.GetAttributableValue (ec, value_type, out value); - } } // // Implements the `stackalloc' keyword // public class StackAlloc : Expression { - Type otype; + TypeSpec otype; Expression t; Expression count; @@ -9254,7 +8853,7 @@ namespace Mono.CSharp { if (!TypeManager.VerifyUnmanaged (ec.Compiler, otype, loc)) return null; - type = TypeManager.GetPointerType (otype); + type = PointerContainer.MakeType (otype); eclass = ExprClass.Value; return this; @@ -9263,17 +8862,16 @@ namespace Mono.CSharp { public override void Emit (EmitContext ec) { int size = GetTypeSize (otype); - ILGenerator ig = ec.ig; count.Emit (ec); if (size == 0) - ig.Emit (OpCodes.Sizeof, otype); + ec.Emit (OpCodes.Sizeof, otype); else - IntConstant.EmitInt (ig, size); + ec.EmitInt (size); - ig.Emit (OpCodes.Mul_Ovf_Un); - ig.Emit (OpCodes.Localloc); + ec.Emit (OpCodes.Mul_Ovf_Un); + ec.Emit (OpCodes.Localloc); } protected override void CloneTo (CloneContext clonectx, Expression t) @@ -9324,7 +8922,7 @@ namespace Mono.CSharp { return EmptyExpressionStatement.Instance; MemberExpr me = MemberLookupFinal (ec, ec.CurrentInitializerVariable.Type, ec.CurrentInitializerVariable.Type, - Name, MemberTypes.Field | MemberTypes.Property, BindingFlags.Public | BindingFlags.Instance, loc) as MemberExpr; + Name, 0, MemberKind.Field | MemberKind.Property, BindingRestriction.AccessibleOnly | BindingRestriction.InstanceOnly, loc) as MemberExpr; if (me == null) return null; @@ -9345,24 +8943,13 @@ namespace Mono.CSharp { return this; } - Expression expr = base.DoResolve (ec); - if (expr == null) - return null; - - // - // Ignore field initializers with default value - // - Constant c = source as Constant; - if (c != null && c.IsDefaultInitializer (type) && target.eclass == ExprClass.Variable) - return EmptyExpressionStatement.Instance.Resolve (ec); - - return expr; + return base.DoResolve (ec); } - protected override Expression Error_MemberLookupFailed (ResolveContext ec, Type type, MemberInfo[] members) + protected override MemberExpr Error_MemberLookupFailed (ResolveContext ec, TypeSpec type, IList members) { - MemberInfo member = members [0]; - if (member.MemberType != MemberTypes.Property && member.MemberType != MemberTypes.Field) + var member = members.First (); + if (member.Kind != MemberKind.Property && member.Kind != MemberKind.Field) ec.Report.Error (1913, loc, "Member `{0}' cannot be initialized. An object " + "initializer may only be used for fields, or properties", TypeManager.GetFullNameSignature (member)); else @@ -9401,7 +8988,7 @@ namespace Mono.CSharp { { } - protected override void Error_TypeDoesNotContainDefinition (ResolveContext ec, Type type, string name) + protected override void Error_TypeDoesNotContainDefinition (ResolveContext ec, TypeSpec type, string name) { if (TypeManager.HasElementType (type)) return; @@ -9417,7 +9004,7 @@ namespace Mono.CSharp { this.loc = argument.Location; } - public CollectionElementInitializer (ArrayList arguments, Location loc) + public CollectionElementInitializer (List arguments, Location loc) : base (null, new Arguments (arguments.Count)) { foreach (Expression e in arguments) @@ -9431,12 +9018,12 @@ namespace Mono.CSharp { Arguments args = new Arguments (2); args.Add (new Argument (mg.CreateExpressionTree (ec))); - ArrayList expr_initializers = new ArrayList (arguments.Count); + var expr_initializers = new ArrayInitializer (arguments.Count, loc); foreach (Argument a in arguments) expr_initializers.Add (a.CreateExpressionTree (ec)); args.Add (new Argument (new ArrayCreation ( - CreateExpressionTypeExpression (ec, loc), "[]", expr_initializers, loc))); + CreateExpressionTypeExpression (ec, loc), expr_initializers, loc))); return CreateExpressionFactoryCall (ec, "ElementInit", args); } @@ -9460,13 +9047,13 @@ namespace Mono.CSharp { // public class CollectionOrObjectInitializers : ExpressionStatement { - ArrayList initializers; + IList initializers; bool is_collection_initialization; public static readonly CollectionOrObjectInitializers Empty = - new CollectionOrObjectInitializers (new ArrayList (0), Location.Null); + new CollectionOrObjectInitializers (Array.AsReadOnly (new Expression [0]), Location.Null); - public CollectionOrObjectInitializers (ArrayList initializers, Location loc) + public CollectionOrObjectInitializers (IList initializers, Location loc) { this.initializers = initializers; this.loc = loc; @@ -9488,39 +9075,39 @@ namespace Mono.CSharp { { CollectionOrObjectInitializers t = (CollectionOrObjectInitializers) target; - t.initializers = new ArrayList (initializers.Count); - foreach (Expression e in initializers) + t.initializers = new List (initializers.Count); + foreach (var e in initializers) t.initializers.Add (e.Clone (clonectx)); } public override Expression CreateExpressionTree (ResolveContext ec) { - ArrayList expr_initializers = new ArrayList (initializers.Count); + var expr_initializers = new ArrayInitializer (initializers.Count, loc); foreach (Expression e in initializers) { Expression expr = e.CreateExpressionTree (ec); if (expr != null) expr_initializers.Add (expr); } - return new ImplicitlyTypedArrayCreation ("[]", expr_initializers, loc); + return new ImplicitlyTypedArrayCreation (expr_initializers, loc); } protected override Expression DoResolve (ResolveContext ec) { - ArrayList element_names = null; + List element_names = null; for (int i = 0; i < initializers.Count; ++i) { - Expression initializer = (Expression) initializers [i]; + Expression initializer = initializers [i]; ElementInitializer element_initializer = initializer as ElementInitializer; if (i == 0) { if (element_initializer != null) { - element_names = new ArrayList (initializers.Count); + element_names = new List (initializers.Count); element_names.Add (element_initializer.Name); } else if (initializer is CompletingExpression){ initializer.Resolve (ec); throw new InternalErrorException ("This line should never be reached"); } else { - if (!TypeManager.ImplementsInterface (ec.CurrentInitializerVariable.Type, TypeManager.ienumerable_type)) { + if (!ec.CurrentInitializerVariable.Type.ImplementsInterface (TypeManager.ienumerable_type)) { ec.Report.Error (1922, loc, "A field or property `{0}' cannot be initialized with a collection " + "object initializer because type `{1}' does not implement `{2}' interface", ec.CurrentInitializerVariable.GetSignatureForError (), @@ -9577,12 +9164,6 @@ namespace Mono.CSharp { foreach (ExpressionStatement e in initializers) e.EmitStatement (ec); } - - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) - { - foreach (Expression e in initializers) - e.MutateHoistedGenericType (storey); - } } // @@ -9642,7 +9223,7 @@ namespace Mono.CSharp { CollectionOrObjectInitializers initializers; IMemoryLocation instance; - public NewInitialize (Expression requested_type, Arguments arguments, CollectionOrObjectInitializers initializers, Location l) + public NewInitialize (FullNamedExpression requested_type, Arguments arguments, CollectionOrObjectInitializers initializers, Location l) : base (requested_type, arguments, l) { this.initializers = initializers; @@ -9733,23 +9314,17 @@ namespace Mono.CSharp { return !initializers.IsEmpty; } } - - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) - { - base.MutateHoistedGenericType (storey); - initializers.MutateHoistedGenericType (storey); - } } public class NewAnonymousType : New { - static readonly ArrayList EmptyParameters = new ArrayList (0); + static readonly AnonymousTypeParameter[] EmptyParameters = new AnonymousTypeParameter[0]; - ArrayList parameters; + List parameters; readonly TypeContainer parent; AnonymousTypeClass anonymous_type; - public NewAnonymousType (ArrayList parameters, TypeContainer parent, Location loc) + public NewAnonymousType (List parameters, TypeContainer parent, Location loc) : base (null, null, loc) { this.parameters = parameters; @@ -9762,12 +9337,12 @@ namespace Mono.CSharp { return; NewAnonymousType t = (NewAnonymousType) target; - t.parameters = new ArrayList (parameters.Count); + t.parameters = new List (parameters.Count); foreach (AnonymousTypeParameter atp in parameters) - t.parameters.Add (atp.Clone (clonectx)); + t.parameters.Add ((AnonymousTypeParameter) atp.Clone (clonectx)); } - AnonymousTypeClass CreateAnonymousType (ResolveContext ec, ArrayList parameters) + AnonymousTypeClass CreateAnonymousType (ResolveContext ec, IList parameters) { AnonymousTypeClass type = parent.Module.Compiled.GetAnonymousType (parameters); if (type != null) @@ -9777,7 +9352,9 @@ namespace Mono.CSharp { if (type == null) return null; + type.CreateType (); type.DefineType (); + type.ResolveTypeParameters (); type.Define (); type.EmitType (); if (ec.Report.Errors == 0) @@ -9792,18 +9369,18 @@ namespace Mono.CSharp { if (parameters == null) return base.CreateExpressionTree (ec); - ArrayList init = new ArrayList (parameters.Count); + var init = new ArrayInitializer (parameters.Count, loc); foreach (Property p in anonymous_type.Properties) - init.Add (new TypeOfMethod (TypeBuilder.GetMethod (type, p.GetBuilder), loc)); + init.Add (new TypeOfMethod (MemberCache.GetMember (type, p.Get.Spec), loc)); - ArrayList ctor_args = new ArrayList (Arguments.Count); + var ctor_args = new ArrayInitializer (Arguments.Count, loc); foreach (Argument a in Arguments) ctor_args.Add (a.CreateExpressionTree (ec)); Arguments args = new Arguments (3); args.Add (new Argument (method.CreateExpressionTree (ec))); - args.Add (new Argument (new ArrayCreation (TypeManager.expression_type_expr, "[]", ctor_args, loc))); - args.Add (new Argument (new ImplicitlyTypedArrayCreation ("[]", init, loc))); + args.Add (new Argument (new ArrayCreation (TypeManager.expression_type_expr, ctor_args, loc))); + args.Add (new Argument (new ImplicitlyTypedArrayCreation (init, loc))); return CreateExpressionFactoryCall (ec, "New", args); } @@ -9817,7 +9394,7 @@ namespace Mono.CSharp { if (parameters == null) { anonymous_type = CreateAnonymousType (ec, EmptyParameters); - RequestedType = new TypeExpression (anonymous_type.TypeBuilder, loc); + RequestedType = new TypeExpression (anonymous_type.Definition, loc); return base.DoResolve (ec); } @@ -9842,7 +9419,7 @@ namespace Mono.CSharp { if (anonymous_type == null) return null; - RequestedType = new GenericTypeExpr (anonymous_type.TypeBuilder, new TypeArguments (t_args), loc); + RequestedType = new GenericTypeExpr (anonymous_type.Definition, new TypeArguments (t_args), loc); return base.DoResolve (ec); } }