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