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
, TypeContainer 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 ec
= new EmitContext (this, this, Location
, null, null, ModFlags
, false);
84 foreach (TypeParameter type_param
in TypeParameters
)
85 if (!type_param
.Resolve (this))
89 if (TypeManager
.multicast_delegate_type
== null && !RootContext
.StdLib
) {
90 Namespace system
= RootNamespace
.Global
.GetNamespace ("System", true);
91 TypeExpr expr
= system
.Lookup (this, "MulticastDelegate", Location
) as TypeExpr
;
92 TypeManager
.multicast_delegate_type
= expr
.ResolveType (ec
);
95 if (TypeManager
.multicast_delegate_type
== null)
96 Report
.Error (-100, Location
, "Internal error: delegate used before " +
97 "System.MulticastDelegate is resolved. This can only " +
98 "happen during corlib compilation, when using a delegate " +
99 "in any of the `core' classes. See bug #72015 for details.");
102 if (TypeManager
.NamespaceClash (Name
, Location
))
105 ModuleBuilder builder
= CodeGen
.Module
.Builder
;
107 TypeBuilder
= builder
.DefineType (
108 Name
, TypeAttr
, TypeManager
.multicast_delegate_type
);
110 TypeBuilder builder
= Parent
.TypeBuilder
;
112 string name
= Name
.Substring (1 + Name
.LastIndexOf ('.'));
113 TypeBuilder
= builder
.DefineNestedType (
114 name
, TypeAttr
, TypeManager
.multicast_delegate_type
);
117 TypeManager
.AddUserType (this);
120 string[] param_names
= new string [TypeParameters
.Length
];
121 for (int i
= 0; i
< TypeParameters
.Length
; i
++)
122 param_names
[i
] = TypeParameters
[i
].Name
;
124 GenericTypeParameterBuilder
[] gen_params
;
125 gen_params
= TypeBuilder
.DefineGenericParameters (param_names
);
127 int offset
= CountTypeParameters
- CurrentTypeParameters
.Length
;
128 for (int i
= offset
; i
< gen_params
.Length
; i
++)
129 CurrentTypeParameters
[i
- offset
].Define (gen_params
[i
]);
131 foreach (TypeParameter type_param
in CurrentTypeParameters
) {
132 if (!type_param
.Resolve (this))
136 Expression current
= new SimpleName (
137 MemberName
.Basename
, TypeParameters
, Location
);
138 current
= current
.ResolveAsTypeTerminal (ec
);
142 CurrentType
= current
.Type
;
148 public override bool Define ()
150 MethodAttributes mattr
;
154 foreach (TypeParameter type_param
in TypeParameters
)
155 type_param
.DefineType (ec
);
159 throw new InternalErrorException ("Define called before DefineType?");
161 // FIXME: POSSIBLY make this static, as it is always constant
163 Type
[] const_arg_types
= new Type
[2];
164 const_arg_types
[0] = TypeManager
.object_type
;
165 const_arg_types
[1] = TypeManager
.intptr_type
;
167 mattr
= MethodAttributes
.RTSpecialName
| MethodAttributes
.SpecialName
|
168 MethodAttributes
.HideBySig
| MethodAttributes
.Public
;
170 ConstructorBuilder
= TypeBuilder
.DefineConstructor (mattr
,
171 CallingConventions
.Standard
,
174 ConstructorBuilder
.DefineParameter (1, ParameterAttributes
.None
, "object");
175 ConstructorBuilder
.DefineParameter (2, ParameterAttributes
.None
, "method");
177 // HACK because System.Reflection.Emit is lame
179 Parameter
[] fixed_pars
= new Parameter
[2];
180 fixed_pars
[0] = new Parameter (TypeManager
.object_type
, "object",
181 Parameter
.Modifier
.NONE
, null, Location
);
182 fixed_pars
[1] = new Parameter (TypeManager
.intptr_type
, "method",
183 Parameter
.Modifier
.NONE
, null, Location
);
184 Parameters const_parameters
= new Parameters (fixed_pars
);
185 const_parameters
.Resolve (null);
187 TypeManager
.RegisterMethod (ConstructorBuilder
, const_parameters
);
190 ConstructorBuilder
.SetImplementationFlags (MethodImplAttributes
.Runtime
);
193 // Here the various methods like Invoke, BeginInvoke etc are defined
195 // First, call the `out of band' special method for
196 // defining recursively any types we need:
198 if (!Parameters
.Resolve (ec
))
205 // Check accessibility
206 foreach (Type partype
in Parameters
.Types
){
207 if (!Parent
.AsAccessible (partype
, ModFlags
)) {
208 Report
.Error (59, Location
,
209 "Inconsistent accessibility: parameter type `" +
210 TypeManager
.CSharpName (partype
) + "' is less " +
211 "accessible than delegate `" + Name
+ "'");
214 if (partype
.IsPointer
&& !UnsafeOK (Parent
))
218 ReturnType
= ReturnType
.ResolveAsTypeTerminal (ec
, false);
219 if (ReturnType
== null)
222 ret_type
= ReturnType
.Type
;
223 if (ret_type
== null)
226 CheckObsoleteType (ReturnType
);
228 if (!Parent
.AsAccessible (ret_type
, ModFlags
)) {
229 Report
.Error (58, Location
,
230 "Inconsistent accessibility: return type `" +
231 TypeManager
.CSharpName (ret_type
) + "' is less " +
232 "accessible than delegate `" + Name
+ "'");
236 if (ret_type
.IsPointer
&& !UnsafeOK (Parent
))
239 if (RootContext
.StdLib
&& (ret_type
== TypeManager
.arg_iterator_type
|| ret_type
== TypeManager
.typed_reference_type
)) {
240 Method
.Error1599 (Location
, ret_type
);
245 // We don't have to check any others because they are all
246 // guaranteed to be accessible - they are standard types.
249 CallingConventions cc
= Parameters
.CallingConvention
;
251 mattr
= MethodAttributes
.Public
| MethodAttributes
.HideBySig
| MethodAttributes
.Virtual
;
253 InvokeBuilder
= TypeBuilder
.DefineMethod ("Invoke",
260 // Define parameters, and count out/ref parameters
263 foreach (Parameter p
in Parameters
.FixedParameters
) {
264 if ((p
.ModFlags
& Parameter
.Modifier
.ISBYREF
) != 0)
268 InvokeBuilder
.SetImplementationFlags (MethodImplAttributes
.Runtime
);
270 TypeManager
.RegisterMethod (InvokeBuilder
, Parameters
);
275 int params_num
= Parameters
.Count
;
276 Type
[] async_param_types
= new Type
[params_num
+ 2];
278 Parameters
.Types
.CopyTo (async_param_types
, 0);
280 async_param_types
[params_num
] = TypeManager
.asynccallback_type
;
281 async_param_types
[params_num
+ 1] = TypeManager
.object_type
;
283 mattr
= MethodAttributes
.Public
| MethodAttributes
.HideBySig
|
284 MethodAttributes
.Virtual
| MethodAttributes
.NewSlot
;
286 BeginInvokeBuilder
= TypeBuilder
.DefineMethod ("BeginInvoke",
289 TypeManager
.iasyncresult_type
,
292 i
= Parameters
.Count
;
293 Parameters
.ApplyAttributes (ec
, BeginInvokeBuilder
);
294 BeginInvokeBuilder
.DefineParameter (i
+ 1, ParameterAttributes
.None
, "callback");
295 BeginInvokeBuilder
.DefineParameter (i
+ 2, ParameterAttributes
.None
, "object");
297 BeginInvokeBuilder
.SetImplementationFlags (MethodImplAttributes
.Runtime
);
299 Parameter
[] async_params
= new Parameter
[params_num
+ 2];
300 Parameters
.FixedParameters
.CopyTo (async_params
, 0);
302 async_params
[params_num
] = new Parameter (
303 TypeManager
.asynccallback_type
, "callback",
304 Parameter
.Modifier
.NONE
, null, Location
);
305 async_params
[params_num
+ 1] = new Parameter (
306 TypeManager
.object_type
, "object",
307 Parameter
.Modifier
.NONE
, null, Location
);
309 Parameters async_parameters
= new Parameters (async_params
);
310 async_parameters
.Resolve (ec
);
311 async_parameters
.ApplyAttributes (ec
, BeginInvokeBuilder
);
313 TypeManager
.RegisterMethod (BeginInvokeBuilder
, async_parameters
);
316 // EndInvoke is a bit more interesting, all the parameters labeled as
317 // out or ref have to be duplicated here.
320 Type
[] end_param_types
= new Type
[out_params
+ 1];
321 Parameter
[] end_params
= new Parameter
[out_params
+ 1];
324 int top
= Parameters
.FixedParameters
.Length
;
325 for (i
= 0; i
< top
; i
++){
326 Parameter p
= Parameters
.FixedParameters
[i
];
327 if ((p
.ModFlags
& Parameter
.Modifier
.ISBYREF
) == 0)
330 end_param_types
[param
] = Parameters
.Types
[i
];
331 end_params
[param
] = p
;
335 end_param_types
[out_params
] = TypeManager
.iasyncresult_type
;
336 end_params
[out_params
] = new Parameter (TypeManager
.system_iasyncresult_expr
, "result", Parameter
.Modifier
.NONE
, null, Location
);
339 // Create method, define parameters, register parameters with type system
341 EndInvokeBuilder
= TypeBuilder
.DefineMethod ("EndInvoke", mattr
, cc
, ret_type
, end_param_types
);
342 EndInvokeBuilder
.SetImplementationFlags (MethodImplAttributes
.Runtime
);
345 // EndInvoke: Label the parameters
347 EndInvokeBuilder
.DefineParameter (out_params
+ 1, ParameterAttributes
.None
, "result");
348 for (i
= 0; i
< end_params
.Length
-1; i
++){
349 EndInvokeBuilder
.DefineParameter (i
+ 1, end_params
[i
].Attributes
, end_params
[i
].Name
);
352 Parameters end_parameters
= new Parameters (end_params
);
353 end_parameters
.Resolve (ec
);
355 TypeManager
.RegisterMethod (EndInvokeBuilder
, end_parameters
);
360 public override void Emit ()
362 Parameters
.ApplyAttributes (ec
, InvokeBuilder
);
364 if (OptAttributes
!= null) {
365 OptAttributes
.Emit (ec
, this);
371 protected override TypeAttributes TypeAttr
{
373 return Modifiers
.TypeAttr (ModFlags
, IsTopLevel
) |
374 TypeAttributes
.Class
| TypeAttributes
.Sealed
|
379 public override string[] ValidAttributeTargets
{
381 return attribute_targets
;
386 protected override bool VerifyClsCompliance (DeclSpace ds
)
388 if (!base.VerifyClsCompliance (ds
)) {
392 Parameters
.VerifyClsCompliance ();
394 if (!AttributeTester
.IsClsCompliant (ReturnType
.Type
)) {
395 Report
.Error (3002, Location
, "Return type of `{0}' is not CLS-compliant", GetSignatureForError ());
401 // Returns the MethodBase for "Invoke" from a delegate type, this is used
402 // to extract the signature of a delegate.
404 public static MethodGroupExpr
GetInvokeMethod (EmitContext ec
, Type delegate_type
,
407 Expression ml
= Expression
.MemberLookup (
408 ec
, delegate_type
, "Invoke", loc
);
410 MethodGroupExpr mg
= ml
as MethodGroupExpr
;
412 Report
.Error (-100, loc
, "Internal error: could not find Invoke method!");
420 /// Verifies whether the method in question is compatible with the delegate
421 /// Returns the method itself if okay and null if not.
423 public static MethodBase
VerifyMethod (EmitContext ec
, Type delegate_type
,
424 MethodGroupExpr old_mg
, MethodBase mb
,
427 MethodGroupExpr mg
= GetInvokeMethod (ec
, delegate_type
, loc
);
431 if (old_mg
.HasTypeArguments
)
432 mg
.HasTypeArguments
= true;
434 MethodBase invoke_mb
= mg
.Methods
[0];
435 ParameterData invoke_pd
= TypeManager
.GetParameterData (invoke_mb
);
437 if (!mg
.HasTypeArguments
&&
438 !TypeManager
.InferTypeArguments (ec
, invoke_pd
, ref mb
))
441 ParameterData pd
= TypeManager
.GetParameterData (mb
);
443 if (invoke_pd
.Count
!= pd
.Count
)
446 for (int i
= pd
.Count
; i
> 0; ) {
449 Type invoke_pd_type
= invoke_pd
.ParameterType (i
);
450 Type pd_type
= pd
.ParameterType (i
);
451 Parameter
.Modifier invoke_pd_type_mod
= invoke_pd
.ParameterModifier (i
);
452 Parameter
.Modifier pd_type_mod
= pd
.ParameterModifier (i
);
454 if (invoke_pd_type
== pd_type
&&
455 invoke_pd_type_mod
== pd_type_mod
)
458 if (invoke_pd_type
.IsSubclassOf (pd_type
) &&
459 invoke_pd_type_mod
== pd_type_mod
)
460 if (RootContext
.Version
== LanguageVersion
.ISO_1
) {
461 Report
.FeatureIsNotStandardized (loc
, "contravariance");
469 Type invoke_mb_retval
= ((MethodInfo
) invoke_mb
).ReturnType
;
470 Type mb_retval
= ((MethodInfo
) mb
).ReturnType
;
471 if (invoke_mb_retval
== mb_retval
)
474 if (mb_retval
.IsSubclassOf (invoke_mb_retval
))
475 if (RootContext
.Version
== LanguageVersion
.ISO_1
) {
476 Report
.FeatureIsNotStandardized (loc
, "covariance");
486 // Verifies whether the invocation arguments are compatible with the
487 // delegate's target method
489 public static bool VerifyApplicability (EmitContext ec
, Type delegate_type
,
490 ArrayList args
, Location loc
)
497 arg_count
= args
.Count
;
499 Expression ml
= Expression
.MemberLookup (
500 ec
, delegate_type
, "Invoke", loc
);
502 MethodGroupExpr me
= ml
as MethodGroupExpr
;
504 Report
.Error (-100, loc
, "Internal error: could not find Invoke method!" + delegate_type
);
508 MethodBase mb
= me
.Methods
[0];
509 ParameterData pd
= TypeManager
.GetParameterData (mb
);
511 int pd_count
= pd
.Count
;
513 bool params_method
= pd
.HasParams
;
514 bool is_params_applicable
= false;
515 bool is_applicable
= Invocation
.IsApplicable (ec
, me
, args
, arg_count
, ref mb
);
517 if (!is_applicable
&& params_method
&&
518 Invocation
.IsParamsMethodApplicable (ec
, me
, args
, arg_count
, ref mb
))
519 is_applicable
= is_params_applicable
= true;
521 if (!is_applicable
&& !params_method
&& arg_count
!= pd_count
) {
522 Report
.Error (1593, loc
, "Delegate `{0}' does not take `{1}' arguments",
523 TypeManager
.CSharpName (delegate_type
), arg_count
.ToString ());
527 return Invocation
.VerifyArgumentsCompat (
528 ec
, args
, arg_count
, mb
,
529 is_params_applicable
|| (!is_applicable
&& params_method
),
530 delegate_type
, false, loc
);
534 /// Verifies whether the delegate in question is compatible with this one in
535 /// order to determine if instantiation from the same is possible.
537 public static bool VerifyDelegate (EmitContext ec
, Type delegate_type
, Type probe_type
, Location loc
)
539 Expression ml
= Expression
.MemberLookup (
540 ec
, delegate_type
, "Invoke", loc
);
542 if (!(ml
is MethodGroupExpr
)) {
543 Report
.Error (-100, loc
, "Internal error: could not find Invoke method!");
547 MethodBase mb
= ((MethodGroupExpr
) ml
).Methods
[0];
548 ParameterData pd
= TypeManager
.GetParameterData (mb
);
550 Expression probe_ml
= Expression
.MemberLookup (
551 ec
, delegate_type
, "Invoke", loc
);
553 if (!(probe_ml
is MethodGroupExpr
)) {
554 Report
.Error (-100, loc
, "Internal error: could not find Invoke method!");
558 MethodBase probe_mb
= ((MethodGroupExpr
) probe_ml
).Methods
[0];
559 ParameterData probe_pd
= TypeManager
.GetParameterData (probe_mb
);
561 if (((MethodInfo
) mb
).ReturnType
!= ((MethodInfo
) probe_mb
).ReturnType
)
564 if (pd
.Count
!= probe_pd
.Count
)
567 for (int i
= pd
.Count
; i
> 0; ) {
570 if (pd
.ParameterType (i
) != probe_pd
.ParameterType (i
) ||
571 pd
.ParameterModifier (i
) != probe_pd
.ParameterModifier (i
))
578 public static string FullDelegateDesc (Type del_type
, MethodBase mb
, ParameterData pd
)
580 StringBuilder sb
= new StringBuilder ();
581 sb
.Append (TypeManager
.CSharpName (((MethodInfo
) mb
).ReturnType
));
583 sb
.Append (TypeManager
.CSharpName (del_type
));
584 sb
.Append (pd
.GetSignatureForError ());
585 return sb
.ToString ();
588 // Hack around System.Reflection as found everywhere else
589 public override MemberList
FindMembers (MemberTypes mt
, BindingFlags bf
,
590 MemberFilter filter
, object criteria
)
592 ArrayList members
= new ArrayList ();
594 if ((mt
& MemberTypes
.Method
) != 0) {
595 if (ConstructorBuilder
!= null)
596 if (filter (ConstructorBuilder
, criteria
))
597 members
.Add (ConstructorBuilder
);
599 if (InvokeBuilder
!= null)
600 if (filter (InvokeBuilder
, criteria
))
601 members
.Add (InvokeBuilder
);
603 if (BeginInvokeBuilder
!= null)
604 if (filter (BeginInvokeBuilder
, criteria
))
605 members
.Add (BeginInvokeBuilder
);
607 if (EndInvokeBuilder
!= null)
608 if (filter (EndInvokeBuilder
, criteria
))
609 members
.Add (EndInvokeBuilder
);
612 return new MemberList (members
);
615 public override MemberCache MemberCache
{
621 public Expression InstanceExpression
{
623 return instance_expr
;
626 instance_expr
= value;
630 public MethodBase TargetMethod
{
632 return delegate_method
;
635 delegate_method
= value;
639 public Type TargetReturnType
{
645 public override AttributeTargets AttributeTargets
{
647 return AttributeTargets
.Delegate
;
652 // Represents header string for documentation comment.
654 public override string DocCommentHeader
{
661 // Base class for `NewDelegate' and `ImplicitDelegateCreation'
663 public abstract class DelegateCreation
: Expression
{
664 protected MethodBase constructor_method
;
665 protected MethodBase delegate_method
;
666 protected MethodGroupExpr method_group
;
667 protected Expression delegate_instance_expression
;
669 public DelegateCreation () {}
671 public static void Error_NoMatchingMethodForDelegate (EmitContext ec
, MethodGroupExpr mg
, Type type
, Location loc
)
674 MethodBase found_method
= mg
.Methods
[0];
676 if (mg
.Methods
.Length
> 1)
677 method_desc
= found_method
.Name
;
679 method_desc
= Invocation
.FullMethodDesc (found_method
);
681 Expression invoke_method
= Expression
.MemberLookup (
682 ec
, type
, "Invoke", MemberTypes
.Method
,
683 Expression
.AllBindingFlags
, loc
);
684 MethodInfo method
= ((MethodGroupExpr
) invoke_method
).Methods
[0] as MethodInfo
;
686 ParameterData param
= TypeManager
.GetParameterData (method
);
687 string delegate_desc
= Delegate
.FullDelegateDesc (type
, method
, param
);
689 if (!mg
.HasTypeArguments
&&
690 !TypeManager
.InferTypeArguments (ec
, param
, ref found_method
))
691 Report
.Error (411, loc
, "The type arguments for " +
692 "method `{0}' cannot be infered from " +
693 "the usage. Try specifying the type " +
694 "arguments explicitly.", method_desc
);
695 else if (method
.ReturnType
!= ((MethodInfo
) found_method
).ReturnType
) {
696 Report
.Error (407, loc
, "`{0}' has the wrong return type to match the delegate `{1}'", method_desc
, delegate_desc
);
698 Report
.Error (123, loc
, "Method `{0}' does not match delegate `{1}'", method_desc
, delegate_desc
);
702 public override void Emit (EmitContext ec
)
704 if (delegate_instance_expression
== null || delegate_method
.IsStatic
)
705 ec
.ig
.Emit (OpCodes
.Ldnull
);
707 delegate_instance_expression
.Emit (ec
);
709 if (delegate_method
.IsVirtual
&& !method_group
.IsBase
) {
710 ec
.ig
.Emit (OpCodes
.Dup
);
711 ec
.ig
.Emit (OpCodes
.Ldvirtftn
, (MethodInfo
) delegate_method
);
713 ec
.ig
.Emit (OpCodes
.Ldftn
, (MethodInfo
) delegate_method
);
714 ec
.ig
.Emit (OpCodes
.Newobj
, (ConstructorInfo
) constructor_method
);
717 protected bool ResolveConstructorMethod (EmitContext ec
)
719 Expression ml
= Expression
.MemberLookup (
720 ec
, type
, ".ctor", loc
);
722 if (!(ml
is MethodGroupExpr
)) {
723 Report
.Error (-100, loc
, "Internal error: Could not find delegate constructor!");
727 constructor_method
= ((MethodGroupExpr
) ml
).Methods
[0];
731 protected Expression
ResolveMethodGroupExpr (EmitContext ec
, MethodGroupExpr mg
,
734 foreach (MethodInfo mi
in mg
.Methods
){
735 delegate_method
= Delegate
.VerifyMethod (ec
, type
, mg
, mi
, loc
);
737 if (delegate_method
!= null)
741 if (delegate_method
== null) {
743 Error_NoMatchingMethodForDelegate (ec
, mg
, type
, loc
);
748 // Check safe/unsafe of the delegate
751 ParameterData param
= TypeManager
.GetParameterData (delegate_method
);
752 int count
= param
.Count
;
754 for (int i
= 0; i
< count
; i
++){
755 if (param
.ParameterType (i
).IsPointer
){
756 Expression
.UnsafeError (loc
);
762 //TODO: implement caching when performance will be low
763 IMethodData md
= TypeManager
.GetMethod (delegate_method
);
765 if (System
.Attribute
.GetCustomAttribute (delegate_method
, TypeManager
.conditional_attribute_type
) != null) {
766 Report
.Error (1618, loc
, "Cannot create delegate with `{0}' because it has a Conditional attribute", TypeManager
.CSharpSignature (delegate_method
));
769 md
.SetMemberIsUsed ();
770 if (md
.OptAttributes
!= null && md
.OptAttributes
.Search (TypeManager
.conditional_attribute_type
, ec
) != null) {
771 Report
.Error (1618, loc
, "Cannot create delegate with `{0}' because it has a Conditional attribute", TypeManager
.CSharpSignature (delegate_method
));
775 if (mg
.InstanceExpression
!= null)
776 delegate_instance_expression
= mg
.InstanceExpression
.Resolve (ec
);
777 else if (ec
.IsStatic
) {
778 if (!delegate_method
.IsStatic
) {
779 Report
.Error (120, loc
, "`{0}': An object reference is required for the nonstatic field, method or property",
780 TypeManager
.CSharpSignature (delegate_method
));
783 delegate_instance_expression
= null;
785 delegate_instance_expression
= ec
.GetThis (loc
);
787 if (delegate_instance_expression
!= null && delegate_instance_expression
.Type
.IsValueType
)
788 delegate_instance_expression
= new BoxedCast (
789 delegate_instance_expression
, TypeManager
.object_type
);
792 eclass
= ExprClass
.Value
;
798 // Created from the conversion code
800 public class ImplicitDelegateCreation
: DelegateCreation
{
802 ImplicitDelegateCreation (Type t
, Location l
)
808 public override Expression
DoResolve (EmitContext ec
)
813 static public Expression
Create (EmitContext ec
, MethodGroupExpr mge
,
814 Type target_type
, bool check_only
, Location loc
)
816 ImplicitDelegateCreation d
= new ImplicitDelegateCreation (target_type
, loc
);
817 if (d
.ResolveConstructorMethod (ec
))
818 return d
.ResolveMethodGroupExpr (ec
, mge
, check_only
);
825 // A delegate-creation-expression, invoked from the `New' class
827 public class NewDelegate
: DelegateCreation
{
828 public ArrayList Arguments
;
831 // This constructor is invoked from the `New' expression
833 public NewDelegate (Type type
, ArrayList Arguments
, Location loc
)
836 this.Arguments
= Arguments
;
840 public override Expression
DoResolve (EmitContext ec
)
842 if (Arguments
== null || Arguments
.Count
!= 1) {
843 Report
.Error (149, loc
,
844 "Method name expected");
848 if (!ResolveConstructorMethod (ec
))
851 Argument a
= (Argument
) Arguments
[0];
853 if (!a
.ResolveMethodGroup (ec
, loc
))
856 Expression e
= a
.Expr
;
858 if (e
is AnonymousMethod
&& RootContext
.Version
!= LanguageVersion
.ISO_1
)
859 return ((AnonymousMethod
) e
).Compatible (ec
, type
, false);
861 MethodGroupExpr mg
= e
as MethodGroupExpr
;
863 return ResolveMethodGroupExpr (ec
, mg
, false);
865 Type e_type
= e
.Type
;
867 if (!TypeManager
.IsDelegateType (e_type
)) {
868 Report
.Error (149, loc
, "Method name expected");
872 method_group
= Expression
.MemberLookup (
873 ec
, type
, "Invoke", MemberTypes
.Method
,
874 Expression
.AllBindingFlags
, loc
) as MethodGroupExpr
;
876 if (method_group
== null) {
877 Report
.Error (-200, loc
, "Internal error ! Could not find Invoke method!");
881 // This is what MS' compiler reports. We could always choose
882 // to be more verbose and actually give delegate-level specifics
883 if (!Delegate
.VerifyDelegate (ec
, type
, e_type
, loc
)) {
884 Report
.Error (29, loc
, "Cannot implicitly convert type '" + e_type
+ "' " +
885 "to type '" + type
+ "'");
889 delegate_instance_expression
= e
;
890 delegate_method
= method_group
.Methods
[0];
892 eclass
= ExprClass
.Value
;
897 public class DelegateInvocation
: ExpressionStatement
{
899 public Expression InstanceExpr
;
900 public ArrayList Arguments
;
904 public DelegateInvocation (Expression instance_expr
, ArrayList args
, Location loc
)
906 this.InstanceExpr
= instance_expr
;
907 this.Arguments
= args
;
911 public override Expression
DoResolve (EmitContext ec
)
913 if (InstanceExpr
is EventExpr
) {
915 EventInfo ei
= ((EventExpr
) InstanceExpr
).EventInfo
;
917 Expression ml
= MemberLookup (
918 ec
, ec
.ContainerType
, ei
.Name
,
919 MemberTypes
.Event
, AllBindingFlags
| BindingFlags
.DeclaredOnly
, loc
);
923 // If this is the case, then the Event does not belong
924 // to this Type and so, according to the spec
925 // cannot be accessed directly
927 // Note that target will not appear as an EventExpr
928 // in the case it is being referenced within the same type container;
929 // it will appear as a FieldExpr in that case.
932 Assign
.error70 (ei
, loc
);
938 Type del_type
= InstanceExpr
.Type
;
939 if (del_type
== null)
942 if (Arguments
!= null){
943 foreach (Argument a
in Arguments
){
944 if (!a
.Resolve (ec
, loc
))
949 if (!Delegate
.VerifyApplicability (ec
, del_type
, Arguments
, loc
))
952 Expression lookup
= Expression
.MemberLookup (ec
, del_type
, "Invoke", loc
);
953 if (!(lookup
is MethodGroupExpr
)) {
954 Report
.Error (-100, loc
, "Internal error: could not find Invoke method!");
958 method
= ((MethodGroupExpr
) lookup
).Methods
[0];
959 type
= ((MethodInfo
) method
).ReturnType
;
960 eclass
= ExprClass
.Value
;
965 public override void Emit (EmitContext ec
)
968 // Invocation on delegates call the virtual Invoke member
969 // so we are always `instance' calls
971 Invocation
.EmitCall (ec
, false, false, InstanceExpr
, method
, Arguments
, loc
);
974 public override void EmitStatement (EmitContext ec
)
978 // Pop the return value if there is one
980 if (method
is MethodInfo
){
981 Type ret
= ((MethodInfo
)method
).ReturnType
;
982 if (TypeManager
.TypeToCoreType (ret
) != TypeManager
.void_type
)
983 ec
.ig
.Emit (OpCodes
.Pop
);