X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fexpression.cs;h=5a2b3615b25bef788e947fae9d719f7942fd6df6;hb=cafb63ae22a218cda3fa7b48ac4d22b5519e2747;hp=bde0196da34ec8c24de28a2e98c01dd35065e110;hpb=089d5fed1917f774dfd602b2e3e4f5a60285a349;p=mono.git diff --git a/mcs/mcs/expression.cs b/mcs/mcs/expression.cs index bde0196da34..5a2b3615b25 100644 --- a/mcs/mcs/expression.cs +++ b/mcs/mcs/expression.cs @@ -3,6 +3,7 @@ // // Author: // Miguel de Icaza (miguel@ximian.com) +// Marek Safar (marek.safar@seznam.cz) // // (C) 2001, 2002, 2003 Ximian, Inc. // (C) 2003, 2004 Novell, Inc. @@ -106,6 +107,13 @@ namespace Mono.CSharp { { throw new Exception ("Should not happen"); } + + public override Location Location + { + get { + return Expr.Location; + } + } } /// @@ -187,37 +195,37 @@ namespace Mono.CSharp { Expression e = null; if (expr is IntConstant) - e = new IntConstant (-((IntConstant) expr).Value); + e = new IntConstant (-((IntConstant) expr).Value, expr.Location); else if (expr is UIntConstant){ uint value = ((UIntConstant) expr).Value; if (value < 2147483649) - return new IntConstant (-(int)value); + return new IntConstant (-(int)value, expr.Location); else - e = new LongConstant (-value); + e = new LongConstant (-value, expr.Location); } else if (expr is LongConstant) - e = new LongConstant (-((LongConstant) expr).Value); + e = new LongConstant (-((LongConstant) expr).Value, expr.Location); else if (expr is ULongConstant){ ulong value = ((ULongConstant) expr).Value; if (value < 9223372036854775809) - return new LongConstant(-(long)value); + return new LongConstant(-(long)value, expr.Location); } else if (expr is FloatConstant) - e = new FloatConstant (-((FloatConstant) expr).Value); + e = new FloatConstant (-((FloatConstant) expr).Value, expr.Location); else if (expr is DoubleConstant) - e = new DoubleConstant (-((DoubleConstant) expr).Value); + e = new DoubleConstant (-((DoubleConstant) expr).Value, expr.Location); else if (expr is DecimalConstant) - e = new DecimalConstant (-((DecimalConstant) expr).Value); + e = new DecimalConstant (-((DecimalConstant) expr).Value, expr.Location); else if (expr is ShortConstant) - e = new IntConstant (-((ShortConstant) expr).Value); + e = new IntConstant (-((ShortConstant) expr).Value, expr.Location); else if (expr is UShortConstant) - e = new IntConstant (-((UShortConstant) expr).Value); + e = new IntConstant (-((UShortConstant) expr).Value, expr.Location); else if (expr is SByteConstant) - e = new IntConstant (-((SByteConstant) expr).Value); + e = new IntConstant (-((SByteConstant) expr).Value, expr.Location); else if (expr is ByteConstant) - e = new IntConstant (-((ByteConstant) expr).Value); + e = new IntConstant (-((ByteConstant) expr).Value, expr.Location); return e; } @@ -254,7 +262,7 @@ namespace Mono.CSharp { } BoolConstant b = (BoolConstant) e; - result = new BoolConstant (!(b.Value)); + result = new BoolConstant (!(b.Value), b.Location); return true; case Operator.OnesComplement: @@ -303,13 +311,13 @@ namespace Mono.CSharp { } if (expr_type == TypeManager.int32_type){ - result = new IntConstant (~ ((IntConstant) e).Value); + result = new IntConstant (~ ((IntConstant) e).Value, e.Location); } else if (expr_type == TypeManager.uint32_type){ - result = new UIntConstant (~ ((UIntConstant) e).Value); + result = new UIntConstant (~ ((UIntConstant) e).Value, e.Location); } else if (expr_type == TypeManager.int64_type){ - result = new LongConstant (~ ((LongConstant) e).Value); + result = new LongConstant (~ ((LongConstant) e).Value, e.Location); } else if (expr_type == TypeManager.uint64_type){ - result = new ULongConstant (~ ((ULongConstant) e).Value); + result = new ULongConstant (~ ((ULongConstant) e).Value, e.Location); } else { result = null; Error23 (expr_type); @@ -351,7 +359,7 @@ namespace Mono.CSharp { op_name = oper_names [(int) Oper]; - mg = MemberLookup (ec, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc); + mg = MemberLookup (ec.ContainerType, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc); if (mg != null) { Expression e = StaticCallExpr.MakeSimpleCall ( @@ -605,7 +613,7 @@ namespace Mono.CSharp { throw new Exception ("This should be caught by Resolve"); case Operator.UnaryNegation: - if (ec.CheckState) { + if (ec.CheckState && type != TypeManager.float_type && type != TypeManager.double_type) { ig.Emit (OpCodes.Ldc_I4_0); if (type == TypeManager.int64_type) ig.Emit (OpCodes.Conv_U8); @@ -685,7 +693,7 @@ namespace Mono.CSharp { Emit (ec); if (leave_copy) { ec.ig.Emit (OpCodes.Dup); - temporary = new LocalTemporary (ec, expr.Type); + temporary = new LocalTemporary (expr.Type); temporary.Store (ec); } } @@ -702,7 +710,7 @@ namespace Mono.CSharp { source.Emit (ec); if (leave_copy) { ec.ig.Emit (OpCodes.Dup); - temporary = new LocalTemporary (ec, expr.Type); + temporary = new LocalTemporary (expr.Type); temporary.Store (ec); } @@ -842,7 +850,7 @@ namespace Mono.CSharp { else op_name = "op_Decrement"; - mg = MemberLookup (ec, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc); + mg = MemberLookup (ec.ContainerType, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc); if (mg != null) { method = StaticCallExpr.MakeSimpleCall ( @@ -872,7 +880,7 @@ namespace Mono.CSharp { if (expr == null) return null; } else { - expr.Error_UnexpectedKind (ec, "variable, indexer or property access", loc); + expr.Error_UnexpectedKind (ec.DeclContainer, "variable, indexer or property access", loc); return null; } @@ -982,7 +990,6 @@ namespace Mono.CSharp { this.is_expr = is_expr; ((IAssignMethod) expr).EmitAssign (ec, this, is_expr && (mode == Mode.PreIncrement || mode == Mode.PreDecrement), true); } - public override void Emit (EmitContext ec) { @@ -1041,9 +1048,8 @@ namespace Mono.CSharp { TypeExpr texpr = ProbeType.ResolveAsTypeTerminal (ec, false); if (texpr == null) return null; - probe_type = texpr.ResolveType (ec); - CheckObsoleteAttribute (probe_type); + probe_type = texpr.Type; expr = expr.Resolve (ec); if (expr == null) @@ -1180,7 +1186,7 @@ namespace Mono.CSharp { } return this; - } + } } /// @@ -1193,6 +1199,7 @@ namespace Mono.CSharp { } bool do_isinst = false; + Expression resolved_type; public override void Emit (EmitContext ec) { @@ -1213,10 +1220,12 @@ namespace Mono.CSharp { public override Expression DoResolve (EmitContext ec) { - Expression e = base.DoResolve (ec); + if (resolved_type == null) { + resolved_type = base.DoResolve (ec); - if (e == null) - return null; + if (resolved_type == null) + return null; + } type = probe_type; eclass = ExprClass.Value; @@ -1229,7 +1238,7 @@ namespace Mono.CSharp { } - e = Convert.ImplicitConversion (ec, expr, probe_type, loc); + Expression e = Convert.ImplicitConversion (ec, expr, probe_type, loc); if (e != null){ expr = e; do_isinst = false; @@ -1243,7 +1252,12 @@ namespace Mono.CSharp { Error_CannotConvertType (etype, probe_type, loc); return null; - } + } + + public override bool GetAttributableValue (Type valueType, out object value) + { + return expr.GetAttributableValue (valueType, out value); + } } /// @@ -1266,527 +1280,18 @@ namespace Mono.CSharp { this.target_type = cast_type; this.expr = expr; this.loc = loc; + + if (target_type == TypeManager.system_void_expr) + Report.Error (1547, loc, "Keyword `void' cannot be used in this context"); } public Expression TargetType { - get { - return target_type; - } + get { return target_type; } } public Expression Expr { - get { - return expr; - } - set { - expr = value; - } - } - - bool CheckRange (EmitContext ec, long value, Type type, long min, long max) - { - if (!ec.ConstantCheckState) - return true; - - if ((value < min) || (value > max)) { - Error (221, "Constant value `" + value + "' cannot be converted " + - "to a `" + TypeManager.CSharpName (type) + "' (use `unchecked' " + - "syntax to override)"); - return false; - } - - return true; - } - - bool CheckRange (EmitContext ec, ulong value, Type type, ulong max) - { - if (!ec.ConstantCheckState) - return true; - - if (value > max) { - Error (221, "Constant value `" + value + "' cannot be converted " + - "to a `" + TypeManager.CSharpName (type) + "' (use `unchecked' " + - "syntax to override)"); - return false; - } - - return true; - } - - bool CheckUnsigned (EmitContext ec, long value, Type type) - { - if (!ec.ConstantCheckState) - return true; - - if (value < 0) { - Error (221, "Constant value `" + value + "' cannot be converted " + - "to a `" + TypeManager.CSharpName (type) + "' (use `unchecked' " + - "syntax to override)"); - return false; - } - - return true; - } - - // TODO: move to constant - /// - /// Attempts to do a compile-time folding of a constant cast. - /// - Expression TryReduce (EmitContext ec, Type target_type) - { - if (expr.Type == target_type) - return expr; - - if (TypeManager.IsEnumType (target_type) && TypeManager.EnumToUnderlying (target_type) == expr.Type) - return new EnumConstant ((Constant)expr, target_type); - - Expression real_expr = expr; - if (real_expr is EnumConstant) - real_expr = ((EnumConstant) real_expr).Child; - - if (real_expr is ByteConstant){ - byte v = ((ByteConstant) real_expr).Value; - - if (target_type == TypeManager.sbyte_type) { - if (!CheckRange (ec, v, target_type, SByte.MinValue, SByte.MaxValue)) - return null; - return new SByteConstant ((sbyte) v); - } - if (target_type == TypeManager.short_type) - return new ShortConstant ((short) v); - if (target_type == TypeManager.ushort_type) - return new UShortConstant ((ushort) v); - if (target_type == TypeManager.int32_type) - return new IntConstant ((int) v); - if (target_type == TypeManager.uint32_type) - return new UIntConstant ((uint) v); - if (target_type == TypeManager.int64_type) - return new LongConstant ((long) v); - if (target_type == TypeManager.uint64_type) - return new ULongConstant ((ulong) v); - if (target_type == TypeManager.float_type) - return new FloatConstant ((float) v); - if (target_type == TypeManager.double_type) - return new DoubleConstant ((double) v); - if (target_type == TypeManager.char_type) - return new CharConstant ((char) v); - if (target_type == TypeManager.decimal_type) - return new DecimalConstant ((decimal) v); - } - if (real_expr is SByteConstant){ - sbyte v = ((SByteConstant) real_expr).Value; - - if (target_type == TypeManager.byte_type) { - if (!CheckUnsigned (ec, v, target_type)) - return null; - return new ByteConstant ((byte) v); - } - if (target_type == TypeManager.short_type) - return new ShortConstant ((short) v); - if (target_type == TypeManager.ushort_type) { - if (!CheckUnsigned (ec, v, target_type)) - return null; - return new UShortConstant ((ushort) v); - } if (target_type == TypeManager.int32_type) - return new IntConstant ((int) v); - if (target_type == TypeManager.uint32_type) { - if (!CheckUnsigned (ec, v, target_type)) - return null; - return new UIntConstant ((uint) v); - } if (target_type == TypeManager.int64_type) - return new LongConstant ((long) v); - if (target_type == TypeManager.uint64_type) { - if (!CheckUnsigned (ec, v, target_type)) - return null; - return new ULongConstant ((ulong) v); - } - if (target_type == TypeManager.float_type) - return new FloatConstant ((float) v); - if (target_type == TypeManager.double_type) - return new DoubleConstant ((double) v); - if (target_type == TypeManager.char_type) { - if (!CheckUnsigned (ec, v, target_type)) - return null; - return new CharConstant ((char) v); - } - if (target_type == TypeManager.decimal_type) - return new DecimalConstant ((decimal) v); - } - if (real_expr is ShortConstant){ - short v = ((ShortConstant) real_expr).Value; - - if (target_type == TypeManager.byte_type) { - if (!CheckRange (ec, v, target_type, Byte.MinValue, Byte.MaxValue)) - return null; - return new ByteConstant ((byte) v); - } - if (target_type == TypeManager.sbyte_type) { - if (!CheckRange (ec, v, target_type, SByte.MinValue, SByte.MaxValue)) - return null; - return new SByteConstant ((sbyte) v); - } - if (target_type == TypeManager.ushort_type) { - if (!CheckUnsigned (ec, v, target_type)) - return null; - return new UShortConstant ((ushort) v); - } - if (target_type == TypeManager.int32_type) - return new IntConstant ((int) v); - if (target_type == TypeManager.uint32_type) { - if (!CheckUnsigned (ec, v, target_type)) - return null; - return new UIntConstant ((uint) v); - } - if (target_type == TypeManager.int64_type) - return new LongConstant ((long) v); - if (target_type == TypeManager.uint64_type) { - if (!CheckUnsigned (ec, v, target_type)) - return null; - return new ULongConstant ((ulong) v); - } - if (target_type == TypeManager.float_type) - return new FloatConstant ((float) v); - if (target_type == TypeManager.double_type) - return new DoubleConstant ((double) v); - if (target_type == TypeManager.char_type) { - if (!CheckRange (ec, v, target_type, Char.MinValue, Char.MaxValue)) - return null; - return new CharConstant ((char) v); - } - if (target_type == TypeManager.decimal_type) - return new DecimalConstant ((decimal) v); - } - if (real_expr is UShortConstant){ - ushort v = ((UShortConstant) real_expr).Value; - - if (target_type == TypeManager.byte_type) { - if (!CheckRange (ec, v, target_type, Byte.MinValue, Byte.MaxValue)) - return null; - return new ByteConstant ((byte) v); - } - if (target_type == TypeManager.sbyte_type) { - if (!CheckRange (ec, v, target_type, SByte.MinValue, SByte.MaxValue)) - return null; - return new SByteConstant ((sbyte) v); - } - if (target_type == TypeManager.short_type) { - if (!CheckRange (ec, v, target_type, Int16.MinValue, Int16.MaxValue)) - return null; - return new ShortConstant ((short) v); - } - if (target_type == TypeManager.int32_type) - return new IntConstant ((int) v); - if (target_type == TypeManager.uint32_type) - return new UIntConstant ((uint) v); - if (target_type == TypeManager.int64_type) - return new LongConstant ((long) v); - if (target_type == TypeManager.uint64_type) - return new ULongConstant ((ulong) v); - if (target_type == TypeManager.float_type) - return new FloatConstant ((float) v); - if (target_type == TypeManager.double_type) - return new DoubleConstant ((double) v); - if (target_type == TypeManager.char_type) { - if (!CheckRange (ec, v, target_type, Char.MinValue, Char.MaxValue)) - return null; - return new CharConstant ((char) v); - } - if (target_type == TypeManager.decimal_type) - return new DecimalConstant ((decimal) v); - } - if (real_expr is IntConstant){ - int v = ((IntConstant) real_expr).Value; - - if (target_type == TypeManager.byte_type) { - if (!CheckRange (ec, v, target_type, Byte.MinValue, Byte.MaxValue)) - return null; - return new ByteConstant ((byte) v); - } - if (target_type == TypeManager.sbyte_type) { - if (!CheckRange (ec, v, target_type, SByte.MinValue, SByte.MaxValue)) - return null; - return new SByteConstant ((sbyte) v); - } - if (target_type == TypeManager.short_type) { - if (!CheckRange (ec, v, target_type, Int16.MinValue, Int16.MaxValue)) - return null; - return new ShortConstant ((short) v); - } - if (target_type == TypeManager.ushort_type) { - if (!CheckRange (ec, v, target_type, UInt16.MinValue, UInt16.MaxValue)) - return null; - return new UShortConstant ((ushort) v); - } - if (target_type == TypeManager.uint32_type) { - if (!CheckRange (ec, v, target_type, Int32.MinValue, Int32.MaxValue)) - return null; - return new UIntConstant ((uint) v); - } - if (target_type == TypeManager.int64_type) - return new LongConstant ((long) v); - if (target_type == TypeManager.uint64_type) { - if (!CheckUnsigned (ec, v, target_type)) - return null; - return new ULongConstant ((ulong) v); - } - if (target_type == TypeManager.float_type) - return new FloatConstant ((float) v); - if (target_type == TypeManager.double_type) - return new DoubleConstant ((double) v); - if (target_type == TypeManager.char_type) { - if (!CheckRange (ec, v, target_type, Char.MinValue, Char.MaxValue)) - return null; - return new CharConstant ((char) v); - } - if (target_type == TypeManager.decimal_type) - return new DecimalConstant ((decimal) v); - } - if (real_expr is UIntConstant){ - uint v = ((UIntConstant) real_expr).Value; - - if (target_type == TypeManager.byte_type) { - if (!CheckRange (ec, v, target_type, Char.MinValue, Char.MaxValue)) - return null; - return new ByteConstant ((byte) v); - } - if (target_type == TypeManager.sbyte_type) { - if (!CheckRange (ec, v, target_type, SByte.MinValue, SByte.MaxValue)) - return null; - return new SByteConstant ((sbyte) v); - } - if (target_type == TypeManager.short_type) { - if (!CheckRange (ec, v, target_type, Int16.MinValue, Int16.MaxValue)) - return null; - return new ShortConstant ((short) v); - } - if (target_type == TypeManager.ushort_type) { - if (!CheckRange (ec, v, target_type, UInt16.MinValue, UInt16.MaxValue)) - return null; - return new UShortConstant ((ushort) v); - } - if (target_type == TypeManager.int32_type) { - if (!CheckRange (ec, v, target_type, Int32.MinValue, Int32.MaxValue)) - return null; - return new IntConstant ((int) v); - } - if (target_type == TypeManager.int64_type) - return new LongConstant ((long) v); - if (target_type == TypeManager.uint64_type) - return new ULongConstant ((ulong) v); - if (target_type == TypeManager.float_type) - return new FloatConstant ((float) v); - if (target_type == TypeManager.double_type) - return new DoubleConstant ((double) v); - if (target_type == TypeManager.char_type) { - if (!CheckRange (ec, v, target_type, Char.MinValue, Char.MaxValue)) - return null; - return new CharConstant ((char) v); - } - if (target_type == TypeManager.decimal_type) - return new DecimalConstant ((decimal) v); - } - if (real_expr is LongConstant){ - long v = ((LongConstant) real_expr).Value; - - if (target_type == TypeManager.byte_type) { - if (!CheckRange (ec, v, target_type, Byte.MinValue, Byte.MaxValue)) - return null; - return new ByteConstant ((byte) v); - } - if (target_type == TypeManager.sbyte_type) { - if (!CheckRange (ec, v, target_type, SByte.MinValue, SByte.MaxValue)) - return null; - return new SByteConstant ((sbyte) v); - } - if (target_type == TypeManager.short_type) { - if (!CheckRange (ec, v, target_type, Int16.MinValue, Int16.MaxValue)) - return null; - return new ShortConstant ((short) v); - } - if (target_type == TypeManager.ushort_type) { - if (!CheckRange (ec, v, target_type, UInt16.MinValue, UInt16.MaxValue)) - return null; - return new UShortConstant ((ushort) v); - } - if (target_type == TypeManager.int32_type) { - if (!CheckRange (ec, v, target_type, Int32.MinValue, Int32.MaxValue)) - return null; - return new IntConstant ((int) v); - } - if (target_type == TypeManager.uint32_type) { - if (!CheckRange (ec, v, target_type, UInt32.MinValue, UInt32.MaxValue)) - return null; - return new UIntConstant ((uint) v); - } - if (target_type == TypeManager.uint64_type) { - if (!CheckUnsigned (ec, v, target_type)) - return null; - return new ULongConstant ((ulong) v); - } - if (target_type == TypeManager.float_type) - return new FloatConstant ((float) v); - if (target_type == TypeManager.double_type) - return new DoubleConstant ((double) v); - if (target_type == TypeManager.char_type) { - if (!CheckRange (ec, v, target_type, Char.MinValue, Char.MaxValue)) - return null; - return new CharConstant ((char) v); - } - if (target_type == TypeManager.decimal_type) - return new DecimalConstant ((decimal) v); - } - if (real_expr is ULongConstant){ - ulong v = ((ULongConstant) real_expr).Value; - - if (target_type == TypeManager.byte_type) { - if (!CheckRange (ec, v, target_type, Byte.MaxValue)) - return null; - return new ByteConstant ((byte) v); - } - if (target_type == TypeManager.sbyte_type) { - if (!CheckRange (ec, v, target_type, (ulong) SByte.MaxValue)) - return null; - return new SByteConstant ((sbyte) v); - } - if (target_type == TypeManager.short_type) { - if (!CheckRange (ec, v, target_type, (ulong) Int16.MaxValue)) - return null; - return new ShortConstant ((short) v); - } - if (target_type == TypeManager.ushort_type) { - if (!CheckRange (ec, v, target_type, UInt16.MaxValue)) - return null; - return new UShortConstant ((ushort) v); - } - if (target_type == TypeManager.int32_type) { - if (!CheckRange (ec, v, target_type, Int32.MaxValue)) - return null; - return new IntConstant ((int) v); - } - if (target_type == TypeManager.uint32_type) { - if (!CheckRange (ec, v, target_type, UInt32.MaxValue)) - return null; - return new UIntConstant ((uint) v); - } - if (target_type == TypeManager.int64_type) { - if (!CheckRange (ec, v, target_type, (ulong) Int64.MaxValue)) - return null; - return new LongConstant ((long) v); - } - if (target_type == TypeManager.float_type) - return new FloatConstant ((float) v); - if (target_type == TypeManager.double_type) - return new DoubleConstant ((double) v); - if (target_type == TypeManager.char_type) { - if (!CheckRange (ec, v, target_type, Char.MaxValue)) - return null; - return new CharConstant ((char) v); - } - if (target_type == TypeManager.decimal_type) - return new DecimalConstant ((decimal) v); - } - if (real_expr is FloatConstant){ - float v = ((FloatConstant) real_expr).Value; - - if (target_type == TypeManager.byte_type) - return new ByteConstant ((byte) v); - if (target_type == TypeManager.sbyte_type) - return new SByteConstant ((sbyte) v); - if (target_type == TypeManager.short_type) - return new ShortConstant ((short) v); - if (target_type == TypeManager.ushort_type) - return new UShortConstant ((ushort) v); - if (target_type == TypeManager.int32_type) - return new IntConstant ((int) v); - if (target_type == TypeManager.uint32_type) - return new UIntConstant ((uint) v); - if (target_type == TypeManager.int64_type) - return new LongConstant ((long) v); - if (target_type == TypeManager.uint64_type) - return new ULongConstant ((ulong) v); - if (target_type == TypeManager.double_type) - return new DoubleConstant ((double) v); - if (target_type == TypeManager.char_type) - return new CharConstant ((char) v); - if (target_type == TypeManager.decimal_type) - return new DecimalConstant ((decimal) v); - } - if (real_expr is DoubleConstant){ - double v = ((DoubleConstant) real_expr).Value; - - if (target_type == TypeManager.byte_type){ - return new ByteConstant ((byte) v); - } if (target_type == TypeManager.sbyte_type) - return new SByteConstant ((sbyte) v); - if (target_type == TypeManager.short_type) - return new ShortConstant ((short) v); - if (target_type == TypeManager.ushort_type) - return new UShortConstant ((ushort) v); - if (target_type == TypeManager.int32_type) - return new IntConstant ((int) v); - if (target_type == TypeManager.uint32_type) - return new UIntConstant ((uint) v); - if (target_type == TypeManager.int64_type) - return new LongConstant ((long) v); - if (target_type == TypeManager.uint64_type) - return new ULongConstant ((ulong) v); - if (target_type == TypeManager.float_type) - return new FloatConstant ((float) v); - if (target_type == TypeManager.char_type) - return new CharConstant ((char) v); - if (target_type == TypeManager.decimal_type) - return new DecimalConstant ((decimal) v); - } - - if (real_expr is CharConstant){ - char v = ((CharConstant) real_expr).Value; - - if (target_type == TypeManager.byte_type) { - if (!CheckRange (ec, v, target_type, Byte.MinValue, Byte.MaxValue)) - return null; - return new ByteConstant ((byte) v); - } - if (target_type == TypeManager.sbyte_type) { - if (!CheckRange (ec, v, target_type, SByte.MinValue, SByte.MaxValue)) - return null; - return new SByteConstant ((sbyte) v); - } - if (target_type == TypeManager.short_type) { - if (!CheckRange (ec, v, target_type, Int16.MinValue, Int16.MaxValue)) - return null; - return new ShortConstant ((short) v); - } - if (target_type == TypeManager.int32_type) - return new IntConstant ((int) v); - if (target_type == TypeManager.uint32_type) - return new UIntConstant ((uint) v); - if (target_type == TypeManager.int64_type) - return new LongConstant ((long) v); - if (target_type == TypeManager.uint64_type) - return new ULongConstant ((ulong) v); - if (target_type == TypeManager.float_type) - return new FloatConstant ((float) v); - if (target_type == TypeManager.double_type) - return new DoubleConstant ((double) v); - if (target_type == TypeManager.char_type) { - if (!CheckRange (ec, v, target_type, Char.MinValue, Char.MaxValue)) - return null; - return new CharConstant ((char) v); - } - if (target_type == TypeManager.decimal_type) - return new DecimalConstant ((decimal) v); - } - - return null; - } - - public override Expression DoResolveLValue (EmitContext ec, Expression right_side) - { - expr = expr.DoResolveLValue (ec, right_side); - if (expr == null) - return null; - - return ResolveRest (ec); + get { return expr; } + set { expr = value; } } public override Expression DoResolve (EmitContext ec) @@ -1795,18 +1300,11 @@ namespace Mono.CSharp { if (expr == null) return null; - return ResolveRest (ec); - } - - Expression ResolveRest (EmitContext ec) - { TypeExpr target = target_type.ResolveAsTypeTerminal (ec, false); if (target == null) return null; - type = target.ResolveType (ec); - - CheckObsoleteAttribute (type); + type = target.Type; if (type.IsAbstract && type.IsSealed) { Report.Error (716, loc, "Cannot convert to static type `{0}'", TypeManager.CSharpName (type)); @@ -1815,11 +1313,16 @@ namespace Mono.CSharp { eclass = ExprClass.Value; - if (expr is Constant){ - Expression e = TryReduce (ec, type); - - if (e != null) - return e; + Constant c = expr as Constant; + if (c != null) { + try { + c = c.TryReduce (ec, type, loc); + if (c != null) + return c; + } + catch (OverflowException) { + return null; + } } if (type.IsPointer && !ec.InUnsafe) { @@ -1832,9 +1335,6 @@ namespace Mono.CSharp { public override void Emit (EmitContext ec) { - // - // This one will never happen - // throw new Exception ("Should not happen"); } } @@ -1926,7 +1426,7 @@ namespace Mono.CSharp { /// /// Returns a stringified representation of the Operator /// - static string OperName (Operator oper) + public static string OperName (Operator oper) { switch (oper){ case Operator.Multiply: @@ -1994,7 +1494,7 @@ namespace Mono.CSharp { + "'"); } - bool IsOfType (EmitContext ec, Type l, Type r, Type t, bool check_user_conversions) + static bool IsOfType (EmitContext ec, Type l, Type r, Type t, bool check_user_conversions) { if ((l == t) || (r == t)) return true; @@ -2062,9 +1562,9 @@ namespace Mono.CSharp { long ll = ((LongConstant) right).Value; if (ll >= 0) - right = new ULongConstant ((ulong) ll); + right = new ULongConstant ((ulong) ll, right.Location); } else { - e = Convert.ImplicitNumericConversion (ec, right, l, loc); + e = Convert.ImplicitNumericConversion (right, l); if (e != null) right = e; } @@ -2079,9 +1579,9 @@ namespace Mono.CSharp { long ll = ((LongConstant) left).Value; if (ll > 0) - left = new ULongConstant ((ulong) ll); + left = new ULongConstant ((ulong) ll, right.Location); } else { - e = Convert.ImplicitNumericConversion (ec, left, r, loc); + e = Convert.ImplicitNumericConversion (left, r); if (e != null) left = e; } @@ -2123,7 +1623,7 @@ namespace Mono.CSharp { int val = ic.Value; if (val >= 0){ - right = new UIntConstant ((uint) val); + right = new UIntConstant ((uint) val, ic.Location); type = l; return true; @@ -2136,7 +1636,7 @@ namespace Mono.CSharp { int val = ic.Value; if (val >= 0){ - left = new UIntConstant ((uint) val); + left = new UIntConstant ((uint) val, ic.Location); type = r; return true; } @@ -2184,14 +1684,19 @@ namespace Mono.CSharp { } static public void Error_OperatorCannotBeApplied (Location loc, string name, Type l, Type r) + { + Error_OperatorCannotBeApplied (loc, name, TypeManager.CSharpName (l), TypeManager.CSharpName (r)); + } + + public static void Error_OperatorCannotBeApplied (Location loc, string name, string left, string right) { Report.Error (19, loc, "Operator `{0}' cannot be applied to operands of type `{1}' and `{2}'", - name, TypeManager.CSharpName (l), TypeManager.CSharpName (r)); + name, left, right); } void Error_OperatorCannotBeApplied () { - Error_OperatorCannotBeApplied (loc, OperName (oper), left.Type, right.Type); + Error_OperatorCannotBeApplied (Location, OperName (oper), left.GetSignatureForError (), right.GetSignatureForError ()); } static bool is_unsigned (Type t) @@ -2250,10 +1755,10 @@ namespace Mono.CSharp { type = e.Type; if (type == TypeManager.int32_type || type == TypeManager.uint32_type){ - right = new Binary (Binary.Operator.BitwiseAnd, right, new IntLiteral (31)); + right = new Binary (Binary.Operator.BitwiseAnd, right, new IntConstant (31, loc)); right = right.DoResolve (ec); } else { - right = new Binary (Binary.Operator.BitwiseAnd, right, new IntLiteral (63)); + right = new Binary (Binary.Operator.BitwiseAnd, right, new IntConstant (63, loc)); right = right.DoResolve (ec); } @@ -2317,10 +1822,10 @@ namespace Mono.CSharp { string op = oper_names [(int) oper]; MethodGroupExpr union; - left_operators = MemberLookup (ec, l, op, MemberTypes.Method, AllBindingFlags, loc); + left_operators = MemberLookup (ec.ContainerType, l, op, MemberTypes.Method, AllBindingFlags, loc); if (r != l){ right_operators = MemberLookup ( - ec, r, op, MemberTypes.Method, AllBindingFlags, loc); + ec.ContainerType, r, op, MemberTypes.Method, AllBindingFlags, loc); union = Invocation.MakeUnionSet (left_operators, right_operators, loc); } else union = (MethodGroupExpr) left_operators; @@ -2351,7 +1856,7 @@ namespace Mono.CSharp { // Simple constant folding if (left is StringConstant && right is StringConstant) - return new StringConstant (((StringConstant) left).Value + ((StringConstant) right).Value); + return new StringConstant (((StringConstant) left).Value + ((StringConstant) right).Value, left.Location); if (l == TypeManager.string_type || r == TypeManager.string_type) { @@ -2441,9 +1946,9 @@ namespace Mono.CSharp { // Also, a standard conversion must exist from either one // bool left_to_right = - Convert.ImplicitStandardConversionExists (ec, left, r); + Convert.ImplicitStandardConversionExists (left, r); bool right_to_left = !left_to_right && - Convert.ImplicitStandardConversionExists (ec, right, l); + Convert.ImplicitStandardConversionExists (right, l); if (!left_to_right && !right_to_left) { Error_OperatorCannotBeApplied (); @@ -2499,7 +2004,7 @@ namespace Mono.CSharp { // +, -, *, /, %, &, |, ^, ==, !=, <, >, <=, >= // if (oper == Operator.Addition || oper == Operator.Subtraction) { - if (l.IsSubclassOf (TypeManager.delegate_type)){ + if (TypeManager.IsDelegateType (l)){ if (((right.eclass == ExprClass.MethodGroup) || (r == TypeManager.anonymous_method_type))){ if ((RootContext.Version != LanguageVersion.ISO_1)){ @@ -2510,15 +2015,15 @@ namespace Mono.CSharp { r = right.Type; } } - - if (r.IsSubclassOf (TypeManager.delegate_type)){ + + if (TypeManager.IsDelegateType (r)){ MethodInfo method; ArrayList args = new ArrayList (2); - + args = new ArrayList (2); args.Add (new Argument (left, Argument.AType.Expression)); args.Add (new Argument (right, Argument.AType.Expression)); - + if (oper == Operator.Addition) method = TypeManager.delegate_combine_delegate_delegate; else @@ -2528,11 +2033,11 @@ namespace Mono.CSharp { Error_OperatorCannotBeApplied (); return null; } - + return new BinaryDelegate (l, method, args); } } - + // // Pointer arithmetic: // @@ -2756,8 +2261,48 @@ namespace Mono.CSharp { return this; } + Constant EnumLiftUp (Constant left, Constant right) + { + switch (oper) { + case Operator.BitwiseOr: + case Operator.BitwiseAnd: + case Operator.ExclusiveOr: + case Operator.Equality: + case Operator.Inequality: + case Operator.LessThan: + case Operator.LessThanOrEqual: + case Operator.GreaterThan: + case Operator.GreaterThanOrEqual: + if (left is EnumConstant) + return left; + + if (left.IsZeroInteger) + return new EnumConstant (left, right.Type); + + break; + + case Operator.Addition: + case Operator.Subtraction: + return left; + + case Operator.Multiply: + case Operator.Division: + case Operator.Modulus: + case Operator.LeftShift: + case Operator.RightShift: + if (right is EnumConstant || left is EnumConstant) + break; + return left; + } + Error_OperatorCannotBeApplied (loc, Binary.OperName (oper), left.Type, right.Type); + return null; + } + public override Expression DoResolve (EmitContext ec) { + if (left == null) + return null; + if ((oper == Operator.Subtraction) && (left is ParenthesizedExpression)) { left = ((ParenthesizedExpression) left).Expr; left = left.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.Type); @@ -2765,7 +2310,7 @@ namespace Mono.CSharp { return null; if (left.eclass == ExprClass.Type) { - Error (75, "To cast a negative value, you must enclose the value in parentheses"); + Report.Error (75, loc, "To cast a negative value, you must enclose the value in parentheses"); return null; } } else @@ -2789,9 +2334,19 @@ namespace Mono.CSharp { return null; eclass = ExprClass.Value; - Constant rc = right as Constant; + // The conversion rules are ignored in enum context but why + if (!ec.InEnumContext && lc != null && rc != null && (TypeManager.IsEnumType (left.Type) || TypeManager.IsEnumType (right.Type))) { + left = lc = EnumLiftUp (lc, rc); + if (lc == null) + return null; + + right = rc = EnumLiftUp (rc, lc); + if (rc == null) + return null; + } + if (oper == Operator.BitwiseAnd) { if (rc != null && rc.IsZeroInteger) { return lc is EnumConstant ? @@ -2812,6 +2367,11 @@ namespace Mono.CSharp { if (rc is EnumConstant && lc != null && lc.IsZeroInteger) return rc; + } else if (oper == Operator.LogicalAnd) { + if (rc != null && rc.IsDefaultValue && rc.Type == TypeManager.bool_type) + return rc; + if (lc != null && lc.IsDefaultValue && lc.Type == TypeManager.bool_type) + return lc; } if (rc != null && lc != null){ @@ -2822,20 +2382,25 @@ namespace Mono.CSharp { return e; } - // Check CS0652 warning here (before resolving operator). - if (oper == Operator.Equality || - oper == Operator.Inequality || - oper == Operator.LessThanOrEqual || - oper == Operator.LessThan || - oper == Operator.GreaterThanOrEqual || - oper == Operator.GreaterThan){ - CheckUselessComparison (left as Constant, right.Type); - CheckUselessComparison (right as Constant, left.Type); + // Comparison warnings + if (oper == Operator.Equality || oper == Operator.Inequality || + oper == Operator.LessThanOrEqual || oper == Operator.LessThan || + oper == Operator.GreaterThanOrEqual || oper == Operator.GreaterThan){ + if (left.Equals (right)) { + Report.Warning (1718, 3, loc, "Comparison made to same variable; did you mean to compare something else?"); + } + CheckUselessComparison (lc, right.Type); + CheckUselessComparison (rc, left.Type); } return ResolveOperator (ec); } + public override TypeExpr ResolveAsTypeTerminal (IResolveContext ec, bool silent) + { + return null; + } + private void CheckUselessComparison (Constant c, Type type) { if (c == null || !IsTypeIntegral (type) @@ -3335,11 +2900,21 @@ namespace Mono.CSharp { // // Constant folding // - if (operand is StringConstant && operands.Count != 0) { - StringConstant last_operand = operands [operands.Count - 1] as StringConstant; - if (last_operand != null) { - operands [operands.Count - 1] = new StringConstant (last_operand.Value + ((StringConstant) operand).Value); - return; + StringConstant sc = operand as StringConstant; + if (sc != null) { +// TODO: it will be better to do this silently as an optimalization +// int i = 0; +// string s = "" + i; +// because this code has poor performace +// if (sc.Value.Length == 0) +// Report.Warning (-300, 3, Location, "Appending an empty string has no effect. Did you intend to append a space string?"); + + if (operands.Count != 0) { + StringConstant last_operand = operands [operands.Count - 1] as StringConstant; + if (last_operand != null) { + operands [operands.Count - 1] = new StringConstant (last_operand.Value + ((StringConstant) operand).Value, last_operand.Location); + return; + } } } @@ -3495,7 +3070,7 @@ namespace Mono.CSharp { protected void Error19 () { - Binary.Error_OperatorCannotBeApplied (loc, is_and ? "&&" : "||", type, type); + Binary.Error_OperatorCannotBeApplied (loc, is_and ? "&&" : "||", left.GetSignatureForError (), right.GetSignatureForError ()); } protected void Error218 () @@ -3518,7 +3093,7 @@ namespace Mono.CSharp { return null; } - left_temp = new LocalTemporary (ec, type); + left_temp = new LocalTemporary (type); ArrayList arguments = new ArrayList (); arguments.Add (new Argument (left_temp, Argument.AType.Expression)); @@ -3633,7 +3208,7 @@ namespace Mono.CSharp { Constant right_const = right as Constant; if (right_const != null && size != 0) { - Expression ex = ConstantFold.BinaryFold (ec, Binary.Operator.Multiply, new IntConstant (size), right_const, loc); + Expression ex = ConstantFold.BinaryFold (ec, Binary.Operator.Multiply, new IntConstant (size, right.Location), right_const, loc); if (ex == null) return; ex.Emit (ec); @@ -3769,6 +3344,11 @@ namespace Mono.CSharp { return this; } + public override TypeExpr ResolveAsTypeTerminal (IResolveContext ec, bool silent) + { + return null; + } + public override void Emit (EmitContext ec) { ILGenerator ig = ec.ig; @@ -3795,7 +3375,7 @@ namespace Mono.CSharp { bool is_readonly; bool prepared; LocalTemporary temp; - + public LocalVariableReference (Block block, string name, Location l) { Block = block; @@ -3817,15 +3397,11 @@ namespace Mono.CSharp { } public VariableInfo VariableInfo { - get { - return local_info.VariableInfo; - } + get { return local_info.VariableInfo; } } public bool IsReadOnly { - get { - return is_readonly; - } + get { return is_readonly; } } public bool VerifyAssigned (EmitContext ec) @@ -3834,49 +3410,25 @@ namespace Mono.CSharp { return variable_info == null || variable_info.IsAssigned (ec, loc); } - protected Expression DoResolveBase (EmitContext ec, Expression lvalue_right_side) + void ResolveLocalInfo () { if (local_info == null) { local_info = Block.GetLocalInfo (Name); - - // is out param - if (lvalue_right_side == EmptyExpression.Null) - local_info.Used = true; - is_readonly = local_info.ReadOnly; } + } + protected Expression DoResolveBase (EmitContext ec) + { type = local_info.VariableType; - VariableInfo variable_info = local_info.VariableInfo; - if (lvalue_right_side != null){ - if (is_readonly){ - if (lvalue_right_side is LocalVariableReference || lvalue_right_side == EmptyExpression.Null) - Report.Error (1657, loc, "Cannot pass `{0}' as a ref or out argument because it is a `{1}'", - Name, local_info.GetReadOnlyContext ()); - else - Report.Error (1656, loc, "Cannot assign to `{0}' because it is a `{1}'", - Name, local_info.GetReadOnlyContext ()); - return null; - } - - if (variable_info != null) - variable_info.SetAssigned (ec); - } - Expression e = Block.GetConstantExpression (Name); - if (e != null) { - local_info.Used = true; - eclass = ExprClass.Value; + if (e != null) return e.Resolve (ec); - } if (!VerifyAssigned (ec)) return null; - if (lvalue_right_side == null) - local_info.Used = true; - if (ec.CurrentAnonymousMethod != null){ // // If we are referencing a variable from the external block @@ -3895,19 +3447,42 @@ namespace Mono.CSharp { return this; } - + public override Expression DoResolve (EmitContext ec) { - return DoResolveBase (ec, null); + ResolveLocalInfo (); + local_info.Used = true; + return DoResolveBase (ec); } override public Expression DoResolveLValue (EmitContext ec, Expression right_side) { - Expression ret = DoResolveBase (ec, right_side); - if (ret != null) - CheckObsoleteAttribute (ret.Type); - - return ret; + ResolveLocalInfo (); + + if (is_readonly) { + int code; + string msg; + if (right_side == EmptyExpression.OutAccess) { + code = 1657; msg = "Cannot pass `{0}' as a ref or out argument because it is a `{1}'"; + } else if (right_side == EmptyExpression.LValueMemberAccess) { + code = 1654; msg = "Cannot assign to members of `{0}' because it is a `{1}'"; + } else if (right_side == EmptyExpression.LValueMemberOutAccess) { + code = 1655; msg = "Cannot pass members of `{0}' as ref or out arguments because it is a `{1}'"; + } else { + code = 1656; msg = "Cannot assign to `{0}' because it is a `{1}'"; + } + Report.Error (code, loc, msg, Name, local_info.GetReadOnlyContext ()); + return null; + } + + // is out param + if (right_side == EmptyExpression.OutAccess) + local_info.Used = true; + + if (VariableInfo != null) + VariableInfo.SetAssigned (ec); + + return DoResolveBase (ec); } public bool VerifyFixed () @@ -3916,7 +3491,7 @@ namespace Mono.CSharp { return true; } - public override int GetHashCode() + public override int GetHashCode () { return Name.GetHashCode (); } @@ -3956,7 +3531,7 @@ namespace Mono.CSharp { if (leave_copy){ ec.ig.Emit (OpCodes.Dup); if (local_info.FieldBuilder != null){ - temp = new LocalTemporary (ec, Type); + temp = new LocalTemporary (Type); temp.Store (ec); } } @@ -3989,7 +3564,7 @@ namespace Mono.CSharp { source.Emit (ec); if (leave_copy){ ig.Emit (OpCodes.Dup); - temp = new LocalTemporary (ec, Type); + temp = new LocalTemporary (Type); temp.Store (ec); } ig.Emit (OpCodes.Stfld, local_info.FieldBuilder); @@ -4027,12 +3602,11 @@ namespace Mono.CSharp { /// representation. /// public class ParameterReference : Expression, IAssignMethod, IMemoryLocation, IVariable { - Parameters pars; - String name; + Parameter par; + string name; int idx; Block block; VariableInfo vi; - public Parameter.Modifier mod; public bool is_ref, is_out, prepared; public bool IsOut { @@ -4049,20 +3623,16 @@ namespace Mono.CSharp { LocalTemporary temp; - public ParameterReference (Parameters pars, Block block, int idx, string name, Location loc) + public ParameterReference (Parameter par, Block block, int idx, Location loc) { - this.pars = pars; + this.par = par; + this.name = par.Name; this.block = block; this.idx = idx; - this.name = name; this.loc = loc; eclass = ExprClass.Variable; } - public ParameterReference (InternalParameters pars, Block block, int idx, Location loc) - : this (pars.Parameters, block, idx, pars.ParameterName (idx), loc) - { } - public VariableInfo VariableInfo { get { return vi; } } @@ -4070,7 +3640,7 @@ namespace Mono.CSharp { public bool VerifyFixed () { // A parameter is fixed if it's a value parameter (i.e., no modifier like out, ref, param). - return mod == Parameter.Modifier.NONE; + return par.ModFlags == Parameter.Modifier.NONE; } public bool IsAssigned (EmitContext ec, Location loc) @@ -4079,7 +3649,7 @@ namespace Mono.CSharp { return true; Report.Error (269, loc, - "Use of unassigned out parameter `{0}'", name); + "Use of unassigned out parameter `{0}'", par.Name); return false; } @@ -4099,27 +3669,32 @@ namespace Mono.CSharp { ec.CurrentBranching.SetAssigned (vi); } - public void SetFieldAssigned (EmitContext ec, string field_name) + public void SetFieldAssigned (EmitContext ec, string field_name) { if (is_out && ec.DoFlowAnalysis) ec.CurrentBranching.SetFieldAssigned (vi, field_name); } - protected void DoResolveBase (EmitContext ec) + protected bool DoResolveBase (EmitContext ec) { - type = pars.GetParameterInfo (ec, idx, out mod); + if (!par.Resolve (ec)) { + //TODO: + } + + type = par.ParameterType; + Parameter.Modifier mod = par.ModFlags; is_ref = (mod & Parameter.Modifier.ISBYREF) != 0; - is_out = (mod & Parameter.Modifier.OUT) != 0; + is_out = (mod & Parameter.Modifier.OUT) == Parameter.Modifier.OUT; eclass = ExprClass.Variable; if (is_out) vi = block.ParameterMap [idx]; if (ec.CurrentAnonymousMethod != null){ - if (is_ref){ + if (is_ref && !block.Toplevel.IsLocalParameter (name)){ Report.Error (1628, Location, "Cannot use ref or out parameter `{0}' inside an anonymous method block", - name); - return; + par.Name); + return false; } // @@ -4131,6 +3706,8 @@ namespace Mono.CSharp { ec.CaptureParameter (name, type, idx); } } + + return true; } public override int GetHashCode() @@ -4161,7 +3738,8 @@ namespace Mono.CSharp { // public override Expression DoResolve (EmitContext ec) { - DoResolveBase (ec); + if (!DoResolveBase (ec)) + return null; if (is_out && ec.DoFlowAnalysis && (!ec.OmitStructFlowAnalysis || !vi.TypeInfo.IsStruct) && !IsAssigned (ec, loc)) return null; @@ -4171,7 +3749,8 @@ namespace Mono.CSharp { override public Expression DoResolveLValue (EmitContext ec, Expression right_side) { - DoResolveBase (ec); + if (!DoResolveBase (ec)) + return null; SetAssigned (ec); @@ -4223,11 +3802,8 @@ namespace Mono.CSharp { ILGenerator ig = ec.ig; int arg_idx = idx; - if (ec.HaveCaptureInfo && ec.IsParameterCaptured (name)){ - if (leave_copy) - throw new InternalErrorException (); - - ec.EmitParameter (name); + if (ec.HaveCaptureInfo && ec.IsParameterCaptured (name)){ + ec.EmitParameter (name, leave_copy, prepared, ref temp); return; } @@ -4251,7 +3827,7 @@ namespace Mono.CSharp { ec.ig.Emit (OpCodes.Dup); if (is_ref) { - temp = new LocalTemporary (ec, type); + temp = new LocalTemporary (type); temp.Store (ec); } } @@ -4259,15 +3835,16 @@ namespace Mono.CSharp { public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) { + prepared = prepare_for_load; if (ec.HaveCaptureInfo && ec.IsParameterCaptured (name)){ - ec.EmitAssignParameter (name, source, leave_copy, prepare_for_load); + ec.EmitAssignParameter (name, source, leave_copy, prepare_for_load, ref temp); return; } ILGenerator ig = ec.ig; int arg_idx = idx; - prepared = prepare_for_load; + if (!ec.MethodIsStatic) arg_idx++; @@ -4282,7 +3859,7 @@ namespace Mono.CSharp { if (is_ref) { if (leave_copy) { - temp = new LocalTemporary (ec, type); + temp = new LocalTemporary (type); temp.Store (ec); } @@ -4323,6 +3900,10 @@ namespace Mono.CSharp { } } + public override string ToString () + { + return "ParameterReference[" + name + "]"; + } } /// @@ -4365,10 +3946,10 @@ namespace Mono.CSharp { get { switch (ArgType) { case AType.Out: - return Parameter.Modifier.OUT | Parameter.Modifier.ISBYREF; + return Parameter.Modifier.OUT; case AType.Ref: - return Parameter.Modifier.REF | Parameter.Modifier.ISBYREF; + return Parameter.Modifier.REF; default: return Parameter.Modifier.NONE; @@ -4386,7 +3967,7 @@ namespace Mono.CSharp { TypeManager.CSharpName (a.Expr.Type); } - public bool ResolveMethodGroup (EmitContext ec, Location loc) + public bool ResolveMethodGroup (EmitContext ec) { // FIXME: csc doesn't report any error if you try to use `ref' or // `out' in a delegate creation expression. @@ -4396,118 +3977,47 @@ namespace Mono.CSharp { return true; } - - void Error_LValueRequired (Location loc) - { - Report.Error (1510, loc, "A ref or out argument must be an assignable variable"); - } public bool Resolve (EmitContext ec, Location loc) { bool old_do_flow_analysis = ec.DoFlowAnalysis; ec.DoFlowAnalysis = true; - if (ArgType == AType.Ref) { - ec.InRefOutArgumentResolving = true; + // Verify that the argument is readable + if (ArgType != AType.Out) Expr = Expr.Resolve (ec); - ec.InRefOutArgumentResolving = false; - if (Expr == null) { - ec.DoFlowAnalysis = old_do_flow_analysis; - return false; - } - Expr = Expr.DoResolveLValue (ec, Expr); - if (Expr == null) - Error_LValueRequired (loc); - } else if (ArgType == AType.Out) { - ec.InRefOutArgumentResolving = true; - Expr = Expr.DoResolveLValue (ec, EmptyExpression.Null); - ec.InRefOutArgumentResolving = false; - - if (Expr == null) - Error_LValueRequired (loc); - } - else - Expr = Expr.Resolve (ec); + // Verify that the argument is writeable + if (Expr != null && (ArgType == AType.Out || ArgType == AType.Ref)) + Expr = Expr.ResolveLValue (ec, EmptyExpression.OutAccess, loc); ec.DoFlowAnalysis = old_do_flow_analysis; - if (Expr == null) - return false; + return Expr != null; + } - if (ArgType == AType.Expression) - return true; - else { - // - // Catch errors where fields of a MarshalByRefObject are passed as ref or out - // This is only allowed for `this' - // - FieldExpr fe = Expr as FieldExpr; - if (fe != null && !fe.IsStatic){ - Expression instance = fe.InstanceExpression; - - if (instance.GetType () != typeof (This)){ - if (fe.InstanceExpression.Type.IsSubclassOf (TypeManager.mbr_type)){ - Report.SymbolRelatedToPreviousError (fe.InstanceExpression.Type); - Report.Warning (197, 1, loc, - "Passing `{0}' as ref or out or taking its address may cause a runtime exception because it is a field of a marshal-by-reference class", - fe.GetSignatureForError ()); - return false; - } - } - } + public void Emit (EmitContext ec) + { + if (ArgType != AType.Ref && ArgType != AType.Out) { + Expr.Emit (ec); + return; } - if (Expr.eclass != ExprClass.Variable){ - // - // We just probe to match the CSC output - // - if (Expr.eclass == ExprClass.PropertyAccess || - Expr.eclass == ExprClass.IndexerAccess){ - Report.Error (206, loc, "A property or indexer `{0}' may not be passed as an out or ref parameter", - Expr.GetSignatureForError ()); - } else { - Error_LValueRequired (loc); - } - return false; - } + AddressOp mode = AddressOp.Store; + if (ArgType == AType.Ref) + mode |= AddressOp.Load; - return true; - } + IMemoryLocation ml = (IMemoryLocation) Expr; + ParameterReference pr = ml as ParameterReference; - public void Emit (EmitContext ec) - { - // - // Ref and Out parameters need to have their addresses taken. // // ParameterReferences might already be references, so we want // to pass just the value // - if (ArgType == AType.Ref || ArgType == AType.Out){ - AddressOp mode = AddressOp.Store; - - if (ArgType == AType.Ref) - mode |= AddressOp.Load; - - if (Expr is ParameterReference){ - ParameterReference pr = (ParameterReference) Expr; - - if (pr.IsRef) - pr.EmitLoad (ec); - else { - - pr.AddressOf (ec, mode); - } - } else { - if (Expr is IMemoryLocation) - ((IMemoryLocation) Expr).AddressOf (ec, mode); - else { - Error_LValueRequired (Expr.Location); - return; - } - } - } else - Expr.Emit (ec); + if (pr != null && pr.IsRef) + pr.EmitLoad (ec); + else + ml.AddressOf (ec, mode); } } @@ -4547,7 +4057,7 @@ namespace Mono.CSharp { /// q if a->q is better, /// null if neither is better /// - static Type BetterConversion (EmitContext ec, Argument a, Type p, Type q, Location loc) + static Type BetterConversion (EmitContext ec, Argument a, Type p, Type q) { Type argument_type = a.Type; Expression argument_expr = a.Expr; @@ -4642,13 +4152,13 @@ namespace Mono.CSharp { /// and the current best match /// /// - /// Returns an integer indicating : + /// Returns a boolean indicating : /// false if candidate ain't better - /// true if candidate is better than the current best match + /// true if candidate is better than the current best match /// static bool BetterFunction (EmitContext ec, ArrayList args, int argument_count, MethodBase candidate, bool candidate_params, - MethodBase best, bool best_params, Location loc) + MethodBase best, bool best_params) { ParameterData candidate_pd = TypeManager.GetParameterData (candidate); ParameterData best_pd = TypeManager.GetParameterData (best); @@ -4673,7 +4183,7 @@ namespace Mono.CSharp { continue; same = false; - Type better = BetterConversion (ec, a, ct, bt, loc); + Type better = BetterConversion (ec, a, ct, bt); // for each argument, the conversion to 'ct' should be no worse than // the conversion to 'bt'. @@ -4711,7 +4221,7 @@ namespace Mono.CSharp { return !candidate_params && best_params; } - static bool IsOverride (MethodBase cand_method, MethodBase base_method) + internal static bool IsOverride (MethodBase cand_method, MethodBase base_method) { if (!IsAncestralType (base_method.DeclaringType, cand_method.DeclaringType)) return false; @@ -4797,24 +4307,16 @@ namespace Mono.CSharp { return union; } - public static bool IsParamsMethodApplicable (EmitContext ec, MethodGroupExpr me, + public static bool IsParamsMethodApplicable (EmitContext ec, ArrayList arguments, int arg_count, - ref MethodBase candidate) + MethodBase candidate) { return IsParamsMethodApplicable ( - ec, me, arguments, arg_count, false, ref candidate) || + ec, arguments, arg_count, candidate, false) || IsParamsMethodApplicable ( - ec, me, arguments, arg_count, true, ref candidate); - + ec, arguments, arg_count, candidate, true); - } - static bool IsParamsMethodApplicable (EmitContext ec, MethodGroupExpr me, - ArrayList arguments, int arg_count, - bool do_varargs, ref MethodBase candidate) - { - return IsParamsMethodApplicable ( - ec, arguments, arg_count, candidate, do_varargs); } /// @@ -4838,7 +4340,7 @@ namespace Mono.CSharp { if (pd_count != arg_count) return false; } else { - if (pd.ParameterModifier (count) != Parameter.Modifier.PARAMS) + if (!pd.HasParams) return false; } @@ -4858,9 +4360,9 @@ namespace Mono.CSharp { Argument a = (Argument) arguments [i]; Parameter.Modifier a_mod = a.Modifier & - (unchecked (~(Parameter.Modifier.OUT | Parameter.Modifier.REF))); + (unchecked (~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK))); Parameter.Modifier p_mod = pd.ParameterModifier (i) & - (unchecked (~(Parameter.Modifier.OUT | Parameter.Modifier.REF))); + (unchecked (~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK))); if (a_mod == p_mod) { @@ -4868,8 +4370,8 @@ namespace Mono.CSharp { if (!Convert.ImplicitConversionExists (ec, a.Expr, pd.ParameterType (i))) - return false; - + return false; + if ((a_mod & Parameter.Modifier.ISBYREF) != 0) { Type pt = pd.ParameterType (i); @@ -4904,19 +4406,12 @@ namespace Mono.CSharp { return true; } - public static bool IsApplicable (EmitContext ec, MethodGroupExpr me, - ArrayList arguments, int arg_count, - ref MethodBase candidate) - { - return IsApplicable (ec, arguments, arg_count, candidate); - } - /// /// Determines if the candidate method is applicable (section 14.4.2.1) /// to the given set of arguments /// - static bool IsApplicable (EmitContext ec, ArrayList arguments, int arg_count, - MethodBase candidate) + public static bool IsApplicable (EmitContext ec, ArrayList arguments, int arg_count, + MethodBase candidate) { ParameterData pd = TypeManager.GetParameterData (candidate); @@ -4929,28 +4424,22 @@ namespace Mono.CSharp { Argument a = (Argument) arguments [i]; Parameter.Modifier a_mod = a.Modifier & - unchecked (~(Parameter.Modifier.OUT | Parameter.Modifier.REF)); + ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK); + Parameter.Modifier p_mod = pd.ParameterModifier (i) & - unchecked (~(Parameter.Modifier.OUT | Parameter.Modifier.REF)); + ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK | Parameter.Modifier.PARAMS); - if (a_mod == p_mod || - (a_mod == Parameter.Modifier.NONE && p_mod == Parameter.Modifier.PARAMS)) { - if (a_mod == Parameter.Modifier.NONE) { - if (!Convert.ImplicitConversionExists (ec, - a.Expr, - pd.ParameterType (i))) - return false; - } - - if ((a_mod & Parameter.Modifier.ISBYREF) != 0) { - Type pt = pd.ParameterType (i); + if (a_mod == p_mod) { + Type pt = pd.ParameterType (i); - if (!pt.IsByRef) - pt = TypeManager.GetReferenceType (pt); - - if (pt != a.Type) + if (a_mod == Parameter.Modifier.NONE) { + if (!Convert.ImplicitConversionExists (ec, a.Expr, pt)) return false; + continue; } + + if (pt != a.Type) + return false; } else return false; } @@ -4958,10 +4447,10 @@ namespace Mono.CSharp { return true; } - static private bool IsAncestralType (Type first_type, Type second_type) + static internal bool IsAncestralType (Type first_type, Type second_type) { return first_type != second_type && - (second_type.IsSubclassOf (first_type) || + (TypeManager.IsSubclassOf (second_type, first_type) || TypeManager.ImplementsInterface (second_type, first_type)); } @@ -4982,7 +4471,7 @@ namespace Mono.CSharp { /// /// public static MethodBase OverloadResolve (EmitContext ec, MethodGroupExpr me, - ArrayList Arguments, bool may_fail, + ArrayList Arguments, bool may_fail, Location loc) { MethodBase method = null; @@ -5012,45 +4501,57 @@ namespace Mono.CSharp { MethodBase[] methods = me.Methods; + int nmethods = methods.Length; + + if (!me.IsBase) { + // + // Methods marked 'override' don't take part in 'applicable_type' + // computation, nor in the actual overload resolution. + // However, they still need to be emitted instead of a base virtual method. + // So, we salt them away into the 'candidate_overrides' array. + // + // In case of reflected methods, we replace each overriding method with + // its corresponding base virtual method. This is to improve compatibility + // with non-C# libraries which change the visibility of overrides (#75636) + // + int j = 0; + for (int i = 0; i < methods.Length; ++i) { + MethodBase m = methods [i]; + if (TypeManager.IsOverride (m)) { + if (candidate_overrides == null) + candidate_overrides = new ArrayList (); + candidate_overrides.Add (m); + m = TypeManager.TryGetBaseDefinition (m); + } + if (m != null) + methods [j++] = m; + } + nmethods = j; + } + + int applicable_errors = Report.Errors; + // // First we construct the set of applicable methods // bool is_sorted = true; - for (int i = 0; i < methods.Length; i++){ + for (int i = 0; i < nmethods; i++){ Type decl_type = methods [i].DeclaringType; // // If we have already found an applicable method // we eliminate all base types (Section 14.5.5.1) // - if ((applicable_type != null) && - IsAncestralType (decl_type, applicable_type)) + if (applicable_type != null && IsAncestralType (decl_type, applicable_type)) continue; - // - // Methods marked 'override' don't take part in 'applicable_type' - // computation, nor in the actual overload resolution. - // However, they still need to be emitted instead of a base virtual method. - // We avoid doing the 'applicable' test here, since it'll anyway be applied - // to the base virtual function, and IsOverride is much faster than IsApplicable. - // - if (!me.IsBase && TypeManager.IsOverride (methods [i])) { - if (candidate_overrides == null) - candidate_overrides = new ArrayList (); - candidate_overrides.Add (methods [i]); - continue; - } - // // Check if candidate is applicable (section 14.4.2.1) // Is candidate applicable in normal form? // - bool is_applicable = IsApplicable ( - ec, me, Arguments, arg_count, ref methods [i]); + bool is_applicable = IsApplicable (ec, Arguments, arg_count, methods [i]); - if (!is_applicable && - (IsParamsMethodApplicable ( - ec, me, Arguments, arg_count, ref methods [i]))) { + if (!is_applicable && IsParamsMethodApplicable (ec, Arguments, arg_count, methods [i])) { MethodBase candidate = methods [i]; if (candidate_to_form == null) candidate_to_form = new PtrHashtable (); @@ -5073,6 +4574,9 @@ namespace Mono.CSharp { } } + if (applicable_errors != Report.Errors) + return null; + int candidate_top = candidates.Count; if (applicable_type == null) { @@ -5081,7 +4585,7 @@ namespace Mono.CSharp { // return by providing info about the closest match // int errors = Report.Errors; - for (int i = 0; i < methods.Length; ++i) { + for (int i = 0; i < nmethods; ++i) { MethodBase c = (MethodBase) methods [i]; ParameterData pd = TypeManager.GetParameterData (c); @@ -5176,7 +4680,7 @@ namespace Mono.CSharp { if (BetterFunction (ec, Arguments, arg_count, candidate, cand_params, - method, method_params, loc)) { + method, method_params)) { method = candidate; method_params = cand_params; } @@ -5195,8 +4699,7 @@ namespace Mono.CSharp { bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate); if (!BetterFunction (ec, Arguments, arg_count, method, method_params, - candidate, cand_params, - loc)) { + candidate, cand_params)) { Report.SymbolRelatedToPreviousError (candidate); ambiguous = candidate; } @@ -5234,18 +4737,20 @@ namespace Mono.CSharp { method_params, null, may_fail, loc)) return null; - if (method != null) { - IMethodData data = TypeManager.GetMethod (method); - if (data != null) - data.SetMemberIsUsed (); - } + if (method == null) + return null; + + IMethodData data = TypeManager.GetMethod (method); + if (data != null) + data.SetMemberIsUsed (); + return method; } public static void Error_WrongNumArguments (Location loc, String name, int arg_count) { Report.Error (1501, loc, "No overload for method `{0}' takes `{1}' arguments", - name, arg_count); + name, arg_count.ToString ()); } static void Error_InvokeOnDelegate (Location loc) @@ -5264,21 +4769,20 @@ namespace Mono.CSharp { Report.Error (1594, loc, "Delegate `{0}' has some invalid arguments", TypeManager.CSharpName (delegate_type)); - string par_desc = expected_par.ParameterDesc (idx); + Parameter.Modifier mod = expected_par.ParameterModifier (idx); - if (a.Modifier != expected_par.ParameterModifier (idx)) { - if ((expected_par.ParameterModifier (idx) & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) == 0) + string index = (idx + 1).ToString (); + if (mod != Parameter.Modifier.ARGLIST && mod != a.Modifier) { + if ((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) == 0) Report.Error (1615, loc, "Argument `{0}' should not be passed with the `{1}' keyword", - idx + 1, Parameter.GetModifierSignature (a.Modifier)); + index, Parameter.GetModifierSignature (a.Modifier)); else Report.Error (1620, loc, "Argument `{0}' must be passed with the `{1}' keyword", - idx + 1, Parameter.GetModifierSignature (expected_par.ParameterModifier (idx))); - return; + index, Parameter.GetModifierSignature (mod)); + } else { + Report.Error (1503, loc, "Argument {0}: Cannot convert from `{1}' to `{2}'", + index, Argument.FullDesc (a), expected_par.ParameterDesc (idx)); } - - Report.Error (1503, loc, - String.Format ("Argument {0}: Cannot convert from `{1}' to `{2}'", - idx + 1, Argument.FullDesc (a), par_desc)); } public static bool VerifyArgumentsCompat (EmitContext ec, ArrayList Arguments, @@ -5288,88 +4792,63 @@ namespace Mono.CSharp { Location loc) { ParameterData pd = TypeManager.GetParameterData (method); - int pd_count = pd.Count; - - for (int j = 0; j < arg_count; j++) { + int j; + for (j = 0; j < arg_count; j++) { Argument a = (Argument) Arguments [j]; Expression a_expr = a.Expr; Type parameter_type = pd.ParameterType (j); Parameter.Modifier pm = pd.ParameterModifier (j); - - if (pm == Parameter.Modifier.PARAMS){ - if ((pm & ~Parameter.Modifier.PARAMS) != a.Modifier) { - if (!may_fail) - Error_InvalidArguments ( - loc, j, method, delegate_type, - a, pd); - return false; - } + Parameter.Modifier am = a.Modifier; + if (pm == Parameter.Modifier.ARGLIST) { + if (!(a.Expr is Arglist)) + break; + continue; + } + + if (pm == Parameter.Modifier.PARAMS) { + pm = Parameter.Modifier.NONE; if (chose_params_expanded) parameter_type = TypeManager.GetElementType (parameter_type); - } else if (pm == Parameter.Modifier.ARGLIST){ - continue; - } else { - // - // Check modifiers - // - if (pd.ParameterModifier (j) != a.Modifier){ - if (!may_fail) - Error_InvalidArguments ( - loc, j, method, delegate_type, - a, pd); - return false; - } } - // - // Check Type - // - if (!a.Type.Equals (parameter_type)){ - Expression conv; - - conv = Convert.ImplicitConversion (ec, a_expr, parameter_type, loc); + if (pm != am) + break; + + if (!a.Type.Equals (parameter_type)) { + if (pm == Parameter.Modifier.OUT || pm == Parameter.Modifier.REF) + break; + + Expression conv = Convert.ImplicitConversion (ec, a_expr, parameter_type, loc); + if (conv == null) + break; - if (conv == null) { - if (!may_fail) - Error_InvalidArguments (loc, j, method, delegate_type, a, pd); - return false; - } - - // // Update the argument with the implicit conversion - // if (a_expr != conv) a.Expr = conv; } - if (parameter_type.IsPointer){ - if (!ec.InUnsafe){ - UnsafeError (loc); - return false; - } - } - - Parameter.Modifier a_mod = a.Modifier & - unchecked (~(Parameter.Modifier.OUT | Parameter.Modifier.REF)); - Parameter.Modifier p_mod = pd.ParameterModifier (j) & - unchecked (~(Parameter.Modifier.OUT | Parameter.Modifier.REF)); - - if (a_mod != p_mod && - pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS) { - if (!may_fail) { - Invocation.Error_InvalidArguments (loc, j, method, null, a, pd); - } - + if (parameter_type.IsPointer && !ec.InUnsafe) { + UnsafeError (loc); return false; } } - return true; + if (j == arg_count) + return true; + + if (!may_fail) + Error_InvalidArguments (loc, j, method, delegate_type, (Argument) Arguments [j], pd); + return false; } + private bool resolved = false; public override Expression DoResolve (EmitContext ec) { + if (resolved) + return this.method == null ? null : this; + + resolved = true; // // First, resolve the expression that is used to // trigger the invocation @@ -5405,7 +4884,7 @@ namespace Mono.CSharp { } MethodGroupExpr mg = (MethodGroupExpr) expr; - method = OverloadResolve (ec, mg, Arguments, false, loc); + MethodBase method = OverloadResolve (ec, mg, Arguments, false, loc); if (method == null) return null; @@ -5459,9 +4938,10 @@ namespace Mono.CSharp { } if (mg.InstanceExpression != null) - mg.InstanceExpression.CheckMarshallByRefAccess (ec.ContainerType); + mg.InstanceExpression.CheckMarshalByRefAccess (); eclass = ExprClass.Value; + this.method = method; return this; } @@ -5541,33 +5021,12 @@ namespace Mono.CSharp { /// public static void EmitArguments (EmitContext ec, MethodBase mb, ArrayList arguments, bool dup_args, LocalTemporary this_arg) { - ParameterData pd; - if (mb != null) - pd = TypeManager.GetParameterData (mb); - else - pd = null; - + ParameterData pd = mb == null ? null : TypeManager.GetParameterData (mb); + int top = arguments == null ? 0 : arguments.Count; LocalTemporary [] temps = null; - if (dup_args) - temps = new LocalTemporary [arguments.Count]; - - // - // If we are calling a params method with no arguments, special case it - // - if (arguments == null){ - if (pd != null && pd.Count > 0 && - pd.ParameterModifier (0) == Parameter.Modifier.PARAMS){ - ILGenerator ig = ec.ig; - - IntConstant.EmitInt (ig, 0); - ig.Emit (OpCodes.Newarr, TypeManager.GetElementType (pd.ParameterType (0))); - } - - return; - } - - int top = arguments.Count; + if (dup_args && top != 0) + temps = new LocalTemporary [top]; for (int i = 0; i < top; i++){ Argument a = (Argument) arguments [i]; @@ -5589,7 +5048,7 @@ namespace Mono.CSharp { a.Emit (ec); if (dup_args) { ec.ig.Emit (OpCodes.Dup); - (temps [i] = new LocalTemporary (ec, a.Type)).Store (ec); + (temps [i] = new LocalTemporary (a.Type)).Store (ec); } } @@ -5610,8 +5069,7 @@ namespace Mono.CSharp { } } - static Type[] GetVarargsTypes (EmitContext ec, MethodBase mb, - ArrayList arguments) + static Type[] GetVarargsTypes (MethodBase mb, ArrayList arguments) { ParameterData pd = TypeManager.GetParameterData (mb); @@ -5627,14 +5085,14 @@ namespace Mono.CSharp { /// /// This checks the ConditionalAttribute on the method /// - static bool IsMethodExcluded (MethodBase method, EmitContext ec) + static bool IsMethodExcluded (MethodBase method) { if (method.IsConstructor) return false; IMethodData md = TypeManager.GetMethod (method); if (md != null) - return md.IsExcluded (ec); + return md.IsExcluded (); // For some methods (generated by delegate class) GetMethod returns null // because they are not included in builder_to_method table @@ -5703,7 +5161,7 @@ namespace Mono.CSharp { method = TypeManager.void_array_copyto_array_int; } - if (ec.TestObsoleteMethodUsage) { + if (!ec.IsInObsoleteScope) { // // This checks ObsoleteAttribute on the method and on the declaring type // @@ -5711,15 +5169,14 @@ namespace Mono.CSharp { if (oa != null) AttributeTester.Report_ObsoleteMessage (oa, TypeManager.CSharpSignature (method), loc); - oa = AttributeTester.GetObsoleteAttribute (method.DeclaringType); if (oa != null) { AttributeTester.Report_ObsoleteMessage (oa, method.DeclaringType.FullName, loc); } } - if (IsMethodExcluded (method, ec)) - return; + if (IsMethodExcluded (method)) + return; if (!is_static){ if (instance_expr == EmptyExpression.Null) { @@ -5730,13 +5187,16 @@ namespace Mono.CSharp { this_call = instance_expr is This; if (decl_type.IsValueType || (!this_call && instance_expr.Type.IsValueType)) struct_call = true; - + + // + // If this is ourselves, push "this" + // if (!omit_args) { Type t = null; // // Push the instance expression // - if (instance_expr.Type.IsValueType) { + if (TypeManager.IsValueType (instance_expr.Type)) { // // Special case: calls to a function declared in a // reference-type with a value-type argument need @@ -5753,7 +5213,7 @@ namespace Mono.CSharp { ((IMemoryLocation)instance_expr). AddressOf (ec, AddressOp.LoadStore); } else { - LocalTemporary temp = new LocalTemporary (ec, instance_expr.Type); + LocalTemporary temp = new LocalTemporary (instance_expr.Type); instance_expr.Emit (ec); temp.Store (ec); temp.AddressOf (ec, AddressOp.Load); @@ -5773,9 +5233,11 @@ namespace Mono.CSharp { } if (dup_args) { - this_arg = new LocalTemporary (ec, t); ig.Emit (OpCodes.Dup); - this_arg.Store (ec); + if (Arguments != null && Arguments.Count != 0) { + this_arg = new LocalTemporary (t); + this_arg.Store (ec); + } } } } @@ -5790,7 +5252,7 @@ namespace Mono.CSharp { call_op = OpCodes.Callvirt; if ((method.CallingConvention & CallingConventions.VarArgs) != 0) { - Type[] varargs_types = GetVarargsTypes (ec, method, Arguments); + Type[] varargs_types = GetVarargsTypes (method, Arguments); ig.EmitCall (call_op, (MethodInfo) method, varargs_types); return; } @@ -6019,35 +5481,58 @@ namespace Mono.CSharp { public static Constant Constantify (Type t) { if (t == TypeManager.int32_type) - return new IntConstant (0); + return new IntConstant (0, Location.Null); if (t == TypeManager.uint32_type) - return new UIntConstant (0); + return new UIntConstant (0, Location.Null); if (t == TypeManager.int64_type) - return new LongConstant (0); + return new LongConstant (0, Location.Null); if (t == TypeManager.uint64_type) - return new ULongConstant (0); + return new ULongConstant (0, Location.Null); if (t == TypeManager.float_type) - return new FloatConstant (0); + return new FloatConstant (0, Location.Null); if (t == TypeManager.double_type) - return new DoubleConstant (0); + return new DoubleConstant (0, Location.Null); if (t == TypeManager.short_type) - return new ShortConstant (0); + return new ShortConstant (0, Location.Null); if (t == TypeManager.ushort_type) - return new UShortConstant (0); + return new UShortConstant (0, Location.Null); if (t == TypeManager.sbyte_type) - return new SByteConstant (0); + return new SByteConstant (0, Location.Null); if (t == TypeManager.byte_type) - return new ByteConstant (0); + return new ByteConstant (0, Location.Null); if (t == TypeManager.char_type) - return new CharConstant ('\0'); + return new CharConstant ('\0', Location.Null); if (t == TypeManager.bool_type) - return new BoolConstant (false); + return new BoolConstant (false, Location.Null); if (t == TypeManager.decimal_type) - return new DecimalConstant (0); + return new DecimalConstant (0, Location.Null); return null; } + // + // Checks whether the type is an interface that has the + // [ComImport, CoClass] attributes and must be treated + // specially + // + public Expression CheckComImport (EmitContext ec) + { + if (!type.IsInterface) + return null; + + // + // Turn the call into: + // (the-interface-stated) (new class-referenced-in-coclassattribute ()) + // + Type real_class = AttributeTester.GetCoClassAttribute (type); + if (real_class == null) + return null; + + New proxy = new New (new TypeExpression (real_class, loc), Arguments, loc); + Cast cast = new Cast (new TypeExpression (type, loc), proxy, loc); + return cast.Resolve (ec); + } + public override Expression DoResolve (EmitContext ec) { // @@ -6068,7 +5553,7 @@ namespace Mono.CSharp { if (texpr == null) return null; - type = texpr.ResolveType (ec); + type = texpr.Type; if (Arguments == null) { Expression c = Constantify (type); @@ -6076,9 +5561,7 @@ namespace Mono.CSharp { return c; } - CheckObsoleteAttribute (type); - - if (TypeManager.IsDelegateType (type)) { + if (TypeManager.IsDelegateType (type)) { RequestedType = (new NewDelegate (type, Arguments, loc)).Resolve (ec); if (RequestedType != null) if (!(RequestedType is DelegateCreation)) @@ -6093,6 +5576,10 @@ namespace Mono.CSharp { } if (type.IsInterface || type.IsAbstract){ + RequestedType = CheckComImport (ec); + if (RequestedType != null) + return RequestedType; + Report.SymbolRelatedToPreviousError (type); Report.Error (144, loc, "Cannot create an instance of the abstract class or interface `{0}'", TypeManager.CSharpName (type)); return null; @@ -6118,7 +5605,7 @@ namespace Mono.CSharp { MethodGroupExpr mg = ml as MethodGroupExpr; if (mg == null) { - ml.Error_UnexpectedKind (ec, "method group", loc); + ml.Error_UnexpectedKind (ec.DeclContainer, "method group", loc); return null; } @@ -6132,7 +5619,7 @@ namespace Mono.CSharp { method = Invocation.OverloadResolve (ec, mg, Arguments, false, loc); if (method == null) { if (almostMatchedMembers.Count != 0) - MemberLookupFailed (ec, type, type, ".ctor", null, true, loc); + MemberLookupFailed (ec.ContainerType, type, type, ".ctor", null, true, loc); return null; } @@ -6165,7 +5652,7 @@ namespace Mono.CSharp { // bool DoEmit (EmitContext ec, bool need_value_on_stack) { - bool is_value_type = type.IsValueType; + bool is_value_type = TypeManager.IsValueType (type); ILGenerator ig = ec.ig; if (is_value_type){ @@ -6175,7 +5662,7 @@ namespace Mono.CSharp { // We need to create a new LocalTemporary each time since // you can't share LocalBuilders among ILGeneators. if (!value_target_set) - value_target = new LocalTemporary (ec, type); + value_target = new LocalTemporary (type); ml = (IMemoryLocation) value_target; ml.AddressOf (ec, AddressOp.Store); @@ -6224,7 +5711,7 @@ namespace Mono.CSharp { } if (!value_target_set) - value_target = new LocalTemporary (ec, type); + value_target = new LocalTemporary (type); IMemoryLocation ml = (IMemoryLocation) value_target; ml.AddressOf (ec, AddressOp.Store); @@ -6276,15 +5763,10 @@ namespace Mono.CSharp { ArrayList array_data; - Hashtable bounds; - - // - // The number of array initializers that we can handle - // via the InitializeArray method - through EmitStaticInitializers - // - int num_automatic_initializers; + IDictionary bounds; - const int max_automatic_initializers = 6; + // The number of constants in array initializers + int const_initializers_count; public ArrayCreation (Expression requested_base_type, ArrayList exprs, string rank, ArrayList initializers, Location l) { @@ -6334,20 +5816,25 @@ namespace Mono.CSharp { Error (178, "Invalid rank specifier: expected `,' or `]'"); } - public bool CheckIndices (EmitContext ec, ArrayList probe, int idx, bool specified_dims) + bool CheckIndices (EmitContext ec, ArrayList probe, int idx, bool specified_dims) { if (specified_dims) { Argument a = (Argument) arguments [idx]; - + if (!a.Resolve (ec, loc)) return false; - - if (!(a.Expr is Constant)) { - Error (150, "A constant value is expected"); + + Constant c = a.Expr as Constant; + if (c != null) { + c = c.ToType (TypeManager.int32_type, a.Expr.Location); + } + + if (c == null) { + Report.Error (150, a.Expr.Location, "A constant value is expected"); return false; } - - int value = (int) ((Constant) a.Expr).GetValue (); + + int value = (int) c.GetValue (); if (value != probe.Count) { Error_IncorrectArrayInitializer (); @@ -6371,7 +5858,7 @@ namespace Mono.CSharp { Error_IncorrectArrayInitializer (); return false; } - if (specified_dims && (idx + 1 >= arguments.Count)){ + if (idx + 1 >= dimensions){ Error (623, "Array initializers can only be used in a variable or field initializer. Try using a new expression instead"); return false; } @@ -6387,43 +5874,42 @@ namespace Mono.CSharp { Expression tmp = (Expression) o; tmp = tmp.Resolve (ec); - probe [i] = tmp; if (tmp == null) return false; - // Console.WriteLine ("I got: " + tmp); - // Handle initialization from vars, fields etc. - Expression conv = Convert.ImplicitConversionRequired ( ec, tmp, underlying_type, loc); if (conv == null) return false; + + // Initializers with the default values can be ignored + Constant c = tmp as Constant; + if (c != null) { + if (c.IsDefaultInitializer (array_element_type)) { + conv = null; + } + else { + ++const_initializers_count; + } + } else { + // Used to invalidate static initializer + const_initializers_count = int.MinValue; + } - if (conv is StringConstant || conv is DecimalConstant || conv is NullCast) { - // These are subclasses of Constant that can appear as elements of an - // array that cannot be statically initialized (with num_automatic_initializers - // > max_automatic_initializers), so num_automatic_initializers should be left as zero. - array_data.Add (conv); - } else if (conv is Constant) { - // These are the types of Constant that can appear in arrays that can be - // statically allocated. - array_data.Add (conv); - num_automatic_initializers++; - } else - array_data.Add (conv); + array_data.Add (conv); } } return true; } - public void UpdateIndices (EmitContext ec) + public void UpdateIndices () { int i = 0; for (ArrayList probe = initializers; probe != null;) { if (probe.Count > 0 && probe [0] is ArrayList) { - Expression e = new IntConstant (probe.Count); + Expression e = new IntConstant (probe.Count, Location.Null); arguments.Add (new Argument (e, Argument.AType.Expression)); bounds [i++] = probe.Count; @@ -6431,23 +5917,20 @@ namespace Mono.CSharp { probe = (ArrayList) probe [0]; } else { - Expression e = new IntConstant (probe.Count); + Expression e = new IntConstant (probe.Count, Location.Null); arguments.Add (new Argument (e, Argument.AType.Expression)); bounds [i++] = probe.Count; - probe = null; + return; } } } - public bool ValidateInitializers (EmitContext ec, Type array_type) + bool ResolveInitializers (EmitContext ec) { if (initializers == null) { - if (expect_initializers) - return false; - else - return true; + return !expect_initializers; } if (underlying_type == null) @@ -6458,30 +5941,24 @@ namespace Mono.CSharp { // will need to store them in the byte blob later // array_data = new ArrayList (); - bounds = new Hashtable (); + bounds = new System.Collections.Specialized.HybridDictionary (); - bool ret; + if (arguments != null) + return CheckIndices (ec, initializers, 0, true); - if (arguments != null) { - ret = CheckIndices (ec, initializers, 0, true); - return ret; - } else { - arguments = new ArrayList (); + arguments = new ArrayList (); - ret = CheckIndices (ec, initializers, 0, false); - - if (!ret) - return false; + if (!CheckIndices (ec, initializers, 0, false)) + return false; - UpdateIndices (ec); + UpdateIndices (); - if (arguments.Count != dimensions) { - Error_IncorrectArrayInitializer (); - return false; - } - - return ret; + if (arguments.Count != dimensions) { + Error_IncorrectArrayInitializer (); + return false; } + + return true; } // @@ -6511,12 +5988,7 @@ namespace Mono.CSharp { if (array_type_expr == null) return false; - type = array_type_expr.ResolveType (ec); - - if (!type.IsArray) { - Error (622, "Can only use array initializer expressions to assign to array types. Try using a new expression instead."); - return false; - } + type = array_type_expr.Type; underlying_type = TypeManager.GetElementType (type); dimensions = type.GetArrayRank (); @@ -6525,18 +5997,26 @@ namespace Mono.CSharp { public override Expression DoResolve (EmitContext ec) { - int arg_count; + if (type != null) + return this; if (!LookupType (ec)) return null; + array_element_type = TypeManager.GetElementType (type); + if (array_element_type.IsAbstract && array_element_type.IsSealed) { + Report.Error (719, loc, "`{0}': array elements cannot be of static type", TypeManager.CSharpName (array_element_type)); + return null; + } + // // First step is to validate the initializers and fill // in any missing bits // - if (!ValidateInitializers (ec, type)) + if (!ResolveInitializers (ec)) return null; + int arg_count; if (arguments == null) arg_count = 0; else { @@ -6553,13 +6033,6 @@ namespace Mono.CSharp { } } - array_element_type = TypeManager.GetElementType (type); - - if (array_element_type.IsAbstract && array_element_type.IsSealed) { - Report.Error (719, loc, "`{0}': array elements cannot be of static type", TypeManager.CSharpName (array_element_type)); - return null; - } - if (arg_count == 1) { is_one_dimensional = true; eclass = ExprClass.Value; @@ -6571,11 +6044,11 @@ namespace Mono.CSharp { if (is_builtin_type) { Expression ml; - ml = MemberLookup (ec, type, ".ctor", MemberTypes.Constructor, + ml = MemberLookup (ec.ContainerType, type, ".ctor", MemberTypes.Constructor, AllBindingFlags, loc); if (!(ml is MethodGroupExpr)) { - ml.Error_UnexpectedKind (ec, "method group", loc); + ml.Error_UnexpectedKind (ec.DeclContainer, "method group", loc); return null; } @@ -6626,7 +6099,7 @@ namespace Mono.CSharp { } } - public static byte [] MakeByteBlob (ArrayList array_data, Type underlying_type, Location loc) + byte [] MakeByteBlob () { int factor; byte [] data; @@ -6642,7 +6115,7 @@ namespace Mono.CSharp { data = new byte [(count * factor + 4) & ~3]; int idx = 0; - + for (int i = 0; i < count; ++i) { object v = array_data [i]; @@ -6781,7 +6254,7 @@ namespace Mono.CSharp { FieldBuilder fb; ILGenerator ig = ec.ig; - byte [] data = MakeByteBlob (array_data, underlying_type, loc); + byte [] data = MakeByteBlob (); fb = RootContext.MakeStaticData (data); @@ -6802,87 +6275,67 @@ namespace Mono.CSharp { ILGenerator ig = ec.ig; int dims = bounds.Count; int [] current_pos = new int [dims]; - int top = array_data.Count; MethodInfo set = null; if (dims != 1){ - Type [] args; - ModuleBuilder mb = null; - mb = CodeGen.Module.Builder; - args = new Type [dims + 1]; + Type [] args = new Type [dims + 1]; - int j; - for (j = 0; j < dims; j++) + for (int j = 0; j < dims; j++) args [j] = TypeManager.int32_type; - - args [j] = array_element_type; + args [dims] = array_element_type; - set = mb.GetArrayMethod ( + set = CodeGen.Module.Builder.GetArrayMethod ( type, "Set", CallingConventions.HasThis | CallingConventions.Standard, TypeManager.void_type, args); } - - for (int i = 0; i < top; i++){ - Expression e = null; + for (int i = 0; i < array_data.Count; i++){ - if (array_data [i] is Expression) - e = (Expression) array_data [i]; + Expression e = (Expression)array_data [i]; if (e != null) { - // - // Basically we do this for string literals and - // other non-literal expressions - // - if (e is EnumConstant){ - e = ((EnumConstant) e).Child; - } - - if (e is StringConstant || e is DecimalConstant || !(e is Constant) || - num_automatic_initializers <= max_automatic_initializers) { - Type etype = e.Type; + Type etype = e.Type; - ig.Emit (OpCodes.Dup); + ig.Emit (OpCodes.Dup); - for (int idx = 0; idx < dims; idx++) - IntConstant.EmitInt (ig, current_pos [idx]); + for (int idx = 0; idx < dims; idx++) + IntConstant.EmitInt (ig, current_pos [idx]); - // - // If we are dealing with a struct, get the - // address of it, so we can store it. - // - if ((dims == 1) && - TypeManager.IsValueType (etype) && - (!TypeManager.IsBuiltinOrEnum (etype) || - etype == TypeManager.decimal_type)) { - if (e is New){ - New n = (New) e; - - // - // Let new know that we are providing - // the address where to store the results - // - n.DisableTemporaryValueType (); - } + // + // If we are dealing with a struct, get the + // address of it, so we can store it. + // + if ((dims == 1) && + TypeManager.IsValueType (etype) && + (!TypeManager.IsBuiltinOrEnum (etype) || + etype == TypeManager.decimal_type)) { + if (e is New){ + New n = (New) e; - ig.Emit (OpCodes.Ldelema, etype); + // + // Let new know that we are providing + // the address where to store the results + // + n.DisableTemporaryValueType (); } - e.Emit (ec); + ig.Emit (OpCodes.Ldelema, etype); + } + + e.Emit (ec); - if (dims == 1) { - bool is_stobj; - OpCode op = ArrayAccess.GetStoreOpcode (etype, out is_stobj); - if (is_stobj) - ig.Emit (OpCodes.Stobj, etype); - else - ig.Emit (op); - } else - ig.Emit (OpCodes.Call, set); + if (dims == 1) { + bool is_stobj; + OpCode op = ArrayAccess.GetStoreOpcode (etype, out is_stobj); + if (is_stobj) + ig.Emit (OpCodes.Stobj, etype); + else + ig.Emit (op); + } else + ig.Emit (OpCodes.Call, set); - } } // @@ -6926,49 +6379,72 @@ namespace Mono.CSharp { ig.Emit (OpCodes.Newobj, (MethodInfo) new_method); } - if (initializers != null){ - // - // FIXME: Set this variable correctly. - // - bool dynamic_initializers = true; + if (initializers == null) + return; - // This will never be true for array types that cannot be statically - // initialized. num_automatic_initializers will always be zero. See - // CheckIndices. - if (num_automatic_initializers > max_automatic_initializers) - EmitStaticInitializers (ec); - - if (dynamic_initializers) - EmitDynamicInitializers (ec); + // This is a treshold for static initializers + // I tried to make more accurate but it seems to me that Array.Initialize is + // always slower (managed -> unmanaged switch?) + const int max_automatic_initializers = 200; + + if (const_initializers_count > max_automatic_initializers && TypeManager.IsPrimitiveType (array_element_type)) { + EmitStaticInitializers (ec); + return; } + + EmitDynamicInitializers (ec); } - public object EncodeAsAttribute () + public override bool GetAttributableValue (Type valueType, out object value) { if (!is_one_dimensional){ - Report.Error (-211, Location, "attribute can not encode multi-dimensional arrays"); - return null; +// Report.Error (-211, Location, "attribute can not encode multi-dimensional arrays"); + return base.GetAttributableValue (null, out value); } - if (array_data == null){ - Report.Error (-212, Location, "array should be initialized when passing it to an attribute"); - return null; + if (array_data == null) { + Constant c = (Constant)((Argument)arguments [0]).Expr; + if (c.IsDefaultValue) { + value = Array.CreateInstance (array_element_type, 0); + return true; + } +// Report.Error (-212, Location, "array should be initialized when passing it to an attribute"); + return base.GetAttributableValue (null, out value); } - object [] ret = new object [array_data.Count]; - int i = 0; - foreach (Expression e in array_data){ - object v; - - if (e is NullLiteral) - v = null; - else { - if (!Attribute.GetAttributeArgumentExpression (e, Location, array_element_type, out v)) - return null; + 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]; + if (e == null) // Is null when initializer is optimized away + e = (Expression)initializers [i]; + + if (!e.GetAttributableValue (array_element_type, out element_value)) { + value = null; + return false; } - ret [i++] = v; + ret.SetValue (element_value, i); } - return ret; + value = ret; + return true; + } + } + + public sealed class CompilerGeneratedThis : This + { + public static This Instance = new CompilerGeneratedThis (); + + private CompilerGeneratedThis () + : base (Location.Null) + { + } + + public override Expression DoResolve (EmitContext ec) + { + eclass = ExprClass.Variable; + type = ec.ContainerType; + return this; } } @@ -6997,8 +6473,7 @@ namespace Mono.CSharp { public bool VerifyFixed () { - // Treat 'this' as a value parameter for the purpose of fixed variable determination. - return true; + return !TypeManager.IsValueType (Type); } public bool ResolveBase (EmitContext ec) @@ -7067,11 +6542,20 @@ namespace Mono.CSharp { ILGenerator ig = ec.ig; if (ec.TypeContainer is Struct){ - ec.EmitThis (); + ec.EmitThis (false); source.Emit (ec); - if (leave_copy) + + LocalTemporary t = null; + if (leave_copy) { + t = new LocalTemporary (type); ec.ig.Emit (OpCodes.Dup); + t.Store (ec); + } + ig.Emit (OpCodes.Stobj, type); + + if (leave_copy) + t.Emit (ec); } else { throw new Exception ("how did you get here"); } @@ -7081,7 +6565,7 @@ namespace Mono.CSharp { { ILGenerator ig = ec.ig; - ec.EmitThis (); + ec.EmitThis (false); if (ec.TypeContainer is Struct) ig.Emit (OpCodes.Ldobj, type); } @@ -7102,7 +6586,7 @@ namespace Mono.CSharp { public void AddressOf (EmitContext ec, AddressOp mode) { - ec.EmitThis (); + ec.EmitThis (true); // FIMXE // FIGURE OUT WHY LDARG_S does not work @@ -7125,19 +6609,13 @@ namespace Mono.CSharp { this.loc = loc; } - public bool ResolveBase (EmitContext ec) + public override Expression DoResolve (EmitContext ec) { eclass = ExprClass.Variable; type = TypeManager.runtime_argument_handle_type; - return true; - } - public override Expression DoResolve (EmitContext ec) - { - if (!ResolveBase (ec)) - return null; - - if (ec.IsFieldInitializer || !ec.CurrentBlock.Toplevel.HasVarargs) { + if (ec.IsFieldInitializer || !ec.CurrentBlock.Toplevel.HasVarargs) + { Error (190, "The __arglist construct is valid only within " + "a variable argument method."); return null; @@ -7221,7 +6699,7 @@ namespace Mono.CSharp { /// Implements the typeof operator /// public class TypeOf : Expression { - public Expression QueriedType; + readonly Expression QueriedType; protected Type typearg; public TypeOf (Expression queried_type, Location l) @@ -7236,7 +6714,7 @@ namespace Mono.CSharp { if (texpr == null) return null; - typearg = texpr.ResolveType (ec); + typearg = texpr.Type; if (typearg == TypeManager.void_type) { Error (673, "System.Void cannot be used from C#. Use typeof (void) to get the void type object"); @@ -7247,7 +6725,6 @@ namespace Mono.CSharp { UnsafeError (loc); return null; } - CheckObsoleteAttribute (typearg); type = TypeManager.type_type; // Even though what is returned is a type object, it's treated as a value by the compiler. @@ -7262,8 +6739,14 @@ namespace Mono.CSharp { ec.ig.Emit (OpCodes.Call, TypeManager.system_type_get_type_from_handle); } - public Type TypeArg { - get { return typearg; } + public override bool GetAttributableValue (Type valueType, out object value) + { + if (valueType == TypeManager.object_type) { + value = (object)typearg; + return true; + } + value = typearg; + return true; } } @@ -7305,11 +6788,11 @@ namespace Mono.CSharp { if (texpr == null) return null; - type_queried = texpr.ResolveType (ec); + type_queried = texpr.Type; int size_of = GetTypeSize (type_queried); if (size_of > 0) { - return new IntConstant (size_of); + return new IntConstant (size_of, loc); } if (!ec.InUnsafe) { @@ -7318,8 +6801,6 @@ namespace Mono.CSharp { return null; } - CheckObsoleteAttribute (type_queried); - if (!TypeManager.VerifyUnManaged (type_queried, loc)){ return null; } @@ -7354,13 +6835,13 @@ namespace Mono.CSharp { loc = l; } - public override FullNamedExpression ResolveAsTypeStep (EmitContext ec, bool silent) + public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent) { if (alias == "global") - return new MemberAccess (Namespace.Root, identifier, loc).ResolveAsTypeStep (ec, silent); + return new MemberAccess (RootNamespace.Global, identifier).ResolveAsTypeStep (ec, silent); int errors = Report.Errors; - FullNamedExpression fne = ec.DeclSpace.NamespaceEntry.LookupAlias (alias); + FullNamedExpression fne = ec.DeclContainer.NamespaceEntry.LookupAlias (alias); if (fne == null) { if (errors == Report.Errors) Report.Error (432, loc, "Alias `{0}' not found", alias); @@ -7371,17 +6852,17 @@ namespace Mono.CSharp { Report.Error (431, loc, "`{0}' cannot be used with '::' since it denotes a type", alias); return null; } - return new MemberAccess (fne, identifier, loc).ResolveAsTypeStep (ec, silent); + return new MemberAccess (fne, identifier).ResolveAsTypeStep (ec, silent); } public override Expression DoResolve (EmitContext ec) { FullNamedExpression fne; if (alias == "global") { - fne = Namespace.Root; + fne = RootNamespace.Global; } else { int errors = Report.Errors; - fne = ec.DeclSpace.NamespaceEntry.LookupAlias (alias); + fne = ec.DeclContainer.NamespaceEntry.LookupAlias (alias); if (fne == null) { if (errors == Report.Errors) Report.Error (432, loc, "Alias `{0}' not found", alias); @@ -7389,7 +6870,7 @@ namespace Mono.CSharp { } } - Expression retval = new MemberAccess (fne, identifier, loc).DoResolve (ec); + Expression retval = new MemberAccess (fne, identifier).DoResolve (ec); if (retval == null) return null; @@ -7427,14 +6908,14 @@ namespace Mono.CSharp { /// Implements the member access expression /// public class MemberAccess : Expression { - public readonly string Identifier; // TODO: LocatedToken + public readonly string Identifier; Expression expr; - public MemberAccess (Expression expr, string id, Location l) + public MemberAccess (Expression expr, string id) { this.expr = expr; Identifier = id; - loc = l; + loc = expr.Location; } public Expression Expr { @@ -7465,7 +6946,7 @@ namespace Mono.CSharp { if (new_expr is Namespace) { Namespace ns = (Namespace) new_expr; - FullNamedExpression retval = ns.Lookup (ec.DeclSpace, Identifier, loc); + FullNamedExpression retval = ns.Lookup (ec.DeclContainer, Identifier, loc); if (retval == null) Report.Error (234, loc, "The type or namespace name `{0}' does not exist in the namespace `{1}'. Are you missing an assembly reference?", Identifier, ns.FullName); @@ -7477,7 +6958,13 @@ namespace Mono.CSharp { Error (23, "The `.' operator can not be applied to pointer operands (" + TypeManager.CSharpName (expr_type) + ")"); return null; + } else if (expr_type == TypeManager.void_type) { + Error (23, "The `.' operator can not be applied to operands of type 'void'"); + return null; + } else if (expr_type == TypeManager.anonymous_method_type){ + Error (23, "The `.' operator can not be applied to anonymous methods"); } + Expression member_lookup; member_lookup = MemberLookupFinal (ec, expr_type, expr_type, Identifier, loc); @@ -7528,23 +7015,21 @@ namespace Mono.CSharp { return DoResolve (ec, right_side); } - public override FullNamedExpression ResolveAsTypeStep (EmitContext ec, bool silent) + public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent) { return ResolveNamespaceOrType (ec, silent); } - public FullNamedExpression ResolveNamespaceOrType (EmitContext ec, bool silent) + public FullNamedExpression ResolveNamespaceOrType (IResolveContext rc, bool silent) { - FullNamedExpression new_expr = expr.ResolveAsTypeStep (ec, silent); + FullNamedExpression new_expr = expr.ResolveAsTypeStep (rc, silent); - if (new_expr == null) { - Report.Error (234, "No such name or typespace {0}", expr); + if (new_expr == null) return null; - } if (new_expr is Namespace) { Namespace ns = (Namespace) new_expr; - FullNamedExpression retval = ns.Lookup (ec.DeclSpace, Identifier, loc); + FullNamedExpression retval = ns.Lookup (rc.DeclContainer, Identifier, loc); if (!silent && retval == null) Report.Error (234, loc, "The type or namespace name `{0}' does not exist in the namespace `{1}'. Are you missing an assembly reference?", Identifier, ns.FullName); @@ -7559,10 +7044,10 @@ namespace Mono.CSharp { return null; } - Expression member_lookup = MemberLookup (ec, expr_type, expr_type, Identifier, loc); + Expression member_lookup = MemberLookup (rc.DeclContainer.TypeBuilder, expr_type, expr_type, Identifier, loc); if (member_lookup == null) { int errors = Report.Errors; - MemberLookupFailed (ec, expr_type, expr_type, Identifier, null, false, loc); + MemberLookupFailed (rc.DeclContainer.TypeBuilder, expr_type, expr_type, Identifier, null, false, loc); if (!silent && errors == Report.Errors) { Report.Error (426, loc, "The nested type `{0}' does not exist in the type `{1}'", @@ -7572,12 +7057,11 @@ namespace Mono.CSharp { } if (!(member_lookup is TypeExpr)) { - new_expr.Error_UnexpectedKind (ec, "type", loc); + new_expr.Error_UnexpectedKind (rc.DeclContainer, "type", loc); return null; } - member_lookup = member_lookup.Resolve (ec, ResolveFlags.Type); - return (member_lookup as TypeExpr); + return member_lookup.ResolveAsTypeTerminal (rc, silent); } public override void Emit (EmitContext ec) @@ -7809,11 +7293,10 @@ namespace Mono.CSharp { Report.Error (1708, loc, "Fixed size buffers can only be accessed through locals or fields"); return null; } -// TODO: not sure whether it is correct -// if (!ec.InFixedInitializer) { -// Error (1666, "You cannot use fixed sized buffers contained in unfixed expressions. Try using the fixed statement"); -// return null; -// } + if (!ec.InFixedInitializer && ec.ContainerType.IsValueType) { + Error (1666, "You cannot use fixed size buffers contained in unfixed expressions. Try using the fixed statement"); + return null; + } return MakePointerAccess (ec, ff.ElementType); } } @@ -7866,7 +7349,7 @@ namespace Mono.CSharp { Type t = ea.Expr.Type; if (t.GetArrayRank () != ea.Arguments.Count){ Report.Error (22, ea.Location, "Wrong number of indexes `{0}' inside [], expected `{1}'", - ea.Arguments.Count, t.GetArrayRank ()); + ea.Arguments.Count.ToString (), t.GetArrayRank ().ToString ()); return null; } @@ -8072,7 +7555,7 @@ namespace Mono.CSharp { if (leave_copy) { ec.ig.Emit (OpCodes.Dup); - temp = new LocalTemporary (ec, this.type); + temp = new LocalTemporary (this.type); temp.Store (ec); } } @@ -8095,7 +7578,7 @@ namespace Mono.CSharp { source.Emit (ec); if (leave_copy) { ec.ig.Emit (OpCodes.Dup); - temp = new LocalTemporary (ec, this.type); + temp = new LocalTemporary (this.type); temp.Store (ec); } StoreFromPtr (ec.ig, t); @@ -8122,7 +7605,7 @@ namespace Mono.CSharp { source.Emit (ec); if (leave_copy) { ec.ig.Emit (OpCodes.Dup); - temp = new LocalTemporary (ec, this.type); + temp = new LocalTemporary (this.type); temp.Store (ec); } @@ -8139,7 +7622,7 @@ namespace Mono.CSharp { source.Emit (ec); if (leave_copy) { ec.ig.Emit (OpCodes.Dup); - temp = new LocalTemporary (ec, this.type); + temp = new LocalTemporary (this.type); temp.Store (ec); } @@ -8253,7 +7736,7 @@ namespace Mono.CSharp { BindingFlags.DeclaredOnly, p_name, null); } - static public Indexers GetIndexersForType (Type caller_type, Type lookup_type, Location loc) + static public Indexers GetIndexersForType (Type caller_type, Type lookup_type) { Indexers ix = empty; @@ -8329,7 +7812,7 @@ namespace Mono.CSharp { bool found_any = false, found_any_getters = false; Type lookup_type = indexer_type; - Indexers ilist = Indexers.GetIndexersForType (current_type, lookup_type, loc); + Indexers ilist = Indexers.GetIndexersForType (current_type, lookup_type); if (ilist.Properties != null) { found_any = true; foreach (Indexers.Indexer ix in ilist.Properties) { @@ -8376,7 +7859,7 @@ namespace Mono.CSharp { return null; } - instance_expr.CheckMarshallByRefAccess (ec.ContainerType); + instance_expr.CheckMarshalByRefAccess (); eclass = ExprClass.IndexerAccess; return this; @@ -8384,13 +7867,26 @@ namespace Mono.CSharp { public override Expression DoResolveLValue (EmitContext ec, Expression right_side) { + if (right_side == EmptyExpression.OutAccess) { + Report.Error (206, loc, "A property or indexer `{0}' may not be passed as an out or ref parameter", + GetSignatureForError ()); + return null; + } + + // if the indexer returns a value type, and we try to set a field in it + if (right_side == EmptyExpression.LValueMemberAccess || right_side == EmptyExpression.LValueMemberOutAccess) { + Report.Error (1612, loc, "Cannot modify the return value of `{0}' because it is not a variable", + GetSignatureForError ()); + return null; + } + ArrayList AllSetters = new ArrayList(); if (!CommonResolve (ec)) return null; bool found_any = false, found_any_setters = false; - Indexers ilist = Indexers.GetIndexersForType (current_type, indexer_type, loc); + Indexers ilist = Indexers.GetIndexersForType (current_type, indexer_type); if (ilist.Properties != null) { found_any = true; foreach (Indexers.Indexer ix in ilist.Properties) { @@ -8443,7 +7939,7 @@ namespace Mono.CSharp { } } - instance_expr.CheckMarshallByRefAccess (ec.ContainerType); + instance_expr.CheckMarshalByRefAccess (); eclass = ExprClass.IndexerAccess; return this; @@ -8457,7 +7953,7 @@ namespace Mono.CSharp { Invocation.EmitCall (ec, is_base_indexer, false, instance_expr, get, arguments, loc, prepared, false); if (leave_copy) { ec.ig.Emit (OpCodes.Dup); - temp = new LocalTemporary (ec, Type); + temp = new LocalTemporary (Type); temp.Store (ec); } } @@ -8476,11 +7972,11 @@ namespace Mono.CSharp { source.Emit (ec); if (leave_copy) { ec.ig.Emit (OpCodes.Dup); - temp = new LocalTemporary (ec, Type); + temp = new LocalTemporary (Type); temp.Store (ec); } } else if (leave_copy) { - temp = new LocalTemporary (ec, Type); + temp = new LocalTemporary (Type); source.Emit (ec); temp.Store (ec); a.Expr = temp; @@ -8497,6 +7993,12 @@ namespace Mono.CSharp { { Emit (ec, false); } + + public override string GetSignatureForError () + { + // FIXME: print the argument list of the indexer + return instance_expr.GetSignatureForError () + ".this[...]"; + } } /// @@ -8558,10 +8060,10 @@ namespace Mono.CSharp { return null; } - member_lookup = MemberLookup (ec, ec.ContainerType, null, base_type, member, + member_lookup = MemberLookup (ec.ContainerType, null, base_type, member, AllMemberTypes, AllBindingFlags, loc); if (member_lookup == null) { - MemberLookupFailed (ec, base_type, base_type, member, null, true, loc); + MemberLookupFailed (ec.ContainerType, base_type, base_type, member, null, true, loc); return null; } @@ -8635,6 +8137,10 @@ namespace Mono.CSharp { public class EmptyExpression : Expression { public static readonly EmptyExpression Null = new EmptyExpression (); + public static readonly EmptyExpression OutAccess = new EmptyExpression (); + public static readonly EmptyExpression LValueMemberAccess = new EmptyExpression (); + public static readonly EmptyExpression LValueMemberOutAccess = new EmptyExpression (); + static EmptyExpression temp = new EmptyExpression (); public static EmptyExpression Grab () { @@ -8751,14 +8257,13 @@ namespace Mono.CSharp { loc = l; } - public override TypeExpr DoResolveAsTypeStep (EmitContext ec) + protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec) { TypeExpr lexpr = left.ResolveAsTypeTerminal (ec, false); if (lexpr == null) return null; - Type ltype = lexpr.ResolveType (ec); - + Type ltype = lexpr.Type; if ((ltype == TypeManager.void_type) && (dim != "*")) { Report.Error (1547, Location, "Keyword 'void' cannot be used in this context"); @@ -8774,7 +8279,7 @@ namespace Mono.CSharp { throw new InternalErrorException ("Couldn't create computed type " + ltype + dim); } - if (!ec.InUnsafe && type.IsPointer){ + if (type.IsPointer && !ec.IsInUnsafeScope){ UnsafeError (loc); return null; } @@ -8790,19 +8295,20 @@ namespace Mono.CSharp { } public override string Name { - get { - return left + dim; - } + get { return left + dim; } } public override string FullName { - get { - return type.FullName; - } + get { return type.FullName; } + } + + public override string GetSignatureForError () + { + return left.GetSignatureForError () + dim; } } - public class FixedBufferPtr: Expression { + public class FixedBufferPtr : Expression { Expression array; public FixedBufferPtr (Expression array, Type array_type, Location l) @@ -8928,7 +8434,7 @@ namespace Mono.CSharp { if (texpr == null) return null; - otype = texpr.ResolveType (ec); + otype = texpr.Type; if (!TypeManager.VerifyUnManaged (otype, loc)) return null;