2009-07-20 Jb Evain <jbevain@novell.com>
[mcs.git] / mcs / parameter.cs
blobbfef2d87ca652e9c8a8739597d1990afad4429c4
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 override IResolveContext ResolveContext {
93 get {
94 throw new NotSupportedException ();
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):
116 base (null)
118 builder = mb.DefineParameter (1, ParameterAttributes.None, "value");
121 public override AttributeTargets AttributeTargets {
122 get {
123 return AttributeTargets.Parameter;
127 public override IResolveContext ResolveContext {
128 get {
129 throw new NotSupportedException ();
133 /// <summary>
134 /// Is never called
135 /// </summary>
136 public override string[] ValidAttributeTargets {
137 get {
138 return null;
143 public class ImplicitLambdaParameter : Parameter
145 public ImplicitLambdaParameter (string name, Location loc)
146 : base (null, name, Modifier.NONE, null, loc)
150 public override Type Resolve (IResolveContext ec)
152 if (parameter_type == null)
153 throw new InternalErrorException ("A type of implicit lambda parameter `{0}' is not set",
154 Name);
156 return parameter_type;
159 public Type Type {
160 set { parameter_type = value; }
164 public class ParamsParameter : Parameter {
165 public ParamsParameter (FullNamedExpression type, string name, Attributes attrs, Location loc):
166 base (type, name, Parameter.Modifier.PARAMS, attrs, loc)
170 public override Type Resolve (IResolveContext ec)
172 if (base.Resolve (ec) == null)
173 return null;
175 if (!parameter_type.IsArray || parameter_type.GetArrayRank () != 1) {
176 Report.Error (225, Location, "The params parameter must be a single dimensional array");
177 return null;
180 return parameter_type;
183 public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
185 base.ApplyAttributes (mb, cb, index);
186 PredefinedAttributes.Get.ParamArray.EmitAttribute (builder, Location);
190 public class ArglistParameter : Parameter {
191 // Doesn't have proper type because it's never chosen for better conversion
192 public ArglistParameter (Location loc) :
193 base (null, String.Empty, Parameter.Modifier.NONE, null, loc)
197 public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
199 // Nothing to do
202 public override bool CheckAccessibility (InterfaceMemberBase member)
204 return true;
207 public override Type Resolve (IResolveContext ec)
209 return InternalType.Arglist;
212 public override string GetSignatureForError ()
214 return "__arglist";
218 public interface IParameterData
220 Expression DefaultValue { get; }
221 bool HasExtensionMethodModifier { get; }
222 bool HasDefaultValue { get; }
223 Parameter.Modifier ModFlags { get; }
224 string Name { get; }
228 // Parameter information created by parser
230 public class Parameter : ParameterBase, IParameterData, ILocalVariable {
231 [Flags]
232 public enum Modifier : byte {
233 NONE = 0,
234 REF = REFMASK | ISBYREF,
235 OUT = OUTMASK | ISBYREF,
236 PARAMS = 4,
237 // This is a flag which says that it's either REF or OUT.
238 ISBYREF = 8,
239 REFMASK = 32,
240 OUTMASK = 64,
241 This = 128
244 static string[] attribute_targets = new string [] { "param" };
246 protected FullNamedExpression TypeName;
247 readonly Modifier modFlags;
248 string name;
249 Expression default_expr;
250 protected Type parameter_type;
251 public readonly Location Location;
252 int idx;
253 public bool HasAddressTaken;
255 IResolveContext resolve_context;
256 LocalVariableReference expr_tree_variable;
257 static TypeExpr parameter_expr_tree_type;
259 public HoistedVariable HoistedVariableReference;
261 public Parameter (FullNamedExpression type, string name, Modifier mod, Attributes attrs, Location loc)
262 : base (attrs)
264 if (type == TypeManager.system_void_expr)
265 Report.Error (1536, loc, "Invalid parameter type `void'");
267 this.name = name;
268 modFlags = mod;
269 Location = loc;
270 TypeName = type;
273 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
275 if (a.Type == pa.In && ModFlags == Modifier.OUT) {
276 Report.Error (36, a.Location, "An out parameter cannot have the `In' attribute");
277 return;
280 if (a.Type == pa.ParamArray) {
281 Report.Error (674, a.Location, "Do not use `System.ParamArrayAttribute'. Use the `params' keyword instead");
282 return;
285 if (a.Type == PredefinedAttributes.Get.Out && (ModFlags & Modifier.REF) == Modifier.REF &&
286 !OptAttributes.Contains (pa.In)) {
287 Report.Error (662, a.Location,
288 "Cannot specify only `Out' attribute on a ref parameter. Use both `In' and `Out' attributes or neither");
289 return;
292 if (a.Type == pa.CLSCompliant) {
293 Report.Warning (3022, 1, a.Location, "CLSCompliant attribute has no meaning when applied to parameters. Try putting it on the method instead");
296 if (HasDefaultValue && (a.Type == pa.DefaultParameterValue || a.Type == pa.OptionalParameter)) {
297 Report.Error (1745, a.Location,
298 "Cannot specify `{0}' attribute on optional parameter `{1}'",
299 TypeManager.CSharpName (a.Type).Replace ("Attribute", ""), Name);
300 return;
303 if (a.Type == pa.DefaultParameterValue) {
304 object val = a.GetParameterDefaultValue ();
305 if (val != null) {
306 Type t = val.GetType ();
307 if (t.IsArray || TypeManager.IsSubclassOf (t, TypeManager.type_type)) {
308 if (parameter_type == TypeManager.object_type) {
309 if (!t.IsArray)
310 t = TypeManager.type_type;
312 Report.Error (1910, a.Location, "Argument of type `{0}' is not applicable for the DefaultParameterValue attribute",
313 TypeManager.CSharpName (t));
314 } else {
315 Report.Error (1909, a.Location, "The DefaultParameterValue attribute is not applicable on parameters of type `{0}'",
316 TypeManager.CSharpName (parameter_type)); ;
318 return;
322 if (parameter_type == TypeManager.object_type ||
323 (val == null && !TypeManager.IsGenericParameter (parameter_type) && TypeManager.IsReferenceType (parameter_type)) ||
324 (val != null && TypeManager.TypeToCoreType (val.GetType ()) == parameter_type))
325 builder.SetConstant (val);
326 else
327 Report.Error (1908, a.Location, "The type of the default value should match the type of the parameter");
328 return;
331 base.ApplyAttributeBuilder (a, cb, pa);
334 public virtual bool CheckAccessibility (InterfaceMemberBase member)
336 if (parameter_type == null || TypeManager.IsGenericParameter (parameter_type))
337 return true;
339 return member.IsAccessibleAs (parameter_type);
342 public override IResolveContext ResolveContext {
343 get {
344 return resolve_context;
348 // <summary>
349 // Resolve is used in method definitions
350 // </summary>
351 public virtual Type Resolve (IResolveContext rc)
353 // HACK: to resolve attributes correctly
354 this.resolve_context = rc;
356 if (parameter_type != null)
357 return parameter_type;
359 TypeExpr texpr = TypeName.ResolveAsTypeTerminal (rc, false);
360 if (texpr == null)
361 return null;
363 parameter_type = texpr.Type;
365 // Ignore all checks for dummy members
366 AbstractPropertyEventMethod pem = rc as AbstractPropertyEventMethod;
367 if (pem != null && pem.IsDummy)
368 return parameter_type;
370 if (default_expr != null) {
371 EmitContext ec = new EmitContext (rc, rc.GenericDeclContainer, Location, null, parameter_type, 0);
372 default_expr = default_expr.Resolve (ec);
373 if (default_expr != null) {
374 Constant value = default_expr as Constant;
375 if (value == null) {
376 if (default_expr != null) {
377 bool is_valid = false;
378 if (default_expr is DefaultValueExpression) {
379 is_valid = true;
380 } else if (default_expr is New && ((New) default_expr).IsDefaultValueType) {
381 is_valid = TypeManager.IsEqual (parameter_type, default_expr.Type) ||
382 (TypeManager.IsNullableType (parameter_type) &&
383 Convert.ImplicitNulableConversion (ec, default_expr, parameter_type) != EmptyExpression.Null);
384 } else {
385 Report.Error (1736, default_expr.Location,
386 "The expression being assigned to optional parameter `{0}' must be a constant or default value",
387 Name);
388 is_valid = true;
391 if (!is_valid) {
392 default_expr = null;
393 Report.Error (1763, Location,
394 "Optional parameter `{0}' of type `{1}' can only be initialized with `null'",
395 Name, GetSignatureForError ());
398 } else {
399 Constant c = value.ConvertImplicitly (parameter_type);
400 if (c == null) {
401 if (parameter_type == TypeManager.object_type) {
402 Report.Error (1763, Location,
403 "Optional parameter `{0}' of type `{1}' can only be initialized with `null'",
404 Name, GetSignatureForError ());
405 } else {
406 Report.Error (1750, Location,
407 "Optional parameter value `{0}' cannot be converted to parameter type `{1}'",
408 value.GetValue (), GetSignatureForError ());
410 default_expr = null;
416 if ((modFlags & Parameter.Modifier.ISBYREF) != 0 &&
417 TypeManager.IsSpecialType (parameter_type)) {
418 Report.Error (1601, Location, "Method or delegate parameter cannot be of type `{0}'",
419 GetSignatureForError ());
420 return null;
423 TypeManager.CheckTypeVariance (parameter_type,
424 (modFlags & Parameter.Modifier.ISBYREF) != 0 ? Variance.None : Variance.Contravariant,
425 rc as MemberCore);
427 if (texpr is TypeParameterExpr)
428 return parameter_type;
430 if ((parameter_type.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) {
431 Report.Error (721, Location, "`{0}': static types cannot be used as parameters",
432 texpr.GetSignatureForError ());
433 return parameter_type;
436 if ((modFlags & Modifier.This) != 0 && parameter_type.IsPointer) {
437 Report.Error (1103, Location, "The type of extension method cannot be `{0}'",
438 TypeManager.CSharpName (parameter_type));
441 return parameter_type;
444 public void ResolveVariable (int idx)
446 this.idx = idx;
449 public bool HasDefaultValue {
450 get { return default_expr != null; }
453 public bool HasExtensionMethodModifier {
454 get { return (modFlags & Modifier.This) != 0; }
457 public Modifier ModFlags {
458 get { return modFlags & ~Modifier.This; }
461 public string Name {
462 get { return name; }
463 set { name = value; }
466 ParameterAttributes Attributes {
467 get { return ParametersCompiled.GetParameterAttribute (modFlags) |
468 (HasDefaultValue ? ParameterAttributes.Optional : ParameterAttributes.None); }
471 public override AttributeTargets AttributeTargets {
472 get {
473 return AttributeTargets.Parameter;
477 public virtual string GetSignatureForError ()
479 string type_name;
480 if (parameter_type != null)
481 type_name = TypeManager.CSharpName (parameter_type);
482 else
483 type_name = TypeName.GetSignatureForError ();
485 string mod = GetModifierSignature (modFlags);
486 if (mod.Length > 0)
487 return String.Concat (mod, " ", type_name);
489 return type_name;
492 public static string GetModifierSignature (Modifier mod)
494 switch (mod) {
495 case Modifier.OUT:
496 return "out";
497 case Modifier.PARAMS:
498 return "params";
499 case Modifier.REF:
500 return "ref";
501 case Modifier.This:
502 return "this";
503 default:
504 return "";
508 public void IsClsCompliant ()
510 if (AttributeTester.IsClsCompliant (parameter_type))
511 return;
513 Report.Warning (3001, 1, Location, "Argument type `{0}' is not CLS-compliant", GetSignatureForError ());
516 public virtual void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
518 if (mb == null)
519 builder = cb.DefineParameter (index, Attributes, Name);
520 else
521 builder = mb.DefineParameter (index, Attributes, Name);
523 if (OptAttributes != null)
524 OptAttributes.Emit ();
526 if (HasDefaultValue) {
528 // Emit constant values for true constants only, the other
529 // constant-like expressions will rely on default value expression
531 Constant c = default_expr as Constant;
532 if (c != null) {
533 if (default_expr.Type == TypeManager.decimal_type) {
534 builder.SetCustomAttribute (Const.CreateDecimalConstantAttribute (c));
535 } else {
536 builder.SetConstant (c.GetValue ());
542 public override string[] ValidAttributeTargets {
543 get {
544 return attribute_targets;
548 public Parameter Clone ()
550 Parameter p = (Parameter) MemberwiseClone ();
551 if (attributes != null) {
552 p.attributes = attributes.Clone ();
553 p.attributes.AttachTo (p);
556 return p;
559 public ExpressionStatement CreateExpressionTreeVariable (EmitContext ec)
562 // A parameter is not hoisted when used directly as ET
564 HoistedVariableReference = null;
566 if ((modFlags & Modifier.ISBYREF) != 0)
567 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 ("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 (EmitContext 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 ("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 ()
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 if (p.DefaultValue == Missing.Value)
967 default_value = EmptyExpression.Null;
968 else
969 default_value = Constant.CreateConstant (types[i], p.DefaultValue, Location.Null);
973 par [i] = new ParameterData (p.Name, mod, default_value);
976 if (varargs != 0) {
977 par [par.Length - 1] = new ArglistParameter (Location.Null);
978 types [types.Length - 1] = InternalType.Arglist;
981 return method != null ?
982 new ParametersImported (par, types, varargs != 0, is_params) :
983 new ParametersImported (par, types);
987 /// <summary>
988 /// Represents the methods parameters
989 /// </summary>
990 public class ParametersCompiled : AParametersCollection
992 public static readonly ParametersCompiled EmptyReadOnlyParameters = new ParametersCompiled ();
994 // Used by C# 2.0 delegates
995 public static readonly ParametersCompiled Undefined = new ParametersCompiled ();
997 private ParametersCompiled ()
999 parameters = new Parameter [0];
1000 types = Type.EmptyTypes;
1003 private ParametersCompiled (Parameter [] parameters, Type [] types)
1005 this.parameters = parameters;
1006 this.types = types;
1009 public ParametersCompiled (params Parameter[] parameters)
1011 if (parameters == null)
1012 throw new ArgumentException ("Use EmptyReadOnlyParameters");
1014 this.parameters = parameters;
1015 int count = parameters.Length;
1017 if (count == 0)
1018 return;
1020 if (count == 1) {
1021 has_params = (parameters [0].ModFlags & Parameter.Modifier.PARAMS) != 0;
1022 return;
1025 for (int i = 0; i < count; i++){
1026 string base_name = parameters [i].Name;
1027 has_params |= (parameters [i].ModFlags & Parameter.Modifier.PARAMS) != 0;
1029 for (int j = i + 1; j < count; j++){
1030 if (base_name != parameters [j].Name)
1031 continue;
1033 ErrorDuplicateName (parameters [i]);
1034 i = j;
1039 public ParametersCompiled (Parameter [] parameters, bool has_arglist) :
1040 this (parameters)
1042 this.has_arglist = has_arglist;
1045 public static ParametersCompiled CreateFullyResolved (Parameter p, Type type)
1047 return new ParametersCompiled (new Parameter [] { p }, new Type [] { type });
1050 public static ParametersCompiled CreateFullyResolved (Parameter[] parameters, Type[] types)
1052 return new ParametersCompiled (parameters, types);
1055 public static ParametersCompiled MergeGenerated (ParametersCompiled userParams, bool checkConflicts, Parameter compilerParams, Type compilerTypes)
1057 return MergeGenerated (userParams, checkConflicts,
1058 new Parameter [] { compilerParams },
1059 new Type [] { compilerTypes });
1063 // Use this method when you merge compiler generated parameters with user parameters
1065 public static ParametersCompiled MergeGenerated (ParametersCompiled userParams, bool checkConflicts, Parameter[] compilerParams, Type[] compilerTypes)
1067 Parameter[] all_params = new Parameter [userParams.Count + compilerParams.Length];
1068 userParams.FixedParameters.CopyTo(all_params, 0);
1070 Type [] all_types;
1071 if (userParams.types != null) {
1072 all_types = new Type [all_params.Length];
1073 userParams.Types.CopyTo (all_types, 0);
1074 } else {
1075 all_types = null;
1078 int last_filled = userParams.Count;
1079 int index = 0;
1080 foreach (Parameter p in compilerParams) {
1081 for (int i = 0; i < last_filled; ++i) {
1082 while (p.Name == all_params [i].Name) {
1083 if (checkConflicts && i < userParams.Count) {
1084 Report.Error (316, userParams [i].Location,
1085 "The parameter name `{0}' conflicts with a compiler generated name", p.Name);
1087 p.Name = '_' + p.Name;
1090 all_params [last_filled] = p;
1091 if (all_types != null)
1092 all_types [last_filled] = compilerTypes [index++];
1093 ++last_filled;
1096 ParametersCompiled parameters = new ParametersCompiled (all_params, all_types);
1097 parameters.has_params = userParams.has_params;
1098 return parameters;
1101 protected virtual void ErrorDuplicateName (Parameter p)
1103 Report.Error (100, p.Location, "The parameter name `{0}' is a duplicate", p.Name);
1106 public bool Resolve (IResolveContext ec)
1108 if (types != null)
1109 return true;
1111 types = new Type [Count];
1113 bool ok = true;
1114 Parameter p;
1115 for (int i = 0; i < FixedParameters.Length; ++i) {
1116 p = this [i];
1117 Type t = p.Resolve (ec);
1118 if (t == null) {
1119 ok = false;
1120 continue;
1123 types [i] = t;
1126 return ok;
1129 public void ResolveVariable ()
1131 for (int i = 0; i < FixedParameters.Length; ++i) {
1132 this [i].ResolveVariable (i);
1136 public CallingConventions CallingConvention
1138 get {
1139 if (HasArglist)
1140 return CallingConventions.VarArgs;
1141 else
1142 return CallingConventions.Standard;
1146 // Define each type attribute (in/out/ref) and
1147 // the argument names.
1148 public void ApplyAttributes (MethodBase builder)
1150 if (Count == 0)
1151 return;
1153 MethodBuilder mb = builder as MethodBuilder;
1154 ConstructorBuilder cb = builder as ConstructorBuilder;
1156 for (int i = 0; i < Count; i++) {
1157 this [i].ApplyAttributes (mb, cb, i + 1);
1161 public void VerifyClsCompliance ()
1163 foreach (Parameter p in FixedParameters)
1164 p.IsClsCompliant ();
1167 public Parameter this [int pos] {
1168 get { return (Parameter) parameters [pos]; }
1171 public Expression CreateExpressionTree (EmitContext ec, Location loc)
1173 ArrayList initializers = new ArrayList (Count);
1174 foreach (Parameter p in FixedParameters) {
1176 // Each parameter expression is stored to local variable
1177 // to save some memory when referenced later.
1179 StatementExpression se = new StatementExpression (p.CreateExpressionTreeVariable (ec));
1180 if (se.Resolve (ec))
1181 ec.CurrentBlock.AddScopeStatement (se);
1183 initializers.Add (p.ExpressionTreeVariableReference ());
1186 return new ArrayCreation (
1187 Parameter.ResolveParameterExpressionType (ec, loc),
1188 "[]", initializers, loc);
1191 public ParametersCompiled Clone ()
1193 ParametersCompiled p = (ParametersCompiled) MemberwiseClone ();
1195 p.parameters = new IParameterData [parameters.Length];
1196 for (int i = 0; i < Count; ++i)
1197 p.parameters [i] = this [i].Clone ();
1199 return p;