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 Expression DefaultExpression {
257 public DefaultParameterValueExpression DefaultValue {
259 return default_expr as DefaultParameterValueExpression;
262 default_expr = value;
266 Expression IParameterData.DefaultValue {
268 var expr = default_expr as DefaultParameterValueExpression;
269 return expr == null ? default_expr : expr.Child;
273 bool HasOptionalExpression {
275 return default_expr is DefaultParameterValueExpression;
279 public Location Location {
285 public Modifier ParameterModifier {
291 public TypeSpec Type {
293 return parameter_type;
296 parameter_type = value;
300 public FullNamedExpression TypeExpression {
306 public override string[] ValidAttributeTargets {
308 return attribute_targets;
314 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
316 if (a.Type == pa.In && ModFlags == Modifier.OUT) {
317 a.Report.Error (36, a.Location, "An out parameter cannot have the `In' attribute");
321 if (a.Type == pa.ParamArray) {
322 a.Report.Error (674, a.Location, "Do not use `System.ParamArrayAttribute'. Use the `params' keyword instead");
326 if (a.Type == pa.Out && (ModFlags & Modifier.REF) == Modifier.REF &&
327 !OptAttributes.Contains (pa.In)) {
328 a.Report.Error (662, a.Location,
329 "Cannot specify only `Out' attribute on a ref parameter. Use both `In' and `Out' attributes or neither");
333 if (a.Type == pa.CLSCompliant) {
334 a.Report.Warning (3022, 1, a.Location, "CLSCompliant attribute has no meaning when applied to parameters. Try putting it on the method instead");
337 if (a.Type == pa.DefaultParameterValue || a.Type == pa.OptionalParameter) {
338 if (HasOptionalExpression) {
339 a.Report.Error (1745, a.Location,
340 "Cannot specify `{0}' attribute on optional parameter `{1}'",
341 TypeManager.CSharpName (a.Type).Replace ("Attribute", ""), Name);
344 if (a.Type == pa.DefaultParameterValue)
348 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
351 public virtual bool CheckAccessibility (InterfaceMemberBase member)
353 if (parameter_type == null)
356 return member.IsAccessibleAs (parameter_type);
360 // Resolve is used in method definitions
362 public virtual TypeSpec Resolve (IMemberContext rc, int index)
364 if (parameter_type != null)
365 return parameter_type;
367 if (attributes != null)
368 attributes.AttachTo (this, rc);
370 parameter_type = texpr.ResolveAsType (rc);
371 if (parameter_type == null)
376 if ((modFlags & Parameter.Modifier.ISBYREF) != 0 && parameter_type.IsSpecialRuntimeType) {
377 rc.Module.Compiler.Report.Error (1601, Location, "Method or delegate parameter cannot be of type `{0}'",
378 GetSignatureForError ());
382 TypeManager.CheckTypeVariance (parameter_type,
383 (modFlags & Parameter.Modifier.ISBYREF) != 0 ? Variance.None : Variance.Contravariant,
386 if (parameter_type.IsStatic) {
387 rc.Module.Compiler.Report.Error (721, Location, "`{0}': static types cannot be used as parameters",
388 texpr.GetSignatureForError ());
389 return parameter_type;
392 if ((modFlags & Modifier.This) != 0 && (parameter_type.IsPointer || parameter_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic)) {
393 rc.Module.Compiler.Report.Error (1103, Location, "The extension method cannot be of type `{0}'",
394 TypeManager.CSharpName (parameter_type));
397 return parameter_type;
400 public void ResolveDefaultValue (ResolveContext rc)
403 // Default value was specified using an expression
405 if (default_expr != null) {
406 ((DefaultParameterValueExpression)default_expr).Resolve (rc, this);
410 if (attributes == null)
413 var opt_attr = attributes.Search (rc.Module.PredefinedAttributes.OptionalParameter);
414 var def_attr = attributes.Search (rc.Module.PredefinedAttributes.DefaultParameterValue);
415 if (def_attr != null) {
416 if (def_attr.Resolve () == null)
419 var default_expr_attr = def_attr.GetParameterDefaultValue ();
420 if (default_expr_attr == null)
423 var dpa_rc = def_attr.CreateResolveContext ();
424 default_expr = default_expr_attr.Resolve (dpa_rc);
426 if (default_expr is BoxedCast)
427 default_expr = ((BoxedCast) default_expr).Child;
429 Constant c = default_expr as Constant;
431 if (parameter_type.BuiltinType == BuiltinTypeSpec.Type.Object) {
432 rc.Report.Error (1910, default_expr.Location,
433 "Argument of type `{0}' is not applicable for the DefaultParameterValue attribute",
434 default_expr.Type.GetSignatureForError ());
436 rc.Report.Error (1909, default_expr.Location,
437 "The DefaultParameterValue attribute is not applicable on parameters of type `{0}'",
438 default_expr.Type.GetSignatureForError ()); ;
445 if (TypeSpecComparer.IsEqual (default_expr.Type, parameter_type) ||
446 (default_expr is NullConstant && TypeSpec.IsReferenceType (parameter_type) && !parameter_type.IsGenericParameter) ||
447 parameter_type.BuiltinType == BuiltinTypeSpec.Type.Object) {
452 // LAMESPEC: Some really weird csc behaviour which we have to mimic
453 // User operators returning same type as parameter type are considered
454 // valid for this attribute only
456 // struct S { public static implicit operator S (int i) {} }
458 // void M ([DefaultParameterValue (3)]S s)
460 var expr = Convert.ImplicitUserConversion (dpa_rc, default_expr, parameter_type, loc);
461 if (expr != null && TypeSpecComparer.IsEqual (expr.Type, parameter_type)) {
465 rc.Report.Error (1908, default_expr.Location, "The type of the default value should match the type of the parameter");
469 if (opt_attr != null) {
470 default_expr = EmptyExpression.MissingValue;
474 public bool HasDefaultValue {
475 get { return default_expr != null; }
478 public bool HasExtensionMethodModifier {
479 get { return (modFlags & Modifier.This) != 0; }
483 // Hoisted parameter variant
485 public HoistedVariable HoistedVariant {
487 return hoisted_variant;
490 hoisted_variant = value;
494 public Modifier ModFlags {
495 get { return modFlags & ~Modifier.This; }
500 set { name = value; }
503 public override AttributeTargets AttributeTargets {
505 return AttributeTargets.Parameter;
509 public void Error_DuplicateName (Report r)
511 r.Error (100, Location, "The parameter name `{0}' is a duplicate", Name);
514 public virtual string GetSignatureForError ()
517 if (parameter_type != null)
518 type_name = TypeManager.CSharpName (parameter_type);
520 type_name = texpr.GetSignatureForError ();
522 string mod = GetModifierSignature (modFlags);
524 return String.Concat (mod, " ", type_name);
529 public static string GetModifierSignature (Modifier mod)
534 case Modifier.PARAMS:
545 public void IsClsCompliant (IMemberContext ctx)
547 if (parameter_type.IsCLSCompliant ())
550 ctx.Module.Compiler.Report.Warning (3001, 1, Location,
551 "Argument type `{0}' is not CLS-compliant", parameter_type.GetSignatureForError ());
554 public virtual void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index, PredefinedAttributes pa)
557 throw new InternalErrorException ("builder already exists");
559 var pattrs = ParametersCompiled.GetParameterAttribute (modFlags);
560 if (HasOptionalExpression)
561 pattrs |= ParameterAttributes.Optional;
564 builder = cb.DefineParameter (index, pattrs, Name);
566 builder = mb.DefineParameter (index, pattrs, Name);
568 if (OptAttributes != null)
569 OptAttributes.Emit ();
571 if (HasDefaultValue) {
573 // Emit constant values for true constants only, the other
574 // constant-like expressions will rely on default value expression
576 var def_value = DefaultValue;
577 Constant c = def_value != null ? def_value.Child as Constant : default_expr as Constant;
579 if (c.Type.BuiltinType == BuiltinTypeSpec.Type.Decimal) {
580 pa.DecimalConstant.EmitAttribute (builder, (decimal) c.GetValue (), c.Location);
582 builder.SetConstant (c.GetValue ());
584 } else if (default_expr.Type.IsStruct) {
586 // Handles special case where default expression is used with value-type
588 // void Foo (S s = default (S)) {}
590 builder.SetConstant (null);
594 if (parameter_type != null) {
595 if (parameter_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
596 pa.Dynamic.EmitAttribute (builder);
597 } else if (parameter_type.HasDynamicElement) {
598 pa.Dynamic.EmitAttribute (builder, parameter_type, Location);
603 public Parameter Clone ()
605 Parameter p = (Parameter) MemberwiseClone ();
606 if (attributes != null)
607 p.attributes = attributes.Clone ();
612 public ExpressionStatement CreateExpressionTreeVariable (BlockContext ec)
614 if ((modFlags & Modifier.ISBYREF) != 0)
615 ec.Report.Error (1951, Location, "An expression tree parameter cannot use `ref' or `out' modifier");
617 expr_tree_variable = TemporaryVariableReference.Create (ResolveParameterExpressionType (ec, Location).Type, ec.CurrentBlock.ParametersBlock, Location);
618 expr_tree_variable = (TemporaryVariableReference) expr_tree_variable.Resolve (ec);
620 Arguments arguments = new Arguments (2);
621 arguments.Add (new Argument (new TypeOf (parameter_type, Location)));
622 arguments.Add (new Argument (new StringConstant (ec.BuiltinTypes, Name, Location)));
623 return new SimpleAssign (ExpressionTreeVariableReference (),
624 Expression.CreateExpressionFactoryCall (ec, "Parameter", null, arguments, Location));
627 public void Emit (EmitContext ec)
629 ec.EmitArgumentLoad (idx);
632 public void EmitAssign (EmitContext ec)
634 ec.EmitArgumentStore (idx);
637 public void EmitAddressOf (EmitContext ec)
639 if ((ModFlags & Modifier.ISBYREF) != 0) {
640 ec.EmitArgumentLoad (idx);
642 ec.EmitArgumentAddress (idx);
646 public TemporaryVariableReference ExpressionTreeVariableReference ()
648 return expr_tree_variable;
652 // System.Linq.Expressions.ParameterExpression type
654 public static TypeExpr ResolveParameterExpressionType (IMemberContext ec, Location location)
656 TypeSpec p_type = ec.Module.PredefinedTypes.ParameterExpression.Resolve ();
657 return new TypeExpression (p_type, location);
660 public void Warning_UselessOptionalParameter (Report Report)
662 Report.Warning (1066, 1, Location,
663 "The default value specified for optional parameter `{0}' will never be used",
669 // Imported or resolved parameter information
671 public class ParameterData : IParameterData
673 readonly string name;
674 readonly Parameter.Modifier modifiers;
675 readonly Expression default_value;
677 public ParameterData (string name, Parameter.Modifier modifiers)
680 this.modifiers = modifiers;
683 public ParameterData (string name, Parameter.Modifier modifiers, Expression defaultValue)
684 : this (name, modifiers)
686 this.default_value = defaultValue;
689 #region IParameterData Members
691 public Expression DefaultValue {
692 get { return default_value; }
695 public bool HasExtensionMethodModifier {
696 get { return (modifiers & Parameter.Modifier.This) != 0; }
699 public bool HasDefaultValue {
700 get { return default_value != null; }
703 public Parameter.Modifier ModFlags {
704 get { return modifiers & ~Parameter.Modifier.This; }
714 public abstract class AParametersCollection
716 protected bool has_arglist;
717 protected bool has_params;
719 // Null object pattern
720 protected IParameterData [] parameters;
721 protected TypeSpec [] types;
723 public CallingConventions CallingConvention {
726 CallingConventions.VarArgs :
727 CallingConventions.Standard;
732 get { return parameters.Length; }
735 public TypeSpec ExtensionMethodType {
740 return FixedParameters [0].HasExtensionMethodModifier ?
745 public IParameterData [] FixedParameters {
751 public static ParameterAttributes GetParameterAttribute (Parameter.Modifier modFlags)
753 return (modFlags & Parameter.Modifier.OUT) == Parameter.Modifier.OUT ?
754 ParameterAttributes.Out : ParameterAttributes.None;
757 // Very expensive operation
758 public MetaType[] GetMetaInfo ()
763 return MetaType.EmptyTypes;
765 types = new MetaType[Count - 1];
768 return MetaType.EmptyTypes;
770 types = new MetaType[Count];
773 for (int i = 0; i < types.Length; ++i) {
774 types[i] = Types[i].GetMetaInfo ();
776 if ((FixedParameters [i].ModFlags & Parameter.Modifier.ISBYREF) == 0)
779 // TODO MemberCache: Should go to MetaInfo getter
780 types [i] = types [i].MakeByRefType ();
787 // Returns the parameter information based on the name
789 public int GetParameterIndexByName (string name)
791 for (int idx = 0; idx < Count; ++idx) {
792 if (parameters [idx].Name == name)
799 public string GetSignatureForDocumentation ()
804 StringBuilder sb = new StringBuilder ("(");
805 for (int i = 0; i < Count; ++i) {
809 sb.Append (types [i].GetSignatureForDocumentation ());
811 if ((parameters[i].ModFlags & Parameter.Modifier.ISBYREF) != 0)
816 return sb.ToString ();
819 public string GetSignatureForError ()
821 return GetSignatureForError ("(", ")", Count);
824 public string GetSignatureForError (string start, string end, int count)
826 StringBuilder sb = new StringBuilder (start);
827 for (int i = 0; i < count; ++i) {
830 sb.Append (ParameterDesc (i));
833 return sb.ToString ();
836 public bool HasArglist {
837 get { return has_arglist; }
840 public bool HasExtensionMethodType {
845 return FixedParameters [0].HasExtensionMethodModifier;
849 public bool HasParams {
850 get { return has_params; }
853 public bool IsEmpty {
854 get { return parameters.Length == 0; }
857 public AParametersCollection Inflate (TypeParameterInflator inflator)
859 TypeSpec[] inflated_types = null;
860 bool default_value = false;
862 for (int i = 0; i < Count; ++i) {
863 var inflated_param = inflator.Inflate (types[i]);
864 if (inflated_types == null) {
865 if (inflated_param == types[i])
868 default_value |= FixedParameters[i] is DefaultValueExpression;
869 inflated_types = new TypeSpec[types.Length];
870 Array.Copy (types, inflated_types, types.Length);
873 inflated_types[i] = inflated_param;
876 if (inflated_types == null)
879 var clone = (AParametersCollection) MemberwiseClone ();
880 clone.types = inflated_types;
882 for (int i = 0; i < Count; ++i) {
883 var dve = clone.FixedParameters[i] as DefaultValueExpression;
885 throw new NotImplementedException ("net");
886 // clone.FixedParameters [i].DefaultValue = new DefaultValueExpression ();
894 public string ParameterDesc (int pos)
896 if (types == null || types [pos] == null)
897 return ((Parameter)FixedParameters [pos]).GetSignatureForError ();
899 string type = TypeManager.CSharpName (types [pos]);
900 if (FixedParameters [pos].HasExtensionMethodModifier)
901 return "this " + type;
903 Parameter.Modifier mod = FixedParameters [pos].ModFlags;
907 return Parameter.GetModifierSignature (mod) + " " + type;
910 public TypeSpec[] Types {
911 get { return types; }
912 set { types = value; }
917 // A collection of imported or resolved parameters
919 public class ParametersImported : AParametersCollection
921 public ParametersImported (IParameterData [] parameters, TypeSpec [] types, bool hasArglist, bool hasParams)
923 this.parameters = parameters;
925 this.has_arglist = hasArglist;
926 this.has_params = hasParams;
929 public ParametersImported (IParameterData[] param, TypeSpec[] types, bool hasParams)
931 this.parameters = param;
933 this.has_params = hasParams;
938 /// Represents the methods parameters
940 public class ParametersCompiled : AParametersCollection
942 public static readonly ParametersCompiled EmptyReadOnlyParameters = new ParametersCompiled ();
944 // Used by C# 2.0 delegates
945 public static readonly ParametersCompiled Undefined = new ParametersCompiled ();
947 private ParametersCompiled ()
949 parameters = new Parameter [0];
950 types = TypeSpec.EmptyTypes;
953 private ParametersCompiled (IParameterData[] parameters, TypeSpec[] types)
955 this.parameters = parameters;
959 public ParametersCompiled (params Parameter[] parameters)
961 if (parameters == null || parameters.Length == 0)
962 throw new ArgumentException ("Use EmptyReadOnlyParameters");
964 this.parameters = parameters;
965 int count = parameters.Length;
967 for (int i = 0; i < count; i++){
968 has_params |= (parameters [i].ModFlags & Parameter.Modifier.PARAMS) != 0;
972 public ParametersCompiled (Parameter [] parameters, bool has_arglist) :
975 this.has_arglist = has_arglist;
978 public static ParametersCompiled CreateFullyResolved (Parameter p, TypeSpec type)
980 return new ParametersCompiled (new Parameter [] { p }, new TypeSpec [] { type });
983 public static ParametersCompiled CreateFullyResolved (Parameter[] parameters, TypeSpec[] types)
985 return new ParametersCompiled (parameters, types);
989 // TODO: This does not fit here, it should go to different version of AParametersCollection
990 // as the underlying type is not Parameter and some methods will fail to cast
992 public static AParametersCollection CreateFullyResolved (params TypeSpec[] types)
994 var pd = new ParameterData [types.Length];
995 for (int i = 0; i < pd.Length; ++i)
996 pd[i] = new ParameterData (null, Parameter.Modifier.NONE, null);
998 return new ParametersCompiled (pd, types);
1001 public static ParametersCompiled CreateImplicitParameter (FullNamedExpression texpr, Location loc)
1003 return new ParametersCompiled (
1004 new[] { new Parameter (texpr, "value", Parameter.Modifier.NONE, null, loc) },
1008 public void CheckConstraints (IMemberContext mc)
1010 foreach (Parameter p in parameters) {
1012 // It's null for compiler generated types or special types like __arglist
1014 if (p.TypeExpression != null)
1015 ConstraintChecker.Check (mc, p.Type, p.TypeExpression.Location);
1020 // Returns non-zero value for equal CLS parameter signatures
1022 public static int IsSameClsSignature (AParametersCollection a, AParametersCollection b)
1026 for (int i = 0; i < a.Count; ++i) {
1027 var a_type = a.Types[i];
1028 var b_type = b.Types[i];
1029 if (TypeSpecComparer.Override.IsEqual (a_type, b_type)) {
1030 const Parameter.Modifier ref_out = Parameter.Modifier.REF | Parameter.Modifier.OUT;
1031 if ((a.FixedParameters[i].ModFlags & ref_out) != (b.FixedParameters[i].ModFlags & ref_out))
1037 var ac_a = a_type as ArrayContainer;
1041 var ac_b = b_type as ArrayContainer;
1045 if (ac_a.Element is ArrayContainer || ac_b.Element is ArrayContainer) {
1050 if (ac_a.Rank != ac_b.Rank && TypeSpecComparer.Override.IsEqual (ac_a.Element, ac_b.Element)) {
1061 public static ParametersCompiled MergeGenerated (CompilerContext ctx, ParametersCompiled userParams, bool checkConflicts, Parameter compilerParams, TypeSpec compilerTypes)
1063 return MergeGenerated (ctx, userParams, checkConflicts,
1064 new Parameter [] { compilerParams },
1065 new TypeSpec [] { compilerTypes });
1069 // Use this method when you merge compiler generated parameters with user parameters
1071 public static ParametersCompiled MergeGenerated (CompilerContext ctx, ParametersCompiled userParams, bool checkConflicts, Parameter[] compilerParams, TypeSpec[] compilerTypes)
1073 Parameter[] all_params = new Parameter [userParams.Count + compilerParams.Length];
1074 userParams.FixedParameters.CopyTo(all_params, 0);
1076 TypeSpec [] all_types;
1077 if (userParams.types != null) {
1078 all_types = new TypeSpec [all_params.Length];
1079 userParams.Types.CopyTo (all_types, 0);
1084 int last_filled = userParams.Count;
1086 foreach (Parameter p in compilerParams) {
1087 for (int i = 0; i < last_filled; ++i) {
1088 while (p.Name == all_params [i].Name) {
1089 if (checkConflicts && i < userParams.Count) {
1090 ctx.Report.Error (316, userParams[i].Location,
1091 "The parameter name `{0}' conflicts with a compiler generated name", p.Name);
1093 p.Name = '_' + p.Name;
1096 all_params [last_filled] = p;
1097 if (all_types != null)
1098 all_types [last_filled] = compilerTypes [index++];
1102 ParametersCompiled parameters = new ParametersCompiled (all_params, all_types);
1103 parameters.has_params = userParams.has_params;
1108 // Parameters checks for members which don't have a block
1110 public void CheckParameters (MemberCore member)
1112 for (int i = 0; i < parameters.Length; ++i) {
1113 var name = parameters[i].Name;
1114 for (int ii = i + 1; ii < parameters.Length; ++ii) {
1115 if (parameters[ii].Name == name)
1116 this[ii].Error_DuplicateName (member.Compiler.Report);
1121 public bool Resolve (IMemberContext ec)
1126 types = new TypeSpec [Count];
1130 for (int i = 0; i < FixedParameters.Length; ++i) {
1132 TypeSpec t = p.Resolve (ec, i);
1144 public void ResolveDefaultValues (MemberCore m)
1146 ResolveContext rc = null;
1147 for (int i = 0; i < parameters.Length; ++i) {
1148 Parameter p = (Parameter) parameters [i];
1151 // Try not to enter default values resolution if there are is not any default value possible
1153 if (p.HasDefaultValue || p.OptAttributes != null) {
1155 rc = new ResolveContext (m);
1157 p.ResolveDefaultValue (rc);
1162 // Define each type attribute (in/out/ref) and
1163 // the argument names.
1164 public void ApplyAttributes (IMemberContext mc, MethodBase builder)
1169 MethodBuilder mb = builder as MethodBuilder;
1170 ConstructorBuilder cb = builder as ConstructorBuilder;
1171 var pa = mc.Module.PredefinedAttributes;
1173 for (int i = 0; i < Count; i++) {
1174 this [i].ApplyAttributes (mb, cb, i + 1, pa);
1178 public void VerifyClsCompliance (IMemberContext ctx)
1180 foreach (Parameter p in FixedParameters)
1181 p.IsClsCompliant (ctx);
1184 public Parameter this [int pos] {
1185 get { return (Parameter) parameters [pos]; }
1188 public Expression CreateExpressionTree (BlockContext ec, Location loc)
1190 var initializers = new ArrayInitializer (Count, loc);
1191 foreach (Parameter p in FixedParameters) {
1193 // Each parameter expression is stored to local variable
1194 // to save some memory when referenced later.
1196 StatementExpression se = new StatementExpression (p.CreateExpressionTreeVariable (ec), Location.Null);
1197 if (se.Resolve (ec)) {
1198 ec.CurrentBlock.AddScopeStatement (new TemporaryVariableReference.Declarator (p.ExpressionTreeVariableReference ()));
1199 ec.CurrentBlock.AddScopeStatement (se);
1202 initializers.Add (p.ExpressionTreeVariableReference ());
1205 return new ArrayCreation (
1206 Parameter.ResolveParameterExpressionType (ec, loc),
1210 public ParametersCompiled Clone ()
1212 ParametersCompiled p = (ParametersCompiled) MemberwiseClone ();
1214 p.parameters = new IParameterData [parameters.Length];
1215 for (int i = 0; i < Count; ++i)
1216 p.parameters [i] = this [i].Clone ();
1223 // Default parameter value expression. We need this wrapper to handle
1224 // default parameter values of folded constants (e.g. indexer parameters).
1225 // The expression is resolved only once but applied to two methods which
1226 // both share reference to this expression and we ensure that resolving
1227 // this expression always returns same instance
1229 public class DefaultParameterValueExpression : CompositeExpression
1231 public DefaultParameterValueExpression (Expression expr)
1236 protected override Expression DoResolve (ResolveContext rc)
1238 return base.DoResolve (rc);
1241 public void Resolve (ResolveContext rc, Parameter p)
1243 var expr = Resolve (rc);
1249 if (!(expr is Constant || expr is DefaultValueExpression || (expr is New && ((New) expr).IsDefaultStruct))) {
1250 rc.Report.Error (1736, Location,
1251 "The expression being assigned to optional parameter `{0}' must be a constant or default value",
1257 var parameter_type = p.Type;
1258 if (type == parameter_type)
1261 var res = Convert.ImplicitConversionStandard (rc, expr, parameter_type, Location);
1263 if (parameter_type.IsNullableType && res is Nullable.Wrap) {
1264 Nullable.Wrap wrap = (Nullable.Wrap) res;
1266 if (!(res is Constant)) {
1267 rc.Report.Error (1770, Location,
1268 "The expression being assigned to nullable optional parameter `{0}' must be default value",
1274 if (!expr.IsNull && TypeSpec.IsReferenceType (parameter_type) && parameter_type.BuiltinType != BuiltinTypeSpec.Type.String) {
1275 rc.Report.Error (1763, Location,
1276 "Optional parameter `{0}' of type `{1}' can only be initialized with `null'",
1277 p.Name, parameter_type.GetSignatureForError ());
1286 rc.Report.Error (1750, Location,
1287 "Optional parameter expression of type `{0}' cannot be converted to parameter type `{1}'",
1288 type.GetSignatureForError (), parameter_type.GetSignatureForError ());
1291 public override object Accept (StructuralVisitor visitor)
1293 return visitor.Visit (this);