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