2010-04-06 Jb Evain <jbevain@novell.com>
[mcs.git] / mcs / parameter.cs
blob26aa628a1ee1812b811fd775a57a5b638476a045
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.Text;
18 namespace Mono.CSharp {
20 /// <summary>
21 /// Abstract Base class for parameters of a method.
22 /// </summary>
23 public abstract class ParameterBase : Attributable
25 protected ParameterBuilder builder;
27 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
29 #if false
30 if (a.Type == pa.MarshalAs) {
31 UnmanagedMarshal marshal = a.GetMarshal (this);
32 if (marshal != null) {
33 builder.SetMarshal (marshal);
35 return;
37 #endif
38 if (a.HasSecurityAttribute) {
39 a.Error_InvalidSecurityParent ();
40 return;
43 if (a.Type == pa.Dynamic) {
44 a.Error_MisusedDynamicAttribute ();
45 return;
48 builder.SetCustomAttribute (cb);
51 public ParameterBuilder Builder {
52 get {
53 return builder;
57 public override bool IsClsComplianceRequired()
59 return false;
63 /// <summary>
64 /// Class for applying custom attributes on the return type
65 /// </summary>
66 public class ReturnParameter : ParameterBase
68 MemberCore method;
70 // TODO: merge method and mb
71 public ReturnParameter (MemberCore method, MethodBuilder mb, Location location)
73 this.method = method;
74 try {
75 builder = mb.DefineParameter (0, ParameterAttributes.None, "");
77 catch (ArgumentOutOfRangeException) {
78 method.Compiler.Report.RuntimeMissingSupport (location, "custom attributes on the return type");
82 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
84 if (a.Type == pa.CLSCompliant) {
85 method.Compiler.Report.Warning (3023, 1, a.Location,
86 "CLSCompliant attribute has no meaning when applied to return types. Try putting it on the method instead");
89 // This occurs after Warning -28
90 if (builder == null)
91 return;
93 base.ApplyAttributeBuilder (a, cb, pa);
96 public override AttributeTargets AttributeTargets {
97 get {
98 return AttributeTargets.ReturnValue;
102 /// <summary>
103 /// Is never called
104 /// </summary>
105 public override string[] ValidAttributeTargets {
106 get {
107 return null;
112 /// <summary>
113 /// Class for applying custom attributes on the implicit parameter type
114 /// of the 'set' method in properties, and the 'add' and 'remove' methods in events.
115 /// </summary>
116 ///
117 // TODO: should use more code from Parameter.ApplyAttributeBuilder
118 public class ImplicitParameter : ParameterBase {
119 public ImplicitParameter (MethodBuilder mb)
121 builder = mb.DefineParameter (1, ParameterAttributes.None, "value");
124 public override AttributeTargets AttributeTargets {
125 get {
126 return AttributeTargets.Parameter;
130 /// <summary>
131 /// Is never called
132 /// </summary>
133 public override string[] ValidAttributeTargets {
134 get {
135 return null;
140 public class ImplicitLambdaParameter : Parameter
142 public ImplicitLambdaParameter (string name, Location loc)
143 : base (null, name, Modifier.NONE, null, loc)
147 public override Type Resolve (IMemberContext ec)
149 if (parameter_type == null)
150 throw new InternalErrorException ("A type of implicit lambda parameter `{0}' is not set",
151 Name);
153 return parameter_type;
156 public Type Type {
157 set { parameter_type = value; }
161 public class ParamsParameter : Parameter {
162 public ParamsParameter (FullNamedExpression type, string name, Attributes attrs, Location loc):
163 base (type, name, Parameter.Modifier.PARAMS, attrs, loc)
167 public override Type Resolve (IMemberContext ec)
169 if (base.Resolve (ec) == null)
170 return null;
172 if (!parameter_type.IsArray || parameter_type.GetArrayRank () != 1) {
173 ec.Compiler.Report.Error (225, Location, "The params parameter must be a single dimensional array");
174 return null;
177 return parameter_type;
180 public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
182 base.ApplyAttributes (mb, cb, index);
183 PredefinedAttributes.Get.ParamArray.EmitAttribute (builder);
187 public class ArglistParameter : Parameter {
188 // Doesn't have proper type because it's never chosen for better conversion
189 public ArglistParameter (Location loc) :
190 base (null, String.Empty, Parameter.Modifier.NONE, null, loc)
194 public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
196 // Nothing to do
199 public override bool CheckAccessibility (InterfaceMemberBase member)
201 return true;
204 public override Type Resolve (IMemberContext ec)
206 return InternalType.Arglist;
209 public override string GetSignatureForError ()
211 return "__arglist";
215 public interface IParameterData
217 Expression DefaultValue { get; }
218 bool HasExtensionMethodModifier { get; }
219 bool HasDefaultValue { get; }
220 Parameter.Modifier ModFlags { get; }
221 string Name { get; }
225 // Parameter information created by parser
227 public class Parameter : ParameterBase, IParameterData, ILocalVariable {
228 [Flags]
229 public enum Modifier : byte {
230 NONE = 0,
231 REF = REFMASK | ISBYREF,
232 OUT = OUTMASK | ISBYREF,
233 PARAMS = 4,
234 // This is a flag which says that it's either REF or OUT.
235 ISBYREF = 8,
236 REFMASK = 32,
237 OUTMASK = 64,
238 This = 128
241 static string[] attribute_targets = new string [] { "param" };
243 protected FullNamedExpression TypeName;
244 readonly Modifier modFlags;
245 string name;
246 Expression default_expr;
247 protected Type parameter_type;
248 public readonly Location Location;
249 int idx;
250 public bool HasAddressTaken;
252 Expression expr_tree_variable;
253 static TypeExpr parameter_expr_tree_type;
255 HoistedVariable hoisted_variant;
257 public Parameter (FullNamedExpression type, string name, Modifier mod, Attributes attrs, Location loc)
259 this.name = name;
260 modFlags = mod;
261 Location = loc;
262 TypeName = type;
264 // Only assign, attributes will be attached during resolve
265 base.attributes = attrs;
268 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
270 if (a.Type == pa.In && ModFlags == Modifier.OUT) {
271 a.Report.Error (36, a.Location, "An out parameter cannot have the `In' attribute");
272 return;
275 if (a.Type == pa.ParamArray) {
276 a.Report.Error (674, a.Location, "Do not use `System.ParamArrayAttribute'. Use the `params' keyword instead");
277 return;
280 if (a.Type == PredefinedAttributes.Get.Out && (ModFlags & Modifier.REF) == Modifier.REF &&
281 !OptAttributes.Contains (pa.In)) {
282 a.Report.Error (662, a.Location,
283 "Cannot specify only `Out' attribute on a ref parameter. Use both `In' and `Out' attributes or neither");
284 return;
287 if (a.Type == pa.CLSCompliant) {
288 a.Report.Warning (3022, 1, a.Location, "CLSCompliant attribute has no meaning when applied to parameters. Try putting it on the method instead");
291 if (HasDefaultValue && (a.Type == pa.DefaultParameterValue || a.Type == pa.OptionalParameter)) {
292 a.Report.Error (1745, a.Location,
293 "Cannot specify `{0}' attribute on optional parameter `{1}'",
294 TypeManager.CSharpName (a.Type).Replace ("Attribute", ""), Name);
295 return;
298 if (a.Type == pa.DefaultParameterValue) {
299 object val = a.GetParameterDefaultValue ();
300 if (val != null) {
301 Type t = val.GetType ();
302 if (t.IsArray || TypeManager.IsSubclassOf (t, TypeManager.type_type)) {
303 if (parameter_type == TypeManager.object_type) {
304 if (!t.IsArray)
305 t = TypeManager.type_type;
307 a.Report.Error (1910, a.Location, "Argument of type `{0}' is not applicable for the DefaultParameterValue attribute",
308 TypeManager.CSharpName (t));
309 } else {
310 a.Report.Error (1909, a.Location, "The DefaultParameterValue attribute is not applicable on parameters of type `{0}'",
311 TypeManager.CSharpName (parameter_type)); ;
313 return;
317 if (parameter_type == TypeManager.object_type ||
318 (val == null && !TypeManager.IsGenericParameter (parameter_type) && TypeManager.IsReferenceType (parameter_type)) ||
319 (val != null && TypeManager.TypeToCoreType (val.GetType ()) == parameter_type))
320 builder.SetConstant (val);
321 else
322 a.Report.Error (1908, a.Location, "The type of the default value should match the type of the parameter");
323 return;
326 base.ApplyAttributeBuilder (a, cb, pa);
329 public virtual bool CheckAccessibility (InterfaceMemberBase member)
331 if (parameter_type == null || TypeManager.IsGenericParameter (parameter_type))
332 return true;
334 return member.IsAccessibleAs (parameter_type);
337 // <summary>
338 // Resolve is used in method definitions
339 // </summary>
340 public virtual Type Resolve (IMemberContext rc)
342 if (parameter_type != null)
343 return parameter_type;
345 if (attributes != null)
346 attributes.AttachTo (this, rc);
348 TypeExpr texpr = TypeName.ResolveAsTypeTerminal (rc, false);
349 if (texpr == null)
350 return null;
352 parameter_type = texpr.Type;
354 // Ignore all checks for dummy members
355 AbstractPropertyEventMethod pem = rc as AbstractPropertyEventMethod;
356 if (pem != null && pem.IsDummy)
357 return parameter_type;
359 if (default_expr != null)
360 default_expr = ResolveDefaultValue (new ResolveContext (rc));
362 if ((modFlags & Parameter.Modifier.ISBYREF) != 0 &&
363 TypeManager.IsSpecialType (parameter_type)) {
364 rc.Compiler.Report.Error (1601, Location, "Method or delegate parameter cannot be of type `{0}'",
365 GetSignatureForError ());
366 return null;
369 TypeManager.CheckTypeVariance (parameter_type,
370 (modFlags & Parameter.Modifier.ISBYREF) != 0 ? Variance.None : Variance.Contravariant,
371 rc);
373 if (TypeManager.IsGenericParameter (parameter_type))
374 return parameter_type;
376 if ((parameter_type.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) {
377 rc.Compiler.Report.Error (721, Location, "`{0}': static types cannot be used as parameters",
378 texpr.GetSignatureForError ());
379 return parameter_type;
382 if ((modFlags & Modifier.This) != 0 && (parameter_type.IsPointer || TypeManager.IsDynamicType (parameter_type))) {
383 rc.Compiler.Report.Error (1103, Location, "The extension method cannot be of type `{0}'",
384 TypeManager.CSharpName (parameter_type));
387 return parameter_type;
390 Expression ResolveDefaultValue (ResolveContext rc)
392 default_expr = default_expr.Resolve (rc);
393 if (default_expr == null)
394 return null;
396 if (!(default_expr is Constant || default_expr is DefaultValueExpression)) {
397 if (TypeManager.IsNullableType (parameter_type)) {
398 rc.Compiler.Report.Error (1770, default_expr.Location,
399 "The expression being assigned to nullable optional parameter `{0}' must be default value",
400 Name);
401 } else {
402 rc.Compiler.Report.Error (1736, default_expr.Location,
403 "The expression being assigned to optional parameter `{0}' must be a constant or default value",
404 Name);
407 return null;
410 if (TypeManager.IsEqual (default_expr.Type, parameter_type))
411 return default_expr;
413 if (TypeManager.IsNullableType (parameter_type)) {
414 if (Convert.ImplicitNulableConversion (rc, default_expr, parameter_type) != null)
415 return default_expr;
416 } else {
417 var res = Convert.ImplicitConversionStandard (rc, default_expr, parameter_type, default_expr.Location);
418 if (res != null) {
419 if (!default_expr.IsNull && TypeManager.IsReferenceType (parameter_type) && parameter_type != TypeManager.string_type) {
420 rc.Compiler.Report.Error (1763, default_expr.Location,
421 "Optional parameter `{0}' of type `{1}' can only be initialized with `null'",
422 Name, GetSignatureForError ());
424 return null;
427 return res;
431 rc.Compiler.Report.Error (1750, Location,
432 "Optional parameter expression of type `{0}' cannot be converted to parameter type `{1}'",
433 TypeManager.CSharpName (default_expr.Type), GetSignatureForError ());
435 return null;
438 public void ResolveVariable (int idx)
440 this.idx = idx;
443 public bool HasDefaultValue {
444 get { return default_expr != null; }
447 public bool HasExtensionMethodModifier {
448 get { return (modFlags & Modifier.This) != 0; }
452 // Hoisted parameter variant
454 public HoistedVariable HoistedVariant {
455 get {
456 return hoisted_variant;
458 set {
459 hoisted_variant = value;
463 public Modifier ModFlags {
464 get { return modFlags & ~Modifier.This; }
467 public string Name {
468 get { return name; }
469 set { name = value; }
472 ParameterAttributes Attributes {
473 get { return ParametersCompiled.GetParameterAttribute (modFlags) |
474 (HasDefaultValue ? ParameterAttributes.Optional : ParameterAttributes.None); }
477 public override AttributeTargets AttributeTargets {
478 get {
479 return AttributeTargets.Parameter;
483 public virtual string GetSignatureForError ()
485 string type_name;
486 if (parameter_type != null)
487 type_name = TypeManager.CSharpName (parameter_type);
488 else
489 type_name = TypeName.GetSignatureForError ();
491 string mod = GetModifierSignature (modFlags);
492 if (mod.Length > 0)
493 return String.Concat (mod, " ", type_name);
495 return type_name;
498 public static string GetModifierSignature (Modifier mod)
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 "";
514 public void IsClsCompliant (IMemberContext ctx)
516 if (AttributeTester.IsClsCompliant (parameter_type))
517 return;
519 ctx.Compiler.Report.Warning (3001, 1, Location,
520 "Argument type `{0}' is not CLS-compliant", GetSignatureForError ());
523 public virtual void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
525 if (mb == null)
526 builder = cb.DefineParameter (index, Attributes, Name);
527 else
528 builder = mb.DefineParameter (index, Attributes, Name);
530 if (OptAttributes != null)
531 OptAttributes.Emit ();
533 if (HasDefaultValue) {
535 // Emit constant values for true constants only, the other
536 // constant-like expressions will rely on default value expression
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 ());
548 if (TypeManager.IsDynamicType (parameter_type)) {
549 PredefinedAttributes.Get.Dynamic.EmitAttribute (builder);
550 } else {
551 var trans_flags = TypeManager.HasDynamicTypeUsed (parameter_type);
552 if (trans_flags != null) {
553 var pa = PredefinedAttributes.Get.DynamicTransform;
554 if (pa.Constructor != null || pa.ResolveConstructor (Location, TypeManager.bool_type.MakeArrayType ())) {
555 builder.SetCustomAttribute (
556 new CustomAttributeBuilder (pa.Constructor, new object [] { trans_flags }));
562 public override string[] ValidAttributeTargets {
563 get {
564 return attribute_targets;
568 public Parameter Clone ()
570 Parameter p = (Parameter) MemberwiseClone ();
571 if (attributes != null)
572 p.attributes = attributes.Clone ();
574 return p;
577 public ExpressionStatement CreateExpressionTreeVariable (BlockContext ec)
579 if ((modFlags & Modifier.ISBYREF) != 0)
580 ec.Report.Error (1951, Location, "An expression tree parameter cannot use `ref' or `out' modifier");
582 expr_tree_variable = new TemporaryVariable (ResolveParameterExpressionType (ec, Location).Type, Location);
583 expr_tree_variable = expr_tree_variable.Resolve (ec);
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));
593 public Expression DefaultValue {
594 get { return default_expr; }
595 set { default_expr = value; }
598 public void Emit (EmitContext ec)
600 int arg_idx = idx;
601 if (!ec.IsStatic)
602 arg_idx++;
604 ParameterReference.EmitLdArg (ec.ig, arg_idx);
607 public void EmitAssign (EmitContext ec)
609 int arg_idx = idx;
610 if (!ec.IsStatic)
611 arg_idx++;
613 if (arg_idx <= 255)
614 ec.ig.Emit (OpCodes.Starg_S, (byte) arg_idx);
615 else
616 ec.ig.Emit (OpCodes.Starg, arg_idx);
619 public void EmitAddressOf (EmitContext ec)
621 int arg_idx = idx;
623 if (!ec.IsStatic)
624 arg_idx++;
626 bool is_ref = (ModFlags & Modifier.ISBYREF) != 0;
627 if (is_ref) {
628 ParameterReference.EmitLdArg (ec.ig, arg_idx);
629 } else {
630 if (arg_idx <= 255)
631 ec.ig.Emit (OpCodes.Ldarga_S, (byte) arg_idx);
632 else
633 ec.ig.Emit (OpCodes.Ldarga, arg_idx);
637 public Expression ExpressionTreeVariableReference ()
639 return expr_tree_variable;
643 // System.Linq.Expressions.ParameterExpression type
645 public static TypeExpr ResolveParameterExpressionType (IMemberContext ec, Location location)
647 if (parameter_expr_tree_type != null)
648 return parameter_expr_tree_type;
650 Type p_type = TypeManager.parameter_expression_type;
651 if (p_type == null) {
652 p_type = TypeManager.CoreLookupType (ec.Compiler, "System.Linq.Expressions", "ParameterExpression", MemberKind.Class, true);
653 TypeManager.parameter_expression_type = p_type;
656 parameter_expr_tree_type = new TypeExpression (p_type, location).
657 ResolveAsTypeTerminal (ec, false);
659 return parameter_expr_tree_type;
662 public void Warning_UselessOptionalParameter (Report Report)
664 Report.Warning (1066, 1, Location,
665 "The default value specified for optional parameter `{0}' will never be used",
666 Name);
671 // Imported or resolved parameter information
673 public class ParameterData : IParameterData
675 readonly string name;
676 readonly Parameter.Modifier modifiers;
677 readonly Expression default_value;
679 public ParameterData (string name, Parameter.Modifier modifiers)
681 this.name = name;
682 this.modifiers = modifiers;
685 public ParameterData (string name, Parameter.Modifier modifiers, Expression defaultValue)
686 : this (name, modifiers)
688 this.default_value = defaultValue;
691 #region IParameterData Members
693 public Expression DefaultValue {
694 get { return default_value; }
697 public bool HasExtensionMethodModifier {
698 get { return (modifiers & Parameter.Modifier.This) != 0; }
701 public bool HasDefaultValue {
702 get { return default_value != null; }
705 public Parameter.Modifier ModFlags {
706 get { return modifiers & ~Parameter.Modifier.This; }
709 public string Name {
710 get { return name; }
713 #endregion
716 public abstract class AParametersCollection
718 protected bool has_arglist;
719 protected bool has_params;
721 // Null object pattern
722 protected IParameterData [] parameters;
723 protected Type [] types;
725 public ParametersCompiled AsCompiled {
726 get { return (ParametersCompiled) this; }
729 public CallingConventions CallingConvention {
730 get {
731 return has_arglist ?
732 CallingConventions.VarArgs :
733 CallingConventions.Standard;
737 public int Count {
738 get { return parameters.Length; }
741 public Type ExtensionMethodType {
742 get {
743 if (Count == 0)
744 return null;
746 return FixedParameters [0].HasExtensionMethodModifier ?
747 types [0] : null;
751 public IParameterData [] FixedParameters {
752 get {
753 return parameters;
757 public static ParameterAttributes GetParameterAttribute (Parameter.Modifier modFlags)
759 return (modFlags & Parameter.Modifier.OUT) == Parameter.Modifier.OUT ?
760 ParameterAttributes.Out : ParameterAttributes.None;
763 public Type [] GetEmitTypes ()
765 Type [] types = null;
766 if (has_arglist) {
767 if (Count == 1)
768 return Type.EmptyTypes;
770 types = new Type [Count - 1];
771 Array.Copy (Types, types, types.Length);
774 for (int i = 0; i < Count; ++i) {
775 if ((FixedParameters [i].ModFlags & Parameter.Modifier.ISBYREF) == 0)
776 continue;
778 if (types == null)
779 types = (Type []) Types.Clone ();
781 types [i] = TypeManager.GetReferenceType (types [i]);
784 if (types == null)
785 types = Types;
787 return types;
791 // Returns the parameter information based on the name
793 public int GetParameterIndexByName (string name)
795 for (int idx = 0; idx < Count; ++idx) {
796 if (parameters [idx].Name == name)
797 return idx;
800 return -1;
803 public string GetSignatureForError ()
805 StringBuilder sb = new StringBuilder ("(");
806 for (int i = 0; i < Count; ++i) {
807 if (i != 0)
808 sb.Append (", ");
809 sb.Append (ParameterDesc (i));
811 sb.Append (')');
812 return sb.ToString ();
815 public bool HasArglist {
816 get { return has_arglist; }
819 public bool HasExtensionMethodType {
820 get {
821 if (Count == 0)
822 return false;
824 return FixedParameters [0].HasExtensionMethodModifier;
828 public bool HasParams {
829 get { return has_params; }
832 public bool IsEmpty {
833 get { return parameters.Length == 0; }
836 public string ParameterDesc (int pos)
838 if (types == null || types [pos] == null)
839 return ((Parameter)FixedParameters [pos]).GetSignatureForError ();
841 string type = TypeManager.CSharpName (types [pos]);
842 if (FixedParameters [pos].HasExtensionMethodModifier)
843 return "this " + type;
845 Parameter.Modifier mod = FixedParameters [pos].ModFlags;
846 if (mod == 0)
847 return type;
849 return Parameter.GetModifierSignature (mod) + " " + type;
852 public Type[] Types {
853 get { return types; }
854 set { types = value; }
857 #if MS_COMPATIBLE
858 public AParametersCollection InflateTypes (Type[] genArguments, Type[] argTypes)
860 AParametersCollection p = (AParametersCollection) MemberwiseClone (); // Clone ();
862 for (int i = 0; i < Count; ++i) {
863 if (types[i].IsGenericType) {
864 Type[] gen_arguments_open = new Type[types[i].GetGenericTypeDefinition ().GetGenericArguments ().Length];
865 Type[] gen_arguments = types[i].GetGenericArguments ();
866 for (int ii = 0; ii < gen_arguments_open.Length; ++ii) {
867 if (gen_arguments[ii].IsGenericParameter) {
868 Type t = argTypes[gen_arguments[ii].GenericParameterPosition];
869 gen_arguments_open[ii] = t;
870 } else
871 gen_arguments_open[ii] = gen_arguments[ii];
874 p.types[i] = types[i].GetGenericTypeDefinition ().MakeGenericType (gen_arguments_open);
875 continue;
878 if (types[i].IsGenericParameter) {
879 Type gen_argument = argTypes[types[i].GenericParameterPosition];
880 p.types[i] = gen_argument;
881 continue;
885 return p;
887 #endif
891 // A collection of imported or resolved parameters
893 public class ParametersImported : AParametersCollection
895 ParametersImported (AParametersCollection param, Type[] types)
897 this.parameters = param.FixedParameters;
898 this.types = types;
899 has_arglist = param.HasArglist;
900 has_params = param.HasParams;
903 ParametersImported (IParameterData [] parameters, Type [] types, bool hasArglist, bool hasParams)
905 this.parameters = parameters;
906 this.types = types;
907 this.has_arglist = hasArglist;
908 this.has_params = hasParams;
911 public ParametersImported (IParameterData [] param, Type[] types)
913 this.parameters = param;
914 this.types = types;
917 public static AParametersCollection Create (MethodBase method)
919 return Create (method.GetParameters (), method);
923 // Generic method parameters importer, param is shared between all instances
925 public static AParametersCollection Create (AParametersCollection param, MethodBase method)
927 if (param.IsEmpty)
928 return param;
930 ParameterInfo [] pi = method.GetParameters ();
931 Type [] types = new Type [pi.Length];
932 for (int i = 0; i < types.Length; i++) {
933 Type t = pi [i].ParameterType;
934 if (t.IsByRef)
935 t = TypeManager.GetElementType (t);
937 types [i] = TypeManager.TypeToCoreType (t);
940 return new ParametersImported (param, types);
944 // Imports SRE parameters
946 public static AParametersCollection Create (ParameterInfo [] pi, MethodBase method)
948 int varargs = method != null && (method.CallingConvention & CallingConventions.VarArgs) != 0 ? 1 : 0;
950 if (pi.Length == 0 && varargs == 0)
951 return ParametersCompiled.EmptyReadOnlyParameters;
953 Type [] types = new Type [pi.Length + varargs];
954 IParameterData [] par = new IParameterData [pi.Length + varargs];
955 bool is_params = false;
956 PredefinedAttribute extension_attr = PredefinedAttributes.Get.Extension;
957 PredefinedAttribute param_attr = PredefinedAttributes.Get.ParamArray;
958 for (int i = 0; i < pi.Length; i++) {
959 types [i] = TypeManager.TypeToCoreType (pi [i].ParameterType);
961 ParameterInfo p = pi [i];
962 Parameter.Modifier mod = 0;
963 Expression default_value = null;
964 if (types [i].IsByRef) {
965 if ((p.Attributes & (ParameterAttributes.Out | ParameterAttributes.In)) == ParameterAttributes.Out)
966 mod = Parameter.Modifier.OUT;
967 else
968 mod = Parameter.Modifier.REF;
971 // Strip reference wrapping
973 types [i] = TypeManager.GetElementType (types [i]);
974 } else if (i == 0 && extension_attr.IsDefined && method != null && method.IsStatic &&
975 (method.DeclaringType.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute &&
976 method.IsDefined (extension_attr.Type, false)) {
977 mod = Parameter.Modifier.This;
978 } else {
979 if (i >= pi.Length - 2 && types[i].IsArray) {
980 if (p.IsDefined (param_attr.Type, false)) {
981 mod = Parameter.Modifier.PARAMS;
982 is_params = true;
986 if (!is_params && p.IsOptional) {
987 object value = p.DefaultValue;
988 if (value == Missing.Value) {
989 default_value = EmptyExpression.Null;
990 } else if (value == null) {
991 default_value = new NullLiteral (Location.Null);
992 } else {
993 default_value = Constant.CreateConstant (null, value.GetType (), value, Location.Null);
998 par [i] = new ParameterData (p.Name, mod, default_value);
1001 if (varargs != 0) {
1002 par [par.Length - 1] = new ArglistParameter (Location.Null);
1003 types [types.Length - 1] = InternalType.Arglist;
1006 return method != null ?
1007 new ParametersImported (par, types, varargs != 0, is_params) :
1008 new ParametersImported (par, types);
1012 /// <summary>
1013 /// Represents the methods parameters
1014 /// </summary>
1015 public class ParametersCompiled : AParametersCollection
1017 public static readonly ParametersCompiled EmptyReadOnlyParameters = new ParametersCompiled ();
1019 // Used by C# 2.0 delegates
1020 public static readonly ParametersCompiled Undefined = new ParametersCompiled ();
1022 private ParametersCompiled ()
1024 parameters = new Parameter [0];
1025 types = Type.EmptyTypes;
1028 private ParametersCompiled (Parameter [] parameters, Type [] types)
1030 this.parameters = parameters;
1031 this.types = types;
1034 public ParametersCompiled (CompilerContext ctx, params Parameter[] parameters)
1036 if (parameters == null)
1037 throw new ArgumentException ("Use EmptyReadOnlyParameters");
1039 this.parameters = parameters;
1040 int count = parameters.Length;
1042 if (count == 0)
1043 return;
1045 if (count == 1) {
1046 has_params = (parameters [0].ModFlags & Parameter.Modifier.PARAMS) != 0;
1047 return;
1050 for (int i = 0; i < count; i++){
1051 string base_name = parameters [i].Name;
1052 has_params |= (parameters [i].ModFlags & Parameter.Modifier.PARAMS) != 0;
1054 for (int j = i + 1; j < count; j++){
1055 if (base_name != parameters [j].Name)
1056 continue;
1058 ErrorDuplicateName (parameters[i], ctx.Report);
1059 i = j;
1064 public ParametersCompiled (CompilerContext ctx, Parameter [] parameters, bool has_arglist) :
1065 this (ctx, parameters)
1067 this.has_arglist = has_arglist;
1070 public static ParametersCompiled CreateFullyResolved (Parameter p, Type type)
1072 return new ParametersCompiled (new Parameter [] { p }, new Type [] { type });
1075 public static ParametersCompiled CreateFullyResolved (Parameter[] parameters, Type[] types)
1077 return new ParametersCompiled (parameters, types);
1080 public static ParametersCompiled MergeGenerated (CompilerContext ctx, ParametersCompiled userParams, bool checkConflicts, Parameter compilerParams, Type compilerTypes)
1082 return MergeGenerated (ctx, userParams, checkConflicts,
1083 new Parameter [] { compilerParams },
1084 new Type [] { compilerTypes });
1088 // Use this method when you merge compiler generated parameters with user parameters
1090 public static ParametersCompiled MergeGenerated (CompilerContext ctx, ParametersCompiled userParams, bool checkConflicts, Parameter[] compilerParams, Type[] compilerTypes)
1092 Parameter[] all_params = new Parameter [userParams.Count + compilerParams.Length];
1093 userParams.FixedParameters.CopyTo(all_params, 0);
1095 Type [] all_types;
1096 if (userParams.types != null) {
1097 all_types = new Type [all_params.Length];
1098 userParams.Types.CopyTo (all_types, 0);
1099 } else {
1100 all_types = null;
1103 int last_filled = userParams.Count;
1104 int index = 0;
1105 foreach (Parameter p in compilerParams) {
1106 for (int i = 0; i < last_filled; ++i) {
1107 while (p.Name == all_params [i].Name) {
1108 if (checkConflicts && i < userParams.Count) {
1109 ctx.Report.Error (316, userParams[i].Location,
1110 "The parameter name `{0}' conflicts with a compiler generated name", p.Name);
1112 p.Name = '_' + p.Name;
1115 all_params [last_filled] = p;
1116 if (all_types != null)
1117 all_types [last_filled] = compilerTypes [index++];
1118 ++last_filled;
1121 ParametersCompiled parameters = new ParametersCompiled (all_params, all_types);
1122 parameters.has_params = userParams.has_params;
1123 return parameters;
1126 protected virtual void ErrorDuplicateName (Parameter p, Report Report)
1128 Report.Error (100, p.Location, "The parameter name `{0}' is a duplicate", p.Name);
1131 public bool Resolve (IMemberContext ec)
1133 if (types != null)
1134 return true;
1136 types = new Type [Count];
1138 bool ok = true;
1139 Parameter p;
1140 for (int i = 0; i < FixedParameters.Length; ++i) {
1141 p = this [i];
1142 Type t = p.Resolve (ec);
1143 if (t == null) {
1144 ok = false;
1145 continue;
1148 types [i] = t;
1151 return ok;
1154 public void ResolveVariable ()
1156 for (int i = 0; i < FixedParameters.Length; ++i) {
1157 this [i].ResolveVariable (i);
1161 // Define each type attribute (in/out/ref) and
1162 // the argument names.
1163 public void ApplyAttributes (MethodBase builder)
1165 if (Count == 0)
1166 return;
1168 MethodBuilder mb = builder as MethodBuilder;
1169 ConstructorBuilder cb = builder as ConstructorBuilder;
1171 for (int i = 0; i < Count; i++) {
1172 this [i].ApplyAttributes (mb, cb, i + 1);
1176 public void VerifyClsCompliance (IMemberContext ctx)
1178 foreach (Parameter p in FixedParameters)
1179 p.IsClsCompliant (ctx);
1182 public Parameter this [int pos] {
1183 get { return (Parameter) parameters [pos]; }
1186 public Expression CreateExpressionTree (BlockContext ec, Location loc)
1188 var initializers = new ArrayInitializer (Count, loc);
1189 foreach (Parameter p in FixedParameters) {
1191 // Each parameter expression is stored to local variable
1192 // to save some memory when referenced later.
1194 StatementExpression se = new StatementExpression (p.CreateExpressionTreeVariable (ec));
1195 if (se.Resolve (ec))
1196 ec.CurrentBlock.AddScopeStatement (se);
1198 initializers.Add (p.ExpressionTreeVariableReference ());
1201 return new ArrayCreation (
1202 Parameter.ResolveParameterExpressionType (ec, loc),
1203 "[]", initializers, loc);
1206 public ParametersCompiled Clone ()
1208 ParametersCompiled p = (ParametersCompiled) MemberwiseClone ();
1210 p.parameters = new IParameterData [parameters.Length];
1211 for (int i = 0; i < Count; ++i)
1212 p.parameters [i] = this [i].Clone ();
1214 return p;