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