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
;
16 using System
.Collections
;
19 namespace Mono
.CSharp
{
22 /// Abstract Base class for parameters of a method.
24 public abstract class ParameterBase
: Attributable
{
26 protected ParameterBuilder builder
;
28 protected ParameterBase (Attributes attrs
)
33 public override void ApplyAttributeBuilder (Attribute a
, CustomAttributeBuilder cb
, PredefinedAttributes pa
)
36 if (a
.Type
== pa
.MarshalAs
) {
37 UnmanagedMarshal marshal
= a
.GetMarshal (this);
38 if (marshal
!= null) {
39 builder
.SetMarshal (marshal
);
44 if (a
.HasSecurityAttribute
) {
45 a
.Error_InvalidSecurityParent ();
49 builder
.SetCustomAttribute (cb
);
52 public override bool IsClsComplianceRequired()
59 /// Class for applying custom attributes on the return type
61 public class ReturnParameter
: ParameterBase
{
62 public ReturnParameter (MethodBuilder mb
, Location location
):
66 builder
= mb
.DefineParameter (0, ParameterAttributes
.None
, "");
68 catch (ArgumentOutOfRangeException
) {
69 Report
.RuntimeMissingSupport (location
, "custom attributes on the return type");
73 public override void ApplyAttributeBuilder (Attribute a
, CustomAttributeBuilder cb
, PredefinedAttributes pa
)
75 if (a
.Type
== pa
.CLSCompliant
) {
76 Report
.Warning (3023, 1, a
.Location
, "CLSCompliant attribute has no meaning when applied to return types. Try putting it on the method instead");
79 // This occurs after Warning -28
83 base.ApplyAttributeBuilder (a
, cb
, pa
);
86 public override AttributeTargets AttributeTargets
{
88 return AttributeTargets
.ReturnValue
;
92 public override IResolveContext ResolveContext
{
94 throw new NotSupportedException ();
101 public override string[] ValidAttributeTargets
{
109 /// Class for applying custom attributes on the implicit parameter type
110 /// of the 'set' method in properties, and the 'add' and 'remove' methods in events.
113 // TODO: should use more code from Parameter.ApplyAttributeBuilder
114 public class ImplicitParameter
: ParameterBase
{
115 public ImplicitParameter (MethodBuilder mb
):
118 builder
= mb
.DefineParameter (1, ParameterAttributes
.None
, "value");
121 public override AttributeTargets AttributeTargets
{
123 return AttributeTargets
.Parameter
;
127 public override IResolveContext ResolveContext
{
129 throw new NotSupportedException ();
136 public override string[] ValidAttributeTargets
{
143 public class ImplicitLambdaParameter
: Parameter
145 public ImplicitLambdaParameter (string name
, Location loc
)
146 : base (null, name
, Modifier
.NONE
, null, loc
)
150 public override Type
Resolve (IResolveContext ec
)
152 if (parameter_type
== null)
153 throw new InternalErrorException ("A type of implicit lambda parameter `{0}' is not set",
156 return parameter_type
;
160 set { parameter_type = value; }
164 public class ParamsParameter
: Parameter
{
165 public ParamsParameter (FullNamedExpression type
, string name
, Attributes attrs
, Location loc
):
166 base (type
, name
, Parameter
.Modifier
.PARAMS
, attrs
, loc
)
170 public override Type
Resolve (IResolveContext ec
)
172 if (base.Resolve (ec
) == null)
175 if (!parameter_type
.IsArray
|| parameter_type
.GetArrayRank () != 1) {
176 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
, Location
);
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
)
197 public override void ApplyAttributes (MethodBuilder mb
, ConstructorBuilder cb
, int index
)
202 public override bool CheckAccessibility (InterfaceMemberBase member
)
207 public override Type
Resolve (IResolveContext ec
)
209 return InternalType
.Arglist
;
212 public override string GetSignatureForError ()
218 public interface IParameterData
220 Expression DefaultValue { get; }
221 bool HasExtensionMethodModifier { get; }
222 bool HasDefaultValue { get; }
223 Parameter
.Modifier ModFlags { get; }
228 // Parameter information created by parser
230 public class Parameter
: ParameterBase
, IParameterData
, ILocalVariable
{
232 public enum Modifier
: byte {
234 REF
= REFMASK
| ISBYREF
,
235 OUT
= OUTMASK
| ISBYREF
,
237 // This is a flag which says that it's either REF or OUT.
244 static string[] attribute_targets
= new string [] { "param" }
;
246 protected FullNamedExpression TypeName
;
247 readonly Modifier modFlags
;
249 Expression default_expr
;
250 protected Type parameter_type
;
251 public readonly Location Location
;
253 public bool HasAddressTaken
;
255 IResolveContext resolve_context
;
256 LocalVariableReference expr_tree_variable
;
257 static TypeExpr parameter_expr_tree_type
;
259 public HoistedVariable HoistedVariableReference
;
261 public Parameter (FullNamedExpression type
, string name
, Modifier mod
, Attributes attrs
, Location loc
)
264 if (type
== TypeManager
.system_void_expr
)
265 Report
.Error (1536, loc
, "Invalid parameter type `void'");
273 public override void ApplyAttributeBuilder (Attribute a
, CustomAttributeBuilder cb
, PredefinedAttributes pa
)
275 if (a
.Type
== pa
.In
&& ModFlags
== Modifier
.OUT
) {
276 Report
.Error (36, a
.Location
, "An out parameter cannot have the `In' attribute");
280 if (a
.Type
== pa
.ParamArray
) {
281 Report
.Error (674, a
.Location
, "Do not use `System.ParamArrayAttribute'. Use the `params' keyword instead");
285 if (a
.Type
== PredefinedAttributes
.Get
.Out
&& (ModFlags
& Modifier
.REF
) == Modifier
.REF
&&
286 !OptAttributes
.Contains (pa
.In
)) {
287 Report
.Error (662, a
.Location
,
288 "Cannot specify only `Out' attribute on a ref parameter. Use both `In' and `Out' attributes or neither");
292 if (a
.Type
== pa
.CLSCompliant
) {
293 Report
.Warning (3022, 1, a
.Location
, "CLSCompliant attribute has no meaning when applied to parameters. Try putting it on the method instead");
296 if (HasDefaultValue
&& (a
.Type
== pa
.DefaultParameterValue
|| a
.Type
== pa
.OptionalParameter
)) {
297 Report
.Error (1745, a
.Location
,
298 "Cannot specify `{0}' attribute on optional parameter `{1}'",
299 TypeManager
.CSharpName (a
.Type
).Replace ("Attribute", ""), Name
);
303 if (a
.Type
== pa
.DefaultParameterValue
) {
304 object val
= a
.GetParameterDefaultValue ();
306 Type t
= val
.GetType ();
307 if (t
.IsArray
|| TypeManager
.IsSubclassOf (t
, TypeManager
.type_type
)) {
308 if (parameter_type
== TypeManager
.object_type
) {
310 t
= TypeManager
.type_type
;
312 Report
.Error (1910, a
.Location
, "Argument of type `{0}' is not applicable for the DefaultParameterValue attribute",
313 TypeManager
.CSharpName (t
));
315 Report
.Error (1909, a
.Location
, "The DefaultParameterValue attribute is not applicable on parameters of type `{0}'",
316 TypeManager
.CSharpName (parameter_type
)); ;
322 if (parameter_type
== TypeManager
.object_type
||
323 (val
== null && !TypeManager
.IsGenericParameter (parameter_type
) && TypeManager
.IsReferenceType (parameter_type
)) ||
324 (val
!= null && TypeManager
.TypeToCoreType (val
.GetType ()) == parameter_type
))
325 builder
.SetConstant (val
);
327 Report
.Error (1908, a
.Location
, "The type of the default value should match the type of the parameter");
331 base.ApplyAttributeBuilder (a
, cb
, pa
);
334 public virtual bool CheckAccessibility (InterfaceMemberBase member
)
336 if (parameter_type
== null || TypeManager
.IsGenericParameter (parameter_type
))
339 return member
.IsAccessibleAs (parameter_type
);
342 public override IResolveContext ResolveContext
{
344 return resolve_context
;
349 // Resolve is used in method definitions
351 public virtual Type
Resolve (IResolveContext rc
)
353 // HACK: to resolve attributes correctly
354 this.resolve_context
= rc
;
356 if (parameter_type
!= null)
357 return parameter_type
;
359 TypeExpr texpr
= TypeName
.ResolveAsTypeTerminal (rc
, false);
363 parameter_type
= texpr
.Type
;
365 // Ignore all checks for dummy members
366 AbstractPropertyEventMethod pem
= rc
as AbstractPropertyEventMethod
;
367 if (pem
!= null && pem
.IsDummy
)
368 return parameter_type
;
370 if (default_expr
!= null) {
371 EmitContext ec
= new EmitContext (rc
, rc
.GenericDeclContainer
, Location
, null, parameter_type
, 0);
372 default_expr
= default_expr
.Resolve (ec
);
373 if (default_expr
!= null) {
374 Constant
value = default_expr
as Constant
;
376 if (default_expr
!= null) {
377 bool is_valid
= false;
378 if (default_expr
is DefaultValueExpression
) {
380 } else if (default_expr
is New
&& ((New
) default_expr
).IsDefaultValueType
) {
381 is_valid
= TypeManager
.IsEqual (parameter_type
, default_expr
.Type
) ||
382 (TypeManager
.IsNullableType (parameter_type
) &&
383 Convert
.ImplicitNulableConversion (ec
, default_expr
, parameter_type
) != EmptyExpression
.Null
);
385 Report
.Error (1736, default_expr
.Location
,
386 "The expression being assigned to optional parameter `{0}' must be a constant or default value",
393 Report
.Error (1763, Location
,
394 "Optional parameter `{0}' of type `{1}' can only be initialized with `null'",
395 Name
, GetSignatureForError ());
399 Constant c
= value.ConvertImplicitly (parameter_type
);
401 if (parameter_type
== TypeManager
.object_type
) {
402 Report
.Error (1763, Location
,
403 "Optional parameter `{0}' of type `{1}' can only be initialized with `null'",
404 Name
, GetSignatureForError ());
406 Report
.Error (1750, Location
,
407 "Optional parameter value `{0}' cannot be converted to parameter type `{1}'",
408 value.GetValue (), GetSignatureForError ());
416 if ((modFlags
& Parameter
.Modifier
.ISBYREF
) != 0 &&
417 TypeManager
.IsSpecialType (parameter_type
)) {
418 Report
.Error (1601, Location
, "Method or delegate parameter cannot be of type `{0}'",
419 GetSignatureForError ());
423 TypeManager
.CheckTypeVariance (parameter_type
,
424 (modFlags
& Parameter
.Modifier
.ISBYREF
) != 0 ? Variance
.None
: Variance
.Contravariant
,
427 if (texpr
is TypeParameterExpr
)
428 return parameter_type
;
430 if ((parameter_type
.Attributes
& Class
.StaticClassAttribute
) == Class
.StaticClassAttribute
) {
431 Report
.Error (721, Location
, "`{0}': static types cannot be used as parameters",
432 texpr
.GetSignatureForError ());
433 return parameter_type
;
436 if ((modFlags
& Modifier
.This
) != 0 && parameter_type
.IsPointer
) {
437 Report
.Error (1103, Location
, "The type of extension method cannot be `{0}'",
438 TypeManager
.CSharpName (parameter_type
));
441 return parameter_type
;
444 public void ResolveVariable (int idx
)
449 public bool HasDefaultValue
{
450 get { return default_expr != null; }
453 public bool HasExtensionMethodModifier
{
454 get { return (modFlags & Modifier.This) != 0; }
457 public Modifier ModFlags
{
458 get { return modFlags & ~Modifier.This; }
463 set { name = value; }
466 ParameterAttributes Attributes
{
467 get { return ParametersCompiled
.GetParameterAttribute (modFlags
) |
468 (HasDefaultValue
? ParameterAttributes
.Optional
: ParameterAttributes
.None
); }
471 public override AttributeTargets AttributeTargets
{
473 return AttributeTargets
.Parameter
;
477 public virtual string GetSignatureForError ()
480 if (parameter_type
!= null)
481 type_name
= TypeManager
.CSharpName (parameter_type
);
483 type_name
= TypeName
.GetSignatureForError ();
485 string mod
= GetModifierSignature (modFlags
);
487 return String
.Concat (mod
, " ", type_name
);
492 public static string GetModifierSignature (Modifier mod
)
497 case Modifier
.PARAMS
:
508 public void IsClsCompliant ()
510 if (AttributeTester
.IsClsCompliant (parameter_type
))
513 Report
.Warning (3001, 1, Location
, "Argument type `{0}' is not CLS-compliant", GetSignatureForError ());
516 public virtual void ApplyAttributes (MethodBuilder mb
, ConstructorBuilder cb
, int index
)
519 builder
= cb
.DefineParameter (index
, Attributes
, Name
);
521 builder
= mb
.DefineParameter (index
, Attributes
, Name
);
523 if (OptAttributes
!= null)
524 OptAttributes
.Emit ();
526 if (HasDefaultValue
) {
528 // Emit constant values for true constants only, the other
529 // constant-like expressions will rely on default value expression
531 Constant c
= default_expr
as Constant
;
533 if (default_expr
.Type
== TypeManager
.decimal_type
) {
534 builder
.SetCustomAttribute (Const
.CreateDecimalConstantAttribute (c
));
536 builder
.SetConstant (c
.GetValue ());
542 public override string[] ValidAttributeTargets
{
544 return attribute_targets
;
548 public Parameter
Clone ()
550 Parameter p
= (Parameter
) MemberwiseClone ();
551 if (attributes
!= null) {
552 p
.attributes
= attributes
.Clone ();
553 p
.attributes
.AttachTo (p
);
559 public ExpressionStatement
CreateExpressionTreeVariable (EmitContext ec
)
562 // A parameter is not hoisted when used directly as ET
564 HoistedVariableReference
= null;
566 if ((modFlags
& Modifier
.ISBYREF
) != 0)
567 Report
.Error (1951, Location
, "An expression tree parameter cannot use `ref' or `out' modifier");
569 LocalInfo variable
= ec
.CurrentBlock
.AddTemporaryVariable (
570 ResolveParameterExpressionType (ec
, Location
), Location
);
571 variable
.Resolve (ec
);
573 expr_tree_variable
= new LocalVariableReference (
574 ec
.CurrentBlock
, variable
.Name
, Location
, variable
, false);
576 Arguments arguments
= new Arguments (2);
577 arguments
.Add (new Argument (new TypeOf (
578 new TypeExpression (parameter_type
, Location
), Location
)));
579 arguments
.Add (new Argument (new StringConstant (Name
, Location
)));
580 return new SimpleAssign (ExpressionTreeVariableReference (),
581 Expression
.CreateExpressionFactoryCall ("Parameter", null, arguments
, Location
));
584 public Expression DefaultValue
{
585 get { return default_expr; }
586 set { default_expr = value; }
589 public void Emit (EmitContext ec
)
595 ParameterReference
.EmitLdArg (ec
.ig
, arg_idx
);
598 public void EmitAssign (EmitContext ec
)
605 ec
.ig
.Emit (OpCodes
.Starg_S
, (byte) arg_idx
);
607 ec
.ig
.Emit (OpCodes
.Starg
, arg_idx
);
610 public void EmitAddressOf (EmitContext ec
)
617 bool is_ref
= (ModFlags
& Modifier
.ISBYREF
) != 0;
619 ParameterReference
.EmitLdArg (ec
.ig
, arg_idx
);
622 ec
.ig
.Emit (OpCodes
.Ldarga_S
, (byte) arg_idx
);
624 ec
.ig
.Emit (OpCodes
.Ldarga
, arg_idx
);
628 public Expression
ExpressionTreeVariableReference ()
630 return expr_tree_variable
;
634 // System.Linq.Expressions.ParameterExpression type
636 public static TypeExpr
ResolveParameterExpressionType (EmitContext ec
, Location location
)
638 if (parameter_expr_tree_type
!= null)
639 return parameter_expr_tree_type
;
641 Type p_type
= TypeManager
.parameter_expression_type
;
642 if (p_type
== null) {
643 p_type
= TypeManager
.CoreLookupType ("System.Linq.Expressions", "ParameterExpression", Kind
.Class
, true);
644 TypeManager
.parameter_expression_type
= p_type
;
647 parameter_expr_tree_type
= new TypeExpression (p_type
, location
).
648 ResolveAsTypeTerminal (ec
, false);
650 return parameter_expr_tree_type
;
653 public void Warning_UselessOptionalParameter ()
655 Report
.Warning (1066, 1, Location
,
656 "The default value specified for optional parameter `{0}' will never be used",
662 // Imported or resolved parameter information
664 public class ParameterData
: IParameterData
666 readonly string name
;
667 readonly Parameter
.Modifier modifiers
;
668 readonly Expression default_value
;
670 public ParameterData (string name
, Parameter
.Modifier modifiers
)
673 this.modifiers
= modifiers
;
676 public ParameterData (string name
, Parameter
.Modifier modifiers
, Expression defaultValue
)
677 : this (name
, modifiers
)
679 this.default_value
= defaultValue
;
682 #region IParameterData Members
684 public Expression DefaultValue
{
685 get { return default_value; }
688 public bool HasExtensionMethodModifier
{
689 get { return (modifiers & Parameter.Modifier.This) != 0; }
692 public bool HasDefaultValue
{
693 get { return default_value != null; }
696 public Parameter
.Modifier ModFlags
{
697 get { return modifiers & ~Parameter.Modifier.This; }
707 public abstract class AParametersCollection
709 protected bool has_arglist
;
710 protected bool has_params
;
712 // Null object pattern
713 protected IParameterData
[] parameters
;
714 protected Type
[] types
;
717 get { return parameters.Length; }
720 public Type ExtensionMethodType
{
725 return FixedParameters
[0].HasExtensionMethodModifier
?
730 public IParameterData
[] FixedParameters
{
736 public static ParameterAttributes
GetParameterAttribute (Parameter
.Modifier modFlags
)
738 return (modFlags
& Parameter
.Modifier
.OUT
) == Parameter
.Modifier
.OUT
?
739 ParameterAttributes
.Out
: ParameterAttributes
.None
;
742 public Type
[] GetEmitTypes ()
744 Type
[] types
= null;
747 return Type
.EmptyTypes
;
749 types
= new Type
[Count
- 1];
750 Array
.Copy (Types
, types
, types
.Length
);
753 for (int i
= 0; i
< Count
; ++i
) {
754 if ((FixedParameters
[i
].ModFlags
& Parameter
.Modifier
.ISBYREF
) == 0)
758 types
= (Type
[]) Types
.Clone ();
760 types
[i
] = TypeManager
.GetReferenceType (types
[i
]);
770 // Returns the parameter information based on the name
772 public int GetParameterIndexByName (string name
)
774 for (int idx
= 0; idx
< Count
; ++idx
) {
775 if (parameters
[idx
].Name
== name
)
782 public string GetSignatureForError ()
784 StringBuilder sb
= new StringBuilder ("(");
785 for (int i
= 0; i
< Count
; ++i
) {
788 sb
.Append (ParameterDesc (i
));
791 return sb
.ToString ();
794 public bool HasArglist
{
795 get { return has_arglist; }
798 public bool HasExtensionMethodType
{
803 return FixedParameters
[0].HasExtensionMethodModifier
;
807 public bool HasParams
{
808 get { return has_params; }
811 public bool IsEmpty
{
812 get { return parameters.Length == 0; }
815 public string ParameterDesc (int pos
)
817 if (types
== null || types
[pos
] == null)
818 return ((Parameter
)FixedParameters
[pos
]).GetSignatureForError ();
820 string type
= TypeManager
.CSharpName (types
[pos
]);
821 if (FixedParameters
[pos
].HasExtensionMethodModifier
)
822 return "this " + type
;
824 Parameter
.Modifier mod
= FixedParameters
[pos
].ModFlags
;
828 return Parameter
.GetModifierSignature (mod
) + " " + type
;
831 public Type
[] Types
{
832 get { return types; }
833 set { types = value; }
837 public AParametersCollection
InflateTypes (Type
[] genArguments
, Type
[] argTypes
)
839 AParametersCollection p
= (AParametersCollection
) MemberwiseClone (); // Clone ();
841 for (int i
= 0; i
< Count
; ++i
) {
842 if (types
[i
].IsGenericType
) {
843 Type
[] gen_arguments_open
= new Type
[types
[i
].GetGenericTypeDefinition ().GetGenericArguments ().Length
];
844 Type
[] gen_arguments
= types
[i
].GetGenericArguments ();
845 for (int ii
= 0; ii
< gen_arguments_open
.Length
; ++ii
) {
846 if (gen_arguments
[ii
].IsGenericParameter
) {
847 Type t
= argTypes
[gen_arguments
[ii
].GenericParameterPosition
];
848 gen_arguments_open
[ii
] = t
;
850 gen_arguments_open
[ii
] = gen_arguments
[ii
];
853 p
.types
[i
] = types
[i
].GetGenericTypeDefinition ().MakeGenericType (gen_arguments_open
);
857 if (types
[i
].IsGenericParameter
) {
858 Type gen_argument
= argTypes
[types
[i
].GenericParameterPosition
];
859 p
.types
[i
] = gen_argument
;
870 // A collection of imported or resolved parameters
872 public class ParametersImported
: AParametersCollection
874 ParametersImported (AParametersCollection param
, Type
[] types
)
876 this.parameters
= param
.FixedParameters
;
878 has_arglist
= param
.HasArglist
;
879 has_params
= param
.HasParams
;
882 ParametersImported (IParameterData
[] parameters
, Type
[] types
, bool hasArglist
, bool hasParams
)
884 this.parameters
= parameters
;
886 this.has_arglist
= hasArglist
;
887 this.has_params
= hasParams
;
890 public ParametersImported (IParameterData
[] param
, Type
[] types
)
892 this.parameters
= param
;
896 public static AParametersCollection
Create (MethodBase method
)
898 return Create (method
.GetParameters (), method
);
902 // Generic method parameters importer, param is shared between all instances
904 public static AParametersCollection
Create (AParametersCollection param
, MethodBase method
)
909 ParameterInfo
[] pi
= method
.GetParameters ();
910 Type
[] types
= new Type
[pi
.Length
];
911 for (int i
= 0; i
< types
.Length
; i
++) {
912 Type t
= pi
[i
].ParameterType
;
914 t
= TypeManager
.GetElementType (t
);
916 types
[i
] = TypeManager
.TypeToCoreType (t
);
919 return new ParametersImported (param
, types
);
923 // Imports SRE parameters
925 public static AParametersCollection
Create (ParameterInfo
[] pi
, MethodBase method
)
927 int varargs
= method
!= null && (method
.CallingConvention
& CallingConventions
.VarArgs
) != 0 ? 1 : 0;
929 if (pi
.Length
== 0 && varargs
== 0)
930 return ParametersCompiled
.EmptyReadOnlyParameters
;
932 Type
[] types
= new Type
[pi
.Length
+ varargs
];
933 IParameterData
[] par
= new IParameterData
[pi
.Length
+ varargs
];
934 bool is_params
= false;
935 PredefinedAttribute extension_attr
= PredefinedAttributes
.Get
.Extension
;
936 PredefinedAttribute param_attr
= PredefinedAttributes
.Get
.ParamArray
;
937 for (int i
= 0; i
< pi
.Length
; i
++) {
938 types
[i
] = TypeManager
.TypeToCoreType (pi
[i
].ParameterType
);
940 ParameterInfo p
= pi
[i
];
941 Parameter
.Modifier mod
= 0;
942 Expression default_value
= null;
943 if (types
[i
].IsByRef
) {
944 if ((p
.Attributes
& (ParameterAttributes
.Out
| ParameterAttributes
.In
)) == ParameterAttributes
.Out
)
945 mod
= Parameter
.Modifier
.OUT
;
947 mod
= Parameter
.Modifier
.REF
;
950 // Strip reference wrapping
952 types
[i
] = TypeManager
.GetElementType (types
[i
]);
953 } else if (i
== 0 && extension_attr
.IsDefined
&& method
!= null && method
.IsStatic
&&
954 (method
.DeclaringType
.Attributes
& Class
.StaticClassAttribute
) == Class
.StaticClassAttribute
&&
955 method
.IsDefined (extension_attr
.Type
, false)) {
956 mod
= Parameter
.Modifier
.This
;
958 if (i
>= pi
.Length
- 2 && types
[i
].IsArray
) {
959 if (p
.IsDefined (param_attr
.Type
, false)) {
960 mod
= Parameter
.Modifier
.PARAMS
;
965 if (!is_params
&& p
.IsOptional
) {
966 if (p
.DefaultValue
== Missing
.Value
)
967 default_value
= EmptyExpression
.Null
;
969 default_value
= Constant
.CreateConstant (types
[i
], p
.DefaultValue
, Location
.Null
);
973 par
[i
] = new ParameterData (p
.Name
, mod
, default_value
);
977 par
[par
.Length
- 1] = new ArglistParameter (Location
.Null
);
978 types
[types
.Length
- 1] = InternalType
.Arglist
;
981 return method
!= null ?
982 new ParametersImported (par
, types
, varargs
!= 0, is_params
) :
983 new ParametersImported (par
, types
);
988 /// Represents the methods parameters
990 public class ParametersCompiled
: AParametersCollection
992 public static readonly ParametersCompiled EmptyReadOnlyParameters
= new ParametersCompiled ();
994 // Used by C# 2.0 delegates
995 public static readonly ParametersCompiled Undefined
= new ParametersCompiled ();
997 private ParametersCompiled ()
999 parameters
= new Parameter
[0];
1000 types
= Type
.EmptyTypes
;
1003 private ParametersCompiled (Parameter
[] parameters
, Type
[] types
)
1005 this.parameters
= parameters
;
1009 public ParametersCompiled (params Parameter
[] parameters
)
1011 if (parameters
== null)
1012 throw new ArgumentException ("Use EmptyReadOnlyParameters");
1014 this.parameters
= parameters
;
1015 int count
= parameters
.Length
;
1021 has_params
= (parameters
[0].ModFlags
& Parameter
.Modifier
.PARAMS
) != 0;
1025 for (int i
= 0; i
< count
; i
++){
1026 string base_name
= parameters
[i
].Name
;
1027 has_params
|= (parameters
[i
].ModFlags
& Parameter
.Modifier
.PARAMS
) != 0;
1029 for (int j
= i
+ 1; j
< count
; j
++){
1030 if (base_name
!= parameters
[j
].Name
)
1033 ErrorDuplicateName (parameters
[i
]);
1039 public ParametersCompiled (Parameter
[] parameters
, bool has_arglist
) :
1042 this.has_arglist
= has_arglist
;
1045 public static ParametersCompiled
CreateFullyResolved (Parameter p
, Type type
)
1047 return new ParametersCompiled (new Parameter
[] { p }
, new Type
[] { type }
);
1050 public static ParametersCompiled
CreateFullyResolved (Parameter
[] parameters
, Type
[] types
)
1052 return new ParametersCompiled (parameters
, types
);
1055 public static ParametersCompiled
MergeGenerated (ParametersCompiled userParams
, bool checkConflicts
, Parameter compilerParams
, Type compilerTypes
)
1057 return MergeGenerated (userParams
, checkConflicts
,
1058 new Parameter
[] { compilerParams }
,
1059 new Type
[] { compilerTypes }
);
1063 // Use this method when you merge compiler generated parameters with user parameters
1065 public static ParametersCompiled
MergeGenerated (ParametersCompiled userParams
, bool checkConflicts
, Parameter
[] compilerParams
, Type
[] compilerTypes
)
1067 Parameter
[] all_params
= new Parameter
[userParams
.Count
+ compilerParams
.Length
];
1068 userParams
.FixedParameters
.CopyTo(all_params
, 0);
1071 if (userParams
.types
!= null) {
1072 all_types
= new Type
[all_params
.Length
];
1073 userParams
.Types
.CopyTo (all_types
, 0);
1078 int last_filled
= userParams
.Count
;
1080 foreach (Parameter p
in compilerParams
) {
1081 for (int i
= 0; i
< last_filled
; ++i
) {
1082 while (p
.Name
== all_params
[i
].Name
) {
1083 if (checkConflicts
&& i
< userParams
.Count
) {
1084 Report
.Error (316, userParams
[i
].Location
,
1085 "The parameter name `{0}' conflicts with a compiler generated name", p
.Name
);
1087 p
.Name
= '_' + p
.Name
;
1090 all_params
[last_filled
] = p
;
1091 if (all_types
!= null)
1092 all_types
[last_filled
] = compilerTypes
[index
++];
1096 ParametersCompiled parameters
= new ParametersCompiled (all_params
, all_types
);
1097 parameters
.has_params
= userParams
.has_params
;
1101 protected virtual void ErrorDuplicateName (Parameter p
)
1103 Report
.Error (100, p
.Location
, "The parameter name `{0}' is a duplicate", p
.Name
);
1106 public bool Resolve (IResolveContext ec
)
1111 types
= new Type
[Count
];
1115 for (int i
= 0; i
< FixedParameters
.Length
; ++i
) {
1117 Type t
= p
.Resolve (ec
);
1129 public void ResolveVariable ()
1131 for (int i
= 0; i
< FixedParameters
.Length
; ++i
) {
1132 this [i
].ResolveVariable (i
);
1136 public CallingConventions CallingConvention
1140 return CallingConventions
.VarArgs
;
1142 return CallingConventions
.Standard
;
1146 // Define each type attribute (in/out/ref) and
1147 // the argument names.
1148 public void ApplyAttributes (MethodBase builder
)
1153 MethodBuilder mb
= builder
as MethodBuilder
;
1154 ConstructorBuilder cb
= builder
as ConstructorBuilder
;
1156 for (int i
= 0; i
< Count
; i
++) {
1157 this [i
].ApplyAttributes (mb
, cb
, i
+ 1);
1161 public void VerifyClsCompliance ()
1163 foreach (Parameter p
in FixedParameters
)
1164 p
.IsClsCompliant ();
1167 public Parameter
this [int pos
] {
1168 get { return (Parameter) parameters [pos]; }
1171 public Expression
CreateExpressionTree (EmitContext ec
, Location loc
)
1173 ArrayList initializers
= new ArrayList (Count
);
1174 foreach (Parameter p
in FixedParameters
) {
1176 // Each parameter expression is stored to local variable
1177 // to save some memory when referenced later.
1179 StatementExpression se
= new StatementExpression (p
.CreateExpressionTreeVariable (ec
));
1180 if (se
.Resolve (ec
))
1181 ec
.CurrentBlock
.AddScopeStatement (se
);
1183 initializers
.Add (p
.ExpressionTreeVariableReference ());
1186 return new ArrayCreation (
1187 Parameter
.ResolveParameterExpressionType (ec
, loc
),
1188 "[]", initializers
, loc
);
1191 public ParametersCompiled
Clone ()
1193 ParametersCompiled p
= (ParametersCompiled
) MemberwiseClone ();
1195 p
.parameters
= new IParameterData
[parameters
.Length
];
1196 for (int i
= 0; i
< Count
; ++i
)
1197 p
.parameters
[i
] = this [i
].Clone ();