X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fexpression.cs;h=9005f6641e63b54bd625e0bb7dea0b21d758e0bc;hb=7713641ae9075059e06b2c3c78944c83a46ba393;hp=6361593a76daa5cc4b38cf43e38800e7d08022bb;hpb=08c8eaa6cd668fb552117ead1d3c6b5577deea24;p=mono.git diff --git a/mcs/mcs/expression.cs b/mcs/mcs/expression.cs index 6361593a76d..9005f6641e6 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 ( @@ -393,28 +401,24 @@ namespace Mono.CSharp { Expression e; e = Convert.ImplicitConversion (ec, Expr, TypeManager.int32_type, loc); - if (e != null){ - type = TypeManager.int32_type; - return this; - } + if (e != null) + goto ok; e = Convert.ImplicitConversion (ec, Expr, TypeManager.uint32_type, loc); - if (e != null){ - type = TypeManager.uint32_type; - return this; - } + if (e != null) + goto ok; e = Convert.ImplicitConversion (ec, Expr, TypeManager.int64_type, loc); - if (e != null){ - type = TypeManager.int64_type; - return this; - } + if (e != null) + goto ok; e = Convert.ImplicitConversion (ec, Expr, TypeManager.uint64_type, loc); - if (e != null){ - type = TypeManager.uint64_type; - return this; - } + if (e != null) + goto ok; Error23 (expr_type); return null; + ok: + Expr = e; + expr_type = e.Type; } + type = expr_type; return this; @@ -609,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); @@ -846,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 ( @@ -876,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; } @@ -1047,8 +1051,6 @@ namespace Mono.CSharp { return null; probe_type = texpr.ResolveType (ec); - CheckObsoleteAttribute (probe_type); - expr = expr.Resolve (ec); if (expr == null) return null; @@ -1197,6 +1199,7 @@ namespace Mono.CSharp { } bool do_isinst = false; + Expression resolved_type; public override void Emit (EmitContext ec) { @@ -1217,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; @@ -1233,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; @@ -1247,7 +1252,12 @@ namespace Mono.CSharp { Error_CannotConvertType (etype, probe_type, loc); return null; - } + } + + public override bool GetAttributableValue (out object value) + { + return expr.GetAttributableValue (out value); + } } /// @@ -1286,503 +1296,6 @@ namespace Mono.CSharp { 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)) - 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) { @@ -1810,8 +1323,6 @@ namespace Mono.CSharp { type = target.ResolveType (ec); - CheckObsoleteAttribute (type); - if (type.IsAbstract && type.IsSealed) { Report.Error (716, loc, "Cannot convert to static type `{0}'", TypeManager.CSharpName (type)); return null; @@ -1819,11 +1330,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) { @@ -1930,7 +1446,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: @@ -2023,7 +1539,7 @@ namespace Mono.CSharp { // type, otherwise ConvertImplict() already finds the user-defined conversion for us, // so we don't explicitly check for performance reasons. // - bool DoNumericPromotions (EmitContext ec, Type l, Type r, bool check_user_conv) + bool DoNumericPromotions (EmitContext ec, Type l, Type r, Expression lexpr, Expression rexpr, bool check_user_conv) { if (IsOfType (ec, l, r, TypeManager.double_type, check_user_conv)){ // @@ -2066,9 +1582,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 (ec, right, l); if (e != null) right = e; } @@ -2083,9 +1599,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 (ec, left, r); if (e != null) left = e; } @@ -2127,7 +1643,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; @@ -2140,7 +1656,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; } @@ -2175,6 +1691,12 @@ namespace Mono.CSharp { left = ForceConversion (ec, left, TypeManager.int32_type); right = ForceConversion (ec, right, TypeManager.int32_type); + bool strConv = + Convert.ImplicitConversionExists (ec, lexpr, TypeManager.string_type) && + Convert.ImplicitConversionExists (ec, rexpr, TypeManager.string_type); + if (strConv && left != null && right != null) + Error_OperatorAmbiguous (loc, oper, l, r); + type = TypeManager.int32_type; } @@ -2182,14 +1704,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) @@ -2248,10 +1775,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); } @@ -2315,10 +1842,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; @@ -2349,7 +1876,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) { @@ -2709,7 +2236,7 @@ namespace Mono.CSharp { // This will leave left or right set to null if there is an error // bool check_user_conv = is_user_defined (l) && is_user_defined (r); - DoNumericPromotions (ec, l, r, check_user_conv); + DoNumericPromotions (ec, l, r, left, right, check_user_conv); if (left == null || right == null){ Error_OperatorCannotBeApplied (loc, OperName (oper), l, r); return null; @@ -2754,8 +2281,48 @@ namespace Mono.CSharp { return this; } + Constant EnumLiftUp (EmitContext ec, 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); @@ -2763,7 +2330,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 @@ -2787,9 +2354,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 (ec, lc, rc); + if (lc == null) + return null; + + right = rc = EnumLiftUp (ec, rc, lc); + if (rc == null) + return null; + } + if (oper == Operator.BitwiseAnd) { if (rc != null && rc.IsZeroInteger) { return lc is EnumConstant ? @@ -2803,6 +2380,19 @@ namespace Mono.CSharp { lc; } } + else if (oper == Operator.BitwiseOr) { + if (lc is EnumConstant && + rc != null && rc.IsZeroInteger) + return lc; + 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){ int prev_e = Report.Errors; @@ -2812,9 +2402,109 @@ namespace Mono.CSharp { return e; } + // 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); } + private void CheckUselessComparison (Constant c, Type type) + { + if (c == null || !IsTypeIntegral (type) + || c is StringConstant + || c is BoolConstant + || c is CharConstant + || c is FloatConstant + || c is DoubleConstant + || c is DecimalConstant + ) + return; + + long value = 0; + + if (c is ULongConstant) { + ulong uvalue = ((ULongConstant) c).Value; + if (uvalue > long.MaxValue) { + if (type == TypeManager.byte_type || + type == TypeManager.sbyte_type || + type == TypeManager.short_type || + type == TypeManager.ushort_type || + type == TypeManager.int32_type || + type == TypeManager.uint32_type || + type == TypeManager.int64_type) + WarnUselessComparison (type); + return; + } + value = (long) uvalue; + } + else if (c is ByteConstant) + value = ((ByteConstant) c).Value; + else if (c is SByteConstant) + value = ((SByteConstant) c).Value; + else if (c is ShortConstant) + value = ((ShortConstant) c).Value; + else if (c is UShortConstant) + value = ((UShortConstant) c).Value; + else if (c is IntConstant) + value = ((IntConstant) c).Value; + else if (c is UIntConstant) + value = ((UIntConstant) c).Value; + else if (c is LongConstant) + value = ((LongConstant) c).Value; + + if (value != 0) { + if (IsValueOutOfRange (value, type)) + WarnUselessComparison (type); + return; + } + } + + private bool IsValueOutOfRange (long value, Type type) + { + if (IsTypeUnsigned (type) && value < 0) + return true; + return type == TypeManager.sbyte_type && (value >= 0x80 || value < -0x80) || + type == TypeManager.byte_type && value >= 0x100 || + type == TypeManager.short_type && (value >= 0x8000 || value < -0x8000) || + type == TypeManager.ushort_type && value >= 0x10000 || + type == TypeManager.int32_type && (value >= 0x80000000 || value < -0x80000000) || + type == TypeManager.uint32_type && value >= 0x100000000; + } + + private static bool IsTypeIntegral (Type type) + { + return type == TypeManager.uint64_type || + type == TypeManager.int64_type || + type == TypeManager.uint32_type || + type == TypeManager.int32_type || + type == TypeManager.ushort_type || + type == TypeManager.short_type || + type == TypeManager.sbyte_type || + type == TypeManager.byte_type; + } + + private static bool IsTypeUnsigned (Type type) + { + return type == TypeManager.uint64_type || + type == TypeManager.uint32_type || + type == TypeManager.ushort_type || + type == TypeManager.byte_type; + } + + private void WarnUselessComparison (Type type) + { + Report.Warning (652, 2, loc, "Comparison to integral constant is useless; the constant is outside the range of type `{0}'", + TypeManager.CSharpName (type)); + } + /// /// EmitBranchable is called from Statement.EmitBoolExpression in the /// context of a conditional bool expression. This function will return @@ -3228,7 +2918,7 @@ namespace Mono.CSharp { 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); + operands [operands.Count - 1] = new StringConstant (last_operand.Value + ((StringConstant) operand).Value, last_operand.Location); return; } } @@ -3385,7 +3075,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 () @@ -3523,7 +3213,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); @@ -3600,6 +3290,11 @@ namespace Mono.CSharp { return null; } + Assign ass = expr as Assign; + if (ass != null && ass.Source is Constant) { + Report.Warning (665, 3, loc, "Assignment in conditional expression is always constant; did you mean to use == instead of = ?"); + } + trueExpr = trueExpr.Resolve (ec); falseExpr = falseExpr.Resolve (ec); @@ -3713,13 +3408,19 @@ namespace Mono.CSharp { } } + public bool VerifyAssigned (EmitContext ec) + { + VariableInfo variable_info = local_info.VariableInfo; + return variable_info == null || variable_info.IsAssigned (ec, loc); + } + protected Expression DoResolveBase (EmitContext ec, Expression lvalue_right_side) { if (local_info == null) { local_info = Block.GetLocalInfo (Name); // is out param - if (lvalue_right_side == EmptyExpression.Null) + if (lvalue_right_side == EmptyExpression.OutAccess) local_info.Used = true; is_readonly = local_info.ReadOnly; @@ -3730,9 +3431,12 @@ namespace Mono.CSharp { 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) + if (lvalue_right_side is LocalVariableReference || lvalue_right_side == EmptyExpression.OutAccess) Report.Error (1657, loc, "Cannot pass `{0}' as a ref or out argument because it is a `{1}'", Name, local_info.GetReadOnlyContext ()); + else if (lvalue_right_side == EmptyExpression.LValueMemberAccess) + Report.Error (1654, loc, "Cannot assign to members of `{0}' 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 ()); @@ -3750,7 +3454,7 @@ namespace Mono.CSharp { return e.Resolve (ec); } - if ((variable_info != null) && !variable_info.IsAssigned (ec, loc)) + if (!VerifyAssigned (ec)) return null; if (lvalue_right_side == null) @@ -3782,11 +3486,7 @@ namespace Mono.CSharp { override public Expression DoResolveLValue (EmitContext ec, Expression right_side) { - Expression ret = DoResolveBase (ec, right_side); - if (ret != null) - CheckObsoleteAttribute (ret.Type); - - return ret; + return DoResolveBase (ec, right_side); } public bool VerifyFixed () @@ -3906,12 +3606,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 { @@ -3928,20 +3627,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; } } @@ -3949,7 +3644,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) @@ -3958,7 +3653,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; } @@ -3986,18 +3681,23 @@ namespace Mono.CSharp { protected void 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); + par.Name); return; } @@ -4042,7 +3742,7 @@ namespace Mono.CSharp { { DoResolveBase (ec); - if (is_out && ec.DoFlowAnalysis && !IsAssigned (ec, loc)) + if (is_out && ec.DoFlowAnalysis && (!ec.OmitStructFlowAnalysis || !vi.TypeInfo.IsStruct) && !IsAssigned (ec, loc)) return null; return this; @@ -4102,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; } @@ -4138,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++; @@ -4202,6 +3900,10 @@ namespace Mono.CSharp { } } + public override string ToString () + { + return "ParameterReference[" + name + "]"; + } } /// @@ -4244,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; @@ -4295,15 +3997,17 @@ namespace Mono.CSharp { return false; } + int errors = Report.Errors; Expr = Expr.DoResolveLValue (ec, Expr); - if (Expr == null) + if (Expr == null && errors == Report.Errors) Error_LValueRequired (loc); } else if (ArgType == AType.Out) { + int errors = Report.Errors; ec.InRefOutArgumentResolving = true; - Expr = Expr.DoResolveLValue (ec, EmptyExpression.Null); + Expr = Expr.DoResolveLValue (ec, EmptyExpression.OutAccess); ec.InRefOutArgumentResolving = false; - if (Expr == null) + if (Expr == null && errors == Report.Errors) Error_LValueRequired (loc); } else @@ -4336,20 +4040,6 @@ namespace Mono.CSharp { } } } - - 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; - } return true; } @@ -4590,7 +4280,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; @@ -4676,26 +4366,18 @@ 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); - } - /// /// Determines if the candidate method, if a params method, is applicable /// in its expanded form to the given set of arguments @@ -4717,7 +4399,7 @@ namespace Mono.CSharp { if (pd_count != arg_count) return false; } else { - if (pd.ParameterModifier (count) != Parameter.Modifier.PARAMS) + if (!pd.HasParams) return false; } @@ -4737,9 +4419,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) { @@ -4747,8 +4429,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); @@ -4783,19 +4465,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); @@ -4808,28 +4483,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; } @@ -4837,7 +4506,7 @@ 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) || @@ -4891,45 +4560,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)) - 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]); + if (applicable_type != null && IsAncestralType (decl_type, applicable_type)) 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 (); @@ -4952,6 +4633,9 @@ namespace Mono.CSharp { } } + if (applicable_errors != Report.Errors) + return null; + int candidate_top = candidates.Count; if (applicable_type == null) { @@ -4960,7 +4644,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); @@ -4969,6 +4653,12 @@ namespace Mono.CSharp { VerifyArgumentsCompat (ec, Arguments, arg_count, c, false, null, may_fail, loc); + + if (!may_fail && errors == Report.Errors) + throw new InternalErrorException ( + "VerifyArgumentsCompat and IsApplicable do not agree; " + + "likely reason: ImplicitConversion and ImplicitConversionExists have gone out of sync"); + break; } @@ -5054,7 +4744,6 @@ namespace Mono.CSharp { method_params = cand_params; } } - // // Now check that there are no ambiguities i.e the selected method // should be better than all the others @@ -5119,7 +4808,7 @@ namespace Mono.CSharp { 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) @@ -5138,21 +4827,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, @@ -5173,15 +4861,18 @@ namespace Mono.CSharp { if (pm == Parameter.Modifier.PARAMS){ if ((pm & ~Parameter.Modifier.PARAMS) != a.Modifier) { if (!may_fail) - Error_InvalidArguments ( - loc, j, method, delegate_type, - a, pd); + Error_InvalidArguments (loc, j, method, delegate_type, a, pd); return false; } if (chose_params_expanded) parameter_type = TypeManager.GetElementType (parameter_type); - } else if (pm == Parameter.Modifier.ARGLIST){ + } else if (pm == Parameter.Modifier.ARGLIST) { + if (!(a.Expr is Arglist)) { + if (!may_fail) + Error_InvalidArguments (loc, j, method, delegate_type, a, pd); + return false; + } continue; } else { // @@ -5189,9 +4880,7 @@ namespace Mono.CSharp { // if (pd.ParameterModifier (j) != a.Modifier){ if (!may_fail) - Error_InvalidArguments ( - loc, j, method, delegate_type, - a, pd); + Error_InvalidArguments (loc, j, method, delegate_type, a, pd); return false; } } @@ -5242,8 +4931,13 @@ namespace Mono.CSharp { return true; } + 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 @@ -5279,7 +4973,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; @@ -5328,21 +5022,44 @@ namespace Mono.CSharp { return null; } - if ((method.Attributes & MethodAttributes.SpecialName) != 0) { - if (TypeManager.LookupDeclSpace (method.DeclaringType) != null || TypeManager.IsSpecialMethod (method)) { - Report.Error (571, loc, "`{0}': cannot explicitly call operator or accessor", - TypeManager.CSharpSignature (method, true)); - return null; - } + if ((method.Attributes & MethodAttributes.SpecialName) != 0 && IsSpecialMethodInvocation (method)) { + return null; } if (mg.InstanceExpression != null) mg.InstanceExpression.CheckMarshallByRefAccess (ec.ContainerType); eclass = ExprClass.Value; + this.method = method; return this; } + bool IsSpecialMethodInvocation (MethodBase method) + { + IMethodData md = TypeManager.GetMethod (method); + if (md != null) { + if (!(md is AbstractPropertyEventMethod) && !(md is Operator)) + return false; + } else { + if (!TypeManager.IsSpecialMethod (method)) + return false; + + int args = TypeManager.GetParameterData (method).Count; + if (method.Name.StartsWith ("get_") && args > 0) + return false; + else if (method.Name.StartsWith ("set_") && args > 2) + return false; + + // TODO: check operators and events as well ? + } + + Report.SymbolRelatedToPreviousError (method); + Report.Error (571, loc, "`{0}': cannot explicitly call operator or accessor", + TypeManager.CSharpSignature (method, true)); + + return true; + } + // // Emits the list of arguments as an array // @@ -5393,33 +5110,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]; @@ -5479,14 +5175,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 @@ -5555,7 +5251,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 // @@ -5570,8 +5266,8 @@ namespace Mono.CSharp { } } - if (IsMethodExcluded (method, ec)) - return; + if (IsMethodExcluded (method)) + return; if (!is_static){ if (instance_expr == EmptyExpression.Null) { @@ -5625,9 +5321,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 (ec, t); + this_arg.Store (ec); + } } } } @@ -5871,35 +5569,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) { // @@ -5928,9 +5649,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)) @@ -5939,11 +5658,17 @@ namespace Mono.CSharp { } if (type.IsAbstract && type.IsSealed) { + Report.SymbolRelatedToPreviousError (type); Report.Error (712, loc, "Cannot create an instance of the static class `{0}'", TypeManager.CSharpName (type)); return null; } 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; } @@ -5968,7 +5693,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; } @@ -5982,7 +5707,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; } @@ -6188,16 +5913,21 @@ namespace Mono.CSharp { { 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 (); @@ -6273,7 +6003,7 @@ namespace Mono.CSharp { 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; @@ -6281,7 +6011,7 @@ 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; @@ -6294,10 +6024,7 @@ namespace Mono.CSharp { public bool ValidateInitializers (EmitContext ec, Type array_type) { if (initializers == null) { - if (expect_initializers) - return false; - else - return true; + return !expect_initializers; } if (underlying_type == null) @@ -6310,17 +6037,12 @@ namespace Mono.CSharp { array_data = new ArrayList (); bounds = new Hashtable (); - bool ret; - if (arguments != null) { - ret = CheckIndices (ec, initializers, 0, true); - return ret; + return CheckIndices (ec, initializers, 0, true); } else { arguments = new ArrayList (); - ret = CheckIndices (ec, initializers, 0, false); - - if (!ret) + if (!CheckIndices (ec, initializers, 0, false)) return false; UpdateIndices (ec); @@ -6330,7 +6052,7 @@ namespace Mono.CSharp { return false; } - return ret; + return true; } } @@ -6361,12 +6083,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.ResolveType (ec); underlying_type = TypeManager.GetElementType (type); dimensions = type.GetArrayRank (); @@ -6421,11 +6138,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; } @@ -6693,7 +6410,7 @@ namespace Mono.CSharp { if (e is StringConstant || e is DecimalConstant || !(e is Constant) || num_automatic_initializers <= max_automatic_initializers) { Type etype = e.Type; - + ig.Emit (OpCodes.Dup); for (int idx = 0; idx < dims; idx++) @@ -6704,7 +6421,7 @@ namespace Mono.CSharp { // address of it, so we can store it. // if ((dims == 1) && - etype.IsSubclassOf (TypeManager.value_type) && + TypeManager.IsValueType (etype) && (!TypeManager.IsBuiltinOrEnum (etype) || etype == TypeManager.decimal_type)) { if (e is New){ @@ -6793,32 +6510,33 @@ namespace Mono.CSharp { } } - public object EncodeAsAttribute () + public override bool GetAttributableValue (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 (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 = new object [0]; + return true; + } +// Report.Error (-212, Location, "array should be initialized when passing it to an attribute"); + return base.GetAttributableValue (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; + for (int i = 0; i < ret.Length; ++i) + { + if (!((Expression)array_data [i]).GetAttributableValue (out ret [i])) { + value = null; + return false; } - ret [i++] = v; } - return ret; + value = ret; + return true; } } @@ -6847,8 +6565,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) @@ -6875,7 +6592,7 @@ namespace Mono.CSharp { if (!ResolveBase (ec)) return null; - if ((variable_info != null) && !variable_info.IsAssigned (ec)) { + if ((variable_info != null) && !(type.IsValueType && ec.OmitStructFlowAnalysis) && !variable_info.IsAssigned (ec)) { Error (188, "The `this' object cannot be used before all of its fields are assigned to"); variable_info.SetAssigned (ec); return this; @@ -6917,11 +6634,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 (ec, 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"); } @@ -6931,7 +6657,7 @@ namespace Mono.CSharp { { ILGenerator ig = ec.ig; - ec.EmitThis (); + ec.EmitThis (false); if (ec.TypeContainer is Struct) ig.Emit (OpCodes.Ldobj, type); } @@ -6952,7 +6678,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 @@ -7071,7 +6797,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) @@ -7097,7 +6823,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. @@ -7112,8 +6837,10 @@ 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 (out object value) + { + value = typearg; + return true; } } @@ -7159,7 +6886,7 @@ namespace Mono.CSharp { int size_of = GetTypeSize (type_queried); if (size_of > 0) { - return new IntConstant (size_of); + return new IntConstant (size_of, loc); } if (!ec.InUnsafe) { @@ -7168,8 +6895,6 @@ namespace Mono.CSharp { return null; } - CheckObsoleteAttribute (type_queried); - if (!TypeManager.VerifyUnManaged (type_queried, loc)){ return null; } @@ -7204,13 +6929,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, loc).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); @@ -7228,10 +6953,10 @@ namespace Mono.CSharp { { 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); @@ -7277,14 +7002,15 @@ namespace Mono.CSharp { /// Implements the member access expression /// public class MemberAccess : Expression { - public readonly string Identifier; // TODO: LocatedToken + public readonly string Identifier; Expression expr; + // TODO: Location can be removed public MemberAccess (Expression expr, string id, Location l) { this.expr = expr; Identifier = id; - loc = l; + loc = expr.Location; } public Expression Expr { @@ -7308,14 +7034,14 @@ namespace Mono.CSharp { SimpleName original = expr as SimpleName; Expression new_expr = expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.Type | - ResolveFlags.Intermediate | ResolveFlags.DisableFlowAnalysis); + ResolveFlags.Intermediate | ResolveFlags.DisableStructFlowAnalysis); 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 (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); @@ -7327,7 +7053,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); @@ -7350,15 +7082,22 @@ namespace Mono.CSharp { if (member_lookup == null) return null; + if (original != null && !TypeManager.IsValueType (expr_type)) { + me = member_lookup as MemberExpr; + if (me != null && me.IsInstance) { + LocalVariableReference var = new_expr as LocalVariableReference; + if (var != null && !var.VerifyAssigned (ec)) + return null; + } + } + // The following DoResolve/DoResolveLValue will do the definite assignment // check. if (right_side != null) - member_lookup = member_lookup.DoResolveLValue (ec, right_side); + return member_lookup.DoResolveLValue (ec, right_side); else - member_lookup = member_lookup.DoResolve (ec); - - return member_lookup; + return member_lookup.DoResolve (ec); } public override Expression DoResolve (EmitContext ec) @@ -7371,23 +7110,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); @@ -7402,10 +7139,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}'", @@ -7415,11 +7152,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); + member_lookup = member_lookup.ResolveAsTypeTerminal (rc, silent); return (member_lookup as TypeExpr); } @@ -7652,11 +7389,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); } } @@ -7709,7 +7445,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; } @@ -7782,7 +7518,9 @@ namespace Mono.CSharp { } else if (type.IsValueType){ ig.Emit (OpCodes.Ldelema, type); ig.Emit (OpCodes.Ldobj, type); - } else + } else if (type.IsPointer) + ig.Emit (OpCodes.Ldelem_I); + else ig.Emit (OpCodes.Ldelem_Ref); } @@ -7817,7 +7555,9 @@ namespace Mono.CSharp { } else if (t.IsValueType) { is_stobj = true; return OpCodes.Stobj; - } else + } else if (t.IsPointer) + return OpCodes.Stelem_I; + else return OpCodes.Stelem_Ref; } @@ -8223,6 +7963,19 @@ 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) { + 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; @@ -8336,6 +8089,12 @@ namespace Mono.CSharp { { Emit (ec, false); } + + public override string GetSignatureForError () + { + // FIXME: print the argument list of the indexer + return instance_expr.GetSignatureForError () + ".this[...]"; + } } /// @@ -8397,10 +8156,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; } @@ -8474,6 +8233,9 @@ 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 (); + static EmptyExpression temp = new EmptyExpression (); public static EmptyExpression Grab () { @@ -8590,14 +8352,13 @@ namespace Mono.CSharp { loc = l; } - public override TypeExpr DoResolveAsTypeStep (EmitContext ec) + public override TypeExpr DoResolveAsTypeStep (IResolveContext ec) { TypeExpr lexpr = left.ResolveAsTypeTerminal (ec, false); if (lexpr == null) return null; Type ltype = lexpr.ResolveType (ec); - if ((ltype == TypeManager.void_type) && (dim != "*")) { Report.Error (1547, Location, "Keyword 'void' cannot be used in this context"); @@ -8613,7 +8374,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; } @@ -8629,19 +8390,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)