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
;
19 namespace Mono
.CSharp
{
22 // Delegate container implementation
24 public class Delegate
: TypeContainer
26 FullNamedExpression ReturnType
;
27 public readonly AParametersCollection Parameters
;
29 // TODO: Maybe I can keep member cache only and not the builders
30 Constructor Constructor
;
32 Method BeginInvokeBuilder
;
33 Method EndInvokeBuilder
;
35 static readonly string[] attribute_targets
= new string [] { "type", "return" }
;
37 public static readonly string InvokeMethodName
= "Invoke";
39 Expression instance_expr
;
40 ReturnParameter return_attributes
;
42 const Modifiers MethodModifiers
= Modifiers
.PUBLIC
| Modifiers
.VIRTUAL
;
44 const Modifiers AllowedModifiers
=
52 public Delegate (NamespaceEntry ns
, DeclSpace parent
, FullNamedExpression type
,
53 Modifiers mod_flags
, MemberName name
, ParametersCompiled param_list
,
55 : base (ns
, parent
, name
, attrs
, MemberKind
.Delegate
)
58 this.ReturnType
= type
;
59 ModFlags
= ModifiersExtensions
.Check (AllowedModifiers
, mod_flags
,
60 IsTopLevel
? Modifiers
.INTERNAL
:
61 Modifiers
.PRIVATE
, name
.Location
, Report
);
62 Parameters
= param_list
;
65 public override void ApplyAttributeBuilder (Attribute a
, CustomAttributeBuilder cb
, PredefinedAttributes pa
)
67 if (a
.Target
== AttributeTargets
.ReturnValue
) {
68 if (return_attributes
== null)
69 return_attributes
= new ReturnParameter (this, InvokeBuilder
.MethodBuilder
, Location
);
71 return_attributes
.ApplyAttributeBuilder (a
, cb
, pa
);
75 base.ApplyAttributeBuilder (a
, cb
, pa
);
78 public override AttributeTargets AttributeTargets
{
80 return AttributeTargets
.Delegate
;
84 protected override Type BaseType
{
86 return TypeManager
.multicast_delegate_type
;
90 protected override bool DoDefineMembers ()
93 foreach (TypeParameter type_param
in TypeParameters
) {
94 if (!type_param
.Resolve (this))
98 foreach (TypeParameter type_param
in TypeParameters
) {
99 if (!type_param
.DefineType (this))
104 member_cache
= new MemberCache (BaseType
, this);
106 var ctor_parameters
= ParametersCompiled
.CreateFullyResolved (
108 new Parameter (new TypeExpression (TypeManager
.object_type
, Location
), "object", Parameter
.Modifier
.NONE
, null, Location
),
109 new Parameter (new TypeExpression (TypeManager
.intptr_type
, Location
), "method", Parameter
.Modifier
.NONE
, null, Location
)
112 TypeManager
.object_type
,
113 TypeManager
.intptr_type
117 Constructor
= new Constructor (this, System
.Reflection
.ConstructorInfo
.ConstructorName
,
118 Modifiers
.PUBLIC
, null, ctor_parameters
, null, Location
);
119 Constructor
.Define ();
122 // Here the various methods like Invoke, BeginInvoke etc are defined
124 // First, call the `out of band' special method for
125 // defining recursively any types we need:
127 var p
= Parameters
.AsCompiled
;
129 if (!p
.Resolve (this))
136 // Check accessibility
137 foreach (var partype
in p
.Types
) {
138 if (!IsAccessibleAs (partype
)) {
139 Report
.SymbolRelatedToPreviousError (partype
);
140 Report
.Error (59, Location
,
141 "Inconsistent accessibility: parameter type `{0}' is less accessible than delegate `{1}'",
142 TypeManager
.CSharpName (partype
), GetSignatureForError ());
146 ReturnType
= ReturnType
.ResolveAsTypeTerminal (this, false);
147 if (ReturnType
== null)
150 var ret_type
= ReturnType
.Type
;
153 // We don't have to check any others because they are all
154 // guaranteed to be accessible - they are standard types.
156 if (!IsAccessibleAs (ret_type
)) {
157 Report
.SymbolRelatedToPreviousError (ret_type
);
158 Report
.Error (58, Location
,
159 "Inconsistent accessibility: return type `" +
160 TypeManager
.CSharpName (ret_type
) + "' is less " +
161 "accessible than delegate `" + GetSignatureForError () + "'");
165 CheckProtectedModifier ();
167 if (RootContext
.StdLib
&& TypeManager
.IsSpecialType (ret_type
)) {
168 Method
.Error1599 (Location
, ret_type
, Report
);
172 TypeManager
.CheckTypeVariance (ret_type
, Variance
.Covariant
, this);
174 InvokeBuilder
= new Method (this, null, ReturnType
, MethodModifiers
, new MemberName (InvokeMethodName
), p
, null);
175 InvokeBuilder
.Define ();
178 // Don't emit async method for compiler generated delegates (e.g. dynamic site containers)
180 if (TypeManager
.iasyncresult_type
!= null && TypeManager
.asynccallback_type
!= null && !IsCompilerGenerated
) {
181 DefineAsyncMethods (Parameters
.CallingConvention
);
187 void DefineAsyncMethods (CallingConventions cc
)
192 Parameter
[] compiled
= new Parameter
[Parameters
.Count
];
193 for (int i
= 0; i
< compiled
.Length
; ++i
)
194 compiled
[i
] = new Parameter (new TypeExpression (Parameters
.Types
[i
], Location
),
195 Parameters
.FixedParameters
[i
].Name
,
196 Parameters
.FixedParameters
[i
].ModFlags
& (Parameter
.Modifier
.REF
| Parameter
.Modifier
.OUT
),
199 ParametersCompiled async_parameters
= new ParametersCompiled (Compiler
, compiled
);
201 async_parameters
= ParametersCompiled
.MergeGenerated (Compiler
, async_parameters
, false,
203 new Parameter (new TypeExpression (TypeManager
.asynccallback_type
, Location
), "callback", Parameter
.Modifier
.NONE
, null, Location
),
204 new Parameter (new TypeExpression (TypeManager
.object_type
, Location
), "object", Parameter
.Modifier
.NONE
, null, Location
)
207 TypeManager
.asynccallback_type
,
208 TypeManager
.object_type
212 BeginInvokeBuilder
= new Method (this, null,
213 new TypeExpression (TypeManager
.iasyncresult_type
, Location
), MethodModifiers
,
214 new MemberName ("BeginInvoke"), async_parameters
, null);
215 BeginInvokeBuilder
.Define ();
218 // EndInvoke is a bit more interesting, all the parameters labeled as
219 // out or ref have to be duplicated here.
223 // Define parameters, and count out/ref parameters
225 ParametersCompiled end_parameters
;
228 foreach (Parameter p
in Parameters
.FixedParameters
) {
229 if ((p
.ModFlags
& Parameter
.Modifier
.ISBYREF
) != 0)
233 if (out_params
> 0) {
234 var end_param_types
= new Type
[out_params
];
235 Parameter
[] end_params
= new Parameter
[out_params
];
238 for (int i
= 0; i
< Parameters
.FixedParameters
.Length
; ++i
) {
239 Parameter p
= Parameters
.AsCompiled
[i
];
240 if ((p
.ModFlags
& Parameter
.Modifier
.ISBYREF
) == 0)
243 end_param_types
[param
] = Parameters
.Types
[i
];
244 end_params
[param
] = p
;
247 end_parameters
= ParametersCompiled
.CreateFullyResolved (end_params
, end_param_types
);
249 end_parameters
= ParametersCompiled
.EmptyReadOnlyParameters
;
252 end_parameters
= ParametersCompiled
.MergeGenerated (Compiler
, end_parameters
, false,
254 new TypeExpression (TypeManager
.iasyncresult_type
, Location
),
255 "result", Parameter
.Modifier
.NONE
, null, Location
),
256 TypeManager
.iasyncresult_type
);
259 // Create method, define parameters, register parameters with type system
261 EndInvokeBuilder
= new Method (this, null, ReturnType
, MethodModifiers
, new MemberName ("EndInvoke"), end_parameters
, null);
262 EndInvokeBuilder
.Define ();
265 public override void Emit ()
267 if (TypeManager
.IsDynamicType (ReturnType
.Type
)) {
268 return_attributes
= new ReturnParameter (this, InvokeBuilder
.MethodBuilder
, Location
);
269 PredefinedAttributes
.Get
.Dynamic
.EmitAttribute (return_attributes
.Builder
);
271 var trans_flags
= TypeManager
.HasDynamicTypeUsed (ReturnType
.Type
);
272 if (trans_flags
!= null) {
273 var pa
= PredefinedAttributes
.Get
.DynamicTransform
;
274 if (pa
.Constructor
!= null || pa
.ResolveConstructor (Location
, TypeManager
.bool_type
.MakeArrayType ())) {
275 return_attributes
= new ReturnParameter (this, InvokeBuilder
.MethodBuilder
, Location
);
276 return_attributes
.Builder
.SetCustomAttribute (
277 new CustomAttributeBuilder (pa
.Constructor
, new object [] { trans_flags }
));
282 Parameters
.AsCompiled
.ApplyAttributes (InvokeBuilder
.MethodBuilder
);
284 Constructor
.ConstructorBuilder
.SetImplementationFlags (MethodImplAttributes
.Runtime
);
285 InvokeBuilder
.MethodBuilder
.SetImplementationFlags (MethodImplAttributes
.Runtime
);
287 if (BeginInvokeBuilder
!= null) {
288 BeginInvokeBuilder
.Parameters
.ApplyAttributes (BeginInvokeBuilder
.MethodBuilder
);
290 BeginInvokeBuilder
.MethodBuilder
.SetImplementationFlags (MethodImplAttributes
.Runtime
);
291 EndInvokeBuilder
.MethodBuilder
.SetImplementationFlags (MethodImplAttributes
.Runtime
);
294 if (OptAttributes
!= null) {
295 OptAttributes
.Emit ();
301 protected override TypeAttributes TypeAttr
{
303 return ModifiersExtensions
.TypeAttr (ModFlags
, IsTopLevel
) |
304 TypeAttributes
.Class
| TypeAttributes
.Sealed
|
309 public override string[] ValidAttributeTargets
{
311 return attribute_targets
;
316 protected override bool VerifyClsCompliance ()
318 if (!base.VerifyClsCompliance ()) {
322 Parameters
.AsCompiled
.VerifyClsCompliance (this);
324 if (!AttributeTester
.IsClsCompliant (ReturnType
.Type
)) {
325 Report
.Warning (3002, 1, Location
, "Return type of `{0}' is not CLS-compliant",
326 GetSignatureForError ());
332 public static MethodSpec
GetConstructor (CompilerContext ctx
, Type container_type
, Type delegate_type
)
334 Type dt
= delegate_type
;
335 Type
[] g_args
= null;
336 if (TypeManager
.IsGenericType (delegate_type
)) {
337 g_args
= TypeManager
.GetTypeArguments (delegate_type
);
338 delegate_type
= TypeManager
.DropGenericTypeArguments (delegate_type
);
341 Delegate d
= TypeManager
.LookupDelegate (delegate_type
);
344 return Import
.CreateMethod (TypeBuilder
.GetConstructor (dt
, d
.Constructor
.ConstructorBuilder
));
346 return d
.Constructor
.Spec
;
349 Expression ml
= Expression
.MemberLookup (ctx
, container_type
,
350 null, dt
, ConstructorInfo
.ConstructorName
, MemberTypes
.Constructor
,
351 BindingFlags
.Public
| BindingFlags
.Instance
| BindingFlags
.DeclaredOnly
, Location
.Null
);
353 MethodGroupExpr mg
= ml
as MethodGroupExpr
;
355 ctx
.Report
.Error (-100, Location
.Null
, "Internal error: could not find delegate constructor!");
356 // FIXME: null will cause a crash later
360 return mg
.Methods
[0];
364 // Returns the MethodBase for "Invoke" from a delegate type, this is used
365 // to extract the signature of a delegate.
367 public static MethodSpec
GetInvokeMethod (CompilerContext ctx
, Type container_type
, Type delegate_type
)
369 Type dt
= delegate_type
;
371 Type
[] g_args
= null;
372 if (TypeManager
.IsGenericType (delegate_type
)) {
373 g_args
= TypeManager
.GetTypeArguments (delegate_type
);
374 delegate_type
= TypeManager
.DropGenericTypeArguments (delegate_type
);
377 Delegate d
= TypeManager
.LookupDelegate (delegate_type
);
380 if (g_args
!= null) {
381 invoke
= Import
.CreateMethod (TypeBuilder
.GetMethod (dt
, d
.InvokeBuilder
.MethodBuilder
));
383 // ParametersCompiled p = (ParametersCompiled) d.Parameters.InflateTypes (g_args, g_args);
384 // TypeManager.RegisterMethod (invoke, p);
388 return d
.InvokeBuilder
.Spec
;
391 Expression ml
= Expression
.MemberLookup (ctx
, container_type
, null, dt
,
392 "Invoke", Location
.Null
);
394 MethodGroupExpr mg
= ml
as MethodGroupExpr
;
396 ctx
.Report
.Error (-100, Location
.Null
, "Internal error: could not find Invoke method!");
397 // FIXME: null will cause a crash later
401 invoke
= mg
.Methods
[0];
403 // if (g_args != null) {
404 // AParametersCollection p = TypeManager.GetParameterData (invoke);
405 // p = p.InflateTypes (g_args, g_args);
406 // TypeManager.RegisterMethod (invoke, p);
415 // 15.2 Delegate compatibility
417 public static bool IsTypeCovariant (Expression a
, Type b
)
420 // For each value parameter (a parameter with no ref or out modifier), an
421 // identity conversion or implicit reference conversion exists from the
422 // parameter type in D to the corresponding parameter type in M
427 if (RootContext
.Version
== LanguageVersion
.ISO_1
)
430 return Convert
.ImplicitReferenceConversionExists (a
, b
);
433 public static string FullDelegateDesc (MethodSpec invoke_method
)
435 return TypeManager
.GetFullNameSignature (invoke_method
.MetaInfo
).Replace (".Invoke", "");
438 public Expression InstanceExpression
{
440 return instance_expr
;
443 instance_expr
= value;
449 // Base class for `NewDelegate' and `ImplicitDelegateCreation'
451 public abstract class DelegateCreation
: Expression
, MethodGroupExpr
.IErrorHandler
453 protected MethodSpec constructor_method
;
454 protected MethodSpec delegate_method
;
455 // We keep this to handle IsBase only
456 protected MethodGroupExpr method_group
;
457 protected Expression delegate_instance_expression
;
459 // TODO: Should either cache it or use interface to abstract it
460 public static Arguments
CreateDelegateMethodArguments (AParametersCollection pd
, Location loc
)
462 Arguments delegate_arguments
= new Arguments (pd
.Count
);
463 for (int i
= 0; i
< pd
.Count
; ++i
) {
464 Argument
.AType atype_modifier
;
465 Type atype
= pd
.Types
[i
];
466 switch (pd
.FixedParameters
[i
].ModFlags
) {
467 case Parameter
.Modifier
.REF
:
468 atype_modifier
= Argument
.AType
.Ref
;
469 //atype = atype.GetElementType ();
471 case Parameter
.Modifier
.OUT
:
472 atype_modifier
= Argument
.AType
.Out
;
473 //atype = atype.GetElementType ();
479 delegate_arguments
.Add (new Argument (new TypeExpression (atype
, loc
), atype_modifier
));
481 return delegate_arguments
;
484 public override Expression
CreateExpressionTree (ResolveContext ec
)
486 MemberAccess ma
= new MemberAccess (new MemberAccess (new QualifiedAliasMember ("global", "System", loc
), "Delegate", loc
), "CreateDelegate", loc
);
488 Arguments args
= new Arguments (3);
489 args
.Add (new Argument (new TypeOf (new TypeExpression (type
, loc
), loc
)));
490 args
.Add (new Argument (new NullLiteral (loc
)));
491 args
.Add (new Argument (new TypeOfMethod (delegate_method
, loc
)));
492 Expression e
= new Invocation (ma
, args
).Resolve (ec
);
496 e
= Convert
.ExplicitConversion (ec
, e
, type
, loc
);
500 return e
.CreateExpressionTree (ec
);
503 protected override Expression
DoResolve (ResolveContext ec
)
505 constructor_method
= Delegate
.GetConstructor (ec
.Compiler
, ec
.CurrentType
, type
);
507 var invoke_method
= Delegate
.GetInvokeMethod (ec
.Compiler
, ec
.CurrentType
, type
);
508 method_group
.DelegateType
= type
;
509 method_group
.CustomErrorHandler
= this;
511 Arguments arguments
= CreateDelegateMethodArguments (invoke_method
.Parameters
, loc
);
512 method_group
= method_group
.OverloadResolve (ec
, ref arguments
, false, loc
);
513 if (method_group
== null)
516 delegate_method
= (MethodSpec
) method_group
;
518 if (TypeManager
.IsNullableType (delegate_method
.DeclaringType
)) {
519 ec
.Report
.Error (1728, loc
, "Cannot create delegate from method `{0}' because it is a member of System.Nullable<T> type",
520 TypeManager
.GetFullNameSignature (delegate_method
.MetaInfo
));
524 Invocation
.IsSpecialMethodInvocation (ec
, delegate_method
, loc
);
526 ExtensionMethodGroupExpr emg
= method_group
as ExtensionMethodGroupExpr
;
528 delegate_instance_expression
= emg
.ExtensionExpression
;
529 Type e_type
= delegate_instance_expression
.Type
;
530 if (TypeManager
.IsValueType (e_type
)) {
531 ec
.Report
.Error (1113, loc
, "Extension method `{0}' of value type `{1}' cannot be used to create delegates",
532 TypeManager
.CSharpSignature (delegate_method
.MetaInfo
), TypeManager
.CSharpName (e_type
));
536 Type rt
= TypeManager
.TypeToCoreType (delegate_method
.ReturnType
);
537 Expression ret_expr
= new TypeExpression (rt
, loc
);
538 if (!Delegate
.IsTypeCovariant (ret_expr
, (TypeManager
.TypeToCoreType (invoke_method
.ReturnType
)))) {
539 Error_ConversionFailed (ec
, delegate_method
, ret_expr
);
542 if (Invocation
.IsMethodExcluded (delegate_method
, loc
)) {
543 ec
.Report
.SymbolRelatedToPreviousError (delegate_method
.MetaInfo
);
544 MethodOrOperator m
= TypeManager
.GetMethod (delegate_method
.MetaInfo
) as MethodOrOperator
;
545 if (m
!= null && m
.IsPartialDefinition
) {
546 ec
.Report
.Error (762, loc
, "Cannot create delegate from partial method declaration `{0}'",
547 TypeManager
.CSharpSignature (delegate_method
.MetaInfo
));
549 ec
.Report
.Error (1618, loc
, "Cannot create delegate with `{0}' because it has a Conditional attribute",
550 TypeManager
.CSharpSignature (delegate_method
.MetaInfo
));
554 DoResolveInstanceExpression (ec
);
555 eclass
= ExprClass
.Value
;
559 void DoResolveInstanceExpression (ResolveContext ec
)
562 // Argument is another delegate
564 if (delegate_instance_expression
!= null)
567 if (method_group
.IsStatic
) {
568 delegate_instance_expression
= null;
572 Expression instance
= method_group
.InstanceExpression
;
573 if (instance
!= null && instance
!= EmptyExpression
.Null
) {
574 delegate_instance_expression
= instance
;
575 Type instance_type
= delegate_instance_expression
.Type
;
576 if (TypeManager
.IsValueType (instance_type
) || TypeManager
.IsGenericParameter (instance_type
)) {
577 delegate_instance_expression
= new BoxedCast (
578 delegate_instance_expression
, TypeManager
.object_type
);
581 delegate_instance_expression
= ec
.GetThis (loc
);
585 public override void Emit (EmitContext ec
)
587 if (delegate_instance_expression
== null)
588 ec
.ig
.Emit (OpCodes
.Ldnull
);
590 delegate_instance_expression
.Emit (ec
);
592 if (!delegate_method
.DeclaringType
.IsSealed
&& delegate_method
.IsVirtual
&& !method_group
.IsBase
) {
593 ec
.ig
.Emit (OpCodes
.Dup
);
594 ec
.ig
.Emit (OpCodes
.Ldvirtftn
, (MethodInfo
) delegate_method
.MetaInfo
);
596 ec
.ig
.Emit (OpCodes
.Ldftn
, (MethodInfo
) delegate_method
.MetaInfo
);
599 ec
.ig
.Emit (OpCodes
.Newobj
, (ConstructorInfo
) constructor_method
.MetaInfo
);
602 void Error_ConversionFailed (ResolveContext ec
, MethodSpec method
, Expression return_type
)
604 var invoke_method
= Delegate
.GetInvokeMethod (ec
.Compiler
, ec
.CurrentType
, type
);
605 string member_name
= delegate_instance_expression
!= null ?
606 Delegate
.FullDelegateDesc (method
) :
607 TypeManager
.GetFullNameSignature (method
.MetaInfo
);
609 ec
.Report
.SymbolRelatedToPreviousError (type
);
610 ec
.Report
.SymbolRelatedToPreviousError (method
.MetaInfo
);
611 if (RootContext
.Version
== LanguageVersion
.ISO_1
) {
612 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",
613 TypeManager
.CSharpName (method
.ReturnType
), member_name
,
614 TypeManager
.CSharpName (invoke_method
.ReturnType
), Delegate
.FullDelegateDesc (invoke_method
));
617 if (return_type
== null) {
618 ec
.Report
.Error (123, loc
, "A method or delegate `{0}' parameters do not match delegate `{1}' parameters",
619 member_name
, Delegate
.FullDelegateDesc (invoke_method
));
623 ec
.Report
.Error (407, loc
, "A method or delegate `{0} {1}' return type does not match delegate `{2} {3}' return type",
624 return_type
.GetSignatureForError (), member_name
,
625 TypeManager
.CSharpName (invoke_method
.ReturnType
), Delegate
.FullDelegateDesc (invoke_method
));
628 public static bool ImplicitStandardConversionExists (ResolveContext ec
, MethodGroupExpr mg
, Type target_type
)
630 if (target_type
== TypeManager
.delegate_type
|| target_type
== TypeManager
.multicast_delegate_type
)
633 mg
.DelegateType
= target_type
;
634 var invoke
= Delegate
.GetInvokeMethod (ec
.Compiler
, null, target_type
);
636 Arguments arguments
= CreateDelegateMethodArguments (invoke
.Parameters
, mg
.Location
);
637 return mg
.OverloadResolve (ec
, ref arguments
, true, mg
.Location
) != null;
640 public override void MutateHoistedGenericType (AnonymousMethodStorey storey
)
642 if (delegate_instance_expression
!= null)
643 delegate_instance_expression
.MutateHoistedGenericType (storey
);
645 storey
.MutateGenericMethod (delegate_method
);
646 storey
.MutateConstructor (constructor_method
);
649 #region IErrorHandler Members
651 public bool NoExactMatch (ResolveContext ec
, MethodSpec method
)
653 if (method
.IsGenericMethod
)
656 Error_ConversionFailed (ec
, method
, null);
660 public bool AmbiguousCall (ResolveContext ec
, MethodSpec ambiguous
)
669 // Created from the conversion code
671 public class ImplicitDelegateCreation
: DelegateCreation
673 ImplicitDelegateCreation (Type t
, MethodGroupExpr mg
, Location l
)
676 this.method_group
= mg
;
680 static public Expression
Create (ResolveContext ec
, MethodGroupExpr mge
,
681 Type target_type
, Location loc
)
683 ImplicitDelegateCreation d
= new ImplicitDelegateCreation (target_type
, mge
, loc
);
684 return d
.DoResolve (ec
);
689 // A delegate-creation-expression, invoked from the `New' class
691 public class NewDelegate
: DelegateCreation
693 public Arguments Arguments
;
696 // This constructor is invoked from the `New' expression
698 public NewDelegate (Type type
, Arguments Arguments
, Location loc
)
701 this.Arguments
= Arguments
;
705 protected override Expression
DoResolve (ResolveContext ec
)
707 if (Arguments
== null || Arguments
.Count
!= 1) {
708 ec
.Report
.Error (149, loc
, "Method name expected");
712 Argument a
= Arguments
[0];
713 if (!a
.ResolveMethodGroup (ec
))
716 Expression e
= a
.Expr
;
718 AnonymousMethodExpression ame
= e
as AnonymousMethodExpression
;
719 if (ame
!= null && RootContext
.Version
!= LanguageVersion
.ISO_1
) {
720 e
= ame
.Compatible (ec
, type
);
724 return e
.Resolve (ec
);
727 method_group
= e
as MethodGroupExpr
;
728 if (method_group
== null) {
729 if (TypeManager
.IsDynamicType (e
.Type
)) {
730 e
= Convert
.ImplicitConversionRequired (ec
, e
, type
, loc
);
731 } else if (!TypeManager
.IsDelegateType (e
.Type
)) {
732 e
.Error_UnexpectedKind (ec
, ResolveFlags
.MethodGroup
| ResolveFlags
.Type
, loc
);
737 // An argument is not a method but another delegate
739 delegate_instance_expression
= e
;
740 method_group
= new MethodGroupExpr (new [] {
741 Delegate
.GetInvokeMethod (ec
.Compiler
, ec
.CurrentType
, e
.Type
) }, e
.Type
, loc
);
744 return base.DoResolve (ec
);
749 // Invocation converted to delegate Invoke call
751 class DelegateInvocation
: ExpressionStatement
753 readonly Expression InstanceExpr
;
757 public DelegateInvocation (Expression instance_expr
, Arguments args
, Location loc
)
759 this.InstanceExpr
= instance_expr
;
760 this.arguments
= args
;
764 public override Expression
CreateExpressionTree (ResolveContext ec
)
766 Arguments args
= Arguments
.CreateForExpressionTree (ec
, this.arguments
,
767 InstanceExpr
.CreateExpressionTree (ec
));
769 return CreateExpressionFactoryCall (ec
, "Invoke", args
);
772 protected override Expression
DoResolve (ResolveContext ec
)
774 if (InstanceExpr
is EventExpr
) {
775 ((EventExpr
) InstanceExpr
).Error_CannotAssign (ec
);
779 Type del_type
= InstanceExpr
.Type
;
780 if (del_type
== null)
783 method
= Delegate
.GetInvokeMethod (ec
.Compiler
, ec
.CurrentType
, del_type
);
785 var me
= new MethodGroupExpr (new [] { mb }
, del_type
, loc
);
786 me
.InstanceExpression
= InstanceExpr
;
788 AParametersCollection pd
= mb
.Parameters
;
789 int pd_count
= pd
.Count
;
791 int arg_count
= arguments
== null ? 0 : arguments
.Count
;
793 bool params_method
= pd
.HasParams
;
794 bool is_params_applicable
= false;
795 bool is_applicable
= me
.IsApplicable (ec
, ref arguments
, arg_count
, ref mb
, ref is_params_applicable
) == 0;
796 if (arguments
!= null)
797 arg_count
= arguments
.Count
;
799 if (!is_applicable
&& !params_method
&& arg_count
!= pd_count
) {
800 ec
.Report
.Error (1593, loc
, "Delegate `{0}' does not take `{1}' arguments",
801 TypeManager
.CSharpName (del_type
), arg_count
.ToString ());
802 } else if (arguments
== null || !arguments
.HasDynamic
) {
803 me
.VerifyArgumentsCompat (ec
, ref arguments
, arg_count
, mb
,
804 is_params_applicable
|| (!is_applicable
&& params_method
), false, loc
);
807 type
= TypeManager
.TypeToCoreType (method
.ReturnType
);
808 eclass
= ExprClass
.Value
;
812 public override void Emit (EmitContext ec
)
815 // Invocation on delegates call the virtual Invoke member
816 // so we are always `instance' calls
818 Invocation
.EmitCall (ec
, false, InstanceExpr
, method
, arguments
, loc
);
821 public override void EmitStatement (EmitContext ec
)
825 // Pop the return value if there is one
827 if (type
!= TypeManager
.void_type
)
828 ec
.ig
.Emit (OpCodes
.Pop
);
831 public override System
.Linq
.Expressions
.Expression
MakeExpression (BuilderContext ctx
)
833 return Invocation
.MakeExpression (ctx
, InstanceExpr
, method
, arguments
);
836 public override void MutateHoistedGenericType (AnonymousMethodStorey storey
)
838 storey
.MutateGenericMethod (method
);
839 type
= storey
.MutateType (type
);
841 if (arguments
!= null)
842 arguments
.MutateHoistedGenericType (storey
);
844 InstanceExpr
.MutateHoistedGenericType (storey
);