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-2008 Novell, Inc (http://www.ximian.com)
16 using System
.Collections
;
17 using System
.Reflection
;
18 using System
.Reflection
.Emit
;
21 namespace Mono
.CSharp
{
26 public class Delegate
: DeclSpace
, IMemberContainer
28 FullNamedExpression ReturnType
;
29 public ParametersCompiled Parameters
;
31 public ConstructorBuilder ConstructorBuilder
;
32 public MethodBuilder InvokeBuilder
;
33 public MethodBuilder BeginInvokeBuilder
;
34 public MethodBuilder EndInvokeBuilder
;
38 static string[] attribute_targets
= new string [] { "type", "return" }
;
40 Expression instance_expr
;
41 MethodBase delegate_method
;
42 ReturnParameter return_attributes
;
44 MemberCache member_cache
;
46 const MethodAttributes mattr
= MethodAttributes
.Public
| MethodAttributes
.HideBySig
|
47 MethodAttributes
.Virtual
| MethodAttributes
.NewSlot
;
49 const int AllowedModifiers
=
57 public Delegate (NamespaceEntry ns
, DeclSpace parent
, FullNamedExpression type
,
58 int mod_flags
, MemberName name
, ParametersCompiled param_list
,
60 : base (ns
, parent
, name
, attrs
)
63 this.ReturnType
= type
;
64 ModFlags
= Modifiers
.Check (AllowedModifiers
, mod_flags
,
65 IsTopLevel
? Modifiers
.INTERNAL
:
66 Modifiers
.PRIVATE
, name
.Location
);
67 Parameters
= param_list
;
70 public override void ApplyAttributeBuilder (Attribute a
, CustomAttributeBuilder cb
, PredefinedAttributes pa
)
72 if (a
.Target
== AttributeTargets
.ReturnValue
) {
73 if (return_attributes
== null)
74 return_attributes
= new ReturnParameter (InvokeBuilder
, Location
);
76 return_attributes
.ApplyAttributeBuilder (a
, cb
, pa
);
80 base.ApplyAttributeBuilder (a
, cb
, pa
);
83 public override TypeBuilder
DefineType ()
85 if (TypeBuilder
!= null)
89 if (TypeManager
.NamespaceClash (Name
, Location
))
92 ModuleBuilder builder
= Module
.Builder
;
94 TypeBuilder
= builder
.DefineType (
95 Name
, TypeAttr
, TypeManager
.multicast_delegate_type
);
97 TypeBuilder builder
= Parent
.TypeBuilder
;
99 string name
= Name
.Substring (1 + Name
.LastIndexOf ('.'));
100 TypeBuilder
= builder
.DefineNestedType (
101 name
, TypeAttr
, TypeManager
.multicast_delegate_type
);
104 TypeManager
.AddUserType (this);
108 string[] param_names
= new string [TypeParameters
.Length
];
109 for (int i
= 0; i
< TypeParameters
.Length
; i
++)
110 param_names
[i
] = TypeParameters
[i
].Name
;
112 GenericTypeParameterBuilder
[] gen_params
;
113 gen_params
= TypeBuilder
.DefineGenericParameters (param_names
);
115 int offset
= CountTypeParameters
- CurrentTypeParameters
.Length
;
116 for (int i
= offset
; i
< gen_params
.Length
; i
++)
117 CurrentTypeParameters
[i
- offset
].Define (gen_params
[i
]);
119 foreach (TypeParameter type_param
in CurrentTypeParameters
) {
120 if (!type_param
.Resolve (this))
124 Expression current
= new SimpleName (
125 MemberName
.Basename
, TypeParameters
, Location
);
126 current
= current
.ResolveAsTypeTerminal (this, false);
130 CurrentType
= current
.Type
;
137 public override bool Define ()
140 foreach (TypeParameter type_param
in TypeParameters
) {
141 if (!type_param
.Resolve (this))
145 foreach (TypeParameter type_param
in TypeParameters
) {
146 if (!type_param
.DefineType (this))
151 member_cache
= new MemberCache (TypeManager
.multicast_delegate_type
, this);
153 // FIXME: POSSIBLY make this static, as it is always constant
155 Type
[] const_arg_types
= new Type
[2];
156 const_arg_types
[0] = TypeManager
.object_type
;
157 const_arg_types
[1] = TypeManager
.intptr_type
;
159 const MethodAttributes ctor_mattr
= MethodAttributes
.RTSpecialName
| MethodAttributes
.SpecialName
|
160 MethodAttributes
.HideBySig
| MethodAttributes
.Public
;
162 ConstructorBuilder
= TypeBuilder
.DefineConstructor (ctor_mattr
,
163 CallingConventions
.Standard
,
166 ConstructorBuilder
.DefineParameter (1, ParameterAttributes
.None
, "object");
167 ConstructorBuilder
.DefineParameter (2, ParameterAttributes
.None
, "method");
169 // HACK because System.Reflection.Emit is lame
171 IParameterData
[] fixed_pars
= new IParameterData
[] {
172 new ParameterData ("object", Parameter
.Modifier
.NONE
),
173 new ParameterData ("method", Parameter
.Modifier
.NONE
)
176 AParametersCollection const_parameters
= new ParametersImported (
178 new Type
[] { TypeManager.object_type, TypeManager.intptr_type }
);
180 TypeManager
.RegisterMethod (ConstructorBuilder
, const_parameters
);
181 member_cache
.AddMember (ConstructorBuilder
, this);
183 ConstructorBuilder
.SetImplementationFlags (MethodImplAttributes
.Runtime
);
186 // Here the various methods like Invoke, BeginInvoke etc are defined
188 // First, call the `out of band' special method for
189 // defining recursively any types we need:
191 if (!Parameters
.Resolve (this))
198 // Check accessibility
199 foreach (Type partype
in Parameters
.Types
){
200 if (!IsAccessibleAs (partype
)) {
201 Report
.SymbolRelatedToPreviousError (partype
);
202 Report
.Error (59, Location
,
203 "Inconsistent accessibility: parameter type `{0}' is less accessible than delegate `{1}'",
204 TypeManager
.CSharpName (partype
),
205 GetSignatureForError ());
210 ReturnType
= ReturnType
.ResolveAsTypeTerminal (this, false);
211 if (ReturnType
== null)
214 ret_type
= ReturnType
.Type
;
216 if (!IsAccessibleAs (ret_type
)) {
217 Report
.SymbolRelatedToPreviousError (ret_type
);
218 Report
.Error (58, Location
,
219 "Inconsistent accessibility: return type `" +
220 TypeManager
.CSharpName (ret_type
) + "' is less " +
221 "accessible than delegate `" + GetSignatureForError () + "'");
225 CheckProtectedModifier ();
227 if (RootContext
.StdLib
&& TypeManager
.IsSpecialType (ret_type
)) {
228 Method
.Error1599 (Location
, ret_type
);
233 if (ret_type
.IsGenericParameter
&& (ret_type
.GenericParameterAttributes
& GenericParameterAttributes
.Contravariant
) != 0) {
234 Report
.Error (-33, Location
, "Contravariant type parameters can only be used in input positions");
240 // We don't have to check any others because they are all
241 // guaranteed to be accessible - they are standard types.
244 CallingConventions cc
= Parameters
.CallingConvention
;
246 InvokeBuilder
= TypeBuilder
.DefineMethod ("Invoke",
250 Parameters
.GetEmitTypes ());
252 InvokeBuilder
.SetImplementationFlags (MethodImplAttributes
.Runtime
);
254 TypeManager
.RegisterMethod (InvokeBuilder
, Parameters
);
255 member_cache
.AddMember (InvokeBuilder
, this);
257 if (TypeManager
.iasyncresult_type
!= null && TypeManager
.asynccallback_type
!= null) {
258 DefineAsyncMethods (cc
);
264 void DefineAsyncMethods (CallingConventions cc
)
269 ParametersCompiled async_parameters
= ParametersCompiled
.MergeGenerated (Parameters
, false,
271 new Parameter (null, "callback", Parameter
.Modifier
.NONE
, null, Location
),
272 new Parameter (null, "object", Parameter
.Modifier
.NONE
, null, Location
)
275 TypeManager
.asynccallback_type
,
276 TypeManager
.object_type
280 BeginInvokeBuilder
= TypeBuilder
.DefineMethod ("BeginInvoke",
281 mattr
, cc
, TypeManager
.iasyncresult_type
, async_parameters
.GetEmitTypes ());
283 BeginInvokeBuilder
.SetImplementationFlags (MethodImplAttributes
.Runtime
);
284 TypeManager
.RegisterMethod (BeginInvokeBuilder
, async_parameters
);
285 member_cache
.AddMember (BeginInvokeBuilder
, this);
288 // EndInvoke is a bit more interesting, all the parameters labeled as
289 // out or ref have to be duplicated here.
293 // Define parameters, and count out/ref parameters
295 ParametersCompiled end_parameters
;
298 foreach (Parameter p
in Parameters
.FixedParameters
) {
299 if ((p
.ModFlags
& Parameter
.Modifier
.ISBYREF
) != 0)
303 if (out_params
> 0) {
304 Type
[] end_param_types
= new Type
[out_params
];
305 Parameter
[] end_params
= new Parameter
[out_params
];
308 for (int i
= 0; i
< Parameters
.FixedParameters
.Length
; ++i
) {
309 Parameter p
= Parameters
[i
];
310 if ((p
.ModFlags
& Parameter
.Modifier
.ISBYREF
) == 0)
313 end_param_types
[param
] = Parameters
.Types
[i
];
314 end_params
[param
] = p
;
317 end_parameters
= ParametersCompiled
.CreateFullyResolved (end_params
, end_param_types
);
319 end_parameters
= ParametersCompiled
.EmptyReadOnlyParameters
;
322 end_parameters
= ParametersCompiled
.MergeGenerated (end_parameters
, false,
323 new Parameter (null, "result", Parameter
.Modifier
.NONE
, null, Location
), TypeManager
.iasyncresult_type
);
326 // Create method, define parameters, register parameters with type system
328 EndInvokeBuilder
= TypeBuilder
.DefineMethod ("EndInvoke", mattr
, cc
, ret_type
, end_parameters
.GetEmitTypes ());
329 EndInvokeBuilder
.SetImplementationFlags (MethodImplAttributes
.Runtime
);
331 end_parameters
.ApplyAttributes (EndInvokeBuilder
);
332 TypeManager
.RegisterMethod (EndInvokeBuilder
, end_parameters
);
333 member_cache
.AddMember (EndInvokeBuilder
, this);
336 public override void Emit ()
338 Parameters
.ApplyAttributes (InvokeBuilder
);
340 if (BeginInvokeBuilder
!= null) {
341 ParametersCompiled p
= (ParametersCompiled
) TypeManager
.GetParameterData (BeginInvokeBuilder
);
342 p
.ApplyAttributes (BeginInvokeBuilder
);
345 if (OptAttributes
!= null) {
346 OptAttributes
.Emit ();
352 protected override TypeAttributes TypeAttr
{
354 return Modifiers
.TypeAttr (ModFlags
, IsTopLevel
) |
355 TypeAttributes
.Class
| TypeAttributes
.Sealed
|
360 public override string[] ValidAttributeTargets
{
362 return attribute_targets
;
367 protected override bool VerifyClsCompliance ()
369 if (!base.VerifyClsCompliance ()) {
373 Parameters
.VerifyClsCompliance ();
375 if (!AttributeTester
.IsClsCompliant (ReturnType
.Type
)) {
376 Report
.Warning (3002, 1, Location
, "Return type of `{0}' is not CLS-compliant",
377 GetSignatureForError ());
383 public static ConstructorInfo
GetConstructor (Type container_type
, Type delegate_type
)
385 Type dt
= delegate_type
;
386 Type
[] g_args
= null;
387 if (TypeManager
.IsGenericType (delegate_type
)) {
388 g_args
= TypeManager
.GetTypeArguments (delegate_type
);
389 delegate_type
= TypeManager
.DropGenericTypeArguments (delegate_type
);
392 Delegate d
= TypeManager
.LookupDelegate (delegate_type
);
396 return TypeBuilder
.GetConstructor (dt
, d
.ConstructorBuilder
);
398 return d
.ConstructorBuilder
;
401 Expression ml
= Expression
.MemberLookup (container_type
,
402 null, dt
, ConstructorInfo
.ConstructorName
, MemberTypes
.Constructor
,
403 BindingFlags
.Public
| BindingFlags
.Instance
| BindingFlags
.DeclaredOnly
, Location
.Null
);
405 MethodGroupExpr mg
= ml
as MethodGroupExpr
;
407 Report
.Error (-100, Location
.Null
, "Internal error: could not find delegate constructor!");
408 // FIXME: null will cause a crash later
412 return (ConstructorInfo
) mg
.Methods
[0];
416 // Returns the MethodBase for "Invoke" from a delegate type, this is used
417 // to extract the signature of a delegate.
419 public static MethodInfo
GetInvokeMethod (Type container_type
, Type delegate_type
)
421 Type dt
= delegate_type
;
423 Type
[] g_args
= null;
424 if (TypeManager
.IsGenericType (delegate_type
)) {
425 g_args
= TypeManager
.GetTypeArguments (delegate_type
);
426 delegate_type
= TypeManager
.DropGenericTypeArguments (delegate_type
);
429 Delegate d
= TypeManager
.LookupDelegate (delegate_type
);
433 if (g_args
!= null) {
434 invoke
= TypeBuilder
.GetMethod (dt
, d
.InvokeBuilder
);
436 ParametersCompiled p
= (ParametersCompiled
) d
.Parameters
.InflateTypes (g_args
, g_args
);
437 TypeManager
.RegisterMethod (invoke
, p
);
442 return d
.InvokeBuilder
;
445 Expression ml
= Expression
.MemberLookup (container_type
, null, dt
,
446 "Invoke", Location
.Null
);
448 MethodGroupExpr mg
= ml
as MethodGroupExpr
;
450 Report
.Error (-100, Location
.Null
, "Internal error: could not find Invoke method!");
451 // FIXME: null will cause a crash later
455 invoke
= (MethodInfo
) mg
.Methods
[0];
457 if (g_args
!= null) {
458 AParametersCollection p
= TypeManager
.GetParameterData (invoke
);
459 p
= p
.InflateTypes (g_args
, g_args
);
460 TypeManager
.RegisterMethod (invoke
, p
);
469 // 15.2 Delegate compatibility
471 public static bool IsTypeCovariant (Expression a
, Type b
)
474 // For each value parameter (a parameter with no ref or out modifier), an
475 // identity conversion or implicit reference conversion exists from the
476 // parameter type in D to the corresponding parameter type in M
481 if (RootContext
.Version
== LanguageVersion
.ISO_1
)
484 return Convert
.ImplicitReferenceConversionExists (a
, b
);
488 /// Verifies whether the method in question is compatible with the delegate
489 /// Returns the method itself if okay and null if not.
491 public static MethodBase
VerifyMethod (Type container_type
, Type delegate_type
,
492 MethodGroupExpr old_mg
, MethodBase mb
)
494 bool is_method_definition
= TypeManager
.IsGenericMethodDefinition (mb
);
496 MethodInfo invoke_mb
= GetInvokeMethod (container_type
, delegate_type
);
497 if (invoke_mb
== null)
500 if (is_method_definition
)
501 invoke_mb
= (MethodInfo
) TypeManager
.DropGenericMethodArguments (invoke_mb
);
503 AParametersCollection invoke_pd
= TypeManager
.GetParameterData (invoke_mb
);
506 if (!is_method_definition
&& old_mg
.type_arguments
== null &&
507 !TypeManager
.InferTypeArguments (invoke_pd
, ref mb
))
510 AParametersCollection pd
= TypeManager
.GetParameterData (mb
);
512 if (invoke_pd
.Count
!= pd
.Count
)
515 for (int i
= pd
.Count
; i
> 0; ) {
518 Type invoke_pd_type
= invoke_pd
.Types
[i
];
519 Type pd_type
= pd
.Types
[i
];
520 Parameter
.Modifier invoke_pd_type_mod
= invoke_pd
.FixedParameters
[i
].ModFlags
;
521 Parameter
.Modifier pd_type_mod
= pd
.FixedParameters
[i
].ModFlags
;
523 invoke_pd_type_mod
&= ~Parameter
.Modifier
.PARAMS
;
524 pd_type_mod
&= ~Parameter
.Modifier
.PARAMS
;
526 if (invoke_pd_type_mod
!= pd_type_mod
)
529 if (TypeManager
.IsEqual (invoke_pd_type
, pd_type
))
532 if (IsTypeCovariant (new EmptyExpression (invoke_pd_type
), pd_type
))
538 Type invoke_mb_retval
= ((MethodInfo
) invoke_mb
).ReturnType
;
539 Type mb_retval
= ((MethodInfo
) mb
).ReturnType
;
540 if (TypeManager
.TypeToCoreType (invoke_mb_retval
) == TypeManager
.TypeToCoreType (mb_retval
))
543 //if (!IsTypeCovariant (mb_retval, invoke_mb_retval))
546 if (RootContext
.Version
== LanguageVersion
.ISO_1
)
553 // Verifies whether the invocation arguments are compatible with the
554 // delegate's target method
556 public static bool VerifyApplicability (EmitContext ec
, Type delegate_type
,
557 ArrayList args
, Location loc
)
564 arg_count
= args
.Count
;
566 MethodBase mb
= GetInvokeMethod (ec
.ContainerType
, delegate_type
);
567 MethodGroupExpr me
= new MethodGroupExpr (new MemberInfo
[] { mb }
, delegate_type
, loc
);
569 AParametersCollection pd
= TypeManager
.GetParameterData (mb
);
571 int pd_count
= pd
.Count
;
573 bool params_method
= pd
.HasParams
;
574 bool is_params_applicable
= false;
575 bool is_applicable
= me
.IsApplicable (ec
, args
, arg_count
, ref mb
, ref is_params_applicable
) == 0;
577 if (!is_applicable
&& !params_method
&& arg_count
!= pd_count
) {
578 Report
.Error (1593, loc
, "Delegate `{0}' does not take `{1}' arguments",
579 TypeManager
.CSharpName (delegate_type
), arg_count
.ToString ());
583 return me
.VerifyArgumentsCompat (
584 ec
, ref args
, arg_count
, mb
,
585 is_params_applicable
|| (!is_applicable
&& params_method
),
589 public static string FullDelegateDesc (MethodBase invoke_method
)
591 return TypeManager
.GetFullNameSignature (invoke_method
).Replace (".Invoke", "");
594 public override MemberCache MemberCache
{
600 public Expression InstanceExpression
{
602 return instance_expr
;
605 instance_expr
= value;
609 public MethodBase TargetMethod
{
611 return delegate_method
;
614 delegate_method
= value;
618 public Type TargetReturnType
{
624 public override AttributeTargets AttributeTargets
{
626 return AttributeTargets
.Delegate
;
631 // Represents header string for documentation comment.
633 public override string DocCommentHeader
{
637 #region IMemberContainer Members
639 string IMemberContainer
.Name
641 get { throw new NotImplementedException (); }
644 Type IMemberContainer
.Type
646 get { throw new NotImplementedException (); }
649 MemberCache IMemberContainer
.BaseCache
651 get { throw new NotImplementedException (); }
654 bool IMemberContainer
.IsInterface
{
660 MemberList IMemberContainer
.GetMembers (MemberTypes mt
, BindingFlags bf
)
662 throw new NotImplementedException ();
669 // Base class for `NewDelegate' and `ImplicitDelegateCreation'
671 public abstract class DelegateCreation
: Expression
, MethodGroupExpr
.IErrorHandler
673 protected ConstructorInfo constructor_method
;
674 protected MethodInfo delegate_method
;
675 // We keep this to handle IsBase only
676 protected MethodGroupExpr method_group
;
677 protected Expression delegate_instance_expression
;
679 public static ArrayList
CreateDelegateMethodArguments (MethodInfo invoke_method
, Location loc
)
681 AParametersCollection pd
= TypeManager
.GetParameterData (invoke_method
);
682 ArrayList delegate_arguments
= new ArrayList (pd
.Count
);
683 for (int i
= 0; i
< pd
.Count
; ++i
) {
684 Argument
.AType atype_modifier
;
685 Type atype
= pd
.Types
[i
];
686 switch (pd
.FixedParameters
[i
].ModFlags
) {
687 case Parameter
.Modifier
.REF
:
688 atype_modifier
= Argument
.AType
.Ref
;
689 //atype = atype.GetElementType ();
691 case Parameter
.Modifier
.OUT
:
692 atype_modifier
= Argument
.AType
.Out
;
693 //atype = atype.GetElementType ();
695 case Parameter
.Modifier
.ARGLIST
:
696 // __arglist is not valid
697 throw new InternalErrorException ("__arglist modifier");
699 atype_modifier
= Argument
.AType
.Expression
;
702 delegate_arguments
.Add (new Argument (new TypeExpression (atype
, loc
), atype_modifier
));
704 return delegate_arguments
;
707 public override Expression
CreateExpressionTree (EmitContext ec
)
709 MemberAccess ma
= new MemberAccess (new MemberAccess (new QualifiedAliasMember ("global", "System", loc
), "Delegate", loc
), "CreateDelegate", loc
);
711 ArrayList args
= new ArrayList (3);
712 args
.Add (new Argument (new TypeOf (new TypeExpression (type
, loc
), loc
)));
713 args
.Add (new Argument (new NullLiteral (loc
)));
714 args
.Add (new Argument (new TypeOfMethodInfo (delegate_method
, loc
)));
715 Expression e
= new Invocation (ma
, args
).Resolve (ec
);
719 e
= Convert
.ExplicitConversion (ec
, e
, type
, loc
);
723 return e
.CreateExpressionTree (ec
);
726 public override Expression
DoResolve (EmitContext ec
)
728 constructor_method
= Delegate
.GetConstructor (ec
.ContainerType
, type
);
730 MethodInfo invoke_method
= Delegate
.GetInvokeMethod (ec
.ContainerType
, type
);
731 method_group
.DelegateType
= type
;
732 method_group
.CustomErrorHandler
= this;
734 ArrayList arguments
= CreateDelegateMethodArguments (invoke_method
, loc
);
735 method_group
= method_group
.OverloadResolve (ec
, ref arguments
, false, loc
);
736 if (method_group
== null)
739 delegate_method
= (MethodInfo
) method_group
;
741 if (TypeManager
.IsNullableType (delegate_method
.DeclaringType
)) {
742 Report
.Error (1728, loc
, "Cannot create delegate from method `{0}' because it is a member of System.Nullable<T> type",
743 TypeManager
.GetFullNameSignature (delegate_method
));
747 Invocation
.IsSpecialMethodInvocation (delegate_method
, loc
);
749 ExtensionMethodGroupExpr emg
= method_group
as ExtensionMethodGroupExpr
;
751 delegate_instance_expression
= emg
.ExtensionExpression
;
752 Type e_type
= delegate_instance_expression
.Type
;
753 if (TypeManager
.IsValueType (e_type
)) {
754 Report
.Error (1113, loc
, "Extension method `{0}' of value type `{1}' cannot be used to create delegates",
755 TypeManager
.CSharpSignature (delegate_method
), TypeManager
.CSharpName (e_type
));
759 Type rt
= TypeManager
.TypeToCoreType (delegate_method
.ReturnType
);
760 Expression ret_expr
= new TypeExpression (rt
, loc
);
761 if (!Delegate
.IsTypeCovariant (ret_expr
, (TypeManager
.TypeToCoreType (invoke_method
.ReturnType
)))) {
762 Error_ConversionFailed (ec
, delegate_method
, ret_expr
);
765 if (Invocation
.IsMethodExcluded (delegate_method
, loc
)) {
766 Report
.SymbolRelatedToPreviousError (delegate_method
);
767 MethodOrOperator m
= TypeManager
.GetMethod (delegate_method
) as MethodOrOperator
;
768 if (m
!= null && m
.IsPartialDefinition
) {
769 Report
.Error (762, loc
, "Cannot create delegate from partial method declaration `{0}'",
770 TypeManager
.CSharpSignature (delegate_method
));
772 Report
.Error (1618, loc
, "Cannot create delegate with `{0}' because it has a Conditional attribute",
773 TypeManager
.CSharpSignature (delegate_method
));
777 DoResolveInstanceExpression (ec
);
778 eclass
= ExprClass
.Value
;
782 void DoResolveInstanceExpression (EmitContext ec
)
785 // Argument is another delegate
787 if (delegate_instance_expression
!= null)
790 Expression instance
= method_group
.InstanceExpression
;
791 if (instance
!= null && instance
!= EmptyExpression
.Null
) {
792 delegate_instance_expression
= instance
;
793 Type instance_type
= delegate_instance_expression
.Type
;
794 if (TypeManager
.IsValueType (instance_type
) || TypeManager
.IsGenericParameter (instance_type
)) {
795 delegate_instance_expression
= new BoxedCast (
796 delegate_instance_expression
, TypeManager
.object_type
);
798 } else if (!delegate_method
.IsStatic
&& !ec
.IsStatic
) {
799 delegate_instance_expression
= ec
.GetThis (loc
);
803 public override void Emit (EmitContext ec
)
805 if (delegate_instance_expression
== null)
806 ec
.ig
.Emit (OpCodes
.Ldnull
);
808 delegate_instance_expression
.Emit (ec
);
810 if (!delegate_method
.DeclaringType
.IsSealed
&& delegate_method
.IsVirtual
&& !method_group
.IsBase
) {
811 ec
.ig
.Emit (OpCodes
.Dup
);
812 ec
.ig
.Emit (OpCodes
.Ldvirtftn
, delegate_method
);
814 ec
.ig
.Emit (OpCodes
.Ldftn
, delegate_method
);
817 ec
.ig
.Emit (OpCodes
.Newobj
, constructor_method
);
820 void Error_ConversionFailed (EmitContext ec
, MethodBase method
, Expression return_type
)
822 MethodInfo invoke_method
= Delegate
.GetInvokeMethod (ec
.ContainerType
, type
);
823 string member_name
= delegate_instance_expression
!= null ?
824 Delegate
.FullDelegateDesc (method
) :
825 TypeManager
.GetFullNameSignature (method
);
827 Report
.SymbolRelatedToPreviousError (type
);
828 Report
.SymbolRelatedToPreviousError (method
);
829 if (RootContext
.Version
== LanguageVersion
.ISO_1
) {
830 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",
831 TypeManager
.CSharpName (((MethodInfo
) method
).ReturnType
), member_name
,
832 TypeManager
.CSharpName (invoke_method
.ReturnType
), Delegate
.FullDelegateDesc (invoke_method
));
835 if (return_type
== null) {
836 Report
.Error (123, loc
, "A method or delegate `{0}' parameters do not match delegate `{1}' parameters",
837 member_name
, Delegate
.FullDelegateDesc (invoke_method
));
841 Report
.Error (407, loc
, "A method or delegate `{0} {1}' return type does not match delegate `{2} {3}' return type",
842 return_type
.GetSignatureForError (), member_name
,
843 TypeManager
.CSharpName (invoke_method
.ReturnType
), Delegate
.FullDelegateDesc (invoke_method
));
846 public static MethodBase
ImplicitStandardConversionExists (MethodGroupExpr mg
, Type target_type
)
848 if (target_type
== TypeManager
.delegate_type
|| target_type
== TypeManager
.multicast_delegate_type
)
851 foreach (MethodInfo mi
in mg
.Methods
){
852 MethodBase mb
= Delegate
.VerifyMethod (mg
.DeclaringType
, target_type
, mg
, mi
);
859 public override void MutateHoistedGenericType (AnonymousMethodStorey storey
)
861 if (delegate_instance_expression
!= null)
862 delegate_instance_expression
.MutateHoistedGenericType (storey
);
864 delegate_method
= storey
.MutateGenericMethod (delegate_method
);
865 constructor_method
= storey
.MutateConstructor (constructor_method
);
868 #region IErrorHandler Members
870 public bool NoExactMatch (EmitContext ec
, MethodBase method
)
872 if (TypeManager
.IsGenericMethod (method
))
875 Error_ConversionFailed (ec
, method
, null);
879 public bool AmbiguousCall (MethodBase ambiguous
)
888 // Created from the conversion code
890 public class ImplicitDelegateCreation
: DelegateCreation
892 ImplicitDelegateCreation (Type t
, MethodGroupExpr mg
, Location l
)
895 this.method_group
= mg
;
899 static public Expression
Create (EmitContext ec
, MethodGroupExpr mge
,
900 Type target_type
, Location loc
)
902 ImplicitDelegateCreation d
= new ImplicitDelegateCreation (target_type
, mge
, loc
);
903 return d
.DoResolve (ec
);
908 // A delegate-creation-expression, invoked from the `New' class
910 public class NewDelegate
: DelegateCreation
912 public ArrayList Arguments
;
915 // This constructor is invoked from the `New' expression
917 public NewDelegate (Type type
, ArrayList Arguments
, Location loc
)
920 this.Arguments
= Arguments
;
924 public override Expression
DoResolve (EmitContext ec
)
926 if (Arguments
== null || Arguments
.Count
!= 1) {
927 Error_InvalidDelegateArgument ();
931 Argument a
= (Argument
) Arguments
[0];
932 if (!a
.ResolveMethodGroup (ec
))
935 Expression e
= a
.Expr
;
937 AnonymousMethodExpression ame
= e
as AnonymousMethodExpression
;
938 if (ame
!= null && RootContext
.Version
!= LanguageVersion
.ISO_1
) {
939 e
= ame
.Compatible (ec
, type
);
943 return e
.Resolve (ec
);
946 method_group
= e
as MethodGroupExpr
;
947 if (method_group
== null) {
948 if (!TypeManager
.IsDelegateType (e
.Type
)) {
949 e
.Error_UnexpectedKind (ResolveFlags
.MethodGroup
| ResolveFlags
.Type
, loc
);
954 // An argument is not a method but another delegate
956 delegate_instance_expression
= e
;
957 method_group
= new MethodGroupExpr (new MemberInfo
[] {
958 Delegate
.GetInvokeMethod (ec
.ContainerType
, e
.Type
) }, e
.Type
, loc
);
961 return base.DoResolve (ec
);
964 void Error_InvalidDelegateArgument ()
966 Report
.Error (149, loc
, "Method name expected");
970 public class DelegateInvocation
: ExpressionStatement
{
972 readonly Expression InstanceExpr
;
973 readonly ArrayList Arguments
;
977 public DelegateInvocation (Expression instance_expr
, ArrayList args
, Location loc
)
979 this.InstanceExpr
= instance_expr
;
980 this.Arguments
= args
;
984 public override Expression
CreateExpressionTree (EmitContext ec
)
987 if (Arguments
== null)
988 args
= new ArrayList (1);
990 args
= new ArrayList (Arguments
.Count
+ 1);
992 args
.Add (new Argument (InstanceExpr
.CreateExpressionTree (ec
)));
993 if (Arguments
!= null) {
994 foreach (Argument a
in Arguments
)
995 args
.Add (new Argument (a
.Expr
.CreateExpressionTree (ec
)));
998 return CreateExpressionFactoryCall ("Invoke", args
);
1001 public override Expression
DoResolve (EmitContext ec
)
1003 if (InstanceExpr
is EventExpr
) {
1004 ((EventExpr
) InstanceExpr
).Error_CannotAssign ();
1008 Type del_type
= InstanceExpr
.Type
;
1009 if (del_type
== null)
1012 if (Arguments
!= null){
1013 foreach (Argument a
in Arguments
){
1014 if (!a
.Resolve (ec
, loc
))
1019 if (!Delegate
.VerifyApplicability (ec
, del_type
, Arguments
, loc
))
1022 method
= Delegate
.GetInvokeMethod (ec
.ContainerType
, del_type
);
1023 type
= TypeManager
.TypeToCoreType (method
.ReturnType
);
1024 eclass
= ExprClass
.Value
;
1029 public override void Emit (EmitContext ec
)
1032 // Invocation on delegates call the virtual Invoke member
1033 // so we are always `instance' calls
1035 Invocation
.EmitCall (ec
, false, InstanceExpr
, method
, Arguments
, loc
);
1038 public override void EmitStatement (EmitContext ec
)
1042 // Pop the return value if there is one
1044 if (type
!= TypeManager
.void_type
)
1045 ec
.ig
.Emit (OpCodes
.Pop
);
1048 public override void MutateHoistedGenericType (AnonymousMethodStorey storey
)
1050 method
= storey
.MutateGenericMethod (method
);
1051 type
= storey
.MutateType (type
);
1053 if (Arguments
!= null) {
1054 foreach (Argument a
in Arguments
) {
1055 a
.Expr
.MutateHoistedGenericType (storey
);
1059 InstanceExpr
.MutateHoistedGenericType (storey
);