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.
11 // Copyright 2011 Xamarin Inc
18 using MetaType = IKVM.Reflection.Type;
19 using IKVM.Reflection;
20 using IKVM.Reflection.Emit;
22 using MetaType = System.Type;
23 using System.Reflection;
24 using System.Reflection.Emit;
27 namespace Mono.CSharp {
30 /// Abstract Base class for parameters of a method.
32 public abstract class ParameterBase : Attributable
34 protected ParameterBuilder builder;
36 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
39 if (a.Type == pa.MarshalAs) {
40 UnmanagedMarshal marshal = a.GetMarshal (this);
41 if (marshal != null) {
42 builder.SetMarshal (marshal);
47 if (a.HasSecurityAttribute) {
48 a.Error_InvalidSecurityParent ();
52 if (a.Type == pa.Dynamic) {
53 a.Error_MisusedDynamicAttribute ();
57 builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
60 public ParameterBuilder Builder {
66 public override bool IsClsComplianceRequired()
73 /// Class for applying custom attributes on the return type
75 public class ReturnParameter : ParameterBase
79 // TODO: merge method and mb
80 public ReturnParameter (MemberCore method, MethodBuilder mb, Location location)
84 builder = mb.DefineParameter (0, ParameterAttributes.None, "");
86 catch (ArgumentOutOfRangeException) {
87 method.Compiler.Report.RuntimeMissingSupport (location, "custom attributes on the return type");
91 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
93 if (a.Type == pa.CLSCompliant) {
94 method.Compiler.Report.Warning (3023, 1, a.Location,
95 "CLSCompliant attribute has no meaning when applied to return types. Try putting it on the method instead");
98 // This occurs after Warning -28
102 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
105 public override AttributeTargets AttributeTargets {
107 return AttributeTargets.ReturnValue;
114 public override string[] ValidAttributeTargets {
121 public class ImplicitLambdaParameter : Parameter
123 public ImplicitLambdaParameter (string name, Location loc)
124 : base (null, name, Modifier.NONE, null, loc)
128 public override TypeSpec Resolve (IMemberContext ec, int index)
130 if (parameter_type == null)
131 throw new InternalErrorException ("A type of implicit lambda parameter `{0}' is not set",
135 return parameter_type;
138 public void SetParameterType (TypeSpec type)
140 parameter_type = type;
144 public class ParamsParameter : Parameter {
145 public ParamsParameter (FullNamedExpression type, string name, Attributes attrs, Location loc):
146 base (type, name, Parameter.Modifier.PARAMS, attrs, loc)
150 public override TypeSpec Resolve (IMemberContext ec, int index)
152 if (base.Resolve (ec, index) == null)
155 var ac = parameter_type as ArrayContainer;
156 if (ac == null || ac.Rank != 1) {
157 ec.Module.Compiler.Report.Error (225, Location, "The params parameter must be a single dimensional array");
161 return parameter_type;
164 public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index, PredefinedAttributes pa)
166 base.ApplyAttributes (mb, cb, index, pa);
167 pa.ParamArray.EmitAttribute (builder);
171 public class ArglistParameter : Parameter {
172 // Doesn't have proper type because it's never chosen for better conversion
173 public ArglistParameter (Location loc) :
174 base (null, String.Empty, Parameter.Modifier.NONE, null, loc)
176 parameter_type = InternalType.Arglist;
179 public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index, PredefinedAttributes pa)
184 public override bool CheckAccessibility (InterfaceMemberBase member)
189 public override TypeSpec Resolve (IMemberContext ec, int index)
191 return parameter_type;
195 public interface IParameterData
197 Expression DefaultValue { get; }
198 bool HasExtensionMethodModifier { get; }
199 bool HasDefaultValue { get; }
200 Parameter.Modifier ModFlags { get; }
205 // Parameter information created by parser
207 public class Parameter : ParameterBase, IParameterData, ILocalVariable // TODO: INamedBlockVariable
210 public enum Modifier : byte {
212 REF = REFMASK | ISBYREF,
213 OUT = OUTMASK | ISBYREF,
215 // This is a flag which says that it's either REF or OUT.
219 SignatureMask = REFMASK | OUTMASK,
223 static readonly string[] attribute_targets = new string[] { "param" };
225 FullNamedExpression texpr;
226 readonly Modifier modFlags;
228 Expression default_expr;
229 protected TypeSpec parameter_type;
230 readonly Location loc;
232 public bool HasAddressTaken;
234 TemporaryVariableReference expr_tree_variable;
236 HoistedVariable hoisted_variant;
238 public Parameter (FullNamedExpression type, string name, Modifier mod, Attributes attrs, Location loc)
245 // Only assign, attributes will be attached during resolve
246 base.attributes = attrs;
251 public DefaultParameterValueExpression DefaultValue {
253 return default_expr as DefaultParameterValueExpression;
256 default_expr = value;
260 Expression IParameterData.DefaultValue {
262 var expr = default_expr as DefaultParameterValueExpression;
263 return expr == null ? default_expr : expr.Child;
267 bool HasOptionalExpression {
269 return default_expr is DefaultParameterValueExpression;
273 public Location Location {
279 public TypeSpec Type {
281 return parameter_type;
284 parameter_type = value;
288 public FullNamedExpression TypeExpression {
294 public override string[] ValidAttributeTargets {
296 return attribute_targets;
302 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
304 if (a.Type == pa.In && ModFlags == Modifier.OUT) {
305 a.Report.Error (36, a.Location, "An out parameter cannot have the `In' attribute");
309 if (a.Type == pa.ParamArray) {
310 a.Report.Error (674, a.Location, "Do not use `System.ParamArrayAttribute'. Use the `params' keyword instead");
314 if (a.Type == pa.Out && (ModFlags & Modifier.REF) == Modifier.REF &&
315 !OptAttributes.Contains (pa.In)) {
316 a.Report.Error (662, a.Location,
317 "Cannot specify only `Out' attribute on a ref parameter. Use both `In' and `Out' attributes or neither");
321 if (a.Type == pa.CLSCompliant) {
322 a.Report.Warning (3022, 1, a.Location, "CLSCompliant attribute has no meaning when applied to parameters. Try putting it on the method instead");
325 if (a.Type == pa.DefaultParameterValue || a.Type == pa.OptionalParameter) {
326 if (HasOptionalExpression) {
327 a.Report.Error (1745, a.Location,
328 "Cannot specify `{0}' attribute on optional parameter `{1}'",
329 TypeManager.CSharpName (a.Type).Replace ("Attribute", ""), Name);
332 if (a.Type == pa.DefaultParameterValue)
336 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
339 public virtual bool CheckAccessibility (InterfaceMemberBase member)
341 if (parameter_type == null)
344 return member.IsAccessibleAs (parameter_type);
348 // Resolve is used in method definitions
350 public virtual TypeSpec Resolve (IMemberContext rc, int index)
352 if (parameter_type != null)
353 return parameter_type;
355 if (attributes != null)
356 attributes.AttachTo (this, rc);
358 parameter_type = texpr.ResolveAsType (rc);
359 if (parameter_type == null)
364 if ((modFlags & Parameter.Modifier.ISBYREF) != 0 && parameter_type.IsSpecialRuntimeType) {
365 rc.Module.Compiler.Report.Error (1601, Location, "Method or delegate parameter cannot be of type `{0}'",
366 GetSignatureForError ());
370 TypeManager.CheckTypeVariance (parameter_type,
371 (modFlags & Parameter.Modifier.ISBYREF) != 0 ? Variance.None : Variance.Contravariant,
374 if (parameter_type.IsStatic) {
375 rc.Module.Compiler.Report.Error (721, Location, "`{0}': static types cannot be used as parameters",
376 texpr.GetSignatureForError ());
377 return parameter_type;
380 if ((modFlags & Modifier.This) != 0 && (parameter_type.IsPointer || parameter_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic)) {
381 rc.Module.Compiler.Report.Error (1103, Location, "The extension method cannot be of type `{0}'",
382 TypeManager.CSharpName (parameter_type));
385 return parameter_type;
388 public void ResolveDefaultValue (ResolveContext rc)
391 // Default value was specified using an expression
393 if (default_expr != null) {
394 ((DefaultParameterValueExpression)default_expr).Resolve (rc, this);
398 if (attributes == null)
401 var opt_attr = attributes.Search (rc.Module.PredefinedAttributes.OptionalParameter);
402 var def_attr = attributes.Search (rc.Module.PredefinedAttributes.DefaultParameterValue);
403 if (def_attr != null) {
404 if (def_attr.Resolve () == null)
407 var default_expr_attr = def_attr.GetParameterDefaultValue ();
408 if (default_expr_attr == null)
411 var dpa_rc = def_attr.CreateResolveContext ();
412 default_expr = default_expr_attr.Resolve (dpa_rc);
414 if (default_expr is BoxedCast)
415 default_expr = ((BoxedCast) default_expr).Child;
417 Constant c = default_expr as Constant;
419 if (parameter_type.BuiltinType == BuiltinTypeSpec.Type.Object) {
420 rc.Report.Error (1910, default_expr.Location,
421 "Argument of type `{0}' is not applicable for the DefaultParameterValue attribute",
422 default_expr.Type.GetSignatureForError ());
424 rc.Report.Error (1909, default_expr.Location,
425 "The DefaultParameterValue attribute is not applicable on parameters of type `{0}'",
426 default_expr.Type.GetSignatureForError ()); ;
433 if (TypeSpecComparer.IsEqual (default_expr.Type, parameter_type) ||
434 (default_expr is NullConstant && TypeSpec.IsReferenceType (parameter_type) && !parameter_type.IsGenericParameter) ||
435 parameter_type.BuiltinType == BuiltinTypeSpec.Type.Object) {
440 // LAMESPEC: Some really weird csc behaviour which we have to mimic
441 // User operators returning same type as parameter type are considered
442 // valid for this attribute only
444 // struct S { public static implicit operator S (int i) {} }
446 // void M ([DefaultParameterValue (3)]S s)
448 var expr = Convert.ImplicitUserConversion (dpa_rc, default_expr, parameter_type, loc);
449 if (expr != null && TypeSpecComparer.IsEqual (expr.Type, parameter_type)) {
453 rc.Report.Error (1908, default_expr.Location, "The type of the default value should match the type of the parameter");
457 if (opt_attr != null) {
458 default_expr = EmptyExpression.MissingValue;
462 public bool HasDefaultValue {
463 get { return default_expr != null; }
466 public bool HasExtensionMethodModifier {
467 get { return (modFlags & Modifier.This) != 0; }
471 // Hoisted parameter variant
473 public HoistedVariable HoistedVariant {
475 return hoisted_variant;
478 hoisted_variant = value;
482 public Modifier ModFlags {
483 get { return modFlags & ~Modifier.This; }
488 set { name = value; }
491 public override AttributeTargets AttributeTargets {
493 return AttributeTargets.Parameter;
497 public void Error_DuplicateName (Report r)
499 r.Error (100, Location, "The parameter name `{0}' is a duplicate", Name);
502 public virtual string GetSignatureForError ()
505 if (parameter_type != null)
506 type_name = TypeManager.CSharpName (parameter_type);
508 type_name = texpr.GetSignatureForError ();
510 string mod = GetModifierSignature (modFlags);
512 return String.Concat (mod, " ", type_name);
517 public static string GetModifierSignature (Modifier mod)
522 case Modifier.PARAMS:
533 public void IsClsCompliant (IMemberContext ctx)
535 if (parameter_type.IsCLSCompliant ())
538 ctx.Module.Compiler.Report.Warning (3001, 1, Location,
539 "Argument type `{0}' is not CLS-compliant", parameter_type.GetSignatureForError ());
542 public virtual void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index, PredefinedAttributes pa)
545 throw new InternalErrorException ("builder already exists");
547 var pattrs = ParametersCompiled.GetParameterAttribute (modFlags);
548 if (HasOptionalExpression)
549 pattrs |= ParameterAttributes.Optional;
552 builder = cb.DefineParameter (index, pattrs, Name);
554 builder = mb.DefineParameter (index, pattrs, Name);
556 if (OptAttributes != null)
557 OptAttributes.Emit ();
559 if (HasDefaultValue) {
561 // Emit constant values for true constants only, the other
562 // constant-like expressions will rely on default value expression
564 var def_value = DefaultValue;
565 Constant c = def_value != null ? def_value.Child as Constant : default_expr as Constant;
567 if (c.Type.BuiltinType == BuiltinTypeSpec.Type.Decimal) {
568 pa.DecimalConstant.EmitAttribute (builder, (decimal) c.GetValue (), c.Location);
570 builder.SetConstant (c.GetValue ());
572 } else if (default_expr.Type.IsStruct) {
574 // Handles special case where default expression is used with value-type
576 // void Foo (S s = default (S)) {}
578 builder.SetConstant (null);
582 if (parameter_type != null) {
583 if (parameter_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
584 pa.Dynamic.EmitAttribute (builder);
585 } else if (parameter_type.HasDynamicElement) {
586 pa.Dynamic.EmitAttribute (builder, parameter_type, Location);
591 public Parameter Clone ()
593 Parameter p = (Parameter) MemberwiseClone ();
594 if (attributes != null)
595 p.attributes = attributes.Clone ();
600 public ExpressionStatement CreateExpressionTreeVariable (BlockContext ec)
602 if ((modFlags & Modifier.ISBYREF) != 0)
603 ec.Report.Error (1951, Location, "An expression tree parameter cannot use `ref' or `out' modifier");
605 expr_tree_variable = TemporaryVariableReference.Create (ResolveParameterExpressionType (ec, Location).Type, ec.CurrentBlock.ParametersBlock, Location);
606 expr_tree_variable = (TemporaryVariableReference) expr_tree_variable.Resolve (ec);
608 Arguments arguments = new Arguments (2);
609 arguments.Add (new Argument (new TypeOf (parameter_type, Location)));
610 arguments.Add (new Argument (new StringConstant (ec.BuiltinTypes, Name, Location)));
611 return new SimpleAssign (ExpressionTreeVariableReference (),
612 Expression.CreateExpressionFactoryCall (ec, "Parameter", null, arguments, Location));
615 public void Emit (EmitContext ec)
617 ec.EmitArgumentLoad (idx);
620 public void EmitAssign (EmitContext ec)
622 ec.EmitArgumentStore (idx);
625 public void EmitAddressOf (EmitContext ec)
627 if ((ModFlags & Modifier.ISBYREF) != 0) {
628 ec.EmitArgumentLoad (idx);
630 ec.EmitArgumentAddress (idx);
634 public TemporaryVariableReference ExpressionTreeVariableReference ()
636 return expr_tree_variable;
640 // System.Linq.Expressions.ParameterExpression type
642 public static TypeExpr ResolveParameterExpressionType (IMemberContext ec, Location location)
644 TypeSpec p_type = ec.Module.PredefinedTypes.ParameterExpression.Resolve ();
645 return new TypeExpression (p_type, location);
648 public void Warning_UselessOptionalParameter (Report Report)
650 Report.Warning (1066, 1, Location,
651 "The default value specified for optional parameter `{0}' will never be used",
657 // Imported or resolved parameter information
659 public class ParameterData : IParameterData
661 readonly string name;
662 readonly Parameter.Modifier modifiers;
663 readonly Expression default_value;
665 public ParameterData (string name, Parameter.Modifier modifiers)
668 this.modifiers = modifiers;
671 public ParameterData (string name, Parameter.Modifier modifiers, Expression defaultValue)
672 : this (name, modifiers)
674 this.default_value = defaultValue;
677 #region IParameterData Members
679 public Expression DefaultValue {
680 get { return default_value; }
683 public bool HasExtensionMethodModifier {
684 get { return (modifiers & Parameter.Modifier.This) != 0; }
687 public bool HasDefaultValue {
688 get { return default_value != null; }
691 public Parameter.Modifier ModFlags {
692 get { return modifiers & ~Parameter.Modifier.This; }
702 public abstract class AParametersCollection
704 protected bool has_arglist;
705 protected bool has_params;
707 // Null object pattern
708 protected IParameterData [] parameters;
709 protected TypeSpec [] types;
711 public CallingConventions CallingConvention {
714 CallingConventions.VarArgs :
715 CallingConventions.Standard;
720 get { return parameters.Length; }
723 public TypeSpec ExtensionMethodType {
728 return FixedParameters [0].HasExtensionMethodModifier ?
733 public IParameterData [] FixedParameters {
739 public static ParameterAttributes GetParameterAttribute (Parameter.Modifier modFlags)
741 return (modFlags & Parameter.Modifier.OUT) == Parameter.Modifier.OUT ?
742 ParameterAttributes.Out : ParameterAttributes.None;
745 // Very expensive operation
746 public MetaType[] GetMetaInfo ()
751 return MetaType.EmptyTypes;
753 types = new MetaType[Count - 1];
756 return MetaType.EmptyTypes;
758 types = new MetaType[Count];
761 for (int i = 0; i < types.Length; ++i) {
762 types[i] = Types[i].GetMetaInfo ();
764 if ((FixedParameters [i].ModFlags & Parameter.Modifier.ISBYREF) == 0)
767 // TODO MemberCache: Should go to MetaInfo getter
768 types [i] = types [i].MakeByRefType ();
775 // Returns the parameter information based on the name
777 public int GetParameterIndexByName (string name)
779 for (int idx = 0; idx < Count; ++idx) {
780 if (parameters [idx].Name == name)
787 public string GetSignatureForDocumentation ()
792 StringBuilder sb = new StringBuilder ("(");
793 for (int i = 0; i < Count; ++i) {
797 sb.Append (types [i].GetSignatureForDocumentation ());
799 if ((parameters[i].ModFlags & Parameter.Modifier.ISBYREF) != 0)
804 return sb.ToString ();
807 public string GetSignatureForError ()
809 return GetSignatureForError ("(", ")", Count);
812 public string GetSignatureForError (string start, string end, int count)
814 StringBuilder sb = new StringBuilder (start);
815 for (int i = 0; i < count; ++i) {
818 sb.Append (ParameterDesc (i));
821 return sb.ToString ();
824 public bool HasArglist {
825 get { return has_arglist; }
828 public bool HasExtensionMethodType {
833 return FixedParameters [0].HasExtensionMethodModifier;
837 public bool HasParams {
838 get { return has_params; }
841 public bool IsEmpty {
842 get { return parameters.Length == 0; }
845 public AParametersCollection Inflate (TypeParameterInflator inflator)
847 TypeSpec[] inflated_types = null;
848 bool default_value = false;
850 for (int i = 0; i < Count; ++i) {
851 var inflated_param = inflator.Inflate (types[i]);
852 if (inflated_types == null) {
853 if (inflated_param == types[i])
856 default_value |= FixedParameters[i] is DefaultValueExpression;
857 inflated_types = new TypeSpec[types.Length];
858 Array.Copy (types, inflated_types, types.Length);
861 inflated_types[i] = inflated_param;
864 if (inflated_types == null)
867 var clone = (AParametersCollection) MemberwiseClone ();
868 clone.types = inflated_types;
870 for (int i = 0; i < Count; ++i) {
871 var dve = clone.FixedParameters[i] as DefaultValueExpression;
873 throw new NotImplementedException ("net");
874 // clone.FixedParameters [i].DefaultValue = new DefaultValueExpression ();
882 public string ParameterDesc (int pos)
884 if (types == null || types [pos] == null)
885 return ((Parameter)FixedParameters [pos]).GetSignatureForError ();
887 string type = TypeManager.CSharpName (types [pos]);
888 if (FixedParameters [pos].HasExtensionMethodModifier)
889 return "this " + type;
891 Parameter.Modifier mod = FixedParameters [pos].ModFlags;
895 return Parameter.GetModifierSignature (mod) + " " + type;
898 public TypeSpec[] Types {
899 get { return types; }
900 set { types = value; }
905 // A collection of imported or resolved parameters
907 public class ParametersImported : AParametersCollection
909 public ParametersImported (IParameterData [] parameters, TypeSpec [] types, bool hasArglist, bool hasParams)
911 this.parameters = parameters;
913 this.has_arglist = hasArglist;
914 this.has_params = hasParams;
917 public ParametersImported (IParameterData[] param, TypeSpec[] types, bool hasParams)
919 this.parameters = param;
921 this.has_params = hasParams;
926 /// Represents the methods parameters
928 public class ParametersCompiled : AParametersCollection
930 public static readonly ParametersCompiled EmptyReadOnlyParameters = new ParametersCompiled ();
932 // Used by C# 2.0 delegates
933 public static readonly ParametersCompiled Undefined = new ParametersCompiled ();
935 private ParametersCompiled ()
937 parameters = new Parameter [0];
938 types = TypeSpec.EmptyTypes;
941 private ParametersCompiled (IParameterData[] parameters, TypeSpec[] types)
943 this.parameters = parameters;
947 public ParametersCompiled (params Parameter[] parameters)
949 if (parameters == null || parameters.Length == 0)
950 throw new ArgumentException ("Use EmptyReadOnlyParameters");
952 this.parameters = parameters;
953 int count = parameters.Length;
955 for (int i = 0; i < count; i++){
956 has_params |= (parameters [i].ModFlags & Parameter.Modifier.PARAMS) != 0;
960 public ParametersCompiled (Parameter [] parameters, bool has_arglist) :
963 this.has_arglist = has_arglist;
966 public static ParametersCompiled CreateFullyResolved (Parameter p, TypeSpec type)
968 return new ParametersCompiled (new Parameter [] { p }, new TypeSpec [] { type });
971 public static ParametersCompiled CreateFullyResolved (Parameter[] parameters, TypeSpec[] types)
973 return new ParametersCompiled (parameters, types);
977 // TODO: This does not fit here, it should go to different version of AParametersCollection
978 // as the underlying type is not Parameter and some methods will fail to cast
980 public static AParametersCollection CreateFullyResolved (params TypeSpec[] types)
982 var pd = new ParameterData [types.Length];
983 for (int i = 0; i < pd.Length; ++i)
984 pd[i] = new ParameterData (null, Parameter.Modifier.NONE, null);
986 return new ParametersCompiled (pd, types);
989 public static ParametersCompiled CreateImplicitParameter (FullNamedExpression texpr, Location loc)
991 return new ParametersCompiled (
992 new[] { new Parameter (texpr, "value", Parameter.Modifier.NONE, null, loc) },
996 public void CheckConstraints (IMemberContext mc)
998 foreach (Parameter p in parameters) {
1000 // It's null for compiler generated types or special types like __arglist
1002 if (p.TypeExpression != null)
1003 ConstraintChecker.Check (mc, p.Type, p.TypeExpression.Location);
1008 // Returns non-zero value for equal CLS parameter signatures
1010 public static int IsSameClsSignature (AParametersCollection a, AParametersCollection b)
1014 for (int i = 0; i < a.Count; ++i) {
1015 var a_type = a.Types[i];
1016 var b_type = b.Types[i];
1017 if (TypeSpecComparer.Override.IsEqual (a_type, b_type)) {
1018 const Parameter.Modifier ref_out = Parameter.Modifier.REF | Parameter.Modifier.OUT;
1019 if ((a.FixedParameters[i].ModFlags & ref_out) != (b.FixedParameters[i].ModFlags & ref_out))
1025 var ac_a = a_type as ArrayContainer;
1029 var ac_b = b_type as ArrayContainer;
1033 if (ac_a.Element is ArrayContainer || ac_b.Element is ArrayContainer) {
1038 if (ac_a.Rank != ac_b.Rank && TypeSpecComparer.Override.IsEqual (ac_a.Element, ac_b.Element)) {
1049 public static ParametersCompiled MergeGenerated (CompilerContext ctx, ParametersCompiled userParams, bool checkConflicts, Parameter compilerParams, TypeSpec compilerTypes)
1051 return MergeGenerated (ctx, userParams, checkConflicts,
1052 new Parameter [] { compilerParams },
1053 new TypeSpec [] { compilerTypes });
1057 // Use this method when you merge compiler generated parameters with user parameters
1059 public static ParametersCompiled MergeGenerated (CompilerContext ctx, ParametersCompiled userParams, bool checkConflicts, Parameter[] compilerParams, TypeSpec[] compilerTypes)
1061 Parameter[] all_params = new Parameter [userParams.Count + compilerParams.Length];
1062 userParams.FixedParameters.CopyTo(all_params, 0);
1064 TypeSpec [] all_types;
1065 if (userParams.types != null) {
1066 all_types = new TypeSpec [all_params.Length];
1067 userParams.Types.CopyTo (all_types, 0);
1072 int last_filled = userParams.Count;
1074 foreach (Parameter p in compilerParams) {
1075 for (int i = 0; i < last_filled; ++i) {
1076 while (p.Name == all_params [i].Name) {
1077 if (checkConflicts && i < userParams.Count) {
1078 ctx.Report.Error (316, userParams[i].Location,
1079 "The parameter name `{0}' conflicts with a compiler generated name", p.Name);
1081 p.Name = '_' + p.Name;
1084 all_params [last_filled] = p;
1085 if (all_types != null)
1086 all_types [last_filled] = compilerTypes [index++];
1090 ParametersCompiled parameters = new ParametersCompiled (all_params, all_types);
1091 parameters.has_params = userParams.has_params;
1096 // Parameters checks for members which don't have a block
1098 public void CheckParameters (MemberCore member)
1100 for (int i = 0; i < parameters.Length; ++i) {
1101 var name = parameters[i].Name;
1102 for (int ii = i + 1; ii < parameters.Length; ++ii) {
1103 if (parameters[ii].Name == name)
1104 this[ii].Error_DuplicateName (member.Compiler.Report);
1109 public bool Resolve (IMemberContext ec)
1114 types = new TypeSpec [Count];
1118 for (int i = 0; i < FixedParameters.Length; ++i) {
1120 TypeSpec t = p.Resolve (ec, i);
1132 public void ResolveDefaultValues (MemberCore m)
1134 ResolveContext rc = null;
1135 for (int i = 0; i < parameters.Length; ++i) {
1136 Parameter p = (Parameter) parameters [i];
1139 // Try not to enter default values resolution if there are is not any default value possible
1141 if (p.HasDefaultValue || p.OptAttributes != null) {
1143 rc = new ResolveContext (m);
1145 p.ResolveDefaultValue (rc);
1150 // Define each type attribute (in/out/ref) and
1151 // the argument names.
1152 public void ApplyAttributes (IMemberContext mc, MethodBase builder)
1157 MethodBuilder mb = builder as MethodBuilder;
1158 ConstructorBuilder cb = builder as ConstructorBuilder;
1159 var pa = mc.Module.PredefinedAttributes;
1161 for (int i = 0; i < Count; i++) {
1162 this [i].ApplyAttributes (mb, cb, i + 1, pa);
1166 public void VerifyClsCompliance (IMemberContext ctx)
1168 foreach (Parameter p in FixedParameters)
1169 p.IsClsCompliant (ctx);
1172 public Parameter this [int pos] {
1173 get { return (Parameter) parameters [pos]; }
1176 public Expression CreateExpressionTree (BlockContext ec, Location loc)
1178 var initializers = new ArrayInitializer (Count, loc);
1179 foreach (Parameter p in FixedParameters) {
1181 // Each parameter expression is stored to local variable
1182 // to save some memory when referenced later.
1184 StatementExpression se = new StatementExpression (p.CreateExpressionTreeVariable (ec));
1185 if (se.Resolve (ec)) {
1186 ec.CurrentBlock.AddScopeStatement (new TemporaryVariableReference.Declarator (p.ExpressionTreeVariableReference ()));
1187 ec.CurrentBlock.AddScopeStatement (se);
1190 initializers.Add (p.ExpressionTreeVariableReference ());
1193 return new ArrayCreation (
1194 Parameter.ResolveParameterExpressionType (ec, loc),
1198 public ParametersCompiled Clone ()
1200 ParametersCompiled p = (ParametersCompiled) MemberwiseClone ();
1202 p.parameters = new IParameterData [parameters.Length];
1203 for (int i = 0; i < Count; ++i)
1204 p.parameters [i] = this [i].Clone ();
1211 // Default parameter value expression. We need this wrapper to handle
1212 // default parameter values of folded constants when for indexer parameters
1213 // The expression is resolved only once but applied to two methods which
1214 // both share reference to this expression and we ensure that resolving
1215 // this expression always returns same instance
1217 public class DefaultParameterValueExpression : CompositeExpression
1219 public DefaultParameterValueExpression (Expression expr)
1224 protected override Expression DoResolve (ResolveContext rc)
1226 return base.DoResolve (rc);
1229 public void Resolve (ResolveContext rc, Parameter p)
1231 var expr = Resolve (rc);
1237 if (!(expr is Constant || expr is DefaultValueExpression || (expr is New && ((New) expr).IsDefaultStruct))) {
1238 rc.Report.Error (1736, Location,
1239 "The expression being assigned to optional parameter `{0}' must be a constant or default value",
1245 var parameter_type = p.Type;
1246 if (type == parameter_type)
1249 var res = Convert.ImplicitConversionStandard (rc, expr, parameter_type, Location);
1251 if (parameter_type.IsNullableType && res is Nullable.Wrap) {
1252 Nullable.Wrap wrap = (Nullable.Wrap) res;
1254 if (!(res is Constant)) {
1255 rc.Report.Error (1770, Location,
1256 "The expression being assigned to nullable optional parameter `{0}' must be default value",
1262 if (!expr.IsNull && TypeSpec.IsReferenceType (parameter_type) && parameter_type.BuiltinType != BuiltinTypeSpec.Type.String) {
1263 rc.Report.Error (1763, Location,
1264 "Optional parameter `{0}' of type `{1}' can only be initialized with `null'",
1265 p.Name, parameter_type.GetSignatureForError ());
1274 rc.Report.Error (1750, Location,
1275 "Optional parameter expression of type `{0}' cannot be converted to parameter type `{1}'",
1276 type.GetSignatureForError (), parameter_type.GetSignatureForError ());