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