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 readonly 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;
234 HoistedVariable hoisted_variant;
236 public Parameter (FullNamedExpression type, string name, Modifier mod, Attributes attrs, Location loc)
243 // Only assign, attributes will be attached during resolve
244 base.attributes = attrs;
249 public DefaultParameterValueExpression DefaultValue {
251 return default_expr as DefaultParameterValueExpression;
254 default_expr = value;
258 Expression IParameterData.DefaultValue {
260 var expr = default_expr as DefaultParameterValueExpression;
261 return expr == null ? default_expr : expr.Child;
265 bool HasOptionalExpression {
267 return default_expr is DefaultParameterValueExpression;
271 public Location Location {
277 public TypeSpec Type {
279 return parameter_type;
283 public FullNamedExpression TypeExpression {
289 public override string[] ValidAttributeTargets {
291 return attribute_targets;
297 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
299 if (a.Type == pa.In && ModFlags == Modifier.OUT) {
300 a.Report.Error (36, a.Location, "An out parameter cannot have the `In' attribute");
304 if (a.Type == pa.ParamArray) {
305 a.Report.Error (674, a.Location, "Do not use `System.ParamArrayAttribute'. Use the `params' keyword instead");
309 if (a.Type == pa.Out && (ModFlags & Modifier.REF) == Modifier.REF &&
310 !OptAttributes.Contains (pa.In)) {
311 a.Report.Error (662, a.Location,
312 "Cannot specify only `Out' attribute on a ref parameter. Use both `In' and `Out' attributes or neither");
316 if (a.Type == pa.CLSCompliant) {
317 a.Report.Warning (3022, 1, a.Location, "CLSCompliant attribute has no meaning when applied to parameters. Try putting it on the method instead");
320 if (a.Type == pa.DefaultParameterValue || a.Type == pa.OptionalParameter) {
321 if (HasOptionalExpression) {
322 a.Report.Error (1745, a.Location,
323 "Cannot specify `{0}' attribute on optional parameter `{1}'",
324 TypeManager.CSharpName (a.Type).Replace ("Attribute", ""), Name);
327 if (a.Type == pa.DefaultParameterValue)
331 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
334 public virtual bool CheckAccessibility (InterfaceMemberBase member)
336 if (parameter_type == null)
339 return member.IsAccessibleAs (parameter_type);
343 // Resolve is used in method definitions
345 public virtual TypeSpec Resolve (IMemberContext rc, int index)
347 if (parameter_type != null)
348 return parameter_type;
350 if (attributes != null)
351 attributes.AttachTo (this, rc);
353 var expr = texpr.ResolveAsTypeTerminal (rc, false);
359 parameter_type = texpr.Type;
361 if ((modFlags & Parameter.Modifier.ISBYREF) != 0 && parameter_type.IsSpecialRuntimeType) {
362 rc.Module.Compiler.Report.Error (1601, Location, "Method or delegate parameter cannot be of type `{0}'",
363 GetSignatureForError ());
367 TypeManager.CheckTypeVariance (parameter_type,
368 (modFlags & Parameter.Modifier.ISBYREF) != 0 ? Variance.None : Variance.Contravariant,
371 if (parameter_type.IsStatic) {
372 rc.Module.Compiler.Report.Error (721, Location, "`{0}': static types cannot be used as parameters",
373 texpr.GetSignatureForError ());
374 return parameter_type;
377 if ((modFlags & Modifier.This) != 0 && (parameter_type.IsPointer || parameter_type.BuildinType == BuildinTypeSpec.Type.Dynamic)) {
378 rc.Module.Compiler.Report.Error (1103, Location, "The extension method cannot be of type `{0}'",
379 TypeManager.CSharpName (parameter_type));
382 return parameter_type;
385 public void ResolveDefaultValue (ResolveContext rc)
388 // Default value was specified using an expression
390 if (default_expr != null) {
391 ((DefaultParameterValueExpression)default_expr).Resolve (rc, this);
395 if (attributes == null)
398 var opt_attr = attributes.Search (rc.Module.PredefinedAttributes.OptionalParameter);
399 var def_attr = attributes.Search (rc.Module.PredefinedAttributes.DefaultParameterValue);
400 if (def_attr != null) {
401 if (def_attr.Resolve () == null)
404 var default_expr_attr = def_attr.GetParameterDefaultValue ();
405 if (default_expr_attr == null)
408 var dpa_rc = def_attr.CreateResolveContext ();
409 default_expr = default_expr_attr.Resolve (dpa_rc);
411 if (default_expr is BoxedCast)
412 default_expr = ((BoxedCast) default_expr).Child;
414 Constant c = default_expr as Constant;
416 if (parameter_type.BuildinType == BuildinTypeSpec.Type.Object) {
417 rc.Report.Error (1910, default_expr.Location,
418 "Argument of type `{0}' is not applicable for the DefaultParameterValue attribute",
419 default_expr.Type.GetSignatureForError ());
421 rc.Report.Error (1909, default_expr.Location,
422 "The DefaultParameterValue attribute is not applicable on parameters of type `{0}'",
423 default_expr.Type.GetSignatureForError ()); ;
430 if (TypeSpecComparer.IsEqual (default_expr.Type, parameter_type) ||
431 (default_expr is NullConstant && TypeManager.IsReferenceType (parameter_type) && !parameter_type.IsGenericParameter) ||
432 parameter_type.BuildinType == BuildinTypeSpec.Type.Object) {
437 // LAMESPEC: Some really weird csc behaviour which we have to mimic
438 // User operators returning same type as parameter type are considered
439 // valid for this attribute only
441 // struct S { public static implicit operator S (int i) {} }
443 // void M ([DefaultParameterValue (3)]S s)
445 var expr = Convert.ImplicitUserConversion (dpa_rc, default_expr, parameter_type, loc);
446 if (expr != null && TypeSpecComparer.IsEqual (expr.Type, parameter_type)) {
450 rc.Report.Error (1908, default_expr.Location, "The type of the default value should match the type of the parameter");
454 if (opt_attr != null) {
455 default_expr = EmptyExpression.MissingValue;
459 public bool HasDefaultValue {
460 get { return default_expr != null; }
463 public bool HasExtensionMethodModifier {
464 get { return (modFlags & Modifier.This) != 0; }
468 // Hoisted parameter variant
470 public HoistedVariable HoistedVariant {
472 return hoisted_variant;
475 hoisted_variant = value;
479 public Modifier ModFlags {
480 get { return modFlags & ~Modifier.This; }
485 set { name = value; }
488 public override AttributeTargets AttributeTargets {
490 return AttributeTargets.Parameter;
494 public virtual string GetSignatureForError ()
497 if (parameter_type != null)
498 type_name = TypeManager.CSharpName (parameter_type);
500 type_name = texpr.GetSignatureForError ();
502 string mod = GetModifierSignature (modFlags);
504 return String.Concat (mod, " ", type_name);
509 public static string GetModifierSignature (Modifier mod)
514 case Modifier.PARAMS:
525 public void IsClsCompliant (IMemberContext ctx)
527 if (parameter_type.IsCLSCompliant ())
530 ctx.Module.Compiler.Report.Warning (3001, 1, Location,
531 "Argument type `{0}' is not CLS-compliant", parameter_type.GetSignatureForError ());
534 public virtual void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index, PredefinedAttributes pa)
537 throw new InternalErrorException ("builder already exists");
539 var pattrs = ParametersCompiled.GetParameterAttribute (modFlags);
540 if (HasOptionalExpression)
541 pattrs |= ParameterAttributes.Optional;
544 builder = cb.DefineParameter (index, pattrs, Name);
546 builder = mb.DefineParameter (index, pattrs, Name);
548 if (OptAttributes != null)
549 OptAttributes.Emit ();
551 if (HasDefaultValue) {
553 // Emit constant values for true constants only, the other
554 // constant-like expressions will rely on default value expression
556 var def_value = DefaultValue;
557 Constant c = def_value != null ? def_value.Child as Constant : default_expr as Constant;
559 if (default_expr.Type.BuildinType == BuildinTypeSpec.Type.Decimal) {
560 pa.DecimalConstant.EmitAttribute (builder, (decimal) c.GetValue (), c.Location);
562 builder.SetConstant (c.GetValue ());
564 } else if (default_expr.Type.IsStruct) {
566 // Handles special case where default expression is used with value-type
568 // void Foo (S s = default (S)) {}
570 builder.SetConstant (null);
574 if (parameter_type != null) {
575 if (parameter_type.BuildinType == BuildinTypeSpec.Type.Dynamic) {
576 pa.Dynamic.EmitAttribute (builder);
577 } else if (parameter_type.HasDynamicElement) {
578 pa.Dynamic.EmitAttribute (builder, parameter_type, Location);
583 public Parameter Clone ()
585 Parameter p = (Parameter) MemberwiseClone ();
586 if (attributes != null)
587 p.attributes = attributes.Clone ();
592 public ExpressionStatement CreateExpressionTreeVariable (BlockContext ec)
594 if ((modFlags & Modifier.ISBYREF) != 0)
595 ec.Report.Error (1951, Location, "An expression tree parameter cannot use `ref' or `out' modifier");
597 expr_tree_variable = TemporaryVariableReference.Create (ResolveParameterExpressionType (ec, Location).Type, ec.CurrentBlock.ParametersBlock, Location);
598 expr_tree_variable = (TemporaryVariableReference) expr_tree_variable.Resolve (ec);
600 Arguments arguments = new Arguments (2);
601 arguments.Add (new Argument (new TypeOf (
602 new TypeExpression (parameter_type, Location), Location)));
603 arguments.Add (new Argument (new StringConstant (ec.BuildinTypes, Name, Location)));
604 return new SimpleAssign (ExpressionTreeVariableReference (),
605 Expression.CreateExpressionFactoryCall (ec, "Parameter", null, arguments, Location));
608 public void Emit (EmitContext ec)
614 ParameterReference.EmitLdArg (ec, arg_idx);
617 public void EmitAssign (EmitContext ec)
624 ec.Emit (OpCodes.Starg_S, (byte) arg_idx);
626 ec.Emit (OpCodes.Starg, arg_idx);
629 public void EmitAddressOf (EmitContext ec)
636 bool is_ref = (ModFlags & Modifier.ISBYREF) != 0;
638 ParameterReference.EmitLdArg (ec, arg_idx);
641 ec.Emit (OpCodes.Ldarga_S, (byte) arg_idx);
643 ec.Emit (OpCodes.Ldarga, arg_idx);
647 public TemporaryVariableReference ExpressionTreeVariableReference ()
649 return expr_tree_variable;
653 // System.Linq.Expressions.ParameterExpression type
655 public static TypeExpr ResolveParameterExpressionType (IMemberContext ec, Location location)
657 TypeSpec p_type = ec.Module.PredefinedTypes.ParameterExpression.Resolve (location);
658 return new TypeExpression (p_type, location);
661 public void Warning_UselessOptionalParameter (Report Report)
663 Report.Warning (1066, 1, Location,
664 "The default value specified for optional parameter `{0}' will never be used",
670 // Imported or resolved parameter information
672 public class ParameterData : IParameterData
674 readonly string name;
675 readonly Parameter.Modifier modifiers;
676 readonly Expression default_value;
678 public ParameterData (string name, Parameter.Modifier modifiers)
681 this.modifiers = modifiers;
684 public ParameterData (string name, Parameter.Modifier modifiers, Expression defaultValue)
685 : this (name, modifiers)
687 this.default_value = defaultValue;
690 #region IParameterData Members
692 public Expression DefaultValue {
693 get { return default_value; }
696 public bool HasExtensionMethodModifier {
697 get { return (modifiers & Parameter.Modifier.This) != 0; }
700 public bool HasDefaultValue {
701 get { return default_value != null; }
704 public Parameter.Modifier ModFlags {
705 get { return modifiers & ~Parameter.Modifier.This; }
715 public abstract class AParametersCollection
717 protected bool has_arglist;
718 protected bool has_params;
720 // Null object pattern
721 protected IParameterData [] parameters;
722 protected TypeSpec [] types;
724 public CallingConventions CallingConvention {
727 CallingConventions.VarArgs :
728 CallingConventions.Standard;
733 get { return parameters.Length; }
736 public TypeSpec ExtensionMethodType {
741 return FixedParameters [0].HasExtensionMethodModifier ?
746 public IParameterData [] FixedParameters {
752 public static ParameterAttributes GetParameterAttribute (Parameter.Modifier modFlags)
754 return (modFlags & Parameter.Modifier.OUT) == Parameter.Modifier.OUT ?
755 ParameterAttributes.Out : ParameterAttributes.None;
758 // Very expensive operation
759 public MetaType[] GetMetaInfo ()
764 return MetaType.EmptyTypes;
766 types = new MetaType[Count - 1];
769 return MetaType.EmptyTypes;
771 types = new MetaType[Count];
774 for (int i = 0; i < types.Length; ++i) {
775 types[i] = Types[i].GetMetaInfo ();
777 if ((FixedParameters [i].ModFlags & Parameter.Modifier.ISBYREF) == 0)
780 // TODO MemberCache: Should go to MetaInfo getter
781 types [i] = types [i].MakeByRefType ();
788 // Returns the parameter information based on the name
790 public int GetParameterIndexByName (string name)
792 for (int idx = 0; idx < Count; ++idx) {
793 if (parameters [idx].Name == name)
800 public string GetSignatureForError ()
802 return GetSignatureForError ("(", ")", Count);
805 public string GetSignatureForError (string start, string end, int count)
807 StringBuilder sb = new StringBuilder (start);
808 for (int i = 0; i < count; ++i) {
811 sb.Append (ParameterDesc (i));
814 return sb.ToString ();
817 public bool HasArglist {
818 get { return has_arglist; }
821 public bool HasExtensionMethodType {
826 return FixedParameters [0].HasExtensionMethodModifier;
830 public bool HasParams {
831 get { return has_params; }
834 public bool IsEmpty {
835 get { return parameters.Length == 0; }
838 public AParametersCollection Inflate (TypeParameterInflator inflator)
840 TypeSpec[] inflated_types = null;
841 bool default_value = false;
843 for (int i = 0; i < Count; ++i) {
844 var inflated_param = inflator.Inflate (types[i]);
845 if (inflated_types == null) {
846 if (inflated_param == types[i])
849 default_value |= FixedParameters[i] is DefaultValueExpression;
850 inflated_types = new TypeSpec[types.Length];
851 Array.Copy (types, inflated_types, types.Length);
854 inflated_types[i] = inflated_param;
857 if (inflated_types == null)
860 var clone = (AParametersCollection) MemberwiseClone ();
861 clone.types = inflated_types;
863 for (int i = 0; i < Count; ++i) {
864 var dve = clone.FixedParameters[i] as DefaultValueExpression;
866 throw new NotImplementedException ("net");
867 // clone.FixedParameters [i].DefaultValue = new DefaultValueExpression ();
875 public string ParameterDesc (int pos)
877 if (types == null || types [pos] == null)
878 return ((Parameter)FixedParameters [pos]).GetSignatureForError ();
880 string type = TypeManager.CSharpName (types [pos]);
881 if (FixedParameters [pos].HasExtensionMethodModifier)
882 return "this " + type;
884 Parameter.Modifier mod = FixedParameters [pos].ModFlags;
888 return Parameter.GetModifierSignature (mod) + " " + type;
891 public TypeSpec[] Types {
892 get { return types; }
893 set { types = value; }
898 // A collection of imported or resolved parameters
900 public class ParametersImported : AParametersCollection
902 public ParametersImported (IParameterData [] parameters, TypeSpec [] types, bool hasArglist, bool hasParams)
904 this.parameters = parameters;
906 this.has_arglist = hasArglist;
907 this.has_params = hasParams;
910 public ParametersImported (IParameterData[] param, TypeSpec[] types, bool hasParams)
912 this.parameters = param;
914 this.has_params = hasParams;
919 /// Represents the methods parameters
921 public class ParametersCompiled : AParametersCollection
923 public static readonly ParametersCompiled EmptyReadOnlyParameters = new ParametersCompiled ();
925 // Used by C# 2.0 delegates
926 public static readonly ParametersCompiled Undefined = new ParametersCompiled ();
928 private ParametersCompiled ()
930 parameters = new Parameter [0];
931 types = TypeSpec.EmptyTypes;
934 private ParametersCompiled (IParameterData[] parameters, TypeSpec[] types)
936 this.parameters = parameters;
940 public ParametersCompiled (params Parameter[] parameters)
942 if (parameters == null || parameters.Length == 0)
943 throw new ArgumentException ("Use EmptyReadOnlyParameters");
945 this.parameters = parameters;
946 int count = parameters.Length;
948 for (int i = 0; i < count; i++){
949 has_params |= (parameters [i].ModFlags & Parameter.Modifier.PARAMS) != 0;
953 public ParametersCompiled (Parameter [] parameters, bool has_arglist) :
956 this.has_arglist = has_arglist;
959 public static ParametersCompiled CreateFullyResolved (Parameter p, TypeSpec type)
961 return new ParametersCompiled (new Parameter [] { p }, new TypeSpec [] { type });
964 public static ParametersCompiled CreateFullyResolved (Parameter[] parameters, TypeSpec[] types)
966 return new ParametersCompiled (parameters, types);
970 // TODO: This does not fit here, it should go to different version of AParametersCollection
971 // as the underlying type is not Parameter and some methods will fail to cast
973 public static AParametersCollection CreateFullyResolved (params TypeSpec[] types)
975 var pd = new ParameterData [types.Length];
976 for (int i = 0; i < pd.Length; ++i)
977 pd[i] = new ParameterData (null, Parameter.Modifier.NONE, null);
979 return new ParametersCompiled (pd, types);
982 public static ParametersCompiled CreateImplicitParameter (FullNamedExpression texpr, Location loc)
984 return new ParametersCompiled (
985 new[] { new Parameter (texpr, "value", Parameter.Modifier.NONE, null, loc) },
990 // Returns non-zero value for equal CLS parameter signatures
992 public static int IsSameClsSignature (AParametersCollection a, AParametersCollection b)
996 for (int i = 0; i < a.Count; ++i) {
997 var a_type = a.Types[i];
998 var b_type = b.Types[i];
999 if (TypeSpecComparer.Override.IsEqual (a_type, b_type)) {
1000 const Parameter.Modifier ref_out = Parameter.Modifier.REF | Parameter.Modifier.OUT;
1001 if ((a.FixedParameters[i].ModFlags & ref_out) != (b.FixedParameters[i].ModFlags & ref_out))
1007 var ac_a = a_type as ArrayContainer;
1011 var ac_b = b_type as ArrayContainer;
1015 if (ac_a.Element is ArrayContainer || ac_b.Element is ArrayContainer) {
1020 if (ac_a.Rank != ac_b.Rank && TypeSpecComparer.Override.IsEqual (ac_a.Element, ac_b.Element)) {
1031 public static ParametersCompiled MergeGenerated (CompilerContext ctx, ParametersCompiled userParams, bool checkConflicts, Parameter compilerParams, TypeSpec compilerTypes)
1033 return MergeGenerated (ctx, userParams, checkConflicts,
1034 new Parameter [] { compilerParams },
1035 new TypeSpec [] { compilerTypes });
1039 // Use this method when you merge compiler generated parameters with user parameters
1041 public static ParametersCompiled MergeGenerated (CompilerContext ctx, ParametersCompiled userParams, bool checkConflicts, Parameter[] compilerParams, TypeSpec[] compilerTypes)
1043 Parameter[] all_params = new Parameter [userParams.Count + compilerParams.Length];
1044 userParams.FixedParameters.CopyTo(all_params, 0);
1046 TypeSpec [] all_types;
1047 if (userParams.types != null) {
1048 all_types = new TypeSpec [all_params.Length];
1049 userParams.Types.CopyTo (all_types, 0);
1054 int last_filled = userParams.Count;
1056 foreach (Parameter p in compilerParams) {
1057 for (int i = 0; i < last_filled; ++i) {
1058 while (p.Name == all_params [i].Name) {
1059 if (checkConflicts && i < userParams.Count) {
1060 ctx.Report.Error (316, userParams[i].Location,
1061 "The parameter name `{0}' conflicts with a compiler generated name", p.Name);
1063 p.Name = '_' + p.Name;
1066 all_params [last_filled] = p;
1067 if (all_types != null)
1068 all_types [last_filled] = compilerTypes [index++];
1072 ParametersCompiled parameters = new ParametersCompiled (all_params, all_types);
1073 parameters.has_params = userParams.has_params;
1077 public bool Resolve (IMemberContext ec)
1082 types = new TypeSpec [Count];
1086 for (int i = 0; i < FixedParameters.Length; ++i) {
1088 TypeSpec t = p.Resolve (ec, i);
1100 public void ResolveDefaultValues (MemberCore m)
1102 ResolveContext rc = null;
1103 for (int i = 0; i < parameters.Length; ++i) {
1104 Parameter p = (Parameter) parameters [i];
1107 // Try not to enter default values resolution if there are is not any default value possible
1109 if (p.HasDefaultValue || p.OptAttributes != null) {
1111 rc = new ResolveContext (m);
1113 p.ResolveDefaultValue (rc);
1118 // Define each type attribute (in/out/ref) and
1119 // the argument names.
1120 public void ApplyAttributes (IMemberContext mc, MethodBase builder)
1125 MethodBuilder mb = builder as MethodBuilder;
1126 ConstructorBuilder cb = builder as ConstructorBuilder;
1127 var pa = mc.Module.PredefinedAttributes;
1129 for (int i = 0; i < Count; i++) {
1130 this [i].ApplyAttributes (mb, cb, i + 1, pa);
1134 public void VerifyClsCompliance (IMemberContext ctx)
1136 foreach (Parameter p in FixedParameters)
1137 p.IsClsCompliant (ctx);
1140 public Parameter this [int pos] {
1141 get { return (Parameter) parameters [pos]; }
1144 public Expression CreateExpressionTree (BlockContext ec, Location loc)
1146 var initializers = new ArrayInitializer (Count, loc);
1147 foreach (Parameter p in FixedParameters) {
1149 // Each parameter expression is stored to local variable
1150 // to save some memory when referenced later.
1152 StatementExpression se = new StatementExpression (p.CreateExpressionTreeVariable (ec));
1153 if (se.Resolve (ec)) {
1154 ec.CurrentBlock.AddScopeStatement (new TemporaryVariableReference.Declarator (p.ExpressionTreeVariableReference ()));
1155 ec.CurrentBlock.AddScopeStatement (se);
1158 initializers.Add (p.ExpressionTreeVariableReference ());
1161 return new ArrayCreation (
1162 Parameter.ResolveParameterExpressionType (ec, loc),
1166 public ParametersCompiled Clone ()
1168 ParametersCompiled p = (ParametersCompiled) MemberwiseClone ();
1170 p.parameters = new IParameterData [parameters.Length];
1171 for (int i = 0; i < Count; ++i)
1172 p.parameters [i] = this [i].Clone ();
1179 // Default parameter value expression. We need this wrapper to handle
1180 // default parameter values of folded constants when for indexer parameters
1181 // The expression is resolved only once but applied to two methods which
1182 // both share reference to this expression and we ensure that resolving
1183 // this expression always returns same instance
1185 public class DefaultParameterValueExpression : CompositeExpression
1187 public DefaultParameterValueExpression (Expression expr)
1192 protected override Expression DoResolve (ResolveContext rc)
1194 return base.DoResolve (rc);
1197 public void Resolve (ResolveContext rc, Parameter p)
1199 var expr = Resolve (rc);
1205 if (!(expr is Constant || expr is DefaultValueExpression || (expr is New && ((New) expr).IsDefaultStruct))) {
1206 rc.Report.Error (1736, Location,
1207 "The expression being assigned to optional parameter `{0}' must be a constant or default value",
1213 var parameter_type = p.Type;
1214 if (type == parameter_type)
1217 var res = Convert.ImplicitConversionStandard (rc, expr, parameter_type, Location);
1219 if (parameter_type.IsNullableType && res is Nullable.Wrap) {
1220 Nullable.Wrap wrap = (Nullable.Wrap) res;
1222 if (!(res is Constant)) {
1223 rc.Report.Error (1770, Location,
1224 "The expression being assigned to nullable optional parameter `{0}' must be default value",
1230 if (!expr.IsNull && TypeManager.IsReferenceType (parameter_type) && parameter_type.BuildinType != BuildinTypeSpec.Type.String) {
1231 rc.Report.Error (1763, Location,
1232 "Optional parameter `{0}' of type `{1}' can only be initialized with `null'",
1233 p.Name, parameter_type.GetSignatureForError ());
1242 rc.Report.Error (1750, Location,
1243 "Optional parameter expression of type `{0}' cannot be converted to parameter type `{1}'",
1244 type.GetSignatureForError (), parameter_type.GetSignatureForError ());