use a 2.0 network stack for MONOTOUCH
[mcs.git] / mcs / parameter.cs
blobf58ca7b220c9130b94f47926f58ebbe966a6657b
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 protected ParameterBase (Attributes attrs)
29 : base (attrs)
33 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
35 #if !NET_2_0
36 if (a.Type == pa.MarshalAs) {
37 UnmanagedMarshal marshal = a.GetMarshal (this);
38 if (marshal != null) {
39 builder.SetMarshal (marshal);
41 return;
43 #endif
44 if (a.HasSecurityAttribute) {
45 a.Error_InvalidSecurityParent ();
46 return;
49 builder.SetCustomAttribute (cb);
52 public override bool IsClsComplianceRequired()
54 return false;
58 /// <summary>
59 /// Class for applying custom attributes on the return type
60 /// </summary>
61 public class ReturnParameter : ParameterBase {
62 public ReturnParameter (MethodBuilder mb, Location location):
63 base (null)
65 try {
66 builder = mb.DefineParameter (0, ParameterAttributes.None, "");
68 catch (ArgumentOutOfRangeException) {
69 Report.RuntimeMissingSupport (location, "custom attributes on the return type");
73 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
75 if (a.Type == pa.CLSCompliant) {
76 Report.Warning (3023, 1, a.Location, "CLSCompliant attribute has no meaning when applied to return types. Try putting it on the method instead");
79 // This occurs after Warning -28
80 if (builder == null)
81 return;
83 base.ApplyAttributeBuilder (a, cb, pa);
86 public override AttributeTargets AttributeTargets {
87 get {
88 return AttributeTargets.ReturnValue;
92 public void EmitPredefined (PredefinedAttribute pa, Location loc)
94 if (builder != null)
95 pa.EmitAttribute (builder, loc);
98 public override IResolveContext ResolveContext {
99 get {
100 throw new NotSupportedException ();
104 /// <summary>
105 /// Is never called
106 /// </summary>
107 public override string[] ValidAttributeTargets {
108 get {
109 return null;
114 /// <summary>
115 /// Class for applying custom attributes on the implicit parameter type
116 /// of the 'set' method in properties, and the 'add' and 'remove' methods in events.
117 /// </summary>
118 ///
119 // TODO: should use more code from Parameter.ApplyAttributeBuilder
120 public class ImplicitParameter : ParameterBase {
121 public ImplicitParameter (MethodBuilder mb):
122 base (null)
124 builder = mb.DefineParameter (1, ParameterAttributes.None, "value");
127 public override AttributeTargets AttributeTargets {
128 get {
129 return AttributeTargets.Parameter;
133 public override IResolveContext ResolveContext {
134 get {
135 throw new NotSupportedException ();
139 /// <summary>
140 /// Is never called
141 /// </summary>
142 public override string[] ValidAttributeTargets {
143 get {
144 return null;
149 public class ImplicitLambdaParameter : Parameter
151 public ImplicitLambdaParameter (string name, Location loc)
152 : base (null, name, Modifier.NONE, null, loc)
156 public override Type Resolve (IResolveContext ec)
158 if (parameter_type == null)
159 throw new InternalErrorException ("A type of implicit lambda parameter `{0}' is not set",
160 Name);
162 return parameter_type;
165 public Type Type {
166 set { parameter_type = value; }
170 public class ParamsParameter : Parameter {
171 public ParamsParameter (FullNamedExpression type, string name, Attributes attrs, Location loc):
172 base (type, name, Parameter.Modifier.PARAMS, attrs, loc)
176 public override Type Resolve (IResolveContext ec)
178 if (base.Resolve (ec) == null)
179 return null;
181 if (!parameter_type.IsArray || parameter_type.GetArrayRank () != 1) {
182 Report.Error (225, Location, "The params parameter must be a single dimensional array");
183 return null;
186 return parameter_type;
189 public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
191 base.ApplyAttributes (mb, cb, index);
192 PredefinedAttributes.Get.ParamArray.EmitAttribute (builder, Location);
196 public class ArglistParameter : Parameter {
197 // Doesn't have proper type because it's never chosen for better conversion
198 public ArglistParameter (Location loc) :
199 base (null, String.Empty, Parameter.Modifier.NONE, null, loc)
203 public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
205 // Nothing to do
208 public override bool CheckAccessibility (InterfaceMemberBase member)
210 return true;
213 public override Type Resolve (IResolveContext ec)
215 return InternalType.Arglist;
218 public override string GetSignatureForError ()
220 return "__arglist";
224 public interface IParameterData
226 Expression DefaultValue { get; }
227 bool HasExtensionMethodModifier { get; }
228 bool HasDefaultValue { get; }
229 Parameter.Modifier ModFlags { get; }
230 string Name { get; }
234 // Parameter information created by parser
236 public class Parameter : ParameterBase, IParameterData, ILocalVariable {
237 [Flags]
238 public enum Modifier : byte {
239 NONE = 0,
240 REF = REFMASK | ISBYREF,
241 OUT = OUTMASK | ISBYREF,
242 PARAMS = 4,
243 // This is a flag which says that it's either REF or OUT.
244 ISBYREF = 8,
245 REFMASK = 32,
246 OUTMASK = 64,
247 This = 128
250 static string[] attribute_targets = new string [] { "param" };
252 protected FullNamedExpression TypeName;
253 readonly Modifier modFlags;
254 string name;
255 Expression default_expr;
256 protected Type parameter_type;
257 public readonly Location Location;
258 int idx;
259 public bool HasAddressTaken;
261 IResolveContext resolve_context;
262 LocalVariableReference expr_tree_variable;
263 static TypeExpr parameter_expr_tree_type;
265 public HoistedVariable HoistedVariableReference;
267 public Parameter (FullNamedExpression type, string name, Modifier mod, Attributes attrs, Location loc)
268 : base (attrs)
270 if (type == TypeManager.system_void_expr)
271 Report.Error (1536, loc, "Invalid parameter type `void'");
273 this.name = name;
274 modFlags = mod;
275 Location = loc;
276 TypeName = type;
279 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
281 if (a.Type == pa.In && ModFlags == Modifier.OUT) {
282 Report.Error (36, a.Location, "An out parameter cannot have the `In' attribute");
283 return;
286 if (a.Type == pa.ParamArray) {
287 Report.Error (674, a.Location, "Do not use `System.ParamArrayAttribute'. Use the `params' keyword instead");
288 return;
291 if (a.Type == PredefinedAttributes.Get.Out && (ModFlags & Modifier.REF) == Modifier.REF &&
292 !OptAttributes.Contains (pa.In)) {
293 Report.Error (662, a.Location,
294 "Cannot specify only `Out' attribute on a ref parameter. Use both `In' and `Out' attributes or neither");
295 return;
298 if (a.Type == pa.CLSCompliant) {
299 Report.Warning (3022, 1, a.Location, "CLSCompliant attribute has no meaning when applied to parameters. Try putting it on the method instead");
302 if (HasDefaultValue && (a.Type == pa.DefaultParameterValue || a.Type == pa.OptionalParameter)) {
303 Report.Error (1745, a.Location,
304 "Cannot specify `{0}' attribute on optional parameter `{1}'",
305 TypeManager.CSharpName (a.Type).Replace ("Attribute", ""), Name);
306 return;
309 if (a.Type == pa.DefaultParameterValue) {
310 object val = a.GetParameterDefaultValue ();
311 if (val != null) {
312 Type t = val.GetType ();
313 if (t.IsArray || TypeManager.IsSubclassOf (t, TypeManager.type_type)) {
314 if (parameter_type == TypeManager.object_type) {
315 if (!t.IsArray)
316 t = TypeManager.type_type;
318 Report.Error (1910, a.Location, "Argument of type `{0}' is not applicable for the DefaultParameterValue attribute",
319 TypeManager.CSharpName (t));
320 } else {
321 Report.Error (1909, a.Location, "The DefaultParameterValue attribute is not applicable on parameters of type `{0}'",
322 TypeManager.CSharpName (parameter_type)); ;
324 return;
328 if (parameter_type == TypeManager.object_type ||
329 (val == null && !TypeManager.IsGenericParameter (parameter_type) && TypeManager.IsReferenceType (parameter_type)) ||
330 (val != null && TypeManager.TypeToCoreType (val.GetType ()) == parameter_type))
331 builder.SetConstant (val);
332 else
333 Report.Error (1908, a.Location, "The type of the default value should match the type of the parameter");
334 return;
337 base.ApplyAttributeBuilder (a, cb, pa);
340 public virtual bool CheckAccessibility (InterfaceMemberBase member)
342 if (parameter_type == null || TypeManager.IsGenericParameter (parameter_type))
343 return true;
345 return member.IsAccessibleAs (parameter_type);
348 public override IResolveContext ResolveContext {
349 get {
350 return resolve_context;
354 // <summary>
355 // Resolve is used in method definitions
356 // </summary>
357 public virtual Type Resolve (IResolveContext rc)
359 // HACK: to resolve attributes correctly
360 this.resolve_context = rc;
362 if (parameter_type != null)
363 return parameter_type;
365 TypeExpr texpr = TypeName.ResolveAsTypeTerminal (rc, false);
366 if (texpr == null)
367 return null;
369 parameter_type = texpr.Type;
371 // Ignore all checks for dummy members
372 AbstractPropertyEventMethod pem = rc as AbstractPropertyEventMethod;
373 if (pem != null && pem.IsDummy)
374 return parameter_type;
376 if (default_expr != null) {
377 EmitContext ec = new EmitContext (rc, rc.GenericDeclContainer, Location, null, parameter_type, 0);
378 default_expr = default_expr.Resolve (ec);
379 if (default_expr != null) {
380 Constant value = default_expr as Constant;
381 if (value == null) {
382 if (default_expr != null) {
383 bool is_valid = false;
384 if (default_expr is DefaultValueExpression) {
385 is_valid = true;
386 } else if (default_expr is New && ((New) default_expr).IsDefaultValueType) {
387 is_valid = TypeManager.IsEqual (parameter_type, default_expr.Type) ||
388 (TypeManager.IsNullableType (parameter_type) &&
389 Convert.ImplicitNulableConversion (ec, default_expr, parameter_type) != EmptyExpression.Null);
390 } else {
391 Report.Error (1736, default_expr.Location,
392 "The expression being assigned to optional parameter `{0}' must be a constant or default value",
393 Name);
394 is_valid = true;
397 if (!is_valid) {
398 default_expr = null;
399 Report.Error (1763, Location,
400 "Optional parameter `{0}' of type `{1}' can only be initialized with `null'",
401 Name, GetSignatureForError ());
404 } else {
405 Constant c = value.ConvertImplicitly (parameter_type);
406 if (c == null) {
407 if (parameter_type == TypeManager.object_type) {
408 Report.Error (1763, Location,
409 "Optional parameter `{0}' of type `{1}' can only be initialized with `null'",
410 Name, GetSignatureForError ());
411 } else {
412 Report.Error (1750, Location,
413 "Optional parameter value `{0}' cannot be converted to parameter type `{1}'",
414 value.GetValue (), GetSignatureForError ());
416 default_expr = null;
422 if ((modFlags & Parameter.Modifier.ISBYREF) != 0 &&
423 TypeManager.IsSpecialType (parameter_type)) {
424 Report.Error (1601, Location, "Method or delegate parameter cannot be of type `{0}'",
425 GetSignatureForError ());
426 return null;
429 TypeManager.CheckTypeVariance (parameter_type,
430 (modFlags & Parameter.Modifier.ISBYREF) != 0 ? Variance.None : Variance.Contravariant,
431 rc as MemberCore);
433 if (texpr is TypeParameterExpr)
434 return parameter_type;
436 if ((parameter_type.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) {
437 Report.Error (721, Location, "`{0}': static types cannot be used as parameters",
438 texpr.GetSignatureForError ());
439 return parameter_type;
442 if ((modFlags & Modifier.This) != 0 && parameter_type.IsPointer) {
443 Report.Error (1103, Location, "The type of extension method cannot be `{0}'",
444 TypeManager.CSharpName (parameter_type));
447 return parameter_type;
450 public void ResolveVariable (int idx)
452 this.idx = idx;
455 public bool HasDefaultValue {
456 get { return default_expr != null; }
459 public bool HasExtensionMethodModifier {
460 get { return (modFlags & Modifier.This) != 0; }
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 ()
516 if (AttributeTester.IsClsCompliant (parameter_type))
517 return;
519 Report.Warning (3001, 1, Location, "Argument type `{0}' is not CLS-compliant", GetSignatureForError ());
522 public virtual void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
524 if (mb == null)
525 builder = cb.DefineParameter (index, Attributes, Name);
526 else
527 builder = mb.DefineParameter (index, Attributes, Name);
529 if (OptAttributes != null)
530 OptAttributes.Emit ();
532 if (HasDefaultValue) {
534 // Emit constant values for true constants only, the other
535 // constant-like expressions will rely on default value expression
537 Constant c = default_expr as Constant;
538 if (c != null) {
539 if (default_expr.Type == TypeManager.decimal_type) {
540 builder.SetCustomAttribute (Const.CreateDecimalConstantAttribute (c));
541 } else {
542 builder.SetConstant (c.GetValue ());
547 if (TypeManager.IsDynamicType (parameter_type))
548 PredefinedAttributes.Get.Dynamic.EmitAttribute (builder, Location);
551 public override string[] ValidAttributeTargets {
552 get {
553 return attribute_targets;
557 public Parameter Clone ()
559 Parameter p = (Parameter) MemberwiseClone ();
560 if (attributes != null) {
561 p.attributes = attributes.Clone ();
562 p.attributes.AttachTo (p);
565 return p;
568 public ExpressionStatement CreateExpressionTreeVariable (EmitContext ec)
571 // A parameter is not hoisted when used directly as ET
573 HoistedVariableReference = null;
575 if ((modFlags & Modifier.ISBYREF) != 0)
576 Report.Error (1951, Location, "An expression tree parameter cannot use `ref' or `out' modifier");
578 LocalInfo variable = ec.CurrentBlock.AddTemporaryVariable (
579 ResolveParameterExpressionType (ec, Location), Location);
580 variable.Resolve (ec);
582 expr_tree_variable = new LocalVariableReference (
583 ec.CurrentBlock, variable.Name, Location, variable, false);
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 ("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 (EmitContext 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 ("System.Linq.Expressions", "ParameterExpression", Kind.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 ()
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 int Count {
726 get { return parameters.Length; }
729 public Type ExtensionMethodType {
730 get {
731 if (Count == 0)
732 return null;
734 return FixedParameters [0].HasExtensionMethodModifier ?
735 types [0] : null;
739 public IParameterData [] FixedParameters {
740 get {
741 return parameters;
745 public static ParameterAttributes GetParameterAttribute (Parameter.Modifier modFlags)
747 return (modFlags & Parameter.Modifier.OUT) == Parameter.Modifier.OUT ?
748 ParameterAttributes.Out : ParameterAttributes.None;
751 public Type [] GetEmitTypes ()
753 Type [] types = null;
754 if (has_arglist) {
755 if (Count == 1)
756 return Type.EmptyTypes;
758 types = new Type [Count - 1];
759 Array.Copy (Types, types, types.Length);
762 for (int i = 0; i < Count; ++i) {
763 if ((FixedParameters [i].ModFlags & Parameter.Modifier.ISBYREF) == 0)
764 continue;
766 if (types == null)
767 types = (Type []) Types.Clone ();
769 types [i] = TypeManager.GetReferenceType (types [i]);
772 if (types == null)
773 types = Types;
775 return types;
779 // Returns the parameter information based on the name
781 public int GetParameterIndexByName (string name)
783 for (int idx = 0; idx < Count; ++idx) {
784 if (parameters [idx].Name == name)
785 return idx;
788 return -1;
791 public string GetSignatureForError ()
793 StringBuilder sb = new StringBuilder ("(");
794 for (int i = 0; i < Count; ++i) {
795 if (i != 0)
796 sb.Append (", ");
797 sb.Append (ParameterDesc (i));
799 sb.Append (')');
800 return sb.ToString ();
803 public bool HasArglist {
804 get { return has_arglist; }
807 public bool HasExtensionMethodType {
808 get {
809 if (Count == 0)
810 return false;
812 return FixedParameters [0].HasExtensionMethodModifier;
816 public bool HasParams {
817 get { return has_params; }
820 public bool IsEmpty {
821 get { return parameters.Length == 0; }
824 public string ParameterDesc (int pos)
826 if (types == null || types [pos] == null)
827 return ((Parameter)FixedParameters [pos]).GetSignatureForError ();
829 string type = TypeManager.CSharpName (types [pos]);
830 if (FixedParameters [pos].HasExtensionMethodModifier)
831 return "this " + type;
833 Parameter.Modifier mod = FixedParameters [pos].ModFlags;
834 if (mod == 0)
835 return type;
837 return Parameter.GetModifierSignature (mod) + " " + type;
840 public Type[] Types {
841 get { return types; }
842 set { types = value; }
845 #if MS_COMPATIBLE
846 public AParametersCollection InflateTypes (Type[] genArguments, Type[] argTypes)
848 AParametersCollection p = (AParametersCollection) MemberwiseClone (); // Clone ();
850 for (int i = 0; i < Count; ++i) {
851 if (types[i].IsGenericType) {
852 Type[] gen_arguments_open = new Type[types[i].GetGenericTypeDefinition ().GetGenericArguments ().Length];
853 Type[] gen_arguments = types[i].GetGenericArguments ();
854 for (int ii = 0; ii < gen_arguments_open.Length; ++ii) {
855 if (gen_arguments[ii].IsGenericParameter) {
856 Type t = argTypes[gen_arguments[ii].GenericParameterPosition];
857 gen_arguments_open[ii] = t;
858 } else
859 gen_arguments_open[ii] = gen_arguments[ii];
862 p.types[i] = types[i].GetGenericTypeDefinition ().MakeGenericType (gen_arguments_open);
863 continue;
866 if (types[i].IsGenericParameter) {
867 Type gen_argument = argTypes[types[i].GenericParameterPosition];
868 p.types[i] = gen_argument;
869 continue;
873 return p;
875 #endif
879 // A collection of imported or resolved parameters
881 public class ParametersImported : AParametersCollection
883 ParametersImported (AParametersCollection param, Type[] types)
885 this.parameters = param.FixedParameters;
886 this.types = types;
887 has_arglist = param.HasArglist;
888 has_params = param.HasParams;
891 ParametersImported (IParameterData [] parameters, Type [] types, bool hasArglist, bool hasParams)
893 this.parameters = parameters;
894 this.types = types;
895 this.has_arglist = hasArglist;
896 this.has_params = hasParams;
899 public ParametersImported (IParameterData [] param, Type[] types)
901 this.parameters = param;
902 this.types = types;
905 public static AParametersCollection Create (MethodBase method)
907 return Create (method.GetParameters (), method);
911 // Generic method parameters importer, param is shared between all instances
913 public static AParametersCollection Create (AParametersCollection param, MethodBase method)
915 if (param.IsEmpty)
916 return param;
918 ParameterInfo [] pi = method.GetParameters ();
919 Type [] types = new Type [pi.Length];
920 for (int i = 0; i < types.Length; i++) {
921 Type t = pi [i].ParameterType;
922 if (t.IsByRef)
923 t = TypeManager.GetElementType (t);
925 types [i] = TypeManager.TypeToCoreType (t);
928 return new ParametersImported (param, types);
932 // Imports SRE parameters
934 public static AParametersCollection Create (ParameterInfo [] pi, MethodBase method)
936 int varargs = method != null && (method.CallingConvention & CallingConventions.VarArgs) != 0 ? 1 : 0;
938 if (pi.Length == 0 && varargs == 0)
939 return ParametersCompiled.EmptyReadOnlyParameters;
941 Type [] types = new Type [pi.Length + varargs];
942 IParameterData [] par = new IParameterData [pi.Length + varargs];
943 bool is_params = false;
944 PredefinedAttribute extension_attr = PredefinedAttributes.Get.Extension;
945 PredefinedAttribute param_attr = PredefinedAttributes.Get.ParamArray;
946 for (int i = 0; i < pi.Length; i++) {
947 types [i] = TypeManager.TypeToCoreType (pi [i].ParameterType);
949 ParameterInfo p = pi [i];
950 Parameter.Modifier mod = 0;
951 Expression default_value = null;
952 if (types [i].IsByRef) {
953 if ((p.Attributes & (ParameterAttributes.Out | ParameterAttributes.In)) == ParameterAttributes.Out)
954 mod = Parameter.Modifier.OUT;
955 else
956 mod = Parameter.Modifier.REF;
959 // Strip reference wrapping
961 types [i] = TypeManager.GetElementType (types [i]);
962 } else if (i == 0 && extension_attr.IsDefined && method != null && method.IsStatic &&
963 (method.DeclaringType.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute &&
964 method.IsDefined (extension_attr.Type, false)) {
965 mod = Parameter.Modifier.This;
966 } else {
967 if (i >= pi.Length - 2 && types[i].IsArray) {
968 if (p.IsDefined (param_attr.Type, false)) {
969 mod = Parameter.Modifier.PARAMS;
970 is_params = true;
974 if (!is_params && p.IsOptional) {
975 if (p.DefaultValue == Missing.Value)
976 default_value = EmptyExpression.Null;
977 else
978 default_value = Constant.CreateConstant (types[i], p.DefaultValue, Location.Null);
982 par [i] = new ParameterData (p.Name, mod, default_value);
985 if (varargs != 0) {
986 par [par.Length - 1] = new ArglistParameter (Location.Null);
987 types [types.Length - 1] = InternalType.Arglist;
990 return method != null ?
991 new ParametersImported (par, types, varargs != 0, is_params) :
992 new ParametersImported (par, types);
996 /// <summary>
997 /// Represents the methods parameters
998 /// </summary>
999 public class ParametersCompiled : AParametersCollection
1001 public static readonly ParametersCompiled EmptyReadOnlyParameters = new ParametersCompiled ();
1003 // Used by C# 2.0 delegates
1004 public static readonly ParametersCompiled Undefined = new ParametersCompiled ();
1006 private ParametersCompiled ()
1008 parameters = new Parameter [0];
1009 types = Type.EmptyTypes;
1012 private ParametersCompiled (Parameter [] parameters, Type [] types)
1014 this.parameters = parameters;
1015 this.types = types;
1018 public ParametersCompiled (params Parameter[] parameters)
1020 if (parameters == null)
1021 throw new ArgumentException ("Use EmptyReadOnlyParameters");
1023 this.parameters = parameters;
1024 int count = parameters.Length;
1026 if (count == 0)
1027 return;
1029 if (count == 1) {
1030 has_params = (parameters [0].ModFlags & Parameter.Modifier.PARAMS) != 0;
1031 return;
1034 for (int i = 0; i < count; i++){
1035 string base_name = parameters [i].Name;
1036 has_params |= (parameters [i].ModFlags & Parameter.Modifier.PARAMS) != 0;
1038 for (int j = i + 1; j < count; j++){
1039 if (base_name != parameters [j].Name)
1040 continue;
1042 ErrorDuplicateName (parameters [i]);
1043 i = j;
1048 public ParametersCompiled (Parameter [] parameters, bool has_arglist) :
1049 this (parameters)
1051 this.has_arglist = has_arglist;
1054 public static ParametersCompiled CreateFullyResolved (Parameter p, Type type)
1056 return new ParametersCompiled (new Parameter [] { p }, new Type [] { type });
1059 public static ParametersCompiled CreateFullyResolved (Parameter[] parameters, Type[] types)
1061 return new ParametersCompiled (parameters, types);
1064 public static ParametersCompiled MergeGenerated (ParametersCompiled userParams, bool checkConflicts, Parameter compilerParams, Type compilerTypes)
1066 return MergeGenerated (userParams, checkConflicts,
1067 new Parameter [] { compilerParams },
1068 new Type [] { compilerTypes });
1072 // Use this method when you merge compiler generated parameters with user parameters
1074 public static ParametersCompiled MergeGenerated (ParametersCompiled userParams, bool checkConflicts, Parameter[] compilerParams, Type[] compilerTypes)
1076 Parameter[] all_params = new Parameter [userParams.Count + compilerParams.Length];
1077 userParams.FixedParameters.CopyTo(all_params, 0);
1079 Type [] all_types;
1080 if (userParams.types != null) {
1081 all_types = new Type [all_params.Length];
1082 userParams.Types.CopyTo (all_types, 0);
1083 } else {
1084 all_types = null;
1087 int last_filled = userParams.Count;
1088 int index = 0;
1089 foreach (Parameter p in compilerParams) {
1090 for (int i = 0; i < last_filled; ++i) {
1091 while (p.Name == all_params [i].Name) {
1092 if (checkConflicts && i < userParams.Count) {
1093 Report.Error (316, userParams [i].Location,
1094 "The parameter name `{0}' conflicts with a compiler generated name", p.Name);
1096 p.Name = '_' + p.Name;
1099 all_params [last_filled] = p;
1100 if (all_types != null)
1101 all_types [last_filled] = compilerTypes [index++];
1102 ++last_filled;
1105 ParametersCompiled parameters = new ParametersCompiled (all_params, all_types);
1106 parameters.has_params = userParams.has_params;
1107 return parameters;
1110 protected virtual void ErrorDuplicateName (Parameter p)
1112 Report.Error (100, p.Location, "The parameter name `{0}' is a duplicate", p.Name);
1115 public bool Resolve (IResolveContext ec)
1117 if (types != null)
1118 return true;
1120 types = new Type [Count];
1122 bool ok = true;
1123 Parameter p;
1124 for (int i = 0; i < FixedParameters.Length; ++i) {
1125 p = this [i];
1126 Type t = p.Resolve (ec);
1127 if (t == null) {
1128 ok = false;
1129 continue;
1132 types [i] = t;
1135 return ok;
1138 public void ResolveVariable ()
1140 for (int i = 0; i < FixedParameters.Length; ++i) {
1141 this [i].ResolveVariable (i);
1145 public CallingConventions CallingConvention
1147 get {
1148 if (HasArglist)
1149 return CallingConventions.VarArgs;
1150 else
1151 return CallingConventions.Standard;
1155 // Define each type attribute (in/out/ref) and
1156 // the argument names.
1157 public void ApplyAttributes (MethodBase builder)
1159 if (Count == 0)
1160 return;
1162 MethodBuilder mb = builder as MethodBuilder;
1163 ConstructorBuilder cb = builder as ConstructorBuilder;
1165 for (int i = 0; i < Count; i++) {
1166 this [i].ApplyAttributes (mb, cb, i + 1);
1170 public void VerifyClsCompliance ()
1172 foreach (Parameter p in FixedParameters)
1173 p.IsClsCompliant ();
1176 public Parameter this [int pos] {
1177 get { return (Parameter) parameters [pos]; }
1180 public Expression CreateExpressionTree (EmitContext ec, Location loc)
1182 ArrayList initializers = new ArrayList (Count);
1183 foreach (Parameter p in FixedParameters) {
1185 // Each parameter expression is stored to local variable
1186 // to save some memory when referenced later.
1188 StatementExpression se = new StatementExpression (p.CreateExpressionTreeVariable (ec));
1189 if (se.Resolve (ec))
1190 ec.CurrentBlock.AddScopeStatement (se);
1192 initializers.Add (p.ExpressionTreeVariableReference ());
1195 return new ArrayCreation (
1196 Parameter.ResolveParameterExpressionType (ec, loc),
1197 "[]", initializers, loc);
1200 public ParametersCompiled Clone ()
1202 ParametersCompiled p = (ParametersCompiled) MemberwiseClone ();
1204 p.parameters = new IParameterData [parameters.Length];
1205 for (int i = 0; i < Count; ++i)
1206 p.parameters [i] = this [i].Clone ();
1208 return p;