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 TypeManager
.RegisterMethod (BeginInvokeBuilder
, async_parameters
);
271 // EndInvoke is a bit more interesting, all the parameters labeled as
272 // out or ref have to be duplicated here.
276 // Define parameters, and count out/ref parameters
278 Parameters end_parameters
;
281 foreach (Parameter p
in Parameters
.FixedParameters
) {
282 if ((p
.ModFlags
& Parameter
.Modifier
.ISBYREF
) != 0)
286 if (out_params
> 0) {
287 Type
[] end_param_types
= new Type
[out_params
];
288 Parameter
[] end_params
= new Parameter
[out_params
];
291 for (int i
= 0; i
< Parameters
.FixedParameters
.Length
; ++i
) {
292 Parameter p
= Parameters
.FixedParameters
[i
];
293 if ((p
.ModFlags
& Parameter
.Modifier
.ISBYREF
) == 0)
296 end_param_types
[param
] = p
.ExternalType();
297 end_params
[param
] = p
;
300 end_parameters
= new Parameters (end_params
, end_param_types
);
303 end_parameters
= Parameters
.EmptyReadOnlyParameters
;
306 end_parameters
= Parameters
.MergeGenerated (end_parameters
,
307 new Parameter (TypeManager
.iasyncresult_type
, "result", Parameter
.Modifier
.NONE
, null, Location
));
310 // Create method, define parameters, register parameters with type system
312 EndInvokeBuilder
= TypeBuilder
.DefineMethod ("EndInvoke", mattr
, cc
, ret_type
, end_parameters
.Types
);
313 EndInvokeBuilder
.SetImplementationFlags (MethodImplAttributes
.Runtime
);
315 end_parameters
.ApplyAttributes (EndInvokeBuilder
);
316 TypeManager
.RegisterMethod (EndInvokeBuilder
, end_parameters
);
321 public override void Emit ()
323 Parameters
.ApplyAttributes (InvokeBuilder
);
325 Parameters p
= (Parameters
)TypeManager
.GetParameterData (BeginInvokeBuilder
);
326 p
.ApplyAttributes (BeginInvokeBuilder
);
328 if (OptAttributes
!= null) {
329 OptAttributes
.Emit ();
335 protected override TypeAttributes TypeAttr
{
337 return Modifiers
.TypeAttr (ModFlags
, IsTopLevel
) |
338 TypeAttributes
.Class
| TypeAttributes
.Sealed
|
343 public override string[] ValidAttributeTargets
{
345 return attribute_targets
;
350 protected override bool VerifyClsCompliance ()
352 if (!base.VerifyClsCompliance ()) {
356 Parameters
.VerifyClsCompliance ();
358 if (!AttributeTester
.IsClsCompliant (ReturnType
.Type
)) {
359 Report
.Error (3002, Location
, "Return type of `{0}' is not CLS-compliant", GetSignatureForError ());
365 // Returns the MethodBase for "Invoke" from a delegate type, this is used
366 // to extract the signature of a delegate.
368 public static MethodGroupExpr
GetInvokeMethod (Type container_type
, Type delegate_type
, Location loc
)
370 Expression ml
= Expression
.MemberLookup (container_type
, null, delegate_type
,
373 MethodGroupExpr mg
= ml
as MethodGroupExpr
;
375 Report
.Error (-100, loc
, "Internal error: could not find Invoke method!");
383 /// Verifies whether the method in question is compatible with the delegate
384 /// Returns the method itself if okay and null if not.
386 public static MethodBase
VerifyMethod (Type container_type
, Type delegate_type
,
387 MethodGroupExpr old_mg
, MethodBase mb
,
390 MethodGroupExpr mg
= GetInvokeMethod (container_type
, delegate_type
, loc
);
394 if (old_mg
.HasTypeArguments
)
395 mg
.HasTypeArguments
= true;
397 MethodBase invoke_mb
= mg
.Methods
[0];
398 ParameterData invoke_pd
= TypeManager
.GetParameterData (invoke_mb
);
401 if (!mg
.HasTypeArguments
&&
402 !TypeManager
.InferTypeArguments (invoke_pd
, ref mb
))
406 ParameterData pd
= TypeManager
.GetParameterData (mb
);
408 if (invoke_pd
.Count
!= pd
.Count
)
411 for (int i
= pd
.Count
; i
> 0; ) {
414 Type invoke_pd_type
= invoke_pd
.ParameterType (i
);
415 Type pd_type
= pd
.ParameterType (i
);
416 Parameter
.Modifier invoke_pd_type_mod
= invoke_pd
.ParameterModifier (i
);
417 Parameter
.Modifier pd_type_mod
= pd
.ParameterModifier (i
);
419 invoke_pd_type_mod
&= ~Parameter
.Modifier
.PARAMS
;
420 pd_type_mod
&= ~Parameter
.Modifier
.PARAMS
;
422 if (invoke_pd_type_mod
!= pd_type_mod
)
425 if (invoke_pd_type
== pd_type
)
428 if (!Convert
.ImplicitReferenceConversionExists (new EmptyExpression (invoke_pd_type
), pd_type
))
431 if (RootContext
.Version
== LanguageVersion
.ISO_1
)
435 Type invoke_mb_retval
= ((MethodInfo
) invoke_mb
).ReturnType
;
436 Type mb_retval
= ((MethodInfo
) mb
).ReturnType
;
437 if (invoke_mb_retval
== mb_retval
)
440 if (!Convert
.ImplicitReferenceConversionExists (new EmptyExpression (mb_retval
), invoke_mb_retval
))
443 if (RootContext
.Version
== LanguageVersion
.ISO_1
)
450 // Verifies whether the invocation arguments are compatible with the
451 // delegate's target method
453 public static bool VerifyApplicability (EmitContext ec
, Type delegate_type
,
454 ArrayList args
, Location loc
)
461 arg_count
= args
.Count
;
463 Expression ml
= Expression
.MemberLookup (
464 ec
.ContainerType
, delegate_type
, "Invoke", loc
);
466 MethodGroupExpr me
= ml
as MethodGroupExpr
;
468 Report
.Error (-100, loc
, "Internal error: could not find Invoke method!" + delegate_type
);
472 MethodBase mb
= me
.Methods
[0];
473 ParameterData pd
= TypeManager
.GetParameterData (mb
);
475 int pd_count
= pd
.Count
;
477 bool params_method
= pd
.HasParams
;
478 bool is_params_applicable
= false;
479 bool is_applicable
= Invocation
.IsApplicable (ec
, me
, args
, arg_count
, ref mb
);
481 if (!is_applicable
&& params_method
&&
482 Invocation
.IsParamsMethodApplicable (ec
, me
, args
, arg_count
, ref mb
))
483 is_applicable
= is_params_applicable
= true;
485 if (!is_applicable
&& !params_method
&& arg_count
!= pd_count
) {
486 Report
.Error (1593, loc
, "Delegate `{0}' does not take `{1}' arguments",
487 TypeManager
.CSharpName (delegate_type
), arg_count
.ToString ());
491 return Invocation
.VerifyArgumentsCompat (
492 ec
, args
, arg_count
, mb
,
493 is_params_applicable
|| (!is_applicable
&& params_method
),
494 delegate_type
, false, loc
);
498 /// Verifies whether the delegate in question is compatible with this one in
499 /// order to determine if instantiation from the same is possible.
501 public static bool VerifyDelegate (EmitContext ec
, Type delegate_type
, Location loc
)
503 Expression ml
= Expression
.MemberLookup (
504 ec
.ContainerType
, delegate_type
, "Invoke", loc
);
506 if (!(ml
is MethodGroupExpr
)) {
507 Report
.Error (-100, loc
, "Internal error: could not find Invoke method!");
511 MethodBase mb
= ((MethodGroupExpr
) ml
).Methods
[0];
512 ParameterData pd
= TypeManager
.GetParameterData (mb
);
514 Expression probe_ml
= Expression
.MemberLookup (
515 ec
.ContainerType
, delegate_type
, "Invoke", loc
);
517 if (!(probe_ml
is MethodGroupExpr
)) {
518 Report
.Error (-100, loc
, "Internal error: could not find Invoke method!");
522 MethodBase probe_mb
= ((MethodGroupExpr
) probe_ml
).Methods
[0];
523 ParameterData probe_pd
= TypeManager
.GetParameterData (probe_mb
);
525 if (((MethodInfo
) mb
).ReturnType
!= ((MethodInfo
) probe_mb
).ReturnType
)
528 if (pd
.Count
!= probe_pd
.Count
)
531 for (int i
= pd
.Count
; i
> 0; ) {
534 if (pd
.ParameterType (i
) != probe_pd
.ParameterType (i
) ||
535 pd
.ParameterModifier (i
) != probe_pd
.ParameterModifier (i
))
542 public static string FullDelegateDesc (Type del_type
, MethodBase mb
, ParameterData pd
)
544 StringBuilder sb
= new StringBuilder ();
545 sb
.Append (TypeManager
.CSharpName (((MethodInfo
) mb
).ReturnType
));
547 sb
.Append (TypeManager
.CSharpName (del_type
));
548 sb
.Append (pd
.GetSignatureForError ());
549 return sb
.ToString ();
552 // Hack around System.Reflection as found everywhere else
553 public override MemberList
FindMembers (MemberTypes mt
, BindingFlags bf
,
554 MemberFilter filter
, object criteria
)
556 ArrayList members
= new ArrayList (2);
558 if ((mt
& MemberTypes
.Constructor
) != 0) {
559 if (ConstructorBuilder
!= null && filter (ConstructorBuilder
, criteria
))
560 members
.Add (ConstructorBuilder
);
563 if ((mt
& MemberTypes
.Method
) != 0) {
564 if (InvokeBuilder
!= null)
565 if (filter (InvokeBuilder
, criteria
))
566 members
.Add (InvokeBuilder
);
568 if (BeginInvokeBuilder
!= null)
569 if (filter (BeginInvokeBuilder
, criteria
))
570 members
.Add (BeginInvokeBuilder
);
572 if (EndInvokeBuilder
!= null)
573 if (filter (EndInvokeBuilder
, criteria
))
574 members
.Add (EndInvokeBuilder
);
577 return new MemberList (members
);
580 public override MemberCache MemberCache
{
586 public Expression InstanceExpression
{
588 return instance_expr
;
591 instance_expr
= value;
595 public MethodBase TargetMethod
{
597 return delegate_method
;
600 delegate_method
= value;
604 public Type TargetReturnType
{
610 public override AttributeTargets AttributeTargets
{
612 return AttributeTargets
.Delegate
;
617 // Represents header string for documentation comment.
619 public override string DocCommentHeader
{
625 // Base class for `NewDelegate' and `ImplicitDelegateCreation'
627 public abstract class DelegateCreation
: Expression
{
628 protected MethodBase constructor_method
;
629 protected MethodBase delegate_method
;
630 protected MethodGroupExpr method_group
;
631 protected Expression delegate_instance_expression
;
633 protected DelegateCreation () {}
635 public static void Error_NoMatchingMethodForDelegate (EmitContext ec
, MethodGroupExpr mg
, Type type
, Location loc
)
638 MethodBase found_method
= mg
.Methods
[0];
640 if (mg
.Methods
.Length
> 1)
641 method_desc
= found_method
.Name
;
643 method_desc
= Invocation
.FullMethodDesc (found_method
);
645 Expression invoke_method
= Expression
.MemberLookup (
646 ec
.ContainerType
, type
, "Invoke", MemberTypes
.Method
,
647 Expression
.AllBindingFlags
, loc
);
648 MethodInfo method
= ((MethodGroupExpr
) invoke_method
).Methods
[0] as MethodInfo
;
650 ParameterData param
= TypeManager
.GetParameterData (method
);
651 string delegate_desc
= Delegate
.FullDelegateDesc (type
, method
, param
);
654 if (!mg
.HasTypeArguments
&&
655 !TypeManager
.InferTypeArguments (param
, ref found_method
)) {
656 Report
.Error (411, loc
, "The type arguments for " +
657 "method `{0}' cannot be inferred from " +
658 "the usage. Try specifying the type " +
659 "arguments explicitly.", method_desc
);
663 Report
.SymbolRelatedToPreviousError (found_method
);
665 if (RootContext
.Version
== LanguageVersion
.ISO_1
) {
666 Report
.Error (410, loc
, "The method `{0}' parameters and return type must be same as delegate `{1}' parameters and return type",
667 method_desc
, delegate_desc
);
671 Type delegateType
= method
.ReturnType
;
672 Type methodType
= ((MethodInfo
) found_method
).ReturnType
;
673 if (delegateType
!= methodType
&&
674 !Convert
.ImplicitReferenceConversionExists (new EmptyExpression (methodType
), delegateType
)) {
675 Report
.Error (407, loc
, "`{0}' has the wrong return type to match the delegate `{1}'", method_desc
, delegate_desc
);
677 Report
.Error (123, loc
, "The method `{0}' parameters do not match delegate `{1}' parameters",
678 TypeManager
.CSharpSignature (found_method
), delegate_desc
);
682 public override void Emit (EmitContext ec
)
684 if (delegate_instance_expression
== null || delegate_method
.IsStatic
)
685 ec
.ig
.Emit (OpCodes
.Ldnull
);
687 delegate_instance_expression
.Emit (ec
);
689 if (delegate_method
.IsVirtual
&& !method_group
.IsBase
) {
690 ec
.ig
.Emit (OpCodes
.Dup
);
691 ec
.ig
.Emit (OpCodes
.Ldvirtftn
, (MethodInfo
) delegate_method
);
693 ec
.ig
.Emit (OpCodes
.Ldftn
, (MethodInfo
) delegate_method
);
694 ec
.ig
.Emit (OpCodes
.Newobj
, (ConstructorInfo
) constructor_method
);
697 protected bool ResolveConstructorMethod (EmitContext ec
)
699 Expression ml
= Expression
.MemberLookupFinal(ec
,
700 null, type
, ".ctor", MemberTypes
.Constructor
, AllBindingFlags
| BindingFlags
.DeclaredOnly
, loc
);
702 if (!(ml
is MethodGroupExpr
)) {
703 Report
.Error (-100, loc
, "Internal error: Could not find delegate constructor!");
707 constructor_method
= ((MethodGroupExpr
) ml
).Methods
[0];
711 public static MethodBase
ImplicitStandardConversionExists (MethodGroupExpr mg
, Type targetType
)
713 foreach (MethodInfo mi
in mg
.Methods
){
714 MethodBase mb
= Delegate
.VerifyMethod (mg
.DeclaringType
, targetType
, mg
, mi
, Location
.Null
);
721 protected Expression
ResolveMethodGroupExpr (EmitContext ec
, MethodGroupExpr mg
)
723 delegate_method
= ImplicitStandardConversionExists (mg
, type
);
725 if (delegate_method
== null) {
726 Error_NoMatchingMethodForDelegate (ec
, mg
, type
, loc
);
731 // Check safe/unsafe of the delegate
734 ParameterData param
= TypeManager
.GetParameterData (delegate_method
);
735 int count
= param
.Count
;
737 for (int i
= 0; i
< count
; i
++){
738 if (param
.ParameterType (i
).IsPointer
){
739 Expression
.UnsafeError (loc
);
745 //TODO: implement caching when performance will be low
746 IMethodData md
= TypeManager
.GetMethod (
747 TypeManager
.DropGenericMethodArguments (delegate_method
));
749 if (System
.Attribute
.GetCustomAttribute (delegate_method
, TypeManager
.conditional_attribute_type
) != null) {
750 Report
.SymbolRelatedToPreviousError (delegate_method
);
751 Report
.Error (1618, loc
, "Cannot create delegate with `{0}' because it has a Conditional attribute", TypeManager
.CSharpSignature (delegate_method
));
755 md
.SetMemberIsUsed ();
756 if (md
.OptAttributes
!= null && md
.OptAttributes
.Search (TypeManager
.conditional_attribute_type
) != null) {
757 Report
.SymbolRelatedToPreviousError (delegate_method
);
758 Report
.Error (1618, loc
, "Cannot create delegate with `{0}' because it has a Conditional attribute", TypeManager
.CSharpSignature (delegate_method
));
763 if (mg
.InstanceExpression
!= null)
764 delegate_instance_expression
= mg
.InstanceExpression
.Resolve (ec
);
765 else if (ec
.IsStatic
) {
766 if (!delegate_method
.IsStatic
) {
767 Report
.Error (120, loc
, "`{0}': An object reference is required for the nonstatic field, method or property",
768 TypeManager
.CSharpSignature (delegate_method
));
771 delegate_instance_expression
= null;
773 delegate_instance_expression
= ec
.GetThis (loc
);
775 if (delegate_instance_expression
!= null && delegate_instance_expression
.Type
.IsValueType
)
776 delegate_instance_expression
= new BoxedCast (
777 delegate_instance_expression
, TypeManager
.object_type
);
780 eclass
= ExprClass
.Value
;
786 // Created from the conversion code
788 public class ImplicitDelegateCreation
: DelegateCreation
{
790 ImplicitDelegateCreation (Type t
, Location l
)
796 public override Expression
DoResolve (EmitContext ec
)
801 static public Expression
Create (EmitContext ec
, MethodGroupExpr mge
,
802 Type target_type
, Location loc
)
804 ImplicitDelegateCreation d
= new ImplicitDelegateCreation (target_type
, loc
);
805 if (!d
.ResolveConstructorMethod (ec
))
808 return d
.ResolveMethodGroupExpr (ec
, mge
);
813 // A delegate-creation-expression, invoked from the `New' class
815 public class NewDelegate
: DelegateCreation
{
816 public ArrayList Arguments
;
819 // This constructor is invoked from the `New' expression
821 public NewDelegate (Type type
, ArrayList Arguments
, Location loc
)
824 this.Arguments
= Arguments
;
828 public override Expression
DoResolve (EmitContext ec
)
830 if (Arguments
== null) {
831 Invocation
.Error_WrongNumArguments (loc
, GetSignatureForError (), 0);
835 if (!ResolveConstructorMethod (ec
))
838 Argument a
= (Argument
) Arguments
[0];
840 if (!a
.ResolveMethodGroup (ec
))
843 Expression e
= a
.Expr
;
845 if (e
is AnonymousMethodExpression
&& RootContext
.Version
!= LanguageVersion
.ISO_1
)
846 return ((AnonymousMethodExpression
) e
).Compatible (ec
, type
);
848 MethodGroupExpr mg
= e
as MethodGroupExpr
;
850 if (TypeManager
.IsNullableType (mg
.DeclaringType
)) {
851 Report
.Error (1728, loc
, "Cannot use method `{0}' as delegate creation expression because it is member of Nullable type",
852 mg
.GetSignatureForError ());
856 return ResolveMethodGroupExpr (ec
, mg
);
859 if (!TypeManager
.IsDelegateType (e
.Type
)) {
860 Report
.Error (149, loc
, "Method name expected");
864 method_group
= Expression
.MemberLookup (
865 ec
.ContainerType
, type
, "Invoke", MemberTypes
.Method
,
866 Expression
.AllBindingFlags
, loc
) as MethodGroupExpr
;
868 if (method_group
== null) {
869 Report
.Error (-200, loc
, "Internal error ! Could not find Invoke method!");
873 // This is what MS' compiler reports. We could always choose
874 // to be more verbose and actually give delegate-level specifics
875 if (!Delegate
.VerifyDelegate (ec
, type
, loc
)) {
876 Report
.Error (29, loc
, "Cannot implicitly convert type '" + e
.Type
+ "' " +
877 "to type '" + type
+ "'");
881 delegate_instance_expression
= e
;
882 delegate_method
= method_group
.Methods
[0];
884 eclass
= ExprClass
.Value
;
889 public class DelegateInvocation
: ExpressionStatement
{
891 public Expression InstanceExpr
;
892 public ArrayList Arguments
;
896 public DelegateInvocation (Expression instance_expr
, ArrayList args
, Location loc
)
898 this.InstanceExpr
= instance_expr
;
899 this.Arguments
= args
;
903 public override Expression
DoResolve (EmitContext ec
)
905 if (InstanceExpr
is EventExpr
) {
907 EventInfo ei
= ((EventExpr
) InstanceExpr
).EventInfo
;
909 Expression ml
= MemberLookup (
910 ec
.ContainerType
, ec
.ContainerType
, ei
.Name
,
911 MemberTypes
.Event
, AllBindingFlags
| BindingFlags
.DeclaredOnly
, loc
);
915 // If this is the case, then the Event does not belong
916 // to this Type and so, according to the spec
917 // cannot be accessed directly
919 // Note that target will not appear as an EventExpr
920 // in the case it is being referenced within the same type container;
921 // it will appear as a FieldExpr in that case.
924 Assign
.error70 (ei
, loc
);
930 Type del_type
= InstanceExpr
.Type
;
931 if (del_type
== null)
934 if (Arguments
!= null){
935 foreach (Argument a
in Arguments
){
936 if (!a
.Resolve (ec
, loc
))
941 if (!Delegate
.VerifyApplicability (ec
, del_type
, Arguments
, loc
))
944 Expression lookup
= Expression
.MemberLookup (ec
.ContainerType
, del_type
, "Invoke", loc
);
945 if (!(lookup
is MethodGroupExpr
)) {
946 Report
.Error (-100, loc
, "Internal error: could not find Invoke method!");
950 method
= ((MethodGroupExpr
) lookup
).Methods
[0];
951 type
= ((MethodInfo
) method
).ReturnType
;
952 eclass
= ExprClass
.Value
;
957 public override void Emit (EmitContext ec
)
960 // Invocation on delegates call the virtual Invoke member
961 // so we are always `instance' calls
963 Invocation
.EmitCall (ec
, false, false, InstanceExpr
, method
, Arguments
, loc
);
966 public override void EmitStatement (EmitContext ec
)
970 // Pop the return value if there is one
972 if (method
is MethodInfo
){
973 Type ret
= ((MethodInfo
)method
).ReturnType
;
974 if (TypeManager
.TypeToCoreType (ret
) != TypeManager
.void_type
)
975 ec
.ig
.Emit (OpCodes
.Pop
);