2 // parameter.cs: Parameter definition.
4 // Author: Miguel de Icaza (miguel@gnu.org)
5 // Marek Safar (marek.safar@seznam.cz)
7 // Dual licensed under the terms of the MIT X11 or GNU GPL
9 // Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10 // Copyright 2003-2008 Novell, Inc.
14 using System.Reflection;
15 using System.Reflection.Emit;
18 namespace Mono.CSharp {
21 /// Abstract Base class for parameters of a method.
23 public abstract class ParameterBase : Attributable
25 protected ParameterBuilder builder;
27 public override void ApplyAttributeBuilder (Attribute a, ConstructorInfo ctor, byte[] cdata, PredefinedAttributes pa)
30 if (a.Type == pa.MarshalAs) {
31 UnmanagedMarshal marshal = a.GetMarshal (this);
32 if (marshal != null) {
33 builder.SetMarshal (marshal);
38 if (a.HasSecurityAttribute) {
39 a.Error_InvalidSecurityParent ();
43 if (a.Type == pa.Dynamic) {
44 a.Error_MisusedDynamicAttribute ();
48 builder.SetCustomAttribute (ctor, cdata);
51 public ParameterBuilder Builder {
57 public override bool IsClsComplianceRequired()
64 /// Class for applying custom attributes on the return type
66 public class ReturnParameter : ParameterBase
70 // TODO: merge method and mb
71 public ReturnParameter (MemberCore method, MethodBuilder mb, Location location)
75 builder = mb.DefineParameter (0, ParameterAttributes.None, "");
77 catch (ArgumentOutOfRangeException) {
78 method.Compiler.Report.RuntimeMissingSupport (location, "custom attributes on the return type");
82 public override void ApplyAttributeBuilder (Attribute a, ConstructorInfo ctor, byte[] cdata, PredefinedAttributes pa)
84 if (a.Type == pa.CLSCompliant) {
85 method.Compiler.Report.Warning (3023, 1, a.Location,
86 "CLSCompliant attribute has no meaning when applied to return types. Try putting it on the method instead");
89 // This occurs after Warning -28
93 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
96 public override AttributeTargets AttributeTargets {
98 return AttributeTargets.ReturnValue;
105 public override string[] ValidAttributeTargets {
113 /// Class for applying custom attributes on the implicit parameter type
114 /// of the 'set' method in properties, and the 'add' and 'remove' methods in events.
117 // TODO: should use more code from Parameter.ApplyAttributeBuilder
118 public class ImplicitParameter : ParameterBase {
119 public ImplicitParameter (MethodBuilder mb)
121 builder = mb.DefineParameter (1, ParameterAttributes.None, "value");
124 public override AttributeTargets AttributeTargets {
126 return AttributeTargets.Parameter;
133 public override string[] ValidAttributeTargets {
140 public class ImplicitLambdaParameter : Parameter
142 public ImplicitLambdaParameter (string name, Location loc)
143 : base (null, name, Modifier.NONE, null, loc)
147 public override Type Resolve (IMemberContext ec)
149 if (parameter_type == null)
150 throw new InternalErrorException ("A type of implicit lambda parameter `{0}' is not set",
153 return parameter_type;
157 set { parameter_type = value; }
161 public class ParamsParameter : Parameter {
162 public ParamsParameter (FullNamedExpression type, string name, Attributes attrs, Location loc):
163 base (type, name, Parameter.Modifier.PARAMS, attrs, loc)
167 public override Type Resolve (IMemberContext ec)
169 if (base.Resolve (ec) == null)
172 if (!parameter_type.IsArray || parameter_type.GetArrayRank () != 1) {
173 ec.Compiler.Report.Error (225, Location, "The params parameter must be a single dimensional array");
177 return parameter_type;
180 public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
182 base.ApplyAttributes (mb, cb, index);
183 PredefinedAttributes.Get.ParamArray.EmitAttribute (builder);
187 public class ArglistParameter : Parameter {
188 // Doesn't have proper type because it's never chosen for better conversion
189 public ArglistParameter (Location loc) :
190 base (null, String.Empty, Parameter.Modifier.NONE, null, loc)
194 public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
199 public override bool CheckAccessibility (InterfaceMemberBase member)
204 public override Type Resolve (IMemberContext ec)
206 return InternalType.Arglist;
209 public override string GetSignatureForError ()
215 public interface IParameterData
217 Expression DefaultValue { get; }
218 bool HasExtensionMethodModifier { get; }
219 bool HasDefaultValue { get; }
220 Parameter.Modifier ModFlags { get; }
225 // Parameter information created by parser
227 public class Parameter : ParameterBase, IParameterData, ILocalVariable {
229 public enum Modifier : byte {
231 REF = REFMASK | ISBYREF,
232 OUT = OUTMASK | ISBYREF,
234 // This is a flag which says that it's either REF or OUT.
241 static string[] attribute_targets = new string [] { "param" };
243 protected FullNamedExpression TypeName;
244 readonly Modifier modFlags;
246 Expression default_expr;
247 protected Type parameter_type;
248 public readonly Location Location;
250 public bool HasAddressTaken;
252 Expression expr_tree_variable;
253 static TypeExpr parameter_expr_tree_type;
255 HoistedVariable hoisted_variant;
257 public Parameter (FullNamedExpression type, string name, Modifier mod, Attributes attrs, Location loc)
264 // Only assign, attributes will be attached during resolve
265 base.attributes = attrs;
268 public override void ApplyAttributeBuilder (Attribute a, ConstructorInfo ctor, byte[] cdata, PredefinedAttributes pa)
270 if (a.Type == pa.In && ModFlags == Modifier.OUT) {
271 a.Report.Error (36, a.Location, "An out parameter cannot have the `In' attribute");
275 if (a.Type == pa.ParamArray) {
276 a.Report.Error (674, a.Location, "Do not use `System.ParamArrayAttribute'. Use the `params' keyword instead");
280 if (a.Type == PredefinedAttributes.Get.Out && (ModFlags & Modifier.REF) == Modifier.REF &&
281 !OptAttributes.Contains (pa.In)) {
282 a.Report.Error (662, a.Location,
283 "Cannot specify only `Out' attribute on a ref parameter. Use both `In' and `Out' attributes or neither");
287 if (a.Type == pa.CLSCompliant) {
288 a.Report.Warning (3022, 1, a.Location, "CLSCompliant attribute has no meaning when applied to parameters. Try putting it on the method instead");
291 if (HasDefaultValue && (a.Type == pa.DefaultParameterValue || a.Type == pa.OptionalParameter)) {
292 a.Report.Error (1745, a.Location,
293 "Cannot specify `{0}' attribute on optional parameter `{1}'",
294 TypeManager.CSharpName (a.Type).Replace ("Attribute", ""), Name);
298 if (a.Type == pa.DefaultParameterValue) {
300 var c = a.GetParameterDefaultValue (out arg_type);
302 if (parameter_type == TypeManager.object_type) {
303 a.Report.Error (1910, a.Location, "Argument of type `{0}' is not applicable for the DefaultParameterValue attribute",
304 TypeManager.CSharpName (arg_type));
306 a.Report.Error (1909, a.Location, "The DefaultParameterValue attribute is not applicable on parameters of type `{0}'",
307 TypeManager.CSharpName (parameter_type)); ;
313 var val = c.GetValue ();
314 if (parameter_type == TypeManager.object_type ||
315 (val == null && !TypeManager.IsGenericParameter (parameter_type) && TypeManager.IsReferenceType (parameter_type)) ||
316 (val != null && TypeManager.TypeToCoreType (val.GetType ()) == parameter_type))
317 builder.SetConstant (val);
319 a.Report.Error (1908, a.Location, "The type of the default value should match the type of the parameter");
323 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
326 public virtual bool CheckAccessibility (InterfaceMemberBase member)
328 if (parameter_type == null || TypeManager.IsGenericParameter (parameter_type))
331 return member.IsAccessibleAs (parameter_type);
335 // Resolve is used in method definitions
337 public virtual Type Resolve (IMemberContext rc)
339 if (parameter_type != null)
340 return parameter_type;
342 if (attributes != null)
343 attributes.AttachTo (this, rc);
345 TypeExpr texpr = TypeName.ResolveAsTypeTerminal (rc, false);
349 parameter_type = texpr.Type;
351 // Ignore all checks for dummy members
352 AbstractPropertyEventMethod pem = rc as AbstractPropertyEventMethod;
353 if (pem != null && pem.IsDummy)
354 return parameter_type;
356 if (default_expr != null)
357 default_expr = ResolveDefaultValue (new ResolveContext (rc));
359 if ((modFlags & Parameter.Modifier.ISBYREF) != 0 &&
360 TypeManager.IsSpecialType (parameter_type)) {
361 rc.Compiler.Report.Error (1601, Location, "Method or delegate parameter cannot be of type `{0}'",
362 GetSignatureForError ());
366 TypeManager.CheckTypeVariance (parameter_type,
367 (modFlags & Parameter.Modifier.ISBYREF) != 0 ? Variance.None : Variance.Contravariant,
370 if (TypeManager.IsGenericParameter (parameter_type))
371 return parameter_type;
373 if ((parameter_type.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) {
374 rc.Compiler.Report.Error (721, Location, "`{0}': static types cannot be used as parameters",
375 texpr.GetSignatureForError ());
376 return parameter_type;
379 if ((modFlags & Modifier.This) != 0 && (parameter_type.IsPointer || TypeManager.IsDynamicType (parameter_type))) {
380 rc.Compiler.Report.Error (1103, Location, "The extension method cannot be of type `{0}'",
381 TypeManager.CSharpName (parameter_type));
384 return parameter_type;
387 Expression ResolveDefaultValue (ResolveContext rc)
389 default_expr = default_expr.Resolve (rc);
390 if (default_expr == null)
393 if (!(default_expr is Constant || default_expr is DefaultValueExpression)) {
394 if (TypeManager.IsNullableType (parameter_type)) {
395 rc.Compiler.Report.Error (1770, default_expr.Location,
396 "The expression being assigned to nullable optional parameter `{0}' must be default value",
399 rc.Compiler.Report.Error (1736, default_expr.Location,
400 "The expression being assigned to optional parameter `{0}' must be a constant or default value",
407 if (TypeManager.IsEqual (default_expr.Type, parameter_type))
410 if (TypeManager.IsNullableType (parameter_type)) {
411 if (Convert.ImplicitNulableConversion (rc, default_expr, parameter_type) != null)
414 var res = Convert.ImplicitConversionStandard (rc, default_expr, parameter_type, default_expr.Location);
416 if (!default_expr.IsNull && TypeManager.IsReferenceType (parameter_type) && parameter_type != TypeManager.string_type) {
417 rc.Compiler.Report.Error (1763, default_expr.Location,
418 "Optional parameter `{0}' of type `{1}' can only be initialized with `null'",
419 Name, GetSignatureForError ());
428 rc.Compiler.Report.Error (1750, Location,
429 "Optional parameter expression of type `{0}' cannot be converted to parameter type `{1}'",
430 TypeManager.CSharpName (default_expr.Type), GetSignatureForError ());
435 public void ResolveVariable (int idx)
440 public bool HasDefaultValue {
441 get { return default_expr != null; }
444 public bool HasExtensionMethodModifier {
445 get { return (modFlags & Modifier.This) != 0; }
449 // Hoisted parameter variant
451 public HoistedVariable HoistedVariant {
453 return hoisted_variant;
456 hoisted_variant = value;
460 public Modifier ModFlags {
461 get { return modFlags & ~Modifier.This; }
466 set { name = value; }
469 ParameterAttributes Attributes {
470 get { return ParametersCompiled.GetParameterAttribute (modFlags) |
471 (HasDefaultValue ? ParameterAttributes.Optional : ParameterAttributes.None); }
474 public override AttributeTargets AttributeTargets {
476 return AttributeTargets.Parameter;
480 public virtual string GetSignatureForError ()
483 if (parameter_type != null)
484 type_name = TypeManager.CSharpName (parameter_type);
486 type_name = TypeName.GetSignatureForError ();
488 string mod = GetModifierSignature (modFlags);
490 return String.Concat (mod, " ", type_name);
495 public static string GetModifierSignature (Modifier mod)
500 case Modifier.PARAMS:
511 public void IsClsCompliant (IMemberContext ctx)
513 if (AttributeTester.IsClsCompliant (parameter_type))
516 ctx.Compiler.Report.Warning (3001, 1, Location,
517 "Argument type `{0}' is not CLS-compliant", GetSignatureForError ());
520 public virtual void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
523 builder = cb.DefineParameter (index, Attributes, Name);
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;
537 if (default_expr.Type == TypeManager.decimal_type) {
538 builder.SetCustomAttribute (Const.CreateDecimalConstantAttribute (c));
540 builder.SetConstant (c.GetTypedValue ());
545 if (TypeManager.IsDynamicType (parameter_type)) {
546 PredefinedAttributes.Get.Dynamic.EmitAttribute (builder);
548 var trans_flags = TypeManager.HasDynamicTypeUsed (parameter_type);
549 if (trans_flags != null) {
550 var pa = PredefinedAttributes.Get.DynamicTransform;
551 if (pa.Constructor != null || pa.ResolveConstructor (Location, TypeManager.bool_type.MakeArrayType ())) {
552 builder.SetCustomAttribute (
553 new CustomAttributeBuilder (pa.Constructor, new object [] { trans_flags }));
559 public override string[] ValidAttributeTargets {
561 return attribute_targets;
565 public Parameter Clone ()
567 Parameter p = (Parameter) MemberwiseClone ();
568 if (attributes != null)
569 p.attributes = attributes.Clone ();
574 public ExpressionStatement CreateExpressionTreeVariable (BlockContext ec)
576 if ((modFlags & Modifier.ISBYREF) != 0)
577 ec.Report.Error (1951, Location, "An expression tree parameter cannot use `ref' or `out' modifier");
579 expr_tree_variable = new TemporaryVariable (ResolveParameterExpressionType (ec, Location).Type, Location);
580 expr_tree_variable = expr_tree_variable.Resolve (ec);
582 Arguments arguments = new Arguments (2);
583 arguments.Add (new Argument (new TypeOf (
584 new TypeExpression (parameter_type, Location), Location)));
585 arguments.Add (new Argument (new StringConstant (Name, Location)));
586 return new SimpleAssign (ExpressionTreeVariableReference (),
587 Expression.CreateExpressionFactoryCall (ec, "Parameter", null, arguments, Location));
590 public Expression DefaultValue {
591 get { return default_expr; }
592 set { default_expr = value; }
595 public void Emit (EmitContext ec)
601 ParameterReference.EmitLdArg (ec.ig, arg_idx);
604 public void EmitAssign (EmitContext ec)
611 ec.ig.Emit (OpCodes.Starg_S, (byte) arg_idx);
613 ec.ig.Emit (OpCodes.Starg, arg_idx);
616 public void EmitAddressOf (EmitContext ec)
623 bool is_ref = (ModFlags & Modifier.ISBYREF) != 0;
625 ParameterReference.EmitLdArg (ec.ig, arg_idx);
628 ec.ig.Emit (OpCodes.Ldarga_S, (byte) arg_idx);
630 ec.ig.Emit (OpCodes.Ldarga, arg_idx);
634 public Expression ExpressionTreeVariableReference ()
636 return expr_tree_variable;
640 // System.Linq.Expressions.ParameterExpression type
642 public static TypeExpr ResolveParameterExpressionType (IMemberContext ec, Location location)
644 if (parameter_expr_tree_type != null)
645 return parameter_expr_tree_type;
647 Type p_type = TypeManager.parameter_expression_type;
648 if (p_type == null) {
649 p_type = TypeManager.CoreLookupType (ec.Compiler, "System.Linq.Expressions", "ParameterExpression", MemberKind.Class, true);
650 TypeManager.parameter_expression_type = p_type;
653 parameter_expr_tree_type = new TypeExpression (p_type, location).
654 ResolveAsTypeTerminal (ec, false);
656 return parameter_expr_tree_type;
659 public void Warning_UselessOptionalParameter (Report Report)
661 Report.Warning (1066, 1, Location,
662 "The default value specified for optional parameter `{0}' will never be used",
668 // Imported or resolved parameter information
670 public class ParameterData : IParameterData
672 readonly string name;
673 readonly Parameter.Modifier modifiers;
674 readonly Expression default_value;
676 public ParameterData (string name, Parameter.Modifier modifiers)
679 this.modifiers = modifiers;
682 public ParameterData (string name, Parameter.Modifier modifiers, Expression defaultValue)
683 : this (name, modifiers)
685 this.default_value = defaultValue;
688 #region IParameterData Members
690 public Expression DefaultValue {
691 get { return default_value; }
694 public bool HasExtensionMethodModifier {
695 get { return (modifiers & Parameter.Modifier.This) != 0; }
698 public bool HasDefaultValue {
699 get { return default_value != null; }
702 public Parameter.Modifier ModFlags {
703 get { return modifiers & ~Parameter.Modifier.This; }
713 public abstract class AParametersCollection
715 protected bool has_arglist;
716 protected bool has_params;
718 // Null object pattern
719 protected IParameterData [] parameters;
720 protected Type [] types;
722 public ParametersCompiled AsCompiled {
723 get { return (ParametersCompiled) this; }
726 public CallingConventions CallingConvention {
729 CallingConventions.VarArgs :
730 CallingConventions.Standard;
735 get { return parameters.Length; }
738 public Type ExtensionMethodType {
743 return FixedParameters [0].HasExtensionMethodModifier ?
748 public IParameterData [] FixedParameters {
754 public static ParameterAttributes GetParameterAttribute (Parameter.Modifier modFlags)
756 return (modFlags & Parameter.Modifier.OUT) == Parameter.Modifier.OUT ?
757 ParameterAttributes.Out : ParameterAttributes.None;
760 public Type [] GetEmitTypes ()
762 Type [] types = null;
765 return Type.EmptyTypes;
767 types = new Type [Count - 1];
768 Array.Copy (Types, types, types.Length);
771 for (int i = 0; i < Count; ++i) {
772 if ((FixedParameters [i].ModFlags & Parameter.Modifier.ISBYREF) == 0)
776 types = (Type []) Types.Clone ();
778 types [i] = TypeManager.GetReferenceType (types [i]);
788 // Returns the parameter information based on the name
790 public int GetParameterIndexByName (string name)
792 for (int idx = 0; idx < Count; ++idx) {
793 if (parameters [idx].Name == name)
800 public string GetSignatureForError ()
802 StringBuilder sb = new StringBuilder ("(");
803 for (int i = 0; i < Count; ++i) {
806 sb.Append (ParameterDesc (i));
809 return sb.ToString ();
812 public bool HasArglist {
813 get { return has_arglist; }
816 public bool HasExtensionMethodType {
821 return FixedParameters [0].HasExtensionMethodModifier;
825 public bool HasParams {
826 get { return has_params; }
829 public bool IsEmpty {
830 get { return parameters.Length == 0; }
833 public string ParameterDesc (int pos)
835 if (types == null || types [pos] == null)
836 return ((Parameter)FixedParameters [pos]).GetSignatureForError ();
838 string type = TypeManager.CSharpName (types [pos]);
839 if (FixedParameters [pos].HasExtensionMethodModifier)
840 return "this " + type;
842 Parameter.Modifier mod = FixedParameters [pos].ModFlags;
846 return Parameter.GetModifierSignature (mod) + " " + type;
849 public Type[] Types {
850 get { return types; }
851 set { types = value; }
855 public AParametersCollection InflateTypes (Type[] genArguments, Type[] argTypes)
857 AParametersCollection p = (AParametersCollection) MemberwiseClone (); // Clone ();
859 for (int i = 0; i < Count; ++i) {
860 if (types[i].IsGenericType) {
861 Type[] gen_arguments_open = new Type[types[i].GetGenericTypeDefinition ().GetGenericArguments ().Length];
862 Type[] gen_arguments = types[i].GetGenericArguments ();
863 for (int ii = 0; ii < gen_arguments_open.Length; ++ii) {
864 if (gen_arguments[ii].IsGenericParameter) {
865 Type t = argTypes[gen_arguments[ii].GenericParameterPosition];
866 gen_arguments_open[ii] = t;
868 gen_arguments_open[ii] = gen_arguments[ii];
871 p.types[i] = types[i].GetGenericTypeDefinition ().MakeGenericType (gen_arguments_open);
875 if (types[i].IsGenericParameter) {
876 Type gen_argument = argTypes[types[i].GenericParameterPosition];
877 p.types[i] = gen_argument;
888 // A collection of imported or resolved parameters
890 public class ParametersImported : AParametersCollection
892 ParametersImported (AParametersCollection param, Type[] types)
894 this.parameters = param.FixedParameters;
896 has_arglist = param.HasArglist;
897 has_params = param.HasParams;
900 ParametersImported (IParameterData [] parameters, Type [] types, bool hasArglist, bool hasParams)
902 this.parameters = parameters;
904 this.has_arglist = hasArglist;
905 this.has_params = hasParams;
908 public ParametersImported (IParameterData [] param, Type[] types)
910 this.parameters = param;
914 public static AParametersCollection Create (MethodBase method)
916 return Create (method.GetParameters (), method);
920 // Generic method parameters importer, param is shared between all instances
922 public static AParametersCollection Create (AParametersCollection param, MethodBase method)
927 ParameterInfo [] pi = method.GetParameters ();
928 Type [] types = new Type [pi.Length];
929 for (int i = 0; i < types.Length; i++) {
930 Type t = pi [i].ParameterType;
932 t = TypeManager.GetElementType (t);
934 types [i] = TypeManager.TypeToCoreType (t);
937 return new ParametersImported (param, types);
941 // Imports SRE parameters
943 public static AParametersCollection Create (ParameterInfo [] pi, MethodBase method)
945 int varargs = method != null && (method.CallingConvention & CallingConventions.VarArgs) != 0 ? 1 : 0;
947 if (pi.Length == 0 && varargs == 0)
948 return ParametersCompiled.EmptyReadOnlyParameters;
950 Type [] types = new Type [pi.Length + varargs];
951 IParameterData [] par = new IParameterData [pi.Length + varargs];
952 bool is_params = false;
953 PredefinedAttribute extension_attr = PredefinedAttributes.Get.Extension;
954 PredefinedAttribute param_attr = PredefinedAttributes.Get.ParamArray;
955 for (int i = 0; i < pi.Length; i++) {
956 types [i] = TypeManager.TypeToCoreType (pi [i].ParameterType);
958 ParameterInfo p = pi [i];
959 Parameter.Modifier mod = 0;
960 Expression default_value = null;
961 if (types [i].IsByRef) {
962 if ((p.Attributes & (ParameterAttributes.Out | ParameterAttributes.In)) == ParameterAttributes.Out)
963 mod = Parameter.Modifier.OUT;
965 mod = Parameter.Modifier.REF;
968 // Strip reference wrapping
970 types [i] = TypeManager.GetElementType (types [i]);
971 } else if (i == 0 && extension_attr.IsDefined && method != null && method.IsStatic &&
972 (method.DeclaringType.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute &&
973 method.IsDefined (extension_attr.Type, false)) {
974 mod = Parameter.Modifier.This;
976 if (i >= pi.Length - 2 && types[i].IsArray) {
977 if (p.IsDefined (param_attr.Type, false)) {
978 mod = Parameter.Modifier.PARAMS;
983 if (!is_params && p.IsOptional) {
984 object value = p.DefaultValue;
985 if (value == Missing.Value) {
986 default_value = EmptyExpression.Null;
987 } else if (value == null) {
988 default_value = new NullLiteral (Location.Null);
990 default_value = Constant.CreateConstant (null, value.GetType (), value, Location.Null);
995 par [i] = new ParameterData (p.Name, mod, default_value);
999 par [par.Length - 1] = new ArglistParameter (Location.Null);
1000 types [types.Length - 1] = InternalType.Arglist;
1003 return method != null ?
1004 new ParametersImported (par, types, varargs != 0, is_params) :
1005 new ParametersImported (par, types);
1010 /// Represents the methods parameters
1012 public class ParametersCompiled : AParametersCollection
1014 public static readonly ParametersCompiled EmptyReadOnlyParameters = new ParametersCompiled ();
1016 // Used by C# 2.0 delegates
1017 public static readonly ParametersCompiled Undefined = new ParametersCompiled ();
1019 private ParametersCompiled ()
1021 parameters = new Parameter [0];
1022 types = Type.EmptyTypes;
1025 private ParametersCompiled (Parameter [] parameters, Type [] types)
1027 this.parameters = parameters;
1031 public ParametersCompiled (CompilerContext ctx, params Parameter[] parameters)
1033 if (parameters == null)
1034 throw new ArgumentException ("Use EmptyReadOnlyParameters");
1036 this.parameters = parameters;
1037 int count = parameters.Length;
1043 has_params = (parameters [0].ModFlags & Parameter.Modifier.PARAMS) != 0;
1047 for (int i = 0; i < count; i++){
1048 string base_name = parameters [i].Name;
1049 has_params |= (parameters [i].ModFlags & Parameter.Modifier.PARAMS) != 0;
1051 for (int j = i + 1; j < count; j++){
1052 if (base_name != parameters [j].Name)
1055 ErrorDuplicateName (parameters[i], ctx.Report);
1061 public ParametersCompiled (CompilerContext ctx, Parameter [] parameters, bool has_arglist) :
1062 this (ctx, parameters)
1064 this.has_arglist = has_arglist;
1067 public static ParametersCompiled CreateFullyResolved (Parameter p, Type type)
1069 return new ParametersCompiled (new Parameter [] { p }, new Type [] { type });
1072 public static ParametersCompiled CreateFullyResolved (Parameter[] parameters, Type[] types)
1074 return new ParametersCompiled (parameters, types);
1077 public static ParametersCompiled MergeGenerated (CompilerContext ctx, ParametersCompiled userParams, bool checkConflicts, Parameter compilerParams, Type compilerTypes)
1079 return MergeGenerated (ctx, userParams, checkConflicts,
1080 new Parameter [] { compilerParams },
1081 new Type [] { compilerTypes });
1085 // Use this method when you merge compiler generated parameters with user parameters
1087 public static ParametersCompiled MergeGenerated (CompilerContext ctx, ParametersCompiled userParams, bool checkConflicts, Parameter[] compilerParams, Type[] compilerTypes)
1089 Parameter[] all_params = new Parameter [userParams.Count + compilerParams.Length];
1090 userParams.FixedParameters.CopyTo(all_params, 0);
1093 if (userParams.types != null) {
1094 all_types = new Type [all_params.Length];
1095 userParams.Types.CopyTo (all_types, 0);
1100 int last_filled = userParams.Count;
1102 foreach (Parameter p in compilerParams) {
1103 for (int i = 0; i < last_filled; ++i) {
1104 while (p.Name == all_params [i].Name) {
1105 if (checkConflicts && i < userParams.Count) {
1106 ctx.Report.Error (316, userParams[i].Location,
1107 "The parameter name `{0}' conflicts with a compiler generated name", p.Name);
1109 p.Name = '_' + p.Name;
1112 all_params [last_filled] = p;
1113 if (all_types != null)
1114 all_types [last_filled] = compilerTypes [index++];
1118 ParametersCompiled parameters = new ParametersCompiled (all_params, all_types);
1119 parameters.has_params = userParams.has_params;
1123 protected virtual void ErrorDuplicateName (Parameter p, Report Report)
1125 Report.Error (100, p.Location, "The parameter name `{0}' is a duplicate", p.Name);
1128 public bool Resolve (IMemberContext ec)
1133 types = new Type [Count];
1137 for (int i = 0; i < FixedParameters.Length; ++i) {
1139 Type t = p.Resolve (ec);
1151 public void ResolveVariable ()
1153 for (int i = 0; i < FixedParameters.Length; ++i) {
1154 this [i].ResolveVariable (i);
1158 // Define each type attribute (in/out/ref) and
1159 // the argument names.
1160 public void ApplyAttributes (MethodBase builder)
1165 MethodBuilder mb = builder as MethodBuilder;
1166 ConstructorBuilder cb = builder as ConstructorBuilder;
1168 for (int i = 0; i < Count; i++) {
1169 this [i].ApplyAttributes (mb, cb, i + 1);
1173 public void VerifyClsCompliance (IMemberContext ctx)
1175 foreach (Parameter p in FixedParameters)
1176 p.IsClsCompliant (ctx);
1179 public Parameter this [int pos] {
1180 get { return (Parameter) parameters [pos]; }
1183 public Expression CreateExpressionTree (BlockContext ec, Location loc)
1185 var initializers = new ArrayInitializer (Count, loc);
1186 foreach (Parameter p in FixedParameters) {
1188 // Each parameter expression is stored to local variable
1189 // to save some memory when referenced later.
1191 StatementExpression se = new StatementExpression (p.CreateExpressionTreeVariable (ec));
1192 if (se.Resolve (ec))
1193 ec.CurrentBlock.AddScopeStatement (se);
1195 initializers.Add (p.ExpressionTreeVariableReference ());
1198 return new ArrayCreation (
1199 Parameter.ResolveParameterExpressionType (ec, loc),
1200 "[]", initializers, loc);
1203 public ParametersCompiled Clone ()
1205 ParametersCompiled p = (ParametersCompiled) MemberwiseClone ();
1207 p.parameters = new IParameterData [parameters.Length];
1208 for (int i = 0; i < Count; ++i)
1209 p.parameters [i] = this [i].Clone ();