Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory.CSharp-5.5.0/Parser/mcs/delegate.cs @ 15682

Last change on this file since 15682 was 11700, checked in by jkarder, 10 years ago

#2077: created branch and added first version

File size: 27.7 KB
Line 
1//
2// delegate.cs: Delegate Handler
3//
4// Authors:
5//     Ravi Pratap (ravi@ximian.com)
6//     Miguel de Icaza (miguel@ximian.com)
7//     Marek Safar (marek.safar@gmail.com)
8//
9// Dual licensed under the terms of the MIT X11 or GNU GPL
10//
11// Copyright 2001 Ximian, Inc (http://www.ximian.com)
12// Copyright 2003-2009 Novell, Inc (http://www.novell.com)
13// Copyright 2011 Xamarin Inc
14//
15
16using System;
17
18#if STATIC
19using IKVM.Reflection;
20using IKVM.Reflection.Emit;
21#else
22using System.Reflection;
23using System.Reflection.Emit;
24#endif
25
26namespace Mono.CSharp {
27
28  //
29  // Delegate container implementation
30  //
31  public class Delegate : TypeDefinition, IParametersMember
32  {
33    public FullNamedExpression ReturnType;
34    readonly ParametersCompiled parameters;
35
36    Constructor Constructor;
37    Method InvokeBuilder;
38    Method BeginInvokeBuilder;
39    Method EndInvokeBuilder;
40
41    static readonly string[] attribute_targets = new string [] { "type", "return" };
42
43    public static readonly string InvokeMethodName = "Invoke";
44   
45    Expression instance_expr;
46    ReturnParameter return_attributes;
47
48    const Modifiers MethodModifiers = Modifiers.PUBLIC | Modifiers.VIRTUAL;
49
50    const Modifiers AllowedModifiers =
51      Modifiers.NEW |
52      Modifiers.PUBLIC |
53      Modifiers.PROTECTED |
54      Modifiers.INTERNAL |
55      Modifiers.UNSAFE |
56      Modifiers.PRIVATE;
57
58    public Delegate (TypeContainer parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, ParametersCompiled param_list,
59         Attributes attrs)
60      : base (parent, name, attrs, MemberKind.Delegate)
61
62    {
63      this.ReturnType = type;
64      ModFlags        = ModifiersExtensions.Check (AllowedModifiers, mod_flags,
65                 IsTopLevel ? Modifiers.INTERNAL :
66                 Modifiers.PRIVATE, name.Location, Report);
67      parameters      = param_list;
68      spec = new TypeSpec (Kind, null, this, null, ModFlags | Modifiers.SEALED);
69    }
70
71    #region Properties
72    public TypeSpec MemberType {
73      get {
74        return ReturnType.Type;
75      }
76    }
77
78    public AParametersCollection Parameters {
79      get {
80        return parameters;
81      }
82    }
83
84    public FullNamedExpression TypExpression {
85      get {
86        return ReturnType;
87      }
88    }
89
90    #endregion
91
92    public override void Accept (StructuralVisitor visitor)
93    {
94      visitor.Visit (this);
95    }
96
97    public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
98    {
99      if (a.Target == AttributeTargets.ReturnValue) {
100        if (return_attributes == null)
101          return_attributes = new ReturnParameter (this, InvokeBuilder.MethodBuilder, Location);
102
103        return_attributes.ApplyAttributeBuilder (a, ctor, cdata, pa);
104        return;
105      }
106
107      base.ApplyAttributeBuilder (a, ctor, cdata, pa);
108    }
109
110    public override AttributeTargets AttributeTargets {
111      get {
112        return AttributeTargets.Delegate;
113      }
114    }
115
116    protected override bool DoDefineMembers ()
117    {
118      var builtin_types = Compiler.BuiltinTypes;
119
120      var ctor_parameters = ParametersCompiled.CreateFullyResolved (
121        new [] {
122          new Parameter (new TypeExpression (builtin_types.Object, Location), "object", Parameter.Modifier.NONE, null, Location),
123          new Parameter (new TypeExpression (builtin_types.IntPtr, Location), "method", Parameter.Modifier.NONE, null, Location)
124        },
125        new [] {
126          builtin_types.Object,
127          builtin_types.IntPtr
128        }
129      );
130
131      Constructor = new Constructor (this, Constructor.ConstructorName,
132        Modifiers.PUBLIC, null, ctor_parameters, Location);
133      Constructor.Define ();
134
135      //
136      // Here the various methods like Invoke, BeginInvoke etc are defined
137      //
138      // First, call the `out of band' special method for
139      // defining recursively any types we need:
140      //
141      var p = parameters;
142
143      if (!p.Resolve (this))
144        return false;
145
146      //
147      // Invoke method
148      //
149
150      // Check accessibility
151      foreach (var partype in p.Types) {
152        if (!IsAccessibleAs (partype)) {
153          Report.SymbolRelatedToPreviousError (partype);
154          Report.Error (59, Location,
155            "Inconsistent accessibility: parameter type `{0}' is less accessible than delegate `{1}'",
156            partype.GetSignatureForError (), GetSignatureForError ());
157        }
158      }
159
160      var ret_type = ReturnType.ResolveAsType (this);
161      if (ret_type == null)
162        return false;
163
164      //
165      // We don't have to check any others because they are all
166      // guaranteed to be accessible - they are standard types.
167      //
168      if (!IsAccessibleAs (ret_type)) {
169        Report.SymbolRelatedToPreviousError (ret_type);
170        Report.Error (58, Location,
171              "Inconsistent accessibility: return type `" +
172              ret_type.GetSignatureForError () + "' is less " +
173              "accessible than delegate `" + GetSignatureForError () + "'");
174        return false;
175      }
176
177      CheckProtectedModifier ();
178
179      if (Compiler.Settings.StdLib && ret_type.IsSpecialRuntimeType) {
180        Method.Error1599 (Location, ret_type, Report);
181        return false;
182      }
183
184      VarianceDecl.CheckTypeVariance (ret_type, Variance.Covariant, this);
185
186      var resolved_rt = new TypeExpression (ret_type, Location);
187      InvokeBuilder = new Method (this, resolved_rt, MethodModifiers, new MemberName (InvokeMethodName), p, null);
188      InvokeBuilder.Define ();
189
190      //
191      // Don't emit async method for compiler generated delegates (e.g. dynamic site containers)
192      //
193      if (!IsCompilerGenerated) {
194        DefineAsyncMethods (resolved_rt);
195      }
196
197      return true;
198    }
199
200    void DefineAsyncMethods (TypeExpression returnType)
201    {
202      var iasync_result = Module.PredefinedTypes.IAsyncResult;
203      var async_callback = Module.PredefinedTypes.AsyncCallback;
204
205      //
206      // It's ok when async types don't exist, the delegate will have Invoke method only
207      //
208      if (!iasync_result.Define () || !async_callback.Define ())
209        return;
210
211      //
212      // BeginInvoke
213      //
214      ParametersCompiled async_parameters;
215      if (Parameters.Count == 0) {
216        async_parameters = ParametersCompiled.EmptyReadOnlyParameters;
217      } else {
218        var compiled = new Parameter[Parameters.Count];
219        for (int i = 0; i < compiled.Length; ++i) {
220          var p = parameters[i];
221          compiled[i] = new Parameter (new TypeExpression (parameters.Types[i], Location),
222            p.Name,
223            p.ModFlags & Parameter.Modifier.RefOutMask,
224            p.OptAttributes == null ? null : p.OptAttributes.Clone (), Location);
225        }
226
227        async_parameters = new ParametersCompiled (compiled);
228      }
229
230      async_parameters = ParametersCompiled.MergeGenerated (Compiler, async_parameters, false,
231        new Parameter[] {
232          new Parameter (new TypeExpression (async_callback.TypeSpec, Location), "callback", Parameter.Modifier.NONE, null, Location),
233          new Parameter (new TypeExpression (Compiler.BuiltinTypes.Object, Location), "object", Parameter.Modifier.NONE, null, Location)
234        },
235        new [] {
236          async_callback.TypeSpec,
237          Compiler.BuiltinTypes.Object
238        }
239      );
240
241      BeginInvokeBuilder = new Method (this,
242        new TypeExpression (iasync_result.TypeSpec, Location), MethodModifiers,
243        new MemberName ("BeginInvoke"), async_parameters, null);
244      BeginInvokeBuilder.Define ();
245
246      //
247      // EndInvoke is a bit more interesting, all the parameters labeled as
248      // out or ref have to be duplicated here.
249      //
250
251      //
252      // Define parameters, and count out/ref parameters
253      //
254      ParametersCompiled end_parameters;
255      int out_params = 0;
256
257      foreach (Parameter p in Parameters.FixedParameters) {
258        if ((p.ModFlags & Parameter.Modifier.RefOutMask) != 0)
259          ++out_params;
260      }
261
262      if (out_params > 0) {
263        Parameter[] end_params = new Parameter[out_params];
264
265        int param = 0;
266        for (int i = 0; i < Parameters.FixedParameters.Length; ++i) {
267          Parameter p = parameters [i];
268          if ((p.ModFlags & Parameter.Modifier.RefOutMask) == 0)
269            continue;
270
271          end_params [param++] = new Parameter (new TypeExpression (p.Type, Location),
272            p.Name,
273            p.ModFlags & Parameter.Modifier.RefOutMask,
274            p.OptAttributes == null ? null : p.OptAttributes.Clone (), Location);
275        }
276
277        end_parameters = new ParametersCompiled (end_params);
278      } else {
279        end_parameters = ParametersCompiled.EmptyReadOnlyParameters;
280      }
281
282      end_parameters = ParametersCompiled.MergeGenerated (Compiler, end_parameters, false,
283        new Parameter (
284          new TypeExpression (iasync_result.TypeSpec, Location),
285          "result", Parameter.Modifier.NONE, null, Location),
286        iasync_result.TypeSpec);
287
288      //
289      // Create method, define parameters, register parameters with type system
290      //
291      EndInvokeBuilder = new Method (this, returnType, MethodModifiers, new MemberName ("EndInvoke"), end_parameters, null);
292      EndInvokeBuilder.Define ();
293    }
294
295    public override void PrepareEmit ()
296    {
297      if (!Parameters.IsEmpty) {
298        parameters.ResolveDefaultValues (this);
299      }
300
301      InvokeBuilder.PrepareEmit ();
302      if (BeginInvokeBuilder != null) {
303        BeginInvokeBuilder.PrepareEmit ();
304        EndInvokeBuilder.PrepareEmit ();
305      }
306    }
307
308    public override void Emit ()
309    {
310      base.Emit ();
311
312      if (ReturnType.Type != null) {
313        if (ReturnType.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
314          return_attributes = new ReturnParameter (this, InvokeBuilder.MethodBuilder, Location);
315          Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder);
316        } else if (ReturnType.Type.HasDynamicElement) {
317          return_attributes = new ReturnParameter (this, InvokeBuilder.MethodBuilder, Location);
318          Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder, ReturnType.Type, Location);
319        }
320
321        ConstraintChecker.Check (this, ReturnType.Type, ReturnType.Location);
322      }
323
324      Constructor.ParameterInfo.ApplyAttributes (this, Constructor.ConstructorBuilder);
325      Constructor.ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
326
327      parameters.CheckConstraints (this);
328      parameters.ApplyAttributes (this, InvokeBuilder.MethodBuilder);
329      InvokeBuilder.MethodBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
330
331      if (BeginInvokeBuilder != null) {
332        BeginInvokeBuilder.ParameterInfo.ApplyAttributes (this, BeginInvokeBuilder.MethodBuilder);
333        EndInvokeBuilder.ParameterInfo.ApplyAttributes (this, EndInvokeBuilder.MethodBuilder);
334
335        BeginInvokeBuilder.MethodBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
336        EndInvokeBuilder.MethodBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
337      }
338    }
339
340    protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
341    {
342      base_type = Compiler.BuiltinTypes.MulticastDelegate;
343      base_class = null;
344      return null;
345    }
346
347    protected override TypeAttributes TypeAttr {
348      get {
349        return base.TypeAttr | TypeAttributes.Class | TypeAttributes.Sealed;
350      }
351    }
352
353    public override string[] ValidAttributeTargets {
354      get {
355        return attribute_targets;
356      }
357    }
358
359    //TODO: duplicate
360    protected override bool VerifyClsCompliance ()
361    {
362      if (!base.VerifyClsCompliance ()) {
363        return false;
364      }
365
366      parameters.VerifyClsCompliance (this);
367
368      if (!InvokeBuilder.MemberType.IsCLSCompliant ()) {
369        Report.Warning (3002, 1, Location, "Return type of `{0}' is not CLS-compliant",
370          GetSignatureForError ());
371      }
372      return true;
373    }
374
375
376    public static MethodSpec GetConstructor (TypeSpec delType)
377    {
378      var ctor = MemberCache.FindMember (delType, MemberFilter.Constructor (null), BindingRestriction.DeclaredOnly);
379      return (MethodSpec) ctor;
380    }
381
382    //
383    // Returns the "Invoke" from a delegate type
384    //
385    public static MethodSpec GetInvokeMethod (TypeSpec delType)
386    {
387      var invoke = MemberCache.FindMember (delType,
388        MemberFilter.Method (InvokeMethodName, 0, null, null),
389        BindingRestriction.DeclaredOnly);
390
391      return (MethodSpec) invoke;
392    }
393
394    public static AParametersCollection GetParameters (TypeSpec delType)
395    {
396      var invoke_mb = GetInvokeMethod (delType);
397      return invoke_mb.Parameters;
398    }
399
400    //
401    // 15.2 Delegate compatibility
402    //
403    public static bool IsTypeCovariant (ResolveContext rc, TypeSpec a, TypeSpec b)
404    {
405      //
406      // For each value parameter (a parameter with no ref or out modifier), an
407      // identity conversion or implicit reference conversion exists from the
408      // parameter type in D to the corresponding parameter type in M
409      //
410      if (a == b)
411        return true;
412
413      if (rc.Module.Compiler.Settings.Version == LanguageVersion.ISO_1)
414        return false;
415
416      if (a.IsGenericParameter && b.IsGenericParameter)
417        return a == b;
418
419      return Convert.ImplicitReferenceConversionExists (a, b);
420    }
421
422    public static string FullDelegateDesc (MethodSpec invoke_method)
423    {
424      return TypeManager.GetFullNameSignature (invoke_method).Replace (".Invoke", "");
425    }
426   
427    public Expression InstanceExpression {
428      get {
429        return instance_expr;
430      }
431      set {
432        instance_expr = value;
433      }
434    }
435  }
436
437  //
438  // Base class for `NewDelegate' and `ImplicitDelegateCreation'
439  //
440  public abstract class DelegateCreation : Expression, OverloadResolver.IErrorHandler
441  {
442    bool conditional_access_receiver;
443    protected MethodSpec constructor_method;
444    protected MethodGroupExpr method_group;
445
446    public bool AllowSpecialMethodsInvocation { get; set; }
447
448    public override bool ContainsEmitWithAwait ()
449    {
450      var instance = method_group.InstanceExpression;
451      return instance != null && instance.ContainsEmitWithAwait ();
452    }
453
454    public static Arguments CreateDelegateMethodArguments (ResolveContext rc, AParametersCollection pd, TypeSpec[] types, Location loc)
455    {
456      Arguments delegate_arguments = new Arguments (pd.Count);
457      for (int i = 0; i < pd.Count; ++i) {
458        Argument.AType atype_modifier;
459        switch (pd.FixedParameters [i].ModFlags & Parameter.Modifier.RefOutMask) {
460        case Parameter.Modifier.REF:
461          atype_modifier = Argument.AType.Ref;
462          break;
463        case Parameter.Modifier.OUT:
464          atype_modifier = Argument.AType.Out;
465          break;
466        default:
467          atype_modifier = 0;
468          break;
469        }
470
471        var ptype = types[i];
472        if (ptype.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
473          ptype = rc.BuiltinTypes.Object;
474
475        delegate_arguments.Add (new Argument (new TypeExpression (ptype, loc), atype_modifier));
476      }
477
478      return delegate_arguments;
479    }
480
481    public override Expression CreateExpressionTree (ResolveContext ec)
482    {
483      MemberAccess ma = new MemberAccess (new MemberAccess (new QualifiedAliasMember ("global", "System", loc), "Delegate", loc), "CreateDelegate", loc);
484
485      Arguments args = new Arguments (3);
486      args.Add (new Argument (new TypeOf (type, loc)));
487
488      if (method_group.InstanceExpression == null)
489        args.Add (new Argument (new NullLiteral (loc)));
490      else
491        args.Add (new Argument (method_group.InstanceExpression));
492
493      args.Add (new Argument (method_group.CreateExpressionTree (ec)));
494      Expression e = new Invocation (ma, args).Resolve (ec);
495      if (e == null)
496        return null;
497
498      e = Convert.ExplicitConversion (ec, e, type, loc);
499      if (e == null)
500        return null;
501
502      return e.CreateExpressionTree (ec);
503    }
504
505    protected override Expression DoResolve (ResolveContext ec)
506    {
507      constructor_method = Delegate.GetConstructor (type);
508
509      var invoke_method = Delegate.GetInvokeMethod (type);
510
511      if (!ec.HasSet (ResolveContext.Options.ConditionalAccessReceiver)) {
512        if (method_group.HasConditionalAccess ()) {
513          conditional_access_receiver = true;
514          ec.Set (ResolveContext.Options.ConditionalAccessReceiver);
515        }
516      }
517
518      Arguments arguments = CreateDelegateMethodArguments (ec, invoke_method.Parameters, invoke_method.Parameters.Types, loc);
519      method_group = method_group.OverloadResolve (ec, ref arguments, this, OverloadResolver.Restrictions.CovariantDelegate);
520
521      if (conditional_access_receiver)
522        ec.With (ResolveContext.Options.ConditionalAccessReceiver, false);
523
524      if (method_group == null)
525        return null;
526
527      var delegate_method = method_group.BestCandidate;
528     
529      if (delegate_method.DeclaringType.IsNullableType) {
530        ec.Report.Error (1728, loc, "Cannot create delegate from method `{0}' because it is a member of System.Nullable<T> type",
531          delegate_method.GetSignatureForError ());
532        return null;
533      }   
534     
535      if (!AllowSpecialMethodsInvocation)
536        Invocation.IsSpecialMethodInvocation (ec, delegate_method, loc);
537
538      ExtensionMethodGroupExpr emg = method_group as ExtensionMethodGroupExpr;
539      if (emg != null) {
540        method_group.InstanceExpression = emg.ExtensionExpression;
541        TypeSpec e_type = emg.ExtensionExpression.Type;
542        if (TypeSpec.IsValueType (e_type)) {
543          ec.Report.Error (1113, loc, "Extension method `{0}' of value type `{1}' cannot be used to create delegates",
544            delegate_method.GetSignatureForError (), e_type.GetSignatureForError ());
545        }
546      }
547
548      TypeSpec rt = method_group.BestCandidateReturnType;
549      if (rt.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
550        rt = ec.BuiltinTypes.Object;
551
552      if (!Delegate.IsTypeCovariant (ec, rt, invoke_method.ReturnType)) {
553        Expression ret_expr = new TypeExpression (delegate_method.ReturnType, loc);
554        Error_ConversionFailed (ec, delegate_method, ret_expr);
555      }
556
557      if (method_group.IsConditionallyExcluded) {
558        ec.Report.SymbolRelatedToPreviousError (delegate_method);
559        MethodOrOperator m = delegate_method.MemberDefinition as MethodOrOperator;
560        if (m != null && m.IsPartialDefinition) {
561          ec.Report.Error (762, loc, "Cannot create delegate from partial method declaration `{0}'",
562            delegate_method.GetSignatureForError ());
563        } else {
564          ec.Report.Error (1618, loc, "Cannot create delegate with `{0}' because it has a Conditional attribute",
565            TypeManager.CSharpSignature (delegate_method));
566        }
567      }
568
569      var expr = method_group.InstanceExpression;
570      if (expr != null && (expr.Type.IsGenericParameter || !TypeSpec.IsReferenceType (expr.Type)))
571        method_group.InstanceExpression = new BoxedCast (expr, ec.BuiltinTypes.Object);
572
573      eclass = ExprClass.Value;
574      return this;
575    }
576   
577    public override void Emit (EmitContext ec)
578    {
579      if (conditional_access_receiver)
580        ec.ConditionalAccess = new ConditionalAccessContext (type, ec.DefineLabel ());
581
582      if (method_group.InstanceExpression == null) {
583        ec.EmitNull ();
584      } else {
585        var ie = new InstanceEmitter (method_group.InstanceExpression, false);
586        ie.Emit (ec, method_group.ConditionalAccess);
587      }
588
589      var delegate_method = method_group.BestCandidate;
590
591      // Any delegate must be sealed
592      if (!delegate_method.DeclaringType.IsDelegate && delegate_method.IsVirtual && !method_group.IsBase) {
593        ec.Emit (OpCodes.Dup);
594        ec.Emit (OpCodes.Ldvirtftn, delegate_method);
595      } else {
596        ec.Emit (OpCodes.Ldftn, delegate_method);
597      }
598
599      ec.Emit (OpCodes.Newobj, constructor_method);
600
601      if (conditional_access_receiver)
602        ec.CloseConditionalAccess (null);
603    }
604
605    public override void FlowAnalysis (FlowAnalysisContext fc)
606    {
607      base.FlowAnalysis (fc);
608      method_group.FlowAnalysis (fc);
609
610      if (conditional_access_receiver)
611        fc.ConditionalAccessEnd ();
612    }
613
614    void Error_ConversionFailed (ResolveContext ec, MethodSpec method, Expression return_type)
615    {
616      var invoke_method = Delegate.GetInvokeMethod (type);
617      string member_name = method_group.InstanceExpression != null ?
618        Delegate.FullDelegateDesc (method) :
619        TypeManager.GetFullNameSignature (method);
620
621      ec.Report.SymbolRelatedToPreviousError (type);
622      ec.Report.SymbolRelatedToPreviousError (method);
623      if (ec.Module.Compiler.Settings.Version == LanguageVersion.ISO_1) {
624        ec.Report.Error (410, loc, "A method or delegate `{0} {1}' parameters and return type must be same as delegate `{2} {3}' parameters and return type",
625          method.ReturnType.GetSignatureForError (), member_name,
626          invoke_method.ReturnType.GetSignatureForError (), Delegate.FullDelegateDesc (invoke_method));
627        return;
628      }
629
630      if (return_type == null) {
631        ec.Report.Error (123, loc, "A method or delegate `{0}' parameters do not match delegate `{1}' parameters",
632          member_name, Delegate.FullDelegateDesc (invoke_method));
633        return;
634      }
635
636      ec.Report.Error (407, loc, "A method or delegate `{0} {1}' return type does not match delegate `{2} {3}' return type",
637        return_type.GetSignatureForError (), member_name,
638        invoke_method.ReturnType.GetSignatureForError (), Delegate.FullDelegateDesc (invoke_method));
639    }
640
641    public static bool ImplicitStandardConversionExists (ResolveContext ec, MethodGroupExpr mg, TypeSpec target_type)
642    {
643//      if (target_type == TypeManager.delegate_type || target_type == TypeManager.multicast_delegate_type)
644//        return false;
645
646      var invoke = Delegate.GetInvokeMethod (target_type);
647
648      Arguments arguments = CreateDelegateMethodArguments (ec, invoke.Parameters, invoke.Parameters.Types, mg.Location);
649      return mg.OverloadResolve (ec, ref arguments, null, OverloadResolver.Restrictions.CovariantDelegate | OverloadResolver.Restrictions.ProbingOnly) != null;
650    }
651
652    #region IErrorHandler Members
653
654    bool OverloadResolver.IErrorHandler.AmbiguousCandidates (ResolveContext ec, MemberSpec best, MemberSpec ambiguous)
655    {
656      return false;
657    }
658
659    bool OverloadResolver.IErrorHandler.ArgumentMismatch (ResolveContext rc, MemberSpec best, Argument arg, int index)
660    {
661      Error_ConversionFailed (rc, best as MethodSpec, null);
662      return true;
663    }
664
665    bool OverloadResolver.IErrorHandler.NoArgumentMatch (ResolveContext rc, MemberSpec best)
666    {
667      Error_ConversionFailed (rc, best as MethodSpec, null);
668      return true;
669    }
670
671    bool OverloadResolver.IErrorHandler.TypeInferenceFailed (ResolveContext rc, MemberSpec best)
672    {
673      return false;
674    }
675
676    #endregion
677  }
678
679  //
680  // Created from the conversion code
681  //
682  public class ImplicitDelegateCreation : DelegateCreation
683  {
684    Field mg_cache;
685
686    public ImplicitDelegateCreation (TypeSpec delegateType, MethodGroupExpr mg, Location loc)
687    {
688      type = delegateType;
689      this.method_group = mg;
690      this.loc = loc;
691    }
692
693    //
694    // Returns true when type is MVAR or has MVAR reference
695    //
696    public static bool ContainsMethodTypeParameter (TypeSpec type)
697    {
698      var tps = type as TypeParameterSpec;
699      if (tps != null)
700        return tps.IsMethodOwned;
701
702      var ec = type as ElementTypeSpec;
703      if (ec != null)
704        return ContainsMethodTypeParameter (ec.Element);
705
706      foreach (var t in type.TypeArguments) {
707        if (ContainsMethodTypeParameter (t)) {
708          return true;
709        }
710      }
711
712      if (type.IsNested)
713        return ContainsMethodTypeParameter (type.DeclaringType);
714
715      return false;
716    }
717   
718    bool HasMvar ()
719    {
720      if (ContainsMethodTypeParameter (type))
721        return false;
722
723      var best = method_group.BestCandidate;
724      if (ContainsMethodTypeParameter (best.DeclaringType))
725        return false;
726
727      if (best.TypeArguments != null) {
728        foreach (var ta in best.TypeArguments) {
729          if (ContainsMethodTypeParameter (ta))
730            return false;
731        }
732      }
733
734      return true;
735    }
736
737    protected override Expression DoResolve (ResolveContext ec)
738    {
739      var expr = base.DoResolve (ec);
740      if (expr == null)
741        return ErrorExpression.Instance;
742
743      if (ec.IsInProbingMode)
744        return expr;
745
746      //
747      // Cache any static delegate creation
748      //
749      if (method_group.InstanceExpression != null)
750        return expr;
751
752      //
753      // Cannot easily cache types with MVAR
754      //
755      if (!HasMvar ())
756        return expr;
757
758      //
759      // Create type level cache for a delegate instance
760      //
761      var parent = ec.CurrentMemberDefinition.Parent.PartialContainer;
762      int id = parent.MethodGroupsCounter++;
763
764      mg_cache = new Field (parent, new TypeExpression (type, loc),
765        Modifiers.STATIC | Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED,
766        new MemberName (CompilerGeneratedContainer.MakeName (null, "f", "mg$cache", id), loc), null);
767      mg_cache.Define ();
768      parent.AddField (mg_cache);
769
770      return expr;
771    }
772
773    public override void Emit (EmitContext ec)
774    {
775      Label l_initialized = ec.DefineLabel ();
776
777      if (mg_cache != null) {
778        ec.Emit (OpCodes.Ldsfld, mg_cache.Spec);
779        ec.Emit (OpCodes.Brtrue_S, l_initialized);
780      }
781
782      base.Emit (ec);
783
784      if (mg_cache != null) {
785        ec.Emit (OpCodes.Stsfld, mg_cache.Spec);
786        ec.MarkLabel (l_initialized);
787        ec.Emit (OpCodes.Ldsfld, mg_cache.Spec);
788      }
789    }
790  }
791 
792  //
793  // A delegate-creation-expression, invoked from the `New' class
794  //
795  public class NewDelegate : DelegateCreation
796  {
797    public Arguments Arguments;
798
799    //
800    // This constructor is invoked from the `New' expression
801    //
802    public NewDelegate (TypeSpec type, Arguments Arguments, Location loc)
803    {
804      this.type = type;
805      this.Arguments = Arguments;
806      this.loc  = loc;
807    }
808
809    protected override Expression DoResolve (ResolveContext ec)
810    {
811      if (Arguments == null || Arguments.Count != 1) {
812        ec.Report.Error (149, loc, "Method name expected");
813        return null;
814      }
815
816      Argument a = Arguments [0];
817      if (!a.ResolveMethodGroup (ec))
818        return null;
819
820      Expression e = a.Expr;
821
822      AnonymousMethodExpression ame = e as AnonymousMethodExpression;
823      if (ame != null && ec.Module.Compiler.Settings.Version != LanguageVersion.ISO_1) {
824        e = ame.Compatible (ec, type);
825        if (e == null)
826          return null;
827
828        return e.Resolve (ec);
829      }
830
831      method_group = e as MethodGroupExpr;
832      if (method_group == null) {
833        if (e.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
834          e = Convert.ImplicitConversionRequired (ec, e, type, loc);
835        } else if (!e.Type.IsDelegate) {
836          e.Error_UnexpectedKind (ec, ResolveFlags.MethodGroup | ResolveFlags.Type, loc);
837          return null;
838        }
839
840        //
841        // An argument is not a method but another delegate
842        //
843        method_group = new MethodGroupExpr (Delegate.GetInvokeMethod (e.Type), e.Type, loc);
844        method_group.InstanceExpression = e;
845      }
846
847      return base.DoResolve (ec);
848    }
849  }
850
851  //
852  // Invocation converted to delegate Invoke call
853  //
854  class DelegateInvocation : ExpressionStatement
855  {
856    readonly Expression InstanceExpr;
857    readonly bool conditionalAccessReceiver;
858    Arguments arguments;
859    MethodSpec method;
860   
861    public DelegateInvocation (Expression instance_expr, Arguments args, bool conditionalAccessReceiver, Location loc)
862    {
863      this.InstanceExpr = instance_expr;
864      this.arguments = args;
865      this.conditionalAccessReceiver = conditionalAccessReceiver;
866      this.loc = loc;
867    }
868
869    public override bool ContainsEmitWithAwait ()
870    {
871      return InstanceExpr.ContainsEmitWithAwait () || (arguments != null && arguments.ContainsEmitWithAwait ());
872    }
873   
874    public override Expression CreateExpressionTree (ResolveContext ec)
875    {
876      Arguments args = Arguments.CreateForExpressionTree (ec, this.arguments,
877        InstanceExpr.CreateExpressionTree (ec));
878
879      return CreateExpressionFactoryCall (ec, "Invoke", args);
880    }
881
882    public override void FlowAnalysis (FlowAnalysisContext fc)
883    {
884      InstanceExpr.FlowAnalysis (fc);
885      if (arguments != null)
886        arguments.FlowAnalysis (fc);
887    }
888
889    protected override Expression DoResolve (ResolveContext ec)
890    {   
891      TypeSpec del_type = InstanceExpr.Type;
892      if (del_type == null)
893        return null;
894
895      //
896      // Do only core overload resolution the rest of the checks has been
897      // done on primary expression
898      //
899      method = Delegate.GetInvokeMethod (del_type);
900      var res = new OverloadResolver (new MemberSpec[] { method }, OverloadResolver.Restrictions.DelegateInvoke, loc);
901      var valid = res.ResolveMember<MethodSpec> (ec, ref arguments);
902      if (valid == null && !res.BestCandidateIsDynamic)
903        return null;
904
905      type = method.ReturnType;
906      if (conditionalAccessReceiver)
907        type = LiftMemberType (ec, type);
908
909      eclass = ExprClass.Value;
910      return this;
911    }
912
913    public override void Emit (EmitContext ec)
914    {
915      if (conditionalAccessReceiver) {
916        ec.ConditionalAccess = new ConditionalAccessContext (type, ec.DefineLabel ());
917      }
918
919      //
920      // Invocation on delegates call the virtual Invoke member
921      // so we are always `instance' calls
922      //
923      var call = new CallEmitter ();
924      call.InstanceExpression = InstanceExpr;
925      call.Emit (ec, method, arguments, loc);
926
927      if (conditionalAccessReceiver)
928        ec.CloseConditionalAccess (type.IsNullableType && type !=  method.ReturnType ? type : null);
929    }
930
931    public override void EmitStatement (EmitContext ec)
932    {
933      if (conditionalAccessReceiver) {
934        ec.ConditionalAccess = new ConditionalAccessContext (type, ec.DefineLabel ()) {
935          Statement = true
936        };
937      }
938
939      var call = new CallEmitter ();
940      call.InstanceExpression = InstanceExpr;
941      call.EmitStatement (ec, method, arguments, loc);
942
943      if (conditionalAccessReceiver)
944        ec.CloseConditionalAccess (null);
945    }
946
947    public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx)
948    {
949      return Invocation.MakeExpression (ctx, InstanceExpr, method, arguments);
950    }
951  }
952}
Note: See TracBrowser for help on using the repository browser.