* src/**/*: Flush; syncs to DbLinq r1053. Adds
[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, "");                 
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                 protected Type parameter_type;
249                 public readonly Location Location;
250                 int idx;
251                 public bool HasAddressTaken;
252
253                 IResolveContext resolve_context;
254                 LocalVariableReference expr_tree_variable;
255                 static TypeExpr parameter_expr_tree_type;
256
257                 public HoistedVariable HoistedVariableReference;
258
259                 public Parameter (FullNamedExpression type, string name, Modifier mod, Attributes attrs, Location loc)
260                         : base (attrs)
261                 {
262                         if (type == TypeManager.system_void_expr)
263                                 Report.Error (1536, loc, "Invalid parameter type `void'");
264
265                         this.name = name;
266                         modFlags = mod;
267                         Location = loc;
268                         TypeName = type;
269                 }
270
271                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
272                 {
273                         if (a.Type == pa.In && ModFlags == Modifier.OUT) {
274                                 Report.Error (36, a.Location, "An out parameter cannot have the `In' attribute");
275                                 return;
276                         }
277
278                         if (a.Type == pa.ParamArray) {
279                                 Report.Error (674, a.Location, "Do not use `System.ParamArrayAttribute'. Use the `params' keyword instead");
280                                 return;
281                         }
282
283                         if (a.Type == PredefinedAttributes.Get.Out && (ModFlags & Modifier.REF) == Modifier.REF &&
284                             !OptAttributes.Contains (pa.In)) {
285                                 Report.Error (662, a.Location,
286                                         "Cannot specify only `Out' attribute on a ref parameter. Use both `In' and `Out' attributes or neither");
287                                 return;
288                         }
289
290                         if (a.Type == pa.CLSCompliant) {
291                                 Report.Warning (3022, 1, a.Location, "CLSCompliant attribute has no meaning when applied to parameters. Try putting it on the method instead");
292                         }
293
294                         // TypeManager.default_parameter_value_attribute_type is null if !NET_2_0, or if System.dll is not referenced
295                         if (a.Type == pa.DefaultParameterValue) {
296                                 object val = a.GetParameterDefaultValue ();
297                                 if (val != null) {
298                                         Type t = val.GetType ();
299                                         if (t.IsArray || TypeManager.IsSubclassOf (t, TypeManager.type_type)) {
300                                                 if (parameter_type == TypeManager.object_type) {
301                                                         if (!t.IsArray)
302                                                                 t = TypeManager.type_type;
303
304                                                         Report.Error (1910, a.Location, "Argument of type `{0}' is not applicable for the DefaultValue attribute",
305                                                                 TypeManager.CSharpName (t));
306                                                 } else {
307                                                         Report.Error (1909, a.Location, "The DefaultValue attribute is not applicable on parameters of type `{0}'",
308                                                                 TypeManager.CSharpName (parameter_type)); ;
309                                                 }
310                                                 return;
311                                         }
312                                 }
313
314                                 if (parameter_type == TypeManager.object_type ||
315                                     (val == null && !TypeManager.IsGenericParameter (parameter_type) && TypeManager.IsReferenceType (parameter_type)) ||
316                                     (val != null && TypeManager.TypeToCoreType (val.GetType ()) == parameter_type))
317                                         builder.SetConstant (val);
318                                 else
319                                         Report.Error (1908, a.Location, "The type of the default value should match the type of the parameter");
320                                 return;
321                         }
322
323                         base.ApplyAttributeBuilder (a, cb, pa);
324                 }
325                 
326                 public virtual bool CheckAccessibility (InterfaceMemberBase member)
327                 {
328                         if (parameter_type == null || TypeManager.IsGenericParameter (parameter_type))
329                                 return true;
330
331                         return member.IsAccessibleAs (parameter_type);
332                 }
333
334                 public override IResolveContext ResolveContext {
335                         get {
336                                 return resolve_context;
337                         }
338                 }
339
340                 // <summary>
341                 //   Resolve is used in method definitions
342                 // </summary>
343                 public virtual Type Resolve (IResolveContext ec)
344                 {
345                         // HACK: to resolve attributes correctly
346                         this.resolve_context = ec;
347
348                         if (parameter_type != null)
349                                 return parameter_type;
350
351                         TypeExpr texpr = TypeName.ResolveAsTypeTerminal (ec, false);
352                         if (texpr == null)
353                                 return null;
354
355                         parameter_type = texpr.Type;
356
357                         if ((modFlags & Parameter.Modifier.ISBYREF) != 0 &&
358                                 TypeManager.IsSpecialType (parameter_type)) {
359                                 Report.Error (1601, Location, "Method or delegate parameter cannot be of type `{0}'",
360                                         GetSignatureForError ());
361                                 return null;
362                         }
363
364 #if GMCS_SOURCE
365                         if (parameter_type.IsGenericParameter) {
366                                 AbstractPropertyEventMethod accessor = ec as AbstractPropertyEventMethod;
367                                 if (accessor == null || !accessor.IsDummy) {
368                                         if ((parameter_type.GenericParameterAttributes & GenericParameterAttributes.Covariant) != 0) {
369                                                 Report.Error (-38, Location, "Covariant type parameters cannot be used as method parameters");
370                                                 return null;
371                                         } else if ((ModFlags & Modifier.ISBYREF) != 0 &&
372                                                    (parameter_type.GenericParameterAttributes & GenericParameterAttributes.Contravariant) != 0) {
373                                                 Report.Error (-37, Location, "Contravariant type parameters cannot be used in output positions");
374                                                 return null;
375                                         }
376                                 }
377                                 return parameter_type;
378                         }
379 #endif
380
381                         if ((parameter_type.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) {
382                                 Report.Error (721, Location, "`{0}': static types cannot be used as parameters",
383                                         texpr.GetSignatureForError ());
384                                 return parameter_type;
385                         }
386
387                         if ((modFlags & Modifier.This) != 0 && parameter_type.IsPointer) {
388                                 Report.Error (1103, Location, "The type of extension method cannot be `{0}'",
389                                         TypeManager.CSharpName (parameter_type));
390                         }
391
392                         return parameter_type;
393                 }
394
395                 public void ResolveVariable (int idx)
396                 {
397                         this.idx = idx;
398                 }
399
400                 public bool HasExtensionMethodModifier {
401                         get { return (modFlags & Modifier.This) != 0; }
402                 }
403
404                 public Modifier ModFlags {
405                         get { return modFlags & ~Modifier.This; }
406                 }
407
408                 public string Name {
409                         get { return name; }
410                         set { name = value; }
411                 }
412
413                 ParameterAttributes Attributes {
414                         get { return ParametersCompiled.GetParameterAttribute (modFlags); }
415                 }
416
417                 public override AttributeTargets AttributeTargets {
418                         get {
419                                 return AttributeTargets.Parameter;
420                         }
421                 }
422
423                 public virtual string GetSignatureForError ()
424                 {
425                         string type_name;
426                         if (parameter_type != null)
427                                 type_name = TypeManager.CSharpName (parameter_type);
428                         else
429                                 type_name = TypeName.GetSignatureForError ();
430
431                         string mod = GetModifierSignature (modFlags);
432                         if (mod.Length > 0)
433                                 return String.Concat (mod, " ", type_name);
434
435                         return type_name;
436                 }
437
438                 public static string GetModifierSignature (Modifier mod)
439                 {
440                         switch (mod) {
441                         case Modifier.OUT:
442                                 return "out";
443                         case Modifier.PARAMS:
444                                 return "params";
445                         case Modifier.REF:
446                                 return "ref";
447                         case Modifier.This:
448                                 return "this";
449                         default:
450                                 return "";
451                         }
452                 }
453
454                 public void IsClsCompliant ()
455                 {
456                         if (AttributeTester.IsClsCompliant (parameter_type))
457                                 return;
458
459                         Report.Warning (3001, 1, Location, "Argument type `{0}' is not CLS-compliant", GetSignatureForError ());
460                 }
461
462                 public virtual void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
463                 {
464                         if (mb == null)
465                                 builder = cb.DefineParameter (index, Attributes, Name);
466                         else
467                                 builder = mb.DefineParameter (index, Attributes, Name);
468
469                         if (OptAttributes != null)
470                                 OptAttributes.Emit ();
471                 }
472
473                 public override string[] ValidAttributeTargets {
474                         get {
475                                 return attribute_targets;
476                         }
477                 }
478
479                 public Parameter Clone ()
480                 {
481                         Parameter p = (Parameter) MemberwiseClone ();
482                         if (attributes != null) {
483                                 p.attributes = attributes.Clone ();
484                                 p.attributes.AttachTo (p);
485                         }
486
487                         return p;
488                 }
489
490                 public ExpressionStatement CreateExpressionTreeVariable (EmitContext ec)
491                 {
492                         //
493                         // A parameter is not hoisted when used directly as ET
494                         //
495                         HoistedVariableReference = null;
496
497                         if ((modFlags & Modifier.ISBYREF) != 0)
498                                 Report.Error (1951, Location, "An expression tree parameter cannot use `ref' or `out' modifier");
499
500                         LocalInfo variable = ec.CurrentBlock.AddTemporaryVariable (
501                                 ResolveParameterExpressionType (ec, Location), Location);
502                         variable.Resolve (ec);
503
504                         expr_tree_variable = new LocalVariableReference (
505                                 ec.CurrentBlock, variable.Name, Location, variable, false);
506
507                         ArrayList arguments = new ArrayList (2);
508                         arguments.Add (new Argument (new TypeOf (
509                                 new TypeExpression (parameter_type, Location), Location)));
510                         arguments.Add (new Argument (new StringConstant (Name, Location)));
511                         return new SimpleAssign (ExpressionTreeVariableReference (),
512                                 Expression.CreateExpressionFactoryCall ("Parameter", null, arguments, Location));
513                 }
514
515                 public void Emit (EmitContext ec)
516                 {
517                         int arg_idx = idx;
518                         if (!ec.IsStatic)
519                                 arg_idx++;
520
521                         ParameterReference.EmitLdArg (ec.ig, arg_idx);
522                 }
523
524                 public void EmitAssign (EmitContext ec)
525                 {
526                         int arg_idx = idx;
527                         if (!ec.IsStatic)
528                                 arg_idx++;
529
530                         if (arg_idx <= 255)
531                                 ec.ig.Emit (OpCodes.Starg_S, (byte) arg_idx);
532                         else
533                                 ec.ig.Emit (OpCodes.Starg, arg_idx);
534                 }
535
536                 public void EmitAddressOf (EmitContext ec)
537                 {
538                         int arg_idx = idx;
539
540                         if (!ec.IsStatic)
541                                 arg_idx++;
542
543                         bool is_ref = (ModFlags & Modifier.ISBYREF) != 0;
544                         if (is_ref) {
545                                 ParameterReference.EmitLdArg (ec.ig, arg_idx);
546                         } else {
547                                 if (arg_idx <= 255)
548                                         ec.ig.Emit (OpCodes.Ldarga_S, (byte) arg_idx);
549                                 else
550                                         ec.ig.Emit (OpCodes.Ldarga, arg_idx);
551                         }
552                 }
553
554                 public Expression ExpressionTreeVariableReference ()
555                 {
556                         return expr_tree_variable;
557                 }
558
559                 //
560                 // System.Linq.Expressions.ParameterExpression type
561                 //
562                 public static TypeExpr ResolveParameterExpressionType (EmitContext ec, Location location)
563                 {
564                         if (parameter_expr_tree_type != null)
565                                 return parameter_expr_tree_type;
566
567                         Type p_type = TypeManager.parameter_expression_type;
568                         if (p_type == null) {
569                                 p_type = TypeManager.CoreLookupType ("System.Linq.Expressions", "ParameterExpression", Kind.Class, true);
570                                 TypeManager.parameter_expression_type = p_type;
571                         }
572
573                         parameter_expr_tree_type = new TypeExpression (p_type, location).
574                                 ResolveAsTypeTerminal (ec, false);
575
576                         return parameter_expr_tree_type;
577                 }
578         }
579
580         //
581         // Imported or resolved parameter information
582         //
583         public class ParameterData : IParameterData
584         {
585                 readonly string name;
586                 readonly Parameter.Modifier modifiers;
587
588                 public ParameterData (string name, Parameter.Modifier modifiers)
589                 {
590                         this.name = name;
591                         this.modifiers = modifiers;
592                 }
593
594                 #region IParameterData Members
595
596                 public bool HasExtensionMethodModifier {
597                         get { return (modifiers & Parameter.Modifier.This) != 0; }
598                 }
599
600                 public Parameter.Modifier ModFlags {
601                         get { return modifiers & ~Parameter.Modifier.This; }
602                 }
603
604                 public string Name {
605                         get { return name; }
606                 }
607
608                 #endregion
609         }
610
611         public abstract class AParametersCollection
612         {
613                 protected bool has_arglist;
614                 protected bool has_params;
615
616                 // Null object pattern
617                 protected IParameterData [] parameters;
618                 protected Type [] types;
619
620                 public int Count {
621                         get { return parameters.Length; }
622                 }
623
624                 public Type ExtensionMethodType {
625                         get {
626                                 if (Count == 0)
627                                         return null;
628
629                                 return FixedParameters [0].HasExtensionMethodModifier ?
630                                         types [0] : null;
631                         }
632                 }
633
634                 public IParameterData [] FixedParameters {
635                         get {
636                                 return parameters;
637                         }
638                 }
639
640                 public static ParameterAttributes GetParameterAttribute (Parameter.Modifier modFlags)
641                 {
642                         return (modFlags & Parameter.Modifier.OUT) == Parameter.Modifier.OUT ?
643                                 ParameterAttributes.Out : ParameterAttributes.None;
644                 }
645
646                 public Type [] GetEmitTypes ()
647                 {
648                         Type [] types = null;
649                         if (has_arglist) {
650                                 if (Count == 1)
651                                         return Type.EmptyTypes;
652
653                                 types = new Type [Count - 1];
654                                 Array.Copy (Types, types, types.Length);
655                         }
656
657                         for (int i = 0; i < Count; ++i) {
658                                 if ((FixedParameters [i].ModFlags & Parameter.Modifier.ISBYREF) == 0)
659                                         continue;
660
661                                 if (types == null)
662                                         types = (Type []) Types.Clone ();
663
664                                 types [i] = TypeManager.GetReferenceType (types [i]);
665                         }
666
667                         if (types == null)
668                                 types = Types;
669
670                         return types;
671                 }
672
673                 public string GetSignatureForError ()
674                 {
675                         StringBuilder sb = new StringBuilder ("(");
676                         for (int i = 0; i < Count; ++i) {
677                                 if (i != 0)
678                                         sb.Append (", ");
679                                 sb.Append (ParameterDesc (i));
680                         }
681                         sb.Append (')');
682                         return sb.ToString ();
683                 }
684
685                 public bool HasArglist {
686                         get { return has_arglist; }
687                 }
688
689                 public bool HasExtensionMethodType {
690                         get {
691                                 if (Count == 0)
692                                         return false;
693
694                                 return FixedParameters [0].HasExtensionMethodModifier;
695                         }
696                 }
697
698                 public bool HasParams {
699                         get { return has_params; }
700                 }
701
702                 public bool IsEmpty {
703                         get { return parameters.Length == 0; }
704                 }
705
706                 public string ParameterDesc (int pos)
707                 {
708                         if (types == null || types [pos] == null)
709                                 return ((Parameter)FixedParameters [pos]).GetSignatureForError ();
710
711                         string type = TypeManager.CSharpName (types [pos]);
712                         if (FixedParameters [pos].HasExtensionMethodModifier)
713                                 return "this " + type;
714
715                         Parameter.Modifier mod = FixedParameters [pos].ModFlags & ~Parameter.Modifier.ARGLIST;
716                         if (mod == 0)
717                                 return type;
718
719                         return Parameter.GetModifierSignature (mod) + " " + type;
720                 }
721
722                 public Type[] Types {
723                         get { return types; }
724                         set { types = value; }
725                 }
726
727 #if MS_COMPATIBLE
728                 public AParametersCollection InflateTypes (Type[] genArguments, Type[] argTypes)
729                 {
730                         AParametersCollection p = (AParametersCollection) MemberwiseClone (); // Clone ();
731
732                         for (int i = 0; i < Count; ++i) {
733                                 if (types[i].IsGenericType) {
734                                         Type[] gen_arguments_open = new Type[types[i].GetGenericTypeDefinition ().GetGenericArguments ().Length];
735                                         Type[] gen_arguments = types[i].GetGenericArguments ();
736                                         for (int ii = 0; ii < gen_arguments_open.Length; ++ii) {
737                                                 if (gen_arguments[ii].IsGenericParameter) {
738                                                         Type t = argTypes[gen_arguments[ii].GenericParameterPosition];
739                                                         gen_arguments_open[ii] = t;
740                                                 } else
741                                                         gen_arguments_open[ii] = gen_arguments[ii];
742                                         }
743
744                                         p.types[i] = types[i].GetGenericTypeDefinition ().MakeGenericType (gen_arguments_open);
745                                         continue;
746                                 }
747
748                                 if (types[i].IsGenericParameter) {
749                                         Type gen_argument = argTypes[types[i].GenericParameterPosition];
750                                         p.types[i] = gen_argument;
751                                         continue;
752                                 }
753                         }
754
755                         return p;
756                 }
757 #endif
758         }
759
760         //
761         // A collection of imported or resolved parameters
762         //
763         public class ParametersImported : AParametersCollection
764         {
765                 ParametersImported (AParametersCollection param, Type[] types)
766                 {
767                         this.parameters = param.FixedParameters;
768                         this.types = types;
769                         has_arglist = param.HasArglist;
770                         has_params = param.HasParams;
771                 }
772
773                 ParametersImported (IParameterData [] parameters, Type [] types, MethodBase method, bool hasParams)
774                 {
775                         this.parameters = parameters;
776                         this.types = types;
777                         has_arglist = (method.CallingConvention & CallingConventions.VarArgs) != 0;
778                         if (has_arglist) {
779                                 this.parameters = new IParameterData [parameters.Length + 1];
780                                 parameters.CopyTo (this.parameters, 0);
781                                 this.parameters [parameters.Length] = new ArglistParameter (Location.Null);
782                                 this.types = new Type [types.Length + 1];
783                                 types.CopyTo (this.types, 0);
784                                 this.types [types.Length] = TypeManager.arg_iterator_type;
785                         }
786                         has_params = hasParams;
787                 }
788
789                 public ParametersImported (IParameterData [] param, Type[] types)
790                 {
791                         this.parameters = param;
792                         this.types = types;
793                 }
794
795                 public static AParametersCollection Create (MethodBase method)
796                 {
797                         return Create (method.GetParameters (), method);
798                 }
799
800                 //
801                 // Generic method parameters importer, param is shared between all instances
802                 //
803                 public static AParametersCollection Create (AParametersCollection param, MethodBase method)
804                 {
805                         if (param.IsEmpty)
806                                 return param;
807
808                         ParameterInfo [] pi = method.GetParameters ();
809                         Type [] types = new Type [pi.Length];
810                         for (int i = 0; i < types.Length; i++) {
811                                 Type t = pi [i].ParameterType;
812                                 if (t.IsByRef)
813                                         t = TypeManager.GetElementType (t);
814
815                                 types [i] = TypeManager.TypeToCoreType (t);
816                         }
817
818                         return new ParametersImported (param, types);
819                 }
820
821                 //
822                 // Imports SRE parameters
823                 //
824                 public static AParametersCollection Create (ParameterInfo [] pi, MethodBase method)
825                 {
826                         if (pi.Length == 0) {
827                                 if (method != null && (method.CallingConvention & CallingConventions.VarArgs) != 0)
828                                         return new ParametersImported (new IParameterData [0], Type.EmptyTypes, method, false);
829
830                                 return ParametersCompiled.EmptyReadOnlyParameters;
831                         }
832
833                         Type [] types = new Type [pi.Length];
834                         IParameterData [] par = new IParameterData [pi.Length];
835                         bool is_params = false;
836                         PredefinedAttribute extension_attr = PredefinedAttributes.Get.Extension;
837                         PredefinedAttribute param_attr = PredefinedAttributes.Get.ParamArray;
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 && extension_attr.IsDefined && method != null && method.IsStatic &&
854                                 (method.DeclaringType.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute &&
855                                         method.IsDefined (extension_attr.Type, false)) {
856                                         mod = Parameter.Modifier.This;
857                                 } else if (i >= pi.Length - 2 && types [i].IsArray) {
858                                         if (p.IsDefined (param_attr.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 ParametersImported (par, types, method, is_params) :
869                                 new ParametersImported (par, types);
870                 }
871         }
872
873         /// <summary>
874         ///   Represents the methods parameters
875         /// </summary>
876         public class ParametersCompiled : AParametersCollection
877         {
878                 public static readonly ParametersCompiled EmptyReadOnlyParameters = new ParametersCompiled ();
879                 
880                 // Used by C# 2.0 delegates
881                 public static readonly ParametersCompiled Undefined = new ParametersCompiled ();
882
883                 private ParametersCompiled ()
884                 {
885                         parameters = new Parameter [0];
886                         types = Type.EmptyTypes;
887                 }
888
889                 private ParametersCompiled (Parameter [] parameters, Type [] types)
890                 {
891                         this.parameters = parameters;
892                     this.types = types;
893                 }
894                 
895                 public ParametersCompiled (params Parameter[] parameters)
896                 {
897                         if (parameters == null)
898                                 throw new ArgumentException ("Use EmptyReadOnlyParameters");
899
900                         this.parameters = parameters;
901                         int count = parameters.Length;
902
903                         if (count == 0)
904                                 return;
905
906                         if (count == 1) {
907                                 has_params = (parameters [0].ModFlags & Parameter.Modifier.PARAMS) != 0;
908                                 return;
909                         }
910
911                         for (int i = 0; i < count; i++){
912                                 string base_name = parameters [i].Name;
913                                 has_params |= (parameters [i].ModFlags & Parameter.Modifier.PARAMS) != 0;
914
915                                 for (int j = i + 1; j < count; j++){
916                                         if (base_name != parameters [j].Name)
917                                                 continue;
918
919                                         ErrorDuplicateName (parameters [i]);
920                                         i = j;
921                                 }
922                         }
923                 }
924
925                 public ParametersCompiled (Parameter [] parameters, bool has_arglist) :
926                         this (parameters)
927                 {
928                         this.has_arglist = has_arglist;
929                 }
930                 
931                 public static ParametersCompiled CreateFullyResolved (Parameter p, Type type)
932                 {
933                         return new ParametersCompiled (new Parameter [] { p }, new Type [] { type });
934                 }
935                 
936                 public static ParametersCompiled CreateFullyResolved (Parameter[] parameters, Type[] types)
937                 {
938                         return new ParametersCompiled (parameters, types);
939                 }
940
941                 public static ParametersCompiled MergeGenerated (ParametersCompiled userParams, bool checkConflicts, Parameter compilerParams, Type compilerTypes)
942                 {
943                         return MergeGenerated (userParams, checkConflicts,
944                                 new Parameter [] { compilerParams },
945                                 new Type [] { compilerTypes });
946                 }
947
948                 //
949                 // Use this method when you merge compiler generated parameters with user parameters
950                 //
951                 public static ParametersCompiled MergeGenerated (ParametersCompiled userParams, bool checkConflicts, Parameter[] compilerParams, Type[] compilerTypes)
952                 {
953                         Parameter[] all_params = new Parameter [userParams.Count + compilerParams.Length];
954                         userParams.FixedParameters.CopyTo(all_params, 0);
955
956                         Type [] all_types;
957                         if (userParams.types != null) {
958                                 all_types = new Type [all_params.Length];
959                                 userParams.Types.CopyTo (all_types, 0);
960                         } else {
961                                 all_types = null;
962                         }
963
964                         int last_filled = userParams.Count;
965                         int index = 0;
966                         foreach (Parameter p in compilerParams) {
967                                 for (int i = 0; i < last_filled; ++i) {
968                                         while (p.Name == all_params [i].Name) {
969                                                 if (checkConflicts && i < userParams.Count) {
970                                                         Report.Error (316, userParams [i].Location,
971                                                                 "The parameter name `{0}' conflicts with a compiler generated name", p.Name);
972                                                 }
973                                                 p.Name = '_' + p.Name;
974                                         }
975                                 }
976                                 all_params [last_filled] = p;
977                                 if (all_types != null)
978                                         all_types [last_filled] = compilerTypes [index++];
979                                 ++last_filled;
980                         }
981                         
982                         ParametersCompiled parameters = new ParametersCompiled (all_params, all_types);
983                         parameters.has_params = userParams.has_params;
984                         return parameters;
985                 }
986
987                 protected virtual void ErrorDuplicateName (Parameter p)
988                 {
989                         Report.Error (100, p.Location, "The parameter name `{0}' is a duplicate", p.Name);
990                 }
991
992                 /// <summary>
993                 ///    Returns the parameter information based on the name
994                 /// </summary>
995                 public int GetParameterIndexByName (string name)
996                 {
997                         for (int idx = 0; idx < Count; ++idx) {
998                                 if (parameters [idx].Name == name)
999                                         return idx;
1000                         }
1001
1002                         return -1;
1003                 }
1004
1005                 public bool Resolve (IResolveContext ec)
1006                 {
1007                         if (types != null)
1008                                 return true;
1009                         
1010                         types = new Type [Count];
1011                         
1012                         bool ok = true;
1013                         Parameter p;
1014                         for (int i = 0; i < FixedParameters.Length; ++i) {
1015                                 p = this [i];
1016                                 Type t = p.Resolve (ec);
1017                                 if (t == null) {
1018                                         ok = false;
1019                                         continue;
1020                                 }
1021
1022                                 types [i] = t;
1023                         }
1024
1025                         return ok;
1026                 }
1027
1028                 public void ResolveVariable ()
1029                 {
1030                         for (int i = 0; i < FixedParameters.Length; ++i) {
1031                                 this [i].ResolveVariable (i);
1032                         }
1033                 }
1034
1035                 public CallingConventions CallingConvention
1036                 {
1037                         get {
1038                                 if (HasArglist)
1039                                         return CallingConventions.VarArgs;
1040                                 else
1041                                         return CallingConventions.Standard;
1042                         }
1043                 }
1044
1045                 // Define each type attribute (in/out/ref) and
1046                 // the argument names.
1047                 public void ApplyAttributes (MethodBase builder)
1048                 {
1049                         if (Count == 0)
1050                                 return;
1051
1052                         MethodBuilder mb = builder as MethodBuilder;
1053                         ConstructorBuilder cb = builder as ConstructorBuilder;
1054
1055                         for (int i = 0; i < Count; i++) {
1056                                 this [i].ApplyAttributes (mb, cb, i + 1);
1057                         }
1058                 }
1059
1060                 public void VerifyClsCompliance ()
1061                 {
1062                         foreach (Parameter p in FixedParameters)
1063                                 p.IsClsCompliant ();
1064                 }
1065
1066                 public Parameter this [int pos] {
1067                         get { return (Parameter) parameters [pos]; }
1068                 }
1069
1070                 public Expression CreateExpressionTree (EmitContext ec, Location loc)
1071                 {
1072                         ArrayList initializers = new ArrayList (Count);
1073                         foreach (Parameter p in FixedParameters) {
1074                                 //
1075                                 // Each parameter expression is stored to local variable
1076                                 // to save some memory when referenced later.
1077                                 //
1078                                 StatementExpression se = new StatementExpression (p.CreateExpressionTreeVariable (ec));
1079                                 if (se.Resolve (ec))
1080                                         ec.CurrentBlock.AddScopeStatement (se);
1081                                 
1082                                 initializers.Add (p.ExpressionTreeVariableReference ());
1083                         }
1084
1085                         return new ArrayCreation (
1086                                 Parameter.ResolveParameterExpressionType (ec, loc),
1087                                 "[]", initializers, loc);
1088                 }
1089
1090                 public ParametersCompiled Clone ()
1091                 {
1092                         ParametersCompiled p = (ParametersCompiled) MemberwiseClone ();
1093
1094                         p.parameters = new IParameterData [parameters.Length];
1095                         for (int i = 0; i < Count; ++i)
1096                                 p.parameters [i] = this [i].Clone ();
1097
1098                         return p;
1099                 }
1100         }
1101 }