Merge branch 'master' of github.com:mono/mono
[mono.git] / mcs / mcs / delegate.cs
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 //
14
15 using System;
16 using System.Reflection;
17 using System.Reflection.Emit;
18 using System.Collections.Generic;
19
20 namespace Mono.CSharp {
21
22         //
23         // Delegate container implementation
24         //
25         public class Delegate : TypeContainer
26         {
27                 FullNamedExpression ReturnType;
28                 public readonly ParametersCompiled Parameters;
29
30                 Constructor Constructor;
31                 Method InvokeBuilder;
32                 Method BeginInvokeBuilder;
33                 Method EndInvokeBuilder;
34
35                 static readonly string[] attribute_targets = new string [] { "type", "return" };
36
37                 public static readonly string InvokeMethodName = "Invoke";
38                 
39                 Expression instance_expr;
40                 ReturnParameter return_attributes;
41
42                 const Modifiers MethodModifiers = Modifiers.PUBLIC | Modifiers.VIRTUAL;
43
44                 const Modifiers AllowedModifiers =
45                         Modifiers.NEW |
46                         Modifiers.PUBLIC |
47                         Modifiers.PROTECTED |
48                         Modifiers.INTERNAL |
49                         Modifiers.UNSAFE |
50                         Modifiers.PRIVATE;
51
52                 public Delegate (NamespaceEntry ns, DeclSpace parent, FullNamedExpression type,
53                                  Modifiers mod_flags, MemberName name, ParametersCompiled param_list,
54                                  Attributes attrs)
55                         : base (ns, parent, name, attrs, MemberKind.Delegate)
56
57                 {
58                         this.ReturnType = type;
59                         ModFlags        = ModifiersExtensions.Check (AllowedModifiers, mod_flags,
60                                                            IsTopLevel ? Modifiers.INTERNAL :
61                                                            Modifiers.PRIVATE, name.Location, Report);
62                         Parameters      = param_list;
63                         spec = new TypeSpec (Kind, null, this, null, ModFlags | Modifiers.SEALED);
64                 }
65
66                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
67                 {
68                         if (a.Target == AttributeTargets.ReturnValue) {
69                                 if (return_attributes == null)
70                                         return_attributes = new ReturnParameter (this, InvokeBuilder.MethodBuilder, Location);
71
72                                 return_attributes.ApplyAttributeBuilder (a, ctor, cdata, pa);
73                                 return;
74                         }
75
76                         base.ApplyAttributeBuilder (a, ctor, cdata, pa);
77                 }
78
79                 public override AttributeTargets AttributeTargets {
80                         get {
81                                 return AttributeTargets.Delegate;
82                         }
83                 }
84
85                 protected override bool DoDefineMembers ()
86                 {
87                         var ctor_parameters = ParametersCompiled.CreateFullyResolved (
88                                 new [] {
89                                         new Parameter (new TypeExpression (TypeManager.object_type, Location), "object", Parameter.Modifier.NONE, null, Location),
90                                         new Parameter (new TypeExpression (TypeManager.intptr_type, Location), "method", Parameter.Modifier.NONE, null, Location)
91                                 },
92                                 new [] {
93                                         TypeManager.object_type,
94                                         TypeManager.intptr_type
95                                 }
96                         );
97
98                         Constructor = new Constructor (this, System.Reflection.ConstructorInfo.ConstructorName,
99                                 Modifiers.PUBLIC, null, ctor_parameters, null, Location);
100                         Constructor.Define ();
101
102                         //
103                         // Here the various methods like Invoke, BeginInvoke etc are defined
104                         //
105                         // First, call the `out of band' special method for
106                         // defining recursively any types we need:
107                         //
108                         var p = Parameters;
109
110                         if (!p.Resolve (this))
111                                 return false;
112
113                         //
114                         // Invoke method
115                         //
116
117                         // Check accessibility
118                         foreach (var partype in p.Types) {
119                                 if (!IsAccessibleAs (partype)) {
120                                         Report.SymbolRelatedToPreviousError (partype);
121                                         Report.Error (59, Location,
122                                                 "Inconsistent accessibility: parameter type `{0}' is less accessible than delegate `{1}'",
123                                                 TypeManager.CSharpName (partype), GetSignatureForError ());
124                                 }
125                         }
126
127                         ReturnType = ReturnType.ResolveAsTypeTerminal (this, false);
128                         if (ReturnType == null)
129                                 return false;
130
131                         var ret_type = ReturnType.Type;
132
133                         //
134                         // We don't have to check any others because they are all
135                         // guaranteed to be accessible - they are standard types.
136                         //
137                         if (!IsAccessibleAs (ret_type)) {
138                                 Report.SymbolRelatedToPreviousError (ret_type);
139                                 Report.Error (58, Location,
140                                                   "Inconsistent accessibility: return type `" +
141                                                   TypeManager.CSharpName (ret_type) + "' is less " +
142                                                   "accessible than delegate `" + GetSignatureForError () + "'");
143                                 return false;
144                         }
145
146                         CheckProtectedModifier ();
147
148                         if (RootContext.StdLib && TypeManager.IsSpecialType (ret_type)) {
149                                 Method.Error1599 (Location, ret_type, Report);
150                                 return false;
151                         }
152
153                         TypeManager.CheckTypeVariance (ret_type, Variance.Covariant, this);
154
155                         InvokeBuilder = new Method (this, null, ReturnType, MethodModifiers, new MemberName (InvokeMethodName), p, null);
156                         InvokeBuilder.Define ();
157
158                         //
159                         // Don't emit async method for compiler generated delegates (e.g. dynamic site containers)
160                         //
161                         if (TypeManager.iasyncresult_type != null && TypeManager.asynccallback_type != null && !IsCompilerGenerated) {
162                                 DefineAsyncMethods (Parameters.CallingConvention);
163                         }
164
165                         return true;
166                 }
167
168                 void DefineAsyncMethods (CallingConventions cc)
169                 {
170                         //
171                         // BeginInvoke
172                         //
173                         ParametersCompiled async_parameters;
174                         if (Parameters.Count == 0) {
175                                 async_parameters = ParametersCompiled.EmptyReadOnlyParameters;
176                         } else {
177                                 var compiled = new Parameter[Parameters.Count];
178                                 for (int i = 0; i < compiled.Length; ++i)
179                                         compiled[i] = new Parameter (new TypeExpression (Parameters.Types[i], Location),
180                                                 Parameters.FixedParameters[i].Name,
181                                                 Parameters.FixedParameters[i].ModFlags & (Parameter.Modifier.REF | Parameter.Modifier.OUT),
182                                                 null, Location);
183
184                                 async_parameters = new ParametersCompiled (compiled);
185                         }
186
187                         async_parameters = ParametersCompiled.MergeGenerated (Compiler, async_parameters, false,
188                                 new Parameter[] {
189                                         new Parameter (new TypeExpression (TypeManager.asynccallback_type, Location), "callback", Parameter.Modifier.NONE, null, Location),
190                                         new Parameter (new TypeExpression (TypeManager.object_type, Location), "object", Parameter.Modifier.NONE, null, Location)
191                                 },
192                                 new [] {
193                                         TypeManager.asynccallback_type,
194                                         TypeManager.object_type
195                                 }
196                         );
197
198                         BeginInvokeBuilder = new Method (this, null,
199                                 new TypeExpression (TypeManager.iasyncresult_type, Location), MethodModifiers,
200                                 new MemberName ("BeginInvoke"), async_parameters, null);
201                         BeginInvokeBuilder.Define ();
202
203                         //
204                         // EndInvoke is a bit more interesting, all the parameters labeled as
205                         // out or ref have to be duplicated here.
206                         //
207
208                         //
209                         // Define parameters, and count out/ref parameters
210                         //
211                         ParametersCompiled end_parameters;
212                         int out_params = 0;
213
214                         foreach (Parameter p in Parameters.FixedParameters) {
215                                 if ((p.ModFlags & Parameter.Modifier.ISBYREF) != 0)
216                                         ++out_params;
217                         }
218
219                         if (out_params > 0) {
220                                 var end_param_types = new TypeSpec [out_params];
221                                 Parameter[] end_params = new Parameter[out_params];
222
223                                 int param = 0;
224                                 for (int i = 0; i < Parameters.FixedParameters.Length; ++i) {
225                                         Parameter p = Parameters [i];
226                                         if ((p.ModFlags & Parameter.Modifier.ISBYREF) == 0)
227                                                 continue;
228
229                                         end_param_types[param] = Parameters.Types[i];
230                                         end_params[param] = p;
231                                         ++param;
232                                 }
233                                 end_parameters = ParametersCompiled.CreateFullyResolved (end_params, end_param_types);
234                         } else {
235                                 end_parameters = ParametersCompiled.EmptyReadOnlyParameters;
236                         }
237
238                         end_parameters = ParametersCompiled.MergeGenerated (Compiler, end_parameters, false,
239                                 new Parameter (
240                                         new TypeExpression (TypeManager.iasyncresult_type, Location),
241                                         "result", Parameter.Modifier.NONE, null, Location),
242                                 TypeManager.iasyncresult_type);
243
244                         //
245                         // Create method, define parameters, register parameters with type system
246                         //
247                         EndInvokeBuilder = new Method (this, null, ReturnType, MethodModifiers, new MemberName ("EndInvoke"), end_parameters, null);
248                         EndInvokeBuilder.Define ();
249                 }
250
251                 public override void DefineConstants ()
252                 {
253                         if (!Parameters.IsEmpty) {
254                                 Parameters.ResolveDefaultValues (this);
255                         }
256                 }
257
258                 public override void EmitType ()
259                 {
260                         if (ReturnType.Type == InternalType.Dynamic) {
261                                 return_attributes = new ReturnParameter (this, InvokeBuilder.MethodBuilder, Location);
262                                 Compiler.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder);
263                         } else {
264                                 var trans_flags = TypeManager.HasDynamicTypeUsed (ReturnType.Type);
265                                 if (trans_flags != null) {
266                                         var pa = Compiler.PredefinedAttributes.DynamicTransform;
267                                         if (pa.Constructor != null || pa.ResolveConstructor (Location, ArrayContainer.MakeType (TypeManager.bool_type))) {
268                                                 return_attributes = new ReturnParameter (this, InvokeBuilder.MethodBuilder, Location);
269                                                 return_attributes.Builder.SetCustomAttribute (
270                                                         new CustomAttributeBuilder (pa.Constructor, new object [] { trans_flags }));
271                                         }
272                                 }
273                         }
274
275                         Parameters.ApplyAttributes (this, InvokeBuilder.MethodBuilder);
276                         
277                         Constructor.ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
278                         InvokeBuilder.MethodBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
279
280                         if (BeginInvokeBuilder != null) {
281                                 BeginInvokeBuilder.ParameterInfo.ApplyAttributes (this, BeginInvokeBuilder.MethodBuilder);
282
283                                 BeginInvokeBuilder.MethodBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
284                                 EndInvokeBuilder.MethodBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
285                         }
286
287                         if (OptAttributes != null) {
288                                 OptAttributes.Emit ();
289                         }
290
291                         base.Emit ();
292                 }
293
294                 protected override TypeExpr[] ResolveBaseTypes (out TypeExpr base_class)
295                 {
296                         base_type = TypeManager.multicast_delegate_type;
297                         base_class = null;
298                         return null;
299                 }
300
301                 protected override TypeAttributes TypeAttr {
302                         get {
303                                 return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel) |
304                                         TypeAttributes.Class | TypeAttributes.Sealed |
305                                         base.TypeAttr;
306                         }
307                 }
308
309                 public override string[] ValidAttributeTargets {
310                         get {
311                                 return attribute_targets;
312                         }
313                 }
314
315                 //TODO: duplicate
316                 protected override bool VerifyClsCompliance ()
317                 {
318                         if (!base.VerifyClsCompliance ()) {
319                                 return false;
320                         }
321
322                         Parameters.VerifyClsCompliance (this);
323
324                         if (!ReturnType.Type.IsCLSCompliant ()) {
325                                 Report.Warning (3002, 1, Location, "Return type of `{0}' is not CLS-compliant",
326                                         GetSignatureForError ());
327                         }
328                         return true;
329                 }
330
331
332                 public static MethodSpec GetConstructor (CompilerContext ctx, TypeSpec container_type, TypeSpec delType)
333                 {
334                         var ctor = MemberCache.FindMember (delType, MemberFilter.Constructor (null), BindingRestriction.DeclaredOnly);
335                         return (MethodSpec) ctor;
336                 }
337
338                 //
339                 // Returns the "Invoke" from a delegate type
340                 //
341                 public static MethodSpec GetInvokeMethod (CompilerContext ctx, TypeSpec delType)
342                 {
343                         var invoke = MemberCache.FindMember (delType,
344                                 MemberFilter.Method (InvokeMethodName, 0, null, null),
345                                 BindingRestriction.DeclaredOnly);
346
347                         return (MethodSpec) invoke;
348                 }
349
350                 public static AParametersCollection GetParameters (CompilerContext ctx, TypeSpec delType)
351                 {
352                         var invoke_mb = GetInvokeMethod (ctx, delType);
353                         return invoke_mb.Parameters;
354                 }
355
356                 //
357                 // 15.2 Delegate compatibility
358                 //
359                 public static bool IsTypeCovariant (Expression a, TypeSpec b)
360                 {
361                         //
362                         // For each value parameter (a parameter with no ref or out modifier), an 
363                         // identity conversion or implicit reference conversion exists from the
364                         // parameter type in D to the corresponding parameter type in M
365                         //
366                         if (a.Type == b)
367                                 return true;
368
369                         if (RootContext.Version == LanguageVersion.ISO_1)
370                                 return false;
371
372                         return Convert.ImplicitReferenceConversionExists (a, b);
373                 }
374
375                 public static string FullDelegateDesc (MethodSpec invoke_method)
376                 {
377                         return TypeManager.GetFullNameSignature (invoke_method).Replace (".Invoke", "");
378                 }
379                 
380                 public Expression InstanceExpression {
381                         get {
382                                 return instance_expr;
383                         }
384                         set {
385                                 instance_expr = value;
386                         }
387                 }
388         }
389
390         //
391         // Base class for `NewDelegate' and `ImplicitDelegateCreation'
392         //
393         public abstract class DelegateCreation : Expression, OverloadResolver.IErrorHandler
394         {
395                 protected MethodSpec constructor_method;
396                 protected MethodGroupExpr method_group;
397
398                 public static Arguments CreateDelegateMethodArguments (AParametersCollection pd, TypeSpec[] types, Location loc)
399                 {
400                         Arguments delegate_arguments = new Arguments (pd.Count);
401                         for (int i = 0; i < pd.Count; ++i) {
402                                 Argument.AType atype_modifier;
403                                 switch (pd.FixedParameters [i].ModFlags) {
404                                 case Parameter.Modifier.REF:
405                                         atype_modifier = Argument.AType.Ref;
406                                         break;
407                                 case Parameter.Modifier.OUT:
408                                         atype_modifier = Argument.AType.Out;
409                                         break;
410                                 default:
411                                         atype_modifier = 0;
412                                         break;
413                                 }
414
415                                 delegate_arguments.Add (new Argument (new TypeExpression (types [i], loc), atype_modifier));
416                         }
417
418                         return delegate_arguments;
419                 }
420
421                 public override Expression CreateExpressionTree (ResolveContext ec)
422                 {
423                         MemberAccess ma = new MemberAccess (new MemberAccess (new QualifiedAliasMember ("global", "System", loc), "Delegate", loc), "CreateDelegate", loc);
424
425                         Arguments args = new Arguments (3);
426                         args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
427                         args.Add (new Argument (new NullLiteral (loc)));
428                         args.Add (new Argument (method_group.CreateExpressionTree (ec)));
429                         Expression e = new Invocation (ma, args).Resolve (ec);
430                         if (e == null)
431                                 return null;
432
433                         e = Convert.ExplicitConversion (ec, e, type, loc);
434                         if (e == null)
435                                 return null;
436
437                         return e.CreateExpressionTree (ec);
438                 }
439
440                 protected override Expression DoResolve (ResolveContext ec)
441                 {
442                         constructor_method = Delegate.GetConstructor (ec.Compiler, ec.CurrentType, type);
443
444                         var invoke_method = Delegate.GetInvokeMethod (ec.Compiler, type);
445
446                         Arguments arguments = CreateDelegateMethodArguments (invoke_method.Parameters, invoke_method.Parameters.Types, loc);
447                         method_group = method_group.OverloadResolve (ec, ref arguments, this, OverloadResolver.Restrictions.CovariantDelegate);
448                         if (method_group == null)
449                                 return null;
450
451                         var delegate_method = method_group.BestCandidate;
452                         
453                         if (TypeManager.IsNullableType (delegate_method.DeclaringType)) {
454                                 ec.Report.Error (1728, loc, "Cannot create delegate from method `{0}' because it is a member of System.Nullable<T> type",
455                                         delegate_method.GetSignatureForError ());
456                                 return null;
457                         }               
458                         
459                         Invocation.IsSpecialMethodInvocation (ec, delegate_method, loc);
460
461                         ExtensionMethodGroupExpr emg = method_group as ExtensionMethodGroupExpr;
462                         if (emg != null) {
463                                 method_group.InstanceExpression = emg.ExtensionExpression;
464                                 TypeSpec e_type = emg.ExtensionExpression.Type;
465                                 if (TypeManager.IsValueType (e_type)) {
466                                         ec.Report.Error (1113, loc, "Extension method `{0}' of value type `{1}' cannot be used to create delegates",
467                                                 delegate_method.GetSignatureForError (), TypeManager.CSharpName (e_type));
468                                 }
469                         }
470
471                         TypeSpec rt = delegate_method.ReturnType;
472                         Expression ret_expr = new TypeExpression (rt, loc);
473                         if (!Delegate.IsTypeCovariant (ret_expr, invoke_method.ReturnType)) {
474                                 Error_ConversionFailed (ec, delegate_method, ret_expr);
475                         }
476
477                         if (delegate_method.IsConditionallyExcluded (loc)) {
478                                 ec.Report.SymbolRelatedToPreviousError (delegate_method);
479                                 MethodOrOperator m = delegate_method.MemberDefinition as MethodOrOperator;
480                                 if (m != null && m.IsPartialDefinition) {
481                                         ec.Report.Error (762, loc, "Cannot create delegate from partial method declaration `{0}'",
482                                                 delegate_method.GetSignatureForError ());
483                                 } else {
484                                         ec.Report.Error (1618, loc, "Cannot create delegate with `{0}' because it has a Conditional attribute",
485                                                 TypeManager.CSharpSignature (delegate_method));
486                                 }
487                         }
488
489                         var expr = method_group.InstanceExpression;
490                         if (expr != null && (expr.Type.IsGenericParameter || !TypeManager.IsReferenceType (expr.Type)))
491                                 method_group.InstanceExpression = new BoxedCast (expr, TypeManager.object_type);
492
493                         eclass = ExprClass.Value;
494                         return this;
495                 }
496                 
497                 public override void Emit (EmitContext ec)
498                 {
499                         if (method_group.InstanceExpression == null)
500                                 ec.Emit (OpCodes.Ldnull);
501                         else
502                                 method_group.InstanceExpression.Emit (ec);
503
504                         var delegate_method = method_group.BestCandidate;
505
506                         // Any delegate must be sealed
507                         if (!delegate_method.DeclaringType.IsDelegate && delegate_method.IsVirtual && !method_group.IsBase) {
508                                 ec.Emit (OpCodes.Dup);
509                                 ec.Emit (OpCodes.Ldvirtftn, delegate_method);
510                         } else {
511                                 ec.Emit (OpCodes.Ldftn, delegate_method);
512                         }
513
514                         ec.Emit (OpCodes.Newobj, constructor_method);
515                 }
516
517                 void Error_ConversionFailed (ResolveContext ec, MethodSpec method, Expression return_type)
518                 {
519                         var invoke_method = Delegate.GetInvokeMethod (ec.Compiler, type);
520                         string member_name = method_group.InstanceExpression != null ?
521                                 Delegate.FullDelegateDesc (method) :
522                                 TypeManager.GetFullNameSignature (method);
523
524                         ec.Report.SymbolRelatedToPreviousError (type);
525                         ec.Report.SymbolRelatedToPreviousError (method);
526                         if (RootContext.Version == LanguageVersion.ISO_1) {
527                                 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",
528                                         TypeManager.CSharpName (method.ReturnType), member_name,
529                                         TypeManager.CSharpName (invoke_method.ReturnType), Delegate.FullDelegateDesc (invoke_method));
530                                 return;
531                         }
532
533                         if (return_type == null) {
534                                 ec.Report.Error (123, loc, "A method or delegate `{0}' parameters do not match delegate `{1}' parameters",
535                                         member_name, Delegate.FullDelegateDesc (invoke_method));
536                                 return;
537                         }
538
539                         ec.Report.Error (407, loc, "A method or delegate `{0} {1}' return type does not match delegate `{2} {3}' return type",
540                                 return_type.GetSignatureForError (), member_name,
541                                 TypeManager.CSharpName (invoke_method.ReturnType), Delegate.FullDelegateDesc (invoke_method));
542                 }
543
544                 public static bool ImplicitStandardConversionExists (ResolveContext ec, MethodGroupExpr mg, TypeSpec target_type)
545                 {
546                         if (target_type == TypeManager.delegate_type || target_type == TypeManager.multicast_delegate_type)
547                                 return false;
548
549                         var invoke = Delegate.GetInvokeMethod (ec.Compiler, target_type);
550
551                         Arguments arguments = CreateDelegateMethodArguments (invoke.Parameters, invoke.Parameters.Types, mg.Location);
552                         return mg.OverloadResolve (ec, ref arguments, null, OverloadResolver.Restrictions.CovariantDelegate | OverloadResolver.Restrictions.ProbingOnly) != null;
553                 }
554
555                 #region IErrorHandler Members
556
557                 bool OverloadResolver.IErrorHandler.AmbiguousCandidates (ResolveContext ec, MemberSpec best, MemberSpec ambiguous)
558                 {
559                         return false;
560                 }
561
562                 bool OverloadResolver.IErrorHandler.ArgumentMismatch (ResolveContext rc, MemberSpec best, Argument arg, int index)
563                 {
564                         Error_ConversionFailed (rc, best as MethodSpec, null);
565                         return true;
566                 }
567
568                 bool OverloadResolver.IErrorHandler.NoArgumentMatch (ResolveContext rc, MemberSpec best)
569                 {
570                         Error_ConversionFailed (rc, best as MethodSpec, null);
571                         return true;
572                 }
573
574                 bool OverloadResolver.IErrorHandler.TypeInferenceFailed (ResolveContext rc, MemberSpec best)
575                 {
576                         return false;
577                 }
578
579                 #endregion
580         }
581
582         //
583         // Created from the conversion code
584         //
585         public class ImplicitDelegateCreation : DelegateCreation
586         {
587                 ImplicitDelegateCreation (TypeSpec t, MethodGroupExpr mg, Location l)
588                 {
589                         type = t;
590                         this.method_group = mg;
591                         loc = l;
592                 }
593
594                 static public Expression Create (ResolveContext ec, MethodGroupExpr mge,
595                                                  TypeSpec target_type, Location loc)
596                 {
597                         ImplicitDelegateCreation d = new ImplicitDelegateCreation (target_type, mge, loc);
598                         return d.DoResolve (ec);
599                 }
600         }
601         
602         //
603         // A delegate-creation-expression, invoked from the `New' class 
604         //
605         public class NewDelegate : DelegateCreation
606         {
607                 public Arguments Arguments;
608
609                 //
610                 // This constructor is invoked from the `New' expression
611                 //
612                 public NewDelegate (TypeSpec type, Arguments Arguments, Location loc)
613                 {
614                         this.type = type;
615                         this.Arguments = Arguments;
616                         this.loc  = loc; 
617                 }
618
619                 protected override Expression DoResolve (ResolveContext ec)
620                 {
621                         if (Arguments == null || Arguments.Count != 1) {
622                                 ec.Report.Error (149, loc, "Method name expected");
623                                 return null;
624                         }
625
626                         Argument a = Arguments [0];
627                         if (!a.ResolveMethodGroup (ec))
628                                 return null;
629
630                         Expression e = a.Expr;
631
632                         AnonymousMethodExpression ame = e as AnonymousMethodExpression;
633                         if (ame != null && RootContext.Version != LanguageVersion.ISO_1) {
634                                 e = ame.Compatible (ec, type);
635                                 if (e == null)
636                                         return null;
637
638                                 return e.Resolve (ec);
639                         }
640
641                         method_group = e as MethodGroupExpr;
642                         if (method_group == null) {
643                                 if (e.Type == InternalType.Dynamic) {
644                                         e = Convert.ImplicitConversionRequired (ec, e, type, loc);
645                                 } else if (!e.Type.IsDelegate) {
646                                         e.Error_UnexpectedKind (ec, ResolveFlags.MethodGroup | ResolveFlags.Type, loc);
647                                         return null;
648                                 }
649
650                                 //
651                                 // An argument is not a method but another delegate
652                                 //
653                                 method_group = new MethodGroupExpr (Delegate.GetInvokeMethod (ec.Compiler, e.Type), e.Type, loc);
654                                 method_group.InstanceExpression = e;
655                         }
656
657                         return base.DoResolve (ec);
658                 }
659         }
660
661         //
662         // Invocation converted to delegate Invoke call
663         //
664         class DelegateInvocation : ExpressionStatement
665         {
666                 readonly Expression InstanceExpr;
667                 Arguments arguments;
668                 MethodSpec method;
669                 
670                 public DelegateInvocation (Expression instance_expr, Arguments args, Location loc)
671                 {
672                         this.InstanceExpr = instance_expr;
673                         this.arguments = args;
674                         this.loc = loc;
675                 }
676                 
677                 public override Expression CreateExpressionTree (ResolveContext ec)
678                 {
679                         Arguments args = Arguments.CreateForExpressionTree (ec, this.arguments,
680                                 InstanceExpr.CreateExpressionTree (ec));
681
682                         return CreateExpressionFactoryCall (ec, "Invoke", args);
683                 }
684
685                 protected override Expression DoResolve (ResolveContext ec)
686                 {
687                         if (InstanceExpr is EventExpr) {
688                                 ((EventExpr) InstanceExpr).Error_CannotAssign (ec);
689                                 return null;
690                         }
691                         
692                         TypeSpec del_type = InstanceExpr.Type;
693                         if (del_type == null)
694                                 return null;
695
696                         //
697                         // Do only core overload resolution the rest of the checks has been
698                         // done on primary expression
699                         //
700                         method = Delegate.GetInvokeMethod (ec.Compiler, del_type);
701                         var res = new OverloadResolver (new MemberSpec[] { method }, OverloadResolver.Restrictions.DelegateInvoke, loc);
702                         var valid = res.ResolveMember<MethodSpec> (ec, ref arguments);
703                         if (valid == null && !res.BestCandidateIsDynamic)
704                                 return null;
705
706                         type = method.ReturnType;
707                         eclass = ExprClass.Value;
708                         return this;
709                 }
710
711                 public override void Emit (EmitContext ec)
712                 {
713                         //
714                         // Invocation on delegates call the virtual Invoke member
715                         // so we are always `instance' calls
716                         //
717                         Invocation.EmitCall (ec, InstanceExpr, method, arguments, loc);
718                 }
719
720                 public override void EmitStatement (EmitContext ec)
721                 {
722                         Emit (ec);
723                         // 
724                         // Pop the return value if there is one
725                         //
726                         if (type != TypeManager.void_type)
727                                 ec.Emit (OpCodes.Pop);
728                 }
729
730                 public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx)
731                 {
732                         return Invocation.MakeExpression (ctx, InstanceExpr, method, arguments);
733                 }
734         }
735 }