2010-01-12 Zoltan Varga <vargaz@gmail.com>
[mcs.git] / mcs / parameter.cs
blobbf89f66c60635ea24e2d22d2c7ff7664dee898da
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.
13 using System;
14 using System.Reflection;
15 using System.Reflection.Emit;
16 using System.Collections;
17 using System.Text;
19 namespace Mono.CSharp {
21 /// <summary>
22 /// Abstract Base class for parameters of a method.
23 /// </summary>
24 public abstract class ParameterBase : Attributable
26 protected ParameterBuilder builder;
28 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
30 #if !NET_2_0
31 if (a.Type == pa.MarshalAs) {
32 UnmanagedMarshal marshal = a.GetMarshal (this);
33 if (marshal != null) {
34 builder.SetMarshal (marshal);
36 return;
38 #endif
39 if (a.HasSecurityAttribute) {
40 a.Error_InvalidSecurityParent ();
41 return;
44 builder.SetCustomAttribute (cb);
47 public override bool IsClsComplianceRequired()
49 return false;
53 /// <summary>
54 /// Class for applying custom attributes on the return type
55 /// </summary>
56 public class ReturnParameter : ParameterBase {
57 public ReturnParameter (MethodBuilder mb, Location location)
59 try {
60 builder = mb.DefineParameter (0, ParameterAttributes.None, "");
62 catch (ArgumentOutOfRangeException) {
63 RootContext.ToplevelTypes.Compiler.Report.RuntimeMissingSupport (location, "custom attributes on the return type");
67 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
69 if (a.Type == pa.CLSCompliant) {
70 RootContext.ToplevelTypes.Compiler.Report.Warning (3023, 1, a.Location,
71 "CLSCompliant attribute has no meaning when applied to return types. Try putting it on the method instead");
74 // This occurs after Warning -28
75 if (builder == null)
76 return;
78 base.ApplyAttributeBuilder (a, cb, pa);
81 public override AttributeTargets AttributeTargets {
82 get {
83 return AttributeTargets.ReturnValue;
87 public void EmitPredefined (PredefinedAttribute pa, Location loc)
89 if (builder != null)
90 pa.EmitAttribute (builder, loc);
93 /// <summary>
94 /// Is never called
95 /// </summary>
96 public override string[] ValidAttributeTargets {
97 get {
98 return null;
103 /// <summary>
104 /// Class for applying custom attributes on the implicit parameter type
105 /// of the 'set' method in properties, and the 'add' and 'remove' methods in events.
106 /// </summary>
107 ///
108 // TODO: should use more code from Parameter.ApplyAttributeBuilder
109 public class ImplicitParameter : ParameterBase {
110 public ImplicitParameter (MethodBuilder mb)
112 builder = mb.DefineParameter (1, ParameterAttributes.None, "value");
115 public override AttributeTargets AttributeTargets {
116 get {
117 return AttributeTargets.Parameter;
121 /// <summary>
122 /// Is never called
123 /// </summary>
124 public override string[] ValidAttributeTargets {
125 get {
126 return null;
131 public class ImplicitLambdaParameter : Parameter
133 public ImplicitLambdaParameter (string name, Location loc)
134 : base (null, name, Modifier.NONE, null, loc)
138 public override Type Resolve (IMemberContext ec)
140 if (parameter_type == null)
141 throw new InternalErrorException ("A type of implicit lambda parameter `{0}' is not set",
142 Name);
144 return parameter_type;
147 public Type Type {
148 set { parameter_type = value; }
152 public class ParamsParameter : Parameter {
153 public ParamsParameter (FullNamedExpression type, string name, Attributes attrs, Location loc):
154 base (type, name, Parameter.Modifier.PARAMS, attrs, loc)
158 public override Type Resolve (IMemberContext ec)
160 if (base.Resolve (ec) == null)
161 return null;
163 if (!parameter_type.IsArray || parameter_type.GetArrayRank () != 1) {
164 ec.Compiler.Report.Error (225, Location, "The params parameter must be a single dimensional array");
165 return null;
168 return parameter_type;
171 public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
173 base.ApplyAttributes (mb, cb, index);
174 PredefinedAttributes.Get.ParamArray.EmitAttribute (builder, Location);
178 public class ArglistParameter : Parameter {
179 // Doesn't have proper type because it's never chosen for better conversion
180 public ArglistParameter (Location loc) :
181 base (null, String.Empty, Parameter.Modifier.NONE, null, loc)
185 public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
187 // Nothing to do
190 public override bool CheckAccessibility (InterfaceMemberBase member)
192 return true;
195 public override Type Resolve (IMemberContext ec)
197 return InternalType.Arglist;
200 public override string GetSignatureForError ()
202 return "__arglist";
206 public interface IParameterData
208 Expression DefaultValue { get; }
209 bool HasExtensionMethodModifier { get; }
210 bool HasDefaultValue { get; }
211 Parameter.Modifier ModFlags { get; }
212 string Name { get; }
216 // Parameter information created by parser
218 public class Parameter : ParameterBase, IParameterData, ILocalVariable {
219 [Flags]
220 public enum Modifier : byte {
221 NONE = 0,
222 REF = REFMASK | ISBYREF,
223 OUT = OUTMASK | ISBYREF,
224 PARAMS = 4,
225 // This is a flag which says that it's either REF or OUT.
226 ISBYREF = 8,
227 REFMASK = 32,
228 OUTMASK = 64,
229 This = 128
232 static string[] attribute_targets = new string [] { "param" };
234 protected FullNamedExpression TypeName;
235 readonly Modifier modFlags;
236 string name;
237 Expression default_expr;
238 protected Type parameter_type;
239 public readonly Location Location;
240 int idx;
241 public bool HasAddressTaken;
243 LocalVariableReference expr_tree_variable;
244 static TypeExpr parameter_expr_tree_type;
246 public HoistedVariable HoistedVariableReference;
248 public Parameter (FullNamedExpression type, string name, Modifier mod, Attributes attrs, Location loc)
250 this.name = name;
251 modFlags = mod;
252 Location = loc;
253 TypeName = type;
255 // Only assign, attributes will be attached during resolve
256 base.attributes = attrs;
259 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
261 Report Report = RootContext.ToplevelTypes.Compiler.Report;
263 if (a.Type == pa.In && ModFlags == Modifier.OUT) {
264 Report.Error (36, a.Location, "An out parameter cannot have the `In' attribute");
265 return;
268 if (a.Type == pa.ParamArray) {
269 Report.Error (674, a.Location, "Do not use `System.ParamArrayAttribute'. Use the `params' keyword instead");
270 return;
273 if (a.Type == PredefinedAttributes.Get.Out && (ModFlags & Modifier.REF) == Modifier.REF &&
274 !OptAttributes.Contains (pa.In)) {
275 Report.Error (662, a.Location,
276 "Cannot specify only `Out' attribute on a ref parameter. Use both `In' and `Out' attributes or neither");
277 return;
280 if (a.Type == pa.CLSCompliant) {
281 Report.Warning (3022, 1, a.Location, "CLSCompliant attribute has no meaning when applied to parameters. Try putting it on the method instead");
284 if (HasDefaultValue && (a.Type == pa.DefaultParameterValue || a.Type == pa.OptionalParameter)) {
285 Report.Error (1745, a.Location,
286 "Cannot specify `{0}' attribute on optional parameter `{1}'",
287 TypeManager.CSharpName (a.Type).Replace ("Attribute", ""), Name);
288 return;
291 if (a.Type == pa.DefaultParameterValue) {
292 object val = a.GetParameterDefaultValue ();
293 if (val != null) {
294 Type t = val.GetType ();
295 if (t.IsArray || TypeManager.IsSubclassOf (t, TypeManager.type_type)) {
296 if (parameter_type == TypeManager.object_type) {
297 if (!t.IsArray)
298 t = TypeManager.type_type;
300 Report.Error (1910, a.Location, "Argument of type `{0}' is not applicable for the DefaultParameterValue attribute",
301 TypeManager.CSharpName (t));
302 } else {
303 Report.Error (1909, a.Location, "The DefaultParameterValue attribute is not applicable on parameters of type `{0}'",
304 TypeManager.CSharpName (parameter_type)); ;
306 return;
310 if (parameter_type == TypeManager.object_type ||
311 (val == null && !TypeManager.IsGenericParameter (parameter_type) && TypeManager.IsReferenceType (parameter_type)) ||
312 (val != null && TypeManager.TypeToCoreType (val.GetType ()) == parameter_type))
313 builder.SetConstant (val);
314 else
315 Report.Error (1908, a.Location, "The type of the default value should match the type of the parameter");
316 return;
319 base.ApplyAttributeBuilder (a, cb, pa);
322 public virtual bool CheckAccessibility (InterfaceMemberBase member)
324 if (parameter_type == null || TypeManager.IsGenericParameter (parameter_type))
325 return true;
327 return member.IsAccessibleAs (parameter_type);
330 // <summary>
331 // Resolve is used in method definitions
332 // </summary>
333 public virtual Type Resolve (IMemberContext rc)
335 if (parameter_type != null)
336 return parameter_type;
338 if (attributes != null)
339 attributes.AttachTo (this, rc);
341 TypeExpr texpr = TypeName.ResolveAsTypeTerminal (rc, false);
342 if (texpr == null)
343 return null;
345 parameter_type = texpr.Type;
347 // Ignore all checks for dummy members
348 AbstractPropertyEventMethod pem = rc as AbstractPropertyEventMethod;
349 if (pem != null && pem.IsDummy)
350 return parameter_type;
352 if (default_expr != null) {
353 ResolveContext ec = new ResolveContext (rc);
354 default_expr = default_expr.Resolve (ec);
355 if (default_expr != null) {
356 Constant value = default_expr as Constant;
357 if (value == null) {
358 if (default_expr != null) {
359 bool is_valid = false;
360 if (default_expr is DefaultValueExpression) {
361 is_valid = true;
362 } else if (default_expr is New && ((New) default_expr).IsDefaultValueType) {
363 is_valid = TypeManager.IsEqual (parameter_type, default_expr.Type) ||
364 (TypeManager.IsNullableType (parameter_type) &&
365 Convert.ImplicitNulableConversion (ec, default_expr, parameter_type) != EmptyExpression.Null);
366 } else {
367 rc.Compiler.Report.Error (1736, default_expr.Location,
368 "The expression being assigned to optional parameter `{0}' must be a constant or default value",
369 Name);
370 is_valid = true;
373 if (!is_valid) {
374 default_expr = null;
375 ec.Compiler.Report.Error (1763, Location,
376 "Optional parameter `{0}' of type `{1}' can only be initialized with `null'",
377 Name, GetSignatureForError ());
380 } else {
381 Constant c = value.ConvertImplicitly (parameter_type);
382 if (c == null) {
383 if (parameter_type == TypeManager.object_type) {
384 rc.Compiler.Report.Error (1763, Location,
385 "Optional parameter `{0}' of type `{1}' can only be initialized with `null'",
386 Name, GetSignatureForError ());
387 } else {
388 rc.Compiler.Report.Error (1750, Location,
389 "Optional parameter value `{0}' cannot be converted to parameter type `{1}'",
390 value.GetValue (), GetSignatureForError ());
392 default_expr = null;
398 if ((modFlags & Parameter.Modifier.ISBYREF) != 0 &&
399 TypeManager.IsSpecialType (parameter_type)) {
400 rc.Compiler.Report.Error (1601, Location, "Method or delegate parameter cannot be of type `{0}'",
401 GetSignatureForError ());
402 return null;
405 TypeManager.CheckTypeVariance (parameter_type,
406 (modFlags & Parameter.Modifier.ISBYREF) != 0 ? Variance.None : Variance.Contravariant,
407 rc);
409 if (TypeManager.IsGenericParameter (parameter_type))
410 return parameter_type;
412 if ((parameter_type.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) {
413 rc.Compiler.Report.Error (721, Location, "`{0}': static types cannot be used as parameters",
414 texpr.GetSignatureForError ());
415 return parameter_type;
418 if ((modFlags & Modifier.This) != 0 && (parameter_type.IsPointer || TypeManager.IsDynamicType (parameter_type))) {
419 rc.Compiler.Report.Error (1103, Location, "The extension method cannot be of type `{0}'",
420 TypeManager.CSharpName (parameter_type));
423 return parameter_type;
426 public void ResolveVariable (int idx)
428 this.idx = idx;
431 public bool HasDefaultValue {
432 get { return default_expr != null; }
435 public bool HasExtensionMethodModifier {
436 get { return (modFlags & Modifier.This) != 0; }
439 public Modifier ModFlags {
440 get { return modFlags & ~Modifier.This; }
443 public string Name {
444 get { return name; }
445 set { name = value; }
448 ParameterAttributes Attributes {
449 get { return ParametersCompiled.GetParameterAttribute (modFlags) |
450 (HasDefaultValue ? ParameterAttributes.Optional : ParameterAttributes.None); }
453 public override AttributeTargets AttributeTargets {
454 get {
455 return AttributeTargets.Parameter;
459 public virtual string GetSignatureForError ()
461 string type_name;
462 if (parameter_type != null)
463 type_name = TypeManager.CSharpName (parameter_type);
464 else
465 type_name = TypeName.GetSignatureForError ();
467 string mod = GetModifierSignature (modFlags);
468 if (mod.Length > 0)
469 return String.Concat (mod, " ", type_name);
471 return type_name;
474 public static string GetModifierSignature (Modifier mod)
476 switch (mod) {
477 case Modifier.OUT:
478 return "out";
479 case Modifier.PARAMS:
480 return "params";
481 case Modifier.REF:
482 return "ref";
483 case Modifier.This:
484 return "this";
485 default:
486 return "";
490 public void IsClsCompliant ()
492 if (AttributeTester.IsClsCompliant (parameter_type))
493 return;
495 RootContext.ToplevelTypes.Compiler.Report.Warning (3001, 1, Location, "Argument type `{0}' is not CLS-compliant", GetSignatureForError ());
498 public virtual void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
500 if (mb == null)
501 builder = cb.DefineParameter (index, Attributes, Name);
502 else
503 builder = mb.DefineParameter (index, Attributes, Name);
505 if (OptAttributes != null)
506 OptAttributes.Emit ();
508 if (HasDefaultValue) {
510 // Emit constant values for true constants only, the other
511 // constant-like expressions will rely on default value expression
513 Constant c = default_expr as Constant;
514 if (c != null) {
515 if (default_expr.Type == TypeManager.decimal_type) {
516 builder.SetCustomAttribute (Const.CreateDecimalConstantAttribute (c));
517 } else {
518 builder.SetConstant (c.GetValue ());
523 if (TypeManager.IsDynamicType (parameter_type))
524 PredefinedAttributes.Get.Dynamic.EmitAttribute (builder, Location);
527 public override string[] ValidAttributeTargets {
528 get {
529 return attribute_targets;
533 public Parameter Clone ()
535 Parameter p = (Parameter) MemberwiseClone ();
536 if (attributes != null)
537 p.attributes = attributes.Clone ();
539 return p;
542 public ExpressionStatement CreateExpressionTreeVariable (BlockContext ec)
545 // A parameter is not hoisted when used directly as ET
547 HoistedVariableReference = null;
549 if ((modFlags & Modifier.ISBYREF) != 0)
550 ec.Report.Error (1951, Location, "An expression tree parameter cannot use `ref' or `out' modifier");
552 LocalInfo variable = ec.CurrentBlock.AddTemporaryVariable (
553 ResolveParameterExpressionType (ec, Location), Location);
554 variable.Resolve (ec);
556 expr_tree_variable = new LocalVariableReference (
557 ec.CurrentBlock, variable.Name, Location, variable, false);
559 Arguments arguments = new Arguments (2);
560 arguments.Add (new Argument (new TypeOf (
561 new TypeExpression (parameter_type, Location), Location)));
562 arguments.Add (new Argument (new StringConstant (Name, Location)));
563 return new SimpleAssign (ExpressionTreeVariableReference (),
564 Expression.CreateExpressionFactoryCall (ec, "Parameter", null, arguments, Location));
567 public Expression DefaultValue {
568 get { return default_expr; }
569 set { default_expr = value; }
572 public void Emit (EmitContext ec)
574 int arg_idx = idx;
575 if (!ec.IsStatic)
576 arg_idx++;
578 ParameterReference.EmitLdArg (ec.ig, arg_idx);
581 public void EmitAssign (EmitContext ec)
583 int arg_idx = idx;
584 if (!ec.IsStatic)
585 arg_idx++;
587 if (arg_idx <= 255)
588 ec.ig.Emit (OpCodes.Starg_S, (byte) arg_idx);
589 else
590 ec.ig.Emit (OpCodes.Starg, arg_idx);
593 public void EmitAddressOf (EmitContext ec)
595 int arg_idx = idx;
597 if (!ec.IsStatic)
598 arg_idx++;
600 bool is_ref = (ModFlags & Modifier.ISBYREF) != 0;
601 if (is_ref) {
602 ParameterReference.EmitLdArg (ec.ig, arg_idx);
603 } else {
604 if (arg_idx <= 255)
605 ec.ig.Emit (OpCodes.Ldarga_S, (byte) arg_idx);
606 else
607 ec.ig.Emit (OpCodes.Ldarga, arg_idx);
611 public Expression ExpressionTreeVariableReference ()
613 return expr_tree_variable;
617 // System.Linq.Expressions.ParameterExpression type
619 public static TypeExpr ResolveParameterExpressionType (IMemberContext ec, Location location)
621 if (parameter_expr_tree_type != null)
622 return parameter_expr_tree_type;
624 Type p_type = TypeManager.parameter_expression_type;
625 if (p_type == null) {
626 p_type = TypeManager.CoreLookupType (ec.Compiler, "System.Linq.Expressions", "ParameterExpression", Kind.Class, true);
627 TypeManager.parameter_expression_type = p_type;
630 parameter_expr_tree_type = new TypeExpression (p_type, location).
631 ResolveAsTypeTerminal (ec, false);
633 return parameter_expr_tree_type;
636 public void Warning_UselessOptionalParameter (Report Report)
638 Report.Warning (1066, 1, Location,
639 "The default value specified for optional parameter `{0}' will never be used",
640 Name);
645 // Imported or resolved parameter information
647 public class ParameterData : IParameterData
649 readonly string name;
650 readonly Parameter.Modifier modifiers;
651 readonly Expression default_value;
653 public ParameterData (string name, Parameter.Modifier modifiers)
655 this.name = name;
656 this.modifiers = modifiers;
659 public ParameterData (string name, Parameter.Modifier modifiers, Expression defaultValue)
660 : this (name, modifiers)
662 this.default_value = defaultValue;
665 #region IParameterData Members
667 public Expression DefaultValue {
668 get { return default_value; }
671 public bool HasExtensionMethodModifier {
672 get { return (modifiers & Parameter.Modifier.This) != 0; }
675 public bool HasDefaultValue {
676 get { return default_value != null; }
679 public Parameter.Modifier ModFlags {
680 get { return modifiers & ~Parameter.Modifier.This; }
683 public string Name {
684 get { return name; }
687 #endregion
690 public abstract class AParametersCollection
692 protected bool has_arglist;
693 protected bool has_params;
695 // Null object pattern
696 protected IParameterData [] parameters;
697 protected Type [] types;
699 public int Count {
700 get { return parameters.Length; }
703 public Type ExtensionMethodType {
704 get {
705 if (Count == 0)
706 return null;
708 return FixedParameters [0].HasExtensionMethodModifier ?
709 types [0] : null;
713 public IParameterData [] FixedParameters {
714 get {
715 return parameters;
719 public static ParameterAttributes GetParameterAttribute (Parameter.Modifier modFlags)
721 return (modFlags & Parameter.Modifier.OUT) == Parameter.Modifier.OUT ?
722 ParameterAttributes.Out : ParameterAttributes.None;
725 public Type [] GetEmitTypes ()
727 Type [] types = null;
728 if (has_arglist) {
729 if (Count == 1)
730 return Type.EmptyTypes;
732 types = new Type [Count - 1];
733 Array.Copy (Types, types, types.Length);
736 for (int i = 0; i < Count; ++i) {
737 if ((FixedParameters [i].ModFlags & Parameter.Modifier.ISBYREF) == 0)
738 continue;
740 if (types == null)
741 types = (Type []) Types.Clone ();
743 types [i] = TypeManager.GetReferenceType (types [i]);
746 if (types == null)
747 types = Types;
749 return types;
753 // Returns the parameter information based on the name
755 public int GetParameterIndexByName (string name)
757 for (int idx = 0; idx < Count; ++idx) {
758 if (parameters [idx].Name == name)
759 return idx;
762 return -1;
765 public string GetSignatureForError ()
767 StringBuilder sb = new StringBuilder ("(");
768 for (int i = 0; i < Count; ++i) {
769 if (i != 0)
770 sb.Append (", ");
771 sb.Append (ParameterDesc (i));
773 sb.Append (')');
774 return sb.ToString ();
777 public bool HasArglist {
778 get { return has_arglist; }
781 public bool HasExtensionMethodType {
782 get {
783 if (Count == 0)
784 return false;
786 return FixedParameters [0].HasExtensionMethodModifier;
790 public bool HasParams {
791 get { return has_params; }
794 public bool IsEmpty {
795 get { return parameters.Length == 0; }
798 public string ParameterDesc (int pos)
800 if (types == null || types [pos] == null)
801 return ((Parameter)FixedParameters [pos]).GetSignatureForError ();
803 string type = TypeManager.CSharpName (types [pos]);
804 if (FixedParameters [pos].HasExtensionMethodModifier)
805 return "this " + type;
807 Parameter.Modifier mod = FixedParameters [pos].ModFlags;
808 if (mod == 0)
809 return type;
811 return Parameter.GetModifierSignature (mod) + " " + type;
814 public Type[] Types {
815 get { return types; }
816 set { types = value; }
819 #if MS_COMPATIBLE
820 public AParametersCollection InflateTypes (Type[] genArguments, Type[] argTypes)
822 AParametersCollection p = (AParametersCollection) MemberwiseClone (); // Clone ();
824 for (int i = 0; i < Count; ++i) {
825 if (types[i].IsGenericType) {
826 Type[] gen_arguments_open = new Type[types[i].GetGenericTypeDefinition ().GetGenericArguments ().Length];
827 Type[] gen_arguments = types[i].GetGenericArguments ();
828 for (int ii = 0; ii < gen_arguments_open.Length; ++ii) {
829 if (gen_arguments[ii].IsGenericParameter) {
830 Type t = argTypes[gen_arguments[ii].GenericParameterPosition];
831 gen_arguments_open[ii] = t;
832 } else
833 gen_arguments_open[ii] = gen_arguments[ii];
836 p.types[i] = types[i].GetGenericTypeDefinition ().MakeGenericType (gen_arguments_open);
837 continue;
840 if (types[i].IsGenericParameter) {
841 Type gen_argument = argTypes[types[i].GenericParameterPosition];
842 p.types[i] = gen_argument;
843 continue;
847 return p;
849 #endif
853 // A collection of imported or resolved parameters
855 public class ParametersImported : AParametersCollection
857 ParametersImported (AParametersCollection param, Type[] types)
859 this.parameters = param.FixedParameters;
860 this.types = types;
861 has_arglist = param.HasArglist;
862 has_params = param.HasParams;
865 ParametersImported (IParameterData [] parameters, Type [] types, bool hasArglist, bool hasParams)
867 this.parameters = parameters;
868 this.types = types;
869 this.has_arglist = hasArglist;
870 this.has_params = hasParams;
873 public ParametersImported (IParameterData [] param, Type[] types)
875 this.parameters = param;
876 this.types = types;
879 public static AParametersCollection Create (MethodBase method)
881 return Create (method.GetParameters (), method);
885 // Generic method parameters importer, param is shared between all instances
887 public static AParametersCollection Create (AParametersCollection param, MethodBase method)
889 if (param.IsEmpty)
890 return param;
892 ParameterInfo [] pi = method.GetParameters ();
893 Type [] types = new Type [pi.Length];
894 for (int i = 0; i < types.Length; i++) {
895 Type t = pi [i].ParameterType;
896 if (t.IsByRef)
897 t = TypeManager.GetElementType (t);
899 types [i] = TypeManager.TypeToCoreType (t);
902 return new ParametersImported (param, types);
906 // Imports SRE parameters
908 public static AParametersCollection Create (ParameterInfo [] pi, MethodBase method)
910 int varargs = method != null && (method.CallingConvention & CallingConventions.VarArgs) != 0 ? 1 : 0;
912 if (pi.Length == 0 && varargs == 0)
913 return ParametersCompiled.EmptyReadOnlyParameters;
915 Type [] types = new Type [pi.Length + varargs];
916 IParameterData [] par = new IParameterData [pi.Length + varargs];
917 bool is_params = false;
918 PredefinedAttribute extension_attr = PredefinedAttributes.Get.Extension;
919 PredefinedAttribute param_attr = PredefinedAttributes.Get.ParamArray;
920 for (int i = 0; i < pi.Length; i++) {
921 types [i] = TypeManager.TypeToCoreType (pi [i].ParameterType);
923 ParameterInfo p = pi [i];
924 Parameter.Modifier mod = 0;
925 Expression default_value = null;
926 if (types [i].IsByRef) {
927 if ((p.Attributes & (ParameterAttributes.Out | ParameterAttributes.In)) == ParameterAttributes.Out)
928 mod = Parameter.Modifier.OUT;
929 else
930 mod = Parameter.Modifier.REF;
933 // Strip reference wrapping
935 types [i] = TypeManager.GetElementType (types [i]);
936 } else if (i == 0 && extension_attr.IsDefined && method != null && method.IsStatic &&
937 (method.DeclaringType.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute &&
938 method.IsDefined (extension_attr.Type, false)) {
939 mod = Parameter.Modifier.This;
940 } else {
941 if (i >= pi.Length - 2 && types[i].IsArray) {
942 if (p.IsDefined (param_attr.Type, false)) {
943 mod = Parameter.Modifier.PARAMS;
944 is_params = true;
948 if (!is_params && p.IsOptional) {
949 object value = p.DefaultValue;
950 if (value == Missing.Value) {
951 default_value = EmptyExpression.Null;
952 } else if (value == null) {
953 default_value = new NullLiteral (Location.Null);
954 } else {
955 default_value = Constant.CreateConstant (value.GetType (), value, Location.Null);
960 par [i] = new ParameterData (p.Name, mod, default_value);
963 if (varargs != 0) {
964 par [par.Length - 1] = new ArglistParameter (Location.Null);
965 types [types.Length - 1] = InternalType.Arglist;
968 return method != null ?
969 new ParametersImported (par, types, varargs != 0, is_params) :
970 new ParametersImported (par, types);
974 /// <summary>
975 /// Represents the methods parameters
976 /// </summary>
977 public class ParametersCompiled : AParametersCollection
979 public static readonly ParametersCompiled EmptyReadOnlyParameters = new ParametersCompiled ();
981 // Used by C# 2.0 delegates
982 public static readonly ParametersCompiled Undefined = new ParametersCompiled ();
984 private ParametersCompiled ()
986 parameters = new Parameter [0];
987 types = Type.EmptyTypes;
990 private ParametersCompiled (Parameter [] parameters, Type [] types)
992 this.parameters = parameters;
993 this.types = types;
996 public ParametersCompiled (params Parameter[] parameters)
998 if (parameters == null)
999 throw new ArgumentException ("Use EmptyReadOnlyParameters");
1001 this.parameters = parameters;
1002 int count = parameters.Length;
1004 if (count == 0)
1005 return;
1007 if (count == 1) {
1008 has_params = (parameters [0].ModFlags & Parameter.Modifier.PARAMS) != 0;
1009 return;
1012 for (int i = 0; i < count; i++){
1013 string base_name = parameters [i].Name;
1014 has_params |= (parameters [i].ModFlags & Parameter.Modifier.PARAMS) != 0;
1016 for (int j = i + 1; j < count; j++){
1017 if (base_name != parameters [j].Name)
1018 continue;
1020 ErrorDuplicateName (parameters[i], RootContext.ToplevelTypes.Compiler.Report);
1021 i = j;
1026 public ParametersCompiled (Parameter [] parameters, bool has_arglist) :
1027 this (parameters)
1029 this.has_arglist = has_arglist;
1032 public static ParametersCompiled CreateFullyResolved (Parameter p, Type type)
1034 return new ParametersCompiled (new Parameter [] { p }, new Type [] { type });
1037 public static ParametersCompiled CreateFullyResolved (Parameter[] parameters, Type[] types)
1039 return new ParametersCompiled (parameters, types);
1042 public static ParametersCompiled MergeGenerated (ParametersCompiled userParams, bool checkConflicts, Parameter compilerParams, Type compilerTypes)
1044 return MergeGenerated (userParams, checkConflicts,
1045 new Parameter [] { compilerParams },
1046 new Type [] { compilerTypes });
1050 // Use this method when you merge compiler generated parameters with user parameters
1052 public static ParametersCompiled MergeGenerated (ParametersCompiled userParams, bool checkConflicts, Parameter[] compilerParams, Type[] compilerTypes)
1054 Parameter[] all_params = new Parameter [userParams.Count + compilerParams.Length];
1055 userParams.FixedParameters.CopyTo(all_params, 0);
1057 Type [] all_types;
1058 if (userParams.types != null) {
1059 all_types = new Type [all_params.Length];
1060 userParams.Types.CopyTo (all_types, 0);
1061 } else {
1062 all_types = null;
1065 int last_filled = userParams.Count;
1066 int index = 0;
1067 foreach (Parameter p in compilerParams) {
1068 for (int i = 0; i < last_filled; ++i) {
1069 while (p.Name == all_params [i].Name) {
1070 if (checkConflicts && i < userParams.Count) {
1071 RootContext.ToplevelTypes.Compiler.Report.Error (316, userParams[i].Location,
1072 "The parameter name `{0}' conflicts with a compiler generated name", p.Name);
1074 p.Name = '_' + p.Name;
1077 all_params [last_filled] = p;
1078 if (all_types != null)
1079 all_types [last_filled] = compilerTypes [index++];
1080 ++last_filled;
1083 ParametersCompiled parameters = new ParametersCompiled (all_params, all_types);
1084 parameters.has_params = userParams.has_params;
1085 return parameters;
1088 protected virtual void ErrorDuplicateName (Parameter p, Report Report)
1090 Report.Error (100, p.Location, "The parameter name `{0}' is a duplicate", p.Name);
1093 public bool Resolve (IMemberContext ec)
1095 if (types != null)
1096 return true;
1098 types = new Type [Count];
1100 bool ok = true;
1101 Parameter p;
1102 for (int i = 0; i < FixedParameters.Length; ++i) {
1103 p = this [i];
1104 Type t = p.Resolve (ec);
1105 if (t == null) {
1106 ok = false;
1107 continue;
1110 types [i] = t;
1113 return ok;
1116 public void ResolveVariable ()
1118 for (int i = 0; i < FixedParameters.Length; ++i) {
1119 this [i].ResolveVariable (i);
1123 public CallingConventions CallingConvention
1125 get {
1126 if (HasArglist)
1127 return CallingConventions.VarArgs;
1128 else
1129 return CallingConventions.Standard;
1133 // Define each type attribute (in/out/ref) and
1134 // the argument names.
1135 public void ApplyAttributes (MethodBase builder)
1137 if (Count == 0)
1138 return;
1140 MethodBuilder mb = builder as MethodBuilder;
1141 ConstructorBuilder cb = builder as ConstructorBuilder;
1143 for (int i = 0; i < Count; i++) {
1144 this [i].ApplyAttributes (mb, cb, i + 1);
1148 public void VerifyClsCompliance ()
1150 foreach (Parameter p in FixedParameters)
1151 p.IsClsCompliant ();
1154 public Parameter this [int pos] {
1155 get { return (Parameter) parameters [pos]; }
1158 public Expression CreateExpressionTree (BlockContext ec, Location loc)
1160 ArrayList initializers = new ArrayList (Count);
1161 foreach (Parameter p in FixedParameters) {
1163 // Each parameter expression is stored to local variable
1164 // to save some memory when referenced later.
1166 StatementExpression se = new StatementExpression (p.CreateExpressionTreeVariable (ec));
1167 if (se.Resolve (ec))
1168 ec.CurrentBlock.AddScopeStatement (se);
1170 initializers.Add (p.ExpressionTreeVariableReference ());
1173 return new ArrayCreation (
1174 Parameter.ResolveParameterExpressionType (ec, loc),
1175 "[]", initializers, loc);
1178 public ParametersCompiled Clone ()
1180 ParametersCompiled p = (ParametersCompiled) MemberwiseClone ();
1182 p.parameters = new IParameterData [parameters.Length];
1183 for (int i = 0; i < Count; ++i)
1184 p.parameters [i] = this [i].Clone ();
1186 return p;