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
;
36 static string[] attribute_targets
= new string [] { "type", "return" }
;
38 Expression instance_expr
;
39 MethodBase delegate_method
;
40 ReturnParameter return_attributes
;
42 const int AllowedModifiers
=
50 public Delegate (NamespaceEntry ns
, DeclSpace parent
, Expression type
,
51 int mod_flags
, MemberName name
, Parameters param_list
,
53 : base (ns
, parent
, name
, attrs
)
56 this.ReturnType
= type
;
57 ModFlags
= Modifiers
.Check (AllowedModifiers
, mod_flags
,
58 IsTopLevel
? Modifiers
.INTERNAL
:
59 Modifiers
.PRIVATE
, name
.Location
);
60 Parameters
= param_list
;
63 public override void ApplyAttributeBuilder(Attribute a
, CustomAttributeBuilder cb
)
65 if (a
.Target
== AttributeTargets
.ReturnValue
) {
66 if (return_attributes
== null)
67 return_attributes
= new ReturnParameter (InvokeBuilder
, Location
);
69 return_attributes
.ApplyAttributeBuilder (a
, cb
);
73 base.ApplyAttributeBuilder (a
, cb
);
76 public override TypeBuilder
DefineType ()
78 if (TypeBuilder
!= null)
81 if (TypeManager
.multicast_delegate_type
== null && !RootContext
.StdLib
) {
82 Namespace system
= RootNamespace
.Global
.GetNamespace ("System", true);
83 TypeExpr expr
= system
.Lookup (this, "MulticastDelegate", Location
) as TypeExpr
;
84 TypeManager
.multicast_delegate_type
= expr
.Type
;
87 if (TypeManager
.multicast_delegate_type
== null)
88 Report
.Error (-100, Location
, "Internal error: delegate used before " +
89 "System.MulticastDelegate is resolved. This can only " +
90 "happen during corlib compilation, when using a delegate " +
91 "in any of the `core' classes. See bug #72015 for details.");
94 if (TypeManager
.NamespaceClash (Name
, Location
))
97 ModuleBuilder builder
= CodeGen
.Module
.Builder
;
99 TypeBuilder
= builder
.DefineType (
100 Name
, TypeAttr
, TypeManager
.multicast_delegate_type
);
102 TypeBuilder builder
= Parent
.TypeBuilder
;
104 string name
= Name
.Substring (1 + Name
.LastIndexOf ('.'));
105 TypeBuilder
= builder
.DefineNestedType (
106 name
, TypeAttr
, TypeManager
.multicast_delegate_type
);
109 TypeManager
.AddUserType (this);
113 string[] param_names
= new string [TypeParameters
.Length
];
114 for (int i
= 0; i
< TypeParameters
.Length
; i
++)
115 param_names
[i
] = TypeParameters
[i
].Name
;
117 GenericTypeParameterBuilder
[] gen_params
;
118 gen_params
= TypeBuilder
.DefineGenericParameters (param_names
);
120 int offset
= CountTypeParameters
- CurrentTypeParameters
.Length
;
121 for (int i
= offset
; i
< gen_params
.Length
; i
++)
122 CurrentTypeParameters
[i
- offset
].Define (gen_params
[i
]);
124 foreach (TypeParameter type_param
in CurrentTypeParameters
) {
125 if (!type_param
.Resolve (this))
129 Expression current
= new SimpleName (
130 MemberName
.Basename
, TypeParameters
, Location
);
131 current
= current
.ResolveAsTypeTerminal (this, false);
135 CurrentType
= current
.Type
;
142 public override bool Define ()
146 foreach (TypeParameter type_param
in TypeParameters
) {
147 if (!type_param
.Resolve (this))
151 foreach (TypeParameter type_param
in TypeParameters
) {
152 if (!type_param
.DefineType (this))
156 foreach (TypeParameter type_param
in TypeParameters
) {
157 if (!type_param
.CheckDependencies ())
163 // FIXME: POSSIBLY make this static, as it is always constant
165 Type
[] const_arg_types
= new Type
[2];
166 const_arg_types
[0] = TypeManager
.object_type
;
167 const_arg_types
[1] = TypeManager
.intptr_type
;
169 const MethodAttributes ctor_mattr
= MethodAttributes
.RTSpecialName
| MethodAttributes
.SpecialName
|
170 MethodAttributes
.HideBySig
| MethodAttributes
.Public
;
172 ConstructorBuilder
= TypeBuilder
.DefineConstructor (ctor_mattr
,
173 CallingConventions
.Standard
,
176 ConstructorBuilder
.DefineParameter (1, ParameterAttributes
.None
, "object");
177 ConstructorBuilder
.DefineParameter (2, ParameterAttributes
.None
, "method");
179 // HACK because System.Reflection.Emit is lame
181 Parameter
[] fixed_pars
= new Parameter
[2];
182 fixed_pars
[0] = new Parameter (TypeManager
.object_type
, "object",
183 Parameter
.Modifier
.NONE
, null, Location
);
184 fixed_pars
[1] = new Parameter (TypeManager
.intptr_type
, "method",
185 Parameter
.Modifier
.NONE
, null, Location
);
186 Parameters const_parameters
= new Parameters (fixed_pars
);
187 const_parameters
.Resolve (null);
189 TypeManager
.RegisterMethod (ConstructorBuilder
, const_parameters
);
192 ConstructorBuilder
.SetImplementationFlags (MethodImplAttributes
.Runtime
);
195 // Here the various methods like Invoke, BeginInvoke etc are defined
197 // First, call the `out of band' special method for
198 // defining recursively any types we need:
200 if (!Parameters
.Resolve (this))
207 // Check accessibility
208 foreach (Type partype
in Parameters
.Types
){
209 if (!Parent
.AsAccessible (partype
, ModFlags
)) {
210 Report
.Error (59, Location
,
211 "Inconsistent accessibility: parameter type `" +
212 TypeManager
.CSharpName (partype
) + "' is less " +
213 "accessible than delegate `" + Name
+ "'");
218 ReturnType
= ReturnType
.ResolveAsTypeTerminal (this, false);
219 if (ReturnType
== null)
222 ret_type
= ReturnType
.Type
;
224 if (!Parent
.AsAccessible (ret_type
, ModFlags
)) {
225 Report
.Error (58, Location
,
226 "Inconsistent accessibility: return type `" +
227 TypeManager
.CSharpName (ret_type
) + "' is less " +
228 "accessible than delegate `" + Name
+ "'");
232 if (RootContext
.StdLib
&& (ret_type
== TypeManager
.arg_iterator_type
|| ret_type
== TypeManager
.typed_reference_type
)) {
233 Method
.Error1599 (Location
, ret_type
);
238 // We don't have to check any others because they are all
239 // guaranteed to be accessible - they are standard types.
242 CallingConventions cc
= Parameters
.CallingConvention
;
244 const MethodAttributes mattr
= MethodAttributes
.Public
| MethodAttributes
.HideBySig
| MethodAttributes
.Virtual
| MethodAttributes
.NewSlot
;
246 InvokeBuilder
= TypeBuilder
.DefineMethod ("Invoke",
252 InvokeBuilder
.SetImplementationFlags (MethodImplAttributes
.Runtime
);
254 TypeManager
.RegisterMethod (InvokeBuilder
, Parameters
);
260 Parameters async_parameters
= Parameters
.MergeGenerated (Parameters
,
261 new Parameter (TypeManager
.asynccallback_type
, "callback", Parameter
.Modifier
.NONE
, null, Location
),
262 new Parameter (TypeManager
.object_type
, "object", Parameter
.Modifier
.NONE
, null, Location
));
264 BeginInvokeBuilder
= TypeBuilder
.DefineMethod ("BeginInvoke",
265 mattr
, cc
, TypeManager
.iasyncresult_type
, async_parameters
.Types
);
267 BeginInvokeBuilder
.SetImplementationFlags (MethodImplAttributes
.Runtime
);
268 async_parameters
.ApplyAttributes (BeginInvokeBuilder
);
269 TypeManager
.RegisterMethod (BeginInvokeBuilder
, async_parameters
);
272 // EndInvoke is a bit more interesting, all the parameters labeled as
273 // out or ref have to be duplicated here.
277 // Define parameters, and count out/ref parameters
279 Parameters end_parameters
;
282 foreach (Parameter p
in Parameters
.FixedParameters
) {
283 if ((p
.ModFlags
& Parameter
.Modifier
.ISBYREF
) != 0)
287 if (out_params
> 0) {
288 Type
[] end_param_types
= new Type
[out_params
];
289 Parameter
[] end_params
= new Parameter
[out_params
];
292 for (int i
= 0; i
< Parameters
.FixedParameters
.Length
; ++i
) {
293 Parameter p
= Parameters
.FixedParameters
[i
];
294 if ((p
.ModFlags
& Parameter
.Modifier
.ISBYREF
) == 0)
297 end_param_types
[param
] = p
.ExternalType();
298 end_params
[param
] = p
;
301 end_parameters
= new Parameters (end_params
, end_param_types
);
304 end_parameters
= Parameters
.EmptyReadOnlyParameters
;
307 end_parameters
= Parameters
.MergeGenerated (end_parameters
,
308 new Parameter (TypeManager
.iasyncresult_type
, "result", Parameter
.Modifier
.NONE
, null, Location
));
311 // Create method, define parameters, register parameters with type system
313 EndInvokeBuilder
= TypeBuilder
.DefineMethod ("EndInvoke", mattr
, cc
, ret_type
, end_parameters
.Types
);
314 EndInvokeBuilder
.SetImplementationFlags (MethodImplAttributes
.Runtime
);
316 end_parameters
.ApplyAttributes (EndInvokeBuilder
);
317 TypeManager
.RegisterMethod (EndInvokeBuilder
, end_parameters
);
322 public override void Emit ()
324 Parameters
.ApplyAttributes (InvokeBuilder
);
326 if (OptAttributes
!= null) {
327 OptAttributes
.Emit ();
333 protected override TypeAttributes TypeAttr
{
335 return Modifiers
.TypeAttr (ModFlags
, IsTopLevel
) |
336 TypeAttributes
.Class
| TypeAttributes
.Sealed
|
341 public override string[] ValidAttributeTargets
{
343 return attribute_targets
;
348 protected override bool VerifyClsCompliance ()
350 if (!base.VerifyClsCompliance ()) {
354 Parameters
.VerifyClsCompliance ();
356 if (!AttributeTester
.IsClsCompliant (ReturnType
.Type
)) {
357 Report
.Error (3002, Location
, "Return type of `{0}' is not CLS-compliant", GetSignatureForError ());
363 // Returns the MethodBase for "Invoke" from a delegate type, this is used
364 // to extract the signature of a delegate.
366 public static MethodGroupExpr
GetInvokeMethod (Type container_type
, Type delegate_type
, Location loc
)
368 Expression ml
= Expression
.MemberLookup (container_type
, null, delegate_type
,
371 MethodGroupExpr mg
= ml
as MethodGroupExpr
;
373 Report
.Error (-100, loc
, "Internal error: could not find Invoke method!");
381 /// Verifies whether the method in question is compatible with the delegate
382 /// Returns the method itself if okay and null if not.
384 public static MethodBase
VerifyMethod (Type container_type
, Type delegate_type
,
385 MethodGroupExpr old_mg
, MethodBase mb
,
388 MethodGroupExpr mg
= GetInvokeMethod (container_type
, delegate_type
, loc
);
392 if (old_mg
.HasTypeArguments
)
393 mg
.HasTypeArguments
= true;
395 MethodBase invoke_mb
= mg
.Methods
[0];
396 ParameterData invoke_pd
= TypeManager
.GetParameterData (invoke_mb
);
399 if (!mg
.HasTypeArguments
&&
400 !TypeManager
.InferTypeArguments (invoke_pd
, ref mb
))
404 ParameterData pd
= TypeManager
.GetParameterData (mb
);
406 if (invoke_pd
.Count
!= pd
.Count
)
409 for (int i
= pd
.Count
; i
> 0; ) {
412 Type invoke_pd_type
= invoke_pd
.ParameterType (i
);
413 Type pd_type
= pd
.ParameterType (i
);
414 Parameter
.Modifier invoke_pd_type_mod
= invoke_pd
.ParameterModifier (i
);
415 Parameter
.Modifier pd_type_mod
= pd
.ParameterModifier (i
);
417 invoke_pd_type_mod
&= ~Parameter
.Modifier
.PARAMS
;
418 pd_type_mod
&= ~Parameter
.Modifier
.PARAMS
;
420 if (invoke_pd_type_mod
!= pd_type_mod
)
423 if (invoke_pd_type
== pd_type
)
426 if (!Convert
.ImplicitReferenceConversionExists (new EmptyExpression (invoke_pd_type
), pd_type
))
429 if (RootContext
.Version
== LanguageVersion
.ISO_1
)
433 Type invoke_mb_retval
= ((MethodInfo
) invoke_mb
).ReturnType
;
434 Type mb_retval
= ((MethodInfo
) mb
).ReturnType
;
435 if (invoke_mb_retval
== mb_retval
)
438 if (!Convert
.ImplicitReferenceConversionExists (new EmptyExpression (mb_retval
), invoke_mb_retval
))
441 if (RootContext
.Version
== LanguageVersion
.ISO_1
)
448 // Verifies whether the invocation arguments are compatible with the
449 // delegate's target method
451 public static bool VerifyApplicability (EmitContext ec
, Type delegate_type
,
452 ArrayList args
, Location loc
)
459 arg_count
= args
.Count
;
461 Expression ml
= Expression
.MemberLookup (
462 ec
.ContainerType
, delegate_type
, "Invoke", loc
);
464 MethodGroupExpr me
= ml
as MethodGroupExpr
;
466 Report
.Error (-100, loc
, "Internal error: could not find Invoke method!" + delegate_type
);
470 MethodBase mb
= me
.Methods
[0];
471 ParameterData pd
= TypeManager
.GetParameterData (mb
);
473 int pd_count
= pd
.Count
;
475 bool params_method
= pd
.HasParams
;
476 bool is_params_applicable
= false;
477 bool is_applicable
= Invocation
.IsApplicable (ec
, me
, args
, arg_count
, ref mb
);
479 if (!is_applicable
&& params_method
&&
480 Invocation
.IsParamsMethodApplicable (ec
, me
, args
, arg_count
, ref mb
))
481 is_applicable
= is_params_applicable
= true;
483 if (!is_applicable
&& !params_method
&& arg_count
!= pd_count
) {
484 Report
.Error (1593, loc
, "Delegate `{0}' does not take `{1}' arguments",
485 TypeManager
.CSharpName (delegate_type
), arg_count
.ToString ());
489 return Invocation
.VerifyArgumentsCompat (
490 ec
, args
, arg_count
, mb
,
491 is_params_applicable
|| (!is_applicable
&& params_method
),
492 delegate_type
, false, loc
);
496 /// Verifies whether the delegate in question is compatible with this one in
497 /// order to determine if instantiation from the same is possible.
499 public static bool VerifyDelegate (EmitContext ec
, Type delegate_type
, Location loc
)
501 Expression ml
= Expression
.MemberLookup (
502 ec
.ContainerType
, delegate_type
, "Invoke", loc
);
504 if (!(ml
is MethodGroupExpr
)) {
505 Report
.Error (-100, loc
, "Internal error: could not find Invoke method!");
509 MethodBase mb
= ((MethodGroupExpr
) ml
).Methods
[0];
510 ParameterData pd
= TypeManager
.GetParameterData (mb
);
512 Expression probe_ml
= Expression
.MemberLookup (
513 ec
.ContainerType
, delegate_type
, "Invoke", loc
);
515 if (!(probe_ml
is MethodGroupExpr
)) {
516 Report
.Error (-100, loc
, "Internal error: could not find Invoke method!");
520 MethodBase probe_mb
= ((MethodGroupExpr
) probe_ml
).Methods
[0];
521 ParameterData probe_pd
= TypeManager
.GetParameterData (probe_mb
);
523 if (((MethodInfo
) mb
).ReturnType
!= ((MethodInfo
) probe_mb
).ReturnType
)
526 if (pd
.Count
!= probe_pd
.Count
)
529 for (int i
= pd
.Count
; i
> 0; ) {
532 if (pd
.ParameterType (i
) != probe_pd
.ParameterType (i
) ||
533 pd
.ParameterModifier (i
) != probe_pd
.ParameterModifier (i
))
540 public static string FullDelegateDesc (Type del_type
, MethodBase mb
, ParameterData pd
)
542 StringBuilder sb
= new StringBuilder ();
543 sb
.Append (TypeManager
.CSharpName (((MethodInfo
) mb
).ReturnType
));
545 sb
.Append (TypeManager
.CSharpName (del_type
));
546 sb
.Append (pd
.GetSignatureForError ());
547 return sb
.ToString ();
550 // Hack around System.Reflection as found everywhere else
551 public override MemberList
FindMembers (MemberTypes mt
, BindingFlags bf
,
552 MemberFilter filter
, object criteria
)
554 ArrayList members
= new ArrayList (2);
556 if ((mt
& MemberTypes
.Constructor
) != 0) {
557 if (ConstructorBuilder
!= null && filter (ConstructorBuilder
, criteria
))
558 members
.Add (ConstructorBuilder
);
561 if ((mt
& MemberTypes
.Method
) != 0) {
562 if (InvokeBuilder
!= null)
563 if (filter (InvokeBuilder
, criteria
))
564 members
.Add (InvokeBuilder
);
566 if (BeginInvokeBuilder
!= null)
567 if (filter (BeginInvokeBuilder
, criteria
))
568 members
.Add (BeginInvokeBuilder
);
570 if (EndInvokeBuilder
!= null)
571 if (filter (EndInvokeBuilder
, criteria
))
572 members
.Add (EndInvokeBuilder
);
575 return new MemberList (members
);
578 public override MemberCache MemberCache
{
584 public Expression InstanceExpression
{
586 return instance_expr
;
589 instance_expr
= value;
593 public MethodBase TargetMethod
{
595 return delegate_method
;
598 delegate_method
= value;
602 public Type TargetReturnType
{
608 public override AttributeTargets AttributeTargets
{
610 return AttributeTargets
.Delegate
;
615 // Represents header string for documentation comment.
617 public override string DocCommentHeader
{
624 // Base class for `NewDelegate' and `ImplicitDelegateCreation'
626 public abstract class DelegateCreation
: Expression
{
627 protected MethodBase constructor_method
;
628 protected MethodBase delegate_method
;
629 protected MethodGroupExpr method_group
;
630 protected Expression delegate_instance_expression
;
632 protected DelegateCreation () {}
634 public static void Error_NoMatchingMethodForDelegate (EmitContext ec
, MethodGroupExpr mg
, Type type
, Location loc
)
637 MethodBase found_method
= mg
.Methods
[0];
639 if (mg
.Methods
.Length
> 1)
640 method_desc
= found_method
.Name
;
642 method_desc
= Invocation
.FullMethodDesc (found_method
);
644 Expression invoke_method
= Expression
.MemberLookup (
645 ec
.ContainerType
, type
, "Invoke", MemberTypes
.Method
,
646 Expression
.AllBindingFlags
, loc
);
647 MethodInfo method
= ((MethodGroupExpr
) invoke_method
).Methods
[0] as MethodInfo
;
649 ParameterData param
= TypeManager
.GetParameterData (method
);
650 string delegate_desc
= Delegate
.FullDelegateDesc (type
, method
, param
);
653 if (!mg
.HasTypeArguments
&&
654 !TypeManager
.InferTypeArguments (param
, ref found_method
)) {
655 Report
.Error (411, loc
, "The type arguments for " +
656 "method `{0}' cannot be infered from " +
657 "the usage. Try specifying the type " +
658 "arguments explicitly.", method_desc
);
662 Report
.SymbolRelatedToPreviousError (found_method
);
664 if (RootContext
.Version
== LanguageVersion
.ISO_1
) {
665 Report
.Error (410, loc
, "The method `{0}' parameters and return type must be same as delegate `{1}' parameters and return type",
666 method_desc
, delegate_desc
);
670 Type delegateType
= method
.ReturnType
;
671 Type methodType
= ((MethodInfo
) found_method
).ReturnType
;
672 if (delegateType
!= methodType
&&
673 !Convert
.ImplicitReferenceConversionExists (new EmptyExpression (methodType
), delegateType
)) {
674 Report
.Error (407, loc
, "`{0}' has the wrong return type to match the delegate `{1}'", method_desc
, delegate_desc
);
676 Report
.Error (123, loc
, "The method `{0}' parameters do not match delegate `{1}' parameters",
677 TypeManager
.CSharpSignature (found_method
), delegate_desc
);
681 public override void Emit (EmitContext ec
)
683 if (delegate_instance_expression
== null || delegate_method
.IsStatic
)
684 ec
.ig
.Emit (OpCodes
.Ldnull
);
686 delegate_instance_expression
.Emit (ec
);
688 if (delegate_method
.IsVirtual
&& !method_group
.IsBase
) {
689 ec
.ig
.Emit (OpCodes
.Dup
);
690 ec
.ig
.Emit (OpCodes
.Ldvirtftn
, (MethodInfo
) delegate_method
);
692 ec
.ig
.Emit (OpCodes
.Ldftn
, (MethodInfo
) delegate_method
);
693 ec
.ig
.Emit (OpCodes
.Newobj
, (ConstructorInfo
) constructor_method
);
696 protected bool ResolveConstructorMethod (EmitContext ec
)
698 Expression ml
= Expression
.MemberLookupFinal(ec
,
699 null, type
, ".ctor", MemberTypes
.Constructor
, AllBindingFlags
| BindingFlags
.DeclaredOnly
, loc
);
701 if (!(ml
is MethodGroupExpr
)) {
702 Report
.Error (-100, loc
, "Internal error: Could not find delegate constructor!");
706 constructor_method
= ((MethodGroupExpr
) ml
).Methods
[0];
710 public static MethodBase
ImplicitStandardConversionExists (MethodGroupExpr mg
, Type targetType
)
712 foreach (MethodInfo mi
in mg
.Methods
){
713 MethodBase mb
= Delegate
.VerifyMethod (mg
.DeclaringType
, targetType
, mg
, mi
, Location
.Null
);
720 protected Expression
ResolveMethodGroupExpr (EmitContext ec
, MethodGroupExpr mg
)
722 delegate_method
= ImplicitStandardConversionExists (mg
, type
);
724 if (delegate_method
== null) {
725 Error_NoMatchingMethodForDelegate (ec
, mg
, type
, loc
);
730 // Check safe/unsafe of the delegate
733 ParameterData param
= TypeManager
.GetParameterData (delegate_method
);
734 int count
= param
.Count
;
736 for (int i
= 0; i
< count
; i
++){
737 if (param
.ParameterType (i
).IsPointer
){
738 Expression
.UnsafeError (loc
);
744 //TODO: implement caching when performance will be low
745 IMethodData md
= TypeManager
.GetMethod (delegate_method
);
747 if (System
.Attribute
.GetCustomAttribute (delegate_method
, TypeManager
.conditional_attribute_type
) != null) {
748 Report
.SymbolRelatedToPreviousError (delegate_method
);
749 Report
.Error (1618, loc
, "Cannot create delegate with `{0}' because it has a Conditional attribute", TypeManager
.CSharpSignature (delegate_method
));
753 md
.SetMemberIsUsed ();
754 if (md
.OptAttributes
!= null && md
.OptAttributes
.Search (TypeManager
.conditional_attribute_type
) != null) {
755 Report
.SymbolRelatedToPreviousError (delegate_method
);
756 Report
.Error (1618, loc
, "Cannot create delegate with `{0}' because it has a Conditional attribute", TypeManager
.CSharpSignature (delegate_method
));
761 if (mg
.InstanceExpression
!= null)
762 delegate_instance_expression
= mg
.InstanceExpression
.Resolve (ec
);
763 else if (ec
.IsStatic
) {
764 if (!delegate_method
.IsStatic
) {
765 Report
.Error (120, loc
, "`{0}': An object reference is required for the nonstatic field, method or property",
766 TypeManager
.CSharpSignature (delegate_method
));
769 delegate_instance_expression
= null;
771 delegate_instance_expression
= ec
.GetThis (loc
);
773 if (delegate_instance_expression
!= null && delegate_instance_expression
.Type
.IsValueType
)
774 delegate_instance_expression
= new BoxedCast (
775 delegate_instance_expression
, TypeManager
.object_type
);
778 eclass
= ExprClass
.Value
;
784 // Created from the conversion code
786 public class ImplicitDelegateCreation
: DelegateCreation
{
788 ImplicitDelegateCreation (Type t
, Location l
)
794 public override Expression
DoResolve (EmitContext ec
)
799 static public Expression
Create (EmitContext ec
, MethodGroupExpr mge
,
800 Type target_type
, Location loc
)
802 ImplicitDelegateCreation d
= new ImplicitDelegateCreation (target_type
, loc
);
803 if (!d
.ResolveConstructorMethod (ec
))
806 return d
.ResolveMethodGroupExpr (ec
, mge
);
811 // A delegate-creation-expression, invoked from the `New' class
813 public class NewDelegate
: DelegateCreation
{
814 public ArrayList Arguments
;
817 // This constructor is invoked from the `New' expression
819 public NewDelegate (Type type
, ArrayList Arguments
, Location loc
)
822 this.Arguments
= Arguments
;
826 public override Expression
DoResolve (EmitContext ec
)
828 if (Arguments
== null || Arguments
.Count
!= 1) {
829 Report
.Error (149, loc
,
830 "Method name expected");
834 if (!ResolveConstructorMethod (ec
))
837 Argument a
= (Argument
) Arguments
[0];
839 if (!a
.ResolveMethodGroup (ec
))
842 Expression e
= a
.Expr
;
844 if (e
is AnonymousMethodExpression
&& RootContext
.Version
!= LanguageVersion
.ISO_1
)
845 return ((AnonymousMethodExpression
) e
).Compatible (ec
, type
);
847 MethodGroupExpr mg
= e
as MethodGroupExpr
;
849 return ResolveMethodGroupExpr (ec
, mg
);
851 if (!TypeManager
.IsDelegateType (e
.Type
)) {
852 Report
.Error (149, loc
, "Method name expected");
856 method_group
= Expression
.MemberLookup (
857 ec
.ContainerType
, type
, "Invoke", MemberTypes
.Method
,
858 Expression
.AllBindingFlags
, loc
) as MethodGroupExpr
;
860 if (method_group
== null) {
861 Report
.Error (-200, loc
, "Internal error ! Could not find Invoke method!");
865 // This is what MS' compiler reports. We could always choose
866 // to be more verbose and actually give delegate-level specifics
867 if (!Delegate
.VerifyDelegate (ec
, type
, loc
)) {
868 Report
.Error (29, loc
, "Cannot implicitly convert type '" + e
.Type
+ "' " +
869 "to type '" + type
+ "'");
873 delegate_instance_expression
= e
;
874 delegate_method
= method_group
.Methods
[0];
876 eclass
= ExprClass
.Value
;
881 public class DelegateInvocation
: ExpressionStatement
{
883 public Expression InstanceExpr
;
884 public ArrayList Arguments
;
888 public DelegateInvocation (Expression instance_expr
, ArrayList args
, Location loc
)
890 this.InstanceExpr
= instance_expr
;
891 this.Arguments
= args
;
895 public override Expression
DoResolve (EmitContext ec
)
897 if (InstanceExpr
is EventExpr
) {
899 EventInfo ei
= ((EventExpr
) InstanceExpr
).EventInfo
;
901 Expression ml
= MemberLookup (
902 ec
.ContainerType
, ec
.ContainerType
, ei
.Name
,
903 MemberTypes
.Event
, AllBindingFlags
| BindingFlags
.DeclaredOnly
, loc
);
907 // If this is the case, then the Event does not belong
908 // to this Type and so, according to the spec
909 // cannot be accessed directly
911 // Note that target will not appear as an EventExpr
912 // in the case it is being referenced within the same type container;
913 // it will appear as a FieldExpr in that case.
916 Assign
.error70 (ei
, loc
);
922 Type del_type
= InstanceExpr
.Type
;
923 if (del_type
== null)
926 if (Arguments
!= null){
927 foreach (Argument a
in Arguments
){
928 if (!a
.Resolve (ec
, loc
))
933 if (!Delegate
.VerifyApplicability (ec
, del_type
, Arguments
, loc
))
936 Expression lookup
= Expression
.MemberLookup (ec
.ContainerType
, del_type
, "Invoke", loc
);
937 if (!(lookup
is MethodGroupExpr
)) {
938 Report
.Error (-100, loc
, "Internal error: could not find Invoke method!");
942 method
= ((MethodGroupExpr
) lookup
).Methods
[0];
943 type
= ((MethodInfo
) method
).ReturnType
;
944 eclass
= ExprClass
.Value
;
949 public override void Emit (EmitContext ec
)
952 // Invocation on delegates call the virtual Invoke member
953 // so we are always `instance' calls
955 Invocation
.EmitCall (ec
, false, false, InstanceExpr
, method
, Arguments
, loc
);
958 public override void EmitStatement (EmitContext ec
)
962 // Pop the return value if there is one
964 if (method
is MethodInfo
){
965 Type ret
= ((MethodInfo
)method
).ReturnType
;
966 if (TypeManager
.TypeToCoreType (ret
) != TypeManager
.void_type
)
967 ec
.ig
.Emit (OpCodes
.Pop
);