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