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