X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fecore.cs;h=cc6d1bdd23712d23aff6f9952fc7fea66767edfb;hb=f5a54864670ea45323abdcf2577bd752eeded8fc;hp=85597887085fd3139aa0db70334511b2f41b66d1;hpb=f1eb00d4f631a4e0b29a9c445cadafeea1738100;p=mono.git diff --git a/mcs/mcs/ecore.cs b/mcs/mcs/ecore.cs index 85597887085..cc6d1bdd237 100644 --- a/mcs/mcs/ecore.cs +++ b/mcs/mcs/ecore.cs @@ -31,6 +31,7 @@ namespace Mono.CSharp { Variable, Namespace, Type, + TypeParameter, MethodGroup, PropertyAccess, EventAccess, @@ -48,24 +49,26 @@ namespace Mono.CSharp { VariableOrValue = 1, // Returns a type expression. - Type = 2, + Type = 1 << 1, // Returns a method group. - MethodGroup = 4, + MethodGroup = 1 << 2, + + TypeParameter = 1 << 3, // Mask of all the expression class flags. - MaskExprClass = 7, + MaskExprClass = VariableOrValue | Type | MethodGroup | TypeParameter, // Disable control flow analysis while resolving the expression. // This is used when resolving the instance expression of a field expression. - DisableFlowAnalysis = 8, + DisableFlowAnalysis = 1 << 10, // Set if this is resolving the first part of a MemberAccess. - Intermediate = 16, + Intermediate = 1 << 11, // Disable control flow analysis _of struct_ while resolving the expression. // This is used when resolving the instance expression of a field expression. - DisableStructFlowAnalysis = 32, + DisableStructFlowAnalysis = 1 << 12, } @@ -100,8 +103,8 @@ namespace Mono.CSharp { // // An expressions resolved as a direct variable reference // - public interface IVariableReference { - bool IsFixedVariable { get; } + public interface IVariableReference : IFixedExpression + { bool IsHoisted { get; } string Name { get; } VariableInfo VariableInfo { get; } @@ -109,6 +112,15 @@ namespace Mono.CSharp { void SetHasAddressTaken (); } + // + // Implemented by an expression which could be or is always + // fixed + // + public interface IFixedExpression + { + bool IsFixed { get; } + } + /// /// Base class for expressions /// @@ -270,7 +282,7 @@ namespace Mono.CSharp { } } - ConstructedType ct = te as ConstructedType; + GenericTypeExpr ct = te as GenericTypeExpr; if (ct != null) { // Skip constrains check for overrides and explicit implementations // TODO: they should use different overload @@ -286,7 +298,7 @@ namespace Mono.CSharp { return te; } - + public TypeExpr ResolveAsBaseTerminal (IResolveContext ec, bool silent) { int errors = Report.Errors; @@ -295,15 +307,14 @@ namespace Mono.CSharp { if (fne == null) return null; - - if (fne.eclass != ExprClass.Type) { + + TypeExpr te = fne as TypeExpr; + if (te == null) { if (!silent && errors == Report.Errors) fne.Error_UnexpectedKind (null, "type", loc); return null; } - TypeExpr te = fne as TypeExpr; - if (!te.CheckAccessLevel (ec.GenericDeclContainer)) { Report.SymbolRelatedToPreviousError (te.Type); ErrorIsInaccesible (loc, TypeManager.CSharpName (te.Type)); @@ -352,6 +363,11 @@ namespace Mono.CSharp { } public virtual void Error_ValueCannotBeConverted (EmitContext ec, Location loc, Type target, bool expl) + { + Error_ValueCannotBeConvertedCore (ec, loc, target, expl); + } + + protected void Error_ValueCannotBeConvertedCore (EmitContext ec, Location loc, Type target, bool expl) { // The error was already reported as CS1660 if (type == TypeManager.anonymous_method_type) @@ -425,22 +441,25 @@ namespace Mono.CSharp { { get { switch (eclass) { - case ExprClass.Type: - case ExprClass.Namespace: - return ResolveFlags.Type; - - case ExprClass.MethodGroup: - return ResolveFlags.MethodGroup; - - case ExprClass.Value: - case ExprClass.Variable: - case ExprClass.PropertyAccess: - case ExprClass.EventAccess: - case ExprClass.IndexerAccess: - return ResolveFlags.VariableOrValue; - - default: - throw new InternalErrorException (loc.ToString () + " " + GetType () + " ExprClass is Invalid after resolve"); + case ExprClass.Type: + case ExprClass.Namespace: + return ResolveFlags.Type; + + case ExprClass.MethodGroup: + return ResolveFlags.MethodGroup; + + case ExprClass.TypeParameter: + return ResolveFlags.TypeParameter; + + case ExprClass.Value: + case ExprClass.Variable: + case ExprClass.PropertyAccess: + case ExprClass.EventAccess: + case ExprClass.IndexerAccess: + return ResolveFlags.VariableOrValue; + + default: + throw new InternalErrorException (loc.ToString () + " " + GetType () + " ExprClass is Invalid after resolve"); } } } @@ -517,7 +536,11 @@ namespace Mono.CSharp { if (c != null) return c; - Const.Error_ExpressionMustBeConstant (loc, mc.GetSignatureForError ()); + if (type != null && TypeManager.IsReferenceType (type)) + Const.Error_ConstantCanBeInitializedWithNullOnly (type, loc, mc.GetSignatureForError ()); + else + Const.Error_ExpressionMustBeConstant (loc, mc.GetSignatureForError ()); + return null; } @@ -529,7 +552,7 @@ namespace Mono.CSharp { /// Currently ResolveLValue wraps DoResolveLValue to perform sanity /// checking and assertion checking on what we expect from Resolve /// - public Expression ResolveLValue (EmitContext ec, Expression right_side, Location loc) + public Expression ResolveLValue (EmitContext ec, Expression right_side) { int errors = Report.Errors; bool out_access = right_side == EmptyExpression.OutAccess; @@ -558,12 +581,7 @@ namespace Mono.CSharp { if (e.eclass == ExprClass.Invalid) throw new Exception ("Expression " + e + " ExprClass is Invalid after resolve"); - if (e.eclass == ExprClass.MethodGroup) { - ((MethodGroupExpr) e).ReportUsageError (); - return null; - } - - if ((e.type == null) && !(e is ConstructedType)) + if ((e.type == null) && !(e is GenericTypeExpr)) throw new Exception ("Expression " + e + " did not set its type after Resolve"); return e; @@ -631,6 +649,7 @@ namespace Mono.CSharp { return null; } + // TODO: [Obsolete ("Can be removed")] protected static ArrayList almost_matched_members = new ArrayList (4); // @@ -794,7 +813,6 @@ namespace Mono.CSharp { Expression e; int errors = Report.Errors; - e = MemberLookup (ec.ContainerType, qualifier_type, queried_type, name, mt, bf, loc); if (e != null || errors != Report.Errors) @@ -809,42 +827,6 @@ namespace Mono.CSharp { Type queried_type, string name, string class_name, MemberTypes mt, BindingFlags bf) { - if (almost_matched_members.Count != 0) { - for (int i = 0; i < almost_matched_members.Count; ++i) { - MemberInfo m = (MemberInfo) almost_matched_members [i]; - for (int j = 0; j < i; ++j) { - if (m == almost_matched_members [j]) { - m = null; - break; - } - } - if (m == null) - continue; - - Type declaring_type = m.DeclaringType; - - Report.SymbolRelatedToPreviousError (m); - if (qualifier_type == null) { - Report.Error (38, loc, "Cannot access a nonstatic member of outer type `{0}' via nested type `{1}'", - TypeManager.CSharpName (m.DeclaringType), - TypeManager.CSharpName (container_type)); - - } else if (qualifier_type != container_type && - TypeManager.IsNestedFamilyAccessible (container_type, declaring_type)) { - // Although a derived class can access protected members of - // its base class it cannot do so through an instance of the - // base class (CS1540). If the qualifier_type is a base of the - // ec.ContainerType and the lookup succeeds with the latter one, - // then we are in this situation. - Error_CannotAccessProtected (loc, m, qualifier_type, container_type); - } else { - ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (m)); - } - } - almost_matched_members.Clear (); - return null; - } - MemberInfo[] lookup = null; if (queried_type == null) { class_name = "global::"; @@ -854,9 +836,30 @@ namespace Mono.CSharp { name, null); if (lookup != null) { - Report.SymbolRelatedToPreviousError (lookup [0]); - ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (lookup [0])); - return Error_MemberLookupFailed (lookup); + Expression e = Error_MemberLookupFailed (queried_type, lookup); + + // + // FIXME: This is still very wrong, it should be done inside + // OverloadResolve to do correct arguments matching. + // Requires MemberLookup accessiblity check removal + // + if (e == null || (mt & (MemberTypes.Method | MemberTypes.Constructor)) == 0) { + MemberInfo mi = lookup[0]; + Report.SymbolRelatedToPreviousError (mi); + if (qualifier_type != null && container_type != null && qualifier_type != container_type && + TypeManager.IsNestedFamilyAccessible (container_type, mi.DeclaringType)) { + // Although a derived class can access protected members of + // its base class it cannot do so through an instance of the + // base class (CS1540). If the qualifier_type is a base of the + // ec.ContainerType and the lookup succeeds with the latter one, + // then we are in this situation. + Error_CannotAccessProtected (loc, mi, qualifier_type, container_type); + } else { + ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (mi)); + } + } + + return e; } lookup = TypeManager.MemberLookup (queried_type, null, queried_type, @@ -889,10 +892,10 @@ namespace Mono.CSharp { } } - return Error_MemberLookupFailed (lookup); + return Error_MemberLookupFailed (queried_type, lookup); } - protected virtual Expression Error_MemberLookupFailed (MemberInfo[] members) + protected virtual Expression Error_MemberLookupFailed (Type type, MemberInfo[] members) { for (int i = 0; i < members.Length; ++i) { if (!(members [i] is MethodBase)) @@ -900,7 +903,7 @@ namespace Mono.CSharp { } // By default propagate the closest candidates upwards - return new MethodGroupExpr (members, type, loc); + return new MethodGroupExpr (members, type, loc, true); } protected virtual void Error_NegativeArrayIndex (Location loc) @@ -939,8 +942,8 @@ namespace Mono.CSharp { if (operator_group == null) return null; - ArrayList arguments = new ArrayList (1); - arguments.Add (new Argument (e, Argument.AType.Expression)); + Arguments arguments = new Arguments (1); + arguments.Add (new Argument (e)); operator_group = operator_group.OverloadResolve ( ec, ref arguments, false, loc); @@ -983,26 +986,28 @@ namespace Mono.CSharp { { get { switch (eclass){ - case ExprClass.Invalid: - return "Invalid"; - case ExprClass.Value: - return "value"; - case ExprClass.Variable: - return "variable"; - case ExprClass.Namespace: - return "namespace"; - case ExprClass.Type: - return "type"; - case ExprClass.MethodGroup: - return "method group"; - case ExprClass.PropertyAccess: - return "property access"; - case ExprClass.EventAccess: - return "event access"; - case ExprClass.IndexerAccess: - return "indexer access"; - case ExprClass.Nothing: - return "null"; + case ExprClass.Invalid: + return "Invalid"; + case ExprClass.Value: + return "value"; + case ExprClass.Variable: + return "variable"; + case ExprClass.Namespace: + return "namespace"; + case ExprClass.Type: + return "type"; + case ExprClass.MethodGroup: + return "method group"; + case ExprClass.PropertyAccess: + return "property access"; + case ExprClass.EventAccess: + return "event access"; + case ExprClass.IndexerAccess: + return "indexer access"; + case ExprClass.Nothing: + return "null"; + case ExprClass.TypeParameter: + return "type parameter"; } throw new Exception ("Should not happen"); } @@ -1100,7 +1105,7 @@ namespace Mono.CSharp { ig.Emit (OpCodes.Ldind_Ref); else LoadFromPtr (ig, TypeManager.GetEnumUnderlyingType (t)); - } else if (t.IsValueType || TypeManager.IsGenericParameter (t)) + } else if (TypeManager.IsStruct (t) || TypeManager.IsGenericParameter (t)) ig.Emit (OpCodes.Ldobj, t); else if (t.IsPointer) ig.Emit (OpCodes.Ldind_I); @@ -1131,7 +1136,7 @@ namespace Mono.CSharp { ig.Emit (OpCodes.Stind_I1); else if (type == TypeManager.intptr_type) ig.Emit (OpCodes.Stind_I); - else if (type.IsValueType || TypeManager.IsGenericParameter (type)) + else if (TypeManager.IsStruct (type) || TypeManager.IsGenericParameter (type)) ig.Emit (OpCodes.Stobj, type); else ig.Emit (OpCodes.Stind_Ref); @@ -1174,14 +1179,20 @@ namespace Mono.CSharp { { Report.SymbolRelatedToPreviousError (type); if (ec.CurrentInitializerVariable != null) { - Report.Error (1918, loc, "Members of a value type property `{0}' cannot be assigned with an object initializer", - GetSignatureForError ()); + Report.Error (1918, loc, "Members of value type `{0}' cannot be assigned using a property `{1}' object initializer", + TypeManager.CSharpName (type), GetSignatureForError ()); } else { Report.Error (1612, loc, "Cannot modify a value type return value of `{0}'. Consider storing the value in a temporary variable", GetSignatureForError ()); } } + public void Error_ExpressionCannotBeGeneric (Location loc) + { + Report.Error (307, loc, "The {0} `{1}' cannot be used with type arguments", + ExprClassName, GetSignatureForError ()); + } + // // Converts `source' to an int, uint, long or ulong. // @@ -1256,17 +1267,17 @@ namespace Mono.CSharp { // public abstract Expression CreateExpressionTree (EmitContext ec); - protected Expression CreateExpressionFactoryCall (string name, ArrayList args) + protected Expression CreateExpressionFactoryCall (string name, Arguments args) { return CreateExpressionFactoryCall (name, null, args, loc); } - protected Expression CreateExpressionFactoryCall (string name, TypeArguments typeArguments, ArrayList args) + protected Expression CreateExpressionFactoryCall (string name, TypeArguments typeArguments, Arguments args) { return CreateExpressionFactoryCall (name, typeArguments, args, loc); } - public static Expression CreateExpressionFactoryCall (string name, TypeArguments typeArguments, ArrayList args, Location loc) + public static Expression CreateExpressionFactoryCall (string name, TypeArguments typeArguments, Arguments args, Location loc) { return new Invocation (new MemberAccess (CreateExpressionTypeExpression (loc), name, typeArguments, loc), args); } @@ -1353,7 +1364,7 @@ namespace Mono.CSharp { public override Expression CreateExpressionTree (EmitContext ec) { - ArrayList args = new ArrayList (2); + Arguments args = new Arguments (2); args.Add (new Argument (child.CreateExpressionTree (ec))); args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc))); @@ -1383,6 +1394,7 @@ namespace Mono.CSharp { public override void MutateHoistedGenericType (AnonymousMethodStorey storey) { + type = storey.MutateType (type); child.MutateHoistedGenericType (storey); } @@ -1426,19 +1438,23 @@ namespace Mono.CSharp { } } - /// - /// Performs a cast using an operator (op_Explicit or op_Implicit) - /// + // + // Used for predefined class library user casts (no obsolete check, etc.) + // public class OperatorCast : TypeCast { 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) + : this (child, target_type, false) + { + } public OperatorCast (Expression child, Type target_type, bool find_explicit) : base (child, target_type) { - this.find_explicit = find_explicit; + conversion_operator = GetConversionOperator (find_explicit); + if (conversion_operator == null) + throw new InternalErrorException ("Outer conversion routine is out of sync"); } // Returns the implicit operator that converts from @@ -1458,75 +1474,34 @@ namespace Mono.CSharp { } foreach (MethodInfo oper in mi) { - ParameterData pd = TypeManager.GetParameterData (oper); + AParametersCollection pd = TypeManager.GetParameterData (oper); - if (pd.ParameterType (0) == child.Type && TypeManager.TypeToCoreType (oper.ReturnType) == type) + if (pd.Types [0] == child.Type && TypeManager.TypeToCoreType (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); + ec.ig.Emit (OpCodes.Call, conversion_operator); } - } /// /// This is a numeric cast to a Decimal /// - public class CastToDecimal : TypeCast { - MethodInfo conversion_operator; - + public class CastToDecimal : OperatorCast { public CastToDecimal (Expression child) : this (child, false) { } public CastToDecimal (Expression child, bool find_explicit) - : base (child, TypeManager.decimal_type) - { - conversion_operator = GetConversionOperator (find_explicit); - - if (conversion_operator == null) - throw new InternalErrorException ("Outer conversion routine is out of sync"); - } - - // Returns the implicit operator that converts from - // 'child.Type' to System.Decimal. - MethodInfo GetConversionOperator (bool find_explicit) - { - string operator_name = find_explicit ? "op_Explicit" : "op_Implicit"; - - MemberInfo [] 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 && TypeManager.TypeToCoreType (oper.ReturnType) == type) - return oper; - } - - return null; - } - public override void Emit (EmitContext ec) + : base (child, TypeManager.decimal_type, find_explicit) { - ILGenerator ig = ec.ig; - child.Emit (ec); - - ig.Emit (OpCodes.Call, conversion_operator); } } @@ -1556,8 +1531,8 @@ namespace Mono.CSharp { operators = new System.Collections.Specialized.HybridDictionary (); foreach (MethodInfo oper in all_oper) { - ParameterData pd = TypeManager.GetParameterData (oper); - if (pd.ParameterType (0) == TypeManager.decimal_type) + AParametersCollection pd = TypeManager.GetParameterData (oper); + if (pd.Types [0] == TypeManager.decimal_type) operators.Add (TypeManager.TypeToCoreType (oper.ReturnType), oper); } } @@ -1610,9 +1585,10 @@ namespace Mono.CSharp { public override Expression CreateExpressionTree (EmitContext ec) { - ArrayList args = new ArrayList (2); - args.Add (new Argument (child.CreateExpressionTree (ec))); - args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc))); + Arguments args = Arguments.CreateForExpressionTree (ec, null, + child.CreateExpressionTree (ec), + new TypeOf (new TypeExpression (type, loc), loc)); + if (type.IsPointer) Error_PointerInsideExpressionTree (); @@ -1642,12 +1618,18 @@ namespace Mono.CSharp { public override void Emit (EmitContext ec) { - child.Emit (ec); + child.Emit (ec); } public override void EmitBranchable (EmitContext ec, Label label, bool on_true) { child.EmitBranchable (ec, label, on_true); + +#if GMCS_SOURCE + // Only to make verifier happy + if (TypeManager.IsGenericParameter (type) && child.IsNull) + ec.ig.Emit (OpCodes.Unbox_Any, type); +#endif } public override void EmitSideEffect (EmitContext ec) @@ -1662,6 +1644,11 @@ namespace Mono.CSharp { return null; return child.ConvertImplicitly (target_type); } + + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + { + child.MutateHoistedGenericType (storey); + } } @@ -1725,12 +1712,24 @@ namespace Mono.CSharp { return Child.GetValue (); } +#if MS_COMPATIBLE + // Small workaround for big problem + // System.Enum.ToObject cannot be called on dynamic types + // EnumBuilder has to be used, but we cannot use EnumBuilder + // because it does not properly support generics + // + // This works only sometimes + // + if (type.Module == RootContext.ToplevelTypes.Builder) + return Child.GetValue (); +#endif + return System.Enum.ToObject (type, Child.GetValue ()); } public override string AsString () { - return TypeManager.CSharpEnumValue (type, Child.GetValue ()); + return Child.AsString (); } public override Constant Increment() @@ -1820,7 +1819,7 @@ namespace Mono.CSharp { { // boxing is side-effectful, since it involves runtime checks, except when boxing to Object or ValueType // so, we need to emit the box+pop instructions in most cases - if (child.Type.IsValueType && + if (TypeManager.IsStruct (child.Type) && (type == TypeManager.object_type || type == TypeManager.value_type)) child.EmitSideEffect (ec); else @@ -1851,25 +1850,22 @@ namespace Mono.CSharp { public override void Emit (EmitContext ec) { - Type t = type; - ILGenerator ig = ec.ig; - base.Emit (ec); -#if GMCS_SOURCE - if (t.IsGenericParameter || t.IsGenericType && t.IsValueType) - ig.Emit (OpCodes.Unbox_Any, t); - else -#endif - { - ig.Emit (OpCodes.Unbox, t); - LoadFromPtr (ig, t); - } + ILGenerator ig = ec.ig; + +#if GMCS_SOURCE + ig.Emit (OpCodes.Unbox_Any, type); +#else + ig.Emit (OpCodes.Unbox, type); + LoadFromPtr (ig, type); +#endif } public override void MutateHoistedGenericType (AnonymousMethodStorey storey) { type = storey.MutateType (type); + base.MutateHoistedGenericType (storey); } } @@ -2121,46 +2117,38 @@ namespace Mono.CSharp { /// to the class requested /// public sealed class ClassCast : TypeCast { - Type child_generic_parameter; - + readonly bool forced; + public ClassCast (Expression child, Type return_type) : base (child, return_type) - { - if (TypeManager.IsGenericParameter (child.Type)) - child_generic_parameter = child.Type; } - - public override Expression DoResolve (EmitContext ec) + + public ClassCast (Expression child, Type return_type, bool forced) + : base (child, return_type) { - // This should never be invoked, we are born in fully - // initialized state. - - return this; + this.forced = forced; } public override void Emit (EmitContext ec) { base.Emit (ec); - if (child_generic_parameter != null) - ec.ig.Emit (OpCodes.Box, child_generic_parameter); - #if GMCS_SOURCE - if (type.IsGenericParameter) + bool gen = TypeManager.IsGenericParameter (child.Type); + if (gen) + ec.ig.Emit (OpCodes.Box, child.Type); + + if (type.IsGenericParameter) { ec.ig.Emit (OpCodes.Unbox_Any, type); - else + return; + } + + if (gen && !forced) + return; #endif - ec.ig.Emit (OpCodes.Castclass, type); - } - - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) - { - type = storey.MutateType (type); - if (child_generic_parameter != null) - child_generic_parameter = storey.MutateGenericArgument (child_generic_parameter); - - base.MutateHoistedGenericType (storey); + + ec.ig.Emit (OpCodes.Castclass, type); } } @@ -2170,23 +2158,22 @@ namespace Mono.CSharp { // public class ReducedExpression : Expression { - class ReducedConstantExpression : Constant + sealed class ReducedConstantExpression : EmptyConstantCast { - readonly Constant expr; readonly Expression orig_expr; public ReducedConstantExpression (Constant expr, Expression orig_expr) - : base (expr.Location) + : base (expr, expr.Type) { - this.expr = expr; this.orig_expr = orig_expr; - eclass = expr.eclass; - type = expr.Type; } - public override string AsString () + public override Constant ConvertImplicitly (Type target_type) { - return expr.AsString (); + Constant c = base.ConvertImplicitly (target_type); + if (c != null) + c = new ReducedConstantExpression (c, orig_expr); + return c; } public override Expression CreateExpressionTree (EmitContext ec) @@ -2200,51 +2187,57 @@ namespace Mono.CSharp { // Even if resolved result is a constant original expression was not // and attribute accepts constants only // - Attribute.Error_AttributeArgumentNotValid (loc); + Attribute.Error_AttributeArgumentNotValid (orig_expr.Location); value = null; return false; } - public override object GetValue () - { - return expr.GetValue (); - } - public override Constant ConvertExplicitly (bool in_checked_context, Type target_type) { - throw new NotImplementedException (); + Constant c = base.ConvertExplicitly (in_checked_context, target_type); + if (c != null) + c = new ReducedConstantExpression (c, orig_expr); + return c; } + } - public override Expression DoResolve (EmitContext ec) + sealed class ReducedExpressionStatement : ExpressionStatement + { + readonly Expression orig_expr; + readonly ExpressionStatement stm; + + public ReducedExpressionStatement (ExpressionStatement stm, Expression orig) { - return this; + this.orig_expr = orig; + this.stm = stm; + this.loc = orig.Location; } - public override Constant Increment () + public override Expression CreateExpressionTree (EmitContext ec) { - throw new NotImplementedException (); + return orig_expr.CreateExpressionTree (ec); } - public override bool IsDefaultValue { - get { - return expr.IsDefaultValue; - } + public override Expression DoResolve (EmitContext ec) + { + eclass = stm.eclass; + type = stm.Type; + return this; } - public override bool IsNegative { - get { - return expr.IsNegative; - } + public override void Emit (EmitContext ec) + { + stm.Emit (ec); } - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + public override void EmitStatement (EmitContext ec) { - expr.MutateHoistedGenericType (storey); + stm.EmitStatement (ec); } - public override void Emit (EmitContext ec) + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) { - expr.Emit (ec); + stm.MutateHoistedGenericType (storey); } } @@ -2257,17 +2250,26 @@ namespace Mono.CSharp { this.loc = orig_expr.Location; } - public static Expression Create (Constant expr, Expression original_expr) + public static Constant Create (Constant expr, Expression original_expr) { return new ReducedConstantExpression (expr, original_expr); } + public static ExpressionStatement Create (ExpressionStatement s, Expression orig) + { + return new ReducedExpressionStatement (s, orig); + } + public static Expression Create (Expression expr, Expression original_expr) { Constant c = expr as Constant; if (c != null) return Create (c, original_expr); + ExpressionStatement s = expr as ExpressionStatement; + if (s != null) + return Create (s, original_expr); + return new ReducedExpression (expr, original_expr); } @@ -2326,6 +2328,18 @@ namespace Mono.CSharp { } } + public override bool Equals (object obj) + { + ATypeNameExpression atne = obj as ATypeNameExpression; + return atne != null && atne.Name == Name && + (targs == null || targs.Equals (atne.targs)); + } + + public override int GetHashCode () + { + return Name.GetHashCode (); + } + public override string GetSignatureForError () { if (targs != null) { @@ -2357,7 +2371,7 @@ namespace Mono.CSharp { public SimpleName (string name, TypeParameter[] type_params, Location l) : base (name, l) { - targs = new TypeArguments (l); + targs = new TypeArguments (); foreach (TypeParameter type_param in type_params) targs.Add (new TypeParameterExpr (type_param, l)); } @@ -2402,8 +2416,8 @@ namespace Mono.CSharp { "A field initializer cannot reference the nonstatic field, method, or property `{0}'", name); else - Report.Error ( - 120, l, "`{0}': An object reference is required for the nonstatic field, method or property", + Report.Error (120, l, + "An object reference is required to access non-static member `{0}'", name); } @@ -2460,14 +2474,14 @@ namespace Mono.CSharp { for (; (ds != null) && ds.IsGeneric; ds = ds.Parent) { if (arg_count + ds.CountTypeParameters == gen_params.Length) { - TypeArguments new_args = new TypeArguments (loc); + TypeArguments new_args = new TypeArguments (); foreach (TypeParameter param in ds.TypeParameters) new_args.Add (new TypeParameterExpr (param, loc)); if (targs != null) new_args.Add (targs); - return new ConstructedType (t, new_args, loc); + return new GenericTypeExpr (t, new_args, loc); } } @@ -2492,7 +2506,7 @@ namespace Mono.CSharp { return nested.ResolveAsTypeStep (ec, false); if (targs != null) { - ConstructedType ct = new ConstructedType (fne, targs, loc); + GenericTypeExpr ct = new GenericTypeExpr (fne.Type, targs, loc); return ct.ResolveAsTypeStep (ec, false); } @@ -2516,7 +2530,7 @@ namespace Mono.CSharp { string ns = ec.DeclContainer.NamespaceEntry.NS.Name; string fullname = (ns.Length > 0) ? ns + "." + Name : Name; - foreach (Assembly a in RootNamespace.Global.Assemblies) { + foreach (Assembly a in GlobalRootNamespace.Instance.Assemblies) { Type type = a.GetType (fullname); if (type != null) { Report.SymbolRelatedToPreviousError (type); @@ -2534,7 +2548,7 @@ namespace Mono.CSharp { if (targs != null) { FullNamedExpression retval = ec.DeclContainer.LookupNamespaceOrType (SimpleName.RemoveGenericArity (Name), loc, true); if (retval != null) { - Namespace.Error_TypeArgumentsCannotBeUsed (retval.Type, loc); + Namespace.Error_TypeArgumentsCannotBeUsed (retval, loc); return; } } @@ -2608,16 +2622,9 @@ namespace Mono.CSharp { if (current_block != null){ LocalInfo vi = current_block.GetLocalInfo (Name); if (vi != null){ - if (targs != null) { - Report.Error (307, loc, - "The variable `{0}' cannot be used with type arguments", - Name); - return null; - } - LocalVariableReference var = new LocalVariableReference (ec.CurrentBlock, Name, loc); if (right_side != null) { - return var.ResolveLValue (ec, right_side, loc); + return var.ResolveLValue (ec, right_side); } else { ResolveFlags rf = ResolveFlags.VariableOrValue; if (intermediate) @@ -2626,25 +2633,11 @@ namespace Mono.CSharp { } } - ParameterReference pref = current_block.Toplevel.GetParameterReference (Name, loc); - if (pref != null) { - if (targs != null) { - Report.Error (307, loc, - "The variable `{0}' cannot be used with type arguments", - Name); - return null; - } - - if (right_side != null) - return pref.ResolveLValue (ec, right_side, loc); - else - return pref.Resolve (ec); - } - - Expression expr = current_block.Toplevel.GetTransparentIdentifier (Name); + Expression expr = current_block.Toplevel.GetParameterReference (Name, loc); if (expr != null) { if (right_side != null) - return expr.ResolveLValue (ec, right_side, loc); + return expr.ResolveLValue (ec, right_side); + return expr.Resolve (ec); } } @@ -2662,14 +2655,20 @@ namespace Mono.CSharp { e = MemberLookup (ec.ContainerType, lookup_ds.TypeBuilder, Name, loc); if (e != null) { - if (e is PropertyExpr) { + PropertyExpr pe = e as PropertyExpr; + if (pe != null) { + AParametersCollection param = TypeManager.GetParameterData (pe.PropertyInfo); + // since TypeManager.MemberLookup doesn't know if we're doing a lvalue access or not, // it doesn't know which accessor to check permissions against - if (((PropertyExpr) e).IsAccessibleFrom (ec.ContainerType, right_side != null)) + if (param.IsEmpty && pe.IsAccessibleFrom (ec.ContainerType, right_side != null)) break; } else if (e is EventExpr) { if (((EventExpr) e).IsAccessibleFrom (ec.ContainerType)) break; + } else if (targs != null && e is TypeExpression) { + e = new GenericTypeExpr (e.Type, targs, loc).ResolveAsTypeStep (ec, false); + break; } else { break; } @@ -2704,22 +2703,18 @@ namespace Mono.CSharp { } } + if (RootContext.EvalMode){ + FieldInfo fi = Evaluator.LookupField (Name); + if (fi != null) + return new FieldExpr (fi, loc).Resolve (ec); + } + if (almost_matched != null) almost_matched_members = almost_matched; if (almost_matched_type == null) almost_matched_type = ec.ContainerType; - Error_MemberLookupFailed (ec.ContainerType, null, almost_matched_type, Name, + return Error_MemberLookupFailed (ec.ContainerType, null, almost_matched_type, Name, ec.DeclContainer.Name, AllMemberTypes, AllBindingFlags); - return null; - } - - if (e is TypeExpr) { - if (targs == null) - return e; - - ConstructedType ct = new ConstructedType ( - e.Type, targs, loc); - return ct.ResolveAsTypeStep (ec, false); } if (e is MemberExpr) { @@ -2757,11 +2752,13 @@ namespace Mono.CSharp { return null; if (targs != null) { - targs.Resolve (ec); + if (!targs.Resolve (ec)) + return null; + me.SetTypeArguments (targs); } - if (!me.IsStatic && (me.InstanceExpression != null) && + if (!me.IsStatic && (me.InstanceExpression != null && me.InstanceExpression != EmptyExpression.Null) && TypeManager.IsNestedFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) && me.InstanceExpression.Type != me.DeclaringType && !TypeManager.IsFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) && @@ -2778,18 +2775,19 @@ namespace Mono.CSharp { return e; } - - protected override void CloneTo (CloneContext clonectx, Expression target) - { - // CloneTo: Nothing, we do not keep any state on this expression - } } /// /// Represents a namespace or a type. The name of the class was inspired by /// section 10.8.1 (Fully Qualified Names). /// - public abstract class FullNamedExpression : Expression { + public abstract class FullNamedExpression : Expression + { + protected override void CloneTo (CloneContext clonectx, Expression target) + { + // Do nothing, most unresolved type expressions cannot be + // resolved to different type + } public override Expression CreateExpressionTree (EmitContext ec) { @@ -2817,7 +2815,7 @@ namespace Mono.CSharp { /// Expression that evaluates to a type /// public abstract class TypeExpr : FullNamedExpression { - override public FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent) + public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent) { TypeExpr t = DoResolveAsTypeStep (ec); if (t == null) @@ -2837,17 +2835,12 @@ namespace Mono.CSharp { return ds.CheckAccessLevel (Type); } - public virtual bool AsAccessible (DeclSpace ds) - { - return ds.IsAccessibleAs (Type); - } - public virtual bool IsClass { get { return Type.IsClass; } } public virtual bool IsValueType { - get { return Type.IsValueType; } + get { return TypeManager.IsStruct (Type); } } public virtual bool IsInterface { @@ -2914,189 +2907,56 @@ namespace Mono.CSharp { } } - /// - /// Used to create types from a fully qualified name. These are just used - /// by the parser to setup the core types. A TypeLookupExpression is always - /// classified as a type. - /// + // + // Used to create types from a fully qualified name. These are just used + // by the parser to setup the core types. + // public sealed class TypeLookupExpression : TypeExpr { + readonly string ns_name; readonly string name; - public TypeLookupExpression (string name) + public TypeLookupExpression (string ns, string name) { this.name = name; + this.ns_name = ns; eclass = ExprClass.Type; } public override TypeExpr ResolveAsTypeTerminal (IResolveContext ec, bool silent) { - // It's null for corlib compilation only - if (type == null) - return DoResolveAsTypeStep (ec); + // + // It's null only during mscorlib bootstrap when DefineType + // nees to resolve base type of same type + // + // For instance struct Char : IComparable + // + // TODO: it could be removed when Resolve starts to use + // DeclSpace instead of Type + // + if (type == null) { + Namespace ns = GlobalRootNamespace.Instance.GetNamespace (ns_name, false); + FullNamedExpression fne = ns.Lookup (null, name, loc); + if (fne != null) + type = fne.Type; + } return this; } - private class UnexpectedType - { - } - - // This performes recursive type lookup, providing support for generic types. - // For example, given the type: - // - // System.Collections.Generic.KeyValuePair`2[[System.Int32],[System.String]] - // - // The types will be checked in the following order: - // _ - // System | - // System.Collections | - // System.Collections.Generic | - // _ | - // System | recursive call 1 | - // System.Int32 _| | main method call - // _ | - // System | recursive call 2 | - // System.String _| | - // | - // System.Collections.Generic.KeyValuePair`2[[System.Int32],[System.String]] _| - // - private Type TypeLookup (IResolveContext ec, string name) - { - int index = 0; - int dot = 0; - bool done = false; - FullNamedExpression resolved = null; - Type type = null; - Type recursive_type = null; - while (index < name.Length) { - if (name[index] == '[') { - int open = index; - int braces = 1; - do { - index++; - if (name[index] == '[') - braces++; - else if (name[index] == ']') - braces--; - } while (braces > 0); - recursive_type = TypeLookup (ec, name.Substring (open + 1, index - open - 1)); - if (recursive_type == null || (recursive_type == typeof(UnexpectedType))) - return recursive_type; - } - else { - if (name[index] == ',') - done = true; - else if ((name[index] == '.' && !done) || (index == name.Length && name[0] != '[')) { - string substring = name.Substring(dot, index - dot); - - if (resolved == null) - resolved = RootNamespace.Global.Lookup (ec.DeclContainer, substring, Location.Null); - else if (resolved is Namespace) - resolved = (resolved as Namespace).Lookup (ec.DeclContainer, substring, Location.Null); - else if (type != null) - type = TypeManager.GetNestedType (type, substring); - else - return null; - - if (resolved == null) - return null; - else if (type == null && resolved is TypeExpr) - type = resolved.Type; - - dot = index + 1; - } - } - index++; - } - if (name[0] != '[') { - string substring = name.Substring(dot, index - dot); - - if (type != null) - return TypeManager.GetNestedType (type, substring); - - if (resolved != null) { - resolved = (resolved as Namespace).Lookup (ec.DeclContainer, substring, Location.Null); - if (resolved is TypeExpr) - return resolved.Type; - - if (resolved == null) - return null; - - resolved.Error_UnexpectedKind (ec.DeclContainer, "type", loc); - return typeof (UnexpectedType); - } - else - return null; - } - else - return recursive_type; - } - protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec) { - Type t = TypeLookup (ec, name); - if (t == null) { - NamespaceEntry.Error_NamespaceNotFound (loc, name); - return null; - } - if (t == typeof(UnexpectedType)) - return null; - type = t; return this; } - protected override void CloneTo (CloneContext clonectx, Expression target) - { - // CloneTo: Nothing, we do not keep any state on this expression - } - public override string GetSignatureForError () { if (type == null) - return TypeManager.CSharpName (name); + return TypeManager.CSharpName (ns_name + "." + name, null); return base.GetSignatureForError (); } } - /// - /// Represents an "unbound generic type", ie. typeof (Foo<>). - /// See 14.5.11. - /// - public class UnboundTypeExpression : TypeExpr - { - MemberName name; - - public UnboundTypeExpression (MemberName name, Location l) - { - this.name = name; - loc = l; - } - - protected override void CloneTo (CloneContext clonectx, Expression target) - { - // Nothing to clone - } - - protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec) - { - Expression expr; - if (name.Left != null) { - Expression lexpr = name.Left.GetTypeExpression (); - expr = new MemberAccess (lexpr, name.Basename); - } else { - expr = new SimpleName (name.Basename, loc); - } - - FullNamedExpression fne = expr.ResolveAsTypeStep (ec, false); - if (fne == null) - return null; - - type = fne.Type; - return new TypeExpression (type, loc); - } - } - /// /// This class denotes an expression which evaluates to a member /// of a struct or a class. @@ -3175,10 +3035,22 @@ namespace Mono.CSharp { // if (left is TypeExpr) { - left = left.ResolveAsTypeTerminal (ec, true); + left = left.ResolveAsBaseTerminal (ec, false); if (left == null) return null; + // TODO: Same problem as in class.cs, TypeTerminal does not + // always do all necessary checks + ObsoleteAttribute oa = AttributeTester.GetObsoleteAttribute (left.Type); + if (oa != null && !ec.IsInObsoleteScope) { + AttributeTester.Report_ObsoleteMessage (oa, left.GetSignatureForError (), loc); + } + + GenericTypeExpr ct = left as GenericTypeExpr; + if (ct != null && !ct.CheckConstraints (ec)) + return null; + // + if (!IsStatic) { SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ()); return null; @@ -3213,8 +3085,8 @@ namespace Mono.CSharp { SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ()); return; } - - if (InstanceExpression.Type.IsValueType) { + + if (TypeManager.IsValueType (InstanceExpression.Type)) { if (InstanceExpression is IMemoryLocation) { ((IMemoryLocation) InstanceExpression).AddressOf (ec, AddressOp.LoadStore); } else { @@ -3261,39 +3133,30 @@ namespace Mono.CSharp { get { return namespace_entry == null; } } - public override void EmitArguments (EmitContext ec, ArrayList arguments) - { - if (arguments == null) - arguments = new ArrayList (1); - arguments.Insert (0, extension_argument); - base.EmitArguments (ec, arguments); - } - - public override void EmitCall (EmitContext ec, ArrayList arguments) + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) { - if (arguments == null) - arguments = new ArrayList (1); - arguments.Insert (0, extension_argument); - base.EmitCall (ec, arguments); + extension_argument.Expr.MutateHoistedGenericType (storey); + base.MutateHoistedGenericType (storey); } - public override MethodGroupExpr OverloadResolve (EmitContext ec, ref ArrayList arguments, bool may_fail, Location loc) + public override MethodGroupExpr OverloadResolve (EmitContext ec, ref Arguments arguments, bool may_fail, Location loc) { if (arguments == null) - arguments = new ArrayList (1); + arguments = new Arguments (1); arguments.Insert (0, new Argument (ExtensionExpression)); - MethodGroupExpr mg = ResolveOverloadExtensions (ec, arguments, namespace_entry, loc); + MethodGroupExpr mg = ResolveOverloadExtensions (ec, ref arguments, namespace_entry, loc); // Store resolved argument and restore original arguments if (mg != null) - ((ExtensionMethodGroupExpr)mg).extension_argument = (Argument)arguments [0]; - arguments.RemoveAt (0); + ((ExtensionMethodGroupExpr)mg).extension_argument = arguments [0]; + else + arguments.RemoveAt (0); // Clean-up modified arguments for error reporting return mg; } - MethodGroupExpr ResolveOverloadExtensions (EmitContext ec, ArrayList arguments, NamespaceEntry ns, Location loc) + MethodGroupExpr ResolveOverloadExtensions (EmitContext ec, ref Arguments arguments, NamespaceEntry ns, Location loc) { // Use normal resolve rules MethodGroupExpr mg = base.OverloadResolve (ec, ref arguments, ns != null, loc); @@ -3310,7 +3173,7 @@ namespace Mono.CSharp { e.ExtensionExpression = ExtensionExpression; e.SetTypeArguments (type_arguments); - return e.ResolveOverloadExtensions (ec, arguments, e.namespace_entry, loc); + return e.ResolveOverloadExtensions (ec, ref arguments, e.namespace_entry, loc); } } @@ -3322,6 +3185,7 @@ namespace Mono.CSharp { { public interface IErrorHandler { + bool AmbiguousCall (MethodBase ambiguous); bool NoExactMatch (EmitContext ec, MethodBase method); } @@ -3331,7 +3195,9 @@ namespace Mono.CSharp { // TODO: make private public TypeArguments type_arguments; bool identical_type_name; + bool has_inaccessible_candidates_only; Type delegate_type; + Type queried_type; public MethodGroupExpr (MemberInfo [] mi, Type type, Location l) : this (type, l) @@ -3340,6 +3206,12 @@ namespace Mono.CSharp { mi.CopyTo (Methods, 0); } + public MethodGroupExpr (MemberInfo[] mi, Type type, Location l, bool inacessibleCandidatesOnly) + : this (mi, type, l) + { + has_inaccessible_candidates_only = inacessibleCandidatesOnly; + } + public MethodGroupExpr (ArrayList list, Type type, Location l) : this (type, l) { @@ -3362,16 +3234,13 @@ namespace Mono.CSharp { { this.loc = loc; eclass = ExprClass.MethodGroup; - this.type = type; + this.type = typeof (MethodGroupExpr); + queried_type = type; } public override Type DeclaringType { get { - // - // We assume that the top-level type is in the end - // - return Methods [Methods.Length - 1].DeclaringType; - //return Methods [0].DeclaringType; + return queried_type; } } @@ -3385,10 +3254,6 @@ namespace Mono.CSharp { get { return identical_type_name; } - - set { - identical_type_name = value; - } } public override string GetSignatureForError () @@ -3543,29 +3408,33 @@ namespace Mono.CSharp { /// false if candidate ain't better /// true if candidate is better than the current best match /// - static bool BetterFunction (EmitContext ec, ArrayList args, int argument_count, + static bool BetterFunction (EmitContext ec, Arguments args, int argument_count, MethodBase candidate, bool candidate_params, MethodBase best, bool best_params) { - ParameterData candidate_pd = TypeManager.GetParameterData (candidate); - ParameterData best_pd = TypeManager.GetParameterData (best); + AParametersCollection candidate_pd = TypeManager.GetParameterData (candidate); + AParametersCollection best_pd = TypeManager.GetParameterData (best); bool better_at_least_one = false; bool same = true; for (int j = 0, c_idx = 0, b_idx = 0; j < argument_count; ++j, ++c_idx, ++b_idx) { - Argument a = (Argument) args [j]; + Argument a = args [j]; + + // Provided default argument value is never better + if (a.IsDefaultArgument && candidate_params == best_params) + return false; - Type ct = TypeManager.TypeToCoreType (candidate_pd.ParameterType (c_idx)); - Type bt = TypeManager.TypeToCoreType (best_pd.ParameterType (b_idx)); + Type ct = candidate_pd.Types [c_idx]; + Type bt = best_pd.Types [b_idx]; - if (candidate_params && candidate_pd.ParameterModifier (c_idx) == Parameter.Modifier.PARAMS) + if (candidate_params && candidate_pd.FixedParameters [c_idx].ModFlags == Parameter.Modifier.PARAMS) { ct = TypeManager.GetElementType (ct); --c_idx; } - if (best_params && best_pd.ParameterModifier (b_idx) == Parameter.Modifier.PARAMS) + if (best_params && best_pd.FixedParameters [b_idx].ModFlags == Parameter.Modifier.PARAMS) { bt = TypeManager.GetElementType (bt); --b_idx; @@ -3606,10 +3475,12 @@ namespace Mono.CSharp { // // The two methods have equal parameter types. Now apply tie-breaking rules // - if (TypeManager.IsGenericMethod (best) && !TypeManager.IsGenericMethod (candidate)) - return true; - if (!TypeManager.IsGenericMethod (best) && TypeManager.IsGenericMethod (candidate)) + if (TypeManager.IsGenericMethod (best)) { + if (!TypeManager.IsGenericMethod (candidate)) + return true; + } else if (TypeManager.IsGenericMethod (candidate)) { return false; + } // // This handles the following cases: @@ -3629,7 +3500,7 @@ namespace Mono.CSharp { if (candidate_param_count != best_param_count) // can only happen if (candidate_params && best_params) - return candidate_param_count > best_param_count; + return candidate_param_count > best_param_count && best_pd.HasParams; // // now, both methods have the same number of parameters, and the parameters have the same types @@ -3639,14 +3510,14 @@ namespace Mono.CSharp { MethodBase orig_candidate = TypeManager.DropGenericMethodArguments (candidate); MethodBase orig_best = TypeManager.DropGenericMethodArguments (best); - ParameterData orig_candidate_pd = TypeManager.GetParameterData (orig_candidate); - ParameterData orig_best_pd = TypeManager.GetParameterData (orig_best); + AParametersCollection orig_candidate_pd = TypeManager.GetParameterData (orig_candidate); + AParametersCollection orig_best_pd = TypeManager.GetParameterData (orig_best); bool specific_at_least_once = false; for (int j = 0; j < candidate_param_count; ++j) { - Type ct = TypeManager.TypeToCoreType (orig_candidate_pd.ParameterType (j)); - Type bt = TypeManager.TypeToCoreType (orig_best_pd.ParameterType (j)); + Type ct = orig_candidate_pd.Types [j]; + Type bt = orig_best_pd.Types [j]; if (ct.Equals (bt)) continue; Type specific = MoreSpecific (ct, bt); @@ -3683,7 +3554,7 @@ namespace Mono.CSharp { { if (!(left is TypeExpr) && original != null && original.IdenticalNameAndTypeName (ec, left, loc)) - IdenticalTypeName = true; + identical_type_name = true; return base.ResolveMemberAccess (ec, left, loc, original); } @@ -3728,31 +3599,39 @@ namespace Mono.CSharp { ReportUsageError (); } - public virtual void EmitArguments (EmitContext ec, ArrayList arguments) + public void EmitCall (EmitContext ec, Arguments arguments) { - Invocation.EmitArguments (ec, arguments, false, null); + Invocation.EmitCall (ec, IsBase, InstanceExpression, best_candidate, arguments, loc); } - - public virtual void EmitCall (EmitContext ec, ArrayList arguments) + + void Error_AmbiguousCall (MethodBase ambiguous) { - Invocation.EmitCall (ec, IsBase, InstanceExpression, best_candidate, arguments, loc); + if (CustomErrorHandler != null && CustomErrorHandler.AmbiguousCall (ambiguous)) + return; + + Report.SymbolRelatedToPreviousError (best_candidate); + Report.Error (121, loc, "The call is ambiguous between the following methods or properties: `{0}' and `{1}'", + TypeManager.CSharpSignature (ambiguous), TypeManager.CSharpSignature (best_candidate)); } protected virtual void Error_InvalidArguments (EmitContext ec, Location loc, int idx, MethodBase method, - Argument a, ParameterData expected_par, Type paramType) + Argument a, AParametersCollection expected_par, Type paramType) { ExtensionMethodGroupExpr emg = this as ExtensionMethodGroupExpr; if (a is CollectionElementInitializer.ElementInitializerArgument) { Report.SymbolRelatedToPreviousError (method); - if ((expected_par.ParameterModifier (idx) & Parameter.Modifier.ISBYREF) != 0) { + if ((expected_par.FixedParameters [idx].ModFlags & Parameter.Modifier.ISBYREF) != 0) { Report.Error (1954, loc, "The best overloaded collection initalizer method `{0}' cannot have 'ref', or `out' modifier", TypeManager.CSharpSignature (method)); return; } Report.Error (1950, loc, "The best overloaded collection initalizer method `{0}' has some invalid arguments", TypeManager.CSharpSignature (method)); - } else if (delegate_type == null) { + } else if (TypeManager.IsDelegateType (method.DeclaringType)) { + Report.Error (1594, loc, "Delegate `{0}' has some invalid arguments", + TypeManager.CSharpName (method.DeclaringType)); + } else { Report.SymbolRelatedToPreviousError (method); if (emg != null) { Report.Error (1928, loc, @@ -3763,11 +3642,9 @@ namespace Mono.CSharp { Report.Error (1502, loc, "The best overloaded method match for `{0}' has some invalid arguments", TypeManager.CSharpSignature (method)); } - } else - Report.Error (1594, loc, "Delegate `{0}' has some invalid arguments", - TypeManager.CSharpName (delegate_type)); + } - Parameter.Modifier mod = expected_par.ParameterModifier (idx); + Parameter.Modifier mod = idx >= expected_par.Count ? 0 : expected_par.FixedParameters [idx].ModFlags; string index = (idx + 1).ToString (); if (((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) ^ @@ -3803,8 +3680,14 @@ namespace Mono.CSharp { Report.Error (428, loc, "Cannot convert method group `{0}' to non-delegate type `{1}'. Consider using parentheses to invoke the method", Name, TypeManager.CSharpName (target)); } + + void Error_ArgumentCountWrong (int arg_count) + { + Report.Error (1501, loc, "No overload for method `{0}' takes `{1}' arguments", + Name, arg_count.ToString ()); + } - protected virtual int GetApplicableParametersCount (MethodBase method, ParameterData parameters) + protected virtual int GetApplicableParametersCount (MethodBase method, AParametersCollection parameters) { return parameters.Count; } @@ -3823,18 +3706,101 @@ namespace Mono.CSharp { /// 0 = the best, int.MaxValue = the worst /// public int IsApplicable (EmitContext ec, - ArrayList arguments, int arg_count, ref MethodBase method, ref bool params_expanded_form) + ref Arguments arguments, int arg_count, ref MethodBase method, ref bool params_expanded_form) { MethodBase candidate = method; - ParameterData pd = TypeManager.GetParameterData (candidate); + AParametersCollection pd = TypeManager.GetParameterData (candidate); int param_count = GetApplicableParametersCount (candidate, pd); + int optional_count = 0; if (arg_count != param_count) { - if (!pd.HasParams) - return int.MaxValue - 10000 + Math.Abs (arg_count - param_count); - if (arg_count < param_count - 1) - return int.MaxValue - 10000 + Math.Abs (arg_count - param_count); + for (int i = 0; i < pd.Count; ++i) { + if (pd.FixedParameters [i].HasDefaultValue) { + optional_count = pd.Count - i; + break; + } + } + + int args_gap = Math.Abs (arg_count - param_count); + if (optional_count != 0) { + if (args_gap > optional_count) + return int.MaxValue - 10000 + args_gap - optional_count; + + // Readjust expected number when params used + if (pd.HasParams) { + optional_count--; + if (arg_count < param_count) + param_count--; + } + } else if (arg_count != param_count) { + if (!pd.HasParams) + return int.MaxValue - 10000 + args_gap; + if (arg_count < param_count - 1) + return int.MaxValue - 10000 + args_gap; + } + + // Initialize expanded form of a method with 1 params parameter + params_expanded_form = param_count == 1 && pd.HasParams; + + // Resize to fit optional arguments + if (optional_count != 0) { + Arguments resized; + if (arguments == null) { + resized = new Arguments (optional_count); + } else { + resized = new Arguments (param_count); + resized.AddRange (arguments); + } + + for (int i = arg_count; i < param_count; ++i) + resized.Add (null); + arguments = resized; + } + } + + if (arg_count > 0) { + // + // Shuffle named arguments to the right positions if there are any + // + if (arguments [arg_count - 1] is NamedArgument) { + arg_count = arguments.Count; + + for (int i = 0; i < arg_count; ++i) { + bool arg_moved = false; + while (true) { + NamedArgument na = arguments[i] as NamedArgument; + if (na == null) + break; + + int index = pd.GetParameterIndexByName (na.Name.Value); + + // Named parameter not found or already reordered + if (index <= i) + break; + + // When using parameters which should not be available to the user + if (index >= param_count) + break; + + if (!arg_moved) { + arguments.MarkReorderedArgument (na); + arg_moved = true; + } + + Argument temp = arguments[index]; + arguments[index] = arguments[i]; + arguments[i] = temp; + + if (temp == null) + break; + } + } + } else { + arg_count = arguments.Count; + } + } else if (arguments != null) { + arg_count = arguments.Count; } #if GMCS_SOURCE @@ -3866,7 +3832,7 @@ namespace Mono.CSharp { if (type_arguments != null) return int.MaxValue - 15000; } -#endif +#endif // // 2. Each argument has to be implicitly convertible to method parameter @@ -3875,32 +3841,34 @@ namespace Mono.CSharp { Parameter.Modifier p_mod = 0; Type pt = null; for (int i = 0; i < arg_count; i++) { - Argument a = (Argument) arguments [i]; - Parameter.Modifier a_mod = a.Modifier & - ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK); - - if (p_mod != Parameter.Modifier.PARAMS) { - p_mod = pd.ParameterModifier (i) & ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK); + Argument a = arguments [i]; + if (a == null) { + if (!pd.FixedParameters [i].HasDefaultValue) + throw new InternalErrorException (); - if (p_mod == Parameter.Modifier.ARGLIST) { - if (a.Type == TypeManager.runtime_argument_handle_type) - continue; + Expression e = pd.FixedParameters [i].DefaultValue as Constant; + if (e == null) + e = new DefaultValueExpression (new TypeExpression (pd.Types [i], loc), loc).Resolve (ec); - p_mod = 0; - } + arguments [i] = new Argument (e, Argument.AType.Default); + continue; + } - pt = pd.ParameterType (i); + if (p_mod != Parameter.Modifier.PARAMS) { + p_mod = pd.FixedParameters [i].ModFlags & ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK); + pt = pd.Types [i]; } else { params_expanded_form = true; } + Parameter.Modifier a_mod = a.Modifier & ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK); int score = 1; if (!params_expanded_form) score = IsArgumentCompatible (ec, a_mod, a, p_mod & ~Parameter.Modifier.PARAMS, pt); - if (score != 0 && (p_mod & Parameter.Modifier.PARAMS) != 0) { + if (score != 0 && (p_mod & Parameter.Modifier.PARAMS) != 0 && delegate_type == null) { // It can be applicable in expanded form - score = IsArgumentCompatible (ec, a_mod, a, 0, pt.GetElementType ()); + score = IsArgumentCompatible (ec, a_mod, a, 0, TypeManager.GetElementType (pt)); if (score == 0) params_expanded_form = true; } @@ -3913,7 +3881,7 @@ namespace Mono.CSharp { } if (arg_count != param_count) - params_expanded_form = true; + params_expanded_form = true; return 0; } @@ -3925,18 +3893,16 @@ namespace Mono.CSharp { // if (arg_mod != 0 || param_mod != 0) { if (TypeManager.HasElementType (parameter)) - parameter = parameter.GetElementType (); + parameter = TypeManager.GetElementType (parameter); Type a_type = argument.Type; if (TypeManager.HasElementType (a_type)) - a_type = a_type.GetElementType (); + a_type = TypeManager.GetElementType (a_type); if (a_type != parameter) return 2; } else { - if (delegate_type != null ? - !Delegate.IsTypeCovariant (argument.Expr, parameter) : - !Convert.ImplicitConversionExists (ec, argument.Expr, parameter)) + if (!Convert.ImplicitConversionExists (ec, argument.Expr, parameter)) return 2; } @@ -3951,18 +3917,18 @@ namespace Mono.CSharp { if (!IsAncestralType (base_method.DeclaringType, cand_method.DeclaringType)) return false; - ParameterData cand_pd = TypeManager.GetParameterData (cand_method); - ParameterData base_pd = TypeManager.GetParameterData (base_method); + AParametersCollection cand_pd = TypeManager.GetParameterData (cand_method); + AParametersCollection base_pd = TypeManager.GetParameterData (base_method); if (cand_pd.Count != base_pd.Count) return false; for (int j = 0; j < cand_pd.Count; ++j) { - Parameter.Modifier cm = cand_pd.ParameterModifier (j); - Parameter.Modifier bm = base_pd.ParameterModifier (j); - Type ct = TypeManager.TypeToCoreType (cand_pd.ParameterType (j)); - Type bt = TypeManager.TypeToCoreType (base_pd.ParameterType (j)); + Parameter.Modifier cm = cand_pd.FixedParameters [j].ModFlags; + Parameter.Modifier bm = base_pd.FixedParameters [j].ModFlags; + Type ct = cand_pd.Types [j]; + Type bt = base_pd.Types [j]; if (cm != bm || ct != bt) return false; @@ -4063,12 +4029,11 @@ namespace Mono.CSharp { /// that is the best match of me on Arguments. /// /// - public virtual MethodGroupExpr OverloadResolve (EmitContext ec, ref ArrayList Arguments, + public virtual MethodGroupExpr OverloadResolve (EmitContext ec, ref Arguments Arguments, bool may_fail, Location loc) { bool method_params = false; Type applicable_type = null; - int arg_count = 0; ArrayList candidates = new ArrayList (2); ArrayList candidate_overrides = null; @@ -4080,9 +4045,10 @@ namespace Mono.CSharp { // false is normal form, true is expanded form // Hashtable candidate_to_form = null; + Hashtable candidates_expanded = null; + Arguments candidate_args = Arguments; - if (Arguments != null) - arg_count = Arguments.Count; + int arg_count = Arguments != null ? Arguments.Count : 0; if (RootContext.Version == LanguageVersion.ISO_1 && Name == "Invoke" && TypeManager.IsDelegateType (DeclaringType)) { if (!may_fail) @@ -4143,7 +4109,7 @@ namespace Mono.CSharp { // Check if candidate is applicable (section 14.4.2.1) // bool params_expanded_form = false; - int candidate_rate = IsApplicable (ec, Arguments, arg_count, ref Methods [i], ref params_expanded_form); + int candidate_rate = IsApplicable (ec, ref candidate_args, arg_count, ref Methods [i], ref params_expanded_form); if (candidate_rate < best_candidate_rate) { best_candidate_rate = candidate_rate; @@ -4156,8 +4122,16 @@ namespace Mono.CSharp { MethodBase candidate = Methods [i]; candidate_to_form [candidate] = candidate; } + + if (candidate_args != Arguments) { + if (candidates_expanded == null) + candidates_expanded = new Hashtable (2); - if (candidate_rate != 0) { + candidates_expanded.Add (Methods [i], candidate_args); + candidate_args = Arguments; + } + + if (candidate_rate != 0 || has_inaccessible_candidates_only) { if (msg_recorder != null) msg_recorder.EndSession (); continue; @@ -4207,12 +4181,10 @@ namespace Mono.CSharp { // return error info about the closest match // if (best_candidate != null) { - if (CustomErrorHandler != null) { - if (CustomErrorHandler.NoExactMatch (ec, best_candidate)) - return null; - } + if (CustomErrorHandler != null && !has_inaccessible_candidates_only && CustomErrorHandler.NoExactMatch (ec, best_candidate)) + return null; - ParameterData pd = TypeManager.GetParameterData (best_candidate); + AParametersCollection pd = TypeManager.GetParameterData (best_candidate); bool cand_params = candidate_to_form != null && candidate_to_form.Contains (best_candidate); if (arg_count == pd.Count || pd.HasParams) { if (TypeManager.IsGenericMethodDefinition (best_candidate)) { @@ -4223,8 +4195,8 @@ namespace Mono.CSharp { TypeManager.CSharpSignature (best_candidate)); return null; } - - Type [] g_args = TypeManager.GetGenericArguments (best_candidate); + + Type[] g_args = TypeManager.GetGenericArguments (best_candidate); if (type_arguments.Count != g_args.Length) { Report.SymbolRelatedToPreviousError (best_candidate); Report.Error (305, loc, "Using the generic method `{0}' requires `{1}' type argument(s)", @@ -4238,29 +4210,41 @@ namespace Mono.CSharp { return null; } } - + + if (has_inaccessible_candidates_only) { + if (InstanceExpression != null && type != ec.ContainerType && TypeManager.IsNestedFamilyAccessible (ec.ContainerType, best_candidate.DeclaringType)) { + // Although a derived class can access protected members of + // its base class it cannot do so through an instance of the + // base class (CS1540). If the qualifier_type is a base of the + // ec.ContainerType and the lookup succeeds with the latter one, + // then we are in this situation. + Error_CannotAccessProtected (loc, best_candidate, queried_type, ec.ContainerType); + } else { + Report.SymbolRelatedToPreviousError (best_candidate); + ErrorIsInaccesible (loc, GetSignatureForError ()); + } + } + if (!VerifyArgumentsCompat (ec, ref Arguments, arg_count, best_candidate, cand_params, may_fail, loc)) return null; + + if (has_inaccessible_candidates_only) + return null; + + throw new InternalErrorException ("VerifyArgumentsCompat didn't find any problem with rejected candidate " + best_candidate); } } - if (almost_matched_members.Count != 0) { - Error_MemberLookupFailed (ec.ContainerType, type, type, ".ctor", - null, MemberTypes.Constructor, AllBindingFlags); - return null; - } - // // We failed to find any method with correct argument count // if (Name == ConstructorInfo.ConstructorName) { - Report.SymbolRelatedToPreviousError (type); + Report.SymbolRelatedToPreviousError (queried_type); Report.Error (1729, loc, "The type `{0}' does not contain a constructor that takes `{1}' arguments", - TypeManager.CSharpName (type), arg_count); + TypeManager.CSharpName (queried_type), arg_count); } else { - Report.Error (1501, loc, "No overload for method `{0}' takes `{1}' arguments", - Name, arg_count.ToString ()); + Error_ArgumentCountWrong (arg_count); } return null; @@ -4322,8 +4306,16 @@ namespace Mono.CSharp { // best_candidate = (MethodBase) candidates [0]; - if (delegate_type == null) - method_params = candidate_to_form != null && candidate_to_form.Contains (best_candidate); + method_params = candidate_to_form != null && candidate_to_form.Contains (best_candidate); + + // + // TODO: Broken inverse order of candidates logic does not work with optional + // parameters used for method overrides and I am not going to fix it for SRE + // + if (candidates_expanded != null && candidates_expanded.Contains (best_candidate)) { + candidate_args = (Arguments) candidates_expanded [best_candidate]; + arg_count = candidate_args.Count; + } for (int ix = 1; ix < candidate_top; ix++) { MethodBase candidate = (MethodBase) candidates [ix]; @@ -4333,7 +4325,7 @@ namespace Mono.CSharp { bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate); - if (BetterFunction (ec, Arguments, arg_count, + if (BetterFunction (ec, candidate_args, arg_count, candidate, cand_params, best_candidate, method_params)) { best_candidate = candidate; @@ -4352,7 +4344,7 @@ namespace Mono.CSharp { continue; bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate); - if (!BetterFunction (ec, Arguments, arg_count, + if (!BetterFunction (ec, candidate_args, arg_count, best_candidate, method_params, candidate, cand_params)) { @@ -4363,10 +4355,7 @@ namespace Mono.CSharp { } if (ambiguous != null) { - Report.SymbolRelatedToPreviousError (ambiguous); - Report.SymbolRelatedToPreviousError (best_candidate); - Report.Error (121, loc, "The call is ambiguous between the following methods or properties: `{0}' and `{1}'", - TypeManager.CSharpSignature (ambiguous), TypeManager.CSharpSignature (best_candidate)); + Error_AmbiguousCall (ambiguous); return this; } @@ -4416,7 +4405,7 @@ namespace Mono.CSharp { // necessary etc. and return if everything is // all right // - if (!VerifyArgumentsCompat (ec, ref Arguments, arg_count, best_candidate, + if (!VerifyArgumentsCompat (ec, ref candidate_args, arg_count, best_candidate, method_params, may_fail, loc)) return null; @@ -4424,16 +4413,22 @@ namespace Mono.CSharp { return null; MethodBase the_method = TypeManager.DropGenericMethodArguments (best_candidate); -#if GMCS_SOURCE - if (the_method.IsGenericMethodDefinition && + if (TypeManager.IsGenericMethodDefinition (the_method) && !ConstraintChecker.CheckConstraints (ec, the_method, best_candidate, loc)) return null; -#endif + + // + // Check ObsoleteAttribute on the best method + // + ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (the_method); + if (oa != null && !ec.IsInObsoleteScope) + AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc); IMethodData data = TypeManager.GetMethod (the_method); if (data != null) data.SetMemberIsUsed (); + Arguments = candidate_args; return this; } @@ -4442,12 +4437,13 @@ namespace Mono.CSharp { type_arguments = ta; } - public bool VerifyArgumentsCompat (EmitContext ec, ref ArrayList arguments, + public bool VerifyArgumentsCompat (EmitContext ec, ref Arguments arguments, int arg_count, MethodBase method, bool chose_params_expanded, bool may_fail, Location loc) { - ParameterData pd = TypeManager.GetParameterData (method); + AParametersCollection pd = TypeManager.GetParameterData (method); + int param_count = GetApplicableParametersCount (method, pd); int errors = Report.Errors; Parameter.Modifier p_mod = 0; @@ -4458,25 +4454,17 @@ namespace Mono.CSharp { bool has_unsafe_arg = false; for (; a_idx < arg_count; a_idx++, ++a_pos) { - a = (Argument) arguments [a_idx]; + a = arguments [a_idx]; if (p_mod != Parameter.Modifier.PARAMS) { - p_mod = pd.ParameterModifier (a_idx); - pt = pd.ParameterType (a_idx); + p_mod = pd.FixedParameters [a_idx].ModFlags; + pt = pd.Types [a_idx]; has_unsafe_arg |= pt.IsPointer; - if (p_mod == Parameter.Modifier.ARGLIST) { - if (a.Type != TypeManager.runtime_argument_handle_type) - break; - continue; - } - if (p_mod == Parameter.Modifier.PARAMS) { if (chose_params_expanded) { params_initializers = new ArrayList (arg_count - a_idx); pt = TypeManager.GetElementType (pt); } - } else if (p_mod != 0) { - pt = TypeManager.GetElementType (pt); } } @@ -4491,17 +4479,42 @@ namespace Mono.CSharp { break; continue; - } - - Expression conv; - if (TypeManager.IsEqual (a.Type, pt)) { - conv = a.Expr; } else { - conv = Convert.ImplicitConversion (ec, a.Expr, pt, loc); - if (conv == null) - break; + NamedArgument na = a as NamedArgument; + if (na != null) { + int name_index = pd.GetParameterIndexByName (na.Name.Value); + if (name_index < 0 || name_index >= param_count) { + if (DeclaringType != null && TypeManager.IsDelegateType (DeclaringType)) { + Report.SymbolRelatedToPreviousError (DeclaringType); + Report.Error (1746, na.Name.Location, + "The delegate `{0}' does not contain a parameter named `{1}'", + TypeManager.CSharpName (DeclaringType), na.Name.Value); + } else { + Report.SymbolRelatedToPreviousError (best_candidate); + Report.Error (1739, na.Name.Location, + "The best overloaded method match for `{0}' does not contain a parameter named `{1}'", + TypeManager.CSharpSignature (method), na.Name.Value); + } + } else if (arguments[name_index] != a) { + if (DeclaringType != null && TypeManager.IsDelegateType (DeclaringType)) + Report.SymbolRelatedToPreviousError (DeclaringType); + else + Report.SymbolRelatedToPreviousError (best_candidate); + + Report.Error (1744, na.Name.Location, + "Named argument `{0}' cannot be used for a parameter which has positional argument specified", + na.Name.Value); + } + } } + if (delegate_type != null && !Delegate.IsTypeCovariant (a.Expr, pt)) + break; + + Expression conv = Convert.ImplicitConversion (ec, a.Expr, pt, loc); + if (conv == null) + break; + // // Convert params arguments to an array initializer // @@ -4518,45 +4531,52 @@ namespace Mono.CSharp { a.Expr = conv; } + if (a_idx != arg_count) { + if (!may_fail && Report.Errors == errors) { + if (CustomErrorHandler != null) + CustomErrorHandler.NoExactMatch (ec, best_candidate); + else + Error_InvalidArguments (ec, loc, a_pos, method, a, pd, pt); + } + return false; + } + // // Fill not provided arguments required by params modifier // - if (params_initializers == null && pd.HasParams && arg_count < pd.Count && a_idx + 1 == pd.Count) { + if (params_initializers == null && pd.HasParams && arg_count + 1 == param_count) { if (arguments == null) - arguments = new ArrayList (1); + arguments = new Arguments (1); - pt = pd.Types [GetApplicableParametersCount (method, pd) - 1]; + pt = pd.Types [param_count - 1]; pt = TypeManager.GetElementType (pt); has_unsafe_arg |= pt.IsPointer; params_initializers = new ArrayList (0); } - if (a_idx == arg_count) { - // - // Append an array argument with all params arguments - // - if (params_initializers != null) { - arguments.Add (new Argument ( - new ArrayCreation (new TypeExpression (pt, loc), "[]", - params_initializers, loc).Resolve (ec))); - } - - if (has_unsafe_arg && !ec.InUnsafe) { - if (!may_fail) - UnsafeError (loc); - return false; - } + // + // Append an array argument with all params arguments + // + if (params_initializers != null) { + arguments.Add (new Argument ( + new ArrayCreation (new TypeExpression (pt, loc), "[]", + params_initializers, loc).Resolve (ec))); + arg_count++; + } - return true; + if (arg_count < param_count) { + if (!may_fail) + Error_ArgumentCountWrong (arg_count); + return false; } - if (!may_fail && Report.Errors == errors) { - if (CustomErrorHandler != null) - CustomErrorHandler.NoExactMatch (ec, best_candidate); - else - Error_InvalidArguments (ec, loc, a_pos, method, a, pd, pt); + if (has_unsafe_arg && !ec.InUnsafe) { + if (!may_fail) + UnsafeError (loc); + return false; } - return false; + + return true; } } @@ -4643,18 +4663,15 @@ namespace Mono.CSharp { LocalTemporary temp; bool prepared; - bool in_initializer; - - public FieldExpr (FieldInfo fi, Location l, bool in_initializer): - this (fi, l) + + protected FieldExpr (Location l) { - this.in_initializer = in_initializer; + loc = l; } public FieldExpr (FieldInfo fi, Location l) { FieldInfo = fi; - eclass = ExprClass.Variable; type = TypeManager.TypeToCoreType (fi.FieldType); loc = l; } @@ -4662,6 +4679,8 @@ namespace Mono.CSharp { public FieldExpr (FieldInfo fi, Type genericType, Location l) : this (fi, l) { + if (TypeManager.IsGenericTypeDefinition (genericType)) + return; this.constructed_generic_type = genericType; } @@ -4729,15 +4748,16 @@ namespace Mono.CSharp { instance = InstanceExpression.CreateExpressionTree (ec); } - ArrayList args = new ArrayList (2); - args.Add (new Argument (instance)); - args.Add (new Argument (CreateTypeOfExpression ())); + Arguments args = Arguments.CreateForExpressionTree (ec, null, + instance, + CreateTypeOfExpression ()); + return CreateExpressionFactoryCall ("Field", args); } public Expression CreateTypeOfExpression () { - return new TypeOfField (FieldInfo, loc); + return new TypeOfField (GetConstructedFieldInfo (), loc); } override public Expression DoResolve (EmitContext ec) @@ -4765,11 +4785,15 @@ namespace Mono.CSharp { using (ec.With (EmitContext.Flags.DoFlowAnalysis, false)) { Expression right_side = out_access ? EmptyExpression.LValueMemberOutAccess : EmptyExpression.LValueMemberAccess; - InstanceExpression = InstanceExpression.ResolveLValue (ec, right_side, loc); + + if (InstanceExpression != EmptyExpression.Null) + InstanceExpression = InstanceExpression.ResolveLValue (ec, right_side); } } else { ResolveFlags rf = ResolveFlags.VariableOrValue | ResolveFlags.DisableFlowAnalysis; - InstanceExpression = InstanceExpression.Resolve (ec, rf); + + if (InstanceExpression != EmptyExpression.Null) + InstanceExpression = InstanceExpression.Resolve (ec, rf); } if (InstanceExpression == null) @@ -4780,16 +4804,16 @@ namespace Mono.CSharp { } } - if (!in_initializer && !ec.IsInFieldInitializer) { - ObsoleteAttribute oa; + // TODO: the code above uses some non-standard multi-resolve rules + if (eclass != ExprClass.Invalid) + return this; + + if (!ec.IsInObsoleteScope) { FieldBase f = TypeManager.GetField (FieldInfo); if (f != null) { - if (!ec.IsInObsoleteScope) - f.CheckObsoleteness (loc); - - // To be sure that type is external because we do not register generated fields - } else if (!(FieldInfo.DeclaringType is TypeBuilder)) { - oa = AttributeTester.GetMemberObsoleteAttribute (FieldInfo); + f.CheckObsoleteness (loc); + } else { + ObsoleteAttribute oa = AttributeTester.GetMemberObsoleteAttribute (FieldInfo); if (oa != null) AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (FieldInfo), loc); } @@ -4799,7 +4823,8 @@ namespace Mono.CSharp { IVariableReference var = InstanceExpression as IVariableReference; if (fb != null) { - if (!ec.InFixedInitializer && ec.ContainerType.IsValueType) { + IFixedExpression fe = InstanceExpression as IFixedExpression; + if (!ec.InFixedInitializer && (fe == null || !fe.IsFixed)) { Report.Error (1666, loc, "You cannot use fixed size buffers contained in unfixed expressions. Try using the fixed statement"); } @@ -4814,6 +4839,8 @@ namespace Mono.CSharp { return new FixedBufferPtr (this, fb.ElementType, loc).Resolve (ec); } + eclass = ExprClass.Variable; + // If the instance expression is a local variable or parameter. if (var == null || var.VariableInfo == null) return this; @@ -4823,6 +4850,7 @@ namespace Mono.CSharp { return null; variable_info = vi.GetSubStruct (FieldInfo.Name); + eclass = ExprClass.Variable; return this; } @@ -4869,7 +4897,7 @@ namespace Mono.CSharp { if (var != null && var.VariableInfo != null) var.VariableInfo.SetFieldAssigned (ec, FieldInfo.Name); - bool lvalue_instance = !FieldInfo.IsStatic && FieldInfo.DeclaringType.IsValueType; + bool lvalue_instance = !FieldInfo.IsStatic && TypeManager.IsValueType (FieldInfo.DeclaringType); bool out_access = right_side == EmptyExpression.OutAccess || right_side == EmptyExpression.LValueMemberOutAccess; Expression e = DoResolve (ec, lvalue_instance, out_access); @@ -4911,12 +4939,13 @@ namespace Mono.CSharp { GetSignatureForError ()); } + eclass = ExprClass.Variable; return this; } bool is_marshal_by_ref () { - return !IsStatic && Type.IsValueType && TypeManager.mbr_type != null && TypeManager.IsSubclassOf (DeclaringType, TypeManager.mbr_type); + return !IsStatic && TypeManager.IsStruct (Type) && TypeManager.mbr_type != null && TypeManager.IsSubclassOf (DeclaringType, TypeManager.mbr_type); } public override void CheckMarshalByRefAccess (EmitContext ec) @@ -4933,13 +4962,17 @@ namespace Mono.CSharp { return FieldInfo.GetHashCode (); } - public bool IsFixedVariable { + public bool IsFixed { get { // // A variable of the form V.I is fixed when V is a fixed variable of a struct type // IVariableReference variable = InstanceExpression as IVariableReference; - return variable != null && InstanceExpression.Type.IsValueType && variable.IsFixedVariable; + if (variable != null) + return TypeManager.IsStruct (InstanceExpression.Type) && variable.IsFixed; + + IFixedExpression fe = InstanceExpression as IFixedExpression; + return fe != null && fe.IsFixed; } } @@ -4987,15 +5020,21 @@ namespace Mono.CSharp { if (!prepared) EmitInstance (ec, false); - IFixedBuffer ff = AttributeTester.GetFixedBuffer (FieldInfo); - if (ff != null) { - ig.Emit (OpCodes.Ldflda, GetConstructedFieldInfo ()); - ig.Emit (OpCodes.Ldflda, ff.Element); + // Optimization for build-in types + // TODO: Iterators don't set current container + if (TypeManager.IsStruct (type) && type == ec.DeclContainer.TypeBuilder && ec.CurrentIterator == null) { + LoadFromPtr (ig, type); } else { - if (is_volatile) - ig.Emit (OpCodes.Volatile); + IFixedBuffer ff = AttributeTester.GetFixedBuffer (FieldInfo); + if (ff != null) { + ig.Emit (OpCodes.Ldflda, GetConstructedFieldInfo ()); + ig.Emit (OpCodes.Ldflda, ff.Element); + } else { + if (is_volatile) + ig.Emit (OpCodes.Volatile); - ig.Emit (OpCodes.Ldfld, GetConstructedFieldInfo ()); + ig.Emit (OpCodes.Ldfld, GetConstructedFieldInfo ()); + } } } @@ -5023,7 +5062,7 @@ namespace Mono.CSharp { prepared = prepare_for_load; EmitInstance (ec, prepared); - source.Emit (ec); + source.Emit (ec); if (leave_copy) { ec.ig.Emit (OpCodes.Dup); if (!FieldInfo.IsStatic) { @@ -5194,9 +5233,9 @@ namespace Mono.CSharp { public override Expression CreateExpressionTree (EmitContext ec) { - ArrayList args; + Arguments args; if (IsSingleDimensionalArrayLength ()) { - args = new ArrayList (1); + args = new Arguments (1); args.Add (new Argument (InstanceExpression.CreateExpressionTree (ec))); return CreateExpressionFactoryCall ("ArrayLength", args); } @@ -5206,7 +5245,7 @@ namespace Mono.CSharp { return null; } - args = new ArrayList (2); + args = new Arguments (2); if (InstanceExpression == null) args.Add (new Argument (new NullLiteral (loc))); else @@ -5299,7 +5338,10 @@ namespace Mono.CSharp { InstanceExpression.MutateHoistedGenericType (storey); type = storey.MutateType (type); - getter = storey.MutateGenericMethod (getter); + if (getter != null) + getter = storey.MutateGenericMethod (getter); + if (setter != null) + setter = storey.MutateGenericMethod (setter); } bool InstanceResolve (EmitContext ec, bool lvalue_instance, bool must_do_cs1540_check) @@ -5316,7 +5358,7 @@ namespace Mono.CSharp { InstanceExpression = InstanceExpression.DoResolve (ec); if (lvalue_instance && InstanceExpression != null) - InstanceExpression = InstanceExpression.ResolveLValue (ec, EmptyExpression.LValueMemberAccess, loc); + InstanceExpression = InstanceExpression.ResolveLValue (ec, EmptyExpression.LValueMemberAccess); if (InstanceExpression == null) return false; @@ -5345,7 +5387,7 @@ namespace Mono.CSharp { StringBuilder sig = new StringBuilder (TypeManager.CSharpName (mi.DeclaringType)); sig.Append ('.'); - ParameterData iparams = TypeManager.GetParameterData (mi); + AParametersCollection iparams = TypeManager.GetParameterData (mi); sig.Append (getter ? "get_" : "set_"); sig.Append (Name); sig.Append (iparams.GetSignatureForError ()); @@ -5427,12 +5469,21 @@ namespace Mono.CSharp { // if (IsBase && getter.IsAbstract) { Error_CannotCallAbstractBase (TypeManager.GetFullNameSignature (PropertyInfo)); - return null; } if (PropertyInfo.PropertyType.IsPointer && !ec.InUnsafe){ UnsafeError (loc); - return null; + } + + if (!ec.IsInObsoleteScope) { + PropertyBase pb = TypeManager.GetProperty (PropertyInfo); + if (pb != null) { + pb.CheckObsoleteness (loc); + } else { + ObsoleteAttribute oa = AttributeTester.GetMemberObsoleteAttribute (PropertyInfo); + if (oa != null) + AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc); + } } resolved = true; @@ -5443,7 +5494,7 @@ namespace Mono.CSharp { override public Expression DoResolveLValue (EmitContext ec, Expression right_side) { if (right_side == EmptyExpression.OutAccess) { - if (ec.CurrentBlock.Toplevel.GetTransparentIdentifier (PropertyInfo.Name) != null) { + if (ec.CurrentBlock.Toplevel.GetParameterReference (PropertyInfo.Name, loc) is MemberAccess) { Report.Error (1939, loc, "A range variable `{0}' may not be passes as `ref' or `out' parameter", PropertyInfo.Name); } else { @@ -5467,7 +5518,7 @@ namespace Mono.CSharp { if (getter == null) return null; - if (ec.CurrentBlock.Toplevel.GetTransparentIdentifier (PropertyInfo.Name) != null) { + if (ec.CurrentBlock.Toplevel.GetParameterReference (PropertyInfo.Name, loc) is MemberAccess) { Report.Error (1947, loc, "A range variable `{0}' cannot be assigned to. Consider using `let' clause to store the value", PropertyInfo.Name); } else { @@ -5497,7 +5548,7 @@ namespace Mono.CSharp { return null; } - if (!InstanceResolve (ec, PropertyInfo.DeclaringType.IsValueType, must_do_cs1540_check)) + if (!InstanceResolve (ec, TypeManager.IsStruct (PropertyInfo.DeclaringType), must_do_cs1540_check)) return null; // @@ -5505,13 +5556,23 @@ namespace Mono.CSharp { // if (IsBase && setter.IsAbstract){ Error_CannotCallAbstractBase (TypeManager.GetFullNameSignature (PropertyInfo)); - return null; } if (PropertyInfo.PropertyType.IsPointer && !ec.InUnsafe) { UnsafeError (loc); } + if (!ec.IsInObsoleteScope) { + PropertyBase pb = TypeManager.GetProperty (PropertyInfo); + if (pb != null) { + pb.CheckObsoleteness (loc); + } else { + ObsoleteAttribute oa = AttributeTester.GetMemberObsoleteAttribute (PropertyInfo); + if (oa != null) + AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc); + } + } + return this; } @@ -5569,8 +5630,8 @@ namespace Mono.CSharp { my_source = temp; } - ArrayList args = new ArrayList (1); - args.Add (new Argument (my_source, Argument.AType.Expression)); + Arguments args = new Arguments (1); + args.Add (new Argument (my_source)); Invocation.EmitCall (ec, IsBase, InstanceExpression, setter, args, loc, false, prepared); @@ -5657,7 +5718,7 @@ namespace Mono.CSharp { if ((mi.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0 && !ec.IsInCompoundAssignment) Error_AssignmentEventOnly (); - FieldExpr ml = new FieldExpr (mi.FieldBuilder, loc); + FieldExpr ml = new FieldExpr (mi.BackingField.FieldBuilder, loc); InstanceExpression = null; @@ -5746,6 +5807,17 @@ namespace Mono.CSharp { Error_CannotAssign (); return null; } + + if (!ec.IsInObsoleteScope) { + EventField ev = TypeManager.GetEventField (EventInfo); + if (ev != null) { + ev.CheckObsoleteness (loc); + } else { + ObsoleteAttribute oa = AttributeTester.GetMemberObsoleteAttribute (EventInfo); + if (oa != null) + AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc); + } + } return this; } @@ -5769,8 +5841,8 @@ namespace Mono.CSharp { public void EmitAddOrRemove (EmitContext ec, bool is_add, Expression source) { - ArrayList args = new ArrayList (1); - args.Add (new Argument (source, Argument.AType.Expression)); + Arguments args = new Arguments (1); + args.Add (new Argument (source)); Invocation.EmitCall (ec, IsBase, InstanceExpression, is_add ? add_accessor : remove_accessor, args, loc); } } @@ -5828,11 +5900,12 @@ namespace Mono.CSharp { EmitAssign (ec, source, false, false); } - public override HoistedVariable HoistedVariable { - get { return li.HoistedVariableReference; } + public override HoistedVariable GetHoistedVariable (EmitContext ec) + { + return li.HoistedVariableReference; } - public override bool IsFixedVariable { + public override bool IsFixed { get { return true; } }