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
;
18 namespace Mono
.CSharp
{
21 /// Abstract Base class for parameters of a method.
23 public abstract class ParameterBase
: Attributable
25 protected ParameterBuilder builder
;
27 public override void ApplyAttributeBuilder (Attribute a
, CustomAttributeBuilder cb
, PredefinedAttributes pa
)
30 if (a
.Type
== pa
.MarshalAs
) {
31 UnmanagedMarshal marshal
= a
.GetMarshal (this);
32 if (marshal
!= null) {
33 builder
.SetMarshal (marshal
);
38 if (a
.HasSecurityAttribute
) {
39 a
.Error_InvalidSecurityParent ();
43 if (a
.Type
== pa
.Dynamic
) {
44 a
.Error_MisusedDynamicAttribute ();
48 builder
.SetCustomAttribute (cb
);
51 public ParameterBuilder Builder
{
57 public override bool IsClsComplianceRequired()
64 /// Class for applying custom attributes on the return type
66 public class ReturnParameter
: ParameterBase
70 // TODO: merge method and mb
71 public ReturnParameter (MemberCore method
, MethodBuilder mb
, Location location
)
75 builder
= mb
.DefineParameter (0, ParameterAttributes
.None
, "");
77 catch (ArgumentOutOfRangeException
) {
78 method
.Compiler
.Report
.RuntimeMissingSupport (location
, "custom attributes on the return type");
82 public override void ApplyAttributeBuilder (Attribute a
, CustomAttributeBuilder cb
, PredefinedAttributes pa
)
84 if (a
.Type
== pa
.CLSCompliant
) {
85 method
.Compiler
.Report
.Warning (3023, 1, a
.Location
,
86 "CLSCompliant attribute has no meaning when applied to return types. Try putting it on the method instead");
89 // This occurs after Warning -28
93 base.ApplyAttributeBuilder (a
, cb
, pa
);
96 public override AttributeTargets AttributeTargets
{
98 return AttributeTargets
.ReturnValue
;
105 public override string[] ValidAttributeTargets
{
113 /// Class for applying custom attributes on the implicit parameter type
114 /// of the 'set' method in properties, and the 'add' and 'remove' methods in events.
117 // TODO: should use more code from Parameter.ApplyAttributeBuilder
118 public class ImplicitParameter
: ParameterBase
{
119 public ImplicitParameter (MethodBuilder mb
)
121 builder
= mb
.DefineParameter (1, ParameterAttributes
.None
, "value");
124 public override AttributeTargets AttributeTargets
{
126 return AttributeTargets
.Parameter
;
133 public override string[] ValidAttributeTargets
{
140 public class ImplicitLambdaParameter
: Parameter
142 public ImplicitLambdaParameter (string name
, Location loc
)
143 : base (null, name
, Modifier
.NONE
, null, loc
)
147 public override Type
Resolve (IMemberContext ec
)
149 if (parameter_type
== null)
150 throw new InternalErrorException ("A type of implicit lambda parameter `{0}' is not set",
153 return parameter_type
;
157 set { parameter_type = value; }
161 public class ParamsParameter
: Parameter
{
162 public ParamsParameter (FullNamedExpression type
, string name
, Attributes attrs
, Location loc
):
163 base (type
, name
, Parameter
.Modifier
.PARAMS
, attrs
, loc
)
167 public override Type
Resolve (IMemberContext ec
)
169 if (base.Resolve (ec
) == null)
172 if (!parameter_type
.IsArray
|| parameter_type
.GetArrayRank () != 1) {
173 ec
.Compiler
.Report
.Error (225, Location
, "The params parameter must be a single dimensional array");
177 return parameter_type
;
180 public override void ApplyAttributes (MethodBuilder mb
, ConstructorBuilder cb
, int index
)
182 base.ApplyAttributes (mb
, cb
, index
);
183 PredefinedAttributes
.Get
.ParamArray
.EmitAttribute (builder
);
187 public class ArglistParameter
: Parameter
{
188 // Doesn't have proper type because it's never chosen for better conversion
189 public ArglistParameter (Location loc
) :
190 base (null, String
.Empty
, Parameter
.Modifier
.NONE
, null, loc
)
194 public override void ApplyAttributes (MethodBuilder mb
, ConstructorBuilder cb
, int index
)
199 public override bool CheckAccessibility (InterfaceMemberBase member
)
204 public override Type
Resolve (IMemberContext ec
)
206 return InternalType
.Arglist
;
209 public override string GetSignatureForError ()
215 public interface IParameterData
217 Expression DefaultValue { get; }
218 bool HasExtensionMethodModifier { get; }
219 bool HasDefaultValue { get; }
220 Parameter
.Modifier ModFlags { get; }
225 // Parameter information created by parser
227 public class Parameter
: ParameterBase
, IParameterData
, ILocalVariable
{
229 public enum Modifier
: byte {
231 REF
= REFMASK
| ISBYREF
,
232 OUT
= OUTMASK
| ISBYREF
,
234 // This is a flag which says that it's either REF or OUT.
241 static string[] attribute_targets
= new string [] { "param" }
;
243 protected FullNamedExpression TypeName
;
244 readonly Modifier modFlags
;
246 Expression default_expr
;
247 protected Type parameter_type
;
248 public readonly Location Location
;
250 public bool HasAddressTaken
;
252 Expression expr_tree_variable
;
253 static TypeExpr parameter_expr_tree_type
;
255 HoistedVariable hoisted_variant
;
257 public Parameter (FullNamedExpression type
, string name
, Modifier mod
, Attributes attrs
, Location loc
)
264 // Only assign, attributes will be attached during resolve
265 base.attributes
= attrs
;
268 public override void ApplyAttributeBuilder (Attribute a
, CustomAttributeBuilder cb
, PredefinedAttributes pa
)
270 if (a
.Type
== pa
.In
&& ModFlags
== Modifier
.OUT
) {
271 a
.Report
.Error (36, a
.Location
, "An out parameter cannot have the `In' attribute");
275 if (a
.Type
== pa
.ParamArray
) {
276 a
.Report
.Error (674, a
.Location
, "Do not use `System.ParamArrayAttribute'. Use the `params' keyword instead");
280 if (a
.Type
== PredefinedAttributes
.Get
.Out
&& (ModFlags
& Modifier
.REF
) == Modifier
.REF
&&
281 !OptAttributes
.Contains (pa
.In
)) {
282 a
.Report
.Error (662, a
.Location
,
283 "Cannot specify only `Out' attribute on a ref parameter. Use both `In' and `Out' attributes or neither");
287 if (a
.Type
== pa
.CLSCompliant
) {
288 a
.Report
.Warning (3022, 1, a
.Location
, "CLSCompliant attribute has no meaning when applied to parameters. Try putting it on the method instead");
291 if (HasDefaultValue
&& (a
.Type
== pa
.DefaultParameterValue
|| a
.Type
== pa
.OptionalParameter
)) {
292 a
.Report
.Error (1745, a
.Location
,
293 "Cannot specify `{0}' attribute on optional parameter `{1}'",
294 TypeManager
.CSharpName (a
.Type
).Replace ("Attribute", ""), Name
);
298 if (a
.Type
== pa
.DefaultParameterValue
) {
299 object val
= a
.GetParameterDefaultValue ();
301 Type t
= val
.GetType ();
302 if (t
.IsArray
|| TypeManager
.IsSubclassOf (t
, TypeManager
.type_type
)) {
303 if (parameter_type
== TypeManager
.object_type
) {
305 t
= TypeManager
.type_type
;
307 a
.Report
.Error (1910, a
.Location
, "Argument of type `{0}' is not applicable for the DefaultParameterValue attribute",
308 TypeManager
.CSharpName (t
));
310 a
.Report
.Error (1909, a
.Location
, "The DefaultParameterValue attribute is not applicable on parameters of type `{0}'",
311 TypeManager
.CSharpName (parameter_type
)); ;
317 if (parameter_type
== TypeManager
.object_type
||
318 (val
== null && !TypeManager
.IsGenericParameter (parameter_type
) && TypeManager
.IsReferenceType (parameter_type
)) ||
319 (val
!= null && TypeManager
.TypeToCoreType (val
.GetType ()) == parameter_type
))
320 builder
.SetConstant (val
);
322 a
.Report
.Error (1908, a
.Location
, "The type of the default value should match the type of the parameter");
326 base.ApplyAttributeBuilder (a
, cb
, pa
);
329 public virtual bool CheckAccessibility (InterfaceMemberBase member
)
331 if (parameter_type
== null || TypeManager
.IsGenericParameter (parameter_type
))
334 return member
.IsAccessibleAs (parameter_type
);
338 // Resolve is used in method definitions
340 public virtual Type
Resolve (IMemberContext rc
)
342 if (parameter_type
!= null)
343 return parameter_type
;
345 if (attributes
!= null)
346 attributes
.AttachTo (this, rc
);
348 TypeExpr texpr
= TypeName
.ResolveAsTypeTerminal (rc
, false);
352 parameter_type
= texpr
.Type
;
354 // Ignore all checks for dummy members
355 AbstractPropertyEventMethod pem
= rc
as AbstractPropertyEventMethod
;
356 if (pem
!= null && pem
.IsDummy
)
357 return parameter_type
;
359 if (default_expr
!= null)
360 default_expr
= ResolveDefaultValue (new ResolveContext (rc
));
362 if ((modFlags
& Parameter
.Modifier
.ISBYREF
) != 0 &&
363 TypeManager
.IsSpecialType (parameter_type
)) {
364 rc
.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 (TypeManager
.IsGenericParameter (parameter_type
))
374 return parameter_type
;
376 if ((parameter_type
.Attributes
& Class
.StaticClassAttribute
) == Class
.StaticClassAttribute
) {
377 rc
.Compiler
.Report
.Error (721, Location
, "`{0}': static types cannot be used as parameters",
378 texpr
.GetSignatureForError ());
379 return parameter_type
;
382 if ((modFlags
& Modifier
.This
) != 0 && (parameter_type
.IsPointer
|| TypeManager
.IsDynamicType (parameter_type
))) {
383 rc
.Compiler
.Report
.Error (1103, Location
, "The extension method cannot be of type `{0}'",
384 TypeManager
.CSharpName (parameter_type
));
387 return parameter_type
;
390 Expression
ResolveDefaultValue (ResolveContext rc
)
392 default_expr
= default_expr
.Resolve (rc
);
393 if (default_expr
== null)
396 if (!(default_expr
is Constant
|| default_expr
is DefaultValueExpression
)) {
397 if (TypeManager
.IsNullableType (parameter_type
)) {
398 rc
.Compiler
.Report
.Error (1770, default_expr
.Location
,
399 "The expression being assigned to nullable optional parameter `{0}' must be default value",
402 rc
.Compiler
.Report
.Error (1736, default_expr
.Location
,
403 "The expression being assigned to optional parameter `{0}' must be a constant or default value",
410 if (TypeManager
.IsEqual (default_expr
.Type
, parameter_type
))
413 if (TypeManager
.IsNullableType (parameter_type
)) {
414 if (Convert
.ImplicitNulableConversion (rc
, default_expr
, parameter_type
) != null)
417 var res
= Convert
.ImplicitConversionStandard (rc
, default_expr
, parameter_type
, default_expr
.Location
);
419 if (!default_expr
.IsNull
&& TypeManager
.IsReferenceType (parameter_type
) && parameter_type
!= TypeManager
.string_type
) {
420 rc
.Compiler
.Report
.Error (1763, default_expr
.Location
,
421 "Optional parameter `{0}' of type `{1}' can only be initialized with `null'",
422 Name
, GetSignatureForError ());
431 rc
.Compiler
.Report
.Error (1750, Location
,
432 "Optional parameter expression of type `{0}' cannot be converted to parameter type `{1}'",
433 TypeManager
.CSharpName (default_expr
.Type
), GetSignatureForError ());
438 public void ResolveVariable (int idx
)
443 public bool HasDefaultValue
{
444 get { return default_expr != null; }
447 public bool HasExtensionMethodModifier
{
448 get { return (modFlags & Modifier.This) != 0; }
452 // Hoisted parameter variant
454 public HoistedVariable HoistedVariant
{
456 return hoisted_variant
;
459 hoisted_variant
= value;
463 public Modifier ModFlags
{
464 get { return modFlags & ~Modifier.This; }
469 set { name = value; }
472 ParameterAttributes Attributes
{
473 get { return ParametersCompiled
.GetParameterAttribute (modFlags
) |
474 (HasDefaultValue
? ParameterAttributes
.Optional
: ParameterAttributes
.None
); }
477 public override AttributeTargets AttributeTargets
{
479 return AttributeTargets
.Parameter
;
483 public virtual string GetSignatureForError ()
486 if (parameter_type
!= null)
487 type_name
= TypeManager
.CSharpName (parameter_type
);
489 type_name
= TypeName
.GetSignatureForError ();
491 string mod
= GetModifierSignature (modFlags
);
493 return String
.Concat (mod
, " ", type_name
);
498 public static string GetModifierSignature (Modifier mod
)
503 case Modifier
.PARAMS
:
514 public void IsClsCompliant (IMemberContext ctx
)
516 if (AttributeTester
.IsClsCompliant (parameter_type
))
519 ctx
.Compiler
.Report
.Warning (3001, 1, Location
,
520 "Argument type `{0}' is not CLS-compliant", GetSignatureForError ());
523 public virtual void ApplyAttributes (MethodBuilder mb
, ConstructorBuilder cb
, int index
)
526 builder
= cb
.DefineParameter (index
, Attributes
, Name
);
528 builder
= mb
.DefineParameter (index
, Attributes
, Name
);
530 if (OptAttributes
!= null)
531 OptAttributes
.Emit ();
533 if (HasDefaultValue
) {
535 // Emit constant values for true constants only, the other
536 // constant-like expressions will rely on default value expression
538 Constant c
= default_expr
as Constant
;
540 if (default_expr
.Type
== TypeManager
.decimal_type
) {
541 builder
.SetCustomAttribute (Const
.CreateDecimalConstantAttribute (c
));
543 builder
.SetConstant (c
.GetTypedValue ());
548 if (TypeManager
.IsDynamicType (parameter_type
)) {
549 PredefinedAttributes
.Get
.Dynamic
.EmitAttribute (builder
);
551 var trans_flags
= TypeManager
.HasDynamicTypeUsed (parameter_type
);
552 if (trans_flags
!= null) {
553 var pa
= PredefinedAttributes
.Get
.DynamicTransform
;
554 if (pa
.Constructor
!= null || pa
.ResolveConstructor (Location
, TypeManager
.bool_type
.MakeArrayType ())) {
555 builder
.SetCustomAttribute (
556 new CustomAttributeBuilder (pa
.Constructor
, new object [] { trans_flags }
));
562 public override string[] ValidAttributeTargets
{
564 return attribute_targets
;
568 public Parameter
Clone ()
570 Parameter p
= (Parameter
) MemberwiseClone ();
571 if (attributes
!= null)
572 p
.attributes
= attributes
.Clone ();
577 public ExpressionStatement
CreateExpressionTreeVariable (BlockContext ec
)
579 if ((modFlags
& Modifier
.ISBYREF
) != 0)
580 ec
.Report
.Error (1951, Location
, "An expression tree parameter cannot use `ref' or `out' modifier");
582 expr_tree_variable
= new TemporaryVariable (ResolveParameterExpressionType (ec
, Location
).Type
, Location
);
583 expr_tree_variable
= expr_tree_variable
.Resolve (ec
);
585 Arguments arguments
= new Arguments (2);
586 arguments
.Add (new Argument (new TypeOf (
587 new TypeExpression (parameter_type
, Location
), Location
)));
588 arguments
.Add (new Argument (new StringConstant (Name
, Location
)));
589 return new SimpleAssign (ExpressionTreeVariableReference (),
590 Expression
.CreateExpressionFactoryCall (ec
, "Parameter", null, arguments
, Location
));
593 public Expression DefaultValue
{
594 get { return default_expr; }
595 set { default_expr = value; }
598 public void Emit (EmitContext ec
)
604 ParameterReference
.EmitLdArg (ec
.ig
, arg_idx
);
607 public void EmitAssign (EmitContext ec
)
614 ec
.ig
.Emit (OpCodes
.Starg_S
, (byte) arg_idx
);
616 ec
.ig
.Emit (OpCodes
.Starg
, arg_idx
);
619 public void EmitAddressOf (EmitContext ec
)
626 bool is_ref
= (ModFlags
& Modifier
.ISBYREF
) != 0;
628 ParameterReference
.EmitLdArg (ec
.ig
, arg_idx
);
631 ec
.ig
.Emit (OpCodes
.Ldarga_S
, (byte) arg_idx
);
633 ec
.ig
.Emit (OpCodes
.Ldarga
, arg_idx
);
637 public Expression
ExpressionTreeVariableReference ()
639 return expr_tree_variable
;
643 // System.Linq.Expressions.ParameterExpression type
645 public static TypeExpr
ResolveParameterExpressionType (IMemberContext ec
, Location location
)
647 if (parameter_expr_tree_type
!= null)
648 return parameter_expr_tree_type
;
650 Type p_type
= TypeManager
.parameter_expression_type
;
651 if (p_type
== null) {
652 p_type
= TypeManager
.CoreLookupType (ec
.Compiler
, "System.Linq.Expressions", "ParameterExpression", MemberKind
.Class
, true);
653 TypeManager
.parameter_expression_type
= p_type
;
656 parameter_expr_tree_type
= new TypeExpression (p_type
, location
).
657 ResolveAsTypeTerminal (ec
, false);
659 return parameter_expr_tree_type
;
662 public void Warning_UselessOptionalParameter (Report Report
)
664 Report
.Warning (1066, 1, Location
,
665 "The default value specified for optional parameter `{0}' will never be used",
671 // Imported or resolved parameter information
673 public class ParameterData
: IParameterData
675 readonly string name
;
676 readonly Parameter
.Modifier modifiers
;
677 readonly Expression default_value
;
679 public ParameterData (string name
, Parameter
.Modifier modifiers
)
682 this.modifiers
= modifiers
;
685 public ParameterData (string name
, Parameter
.Modifier modifiers
, Expression defaultValue
)
686 : this (name
, modifiers
)
688 this.default_value
= defaultValue
;
691 #region IParameterData Members
693 public Expression DefaultValue
{
694 get { return default_value; }
697 public bool HasExtensionMethodModifier
{
698 get { return (modifiers & Parameter.Modifier.This) != 0; }
701 public bool HasDefaultValue
{
702 get { return default_value != null; }
705 public Parameter
.Modifier ModFlags
{
706 get { return modifiers & ~Parameter.Modifier.This; }
716 public abstract class AParametersCollection
718 protected bool has_arglist
;
719 protected bool has_params
;
721 // Null object pattern
722 protected IParameterData
[] parameters
;
723 protected Type
[] types
;
725 public ParametersCompiled AsCompiled
{
726 get { return (ParametersCompiled) this; }
729 public CallingConventions CallingConvention
{
732 CallingConventions
.VarArgs
:
733 CallingConventions
.Standard
;
738 get { return parameters.Length; }
741 public Type ExtensionMethodType
{
746 return FixedParameters
[0].HasExtensionMethodModifier
?
751 public IParameterData
[] FixedParameters
{
757 public static ParameterAttributes
GetParameterAttribute (Parameter
.Modifier modFlags
)
759 return (modFlags
& Parameter
.Modifier
.OUT
) == Parameter
.Modifier
.OUT
?
760 ParameterAttributes
.Out
: ParameterAttributes
.None
;
763 public Type
[] GetEmitTypes ()
765 Type
[] types
= null;
768 return Type
.EmptyTypes
;
770 types
= new Type
[Count
- 1];
771 Array
.Copy (Types
, types
, types
.Length
);
774 for (int i
= 0; i
< Count
; ++i
) {
775 if ((FixedParameters
[i
].ModFlags
& Parameter
.Modifier
.ISBYREF
) == 0)
779 types
= (Type
[]) Types
.Clone ();
781 types
[i
] = TypeManager
.GetReferenceType (types
[i
]);
791 // Returns the parameter information based on the name
793 public int GetParameterIndexByName (string name
)
795 for (int idx
= 0; idx
< Count
; ++idx
) {
796 if (parameters
[idx
].Name
== name
)
803 public string GetSignatureForError ()
805 StringBuilder sb
= new StringBuilder ("(");
806 for (int i
= 0; i
< Count
; ++i
) {
809 sb
.Append (ParameterDesc (i
));
812 return sb
.ToString ();
815 public bool HasArglist
{
816 get { return has_arglist; }
819 public bool HasExtensionMethodType
{
824 return FixedParameters
[0].HasExtensionMethodModifier
;
828 public bool HasParams
{
829 get { return has_params; }
832 public bool IsEmpty
{
833 get { return parameters.Length == 0; }
836 public string ParameterDesc (int pos
)
838 if (types
== null || types
[pos
] == null)
839 return ((Parameter
)FixedParameters
[pos
]).GetSignatureForError ();
841 string type
= TypeManager
.CSharpName (types
[pos
]);
842 if (FixedParameters
[pos
].HasExtensionMethodModifier
)
843 return "this " + type
;
845 Parameter
.Modifier mod
= FixedParameters
[pos
].ModFlags
;
849 return Parameter
.GetModifierSignature (mod
) + " " + type
;
852 public Type
[] Types
{
853 get { return types; }
854 set { types = value; }
858 public AParametersCollection
InflateTypes (Type
[] genArguments
, Type
[] argTypes
)
860 AParametersCollection p
= (AParametersCollection
) MemberwiseClone (); // Clone ();
862 for (int i
= 0; i
< Count
; ++i
) {
863 if (types
[i
].IsGenericType
) {
864 Type
[] gen_arguments_open
= new Type
[types
[i
].GetGenericTypeDefinition ().GetGenericArguments ().Length
];
865 Type
[] gen_arguments
= types
[i
].GetGenericArguments ();
866 for (int ii
= 0; ii
< gen_arguments_open
.Length
; ++ii
) {
867 if (gen_arguments
[ii
].IsGenericParameter
) {
868 Type t
= argTypes
[gen_arguments
[ii
].GenericParameterPosition
];
869 gen_arguments_open
[ii
] = t
;
871 gen_arguments_open
[ii
] = gen_arguments
[ii
];
874 p
.types
[i
] = types
[i
].GetGenericTypeDefinition ().MakeGenericType (gen_arguments_open
);
878 if (types
[i
].IsGenericParameter
) {
879 Type gen_argument
= argTypes
[types
[i
].GenericParameterPosition
];
880 p
.types
[i
] = gen_argument
;
891 // A collection of imported or resolved parameters
893 public class ParametersImported
: AParametersCollection
895 ParametersImported (AParametersCollection param
, Type
[] types
)
897 this.parameters
= param
.FixedParameters
;
899 has_arglist
= param
.HasArglist
;
900 has_params
= param
.HasParams
;
903 ParametersImported (IParameterData
[] parameters
, Type
[] types
, bool hasArglist
, bool hasParams
)
905 this.parameters
= parameters
;
907 this.has_arglist
= hasArglist
;
908 this.has_params
= hasParams
;
911 public ParametersImported (IParameterData
[] param
, Type
[] types
)
913 this.parameters
= param
;
917 public static AParametersCollection
Create (MethodBase method
)
919 return Create (method
.GetParameters (), method
);
923 // Generic method parameters importer, param is shared between all instances
925 public static AParametersCollection
Create (AParametersCollection param
, MethodBase method
)
930 ParameterInfo
[] pi
= method
.GetParameters ();
931 Type
[] types
= new Type
[pi
.Length
];
932 for (int i
= 0; i
< types
.Length
; i
++) {
933 Type t
= pi
[i
].ParameterType
;
935 t
= TypeManager
.GetElementType (t
);
937 types
[i
] = TypeManager
.TypeToCoreType (t
);
940 return new ParametersImported (param
, types
);
944 // Imports SRE parameters
946 public static AParametersCollection
Create (ParameterInfo
[] pi
, MethodBase method
)
948 int varargs
= method
!= null && (method
.CallingConvention
& CallingConventions
.VarArgs
) != 0 ? 1 : 0;
950 if (pi
.Length
== 0 && varargs
== 0)
951 return ParametersCompiled
.EmptyReadOnlyParameters
;
953 Type
[] types
= new Type
[pi
.Length
+ varargs
];
954 IParameterData
[] par
= new IParameterData
[pi
.Length
+ varargs
];
955 bool is_params
= false;
956 PredefinedAttribute extension_attr
= PredefinedAttributes
.Get
.Extension
;
957 PredefinedAttribute param_attr
= PredefinedAttributes
.Get
.ParamArray
;
958 for (int i
= 0; i
< pi
.Length
; i
++) {
959 types
[i
] = TypeManager
.TypeToCoreType (pi
[i
].ParameterType
);
961 ParameterInfo p
= pi
[i
];
962 Parameter
.Modifier mod
= 0;
963 Expression default_value
= null;
964 if (types
[i
].IsByRef
) {
965 if ((p
.Attributes
& (ParameterAttributes
.Out
| ParameterAttributes
.In
)) == ParameterAttributes
.Out
)
966 mod
= Parameter
.Modifier
.OUT
;
968 mod
= Parameter
.Modifier
.REF
;
971 // Strip reference wrapping
973 types
[i
] = TypeManager
.GetElementType (types
[i
]);
974 } else if (i
== 0 && extension_attr
.IsDefined
&& method
!= null && method
.IsStatic
&&
975 (method
.DeclaringType
.Attributes
& Class
.StaticClassAttribute
) == Class
.StaticClassAttribute
&&
976 method
.IsDefined (extension_attr
.Type
, false)) {
977 mod
= Parameter
.Modifier
.This
;
979 if (i
>= pi
.Length
- 2 && types
[i
].IsArray
) {
980 if (p
.IsDefined (param_attr
.Type
, false)) {
981 mod
= Parameter
.Modifier
.PARAMS
;
986 if (!is_params
&& p
.IsOptional
) {
987 object value = p
.DefaultValue
;
988 if (value == Missing
.Value
) {
989 default_value
= EmptyExpression
.Null
;
990 } else if (value == null) {
991 default_value
= new NullLiteral (Location
.Null
);
993 default_value
= Constant
.CreateConstant (null, value.GetType (), value, Location
.Null
);
998 par
[i
] = new ParameterData (p
.Name
, mod
, default_value
);
1002 par
[par
.Length
- 1] = new ArglistParameter (Location
.Null
);
1003 types
[types
.Length
- 1] = InternalType
.Arglist
;
1006 return method
!= null ?
1007 new ParametersImported (par
, types
, varargs
!= 0, is_params
) :
1008 new ParametersImported (par
, types
);
1013 /// Represents the methods parameters
1015 public class ParametersCompiled
: AParametersCollection
1017 public static readonly ParametersCompiled EmptyReadOnlyParameters
= new ParametersCompiled ();
1019 // Used by C# 2.0 delegates
1020 public static readonly ParametersCompiled Undefined
= new ParametersCompiled ();
1022 private ParametersCompiled ()
1024 parameters
= new Parameter
[0];
1025 types
= Type
.EmptyTypes
;
1028 private ParametersCompiled (Parameter
[] parameters
, Type
[] types
)
1030 this.parameters
= parameters
;
1034 public ParametersCompiled (CompilerContext ctx
, params Parameter
[] parameters
)
1036 if (parameters
== null)
1037 throw new ArgumentException ("Use EmptyReadOnlyParameters");
1039 this.parameters
= parameters
;
1040 int count
= parameters
.Length
;
1046 has_params
= (parameters
[0].ModFlags
& Parameter
.Modifier
.PARAMS
) != 0;
1050 for (int i
= 0; i
< count
; i
++){
1051 string base_name
= parameters
[i
].Name
;
1052 has_params
|= (parameters
[i
].ModFlags
& Parameter
.Modifier
.PARAMS
) != 0;
1054 for (int j
= i
+ 1; j
< count
; j
++){
1055 if (base_name
!= parameters
[j
].Name
)
1058 ErrorDuplicateName (parameters
[i
], ctx
.Report
);
1064 public ParametersCompiled (CompilerContext ctx
, Parameter
[] parameters
, bool has_arglist
) :
1065 this (ctx
, parameters
)
1067 this.has_arglist
= has_arglist
;
1070 public static ParametersCompiled
CreateFullyResolved (Parameter p
, Type type
)
1072 return new ParametersCompiled (new Parameter
[] { p }
, new Type
[] { type }
);
1075 public static ParametersCompiled
CreateFullyResolved (Parameter
[] parameters
, Type
[] types
)
1077 return new ParametersCompiled (parameters
, types
);
1080 public static ParametersCompiled
MergeGenerated (CompilerContext ctx
, ParametersCompiled userParams
, bool checkConflicts
, Parameter compilerParams
, Type compilerTypes
)
1082 return MergeGenerated (ctx
, userParams
, checkConflicts
,
1083 new Parameter
[] { compilerParams }
,
1084 new Type
[] { compilerTypes }
);
1088 // Use this method when you merge compiler generated parameters with user parameters
1090 public static ParametersCompiled
MergeGenerated (CompilerContext ctx
, ParametersCompiled userParams
, bool checkConflicts
, Parameter
[] compilerParams
, Type
[] compilerTypes
)
1092 Parameter
[] all_params
= new Parameter
[userParams
.Count
+ compilerParams
.Length
];
1093 userParams
.FixedParameters
.CopyTo(all_params
, 0);
1096 if (userParams
.types
!= null) {
1097 all_types
= new Type
[all_params
.Length
];
1098 userParams
.Types
.CopyTo (all_types
, 0);
1103 int last_filled
= userParams
.Count
;
1105 foreach (Parameter p
in compilerParams
) {
1106 for (int i
= 0; i
< last_filled
; ++i
) {
1107 while (p
.Name
== all_params
[i
].Name
) {
1108 if (checkConflicts
&& i
< userParams
.Count
) {
1109 ctx
.Report
.Error (316, userParams
[i
].Location
,
1110 "The parameter name `{0}' conflicts with a compiler generated name", p
.Name
);
1112 p
.Name
= '_' + p
.Name
;
1115 all_params
[last_filled
] = p
;
1116 if (all_types
!= null)
1117 all_types
[last_filled
] = compilerTypes
[index
++];
1121 ParametersCompiled parameters
= new ParametersCompiled (all_params
, all_types
);
1122 parameters
.has_params
= userParams
.has_params
;
1126 protected virtual void ErrorDuplicateName (Parameter p
, Report Report
)
1128 Report
.Error (100, p
.Location
, "The parameter name `{0}' is a duplicate", p
.Name
);
1131 public bool Resolve (IMemberContext ec
)
1136 types
= new Type
[Count
];
1140 for (int i
= 0; i
< FixedParameters
.Length
; ++i
) {
1142 Type t
= p
.Resolve (ec
);
1154 public void ResolveVariable ()
1156 for (int i
= 0; i
< FixedParameters
.Length
; ++i
) {
1157 this [i
].ResolveVariable (i
);
1161 // Define each type attribute (in/out/ref) and
1162 // the argument names.
1163 public void ApplyAttributes (MethodBase builder
)
1168 MethodBuilder mb
= builder
as MethodBuilder
;
1169 ConstructorBuilder cb
= builder
as ConstructorBuilder
;
1171 for (int i
= 0; i
< Count
; i
++) {
1172 this [i
].ApplyAttributes (mb
, cb
, i
+ 1);
1176 public void VerifyClsCompliance (IMemberContext ctx
)
1178 foreach (Parameter p
in FixedParameters
)
1179 p
.IsClsCompliant (ctx
);
1182 public Parameter
this [int pos
] {
1183 get { return (Parameter) parameters [pos]; }
1186 public Expression
CreateExpressionTree (BlockContext ec
, Location loc
)
1188 var initializers
= new ArrayInitializer (Count
, loc
);
1189 foreach (Parameter p
in FixedParameters
) {
1191 // Each parameter expression is stored to local variable
1192 // to save some memory when referenced later.
1194 StatementExpression se
= new StatementExpression (p
.CreateExpressionTreeVariable (ec
));
1195 if (se
.Resolve (ec
))
1196 ec
.CurrentBlock
.AddScopeStatement (se
);
1198 initializers
.Add (p
.ExpressionTreeVariableReference ());
1201 return new ArrayCreation (
1202 Parameter
.ResolveParameterExpressionType (ec
, loc
),
1203 "[]", initializers
, loc
);
1206 public ParametersCompiled
Clone ()
1208 ParametersCompiled p
= (ParametersCompiled
) MemberwiseClone ();
1210 p
.parameters
= new IParameterData
[parameters
.Length
];
1211 for (int i
= 0; i
< Count
; ++i
)
1212 p
.parameters
[i
] = this [i
].Clone ();