X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fdelegate.cs;h=2073041afa252248e1f856efef43e9b91afaa1d4;hb=e3cfac464bfd8f5f815d86c04552a39d54197145;hp=7632a6128fd43ae74c53de938fef8abedc8e1a9f;hpb=416d4e10f905b8fe3d57f20b957e8cff86a7f1ec;p=mono.git diff --git a/mcs/mcs/delegate.cs b/mcs/mcs/delegate.cs index 7632a6128fd..2073041afa2 100644 --- a/mcs/mcs/delegate.cs +++ b/mcs/mcs/delegate.cs @@ -294,9 +294,8 @@ namespace Mono.CSharp { public override void PrepareEmit () { - if (!Parameters.IsEmpty) { - parameters.ResolveDefaultValues (this); - } + if ((caching_flags & Flags.CloseTypeCreated) != 0) + return; InvokeBuilder.PrepareEmit (); if (BeginInvokeBuilder != null) { @@ -439,6 +438,7 @@ namespace Mono.CSharp { // public abstract class DelegateCreation : Expression, OverloadResolver.IErrorHandler { + bool conditional_access_receiver; protected MethodSpec constructor_method; protected MethodGroupExpr method_group; @@ -507,8 +507,19 @@ namespace Mono.CSharp { var invoke_method = Delegate.GetInvokeMethod (type); + if (!ec.HasSet (ResolveContext.Options.ConditionalAccessReceiver)) { + if (method_group.HasConditionalAccess ()) { + conditional_access_receiver = true; + ec.Set (ResolveContext.Options.ConditionalAccessReceiver); + } + } + Arguments arguments = CreateDelegateMethodArguments (ec, invoke_method.Parameters, invoke_method.Parameters.Types, loc); method_group = method_group.OverloadResolve (ec, ref arguments, this, OverloadResolver.Restrictions.CovariantDelegate); + + if (conditional_access_receiver) + ec.With (ResolveContext.Options.ConditionalAccessReceiver, false); + if (method_group == null) return null; @@ -564,10 +575,15 @@ namespace Mono.CSharp { public override void Emit (EmitContext ec) { - if (method_group.InstanceExpression == null) + if (conditional_access_receiver) + ec.ConditionalAccess = new ConditionalAccessContext (type, ec.DefineLabel ()); + + if (method_group.InstanceExpression == null) { ec.EmitNull (); - else - method_group.InstanceExpression.Emit (ec); + } else { + var ie = new InstanceEmitter (method_group.InstanceExpression, false); + ie.Emit (ec, method_group.ConditionalAccess); + } var delegate_method = method_group.BestCandidate; @@ -580,11 +596,18 @@ namespace Mono.CSharp { } ec.Emit (OpCodes.Newobj, constructor_method); + + if (conditional_access_receiver) + ec.CloseConditionalAccess (null); } - public override void FlowAnalysis (FlowAnalysisContext fc) { + public override void FlowAnalysis (FlowAnalysisContext fc) + { base.FlowAnalysis (fc); method_group.FlowAnalysis (fc); + + if (conditional_access_receiver) + fc.ConditionalAccessEnd (); } void Error_ConversionFailed (ResolveContext ec, MethodSpec method, Expression return_type) @@ -622,7 +645,8 @@ namespace Mono.CSharp { var invoke = Delegate.GetInvokeMethod (target_type); Arguments arguments = CreateDelegateMethodArguments (ec, invoke.Parameters, invoke.Parameters.Types, mg.Location); - return mg.OverloadResolve (ec, ref arguments, null, OverloadResolver.Restrictions.CovariantDelegate | OverloadResolver.Restrictions.ProbingOnly) != null; + mg = mg.OverloadResolve (ec, ref arguments, null, OverloadResolver.Restrictions.CovariantDelegate | OverloadResolver.Restrictions.ProbingOnly); + return mg != null && Delegate.IsTypeCovariant (ec, mg.BestCandidateReturnType, invoke.ReturnType); } #region IErrorHandler Members @@ -830,13 +854,15 @@ namespace Mono.CSharp { class DelegateInvocation : ExpressionStatement { readonly Expression InstanceExpr; + readonly bool conditionalAccessReceiver; Arguments arguments; MethodSpec method; - public DelegateInvocation (Expression instance_expr, Arguments args, Location loc) + public DelegateInvocation (Expression instance_expr, Arguments args, bool conditionalAccessReceiver, Location loc) { this.InstanceExpr = instance_expr; this.arguments = args; + this.conditionalAccessReceiver = conditionalAccessReceiver; this.loc = loc; } @@ -877,29 +903,45 @@ namespace Mono.CSharp { return null; type = method.ReturnType; + if (conditionalAccessReceiver) + type = LiftMemberType (ec, type); + eclass = ExprClass.Value; return this; } public override void Emit (EmitContext ec) { + if (conditionalAccessReceiver) { + ec.ConditionalAccess = new ConditionalAccessContext (type, ec.DefineLabel ()); + } + // // Invocation on delegates call the virtual Invoke member // so we are always `instance' calls // var call = new CallEmitter (); call.InstanceExpression = InstanceExpr; - call.EmitPredefined (ec, method, arguments, loc); + call.Emit (ec, method, arguments, loc); + + if (conditionalAccessReceiver) + ec.CloseConditionalAccess (type.IsNullableType && type != method.ReturnType ? type : null); } public override void EmitStatement (EmitContext ec) { - Emit (ec); - // - // Pop the return value if there is one - // - if (type.Kind != MemberKind.Void) - ec.Emit (OpCodes.Pop); + if (conditionalAccessReceiver) { + ec.ConditionalAccess = new ConditionalAccessContext (type, ec.DefineLabel ()) { + Statement = true + }; + } + + var call = new CallEmitter (); + call.InstanceExpression = InstanceExpr; + call.EmitStatement (ec, method, arguments, loc); + + if (conditionalAccessReceiver) + ec.CloseConditionalAccess (null); } public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx)