2009-11-15 Jb Evain <jbevain@novell.com>
[mcs.git] / mcs / parameter.cs
blob5cea7493d7c822bede3c0cbcbe4aad37021b71a6
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 false
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 if (a.Type == pa.Dynamic) {
45 a.Error_MisusedDynamicAttribute ();
46 return;
49 builder.SetCustomAttribute (cb);
52 public ParameterBuilder Builder {
53 get {
54 return builder;
58 public override bool IsClsComplianceRequired()
60 return false;
64 /// <summary>
65 /// Class for applying custom attributes on the return type
66 /// </summary>
67 public class ReturnParameter : ParameterBase {
68 public ReturnParameter (MethodBuilder mb, Location location)
70 try {
71 builder = mb.DefineParameter (0, ParameterAttributes.None, "");
73 catch (ArgumentOutOfRangeException) {
74 RootContext.ToplevelTypes.Compiler.Report.RuntimeMissingSupport (location, "custom attributes on the return type");
78 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
80 if (a.Type == pa.CLSCompliant) {
81 RootContext.ToplevelTypes.Compiler.Report.Warning (3023, 1, a.Location,
82 "CLSCompliant attribute has no meaning when applied to return types. Try putting it on the method instead");
85 // This occurs after Warning -28
86 if (builder == null)
87 return;
89 base.ApplyAttributeBuilder (a, cb, pa);
92 public override AttributeTargets AttributeTargets {
93 get {
94 return AttributeTargets.ReturnValue;
98 /// <summary>
99 /// Is never called
100 /// </summary>
101 public override string[] ValidAttributeTargets {
102 get {
103 return null;
108 /// <summary>
109 /// Class for applying custom attributes on the implicit parameter type
110 /// of the 'set' method in properties, and the 'add' and 'remove' methods in events.
111 /// </summary>
112 ///
113 // TODO: should use more code from Parameter.ApplyAttributeBuilder
114 public class ImplicitParameter : ParameterBase {
115 public ImplicitParameter (MethodBuilder mb)
117 builder = mb.DefineParameter (1, ParameterAttributes.None, "value");
120 public override AttributeTargets AttributeTargets {
121 get {
122 return AttributeTargets.Parameter;
126 /// <summary>
127 /// Is never called
128 /// </summary>
129 public override string[] ValidAttributeTargets {
130 get {
131 return null;
136 public class ImplicitLambdaParameter : Parameter
138 public ImplicitLambdaParameter (string name, Location loc)
139 : base (null, name, Modifier.NONE, null, loc)
143 public override Type Resolve (IMemberContext ec)
145 if (parameter_type == null)
146 throw new InternalErrorException ("A type of implicit lambda parameter `{0}' is not set",
147 Name);
149 return parameter_type;
152 public Type Type {
153 set { parameter_type = value; }
157 public class ParamsParameter : Parameter {
158 public ParamsParameter (FullNamedExpression type, string name, Attributes attrs, Location loc):
159 base (type, name, Parameter.Modifier.PARAMS, attrs, loc)
163 public override Type Resolve (IMemberContext ec)
165 if (base.Resolve (ec) == null)
166 return null;
168 if (!parameter_type.IsArray || parameter_type.GetArrayRank () != 1) {
169 ec.Compiler.Report.Error (225, Location, "The params parameter must be a single dimensional array");
170 return null;
173 return parameter_type;
176 public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
178 base.ApplyAttributes (mb, cb, index);
179 PredefinedAttributes.Get.ParamArray.EmitAttribute (builder);
183 public class ArglistParameter : Parameter {
184 // Doesn't have proper type because it's never chosen for better conversion
185 public ArglistParameter (Location loc) :
186 base (null, String.Empty, Parameter.Modifier.NONE, null, loc)
190 public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
192 // Nothing to do
195 public override bool CheckAccessibility (InterfaceMemberBase member)
197 return true;
200 public override Type Resolve (IMemberContext ec)
202 return InternalType.Arglist;
205 public override string GetSignatureForError ()
207 return "__arglist";
211 public interface IParameterData
213 Expression DefaultValue { get; }
214 bool HasExtensionMethodModifier { get; }
215 bool HasDefaultValue { get; }
216 Parameter.Modifier ModFlags { get; }
217 string Name { get; }
221 // Parameter information created by parser
223 public class Parameter : ParameterBase, IParameterData, ILocalVariable {
224 [Flags]
225 public enum Modifier : byte {
226 NONE = 0,
227 REF = REFMASK | ISBYREF,
228 OUT = OUTMASK | ISBYREF,
229 PARAMS = 4,
230 // This is a flag which says that it's either REF or OUT.
231 ISBYREF = 8,
232 REFMASK = 32,
233 OUTMASK = 64,
234 This = 128
237 static string[] attribute_targets = new string [] { "param" };
239 protected FullNamedExpression TypeName;
240 readonly Modifier modFlags;
241 string name;
242 Expression default_expr;
243 protected Type parameter_type;
244 public readonly Location Location;
245 int idx;
246 public bool HasAddressTaken;
248 LocalVariableReference expr_tree_variable;
249 static TypeExpr parameter_expr_tree_type;
251 HoistedVariable hoisted_variant;
253 public Parameter (FullNamedExpression type, string name, Modifier mod, Attributes attrs, Location loc)
255 this.name = name;
256 modFlags = mod;
257 Location = loc;
258 TypeName = type;
260 // Only assign, attributes will be attached during resolve
261 base.attributes = attrs;
264 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
266 Report Report = RootContext.ToplevelTypes.Compiler.Report;
268 if (a.Type == pa.In && ModFlags == Modifier.OUT) {
269 Report.Error (36, a.Location, "An out parameter cannot have the `In' attribute");
270 return;
273 if (a.Type == pa.ParamArray) {
274 Report.Error (674, a.Location, "Do not use `System.ParamArrayAttribute'. Use the `params' keyword instead");
275 return;
278 if (a.Type == PredefinedAttributes.Get.Out && (ModFlags & Modifier.REF) == Modifier.REF &&
279 !OptAttributes.Contains (pa.In)) {
280 Report.Error (662, a.Location,
281 "Cannot specify only `Out' attribute on a ref parameter. Use both `In' and `Out' attributes or neither");
282 return;
285 if (a.Type == pa.CLSCompliant) {
286 Report.Warning (3022, 1, a.Location, "CLSCompliant attribute has no meaning when applied to parameters. Try putting it on the method instead");
289 if (HasDefaultValue && (a.Type == pa.DefaultParameterValue || a.Type == pa.OptionalParameter)) {
290 Report.Error (1745, a.Location,
291 "Cannot specify `{0}' attribute on optional parameter `{1}'",
292 TypeManager.CSharpName (a.Type).Replace ("Attribute", ""), Name);
293 return;
296 if (a.Type == pa.DefaultParameterValue) {
297 object val = a.GetParameterDefaultValue ();
298 if (val != null) {
299 Type t = val.GetType ();
300 if (t.IsArray || TypeManager.IsSubclassOf (t, TypeManager.type_type)) {
301 if (parameter_type == TypeManager.object_type) {
302 if (!t.IsArray)
303 t = TypeManager.type_type;
305 Report.Error (1910, a.Location, "Argument of type `{0}' is not applicable for the DefaultParameterValue attribute",
306 TypeManager.CSharpName (t));
307 } else {
308 Report.Error (1909, a.Location, "The DefaultParameterValue attribute is not applicable on parameters of type `{0}'",
309 TypeManager.CSharpName (parameter_type)); ;
311 return;
315 if (parameter_type == TypeManager.object_type ||
316 (val == null && !TypeManager.IsGenericParameter (parameter_type) && TypeManager.IsReferenceType (parameter_type)) ||
317 (val != null && TypeManager.TypeToCoreType (val.GetType ()) == parameter_type))
318 builder.SetConstant (val);
319 else
320 Report.Error (1908, a.Location, "The type of the default value should match the type of the parameter");
321 return;
324 base.ApplyAttributeBuilder (a, cb, pa);
327 public virtual bool CheckAccessibility (InterfaceMemberBase member)
329 if (parameter_type == null || TypeManager.IsGenericParameter (parameter_type))
330 return true;
332 return member.IsAccessibleAs (parameter_type);
335 // <summary>
336 // Resolve is used in method definitions
337 // </summary>
338 public virtual Type Resolve (IMemberContext rc)
340 if (parameter_type != null)
341 return parameter_type;
343 if (attributes != null)
344 attributes.AttachTo (this, rc);
346 TypeExpr texpr = TypeName.ResolveAsTypeTerminal (rc, false);
347 if (texpr == null)
348 return null;
350 parameter_type = texpr.Type;
352 // Ignore all checks for dummy members
353 AbstractPropertyEventMethod pem = rc as AbstractPropertyEventMethod;
354 if (pem != null && pem.IsDummy)
355 return parameter_type;
357 if (default_expr != null)
358 default_expr = ResolveDefaultValue (new ResolveContext (rc));
360 if ((modFlags & Parameter.Modifier.ISBYREF) != 0 &&
361 TypeManager.IsSpecialType (parameter_type)) {
362 rc.Compiler.Report.Error (1601, Location, "Method or delegate parameter cannot be of type `{0}'",
363 GetSignatureForError ());
364 return null;
367 TypeManager.CheckTypeVariance (parameter_type,
368 (modFlags & Parameter.Modifier.ISBYREF) != 0 ? Variance.None : Variance.Contravariant,
369 rc);
371 if (TypeManager.IsGenericParameter (parameter_type))
372 return parameter_type;
374 if ((parameter_type.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) {
375 rc.Compiler.Report.Error (721, Location, "`{0}': static types cannot be used as parameters",
376 texpr.GetSignatureForError ());
377 return parameter_type;
380 if ((modFlags & Modifier.This) != 0 && (parameter_type.IsPointer || TypeManager.IsDynamicType (parameter_type))) {
381 rc.Compiler.Report.Error (1103, Location, "The extension method cannot be of type `{0}'",
382 TypeManager.CSharpName (parameter_type));
385 return parameter_type;
388 Expression ResolveDefaultValue (ResolveContext rc)
390 default_expr = default_expr.Resolve (rc);
391 if (default_expr == null)
392 return null;
394 if (!(default_expr is Constant || default_expr is DefaultValueExpression)) {
395 if (TypeManager.IsNullableType (parameter_type)) {
396 rc.Compiler.Report.Error (1770, default_expr.Location,
397 "The expression being assigned to nullable optional parameter `{0}' must be default value",
398 Name);
399 } else {
400 rc.Compiler.Report.Error (1736, default_expr.Location,
401 "The expression being assigned to optional parameter `{0}' must be a constant or default value",
402 Name);
405 return null;
408 if (TypeManager.IsEqual (default_expr.Type, parameter_type))
409 return default_expr;
411 if (TypeManager.IsNullableType (parameter_type)) {
412 if (Convert.ImplicitNulableConversion (rc, default_expr, parameter_type) != null)
413 return default_expr;
414 } else {
415 var res = Convert.ImplicitConversionStandard (rc, default_expr, parameter_type, default_expr.Location);
416 if (res != null) {
417 if (!default_expr.IsNull && TypeManager.IsReferenceType (parameter_type) && parameter_type != TypeManager.string_type) {
418 rc.Compiler.Report.Error (1763, default_expr.Location,
419 "Optional parameter `{0}' of type `{1}' can only be initialized with `null'",
420 Name, GetSignatureForError ());
422 return null;
425 return res;
429 rc.Compiler.Report.Error (1750, Location,
430 "Optional parameter expression of type `{0}' cannot be converted to parameter type `{1}'",
431 TypeManager.CSharpName (default_expr.Type), GetSignatureForError ());
433 return null;
436 public void ResolveVariable (int idx)
438 this.idx = idx;
441 public bool HasDefaultValue {
442 get { return default_expr != null; }
445 public bool HasExtensionMethodModifier {
446 get { return (modFlags & Modifier.This) != 0; }
450 // Hoisted parameter variant
452 public HoistedVariable HoistedVariant {
453 get {
454 return hoisted_variant;
456 set {
457 hoisted_variant = value;
461 public Modifier ModFlags {
462 get { return modFlags & ~Modifier.This; }
465 public string Name {
466 get { return name; }
467 set { name = value; }
470 ParameterAttributes Attributes {
471 get { return ParametersCompiled.GetParameterAttribute (modFlags) |
472 (HasDefaultValue ? ParameterAttributes.Optional : ParameterAttributes.None); }
475 public override AttributeTargets AttributeTargets {
476 get {
477 return AttributeTargets.Parameter;
481 public virtual string GetSignatureForError ()
483 string type_name;
484 if (parameter_type != null)
485 type_name = TypeManager.CSharpName (parameter_type);
486 else
487 type_name = TypeName.GetSignatureForError ();
489 string mod = GetModifierSignature (modFlags);
490 if (mod.Length > 0)
491 return String.Concat (mod, " ", type_name);
493 return type_name;
496 public static string GetModifierSignature (Modifier mod)
498 switch (mod) {
499 case Modifier.OUT:
500 return "out";
501 case Modifier.PARAMS:
502 return "params";
503 case Modifier.REF:
504 return "ref";
505 case Modifier.This:
506 return "this";
507 default:
508 return "";
512 public void IsClsCompliant ()
514 if (AttributeTester.IsClsCompliant (parameter_type))
515 return;
517 RootContext.ToplevelTypes.Compiler.Report.Warning (3001, 1, Location, "Argument type `{0}' is not CLS-compliant", GetSignatureForError ());
520 public virtual void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
522 if (mb == null)
523 builder = cb.DefineParameter (index, Attributes, Name);
524 else
525 builder = mb.DefineParameter (index, Attributes, Name);
527 if (OptAttributes != null)
528 OptAttributes.Emit ();
530 if (HasDefaultValue) {
532 // Emit constant values for true constants only, the other
533 // constant-like expressions will rely on default value expression
535 Constant c = default_expr as Constant;
536 if (c != null) {
537 if (default_expr.Type == TypeManager.decimal_type) {
538 builder.SetCustomAttribute (Const.CreateDecimalConstantAttribute (c));
539 } else {
540 builder.SetConstant (c.GetTypedValue ());
545 if (TypeManager.IsDynamicType (parameter_type))
546 PredefinedAttributes.Get.Dynamic.EmitAttribute (builder);
549 public override string[] ValidAttributeTargets {
550 get {
551 return attribute_targets;
555 public Parameter Clone ()
557 Parameter p = (Parameter) MemberwiseClone ();
558 if (attributes != null)
559 p.attributes = attributes.Clone ();
561 return p;
564 public ExpressionStatement CreateExpressionTreeVariable (BlockContext ec)
566 if ((modFlags & Modifier.ISBYREF) != 0)
567 ec.Report.Error (1951, Location, "An expression tree parameter cannot use `ref' or `out' modifier");
569 LocalInfo variable = ec.CurrentBlock.AddTemporaryVariable (
570 ResolveParameterExpressionType (ec, Location), Location);
571 variable.Resolve (ec);
573 expr_tree_variable = new LocalVariableReference (
574 ec.CurrentBlock, variable.Name, Location, variable, false);
576 Arguments arguments = new Arguments (2);
577 arguments.Add (new Argument (new TypeOf (
578 new TypeExpression (parameter_type, Location), Location)));
579 arguments.Add (new Argument (new StringConstant (Name, Location)));
580 return new SimpleAssign (ExpressionTreeVariableReference (),
581 Expression.CreateExpressionFactoryCall (ec, "Parameter", null, arguments, Location));
584 public Expression DefaultValue {
585 get { return default_expr; }
586 set { default_expr = value; }
589 public void Emit (EmitContext ec)
591 int arg_idx = idx;
592 if (!ec.IsStatic)
593 arg_idx++;
595 ParameterReference.EmitLdArg (ec.ig, arg_idx);
598 public void EmitAssign (EmitContext ec)
600 int arg_idx = idx;
601 if (!ec.IsStatic)
602 arg_idx++;
604 if (arg_idx <= 255)
605 ec.ig.Emit (OpCodes.Starg_S, (byte) arg_idx);
606 else
607 ec.ig.Emit (OpCodes.Starg, arg_idx);
610 public void EmitAddressOf (EmitContext ec)
612 int arg_idx = idx;
614 if (!ec.IsStatic)
615 arg_idx++;
617 bool is_ref = (ModFlags & Modifier.ISBYREF) != 0;
618 if (is_ref) {
619 ParameterReference.EmitLdArg (ec.ig, arg_idx);
620 } else {
621 if (arg_idx <= 255)
622 ec.ig.Emit (OpCodes.Ldarga_S, (byte) arg_idx);
623 else
624 ec.ig.Emit (OpCodes.Ldarga, arg_idx);
628 public Expression ExpressionTreeVariableReference ()
630 return expr_tree_variable;
634 // System.Linq.Expressions.ParameterExpression type
636 public static TypeExpr ResolveParameterExpressionType (IMemberContext ec, Location location)
638 if (parameter_expr_tree_type != null)
639 return parameter_expr_tree_type;
641 Type p_type = TypeManager.parameter_expression_type;
642 if (p_type == null) {
643 p_type = TypeManager.CoreLookupType (ec.Compiler, "System.Linq.Expressions", "ParameterExpression", Kind.Class, true);
644 TypeManager.parameter_expression_type = p_type;
647 parameter_expr_tree_type = new TypeExpression (p_type, location).
648 ResolveAsTypeTerminal (ec, false);
650 return parameter_expr_tree_type;
653 public void Warning_UselessOptionalParameter (Report Report)
655 Report.Warning (1066, 1, Location,
656 "The default value specified for optional parameter `{0}' will never be used",
657 Name);
662 // Imported or resolved parameter information
664 public class ParameterData : IParameterData
666 readonly string name;
667 readonly Parameter.Modifier modifiers;
668 readonly Expression default_value;
670 public ParameterData (string name, Parameter.Modifier modifiers)
672 this.name = name;
673 this.modifiers = modifiers;
676 public ParameterData (string name, Parameter.Modifier modifiers, Expression defaultValue)
677 : this (name, modifiers)
679 this.default_value = defaultValue;
682 #region IParameterData Members
684 public Expression DefaultValue {
685 get { return default_value; }
688 public bool HasExtensionMethodModifier {
689 get { return (modifiers & Parameter.Modifier.This) != 0; }
692 public bool HasDefaultValue {
693 get { return default_value != null; }
696 public Parameter.Modifier ModFlags {
697 get { return modifiers & ~Parameter.Modifier.This; }
700 public string Name {
701 get { return name; }
704 #endregion
707 public abstract class AParametersCollection
709 protected bool has_arglist;
710 protected bool has_params;
712 // Null object pattern
713 protected IParameterData [] parameters;
714 protected Type [] types;
716 public int Count {
717 get { return parameters.Length; }
720 public Type ExtensionMethodType {
721 get {
722 if (Count == 0)
723 return null;
725 return FixedParameters [0].HasExtensionMethodModifier ?
726 types [0] : null;
730 public IParameterData [] FixedParameters {
731 get {
732 return parameters;
736 public static ParameterAttributes GetParameterAttribute (Parameter.Modifier modFlags)
738 return (modFlags & Parameter.Modifier.OUT) == Parameter.Modifier.OUT ?
739 ParameterAttributes.Out : ParameterAttributes.None;
742 public Type [] GetEmitTypes ()
744 Type [] types = null;
745 if (has_arglist) {
746 if (Count == 1)
747 return Type.EmptyTypes;
749 types = new Type [Count - 1];
750 Array.Copy (Types, types, types.Length);
753 for (int i = 0; i < Count; ++i) {
754 if ((FixedParameters [i].ModFlags & Parameter.Modifier.ISBYREF) == 0)
755 continue;
757 if (types == null)
758 types = (Type []) Types.Clone ();
760 types [i] = TypeManager.GetReferenceType (types [i]);
763 if (types == null)
764 types = Types;
766 return types;
770 // Returns the parameter information based on the name
772 public int GetParameterIndexByName (string name)
774 for (int idx = 0; idx < Count; ++idx) {
775 if (parameters [idx].Name == name)
776 return idx;
779 return -1;
782 public string GetSignatureForError ()
784 StringBuilder sb = new StringBuilder ("(");
785 for (int i = 0; i < Count; ++i) {
786 if (i != 0)
787 sb.Append (", ");
788 sb.Append (ParameterDesc (i));
790 sb.Append (')');
791 return sb.ToString ();
794 public bool HasArglist {
795 get { return has_arglist; }
798 public bool HasExtensionMethodType {
799 get {
800 if (Count == 0)
801 return false;
803 return FixedParameters [0].HasExtensionMethodModifier;
807 public bool HasParams {
808 get { return has_params; }
811 public bool IsEmpty {
812 get { return parameters.Length == 0; }
815 public string ParameterDesc (int pos)
817 if (types == null || types [pos] == null)
818 return ((Parameter)FixedParameters [pos]).GetSignatureForError ();
820 string type = TypeManager.CSharpName (types [pos]);
821 if (FixedParameters [pos].HasExtensionMethodModifier)
822 return "this " + type;
824 Parameter.Modifier mod = FixedParameters [pos].ModFlags;
825 if (mod == 0)
826 return type;
828 return Parameter.GetModifierSignature (mod) + " " + type;
831 public Type[] Types {
832 get { return types; }
833 set { types = value; }
836 #if MS_COMPATIBLE
837 public AParametersCollection InflateTypes (Type[] genArguments, Type[] argTypes)
839 AParametersCollection p = (AParametersCollection) MemberwiseClone (); // Clone ();
841 for (int i = 0; i < Count; ++i) {
842 if (types[i].IsGenericType) {
843 Type[] gen_arguments_open = new Type[types[i].GetGenericTypeDefinition ().GetGenericArguments ().Length];
844 Type[] gen_arguments = types[i].GetGenericArguments ();
845 for (int ii = 0; ii < gen_arguments_open.Length; ++ii) {
846 if (gen_arguments[ii].IsGenericParameter) {
847 Type t = argTypes[gen_arguments[ii].GenericParameterPosition];
848 gen_arguments_open[ii] = t;
849 } else
850 gen_arguments_open[ii] = gen_arguments[ii];
853 p.types[i] = types[i].GetGenericTypeDefinition ().MakeGenericType (gen_arguments_open);
854 continue;
857 if (types[i].IsGenericParameter) {
858 Type gen_argument = argTypes[types[i].GenericParameterPosition];
859 p.types[i] = gen_argument;
860 continue;
864 return p;
866 #endif
870 // A collection of imported or resolved parameters
872 public class ParametersImported : AParametersCollection
874 ParametersImported (AParametersCollection param, Type[] types)
876 this.parameters = param.FixedParameters;
877 this.types = types;
878 has_arglist = param.HasArglist;
879 has_params = param.HasParams;
882 ParametersImported (IParameterData [] parameters, Type [] types, bool hasArglist, bool hasParams)
884 this.parameters = parameters;
885 this.types = types;
886 this.has_arglist = hasArglist;
887 this.has_params = hasParams;
890 public ParametersImported (IParameterData [] param, Type[] types)
892 this.parameters = param;
893 this.types = types;
896 public static AParametersCollection Create (MethodBase method)
898 return Create (method.GetParameters (), method);
902 // Generic method parameters importer, param is shared between all instances
904 public static AParametersCollection Create (AParametersCollection param, MethodBase method)
906 if (param.IsEmpty)
907 return param;
909 ParameterInfo [] pi = method.GetParameters ();
910 Type [] types = new Type [pi.Length];
911 for (int i = 0; i < types.Length; i++) {
912 Type t = pi [i].ParameterType;
913 if (t.IsByRef)
914 t = TypeManager.GetElementType (t);
916 types [i] = TypeManager.TypeToCoreType (t);
919 return new ParametersImported (param, types);
923 // Imports SRE parameters
925 public static AParametersCollection Create (ParameterInfo [] pi, MethodBase method)
927 int varargs = method != null && (method.CallingConvention & CallingConventions.VarArgs) != 0 ? 1 : 0;
929 if (pi.Length == 0 && varargs == 0)
930 return ParametersCompiled.EmptyReadOnlyParameters;
932 Type [] types = new Type [pi.Length + varargs];
933 IParameterData [] par = new IParameterData [pi.Length + varargs];
934 bool is_params = false;
935 PredefinedAttribute extension_attr = PredefinedAttributes.Get.Extension;
936 PredefinedAttribute param_attr = PredefinedAttributes.Get.ParamArray;
937 for (int i = 0; i < pi.Length; i++) {
938 types [i] = TypeManager.TypeToCoreType (pi [i].ParameterType);
940 ParameterInfo p = pi [i];
941 Parameter.Modifier mod = 0;
942 Expression default_value = null;
943 if (types [i].IsByRef) {
944 if ((p.Attributes & (ParameterAttributes.Out | ParameterAttributes.In)) == ParameterAttributes.Out)
945 mod = Parameter.Modifier.OUT;
946 else
947 mod = Parameter.Modifier.REF;
950 // Strip reference wrapping
952 types [i] = TypeManager.GetElementType (types [i]);
953 } else if (i == 0 && extension_attr.IsDefined && method != null && method.IsStatic &&
954 (method.DeclaringType.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute &&
955 method.IsDefined (extension_attr.Type, false)) {
956 mod = Parameter.Modifier.This;
957 } else {
958 if (i >= pi.Length - 2 && types[i].IsArray) {
959 if (p.IsDefined (param_attr.Type, false)) {
960 mod = Parameter.Modifier.PARAMS;
961 is_params = true;
965 if (!is_params && p.IsOptional) {
966 object value = p.DefaultValue;
967 if (value == Missing.Value) {
968 default_value = EmptyExpression.Null;
969 } else if (value == null) {
970 default_value = new NullLiteral (Location.Null);
971 } else {
972 default_value = Constant.CreateConstant (value.GetType (), value, Location.Null);
977 par [i] = new ParameterData (p.Name, mod, default_value);
980 if (varargs != 0) {
981 par [par.Length - 1] = new ArglistParameter (Location.Null);
982 types [types.Length - 1] = InternalType.Arglist;
985 return method != null ?
986 new ParametersImported (par, types, varargs != 0, is_params) :
987 new ParametersImported (par, types);
991 /// <summary>
992 /// Represents the methods parameters
993 /// </summary>
994 public class ParametersCompiled : AParametersCollection
996 public static readonly ParametersCompiled EmptyReadOnlyParameters = new ParametersCompiled ();
998 // Used by C# 2.0 delegates
999 public static readonly ParametersCompiled Undefined = new ParametersCompiled ();
1001 private ParametersCompiled ()
1003 parameters = new Parameter [0];
1004 types = Type.EmptyTypes;
1007 private ParametersCompiled (Parameter [] parameters, Type [] types)
1009 this.parameters = parameters;
1010 this.types = types;
1013 public ParametersCompiled (params Parameter[] parameters)
1015 if (parameters == null)
1016 throw new ArgumentException ("Use EmptyReadOnlyParameters");
1018 this.parameters = parameters;
1019 int count = parameters.Length;
1021 if (count == 0)
1022 return;
1024 if (count == 1) {
1025 has_params = (parameters [0].ModFlags & Parameter.Modifier.PARAMS) != 0;
1026 return;
1029 for (int i = 0; i < count; i++){
1030 string base_name = parameters [i].Name;
1031 has_params |= (parameters [i].ModFlags & Parameter.Modifier.PARAMS) != 0;
1033 for (int j = i + 1; j < count; j++){
1034 if (base_name != parameters [j].Name)
1035 continue;
1037 ErrorDuplicateName (parameters[i], RootContext.ToplevelTypes.Compiler.Report);
1038 i = j;
1043 public ParametersCompiled (Parameter [] parameters, bool has_arglist) :
1044 this (parameters)
1046 this.has_arglist = has_arglist;
1049 public static ParametersCompiled CreateFullyResolved (Parameter p, Type type)
1051 return new ParametersCompiled (new Parameter [] { p }, new Type [] { type });
1054 public static ParametersCompiled CreateFullyResolved (Parameter[] parameters, Type[] types)
1056 return new ParametersCompiled (parameters, types);
1059 public static ParametersCompiled MergeGenerated (ParametersCompiled userParams, bool checkConflicts, Parameter compilerParams, Type compilerTypes)
1061 return MergeGenerated (userParams, checkConflicts,
1062 new Parameter [] { compilerParams },
1063 new Type [] { compilerTypes });
1067 // Use this method when you merge compiler generated parameters with user parameters
1069 public static ParametersCompiled MergeGenerated (ParametersCompiled userParams, bool checkConflicts, Parameter[] compilerParams, Type[] compilerTypes)
1071 Parameter[] all_params = new Parameter [userParams.Count + compilerParams.Length];
1072 userParams.FixedParameters.CopyTo(all_params, 0);
1074 Type [] all_types;
1075 if (userParams.types != null) {
1076 all_types = new Type [all_params.Length];
1077 userParams.Types.CopyTo (all_types, 0);
1078 } else {
1079 all_types = null;
1082 int last_filled = userParams.Count;
1083 int index = 0;
1084 foreach (Parameter p in compilerParams) {
1085 for (int i = 0; i < last_filled; ++i) {
1086 while (p.Name == all_params [i].Name) {
1087 if (checkConflicts && i < userParams.Count) {
1088 RootContext.ToplevelTypes.Compiler.Report.Error (316, userParams[i].Location,
1089 "The parameter name `{0}' conflicts with a compiler generated name", p.Name);
1091 p.Name = '_' + p.Name;
1094 all_params [last_filled] = p;
1095 if (all_types != null)
1096 all_types [last_filled] = compilerTypes [index++];
1097 ++last_filled;
1100 ParametersCompiled parameters = new ParametersCompiled (all_params, all_types);
1101 parameters.has_params = userParams.has_params;
1102 return parameters;
1105 protected virtual void ErrorDuplicateName (Parameter p, Report Report)
1107 Report.Error (100, p.Location, "The parameter name `{0}' is a duplicate", p.Name);
1110 public bool Resolve (IMemberContext ec)
1112 if (types != null)
1113 return true;
1115 types = new Type [Count];
1117 bool ok = true;
1118 Parameter p;
1119 for (int i = 0; i < FixedParameters.Length; ++i) {
1120 p = this [i];
1121 Type t = p.Resolve (ec);
1122 if (t == null) {
1123 ok = false;
1124 continue;
1127 types [i] = t;
1130 return ok;
1133 public void ResolveVariable ()
1135 for (int i = 0; i < FixedParameters.Length; ++i) {
1136 this [i].ResolveVariable (i);
1140 public CallingConventions CallingConvention
1142 get {
1143 if (HasArglist)
1144 return CallingConventions.VarArgs;
1145 else
1146 return CallingConventions.Standard;
1150 // Define each type attribute (in/out/ref) and
1151 // the argument names.
1152 public void ApplyAttributes (MethodBase builder)
1154 if (Count == 0)
1155 return;
1157 MethodBuilder mb = builder as MethodBuilder;
1158 ConstructorBuilder cb = builder as ConstructorBuilder;
1160 for (int i = 0; i < Count; i++) {
1161 this [i].ApplyAttributes (mb, cb, i + 1);
1165 public void VerifyClsCompliance ()
1167 foreach (Parameter p in FixedParameters)
1168 p.IsClsCompliant ();
1171 public Parameter this [int pos] {
1172 get { return (Parameter) parameters [pos]; }
1175 public Expression CreateExpressionTree (BlockContext ec, Location loc)
1177 ArrayList initializers = new ArrayList (Count);
1178 foreach (Parameter p in FixedParameters) {
1180 // Each parameter expression is stored to local variable
1181 // to save some memory when referenced later.
1183 StatementExpression se = new StatementExpression (p.CreateExpressionTreeVariable (ec));
1184 if (se.Resolve (ec))
1185 ec.CurrentBlock.AddScopeStatement (se);
1187 initializers.Add (p.ExpressionTreeVariableReference ());
1190 return new ArrayCreation (
1191 Parameter.ResolveParameterExpressionType (ec, loc),
1192 "[]", initializers, loc);
1195 public ParametersCompiled Clone ()
1197 ParametersCompiled p = (ParametersCompiled) MemberwiseClone ();
1199 p.parameters = new IParameterData [parameters.Length];
1200 for (int i = 0; i < Count; ++i)
1201 p.parameters [i] = this [i].Clone ();
1203 return p;