X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fecore.cs;h=99671878955cae0bd44f5c92e69b0815b1c08ceb;hb=99ac282cf32a561379126826d0b29a19931a59a0;hp=a312c35864bd82509699459aa601d31fa5fab3ef;hpb=9fa1aa9f490713c0aecfb49873568cb0fdee1b78;p=mono.git diff --git a/mcs/mcs/ecore.cs b/mcs/mcs/ecore.cs index a312c35864b..99671878955 100644 --- a/mcs/mcs/ecore.cs +++ b/mcs/mcs/ecore.cs @@ -12,13 +12,18 @@ using System; using System.Collections.Generic; -using System.Diagnostics; -using System.Reflection; -using System.Reflection.Emit; using System.Text; using SLE = System.Linq.Expressions; using System.Linq; +#if STATIC +using IKVM.Reflection; +using IKVM.Reflection.Emit; +#else +using System.Reflection; +using System.Reflection.Emit; +#endif + namespace Mono.CSharp { /// @@ -129,11 +134,6 @@ namespace Mono.CSharp { get { return loc; } } - // Not nice but we have broken hierarchy. - public virtual void CheckMarshalByRefAccess (ResolveContext ec) - { - } - public virtual string GetSignatureForError () { return type.GetDefinition ().GetSignatureForError (); @@ -216,13 +216,18 @@ namespace Mono.CSharp { return null; } - if (!te.CheckAccessLevel (ec)) { + if (!te.type.IsAccessible (ec.CurrentType)) { ec.Compiler.Report.SymbolRelatedToPreviousError (te.Type); ErrorIsInaccesible (ec, te.Type.GetSignatureForError (), loc); } te.loc = loc; + var dep = te.type.GetMissingDependencies (); + if (dep != null) { + ImportedTypeDefinition.Error_MissingDependency (ec.Compiler, dep, loc); + } + // // Obsolete checks cannot be done when resolving base context as they // require type dependecies to be set but we are just resolving them @@ -553,7 +558,7 @@ namespace Mono.CSharp { protected static MethodSpec ConstructorLookup (ResolveContext rc, TypeSpec type, ref Arguments args, Location loc) { - var ctors = MemberCache.FindMembers (type, ConstructorInfo.ConstructorName, true); + var ctors = MemberCache.FindMembers (type, Constructor.ConstructorName, true); if (ctors == null) { rc.Report.SymbolRelatedToPreviousError (type); if (type.IsStruct) { @@ -604,8 +609,27 @@ namespace Mono.CSharp { if ((arity > 0 || (restrictions & MemberLookupRestrictions.ExactArity) != 0) && member.Arity != arity) continue; - if (rc != null && !member.IsAccessible (currentType)) - continue; + if (rc != null) { + if (!member.IsAccessible (currentType)) + continue; + + // + // With runtime binder we can have a situation where queried type is inaccessible + // because it came via dynamic object, the check about inconsisted accessibility + // had no effect as the type was unknown during compilation + // + // class A { + // private class N { } + // + // public dynamic Foo () + // { + // return new N (); + // } + // } + // + if (rc.Compiler.IsRuntimeBinder && !member.DeclaringType.IsAccessible (currentType)) + continue; + } if ((restrictions & MemberLookupRestrictions.InvocableOnly) != 0) { if (member is MethodSpec) @@ -669,7 +693,7 @@ namespace Mono.CSharp { /// Returns an expression that can be used to invoke operator false /// on the expression if it exists. /// - static public Expression GetOperatorFalse (ResolveContext ec, Expression e, Location loc) + protected static Expression GetOperatorFalse (ResolveContext ec, Expression e, Location loc) { return GetOperatorTrueOrFalse (ec, e, false, loc); } @@ -924,16 +948,11 @@ namespace Mono.CSharp { protected static TypeExpr CreateExpressionTypeExpression (ResolveContext ec, Location loc) { - TypeExpr texpr = TypeManager.expression_type_expr; - if (texpr == null) { - TypeSpec t = TypeManager.CoreLookupType (ec.Compiler, "System.Linq.Expressions", "Expression", MemberKind.Class, true); - if (t == null) - return null; - - TypeManager.expression_type_expr = texpr = new TypeExpression (t, Location.Null); - } + var t = ec.Module.PredefinedTypes.Expression.Resolve (loc); + if (t == null) + return null; - return texpr; + return new TypeExpression (t, loc); } // @@ -1040,9 +1059,13 @@ namespace Mono.CSharp { public override SLE.Expression MakeExpression (BuilderContext ctx) { +#if STATIC + return base.MakeExpression (ctx); +#else return ctx.HasSet (BuilderContext.Options.CheckedScope) ? SLE.Expression.ConvertChecked (child.MakeExpression (ctx), type.GetMetaInfo ()) : SLE.Expression.Convert (child.MakeExpression (ctx), type.GetMetaInfo ()); +#endif } protected override void CloneTo (CloneContext clonectx, Expression t) @@ -1354,27 +1377,19 @@ namespace Mono.CSharp { return Child.GetValue (); } +#if !STATIC public override object GetTypedValue () { - // FIXME: runtime is not ready to work with just emited enums - if (!RootContext.StdLib) { - return Child.GetValue (); - } - -#if MS_COMPATIBLE - // Small workaround for big problem + // + // The method can be used in dynamic context only (on closed types) + // // 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.MemberDefinition is TypeContainer) - return Child.GetValue (); -#endif - return System.Enum.ToObject (type.GetMetaInfo (), Child.GetValue ()); } +#endif public override string AsString () { @@ -1448,6 +1463,12 @@ namespace Mono.CSharp { public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) { + // Only boxing to object type is supported + if (targetType != TypeManager.object_type) { + base.EncodeAttributeValue (rc, enc, targetType); + return; + } + enc.Encode (child.Type); child.EncodeAttributeValue (rc, enc, child.Type); } @@ -1485,13 +1506,6 @@ namespace Mono.CSharp { return this; } - public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) - { - if (right_side == EmptyExpression.LValueMemberAccess || right_side == EmptyExpression.LValueMemberOutAccess) - ec.Report.Error (445, loc, "Cannot modify the result of an unboxing conversion"); - return base.DoResolveLValue (ec, right_side); - } - public override void Emit (EmitContext ec) { base.Emit (ec); @@ -2256,10 +2270,10 @@ namespace Mono.CSharp { } if (Arity == 0 && Name == "dynamic" && RootContext.Version > LanguageVersion.V_3) { - if (!ec.Compiler.PredefinedAttributes.Dynamic.IsDefined) { + if (!ec.Module.PredefinedAttributes.Dynamic.IsDefined) { ec.Compiler.Report.Error (1980, Location, "Dynamic keyword requires `{0}' to be defined. Are you missing System.Core.dll assembly reference?", - ec.Compiler.PredefinedAttributes.Dynamic.GetSignatureForError ()); + ec.Module.PredefinedAttributes.Dynamic.GetSignatureForError ()); } return new DynamicTypeExpr (loc); @@ -2315,10 +2329,19 @@ namespace Mono.CSharp { TypeSpec member_type = rc.CurrentType; TypeSpec current_type = member_type; for (; member_type != null; member_type = member_type.DeclaringType) { - var me = MemberLookup (errorMode ? null : rc, current_type, member_type, Name, lookup_arity, restrictions, loc) as MemberExpr; - if (me == null) + e = MemberLookup (errorMode ? null : rc, current_type, member_type, Name, lookup_arity, restrictions, loc); + if (e == null) continue; + var me = e as MemberExpr; + if (me == null) { + // The name matches a type, defer to ResolveAsTypeStep + if (e is TypeExpr) + break; + + continue; + } + if (errorMode) { if (variable != null) { if (me is FieldExpr || me is ConstantExpr || me is EventExpr || me is PropertyExpr) { @@ -2335,7 +2358,8 @@ namespace Mono.CSharp { ErrorIsInaccesible (rc, me.GetSignatureForError (), loc); } } else { - if (variable != null && (restrictions & MemberLookupRestrictions.InvocableOnly) == 0) { + // LAMESPEC: again, ignores InvocableOnly + if (variable != null) { rc.Report.SymbolRelatedToPreviousError (variable.Location, Name); rc.Report.Error (135, loc, "`{0}' conflicts with a declaration in a child block", Name); } @@ -2378,8 +2402,14 @@ namespace Mono.CSharp { // if ((restrictions & MemberLookupRestrictions.InvocableOnly) == 0 && !variable_found) { e = ResolveAsTypeStep (rc, lookup_arity == 0 || !errorMode); - if (e != null) + if (e != null) { + if (variable != null) { + rc.Report.SymbolRelatedToPreviousError (variable.Location, Name); + rc.Report.Error (135, loc, "`{0}' conflicts with a declaration in a child block", Name); + } + return e; + } } if (errorMode) { @@ -2475,15 +2505,6 @@ namespace Mono.CSharp { return ResolveAsTypeTerminal (ec, false); } - public virtual bool CheckAccessLevel (IMemberContext mc) - { - DeclSpace c = mc.CurrentMemberDefinition as DeclSpace; - if (c == null) - c = mc.CurrentMemberDefinition.Parent; - - return c.CheckAccessLevel (Type); - } - protected abstract TypeExpr DoResolveAsTypeStep (IMemberContext ec); public override bool Equals (object obj) @@ -2615,7 +2636,7 @@ namespace Mono.CSharp { // get/set member expressions second call would fail to proxy because left expression // would be of 'this' and not 'base' if (rc.CurrentType.IsStruct) - InstanceExpression = rc.GetThis (loc); + InstanceExpression = new This (loc).Resolve (rc); } if (targs != null) @@ -2677,6 +2698,11 @@ namespace Mono.CSharp { UnsafeError (rc, loc); } + var dep = member.GetMissingDependencies (); + if (dep != null) { + ImportedTypeDefinition.Error_MissingDependency (rc.Compiler, dep, loc); + } + if (!rc.IsObsolete) { ObsoleteAttribute oa = member.GetAttributeObsolete (); if (oa != null) @@ -2715,15 +2741,20 @@ namespace Mono.CSharp { return left; } - public bool ResolveInstanceExpression (ResolveContext rc) + public bool ResolveInstanceExpression (ResolveContext rc, Expression rhs) { if (IsStatic) { if (InstanceExpression != null) { if (InstanceExpression is TypeExpr) { - ObsoleteAttribute oa = InstanceExpression.Type.GetAttributeObsolete (); - if (oa != null && !rc.IsObsolete) { - AttributeTester.Report_ObsoleteMessage (oa, InstanceExpression.GetSignatureForError (), loc, rc.Report); - } + var t = InstanceExpression.Type; + do { + ObsoleteAttribute oa = t.GetAttributeObsolete (); + if (oa != null && !rc.IsObsolete) { + AttributeTester.Report_ObsoleteMessage (oa, t.GetSignatureForError (), loc, rc.Report); + } + + t = t.DeclaringType; + } while (t != null); } else { var runtime_expr = InstanceExpression as RuntimeValueExpression; if (runtime_expr == null || !runtime_expr.IsSuggestionOnly) { @@ -2759,13 +2790,21 @@ namespace Mono.CSharp { DeclaringType.GetSignatureForError (), rc.CurrentType.GetSignatureForError ()); } - InstanceExpression = rc.GetThis (loc); + InstanceExpression = new This (loc); + if (this is FieldExpr && rc.CurrentType.IsStruct) { + using (rc.Set (ResolveContext.Options.OmitStructFlowAnalysis)) { + InstanceExpression = InstanceExpression.Resolve (rc); + } + } else { + InstanceExpression = InstanceExpression.Resolve (rc); + } + return false; } var me = InstanceExpression as MemberExpr; if (me != null) { - me.ResolveInstanceExpression (rc); + me.ResolveInstanceExpression (rc, rhs); var fe = me as FieldExpr; if (fe != null && fe.IsMarshalByRefAccess ()) { @@ -2774,6 +2813,29 @@ namespace Mono.CSharp { "Cannot call methods, properties, or indexers on `{0}' because it is a value type member of a marshal-by-reference class", me.GetSignatureForError ()); } + + return true; + } + + // + // Run member-access postponed check once we know that + // the expression is not field expression which is the only + // expression which can use uninitialized this + // + if (InstanceExpression is This && !(this is FieldExpr) && rc.CurrentType.IsStruct) { + ((This)InstanceExpression).CheckStructThisDefiniteAssignment (rc); + } + + // + // Additional checks for l-value member access + // + if (rhs != null) { + // + // TODO: It should be recursive but that would break csc compatibility + // + if (InstanceExpression is UnboxCast) { + rc.Report.Error (445, InstanceExpression.Location, "Cannot modify the result of an unboxing conversion"); + } } return true; @@ -2876,7 +2938,7 @@ namespace Mono.CSharp { var me = ExtensionExpression as MemberExpr; if (me != null) - me.ResolveInstanceExpression (ec); + me.ResolveInstanceExpression (ec, null); InstanceExpression = null; return this; @@ -2926,6 +2988,7 @@ namespace Mono.CSharp { { protected IList Methods; MethodSpec best_candidate; + TypeSpec best_candidate_return; protected TypeArguments type_arguments; SimpleName simple_name; @@ -2954,6 +3017,12 @@ namespace Mono.CSharp { } } + public TypeSpec BestCandidateReturnType { + get { + return best_candidate_return; + } + } + protected override TypeSpec DeclaringType { get { return queried_type; @@ -2999,7 +3068,8 @@ namespace Mono.CSharp { public static MethodGroupExpr CreatePredefined (MethodSpec best, TypeSpec queriedType, Location loc) { return new MethodGroupExpr (best, queriedType, loc) { - best_candidate = best + best_candidate = best, + best_candidate_return = best.ReturnType }; } @@ -3101,7 +3171,7 @@ namespace Mono.CSharp { if (r.BestCandidateNewMethodGroup != null) return r.BestCandidateNewMethodGroup; - if (best_candidate.Kind == MemberKind.Method) { + if (best_candidate.Kind == MemberKind.Method && (restr & OverloadResolver.Restrictions.ProbingOnly) == 0) { if (InstanceExpression != null) { if (best_candidate.IsExtensionMethod && args[0].Expr == InstanceExpression) { InstanceExpression = null; @@ -3114,12 +3184,19 @@ namespace Mono.CSharp { } } - ResolveInstanceExpression (ec); + ResolveInstanceExpression (ec, null); if (InstanceExpression != null) CheckProtectedMemberAccess (ec, best_candidate); } - best_candidate = CandidateToBaseOverride (ec, best_candidate); + var base_override = CandidateToBaseOverride (ec, best_candidate); + if (base_override == best_candidate) { + best_candidate_return = r.BestCandidateReturnType; + } else { + best_candidate = base_override; + best_candidate_return = best_candidate.ReturnType; + } + return this; } @@ -3228,10 +3305,12 @@ namespace Mono.CSharp { { public readonly MemberSpec Member; public readonly bool Expanded; + public readonly AParametersCollection Parameters; - public AmbiguousCandidate (MemberSpec member, bool expanded) + public AmbiguousCandidate (MemberSpec member, AParametersCollection parameters, bool expanded) { Member = member; + Parameters = parameters; Expanded = expanded; } } @@ -3243,6 +3322,7 @@ namespace Mono.CSharp { IErrorHandler custom_errors; Restrictions restrictions; MethodGroupExpr best_candidate_extension_group; + TypeSpec best_candidate_return_type; SessionReportPrinter lambda_conv_msgs; ReportPrinter prev_recorder; @@ -3290,6 +3370,15 @@ namespace Mono.CSharp { } } + // + // Return type can be different between best candidate and closest override + // + public TypeSpec BestCandidateReturnType { + get { + return best_candidate_return_type; + } + } + public IErrorHandler CustomErrors { get { return custom_errors; @@ -3331,23 +3420,51 @@ namespace Mono.CSharp { static int BetterExpressionConversion (ResolveContext ec, Argument a, TypeSpec p, TypeSpec q) { TypeSpec argument_type = a.Type; + + // + // If argument is an anonymous function + // if (argument_type == InternalType.AnonymousMethod && RootContext.Version > LanguageVersion.ISO_2) { // - // Uwrap delegate from Expression + // p and q are delegate types or expression tree types // - if (p.GetDefinition () == TypeManager.expression_type) { + if (p.GetDefinition () == TypeManager.expression_type || q.GetDefinition () == TypeManager.expression_type) { + if (q.MemberDefinition != p.MemberDefinition) { + return 0; + } + + // + // Uwrap delegate from Expression + // + q = TypeManager.GetTypeArguments (q)[0]; p = TypeManager.GetTypeArguments (p)[0]; } - if (q.GetDefinition () == TypeManager.expression_type) { - q = TypeManager.GetTypeArguments (q)[0]; + + var p_m = Delegate.GetInvokeMethod (ec.Compiler, p); + var q_m = Delegate.GetInvokeMethod (ec.Compiler, q); + + // + // With identical parameter lists + // + if (!TypeSpecComparer.Equals (p_m.Parameters.Types,q_m.Parameters.Types)) + return 0; + + p = p_m.ReturnType; + q = q_m.ReturnType; + + // + // if p is void returning, and q has a return type Y, then C2 is the better conversion. + // + if (p == TypeManager.void_type) { + return q != TypeManager.void_type ? 2 : 0; } - p = Delegate.GetInvokeMethod (ec.Compiler, p).ReturnType; - q = Delegate.GetInvokeMethod (ec.Compiler, q).ReturnType; - if (p == TypeManager.void_type && q != TypeManager.void_type) - return 2; - if (q == TypeManager.void_type && p != TypeManager.void_type) - return 1; + // + // if p has a return type Y, and q is void returning, then C1 is the better conversion. + // + if (q == TypeManager.void_type) { + return p != TypeManager.void_type ? 1: 0; + } } else { if (argument_type == p) return 1; @@ -3405,6 +3522,8 @@ namespace Mono.CSharp { return 1; } + // FIXME: handle lifted operators + // TODO: this is expensive Expression p_tmp = new EmptyExpression (p); Expression q_tmp = new EmptyExpression (q); @@ -3430,8 +3549,8 @@ namespace Mono.CSharp { /// false if candidate ain't better /// true if candidate is better than the current best match /// - static bool BetterFunction (ResolveContext ec, Arguments args, MemberSpec candidate, bool candidate_params, - MemberSpec best, bool best_params) + static bool BetterFunction (ResolveContext ec, Arguments args, MemberSpec candidate, AParametersCollection cparam, bool candidate_params, + MemberSpec best, AParametersCollection bparam, bool best_params) { AParametersCollection candidate_pd = ((IParametersMember) candidate).Parameters; AParametersCollection best_pd = ((IParametersMember) best).Parameters; @@ -3440,27 +3559,46 @@ namespace Mono.CSharp { bool same = true; int args_count = args == null ? 0 : args.Count; int j = 0; + Argument a = null; + TypeSpec ct, bt; for (int c_idx = 0, b_idx = 0; j < args_count; ++j, ++c_idx, ++b_idx) { - Argument a = args[j]; + a = args[j]; // Default arguments are ignored for better decision if (a.IsDefaultArgument) break; - TypeSpec ct = candidate_pd.Types[c_idx]; - TypeSpec bt = best_pd.Types[b_idx]; + // + // When comparing named argument the parameter type index has to be looked up + // in original parameter set (override version for virtual members) + // + NamedArgument na = a as NamedArgument; + if (na != null) { + int idx = cparam.GetParameterIndexByName (na.Name); + ct = candidate_pd.Types[idx]; + if (candidate_params && candidate_pd.FixedParameters[idx].ModFlags == Parameter.Modifier.PARAMS) + ct = TypeManager.GetElementType (ct); + + idx = bparam.GetParameterIndexByName (na.Name); + bt = best_pd.Types[idx]; + if (best_params && best_pd.FixedParameters[idx].ModFlags == Parameter.Modifier.PARAMS) + bt = TypeManager.GetElementType (bt); + } else { + ct = candidate_pd.Types[c_idx]; + bt = best_pd.Types[b_idx]; - if (candidate_params && candidate_pd.FixedParameters[c_idx].ModFlags == Parameter.Modifier.PARAMS) { - ct = TypeManager.GetElementType (ct); - --c_idx; - } + if (candidate_params && candidate_pd.FixedParameters[c_idx].ModFlags == Parameter.Modifier.PARAMS) { + ct = TypeManager.GetElementType (ct); + --c_idx; + } - if (best_params && best_pd.FixedParameters[b_idx].ModFlags == Parameter.Modifier.PARAMS) { - bt = TypeManager.GetElementType (bt); - --b_idx; + if (best_params && best_pd.FixedParameters[b_idx].ModFlags == Parameter.Modifier.PARAMS) { + bt = TypeManager.GetElementType (bt); + --b_idx; + } } - if (ct == bt) + if (TypeSpecComparer.IsEqual (ct, bt)) continue; same = false; @@ -3489,7 +3627,7 @@ namespace Mono.CSharp { // The call Add (3, 4, 5) should be ambiguous. Without this check, the // first candidate would've chosen as better. // - if (!same) + if (!same && !a.IsDefaultArgument) return false; // @@ -3505,6 +3643,7 @@ namespace Mono.CSharp { // Prefer non-optional version // // LAMESPEC: Specification claims this should be done at last but the opposite is true + // if (candidate_params == best_params && candidate_pd.Count != best_pd.Count) { if (candidate_pd.Count >= best_pd.Count) return false; @@ -3550,8 +3689,15 @@ namespace Mono.CSharp { bool specific_at_least_once = false; for (j = 0; j < candidate_param_count; ++j) { - var ct = candidate_def_pd.Types[j]; - var bt = best_def_pd.Types[j]; + NamedArgument na = args_count == 0 ? null : args [j] as NamedArgument; + if (na != null) { + ct = candidate_def_pd.Types[cparam.GetParameterIndexByName (na.Name)]; + bt = best_def_pd.Types[bparam.GetParameterIndexByName (na.Name)]; + } else { + ct = candidate_def_pd.Types[j]; + bt = best_def_pd.Types[j]; + } + if (ct == bt) continue; TypeSpec specific = MoreSpecific (ct, bt); @@ -3564,9 +3710,6 @@ namespace Mono.CSharp { if (specific_at_least_once) return true; - // FIXME: handle lifted operators - // ... - return false; } @@ -3586,8 +3729,14 @@ namespace Mono.CSharp { // A return value rates candidate method compatibility, // 0 = the best, int.MaxValue = the worst // - int IsApplicable (ResolveContext ec, ref Arguments arguments, int arg_count, ref MemberSpec candidate, AParametersCollection pd, ref bool params_expanded_form, ref bool dynamicArgument) + int IsApplicable (ResolveContext ec, ref Arguments arguments, int arg_count, ref MemberSpec candidate, IParametersMember pm, ref bool params_expanded_form, ref bool dynamicArgument, ref TypeSpec returnType) { + // Parameters of most-derived type used mainly for named and optional parameters + var pd = pm.Parameters; + + // Used for params modifier only, that's legacy of C# 1.0 which uses base type for + // params modifier instead of most-derived type + var cpd = ((IParametersMember) candidate).Parameters; int param_count = pd.Count; int optional_count = 0; int score; @@ -3607,7 +3756,7 @@ namespace Mono.CSharp { return int.MaxValue - 10000 + args_gap - optional_count; // Readjust expected number when params used - if (pd.HasParams) { + if (cpd.HasParams) { optional_count--; if (arg_count < param_count) param_count--; @@ -3615,7 +3764,7 @@ namespace Mono.CSharp { return int.MaxValue - 10000 + args_gap; } } else if (arg_count != param_count) { - if (!pd.HasParams) + if (!cpd.HasParams) return int.MaxValue - 10000 + args_gap; if (arg_count < param_count - 1) return int.MaxValue - 10000 + args_gap; @@ -3664,7 +3813,7 @@ namespace Mono.CSharp { Argument temp; if (index >= param_count) { // When using parameters which should not be available to the user - if ((pd.FixedParameters[index].ModFlags & Parameter.Modifier.PARAMS) == 0) + if ((cpd.FixedParameters[index].ModFlags & Parameter.Modifier.PARAMS) == 0) break; arguments.Add (null); @@ -3700,6 +3849,7 @@ namespace Mono.CSharp { // // 1. Handle generic method using type arguments when specified or type inference // + TypeSpec[] ptypes; var ms = candidate as MethodSpec; if (ms != null && ms.IsGeneric) { // Setup constraint checker for probing only @@ -3710,8 +3860,7 @@ namespace Mono.CSharp { if (g_args_count != type_arguments.Count) return int.MaxValue - 20000 + System.Math.Abs (type_arguments.Count - g_args_count); - candidate = ms = ms.MakeGenericMethod (type_arguments.Arguments); - pd = ms.Parameters; + ms = ms.MakeGenericMethod (type_arguments.Arguments); } else { // TODO: It should not be here (we don't know yet whether any argument is lambda) but // for now it simplifies things. I should probably add a callback to ResolveContext @@ -3728,8 +3877,7 @@ namespace Mono.CSharp { return ti.InferenceScore - 20000; if (i_args.Length != 0) { - candidate = ms = ms.MakeGenericMethod (i_args); - pd = ms.Parameters; + ms = ms.MakeGenericMethod (i_args); } cc.IgnoreInferredDynamic = true; @@ -3738,12 +3886,33 @@ namespace Mono.CSharp { // // Type arguments constraints have to match for the method to be applicable // - if (!cc.CheckAll (ms.GetGenericMethodDefinition (), ms.TypeArguments, ms.Constraints, loc)) + if (!cc.CheckAll (ms.GetGenericMethodDefinition (), ms.TypeArguments, ms.Constraints, loc)) { + candidate = ms; return int.MaxValue - 25000; + } + // + // We have a generic return type and at same time the method is override which + // means we have to also inflate override return type in case the candidate is + // best candidate and override return type is different to base return type. + // + // virtual Foo with override Foo + // + if (candidate != pm) { + MethodSpec override_ms = (MethodSpec) pm; + var inflator = new TypeParameterInflator (ms.DeclaringType, override_ms.GenericDefinition.TypeParameters, ms.TypeArguments); + returnType = inflator.Inflate (returnType); + } else { + returnType = ms.ReturnType; + } + + candidate = ms; + ptypes = ms.Parameters.Types; } else { if (type_arguments != null) return int.MaxValue - 15000; + + ptypes = cpd.Types; } // @@ -3751,7 +3920,6 @@ namespace Mono.CSharp { // Parameter.Modifier p_mod = 0; TypeSpec pt = null; - TypeSpec[] ptypes = ((IParametersMember) candidate).Parameters.Types; for (int i = 0; i < arg_count; i++) { Argument a = arguments[i]; @@ -3785,7 +3953,7 @@ namespace Mono.CSharp { } if (p_mod != Parameter.Modifier.PARAMS) { - p_mod = pd.FixedParameters[i].ModFlags; + p_mod = (pd.FixedParameters[i].ModFlags & ~Parameter.Modifier.PARAMS) | (cpd.FixedParameters[i].ModFlags & Parameter.Modifier.PARAMS); pt = ptypes [i]; } else if (!params_expanded_form) { params_expanded_form = true; @@ -3825,8 +3993,12 @@ namespace Mono.CSharp { if (score > 0) score = IsArgumentCompatible (ec, a, Parameter.Modifier.NONE, pt); - if (score <= 0) + if (score == 0) { + params_expanded_form = true; + } else if (score < 0) { params_expanded_form = true; + dynamicArgument = true; + } } if (score > 0) { @@ -3839,7 +4011,7 @@ namespace Mono.CSharp { // // When params parameter has no argument it will be provided later if the method is the best candidate // - if (arg_count + 1 == pd.Count && (pd.FixedParameters [arg_count].ModFlags & Parameter.Modifier.PARAMS) != 0) + if (arg_count + 1 == pd.Count && (cpd.FixedParameters [arg_count].ModFlags & Parameter.Modifier.PARAMS) != 0) params_expanded_form = true; // @@ -3999,8 +4171,13 @@ namespace Mono.CSharp { if ((member.Modifiers & Modifiers.OVERRIDE) != 0) continue; - if (!member.IsAccessible (current_type) && !error_mode) - continue; + if (!error_mode) { + if (!member.IsAccessible (current_type)) + continue; + + if (rc.Compiler.IsRuntimeBinder && !member.DeclaringType.IsAccessible (current_type)) + continue; + } IParametersMember pm = member as IParametersMember; if (pm == null) { @@ -4029,7 +4206,8 @@ namespace Mono.CSharp { // bool params_expanded_form = false; bool dynamic_argument = false; - int candidate_rate = IsApplicable (rc, ref candidate_args, args_count, ref member, pm.Parameters, ref params_expanded_form, ref dynamic_argument); + TypeSpec rt = pm.MemberType; + int candidate_rate = IsApplicable (rc, ref candidate_args, args_count, ref member, pm, ref params_expanded_form, ref dynamic_argument, ref rt); // // How does it score compare to others @@ -4041,6 +4219,7 @@ namespace Mono.CSharp { best_candidate_params = params_expanded_form; best_candidate_dynamic = dynamic_argument; best_parameter_member = pm; + best_candidate_return_type = rt; } else if (candidate_rate == 0) { // // The member look is done per type for most operations but sometimes @@ -4052,19 +4231,51 @@ namespace Mono.CSharp { continue; } - // Is the new candidate better - if (BetterFunction (rc, candidate_args, member, params_expanded_form, best_candidate, best_candidate_params)) { + bool is_better; + if (best_candidate.DeclaringType.IsInterface && member.DeclaringType.ImplementsInterface (best_candidate.DeclaringType, false)) { + // + // We pack all interface members into top level type which makes the overload resolution + // more complicated for interfaces. We accomodate for this by removing methods with same + // signature when building the cache hence this path should not really be hit often + // + // Example: + // interface IA { void Foo (int arg); } + // interface IB : IA { void Foo (params int[] args); } + // + // IB::Foo is the best overload when calling IB.Foo (1) + // + is_better = true; + if (ambiguous_candidates != null) { + foreach (var amb_cand in ambiguous_candidates) { + if (member.DeclaringType.ImplementsInterface (best_candidate.DeclaringType, false)) { + continue; + } + + is_better = false; + break; + } + + if (is_better) + ambiguous_candidates = null; + } + } else { + // Is the new candidate better + is_better = BetterFunction (rc, candidate_args, member, pm.Parameters, params_expanded_form, best_candidate, best_parameter_member.Parameters, best_candidate_params); + } + + if (is_better) { best_candidate = member; best_candidate_args = candidate_args; best_candidate_params = params_expanded_form; best_candidate_dynamic = dynamic_argument; best_parameter_member = pm; + best_candidate_return_type = rt; } else { // It's not better but any other found later could be but we are not sure yet if (ambiguous_candidates == null) ambiguous_candidates = new List (); - ambiguous_candidates.Add (new AmbiguousCandidate (member, params_expanded_form)); + ambiguous_candidates.Add (new AmbiguousCandidate (member, pm.Parameters, params_expanded_form)); } } @@ -4136,7 +4347,7 @@ namespace Mono.CSharp { for (int ix = 0; ix < ambiguous_candidates.Count; ix++) { var candidate = ambiguous_candidates [ix]; - if (!BetterFunction (rc, candidate_args, best_candidate, best_candidate_params, candidate.Member, candidate.Expanded)) { + if (!BetterFunction (rc, best_candidate_args, best_candidate, best_parameter_member.Parameters, best_candidate_params, candidate.Member, candidate.Parameters, candidate.Expanded)) { var ambiguous = candidate.Member; if (custom_errors == null || !custom_errors.AmbiguousCandidates (rc, best_candidate, ambiguous)) { rc.Report.SymbolRelatedToPreviousError (best_candidate); @@ -4176,6 +4387,11 @@ namespace Mono.CSharp { if (oa != null && !rc.IsObsolete) AttributeTester.Report_ObsoleteMessage (oa, best_candidate.GetSignatureForError (), loc, rc.Report); + var dep = best_candidate.GetMissingDependencies (); + if (dep != null) { + ImportedTypeDefinition.Error_MissingDependency (rc.Compiler, dep, loc); + } + best_candidate.MemberDefinition.SetIsUsed (); args = best_candidate_args; @@ -4260,10 +4476,10 @@ namespace Mono.CSharp { // For candidates which match on parameters count report more details about incorrect arguments // if (pm != null) { - int unexpanded_count = pm.Parameters.HasParams ? pm.Parameters.Count - 1 : pm.Parameters.Count; + int unexpanded_count = ((IParametersMember) best_candidate).Parameters.HasParams ? pm.Parameters.Count - 1 : pm.Parameters.Count; if (pm.Parameters.Count == arg_count || params_expanded || unexpanded_count == arg_count) { // Reject any inaccessible member - if (!best_candidate.IsAccessible (rc.CurrentType)) { + if (!best_candidate.IsAccessible (rc.CurrentType) || !best_candidate.DeclaringType.IsAccessible (rc.CurrentType)) { rc.Report.SymbolRelatedToPreviousError (best_candidate); Expression.ErrorIsInaccesible (rc, best_candidate.GetSignatureForError (), loc); return; @@ -4505,7 +4721,7 @@ namespace Mono.CSharp { protected override Expression DoResolve (ResolveContext rc) { - ResolveInstanceExpression (rc); + ResolveInstanceExpression (rc, null); DoBestMemberChecks (rc, constant); var c = constant.GetConstant (rc); @@ -4558,7 +4774,7 @@ namespace Mono.CSharp { { } -#region Properties + #region Properties public override string Name { get { @@ -4648,18 +4864,22 @@ namespace Mono.CSharp { protected override Expression DoResolve (ResolveContext ec) { - return DoResolve (ec, false, false); + return DoResolve (ec, null); } - Expression DoResolve (ResolveContext ec, bool lvalue_instance, bool out_access) + Expression DoResolve (ResolveContext ec, Expression rhs) { - if (ResolveInstanceExpression (ec)) { + bool lvalue_instance = rhs != null && IsInstance && spec.DeclaringType.IsStruct; + + if (ResolveInstanceExpression (ec, rhs)) { // Resolve the field's instance expression while flow analysis is turned // off: when accessing a field "a.b", we must check whether the field // "a.b" is initialized, not whether the whole struct "a" is initialized. if (lvalue_instance) { using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) { + bool out_access = rhs == EmptyExpression.OutAccess.Instance || rhs == EmptyExpression.LValueMemberOutAccess; + Expression right_side = out_access ? EmptyExpression.LValueMemberOutAccess : EmptyExpression.LValueMemberAccess; @@ -4673,10 +4893,6 @@ namespace Mono.CSharp { if (InstanceExpression == null) return null; - - using (ec.Set (ResolveContext.Options.OmitStructFlowAnalysis)) { - InstanceExpression.CheckMarshalByRefAccess (ec); - } } DoBestMemberChecks (ec, spec); @@ -4758,10 +4974,7 @@ namespace Mono.CSharp { override public Expression DoResolveLValue (ResolveContext ec, Expression right_side) { - bool lvalue_instance = IsInstance && spec.DeclaringType.IsStruct; - bool out_access = right_side == EmptyExpression.OutAccess.Instance || right_side == EmptyExpression.LValueMemberOutAccess; - - Expression e = DoResolve (ec, lvalue_instance, out_access); + Expression e = DoResolve (ec, right_side); if (e == null) return null; @@ -4979,9 +5192,13 @@ namespace Mono.CSharp { public override SLE.Expression MakeExpression (BuilderContext ctx) { +#if STATIC + return base.MakeExpression (ctx); +#else return SLE.Expression.Field ( IsStatic ? null : InstanceExpression.MakeExpression (ctx), spec.GetMetaInfo ()); +#endif } public override void SetTypeArguments (ResolveContext ec, TypeArguments ta) @@ -5071,12 +5288,20 @@ namespace Mono.CSharp { public override SLE.Expression MakeAssignExpression (BuilderContext ctx, Expression source) { +#if STATIC + return base.MakeExpression (ctx); +#else return SLE.Expression.Property (InstanceExpression.MakeExpression (ctx), (MethodInfo) Setter.GetMetaInfo ()); +#endif } public override SLE.Expression MakeExpression (BuilderContext ctx) { +#if STATIC + return base.MakeExpression (ctx); +#else return SLE.Expression.Property (InstanceExpression.MakeExpression (ctx), (MethodInfo) Getter.GetMetaInfo ()); +#endif } void Error_PropertyNotValid (ResolveContext ec) @@ -5164,9 +5389,14 @@ namespace Mono.CSharp { Error_PropertyNotValid (rc); } - if (ResolveInstanceExpression (rc)) { - if (right_side != null && best_candidate.DeclaringType.IsStruct) - InstanceExpression.DoResolveLValue (rc, EmptyExpression.LValueMemberAccess); + ResolveInstanceExpression (rc, right_side); + + if ((best_candidate.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0 && best_candidate.DeclaringType != InstanceExpression.Type) { + var filter = new MemberFilter (best_candidate.Name, 0, MemberKind.Property, null, null); + var p = MemberCache.FindMember (InstanceExpression.Type, filter, BindingRestriction.InstanceOnly | BindingRestriction.OverrideOnly) as PropertySpec; + if (p != null) { + type = p.MemberType; + } } DoBestMemberChecks (rc, best_candidate); @@ -5222,9 +5452,6 @@ namespace Mono.CSharp { if (expr == null) return null; - if (InstanceExpression != null) - InstanceExpression.CheckMarshalByRefAccess (ec); - if (expr != this) return expr.Resolve (ec); } @@ -5394,7 +5621,7 @@ namespace Mono.CSharp { // if (!ec.HasSet (ResolveContext.Options.CompoundAssignmentScope)) { if (spec.BackingField != null && - (spec.DeclaringType == ec.CurrentType || TypeManager.IsNestedChildOf (ec.CurrentType, spec.DeclaringType))) { + (spec.DeclaringType == ec.CurrentType || TypeManager.IsNestedChildOf (ec.CurrentType, spec.DeclaringType.MemberDefinition))) { spec.MemberDefinition.SetIsUsed (); @@ -5413,8 +5640,6 @@ namespace Mono.CSharp { return ml.ResolveMemberAccess (ec, left, original); } - - Error_AssignmentEventOnly (ec); } return base.ResolveMemberAccess (ec, left, original); @@ -5447,10 +5672,10 @@ namespace Mono.CSharp { eclass = ExprClass.EventAccess; type = spec.MemberType; - ResolveInstanceExpression (ec); + ResolveInstanceExpression (ec, null); if (!ec.HasSet (ResolveContext.Options.CompoundAssignmentScope)) { - Error_CannotAssign (ec); + Error_AssignmentEventOnly (ec); } DoBestMemberChecks (ec, spec); @@ -5484,15 +5709,15 @@ namespace Mono.CSharp { void Error_AssignmentEventOnly (ResolveContext ec) { - ec.Report.Error (79, loc, "The event `{0}' can only appear on the left hand side of `+=' or `-=' operator", - GetSignatureForError ()); - } - - public void Error_CannotAssign (ResolveContext ec) - { - ec.Report.Error (70, loc, - "The event `{0}' can only appear on the left hand side of += or -= when used outside of the type `{1}'", - GetSignatureForError (), TypeManager.CSharpName (spec.DeclaringType)); + if (spec.DeclaringType == ec.CurrentType || TypeManager.IsNestedChildOf (ec.CurrentType, spec.DeclaringType.MemberDefinition)) { + ec.Report.Error (79, loc, + "The event `{0}' can only appear on the left hand side of `+=' or `-=' operator", + GetSignatureForError ()); + } else { + ec.Report.Error (70, loc, + "The event `{0}' can only appear on the left hand side of += or -= when used outside of the type `{1}'", + GetSignatureForError (), spec.DeclaringType.GetSignatureForError ()); + } } protected override void Error_CannotCallAbstractBase (ResolveContext rc, string name) @@ -5544,6 +5769,14 @@ namespace Mono.CSharp { this.loc = loc; } + public override bool IsLockedByStatement { + get { + return false; + } + set { + } + } + public LocalVariable LocalInfo { get { return li;