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.
17 using MetaType = IKVM.Reflection.Type;
18 using IKVM.Reflection;
19 using IKVM.Reflection.Emit;
21 using MetaType = System.Type;
22 using System.Reflection;
23 using System.Reflection.Emit;
26 namespace Mono.CSharp {
29 /// Abstract Base class for parameters of a method.
31 public abstract class ParameterBase : Attributable
33 protected ParameterBuilder builder;
35 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
38 if (a.Type == pa.MarshalAs) {
39 UnmanagedMarshal marshal = a.GetMarshal (this);
40 if (marshal != null) {
41 builder.SetMarshal (marshal);
46 if (a.HasSecurityAttribute) {
47 a.Error_InvalidSecurityParent ();
51 if (a.Type == pa.Dynamic) {
52 a.Error_MisusedDynamicAttribute ();
56 builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
59 public ParameterBuilder Builder {
65 public override bool IsClsComplianceRequired()
72 /// Class for applying custom attributes on the return type
74 public class ReturnParameter : ParameterBase
78 // TODO: merge method and mb
79 public ReturnParameter (MemberCore method, MethodBuilder mb, Location location)
83 builder = mb.DefineParameter (0, ParameterAttributes.None, "");
85 catch (ArgumentOutOfRangeException) {
86 method.Compiler.Report.RuntimeMissingSupport (location, "custom attributes on the return type");
90 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
92 if (a.Type == pa.CLSCompliant) {
93 method.Compiler.Report.Warning (3023, 1, a.Location,
94 "CLSCompliant attribute has no meaning when applied to return types. Try putting it on the method instead");
97 // This occurs after Warning -28
101 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
104 public override AttributeTargets AttributeTargets {
106 return AttributeTargets.ReturnValue;
113 public override string[] ValidAttributeTargets {
120 public class ImplicitLambdaParameter : Parameter
122 public ImplicitLambdaParameter (string name, Location loc)
123 : base (null, name, Modifier.NONE, null, loc)
127 public override TypeSpec Resolve (IMemberContext ec, int index)
129 if (parameter_type == null)
130 throw new InternalErrorException ("A type of implicit lambda parameter `{0}' is not set",
134 return parameter_type;
137 public void SetParameterType (TypeSpec type)
139 parameter_type = type;
143 public class ParamsParameter : Parameter {
144 public ParamsParameter (FullNamedExpression type, string name, Attributes attrs, Location loc):
145 base (type, name, Parameter.Modifier.PARAMS, attrs, loc)
149 public override TypeSpec Resolve (IMemberContext ec, int index)
151 if (base.Resolve (ec, index) == null)
154 var ac = parameter_type as ArrayContainer;
155 if (ac == null || ac.Rank != 1) {
156 ec.Module.Compiler.Report.Error (225, Location, "The params parameter must be a single dimensional array");
160 return parameter_type;
163 public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index, PredefinedAttributes pa)
165 base.ApplyAttributes (mb, cb, index, pa);
166 pa.ParamArray.EmitAttribute (builder);
170 public class ArglistParameter : Parameter {
171 // Doesn't have proper type because it's never chosen for better conversion
172 public ArglistParameter (Location loc) :
173 base (null, String.Empty, Parameter.Modifier.NONE, null, loc)
175 parameter_type = InternalType.Arglist;
178 public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index, PredefinedAttributes pa)
183 public override bool CheckAccessibility (InterfaceMemberBase member)
188 public override TypeSpec Resolve (IMemberContext ec, int index)
190 return parameter_type;
194 public interface IParameterData
196 Expression DefaultValue { get; }
197 bool HasExtensionMethodModifier { get; }
198 bool HasDefaultValue { get; }
199 Parameter.Modifier ModFlags { get; }
204 // Parameter information created by parser
206 public class Parameter : ParameterBase, IParameterData, ILocalVariable // TODO: INamedBlockVariable
209 public enum Modifier : byte {
211 REF = REFMASK | ISBYREF,
212 OUT = OUTMASK | ISBYREF,
214 // This is a flag which says that it's either REF or OUT.
221 static string[] attribute_targets = new string [] { "param" };
223 FullNamedExpression texpr;
224 readonly Modifier modFlags;
226 Expression default_expr;
227 protected TypeSpec parameter_type;
228 readonly Location loc;
230 public bool HasAddressTaken;
232 TemporaryVariableReference expr_tree_variable;
233 static TypeExpr parameter_expr_tree_type;
235 HoistedVariable hoisted_variant;
237 public Parameter (FullNamedExpression type, string name, Modifier mod, Attributes attrs, Location loc)
244 // Only assign, attributes will be attached during resolve
245 base.attributes = attrs;
250 public DefaultParameterValueExpression DefaultValue {
252 return default_expr as DefaultParameterValueExpression;
255 default_expr = value;
259 Expression IParameterData.DefaultValue {
261 var expr = default_expr as DefaultParameterValueExpression;
262 return expr == null ? default_expr : expr.Child;
266 bool HasOptionalExpression {
268 return default_expr is DefaultParameterValueExpression;
272 public Location Location {
278 public TypeSpec Type {
280 return parameter_type;
284 public FullNamedExpression TypeExpression {
290 public override string[] ValidAttributeTargets {
292 return attribute_targets;
298 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
300 if (a.Type == pa.In && ModFlags == Modifier.OUT) {
301 a.Report.Error (36, a.Location, "An out parameter cannot have the `In' attribute");
305 if (a.Type == pa.ParamArray) {
306 a.Report.Error (674, a.Location, "Do not use `System.ParamArrayAttribute'. Use the `params' keyword instead");
310 if (a.Type == pa.Out && (ModFlags & Modifier.REF) == Modifier.REF &&
311 !OptAttributes.Contains (pa.In)) {
312 a.Report.Error (662, a.Location,
313 "Cannot specify only `Out' attribute on a ref parameter. Use both `In' and `Out' attributes or neither");
317 if (a.Type == pa.CLSCompliant) {
318 a.Report.Warning (3022, 1, a.Location, "CLSCompliant attribute has no meaning when applied to parameters. Try putting it on the method instead");
321 if (a.Type == pa.DefaultParameterValue || a.Type == pa.OptionalParameter) {
322 if (HasOptionalExpression) {
323 a.Report.Error (1745, a.Location,
324 "Cannot specify `{0}' attribute on optional parameter `{1}'",
325 TypeManager.CSharpName (a.Type).Replace ("Attribute", ""), Name);
328 if (a.Type == pa.DefaultParameterValue)
332 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
335 public virtual bool CheckAccessibility (InterfaceMemberBase member)
337 if (parameter_type == null)
340 return member.IsAccessibleAs (parameter_type);
343 public static void Reset ()
345 parameter_expr_tree_type = null;
349 // Resolve is used in method definitions
351 public virtual TypeSpec Resolve (IMemberContext rc, int index)
353 if (parameter_type != null)
354 return parameter_type;
356 if (attributes != null)
357 attributes.AttachTo (this, rc);
359 var expr = texpr.ResolveAsTypeTerminal (rc, false);
365 parameter_type = texpr.Type;
367 if ((modFlags & Parameter.Modifier.ISBYREF) != 0 &&
368 TypeManager.IsSpecialType (parameter_type)) {
369 rc.Module.Compiler.Report.Error (1601, Location, "Method or delegate parameter cannot be of type `{0}'",
370 GetSignatureForError ());
374 TypeManager.CheckTypeVariance (parameter_type,
375 (modFlags & Parameter.Modifier.ISBYREF) != 0 ? Variance.None : Variance.Contravariant,
378 if (parameter_type.IsStatic) {
379 rc.Module.Compiler.Report.Error (721, Location, "`{0}': static types cannot be used as parameters",
380 texpr.GetSignatureForError ());
381 return parameter_type;
384 if ((modFlags & Modifier.This) != 0 && (parameter_type.IsPointer || parameter_type == InternalType.Dynamic)) {
385 rc.Module.Compiler.Report.Error (1103, Location, "The extension method cannot be of type `{0}'",
386 TypeManager.CSharpName (parameter_type));
389 return parameter_type;
392 public void ResolveDefaultValue (ResolveContext rc)
395 // Default value was specified using an expression
397 if (default_expr != null) {
398 ((DefaultParameterValueExpression)default_expr).Resolve (rc, this);
402 if (attributes == null)
405 var opt_attr = attributes.Search (rc.Module.PredefinedAttributes.OptionalParameter);
406 var def_attr = attributes.Search (rc.Module.PredefinedAttributes.DefaultParameterValue);
407 if (def_attr != null) {
408 if (def_attr.Resolve () == null)
411 var default_expr_attr = def_attr.GetParameterDefaultValue ();
412 if (default_expr_attr == null)
415 var dpa_rc = def_attr.CreateResolveContext ();
416 default_expr = default_expr_attr.Resolve (dpa_rc);
418 if (default_expr is BoxedCast)
419 default_expr = ((BoxedCast) default_expr).Child;
421 Constant c = default_expr as Constant;
423 if (parameter_type.BuildinType == BuildinTypeSpec.Type.Object) {
424 rc.Report.Error (1910, default_expr.Location,
425 "Argument of type `{0}' is not applicable for the DefaultParameterValue attribute",
426 default_expr.Type.GetSignatureForError ());
428 rc.Report.Error (1909, default_expr.Location,
429 "The DefaultParameterValue attribute is not applicable on parameters of type `{0}'",
430 default_expr.Type.GetSignatureForError ()); ;
437 if (TypeSpecComparer.IsEqual (default_expr.Type, parameter_type) ||
438 (default_expr is NullConstant && TypeManager.IsReferenceType (parameter_type) && !parameter_type.IsGenericParameter) ||
439 TypeSpecComparer.IsEqual (parameter_type, TypeManager.object_type)) {
444 // LAMESPEC: Some really weird csc behaviour which we have to mimic
445 // User operators returning same type as parameter type are considered
446 // valid for this attribute only
448 // struct S { public static implicit operator S (int i) {} }
450 // void M ([DefaultParameterValue (3)]S s)
452 var expr = Convert.ImplicitUserConversion (dpa_rc, default_expr, parameter_type, loc);
453 if (expr != null && TypeSpecComparer.IsEqual (expr.Type, parameter_type)) {
457 rc.Report.Error (1908, default_expr.Location, "The type of the default value should match the type of the parameter");
461 if (opt_attr != null) {
462 default_expr = EmptyExpression.MissingValue;
466 public bool HasDefaultValue {
467 get { return default_expr != null; }
470 public bool HasExtensionMethodModifier {
471 get { return (modFlags & Modifier.This) != 0; }
475 // Hoisted parameter variant
477 public HoistedVariable HoistedVariant {
479 return hoisted_variant;
482 hoisted_variant = value;
486 public Modifier ModFlags {
487 get { return modFlags & ~Modifier.This; }
492 set { name = value; }
495 public override AttributeTargets AttributeTargets {
497 return AttributeTargets.Parameter;
501 public virtual string GetSignatureForError ()
504 if (parameter_type != null)
505 type_name = TypeManager.CSharpName (parameter_type);
507 type_name = texpr.GetSignatureForError ();
509 string mod = GetModifierSignature (modFlags);
511 return String.Concat (mod, " ", type_name);
516 public static string GetModifierSignature (Modifier mod)
521 case Modifier.PARAMS:
532 public void IsClsCompliant (IMemberContext ctx)
534 if (parameter_type.IsCLSCompliant ())
537 ctx.Module.Compiler.Report.Warning (3001, 1, Location,
538 "Argument type `{0}' is not CLS-compliant", parameter_type.GetSignatureForError ());
541 public virtual void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index, PredefinedAttributes pa)
544 throw new InternalErrorException ("builder already exists");
546 var pattrs = ParametersCompiled.GetParameterAttribute (modFlags);
547 if (HasOptionalExpression)
548 pattrs |= ParameterAttributes.Optional;
551 builder = cb.DefineParameter (index, pattrs, Name);
553 builder = mb.DefineParameter (index, pattrs, Name);
555 if (OptAttributes != null)
556 OptAttributes.Emit ();
558 if (HasDefaultValue) {
560 // Emit constant values for true constants only, the other
561 // constant-like expressions will rely on default value expression
563 var def_value = DefaultValue;
564 Constant c = def_value != null ? def_value.Child as Constant : default_expr as Constant;
566 if (default_expr.Type.BuildinType == BuildinTypeSpec.Type.Decimal) {
567 pa.DecimalConstant.EmitAttribute (builder, (decimal) c.GetValue (), c.Location);
569 builder.SetConstant (c.GetValue ());
571 } else if (default_expr.Type.IsStruct) {
573 // Handles special case where default expression is used with value-type
575 // void Foo (S s = default (S)) {}
577 builder.SetConstant (null);
581 if (parameter_type != null) {
582 if (parameter_type == InternalType.Dynamic) {
583 pa.Dynamic.EmitAttribute (builder);
584 } else if (parameter_type.HasDynamicElement) {
585 pa.Dynamic.EmitAttribute (builder, parameter_type, Location);
590 public Parameter Clone ()
592 Parameter p = (Parameter) MemberwiseClone ();
593 if (attributes != null)
594 p.attributes = attributes.Clone ();
599 public ExpressionStatement CreateExpressionTreeVariable (BlockContext ec)
601 if ((modFlags & Modifier.ISBYREF) != 0)
602 ec.Report.Error (1951, Location, "An expression tree parameter cannot use `ref' or `out' modifier");
604 expr_tree_variable = TemporaryVariableReference.Create (ResolveParameterExpressionType (ec, Location).Type, ec.CurrentBlock.ParametersBlock, Location);
605 expr_tree_variable = (TemporaryVariableReference) expr_tree_variable.Resolve (ec);
607 Arguments arguments = new Arguments (2);
608 arguments.Add (new Argument (new TypeOf (
609 new TypeExpression (parameter_type, Location), Location)));
610 arguments.Add (new Argument (new StringConstant (ec.BuildinTypes, Name, Location)));
611 return new SimpleAssign (ExpressionTreeVariableReference (),
612 Expression.CreateExpressionFactoryCall (ec, "Parameter", null, arguments, Location));
615 public void Emit (EmitContext ec)
621 ParameterReference.EmitLdArg (ec, arg_idx);
624 public void EmitAssign (EmitContext ec)
631 ec.Emit (OpCodes.Starg_S, (byte) arg_idx);
633 ec.Emit (OpCodes.Starg, arg_idx);
636 public void EmitAddressOf (EmitContext ec)
643 bool is_ref = (ModFlags & Modifier.ISBYREF) != 0;
645 ParameterReference.EmitLdArg (ec, arg_idx);
648 ec.Emit (OpCodes.Ldarga_S, (byte) arg_idx);
650 ec.Emit (OpCodes.Ldarga, arg_idx);
654 public TemporaryVariableReference ExpressionTreeVariableReference ()
656 return expr_tree_variable;
660 // System.Linq.Expressions.ParameterExpression type
662 public static TypeExpr ResolveParameterExpressionType (IMemberContext ec, Location location)
664 if (parameter_expr_tree_type != null)
665 return parameter_expr_tree_type;
667 TypeSpec p_type = ec.Module.PredefinedTypes.ParameterExpression.Resolve (location);
668 parameter_expr_tree_type = new TypeExpression (p_type, location).
669 ResolveAsTypeTerminal (ec, false);
671 return parameter_expr_tree_type;
674 public void Warning_UselessOptionalParameter (Report Report)
676 Report.Warning (1066, 1, Location,
677 "The default value specified for optional parameter `{0}' will never be used",
683 // Imported or resolved parameter information
685 public class ParameterData : IParameterData
687 readonly string name;
688 readonly Parameter.Modifier modifiers;
689 readonly Expression default_value;
691 public ParameterData (string name, Parameter.Modifier modifiers)
694 this.modifiers = modifiers;
697 public ParameterData (string name, Parameter.Modifier modifiers, Expression defaultValue)
698 : this (name, modifiers)
700 this.default_value = defaultValue;
703 #region IParameterData Members
705 public Expression DefaultValue {
706 get { return default_value; }
709 public bool HasExtensionMethodModifier {
710 get { return (modifiers & Parameter.Modifier.This) != 0; }
713 public bool HasDefaultValue {
714 get { return default_value != null; }
717 public Parameter.Modifier ModFlags {
718 get { return modifiers & ~Parameter.Modifier.This; }
728 public abstract class AParametersCollection
730 protected bool has_arglist;
731 protected bool has_params;
733 // Null object pattern
734 protected IParameterData [] parameters;
735 protected TypeSpec [] types;
737 public CallingConventions CallingConvention {
740 CallingConventions.VarArgs :
741 CallingConventions.Standard;
746 get { return parameters.Length; }
749 public TypeSpec ExtensionMethodType {
754 return FixedParameters [0].HasExtensionMethodModifier ?
759 public IParameterData [] FixedParameters {
765 public static ParameterAttributes GetParameterAttribute (Parameter.Modifier modFlags)
767 return (modFlags & Parameter.Modifier.OUT) == Parameter.Modifier.OUT ?
768 ParameterAttributes.Out : ParameterAttributes.None;
771 // Very expensive operation
772 public MetaType[] GetMetaInfo ()
777 return MetaType.EmptyTypes;
779 types = new MetaType[Count - 1];
782 return MetaType.EmptyTypes;
784 types = new MetaType[Count];
787 for (int i = 0; i < types.Length; ++i) {
788 types[i] = Types[i].GetMetaInfo ();
790 if ((FixedParameters [i].ModFlags & Parameter.Modifier.ISBYREF) == 0)
793 // TODO MemberCache: Should go to MetaInfo getter
794 types [i] = types [i].MakeByRefType ();
801 // Returns the parameter information based on the name
803 public int GetParameterIndexByName (string name)
805 for (int idx = 0; idx < Count; ++idx) {
806 if (parameters [idx].Name == name)
813 public string GetSignatureForError ()
815 return GetSignatureForError ("(", ")", Count);
818 public string GetSignatureForError (string start, string end, int count)
820 StringBuilder sb = new StringBuilder (start);
821 for (int i = 0; i < count; ++i) {
824 sb.Append (ParameterDesc (i));
827 return sb.ToString ();
830 public bool HasArglist {
831 get { return has_arglist; }
834 public bool HasExtensionMethodType {
839 return FixedParameters [0].HasExtensionMethodModifier;
843 public bool HasParams {
844 get { return has_params; }
847 public bool IsEmpty {
848 get { return parameters.Length == 0; }
851 public AParametersCollection Inflate (TypeParameterInflator inflator)
853 TypeSpec[] inflated_types = null;
854 bool default_value = false;
856 for (int i = 0; i < Count; ++i) {
857 var inflated_param = inflator.Inflate (types[i]);
858 if (inflated_types == null) {
859 if (inflated_param == types[i])
862 default_value |= FixedParameters[i] is DefaultValueExpression;
863 inflated_types = new TypeSpec[types.Length];
864 Array.Copy (types, inflated_types, types.Length);
867 inflated_types[i] = inflated_param;
870 if (inflated_types == null)
873 var clone = (AParametersCollection) MemberwiseClone ();
874 clone.types = inflated_types;
876 for (int i = 0; i < Count; ++i) {
877 var dve = clone.FixedParameters[i] as DefaultValueExpression;
879 throw new NotImplementedException ("net");
880 // clone.FixedParameters [i].DefaultValue = new DefaultValueExpression ();
888 public string ParameterDesc (int pos)
890 if (types == null || types [pos] == null)
891 return ((Parameter)FixedParameters [pos]).GetSignatureForError ();
893 string type = TypeManager.CSharpName (types [pos]);
894 if (FixedParameters [pos].HasExtensionMethodModifier)
895 return "this " + type;
897 Parameter.Modifier mod = FixedParameters [pos].ModFlags;
901 return Parameter.GetModifierSignature (mod) + " " + type;
904 public TypeSpec[] Types {
905 get { return types; }
906 set { types = value; }
911 // A collection of imported or resolved parameters
913 public class ParametersImported : AParametersCollection
915 public ParametersImported (IParameterData [] parameters, TypeSpec [] types, bool hasArglist, bool hasParams)
917 this.parameters = parameters;
919 this.has_arglist = hasArglist;
920 this.has_params = hasParams;
923 public ParametersImported (IParameterData[] param, TypeSpec[] types, bool hasParams)
925 this.parameters = param;
927 this.has_params = hasParams;
932 /// Represents the methods parameters
934 public class ParametersCompiled : AParametersCollection
936 public static readonly ParametersCompiled EmptyReadOnlyParameters = new ParametersCompiled ();
938 // Used by C# 2.0 delegates
939 public static readonly ParametersCompiled Undefined = new ParametersCompiled ();
941 private ParametersCompiled ()
943 parameters = new Parameter [0];
944 types = TypeSpec.EmptyTypes;
947 private ParametersCompiled (IParameterData[] parameters, TypeSpec[] types)
949 this.parameters = parameters;
953 public ParametersCompiled (params Parameter[] parameters)
955 if (parameters == null || parameters.Length == 0)
956 throw new ArgumentException ("Use EmptyReadOnlyParameters");
958 this.parameters = parameters;
959 int count = parameters.Length;
961 for (int i = 0; i < count; i++){
962 has_params |= (parameters [i].ModFlags & Parameter.Modifier.PARAMS) != 0;
966 public ParametersCompiled (Parameter [] parameters, bool has_arglist) :
969 this.has_arglist = has_arglist;
972 public static ParametersCompiled CreateFullyResolved (Parameter p, TypeSpec type)
974 return new ParametersCompiled (new Parameter [] { p }, new TypeSpec [] { type });
977 public static ParametersCompiled CreateFullyResolved (Parameter[] parameters, TypeSpec[] types)
979 return new ParametersCompiled (parameters, types);
983 // TODO: This does not fit here, it should go to different version of AParametersCollection
984 // as the underlying type is not Parameter and some methods will fail to cast
986 public static AParametersCollection CreateFullyResolved (TypeSpec[] types)
988 var pd = new ParameterData [types.Length];
989 for (int i = 0; i < pd.Length; ++i)
990 pd[i] = new ParameterData (null, Parameter.Modifier.NONE, null);
992 return new ParametersCompiled (pd, types);
995 public static ParametersCompiled CreateImplicitParameter (FullNamedExpression texpr, Location loc)
997 return new ParametersCompiled (
998 new[] { new Parameter (texpr, "value", Parameter.Modifier.NONE, null, loc) },
1003 // Returns non-zero value for equal CLS parameter signatures
1005 public static int IsSameClsSignature (AParametersCollection a, AParametersCollection b)
1009 for (int i = 0; i < a.Count; ++i) {
1010 var a_type = a.Types[i];
1011 var b_type = b.Types[i];
1012 if (TypeSpecComparer.Override.IsEqual (a_type, b_type)) {
1013 const Parameter.Modifier ref_out = Parameter.Modifier.REF | Parameter.Modifier.OUT;
1014 if ((a.FixedParameters[i].ModFlags & ref_out) != (b.FixedParameters[i].ModFlags & ref_out))
1020 var ac_a = a_type as ArrayContainer;
1024 var ac_b = b_type as ArrayContainer;
1028 if (ac_a.Element is ArrayContainer || ac_b.Element is ArrayContainer) {
1033 if (ac_a.Rank != ac_b.Rank && TypeSpecComparer.Override.IsEqual (ac_a.Element, ac_b.Element)) {
1044 public static ParametersCompiled MergeGenerated (CompilerContext ctx, ParametersCompiled userParams, bool checkConflicts, Parameter compilerParams, TypeSpec compilerTypes)
1046 return MergeGenerated (ctx, userParams, checkConflicts,
1047 new Parameter [] { compilerParams },
1048 new TypeSpec [] { compilerTypes });
1052 // Use this method when you merge compiler generated parameters with user parameters
1054 public static ParametersCompiled MergeGenerated (CompilerContext ctx, ParametersCompiled userParams, bool checkConflicts, Parameter[] compilerParams, TypeSpec[] compilerTypes)
1056 Parameter[] all_params = new Parameter [userParams.Count + compilerParams.Length];
1057 userParams.FixedParameters.CopyTo(all_params, 0);
1059 TypeSpec [] all_types;
1060 if (userParams.types != null) {
1061 all_types = new TypeSpec [all_params.Length];
1062 userParams.Types.CopyTo (all_types, 0);
1067 int last_filled = userParams.Count;
1069 foreach (Parameter p in compilerParams) {
1070 for (int i = 0; i < last_filled; ++i) {
1071 while (p.Name == all_params [i].Name) {
1072 if (checkConflicts && i < userParams.Count) {
1073 ctx.Report.Error (316, userParams[i].Location,
1074 "The parameter name `{0}' conflicts with a compiler generated name", p.Name);
1076 p.Name = '_' + p.Name;
1079 all_params [last_filled] = p;
1080 if (all_types != null)
1081 all_types [last_filled] = compilerTypes [index++];
1085 ParametersCompiled parameters = new ParametersCompiled (all_params, all_types);
1086 parameters.has_params = userParams.has_params;
1090 public bool Resolve (IMemberContext ec)
1095 types = new TypeSpec [Count];
1099 for (int i = 0; i < FixedParameters.Length; ++i) {
1101 TypeSpec t = p.Resolve (ec, i);
1113 public void ResolveDefaultValues (MemberCore m)
1115 ResolveContext rc = null;
1116 for (int i = 0; i < parameters.Length; ++i) {
1117 Parameter p = (Parameter) parameters [i];
1120 // Try not to enter default values resolution if there are is not any default value possible
1122 if (p.HasDefaultValue || p.OptAttributes != null) {
1124 rc = new ResolveContext (m);
1126 p.ResolveDefaultValue (rc);
1131 // Define each type attribute (in/out/ref) and
1132 // the argument names.
1133 public void ApplyAttributes (IMemberContext mc, MethodBase builder)
1138 MethodBuilder mb = builder as MethodBuilder;
1139 ConstructorBuilder cb = builder as ConstructorBuilder;
1140 var pa = mc.Module.PredefinedAttributes;
1142 for (int i = 0; i < Count; i++) {
1143 this [i].ApplyAttributes (mb, cb, i + 1, pa);
1147 public void VerifyClsCompliance (IMemberContext ctx)
1149 foreach (Parameter p in FixedParameters)
1150 p.IsClsCompliant (ctx);
1153 public Parameter this [int pos] {
1154 get { return (Parameter) parameters [pos]; }
1157 public Expression CreateExpressionTree (BlockContext ec, Location loc)
1159 var initializers = new ArrayInitializer (Count, loc);
1160 foreach (Parameter p in FixedParameters) {
1162 // Each parameter expression is stored to local variable
1163 // to save some memory when referenced later.
1165 StatementExpression se = new StatementExpression (p.CreateExpressionTreeVariable (ec));
1166 if (se.Resolve (ec)) {
1167 ec.CurrentBlock.AddScopeStatement (new TemporaryVariableReference.Declarator (p.ExpressionTreeVariableReference ()));
1168 ec.CurrentBlock.AddScopeStatement (se);
1171 initializers.Add (p.ExpressionTreeVariableReference ());
1174 return new ArrayCreation (
1175 Parameter.ResolveParameterExpressionType (ec, loc),
1179 public ParametersCompiled Clone ()
1181 ParametersCompiled p = (ParametersCompiled) MemberwiseClone ();
1183 p.parameters = new IParameterData [parameters.Length];
1184 for (int i = 0; i < Count; ++i)
1185 p.parameters [i] = this [i].Clone ();
1192 // Default parameter value expression. We need this wrapper to handle
1193 // default parameter values of folded constants when for indexer parameters
1194 // The expression is resolved only once but applied to two methods which
1195 // both share reference to this expression and we ensure that resolving
1196 // this expression always returns same instance
1198 public class DefaultParameterValueExpression : CompositeExpression
1200 public DefaultParameterValueExpression (Expression expr)
1205 protected override Expression DoResolve (ResolveContext rc)
1207 return base.DoResolve (rc);
1210 public void Resolve (ResolveContext rc, Parameter p)
1212 var expr = Resolve (rc);
1218 if (!(expr is Constant || expr is DefaultValueExpression || (expr is New && ((New) expr).IsDefaultStruct))) {
1219 rc.Report.Error (1736, Location,
1220 "The expression being assigned to optional parameter `{0}' must be a constant or default value",
1226 var parameter_type = p.Type;
1227 if (type == parameter_type)
1230 var res = Convert.ImplicitConversionStandard (rc, expr, parameter_type, Location);
1232 if (TypeManager.IsNullableType (parameter_type) && res is Nullable.Wrap) {
1233 Nullable.Wrap wrap = (Nullable.Wrap) res;
1235 if (!(res is Constant)) {
1236 rc.Report.Error (1770, Location,
1237 "The expression being assigned to nullable optional parameter `{0}' must be default value",
1243 if (!expr.IsNull && TypeManager.IsReferenceType (parameter_type) && parameter_type.BuildinType != BuildinTypeSpec.Type.String) {
1244 rc.Report.Error (1763, Location,
1245 "Optional parameter `{0}' of type `{1}' can only be initialized with `null'",
1246 p.Name, parameter_type.GetSignatureForError ());
1255 rc.Report.Error (1750, Location,
1256 "Optional parameter expression of type `{0}' cannot be converted to parameter type `{1}'",
1257 type.GetSignatureForError (), parameter_type.GetSignatureForError ());