2 // delegate.cs: Delegate Handler
5 // Ravi Pratap (ravi@ximian.com)
6 // Miguel de Icaza (miguel@ximian.com)
7 // Marek Safar (marek.safar@gmail.com)
9 // Dual licensed under the terms of the MIT X11 or GNU GPL
11 // Copyright 2001 Ximian, Inc (http://www.ximian.com)
12 // Copyright 2003-2009 Novell, Inc (http://www.novell.com)
16 using System
.Reflection
;
17 using System
.Reflection
.Emit
;
20 namespace Mono
.CSharp
{
23 // Delegate container implementation
25 public class Delegate
: TypeContainer
27 FullNamedExpression ReturnType
;
28 public ParametersCompiled Parameters
;
30 public ConstructorBuilder ConstructorBuilder
;
31 public MethodBuilder InvokeBuilder
;
32 public MethodBuilder BeginInvokeBuilder
;
33 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 MethodAttributes mattr
= MethodAttributes
.Public
| MethodAttributes
.HideBySig
|
44 MethodAttributes
.Virtual
| MethodAttributes
.NewSlot
;
46 const int AllowedModifiers
=
54 public Delegate (NamespaceEntry ns
, DeclSpace parent
, FullNamedExpression type
,
55 int mod_flags
, MemberName name
, ParametersCompiled param_list
,
57 : base (ns
, parent
, name
, attrs
, Kind
.Delegate
)
60 this.ReturnType
= type
;
61 ModFlags
= Modifiers
.Check (AllowedModifiers
, mod_flags
,
62 IsTopLevel
? Modifiers
.INTERNAL
:
63 Modifiers
.PRIVATE
, name
.Location
, Report
);
64 Parameters
= param_list
;
67 public override void ApplyAttributeBuilder (Attribute a
, CustomAttributeBuilder cb
, PredefinedAttributes pa
)
69 if (a
.Target
== AttributeTargets
.ReturnValue
) {
70 if (return_attributes
== null)
71 return_attributes
= new ReturnParameter (this, InvokeBuilder
, Location
);
73 return_attributes
.ApplyAttributeBuilder (a
, cb
, pa
);
77 base.ApplyAttributeBuilder (a
, cb
, pa
);
80 public override AttributeTargets AttributeTargets
{
82 return AttributeTargets
.Delegate
;
86 protected override bool DoDefineMembers ()
89 foreach (TypeParameter type_param
in TypeParameters
) {
90 if (!type_param
.Resolve (this))
94 foreach (TypeParameter type_param
in TypeParameters
) {
95 if (!type_param
.DefineType (this))
100 member_cache
= new MemberCache (TypeManager
.multicast_delegate_type
, this);
102 // FIXME: POSSIBLY make this static, as it is always constant
104 Type
[] const_arg_types
= new Type
[2];
105 const_arg_types
[0] = TypeManager
.object_type
;
106 const_arg_types
[1] = TypeManager
.intptr_type
;
108 const MethodAttributes ctor_mattr
= MethodAttributes
.RTSpecialName
| MethodAttributes
.SpecialName
|
109 MethodAttributes
.HideBySig
| MethodAttributes
.Public
;
111 ConstructorBuilder
= TypeBuilder
.DefineConstructor (ctor_mattr
,
112 CallingConventions
.Standard
,
115 ConstructorBuilder
.DefineParameter (1, ParameterAttributes
.None
, "object");
116 ConstructorBuilder
.DefineParameter (2, ParameterAttributes
.None
, "method");
118 // HACK because System.Reflection.Emit is lame
120 IParameterData
[] fixed_pars
= new IParameterData
[] {
121 new ParameterData ("object", Parameter
.Modifier
.NONE
),
122 new ParameterData ("method", Parameter
.Modifier
.NONE
)
125 AParametersCollection const_parameters
= new ParametersImported (
127 new Type
[] { TypeManager.object_type, TypeManager.intptr_type }
);
129 TypeManager
.RegisterMethod (ConstructorBuilder
, const_parameters
);
130 member_cache
.AddMember (ConstructorBuilder
, this);
132 ConstructorBuilder
.SetImplementationFlags (MethodImplAttributes
.Runtime
);
135 // Here the various methods like Invoke, BeginInvoke etc are defined
137 // First, call the `out of band' special method for
138 // defining recursively any types we need:
140 if (!Parameters
.Resolve (this))
147 // Check accessibility
148 foreach (Type partype
in Parameters
.Types
){
149 if (!IsAccessibleAs (partype
)) {
150 Report
.SymbolRelatedToPreviousError (partype
);
151 Report
.Error (59, Location
,
152 "Inconsistent accessibility: parameter type `{0}' is less accessible than delegate `{1}'",
153 TypeManager
.CSharpName (partype
),
154 GetSignatureForError ());
159 ReturnType
= ReturnType
.ResolveAsTypeTerminal (this, false);
160 if (ReturnType
== null)
163 ret_type
= ReturnType
.Type
;
165 if (!IsAccessibleAs (ret_type
)) {
166 Report
.SymbolRelatedToPreviousError (ret_type
);
167 Report
.Error (58, Location
,
168 "Inconsistent accessibility: return type `" +
169 TypeManager
.CSharpName (ret_type
) + "' is less " +
170 "accessible than delegate `" + GetSignatureForError () + "'");
174 CheckProtectedModifier ();
176 if (RootContext
.StdLib
&& TypeManager
.IsSpecialType (ret_type
)) {
177 Method
.Error1599 (Location
, ret_type
, Report
);
181 TypeManager
.CheckTypeVariance (ret_type
, Variance
.Covariant
, this);
184 // We don't have to check any others because they are all
185 // guaranteed to be accessible - they are standard types.
188 CallingConventions cc
= Parameters
.CallingConvention
;
190 InvokeBuilder
= TypeBuilder
.DefineMethod ("Invoke",
194 Parameters
.GetEmitTypes ());
196 InvokeBuilder
.SetImplementationFlags (MethodImplAttributes
.Runtime
);
198 TypeManager
.RegisterMethod (InvokeBuilder
, Parameters
);
199 member_cache
.AddMember (InvokeBuilder
, this);
202 // Don't emit async method for compiler generated delegates (e.g. dynamic site containers)
204 if (TypeManager
.iasyncresult_type
!= null && TypeManager
.asynccallback_type
!= null && !IsCompilerGenerated
) {
205 DefineAsyncMethods (cc
);
211 void DefineAsyncMethods (CallingConventions cc
)
216 ParametersCompiled async_parameters
= ParametersCompiled
.MergeGenerated (Compiler
, Parameters
, false,
218 new Parameter (null, "callback", Parameter
.Modifier
.NONE
, null, Location
),
219 new Parameter (null, "object", Parameter
.Modifier
.NONE
, null, Location
)
222 TypeManager
.asynccallback_type
,
223 TypeManager
.object_type
227 BeginInvokeBuilder
= TypeBuilder
.DefineMethod ("BeginInvoke",
228 mattr
, cc
, TypeManager
.iasyncresult_type
, async_parameters
.GetEmitTypes ());
230 BeginInvokeBuilder
.SetImplementationFlags (MethodImplAttributes
.Runtime
);
231 TypeManager
.RegisterMethod (BeginInvokeBuilder
, async_parameters
);
232 member_cache
.AddMember (BeginInvokeBuilder
, this);
235 // EndInvoke is a bit more interesting, all the parameters labeled as
236 // out or ref have to be duplicated here.
240 // Define parameters, and count out/ref parameters
242 ParametersCompiled end_parameters
;
245 foreach (Parameter p
in Parameters
.FixedParameters
) {
246 if ((p
.ModFlags
& Parameter
.Modifier
.ISBYREF
) != 0)
250 if (out_params
> 0) {
251 Type
[] end_param_types
= new Type
[out_params
];
252 Parameter
[] end_params
= new Parameter
[out_params
];
255 for (int i
= 0; i
< Parameters
.FixedParameters
.Length
; ++i
) {
256 Parameter p
= Parameters
[i
];
257 if ((p
.ModFlags
& Parameter
.Modifier
.ISBYREF
) == 0)
260 end_param_types
[param
] = Parameters
.Types
[i
];
261 end_params
[param
] = p
;
264 end_parameters
= ParametersCompiled
.CreateFullyResolved (end_params
, end_param_types
);
266 end_parameters
= ParametersCompiled
.EmptyReadOnlyParameters
;
269 end_parameters
= ParametersCompiled
.MergeGenerated (Compiler
, end_parameters
, false,
270 new Parameter (null, "result", Parameter
.Modifier
.NONE
, null, Location
), TypeManager
.iasyncresult_type
);
273 // Create method, define parameters, register parameters with type system
275 EndInvokeBuilder
= TypeBuilder
.DefineMethod ("EndInvoke", mattr
, cc
, ret_type
, end_parameters
.GetEmitTypes ());
276 EndInvokeBuilder
.SetImplementationFlags (MethodImplAttributes
.Runtime
);
278 end_parameters
.ApplyAttributes (EndInvokeBuilder
);
279 TypeManager
.RegisterMethod (EndInvokeBuilder
, end_parameters
);
280 member_cache
.AddMember (EndInvokeBuilder
, this);
283 public override void Emit ()
285 if (TypeManager
.IsDynamicType (ret_type
)) {
286 return_attributes
= new ReturnParameter (this, InvokeBuilder
, Location
);
287 PredefinedAttributes
.Get
.Dynamic
.EmitAttribute (return_attributes
.Builder
);
289 var trans_flags
= TypeManager
.HasDynamicTypeUsed (ret_type
);
290 if (trans_flags
!= null) {
291 var pa
= PredefinedAttributes
.Get
.DynamicTransform
;
292 if (pa
.Constructor
!= null || pa
.ResolveConstructor (Location
, TypeManager
.bool_type
.MakeArrayType ())) {
293 return_attributes
= new ReturnParameter (this, InvokeBuilder
, Location
);
294 return_attributes
.Builder
.SetCustomAttribute (
295 new CustomAttributeBuilder (pa
.Constructor
, new object [] { trans_flags }
));
300 Parameters
.ApplyAttributes (InvokeBuilder
);
302 if (BeginInvokeBuilder
!= null) {
303 ParametersCompiled p
= (ParametersCompiled
) TypeManager
.GetParameterData (BeginInvokeBuilder
);
304 p
.ApplyAttributes (BeginInvokeBuilder
);
307 if (OptAttributes
!= null) {
308 OptAttributes
.Emit ();
314 protected override TypeAttributes TypeAttr
{
316 return Modifiers
.TypeAttr (ModFlags
, IsTopLevel
) |
317 TypeAttributes
.Class
| TypeAttributes
.Sealed
|
322 public override string[] ValidAttributeTargets
{
324 return attribute_targets
;
329 protected override bool VerifyClsCompliance ()
331 if (!base.VerifyClsCompliance ()) {
335 Parameters
.VerifyClsCompliance (this);
337 if (!AttributeTester
.IsClsCompliant (ReturnType
.Type
)) {
338 Report
.Warning (3002, 1, Location
, "Return type of `{0}' is not CLS-compliant",
339 GetSignatureForError ());
345 public static ConstructorInfo
GetConstructor (CompilerContext ctx
, Type container_type
, Type delegate_type
)
347 Type dt
= delegate_type
;
348 Type
[] g_args
= null;
349 if (TypeManager
.IsGenericType (delegate_type
)) {
350 g_args
= TypeManager
.GetTypeArguments (delegate_type
);
351 delegate_type
= TypeManager
.DropGenericTypeArguments (delegate_type
);
354 Delegate d
= TypeManager
.LookupDelegate (delegate_type
);
357 return TypeBuilder
.GetConstructor (dt
, d
.ConstructorBuilder
);
359 return d
.ConstructorBuilder
;
362 Expression ml
= Expression
.MemberLookup (ctx
, container_type
,
363 null, dt
, ConstructorInfo
.ConstructorName
, MemberTypes
.Constructor
,
364 BindingFlags
.Public
| BindingFlags
.Instance
| BindingFlags
.DeclaredOnly
, Location
.Null
);
366 MethodGroupExpr mg
= ml
as MethodGroupExpr
;
368 ctx
.Report
.Error (-100, Location
.Null
, "Internal error: could not find delegate constructor!");
369 // FIXME: null will cause a crash later
373 return (ConstructorInfo
) mg
.Methods
[0];
377 // Returns the MethodBase for "Invoke" from a delegate type, this is used
378 // to extract the signature of a delegate.
380 public static MethodInfo
GetInvokeMethod (CompilerContext ctx
, Type container_type
, Type delegate_type
)
382 Type dt
= delegate_type
;
384 Type
[] g_args
= null;
385 if (TypeManager
.IsGenericType (delegate_type
)) {
386 g_args
= TypeManager
.GetTypeArguments (delegate_type
);
387 delegate_type
= TypeManager
.DropGenericTypeArguments (delegate_type
);
390 Delegate d
= TypeManager
.LookupDelegate (delegate_type
);
393 if (g_args
!= null) {
394 invoke
= TypeBuilder
.GetMethod (dt
, d
.InvokeBuilder
);
396 ParametersCompiled p
= (ParametersCompiled
) d
.Parameters
.InflateTypes (g_args
, g_args
);
397 TypeManager
.RegisterMethod (invoke
, p
);
401 return d
.InvokeBuilder
;
404 Expression ml
= Expression
.MemberLookup (ctx
, container_type
, null, dt
,
405 "Invoke", Location
.Null
);
407 MethodGroupExpr mg
= ml
as MethodGroupExpr
;
409 ctx
.Report
.Error (-100, Location
.Null
, "Internal error: could not find Invoke method!");
410 // FIXME: null will cause a crash later
414 invoke
= (MethodInfo
) mg
.Methods
[0];
416 if (g_args
!= null) {
417 AParametersCollection p
= TypeManager
.GetParameterData (invoke
);
418 p
= p
.InflateTypes (g_args
, g_args
);
419 TypeManager
.RegisterMethod (invoke
, p
);
428 // 15.2 Delegate compatibility
430 public static bool IsTypeCovariant (Expression a
, Type b
)
433 // For each value parameter (a parameter with no ref or out modifier), an
434 // identity conversion or implicit reference conversion exists from the
435 // parameter type in D to the corresponding parameter type in M
440 if (RootContext
.Version
== LanguageVersion
.ISO_1
)
443 return Convert
.ImplicitReferenceConversionExists (a
, b
);
446 public static string FullDelegateDesc (MethodBase invoke_method
)
448 return TypeManager
.GetFullNameSignature (invoke_method
).Replace (".Invoke", "");
451 public Expression InstanceExpression
{
453 return instance_expr
;
456 instance_expr
= value;
460 public MethodBase TargetMethod
{
462 return delegate_method
;
465 delegate_method
= value;
469 public Type TargetReturnType
{
477 // Base class for `NewDelegate' and `ImplicitDelegateCreation'
479 public abstract class DelegateCreation
: Expression
, MethodGroupExpr
.IErrorHandler
481 protected ConstructorInfo constructor_method
;
482 protected MethodInfo delegate_method
;
483 // We keep this to handle IsBase only
484 protected MethodGroupExpr method_group
;
485 protected Expression delegate_instance_expression
;
487 // TODO: Should either cache it or use interface to abstract it
488 public static Arguments
CreateDelegateMethodArguments (AParametersCollection pd
, Location loc
)
490 Arguments delegate_arguments
= new Arguments (pd
.Count
);
491 for (int i
= 0; i
< pd
.Count
; ++i
) {
492 Argument
.AType atype_modifier
;
493 Type atype
= pd
.Types
[i
];
494 switch (pd
.FixedParameters
[i
].ModFlags
) {
495 case Parameter
.Modifier
.REF
:
496 atype_modifier
= Argument
.AType
.Ref
;
497 //atype = atype.GetElementType ();
499 case Parameter
.Modifier
.OUT
:
500 atype_modifier
= Argument
.AType
.Out
;
501 //atype = atype.GetElementType ();
507 delegate_arguments
.Add (new Argument (new TypeExpression (atype
, loc
), atype_modifier
));
509 return delegate_arguments
;
512 public override Expression
CreateExpressionTree (ResolveContext ec
)
514 MemberAccess ma
= new MemberAccess (new MemberAccess (new QualifiedAliasMember ("global", "System", loc
), "Delegate", loc
), "CreateDelegate", loc
);
516 Arguments args
= new Arguments (3);
517 args
.Add (new Argument (new TypeOf (new TypeExpression (type
, loc
), loc
)));
518 args
.Add (new Argument (new NullLiteral (loc
)));
519 args
.Add (new Argument (new TypeOfMethod (delegate_method
, loc
)));
520 Expression e
= new Invocation (ma
, args
).Resolve (ec
);
524 e
= Convert
.ExplicitConversion (ec
, e
, type
, loc
);
528 return e
.CreateExpressionTree (ec
);
531 protected override Expression
DoResolve (ResolveContext ec
)
533 constructor_method
= Delegate
.GetConstructor (ec
.Compiler
, ec
.CurrentType
, type
);
535 MethodInfo invoke_method
= Delegate
.GetInvokeMethod (ec
.Compiler
, ec
.CurrentType
, type
);
536 method_group
.DelegateType
= type
;
537 method_group
.CustomErrorHandler
= this;
539 Arguments arguments
= CreateDelegateMethodArguments (TypeManager
.GetParameterData (invoke_method
), loc
);
540 method_group
= method_group
.OverloadResolve (ec
, ref arguments
, false, loc
);
541 if (method_group
== null)
544 delegate_method
= (MethodInfo
) method_group
;
546 if (TypeManager
.IsNullableType (delegate_method
.DeclaringType
)) {
547 ec
.Report
.Error (1728, loc
, "Cannot create delegate from method `{0}' because it is a member of System.Nullable<T> type",
548 TypeManager
.GetFullNameSignature (delegate_method
));
552 Invocation
.IsSpecialMethodInvocation (ec
, delegate_method
, loc
);
554 ExtensionMethodGroupExpr emg
= method_group
as ExtensionMethodGroupExpr
;
556 delegate_instance_expression
= emg
.ExtensionExpression
;
557 Type e_type
= delegate_instance_expression
.Type
;
558 if (TypeManager
.IsValueType (e_type
)) {
559 ec
.Report
.Error (1113, loc
, "Extension method `{0}' of value type `{1}' cannot be used to create delegates",
560 TypeManager
.CSharpSignature (delegate_method
), TypeManager
.CSharpName (e_type
));
564 Type rt
= TypeManager
.TypeToCoreType (delegate_method
.ReturnType
);
565 Expression ret_expr
= new TypeExpression (rt
, loc
);
566 if (!Delegate
.IsTypeCovariant (ret_expr
, (TypeManager
.TypeToCoreType (invoke_method
.ReturnType
)))) {
567 Error_ConversionFailed (ec
, delegate_method
, ret_expr
);
570 if (Invocation
.IsMethodExcluded (delegate_method
, loc
)) {
571 ec
.Report
.SymbolRelatedToPreviousError (delegate_method
);
572 MethodOrOperator m
= TypeManager
.GetMethod (delegate_method
) as MethodOrOperator
;
573 if (m
!= null && m
.IsPartialDefinition
) {
574 ec
.Report
.Error (762, loc
, "Cannot create delegate from partial method declaration `{0}'",
575 TypeManager
.CSharpSignature (delegate_method
));
577 ec
.Report
.Error (1618, loc
, "Cannot create delegate with `{0}' because it has a Conditional attribute",
578 TypeManager
.CSharpSignature (delegate_method
));
582 DoResolveInstanceExpression (ec
);
583 eclass
= ExprClass
.Value
;
587 void DoResolveInstanceExpression (ResolveContext ec
)
590 // Argument is another delegate
592 if (delegate_instance_expression
!= null)
595 if (method_group
.IsStatic
) {
596 delegate_instance_expression
= null;
600 Expression instance
= method_group
.InstanceExpression
;
601 if (instance
!= null && instance
!= EmptyExpression
.Null
) {
602 delegate_instance_expression
= instance
;
603 Type instance_type
= delegate_instance_expression
.Type
;
604 if (TypeManager
.IsValueType (instance_type
) || TypeManager
.IsGenericParameter (instance_type
)) {
605 delegate_instance_expression
= new BoxedCast (
606 delegate_instance_expression
, TypeManager
.object_type
);
609 delegate_instance_expression
= ec
.GetThis (loc
);
613 public override void Emit (EmitContext ec
)
615 if (delegate_instance_expression
== null)
616 ec
.ig
.Emit (OpCodes
.Ldnull
);
618 delegate_instance_expression
.Emit (ec
);
620 if (!delegate_method
.DeclaringType
.IsSealed
&& delegate_method
.IsVirtual
&& !method_group
.IsBase
) {
621 ec
.ig
.Emit (OpCodes
.Dup
);
622 ec
.ig
.Emit (OpCodes
.Ldvirtftn
, delegate_method
);
624 ec
.ig
.Emit (OpCodes
.Ldftn
, delegate_method
);
627 ec
.ig
.Emit (OpCodes
.Newobj
, constructor_method
);
630 void Error_ConversionFailed (ResolveContext ec
, MethodBase method
, Expression return_type
)
632 MethodInfo invoke_method
= Delegate
.GetInvokeMethod (ec
.Compiler
, ec
.CurrentType
, type
);
633 string member_name
= delegate_instance_expression
!= null ?
634 Delegate
.FullDelegateDesc (method
) :
635 TypeManager
.GetFullNameSignature (method
);
637 ec
.Report
.SymbolRelatedToPreviousError (type
);
638 ec
.Report
.SymbolRelatedToPreviousError (method
);
639 if (RootContext
.Version
== LanguageVersion
.ISO_1
) {
640 ec
.Report
.Error (410, loc
, "A method or delegate `{0} {1}' parameters and return type must be same as delegate `{2} {3}' parameters and return type",
641 TypeManager
.CSharpName (((MethodInfo
) method
).ReturnType
), member_name
,
642 TypeManager
.CSharpName (invoke_method
.ReturnType
), Delegate
.FullDelegateDesc (invoke_method
));
645 if (return_type
== null) {
646 ec
.Report
.Error (123, loc
, "A method or delegate `{0}' parameters do not match delegate `{1}' parameters",
647 member_name
, Delegate
.FullDelegateDesc (invoke_method
));
651 ec
.Report
.Error (407, loc
, "A method or delegate `{0} {1}' return type does not match delegate `{2} {3}' return type",
652 return_type
.GetSignatureForError (), member_name
,
653 TypeManager
.CSharpName (invoke_method
.ReturnType
), Delegate
.FullDelegateDesc (invoke_method
));
656 public static bool ImplicitStandardConversionExists (ResolveContext ec
, MethodGroupExpr mg
, Type target_type
)
658 if (target_type
== TypeManager
.delegate_type
|| target_type
== TypeManager
.multicast_delegate_type
)
661 mg
.DelegateType
= target_type
;
662 MethodInfo invoke
= Delegate
.GetInvokeMethod (ec
.Compiler
, null, target_type
);
664 Arguments arguments
= CreateDelegateMethodArguments (TypeManager
.GetParameterData (invoke
), mg
.Location
);
665 return mg
.OverloadResolve (ec
, ref arguments
, true, mg
.Location
) != null;
668 public override void MutateHoistedGenericType (AnonymousMethodStorey storey
)
670 if (delegate_instance_expression
!= null)
671 delegate_instance_expression
.MutateHoistedGenericType (storey
);
673 delegate_method
= storey
.MutateGenericMethod (delegate_method
);
674 constructor_method
= storey
.MutateConstructor (constructor_method
);
677 #region IErrorHandler Members
679 public bool NoExactMatch (ResolveContext ec
, MethodBase method
)
681 if (TypeManager
.IsGenericMethod (method
))
684 Error_ConversionFailed (ec
, method
, null);
688 public bool AmbiguousCall (ResolveContext ec
, MethodBase ambiguous
)
697 // Created from the conversion code
699 public class ImplicitDelegateCreation
: DelegateCreation
701 ImplicitDelegateCreation (Type t
, MethodGroupExpr mg
, Location l
)
704 this.method_group
= mg
;
708 static public Expression
Create (ResolveContext ec
, MethodGroupExpr mge
,
709 Type target_type
, Location loc
)
711 ImplicitDelegateCreation d
= new ImplicitDelegateCreation (target_type
, mge
, loc
);
712 return d
.DoResolve (ec
);
717 // A delegate-creation-expression, invoked from the `New' class
719 public class NewDelegate
: DelegateCreation
721 public Arguments Arguments
;
724 // This constructor is invoked from the `New' expression
726 public NewDelegate (Type type
, Arguments Arguments
, Location loc
)
729 this.Arguments
= Arguments
;
733 protected override Expression
DoResolve (ResolveContext ec
)
735 if (Arguments
== null || Arguments
.Count
!= 1) {
736 ec
.Report
.Error (149, loc
, "Method name expected");
740 Argument a
= Arguments
[0];
741 if (!a
.ResolveMethodGroup (ec
))
744 Expression e
= a
.Expr
;
746 AnonymousMethodExpression ame
= e
as AnonymousMethodExpression
;
747 if (ame
!= null && RootContext
.Version
!= LanguageVersion
.ISO_1
) {
748 e
= ame
.Compatible (ec
, type
);
752 return e
.Resolve (ec
);
755 method_group
= e
as MethodGroupExpr
;
756 if (method_group
== null) {
757 if (TypeManager
.IsDynamicType (e
.Type
)) {
758 e
= Convert
.ImplicitConversionRequired (ec
, e
, type
, loc
);
759 } else if (!TypeManager
.IsDelegateType (e
.Type
)) {
760 e
.Error_UnexpectedKind (ec
, ResolveFlags
.MethodGroup
| ResolveFlags
.Type
, loc
);
765 // An argument is not a method but another delegate
767 delegate_instance_expression
= e
;
768 method_group
= new MethodGroupExpr (new MemberInfo
[] {
769 Delegate
.GetInvokeMethod (ec
.Compiler
, ec
.CurrentType
, e
.Type
) }, e
.Type
, loc
);
772 return base.DoResolve (ec
);
777 // Invocation converted to delegate Invoke call
779 class DelegateInvocation
: ExpressionStatement
781 readonly Expression InstanceExpr
;
785 public DelegateInvocation (Expression instance_expr
, Arguments args
, Location loc
)
787 this.InstanceExpr
= instance_expr
;
788 this.arguments
= args
;
792 public override Expression
CreateExpressionTree (ResolveContext ec
)
794 Arguments args
= Arguments
.CreateForExpressionTree (ec
, this.arguments
,
795 InstanceExpr
.CreateExpressionTree (ec
));
797 return CreateExpressionFactoryCall (ec
, "Invoke", args
);
800 protected override Expression
DoResolve (ResolveContext ec
)
802 if (InstanceExpr
is EventExpr
) {
803 ((EventExpr
) InstanceExpr
).Error_CannotAssign (ec
);
807 Type del_type
= InstanceExpr
.Type
;
808 if (del_type
== null)
811 method
= Delegate
.GetInvokeMethod (ec
.Compiler
, ec
.CurrentType
, del_type
);
812 MethodBase mb
= method
;
813 var me
= new MethodGroupExpr (new [] { mb }
, del_type
, loc
);
814 me
.InstanceExpression
= InstanceExpr
;
816 AParametersCollection pd
= TypeManager
.GetParameterData (mb
);
817 int pd_count
= pd
.Count
;
819 int arg_count
= arguments
== null ? 0 : arguments
.Count
;
821 bool params_method
= pd
.HasParams
;
822 bool is_params_applicable
= false;
823 bool is_applicable
= me
.IsApplicable (ec
, ref arguments
, arg_count
, ref mb
, ref is_params_applicable
) == 0;
824 if (arguments
!= null)
825 arg_count
= arguments
.Count
;
827 if (!is_applicable
&& !params_method
&& arg_count
!= pd_count
) {
828 ec
.Report
.Error (1593, loc
, "Delegate `{0}' does not take `{1}' arguments",
829 TypeManager
.CSharpName (del_type
), arg_count
.ToString ());
830 } else if (arguments
== null || !arguments
.HasDynamic
) {
831 me
.VerifyArgumentsCompat (ec
, ref arguments
, arg_count
, mb
,
832 is_params_applicable
|| (!is_applicable
&& params_method
), false, loc
);
835 type
= TypeManager
.TypeToCoreType (method
.ReturnType
);
836 eclass
= ExprClass
.Value
;
840 public override void Emit (EmitContext ec
)
843 // Invocation on delegates call the virtual Invoke member
844 // so we are always `instance' calls
846 Invocation
.EmitCall (ec
, false, InstanceExpr
, method
, arguments
, loc
);
849 public override void EmitStatement (EmitContext ec
)
853 // Pop the return value if there is one
855 if (type
!= TypeManager
.void_type
)
856 ec
.ig
.Emit (OpCodes
.Pop
);
860 public override System
.Linq
.Expressions
.Expression
MakeExpression (BuilderContext ctx
)
862 return Invocation
.MakeExpression (ctx
, InstanceExpr
, method
, arguments
);
866 public override void MutateHoistedGenericType (AnonymousMethodStorey storey
)
868 method
= storey
.MutateGenericMethod (method
);
869 type
= storey
.MutateType (type
);
871 if (arguments
!= null)
872 arguments
.MutateHoistedGenericType (storey
);
874 InstanceExpr
.MutateHoistedGenericType (storey
);