Ensure that we only reflect into monotouch if the type exists.
[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 using System.Linq;
18
19 namespace Mono.CSharp {
20
21         /// <summary>
22         ///   Abstract Base class for parameters of a method.
23         /// </summary>
24         public abstract class ParameterBase : Attributable
25         {
26                 protected ParameterBuilder builder;
27
28                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
29                 {
30 #if false
31                         if (a.Type == pa.MarshalAs) {
32                                 UnmanagedMarshal marshal = a.GetMarshal (this);
33                                 if (marshal != null) {
34                                         builder.SetMarshal (marshal);
35                                 }
36                                 return;
37                         }
38 #endif
39                         if (a.HasSecurityAttribute) {
40                                 a.Error_InvalidSecurityParent ();
41                                 return;
42                         }
43
44                         if (a.Type == pa.Dynamic) {
45                                 a.Error_MisusedDynamicAttribute ();
46                                 return;
47                         }
48
49                         builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
50                 }
51
52                 public ParameterBuilder Builder {
53                         get {
54                                 return builder;
55                         }
56                 }
57
58                 public override bool IsClsComplianceRequired()
59                 {
60                         return false;
61                 }
62         }
63
64         /// <summary>
65         /// Class for applying custom attributes on the return type
66         /// </summary>
67         public class ReturnParameter : ParameterBase
68         {
69                 MemberCore method;
70
71                 // TODO: merge method and mb
72                 public ReturnParameter (MemberCore method, MethodBuilder mb, Location location)
73                 {
74                         this.method = method;
75                         try {
76                                 builder = mb.DefineParameter (0, ParameterAttributes.None, "");                 
77                         }
78                         catch (ArgumentOutOfRangeException) {
79                                 method.Compiler.Report.RuntimeMissingSupport (location, "custom attributes on the return type");
80                         }
81                 }
82
83                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
84                 {
85                         if (a.Type == pa.CLSCompliant) {
86                                 method.Compiler.Report.Warning (3023, 1, a.Location,
87                                         "CLSCompliant attribute has no meaning when applied to return types. Try putting it on the method instead");
88                         }
89
90                         // This occurs after Warning -28
91                         if (builder == null)
92                                 return;
93
94                         base.ApplyAttributeBuilder (a, ctor, cdata, pa);
95                 }
96
97                 public override AttributeTargets AttributeTargets {
98                         get {
99                                 return AttributeTargets.ReturnValue;
100                         }
101                 }
102
103                 /// <summary>
104                 /// Is never called
105                 /// </summary>
106                 public override string[] ValidAttributeTargets {
107                         get {
108                                 return null;
109                         }
110                 }
111         }
112
113         /// <summary>
114         /// Class for applying custom attributes on the implicit parameter type
115         /// of the 'set' method in properties, and the 'add' and 'remove' methods in events.
116         /// </summary>
117         /// 
118         // TODO: should use more code from Parameter.ApplyAttributeBuilder
119         public class ImplicitParameter : ParameterBase {
120                 public ImplicitParameter (MethodBuilder mb)
121                 {
122                         builder = mb.DefineParameter (1, ParameterAttributes.None, "value");                    
123                 }
124
125                 public override AttributeTargets AttributeTargets {
126                         get {
127                                 return AttributeTargets.Parameter;
128                         }
129                 }
130
131                 /// <summary>
132                 /// Is never called
133                 /// </summary>
134                 public override string[] ValidAttributeTargets {
135                         get {
136                                 return null;
137                         }
138                 }
139         }
140
141         public class ImplicitLambdaParameter : Parameter
142         {
143                 public ImplicitLambdaParameter (string name, Location loc)
144                         : base (null, name, Modifier.NONE, null, loc)
145                 {
146                 }
147
148                 public override TypeSpec Resolve (IMemberContext ec, int index)
149                 {
150                         if (parameter_type == null)
151                                 throw new InternalErrorException ("A type of implicit lambda parameter `{0}' is not set",
152                                         Name);
153
154                         base.idx = index;
155                         return parameter_type;
156                 }
157
158                 public TypeSpec Type {
159                         set { parameter_type = value; }
160                 }
161         }
162
163         public class ParamsParameter : Parameter {
164                 public ParamsParameter (FullNamedExpression type, string name, Attributes attrs, Location loc):
165                         base (type, name, Parameter.Modifier.PARAMS, attrs, loc)
166                 {
167                 }
168
169                 public override TypeSpec Resolve (IMemberContext ec, int index)
170                 {
171                         if (base.Resolve (ec, index) == null)
172                                 return null;
173
174                         var ac = parameter_type as ArrayContainer;
175                         if (ac == null || ac.Rank != 1) {
176                                 ec.Compiler.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);
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.NONE, null, loc)
194                 {
195                         parameter_type = InternalType.Arglist;
196                 }
197
198                 public override void  ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
199                 {
200                         // Nothing to do
201                 }
202
203                 public override bool CheckAccessibility (InterfaceMemberBase member)
204                 {
205                         return true;
206                 }
207
208                 public override TypeSpec Resolve (IMemberContext ec, int index)
209                 {
210                         return parameter_type;
211                 }
212         }
213
214         public interface IParameterData
215         {
216                 Expression DefaultValue { get; }
217                 bool HasExtensionMethodModifier { get; }
218                 bool HasDefaultValue { get; }
219                 Parameter.Modifier ModFlags { get; }
220                 string Name { get; }
221         }
222
223         //
224         // Parameter information created by parser
225         //
226         public class Parameter : ParameterBase, IParameterData, ILocalVariable {
227                 [Flags]
228                 public enum Modifier : byte {
229                         NONE    = 0,
230                         REF     = REFMASK | ISBYREF,
231                         OUT     = OUTMASK | ISBYREF,
232                         PARAMS  = 4,
233                         // This is a flag which says that it's either REF or OUT.
234                         ISBYREF = 8,
235                         REFMASK = 32,
236                         OUTMASK = 64,
237                         This    = 128
238                 }
239
240                 static string[] attribute_targets = new string [] { "param" };
241
242                 FullNamedExpression texpr;
243                 readonly Modifier modFlags;
244                 string name;
245                 Expression default_expr;
246                 protected TypeSpec parameter_type;
247                 public readonly Location Location;
248                 protected int idx;
249                 public bool HasAddressTaken;
250
251                 Expression expr_tree_variable;
252                 static TypeExpr parameter_expr_tree_type;
253
254                 HoistedVariable hoisted_variant;
255
256                 public Parameter (FullNamedExpression type, string name, Modifier mod, Attributes attrs, Location loc)
257                 {
258                         this.name = name;
259                         modFlags = mod;
260                         Location = loc;
261                         texpr = type;
262
263                         // Only assign, attributes will be attached during resolve
264                         base.attributes = attrs;
265                 }
266
267 #region Properties
268                 public FullNamedExpression TypeExpression  {
269                         get {
270                                 return texpr;
271                         }
272                 }
273 #endregion
274
275                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
276                 {
277                         if (a.Type == pa.In && ModFlags == Modifier.OUT) {
278                                 a.Report.Error (36, a.Location, "An out parameter cannot have the `In' attribute");
279                                 return;
280                         }
281
282                         if (a.Type == pa.ParamArray) {
283                                 a.Report.Error (674, a.Location, "Do not use `System.ParamArrayAttribute'. Use the `params' keyword instead");
284                                 return;
285                         }
286
287                         if (a.Type == PredefinedAttributes.Get.Out && (ModFlags & Modifier.REF) == Modifier.REF &&
288                             !OptAttributes.Contains (pa.In)) {
289                                 a.Report.Error (662, a.Location,
290                                         "Cannot specify only `Out' attribute on a ref parameter. Use both `In' and `Out' attributes or neither");
291                                 return;
292                         }
293
294                         if (a.Type == pa.CLSCompliant) {
295                                 a.Report.Warning (3022, 1, a.Location, "CLSCompliant attribute has no meaning when applied to parameters. Try putting it on the method instead");
296                         }
297
298                         if (HasDefaultValue && (a.Type == pa.DefaultParameterValue || a.Type == pa.OptionalParameter)) {
299                                 a.Report.Error (1745, a.Location,
300                                         "Cannot specify `{0}' attribute on optional parameter `{1}'",
301                                         TypeManager.CSharpName (a.Type).Replace ("Attribute", ""), Name);
302                                 return;
303                         }
304
305                         if (a.Type == pa.DefaultParameterValue) {
306                                 TypeSpec arg_type;
307                                 var c = a.GetParameterDefaultValue (out arg_type);
308                                 if (c == null) {
309                                         if (parameter_type == TypeManager.object_type) {
310                                                 a.Report.Error (1910, a.Location, "Argument of type `{0}' is not applicable for the DefaultParameterValue attribute",
311                                                         arg_type.GetSignatureForError ());
312                                         } else {
313                                                 a.Report.Error (1909, a.Location, "The DefaultParameterValue attribute is not applicable on parameters of type `{0}'",
314                                                         parameter_type.GetSignatureForError ()); ;
315                                         }
316
317                                         return;
318                                 }
319
320                                 if (arg_type == parameter_type || parameter_type == TypeManager.object_type || 
321                                         (c.IsNull && TypeManager.IsReferenceType (parameter_type) && !TypeManager.IsGenericParameter (parameter_type)))
322                                         builder.SetConstant (c.GetValue ());
323                                 else
324                                         a.Report.Error (1908, a.Location, "The type of the default value should match the type of the parameter");
325
326                                 return;
327                         }
328
329                         base.ApplyAttributeBuilder (a, ctor, cdata, pa);
330                 }
331                 
332                 public virtual bool CheckAccessibility (InterfaceMemberBase member)
333                 {
334                         if (parameter_type == null || TypeManager.IsGenericParameter (parameter_type))
335                                 return true;
336
337                         return member.IsAccessibleAs (parameter_type);
338                 }
339
340                 public static void Reset ()
341                 {
342                         parameter_expr_tree_type = null;
343                 }
344
345                 // <summary>
346                 //   Resolve is used in method definitions
347                 // </summary>
348                 public virtual TypeSpec Resolve (IMemberContext rc, int index)
349                 {
350                         if (parameter_type != null)
351                                 return parameter_type;
352
353                         if (attributes != null)
354                                 attributes.AttachTo (this, rc);
355
356                         var expr = texpr.ResolveAsTypeTerminal (rc, false);
357                         if (expr == null)
358                                 return null;
359
360                         this.idx = index;
361                         texpr = expr;
362                         parameter_type = texpr.Type;
363         
364                         if ((modFlags & Parameter.Modifier.ISBYREF) != 0 &&
365                                 TypeManager.IsSpecialType (parameter_type)) {
366                                 rc.Compiler.Report.Error (1601, Location, "Method or delegate parameter cannot be of type `{0}'",
367                                         GetSignatureForError ());
368                                 return null;
369                         }
370
371                         TypeManager.CheckTypeVariance (parameter_type,
372                                 (modFlags & Parameter.Modifier.ISBYREF) != 0 ? Variance.None : Variance.Contravariant,
373                                 rc);
374
375                         if (parameter_type.IsStatic) {
376                                 rc.Compiler.Report.Error (721, Location, "`{0}': static types cannot be used as parameters",
377                                         texpr.GetSignatureForError ());
378                                 return parameter_type;
379                         }
380
381                         if ((modFlags & Modifier.This) != 0 && (parameter_type.IsPointer || parameter_type == InternalType.Dynamic)) {
382                                 rc.Compiler.Report.Error (1103, Location, "The extension method cannot be of type `{0}'",
383                                         TypeManager.CSharpName (parameter_type));
384                         }
385
386                         return parameter_type;
387                 }
388
389                 public void ResolveDefaultValue (ResolveContext rc)
390                 {
391                         if (default_expr != null)
392                                 default_expr = ResolveDefaultExpression (rc);
393                 }
394
395                 Expression ResolveDefaultExpression (ResolveContext rc)
396                 {
397                         default_expr = default_expr.Resolve (rc);
398                         if (default_expr == null)
399                                 return null;
400
401                         if (!(default_expr is Constant || default_expr is DefaultValueExpression)) {
402                                 if (TypeManager.IsNullableType (parameter_type)) {
403                                         rc.Compiler.Report.Error (1770, default_expr.Location,
404                                                 "The expression being assigned to nullable optional parameter `{0}' must be default value",
405                                                 Name);
406                                 } else {
407                                         rc.Compiler.Report.Error (1736, default_expr.Location,
408                                                 "The expression being assigned to optional parameter `{0}' must be a constant or default value",
409                                                 Name);
410                                 }
411
412                                 return null;
413                         }
414
415                         if (default_expr.Type == parameter_type)
416                                 return default_expr;
417
418                         if (TypeManager.IsNullableType (parameter_type)) {
419                                 if (Convert.ImplicitNulableConversion (rc, default_expr, parameter_type) != null)
420                                         return default_expr;
421                         } else {
422                                 var res = Convert.ImplicitConversionStandard (rc, default_expr, parameter_type, default_expr.Location);
423                                 if (res != null) {
424                                         if (!default_expr.IsNull && TypeManager.IsReferenceType (parameter_type) && parameter_type != TypeManager.string_type) {
425                                                 rc.Compiler.Report.Error (1763, default_expr.Location,
426                                                         "Optional parameter `{0}' of type `{1}' can only be initialized with `null'",
427                                                         Name, GetSignatureForError ());
428
429                                                 return null;
430                                         }
431
432                                         return res;
433                                 }
434                         }
435
436                         rc.Compiler.Report.Error (1750, Location,
437                                 "Optional parameter expression of type `{0}' cannot be converted to parameter type `{1}'",
438                                 TypeManager.CSharpName (default_expr.Type), GetSignatureForError ());
439
440                         return null;
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 = texpr.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 (parameter_type.IsCLSCompliant ())
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 (parameter_type == InternalType.Dynamic) {
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, ArrayContainer.MakeType (TypeManager.bool_type))) {
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, 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.Emit (OpCodes.Starg_S, (byte) arg_idx);
615                         else
616                                 ec.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, arg_idx);
629                         } else {
630                                 if (arg_idx <= 255)
631                                         ec.Emit (OpCodes.Ldarga_S, (byte) arg_idx);
632                                 else
633                                         ec.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                         TypeSpec 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 TypeSpec [] types;
724
725                 public CallingConventions CallingConvention {
726                         get {
727                                 return has_arglist ?
728                                         CallingConventions.VarArgs :
729                                         CallingConventions.Standard;
730                         }
731                 }
732
733                 public int Count {
734                         get { return parameters.Length; }
735                 }
736
737                 public TypeSpec ExtensionMethodType {
738                         get {
739                                 if (Count == 0)
740                                         return null;
741
742                                 return FixedParameters [0].HasExtensionMethodModifier ?
743                                         types [0] : null;
744                         }
745                 }
746
747                 public IParameterData [] FixedParameters {
748                         get {
749                                 return parameters;
750                         }
751                 }
752
753                 public static ParameterAttributes GetParameterAttribute (Parameter.Modifier modFlags)
754                 {
755                         return (modFlags & Parameter.Modifier.OUT) == Parameter.Modifier.OUT ?
756                                 ParameterAttributes.Out : ParameterAttributes.None;
757                 }
758
759                 // Very expensive operation
760                 public Type[] GetMetaInfo ()
761                 {
762                         Type[] types;
763                         if (has_arglist) {
764                                 if (Count == 1)
765                                         return Type.EmptyTypes;
766
767                                 types = new Type [Count - 1];
768                         } else {
769                                 if (Count == 0)
770                                         return Type.EmptyTypes;
771
772                                 types = new Type [Count];
773                         }
774
775                         for (int i = 0; i < types.Length; ++i) {
776                                 types[i] = Types[i].GetMetaInfo ();
777
778                                 if ((FixedParameters [i].ModFlags & Parameter.Modifier.ISBYREF) == 0)
779                                         continue;
780
781                                 // TODO MemberCache: Should go to MetaInfo getter
782                                 types [i] = types [i].MakeByRefType ();
783                         }
784
785                         return types;
786                 }
787
788                 //
789                 // Returns the parameter information based on the name
790                 //
791                 public int GetParameterIndexByName (string name)
792                 {
793                         for (int idx = 0; idx < Count; ++idx) {
794                                 if (parameters [idx].Name == name)
795                                         return idx;
796                         }
797
798                         return -1;
799                 }
800
801                 public string GetSignatureForError ()
802                 {
803                         return GetSignatureForError ("(", ")", Count);
804                 }
805
806                 public string GetSignatureForError (string start, string end, int count)
807                 {
808                         StringBuilder sb = new StringBuilder (start);
809                         for (int i = 0; i < count; ++i) {
810                                 if (i != 0)
811                                         sb.Append (", ");
812                                 sb.Append (ParameterDesc (i));
813                         }
814                         sb.Append (end);
815                         return sb.ToString ();
816                 }
817
818                 public bool HasArglist {
819                         get { return has_arglist; }
820                 }
821
822                 public bool HasExtensionMethodType {
823                         get {
824                                 if (Count == 0)
825                                         return false;
826
827                                 return FixedParameters [0].HasExtensionMethodModifier;
828                         }
829                 }
830
831                 public bool HasParams {
832                         get { return has_params; }
833                 }
834
835                 public bool IsEmpty {
836                         get { return parameters.Length == 0; }
837                 }
838
839                 public AParametersCollection Inflate (TypeParameterInflator inflator)
840                 {
841                         TypeSpec[] inflated_types = null;
842                         bool default_value = false;
843
844                         for (int i = 0; i < Count; ++i) {
845                                 var inflated_param = inflator.Inflate (types[i]);
846                                 if (inflated_types == null) {
847                                         if (inflated_param == types[i])
848                                                 continue;
849
850                                         default_value |= FixedParameters[i] is DefaultValueExpression;
851                                         inflated_types = new TypeSpec[types.Length];
852                                         Array.Copy (types, inflated_types, types.Length);       
853                                 }
854
855                                 inflated_types[i] = inflated_param;
856                         }
857
858                         if (inflated_types == null)
859                                 return this;
860
861                         var clone = (AParametersCollection) MemberwiseClone ();
862                         clone.types = inflated_types;
863                         if (default_value) {
864                                 for (int i = 0; i < Count; ++i) {
865                                         var dve = clone.FixedParameters[i] as DefaultValueExpression;
866                                         if (dve != null) {
867                                                 throw new NotImplementedException ("net");
868                                                 //      clone.FixedParameters [i].DefaultValue = new DefaultValueExpression ();
869                                         }
870                                 }
871                         }
872
873                         return clone;
874                 }
875
876                 public string ParameterDesc (int pos)
877                 {
878                         if (types == null || types [pos] == null)
879                                 return ((Parameter)FixedParameters [pos]).GetSignatureForError ();
880
881                         string type = TypeManager.CSharpName (types [pos]);
882                         if (FixedParameters [pos].HasExtensionMethodModifier)
883                                 return "this " + type;
884
885                         Parameter.Modifier mod = FixedParameters [pos].ModFlags;
886                         if (mod == 0)
887                                 return type;
888
889                         return Parameter.GetModifierSignature (mod) + " " + type;
890                 }
891
892                 public TypeSpec[] Types {
893                         get { return types; }
894                         set { types = value; }
895                 }
896         }
897
898         //
899         // A collection of imported or resolved parameters
900         //
901         public class ParametersImported : AParametersCollection
902         {
903                 ParametersImported (AParametersCollection param, TypeSpec[] types)
904                 {
905                         this.parameters = param.FixedParameters;
906                         this.types = types;
907                         has_arglist = param.HasArglist;
908                         has_params = param.HasParams;
909                 }
910
911                 ParametersImported (IParameterData [] parameters, TypeSpec [] types, bool hasArglist, bool hasParams)
912                 {
913                         this.parameters = parameters;
914                         this.types = types;
915                         this.has_arglist = hasArglist;
916                         this.has_params = hasParams;
917                 }
918
919                 public ParametersImported (IParameterData[] param, TypeSpec[] types, bool hasParams)
920                 {
921                         this.parameters = param;
922                         this.types = types;
923                         this.has_params = hasParams;
924                 }
925
926                 public static AParametersCollection Create (TypeSpec parent, MethodBase method)
927                 {
928                         return Create (parent, method.GetParameters (), method);
929                 }
930
931                 //
932                 // Imports System.Reflection parameters
933                 //
934                 public static AParametersCollection Create (TypeSpec parent, ParameterInfo [] pi, MethodBase method)
935                 {
936                         int varargs = method != null && (method.CallingConvention & CallingConventions.VarArgs) != 0 ? 1 : 0;
937
938                         if (pi.Length == 0 && varargs == 0)
939                                 return ParametersCompiled.EmptyReadOnlyParameters;
940
941                         TypeSpec [] types = new TypeSpec [pi.Length + varargs];
942                         IParameterData [] par = new IParameterData [pi.Length + varargs];
943                         bool is_params = false;
944                         for (int i = 0; i < pi.Length; i++) {
945                                 ParameterInfo p = pi [i];
946                                 Parameter.Modifier mod = 0;
947                                 Expression default_value = null;
948                                 if (p.ParameterType.IsByRef) {
949                                         if ((p.Attributes & (ParameterAttributes.Out | ParameterAttributes.In)) == ParameterAttributes.Out)
950                                                 mod = Parameter.Modifier.OUT;
951                                         else
952                                                 mod = Parameter.Modifier.REF;
953
954                                         //
955                                         // Strip reference wrapping
956                                         //
957                                         types [i] = Import.ImportType (p.ParameterType.GetElementType ());
958                                 } else if (i == 0 && method.IsStatic && parent.IsStatic && // TODO: parent.Assembly.IsExtension &&
959                                         HasExtensionAttribute (method)) {
960                                         mod = Parameter.Modifier.This;
961                                         types[i] = Import.ImportType (p.ParameterType);
962                                 } else {
963                                         types[i] = Import.ImportType (p.ParameterType);
964
965                                         if (i >= pi.Length - 2 && types[i] is ArrayContainer) {
966                                                 var cattrs = CustomAttributeData.GetCustomAttributes (p);
967                                                 if (cattrs != null && cattrs.Any (l => l.Constructor.DeclaringType == typeof (ParamArrayAttribute))) {
968                                                         mod = Parameter.Modifier.PARAMS;
969                                                         is_params = true;
970                                                 }
971                                         }
972
973                                         if (!is_params && p.IsOptional) {
974                                                 object value = p.DefaultValue;
975                                                 if (value == Missing.Value) {
976                                                         default_value = EmptyExpression.Null;
977                                                 } else if (value == null) {
978                                                         default_value = new NullLiteral (Location.Null);
979                                                 } else {
980                                                         default_value = Constant.CreateConstant (null, Import.ImportType (value.GetType ()), value, Location.Null);
981                                                 }
982                                         }
983                                 }
984
985                                 par [i] = new ParameterData (p.Name, mod, default_value);
986                         }
987
988                         if (varargs != 0) {
989                                 par [par.Length - 1] = new ArglistParameter (Location.Null);
990                                 types [types.Length - 1] = InternalType.Arglist;
991                         }
992
993                         return method != null ?
994                                 new ParametersImported (par, types, varargs != 0, is_params) :
995                                 new ParametersImported (par, types, is_params);
996                 }
997
998                 static bool HasExtensionAttribute (MethodBase mb)
999                 {
1000                         var all_attributes = CustomAttributeData.GetCustomAttributes (mb);
1001                         foreach (var attr in all_attributes) {
1002                                 var dt = attr.Constructor.DeclaringType;
1003                                 if (dt.Name == "ExtensionAttribute" && dt.Namespace == "System.Runtime.CompilerServices") {
1004                                         return true;
1005                                 }
1006                         }
1007
1008                         return false;
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 = TypeSpec.EmptyTypes;
1026                 }
1027
1028                 private ParametersCompiled (IParameterData [] parameters, TypeSpec [] 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                                 has_params |= (parameters [i].ModFlags & Parameter.Modifier.PARAMS) != 0;
1052                                 if (ctx != null) {
1053                                         string base_name = parameters[i].Name;
1054
1055                                         for (int j = i + 1; j < count; j++) {
1056                                                 if (base_name != parameters[j].Name)
1057                                                         continue;
1058
1059                                                 ErrorDuplicateName (parameters[i], ctx.Report);
1060                                                 i = j;
1061                                         }
1062                                 }
1063                         }
1064                 }
1065
1066                 public ParametersCompiled (CompilerContext ctx, Parameter [] parameters, bool has_arglist) :
1067                         this (ctx, parameters)
1068                 {
1069                         this.has_arglist = has_arglist;
1070                 }
1071                 
1072                 public static ParametersCompiled CreateFullyResolved (Parameter p, TypeSpec type)
1073                 {
1074                         return new ParametersCompiled (new Parameter [] { p }, new TypeSpec [] { type });
1075                 }
1076                 
1077                 public static ParametersCompiled CreateFullyResolved (IParameterData[] parameters, TypeSpec[] types)
1078                 {
1079                         return new ParametersCompiled (parameters, types);
1080                 }
1081
1082                 public static AParametersCollection CreateFullyResolved (TypeSpec[] types)
1083                 {
1084                         var pd = new ParameterData [types.Length];
1085                         for (int i = 0; i < pd.Length; ++i)
1086                                 pd[i] = new ParameterData (null, Parameter.Modifier.NONE, null);
1087
1088                         return new ParametersCompiled (pd, types);
1089                 }
1090
1091                 public static ParametersCompiled CreateImplicitParameter (FullNamedExpression texpr, Location loc)
1092                 {
1093                         return new ParametersCompiled (
1094                                 new[] { new Parameter (texpr, "value", Parameter.Modifier.NONE, null, loc) },
1095                                 null);
1096                 }
1097
1098                 //
1099                 // Returns non-zero value for equal CLS parameter signatures
1100                 //
1101                 public static int IsSameClsSignature (AParametersCollection a, AParametersCollection b)
1102                 {
1103                         int res = 0;
1104
1105                         for (int i = 0; i < a.Count; ++i) {
1106                                 var a_type = a.Types[i];
1107                                 var b_type = b.Types[i];
1108                                 if (TypeSpecComparer.Override.IsEqual (a_type, b_type)) {
1109                                         const Parameter.Modifier ref_out = Parameter.Modifier.REF | Parameter.Modifier.OUT;
1110                                         if ((a.FixedParameters[i].ModFlags & ref_out) != (b.FixedParameters[i].ModFlags & ref_out))
1111                                                 res |= 1;
1112
1113                                         continue;
1114                                 }
1115
1116                                 var ac_a = a_type as ArrayContainer;
1117                                 if (ac_a == null)
1118                                         return 0;
1119
1120                                 var ac_b = b_type as ArrayContainer;
1121                                 if (ac_b == null)
1122                                         return 0;
1123
1124                                 if (ac_a.Element is ArrayContainer || ac_b.Element is ArrayContainer) {
1125                                         res |= 2;
1126                                         continue;
1127                                 }
1128
1129                                 if (ac_a.Rank != ac_b.Rank && TypeSpecComparer.Override.IsEqual (ac_a.Element, ac_b.Element)) {
1130                                         res |= 1;
1131                                         continue;
1132                                 }
1133
1134                                 return 0;
1135                         }
1136
1137                         return res;
1138                 }
1139
1140                 public static ParametersCompiled MergeGenerated (CompilerContext ctx, ParametersCompiled userParams, bool checkConflicts, Parameter compilerParams, TypeSpec compilerTypes)
1141                 {
1142                         return MergeGenerated (ctx, userParams, checkConflicts,
1143                                 new Parameter [] { compilerParams },
1144                                 new TypeSpec [] { compilerTypes });
1145                 }
1146
1147                 //
1148                 // Use this method when you merge compiler generated parameters with user parameters
1149                 //
1150                 public static ParametersCompiled MergeGenerated (CompilerContext ctx, ParametersCompiled userParams, bool checkConflicts, Parameter[] compilerParams, TypeSpec[] compilerTypes)
1151                 {
1152                         Parameter[] all_params = new Parameter [userParams.Count + compilerParams.Length];
1153                         userParams.FixedParameters.CopyTo(all_params, 0);
1154
1155                         TypeSpec [] all_types;
1156                         if (userParams.types != null) {
1157                                 all_types = new TypeSpec [all_params.Length];
1158                                 userParams.Types.CopyTo (all_types, 0);
1159                         } else {
1160                                 all_types = null;
1161                         }
1162
1163                         int last_filled = userParams.Count;
1164                         int index = 0;
1165                         foreach (Parameter p in compilerParams) {
1166                                 for (int i = 0; i < last_filled; ++i) {
1167                                         while (p.Name == all_params [i].Name) {
1168                                                 if (checkConflicts && i < userParams.Count) {
1169                                                         ctx.Report.Error (316, userParams[i].Location,
1170                                                                 "The parameter name `{0}' conflicts with a compiler generated name", p.Name);
1171                                                 }
1172                                                 p.Name = '_' + p.Name;
1173                                         }
1174                                 }
1175                                 all_params [last_filled] = p;
1176                                 if (all_types != null)
1177                                         all_types [last_filled] = compilerTypes [index++];
1178                                 ++last_filled;
1179                         }
1180                         
1181                         ParametersCompiled parameters = new ParametersCompiled (all_params, all_types);
1182                         parameters.has_params = userParams.has_params;
1183                         return parameters;
1184                 }
1185
1186                 protected virtual void ErrorDuplicateName (Parameter p, Report Report)
1187                 {
1188                         Report.Error (100, p.Location, "The parameter name `{0}' is a duplicate", p.Name);
1189                 }
1190
1191                 public bool Resolve (IMemberContext ec)
1192                 {
1193                         if (types != null)
1194                                 return true;
1195                         
1196                         types = new TypeSpec [Count];
1197                         
1198                         bool ok = true;
1199                         Parameter p;
1200                         for (int i = 0; i < FixedParameters.Length; ++i) {
1201                                 p = this [i];
1202                                 TypeSpec t = p.Resolve (ec, i);
1203                                 if (t == null) {
1204                                         ok = false;
1205                                         continue;
1206                                 }
1207
1208                                 types [i] = t;
1209                         }
1210
1211                         return ok;
1212                 }
1213
1214                 public void ResolveDefaultValues (ResolveContext rc)
1215                 {
1216                         for (int i = 0; i < FixedParameters.Length; ++i) {
1217                                 this [i].ResolveDefaultValue (rc);
1218                         }
1219                 }
1220
1221                 // Define each type attribute (in/out/ref) and
1222                 // the argument names.
1223                 public void ApplyAttributes (MethodBase builder)
1224                 {
1225                         if (Count == 0)
1226                                 return;
1227
1228                         MethodBuilder mb = builder as MethodBuilder;
1229                         ConstructorBuilder cb = builder as ConstructorBuilder;
1230
1231                         for (int i = 0; i < Count; i++) {
1232                                 this [i].ApplyAttributes (mb, cb, i + 1);
1233                         }
1234                 }
1235
1236                 public void VerifyClsCompliance (IMemberContext ctx)
1237                 {
1238                         foreach (Parameter p in FixedParameters)
1239                                 p.IsClsCompliant (ctx);
1240                 }
1241
1242                 public Parameter this [int pos] {
1243                         get { return (Parameter) parameters [pos]; }
1244                 }
1245
1246                 public Expression CreateExpressionTree (BlockContext ec, Location loc)
1247                 {
1248                         var initializers = new ArrayInitializer (Count, loc);
1249                         foreach (Parameter p in FixedParameters) {
1250                                 //
1251                                 // Each parameter expression is stored to local variable
1252                                 // to save some memory when referenced later.
1253                                 //
1254                                 StatementExpression se = new StatementExpression (p.CreateExpressionTreeVariable (ec));
1255                                 if (se.Resolve (ec))
1256                                         ec.CurrentBlock.AddScopeStatement (se);
1257                                 
1258                                 initializers.Add (p.ExpressionTreeVariableReference ());
1259                         }
1260
1261                         return new ArrayCreation (
1262                                 Parameter.ResolveParameterExpressionType (ec, loc),
1263                                 initializers, loc);
1264                 }
1265
1266                 public ParametersCompiled Clone ()
1267                 {
1268                         ParametersCompiled p = (ParametersCompiled) MemberwiseClone ();
1269
1270                         p.parameters = new IParameterData [parameters.Length];
1271                         for (int i = 0; i < Count; ++i)
1272                                 p.parameters [i] = this [i].Clone ();
1273
1274                         return p;
1275                 }
1276         }
1277 }