2008-08-08 Marek Safar <marek.safar@gmail.com>
[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-2008 Novell, Inc (http://www.ximian.com)
13 //
14
15 using System;
16 using System.Collections;
17 using System.Reflection;
18 using System.Reflection.Emit;
19 using System.Text;
20
21 namespace Mono.CSharp {
22
23         /// <summary>
24         ///   Holds Delegates
25         /// </summary>
26         public class Delegate : DeclSpace, IMemberContainer
27         {
28                 FullNamedExpression ReturnType;
29                 public Parameters      Parameters;
30
31                 public ConstructorBuilder ConstructorBuilder;
32                 public MethodBuilder      InvokeBuilder;
33                 public MethodBuilder      BeginInvokeBuilder;
34                 public MethodBuilder      EndInvokeBuilder;
35                 
36                 Type ret_type;
37
38                 static string[] attribute_targets = new string [] { "type", "return" };
39                 
40                 Expression instance_expr;
41                 MethodBase delegate_method;
42                 ReturnParameter return_attributes;
43
44                 MemberCache member_cache;
45
46                 const MethodAttributes mattr = MethodAttributes.Public | MethodAttributes.HideBySig |
47                         MethodAttributes.Virtual | MethodAttributes.NewSlot;
48
49                 const int AllowedModifiers =
50                         Modifiers.NEW |
51                         Modifiers.PUBLIC |
52                         Modifiers.PROTECTED |
53                         Modifiers.INTERNAL |
54                         Modifiers.UNSAFE |
55                         Modifiers.PRIVATE;
56
57                 public Delegate (NamespaceEntry ns, DeclSpace parent, FullNamedExpression type,
58                                  int mod_flags, MemberName name, Parameters param_list,
59                                  Attributes attrs)
60                         : base (ns, parent, name, attrs)
61
62                 {
63                         this.ReturnType = type;
64                         ModFlags        = Modifiers.Check (AllowedModifiers, mod_flags,
65                                                            IsTopLevel ? Modifiers.INTERNAL :
66                                                            Modifiers.PRIVATE, name.Location);
67                         Parameters      = param_list;
68                 }
69
70                 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
71                 {
72                         if (a.Target == AttributeTargets.ReturnValue) {
73                                 if (return_attributes == null)
74                                         return_attributes = new ReturnParameter (InvokeBuilder, Location);
75
76                                 return_attributes.ApplyAttributeBuilder (a, cb);
77                                 return;
78                         }
79
80                         base.ApplyAttributeBuilder (a, cb);
81                 }
82
83                 public override TypeBuilder DefineType ()
84                 {
85                         if (TypeBuilder != null)
86                                 return TypeBuilder;
87
88                         if (IsTopLevel) {
89                                 if (TypeManager.NamespaceClash (Name, Location))
90                                         return null;
91                                 
92                                 ModuleBuilder builder = CodeGen.Module.Builder;
93
94                                 TypeBuilder = builder.DefineType (
95                                         Name, TypeAttr, TypeManager.multicast_delegate_type);
96                         } else {
97                                 TypeBuilder builder = Parent.TypeBuilder;
98
99                                 string name = Name.Substring (1 + Name.LastIndexOf ('.'));
100                                 TypeBuilder = builder.DefineNestedType (
101                                         name, TypeAttr, TypeManager.multicast_delegate_type);
102                         }
103
104                         TypeManager.AddUserType (this);
105
106 #if GMCS_SOURCE
107                         if (IsGeneric) {
108                                 string[] param_names = new string [TypeParameters.Length];
109                                 for (int i = 0; i < TypeParameters.Length; i++)
110                                         param_names [i] = TypeParameters [i].Name;
111
112                                 GenericTypeParameterBuilder[] gen_params;
113                                 gen_params = TypeBuilder.DefineGenericParameters (param_names);
114
115                                 int offset = CountTypeParameters - CurrentTypeParameters.Length;
116                                 for (int i = offset; i < gen_params.Length; i++)
117                                         CurrentTypeParameters [i - offset].Define (gen_params [i]);
118
119                                 foreach (TypeParameter type_param in CurrentTypeParameters) {
120                                         if (!type_param.Resolve (this))
121                                                 return null;
122                                 }
123
124                                 Expression current = new SimpleName (
125                                         MemberName.Basename, TypeParameters, Location);
126                                 current = current.ResolveAsTypeTerminal (this, false);
127                                 if (current == null)
128                                         return null;
129
130                                 CurrentType = current.Type;
131                         }
132 #endif
133
134                         return TypeBuilder;
135                 }
136
137                 public override bool Define ()
138                 {
139 #if GMCS_SOURCE
140                         if (IsGeneric) {
141                                 foreach (TypeParameter type_param in TypeParameters) {
142                                         if (!type_param.Resolve (this))
143                                                 return false;
144                                 }
145
146                                 foreach (TypeParameter type_param in TypeParameters) {
147                                         if (!type_param.DefineType (this))
148                                                 return false;
149                                 }
150
151                                 foreach (TypeParameter type_param in TypeParameters) {
152                                         if (!type_param.CheckDependencies ())
153                                                 return false;
154                                 }
155                         }
156 #endif
157                         member_cache = new MemberCache (TypeManager.multicast_delegate_type, this);
158
159                         // FIXME: POSSIBLY make this static, as it is always constant
160                         //
161                         Type [] const_arg_types = new Type [2];
162                         const_arg_types [0] = TypeManager.object_type;
163                         const_arg_types [1] = TypeManager.intptr_type;
164
165                         const MethodAttributes ctor_mattr = MethodAttributes.RTSpecialName | MethodAttributes.SpecialName |
166                                 MethodAttributes.HideBySig | MethodAttributes.Public;
167
168                         ConstructorBuilder = TypeBuilder.DefineConstructor (ctor_mattr,
169                                                                             CallingConventions.Standard,
170                                                                             const_arg_types);
171
172                         ConstructorBuilder.DefineParameter (1, ParameterAttributes.None, "object");
173                         ConstructorBuilder.DefineParameter (2, ParameterAttributes.None, "method");
174                         //
175                         // HACK because System.Reflection.Emit is lame
176                         //
177                         Parameter [] fixed_pars = new Parameter [2];
178                         fixed_pars [0] = new Parameter (TypeManager.object_type, "object",
179                                                         Parameter.Modifier.NONE, null, Location);
180                         fixed_pars [1] = new Parameter (TypeManager.intptr_type, "method", 
181                                                         Parameter.Modifier.NONE, null, Location);
182                         Parameters const_parameters = new Parameters (fixed_pars);
183                         const_parameters.Resolve (null);
184                         
185                         TypeManager.RegisterMethod (ConstructorBuilder, const_parameters);
186                         member_cache.AddMember (ConstructorBuilder, this);
187                         
188                         ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
189
190                         //
191                         // Here the various methods like Invoke, BeginInvoke etc are defined
192                         //
193                         // First, call the `out of band' special method for
194                         // defining recursively any types we need:
195                         
196                         if (!Parameters.Resolve (this))
197                                 return false;
198
199                         //
200                         // Invoke method
201                         //
202
203                         // Check accessibility
204                         foreach (Type partype in Parameters.Types){
205                                 if (!IsAccessibleAs (partype)) {
206                                         Report.SymbolRelatedToPreviousError (partype);
207                                         Report.Error (59, Location,
208                                                       "Inconsistent accessibility: parameter type `" +
209                                                       TypeManager.CSharpName (partype) + "' is less " +
210                                                           "accessible than delegate `" + GetSignatureForError () + "'");
211                                         return false;
212                                 }
213                         }
214                         
215                         ReturnType = ReturnType.ResolveAsTypeTerminal (this, false);
216                         if (ReturnType == null)
217                                 return false;
218
219                         ret_type = ReturnType.Type;
220             
221                         if (!IsAccessibleAs (ret_type)) {
222                                 Report.SymbolRelatedToPreviousError (ret_type);
223                                 Report.Error (58, Location,
224                                               "Inconsistent accessibility: return type `" +
225                                               TypeManager.CSharpName (ret_type) + "' is less " +
226                                               "accessible than delegate `" + GetSignatureForError () + "'");
227                                 return false;
228                         }
229
230                         CheckProtectedModifier ();
231
232                         if (RootContext.StdLib && (ret_type == TypeManager.arg_iterator_type || ret_type == TypeManager.typed_reference_type)) {
233                                 Method.Error1599 (Location, ret_type);
234                                 return false;
235                         }
236
237                         //
238                         // We don't have to check any others because they are all
239                         // guaranteed to be accessible - they are standard types.
240                         //
241                         
242                         CallingConventions cc = Parameters.CallingConvention;
243
244                         InvokeBuilder = TypeBuilder.DefineMethod ("Invoke", 
245                                                                   mattr,                     
246                                                                   cc,
247                                                                   ret_type,                  
248                                                                   Parameters.Types);
249                         
250                         InvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
251
252                         TypeManager.RegisterMethod (InvokeBuilder, Parameters);
253                         member_cache.AddMember (InvokeBuilder, this);
254
255                         if (TypeManager.iasyncresult_type != null && TypeManager.asynccallback_type != null) {
256                                 DefineAsyncMethods (cc);
257                         }
258
259                         return true;
260                 }
261
262                 void DefineAsyncMethods (CallingConventions cc)
263                 {
264                         //
265                         // BeginInvoke
266                         //
267                         Parameters async_parameters = Parameters.MergeGenerated (Parameters,
268                                 new Parameter (TypeManager.asynccallback_type, "callback", Parameter.Modifier.NONE, null, Location),
269                                 new Parameter (TypeManager.object_type, "object", Parameter.Modifier.NONE, null, Location));
270
271                         BeginInvokeBuilder = TypeBuilder.DefineMethod ("BeginInvoke",
272                                 mattr, cc, TypeManager.iasyncresult_type, async_parameters.Types);
273
274                         BeginInvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
275                         TypeManager.RegisterMethod (BeginInvokeBuilder, async_parameters);
276                         member_cache.AddMember (BeginInvokeBuilder, this);
277
278                         //
279                         // EndInvoke is a bit more interesting, all the parameters labeled as
280                         // out or ref have to be duplicated here.
281                         //
282
283                         //
284                         // Define parameters, and count out/ref parameters
285                         //
286                         Parameters end_parameters;
287                         int out_params = 0;
288
289                         foreach (Parameter p in Parameters.FixedParameters) {
290                                 if ((p.ModFlags & Parameter.Modifier.ISBYREF) != 0)
291                                         ++out_params;
292                         }
293
294                         if (out_params > 0) {
295                                 Type [] end_param_types = new Type [out_params];
296                                 Parameter [] end_params = new Parameter [out_params];
297
298                                 int param = 0;
299                                 for (int i = 0; i < Parameters.FixedParameters.Length; ++i) {
300                                         Parameter p = Parameters.FixedParameters [i];
301                                         if ((p.ModFlags & Parameter.Modifier.ISBYREF) == 0)
302                                                 continue;
303
304                                         end_param_types [param] = p.ExternalType ();
305                                         end_params [param] = p;
306                                         ++param;
307                                 }
308                                 end_parameters = Parameters.CreateFullyResolved (end_params, end_param_types);
309                         } else {
310                                 end_parameters = Parameters.EmptyReadOnlyParameters;
311                         }
312
313                         end_parameters = Parameters.MergeGenerated (end_parameters,
314                                 new Parameter (TypeManager.iasyncresult_type, "result", Parameter.Modifier.NONE, null, Location));
315
316                         //
317                         // Create method, define parameters, register parameters with type system
318                         //
319                         EndInvokeBuilder = TypeBuilder.DefineMethod ("EndInvoke", mattr, cc, ret_type, end_parameters.Types);
320                         EndInvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
321
322                         end_parameters.ApplyAttributes (EndInvokeBuilder);
323                         TypeManager.RegisterMethod (EndInvokeBuilder, end_parameters);
324                         member_cache.AddMember (EndInvokeBuilder, this);
325                 }
326
327                 public override void Emit ()
328                 {
329                         Parameters.ApplyAttributes (InvokeBuilder);
330
331                         if (BeginInvokeBuilder != null) {
332                                 Parameters p = (Parameters) TypeManager.GetParameterData (BeginInvokeBuilder);
333                                 p.ApplyAttributes (BeginInvokeBuilder);
334                         }
335
336                         if (OptAttributes != null) {
337                                 OptAttributes.Emit ();
338                         }
339
340                         base.Emit ();
341                 }
342
343                 protected override TypeAttributes TypeAttr {
344                         get {
345                                 return Modifiers.TypeAttr (ModFlags, IsTopLevel) |
346                                         TypeAttributes.Class | TypeAttributes.Sealed |
347                                         base.TypeAttr;
348                         }
349                 }
350
351                 public override string[] ValidAttributeTargets {
352                         get {
353                                 return attribute_targets;
354                         }
355                 }
356
357                 //TODO: duplicate
358                 protected override bool VerifyClsCompliance ()
359                 {
360                         if (!base.VerifyClsCompliance ()) {
361                                 return false;
362                         }
363
364                         Parameters.VerifyClsCompliance ();
365
366                         if (!AttributeTester.IsClsCompliant (ReturnType.Type)) {
367                                 Report.Warning (3002, 1, Location, "Return type of `{0}' is not CLS-compliant",
368                                         GetSignatureForError ());
369                         }
370                         return true;
371                 }
372
373
374                 public static ConstructorInfo GetConstructor (Type container_type, Type delegate_type)
375                 {
376                         Type dt = delegate_type;
377 #if GMCS_SOURCE
378                         Type[] g_args = null;
379                         if (delegate_type.IsGenericType) {
380                                 g_args = delegate_type.GetGenericArguments ();
381                                 delegate_type = delegate_type.GetGenericTypeDefinition ();
382                         }
383 #endif
384
385                         Delegate d = TypeManager.LookupDelegate (delegate_type);
386                         if (d != null) {
387 #if GMCS_SOURCE
388                                 if (g_args != null)
389                                         return TypeBuilder.GetConstructor (dt, d.ConstructorBuilder);
390 #endif
391                                 return d.ConstructorBuilder;
392                         }
393
394                         Expression ml = Expression.MemberLookup (container_type,
395                                 null, dt, ConstructorInfo.ConstructorName, MemberTypes.Constructor,
396                                 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly, Location.Null);
397
398                         MethodGroupExpr mg = ml as MethodGroupExpr;
399                         if (mg == null) {
400                                 Report.Error (-100, Location.Null, "Internal error: could not find delegate constructor!");
401                                 // FIXME: null will cause a crash later
402                                 return null;
403                         }
404
405                         return (ConstructorInfo) mg.Methods[0];
406                 }
407
408                 //
409                 // Returns the MethodBase for "Invoke" from a delegate type, this is used
410                 // to extract the signature of a delegate.
411                 //
412                 public static MethodInfo GetInvokeMethod (Type container_type, Type delegate_type)
413                 {
414                         Type dt = delegate_type;
415 #if GMCS_SOURCE
416                         Type[] g_args = null;
417                         if (delegate_type.IsGenericType) {
418                                 g_args = delegate_type.GetGenericArguments ();
419                                 delegate_type = delegate_type.GetGenericTypeDefinition ();
420                         }
421 #endif
422                         Delegate d = TypeManager.LookupDelegate (delegate_type);
423                         if (d != null) {
424 #if GMCS_SOURCE
425                                 if (g_args != null) {
426                                         MethodInfo invoke = TypeBuilder.GetMethod (dt, d.InvokeBuilder);
427 #if MS_COMPATIBLE
428                                         Parameters p = (Parameters) d.Parameters.InflateTypes (g_args, g_args);
429                                         TypeManager.RegisterMethod (invoke, p);
430 #endif
431                                         return invoke;
432                                 }
433 #endif
434                                 return d.InvokeBuilder;
435                         }
436
437                         Expression ml = Expression.MemberLookup (container_type, null, dt,
438                                 "Invoke", Location.Null);
439
440                         MethodGroupExpr mg = ml as MethodGroupExpr;
441                         if (mg == null) {
442                                 Report.Error (-100, Location.Null, "Internal error: could not find Invoke method!");
443                                 // FIXME: null will cause a crash later
444                                 return null;
445                         }
446
447                         return (MethodInfo) mg.Methods[0];
448                 }
449
450                 //
451                 // 15.2 Delegate compatibility
452                 //
453                 public static bool IsTypeCovariant (Expression a, Type b)
454                 {
455                         //
456                         // For each value parameter (a parameter with no ref or out modifier), an 
457                         // identity conversion or implicit reference conversion exists from the
458                         // parameter type in D to the corresponding parameter type in M
459                         //
460                         if (a.Type == b)
461                                 return true;
462
463                         if (RootContext.Version == LanguageVersion.ISO_1)
464                                 return false;
465
466                         return Convert.ImplicitReferenceConversionExists (a, b);
467                 }
468                 
469                 /// <summary>
470                 ///  Verifies whether the method in question is compatible with the delegate
471                 ///  Returns the method itself if okay and null if not.
472                 /// </summary>
473                 public static MethodBase VerifyMethod (Type container_type, Type delegate_type,
474                                                        MethodGroupExpr old_mg, MethodBase mb)
475                 {
476                         MethodInfo invoke_mb = GetInvokeMethod (container_type, delegate_type);
477                         if (invoke_mb == null)
478                                 return null;
479
480                         ParameterData invoke_pd = TypeManager.GetParameterData (invoke_mb);
481
482 #if GMCS_SOURCE
483                         if (old_mg.type_arguments == null &&
484                             !TypeManager.InferTypeArguments (invoke_pd, ref mb))
485                                 return null;
486 #endif
487
488                         ParameterData pd = TypeManager.GetParameterData (mb);
489
490                         if (invoke_pd.Count != pd.Count)
491                                 return null;
492
493                         for (int i = pd.Count; i > 0; ) {
494                                 i--;
495
496                                 Type invoke_pd_type = invoke_pd.ParameterType (i);
497                                 Type pd_type = pd.ParameterType (i);
498                                 Parameter.Modifier invoke_pd_type_mod = invoke_pd.ParameterModifier (i);
499                                 Parameter.Modifier pd_type_mod = pd.ParameterModifier (i);
500
501                                 invoke_pd_type_mod &= ~Parameter.Modifier.PARAMS;
502                                 pd_type_mod &= ~Parameter.Modifier.PARAMS;
503
504                                 if (invoke_pd_type_mod != pd_type_mod)
505                                         return null;
506
507                                 if (invoke_pd_type == pd_type)
508                                         continue;
509
510                                 //if (!IsTypeCovariant (invoke_pd_type, pd_type))
511                                 //      return null;
512
513                                 if (RootContext.Version == LanguageVersion.ISO_1)
514                                         return null;
515                         }
516
517                         Type invoke_mb_retval = ((MethodInfo) invoke_mb).ReturnType;
518                         Type mb_retval = ((MethodInfo) mb).ReturnType;
519                         if (TypeManager.TypeToCoreType (invoke_mb_retval) == TypeManager.TypeToCoreType (mb_retval))
520                                 return mb;
521
522                         //if (!IsTypeCovariant (mb_retval, invoke_mb_retval))
523                         //      return null;
524
525                         if (RootContext.Version == LanguageVersion.ISO_1) 
526                                 return null;
527
528                         return mb;
529                 }
530
531                 // <summary>
532                 //  Verifies whether the invocation arguments are compatible with the
533                 //  delegate's target method
534                 // </summary>
535                 public static bool VerifyApplicability (EmitContext ec, Type delegate_type,
536                                                         ArrayList args, Location loc)
537                 {
538                         int arg_count;
539
540                         if (args == null)
541                                 arg_count = 0;
542                         else
543                                 arg_count = args.Count;
544
545                         Expression ml = Expression.MemberLookup (
546                                 ec.ContainerType, delegate_type, "Invoke", loc);
547
548                         MethodGroupExpr me = ml as MethodGroupExpr;
549                         if (me == null) {
550                                 Report.Error (-100, loc, "Internal error: could not find Invoke method!" + delegate_type);
551                                 return false;
552                         }
553                         
554                         MethodBase mb = GetInvokeMethod (ec.ContainerType, delegate_type);
555                         ParameterData pd = TypeManager.GetParameterData (mb);
556
557                         int pd_count = pd.Count;
558
559                         bool params_method = pd.HasParams;
560                         bool is_params_applicable = false;
561                         me.DelegateType = delegate_type;
562                         bool is_applicable = me.IsApplicable (ec, args, arg_count, ref mb, ref is_params_applicable) == 0;
563
564                         if (!is_applicable && !params_method && arg_count != pd_count) {
565                                 Report.Error (1593, loc, "Delegate `{0}' does not take `{1}' arguments",
566                                         TypeManager.CSharpName (delegate_type), arg_count.ToString ());
567                                 return false;
568                         }
569
570                         return me.VerifyArgumentsCompat (
571                                         ec, ref args, arg_count, mb, 
572                                         is_params_applicable || (!is_applicable && params_method),
573                                         false, loc);
574                 }
575                 
576                 public static string FullDelegateDesc (MethodBase invoke_method)
577                 {
578                         return TypeManager.GetFullNameSignature (invoke_method).Replace (".Invoke", "");
579                 }
580                 
581                 public override MemberCache MemberCache {
582                         get {
583                                 return member_cache;
584                         }
585                 }
586
587                 public Expression InstanceExpression {
588                         get {
589                                 return instance_expr;
590                         }
591                         set {
592                                 instance_expr = value;
593                         }
594                 }
595
596                 public MethodBase TargetMethod {
597                         get {
598                                 return delegate_method;
599                         }
600                         set {
601                                 delegate_method = value;
602                         }
603                 }
604
605                 public Type TargetReturnType {
606                         get {
607                                 return ret_type;
608                         }
609                 }
610
611                 public override AttributeTargets AttributeTargets {
612                         get {
613                                 return AttributeTargets.Delegate;
614                         }
615                 }
616
617                 //
618                 //   Represents header string for documentation comment.
619                 //
620                 public override string DocCommentHeader {
621                         get { return "T:"; }
622                 }
623
624                 #region IMemberContainer Members
625
626                 string IMemberContainer.Name
627                 {
628                         get { throw new NotImplementedException (); }
629                 }
630
631                 Type IMemberContainer.Type
632                 {
633                         get { throw new NotImplementedException (); }
634                 }
635
636                 MemberCache IMemberContainer.BaseCache
637                 {
638                         get { throw new NotImplementedException (); }
639                 }
640
641                 bool IMemberContainer.IsInterface {
642                         get {
643                                 return false;
644                         }
645                 }
646
647                 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
648                 {
649                         throw new NotImplementedException ();
650                 }
651
652                 #endregion
653         }
654
655         //
656         // Base class for `NewDelegate' and `ImplicitDelegateCreation'
657         //
658         public abstract class DelegateCreation : Expression, MethodGroupExpr.IErrorHandler
659         {
660                 protected ConstructorInfo constructor_method;
661                 protected MethodInfo delegate_method;
662                 // We keep this to handle IsBase only
663                 protected MethodGroupExpr method_group;
664                 protected Expression delegate_instance_expression;
665
666                 public static ArrayList CreateDelegateMethodArguments (MethodInfo invoke_method, Location loc)
667                 {
668                         ParameterData pd = TypeManager.GetParameterData (invoke_method);
669                         ArrayList delegate_arguments = new ArrayList (pd.Count);
670                         for (int i = 0; i < pd.Count; ++i) {
671                                 Argument.AType atype_modifier;
672                                 Type atype = pd.Types [i];
673                                 switch (pd.ParameterModifier (i)) {
674                                         case Parameter.Modifier.REF:
675                                                 atype_modifier = Argument.AType.Ref;
676                                                 atype = atype.GetElementType ();
677                                                 break;
678                                         case Parameter.Modifier.OUT:
679                                                 atype_modifier = Argument.AType.Out;
680                                                 atype = atype.GetElementType ();
681                                                 break;
682                                         case Parameter.Modifier.ARGLIST:
683                                                 // __arglist is not valid
684                                                 throw new InternalErrorException ("__arglist modifier");
685                                         default:
686                                                 atype_modifier = Argument.AType.Expression;
687                                                 break;
688                                 }
689                                 delegate_arguments.Add (new Argument (new TypeExpression (atype, loc), atype_modifier));
690                         }
691                         return delegate_arguments;
692                 }
693
694                 public override Expression CreateExpressionTree (EmitContext ec)
695                 {
696                         MemberAccess ma = new MemberAccess (new MemberAccess (new QualifiedAliasMember ("global", "System", loc), "Delegate", loc), "CreateDelegate", loc);
697
698                         ArrayList args = new ArrayList (3);
699                         args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
700                         args.Add (new Argument (new NullLiteral (loc)));
701                         args.Add (new Argument (new TypeOfMethodInfo (delegate_method, loc)));
702                         Expression e = new Invocation (ma, args).Resolve (ec);
703                         if (e == null)
704                                 return null;
705
706                         e = Convert.ExplicitConversion (ec, e, type, loc);
707                         if (e == null)
708                                 return null;
709
710                         return e.CreateExpressionTree (ec);
711                 }
712
713                 public override Expression DoResolve (EmitContext ec)
714                 {
715                         constructor_method = Delegate.GetConstructor (ec.ContainerType, type);
716
717                         MethodInfo invoke_method = Delegate.GetInvokeMethod (ec.ContainerType, type);
718                         method_group.DelegateType = type;
719                         method_group.CustomErrorHandler = this;
720
721                         ArrayList arguments = CreateDelegateMethodArguments (invoke_method, loc);
722                         method_group = method_group.OverloadResolve (ec, ref arguments, false, loc);
723                         if (method_group == null)
724                                 return null;
725
726                         delegate_method = (MethodInfo) method_group;
727                         Invocation.IsSpecialMethodInvocation (delegate_method, loc);
728
729                         ExtensionMethodGroupExpr emg = method_group as ExtensionMethodGroupExpr;
730                         if (emg != null) {
731                                 delegate_instance_expression = emg.ExtensionExpression;
732                                 Type e_type = delegate_instance_expression.Type;
733                                 if (TypeManager.IsValueType (e_type)) {
734                                         Report.Error (1113, loc, "Extension method `{0}' of value type `{1}' cannot be used to create delegates",
735                                                 TypeManager.CSharpSignature (delegate_method), TypeManager.CSharpName (e_type));
736                                 }
737                         }
738
739                         Type rt = TypeManager.TypeToCoreType (delegate_method.ReturnType);
740                         Expression ret_expr = new TypeExpression (rt, loc);
741                         if (!Delegate.IsTypeCovariant (ret_expr, (TypeManager.TypeToCoreType (invoke_method.ReturnType)))) {
742                                 Error_ConversionFailed (ec, delegate_method, ret_expr);
743                         }
744
745                         DoResolveInstanceExpression (ec);
746                         eclass = ExprClass.Value;
747                         return this;
748                 }
749
750                 void DoResolveInstanceExpression (EmitContext ec)
751                 {
752                         //
753                         // Argument is another delegate
754                         //
755                         if (delegate_instance_expression != null)
756                                 return;
757
758                         if (method_group.InstanceExpression != null) {
759                                 delegate_instance_expression = method_group.InstanceExpression;
760                                 Type instance_type = delegate_instance_expression.Type;
761                                 if (TypeManager.IsValueType (instance_type) || TypeManager.IsGenericParameter (instance_type)) {
762                                         delegate_instance_expression = new BoxedCast (
763                                                 delegate_instance_expression, TypeManager.object_type);
764                                 }
765                         } else if (!delegate_method.IsStatic && !ec.IsStatic) {
766                                 delegate_instance_expression = ec.GetThis (loc);
767                         }
768                 }
769                 
770                 public override void Emit (EmitContext ec)
771                 {
772                         if (delegate_instance_expression == null)
773                                 ec.ig.Emit (OpCodes.Ldnull);
774                         else
775                                 delegate_instance_expression.Emit (ec);
776
777                         if (!delegate_method.DeclaringType.IsSealed && delegate_method.IsVirtual && !method_group.IsBase) {
778                                 ec.ig.Emit (OpCodes.Dup);
779                                 ec.ig.Emit (OpCodes.Ldvirtftn, (MethodInfo) delegate_method);
780                         } else
781                                 ec.ig.Emit (OpCodes.Ldftn, (MethodInfo) delegate_method);
782                         ec.ig.Emit (OpCodes.Newobj, constructor_method);
783                 }
784
785                 void Error_ConversionFailed (EmitContext ec, MethodBase method, Expression return_type)
786                 {
787                         MethodInfo invoke_method = Delegate.GetInvokeMethod (ec.ContainerType, type);
788                         string member_name = delegate_instance_expression != null ?
789                                 Delegate.FullDelegateDesc (method) :
790                                 TypeManager.GetFullNameSignature (method);
791
792                         Report.SymbolRelatedToPreviousError (type);
793                         Report.SymbolRelatedToPreviousError (method);
794                         if (RootContext.Version == LanguageVersion.ISO_1) {
795                                 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",
796                                         TypeManager.CSharpName (((MethodInfo) method).ReturnType), member_name,
797                                         TypeManager.CSharpName (invoke_method.ReturnType), Delegate.FullDelegateDesc (invoke_method));
798                                 return;
799                         }
800                         if (return_type == null) {
801                                 Report.Error (123, loc, "A method or delegate `{0}' parameters do not match delegate `{1}' parameters",
802                                         member_name, Delegate.FullDelegateDesc (invoke_method));
803                                 return;
804                         }
805
806                         Report.Error (407, loc, "A method or delegate `{0} {1}' return type does not match delegate `{2} {3}' return type",
807                                 return_type.GetSignatureForError (), member_name,
808                                 TypeManager.CSharpName (invoke_method.ReturnType), Delegate.FullDelegateDesc (invoke_method));
809                 }
810
811                 public static MethodBase ImplicitStandardConversionExists (MethodGroupExpr mg, Type target_type)
812                 {
813                         if (target_type == TypeManager.delegate_type || target_type == TypeManager.multicast_delegate_type)
814                                 return null;
815
816                         foreach (MethodInfo mi in mg.Methods){
817                                 MethodBase mb = Delegate.VerifyMethod (mg.DeclaringType, target_type, mg, mi);
818                                 if (mb != null)
819                                         return mb;
820                         }
821                         return null;
822                 }
823
824                 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
825                 {
826                         if (delegate_instance_expression != null)
827                                 delegate_instance_expression.MutateHoistedGenericType (storey);
828
829                         delegate_method = storey.MutateGenericMethod (delegate_method);
830                         constructor_method = storey.MutateConstructor (constructor_method);
831                 }
832
833                 #region IErrorHandler Members
834
835                 public bool NoExactMatch (EmitContext ec, MethodBase method)
836                 {
837                         if (TypeManager.IsGenericMethod (method))
838                                 return false;
839
840                         Error_ConversionFailed (ec, method, null);
841                         return true;
842                 }
843
844                 #endregion
845         }
846
847         //
848         // Created from the conversion code
849         //
850         public class ImplicitDelegateCreation : DelegateCreation
851         {
852                 ImplicitDelegateCreation (Type t, MethodGroupExpr mg, Location l)
853                 {
854                         type = t;
855                         this.method_group = mg;
856                         loc = l;
857                 }
858
859                 static public Expression Create (EmitContext ec, MethodGroupExpr mge,
860                                                  Type target_type, Location loc)
861                 {
862                         ImplicitDelegateCreation d = new ImplicitDelegateCreation (target_type, mge, loc);
863                         return d.DoResolve (ec);
864                 }
865         }
866         
867         //
868         // A delegate-creation-expression, invoked from the `New' class 
869         //
870         public class NewDelegate : DelegateCreation
871         {
872                 public ArrayList Arguments;
873
874                 //
875                 // This constructor is invoked from the `New' expression
876                 //
877                 public NewDelegate (Type type, ArrayList Arguments, Location loc)
878                 {
879                         this.type = type;
880                         this.Arguments = Arguments;
881                         this.loc  = loc; 
882                 }
883
884                 public override Expression DoResolve (EmitContext ec)
885                 {
886                         if (Arguments == null) {
887                                 Error_InvalidDelegateArgument ();
888                                 return null;
889                         }
890
891                         Argument a = (Argument) Arguments [0];
892                         if (!a.ResolveMethodGroup (ec))
893                                 return null;
894
895                         Expression e = a.Expr;
896
897                         AnonymousMethodExpression ame = e as AnonymousMethodExpression;
898                         if (ame != null && RootContext.Version != LanguageVersion.ISO_1) {
899                                 e = ame.Compatible (ec, type);
900                                 if (e == null)
901                                         return null;
902
903                                 return e.Resolve (ec);
904                         }
905
906                         method_group = e as MethodGroupExpr;
907                         if (method_group == null) {
908                                 if (!TypeManager.IsDelegateType (e.Type)) {
909                                         Report.Error (149, loc, "Method name expected");
910                                         return null;
911                                 }
912
913                                 //
914                                 // An argument is not a method but another delegate
915                                 //
916                                 delegate_instance_expression = e;
917                                 method_group = new MethodGroupExpr (new MemberInfo [] { 
918                                         Delegate.GetInvokeMethod (ec.ContainerType, e.Type) }, e.Type, loc);
919                         }
920
921                         if (base.DoResolve (ec) == null)
922                                 return null;
923
924                         if (TypeManager.IsNullableType (method_group.DeclaringType)) {
925                                 Report.Error (1728, loc, "Cannot use method `{0}' as delegate creation expression because it is member of Nullable type",
926                                         TypeManager.GetFullNameSignature (delegate_method));
927                         }
928
929                         if (Invocation.IsMethodExcluded (delegate_method, loc)) {
930                                 Report.SymbolRelatedToPreviousError (delegate_method);
931                                 Report.Error (1618, loc, "Cannot create delegate with `{0}' because it has a Conditional attribute",
932                                         TypeManager.CSharpSignature (delegate_method));
933                         }
934
935                         return this;
936                 }
937
938                 void Error_InvalidDelegateArgument ()
939                 {
940                         Report.Error (149, loc, "Method name expected");
941                 }
942         }
943
944         public class DelegateInvocation : ExpressionStatement {
945
946                 readonly Expression InstanceExpr;
947                 readonly ArrayList  Arguments;
948
949                 MethodInfo method;
950                 
951                 public DelegateInvocation (Expression instance_expr, ArrayList args, Location loc)
952                 {
953                         this.InstanceExpr = instance_expr;
954                         this.Arguments = args;
955                         this.loc = loc;
956                 }
957                 
958                 public override Expression CreateExpressionTree (EmitContext ec)
959                 {
960                         ArrayList args;
961                         if (Arguments == null)
962                                 args = new ArrayList (1);
963                         else
964                                 args = new ArrayList (Arguments.Count + 1);
965
966                         args.Add (new Argument (InstanceExpr.CreateExpressionTree (ec)));
967                         if (Arguments != null) {
968                                 foreach (Argument a in Arguments)
969                                         args.Add (new Argument (a.Expr.CreateExpressionTree (ec)));
970                         }
971
972                         return CreateExpressionFactoryCall ("Invoke", args);
973                 }
974
975                 public override Expression DoResolve (EmitContext ec)
976                 {
977                         if (InstanceExpr is EventExpr) {
978                                 ((EventExpr) InstanceExpr).Error_CannotAssign ();
979                                 return null;
980                         }
981                         
982                         Type del_type = InstanceExpr.Type;
983                         if (del_type == null)
984                                 return null;
985                         
986                         if (Arguments != null){
987                                 foreach (Argument a in Arguments){
988                                         if (!a.Resolve (ec, loc))
989                                                 return null;
990                                 }
991                         }
992                         
993                         if (!Delegate.VerifyApplicability (ec, del_type, Arguments, loc))
994                                 return null;
995
996                         method = Delegate.GetInvokeMethod (ec.ContainerType, del_type);
997                         type = TypeManager.TypeToCoreType (method.ReturnType);
998                         eclass = ExprClass.Value;
999                         
1000                         return this;
1001                 }
1002
1003                 public override void Emit (EmitContext ec)
1004                 {
1005                         //
1006                         // Invocation on delegates call the virtual Invoke member
1007                         // so we are always `instance' calls
1008                         //
1009                         Invocation.EmitCall (ec, false, InstanceExpr, method, Arguments, loc);
1010                 }
1011
1012                 public override void EmitStatement (EmitContext ec)
1013                 {
1014                         Emit (ec);
1015                         // 
1016                         // Pop the return value if there is one
1017                         //
1018                         if (type != TypeManager.void_type)
1019                                 ec.ig.Emit (OpCodes.Pop);
1020                 }
1021
1022                 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
1023                 {
1024                         method = storey.MutateGenericMethod (method);
1025                         type = storey.MutateType (type);
1026
1027                         if (Arguments != null) {
1028                                 foreach (Argument a in Arguments) {
1029                                         a.Expr.MutateHoistedGenericType (storey);
1030                                 }
1031                         }
1032
1033                         InstanceExpr.MutateHoistedGenericType (storey);
1034                 }
1035         }
1036 }