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;
19 namespace Mono.CSharp {
22 /// Abstract Base class for parameters of a method.
24 public abstract class ParameterBase : Attributable
26 protected ParameterBuilder builder;
28 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
31 if (a.Type == pa.MarshalAs) {
32 UnmanagedMarshal marshal = a.GetMarshal (this);
33 if (marshal != null) {
34 builder.SetMarshal (marshal);
39 if (a.HasSecurityAttribute) {
40 a.Error_InvalidSecurityParent ();
44 if (a.Type == pa.Dynamic) {
45 a.Error_MisusedDynamicAttribute ();
49 builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
52 public ParameterBuilder Builder {
58 public override bool IsClsComplianceRequired()
65 /// Class for applying custom attributes on the return type
67 public class ReturnParameter : ParameterBase
71 // TODO: merge method and mb
72 public ReturnParameter (MemberCore method, MethodBuilder mb, Location location)
76 builder = mb.DefineParameter (0, ParameterAttributes.None, "");
78 catch (ArgumentOutOfRangeException) {
79 method.Compiler.Report.RuntimeMissingSupport (location, "custom attributes on the return type");
83 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
85 if (a.Type == pa.CLSCompliant) {
86 method.Compiler.Report.Warning (3023, 1, a.Location,
87 "CLSCompliant attribute has no meaning when applied to return types. Try putting it on the method instead");
90 // This occurs after Warning -28
94 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
97 public override AttributeTargets AttributeTargets {
99 return AttributeTargets.ReturnValue;
106 public override string[] ValidAttributeTargets {
114 /// Class for applying custom attributes on the implicit parameter type
115 /// of the 'set' method in properties, and the 'add' and 'remove' methods in events.
118 // TODO: should use more code from Parameter.ApplyAttributeBuilder
119 public class ImplicitParameter : ParameterBase {
120 public ImplicitParameter (MethodBuilder mb)
122 builder = mb.DefineParameter (1, ParameterAttributes.None, "value");
125 public override AttributeTargets AttributeTargets {
127 return AttributeTargets.Parameter;
134 public override string[] ValidAttributeTargets {
141 public class ImplicitLambdaParameter : Parameter
143 public ImplicitLambdaParameter (string name, Location loc)
144 : base (null, name, Modifier.NONE, null, loc)
148 public override TypeSpec Resolve (IMemberContext ec, int index)
150 if (parameter_type == null)
151 throw new InternalErrorException ("A type of implicit lambda parameter `{0}' is not set",
155 return parameter_type;
158 public TypeSpec Type {
159 set { parameter_type = value; }
163 public class ParamsParameter : Parameter {
164 public ParamsParameter (FullNamedExpression type, string name, Attributes attrs, Location loc):
165 base (type, name, Parameter.Modifier.PARAMS, attrs, loc)
169 public override TypeSpec Resolve (IMemberContext ec, int index)
171 if (base.Resolve (ec, index) == null)
174 var ac = parameter_type as ArrayContainer;
175 if (ac == null || ac.Rank != 1) {
176 ec.Compiler.Report.Error (225, Location, "The params parameter must be a single dimensional array");
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);
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)
195 parameter_type = InternalType.Arglist;
198 public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
203 public override bool CheckAccessibility (InterfaceMemberBase member)
208 public override TypeSpec Resolve (IMemberContext ec, int index)
210 return parameter_type;
214 public interface IParameterData
216 Expression DefaultValue { get; }
217 bool HasExtensionMethodModifier { get; }
218 bool HasDefaultValue { get; }
219 Parameter.Modifier ModFlags { get; }
224 // Parameter information created by parser
226 public class Parameter : ParameterBase, IParameterData, ILocalVariable {
228 public enum Modifier : byte {
230 REF = REFMASK | ISBYREF,
231 OUT = OUTMASK | ISBYREF,
233 // This is a flag which says that it's either REF or OUT.
240 static string[] attribute_targets = new string [] { "param" };
242 FullNamedExpression texpr;
243 readonly Modifier modFlags;
245 Expression default_expr;
246 protected TypeSpec parameter_type;
247 public readonly Location Location;
249 public bool HasAddressTaken;
251 Expression expr_tree_variable;
252 static TypeExpr parameter_expr_tree_type;
254 HoistedVariable hoisted_variant;
256 public Parameter (FullNamedExpression type, string name, Modifier mod, Attributes attrs, Location loc)
263 // Only assign, attributes will be attached during resolve
264 base.attributes = attrs;
268 public Expression DefaultValue {
273 default_expr = value;
277 public FullNamedExpression TypeExpression {
284 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
286 if (a.Type == pa.In && ModFlags == Modifier.OUT) {
287 a.Report.Error (36, a.Location, "An out parameter cannot have the `In' attribute");
291 if (a.Type == pa.ParamArray) {
292 a.Report.Error (674, a.Location, "Do not use `System.ParamArrayAttribute'. Use the `params' keyword instead");
296 if (a.Type == PredefinedAttributes.Get.Out && (ModFlags & Modifier.REF) == Modifier.REF &&
297 !OptAttributes.Contains (pa.In)) {
298 a.Report.Error (662, a.Location,
299 "Cannot specify only `Out' attribute on a ref parameter. Use both `In' and `Out' attributes or neither");
303 if (a.Type == pa.CLSCompliant) {
304 a.Report.Warning (3022, 1, a.Location, "CLSCompliant attribute has no meaning when applied to parameters. Try putting it on the method instead");
307 if (HasDefaultValue && (a.Type == pa.DefaultParameterValue || a.Type == pa.OptionalParameter)) {
308 a.Report.Error (1745, a.Location,
309 "Cannot specify `{0}' attribute on optional parameter `{1}'",
310 TypeManager.CSharpName (a.Type).Replace ("Attribute", ""), Name);
314 if (a.Type == pa.DefaultParameterValue) {
316 var c = a.GetParameterDefaultValue (out arg_type);
318 if (parameter_type == TypeManager.object_type) {
319 a.Report.Error (1910, a.Location, "Argument of type `{0}' is not applicable for the DefaultParameterValue attribute",
320 arg_type.GetSignatureForError ());
322 a.Report.Error (1909, a.Location, "The DefaultParameterValue attribute is not applicable on parameters of type `{0}'",
323 parameter_type.GetSignatureForError ()); ;
329 if (arg_type == parameter_type || parameter_type == TypeManager.object_type ||
330 (c.IsNull && TypeManager.IsReferenceType (parameter_type) && !TypeManager.IsGenericParameter (parameter_type)))
331 builder.SetConstant (c.GetValue ());
333 a.Report.Error (1908, a.Location, "The type of the default value should match the type of the parameter");
338 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
341 public virtual bool CheckAccessibility (InterfaceMemberBase member)
343 if (parameter_type == null)
346 return member.IsAccessibleAs (parameter_type);
349 public static void Reset ()
351 parameter_expr_tree_type = null;
355 // Resolve is used in method definitions
357 public virtual TypeSpec Resolve (IMemberContext rc, int index)
359 if (parameter_type != null)
360 return parameter_type;
362 if (attributes != null)
363 attributes.AttachTo (this, rc);
365 var expr = texpr.ResolveAsTypeTerminal (rc, false);
371 parameter_type = texpr.Type;
373 if ((modFlags & Parameter.Modifier.ISBYREF) != 0 &&
374 TypeManager.IsSpecialType (parameter_type)) {
375 rc.Compiler.Report.Error (1601, Location, "Method or delegate parameter cannot be of type `{0}'",
376 GetSignatureForError ());
380 TypeManager.CheckTypeVariance (parameter_type,
381 (modFlags & Parameter.Modifier.ISBYREF) != 0 ? Variance.None : Variance.Contravariant,
384 if (parameter_type.IsStatic) {
385 rc.Compiler.Report.Error (721, Location, "`{0}': static types cannot be used as parameters",
386 texpr.GetSignatureForError ());
387 return parameter_type;
390 if ((modFlags & Modifier.This) != 0 && (parameter_type.IsPointer || parameter_type == InternalType.Dynamic)) {
391 rc.Compiler.Report.Error (1103, Location, "The extension method cannot be of type `{0}'",
392 TypeManager.CSharpName (parameter_type));
395 return parameter_type;
398 public void ResolveDefaultValue (ResolveContext rc)
401 // Default value was specified using an expression
403 if (default_expr != null) {
404 default_expr = ResolveDefaultExpression (rc);
408 if (attributes == null)
411 var pa = attributes.Search (PredefinedAttributes.Get.OptionalParameter);
416 // Default value was specified using an attribute
418 attributes.Attrs.Remove (pa);
420 TypeSpec expr_type = null;
421 pa = attributes.Search (PredefinedAttributes.Get.DefaultParameterValue);
423 attributes.Attrs.Remove (pa);
424 default_expr = pa.GetParameterDefaultValue (out expr_type);
426 default_expr = EmptyExpression.MissingValue;
429 if (default_expr == null) {
430 if (expr_type == null)
431 expr_type = parameter_type;
433 default_expr = new DefaultValueExpression (new TypeExpression (expr_type, Location), Location);
436 default_expr = default_expr.Resolve (rc);
439 Expression ResolveDefaultExpression (ResolveContext rc)
441 default_expr = default_expr.Resolve (rc);
442 if (default_expr == null)
445 if (!(default_expr is Constant || default_expr is DefaultValueExpression)) {
446 if (TypeManager.IsNullableType (parameter_type)) {
447 rc.Compiler.Report.Error (1770, default_expr.Location,
448 "The expression being assigned to nullable optional parameter `{0}' must be default value",
451 rc.Compiler.Report.Error (1736, default_expr.Location,
452 "The expression being assigned to optional parameter `{0}' must be a constant or default value",
459 if (default_expr.Type == parameter_type)
462 if (TypeManager.IsNullableType (parameter_type)) {
463 if (Convert.ImplicitNulableConversion (rc, default_expr, parameter_type) != null)
466 var res = Convert.ImplicitConversionStandard (rc, default_expr, parameter_type, default_expr.Location);
468 if (!default_expr.IsNull && TypeManager.IsReferenceType (parameter_type) && parameter_type != TypeManager.string_type) {
469 rc.Compiler.Report.Error (1763, default_expr.Location,
470 "Optional parameter `{0}' of type `{1}' can only be initialized with `null'",
471 Name, GetSignatureForError ());
480 rc.Compiler.Report.Error (1750, Location,
481 "Optional parameter expression of type `{0}' cannot be converted to parameter type `{1}'",
482 TypeManager.CSharpName (default_expr.Type), GetSignatureForError ());
487 public bool HasDefaultValue {
488 get { return default_expr != null; }
491 public bool HasExtensionMethodModifier {
492 get { return (modFlags & Modifier.This) != 0; }
496 // Hoisted parameter variant
498 public HoistedVariable HoistedVariant {
500 return hoisted_variant;
503 hoisted_variant = value;
507 public Modifier ModFlags {
508 get { return modFlags & ~Modifier.This; }
513 set { name = value; }
516 ParameterAttributes Attributes {
517 get { return ParametersCompiled.GetParameterAttribute (modFlags) |
518 (HasDefaultValue ? ParameterAttributes.Optional : ParameterAttributes.None); }
521 public override AttributeTargets AttributeTargets {
523 return AttributeTargets.Parameter;
527 public virtual string GetSignatureForError ()
530 if (parameter_type != null)
531 type_name = TypeManager.CSharpName (parameter_type);
533 type_name = texpr.GetSignatureForError ();
535 string mod = GetModifierSignature (modFlags);
537 return String.Concat (mod, " ", type_name);
542 public static string GetModifierSignature (Modifier mod)
547 case Modifier.PARAMS:
558 public void IsClsCompliant (IMemberContext ctx)
560 if (parameter_type.IsCLSCompliant ())
563 ctx.Compiler.Report.Warning (3001, 1, Location,
564 "Argument type `{0}' is not CLS-compliant", GetSignatureForError ());
567 public virtual void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
570 builder = cb.DefineParameter (index, Attributes, Name);
572 builder = mb.DefineParameter (index, Attributes, Name);
574 if (OptAttributes != null)
575 OptAttributes.Emit ();
577 if (HasDefaultValue) {
579 // Emit constant values for true constants only, the other
580 // constant-like expressions will rely on default value expression
582 Constant c = default_expr as Constant;
584 if (default_expr.Type == TypeManager.decimal_type) {
585 builder.SetCustomAttribute (Const.CreateDecimalConstantAttribute (c));
587 builder.SetConstant (c.GetTypedValue ());
592 if (parameter_type == InternalType.Dynamic) {
593 PredefinedAttributes.Get.Dynamic.EmitAttribute (builder);
595 var trans_flags = TypeManager.HasDynamicTypeUsed (parameter_type);
596 if (trans_flags != null) {
597 var pa = PredefinedAttributes.Get.DynamicTransform;
598 if (pa.Constructor != null || pa.ResolveConstructor (Location, ArrayContainer.MakeType (TypeManager.bool_type))) {
599 builder.SetCustomAttribute (
600 new CustomAttributeBuilder (pa.Constructor, new object [] { trans_flags }));
606 public override string[] ValidAttributeTargets {
608 return attribute_targets;
612 public Parameter Clone ()
614 Parameter p = (Parameter) MemberwiseClone ();
615 if (attributes != null)
616 p.attributes = attributes.Clone ();
621 public ExpressionStatement CreateExpressionTreeVariable (BlockContext ec)
623 if ((modFlags & Modifier.ISBYREF) != 0)
624 ec.Report.Error (1951, Location, "An expression tree parameter cannot use `ref' or `out' modifier");
626 expr_tree_variable = new TemporaryVariable (ResolveParameterExpressionType (ec, Location).Type, Location);
627 expr_tree_variable = expr_tree_variable.Resolve (ec);
629 Arguments arguments = new Arguments (2);
630 arguments.Add (new Argument (new TypeOf (
631 new TypeExpression (parameter_type, Location), Location)));
632 arguments.Add (new Argument (new StringConstant (Name, Location)));
633 return new SimpleAssign (ExpressionTreeVariableReference (),
634 Expression.CreateExpressionFactoryCall (ec, "Parameter", null, arguments, Location));
637 public void Emit (EmitContext ec)
643 ParameterReference.EmitLdArg (ec, arg_idx);
646 public void EmitAssign (EmitContext ec)
653 ec.Emit (OpCodes.Starg_S, (byte) arg_idx);
655 ec.Emit (OpCodes.Starg, arg_idx);
658 public void EmitAddressOf (EmitContext ec)
665 bool is_ref = (ModFlags & Modifier.ISBYREF) != 0;
667 ParameterReference.EmitLdArg (ec, arg_idx);
670 ec.Emit (OpCodes.Ldarga_S, (byte) arg_idx);
672 ec.Emit (OpCodes.Ldarga, arg_idx);
676 public Expression ExpressionTreeVariableReference ()
678 return expr_tree_variable;
682 // System.Linq.Expressions.ParameterExpression type
684 public static TypeExpr ResolveParameterExpressionType (IMemberContext ec, Location location)
686 if (parameter_expr_tree_type != null)
687 return parameter_expr_tree_type;
689 TypeSpec p_type = TypeManager.parameter_expression_type;
690 if (p_type == null) {
691 p_type = TypeManager.CoreLookupType (ec.Compiler, "System.Linq.Expressions", "ParameterExpression", MemberKind.Class, true);
692 TypeManager.parameter_expression_type = p_type;
695 parameter_expr_tree_type = new TypeExpression (p_type, location).
696 ResolveAsTypeTerminal (ec, false);
698 return parameter_expr_tree_type;
701 public void Warning_UselessOptionalParameter (Report Report)
703 Report.Warning (1066, 1, Location,
704 "The default value specified for optional parameter `{0}' will never be used",
710 // Imported or resolved parameter information
712 public class ParameterData : IParameterData
714 readonly string name;
715 readonly Parameter.Modifier modifiers;
716 readonly Expression default_value;
718 public ParameterData (string name, Parameter.Modifier modifiers)
721 this.modifiers = modifiers;
724 public ParameterData (string name, Parameter.Modifier modifiers, Expression defaultValue)
725 : this (name, modifiers)
727 this.default_value = defaultValue;
730 #region IParameterData Members
732 public Expression DefaultValue {
733 get { return default_value; }
736 public bool HasExtensionMethodModifier {
737 get { return (modifiers & Parameter.Modifier.This) != 0; }
740 public bool HasDefaultValue {
741 get { return default_value != null; }
744 public Parameter.Modifier ModFlags {
745 get { return modifiers & ~Parameter.Modifier.This; }
755 public abstract class AParametersCollection
757 protected bool has_arglist;
758 protected bool has_params;
760 // Null object pattern
761 protected IParameterData [] parameters;
762 protected TypeSpec [] types;
764 public CallingConventions CallingConvention {
767 CallingConventions.VarArgs :
768 CallingConventions.Standard;
773 get { return parameters.Length; }
776 public TypeSpec ExtensionMethodType {
781 return FixedParameters [0].HasExtensionMethodModifier ?
786 public IParameterData [] FixedParameters {
792 public static ParameterAttributes GetParameterAttribute (Parameter.Modifier modFlags)
794 return (modFlags & Parameter.Modifier.OUT) == Parameter.Modifier.OUT ?
795 ParameterAttributes.Out : ParameterAttributes.None;
798 // Very expensive operation
799 public Type[] GetMetaInfo ()
804 return Type.EmptyTypes;
806 types = new Type [Count - 1];
809 return Type.EmptyTypes;
811 types = new Type [Count];
814 for (int i = 0; i < types.Length; ++i) {
815 types[i] = Types[i].GetMetaInfo ();
817 if ((FixedParameters [i].ModFlags & Parameter.Modifier.ISBYREF) == 0)
820 // TODO MemberCache: Should go to MetaInfo getter
821 types [i] = types [i].MakeByRefType ();
828 // Returns the parameter information based on the name
830 public int GetParameterIndexByName (string name)
832 for (int idx = 0; idx < Count; ++idx) {
833 if (parameters [idx].Name == name)
840 public string GetSignatureForError ()
842 return GetSignatureForError ("(", ")", Count);
845 public string GetSignatureForError (string start, string end, int count)
847 StringBuilder sb = new StringBuilder (start);
848 for (int i = 0; i < count; ++i) {
851 sb.Append (ParameterDesc (i));
854 return sb.ToString ();
857 public bool HasArglist {
858 get { return has_arglist; }
861 public bool HasExtensionMethodType {
866 return FixedParameters [0].HasExtensionMethodModifier;
870 public bool HasParams {
871 get { return has_params; }
874 public bool IsEmpty {
875 get { return parameters.Length == 0; }
878 public AParametersCollection Inflate (TypeParameterInflator inflator)
880 TypeSpec[] inflated_types = null;
881 bool default_value = false;
883 for (int i = 0; i < Count; ++i) {
884 var inflated_param = inflator.Inflate (types[i]);
885 if (inflated_types == null) {
886 if (inflated_param == types[i])
889 default_value |= FixedParameters[i] is DefaultValueExpression;
890 inflated_types = new TypeSpec[types.Length];
891 Array.Copy (types, inflated_types, types.Length);
894 inflated_types[i] = inflated_param;
897 if (inflated_types == null)
900 var clone = (AParametersCollection) MemberwiseClone ();
901 clone.types = inflated_types;
903 for (int i = 0; i < Count; ++i) {
904 var dve = clone.FixedParameters[i] as DefaultValueExpression;
906 throw new NotImplementedException ("net");
907 // clone.FixedParameters [i].DefaultValue = new DefaultValueExpression ();
915 public string ParameterDesc (int pos)
917 if (types == null || types [pos] == null)
918 return ((Parameter)FixedParameters [pos]).GetSignatureForError ();
920 string type = TypeManager.CSharpName (types [pos]);
921 if (FixedParameters [pos].HasExtensionMethodModifier)
922 return "this " + type;
924 Parameter.Modifier mod = FixedParameters [pos].ModFlags;
928 return Parameter.GetModifierSignature (mod) + " " + type;
931 public TypeSpec[] Types {
932 get { return types; }
933 set { types = value; }
938 // A collection of imported or resolved parameters
940 public class ParametersImported : AParametersCollection
942 public ParametersImported (IParameterData [] parameters, TypeSpec [] types, bool hasArglist, bool hasParams)
944 this.parameters = parameters;
946 this.has_arglist = hasArglist;
947 this.has_params = hasParams;
950 public ParametersImported (IParameterData[] param, TypeSpec[] types, bool hasParams)
952 this.parameters = param;
954 this.has_params = hasParams;
959 /// Represents the methods parameters
961 public class ParametersCompiled : AParametersCollection
963 public static readonly ParametersCompiled EmptyReadOnlyParameters = new ParametersCompiled ();
965 // Used by C# 2.0 delegates
966 public static readonly ParametersCompiled Undefined = new ParametersCompiled ();
968 private ParametersCompiled ()
970 parameters = new Parameter [0];
971 types = TypeSpec.EmptyTypes;
974 private ParametersCompiled (IParameterData[] parameters, TypeSpec[] types)
976 this.parameters = parameters;
980 public ParametersCompiled (CompilerContext ctx, params Parameter[] parameters)
982 if (parameters == null)
983 throw new ArgumentException ("Use EmptyReadOnlyParameters");
985 this.parameters = parameters;
986 int count = parameters.Length;
992 has_params = (parameters [0].ModFlags & Parameter.Modifier.PARAMS) != 0;
996 for (int i = 0; i < count; i++){
997 has_params |= (parameters [i].ModFlags & Parameter.Modifier.PARAMS) != 0;
999 string base_name = parameters[i].Name;
1001 for (int j = i + 1; j < count; j++) {
1002 if (base_name != parameters[j].Name)
1005 ErrorDuplicateName (parameters[i], ctx.Report);
1012 public ParametersCompiled (CompilerContext ctx, Parameter [] parameters, bool has_arglist) :
1013 this (ctx, parameters)
1015 this.has_arglist = has_arglist;
1018 public static ParametersCompiled CreateFullyResolved (Parameter p, TypeSpec type)
1020 return new ParametersCompiled (new Parameter [] { p }, new TypeSpec [] { type });
1023 public static ParametersCompiled CreateFullyResolved (Parameter[] parameters, TypeSpec[] types)
1025 return new ParametersCompiled (parameters, types);
1029 // TODO: This does not fit here, it should go to different version of AParametersCollection
1030 // as the underlying type is not Parameter and some methods will fail to cast
1032 public static AParametersCollection CreateFullyResolved (TypeSpec[] types)
1034 var pd = new ParameterData [types.Length];
1035 for (int i = 0; i < pd.Length; ++i)
1036 pd[i] = new ParameterData (null, Parameter.Modifier.NONE, null);
1038 return new ParametersCompiled (pd, types);
1041 public static ParametersCompiled CreateImplicitParameter (FullNamedExpression texpr, Location loc)
1043 return new ParametersCompiled (
1044 new[] { new Parameter (texpr, "value", Parameter.Modifier.NONE, null, loc) },
1049 // Returns non-zero value for equal CLS parameter signatures
1051 public static int IsSameClsSignature (AParametersCollection a, AParametersCollection b)
1055 for (int i = 0; i < a.Count; ++i) {
1056 var a_type = a.Types[i];
1057 var b_type = b.Types[i];
1058 if (TypeSpecComparer.Override.IsEqual (a_type, b_type)) {
1059 const Parameter.Modifier ref_out = Parameter.Modifier.REF | Parameter.Modifier.OUT;
1060 if ((a.FixedParameters[i].ModFlags & ref_out) != (b.FixedParameters[i].ModFlags & ref_out))
1066 var ac_a = a_type as ArrayContainer;
1070 var ac_b = b_type as ArrayContainer;
1074 if (ac_a.Element is ArrayContainer || ac_b.Element is ArrayContainer) {
1079 if (ac_a.Rank != ac_b.Rank && TypeSpecComparer.Override.IsEqual (ac_a.Element, ac_b.Element)) {
1090 public static ParametersCompiled MergeGenerated (CompilerContext ctx, ParametersCompiled userParams, bool checkConflicts, Parameter compilerParams, TypeSpec compilerTypes)
1092 return MergeGenerated (ctx, userParams, checkConflicts,
1093 new Parameter [] { compilerParams },
1094 new TypeSpec [] { compilerTypes });
1098 // Use this method when you merge compiler generated parameters with user parameters
1100 public static ParametersCompiled MergeGenerated (CompilerContext ctx, ParametersCompiled userParams, bool checkConflicts, Parameter[] compilerParams, TypeSpec[] compilerTypes)
1102 Parameter[] all_params = new Parameter [userParams.Count + compilerParams.Length];
1103 userParams.FixedParameters.CopyTo(all_params, 0);
1105 TypeSpec [] all_types;
1106 if (userParams.types != null) {
1107 all_types = new TypeSpec [all_params.Length];
1108 userParams.Types.CopyTo (all_types, 0);
1113 int last_filled = userParams.Count;
1115 foreach (Parameter p in compilerParams) {
1116 for (int i = 0; i < last_filled; ++i) {
1117 while (p.Name == all_params [i].Name) {
1118 if (checkConflicts && i < userParams.Count) {
1119 ctx.Report.Error (316, userParams[i].Location,
1120 "The parameter name `{0}' conflicts with a compiler generated name", p.Name);
1122 p.Name = '_' + p.Name;
1125 all_params [last_filled] = p;
1126 if (all_types != null)
1127 all_types [last_filled] = compilerTypes [index++];
1131 ParametersCompiled parameters = new ParametersCompiled (all_params, all_types);
1132 parameters.has_params = userParams.has_params;
1136 protected virtual void ErrorDuplicateName (Parameter p, Report Report)
1138 Report.Error (100, p.Location, "The parameter name `{0}' is a duplicate", p.Name);
1141 public bool Resolve (IMemberContext ec)
1146 types = new TypeSpec [Count];
1150 for (int i = 0; i < FixedParameters.Length; ++i) {
1152 TypeSpec t = p.Resolve (ec, i);
1164 public void ResolveDefaultValues (MemberCore m)
1166 var count = parameters.Length;
1169 // Try not to enter default values resolution if there are not any
1171 if (parameters[count - 1].HasDefaultValue || (HasParams && count > 1 && parameters[count - 2].HasDefaultValue) ||
1172 ((Parameter) parameters[count - 1]).OptAttributes != null) {
1173 var rc = new ResolveContext (m);
1174 for (int i = 0; i < count; ++i) {
1175 this [i].ResolveDefaultValue (rc);
1180 // Define each type attribute (in/out/ref) and
1181 // the argument names.
1182 public void ApplyAttributes (MethodBase builder)
1187 MethodBuilder mb = builder as MethodBuilder;
1188 ConstructorBuilder cb = builder as ConstructorBuilder;
1190 for (int i = 0; i < Count; i++) {
1191 this [i].ApplyAttributes (mb, cb, i + 1);
1195 public void VerifyClsCompliance (IMemberContext ctx)
1197 foreach (Parameter p in FixedParameters)
1198 p.IsClsCompliant (ctx);
1201 public Parameter this [int pos] {
1202 get { return (Parameter) parameters [pos]; }
1205 public Expression CreateExpressionTree (BlockContext ec, Location loc)
1207 var initializers = new ArrayInitializer (Count, loc);
1208 foreach (Parameter p in FixedParameters) {
1210 // Each parameter expression is stored to local variable
1211 // to save some memory when referenced later.
1213 StatementExpression se = new StatementExpression (p.CreateExpressionTreeVariable (ec));
1214 if (se.Resolve (ec))
1215 ec.CurrentBlock.AddScopeStatement (se);
1217 initializers.Add (p.ExpressionTreeVariableReference ());
1220 return new ArrayCreation (
1221 Parameter.ResolveParameterExpressionType (ec, loc),
1225 public ParametersCompiled Clone ()
1227 ParametersCompiled p = (ParametersCompiled) MemberwiseClone ();
1229 p.parameters = new IParameterData [parameters.Length];
1230 for (int i = 0; i < Count; ++i)
1231 p.parameters [i] = this [i].Clone ();