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