2009-06-12 Bill Holmes <billholmes54@gmail.com>
[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, PredefinedAttributes pa)
34                 {
35 #if !NET_2_0
36                         if (a.Type == pa.MarshalAs) {
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, PredefinedAttributes pa)
74                 {
75                         if (a.Type == pa.CLSCompliant) {
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, pa);
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, "value");                    
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                         PredefinedAttributes.Get.ParamArray.EmitAttribute (builder, Location);
187                 }
188         }
189
190         public class ArglistParameter : Parameter {
191                 // Doesn't have proper type because it's never chosen for better conversion
192                 public ArglistParameter (Location loc) :
193                         base (null, String.Empty, Parameter.Modifier.ARGLIST, null, loc)
194                 {
195                 }
196
197                 public override void  ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
198                 {
199                         // Nothing to do
200                 }
201
202                 public override bool CheckAccessibility (InterfaceMemberBase member)
203                 {
204                         return true;
205                 }
206
207                 public override Type Resolve (IResolveContext ec)
208                 {
209                         return typeof (ArglistParameter);
210                 }
211
212                 public override string GetSignatureForError ()
213                 {
214                         return "__arglist";
215                 }
216         }
217
218         public interface IParameterData
219         {
220                 bool HasExtensionMethodModifier { get; }
221                 Parameter.Modifier ModFlags { get; }
222                 string Name { get; }
223         }
224
225         //
226         // Parameter information created by parser
227         //
228         public class Parameter : ParameterBase, IParameterData, ILocalVariable {
229                 [Flags]
230                 public enum Modifier : byte {
231                         NONE    = 0,
232                         REF     = REFMASK | ISBYREF,
233                         OUT     = OUTMASK | ISBYREF,
234                         PARAMS  = 4,
235                         // This is a flag which says that it's either REF or OUT.
236                         ISBYREF = 8,
237                         ARGLIST = 16,
238                         REFMASK = 32,
239                         OUTMASK = 64,
240                         This    = 128
241                 }
242
243                 static string[] attribute_targets = new string [] { "param" };
244
245                 protected FullNamedExpression TypeName;
246                 readonly Modifier modFlags;
247                 string name;
248                 Expression default_expr;
249                 protected Type parameter_type;
250                 public readonly Location Location;
251                 int idx;
252                 public bool HasAddressTaken;
253
254                 IResolveContext resolve_context;
255                 LocalVariableReference expr_tree_variable;
256                 static TypeExpr parameter_expr_tree_type;
257
258                 public HoistedVariable HoistedVariableReference;
259
260                 public Parameter (FullNamedExpression type, string name, Modifier mod, Attributes attrs, Location loc)
261                         : base (attrs)
262                 {
263                         if (type == TypeManager.system_void_expr)
264                                 Report.Error (1536, loc, "Invalid parameter type `void'");
265
266                         this.name = name;
267                         modFlags = mod;
268                         Location = loc;
269                         TypeName = type;
270                 }
271
272                 public Parameter (FullNamedExpression type, string name, Modifier mod, Attributes attrs, Expression defaultValue, Location loc)
273                         : this (type, name, mod, attrs, loc)
274                 {
275                         default_expr = defaultValue;
276                 }
277
278                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
279                 {
280                         if (a.Type == pa.In && ModFlags == Modifier.OUT) {
281                                 Report.Error (36, a.Location, "An out parameter cannot have the `In' attribute");
282                                 return;
283                         }
284
285                         if (a.Type == pa.ParamArray) {
286                                 Report.Error (674, a.Location, "Do not use `System.ParamArrayAttribute'. Use the `params' keyword instead");
287                                 return;
288                         }
289
290                         if (a.Type == PredefinedAttributes.Get.Out && (ModFlags & Modifier.REF) == Modifier.REF &&
291                             !OptAttributes.Contains (pa.In)) {
292                                 Report.Error (662, a.Location,
293                                         "Cannot specify only `Out' attribute on a ref parameter. Use both `In' and `Out' attributes or neither");
294                                 return;
295                         }
296
297                         if (a.Type == pa.CLSCompliant) {
298                                 Report.Warning (3022, 1, a.Location, "CLSCompliant attribute has no meaning when applied to parameters. Try putting it on the method instead");
299                         }
300
301                         if (HasDefaultValue && (a.Type == pa.DefaultParameterValue || a.Type == pa.OptionalParameter)) {
302                                 Report.Error (1745, a.Location,
303                                         "Cannot specify `{0}' attribute on optional parameter `{1}'",
304                                         TypeManager.CSharpName (a.Type).Replace ("Attribute", ""), Name);
305                                 return;
306                         }
307
308                         if (a.Type == pa.DefaultParameterValue) {
309                                 object val = a.GetParameterDefaultValue ();
310                                 if (val != null) {
311                                         Type t = val.GetType ();
312                                         if (t.IsArray || TypeManager.IsSubclassOf (t, TypeManager.type_type)) {
313                                                 if (parameter_type == TypeManager.object_type) {
314                                                         if (!t.IsArray)
315                                                                 t = TypeManager.type_type;
316
317                                                         Report.Error (1910, a.Location, "Argument of type `{0}' is not applicable for the DefaultParameterValue attribute",
318                                                                 TypeManager.CSharpName (t));
319                                                 } else {
320                                                         Report.Error (1909, a.Location, "The DefaultParameterValue attribute is not applicable on parameters of type `{0}'",
321                                                                 TypeManager.CSharpName (parameter_type)); ;
322                                                 }
323                                                 return;
324                                         }
325                                 }
326
327                                 if (parameter_type == TypeManager.object_type ||
328                                     (val == null && !TypeManager.IsGenericParameter (parameter_type) && TypeManager.IsReferenceType (parameter_type)) ||
329                                     (val != null && TypeManager.TypeToCoreType (val.GetType ()) == parameter_type))
330                                         builder.SetConstant (val);
331                                 else
332                                         Report.Error (1908, a.Location, "The type of the default value should match the type of the parameter");
333                                 return;
334                         }
335
336                         base.ApplyAttributeBuilder (a, cb, pa);
337                 }
338                 
339                 public virtual bool CheckAccessibility (InterfaceMemberBase member)
340                 {
341                         if (parameter_type == null || TypeManager.IsGenericParameter (parameter_type))
342                                 return true;
343
344                         return member.IsAccessibleAs (parameter_type);
345                 }
346
347                 public override IResolveContext ResolveContext {
348                         get {
349                                 return resolve_context;
350                         }
351                 }
352
353                 // <summary>
354                 //   Resolve is used in method definitions
355                 // </summary>
356                 public virtual Type Resolve (IResolveContext rc)
357                 {
358                         // HACK: to resolve attributes correctly
359                         this.resolve_context = rc;
360
361                         if (parameter_type != null)
362                                 return parameter_type;
363
364                         TypeExpr texpr = TypeName.ResolveAsTypeTerminal (rc, false);
365                         if (texpr == null)
366                                 return null;
367
368                         parameter_type = texpr.Type;
369
370                         // Ignore all checks for dummy members
371                         AbstractPropertyEventMethod pem = rc as AbstractPropertyEventMethod;
372                         if (pem != null && pem.IsDummy)
373                                 return parameter_type;
374
375                         if (default_expr != null) {
376                                 EmitContext ec = new EmitContext (rc, rc.DeclContainer, Location, null, parameter_type, 0);
377                                 default_expr = default_expr.Resolve (ec);
378                                 if (default_expr != null) {
379                                         Constant value = default_expr as Constant;
380                                         if (value == null) {
381                                                 if (default_expr != null)
382                                                         Report.Error (1736, default_expr.Location, "The expression being assigned to optional parameter `{0}' must be constant",
383                                                                 Name);
384                                         } else {
385                                                 Constant c = value.ConvertImplicitly (parameter_type);
386                                                 if (c == null)
387                                                         Report.Error (1750, Location,
388                                                                 "Optional parameter value `{0}' cannot be converted to parameter type `{1}'",
389                                                                 value.GetValue (), GetSignatureForError ());
390
391                                         //      value = c;
392                                         }
393
394                                         default_expr = value;
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 (texpr is TypeParameterExpr)
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) {
419                                 Report.Error (1103, Location, "The type of extension method cannot be `{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                                 Constant c = (Constant) default_expr;
510                                 if (default_expr.Type == TypeManager.decimal_type) {
511                                         builder.SetCustomAttribute (Const.CreateDecimalConstantAttribute (c));
512                                 } else {
513                                         builder.SetConstant (c.GetValue ());
514                                 }
515                         }
516                 }
517
518                 public override string[] ValidAttributeTargets {
519                         get {
520                                 return attribute_targets;
521                         }
522                 }
523
524                 public Parameter Clone ()
525                 {
526                         Parameter p = (Parameter) MemberwiseClone ();
527                         if (attributes != null) {
528                                 p.attributes = attributes.Clone ();
529                                 p.attributes.AttachTo (p);
530                         }
531
532                         return p;
533                 }
534
535                 public ExpressionStatement CreateExpressionTreeVariable (EmitContext ec)
536                 {
537                         //
538                         // A parameter is not hoisted when used directly as ET
539                         //
540                         HoistedVariableReference = null;
541
542                         if ((modFlags & Modifier.ISBYREF) != 0)
543                                 Report.Error (1951, Location, "An expression tree parameter cannot use `ref' or `out' modifier");
544
545                         LocalInfo variable = ec.CurrentBlock.AddTemporaryVariable (
546                                 ResolveParameterExpressionType (ec, Location), Location);
547                         variable.Resolve (ec);
548
549                         expr_tree_variable = new LocalVariableReference (
550                                 ec.CurrentBlock, variable.Name, Location, variable, false);
551
552                         ArrayList arguments = new ArrayList (2);
553                         arguments.Add (new Argument (new TypeOf (
554                                 new TypeExpression (parameter_type, Location), Location)));
555                         arguments.Add (new Argument (new StringConstant (Name, Location)));
556                         return new SimpleAssign (ExpressionTreeVariableReference (),
557                                 Expression.CreateExpressionFactoryCall ("Parameter", null, arguments, Location));
558                 }
559
560                 public void Emit (EmitContext ec)
561                 {
562                         int arg_idx = idx;
563                         if (!ec.IsStatic)
564                                 arg_idx++;
565
566                         ParameterReference.EmitLdArg (ec.ig, arg_idx);
567                 }
568
569                 public void EmitAssign (EmitContext ec)
570                 {
571                         int arg_idx = idx;
572                         if (!ec.IsStatic)
573                                 arg_idx++;
574
575                         if (arg_idx <= 255)
576                                 ec.ig.Emit (OpCodes.Starg_S, (byte) arg_idx);
577                         else
578                                 ec.ig.Emit (OpCodes.Starg, arg_idx);
579                 }
580
581                 public void EmitAddressOf (EmitContext ec)
582                 {
583                         int arg_idx = idx;
584
585                         if (!ec.IsStatic)
586                                 arg_idx++;
587
588                         bool is_ref = (ModFlags & Modifier.ISBYREF) != 0;
589                         if (is_ref) {
590                                 ParameterReference.EmitLdArg (ec.ig, arg_idx);
591                         } else {
592                                 if (arg_idx <= 255)
593                                         ec.ig.Emit (OpCodes.Ldarga_S, (byte) arg_idx);
594                                 else
595                                         ec.ig.Emit (OpCodes.Ldarga, arg_idx);
596                         }
597                 }
598
599                 public Expression ExpressionTreeVariableReference ()
600                 {
601                         return expr_tree_variable;
602                 }
603
604                 //
605                 // System.Linq.Expressions.ParameterExpression type
606                 //
607                 public static TypeExpr ResolveParameterExpressionType (EmitContext ec, Location location)
608                 {
609                         if (parameter_expr_tree_type != null)
610                                 return parameter_expr_tree_type;
611
612                         Type p_type = TypeManager.parameter_expression_type;
613                         if (p_type == null) {
614                                 p_type = TypeManager.CoreLookupType ("System.Linq.Expressions", "ParameterExpression", Kind.Class, true);
615                                 TypeManager.parameter_expression_type = p_type;
616                         }
617
618                         parameter_expr_tree_type = new TypeExpression (p_type, location).
619                                 ResolveAsTypeTerminal (ec, false);
620
621                         return parameter_expr_tree_type;
622                 }
623         }
624
625         //
626         // Imported or resolved parameter information
627         //
628         public class ParameterData : IParameterData
629         {
630                 readonly string name;
631                 readonly Parameter.Modifier modifiers;
632
633                 public ParameterData (string name, Parameter.Modifier modifiers)
634                 {
635                         this.name = name;
636                         this.modifiers = modifiers;
637                 }
638
639                 #region IParameterData Members
640
641                 public bool HasExtensionMethodModifier {
642                         get { return (modifiers & Parameter.Modifier.This) != 0; }
643                 }
644
645                 public Parameter.Modifier ModFlags {
646                         get { return modifiers & ~Parameter.Modifier.This; }
647                 }
648
649                 public string Name {
650                         get { return name; }
651                 }
652
653                 #endregion
654         }
655
656         public abstract class AParametersCollection
657         {
658                 protected bool has_arglist;
659                 protected bool has_params;
660
661                 // Null object pattern
662                 protected IParameterData [] parameters;
663                 protected Type [] types;
664
665                 public int Count {
666                         get { return parameters.Length; }
667                 }
668
669                 public Type ExtensionMethodType {
670                         get {
671                                 if (Count == 0)
672                                         return null;
673
674                                 return FixedParameters [0].HasExtensionMethodModifier ?
675                                         types [0] : null;
676                         }
677                 }
678
679                 public IParameterData [] FixedParameters {
680                         get {
681                                 return parameters;
682                         }
683                 }
684
685                 public static ParameterAttributes GetParameterAttribute (Parameter.Modifier modFlags)
686                 {
687                         return (modFlags & Parameter.Modifier.OUT) == Parameter.Modifier.OUT ?
688                                 ParameterAttributes.Out : ParameterAttributes.None;
689                 }
690
691                 public Type [] GetEmitTypes ()
692                 {
693                         Type [] types = null;
694                         if (has_arglist) {
695                                 if (Count == 1)
696                                         return Type.EmptyTypes;
697
698                                 types = new Type [Count - 1];
699                                 Array.Copy (Types, types, types.Length);
700                         }
701
702                         for (int i = 0; i < Count; ++i) {
703                                 if ((FixedParameters [i].ModFlags & Parameter.Modifier.ISBYREF) == 0)
704                                         continue;
705
706                                 if (types == null)
707                                         types = (Type []) Types.Clone ();
708
709                                 types [i] = TypeManager.GetReferenceType (types [i]);
710                         }
711
712                         if (types == null)
713                                 types = Types;
714
715                         return types;
716                 }
717
718                 public string GetSignatureForError ()
719                 {
720                         StringBuilder sb = new StringBuilder ("(");
721                         for (int i = 0; i < Count; ++i) {
722                                 if (i != 0)
723                                         sb.Append (", ");
724                                 sb.Append (ParameterDesc (i));
725                         }
726                         sb.Append (')');
727                         return sb.ToString ();
728                 }
729
730                 public bool HasArglist {
731                         get { return has_arglist; }
732                 }
733
734                 public bool HasExtensionMethodType {
735                         get {
736                                 if (Count == 0)
737                                         return false;
738
739                                 return FixedParameters [0].HasExtensionMethodModifier;
740                         }
741                 }
742
743                 public bool HasParams {
744                         get { return has_params; }
745                 }
746
747                 public bool IsEmpty {
748                         get { return parameters.Length == 0; }
749                 }
750
751                 public string ParameterDesc (int pos)
752                 {
753                         if (types == null || types [pos] == null)
754                                 return ((Parameter)FixedParameters [pos]).GetSignatureForError ();
755
756                         string type = TypeManager.CSharpName (types [pos]);
757                         if (FixedParameters [pos].HasExtensionMethodModifier)
758                                 return "this " + type;
759
760                         Parameter.Modifier mod = FixedParameters [pos].ModFlags & ~Parameter.Modifier.ARGLIST;
761                         if (mod == 0)
762                                 return type;
763
764                         return Parameter.GetModifierSignature (mod) + " " + type;
765                 }
766
767                 public Type[] Types {
768                         get { return types; }
769                         set { types = value; }
770                 }
771
772 #if MS_COMPATIBLE
773                 public AParametersCollection InflateTypes (Type[] genArguments, Type[] argTypes)
774                 {
775                         AParametersCollection p = (AParametersCollection) MemberwiseClone (); // Clone ();
776
777                         for (int i = 0; i < Count; ++i) {
778                                 if (types[i].IsGenericType) {
779                                         Type[] gen_arguments_open = new Type[types[i].GetGenericTypeDefinition ().GetGenericArguments ().Length];
780                                         Type[] gen_arguments = types[i].GetGenericArguments ();
781                                         for (int ii = 0; ii < gen_arguments_open.Length; ++ii) {
782                                                 if (gen_arguments[ii].IsGenericParameter) {
783                                                         Type t = argTypes[gen_arguments[ii].GenericParameterPosition];
784                                                         gen_arguments_open[ii] = t;
785                                                 } else
786                                                         gen_arguments_open[ii] = gen_arguments[ii];
787                                         }
788
789                                         p.types[i] = types[i].GetGenericTypeDefinition ().MakeGenericType (gen_arguments_open);
790                                         continue;
791                                 }
792
793                                 if (types[i].IsGenericParameter) {
794                                         Type gen_argument = argTypes[types[i].GenericParameterPosition];
795                                         p.types[i] = gen_argument;
796                                         continue;
797                                 }
798                         }
799
800                         return p;
801                 }
802 #endif
803         }
804
805         //
806         // A collection of imported or resolved parameters
807         //
808         public class ParametersImported : AParametersCollection
809         {
810                 ParametersImported (AParametersCollection param, Type[] types)
811                 {
812                         this.parameters = param.FixedParameters;
813                         this.types = types;
814                         has_arglist = param.HasArglist;
815                         has_params = param.HasParams;
816                 }
817
818                 ParametersImported (IParameterData [] parameters, Type [] types, MethodBase method, bool hasParams)
819                 {
820                         this.parameters = parameters;
821                         this.types = types;
822                         has_arglist = (method.CallingConvention & CallingConventions.VarArgs) != 0;
823                         if (has_arglist) {
824                                 this.parameters = new IParameterData [parameters.Length + 1];
825                                 parameters.CopyTo (this.parameters, 0);
826                                 this.parameters [parameters.Length] = new ArglistParameter (Location.Null);
827                                 this.types = new Type [types.Length + 1];
828                                 types.CopyTo (this.types, 0);
829                                 this.types [types.Length] = TypeManager.arg_iterator_type;
830                         }
831                         has_params = hasParams;
832                 }
833
834                 public ParametersImported (IParameterData [] param, Type[] types)
835                 {
836                         this.parameters = param;
837                         this.types = types;
838                 }
839
840                 public static AParametersCollection Create (MethodBase method)
841                 {
842                         return Create (method.GetParameters (), method);
843                 }
844
845                 //
846                 // Generic method parameters importer, param is shared between all instances
847                 //
848                 public static AParametersCollection Create (AParametersCollection param, MethodBase method)
849                 {
850                         if (param.IsEmpty)
851                                 return param;
852
853                         ParameterInfo [] pi = method.GetParameters ();
854                         Type [] types = new Type [pi.Length];
855                         for (int i = 0; i < types.Length; i++) {
856                                 Type t = pi [i].ParameterType;
857                                 if (t.IsByRef)
858                                         t = TypeManager.GetElementType (t);
859
860                                 types [i] = TypeManager.TypeToCoreType (t);
861                         }
862
863                         return new ParametersImported (param, types);
864                 }
865
866                 //
867                 // Imports SRE parameters
868                 //
869                 public static AParametersCollection Create (ParameterInfo [] pi, MethodBase method)
870                 {
871                         if (pi.Length == 0) {
872                                 if (method != null && (method.CallingConvention & CallingConventions.VarArgs) != 0)
873                                         return new ParametersImported (new IParameterData [0], Type.EmptyTypes, method, false);
874
875                                 return ParametersCompiled.EmptyReadOnlyParameters;
876                         }
877
878                         Type [] types = new Type [pi.Length];
879                         IParameterData [] par = new IParameterData [pi.Length];
880                         bool is_params = false;
881                         PredefinedAttribute extension_attr = PredefinedAttributes.Get.Extension;
882                         PredefinedAttribute param_attr = PredefinedAttributes.Get.ParamArray;
883                         for (int i = 0; i < types.Length; i++) {
884                                 types [i] = TypeManager.TypeToCoreType (pi [i].ParameterType);
885
886                                 ParameterInfo p = pi [i];
887                                 Parameter.Modifier mod = 0;
888                                 if (types [i].IsByRef) {
889                                         if ((p.Attributes & (ParameterAttributes.Out | ParameterAttributes.In)) == ParameterAttributes.Out)
890                                                 mod = Parameter.Modifier.OUT;
891                                         else
892                                                 mod = Parameter.Modifier.REF;
893
894                                         //
895                                         // Strip reference wrapping
896                                         //
897                                         types [i] = TypeManager.GetElementType (types [i]);
898                                 } else if (i == 0 && extension_attr.IsDefined && method != null && method.IsStatic &&
899                                 (method.DeclaringType.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute &&
900                                         method.IsDefined (extension_attr.Type, false)) {
901                                         mod = Parameter.Modifier.This;
902                                 } else if (i >= pi.Length - 2) {
903                                         if (types[i].IsArray) {
904                                                 if (p.IsDefined (param_attr.Type, false)) {
905                                                         mod = Parameter.Modifier.PARAMS;
906                                                         is_params = true;
907                                                 }
908                                         } else if (types [i] == TypeManager.runtime_argument_handle_type) {
909                                                 par [i] = new ArglistParameter (Location.Null);
910                                                 continue;
911                                         }
912                                 }
913
914                                 par [i] = new ParameterData (p.Name, mod);
915                         }
916
917                         return method != null ?
918                                 new ParametersImported (par, types, method, is_params) :
919                                 new ParametersImported (par, types);
920                 }
921         }
922
923         /// <summary>
924         ///   Represents the methods parameters
925         /// </summary>
926         public class ParametersCompiled : AParametersCollection
927         {
928                 public static readonly ParametersCompiled EmptyReadOnlyParameters = new ParametersCompiled ();
929                 
930                 // Used by C# 2.0 delegates
931                 public static readonly ParametersCompiled Undefined = new ParametersCompiled ();
932
933                 private ParametersCompiled ()
934                 {
935                         parameters = new Parameter [0];
936                         types = Type.EmptyTypes;
937                 }
938
939                 private ParametersCompiled (Parameter [] parameters, Type [] types)
940                 {
941                         this.parameters = parameters;
942                     this.types = types;
943                 }
944                 
945                 public ParametersCompiled (params Parameter[] parameters)
946                 {
947                         if (parameters == null)
948                                 throw new ArgumentException ("Use EmptyReadOnlyParameters");
949
950                         this.parameters = parameters;
951                         int count = parameters.Length;
952
953                         if (count == 0)
954                                 return;
955
956                         if (count == 1) {
957                                 has_params = (parameters [0].ModFlags & Parameter.Modifier.PARAMS) != 0;
958                                 return;
959                         }
960
961                         for (int i = 0; i < count; i++){
962                                 string base_name = parameters [i].Name;
963                                 has_params |= (parameters [i].ModFlags & Parameter.Modifier.PARAMS) != 0;
964
965                                 for (int j = i + 1; j < count; j++){
966                                         if (base_name != parameters [j].Name)
967                                                 continue;
968
969                                         ErrorDuplicateName (parameters [i]);
970                                         i = j;
971                                 }
972                         }
973                 }
974
975                 public ParametersCompiled (Parameter [] parameters, bool has_arglist) :
976                         this (parameters)
977                 {
978                         this.has_arglist = has_arglist;
979                 }
980                 
981                 public static ParametersCompiled CreateFullyResolved (Parameter p, Type type)
982                 {
983                         return new ParametersCompiled (new Parameter [] { p }, new Type [] { type });
984                 }
985                 
986                 public static ParametersCompiled CreateFullyResolved (Parameter[] parameters, Type[] types)
987                 {
988                         return new ParametersCompiled (parameters, types);
989                 }
990
991                 public static ParametersCompiled MergeGenerated (ParametersCompiled userParams, bool checkConflicts, Parameter compilerParams, Type compilerTypes)
992                 {
993                         return MergeGenerated (userParams, checkConflicts,
994                                 new Parameter [] { compilerParams },
995                                 new Type [] { compilerTypes });
996                 }
997
998                 //
999                 // Use this method when you merge compiler generated parameters with user parameters
1000                 //
1001                 public static ParametersCompiled MergeGenerated (ParametersCompiled userParams, bool checkConflicts, Parameter[] compilerParams, Type[] compilerTypes)
1002                 {
1003                         Parameter[] all_params = new Parameter [userParams.Count + compilerParams.Length];
1004                         userParams.FixedParameters.CopyTo(all_params, 0);
1005
1006                         Type [] all_types;
1007                         if (userParams.types != null) {
1008                                 all_types = new Type [all_params.Length];
1009                                 userParams.Types.CopyTo (all_types, 0);
1010                         } else {
1011                                 all_types = null;
1012                         }
1013
1014                         int last_filled = userParams.Count;
1015                         int index = 0;
1016                         foreach (Parameter p in compilerParams) {
1017                                 for (int i = 0; i < last_filled; ++i) {
1018                                         while (p.Name == all_params [i].Name) {
1019                                                 if (checkConflicts && i < userParams.Count) {
1020                                                         Report.Error (316, userParams [i].Location,
1021                                                                 "The parameter name `{0}' conflicts with a compiler generated name", p.Name);
1022                                                 }
1023                                                 p.Name = '_' + p.Name;
1024                                         }
1025                                 }
1026                                 all_params [last_filled] = p;
1027                                 if (all_types != null)
1028                                         all_types [last_filled] = compilerTypes [index++];
1029                                 ++last_filled;
1030                         }
1031                         
1032                         ParametersCompiled parameters = new ParametersCompiled (all_params, all_types);
1033                         parameters.has_params = userParams.has_params;
1034                         return parameters;
1035                 }
1036
1037                 protected virtual void ErrorDuplicateName (Parameter p)
1038                 {
1039                         Report.Error (100, p.Location, "The parameter name `{0}' is a duplicate", p.Name);
1040                 }
1041
1042                 /// <summary>
1043                 ///    Returns the parameter information based on the name
1044                 /// </summary>
1045                 public int GetParameterIndexByName (string name)
1046                 {
1047                         for (int idx = 0; idx < Count; ++idx) {
1048                                 if (parameters [idx].Name == name)
1049                                         return idx;
1050                         }
1051
1052                         return -1;
1053                 }
1054
1055                 public bool Resolve (IResolveContext ec)
1056                 {
1057                         if (types != null)
1058                                 return true;
1059                         
1060                         types = new Type [Count];
1061                         
1062                         bool ok = true;
1063                         Parameter p;
1064                         for (int i = 0; i < FixedParameters.Length; ++i) {
1065                                 p = this [i];
1066                                 Type t = p.Resolve (ec);
1067                                 if (t == null) {
1068                                         ok = false;
1069                                         continue;
1070                                 }
1071
1072                                 types [i] = t;
1073                         }
1074
1075                         return ok;
1076                 }
1077
1078                 public void ResolveVariable ()
1079                 {
1080                         for (int i = 0; i < FixedParameters.Length; ++i) {
1081                                 this [i].ResolveVariable (i);
1082                         }
1083                 }
1084
1085                 public CallingConventions CallingConvention
1086                 {
1087                         get {
1088                                 if (HasArglist)
1089                                         return CallingConventions.VarArgs;
1090                                 else
1091                                         return CallingConventions.Standard;
1092                         }
1093                 }
1094
1095                 // Define each type attribute (in/out/ref) and
1096                 // the argument names.
1097                 public void ApplyAttributes (MethodBase builder)
1098                 {
1099                         if (Count == 0)
1100                                 return;
1101
1102                         MethodBuilder mb = builder as MethodBuilder;
1103                         ConstructorBuilder cb = builder as ConstructorBuilder;
1104
1105                         for (int i = 0; i < Count; i++) {
1106                                 this [i].ApplyAttributes (mb, cb, i + 1);
1107                         }
1108                 }
1109
1110                 public void VerifyClsCompliance ()
1111                 {
1112                         foreach (Parameter p in FixedParameters)
1113                                 p.IsClsCompliant ();
1114                 }
1115
1116                 public Parameter this [int pos] {
1117                         get { return (Parameter) parameters [pos]; }
1118                 }
1119
1120                 public Expression CreateExpressionTree (EmitContext ec, Location loc)
1121                 {
1122                         ArrayList initializers = new ArrayList (Count);
1123                         foreach (Parameter p in FixedParameters) {
1124                                 //
1125                                 // Each parameter expression is stored to local variable
1126                                 // to save some memory when referenced later.
1127                                 //
1128                                 StatementExpression se = new StatementExpression (p.CreateExpressionTreeVariable (ec));
1129                                 if (se.Resolve (ec))
1130                                         ec.CurrentBlock.AddScopeStatement (se);
1131                                 
1132                                 initializers.Add (p.ExpressionTreeVariableReference ());
1133                         }
1134
1135                         return new ArrayCreation (
1136                                 Parameter.ResolveParameterExpressionType (ec, loc),
1137                                 "[]", initializers, loc);
1138                 }
1139
1140                 public ParametersCompiled Clone ()
1141                 {
1142                         ParametersCompiled p = (ParametersCompiled) MemberwiseClone ();
1143
1144                         p.parameters = new IParameterData [parameters.Length];
1145                         for (int i = 0; i < Count; ++i)
1146                                 p.parameters [i] = this [i].Clone ();
1147
1148                         return p;
1149                 }
1150         }
1151 }