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.
218 SignatureMask = REFMASK | OUTMASK,
222 static readonly string[] attribute_targets = new string[] { "param" };
224 FullNamedExpression texpr;
225 readonly Modifier modFlags;
227 Expression default_expr;
228 protected TypeSpec parameter_type;
229 readonly Location loc;
231 public bool HasAddressTaken;
233 TemporaryVariableReference expr_tree_variable;
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;
283 parameter_type = value;
287 public FullNamedExpression TypeExpression {
293 public override string[] ValidAttributeTargets {
295 return attribute_targets;
301 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
303 if (a.Type == pa.In && ModFlags == Modifier.OUT) {
304 a.Report.Error (36, a.Location, "An out parameter cannot have the `In' attribute");
308 if (a.Type == pa.ParamArray) {
309 a.Report.Error (674, a.Location, "Do not use `System.ParamArrayAttribute'. Use the `params' keyword instead");
313 if (a.Type == pa.Out && (ModFlags & Modifier.REF) == Modifier.REF &&
314 !OptAttributes.Contains (pa.In)) {
315 a.Report.Error (662, a.Location,
316 "Cannot specify only `Out' attribute on a ref parameter. Use both `In' and `Out' attributes or neither");
320 if (a.Type == pa.CLSCompliant) {
321 a.Report.Warning (3022, 1, a.Location, "CLSCompliant attribute has no meaning when applied to parameters. Try putting it on the method instead");
324 if (a.Type == pa.DefaultParameterValue || a.Type == pa.OptionalParameter) {
325 if (HasOptionalExpression) {
326 a.Report.Error (1745, a.Location,
327 "Cannot specify `{0}' attribute on optional parameter `{1}'",
328 TypeManager.CSharpName (a.Type).Replace ("Attribute", ""), Name);
331 if (a.Type == pa.DefaultParameterValue)
335 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
338 public virtual bool CheckAccessibility (InterfaceMemberBase member)
340 if (parameter_type == null)
343 return member.IsAccessibleAs (parameter_type);
347 // Resolve is used in method definitions
349 public virtual TypeSpec Resolve (IMemberContext rc, int index)
351 if (parameter_type != null)
352 return parameter_type;
354 if (attributes != null)
355 attributes.AttachTo (this, rc);
357 parameter_type = texpr.ResolveAsType (rc);
358 if (parameter_type == null)
363 if ((modFlags & Parameter.Modifier.ISBYREF) != 0 && parameter_type.IsSpecialRuntimeType) {
364 rc.Module.Compiler.Report.Error (1601, Location, "Method or delegate parameter cannot be of type `{0}'",
365 GetSignatureForError ());
369 TypeManager.CheckTypeVariance (parameter_type,
370 (modFlags & Parameter.Modifier.ISBYREF) != 0 ? Variance.None : Variance.Contravariant,
373 if (parameter_type.IsStatic) {
374 rc.Module.Compiler.Report.Error (721, Location, "`{0}': static types cannot be used as parameters",
375 texpr.GetSignatureForError ());
376 return parameter_type;
379 if ((modFlags & Modifier.This) != 0 && (parameter_type.IsPointer || parameter_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic)) {
380 rc.Module.Compiler.Report.Error (1103, Location, "The extension method cannot be of type `{0}'",
381 TypeManager.CSharpName (parameter_type));
384 return parameter_type;
387 public void ResolveDefaultValue (ResolveContext rc)
390 // Default value was specified using an expression
392 if (default_expr != null) {
393 ((DefaultParameterValueExpression)default_expr).Resolve (rc, this);
397 if (attributes == null)
400 var opt_attr = attributes.Search (rc.Module.PredefinedAttributes.OptionalParameter);
401 var def_attr = attributes.Search (rc.Module.PredefinedAttributes.DefaultParameterValue);
402 if (def_attr != null) {
403 if (def_attr.Resolve () == null)
406 var default_expr_attr = def_attr.GetParameterDefaultValue ();
407 if (default_expr_attr == null)
410 var dpa_rc = def_attr.CreateResolveContext ();
411 default_expr = default_expr_attr.Resolve (dpa_rc);
413 if (default_expr is BoxedCast)
414 default_expr = ((BoxedCast) default_expr).Child;
416 Constant c = default_expr as Constant;
418 if (parameter_type.BuiltinType == BuiltinTypeSpec.Type.Object) {
419 rc.Report.Error (1910, default_expr.Location,
420 "Argument of type `{0}' is not applicable for the DefaultParameterValue attribute",
421 default_expr.Type.GetSignatureForError ());
423 rc.Report.Error (1909, default_expr.Location,
424 "The DefaultParameterValue attribute is not applicable on parameters of type `{0}'",
425 default_expr.Type.GetSignatureForError ()); ;
432 if (TypeSpecComparer.IsEqual (default_expr.Type, parameter_type) ||
433 (default_expr is NullConstant && TypeSpec.IsReferenceType (parameter_type) && !parameter_type.IsGenericParameter) ||
434 parameter_type.BuiltinType == BuiltinTypeSpec.Type.Object) {
439 // LAMESPEC: Some really weird csc behaviour which we have to mimic
440 // User operators returning same type as parameter type are considered
441 // valid for this attribute only
443 // struct S { public static implicit operator S (int i) {} }
445 // void M ([DefaultParameterValue (3)]S s)
447 var expr = Convert.ImplicitUserConversion (dpa_rc, default_expr, parameter_type, loc);
448 if (expr != null && TypeSpecComparer.IsEqual (expr.Type, parameter_type)) {
452 rc.Report.Error (1908, default_expr.Location, "The type of the default value should match the type of the parameter");
456 if (opt_attr != null) {
457 default_expr = EmptyExpression.MissingValue;
461 public bool HasDefaultValue {
462 get { return default_expr != null; }
465 public bool HasExtensionMethodModifier {
466 get { return (modFlags & Modifier.This) != 0; }
470 // Hoisted parameter variant
472 public HoistedVariable HoistedVariant {
474 return hoisted_variant;
477 hoisted_variant = value;
481 public Modifier ModFlags {
482 get { return modFlags & ~Modifier.This; }
487 set { name = value; }
490 public override AttributeTargets AttributeTargets {
492 return AttributeTargets.Parameter;
496 public void Error_DuplicateName (Report r)
498 r.Error (100, Location, "The parameter name `{0}' is a duplicate", Name);
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 (c.Type.BuiltinType == BuiltinTypeSpec.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.BuiltinType == BuiltinTypeSpec.Type.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 (parameter_type, Location)));
609 arguments.Add (new Argument (new StringConstant (ec.BuiltinTypes, Name, Location)));
610 return new SimpleAssign (ExpressionTreeVariableReference (),
611 Expression.CreateExpressionFactoryCall (ec, "Parameter", null, arguments, Location));
614 public void Emit (EmitContext ec)
620 ParameterReference.EmitLdArg (ec, arg_idx);
623 public void EmitAssign (EmitContext ec)
630 ec.Emit (OpCodes.Starg_S, (byte) arg_idx);
632 ec.Emit (OpCodes.Starg, arg_idx);
635 public void EmitAddressOf (EmitContext ec)
642 bool is_ref = (ModFlags & Modifier.ISBYREF) != 0;
644 ParameterReference.EmitLdArg (ec, arg_idx);
647 ec.Emit (OpCodes.Ldarga_S, (byte) arg_idx);
649 ec.Emit (OpCodes.Ldarga, arg_idx);
653 public TemporaryVariableReference ExpressionTreeVariableReference ()
655 return expr_tree_variable;
659 // System.Linq.Expressions.ParameterExpression type
661 public static TypeExpr ResolveParameterExpressionType (IMemberContext ec, Location location)
663 TypeSpec p_type = ec.Module.PredefinedTypes.ParameterExpression.Resolve ();
664 return new TypeExpression (p_type, location);
667 public void Warning_UselessOptionalParameter (Report Report)
669 Report.Warning (1066, 1, Location,
670 "The default value specified for optional parameter `{0}' will never be used",
676 // Imported or resolved parameter information
678 public class ParameterData : IParameterData
680 readonly string name;
681 readonly Parameter.Modifier modifiers;
682 readonly Expression default_value;
684 public ParameterData (string name, Parameter.Modifier modifiers)
687 this.modifiers = modifiers;
690 public ParameterData (string name, Parameter.Modifier modifiers, Expression defaultValue)
691 : this (name, modifiers)
693 this.default_value = defaultValue;
696 #region IParameterData Members
698 public Expression DefaultValue {
699 get { return default_value; }
702 public bool HasExtensionMethodModifier {
703 get { return (modifiers & Parameter.Modifier.This) != 0; }
706 public bool HasDefaultValue {
707 get { return default_value != null; }
710 public Parameter.Modifier ModFlags {
711 get { return modifiers & ~Parameter.Modifier.This; }
721 public abstract class AParametersCollection
723 protected bool has_arglist;
724 protected bool has_params;
726 // Null object pattern
727 protected IParameterData [] parameters;
728 protected TypeSpec [] types;
730 public CallingConventions CallingConvention {
733 CallingConventions.VarArgs :
734 CallingConventions.Standard;
739 get { return parameters.Length; }
742 public TypeSpec ExtensionMethodType {
747 return FixedParameters [0].HasExtensionMethodModifier ?
752 public IParameterData [] FixedParameters {
758 public static ParameterAttributes GetParameterAttribute (Parameter.Modifier modFlags)
760 return (modFlags & Parameter.Modifier.OUT) == Parameter.Modifier.OUT ?
761 ParameterAttributes.Out : ParameterAttributes.None;
764 // Very expensive operation
765 public MetaType[] GetMetaInfo ()
770 return MetaType.EmptyTypes;
772 types = new MetaType[Count - 1];
775 return MetaType.EmptyTypes;
777 types = new MetaType[Count];
780 for (int i = 0; i < types.Length; ++i) {
781 types[i] = Types[i].GetMetaInfo ();
783 if ((FixedParameters [i].ModFlags & Parameter.Modifier.ISBYREF) == 0)
786 // TODO MemberCache: Should go to MetaInfo getter
787 types [i] = types [i].MakeByRefType ();
794 // Returns the parameter information based on the name
796 public int GetParameterIndexByName (string name)
798 for (int idx = 0; idx < Count; ++idx) {
799 if (parameters [idx].Name == name)
806 public string GetSignatureForDocumentation ()
811 StringBuilder sb = new StringBuilder ("(");
812 for (int i = 0; i < Count; ++i) {
816 sb.Append (types [i].GetSignatureForDocumentation ());
818 if ((parameters[i].ModFlags & Parameter.Modifier.ISBYREF) != 0)
823 return sb.ToString ();
826 public string GetSignatureForError ()
828 return GetSignatureForError ("(", ")", Count);
831 public string GetSignatureForError (string start, string end, int count)
833 StringBuilder sb = new StringBuilder (start);
834 for (int i = 0; i < count; ++i) {
837 sb.Append (ParameterDesc (i));
840 return sb.ToString ();
843 public bool HasArglist {
844 get { return has_arglist; }
847 public bool HasExtensionMethodType {
852 return FixedParameters [0].HasExtensionMethodModifier;
856 public bool HasParams {
857 get { return has_params; }
860 public bool IsEmpty {
861 get { return parameters.Length == 0; }
864 public AParametersCollection Inflate (TypeParameterInflator inflator)
866 TypeSpec[] inflated_types = null;
867 bool default_value = false;
869 for (int i = 0; i < Count; ++i) {
870 var inflated_param = inflator.Inflate (types[i]);
871 if (inflated_types == null) {
872 if (inflated_param == types[i])
875 default_value |= FixedParameters[i] is DefaultValueExpression;
876 inflated_types = new TypeSpec[types.Length];
877 Array.Copy (types, inflated_types, types.Length);
880 inflated_types[i] = inflated_param;
883 if (inflated_types == null)
886 var clone = (AParametersCollection) MemberwiseClone ();
887 clone.types = inflated_types;
889 for (int i = 0; i < Count; ++i) {
890 var dve = clone.FixedParameters[i] as DefaultValueExpression;
892 throw new NotImplementedException ("net");
893 // clone.FixedParameters [i].DefaultValue = new DefaultValueExpression ();
901 public string ParameterDesc (int pos)
903 if (types == null || types [pos] == null)
904 return ((Parameter)FixedParameters [pos]).GetSignatureForError ();
906 string type = TypeManager.CSharpName (types [pos]);
907 if (FixedParameters [pos].HasExtensionMethodModifier)
908 return "this " + type;
910 Parameter.Modifier mod = FixedParameters [pos].ModFlags;
914 return Parameter.GetModifierSignature (mod) + " " + type;
917 public TypeSpec[] Types {
918 get { return types; }
919 set { types = value; }
924 // A collection of imported or resolved parameters
926 public class ParametersImported : AParametersCollection
928 public ParametersImported (IParameterData [] parameters, TypeSpec [] types, bool hasArglist, bool hasParams)
930 this.parameters = parameters;
932 this.has_arglist = hasArglist;
933 this.has_params = hasParams;
936 public ParametersImported (IParameterData[] param, TypeSpec[] types, bool hasParams)
938 this.parameters = param;
940 this.has_params = hasParams;
945 /// Represents the methods parameters
947 public class ParametersCompiled : AParametersCollection
949 public static readonly ParametersCompiled EmptyReadOnlyParameters = new ParametersCompiled ();
951 // Used by C# 2.0 delegates
952 public static readonly ParametersCompiled Undefined = new ParametersCompiled ();
954 private ParametersCompiled ()
956 parameters = new Parameter [0];
957 types = TypeSpec.EmptyTypes;
960 private ParametersCompiled (IParameterData[] parameters, TypeSpec[] types)
962 this.parameters = parameters;
966 public ParametersCompiled (params Parameter[] parameters)
968 if (parameters == null || parameters.Length == 0)
969 throw new ArgumentException ("Use EmptyReadOnlyParameters");
971 this.parameters = parameters;
972 int count = parameters.Length;
974 for (int i = 0; i < count; i++){
975 has_params |= (parameters [i].ModFlags & Parameter.Modifier.PARAMS) != 0;
979 public ParametersCompiled (Parameter [] parameters, bool has_arglist) :
982 this.has_arglist = has_arglist;
985 public static ParametersCompiled CreateFullyResolved (Parameter p, TypeSpec type)
987 return new ParametersCompiled (new Parameter [] { p }, new TypeSpec [] { type });
990 public static ParametersCompiled CreateFullyResolved (Parameter[] parameters, TypeSpec[] types)
992 return new ParametersCompiled (parameters, types);
996 // TODO: This does not fit here, it should go to different version of AParametersCollection
997 // as the underlying type is not Parameter and some methods will fail to cast
999 public static AParametersCollection CreateFullyResolved (params TypeSpec[] types)
1001 var pd = new ParameterData [types.Length];
1002 for (int i = 0; i < pd.Length; ++i)
1003 pd[i] = new ParameterData (null, Parameter.Modifier.NONE, null);
1005 return new ParametersCompiled (pd, types);
1008 public static ParametersCompiled CreateImplicitParameter (FullNamedExpression texpr, Location loc)
1010 return new ParametersCompiled (
1011 new[] { new Parameter (texpr, "value", Parameter.Modifier.NONE, null, loc) },
1015 public void CheckConstraints (IMemberContext mc)
1017 foreach (Parameter p in parameters) {
1019 // It's null for compiler generated types or special types like __arglist
1021 if (p.TypeExpression != null)
1022 ConstraintChecker.Check (mc, p.Type, p.TypeExpression.Location);
1027 // Returns non-zero value for equal CLS parameter signatures
1029 public static int IsSameClsSignature (AParametersCollection a, AParametersCollection b)
1033 for (int i = 0; i < a.Count; ++i) {
1034 var a_type = a.Types[i];
1035 var b_type = b.Types[i];
1036 if (TypeSpecComparer.Override.IsEqual (a_type, b_type)) {
1037 const Parameter.Modifier ref_out = Parameter.Modifier.REF | Parameter.Modifier.OUT;
1038 if ((a.FixedParameters[i].ModFlags & ref_out) != (b.FixedParameters[i].ModFlags & ref_out))
1044 var ac_a = a_type as ArrayContainer;
1048 var ac_b = b_type as ArrayContainer;
1052 if (ac_a.Element is ArrayContainer || ac_b.Element is ArrayContainer) {
1057 if (ac_a.Rank != ac_b.Rank && TypeSpecComparer.Override.IsEqual (ac_a.Element, ac_b.Element)) {
1068 public static ParametersCompiled MergeGenerated (CompilerContext ctx, ParametersCompiled userParams, bool checkConflicts, Parameter compilerParams, TypeSpec compilerTypes)
1070 return MergeGenerated (ctx, userParams, checkConflicts,
1071 new Parameter [] { compilerParams },
1072 new TypeSpec [] { compilerTypes });
1076 // Use this method when you merge compiler generated parameters with user parameters
1078 public static ParametersCompiled MergeGenerated (CompilerContext ctx, ParametersCompiled userParams, bool checkConflicts, Parameter[] compilerParams, TypeSpec[] compilerTypes)
1080 Parameter[] all_params = new Parameter [userParams.Count + compilerParams.Length];
1081 userParams.FixedParameters.CopyTo(all_params, 0);
1083 TypeSpec [] all_types;
1084 if (userParams.types != null) {
1085 all_types = new TypeSpec [all_params.Length];
1086 userParams.Types.CopyTo (all_types, 0);
1091 int last_filled = userParams.Count;
1093 foreach (Parameter p in compilerParams) {
1094 for (int i = 0; i < last_filled; ++i) {
1095 while (p.Name == all_params [i].Name) {
1096 if (checkConflicts && i < userParams.Count) {
1097 ctx.Report.Error (316, userParams[i].Location,
1098 "The parameter name `{0}' conflicts with a compiler generated name", p.Name);
1100 p.Name = '_' + p.Name;
1103 all_params [last_filled] = p;
1104 if (all_types != null)
1105 all_types [last_filled] = compilerTypes [index++];
1109 ParametersCompiled parameters = new ParametersCompiled (all_params, all_types);
1110 parameters.has_params = userParams.has_params;
1115 // Parameters checks for members which don't have a block
1117 public void CheckParameters (MemberCore member)
1119 for (int i = 0; i < parameters.Length; ++i) {
1120 var name = parameters[i].Name;
1121 for (int ii = i + 1; ii < parameters.Length; ++ii) {
1122 if (parameters[ii].Name == name)
1123 this[ii].Error_DuplicateName (member.Compiler.Report);
1128 public bool Resolve (IMemberContext ec)
1133 types = new TypeSpec [Count];
1137 for (int i = 0; i < FixedParameters.Length; ++i) {
1139 TypeSpec t = p.Resolve (ec, i);
1151 public void ResolveDefaultValues (MemberCore m)
1153 ResolveContext rc = null;
1154 for (int i = 0; i < parameters.Length; ++i) {
1155 Parameter p = (Parameter) parameters [i];
1158 // Try not to enter default values resolution if there are is not any default value possible
1160 if (p.HasDefaultValue || p.OptAttributes != null) {
1162 rc = new ResolveContext (m);
1164 p.ResolveDefaultValue (rc);
1169 // Define each type attribute (in/out/ref) and
1170 // the argument names.
1171 public void ApplyAttributes (IMemberContext mc, MethodBase builder)
1176 MethodBuilder mb = builder as MethodBuilder;
1177 ConstructorBuilder cb = builder as ConstructorBuilder;
1178 var pa = mc.Module.PredefinedAttributes;
1180 for (int i = 0; i < Count; i++) {
1181 this [i].ApplyAttributes (mb, cb, i + 1, pa);
1185 public void VerifyClsCompliance (IMemberContext ctx)
1187 foreach (Parameter p in FixedParameters)
1188 p.IsClsCompliant (ctx);
1191 public Parameter this [int pos] {
1192 get { return (Parameter) parameters [pos]; }
1195 public Expression CreateExpressionTree (BlockContext ec, Location loc)
1197 var initializers = new ArrayInitializer (Count, loc);
1198 foreach (Parameter p in FixedParameters) {
1200 // Each parameter expression is stored to local variable
1201 // to save some memory when referenced later.
1203 StatementExpression se = new StatementExpression (p.CreateExpressionTreeVariable (ec));
1204 if (se.Resolve (ec)) {
1205 ec.CurrentBlock.AddScopeStatement (new TemporaryVariableReference.Declarator (p.ExpressionTreeVariableReference ()));
1206 ec.CurrentBlock.AddScopeStatement (se);
1209 initializers.Add (p.ExpressionTreeVariableReference ());
1212 return new ArrayCreation (
1213 Parameter.ResolveParameterExpressionType (ec, loc),
1217 public ParametersCompiled Clone ()
1219 ParametersCompiled p = (ParametersCompiled) MemberwiseClone ();
1221 p.parameters = new IParameterData [parameters.Length];
1222 for (int i = 0; i < Count; ++i)
1223 p.parameters [i] = this [i].Clone ();
1230 // Default parameter value expression. We need this wrapper to handle
1231 // default parameter values of folded constants when for indexer parameters
1232 // The expression is resolved only once but applied to two methods which
1233 // both share reference to this expression and we ensure that resolving
1234 // this expression always returns same instance
1236 public class DefaultParameterValueExpression : CompositeExpression
1238 public DefaultParameterValueExpression (Expression expr)
1243 protected override Expression DoResolve (ResolveContext rc)
1245 return base.DoResolve (rc);
1248 public void Resolve (ResolveContext rc, Parameter p)
1250 var expr = Resolve (rc);
1256 if (!(expr is Constant || expr is DefaultValueExpression || (expr is New && ((New) expr).IsDefaultStruct))) {
1257 rc.Report.Error (1736, Location,
1258 "The expression being assigned to optional parameter `{0}' must be a constant or default value",
1264 var parameter_type = p.Type;
1265 if (type == parameter_type)
1268 var res = Convert.ImplicitConversionStandard (rc, expr, parameter_type, Location);
1270 if (parameter_type.IsNullableType && res is Nullable.Wrap) {
1271 Nullable.Wrap wrap = (Nullable.Wrap) res;
1273 if (!(res is Constant)) {
1274 rc.Report.Error (1770, Location,
1275 "The expression being assigned to nullable optional parameter `{0}' must be default value",
1281 if (!expr.IsNull && TypeSpec.IsReferenceType (parameter_type) && parameter_type.BuiltinType != BuiltinTypeSpec.Type.String) {
1282 rc.Report.Error (1763, Location,
1283 "Optional parameter `{0}' of type `{1}' can only be initialized with `null'",
1284 p.Name, parameter_type.GetSignatureForError ());
1293 rc.Report.Error (1750, Location,
1294 "Optional parameter expression of type `{0}' cannot be converted to parameter type `{1}'",
1295 type.GetSignatureForError (), parameter_type.GetSignatureForError ());