2 // delegate.cs: Delegate Handler
5 // Ravi Pratap (ravi@ximian.com)
6 // Miguel de Icaza (miguel@ximian.com)
8 // Licensed under the terms of the GNU GPL
10 // (C) 2001 Ximian, Inc (http://www.ximian.com)
15 using System
.Collections
;
16 using System
.Reflection
;
17 using System
.Reflection
.Emit
;
20 namespace Mono
.CSharp
{
25 public class Delegate
: DeclSpace
{
26 public Expression ReturnType
;
27 public Parameters Parameters
;
29 public ConstructorBuilder ConstructorBuilder
;
30 public MethodBuilder InvokeBuilder
;
31 public MethodBuilder BeginInvokeBuilder
;
32 public MethodBuilder EndInvokeBuilder
;
37 static string[] attribute_targets
= new string [] { "type", "return" }
;
39 Expression instance_expr
;
40 MethodBase delegate_method
;
41 ReturnParameter return_attributes
;
43 const int AllowedModifiers
=
51 public Delegate (NamespaceEntry ns
, TypeContainer parent
, Expression type
,
52 int mod_flags
, MemberName name
, Parameters param_list
,
53 Attributes attrs
, Location l
)
54 : base (ns
, parent
, name
, attrs
, l
)
57 this.ReturnType
= type
;
58 ModFlags
= Modifiers
.Check (AllowedModifiers
, mod_flags
,
59 IsTopLevel
? Modifiers
.INTERNAL
:
60 Modifiers
.PRIVATE
, l
);
61 Parameters
= param_list
;
64 public override void ApplyAttributeBuilder(Attribute a
, CustomAttributeBuilder cb
)
66 if (a
.Target
== AttributeTargets
.ReturnValue
) {
67 if (return_attributes
== null)
68 return_attributes
= new ReturnParameter (InvokeBuilder
, Location
);
70 return_attributes
.ApplyAttributeBuilder (a
, cb
);
74 base.ApplyAttributeBuilder (a
, cb
);
77 public override TypeBuilder
DefineType ()
79 if (TypeBuilder
!= null)
82 TypeAttributes attr
= Modifiers
.TypeAttr (ModFlags
, IsTopLevel
) |
83 TypeAttributes
.Class
| TypeAttributes
.Sealed
;
86 if (TypeManager
.NamespaceClash (Name
, Location
))
89 ModuleBuilder builder
= CodeGen
.Module
.Builder
;
91 TypeBuilder
= builder
.DefineType (
92 Name
, attr
, TypeManager
.multicast_delegate_type
);
94 TypeBuilder builder
= Parent
.TypeBuilder
;
96 string name
= Name
.Substring (1 + Name
.LastIndexOf ('.'));
97 TypeBuilder
= builder
.DefineNestedType (
98 name
, attr
, TypeManager
.multicast_delegate_type
);
101 TypeManager
.AddDelegateType (Name
, TypeBuilder
, this);
106 public override bool DefineMembers (TypeContainer container
)
111 public override bool Define ()
113 MethodAttributes mattr
;
115 EmitContext ec
= new EmitContext (this, this, Location
, null,
116 null, ModFlags
, false);
118 // FIXME: POSSIBLY make this static, as it is always constant
120 Type
[] const_arg_types
= new Type
[2];
121 const_arg_types
[0] = TypeManager
.object_type
;
122 const_arg_types
[1] = TypeManager
.intptr_type
;
124 mattr
= MethodAttributes
.RTSpecialName
| MethodAttributes
.SpecialName
|
125 MethodAttributes
.HideBySig
| MethodAttributes
.Public
;
127 ConstructorBuilder
= TypeBuilder
.DefineConstructor (mattr
,
128 CallingConventions
.Standard
,
131 ConstructorBuilder
.DefineParameter (1, ParameterAttributes
.None
, "object");
132 ConstructorBuilder
.DefineParameter (2, ParameterAttributes
.None
, "method");
134 // HACK because System.Reflection.Emit is lame
137 // FIXME: POSSIBLY make these static, as they are always the same
138 Parameter
[] fixed_pars
= new Parameter
[2];
139 fixed_pars
[0] = new Parameter (TypeManager
.system_object_expr
, "object",
140 Parameter
.Modifier
.NONE
, null);
141 fixed_pars
[1] = new Parameter (TypeManager
.system_intptr_expr
, "method",
142 Parameter
.Modifier
.NONE
, null);
143 Parameters const_parameters
= new Parameters (fixed_pars
, null, Location
);
145 TypeManager
.RegisterMethod (
147 new InternalParameters (const_arg_types
, const_parameters
),
151 ConstructorBuilder
.SetImplementationFlags (MethodImplAttributes
.Runtime
);
154 // Here the various methods like Invoke, BeginInvoke etc are defined
156 // First, call the `out of band' special method for
157 // defining recursively any types we need:
159 if (!Parameters
.ComputeAndDefineParameterTypes (ec
))
162 param_types
= Parameters
.GetParameterInfo (ec
);
163 if (param_types
== null)
170 // Check accessibility
171 foreach (Type partype
in param_types
){
172 if (!Parent
.AsAccessible (partype
, ModFlags
)) {
173 Report
.Error (59, Location
,
174 "Inconsistent accessibility: parameter type `" +
175 TypeManager
.CSharpName (partype
) + "` is less " +
176 "accessible than delegate `" + Name
+ "'");
179 if (partype
.IsPointer
&& !UnsafeOK (Parent
))
183 ReturnType
= ReturnType
.ResolveAsTypeTerminal (ec
, false);
184 if (ReturnType
== null)
187 ret_type
= ReturnType
.Type
;
188 if (ret_type
== null)
191 if (!Parent
.AsAccessible (ret_type
, ModFlags
)) {
192 Report
.Error (58, Location
,
193 "Inconsistent accessibility: return type `" +
194 TypeManager
.CSharpName (ret_type
) + "` is less " +
195 "accessible than delegate `" + Name
+ "'");
199 if (ret_type
.IsPointer
&& !UnsafeOK (Parent
))
203 // We don't have to check any others because they are all
204 // guaranteed to be accessible - they are standard types.
207 CallingConventions cc
= Parameters
.GetCallingConvention ();
209 mattr
= MethodAttributes
.Public
| MethodAttributes
.HideBySig
| MethodAttributes
.Virtual
;
211 InvokeBuilder
= TypeBuilder
.DefineMethod ("Invoke",
218 // Define parameters, and count out/ref parameters
222 if (Parameters
.FixedParameters
!= null){
223 int top
= Parameters
.FixedParameters
.Length
;
226 for (; i
< top
; i
++) {
227 p
= Parameters
.FixedParameters
[i
];
228 p
.DefineParameter (ec
, InvokeBuilder
, null, i
+ 1, Location
);
230 if ((p
.ModFlags
& Parameter
.Modifier
.ISBYREF
) != 0)
234 if (Parameters
.ArrayParameter
!= null){
235 Parameter p
= Parameters
.ArrayParameter
;
236 p
.DefineParameter (ec
, InvokeBuilder
, null, i
+ 1, Location
);
239 InvokeBuilder
.SetImplementationFlags (MethodImplAttributes
.Runtime
);
241 TypeManager
.RegisterMethod (InvokeBuilder
,
242 new InternalParameters (param_types
, Parameters
),
248 int params_num
= param_types
.Length
;
249 Type
[] async_param_types
= new Type
[params_num
+ 2];
251 param_types
.CopyTo (async_param_types
, 0);
253 async_param_types
[params_num
] = TypeManager
.asynccallback_type
;
254 async_param_types
[params_num
+ 1] = TypeManager
.object_type
;
256 mattr
= MethodAttributes
.Public
| MethodAttributes
.HideBySig
|
257 MethodAttributes
.Virtual
| MethodAttributes
.NewSlot
;
259 BeginInvokeBuilder
= TypeBuilder
.DefineMethod ("BeginInvoke",
262 TypeManager
.iasyncresult_type
,
266 if (Parameters
.FixedParameters
!= null){
267 int top
= Parameters
.FixedParameters
.Length
;
270 for (i
= 0 ; i
< top
; i
++) {
271 p
= Parameters
.FixedParameters
[i
];
273 p
.DefineParameter (ec
, BeginInvokeBuilder
, null, i
+ 1, Location
);
276 if (Parameters
.ArrayParameter
!= null){
277 Parameter p
= Parameters
.ArrayParameter
;
278 p
.DefineParameter (ec
, BeginInvokeBuilder
, null, i
+ 1, Location
);
283 BeginInvokeBuilder
.DefineParameter (i
+ 1, ParameterAttributes
.None
, "callback");
284 BeginInvokeBuilder
.DefineParameter (i
+ 2, ParameterAttributes
.None
, "object");
286 BeginInvokeBuilder
.SetImplementationFlags (MethodImplAttributes
.Runtime
);
288 Parameter
[] async_params
= new Parameter
[params_num
+ 2];
290 if (Parameters
.FixedParameters
!= null){
291 Parameters
.FixedParameters
.CopyTo (async_params
, 0);
292 n
= Parameters
.FixedParameters
.Length
;
294 if (Parameters
.ArrayParameter
!= null)
295 async_params
[n
] = Parameters
.ArrayParameter
;
297 async_params
[params_num
] = new Parameter (
298 TypeManager
.system_asynccallback_expr
, "callback",
299 Parameter
.Modifier
.NONE
, null);
300 async_params
[params_num
+ 1] = new Parameter (
301 TypeManager
.system_object_expr
, "object",
302 Parameter
.Modifier
.NONE
, null);
304 Parameters async_parameters
= new Parameters (async_params
, null, Location
);
305 async_parameters
.ComputeAndDefineParameterTypes (ec
);
307 TypeManager
.RegisterMethod (BeginInvokeBuilder
,
308 new InternalParameters (async_param_types
, async_parameters
),
312 // EndInvoke is a bit more interesting, all the parameters labeled as
313 // out or ref have to be duplicated here.
316 Type
[] end_param_types
= new Type
[out_params
+ 1];
317 Parameter
[] end_params
= new Parameter
[out_params
+ 1];
320 int top
= Parameters
.FixedParameters
.Length
;
321 for (i
= 0; i
< top
; i
++){
322 Parameter p
= Parameters
.FixedParameters
[i
];
323 if ((p
.ModFlags
& Parameter
.Modifier
.ISBYREF
) == 0)
326 end_param_types
[param
] = param_types
[i
];
327 end_params
[param
] = p
;
331 end_param_types
[out_params
] = TypeManager
.iasyncresult_type
;
332 end_params
[out_params
] = new Parameter (TypeManager
.system_iasyncresult_expr
, "result", Parameter
.Modifier
.NONE
, null);
335 // Create method, define parameters, register parameters with type system
337 EndInvokeBuilder
= TypeBuilder
.DefineMethod ("EndInvoke", mattr
, cc
, ret_type
, end_param_types
);
338 EndInvokeBuilder
.SetImplementationFlags (MethodImplAttributes
.Runtime
);
341 // EndInvoke: Label the parameters
343 EndInvokeBuilder
.DefineParameter (out_params
+ 1, ParameterAttributes
.None
, "result");
344 for (i
= 0; i
< end_params
.Length
-1; i
++){
345 EndInvokeBuilder
.DefineParameter (i
+ 1, end_params
[i
].Attributes
, end_params
[i
].Name
);
348 Parameters end_parameters
= new Parameters (end_params
, null, Location
);
349 end_parameters
.ComputeAndDefineParameterTypes (ec
);
351 TypeManager
.RegisterMethod (
353 new InternalParameters (end_param_types
, end_parameters
),
359 public override void Emit ()
361 if (OptAttributes
!= null) {
362 EmitContext ec
= new EmitContext (
363 Parent
, this, Location
, null, null, ModFlags
, false);
364 Parameters
.LabelParameters (ec
, InvokeBuilder
, Location
);
365 OptAttributes
.Emit (ec
, this);
371 public override string[] ValidAttributeTargets
{
373 return attribute_targets
;
378 protected override bool VerifyClsCompliance (DeclSpace ds
)
380 if (!base.VerifyClsCompliance (ds
)) {
384 AttributeTester
.AreParametersCompliant (Parameters
.FixedParameters
, Location
);
386 if (!AttributeTester
.IsClsCompliant (ReturnType
.Type
)) {
387 Report
.Error (3002, Location
, "Return type of '{0}' is not CLS-compliant", GetSignatureForError ());
393 // Returns the MethodBase for "Invoke" from a delegate type, this is used
394 // to extract the signature of a delegate.
396 public static MethodInfo
GetInvokeMethod (EmitContext ec
, Type delegate_type
, Location loc
)
398 Expression ml
= Expression
.MemberLookup (
399 ec
, delegate_type
, "Invoke", loc
);
401 if (!(ml
is MethodGroupExpr
)) {
402 Report
.Error (-100, loc
, "Internal error: could not find Invoke method!");
406 return (MethodInfo
) (((MethodGroupExpr
) ml
).Methods
[0]);
410 /// Verifies whether the method in question is compatible with the delegate
411 /// Returns the method itself if okay and null if not.
413 public static MethodBase
VerifyMethod (EmitContext ec
, Type delegate_type
, MethodBase mb
,
416 ParameterData pd
= Invocation
.GetParameterData (mb
);
418 int pd_count
= pd
.Count
;
420 MethodBase invoke_mb
= GetInvokeMethod (ec
, delegate_type
, loc
);
421 if (invoke_mb
== null)
424 ParameterData invoke_pd
= Invocation
.GetParameterData (invoke_mb
);
426 if (invoke_pd
.Count
!= pd_count
)
429 for (int i
= pd_count
; i
> 0; ) {
432 if (invoke_pd
.ParameterType (i
) == pd
.ParameterType (i
) &&
433 invoke_pd
.ParameterModifier (i
) == pd
.ParameterModifier (i
))
440 if (((MethodInfo
) invoke_mb
).ReturnType
== ((MethodInfo
) mb
).ReturnType
)
447 // Verifies whether the invocation arguments are compatible with the
448 // delegate's target method
450 public static bool VerifyApplicability (EmitContext ec
, Type delegate_type
,
451 ArrayList args
, Location loc
)
458 arg_count
= args
.Count
;
460 Expression ml
= Expression
.MemberLookup (
461 ec
, delegate_type
, "Invoke", loc
);
463 if (!(ml
is MethodGroupExpr
)) {
464 Report
.Error (-100, loc
, "Internal error: could not find Invoke method!" + delegate_type
);
468 MethodBase mb
= ((MethodGroupExpr
) ml
).Methods
[0];
469 ParameterData pd
= Invocation
.GetParameterData (mb
);
471 int pd_count
= pd
.Count
;
473 bool params_method
= (pd_count
!= 0) &&
474 (pd
.ParameterModifier (pd_count
- 1) == Parameter
.Modifier
.PARAMS
);
476 if (!params_method
&& pd_count
!= arg_count
) {
477 Report
.Error (1593, loc
,
478 "Delegate '{0}' does not take {1} arguments",
479 delegate_type
.ToString (), arg_count
);
484 // Consider the case:
485 // delegate void FOO(param object[] args);
486 // FOO f = new FOO(...);
487 // f(new object[] {1, 2, 3});
489 // This should be treated like f(1,2,3). This is done by ignoring the
490 // 'param' modifier for that invocation. If that fails, then the
491 // 'param' modifier is considered.
493 // One issue is that 'VerifyArgumentsCompat' modifies the elements of
494 // the 'args' array. However, the modifications appear idempotent.
495 // Normal 'Invocation's also have the same behaviour, implicitly.
499 if (arg_count
== pd_count
)
500 ans
= Invocation
.VerifyArgumentsCompat (
501 ec
, args
, arg_count
, mb
, false,
502 delegate_type
, false, loc
);
503 if (!ans
&& params_method
)
504 ans
= Invocation
.VerifyArgumentsCompat (
505 ec
, args
, arg_count
, mb
, true,
506 delegate_type
, false, loc
);
511 /// Verifies whether the delegate in question is compatible with this one in
512 /// order to determine if instantiation from the same is possible.
514 public static bool VerifyDelegate (EmitContext ec
, Type delegate_type
, Type probe_type
, Location loc
)
516 Expression ml
= Expression
.MemberLookup (
517 ec
, delegate_type
, "Invoke", loc
);
519 if (!(ml
is MethodGroupExpr
)) {
520 Report
.Error (-100, loc
, "Internal error: could not find Invoke method!");
524 MethodBase mb
= ((MethodGroupExpr
) ml
).Methods
[0];
525 ParameterData pd
= Invocation
.GetParameterData (mb
);
527 Expression probe_ml
= Expression
.MemberLookup (
528 ec
, delegate_type
, "Invoke", loc
);
530 if (!(probe_ml
is MethodGroupExpr
)) {
531 Report
.Error (-100, loc
, "Internal error: could not find Invoke method!");
535 MethodBase probe_mb
= ((MethodGroupExpr
) probe_ml
).Methods
[0];
536 ParameterData probe_pd
= Invocation
.GetParameterData (probe_mb
);
538 if (((MethodInfo
) mb
).ReturnType
!= ((MethodInfo
) probe_mb
).ReturnType
)
541 if (pd
.Count
!= probe_pd
.Count
)
544 for (int i
= pd
.Count
; i
> 0; ) {
547 if (pd
.ParameterType (i
) != probe_pd
.ParameterType (i
) ||
548 pd
.ParameterModifier (i
) != probe_pd
.ParameterModifier (i
))
555 public static string FullDelegateDesc (Type del_type
, MethodBase mb
, ParameterData pd
)
557 StringBuilder sb
= new StringBuilder (TypeManager
.CSharpName (((MethodInfo
) mb
).ReturnType
));
559 sb
.Append (" " + del_type
.ToString ());
562 int length
= pd
.Count
;
564 for (int i
= length
; i
> 0; ) {
567 sb
.Append (pd
.ParameterDesc (length
- i
- 1));
573 return sb
.ToString ();
577 // Hack around System.Reflection as found everywhere else
578 public override MemberList
FindMembers (MemberTypes mt
, BindingFlags bf
,
579 MemberFilter filter
, object criteria
)
581 ArrayList members
= new ArrayList ();
583 if ((mt
& MemberTypes
.Method
) != 0) {
584 if (ConstructorBuilder
!= null)
585 if (filter (ConstructorBuilder
, criteria
))
586 members
.Add (ConstructorBuilder
);
588 if (InvokeBuilder
!= null)
589 if (filter (InvokeBuilder
, criteria
))
590 members
.Add (InvokeBuilder
);
592 if (BeginInvokeBuilder
!= null)
593 if (filter (BeginInvokeBuilder
, criteria
))
594 members
.Add (BeginInvokeBuilder
);
596 if (EndInvokeBuilder
!= null)
597 if (filter (EndInvokeBuilder
, criteria
))
598 members
.Add (EndInvokeBuilder
);
601 return new MemberList (members
);
604 public override MemberCache MemberCache
{
610 public Expression InstanceExpression
{
612 return instance_expr
;
615 instance_expr
= value;
619 public MethodBase TargetMethod
{
621 return delegate_method
;
624 delegate_method
= value;
628 public Type TargetReturnType
{
634 public Type
[] ParameterTypes
{
640 public override AttributeTargets AttributeTargets
{
642 return AttributeTargets
.Delegate
;
646 protected override void VerifyObsoleteAttribute()
648 CheckUsageOfObsoleteAttribute (ret_type
);
650 foreach (Type type
in param_types
) {
651 CheckUsageOfObsoleteAttribute (type
);
657 // Base class for `NewDelegate' and `ImplicitDelegateCreation'
659 public abstract class DelegateCreation
: Expression
{
660 protected MethodBase constructor_method
;
661 protected MethodBase delegate_method
;
662 protected MethodGroupExpr method_group
;
663 protected Expression delegate_instance_expression
;
665 public DelegateCreation () {}
667 public static void Error_NoMatchingMethodForDelegate (EmitContext ec
, MethodGroupExpr mg
, Type type
, Location loc
)
671 if (mg
.Methods
.Length
> 1)
672 method_desc
= mg
.Methods
[0].Name
;
674 method_desc
= Invocation
.FullMethodDesc (mg
.Methods
[0]);
676 Expression invoke_method
= Expression
.MemberLookup (
677 ec
, type
, "Invoke", MemberTypes
.Method
,
678 Expression
.AllBindingFlags
, loc
);
679 MethodBase method
= ((MethodGroupExpr
) invoke_method
).Methods
[0];
680 ParameterData param
= Invocation
.GetParameterData (method
);
681 string delegate_desc
= Delegate
.FullDelegateDesc (type
, method
, param
);
683 Report
.Error (123, loc
, "Method '" + method_desc
+ "' does not " +
684 "match delegate '" + delegate_desc
+ "'");
687 public override void Emit (EmitContext ec
)
689 if (delegate_instance_expression
== null || delegate_method
.IsStatic
)
690 ec
.ig
.Emit (OpCodes
.Ldnull
);
692 delegate_instance_expression
.Emit (ec
);
694 if (delegate_method
.IsVirtual
&& !method_group
.IsBase
) {
695 ec
.ig
.Emit (OpCodes
.Dup
);
696 ec
.ig
.Emit (OpCodes
.Ldvirtftn
, (MethodInfo
) delegate_method
);
698 ec
.ig
.Emit (OpCodes
.Ldftn
, (MethodInfo
) delegate_method
);
699 ec
.ig
.Emit (OpCodes
.Newobj
, (ConstructorInfo
) constructor_method
);
702 protected bool ResolveConstructorMethod (EmitContext ec
)
704 Expression ml
= Expression
.MemberLookup (
705 ec
, type
, ".ctor", loc
);
707 if (!(ml
is MethodGroupExpr
)) {
708 Report
.Error (-100, loc
, "Internal error: Could not find delegate constructor!");
712 constructor_method
= ((MethodGroupExpr
) ml
).Methods
[0];
716 protected Expression
ResolveMethodGroupExpr (EmitContext ec
, MethodGroupExpr mg
)
718 foreach (MethodInfo mi
in mg
.Methods
){
719 delegate_method
= Delegate
.VerifyMethod (ec
, type
, mi
, loc
);
721 if (delegate_method
!= null)
725 if (delegate_method
== null) {
726 Error_NoMatchingMethodForDelegate (ec
, mg
, type
, loc
);
731 // Check safe/unsafe of the delegate
734 ParameterData param
= Invocation
.GetParameterData (delegate_method
);
735 int count
= param
.Count
;
737 for (int i
= 0; i
< count
; i
++){
738 if (param
.ParameterType (i
).IsPointer
){
739 Expression
.UnsafeError (loc
);
745 //TODO: implement caching when performance will be low
746 IMethodData md
= TypeManager
.GetMethod (delegate_method
);
748 if (System
.Attribute
.GetCustomAttribute (delegate_method
, TypeManager
.conditional_attribute_type
) != null) {
749 Report
.Error (1618, loc
, "Cannot create delegate with '{0}' because it has a Conditional attribute", TypeManager
.CSharpSignature (delegate_method
));
752 if (md
.OptAttributes
!= null && md
.OptAttributes
.Search (TypeManager
.conditional_attribute_type
, ec
) != null) {
753 Report
.Error (1618, loc
, "Cannot create delegate with '{0}' because it has a Conditional attribute", TypeManager
.CSharpSignature (delegate_method
));
757 if (mg
.InstanceExpression
!= null)
758 delegate_instance_expression
= mg
.InstanceExpression
.Resolve (ec
);
759 else if (ec
.IsStatic
) {
760 if (!delegate_method
.IsStatic
) {
761 Report
.Error (120, loc
,
762 "An object reference is required for the non-static method " +
763 delegate_method
.Name
);
766 delegate_instance_expression
= null;
768 delegate_instance_expression
= ec
.GetThis (loc
);
770 if (delegate_instance_expression
!= null && delegate_instance_expression
.Type
.IsValueType
)
771 delegate_instance_expression
= new BoxedCast (mg
.InstanceExpression
);
774 eclass
= ExprClass
.Value
;
780 // Created from the conversion code
782 public class ImplicitDelegateCreation
: DelegateCreation
{
784 ImplicitDelegateCreation (Type t
, Location l
)
790 public override Expression
DoResolve (EmitContext ec
)
795 static public Expression
Create (EmitContext ec
, MethodGroupExpr mge
, Type target_type
, Location loc
)
797 ImplicitDelegateCreation d
= new ImplicitDelegateCreation (target_type
, loc
);
798 if (d
.ResolveConstructorMethod (ec
))
799 return d
.ResolveMethodGroupExpr (ec
, mge
);
806 // A delegate-creation-expression, invoked from the `New' class
808 public class NewDelegate
: DelegateCreation
{
809 public ArrayList Arguments
;
812 // This constructor is invoked from the `New' expression
814 public NewDelegate (Type type
, ArrayList Arguments
, Location loc
)
817 this.Arguments
= Arguments
;
821 public override Expression
DoResolve (EmitContext ec
)
823 if (Arguments
== null || Arguments
.Count
!= 1) {
824 Report
.Error (149, loc
,
825 "Method name expected");
829 if (!ResolveConstructorMethod (ec
))
832 Argument a
= (Argument
) Arguments
[0];
834 if (!a
.ResolveMethodGroup (ec
, loc
))
837 Expression e
= a
.Expr
;
839 MethodGroupExpr mg
= e
as MethodGroupExpr
;
841 return ResolveMethodGroupExpr (ec
, mg
);
843 Type e_type
= e
.Type
;
845 if (!TypeManager
.IsDelegateType (e_type
)) {
846 e
.Error_UnexpectedKind ("method", loc
);
850 method_group
= Expression
.MemberLookup (
851 ec
, type
, "Invoke", MemberTypes
.Method
,
852 Expression
.AllBindingFlags
, loc
) as MethodGroupExpr
;
854 if (method_group
== null) {
855 Report
.Error (-200, loc
, "Internal error ! Could not find Invoke method!");
859 // This is what MS' compiler reports. We could always choose
860 // to be more verbose and actually give delegate-level specifics
861 if (!Delegate
.VerifyDelegate (ec
, type
, e_type
, loc
)) {
862 Report
.Error (29, loc
, "Cannot implicitly convert type '" + e_type
+ "' " +
863 "to type '" + type
+ "'");
867 delegate_instance_expression
= e
;
868 delegate_method
= method_group
.Methods
[0];
870 eclass
= ExprClass
.Value
;
875 public class DelegateInvocation
: ExpressionStatement
{
877 public Expression InstanceExpr
;
878 public ArrayList Arguments
;
882 public DelegateInvocation (Expression instance_expr
, ArrayList args
, Location loc
)
884 this.InstanceExpr
= instance_expr
;
885 this.Arguments
= args
;
889 public override Expression
DoResolve (EmitContext ec
)
891 if (InstanceExpr
is EventExpr
) {
893 EventInfo ei
= ((EventExpr
) InstanceExpr
).EventInfo
;
895 Expression ml
= MemberLookup (
896 ec
, ec
.ContainerType
, ei
.Name
,
897 MemberTypes
.Event
, AllBindingFlags
| BindingFlags
.DeclaredOnly
, loc
);
901 // If this is the case, then the Event does not belong
902 // to this Type and so, according to the spec
903 // cannot be accessed directly
905 // Note that target will not appear as an EventExpr
906 // in the case it is being referenced within the same type container;
907 // it will appear as a FieldExpr in that case.
910 Assign
.error70 (ei
, loc
);
916 Type del_type
= InstanceExpr
.Type
;
917 if (del_type
== null)
920 if (Arguments
!= null){
921 foreach (Argument a
in Arguments
){
922 if (!a
.Resolve (ec
, loc
))
927 if (!Delegate
.VerifyApplicability (ec
, del_type
, Arguments
, loc
))
930 Expression lookup
= Expression
.MemberLookup (ec
, del_type
, "Invoke", loc
);
931 if (!(lookup
is MethodGroupExpr
)) {
932 Report
.Error (-100, loc
, "Internal error: could not find Invoke method!");
936 method
= ((MethodGroupExpr
) lookup
).Methods
[0];
937 type
= ((MethodInfo
) method
).ReturnType
;
938 eclass
= ExprClass
.Value
;
943 public override void Emit (EmitContext ec
)
946 // Invocation on delegates call the virtual Invoke member
947 // so we are always `instance' calls
949 Invocation
.EmitCall (ec
, false, false, InstanceExpr
, method
, Arguments
, loc
);
952 public override void EmitStatement (EmitContext ec
)
956 // Pop the return value if there is one
958 if (method
is MethodInfo
){
959 if (((MethodInfo
) method
).ReturnType
!= TypeManager
.void_type
)
960 ec
.ig
.Emit (OpCodes
.Pop
);