X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fecore.cs;h=69c937ce0d956b0a008aff432cc9d06c0c0095eb;hb=43b6678d45b2cf3705971998e1f04f67ef4d7667;hp=0d28f18171d05f885b2c61b4af8895adf22ea7f6;hpb=7e63f5f28c115d4bc7c73d035d2c57dcb05f1604;p=mono.git diff --git a/mcs/mcs/ecore.cs b/mcs/mcs/ecore.cs index 0d28f18171d..69c937ce0d9 100644 --- a/mcs/mcs/ecore.cs +++ b/mcs/mcs/ecore.cs @@ -266,11 +266,8 @@ namespace Mono.CSharp { FullNamedExpression fne = ResolveAsTypeStep (ec, silent); - if (fne == null){ - if (!silent && errors == Report.Errors) - Report.Error (118, loc, "Expecting a type."); + if (fne == null) return null; - } if (fne.eclass != ExprClass.Type) { if (!silent && errors == Report.Errors) @@ -297,8 +294,8 @@ namespace Mono.CSharp { protected static void Error_CannotAccessProtected (Location loc, MemberInfo m, Type qualifier, Type container) { - Report.Error (1540, loc, "Cannot access protected member `{0}' via a qualifier of type `{1}';" - + " the qualifier must be of type `{2}' (or derived from it)", + Report.Error (1540, loc, "Cannot access protected member `{0}' via a qualifier of type `{1}'." + + " The qualifier must be of type `{2}' or derived from it", TypeManager.GetFullNameSignature (m), TypeManager.CSharpName (qualifier), TypeManager.CSharpName (container)); @@ -316,7 +313,7 @@ namespace Mono.CSharp { Report.Error (1547, loc, "Keyword `void' cannot be used in this context"); } - public virtual void Error_ValueCannotBeConverted (Location loc, Type target, bool expl) + public virtual void Error_ValueCannotBeConverted (EmitContext ec, Location loc, Type target, bool expl) { if (Type.FullName == target.FullName){ Report.ExtraInformation (loc, @@ -335,15 +332,20 @@ namespace Mono.CSharp { Expression e = (this is EnumConstant) ? ((EnumConstant)this).Child : this; bool b = Convert.ExplicitNumericConversion (e, target) != null; - if (b || Convert.ExplicitReferenceConversionExists (Type, target) || Convert.ExplicitUnsafe (e, target) != null) { - Report.Error (266, loc, "Cannot implicitly convert type `{0}' to `{1}'. An explicit conversion exists (are you missing a cast?)", + if (b || + Convert.ExplicitReferenceConversionExists (Type, target) || + Convert.ExplicitUnsafe (e, target) != null || + (ec != null && Convert.UserDefinedConversion (ec, this, target, Location.Null, true) != null)) + { + Report.Error (266, loc, "Cannot implicitly convert type `{0}' to `{1}'. " + + "An explicit conversion exists (are you missing a cast?)", TypeManager.CSharpName (Type), TypeManager.CSharpName (target)); return; } if (Type != TypeManager.string_type && this is Constant && !(this is EmptyConstantCast)) { Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'", - GetSignatureForError (), TypeManager.CSharpName (target)); + ((Constant)(this)).GetValue ().ToString (), TypeManager.CSharpName (target)); return; } @@ -359,6 +361,11 @@ namespace Mono.CSharp { TypeManager.CSharpName (type), name); } + protected static void Error_ValueAssignment (Location loc) + { + Report.Error (131, loc, "The left-hand side of an assignment must be a variable, a property or an indexer"); + } + ResolveFlags ExprClassToResolveFlags { get { @@ -489,7 +496,7 @@ namespace Mono.CSharp { if (out_access) Report.Error (1510, loc, "A ref or out argument must be an assignable variable"); else - Report.Error (131, loc, "The left-hand side of an assignment or mutating operation must be a variable, property or indexer"); + Error_ValueAssignment (loc); } return null; } @@ -535,64 +542,6 @@ namespace Mono.CSharp { type = null; } - /// - /// Returns a literalized version of a literal FieldInfo - /// - /// - /// - /// The possible return values are: - /// IntConstant, UIntConstant - /// LongLiteral, ULongConstant - /// FloatConstant, DoubleConstant - /// StringConstant - /// - /// The value returned is already resolved. - /// - public static Constant Constantify (object v, Type t) - { - if (t == TypeManager.int32_type) - return new IntConstant ((int) v, Location.Null); - else if (t == TypeManager.uint32_type) - return new UIntConstant ((uint) v, Location.Null); - else if (t == TypeManager.int64_type) - return new LongConstant ((long) v, Location.Null); - else if (t == TypeManager.uint64_type) - return new ULongConstant ((ulong) v, Location.Null); - else if (t == TypeManager.float_type) - return new FloatConstant ((float) v, Location.Null); - else if (t == TypeManager.double_type) - return new DoubleConstant ((double) v, Location.Null); - else if (t == TypeManager.string_type) - return new StringConstant ((string) v, Location.Null); - else if (t == TypeManager.short_type) - return new ShortConstant ((short)v, Location.Null); - else if (t == TypeManager.ushort_type) - return new UShortConstant ((ushort)v, Location.Null); - else if (t == TypeManager.sbyte_type) - return new SByteConstant ((sbyte)v, Location.Null); - else if (t == TypeManager.byte_type) - return new ByteConstant ((byte)v, Location.Null); - else if (t == TypeManager.char_type) - return new CharConstant ((char)v, Location.Null); - else if (t == TypeManager.bool_type) - return new BoolConstant ((bool) v, Location.Null); - else if (t == TypeManager.decimal_type) - return new DecimalConstant ((decimal) v, Location.Null); - else if (TypeManager.IsEnumType (t)){ - Type real_type = TypeManager.TypeToCoreType (v.GetType ()); - if (real_type == t) - real_type = System.Enum.GetUnderlyingType (real_type); - - Constant e = Constantify (v, real_type); - - return new EnumConstant (e, t); - } else if (v == null && !TypeManager.IsValueType (t)) - return new NullLiteral (Location.Null); - else - throw new Exception ("Unknown type for constant (" + t + - "), details: " + v); - } - /// /// Returns a fully formed expression after a MemberLookup /// @@ -682,9 +631,6 @@ namespace Mono.CSharp { continue; } - if (!is_interface) - continue; - Report.SymbolRelatedToPreviousError (m); Report.SymbolRelatedToPreviousError (non_method); Report.Error (229, loc, "Ambiguity between `{0}' and `{1}'", @@ -692,16 +638,29 @@ namespace Mono.CSharp { return null; } - if (non_method != null && is_interface) { - MethodBase method = (MethodBase)methods[0]; - Report.SymbolRelatedToPreviousError (method); - Report.SymbolRelatedToPreviousError (non_method); - Report.Warning (467, 2, loc, "Ambiguity between method `{0}' and non-method `{1}'. Using method `{0}'", - TypeManager.CSharpSignature (method), TypeManager.GetFullNameSignature (non_method)); - } - if (methods.Count == 0) - return new MethodGroupExpr (mi, loc); + return null; + + if (non_method != null) { + MethodBase method = (MethodBase) methods [0]; + + if (method.DeclaringType == non_method.DeclaringType) { + // Cannot happen with C# code, but is valid in IL + Report.SymbolRelatedToPreviousError (method); + Report.SymbolRelatedToPreviousError (non_method); + Report.Error (229, loc, "Ambiguity between `{0}' and `{1}'", + TypeManager.GetFullNameSignature (non_method), + TypeManager.CSharpSignature (method)); + return null; + } + + if (is_interface) { + Report.SymbolRelatedToPreviousError (method); + Report.SymbolRelatedToPreviousError (non_method); + Report.Warning (467, 2, loc, "Ambiguity between method `{0}' and non-method `{1}'. Using method `{0}'", + TypeManager.CSharpSignature (method), TypeManager.GetFullNameSignature (non_method)); + } + } return new MethodGroupExpr (methods, loc); } @@ -739,10 +698,10 @@ namespace Mono.CSharp { name, AllMemberTypes, AllBindingFlags, loc); } - public static Expression MethodLookup (EmitContext ec, Type queried_type, + public static Expression MethodLookup (Type container_type, Type queried_type, string name, Location loc) { - return MemberLookup (ec.ContainerType, null, queried_type, name, + return MemberLookup (container_type, null, queried_type, name, MemberTypes.Method, AllBindingFlags, loc); } @@ -811,7 +770,6 @@ namespace Mono.CSharp { // then we are in this situation. Error_CannotAccessProtected (loc, m, qualifier_type, container_type); } else { - Report.SymbolRelatedToPreviousError (m); ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (m)); } } @@ -895,7 +853,7 @@ namespace Mono.CSharp { return new Nullable.OperatorTrueOrFalse (e, is_true, loc).Resolve (ec); #endif - operator_group = MethodLookup (ec, e.Type, is_true ? "op_True" : "op_False", loc); + operator_group = MethodLookup (ec.ContainerType, e.Type, is_true ? "op_True" : "op_False", loc); if (operator_group == null) return null; @@ -933,7 +891,7 @@ namespace Mono.CSharp { // converted = Expression.GetOperatorTrue (ec, e, loc); if (converted == null){ - e.Error_ValueCannotBeConverted (loc, TypeManager.bool_type, false); + e.Error_ValueCannotBeConverted (ec, loc, TypeManager.bool_type, false); return null; } return converted; @@ -1152,7 +1110,7 @@ namespace Mono.CSharp { target = Convert.ImplicitConversion (ec, source, TypeManager.uint64_type, loc); if (target == null) { - source.Error_ValueCannotBeConverted (loc, TypeManager.int32_type, false); + source.Error_ValueCannotBeConverted (ec, loc, TypeManager.int32_type, false); return null; } } @@ -1256,11 +1214,68 @@ namespace Mono.CSharp { } } + + /// + /// Performs a cast using an operator (op_Explicit or op_Implicit) + /// + public class OperatorCast : EmptyCast { + MethodInfo conversion_operator; + bool find_explicit; + + public OperatorCast (Expression child, Type target_type) : this (child, target_type, false) {} + + public OperatorCast (Expression child, Type target_type, bool find_explicit) + : base (child, target_type) + { + this.find_explicit = find_explicit; + } + + // Returns the implicit operator that converts from + // 'child.Type' to our target type (type) + MethodInfo GetConversionOperator (bool find_explicit) + { + string operator_name = find_explicit ? "op_Explicit" : "op_Implicit"; + + MemberInfo [] mi; + + mi = TypeManager.MemberLookup (child.Type, child.Type, child.Type, MemberTypes.Method, + BindingFlags.Static | BindingFlags.Public, operator_name, null); + + if (mi == null){ + mi = TypeManager.MemberLookup (type, type, type, MemberTypes.Method, + BindingFlags.Static | BindingFlags.Public, operator_name, null); + } + + foreach (MethodInfo oper in mi) { + ParameterData pd = TypeManager.GetParameterData (oper); + + if (pd.ParameterType (0) == child.Type && oper.ReturnType == type) + return oper; + } + + return null; + + + } + public override void Emit (EmitContext ec) + { + ILGenerator ig = ec.ig; + + child.Emit (ec); + conversion_operator = GetConversionOperator (find_explicit); + + if (conversion_operator == null) + throw new InternalErrorException ("Outer conversion routine is out of sync"); + + ig.Emit (OpCodes.Call, conversion_operator); + } + + } + /// /// This is a numeric cast to a Decimal /// public class CastToDecimal : EmptyCast { - MethodInfo conversion_operator; public CastToDecimal (Expression child) @@ -1348,6 +1363,7 @@ namespace Mono.CSharp { } } + // // Constant specialization of EmptyCast. // We need to special case this since an empty cast of @@ -1375,9 +1391,9 @@ namespace Mono.CSharp { return child.GetValue (); } - public override Constant Reduce (bool inCheckedContext, Type target_type) + public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type) { - return child.Reduce (inCheckedContext, target_type); + return child.ConvertExplicitly (inCheckedContext, target_type); } public override Constant Increment () @@ -1400,9 +1416,9 @@ namespace Mono.CSharp { child.Emit (ec); } - public override Constant ToType (Type type) + public override Constant ConvertImplicitly (Type type) { - return child.ToType (type); + return child.ConvertImplicitly (type); } } @@ -1462,37 +1478,8 @@ namespace Mono.CSharp { public override string AsString () { - return Child.AsString (); - } - - public override DoubleConstant ConvertToDouble () - { - return Child.ConvertToDouble (); - } - - public override FloatConstant ConvertToFloat () - { - return Child.ConvertToFloat (); - } - - public override ULongConstant ConvertToULong () - { - return Child.ConvertToULong (); - } - - public override LongConstant ConvertToLong () - { - return Child.ConvertToLong (); - } - - public override UIntConstant ConvertToUInt () - { - return Child.ConvertToUInt (); - } - - public override IntConstant ConvertToInt () - { - return Child.ConvertToInt (); + string value = System.Enum.GetName (type, Child.GetValue ()); + return value == null ? "0" : value; } public override Constant Increment() @@ -1516,15 +1503,15 @@ namespace Mono.CSharp { } } - public override Constant Reduce(bool inCheckedContext, Type target_type) + public override Constant ConvertExplicitly(bool inCheckedContext, Type target_type) { if (Child.Type == target_type) return Child; - return Child.Reduce (inCheckedContext, target_type); + return Child.ConvertExplicitly (inCheckedContext, target_type); } - public override Constant ToType (Type type) + public override Constant ConvertImplicitly (Type type) { if (Type == type) { // This is workaround of mono bug. It can be removed when the latest corlib spreads enough @@ -1532,7 +1519,7 @@ namespace Mono.CSharp { return this; if (type.UnderlyingSystemType != Child.Type) - Child = Child.ToType (type.UnderlyingSystemType); + Child = Child.ConvertImplicitly (type.UnderlyingSystemType); return this; } @@ -1540,7 +1527,7 @@ namespace Mono.CSharp { return null; } - return Child.ToType (type); + return Child.ConvertImplicitly(type); } } @@ -1939,14 +1926,19 @@ namespace Mono.CSharp { public static string RemoveGenericArity (string name) { int start = 0; - StringBuilder sb = new StringBuilder (); - while (start < name.Length) { + StringBuilder sb = null; + do { int pos = name.IndexOf ('`', start); if (pos < 0) { + if (start == 0) + return name; + sb.Append (name.Substring (start)); break; } + if (sb == null) + sb = new StringBuilder (); sb.Append (name.Substring (start, pos-start)); pos++; @@ -1954,7 +1946,7 @@ namespace Mono.CSharp { pos++; start = pos; - } + } while (start < name.Length); return sb.ToString (); } @@ -2096,6 +2088,12 @@ namespace Mono.CSharp { } } + Type t = ec.DeclContainer.NamespaceEntry.NS.LookForAnyGenericType (Name); + if (t != null) { + Namespace.Error_InvalidNumberOfTypeArguments (t, loc); + return null; + } + NamespaceEntry.Error_NamespaceNotFound (loc, Name); return null; } @@ -2294,7 +2292,7 @@ namespace Mono.CSharp { return mg.ResolveGeneric (ec, Arguments); } - if (!me.IsStatic && + if (!me.IsStatic && (me.InstanceExpression != null) && TypeManager.IsNestedFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) && me.InstanceExpression.Type != me.DeclaringType && !TypeManager.IsFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) && @@ -2805,7 +2803,10 @@ namespace Mono.CSharp { Methods = new MethodBase [mi.Length]; mi.CopyTo (Methods, 0); eclass = ExprClass.MethodGroup; - type = TypeManager.object_type; + + // Set the type to something that will never be useful, which will + // trigger the proper conversions. + type = typeof (MethodGroupExpr); loc = l; } @@ -3119,7 +3120,7 @@ namespace Mono.CSharp { ic.CheckObsoleteness (loc); } - return ic.Value; + return ic.CreateConstantReference (loc); } if (t.IsPointer && !ec.InUnsafe) { @@ -3192,8 +3193,6 @@ namespace Mono.CSharp { "this"); return null; } - if ((am.ContainerAnonymousMethod == null) && (InstanceExpression is This)) - ec.CaptureField (this); } } @@ -3520,8 +3519,6 @@ namespace Mono.CSharp { LocalTemporary temp; bool prepared; - internal static PtrHashtable AccessorTable = new PtrHashtable (); - public PropertyExpr (Type containerType, PropertyInfo pi, Location l) { PropertyInfo = pi; @@ -3601,7 +3598,7 @@ namespace Mono.CSharp { // We also perform the permission checking here, as the PropertyInfo does not // hold the information for the accessibility of its setter/getter // - // TODO: can use TypeManager.GetProperty to boost performance + // TODO: Refactor to use some kind of cache together with GetPropertyFromAccessor void ResolveAccessors (Type containerType) { FindAccessors (containerType); @@ -3612,7 +3609,6 @@ namespace Mono.CSharp { if (md != null) md.SetMemberIsUsed (); - AccessorTable [getter] = PropertyInfo; is_static = getter.IsStatic; } @@ -3622,7 +3618,6 @@ namespace Mono.CSharp { if (md != null) md.SetMemberIsUsed (); - AccessorTable [setter] = PropertyInfo; is_static = setter.IsStatic; } } @@ -3639,10 +3634,10 @@ namespace Mono.CSharp { return false; } - if (lvalue_instance) + InstanceExpression = InstanceExpression.DoResolve (ec); + if (lvalue_instance && InstanceExpression != null) InstanceExpression = InstanceExpression.ResolveLValue (ec, EmptyExpression.LValueMemberAccess, loc); - else - InstanceExpression = InstanceExpression.DoResolve (ec); + if (InstanceExpression == null) return false; @@ -3650,8 +3645,9 @@ namespace Mono.CSharp { if (must_do_cs1540_check && (InstanceExpression != EmptyExpression.Null) && !TypeManager.IsInstantiationOfSameGenericType (InstanceExpression.Type, ec.ContainerType) && - TypeManager.IsFamilyAccessible (ec.ContainerType, PropertyInfo.DeclaringType) && - !TypeManager.IsFamilyAccessible (InstanceExpression.Type, ec.ContainerType)) { + !TypeManager.IsNestedChildOf (ec.ContainerType, InstanceExpression.Type) && + !TypeManager.IsSubclassOf (InstanceExpression.Type, ec.ContainerType)) { + Report.SymbolRelatedToPreviousError (PropertyInfo); Error_CannotAccessProtected (loc, PropertyInfo, InstanceExpression.Type, ec.ContainerType); return false; } @@ -3893,8 +3889,6 @@ namespace Mono.CSharp { bool is_static; MethodInfo add_accessor, remove_accessor; - internal static PtrHashtable AccessorTable = new PtrHashtable (); - public EventExpr (EventInfo ei, Location loc) { EventInfo = ei; @@ -3903,11 +3897,6 @@ namespace Mono.CSharp { add_accessor = TypeManager.GetAddMethod (ei); remove_accessor = TypeManager.GetRemoveMethod (ei); - if (add_accessor != null) - AccessorTable [add_accessor] = ei; - if (remove_accessor != null) - AccessorTable [remove_accessor] = ei; - if (add_accessor.IsStatic || remove_accessor.IsStatic) is_static = true; @@ -4040,7 +4029,11 @@ namespace Mono.CSharp { public void EmitAddOrRemove (EmitContext ec, Expression source) { - BinaryDelegate source_del = (BinaryDelegate) source; + BinaryDelegate source_del = source as BinaryDelegate; + if (source_del == null) { + Emit (ec); + return; + } Expression handler = source_del.Right; Argument arg = new Argument (handler, Argument.AType.Expression); @@ -4057,10 +4050,10 @@ namespace Mono.CSharp { } } - public class TemporaryVariable : Expression, IMemoryLocation { LocalInfo li; + Variable var; public TemporaryVariable (Type type, Location loc) { @@ -4078,64 +4071,47 @@ namespace Mono.CSharp { li = ec.CurrentBlock.AddTemporaryVariable (te, loc); if (!li.Resolve (ec)) return null; - - AnonymousContainer am = ec.CurrentAnonymousMethod; - if ((am != null) && am.IsIterator) - ec.CaptureVariable (li); + + if (ec.MustCaptureVariable (li)) { + ScopeInfo scope = li.Block.CreateScopeInfo (); + var = scope.AddLocal (li); + type = var.Type; + } return this; } + + public Variable Variable { + get { return var != null ? var : li.Variable; } + } public override void Emit (EmitContext ec) { - ILGenerator ig = ec.ig; - - if (li.FieldBuilder != null) { - ig.Emit (OpCodes.Ldarg_0); - ig.Emit (OpCodes.Ldfld, li.FieldBuilder); - } else { - ig.Emit (OpCodes.Ldloc, li.LocalBuilder); - } + Variable.EmitInstance (ec); + Variable.Emit (ec); } public void EmitLoadAddress (EmitContext ec) { - ILGenerator ig = ec.ig; - - if (li.FieldBuilder != null) { - ig.Emit (OpCodes.Ldarg_0); - ig.Emit (OpCodes.Ldflda, li.FieldBuilder); - } else { - ig.Emit (OpCodes.Ldloca, li.LocalBuilder); - } + Variable.EmitInstance (ec); + Variable.EmitAddressOf (ec); } public void Store (EmitContext ec, Expression right_side) { - if (li.FieldBuilder != null) - ec.ig.Emit (OpCodes.Ldarg_0); - + Variable.EmitInstance (ec); right_side.Emit (ec); - if (li.FieldBuilder != null) { - ec.ig.Emit (OpCodes.Stfld, li.FieldBuilder); - } else { - ec.ig.Emit (OpCodes.Stloc, li.LocalBuilder); - } + Variable.EmitAssign (ec); } public void EmitThis (EmitContext ec) { - if (li.FieldBuilder != null) { - ec.ig.Emit (OpCodes.Ldarg_0); - } + Variable.EmitInstance (ec); } - public void EmitStore (ILGenerator ig) + public void EmitStore (EmitContext ec) { - if (li.FieldBuilder != null) - ig.Emit (OpCodes.Stfld, li.FieldBuilder); - else - ig.Emit (OpCodes.Stloc, li.LocalBuilder); + Variable.EmitAssign (ec); } public void AddressOf (EmitContext ec, AddressOp mode)