~ubuntu-branches/ubuntu/oneiric/monodevelop/oneiric

« back to all changes in this revision

Viewing changes to src/addins/CSharpBinding/MonoDevelop.CSharp.Parser/mcs/delegate.cs

  • Committer: Bazaar Package Importer
  • Author(s): Jo Shields
  • Date: 2011-06-27 17:03:13 UTC
  • mto: (1.8.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 54.
  • Revision ID: james.westby@ubuntu.com-20110627170313-6cvz3s19x6e9hqe9
ImportĀ upstreamĀ versionĀ 2.5.92+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// delegate.cs: Delegate Handler
 
3
//
 
4
// Authors:
 
5
//     Ravi Pratap (ravi@ximian.com)
 
6
//     Miguel de Icaza (miguel@ximian.com)
 
7
//     Marek Safar (marek.safar@gmail.com)
 
8
//
 
9
// Dual licensed under the terms of the MIT X11 or GNU GPL
 
10
//
 
11
// Copyright 2001 Ximian, Inc (http://www.ximian.com)
 
12
// Copyright 2003-2009 Novell, Inc (http://www.novell.com)
 
13
//
 
14
 
 
15
using System;
 
16
 
 
17
#if STATIC
 
18
using IKVM.Reflection;
 
19
using IKVM.Reflection.Emit;
 
20
#else
 
21
using System.Reflection;
 
22
using System.Reflection.Emit;
 
23
#endif
 
24
 
 
25
namespace Mono.CSharp {
 
26
 
 
27
        //
 
28
        // Delegate container implementation
 
29
        //
 
30
        public class Delegate : TypeContainer, IParametersMember
 
31
        {
 
32
                public FullNamedExpression ReturnType;
 
33
                readonly ParametersCompiled parameters;
 
34
 
 
35
                Constructor Constructor;
 
36
                Method InvokeBuilder;
 
37
                Method BeginInvokeBuilder;
 
38
                Method EndInvokeBuilder;
 
39
 
 
40
                static readonly string[] attribute_targets = new string [] { "type", "return" };
 
41
 
 
42
                public static readonly string InvokeMethodName = "Invoke";
 
43
                
 
44
                Expression instance_expr;
 
45
                ReturnParameter return_attributes;
 
46
 
 
47
                const Modifiers MethodModifiers = Modifiers.PUBLIC | Modifiers.VIRTUAL;
 
48
 
 
49
                const Modifiers AllowedModifiers =
 
50
                        Modifiers.NEW |
 
51
                        Modifiers.PUBLIC |
 
52
                        Modifiers.PROTECTED |
 
53
                        Modifiers.INTERNAL |
 
54
                        Modifiers.UNSAFE |
 
55
                        Modifiers.PRIVATE;
 
56
 
 
57
                public Delegate (NamespaceContainer ns, DeclSpace parent, FullNamedExpression type,
 
58
                                 Modifiers mod_flags, MemberName name, ParametersCompiled param_list,
 
59
                                 Attributes attrs)
 
60
                        : base (ns, parent, name, attrs, MemberKind.Delegate)
 
61
 
 
62
                {
 
63
                        this.ReturnType = type;
 
64
                        ModFlags        = ModifiersExtensions.Check (AllowedModifiers, mod_flags,
 
65
                                                           IsTopLevel ? Modifiers.INTERNAL :
 
66
                                                           Modifiers.PRIVATE, name.Location, Report);
 
67
                        parameters      = param_list;
 
68
                        spec = new TypeSpec (Kind, null, this, null, ModFlags | Modifiers.SEALED);
 
69
                }
 
70
 
 
71
                #region Properties
 
72
                public TypeSpec MemberType {
 
73
                        get {
 
74
                                return ReturnType.Type;
 
75
                        }
 
76
                }
 
77
 
 
78
                public AParametersCollection Parameters {
 
79
                        get {
 
80
                                return parameters;
 
81
                        }
 
82
                }
 
83
                #endregion
 
84
 
 
85
                public override void Accept (StructuralVisitor visitor)
 
86
                {
 
87
                        visitor.Visit (this);
 
88
                }
 
89
 
 
90
                public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
 
91
                {
 
92
                        if (a.Target == AttributeTargets.ReturnValue) {
 
93
                                if (return_attributes == null)
 
94
                                        return_attributes = new ReturnParameter (this, InvokeBuilder.MethodBuilder, Location);
 
95
 
 
96
                                return_attributes.ApplyAttributeBuilder (a, ctor, cdata, pa);
 
97
                                return;
 
98
                        }
 
99
 
 
100
                        base.ApplyAttributeBuilder (a, ctor, cdata, pa);
 
101
                }
 
102
 
 
103
                public override AttributeTargets AttributeTargets {
 
104
                        get {
 
105
                                return AttributeTargets.Delegate;
 
106
                        }
 
107
                }
 
108
 
 
109
                protected override bool DoDefineMembers ()
 
110
                {
 
111
                        var builtin_types = Compiler.BuiltinTypes;
 
112
 
 
113
                        var ctor_parameters = ParametersCompiled.CreateFullyResolved (
 
114
                                new [] {
 
115
                                        new Parameter (new TypeExpression (builtin_types.Object, Location), "object", Parameter.Modifier.NONE, null, Location),
 
116
                                        new Parameter (new TypeExpression (builtin_types.IntPtr, Location), "method", Parameter.Modifier.NONE, null, Location)
 
117
                                },
 
118
                                new [] {
 
119
                                        builtin_types.Object,
 
120
                                        builtin_types.IntPtr
 
121
                                }
 
122
                        );
 
123
 
 
124
                        Constructor = new Constructor (this, Constructor.ConstructorName,
 
125
                                Modifiers.PUBLIC, null, ctor_parameters, null, Location);
 
126
                        Constructor.Define ();
 
127
 
 
128
                        //
 
129
                        // Here the various methods like Invoke, BeginInvoke etc are defined
 
130
                        //
 
131
                        // First, call the `out of band' special method for
 
132
                        // defining recursively any types we need:
 
133
                        //
 
134
                        var p = parameters;
 
135
 
 
136
                        if (!p.Resolve (this))
 
137
                                return false;
 
138
 
 
139
                        //
 
140
                        // Invoke method
 
141
                        //
 
142
 
 
143
                        // Check accessibility
 
144
                        foreach (var partype in p.Types) {
 
145
                                if (!IsAccessibleAs (partype)) {
 
146
                                        Report.SymbolRelatedToPreviousError (partype);
 
147
                                        Report.Error (59, Location,
 
148
                                                "Inconsistent accessibility: parameter type `{0}' is less accessible than delegate `{1}'",
 
149
                                                TypeManager.CSharpName (partype), GetSignatureForError ());
 
150
                                }
 
151
                        }
 
152
 
 
153
                        var ret_type = ReturnType.ResolveAsType (this);
 
154
                        if (ret_type == null)
 
155
                                return false;
 
156
 
 
157
                        //
 
158
                        // We don't have to check any others because they are all
 
159
                        // guaranteed to be accessible - they are standard types.
 
160
                        //
 
161
                        if (!IsAccessibleAs (ret_type)) {
 
162
                                Report.SymbolRelatedToPreviousError (ret_type);
 
163
                                Report.Error (58, Location,
 
164
                                                  "Inconsistent accessibility: return type `" +
 
165
                                                  TypeManager.CSharpName (ret_type) + "' is less " +
 
166
                                                  "accessible than delegate `" + GetSignatureForError () + "'");
 
167
                                return false;
 
168
                        }
 
169
 
 
170
                        CheckProtectedModifier ();
 
171
 
 
172
                        if (Compiler.Settings.StdLib && ret_type.IsSpecialRuntimeType) {
 
173
                                Method.Error1599 (Location, ret_type, Report);
 
174
                                return false;
 
175
                        }
 
176
 
 
177
                        TypeManager.CheckTypeVariance (ret_type, Variance.Covariant, this);
 
178
 
 
179
                        InvokeBuilder = new Method (this, null, ReturnType, MethodModifiers, new MemberName (InvokeMethodName), p, null);
 
180
                        InvokeBuilder.Define ();
 
181
 
 
182
                        //
 
183
                        // Don't emit async method for compiler generated delegates (e.g. dynamic site containers)
 
184
                        //
 
185
                        if (!IsCompilerGenerated) {
 
186
                                DefineAsyncMethods (Parameters.CallingConvention);
 
187
                        }
 
188
 
 
189
                        return true;
 
190
                }
 
191
 
 
192
                void DefineAsyncMethods (CallingConventions cc)
 
193
                {
 
194
                        var iasync_result = Module.PredefinedTypes.IAsyncResult;
 
195
                        var async_callback = Module.PredefinedTypes.AsyncCallback;
 
196
 
 
197
                        //
 
198
                        // It's ok when async types don't exist, the delegate will have Invoke method only
 
199
                        //
 
200
                        if (!iasync_result.Define () || !async_callback.Define ())
 
201
                                return;
 
202
 
 
203
                        //
 
204
                        // BeginInvoke
 
205
                        //
 
206
                        ParametersCompiled async_parameters;
 
207
                        if (Parameters.Count == 0) {
 
208
                                async_parameters = ParametersCompiled.EmptyReadOnlyParameters;
 
209
                        } else {
 
210
                                var compiled = new Parameter[Parameters.Count];
 
211
                                for (int i = 0; i < compiled.Length; ++i) {
 
212
                                        var p = parameters[i];
 
213
                                        compiled[i] = new Parameter (new TypeExpression (parameters.Types[i], Location),
 
214
                                                p.Name,
 
215
                                                p.ModFlags & (Parameter.Modifier.REF | Parameter.Modifier.OUT),
 
216
                                                p.OptAttributes == null ? null : p.OptAttributes.Clone (), Location);
 
217
                                }
 
218
 
 
219
                                async_parameters = new ParametersCompiled (compiled);
 
220
                        }
 
221
 
 
222
                        async_parameters = ParametersCompiled.MergeGenerated (Compiler, async_parameters, false,
 
223
                                new Parameter[] {
 
224
                                        new Parameter (new TypeExpression (async_callback.TypeSpec, Location), "callback", Parameter.Modifier.NONE, null, Location),
 
225
                                        new Parameter (new TypeExpression (Compiler.BuiltinTypes.Object, Location), "object", Parameter.Modifier.NONE, null, Location)
 
226
                                },
 
227
                                new [] {
 
228
                                        async_callback.TypeSpec,
 
229
                                        Compiler.BuiltinTypes.Object
 
230
                                }
 
231
                        );
 
232
 
 
233
                        BeginInvokeBuilder = new Method (this, null,
 
234
                                new TypeExpression (iasync_result.TypeSpec, Location), MethodModifiers,
 
235
                                new MemberName ("BeginInvoke"), async_parameters, null);
 
236
                        BeginInvokeBuilder.Define ();
 
237
 
 
238
                        //
 
239
                        // EndInvoke is a bit more interesting, all the parameters labeled as
 
240
                        // out or ref have to be duplicated here.
 
241
                        //
 
242
 
 
243
                        //
 
244
                        // Define parameters, and count out/ref parameters
 
245
                        //
 
246
                        ParametersCompiled end_parameters;
 
247
                        int out_params = 0;
 
248
 
 
249
                        foreach (Parameter p in Parameters.FixedParameters) {
 
250
                                if ((p.ModFlags & Parameter.Modifier.ISBYREF) != 0)
 
251
                                        ++out_params;
 
252
                        }
 
253
 
 
254
                        if (out_params > 0) {
 
255
                                Parameter[] end_params = new Parameter[out_params];
 
256
 
 
257
                                int param = 0;
 
258
                                for (int i = 0; i < Parameters.FixedParameters.Length; ++i) {
 
259
                                        Parameter p = parameters [i];
 
260
                                        if ((p.ModFlags & Parameter.Modifier.ISBYREF) == 0)
 
261
                                                continue;
 
262
 
 
263
                                        end_params [param++] = new Parameter (new TypeExpression (p.Type, Location),
 
264
                                                p.Name,
 
265
                                                p.ModFlags & (Parameter.Modifier.REF | Parameter.Modifier.OUT),
 
266
                                                p.OptAttributes == null ? null : p.OptAttributes.Clone (), Location);
 
267
                                }
 
268
 
 
269
                                end_parameters = new ParametersCompiled (end_params);
 
270
                        } else {
 
271
                                end_parameters = ParametersCompiled.EmptyReadOnlyParameters;
 
272
                        }
 
273
 
 
274
                        end_parameters = ParametersCompiled.MergeGenerated (Compiler, end_parameters, false,
 
275
                                new Parameter (
 
276
                                        new TypeExpression (iasync_result.TypeSpec, Location),
 
277
                                        "result", Parameter.Modifier.NONE, null, Location),
 
278
                                iasync_result.TypeSpec);
 
279
 
 
280
                        //
 
281
                        // Create method, define parameters, register parameters with type system
 
282
                        //
 
283
                        EndInvokeBuilder = new Method (this, null, ReturnType, MethodModifiers, new MemberName ("EndInvoke"), end_parameters, null);
 
284
                        EndInvokeBuilder.Define ();
 
285
                }
 
286
 
 
287
                public override void DefineConstants ()
 
288
                {
 
289
                        if (!Parameters.IsEmpty) {
 
290
                                parameters.ResolveDefaultValues (this);
 
291
                        }
 
292
                }
 
293
 
 
294
                public override void EmitType ()
 
295
                {
 
296
                        if (ReturnType.Type != null) {
 
297
                                if (ReturnType.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
 
298
                                        return_attributes = new ReturnParameter (this, InvokeBuilder.MethodBuilder, Location);
 
299
                                        Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder);
 
300
                                } else if (ReturnType.Type.HasDynamicElement) {
 
301
                                        return_attributes = new ReturnParameter (this, InvokeBuilder.MethodBuilder, Location);
 
302
                                        Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder, ReturnType.Type, Location);
 
303
                                }
 
304
 
 
305
                                ConstraintChecker.Check (this, ReturnType.Type, ReturnType.Location);
 
306
                        }
 
307
 
 
308
                        Constructor.ParameterInfo.ApplyAttributes (this, Constructor.ConstructorBuilder);
 
309
                        Constructor.ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
 
310
 
 
311
                        parameters.CheckConstraints (this);
 
312
                        parameters.ApplyAttributes (this, InvokeBuilder.MethodBuilder);
 
313
                        InvokeBuilder.MethodBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
 
314
 
 
315
                        if (BeginInvokeBuilder != null) {
 
316
                                BeginInvokeBuilder.ParameterInfo.ApplyAttributes (this, BeginInvokeBuilder.MethodBuilder);
 
317
                                EndInvokeBuilder.ParameterInfo.ApplyAttributes (this, EndInvokeBuilder.MethodBuilder);
 
318
 
 
319
                                BeginInvokeBuilder.MethodBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
 
320
                                EndInvokeBuilder.MethodBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
 
321
                        }
 
322
 
 
323
                        if (OptAttributes != null) {
 
324
                                OptAttributes.Emit ();
 
325
                        }
 
326
 
 
327
                        base.Emit ();
 
328
                }
 
329
 
 
330
                protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
 
331
                {
 
332
                        base_type = Compiler.BuiltinTypes.MulticastDelegate;
 
333
                        base_class = null;
 
334
                        return null;
 
335
                }
 
336
 
 
337
                protected override TypeAttributes TypeAttr {
 
338
                        get {
 
339
                                return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel) |
 
340
                                        TypeAttributes.Class | TypeAttributes.Sealed |
 
341
                                        base.TypeAttr;
 
342
                        }
 
343
                }
 
344
 
 
345
                public override string[] ValidAttributeTargets {
 
346
                        get {
 
347
                                return attribute_targets;
 
348
                        }
 
349
                }
 
350
 
 
351
                //TODO: duplicate
 
352
                protected override bool VerifyClsCompliance ()
 
353
                {
 
354
                        if (!base.VerifyClsCompliance ()) {
 
355
                                return false;
 
356
                        }
 
357
 
 
358
                        parameters.VerifyClsCompliance (this);
 
359
 
 
360
                        if (!InvokeBuilder.MemberType.IsCLSCompliant ()) {
 
361
                                Report.Warning (3002, 1, Location, "Return type of `{0}' is not CLS-compliant",
 
362
                                        GetSignatureForError ());
 
363
                        }
 
364
                        return true;
 
365
                }
 
366
 
 
367
 
 
368
                public static MethodSpec GetConstructor (TypeSpec delType)
 
369
                {
 
370
                        var ctor = MemberCache.FindMember (delType, MemberFilter.Constructor (null), BindingRestriction.DeclaredOnly);
 
371
                        return (MethodSpec) ctor;
 
372
                }
 
373
 
 
374
                //
 
375
                // Returns the "Invoke" from a delegate type
 
376
                //
 
377
                public static MethodSpec GetInvokeMethod (TypeSpec delType)
 
378
                {
 
379
                        var invoke = MemberCache.FindMember (delType,
 
380
                                MemberFilter.Method (InvokeMethodName, 0, null, null),
 
381
                                BindingRestriction.DeclaredOnly);
 
382
 
 
383
                        return (MethodSpec) invoke;
 
384
                }
 
385
 
 
386
                public static AParametersCollection GetParameters (TypeSpec delType)
 
387
                {
 
388
                        var invoke_mb = GetInvokeMethod (delType);
 
389
                        return invoke_mb.Parameters;
 
390
                }
 
391
 
 
392
                //
 
393
                // 15.2 Delegate compatibility
 
394
                //
 
395
                public static bool IsTypeCovariant (ResolveContext rc, TypeSpec a, TypeSpec b)
 
396
                {
 
397
                        //
 
398
                        // For each value parameter (a parameter with no ref or out modifier), an 
 
399
                        // identity conversion or implicit reference conversion exists from the
 
400
                        // parameter type in D to the corresponding parameter type in M
 
401
                        //
 
402
                        if (a == b)
 
403
                                return true;
 
404
 
 
405
                        if (rc.Module.Compiler.Settings.Version == LanguageVersion.ISO_1)
 
406
                                return false;
 
407
 
 
408
                        if (a.IsGenericParameter && b.IsGenericParameter)
 
409
                                return a == b;
 
410
 
 
411
                        return Convert.ImplicitReferenceConversionExists (a, b);
 
412
                }
 
413
 
 
414
                public static string FullDelegateDesc (MethodSpec invoke_method)
 
415
                {
 
416
                        return TypeManager.GetFullNameSignature (invoke_method).Replace (".Invoke", "");
 
417
                }
 
418
                
 
419
                public Expression InstanceExpression {
 
420
                        get {
 
421
                                return instance_expr;
 
422
                        }
 
423
                        set {
 
424
                                instance_expr = value;
 
425
                        }
 
426
                }
 
427
        }
 
428
 
 
429
        //
 
430
        // Base class for `NewDelegate' and `ImplicitDelegateCreation'
 
431
        //
 
432
        public abstract class DelegateCreation : Expression, OverloadResolver.IErrorHandler
 
433
        {
 
434
                protected MethodSpec constructor_method;
 
435
                protected MethodGroupExpr method_group;
 
436
 
 
437
                public static Arguments CreateDelegateMethodArguments (AParametersCollection pd, TypeSpec[] types, Location loc)
 
438
                {
 
439
                        Arguments delegate_arguments = new Arguments (pd.Count);
 
440
                        for (int i = 0; i < pd.Count; ++i) {
 
441
                                Argument.AType atype_modifier;
 
442
                                switch (pd.FixedParameters [i].ModFlags) {
 
443
                                case Parameter.Modifier.REF:
 
444
                                        atype_modifier = Argument.AType.Ref;
 
445
                                        break;
 
446
                                case Parameter.Modifier.OUT:
 
447
                                        atype_modifier = Argument.AType.Out;
 
448
                                        break;
 
449
                                default:
 
450
                                        atype_modifier = 0;
 
451
                                        break;
 
452
                                }
 
453
 
 
454
                                delegate_arguments.Add (new Argument (new TypeExpression (types [i], loc), atype_modifier));
 
455
                        }
 
456
 
 
457
                        return delegate_arguments;
 
458
                }
 
459
 
 
460
                public override Expression CreateExpressionTree (ResolveContext ec)
 
461
                {
 
462
                        MemberAccess ma = new MemberAccess (new MemberAccess (new QualifiedAliasMember ("global", "System", loc), "Delegate", loc), "CreateDelegate", loc);
 
463
 
 
464
                        Arguments args = new Arguments (3);
 
465
                        args.Add (new Argument (new TypeOf (type, loc)));
 
466
 
 
467
                        if (method_group.InstanceExpression == null)
 
468
                                args.Add (new Argument (new NullLiteral (loc)));
 
469
                        else
 
470
                                args.Add (new Argument (method_group.InstanceExpression));
 
471
 
 
472
                        args.Add (new Argument (method_group.CreateExpressionTree (ec)));
 
473
                        Expression e = new Invocation (ma, args).Resolve (ec);
 
474
                        if (e == null)
 
475
                                return null;
 
476
 
 
477
                        e = Convert.ExplicitConversion (ec, e, type, loc);
 
478
                        if (e == null)
 
479
                                return null;
 
480
 
 
481
                        return e.CreateExpressionTree (ec);
 
482
                }
 
483
 
 
484
                protected override Expression DoResolve (ResolveContext ec)
 
485
                {
 
486
                        constructor_method = Delegate.GetConstructor (type);
 
487
 
 
488
                        var invoke_method = Delegate.GetInvokeMethod (type);
 
489
 
 
490
                        Arguments arguments = CreateDelegateMethodArguments (invoke_method.Parameters, invoke_method.Parameters.Types, loc);
 
491
                        method_group = method_group.OverloadResolve (ec, ref arguments, this, OverloadResolver.Restrictions.CovariantDelegate);
 
492
                        if (method_group == null)
 
493
                                return null;
 
494
 
 
495
                        var delegate_method = method_group.BestCandidate;
 
496
                        
 
497
                        if (delegate_method.DeclaringType.IsNullableType) {
 
498
                                ec.Report.Error (1728, loc, "Cannot create delegate from method `{0}' because it is a member of System.Nullable<T> type",
 
499
                                        delegate_method.GetSignatureForError ());
 
500
                                return null;
 
501
                        }               
 
502
                        
 
503
                        Invocation.IsSpecialMethodInvocation (ec, delegate_method, loc);
 
504
 
 
505
                        ExtensionMethodGroupExpr emg = method_group as ExtensionMethodGroupExpr;
 
506
                        if (emg != null) {
 
507
                                method_group.InstanceExpression = emg.ExtensionExpression;
 
508
                                TypeSpec e_type = emg.ExtensionExpression.Type;
 
509
                                if (TypeSpec.IsValueType (e_type)) {
 
510
                                        ec.Report.Error (1113, loc, "Extension method `{0}' of value type `{1}' cannot be used to create delegates",
 
511
                                                delegate_method.GetSignatureForError (), TypeManager.CSharpName (e_type));
 
512
                                }
 
513
                        }
 
514
 
 
515
                        TypeSpec rt = delegate_method.ReturnType;
 
516
                        if (!Delegate.IsTypeCovariant (ec, rt, invoke_method.ReturnType)) {
 
517
                                Expression ret_expr = new TypeExpression (rt, loc);
 
518
                                Error_ConversionFailed (ec, delegate_method, ret_expr);
 
519
                        }
 
520
 
 
521
                        if (delegate_method.IsConditionallyExcluded (ec.Module.Compiler, loc)) {
 
522
                                ec.Report.SymbolRelatedToPreviousError (delegate_method);
 
523
                                MethodOrOperator m = delegate_method.MemberDefinition as MethodOrOperator;
 
524
                                if (m != null && m.IsPartialDefinition) {
 
525
                                        ec.Report.Error (762, loc, "Cannot create delegate from partial method declaration `{0}'",
 
526
                                                delegate_method.GetSignatureForError ());
 
527
                                } else {
 
528
                                        ec.Report.Error (1618, loc, "Cannot create delegate with `{0}' because it has a Conditional attribute",
 
529
                                                TypeManager.CSharpSignature (delegate_method));
 
530
                                }
 
531
                        }
 
532
 
 
533
                        var expr = method_group.InstanceExpression;
 
534
                        if (expr != null && (expr.Type.IsGenericParameter || !TypeSpec.IsReferenceType (expr.Type)))
 
535
                                method_group.InstanceExpression = new BoxedCast (expr, ec.BuiltinTypes.Object);
 
536
 
 
537
                        eclass = ExprClass.Value;
 
538
                        return this;
 
539
                }
 
540
                
 
541
                public override void Emit (EmitContext ec)
 
542
                {
 
543
                        if (method_group.InstanceExpression == null)
 
544
                                ec.Emit (OpCodes.Ldnull);
 
545
                        else
 
546
                                method_group.InstanceExpression.Emit (ec);
 
547
 
 
548
                        var delegate_method = method_group.BestCandidate;
 
549
 
 
550
                        // Any delegate must be sealed
 
551
                        if (!delegate_method.DeclaringType.IsDelegate && delegate_method.IsVirtual && !method_group.IsBase) {
 
552
                                ec.Emit (OpCodes.Dup);
 
553
                                ec.Emit (OpCodes.Ldvirtftn, delegate_method);
 
554
                        } else {
 
555
                                ec.Emit (OpCodes.Ldftn, delegate_method);
 
556
                        }
 
557
 
 
558
                        ec.Emit (OpCodes.Newobj, constructor_method);
 
559
                }
 
560
 
 
561
                void Error_ConversionFailed (ResolveContext ec, MethodSpec method, Expression return_type)
 
562
                {
 
563
                        var invoke_method = Delegate.GetInvokeMethod (type);
 
564
                        string member_name = method_group.InstanceExpression != null ?
 
565
                                Delegate.FullDelegateDesc (method) :
 
566
                                TypeManager.GetFullNameSignature (method);
 
567
 
 
568
                        ec.Report.SymbolRelatedToPreviousError (type);
 
569
                        ec.Report.SymbolRelatedToPreviousError (method);
 
570
                        if (ec.Module.Compiler.Settings.Version == LanguageVersion.ISO_1) {
 
571
                                ec.Report.Error (410, loc, "A method or delegate `{0} {1}' parameters and return type must be same as delegate `{2} {3}' parameters and return type",
 
572
                                        TypeManager.CSharpName (method.ReturnType), member_name,
 
573
                                        TypeManager.CSharpName (invoke_method.ReturnType), Delegate.FullDelegateDesc (invoke_method));
 
574
                                return;
 
575
                        }
 
576
 
 
577
                        if (return_type == null) {
 
578
                                ec.Report.Error (123, loc, "A method or delegate `{0}' parameters do not match delegate `{1}' parameters",
 
579
                                        member_name, Delegate.FullDelegateDesc (invoke_method));
 
580
                                return;
 
581
                        }
 
582
 
 
583
                        ec.Report.Error (407, loc, "A method or delegate `{0} {1}' return type does not match delegate `{2} {3}' return type",
 
584
                                return_type.GetSignatureForError (), member_name,
 
585
                                TypeManager.CSharpName (invoke_method.ReturnType), Delegate.FullDelegateDesc (invoke_method));
 
586
                }
 
587
 
 
588
                public static bool ImplicitStandardConversionExists (ResolveContext ec, MethodGroupExpr mg, TypeSpec target_type)
 
589
                {
 
590
//                      if (target_type == TypeManager.delegate_type || target_type == TypeManager.multicast_delegate_type)
 
591
//                              return false;
 
592
 
 
593
                        var invoke = Delegate.GetInvokeMethod (target_type);
 
594
 
 
595
                        Arguments arguments = CreateDelegateMethodArguments (invoke.Parameters, invoke.Parameters.Types, mg.Location);
 
596
                        return mg.OverloadResolve (ec, ref arguments, null, OverloadResolver.Restrictions.CovariantDelegate | OverloadResolver.Restrictions.ProbingOnly) != null;
 
597
                }
 
598
 
 
599
                #region IErrorHandler Members
 
600
 
 
601
                bool OverloadResolver.IErrorHandler.AmbiguousCandidates (ResolveContext ec, MemberSpec best, MemberSpec ambiguous)
 
602
                {
 
603
                        return false;
 
604
                }
 
605
 
 
606
                bool OverloadResolver.IErrorHandler.ArgumentMismatch (ResolveContext rc, MemberSpec best, Argument arg, int index)
 
607
                {
 
608
                        Error_ConversionFailed (rc, best as MethodSpec, null);
 
609
                        return true;
 
610
                }
 
611
 
 
612
                bool OverloadResolver.IErrorHandler.NoArgumentMatch (ResolveContext rc, MemberSpec best)
 
613
                {
 
614
                        Error_ConversionFailed (rc, best as MethodSpec, null);
 
615
                        return true;
 
616
                }
 
617
 
 
618
                bool OverloadResolver.IErrorHandler.TypeInferenceFailed (ResolveContext rc, MemberSpec best)
 
619
                {
 
620
                        return false;
 
621
                }
 
622
 
 
623
                #endregion
 
624
        }
 
625
 
 
626
        //
 
627
        // Created from the conversion code
 
628
        //
 
629
        public class ImplicitDelegateCreation : DelegateCreation
 
630
        {
 
631
                ImplicitDelegateCreation (TypeSpec t, MethodGroupExpr mg, Location l)
 
632
                {
 
633
                        type = t;
 
634
                        this.method_group = mg;
 
635
                        loc = l;
 
636
                }
 
637
 
 
638
                static public Expression Create (ResolveContext ec, MethodGroupExpr mge,
 
639
                                                 TypeSpec target_type, Location loc)
 
640
                {
 
641
                        ImplicitDelegateCreation d = new ImplicitDelegateCreation (target_type, mge, loc);
 
642
                        return d.DoResolve (ec);
 
643
                }
 
644
        }
 
645
        
 
646
        //
 
647
        // A delegate-creation-expression, invoked from the `New' class 
 
648
        //
 
649
        public class NewDelegate : DelegateCreation
 
650
        {
 
651
                public Arguments Arguments;
 
652
 
 
653
                //
 
654
                // This constructor is invoked from the `New' expression
 
655
                //
 
656
                public NewDelegate (TypeSpec type, Arguments Arguments, Location loc)
 
657
                {
 
658
                        this.type = type;
 
659
                        this.Arguments = Arguments;
 
660
                        this.loc  = loc; 
 
661
                }
 
662
 
 
663
                protected override Expression DoResolve (ResolveContext ec)
 
664
                {
 
665
                        if (Arguments == null || Arguments.Count != 1) {
 
666
                                ec.Report.Error (149, loc, "Method name expected");
 
667
                                return null;
 
668
                        }
 
669
 
 
670
                        Argument a = Arguments [0];
 
671
                        if (!a.ResolveMethodGroup (ec))
 
672
                                return null;
 
673
 
 
674
                        Expression e = a.Expr;
 
675
 
 
676
                        AnonymousMethodExpression ame = e as AnonymousMethodExpression;
 
677
                        if (ame != null && ec.Module.Compiler.Settings.Version != LanguageVersion.ISO_1) {
 
678
                                e = ame.Compatible (ec, type);
 
679
                                if (e == null)
 
680
                                        return null;
 
681
 
 
682
                                return e.Resolve (ec);
 
683
                        }
 
684
 
 
685
                        method_group = e as MethodGroupExpr;
 
686
                        if (method_group == null) {
 
687
                                if (e.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
 
688
                                        e = Convert.ImplicitConversionRequired (ec, e, type, loc);
 
689
                                } else if (!e.Type.IsDelegate) {
 
690
                                        e.Error_UnexpectedKind (ec, ResolveFlags.MethodGroup | ResolveFlags.Type, loc);
 
691
                                        return null;
 
692
                                }
 
693
 
 
694
                                //
 
695
                                // An argument is not a method but another delegate
 
696
                                //
 
697
                                method_group = new MethodGroupExpr (Delegate.GetInvokeMethod (e.Type), e.Type, loc);
 
698
                                method_group.InstanceExpression = e;
 
699
                        }
 
700
 
 
701
                        return base.DoResolve (ec);
 
702
                }
 
703
        }
 
704
 
 
705
        //
 
706
        // Invocation converted to delegate Invoke call
 
707
        //
 
708
        class DelegateInvocation : ExpressionStatement
 
709
        {
 
710
                readonly Expression InstanceExpr;
 
711
                Arguments arguments;
 
712
                MethodSpec method;
 
713
                
 
714
                public DelegateInvocation (Expression instance_expr, Arguments args, Location loc)
 
715
                {
 
716
                        this.InstanceExpr = instance_expr;
 
717
                        this.arguments = args;
 
718
                        this.loc = loc;
 
719
                }
 
720
                
 
721
                public override Expression CreateExpressionTree (ResolveContext ec)
 
722
                {
 
723
                        Arguments args = Arguments.CreateForExpressionTree (ec, this.arguments,
 
724
                                InstanceExpr.CreateExpressionTree (ec));
 
725
 
 
726
                        return CreateExpressionFactoryCall (ec, "Invoke", args);
 
727
                }
 
728
 
 
729
                protected override Expression DoResolve (ResolveContext ec)
 
730
                {               
 
731
                        TypeSpec del_type = InstanceExpr.Type;
 
732
                        if (del_type == null)
 
733
                                return null;
 
734
 
 
735
                        //
 
736
                        // Do only core overload resolution the rest of the checks has been
 
737
                        // done on primary expression
 
738
                        //
 
739
                        method = Delegate.GetInvokeMethod (del_type);
 
740
                        var res = new OverloadResolver (new MemberSpec[] { method }, OverloadResolver.Restrictions.DelegateInvoke, loc);
 
741
                        var valid = res.ResolveMember<MethodSpec> (ec, ref arguments);
 
742
                        if (valid == null && !res.BestCandidateIsDynamic)
 
743
                                return null;
 
744
 
 
745
                        type = method.ReturnType;
 
746
                        eclass = ExprClass.Value;
 
747
                        return this;
 
748
                }
 
749
 
 
750
                public override void Emit (EmitContext ec)
 
751
                {
 
752
                        //
 
753
                        // Invocation on delegates call the virtual Invoke member
 
754
                        // so we are always `instance' calls
 
755
                        //
 
756
                        Invocation.EmitCall (ec, InstanceExpr, method, arguments, loc);
 
757
                }
 
758
 
 
759
                public override void EmitStatement (EmitContext ec)
 
760
                {
 
761
                        Emit (ec);
 
762
                        // 
 
763
                        // Pop the return value if there is one
 
764
                        //
 
765
                        if (type.Kind != MemberKind.Void)
 
766
                                ec.Emit (OpCodes.Pop);
 
767
                }
 
768
 
 
769
                public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx)
 
770
                {
 
771
                        return Invocation.MakeExpression (ctx, InstanceExpr, method, arguments);
 
772
                }
 
773
        }
 
774
}