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.
14 using System
.Reflection
;
15 using System
.Reflection
.Emit
;
19 namespace Mono
.CSharp
{
22 /// Abstract Base class for parameters of a method.
24 public abstract class ParameterBase
: Attributable
26 protected ParameterBuilder builder
;
28 public override void ApplyAttributeBuilder (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
31 if (a
.Type
== pa
.MarshalAs
) {
32 UnmanagedMarshal marshal
= a
.GetMarshal (this);
33 if (marshal
!= null) {
34 builder
.SetMarshal (marshal
);
39 if (a
.HasSecurityAttribute
) {
40 a
.Error_InvalidSecurityParent ();
44 if (a
.Type
== pa
.Dynamic
) {
45 a
.Error_MisusedDynamicAttribute ();
49 builder
.SetCustomAttribute ((ConstructorInfo
) ctor
.GetMetaInfo (), cdata
);
52 public ParameterBuilder Builder
{
58 public override bool IsClsComplianceRequired()
65 /// Class for applying custom attributes on the return type
67 public class ReturnParameter
: ParameterBase
71 // TODO: merge method and mb
72 public ReturnParameter (MemberCore method
, MethodBuilder mb
, Location location
)
76 builder
= mb
.DefineParameter (0, ParameterAttributes
.None
, "");
78 catch (ArgumentOutOfRangeException
) {
79 method
.Compiler
.Report
.RuntimeMissingSupport (location
, "custom attributes on the return type");
83 public override void ApplyAttributeBuilder (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
85 if (a
.Type
== pa
.CLSCompliant
) {
86 method
.Compiler
.Report
.Warning (3023, 1, a
.Location
,
87 "CLSCompliant attribute has no meaning when applied to return types. Try putting it on the method instead");
90 // This occurs after Warning -28
94 base.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
97 public override AttributeTargets AttributeTargets
{
99 return AttributeTargets
.ReturnValue
;
106 public override string[] ValidAttributeTargets
{
114 /// Class for applying custom attributes on the implicit parameter type
115 /// of the 'set' method in properties, and the 'add' and 'remove' methods in events.
118 // TODO: should use more code from Parameter.ApplyAttributeBuilder
119 public class ImplicitParameter
: ParameterBase
{
120 public ImplicitParameter (MethodBuilder mb
)
122 builder
= mb
.DefineParameter (1, ParameterAttributes
.None
, "value");
125 public override AttributeTargets AttributeTargets
{
127 return AttributeTargets
.Parameter
;
134 public override string[] ValidAttributeTargets
{
141 public class ImplicitLambdaParameter
: Parameter
143 public ImplicitLambdaParameter (string name
, Location loc
)
144 : base (null, name
, Modifier
.NONE
, null, loc
)
148 public override TypeSpec
Resolve (IMemberContext ec
, int index
)
150 if (parameter_type
== null)
151 throw new InternalErrorException ("A type of implicit lambda parameter `{0}' is not set",
155 return parameter_type
;
158 public TypeSpec Type
{
159 set { parameter_type = value; }
163 public class ParamsParameter
: Parameter
{
164 public ParamsParameter (FullNamedExpression type
, string name
, Attributes attrs
, Location loc
):
165 base (type
, name
, Parameter
.Modifier
.PARAMS
, attrs
, loc
)
169 public override TypeSpec
Resolve (IMemberContext ec
, int index
)
171 if (base.Resolve (ec
, index
) == null)
174 var ac
= parameter_type
as ArrayContainer
;
175 if (ac
== null || ac
.Rank
!= 1) {
176 ec
.Compiler
.Report
.Error (225, Location
, "The params parameter must be a single dimensional array");
180 return parameter_type
;
183 public override void ApplyAttributes (MethodBuilder mb
, ConstructorBuilder cb
, int index
)
185 base.ApplyAttributes (mb
, cb
, index
);
186 PredefinedAttributes
.Get
.ParamArray
.EmitAttribute (builder
);
190 public class ArglistParameter
: Parameter
{
191 // Doesn't have proper type because it's never chosen for better conversion
192 public ArglistParameter (Location loc
) :
193 base (null, String
.Empty
, Parameter
.Modifier
.NONE
, null, loc
)
195 parameter_type
= InternalType
.Arglist
;
198 public override void ApplyAttributes (MethodBuilder mb
, ConstructorBuilder cb
, int index
)
203 public override bool CheckAccessibility (InterfaceMemberBase member
)
208 public override TypeSpec
Resolve (IMemberContext ec
, int index
)
210 return parameter_type
;
214 public interface IParameterData
216 Expression DefaultValue { get; }
217 bool HasExtensionMethodModifier { get; }
218 bool HasDefaultValue { get; }
219 Parameter
.Modifier ModFlags { get; }
224 // Parameter information created by parser
226 public class Parameter
: ParameterBase
, IParameterData
, ILocalVariable
{
228 public enum Modifier
: byte {
230 REF
= REFMASK
| ISBYREF
,
231 OUT
= OUTMASK
| ISBYREF
,
233 // This is a flag which says that it's either REF or OUT.
240 static string[] attribute_targets
= new string [] { "param" }
;
242 FullNamedExpression texpr
;
243 readonly Modifier modFlags
;
245 Expression default_expr
;
246 protected TypeSpec parameter_type
;
247 public readonly Location Location
;
249 public bool HasAddressTaken
;
251 Expression expr_tree_variable
;
252 static TypeExpr parameter_expr_tree_type
;
254 HoistedVariable hoisted_variant
;
256 public Parameter (FullNamedExpression type
, string name
, Modifier mod
, Attributes attrs
, Location loc
)
263 // Only assign, attributes will be attached during resolve
264 base.attributes
= attrs
;
268 public FullNamedExpression TypeExpression
{
275 public override void ApplyAttributeBuilder (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
277 if (a
.Type
== pa
.In
&& ModFlags
== Modifier
.OUT
) {
278 a
.Report
.Error (36, a
.Location
, "An out parameter cannot have the `In' attribute");
282 if (a
.Type
== pa
.ParamArray
) {
283 a
.Report
.Error (674, a
.Location
, "Do not use `System.ParamArrayAttribute'. Use the `params' keyword instead");
287 if (a
.Type
== PredefinedAttributes
.Get
.Out
&& (ModFlags
& Modifier
.REF
) == Modifier
.REF
&&
288 !OptAttributes
.Contains (pa
.In
)) {
289 a
.Report
.Error (662, a
.Location
,
290 "Cannot specify only `Out' attribute on a ref parameter. Use both `In' and `Out' attributes or neither");
294 if (a
.Type
== pa
.CLSCompliant
) {
295 a
.Report
.Warning (3022, 1, a
.Location
, "CLSCompliant attribute has no meaning when applied to parameters. Try putting it on the method instead");
298 if (HasDefaultValue
&& (a
.Type
== pa
.DefaultParameterValue
|| a
.Type
== pa
.OptionalParameter
)) {
299 a
.Report
.Error (1745, a
.Location
,
300 "Cannot specify `{0}' attribute on optional parameter `{1}'",
301 TypeManager
.CSharpName (a
.Type
).Replace ("Attribute", ""), Name
);
305 if (a
.Type
== pa
.DefaultParameterValue
) {
307 var c
= a
.GetParameterDefaultValue (out arg_type
);
309 if (parameter_type
== TypeManager
.object_type
) {
310 a
.Report
.Error (1910, a
.Location
, "Argument of type `{0}' is not applicable for the DefaultParameterValue attribute",
311 arg_type
.GetSignatureForError ());
313 a
.Report
.Error (1909, a
.Location
, "The DefaultParameterValue attribute is not applicable on parameters of type `{0}'",
314 parameter_type
.GetSignatureForError ()); ;
320 if (arg_type
== parameter_type
|| parameter_type
== TypeManager
.object_type
||
321 (c
.IsNull
&& TypeManager
.IsReferenceType (parameter_type
) && !TypeManager
.IsGenericParameter (parameter_type
)))
322 builder
.SetConstant (c
.GetValue ());
324 a
.Report
.Error (1908, a
.Location
, "The type of the default value should match the type of the parameter");
329 base.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
332 public virtual bool CheckAccessibility (InterfaceMemberBase member
)
334 if (parameter_type
== null || TypeManager
.IsGenericParameter (parameter_type
))
337 return member
.IsAccessibleAs (parameter_type
);
340 public static void Reset ()
342 parameter_expr_tree_type
= null;
346 // Resolve is used in method definitions
348 public virtual TypeSpec
Resolve (IMemberContext rc
, int index
)
350 if (parameter_type
!= null)
351 return parameter_type
;
353 if (attributes
!= null)
354 attributes
.AttachTo (this, rc
);
356 var expr
= texpr
.ResolveAsTypeTerminal (rc
, false);
362 parameter_type
= texpr
.Type
;
364 // Ignore all checks for dummy members
365 AbstractPropertyEventMethod pem
= rc
as AbstractPropertyEventMethod
;
366 if (pem
!= null && pem
.IsDummy
)
367 return parameter_type
;
369 if ((modFlags
& Parameter
.Modifier
.ISBYREF
) != 0 &&
370 TypeManager
.IsSpecialType (parameter_type
)) {
371 rc
.Compiler
.Report
.Error (1601, Location
, "Method or delegate parameter cannot be of type `{0}'",
372 GetSignatureForError ());
376 TypeManager
.CheckTypeVariance (parameter_type
,
377 (modFlags
& Parameter
.Modifier
.ISBYREF
) != 0 ? Variance
.None
: Variance
.Contravariant
,
380 if (parameter_type
.IsStatic
) {
381 rc
.Compiler
.Report
.Error (721, Location
, "`{0}': static types cannot be used as parameters",
382 texpr
.GetSignatureForError ());
383 return parameter_type
;
386 if ((modFlags
& Modifier
.This
) != 0 && (parameter_type
.IsPointer
|| parameter_type
== InternalType
.Dynamic
)) {
387 rc
.Compiler
.Report
.Error (1103, Location
, "The extension method cannot be of type `{0}'",
388 TypeManager
.CSharpName (parameter_type
));
391 return parameter_type
;
394 public void ResolveDefaultValue (ResolveContext rc
)
396 if (default_expr
!= null)
397 default_expr
= ResolveDefaultExpression (rc
);
400 Expression
ResolveDefaultExpression (ResolveContext rc
)
402 default_expr
= default_expr
.Resolve (rc
);
403 if (default_expr
== null)
406 if (!(default_expr
is Constant
|| default_expr
is DefaultValueExpression
)) {
407 if (TypeManager
.IsNullableType (parameter_type
)) {
408 rc
.Compiler
.Report
.Error (1770, default_expr
.Location
,
409 "The expression being assigned to nullable optional parameter `{0}' must be default value",
412 rc
.Compiler
.Report
.Error (1736, default_expr
.Location
,
413 "The expression being assigned to optional parameter `{0}' must be a constant or default value",
420 if (TypeManager
.IsEqual (default_expr
.Type
, parameter_type
))
423 if (TypeManager
.IsNullableType (parameter_type
)) {
424 if (Convert
.ImplicitNulableConversion (rc
, default_expr
, parameter_type
) != null)
427 var res
= Convert
.ImplicitConversionStandard (rc
, default_expr
, parameter_type
, default_expr
.Location
);
429 if (!default_expr
.IsNull
&& TypeManager
.IsReferenceType (parameter_type
) && parameter_type
!= TypeManager
.string_type
) {
430 rc
.Compiler
.Report
.Error (1763, default_expr
.Location
,
431 "Optional parameter `{0}' of type `{1}' can only be initialized with `null'",
432 Name
, GetSignatureForError ());
441 rc
.Compiler
.Report
.Error (1750, Location
,
442 "Optional parameter expression of type `{0}' cannot be converted to parameter type `{1}'",
443 TypeManager
.CSharpName (default_expr
.Type
), GetSignatureForError ());
448 public bool HasDefaultValue
{
449 get { return default_expr != null; }
452 public bool HasExtensionMethodModifier
{
453 get { return (modFlags & Modifier.This) != 0; }
457 // Hoisted parameter variant
459 public HoistedVariable HoistedVariant
{
461 return hoisted_variant
;
464 hoisted_variant
= value;
468 public Modifier ModFlags
{
469 get { return modFlags & ~Modifier.This; }
474 set { name = value; }
477 ParameterAttributes Attributes
{
478 get { return ParametersCompiled
.GetParameterAttribute (modFlags
) |
479 (HasDefaultValue
? ParameterAttributes
.Optional
: ParameterAttributes
.None
); }
482 public override AttributeTargets AttributeTargets
{
484 return AttributeTargets
.Parameter
;
488 public virtual string GetSignatureForError ()
491 if (parameter_type
!= null)
492 type_name
= TypeManager
.CSharpName (parameter_type
);
494 type_name
= texpr
.GetSignatureForError ();
496 string mod
= GetModifierSignature (modFlags
);
498 return String
.Concat (mod
, " ", type_name
);
503 public static string GetModifierSignature (Modifier mod
)
508 case Modifier
.PARAMS
:
519 public void IsClsCompliant (IMemberContext ctx
)
521 if (parameter_type
.IsCLSCompliant ())
524 ctx
.Compiler
.Report
.Warning (3001, 1, Location
,
525 "Argument type `{0}' is not CLS-compliant", GetSignatureForError ());
528 public virtual void ApplyAttributes (MethodBuilder mb
, ConstructorBuilder cb
, int index
)
531 builder
= cb
.DefineParameter (index
, Attributes
, Name
);
533 builder
= mb
.DefineParameter (index
, Attributes
, Name
);
535 if (OptAttributes
!= null)
536 OptAttributes
.Emit ();
538 if (HasDefaultValue
) {
540 // Emit constant values for true constants only, the other
541 // constant-like expressions will rely on default value expression
543 Constant c
= default_expr
as Constant
;
545 if (default_expr
.Type
== TypeManager
.decimal_type
) {
546 builder
.SetCustomAttribute (Const
.CreateDecimalConstantAttribute (c
));
548 builder
.SetConstant (c
.GetTypedValue ());
553 if (parameter_type
== InternalType
.Dynamic
) {
554 PredefinedAttributes
.Get
.Dynamic
.EmitAttribute (builder
);
556 var trans_flags
= TypeManager
.HasDynamicTypeUsed (parameter_type
);
557 if (trans_flags
!= null) {
558 var pa
= PredefinedAttributes
.Get
.DynamicTransform
;
559 if (pa
.Constructor
!= null || pa
.ResolveConstructor (Location
, ArrayContainer
.MakeType (TypeManager
.bool_type
))) {
560 builder
.SetCustomAttribute (
561 new CustomAttributeBuilder (pa
.Constructor
, new object [] { trans_flags }
));
567 public override string[] ValidAttributeTargets
{
569 return attribute_targets
;
573 public Parameter
Clone ()
575 Parameter p
= (Parameter
) MemberwiseClone ();
576 if (attributes
!= null)
577 p
.attributes
= attributes
.Clone ();
582 public ExpressionStatement
CreateExpressionTreeVariable (BlockContext ec
)
584 if ((modFlags
& Modifier
.ISBYREF
) != 0)
585 ec
.Report
.Error (1951, Location
, "An expression tree parameter cannot use `ref' or `out' modifier");
587 expr_tree_variable
= new TemporaryVariable (ResolveParameterExpressionType (ec
, Location
).Type
, Location
);
588 expr_tree_variable
= expr_tree_variable
.Resolve (ec
);
590 Arguments arguments
= new Arguments (2);
591 arguments
.Add (new Argument (new TypeOf (
592 new TypeExpression (parameter_type
, Location
), Location
)));
593 arguments
.Add (new Argument (new StringConstant (Name
, Location
)));
594 return new SimpleAssign (ExpressionTreeVariableReference (),
595 Expression
.CreateExpressionFactoryCall (ec
, "Parameter", null, arguments
, Location
));
598 public Expression DefaultValue
{
599 get { return default_expr; }
600 set { default_expr = value; }
603 public void Emit (EmitContext ec
)
609 ParameterReference
.EmitLdArg (ec
, arg_idx
);
612 public void EmitAssign (EmitContext ec
)
619 ec
.Emit (OpCodes
.Starg_S
, (byte) arg_idx
);
621 ec
.Emit (OpCodes
.Starg
, arg_idx
);
624 public void EmitAddressOf (EmitContext ec
)
631 bool is_ref
= (ModFlags
& Modifier
.ISBYREF
) != 0;
633 ParameterReference
.EmitLdArg (ec
, arg_idx
);
636 ec
.Emit (OpCodes
.Ldarga_S
, (byte) arg_idx
);
638 ec
.Emit (OpCodes
.Ldarga
, arg_idx
);
642 public Expression
ExpressionTreeVariableReference ()
644 return expr_tree_variable
;
648 // System.Linq.Expressions.ParameterExpression type
650 public static TypeExpr
ResolveParameterExpressionType (IMemberContext ec
, Location location
)
652 if (parameter_expr_tree_type
!= null)
653 return parameter_expr_tree_type
;
655 TypeSpec p_type
= TypeManager
.parameter_expression_type
;
656 if (p_type
== null) {
657 p_type
= TypeManager
.CoreLookupType (ec
.Compiler
, "System.Linq.Expressions", "ParameterExpression", MemberKind
.Class
, true);
658 TypeManager
.parameter_expression_type
= p_type
;
661 parameter_expr_tree_type
= new TypeExpression (p_type
, location
).
662 ResolveAsTypeTerminal (ec
, false);
664 return parameter_expr_tree_type
;
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 Type
[] GetMetaInfo ()
770 return Type
.EmptyTypes
;
772 types
= new Type
[Count
- 1];
775 return Type
.EmptyTypes
;
777 types
= new Type
[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 GetSignatureForError ()
808 return GetSignatureForError ("(", ")", Count
);
811 public string GetSignatureForError (string start
, string end
, int count
)
813 StringBuilder sb
= new StringBuilder (start
);
814 for (int i
= 0; i
< count
; ++i
) {
817 sb
.Append (ParameterDesc (i
));
820 return sb
.ToString ();
823 public bool HasArglist
{
824 get { return has_arglist; }
827 public bool HasExtensionMethodType
{
832 return FixedParameters
[0].HasExtensionMethodModifier
;
836 public bool HasParams
{
837 get { return has_params; }
840 public bool IsEmpty
{
841 get { return parameters.Length == 0; }
844 public AParametersCollection
Inflate (TypeParameterInflator inflator
)
846 TypeSpec
[] inflated_types
= null;
847 bool default_value
= false;
849 for (int i
= 0; i
< Count
; ++i
) {
850 var inflated_param
= inflator
.Inflate (types
[i
]);
851 if (inflated_types
== null) {
852 if (inflated_param
== types
[i
])
855 default_value
|= FixedParameters
[i
] is DefaultValueExpression
;
856 inflated_types
= new TypeSpec
[types
.Length
];
857 Array
.Copy (types
, inflated_types
, types
.Length
);
860 inflated_types
[i
] = inflated_param
;
863 if (inflated_types
== null)
866 var clone
= (AParametersCollection
) MemberwiseClone ();
867 clone
.types
= inflated_types
;
869 for (int i
= 0; i
< Count
; ++i
) {
870 var dve
= clone
.FixedParameters
[i
] as DefaultValueExpression
;
872 throw new NotImplementedException ("net");
873 // clone.FixedParameters [i].DefaultValue = new DefaultValueExpression ();
881 public string ParameterDesc (int pos
)
883 if (types
== null || types
[pos
] == null)
884 return ((Parameter
)FixedParameters
[pos
]).GetSignatureForError ();
886 string type
= TypeManager
.CSharpName (types
[pos
]);
887 if (FixedParameters
[pos
].HasExtensionMethodModifier
)
888 return "this " + type
;
890 Parameter
.Modifier mod
= FixedParameters
[pos
].ModFlags
;
894 return Parameter
.GetModifierSignature (mod
) + " " + type
;
897 public TypeSpec
[] Types
{
898 get { return types; }
899 set { types = value; }
904 // A collection of imported or resolved parameters
906 public class ParametersImported
: AParametersCollection
908 ParametersImported (AParametersCollection param
, TypeSpec
[] types
)
910 this.parameters
= param
.FixedParameters
;
912 has_arglist
= param
.HasArglist
;
913 has_params
= param
.HasParams
;
916 ParametersImported (IParameterData
[] parameters
, TypeSpec
[] types
, bool hasArglist
, bool hasParams
)
918 this.parameters
= parameters
;
920 this.has_arglist
= hasArglist
;
921 this.has_params
= hasParams
;
924 public ParametersImported (IParameterData
[] param
, TypeSpec
[] types
)
926 this.parameters
= param
;
930 public static AParametersCollection
Create (TypeSpec parent
, MethodBase method
)
932 return Create (parent
, method
.GetParameters (), method
);
936 // Imports System.Reflection parameters
938 public static AParametersCollection
Create (TypeSpec parent
, ParameterInfo
[] pi
, MethodBase method
)
940 int varargs
= method
!= null && (method
.CallingConvention
& CallingConventions
.VarArgs
) != 0 ? 1 : 0;
942 if (pi
.Length
== 0 && varargs
== 0)
943 return ParametersCompiled
.EmptyReadOnlyParameters
;
945 TypeSpec
[] types
= new TypeSpec
[pi
.Length
+ varargs
];
946 IParameterData
[] par
= new IParameterData
[pi
.Length
+ varargs
];
947 bool is_params
= false;
948 for (int i
= 0; i
< pi
.Length
; i
++) {
949 ParameterInfo p
= pi
[i
];
950 Parameter
.Modifier mod
= 0;
951 Expression default_value
= null;
952 if (p
.ParameterType
.IsByRef
) {
953 if ((p
.Attributes
& (ParameterAttributes
.Out
| ParameterAttributes
.In
)) == ParameterAttributes
.Out
)
954 mod
= Parameter
.Modifier
.OUT
;
956 mod
= Parameter
.Modifier
.REF
;
959 // Strip reference wrapping
961 types
[i
] = Import
.ImportType (p
.ParameterType
.GetElementType ());
962 } else if (i
== 0 && method
.IsStatic
&& parent
.IsStatic
&& // TODO: parent.Assembly.IsExtension &&
963 HasExtensionAttribute (method
)) {
964 mod
= Parameter
.Modifier
.This
;
965 types
[i
] = Import
.ImportType (p
.ParameterType
);
967 types
[i
] = Import
.ImportType (p
.ParameterType
);
969 if (i
>= pi
.Length
- 2 && types
[i
] is ArrayContainer
) {
970 var cattrs
= CustomAttributeData
.GetCustomAttributes (p
);
971 if (cattrs
!= null && cattrs
.Any (l
=> l
.Constructor
.DeclaringType
== typeof (ParamArrayAttribute
))) {
972 mod
= Parameter
.Modifier
.PARAMS
;
977 if (!is_params
&& p
.IsOptional
) {
978 object value = p
.DefaultValue
;
979 if (value == Missing
.Value
) {
980 default_value
= EmptyExpression
.Null
;
981 } else if (value == null) {
982 default_value
= new NullLiteral (Location
.Null
);
984 default_value
= Constant
.CreateConstant (null, Import
.ImportType (value.GetType ()), value, Location
.Null
);
989 par
[i
] = new ParameterData (p
.Name
, mod
, default_value
);
993 par
[par
.Length
- 1] = new ArglistParameter (Location
.Null
);
994 types
[types
.Length
- 1] = InternalType
.Arglist
;
997 return method
!= null ?
998 new ParametersImported (par
, types
, varargs
!= 0, is_params
) :
999 new ParametersImported (par
, types
);
1002 static bool HasExtensionAttribute (MethodBase mb
)
1004 var all_attributes
= CustomAttributeData
.GetCustomAttributes (mb
);
1005 foreach (var attr
in all_attributes
) {
1006 var dt
= attr
.Constructor
.DeclaringType
;
1007 if (dt
.Name
== "ExtensionAttribute" && dt
.Namespace
== "System.Runtime.CompilerServices") {
1017 /// Represents the methods parameters
1019 public class ParametersCompiled
: AParametersCollection
1021 public static readonly ParametersCompiled EmptyReadOnlyParameters
= new ParametersCompiled ();
1023 // Used by C# 2.0 delegates
1024 public static readonly ParametersCompiled Undefined
= new ParametersCompiled ();
1026 private ParametersCompiled ()
1028 parameters
= new Parameter
[0];
1029 types
= TypeSpec
.EmptyTypes
;
1032 private ParametersCompiled (IParameterData
[] parameters
, TypeSpec
[] types
)
1034 this.parameters
= parameters
;
1038 public ParametersCompiled (CompilerContext ctx
, params Parameter
[] parameters
)
1040 if (parameters
== null)
1041 throw new ArgumentException ("Use EmptyReadOnlyParameters");
1043 this.parameters
= parameters
;
1044 int count
= parameters
.Length
;
1050 has_params
= (parameters
[0].ModFlags
& Parameter
.Modifier
.PARAMS
) != 0;
1054 for (int i
= 0; i
< count
; i
++){
1055 string base_name
= parameters
[i
].Name
;
1056 has_params
|= (parameters
[i
].ModFlags
& Parameter
.Modifier
.PARAMS
) != 0;
1058 for (int j
= i
+ 1; j
< count
; j
++){
1059 if (base_name
!= parameters
[j
].Name
)
1062 ErrorDuplicateName (parameters
[i
], ctx
.Report
);
1068 public ParametersCompiled (CompilerContext ctx
, Parameter
[] parameters
, bool has_arglist
) :
1069 this (ctx
, parameters
)
1071 this.has_arglist
= has_arglist
;
1074 public static ParametersCompiled
CreateFullyResolved (Parameter p
, TypeSpec type
)
1076 return new ParametersCompiled (new Parameter
[] { p }
, new TypeSpec
[] { type }
);
1079 public static ParametersCompiled
CreateFullyResolved (IParameterData
[] parameters
, TypeSpec
[] types
)
1081 return new ParametersCompiled (parameters
, types
);
1084 public static AParametersCollection
CreateFullyResolved (TypeSpec
[] types
)
1086 var pd
= new ParameterData
[types
.Length
];
1087 for (int i
= 0; i
< pd
.Length
; ++i
)
1088 pd
[i
] = new ParameterData (null, Parameter
.Modifier
.NONE
, null);
1090 return new ParametersCompiled (pd
, types
);
1094 // Returns non-zero value for equal CLS parameter signatures
1096 public static int IsSameClsSignature (AParametersCollection a
, AParametersCollection b
)
1100 for (int i
= 0; i
< a
.Count
; ++i
) {
1101 var a_type
= a
.Types
[i
];
1102 var b_type
= b
.Types
[i
];
1103 if (TypeSpecComparer
.Override
.IsEqual (a_type
, b_type
)) {
1104 const Parameter
.Modifier ref_out
= Parameter
.Modifier
.REF
| Parameter
.Modifier
.OUT
;
1105 if ((a
.FixedParameters
[i
].ModFlags
& ref_out
) != (b
.FixedParameters
[i
].ModFlags
& ref_out
))
1111 var ac_a
= a_type
as ArrayContainer
;
1115 var ac_b
= b_type
as ArrayContainer
;
1119 if (ac_a
.Element
is ArrayContainer
|| ac_b
.Element
is ArrayContainer
) {
1124 if (ac_a
.Rank
!= ac_b
.Rank
&& TypeSpecComparer
.Override
.IsEqual (ac_a
.Element
, ac_b
.Element
)) {
1135 public static ParametersCompiled
MergeGenerated (CompilerContext ctx
, ParametersCompiled userParams
, bool checkConflicts
, Parameter compilerParams
, TypeSpec compilerTypes
)
1137 return MergeGenerated (ctx
, userParams
, checkConflicts
,
1138 new Parameter
[] { compilerParams }
,
1139 new TypeSpec
[] { compilerTypes }
);
1143 // Use this method when you merge compiler generated parameters with user parameters
1145 public static ParametersCompiled
MergeGenerated (CompilerContext ctx
, ParametersCompiled userParams
, bool checkConflicts
, Parameter
[] compilerParams
, TypeSpec
[] compilerTypes
)
1147 Parameter
[] all_params
= new Parameter
[userParams
.Count
+ compilerParams
.Length
];
1148 userParams
.FixedParameters
.CopyTo(all_params
, 0);
1150 TypeSpec
[] all_types
;
1151 if (userParams
.types
!= null) {
1152 all_types
= new TypeSpec
[all_params
.Length
];
1153 userParams
.Types
.CopyTo (all_types
, 0);
1158 int last_filled
= userParams
.Count
;
1160 foreach (Parameter p
in compilerParams
) {
1161 for (int i
= 0; i
< last_filled
; ++i
) {
1162 while (p
.Name
== all_params
[i
].Name
) {
1163 if (checkConflicts
&& i
< userParams
.Count
) {
1164 ctx
.Report
.Error (316, userParams
[i
].Location
,
1165 "The parameter name `{0}' conflicts with a compiler generated name", p
.Name
);
1167 p
.Name
= '_' + p
.Name
;
1170 all_params
[last_filled
] = p
;
1171 if (all_types
!= null)
1172 all_types
[last_filled
] = compilerTypes
[index
++];
1176 ParametersCompiled parameters
= new ParametersCompiled (all_params
, all_types
);
1177 parameters
.has_params
= userParams
.has_params
;
1181 protected virtual void ErrorDuplicateName (Parameter p
, Report Report
)
1183 Report
.Error (100, p
.Location
, "The parameter name `{0}' is a duplicate", p
.Name
);
1186 public bool Resolve (IMemberContext ec
)
1191 types
= new TypeSpec
[Count
];
1195 for (int i
= 0; i
< FixedParameters
.Length
; ++i
) {
1197 TypeSpec t
= p
.Resolve (ec
, i
);
1209 public void ResolveDefaultValues (ResolveContext rc
)
1211 for (int i
= 0; i
< FixedParameters
.Length
; ++i
) {
1212 this [i
].ResolveDefaultValue (rc
);
1216 // Define each type attribute (in/out/ref) and
1217 // the argument names.
1218 public void ApplyAttributes (MethodBase builder
)
1223 MethodBuilder mb
= builder
as MethodBuilder
;
1224 ConstructorBuilder cb
= builder
as ConstructorBuilder
;
1226 for (int i
= 0; i
< Count
; i
++) {
1227 this [i
].ApplyAttributes (mb
, cb
, i
+ 1);
1231 public void VerifyClsCompliance (IMemberContext ctx
)
1233 foreach (Parameter p
in FixedParameters
)
1234 p
.IsClsCompliant (ctx
);
1237 public Parameter
this [int pos
] {
1238 get { return (Parameter) parameters [pos]; }
1241 public Expression
CreateExpressionTree (BlockContext ec
, Location loc
)
1243 var initializers
= new ArrayInitializer (Count
, loc
);
1244 foreach (Parameter p
in FixedParameters
) {
1246 // Each parameter expression is stored to local variable
1247 // to save some memory when referenced later.
1249 StatementExpression se
= new StatementExpression (p
.CreateExpressionTreeVariable (ec
));
1250 if (se
.Resolve (ec
))
1251 ec
.CurrentBlock
.AddScopeStatement (se
);
1253 initializers
.Add (p
.ExpressionTreeVariableReference ());
1256 return new ArrayCreation (
1257 Parameter
.ResolveParameterExpressionType (ec
, loc
),
1258 "[]", initializers
, loc
);
1261 public ParametersCompiled
Clone ()
1263 ParametersCompiled p
= (ParametersCompiled
) MemberwiseClone ();
1265 p
.parameters
= new IParameterData
[parameters
.Length
];
1266 for (int i
= 0; i
< Count
; ++i
)
1267 p
.parameters
[i
] = this [i
].Clone ();