~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/nrefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/parameter.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// parameter.cs: Parameter definition.
 
3
//
 
4
// Author: Miguel de Icaza (miguel@gnu.org)
 
5
//         Marek Safar (marek.safar@seznam.cz)
 
6
//
 
7
// Dual licensed under the terms of the MIT X11 or GNU GPL
 
8
//
 
9
// Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
 
10
// Copyright 2003-2008 Novell, Inc. 
 
11
// Copyright 2011 Xamarin Inc
 
12
//
 
13
//
 
14
using System;
 
15
using System.Text;
 
16
 
 
17
#if STATIC
 
18
using MetaType = IKVM.Reflection.Type;
 
19
using IKVM.Reflection;
 
20
using IKVM.Reflection.Emit;
 
21
#else
 
22
using MetaType = System.Type;
 
23
using System.Reflection;
 
24
using System.Reflection.Emit;
 
25
#endif
 
26
 
 
27
namespace Mono.CSharp {
 
28
 
 
29
        /// <summary>
 
30
        ///   Abstract Base class for parameters of a method.
 
31
        /// </summary>
 
32
        public abstract class ParameterBase : Attributable
 
33
        {
 
34
                protected ParameterBuilder builder;
 
35
 
 
36
                public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
 
37
                {
 
38
#if false
 
39
                        if (a.Type == pa.MarshalAs) {
 
40
                                UnmanagedMarshal marshal = a.GetMarshal (this);
 
41
                                if (marshal != null) {
 
42
                                        builder.SetMarshal (marshal);
 
43
                                }
 
44
                                return;
 
45
                        }
 
46
#endif
 
47
                        if (a.HasSecurityAttribute) {
 
48
                                a.Error_InvalidSecurityParent ();
 
49
                                return;
 
50
                        }
 
51
 
 
52
                        if (a.Type == pa.Dynamic) {
 
53
                                a.Error_MisusedDynamicAttribute ();
 
54
                                return;
 
55
                        }
 
56
 
 
57
                        builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
 
58
                }
 
59
 
 
60
                public ParameterBuilder Builder {
 
61
                        get {
 
62
                                return builder;
 
63
                        }
 
64
                }
 
65
 
 
66
                public override bool IsClsComplianceRequired()
 
67
                {
 
68
                        return false;
 
69
                }
 
70
        }
 
71
 
 
72
        /// <summary>
 
73
        /// Class for applying custom attributes on the return type
 
74
        /// </summary>
 
75
        public class ReturnParameter : ParameterBase
 
76
        {
 
77
                MemberCore method;
 
78
 
 
79
                // TODO: merge method and mb
 
80
                public ReturnParameter (MemberCore method, MethodBuilder mb, Location location)
 
81
                {
 
82
                        this.method = method;
 
83
                        try {
 
84
                                builder = mb.DefineParameter (0, ParameterAttributes.None, "");                 
 
85
                        }
 
86
                        catch (ArgumentOutOfRangeException) {
 
87
                                method.Compiler.Report.RuntimeMissingSupport (location, "custom attributes on the return type");
 
88
                        }
 
89
                }
 
90
 
 
91
                public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
 
92
                {
 
93
                        if (a.Type == pa.CLSCompliant) {
 
94
                                method.Compiler.Report.Warning (3023, 1, a.Location,
 
95
                                        "CLSCompliant attribute has no meaning when applied to return types. Try putting it on the method instead");
 
96
                        }
 
97
 
 
98
                        // This occurs after Warning -28
 
99
                        if (builder == null)
 
100
                                return;
 
101
 
 
102
                        base.ApplyAttributeBuilder (a, ctor, cdata, pa);
 
103
                }
 
104
 
 
105
                public override AttributeTargets AttributeTargets {
 
106
                        get {
 
107
                                return AttributeTargets.ReturnValue;
 
108
                        }
 
109
                }
 
110
 
 
111
                /// <summary>
 
112
                /// Is never called
 
113
                /// </summary>
 
114
                public override string[] ValidAttributeTargets {
 
115
                        get {
 
116
                                return null;
 
117
                        }
 
118
                }
 
119
        }
 
120
 
 
121
        public class ImplicitLambdaParameter : Parameter
 
122
        {
 
123
                public ImplicitLambdaParameter (string name, Location loc)
 
124
                        : base (null, name, Modifier.NONE, null, loc)
 
125
                {
 
126
                }
 
127
 
 
128
                public override TypeSpec Resolve (IMemberContext ec, int index)
 
129
                {
 
130
                        if (parameter_type == null)
 
131
                                throw new InternalErrorException ("A type of implicit lambda parameter `{0}' is not set",
 
132
                                        Name);
 
133
 
 
134
                        base.idx = index;
 
135
                        return parameter_type;
 
136
                }
 
137
 
 
138
                public void SetParameterType (TypeSpec type)
 
139
                {
 
140
                        parameter_type = type;
 
141
                }
 
142
        }
 
143
 
 
144
        public class ParamsParameter : Parameter {
 
145
                public ParamsParameter (FullNamedExpression type, string name, Attributes attrs, Location loc):
 
146
                        base (type, name, Parameter.Modifier.PARAMS, attrs, loc)
 
147
                {
 
148
                }
 
149
 
 
150
                public override TypeSpec Resolve (IMemberContext ec, int index)
 
151
                {
 
152
                        if (base.Resolve (ec, index) == null)
 
153
                                return null;
 
154
 
 
155
                        var ac = parameter_type as ArrayContainer;
 
156
                        if (ac == null || ac.Rank != 1) {
 
157
                                ec.Module.Compiler.Report.Error (225, Location, "The params parameter must be a single dimensional array");
 
158
                                return null;
 
159
                        }
 
160
 
 
161
                        return parameter_type;
 
162
                }
 
163
 
 
164
                public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index, PredefinedAttributes pa)
 
165
                {
 
166
                        base.ApplyAttributes (mb, cb, index, pa);
 
167
                        pa.ParamArray.EmitAttribute (builder);
 
168
                }
 
169
        }
 
170
 
 
171
        public class ArglistParameter : Parameter {
 
172
                // Doesn't have proper type because it's never chosen for better conversion
 
173
                public ArglistParameter (Location loc) :
 
174
                        base (null, String.Empty, Parameter.Modifier.NONE, null, loc)
 
175
                {
 
176
                        parameter_type = InternalType.Arglist;
 
177
                }
 
178
 
 
179
                public override void  ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index, PredefinedAttributes pa)
 
180
                {
 
181
                        // Nothing to do
 
182
                }
 
183
 
 
184
                public override bool CheckAccessibility (InterfaceMemberBase member)
 
185
                {
 
186
                        return true;
 
187
                }
 
188
 
 
189
                public override TypeSpec Resolve (IMemberContext ec, int index)
 
190
                {
 
191
                        return parameter_type;
 
192
                }
 
193
        }
 
194
 
 
195
        public interface IParameterData
 
196
        {
 
197
                Expression DefaultValue { get; }
 
198
                bool HasExtensionMethodModifier { get; }
 
199
                bool HasDefaultValue { get; }
 
200
                Parameter.Modifier ModFlags { get; }
 
201
                string Name { get; }
 
202
        }
 
203
 
 
204
        //
 
205
        // Parameter information created by parser
 
206
        //
 
207
        public class Parameter : ParameterBase, IParameterData, ILocalVariable // TODO: INamedBlockVariable
 
208
        {
 
209
                [Flags]
 
210
                public enum Modifier : byte {
 
211
                        NONE    = 0,
 
212
                        PARAMS  = 1 << 0,
 
213
                        REF = 1 << 1,
 
214
                        OUT = 1 << 2,
 
215
                        This = 1 << 3,
 
216
                        CallerMemberName = 1 << 4,
 
217
                        CallerLineNumber = 1 << 5,
 
218
                        CallerFilePath = 1 << 6,
 
219
 
 
220
                        RefOutMask = REF | OUT,
 
221
                        ModifierMask = PARAMS | REF | OUT | This,
 
222
                        CallerMask = CallerMemberName | CallerLineNumber | CallerFilePath
 
223
                }
 
224
 
 
225
                static readonly string[] attribute_targets = new string[] { "param" };
 
226
 
 
227
                FullNamedExpression texpr;
 
228
                Modifier modFlags;
 
229
                string name;
 
230
                Expression default_expr;
 
231
                protected TypeSpec parameter_type;
 
232
                readonly Location loc;
 
233
                protected int idx;
 
234
                public bool HasAddressTaken;
 
235
 
 
236
                TemporaryVariableReference expr_tree_variable;
 
237
 
 
238
                HoistedParameter hoisted_variant;
 
239
 
 
240
                public Parameter (FullNamedExpression type, string name, Modifier mod, Attributes attrs, Location loc)
 
241
                {
 
242
                        this.name = name;
 
243
                        modFlags = mod;
 
244
                        this.loc = loc;
 
245
                        texpr = type;
 
246
 
 
247
                        // Only assign, attributes will be attached during resolve
 
248
                        base.attributes = attrs;
 
249
                }
 
250
 
 
251
                #region Properties
 
252
 
 
253
                public Expression DefaultExpression {
 
254
                        get {
 
255
                                return default_expr;
 
256
                        }
 
257
                }
 
258
 
 
259
                public DefaultParameterValueExpression DefaultValue {
 
260
                        get {
 
261
                                return default_expr as DefaultParameterValueExpression;
 
262
                        }
 
263
                        set {
 
264
                                default_expr = value;
 
265
                        }
 
266
                }
 
267
 
 
268
                Expression IParameterData.DefaultValue {
 
269
                        get {
 
270
                                var expr = default_expr as DefaultParameterValueExpression;
 
271
                                return expr == null ? default_expr : expr.Child;
 
272
                        }
 
273
                }
 
274
 
 
275
                bool HasOptionalExpression {
 
276
                        get {
 
277
                                return default_expr is DefaultParameterValueExpression;
 
278
                        }
 
279
                }
 
280
 
 
281
                public Location Location {
 
282
                        get {
 
283
                                return loc;
 
284
                        }
 
285
                }
 
286
 
 
287
                public Modifier ParameterModifier {
 
288
                        get {
 
289
                                return modFlags;
 
290
                        }
 
291
                }
 
292
 
 
293
                public TypeSpec Type {
 
294
                        get {
 
295
                                return parameter_type;
 
296
                        }
 
297
                        set {
 
298
                                parameter_type = value;
 
299
                        }
 
300
                }
 
301
 
 
302
                public FullNamedExpression TypeExpression  {
 
303
                        get {
 
304
                                return texpr;
 
305
                        }
 
306
                }
 
307
 
 
308
                public override string[] ValidAttributeTargets {
 
309
                        get {
 
310
                                return attribute_targets;
 
311
                        }
 
312
                }
 
313
 
 
314
                #endregion
 
315
 
 
316
                public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
 
317
                {
 
318
                        if (a.Type == pa.In && ModFlags == Modifier.OUT) {
 
319
                                a.Report.Error (36, a.Location, "An out parameter cannot have the `In' attribute");
 
320
                                return;
 
321
                        }
 
322
 
 
323
                        if (a.Type == pa.ParamArray) {
 
324
                                a.Report.Error (674, a.Location, "Do not use `System.ParamArrayAttribute'. Use the `params' keyword instead");
 
325
                                return;
 
326
                        }
 
327
 
 
328
                        if (a.Type == pa.Out && (ModFlags & Modifier.REF) != 0 &&
 
329
                            !OptAttributes.Contains (pa.In)) {
 
330
                                a.Report.Error (662, a.Location,
 
331
                                        "Cannot specify only `Out' attribute on a ref parameter. Use both `In' and `Out' attributes or neither");
 
332
                                return;
 
333
                        }
 
334
 
 
335
                        if (a.Type == pa.CLSCompliant) {
 
336
                                a.Report.Warning (3022, 1, a.Location, "CLSCompliant attribute has no meaning when applied to parameters. Try putting it on the method instead");
 
337
                        } else if (a.Type == pa.DefaultParameterValue || a.Type == pa.OptionalParameter) {
 
338
                                if (HasOptionalExpression) {
 
339
                                        a.Report.Error (1745, a.Location,
 
340
                                                "Cannot specify `{0}' attribute on optional parameter `{1}'",
 
341
                                                TypeManager.CSharpName (a.Type).Replace ("Attribute", ""), Name);
 
342
                                }
 
343
 
 
344
                                if (a.Type == pa.DefaultParameterValue)
 
345
                                        return;
 
346
                        } else if (a.Type == pa.CallerMemberNameAttribute) {
 
347
                                if ((modFlags & Modifier.CallerMemberName) == 0) {
 
348
                                        a.Report.Error (4022, a.Location,
 
349
                                                "The CallerMemberName attribute can only be applied to parameters with default value");
 
350
                                }
 
351
                        } else if (a.Type == pa.CallerLineNumberAttribute) {
 
352
                                if ((modFlags & Modifier.CallerLineNumber) == 0) {
 
353
                                        a.Report.Error (4020, a.Location,
 
354
                                                "The CallerLineNumber attribute can only be applied to parameters with default value");
 
355
                                }
 
356
                        } else if (a.Type == pa.CallerFilePathAttribute) {
 
357
                                if ((modFlags & Modifier.CallerFilePath) == 0) {
 
358
                                        a.Report.Error (4021, a.Location,
 
359
                                                "The CallerFilePath attribute can only be applied to parameters with default value");
 
360
                                }
 
361
                        }
 
362
 
 
363
                        base.ApplyAttributeBuilder (a, ctor, cdata, pa);
 
364
                }
 
365
                
 
366
                public virtual bool CheckAccessibility (InterfaceMemberBase member)
 
367
                {
 
368
                        if (parameter_type == null)
 
369
                                return true;
 
370
 
 
371
                        return member.IsAccessibleAs (parameter_type);
 
372
                }
 
373
 
 
374
                // <summary>
 
375
                //   Resolve is used in method definitions
 
376
                // </summary>
 
377
                public virtual TypeSpec Resolve (IMemberContext rc, int index)
 
378
                {
 
379
                        if (parameter_type != null)
 
380
                                return parameter_type;
 
381
 
 
382
                        if (attributes != null)
 
383
                                attributes.AttachTo (this, rc);
 
384
 
 
385
                        parameter_type = texpr.ResolveAsType (rc);
 
386
                        if (parameter_type == null)
 
387
                                return null;
 
388
 
 
389
                        this.idx = index;
 
390
 
 
391
                        if ((modFlags & Parameter.Modifier.RefOutMask) != 0 && parameter_type.IsSpecialRuntimeType) {
 
392
                                rc.Module.Compiler.Report.Error (1601, Location, "Method or delegate parameter cannot be of type `{0}'",
 
393
                                        GetSignatureForError ());
 
394
                                return null;
 
395
                        }
 
396
 
 
397
                        TypeManager.CheckTypeVariance (parameter_type,
 
398
                                (modFlags & Parameter.Modifier.RefOutMask) != 0 ? Variance.None : Variance.Contravariant,
 
399
                                rc);
 
400
 
 
401
                        if (parameter_type.IsStatic) {
 
402
                                rc.Module.Compiler.Report.Error (721, Location, "`{0}': static types cannot be used as parameters",
 
403
                                        texpr.GetSignatureForError ());
 
404
                                return parameter_type;
 
405
                        }
 
406
 
 
407
                        if ((modFlags & Modifier.This) != 0 && (parameter_type.IsPointer || parameter_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic)) {
 
408
                                rc.Module.Compiler.Report.Error (1103, Location, "The extension method cannot be of type `{0}'",
 
409
                                        TypeManager.CSharpName (parameter_type));
 
410
                        }
 
411
 
 
412
                        return parameter_type;
 
413
                }
 
414
 
 
415
                void ResolveCallerAttributes (ResolveContext rc)
 
416
                {
 
417
                        var pa = rc.Module.PredefinedAttributes;
 
418
                        TypeSpec caller_type;
 
419
 
 
420
                        foreach (var attr in attributes.Attrs) {
 
421
                                var atype = attr.ResolveTypeForComparison ();
 
422
                                if (atype == null)
 
423
                                        continue;
 
424
 
 
425
                                if (atype == pa.CallerMemberNameAttribute) {
 
426
                                        caller_type = rc.BuiltinTypes.String;
 
427
                                        if (caller_type != parameter_type && !Convert.ImplicitReferenceConversionExists (caller_type, parameter_type)) {
 
428
                                                rc.Report.Error (4019, attr.Location,
 
429
                                                        "The CallerMemberName attribute cannot be applied because there is no standard conversion from `{0}' to `{1}'",
 
430
                                                        caller_type.GetSignatureForError (), parameter_type.GetSignatureForError ());
 
431
                                        }
 
432
 
 
433
                                        modFlags |= Modifier.CallerMemberName;
 
434
                                        continue;
 
435
                                }
 
436
 
 
437
                                if (atype == pa.CallerLineNumberAttribute) {
 
438
                                        caller_type = rc.BuiltinTypes.Int;
 
439
                                        if (caller_type != parameter_type && !Convert.ImplicitNumericConversionExists (caller_type, parameter_type)) {
 
440
                                                rc.Report.Error (4017, attr.Location,
 
441
                                                        "The CallerMemberName attribute cannot be applied because there is no standard conversion from `{0}' to `{1}'",
 
442
                                                        caller_type.GetSignatureForError (), parameter_type.GetSignatureForError ());
 
443
                                        }
 
444
 
 
445
                                        modFlags |= Modifier.CallerLineNumber;
 
446
                                        continue;
 
447
                                }
 
448
 
 
449
                                if (atype == pa.CallerFilePathAttribute) {
 
450
                                        caller_type = rc.BuiltinTypes.String;
 
451
                                        if (caller_type != parameter_type && !Convert.ImplicitReferenceConversionExists (caller_type, parameter_type)) {
 
452
                                                rc.Report.Error (4018, attr.Location,
 
453
                                                        "The CallerFilePath attribute cannot be applied because there is no standard conversion from `{0}' to `{1}'",
 
454
                                                        caller_type.GetSignatureForError (), parameter_type.GetSignatureForError ());
 
455
                                        }
 
456
 
 
457
                                        modFlags |= Modifier.CallerFilePath;
 
458
                                        continue;
 
459
                                }
 
460
                        }
 
461
                }
 
462
 
 
463
                public void ResolveDefaultValue (ResolveContext rc)
 
464
                {
 
465
                        //
 
466
                        // Default value was specified using an expression
 
467
                        //
 
468
                        if (default_expr != null) {
 
469
                                ((DefaultParameterValueExpression)default_expr).Resolve (rc, this);
 
470
                                if (attributes != null)
 
471
                                        ResolveCallerAttributes (rc);
 
472
 
 
473
                                return;
 
474
                        }
 
475
 
 
476
                        if (attributes == null)
 
477
                                return;
 
478
 
 
479
                        var pa = rc.Module.PredefinedAttributes;
 
480
                        var def_attr = attributes.Search (pa.DefaultParameterValue);
 
481
                        if (def_attr != null) {
 
482
                                if (def_attr.Resolve () == null)
 
483
                                        return;
 
484
 
 
485
                                var default_expr_attr = def_attr.GetParameterDefaultValue ();
 
486
                                if (default_expr_attr == null)
 
487
                                        return;
 
488
 
 
489
                                var dpa_rc = def_attr.CreateResolveContext ();
 
490
                                default_expr = default_expr_attr.Resolve (dpa_rc);
 
491
 
 
492
                                if (default_expr is BoxedCast)
 
493
                                        default_expr = ((BoxedCast) default_expr).Child;
 
494
 
 
495
                                Constant c = default_expr as Constant;
 
496
                                if (c == null) {
 
497
                                        if (parameter_type.BuiltinType == BuiltinTypeSpec.Type.Object) {
 
498
                                                rc.Report.Error (1910, default_expr.Location,
 
499
                                                        "Argument of type `{0}' is not applicable for the DefaultParameterValue attribute",
 
500
                                                        default_expr.Type.GetSignatureForError ());
 
501
                                        } else {
 
502
                                                rc.Report.Error (1909, default_expr.Location,
 
503
                                                        "The DefaultParameterValue attribute is not applicable on parameters of type `{0}'",
 
504
                                                        default_expr.Type.GetSignatureForError ()); ;
 
505
                                        }
 
506
 
 
507
                                        default_expr = null;
 
508
                                        return;
 
509
                                }
 
510
 
 
511
                                if (TypeSpecComparer.IsEqual (default_expr.Type, parameter_type) ||
 
512
                                        (default_expr is NullConstant && TypeSpec.IsReferenceType (parameter_type) && !parameter_type.IsGenericParameter) ||
 
513
                                        parameter_type.BuiltinType == BuiltinTypeSpec.Type.Object) {
 
514
                                        return;
 
515
                                }
 
516
 
 
517
                                //
 
518
                                // LAMESPEC: Some really weird csc behaviour which we have to mimic
 
519
                                // User operators returning same type as parameter type are considered
 
520
                                // valid for this attribute only
 
521
                                //
 
522
                                // struct S { public static implicit operator S (int i) {} }
 
523
                                //
 
524
                                // void M ([DefaultParameterValue (3)]S s)
 
525
                                //
 
526
                                var expr = Convert.ImplicitUserConversion (dpa_rc, default_expr, parameter_type, loc);
 
527
                                if (expr != null && TypeSpecComparer.IsEqual (expr.Type, parameter_type)) {
 
528
                                        return;
 
529
                                }
 
530
                                
 
531
                                rc.Report.Error (1908, default_expr.Location, "The type of the default value should match the type of the parameter");
 
532
                                return;
 
533
                        }
 
534
 
 
535
                        var opt_attr = attributes.Search (pa.OptionalParameter);
 
536
                        if (opt_attr != null) {
 
537
                                default_expr = EmptyExpression.MissingValue;
 
538
                        }
 
539
                }
 
540
 
 
541
                public bool HasDefaultValue {
 
542
                        get { return default_expr != null; }
 
543
                }
 
544
 
 
545
                public bool HasExtensionMethodModifier {
 
546
                        get { return (modFlags & Modifier.This) != 0; }
 
547
                }
 
548
 
 
549
                //
 
550
                // Hoisted parameter variant
 
551
                //
 
552
                public HoistedParameter HoistedVariant {
 
553
                        get {
 
554
                                return hoisted_variant;
 
555
                        }
 
556
                        set {
 
557
                                hoisted_variant = value;
 
558
                        }
 
559
                }
 
560
 
 
561
                public Modifier ModFlags {
 
562
                        get { return modFlags & ~Modifier.This; }
 
563
                }
 
564
 
 
565
                public string Name {
 
566
                        get { return name; }
 
567
                        set { name = value; }
 
568
                }
 
569
 
 
570
                public override AttributeTargets AttributeTargets {
 
571
                        get {
 
572
                                return AttributeTargets.Parameter;
 
573
                        }
 
574
                }
 
575
 
 
576
                public void Error_DuplicateName (Report r)
 
577
                {
 
578
                        r.Error (100, Location, "The parameter name `{0}' is a duplicate", Name);
 
579
                }
 
580
 
 
581
                public virtual string GetSignatureForError ()
 
582
                {
 
583
                        string type_name;
 
584
                        if (parameter_type != null)
 
585
                                type_name = TypeManager.CSharpName (parameter_type);
 
586
                        else
 
587
                                type_name = texpr.GetSignatureForError ();
 
588
 
 
589
                        string mod = GetModifierSignature (modFlags);
 
590
                        if (mod.Length > 0)
 
591
                                return String.Concat (mod, " ", type_name);
 
592
 
 
593
                        return type_name;
 
594
                }
 
595
 
 
596
                public static string GetModifierSignature (Modifier mod)
 
597
                {
 
598
                        switch (mod) {
 
599
                        case Modifier.OUT:
 
600
                                return "out";
 
601
                        case Modifier.PARAMS:
 
602
                                return "params";
 
603
                        case Modifier.REF:
 
604
                                return "ref";
 
605
                        case Modifier.This:
 
606
                                return "this";
 
607
                        default:
 
608
                                return "";
 
609
                        }
 
610
                }
 
611
 
 
612
                public void IsClsCompliant (IMemberContext ctx)
 
613
                {
 
614
                        if (parameter_type.IsCLSCompliant ())
 
615
                                return;
 
616
 
 
617
                        ctx.Module.Compiler.Report.Warning (3001, 1, Location,
 
618
                                "Argument type `{0}' is not CLS-compliant", parameter_type.GetSignatureForError ());
 
619
                }
 
620
 
 
621
                public virtual void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index, PredefinedAttributes pa)
 
622
                {
 
623
                        if (builder != null)
 
624
                                throw new InternalErrorException ("builder already exists");
 
625
 
 
626
                        var pattrs = ParametersCompiled.GetParameterAttribute (modFlags);
 
627
                        if (HasOptionalExpression)
 
628
                                pattrs |= ParameterAttributes.Optional;
 
629
 
 
630
                        if (mb == null)
 
631
                                builder = cb.DefineParameter (index, pattrs, Name);
 
632
                        else
 
633
                                builder = mb.DefineParameter (index, pattrs, Name);
 
634
 
 
635
                        if (OptAttributes != null)
 
636
                                OptAttributes.Emit ();
 
637
 
 
638
                        if (HasDefaultValue) {
 
639
                                //
 
640
                                // Emit constant values for true constants only, the other
 
641
                                // constant-like expressions will rely on default value expression
 
642
                                //
 
643
                                var def_value = DefaultValue;
 
644
                                Constant c = def_value != null ? def_value.Child as Constant : default_expr as Constant;
 
645
                                if (c != null) {
 
646
                                        if (c.Type.BuiltinType == BuiltinTypeSpec.Type.Decimal) {
 
647
                                                pa.DecimalConstant.EmitAttribute (builder, (decimal) c.GetValue (), c.Location);
 
648
                                        } else {
 
649
                                                builder.SetConstant (c.GetValue ());
 
650
                                        }
 
651
                                } else if (default_expr.Type.IsStruct) {
 
652
                                        //
 
653
                                        // Handles special case where default expression is used with value-type
 
654
                                        //
 
655
                                        // void Foo (S s = default (S)) {}
 
656
                                        //
 
657
                                        builder.SetConstant (null);
 
658
                                }
 
659
                        }
 
660
 
 
661
                        if (parameter_type != null) {
 
662
                                if (parameter_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
 
663
                                        pa.Dynamic.EmitAttribute (builder);
 
664
                                } else if (parameter_type.HasDynamicElement) {
 
665
                                        pa.Dynamic.EmitAttribute (builder, parameter_type, Location);
 
666
                                }
 
667
                        }
 
668
                }
 
669
 
 
670
                public Parameter Clone ()
 
671
                {
 
672
                        Parameter p = (Parameter) MemberwiseClone ();
 
673
                        if (attributes != null)
 
674
                                p.attributes = attributes.Clone ();
 
675
 
 
676
                        return p;
 
677
                }
 
678
 
 
679
                public ExpressionStatement CreateExpressionTreeVariable (BlockContext ec)
 
680
                {
 
681
                        if ((modFlags & Modifier.RefOutMask) != 0)
 
682
                                ec.Report.Error (1951, Location, "An expression tree parameter cannot use `ref' or `out' modifier");
 
683
 
 
684
                        expr_tree_variable = TemporaryVariableReference.Create (ResolveParameterExpressionType (ec, Location).Type, ec.CurrentBlock.ParametersBlock, Location);
 
685
                        expr_tree_variable = (TemporaryVariableReference) expr_tree_variable.Resolve (ec);
 
686
 
 
687
                        Arguments arguments = new Arguments (2);
 
688
                        arguments.Add (new Argument (new TypeOf (parameter_type, Location)));
 
689
                        arguments.Add (new Argument (new StringConstant (ec.BuiltinTypes, Name, Location)));
 
690
                        return new SimpleAssign (ExpressionTreeVariableReference (),
 
691
                                Expression.CreateExpressionFactoryCall (ec, "Parameter", null, arguments, Location));
 
692
                }
 
693
 
 
694
                public void Emit (EmitContext ec)
 
695
                {
 
696
                        ec.EmitArgumentLoad (idx);
 
697
                }
 
698
 
 
699
                public void EmitAssign (EmitContext ec)
 
700
                {
 
701
                        ec.EmitArgumentStore (idx);
 
702
                }
 
703
 
 
704
                public void EmitAddressOf (EmitContext ec)
 
705
                {
 
706
                        if ((ModFlags & Modifier.RefOutMask) != 0) {
 
707
                                ec.EmitArgumentLoad (idx);
 
708
                        } else {
 
709
                                ec.EmitArgumentAddress (idx);
 
710
                        }
 
711
                }
 
712
 
 
713
                public TemporaryVariableReference ExpressionTreeVariableReference ()
 
714
                {
 
715
                        return expr_tree_variable;
 
716
                }
 
717
 
 
718
                //
 
719
                // System.Linq.Expressions.ParameterExpression type
 
720
                //
 
721
                public static TypeExpr ResolveParameterExpressionType (IMemberContext ec, Location location)
 
722
                {
 
723
                        TypeSpec p_type = ec.Module.PredefinedTypes.ParameterExpression.Resolve ();
 
724
                        return new TypeExpression (p_type, location);
 
725
                }
 
726
 
 
727
                public void Warning_UselessOptionalParameter (Report Report)
 
728
                {
 
729
                        Report.Warning (1066, 1, Location,
 
730
                                "The default value specified for optional parameter `{0}' will never be used",
 
731
                                Name);
 
732
                }
 
733
        }
 
734
 
 
735
        //
 
736
        // Imported or resolved parameter information
 
737
        //
 
738
        public class ParameterData : IParameterData
 
739
        {
 
740
                readonly string name;
 
741
                readonly Parameter.Modifier modifiers;
 
742
                readonly Expression default_value;
 
743
 
 
744
                public ParameterData (string name, Parameter.Modifier modifiers)
 
745
                {
 
746
                        this.name = name;
 
747
                        this.modifiers = modifiers;
 
748
                }
 
749
 
 
750
                public ParameterData (string name, Parameter.Modifier modifiers, Expression defaultValue)
 
751
                        : this (name, modifiers)
 
752
                {
 
753
                        this.default_value = defaultValue;
 
754
                }
 
755
 
 
756
                #region IParameterData Members
 
757
 
 
758
                public Expression DefaultValue {
 
759
                        get { return default_value; }
 
760
                }
 
761
 
 
762
                public bool HasExtensionMethodModifier {
 
763
                        get { return (modifiers & Parameter.Modifier.This) != 0; }
 
764
                }
 
765
 
 
766
                public bool HasDefaultValue {
 
767
                        get { return default_value != null; }
 
768
                }
 
769
 
 
770
                public Parameter.Modifier ModFlags {
 
771
                        get { return modifiers; }
 
772
                }
 
773
 
 
774
                public string Name {
 
775
                        get { return name; }
 
776
                }
 
777
 
 
778
                #endregion
 
779
        }
 
780
 
 
781
        public abstract class AParametersCollection
 
782
        {
 
783
                protected bool has_arglist;
 
784
                protected bool has_params;
 
785
 
 
786
                // Null object pattern
 
787
                protected IParameterData [] parameters;
 
788
                protected TypeSpec [] types;
 
789
 
 
790
                public CallingConventions CallingConvention {
 
791
                        get {
 
792
                                return has_arglist ?
 
793
                                        CallingConventions.VarArgs :
 
794
                                        CallingConventions.Standard;
 
795
                        }
 
796
                }
 
797
 
 
798
                public int Count {
 
799
                        get { return parameters.Length; }
 
800
                }
 
801
 
 
802
                public TypeSpec ExtensionMethodType {
 
803
                        get {
 
804
                                if (Count == 0)
 
805
                                        return null;
 
806
 
 
807
                                return FixedParameters [0].HasExtensionMethodModifier ?
 
808
                                        types [0] : null;
 
809
                        }
 
810
                }
 
811
 
 
812
                public IParameterData [] FixedParameters {
 
813
                        get {
 
814
                                return parameters;
 
815
                        }
 
816
                }
 
817
 
 
818
                public static ParameterAttributes GetParameterAttribute (Parameter.Modifier modFlags)
 
819
                {
 
820
                        return (modFlags & Parameter.Modifier.OUT) != 0 ?
 
821
                                ParameterAttributes.Out : ParameterAttributes.None;
 
822
                }
 
823
 
 
824
                // Very expensive operation
 
825
                public MetaType[] GetMetaInfo ()
 
826
                {
 
827
                        MetaType[] types;
 
828
                        if (has_arglist) {
 
829
                                if (Count == 1)
 
830
                                        return MetaType.EmptyTypes;
 
831
 
 
832
                                types = new MetaType[Count - 1];
 
833
                        } else {
 
834
                                if (Count == 0)
 
835
                                        return MetaType.EmptyTypes;
 
836
 
 
837
                                types = new MetaType[Count];
 
838
                        }
 
839
 
 
840
                        for (int i = 0; i < types.Length; ++i) {
 
841
                                types[i] = Types[i].GetMetaInfo ();
 
842
 
 
843
                                if ((FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask) == 0)
 
844
                                        continue;
 
845
 
 
846
                                // TODO MemberCache: Should go to MetaInfo getter
 
847
                                types [i] = types [i].MakeByRefType ();
 
848
                        }
 
849
 
 
850
                        return types;
 
851
                }
 
852
 
 
853
                //
 
854
                // Returns the parameter information based on the name
 
855
                //
 
856
                public int GetParameterIndexByName (string name)
 
857
                {
 
858
                        for (int idx = 0; idx < Count; ++idx) {
 
859
                                if (parameters [idx].Name == name)
 
860
                                        return idx;
 
861
                        }
 
862
 
 
863
                        return -1;
 
864
                }
 
865
 
 
866
                public string GetSignatureForDocumentation ()
 
867
                {
 
868
                        if (IsEmpty)
 
869
                                return string.Empty;
 
870
 
 
871
                        StringBuilder sb = new StringBuilder ("(");
 
872
                        for (int i = 0; i < Count; ++i) {
 
873
                                if (i != 0)
 
874
                                        sb.Append (",");
 
875
 
 
876
                                sb.Append (types [i].GetSignatureForDocumentation ());
 
877
 
 
878
                                if ((parameters[i].ModFlags & Parameter.Modifier.RefOutMask) != 0)
 
879
                                        sb.Append ("@");
 
880
                        }
 
881
                        sb.Append (")");
 
882
 
 
883
                        return sb.ToString ();
 
884
                }
 
885
 
 
886
                public string GetSignatureForError ()
 
887
                {
 
888
                        return GetSignatureForError ("(", ")", Count);
 
889
                }
 
890
 
 
891
                public string GetSignatureForError (string start, string end, int count)
 
892
                {
 
893
                        StringBuilder sb = new StringBuilder (start);
 
894
                        for (int i = 0; i < count; ++i) {
 
895
                                if (i != 0)
 
896
                                        sb.Append (", ");
 
897
                                sb.Append (ParameterDesc (i));
 
898
                        }
 
899
                        sb.Append (end);
 
900
                        return sb.ToString ();
 
901
                }
 
902
 
 
903
                public bool HasArglist {
 
904
                        get { return has_arglist; }
 
905
                }
 
906
 
 
907
                public bool HasExtensionMethodType {
 
908
                        get {
 
909
                                if (Count == 0)
 
910
                                        return false;
 
911
 
 
912
                                return FixedParameters [0].HasExtensionMethodModifier;
 
913
                        }
 
914
                }
 
915
 
 
916
                public bool HasParams {
 
917
                        get { return has_params; }
 
918
                }
 
919
 
 
920
                public bool IsEmpty {
 
921
                        get { return parameters.Length == 0; }
 
922
                }
 
923
 
 
924
                public AParametersCollection Inflate (TypeParameterInflator inflator)
 
925
                {
 
926
                        TypeSpec[] inflated_types = null;
 
927
                        bool default_value = false;
 
928
 
 
929
                        for (int i = 0; i < Count; ++i) {
 
930
                                var inflated_param = inflator.Inflate (types[i]);
 
931
                                if (inflated_types == null) {
 
932
                                        if (inflated_param == types[i])
 
933
                                                continue;
 
934
 
 
935
                                        default_value |= FixedParameters[i].HasDefaultValue;
 
936
                                        inflated_types = new TypeSpec[types.Length];
 
937
                                        Array.Copy (types, inflated_types, types.Length);
 
938
                                } else {
 
939
                                        if (inflated_param == types[i])
 
940
                                                continue;
 
941
 
 
942
                                        default_value |= FixedParameters[i].HasDefaultValue;
 
943
                                }
 
944
 
 
945
                                inflated_types[i] = inflated_param;
 
946
                        }
 
947
 
 
948
                        if (inflated_types == null)
 
949
                                return this;
 
950
 
 
951
                        var clone = (AParametersCollection) MemberwiseClone ();
 
952
                        clone.types = inflated_types;
 
953
 
 
954
                        //
 
955
                        // Default expression is original expression from the parameter
 
956
                        // declaration context which can be of nested enum in generic class type.
 
957
                        // In such case we end up with expression type of G<T>.E and e.g. parameter
 
958
                        // type of G<int>.E and conversion would fail without inflate in this
 
959
                        // context.
 
960
                        //
 
961
                        if (default_value) {
 
962
                                clone.parameters = new IParameterData[Count];
 
963
                                for (int i = 0; i < Count; ++i) {
 
964
                                        var fp = FixedParameters[i];
 
965
                                        clone.FixedParameters[i] = fp;
 
966
 
 
967
                                        if (!fp.HasDefaultValue)
 
968
                                                continue;
 
969
 
 
970
                                        var expr = fp.DefaultValue;
 
971
 
 
972
                                        if (inflated_types[i] == expr.Type)
 
973
                                                continue;
 
974
 
 
975
                                        if (expr is DefaultValueExpression)
 
976
                                                expr = new DefaultValueExpression (new TypeExpression (inflated_types[i], expr.Location), expr.Location);
 
977
                                        else if (expr is Constant)
 
978
                                                expr = Constant.CreateConstantFromValue (inflated_types[i], ((Constant) expr).GetValue (), expr.Location);
 
979
 
 
980
                                        clone.FixedParameters[i] = new ParameterData (fp.Name, fp.ModFlags, expr);
 
981
                                }
 
982
                        }
 
983
 
 
984
                        return clone;
 
985
                }
 
986
 
 
987
                public string ParameterDesc (int pos)
 
988
                {
 
989
                        if (types == null || types [pos] == null)
 
990
                                return ((Parameter)FixedParameters [pos]).GetSignatureForError ();
 
991
 
 
992
                        string type = TypeManager.CSharpName (types [pos]);
 
993
                        if (FixedParameters [pos].HasExtensionMethodModifier)
 
994
                                return "this " + type;
 
995
 
 
996
                        var mod = FixedParameters[pos].ModFlags & Parameter.Modifier.ModifierMask;
 
997
                        if (mod == 0)
 
998
                                return type;
 
999
 
 
1000
                        return Parameter.GetModifierSignature (mod) + " " + type;
 
1001
                }
 
1002
 
 
1003
                public TypeSpec[] Types {
 
1004
                        get { return types; }
 
1005
                        set { types = value; }
 
1006
                }
 
1007
        }
 
1008
 
 
1009
        //
 
1010
        // A collection of imported or resolved parameters
 
1011
        //
 
1012
        public class ParametersImported : AParametersCollection
 
1013
        {
 
1014
                public ParametersImported (IParameterData [] parameters, TypeSpec [] types, bool hasArglist, bool hasParams)
 
1015
                {
 
1016
                        this.parameters = parameters;
 
1017
                        this.types = types;
 
1018
                        this.has_arglist = hasArglist;
 
1019
                        this.has_params = hasParams;
 
1020
                }
 
1021
 
 
1022
                public ParametersImported (IParameterData[] param, TypeSpec[] types, bool hasParams)
 
1023
                {
 
1024
                        this.parameters = param;
 
1025
                        this.types = types;
 
1026
                        this.has_params = hasParams;
 
1027
                }
 
1028
        }
 
1029
 
 
1030
        /// <summary>
 
1031
        ///   Represents the methods parameters
 
1032
        /// </summary>
 
1033
        public class ParametersCompiled : AParametersCollection
 
1034
        {
 
1035
                public static readonly ParametersCompiled EmptyReadOnlyParameters = new ParametersCompiled ();
 
1036
                
 
1037
                // Used by C# 2.0 delegates
 
1038
                public static readonly ParametersCompiled Undefined = new ParametersCompiled ();
 
1039
 
 
1040
                private ParametersCompiled ()
 
1041
                {
 
1042
                        parameters = new Parameter [0];
 
1043
                        types = TypeSpec.EmptyTypes;
 
1044
                }
 
1045
 
 
1046
                private ParametersCompiled (IParameterData[] parameters, TypeSpec[] types)
 
1047
                {
 
1048
                        this.parameters = parameters;
 
1049
                    this.types = types;
 
1050
                }
 
1051
                
 
1052
                public ParametersCompiled (params Parameter[] parameters)
 
1053
                {
 
1054
                        if (parameters == null || parameters.Length == 0)
 
1055
                                throw new ArgumentException ("Use EmptyReadOnlyParameters");
 
1056
 
 
1057
                        this.parameters = parameters;
 
1058
                        int count = parameters.Length;
 
1059
 
 
1060
                        for (int i = 0; i < count; i++){
 
1061
                                has_params |= (parameters [i].ModFlags & Parameter.Modifier.PARAMS) != 0;
 
1062
                        }
 
1063
                }
 
1064
 
 
1065
                public ParametersCompiled (Parameter [] parameters, bool has_arglist) :
 
1066
                        this (parameters)
 
1067
                {
 
1068
                        this.has_arglist = has_arglist;
 
1069
                }
 
1070
                
 
1071
                public static ParametersCompiled CreateFullyResolved (Parameter p, TypeSpec type)
 
1072
                {
 
1073
                        return new ParametersCompiled (new Parameter [] { p }, new TypeSpec [] { type });
 
1074
                }
 
1075
                
 
1076
                public static ParametersCompiled CreateFullyResolved (Parameter[] parameters, TypeSpec[] types)
 
1077
                {
 
1078
                        return new ParametersCompiled (parameters, types);
 
1079
                }
 
1080
 
 
1081
                //
 
1082
                // TODO: This does not fit here, it should go to different version of AParametersCollection
 
1083
                // as the underlying type is not Parameter and some methods will fail to cast
 
1084
                //
 
1085
                public static AParametersCollection CreateFullyResolved (params TypeSpec[] types)
 
1086
                {
 
1087
                        var pd = new ParameterData [types.Length];
 
1088
                        for (int i = 0; i < pd.Length; ++i)
 
1089
                                pd[i] = new ParameterData (null, Parameter.Modifier.NONE, null);
 
1090
 
 
1091
                        return new ParametersCompiled (pd, types);
 
1092
                }
 
1093
 
 
1094
                public static ParametersCompiled CreateImplicitParameter (FullNamedExpression texpr, Location loc)
 
1095
                {
 
1096
                        return new ParametersCompiled (
 
1097
                                new[] { new Parameter (texpr, "value", Parameter.Modifier.NONE, null, loc) },
 
1098
                                null);
 
1099
                }
 
1100
 
 
1101
                public void CheckConstraints (IMemberContext mc)
 
1102
                {
 
1103
                        foreach (Parameter p in parameters) {
 
1104
                                //
 
1105
                                // It's null for compiler generated types or special types like __arglist
 
1106
                                //
 
1107
                                if (p.TypeExpression != null)
 
1108
                                        ConstraintChecker.Check (mc, p.Type, p.TypeExpression.Location);
 
1109
                        }
 
1110
                }
 
1111
 
 
1112
                //
 
1113
                // Returns non-zero value for equal CLS parameter signatures
 
1114
                //
 
1115
                public static int IsSameClsSignature (AParametersCollection a, AParametersCollection b)
 
1116
                {
 
1117
                        int res = 0;
 
1118
 
 
1119
                        for (int i = 0; i < a.Count; ++i) {
 
1120
                                var a_type = a.Types[i];
 
1121
                                var b_type = b.Types[i];
 
1122
                                if (TypeSpecComparer.Override.IsEqual (a_type, b_type)) {
 
1123
                                        if ((a.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask) != (b.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask))
 
1124
                                                res |= 1;
 
1125
 
 
1126
                                        continue;
 
1127
                                }
 
1128
 
 
1129
                                var ac_a = a_type as ArrayContainer;
 
1130
                                if (ac_a == null)
 
1131
                                        return 0;
 
1132
 
 
1133
                                var ac_b = b_type as ArrayContainer;
 
1134
                                if (ac_b == null)
 
1135
                                        return 0;
 
1136
 
 
1137
                                if (ac_a.Element is ArrayContainer || ac_b.Element is ArrayContainer) {
 
1138
                                        res |= 2;
 
1139
                                        continue;
 
1140
                                }
 
1141
 
 
1142
                                if (ac_a.Rank != ac_b.Rank && TypeSpecComparer.Override.IsEqual (ac_a.Element, ac_b.Element)) {
 
1143
                                        res |= 1;
 
1144
                                        continue;
 
1145
                                }
 
1146
 
 
1147
                                return 0;
 
1148
                        }
 
1149
 
 
1150
                        return res;
 
1151
                }
 
1152
 
 
1153
                public static ParametersCompiled MergeGenerated (CompilerContext ctx, ParametersCompiled userParams, bool checkConflicts, Parameter compilerParams, TypeSpec compilerTypes)
 
1154
                {
 
1155
                        return MergeGenerated (ctx, userParams, checkConflicts,
 
1156
                                new Parameter [] { compilerParams },
 
1157
                                new TypeSpec [] { compilerTypes });
 
1158
                }
 
1159
 
 
1160
                //
 
1161
                // Use this method when you merge compiler generated parameters with user parameters
 
1162
                //
 
1163
                public static ParametersCompiled MergeGenerated (CompilerContext ctx, ParametersCompiled userParams, bool checkConflicts, Parameter[] compilerParams, TypeSpec[] compilerTypes)
 
1164
                {
 
1165
                        Parameter[] all_params = new Parameter [userParams.Count + compilerParams.Length];
 
1166
                        userParams.FixedParameters.CopyTo(all_params, 0);
 
1167
 
 
1168
                        TypeSpec [] all_types;
 
1169
                        if (userParams.types != null) {
 
1170
                                all_types = new TypeSpec [all_params.Length];
 
1171
                                userParams.Types.CopyTo (all_types, 0);
 
1172
                        } else {
 
1173
                                all_types = null;
 
1174
                        }
 
1175
 
 
1176
                        int last_filled = userParams.Count;
 
1177
                        int index = 0;
 
1178
                        foreach (Parameter p in compilerParams) {
 
1179
                                for (int i = 0; i < last_filled; ++i) {
 
1180
                                        while (p.Name == all_params [i].Name) {
 
1181
                                                if (checkConflicts && i < userParams.Count) {
 
1182
                                                        ctx.Report.Error (316, userParams[i].Location,
 
1183
                                                                "The parameter name `{0}' conflicts with a compiler generated name", p.Name);
 
1184
                                                }
 
1185
                                                p.Name = '_' + p.Name;
 
1186
                                        }
 
1187
                                }
 
1188
                                all_params [last_filled] = p;
 
1189
                                if (all_types != null)
 
1190
                                        all_types [last_filled] = compilerTypes [index++];
 
1191
                                ++last_filled;
 
1192
                        }
 
1193
                        
 
1194
                        ParametersCompiled parameters = new ParametersCompiled (all_params, all_types);
 
1195
                        parameters.has_params = userParams.has_params;
 
1196
                        return parameters;
 
1197
                }
 
1198
 
 
1199
                //
 
1200
                // Parameters checks for members which don't have a block
 
1201
                //
 
1202
                public void CheckParameters (MemberCore member)
 
1203
                {
 
1204
                        for (int i = 0; i < parameters.Length; ++i) {
 
1205
                                var name = parameters[i].Name;
 
1206
                                for (int ii = i + 1; ii < parameters.Length; ++ii) {
 
1207
                                        if (parameters[ii].Name == name)
 
1208
                                                this[ii].Error_DuplicateName (member.Compiler.Report);
 
1209
                                }
 
1210
                        }
 
1211
                }
 
1212
 
 
1213
                public bool Resolve (IMemberContext ec)
 
1214
                {
 
1215
                        if (types != null)
 
1216
                                return true;
 
1217
                        
 
1218
                        types = new TypeSpec [Count];
 
1219
                        
 
1220
                        bool ok = true;
 
1221
                        Parameter p;
 
1222
                        for (int i = 0; i < FixedParameters.Length; ++i) {
 
1223
                                p = this [i];
 
1224
                                TypeSpec t = p.Resolve (ec, i);
 
1225
                                if (t == null) {
 
1226
                                        ok = false;
 
1227
                                        continue;
 
1228
                                }
 
1229
 
 
1230
                                types [i] = t;
 
1231
                        }
 
1232
 
 
1233
                        return ok;
 
1234
                }
 
1235
 
 
1236
                public void ResolveDefaultValues (MemberCore m)
 
1237
                {
 
1238
                        ResolveContext rc = null;
 
1239
                        for (int i = 0; i < parameters.Length; ++i) {
 
1240
                                Parameter p = (Parameter) parameters [i];
 
1241
 
 
1242
                                //
 
1243
                                // Try not to enter default values resolution if there are is not any default value possible
 
1244
                                //
 
1245
                                if (p.HasDefaultValue || p.OptAttributes != null) {
 
1246
                                        if (rc == null)
 
1247
                                                rc = new ResolveContext (m);
 
1248
 
 
1249
                                        p.ResolveDefaultValue (rc);
 
1250
                                }
 
1251
                        }
 
1252
                }
 
1253
 
 
1254
                // Define each type attribute (in/out/ref) and
 
1255
                // the argument names.
 
1256
                public void ApplyAttributes (IMemberContext mc, MethodBase builder)
 
1257
                {
 
1258
                        if (Count == 0)
 
1259
                                return;
 
1260
 
 
1261
                        MethodBuilder mb = builder as MethodBuilder;
 
1262
                        ConstructorBuilder cb = builder as ConstructorBuilder;
 
1263
                        var pa = mc.Module.PredefinedAttributes;
 
1264
 
 
1265
                        for (int i = 0; i < Count; i++) {
 
1266
                                this [i].ApplyAttributes (mb, cb, i + 1, pa);
 
1267
                        }
 
1268
                }
 
1269
 
 
1270
                public void VerifyClsCompliance (IMemberContext ctx)
 
1271
                {
 
1272
                        foreach (Parameter p in FixedParameters)
 
1273
                                p.IsClsCompliant (ctx);
 
1274
                }
 
1275
 
 
1276
                public Parameter this [int pos] {
 
1277
                        get { return (Parameter) parameters [pos]; }
 
1278
                }
 
1279
 
 
1280
                public Expression CreateExpressionTree (BlockContext ec, Location loc)
 
1281
                {
 
1282
                        var initializers = new ArrayInitializer (Count, loc);
 
1283
                        foreach (Parameter p in FixedParameters) {
 
1284
                                //
 
1285
                                // Each parameter expression is stored to local variable
 
1286
                                // to save some memory when referenced later.
 
1287
                                //
 
1288
                                StatementExpression se = new StatementExpression (p.CreateExpressionTreeVariable (ec), Location.Null);
 
1289
                                if (se.Resolve (ec)) {
 
1290
                                        ec.CurrentBlock.AddScopeStatement (new TemporaryVariableReference.Declarator (p.ExpressionTreeVariableReference ()));
 
1291
                                        ec.CurrentBlock.AddScopeStatement (se);
 
1292
                                }
 
1293
                                
 
1294
                                initializers.Add (p.ExpressionTreeVariableReference ());
 
1295
                        }
 
1296
 
 
1297
                        return new ArrayCreation (
 
1298
                                Parameter.ResolveParameterExpressionType (ec, loc),
 
1299
                                initializers, loc);
 
1300
                }
 
1301
 
 
1302
                public ParametersCompiled Clone ()
 
1303
                {
 
1304
                        ParametersCompiled p = (ParametersCompiled) MemberwiseClone ();
 
1305
 
 
1306
                        p.parameters = new IParameterData [parameters.Length];
 
1307
                        for (int i = 0; i < Count; ++i)
 
1308
                                p.parameters [i] = this [i].Clone ();
 
1309
 
 
1310
                        return p;
 
1311
                }
 
1312
        }
 
1313
 
 
1314
        //
 
1315
        // Default parameter value expression. We need this wrapper to handle
 
1316
        // default parameter values of folded constants (e.g. indexer parameters).
 
1317
        // The expression is resolved only once but applied to two methods which
 
1318
        // both share reference to this expression and we ensure that resolving
 
1319
        // this expression always returns same instance
 
1320
        //
 
1321
        public class DefaultParameterValueExpression : CompositeExpression
 
1322
        {
 
1323
                public DefaultParameterValueExpression (Expression expr)
 
1324
                        : base (expr)
 
1325
                {
 
1326
                }
 
1327
 
 
1328
                protected override Expression DoResolve (ResolveContext rc)
 
1329
                {
 
1330
                        return base.DoResolve (rc);
 
1331
                }
 
1332
 
 
1333
                public void Resolve (ResolveContext rc, Parameter p)
 
1334
                {
 
1335
                        var expr = Resolve (rc);
 
1336
                        if (expr == null)
 
1337
                                return;
 
1338
 
 
1339
                        expr = Child;
 
1340
 
 
1341
                        if (!(expr is Constant || expr is DefaultValueExpression || (expr is New && ((New) expr).IsDefaultStruct))) {
 
1342
                                rc.Report.Error (1736, Location,
 
1343
                                        "The expression being assigned to optional parameter `{0}' must be a constant or default value",
 
1344
                                        p.Name);
 
1345
 
 
1346
                                return;
 
1347
                        }
 
1348
 
 
1349
                        var parameter_type = p.Type;
 
1350
                        if (type == parameter_type)
 
1351
                                return;
 
1352
 
 
1353
                        var res = Convert.ImplicitConversionStandard (rc, expr, parameter_type, Location);
 
1354
                        if (res != null) {
 
1355
                                if (parameter_type.IsNullableType && res is Nullable.Wrap) {
 
1356
                                        Nullable.Wrap wrap = (Nullable.Wrap) res;
 
1357
                                        res = wrap.Child;
 
1358
                                        if (!(res is Constant)) {
 
1359
                                                rc.Report.Error (1770, Location,
 
1360
                                                        "The expression being assigned to nullable optional parameter `{0}' must be default value",
 
1361
                                                        p.Name);
 
1362
                                                return;
 
1363
                                        }
 
1364
                                }
 
1365
 
 
1366
                                if (!expr.IsNull && TypeSpec.IsReferenceType (parameter_type) && parameter_type.BuiltinType != BuiltinTypeSpec.Type.String) {
 
1367
                                        rc.Report.Error (1763, Location,
 
1368
                                                "Optional parameter `{0}' of type `{1}' can only be initialized with `null'",
 
1369
                                                p.Name, parameter_type.GetSignatureForError ());
 
1370
 
 
1371
                                        return;
 
1372
                                }
 
1373
 
 
1374
                                this.expr = res;
 
1375
                                return;
 
1376
                        }
 
1377
 
 
1378
                        rc.Report.Error (1750, Location,
 
1379
                                "Optional parameter expression of type `{0}' cannot be converted to parameter type `{1}'",
 
1380
                                type.GetSignatureForError (), parameter_type.GetSignatureForError ());
 
1381
                }
 
1382
                
 
1383
                public override object Accept (StructuralVisitor visitor)
 
1384
                {
 
1385
                        return visitor.Visit (this);
 
1386
                }
 
1387
        }
 
1388
}