X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fgmcs%2Fexpression.cs;h=dad971332431f25d5370495b330041392c1775b0;hb=4a9ecda075e6914d55f4621a87073299b3baa1e3;hp=c31b4ece82c5a6767f7e9eb229e4b68f15d40a3f;hpb=675ed0f76f4c711f4d1d38183bda62c07ad9dfa6;p=mono.git diff --git a/mcs/gmcs/expression.cs b/mcs/gmcs/expression.cs index c31b4ece82c..dad97133243 100644 --- a/mcs/gmcs/expression.cs +++ b/mcs/gmcs/expression.cs @@ -91,10 +91,10 @@ namespace Mono.CSharp { { public Expression Expr; - public ParenthesizedExpression (Expression expr, Location loc) + public ParenthesizedExpression (Expression expr) { this.Expr = expr; - this.loc = loc; + this.loc = expr.Location; } public override Expression DoResolve (EmitContext ec) @@ -107,6 +107,13 @@ namespace Mono.CSharp { { throw new Exception ("Should not happen"); } + + public override Location Location + { + get { + return Expr.Location; + } + } } /// @@ -188,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; } @@ -255,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: @@ -304,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); @@ -394,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; @@ -879,7 +882,7 @@ namespace Mono.CSharp { if (expr == null) return null; } else { - expr.Error_UnexpectedKind ("variable, indexer or property access", loc); + expr.Error_UnexpectedKind (ec, "variable, indexer or property access", loc); return null; } @@ -1031,7 +1034,7 @@ namespace Mono.CSharp { public abstract class Probe : Expression { public Expression ProbeType; protected Expression expr; - protected Type probe_type; + protected TypeExpr probe_type_expr; public Probe (Expression expr, Expression probe_type, Location l) { @@ -1048,12 +1051,11 @@ namespace Mono.CSharp { public override Expression DoResolve (EmitContext ec) { - TypeExpr texpr = ProbeType.ResolveAsTypeTerminal (ec); - if (texpr == null) + probe_type_expr = ProbeType.ResolveAsTypeTerminal (ec); + if (probe_type_expr == null) + return null; + if (probe_type_expr.ResolveType (ec) == null) return null; - probe_type = texpr.Type; - - CheckObsoleteAttribute (probe_type); expr = expr.Resolve (ec); if (expr == null) @@ -1105,7 +1107,7 @@ namespace Mono.CSharp { ig.Emit (OpCodes.Ceq); return; case Action.Probe: - ig.Emit (OpCodes.Isinst, probe_type); + ig.Emit (OpCodes.Isinst, probe_type_expr.Type); ig.Emit (OpCodes.Ldnull); ig.Emit (OpCodes.Cgt_Un); return; @@ -1135,7 +1137,7 @@ namespace Mono.CSharp { return; case Action.Probe: expr.Emit (ec); - ig.Emit (OpCodes.Isinst, probe_type); + ig.Emit (OpCodes.Isinst, probe_type_expr.Type); ig.Emit (onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target); return; } @@ -1160,8 +1162,9 @@ namespace Mono.CSharp { // First case, if at compile time, there is an implicit conversion // then e != null (objects) or true (value types) // + Type probe_type = probe_type_expr.Type; e = Convert.ImplicitConversionStandard (ec, expr, probe_type, loc); - if (e != null){ + if (e != null && !(e is NullCast)){ expr = e; if (etype.IsValueType) action = Action.AlwaysTrue; @@ -1186,10 +1189,10 @@ namespace Mono.CSharp { } if (warning_always_matches) - Warning (183, "The given expression is always of the provided (`{0}') type", TypeManager.CSharpName (probe_type)); + Report.Warning (183, 1, loc, "The given expression is always of the provided (`{0}') type", TypeManager.CSharpName (probe_type)); else if (warning_never_matches){ if (!(probe_type.IsInterface || expr.Type.IsInterface)) - Warning (184, "The given expression is never of the provided (`{0}') type", TypeManager.CSharpName (probe_type)); + Report.Warning (184, 1, loc, "The given expression is never of the provided (`{0}') type", TypeManager.CSharpName (probe_type)); } return this; @@ -1206,6 +1209,7 @@ namespace Mono.CSharp { } bool do_isinst = false; + Expression resolved_type; public override void Emit (EmitContext ec) { @@ -1214,7 +1218,7 @@ namespace Mono.CSharp { expr.Emit (ec); if (do_isinst) - ig.Emit (OpCodes.Isinst, probe_type); + ig.Emit (OpCodes.Isinst, probe_type_expr.Type); } static void Error_CannotConvertType (Type source, Type target, Location loc) @@ -1226,30 +1230,56 @@ 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; + type = probe_type_expr.Type; eclass = ExprClass.Value; Type etype = expr.Type; - if (TypeManager.IsValueType (probe_type)){ + if (type.IsValueType) { Report.Error (77, loc, "The as operator must be used with a reference type (`" + - TypeManager.CSharpName (probe_type) + "' is a value type)"); + TypeManager.CSharpName (type) + "' is a value type)"); return null; } + + // + // If the type is a type parameter, ensure + // that it is constrained by a class + // + TypeParameterExpr tpe = probe_type_expr as TypeParameterExpr; + if (tpe != null){ + Constraints constraints = tpe.TypeParameter.Constraints; + bool error = false; + + if (constraints == null) + error = true; + else { + if (!constraints.HasClassConstraint) + if ((constraints.Attributes & GenericParameterAttributes.ReferenceTypeConstraint) == 0) + error = true; + } + if (error){ + Report.Error (413, loc, + "The as operator requires that the `{0}' type parameter be constrained by a class", + probe_type_expr); + return null; + } + } - e = Convert.ImplicitConversion (ec, expr, probe_type, loc); + Expression e = Convert.ImplicitConversion (ec, expr, type, loc); if (e != null){ expr = e; do_isinst = false; return this; } - if (Convert.ExplicitReferenceConversionExists (etype, probe_type)){ + if (Convert.ExplicitReferenceConversionExists (etype, type)){ if (etype.IsGenericParameter) expr = new BoxedCast (expr, etype); @@ -1257,7 +1287,7 @@ namespace Mono.CSharp { return this; } - Error_CannotConvertType (etype, probe_type, loc); + Error_CannotConvertType (etype, type, loc); return null; } } @@ -1272,6 +1302,11 @@ namespace Mono.CSharp { Expression target_type; Expression expr; + public Cast (Expression cast_type, Expression expr) + : this (cast_type, expr, cast_type.Location) + { + } + public Cast (Expression cast_type, Expression expr, Location loc) { this.target_type = cast_type; @@ -1293,496 +1328,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; - } - - /// - /// Attempts to do a compile-time folding of a constant cast. - /// - Expression TryReduce (EmitContext ec, Type 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) { @@ -1808,9 +1353,7 @@ namespace Mono.CSharp { if (target == null) return null; - type = target.Type; - - CheckObsoleteAttribute (type); + type = target.ResolveType (ec); if (type.IsAbstract && type.IsSealed) { Report.Error (716, loc, "Cannot convert to static type `{0}'", TypeManager.CSharpName (type)); @@ -1819,11 +1362,11 @@ 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) { + c = c.TryReduce (ec, type, loc); + if (c != null) + return c; } if (type.IsPointer && !ec.InUnsafe) { @@ -1891,12 +1434,12 @@ namespace Mono.CSharp { oper_names [(int) Operator.LogicalAnd] = "op_LogicalAnd"; } - public Binary (Operator oper, Expression left, Expression right, Location loc) + public Binary (Operator oper, Expression left, Expression right) { this.oper = oper; this.left = left; this.right = right; - this.loc = loc; + this.loc = left.Location; } public Operator Oper { @@ -1930,7 +1473,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 +1566,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 +1609,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 +1626,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 +1670,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 +1683,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 +1718,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 +1731,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 +1802,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), loc); + 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), loc); + right = new Binary (Binary.Operator.BitwiseAnd, right, new IntConstant (63, loc)); right = right.DoResolve (ec); } @@ -2271,6 +1825,13 @@ namespace Mono.CSharp { t == TypeManager.delegate_type || t.IsSubclassOf (TypeManager.delegate_type); } + static void Warning_UnintendedReferenceComparison (Location loc, string side, Type type) + { + Report.Warning ((side == "left" ? 252 : 253), 2, loc, + "Possible unintended reference comparison; to get a value comparison, " + + "cast the {0} hand side to type `{1}'.", side, TypeManager.CSharpName (type)); + } + Expression ResolveOperator (EmitContext ec) { Type l = left.Type; @@ -2283,7 +1844,7 @@ namespace Mono.CSharp { return null; } - left = new BoxedCast (left); + left = new BoxedCast (left, TypeManager.object_type); Type = TypeManager.bool_type; return this; } @@ -2294,7 +1855,7 @@ namespace Mono.CSharp { return null; } - right = new BoxedCast (right); + right = new BoxedCast (right, TypeManager.object_type); Type = TypeManager.bool_type; return this; } @@ -2321,22 +1882,21 @@ namespace Mono.CSharp { // Do not perform operator overload resolution when both sides are // built-in types // + Expression left_operators = null, right_operators = null; if (!(TypeManager.IsPrimitiveType (l) && TypeManager.IsPrimitiveType (r))){ // // Step 1: Perform Operator Overload location // - Expression left_expr, right_expr; - string op = oper_names [(int) oper]; MethodGroupExpr union; - left_expr = MemberLookup (ec, l, op, MemberTypes.Method, AllBindingFlags, loc); + left_operators = MemberLookup (ec, l, op, MemberTypes.Method, AllBindingFlags, loc); if (r != l){ - right_expr = MemberLookup ( + right_operators = MemberLookup ( ec, r, op, MemberTypes.Method, AllBindingFlags, loc); - union = Invocation.MakeUnionSet (left_expr, right_expr, loc); + union = Invocation.MakeUnionSet (left_operators, right_operators, loc); } else - union = (MethodGroupExpr) left_expr; + union = (MethodGroupExpr) left_operators; if (union != null) { ArrayList args = new ArrayList (2); @@ -2364,7 +1924,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) { @@ -2437,6 +1997,21 @@ namespace Mono.CSharp { } } + if (l.IsGenericParameter && r.IsGenericParameter) { + GenericConstraints l_gc, r_gc; + + l_gc = TypeManager.GetTypeParameterConstraints (l); + r_gc = TypeManager.GetTypeParameterConstraints (r); + + if ((l_gc == null) || (r_gc == null) || + !(l_gc.HasReferenceTypeConstraint || l_gc.HasClassConstraint) || + !(r_gc.HasReferenceTypeConstraint || r_gc.HasClassConstraint)) { + Error_OperatorCannotBeApplied (); + return null; + } + + } + // // operator != (object a, object b) // operator == (object a, object b) @@ -2444,26 +2019,47 @@ namespace Mono.CSharp { // For this to be used, both arguments have to be reference-types. // Read the rationale on the spec (14.9.6) // - // Also, if at compile time we know that the classes do not inherit - // one from the other, then we catch the error there. - // if (!(l.IsValueType || r.IsValueType)){ type = TypeManager.bool_type; if (l == r) return this; - if (l.IsSubclassOf (r) || r.IsSubclassOf (l)) - return this; - // // Also, a standard conversion must exist from either one // - if (!(Convert.ImplicitStandardConversionExists (ec, left, r) || - Convert.ImplicitStandardConversionExists (ec, right, l))){ + bool left_to_right = + Convert.ImplicitStandardConversionExists (ec, left, r); + bool right_to_left = !left_to_right && + Convert.ImplicitStandardConversionExists (ec, right, l); + + if (!left_to_right && !right_to_left) { Error_OperatorCannotBeApplied (); return null; } + + if (left_to_right && left_operators != null && + RootContext.WarningLevel >= 2) { + ArrayList args = new ArrayList (2); + args.Add (new Argument (left, Argument.AType.Expression)); + args.Add (new Argument (left, Argument.AType.Expression)); + MethodBase method = Invocation.OverloadResolve ( + ec, (MethodGroupExpr) left_operators, args, true, Location.Null); + if (method != null) + Warning_UnintendedReferenceComparison (loc, "right", l); + } + + if (right_to_left && right_operators != null && + RootContext.WarningLevel >= 2) { + ArrayList args = new ArrayList (2); + args.Add (new Argument (right, Argument.AType.Expression)); + args.Add (new Argument (right, Argument.AType.Expression)); + MethodBase method = Invocation.OverloadResolve ( + ec, (MethodGroupExpr) right_operators, args, true, Location.Null); + if (method != null) + Warning_UnintendedReferenceComparison (loc, "left", r); + } + // // We are going to have to convert to an object to compare // @@ -2703,7 +2299,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; @@ -2748,6 +2344,43 @@ 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 ((oper == Operator.Subtraction) && (left is ParenthesizedExpression)) { @@ -2757,7 +2390,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 @@ -2781,9 +2414,18 @@ namespace Mono.CSharp { return null; eclass = ExprClass.Value; - Constant rc = right as Constant; + if (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 ? @@ -2797,20 +2439,129 @@ 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; + } if (rc != null && lc != null){ + int prev_e = Report.Errors; Expression e = ConstantFold.BinaryFold ( ec, oper, lc, rc, loc); - if (e != null) + if (e != null || Report.Errors != prev_e) return e; } if (TypeManager.IsNullableType (left.Type) || TypeManager.IsNullableType (right.Type)) return new Nullable.LiftedBinaryOperator (oper, left, right, loc).Resolve (ec); + // 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); + } + 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 @@ -3224,7 +2975,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; } } @@ -3381,7 +3132,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 () @@ -3519,7 +3270,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); @@ -3555,12 +3306,12 @@ namespace Mono.CSharp { public class Conditional : Expression { Expression expr, trueExpr, falseExpr; - public Conditional (Expression expr, Expression trueExpr, Expression falseExpr, Location l) + public Conditional (Expression expr, Expression trueExpr, Expression falseExpr) { this.expr = expr; this.trueExpr = trueExpr; this.falseExpr = falseExpr; - this.loc = l; + this.loc = expr.Location; } public Expression Expr { @@ -3599,6 +3350,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); @@ -3712,6 +3468,12 @@ 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) { @@ -3749,7 +3511,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) @@ -3781,11 +3543,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 () @@ -4041,7 +3799,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; @@ -4409,11 +4167,11 @@ namespace Mono.CSharp { // FIXME: only allow expr to be a method invocation or a // delegate invocation (7.5.5) // - public Invocation (Expression expr, ArrayList arguments, Location l) + public Invocation (Expression expr, ArrayList arguments) { this.expr = expr; Arguments = arguments; - loc = l; + loc = expr.Location; } public Expression Expr { @@ -4423,7 +4181,7 @@ namespace Mono.CSharp { } /// - /// Determines "better conversion" as specified in 7.4.2.3 + /// Determines "better conversion" as specified in 14.4.2.3 /// /// Returns : p if a->p is better, /// q if a->q is better, @@ -4841,7 +4599,7 @@ namespace Mono.CSharp { 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, + if (!TypeManager.IsEqual (a.Type, pd.ParameterType (i)) && !Convert.ImplicitConversionExists (ec, a.Expr, pd.ParameterType (i))) return false; @@ -4985,6 +4743,7 @@ namespace Mono.CSharp { // Okay so we have failed to find anything so we // return by providing info about the closest match // + int errors = Report.Errors; for (int i = 0; i < methods.Length; ++i) { MethodBase c = (MethodBase) methods [i]; ParameterData pd = TypeManager.GetParameterData (c); @@ -4997,11 +4756,16 @@ namespace Mono.CSharp { VerifyArgumentsCompat (ec, Arguments, arg_count, c, false, null, may_fail, loc); - break; - } - if (!may_fail) { + 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; + } + if (!may_fail && errors == Report.Errors) { string report_name = me.Name; if (report_name == ".ctor") report_name = me.DeclaringType.ToString (); @@ -5024,9 +4788,7 @@ namespace Mono.CSharp { return null; } - Error_WrongNumArguments ( - loc, report_name, arg_count); - return null; + Error_WrongNumArguments (loc, report_name, arg_count); } return null; @@ -5104,7 +4866,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 @@ -5171,13 +4932,8 @@ namespace Mono.CSharp { public static void Error_WrongNumArguments (Location loc, String name, int arg_count) { - if (name == "Finalize" && arg_count == 0) { - Report.Error (245, loc, "Destructors and object.Finalize cannot be called directly. Consider calling IDisposable.Dispose if available"); - } - else { - Report.Error (1501, loc, "No overload for method `{0}' takes `{1}' arguments", - name, arg_count); - } + Report.Error (1501, loc, "No overload for method `{0}' takes `{1}' arguments", + name, arg_count); } static void Error_InvokeOnDelegate (Location loc) @@ -5382,17 +5138,16 @@ namespace Mono.CSharp { return null; } - if (method.Name == "Finalize" && Arguments == null) { - Report.Error (250, loc, "Do not directly call your base class Finalize method. It is called automatically from your destructor"); + if (Arguments == null && method.Name == "Finalize") { + if (mg.IsBase) + Report.Error (250, loc, "Do not directly call your base class Finalize method. It is called automatically from your destructor"); + else + Report.Error (245, loc, "Destructors and object.Finalize cannot be called directly. Consider calling IDisposable.Dispose if available"); 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) @@ -5402,6 +5157,32 @@ namespace Mono.CSharp { 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 // @@ -5452,33 +5233,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]; @@ -5646,57 +5406,54 @@ namespace Mono.CSharp { // if (!omit_args) { Type t = null; - if (this_call) { - ig.Emit (OpCodes.Ldarg_0); - t = decl_type; - } else { - Type iexpr_type = instance_expr.Type; + Type iexpr_type = instance_expr.Type; + // + // Push the instance expression + // + if (TypeManager.IsValueType (iexpr_type)) { // - // Push the instance expression - // - if (TypeManager.IsValueType (iexpr_type)) { + // Special case: calls to a function declared in a + // reference-type with a value-type argument need + // to have their value boxed. + if (decl_type.IsValueType || + iexpr_type.IsGenericParameter) { // - // Special case: calls to a function declared in a - // reference-type with a value-type argument need - // to have their value boxed. - if (decl_type.IsValueType || - iexpr_type.IsGenericParameter) { - // - // If the expression implements IMemoryLocation, then - // we can optimize and use AddressOf on the - // return. - // - // If not we have to use some temporary storage for - // it. - if (instance_expr is IMemoryLocation) { - ((IMemoryLocation)instance_expr). - AddressOf (ec, AddressOp.LoadStore); - } else { - LocalTemporary temp = new LocalTemporary (ec, iexpr_type); - instance_expr.Emit (ec); - temp.Store (ec); - temp.AddressOf (ec, AddressOp.Load); - } - - // avoid the overhead of doing this all the time. - if (dup_args) - t = TypeManager.GetReferenceType (iexpr_type); + // If the expression implements IMemoryLocation, then + // we can optimize and use AddressOf on the + // return. + // + // If not we have to use some temporary storage for + // it. + if (instance_expr is IMemoryLocation) { + ((IMemoryLocation)instance_expr). + AddressOf (ec, AddressOp.LoadStore); } else { + LocalTemporary temp = new LocalTemporary (ec, iexpr_type); instance_expr.Emit (ec); - ig.Emit (OpCodes.Box, instance_expr.Type); - t = TypeManager.object_type; + temp.Store (ec); + temp.AddressOf (ec, AddressOp.Load); } + + // avoid the overhead of doing this all the time. + if (dup_args) + t = TypeManager.GetReferenceType (iexpr_type); } else { instance_expr.Emit (ec); - t = instance_expr.Type; + ig.Emit (OpCodes.Box, instance_expr.Type); + t = TypeManager.object_type; } + } else { + instance_expr.Emit (ec); + t = instance_expr.Type; } 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); + } } } } @@ -5758,11 +5515,11 @@ namespace Mono.CSharp { Expression expr; Expression argument; - public InvocationOrCast (Expression expr, Expression argument, Location loc) + public InvocationOrCast (Expression expr, Expression argument) { this.expr = expr; this.argument = argument; - this.loc = loc; + this.loc = expr.Location; } public override Expression DoResolve (EmitContext ec) @@ -5904,7 +5661,7 @@ namespace Mono.CSharp { value_target = value; value_target_set = true; if (!(value_target is IMemoryLocation)){ - Error_UnexpectedKind ("variable", loc); + Error_UnexpectedKind (null, "variable", loc); return false; } return true; @@ -5941,34 +5698,34 @@ namespace Mono.CSharp { /// /// Converts complex core type syntax like 'new int ()' to simple constant /// - Expression Constantify (Type t) + 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; } @@ -5988,26 +5745,20 @@ namespace Mono.CSharp { return RequestedType; return this; } - + TypeExpr texpr = RequestedType.ResolveAsTypeTerminal (ec); if (texpr == null) return null; + type = texpr.ResolveType (ec); + if (Arguments == null) { Expression c = Constantify (type); if (c != null) return c; } - - type = texpr.Type; - if (type == null) - return null; - - CheckObsoleteAttribute (type); - bool IsDelegate = TypeManager.IsDelegateType (type); - - if (IsDelegate){ + if (TypeManager.IsDelegateType (type)) { RequestedType = (new NewDelegate (type, Arguments, loc)).Resolve (ec); if (RequestedType != null) if (!(RequestedType is DelegateCreation)) @@ -6041,11 +5792,13 @@ 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){ + Report.SymbolRelatedToPreviousError (type); Report.Error (144, loc, "Cannot create an instance of the abstract class or interface `{0}'", TypeManager.CSharpName (type)); return null; } @@ -6060,46 +5813,31 @@ namespace Mono.CSharp { if (is_struct && Arguments == null) return this; - Expression ml; - ml = MemberLookupFinal (ec, type, type, ".ctor", - // For member-lookup, treat 'new Foo (bar)' as call to 'foo.ctor (bar)', where 'foo' is of type 'Foo'. - MemberTypes.Constructor, - AllBindingFlags | BindingFlags.DeclaredOnly, loc); + Expression ml = MemberLookupFinal (ec, type, type, ".ctor", + MemberTypes.Constructor, AllBindingFlags | BindingFlags.DeclaredOnly, loc); if (ml == null) return null; - - if (! (ml is MethodGroupExpr)){ - if (!is_struct){ - ml.Error_UnexpectedKind ("method group", loc); - return null; - } + + MethodGroupExpr mg = ml as MethodGroupExpr; + + if (mg == null) { + ml.Error_UnexpectedKind (ec, "method group", loc); + return null; } - if (ml != null) { - if (Arguments != null){ - foreach (Argument a in Arguments){ - if (!a.Resolve (ec, loc)) - return null; - } + if (Arguments != null){ + foreach (Argument a in Arguments){ + if (!a.Resolve (ec, loc)) + return null; } - - method = Invocation.OverloadResolve ( - ec, (MethodGroupExpr) ml, Arguments, true, loc); - } + method = Invocation.OverloadResolve (ec, mg, Arguments, false, loc); if (method == null) { - if (almostMatchedMembers.Count != 0) { + if (almostMatchedMembers.Count != 0) MemberLookupFailed (ec, type, type, ".ctor", null, true, loc); - return null; - } - - if (!is_struct || Arguments.Count > 0) { - Invocation.Error_WrongNumArguments (loc, TypeManager.CSharpName (type), - Arguments == null ? 0 : Arguments.Count); - return null; - } + return null; } return this; @@ -6410,7 +6148,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; @@ -6418,7 +6156,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; @@ -6498,7 +6236,7 @@ namespace Mono.CSharp { if (array_type_expr == null) return false; - type = array_type_expr.Type; + 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."); @@ -6562,7 +6300,7 @@ namespace Mono.CSharp { AllBindingFlags, loc); if (!(ml is MethodGroupExpr)) { - ml.Error_UnexpectedKind ("method group", loc); + ml.Error_UnexpectedKind (ec, "method group", loc); return null; } @@ -6830,7 +6568,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++) @@ -6840,7 +6578,8 @@ namespace Mono.CSharp { // If we are dealing with a struct, get the // address of it, so we can store it. // - if ((dims == 1) && etype.IsValueType && + if ((dims == 1) && + TypeManager.IsValueType (etype) && (!TypeManager.IsBuiltinOrEnum (etype) || etype == TypeManager.decimal_type)) { if (e is New){ @@ -6986,8 +6725,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) @@ -7004,8 +6742,8 @@ namespace Mono.CSharp { return false; } - if ((block != null) && (block.ThisVariable != null)) - variable_info = block.ThisVariable.VariableInfo; + if (block != null && block.Toplevel.ThisVariable != null) + variable_info = block.Toplevel.ThisVariable.VariableInfo; if (ec.CurrentAnonymousMethod != null) ec.CaptureThis (); @@ -7018,7 +6756,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; @@ -7130,7 +6868,7 @@ namespace Mono.CSharp { if (!ResolveBase (ec)) return null; - if (ec.IsFieldInitializer || !ec.CurrentBlock.HasVarargs) { + if (ec.IsFieldInitializer || !ec.CurrentBlock.Toplevel.HasVarargs) { Error (190, "The __arglist construct is valid only within " + "a variable argument method."); return null; @@ -7229,7 +6967,7 @@ namespace Mono.CSharp { if (texpr == null) return null; - typearg = texpr.Type; + typearg = texpr.ResolveType (ec); if (typearg == TypeManager.void_type) { Error (673, "System.Void cannot be used from C#. Use typeof (void) to get the void type object"); @@ -7240,7 +6978,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. @@ -7303,11 +7040,11 @@ namespace Mono.CSharp { return null; } - type_queried = texpr.Type; + type_queried = texpr.ResolveType (ec); int size_of = GetTypeSize (type_queried); if (size_of > 0) { - return new IntConstant (size_of); + return new IntConstant (size_of, loc); } if (!ec.InUnsafe) { @@ -7316,8 +7053,6 @@ namespace Mono.CSharp { return null; } - CheckObsoleteAttribute (type_queried); - if (!TypeManager.VerifyUnManaged (type_queried, loc)){ return null; } @@ -7338,19 +7073,103 @@ namespace Mono.CSharp { } } + /// + /// Implements the qualified-alias-member (::) expression. + /// + public class QualifiedAliasMember : Expression + { + string alias, identifier; + + public QualifiedAliasMember (string alias, string identifier, Location l) + { + this.alias = alias; + this.identifier = identifier; + loc = l; + } + + public override FullNamedExpression ResolveAsTypeStep (EmitContext ec, bool silent) + { + if (alias == "global") + return new MemberAccess (Namespace.Root, identifier, loc).ResolveAsTypeStep (ec, silent); + + int errors = Report.Errors; + FullNamedExpression fne = ec.DeclSpace.NamespaceEntry.LookupAlias (alias); + if (fne == null) { + if (errors == Report.Errors) + Report.Error (432, loc, "Alias `{0}' not found", alias); + return null; + } + if (fne.eclass != ExprClass.Namespace) { + if (!silent) + 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); + } + + public override Expression DoResolve (EmitContext ec) + { + FullNamedExpression fne; + if (alias == "global") { + fne = Namespace.Root; + } else { + int errors = Report.Errors; + fne = ec.DeclSpace.NamespaceEntry.LookupAlias (alias); + if (fne == null) { + if (errors == Report.Errors) + Report.Error (432, loc, "Alias `{0}' not found", alias); + return null; + } + } + + Expression retval = new MemberAccess (fne, identifier, loc).DoResolve (ec); + if (retval == null) + return null; + + if (!(retval is FullNamedExpression)) { + Report.Error (687, loc, "The expression `{0}::{1}' did not resolve to a namespace or a type", alias, identifier); + return null; + } + + // We defer this check till the end to match the behaviour of CSC + if (fne.eclass != ExprClass.Namespace) { + Report.Error (431, loc, "`{0}' cannot be used with '::' since it denotes a type", alias); + return null; + } + return retval; + } + + public override void Emit (EmitContext ec) + { + throw new InternalErrorException ("QualifiedAliasMember found in resolved tree"); + } + + + public override string ToString () + { + return alias + "::" + identifier; + } + + public override string GetSignatureForError () + { + return ToString (); + } + } + /// /// Implements the member access expression /// public class MemberAccess : Expression { - public string Identifier; - protected Expression expr; - protected TypeArguments args; + public readonly string Identifier; + Expression expr; + TypeArguments args; + // TODO: Location can be removed public MemberAccess (Expression expr, string id, Location l) { this.expr = expr; Identifier = id; - loc = l; + loc = expr.Location; } public MemberAccess (Expression expr, string id, TypeArguments args, @@ -7361,11 +7180,11 @@ namespace Mono.CSharp { } public Expression Expr { - get { - return expr; - } + get { return expr; } } + // TODO: this method has very poor performace for Enum fields and + // probably for other constants as well Expression DoResolve (EmitContext ec, Expression right_side) { if (type != null) @@ -7379,14 +7198,15 @@ namespace Mono.CSharp { // SimpleName original = expr as SimpleName; - expr = expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.Type | - ResolveFlags.Intermediate | ResolveFlags.DisableFlowAnalysis); + Expression new_expr = expr.Resolve (ec, + ResolveFlags.VariableOrValue | ResolveFlags.Type | + ResolveFlags.Intermediate | ResolveFlags.DisableStructFlowAnalysis); - if (expr == null) + if (new_expr == null) return null; - if (expr is Namespace) { - Namespace ns = (Namespace) expr; + if (new_expr is Namespace) { + Namespace ns = (Namespace) new_expr; string lookup_id = MemberName.MakeName (Identifier, args); FullNamedExpression retval = ns.Lookup (ec.DeclSpace, lookup_id, loc); if ((retval != null) && (args != null)) @@ -7396,59 +7216,8 @@ namespace Mono.CSharp { Identifier, ns.FullName); return retval; } - - // - // TODO: I mailed Ravi about this, and apparently we can get rid - // of this and put it in the right place. - // - // Handle enums here when they are in transit. - // Note that we cannot afford to hit MemberLookup in this case because - // it will fail to find any members at all - // - - Type expr_type; - if (expr is TypeExpr){ - expr_type = expr.Type; - - if (!ec.DeclSpace.CheckAccessLevel (expr_type)){ - ErrorIsInaccesible (loc, TypeManager.CSharpName (expr_type)); - return null; - } - - if (expr_type == TypeManager.enum_type || expr_type.IsSubclassOf (TypeManager.enum_type)){ - Enum en = TypeManager.LookupEnum (expr_type); - - if (en != null) { - object value = en.LookupEnumValue (Identifier, loc); - - if (value != null){ - MemberCore mc = en.GetDefinition (Identifier); - ObsoleteAttribute oa = mc.GetObsoleteAttribute (en); - if (oa != null) { - AttributeTester.Report_ObsoleteMessage (oa, mc.GetSignatureForError (), Location); - } - oa = en.GetObsoleteAttribute (en); - if (oa != null) { - AttributeTester.Report_ObsoleteMessage (oa, en.GetSignatureForError (), Location); - } - Constant c = Constantify (value, en.UnderlyingType); - return new EnumConstant (c, expr_type); - } - } else { - CheckObsoleteAttribute (expr_type); - - FieldInfo fi = expr_type.GetField (Identifier); - if (fi != null) { - ObsoleteAttribute oa = AttributeTester.GetMemberObsoleteAttribute (fi); - if (oa != null) - AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (fi), Location); - } - } - } - } else - expr_type = expr.Type; - + Type expr_type = new_expr.Type; if (expr_type.IsPointer){ Error (23, "The `.' operator can not be applied to pointer operands (" + TypeManager.CSharpName (expr_type) + ")"); @@ -7470,14 +7239,14 @@ namespace Mono.CSharp { } if (member_lookup is TypeExpr) { - if (!(expr is TypeExpr) && - (original == null || !original.IdenticalNameAndTypeName (ec, expr, loc))) { + if (!(new_expr is TypeExpr) && + (original == null || !original.IdenticalNameAndTypeName (ec, new_expr, loc))) { Report.Error (572, loc, "`{0}': cannot reference a type through an expression; try `{1}' instead", Identifier, member_lookup.GetSignatureForError ()); return null; } - ConstructedType ct = expr as ConstructedType; + ConstructedType ct = new_expr as ConstructedType; if (ct != null) { // // When looking up a nested type in a generic instance @@ -7496,7 +7265,7 @@ namespace Mono.CSharp { } MemberExpr me = (MemberExpr) member_lookup; - member_lookup = me.ResolveMemberAccess (ec, expr, loc, original); + member_lookup = me.ResolveMemberAccess (ec, new_expr, loc, original); if (member_lookup == null) return null; @@ -7508,15 +7277,22 @@ namespace Mono.CSharp { return mg.ResolveGeneric (ec, args); } + 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) @@ -7529,17 +7305,19 @@ namespace Mono.CSharp { return DoResolve (ec, right_side); } - public override FullNamedExpression ResolveAsTypeStep (EmitContext ec) + public override FullNamedExpression ResolveAsTypeStep (EmitContext ec, bool silent) { - return ResolveNamespaceOrType (ec, false); + return ResolveNamespaceOrType (ec, silent); } public FullNamedExpression ResolveNamespaceOrType (EmitContext ec, bool silent) { - FullNamedExpression new_expr = expr.ResolveAsTypeStep (ec); + FullNamedExpression new_expr = expr.ResolveAsTypeStep (ec, silent); - if (new_expr == null) + if (new_expr == null) { + Report.Error (234, "No such name or typespace {0}", expr); return null; + } string lookup_id = MemberName.MakeName (Identifier, args); @@ -7558,7 +7336,7 @@ namespace Mono.CSharp { if (tnew_expr == null) return null; - Type expr_type = tnew_expr.Type; + Type expr_type = tnew_expr.ResolveType (ec); if (expr_type.IsPointer){ Error (23, "The `.' operator can not be applied to pointer operands (" + @@ -7566,20 +7344,22 @@ namespace Mono.CSharp { return null; } - Expression member_lookup = MemberLookup (ec, expr_type, expr_type, lookup_id, loc); + Expression member_lookup = MemberLookup ( + ec, ec.ContainerType, expr_type, expr_type, lookup_id, + MemberTypes.NestedType, BindingFlags.Public | BindingFlags.NonPublic, loc); if (member_lookup == null) { int errors = Report.Errors; MemberLookupFailed (ec, expr_type, expr_type, lookup_id, null, false, loc); - if (!silent && errors == Report.Errors) - Report.Error (234, loc, "The type or namespace name `{0}' does not exist in the namespace `{1}'. Are you missing an assembly reference?", - lookup_id, new_expr.FullName); + if (!silent && errors == Report.Errors) { + Report.Error (426, loc, "The nested type `{0}' does not exist in the type `{1}'", + Identifier, new_expr.GetSignatureForError ()); + } return null; } if (!(member_lookup is TypeExpr)) { - Report.Error (118, loc, "`{0}.{1}' denotes a `{2}', where a type was expected", - new_expr.FullName, lookup_id, member_lookup.ExprClassName ()); + new_expr.Error_UnexpectedKind (ec, "type", loc); return null; } @@ -7618,6 +7398,11 @@ namespace Mono.CSharp { { return expr + "." + MemberName.MakeName (Identifier, args); } + + public override string GetSignatureForError () + { + return expr.GetSignatureForError () + "." + Identifier; + } } /// @@ -7728,11 +7513,11 @@ namespace Mono.CSharp { public ArrayList Arguments; public Expression Expr; - public ElementAccess (Expression e, ArrayList e_list, Location l) + public ElementAccess (Expression e, ArrayList e_list) { Expr = e; - loc = l; + loc = e.Location; if (e_list == null) return; @@ -7965,6 +7750,8 @@ namespace Mono.CSharp { ig.Emit (OpCodes.Ldobj, type); } else if (type.IsGenericParameter) ig.Emit (OpCodes.Ldelem_Any, type); + else if (type.IsPointer) + ig.Emit (OpCodes.Ldelem_I); else ig.Emit (OpCodes.Ldelem_Ref); } @@ -8005,7 +7792,9 @@ namespace Mono.CSharp { } else if (t.IsGenericParameter) { has_type_arg = true; return OpCodes.Stelem_Any; - } else + } else if (t.IsPointer) + return OpCodes.Stelem_I; + else return OpCodes.Stelem_Ref; } @@ -8770,6 +8559,11 @@ namespace Mono.CSharp { Expression left; string dim; + public ComposedCast (Expression left, string dim) + : this (left, dim, left.Location) + { + } + public ComposedCast (Expression left, string dim, Location l) { this.left = left; @@ -8794,7 +8588,10 @@ namespace Mono.CSharp { if (lexpr == null) return null; - Type ltype = lexpr.Type; + bool old = ec.TestObsoleteMethodUsage; + ec.TestObsoleteMethodUsage = true; + Type ltype = lexpr.ResolveType (ec); + ec.TestObsoleteMethodUsage = old; if ((ltype == TypeManager.void_type) && (dim != "*")) { Report.Error (1547, Location, @@ -8850,7 +8647,7 @@ namespace Mono.CSharp { } } - public class FixedBufferPtr: Expression { + public class FixedBufferPtr : Expression { Expression array; public FixedBufferPtr (Expression array, Type array_type, Location l) @@ -8976,7 +8773,7 @@ namespace Mono.CSharp { if (texpr == null) return null; - otype = texpr.Type; + otype = texpr.ResolveType (ec); if (!TypeManager.VerifyUnManaged (otype, loc)) return null;