2 // parameter.cs: Parameter definition.
4 // Author: Miguel de Icaza (miguel@gnu.org)
5 // Marek Safar (marek.safar@seznam.cz)
7 // Licensed under the terms of the GNU GPL
9 // (C) 2001 Ximian, Inc (http://www.ximian.com)
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
;
27 public readonly Location Location
;
29 protected ParameterBase (Attributes attrs
, Location loc
)
35 public override void ApplyAttributeBuilder (Attribute a
, CustomAttributeBuilder cb
)
37 if (a
.Type
== TypeManager
.marshal_as_attr_type
) {
38 UnmanagedMarshal marshal
= a
.GetMarshal (this);
39 if (marshal
!= null) {
40 builder
.SetMarshal (marshal
);
45 if (a
.Type
.IsSubclassOf (TypeManager
.security_attr_type
)) {
46 a
.Error_InvalidSecurityParent ();
50 builder
.SetCustomAttribute (cb
);
53 public override bool IsClsComplianceRequired(DeclSpace ds
)
60 /// Class for applying custom attributes on the return type
62 public class ReturnParameter
: ParameterBase
{
63 public ReturnParameter (MethodBuilder mb
, Location location
):
67 builder
= mb
.DefineParameter (0, ParameterAttributes
.None
, "");
69 catch (ArgumentOutOfRangeException
) {
70 Report
.RuntimeMissingSupport (Location
, "custom attributes on the return type");
74 public override void ApplyAttributeBuilder(Attribute a
, CustomAttributeBuilder cb
)
76 if (a
.Type
== TypeManager
.cls_compliant_attribute_type
) {
77 Report
.Warning (3023, 1, a
.Location
, "CLSCompliant attribute has no meaning when applied to return types. Try putting it on the method instead");
80 // This occurs after Warning -28
84 base.ApplyAttributeBuilder (a
, cb
);
87 public override AttributeTargets AttributeTargets
{
89 return AttributeTargets
.ReturnValue
;
96 public override string[] ValidAttributeTargets
{
104 /// Class for applying custom attributes on the implicit parameter type
105 /// of the 'set' method in properties, and the 'add' and 'remove' methods in events.
108 // TODO: should use more code from Parameter.ApplyAttributeBuilder
109 public class ImplicitParameter
: ParameterBase
{
110 public ImplicitParameter (MethodBuilder mb
, Location loc
):
113 builder
= mb
.DefineParameter (1, ParameterAttributes
.None
, "");
116 public override AttributeTargets AttributeTargets
{
118 return AttributeTargets
.Parameter
;
125 public override string[] ValidAttributeTargets
{
132 public class ParamsParameter
: Parameter
{
133 public ParamsParameter (Expression type
, string name
, Attributes attrs
, Location loc
):
134 base (type
, name
, Parameter
.Modifier
.PARAMS
, attrs
, loc
)
138 public override bool Resolve (EmitContext ec
)
140 if (!base.Resolve (ec
))
143 if (!parameter_type
.IsArray
|| parameter_type
.GetArrayRank () != 1) {
144 Report
.Error (225, Location
, "The params parameter must be a single dimensional array");
150 public override void ApplyAttributes (EmitContext ec
, MethodBuilder mb
, ConstructorBuilder cb
, int index
)
152 base.ApplyAttributes (ec
, mb
, cb
, index
);
154 CustomAttributeBuilder a
= new CustomAttributeBuilder (
155 TypeManager
.cons_param_array_attribute
, new object [0]);
157 builder
.SetCustomAttribute (a
);
161 public class ArglistParameter
: Parameter
{
162 // Doesn't have proper type because it's never choosed for better conversion
163 public ArglistParameter () :
164 base (typeof (ArglistParameter
), "", Parameter
.Modifier
.ARGLIST
, null, Location
.Null
)
168 public override bool Resolve (EmitContext ec
)
173 public override string GetSignatureForError ()
180 /// Represents a single method parameter
182 public class Parameter
: ParameterBase
{
184 public enum Modifier
: byte {
186 REF
= REFMASK
| ISBYREF
,
187 OUT
= OUTMASK
| ISBYREF
,
189 // This is a flag which says that it's either REF or OUT.
196 static string[] attribute_targets
= new string [] { "param" }
;
198 public Expression TypeName
;
199 public readonly Modifier ModFlags
;
200 public readonly string Name
;
201 protected Type parameter_type
;
203 EmitContext ec
; // because ApplyAtrribute doesn't have ec
205 public Parameter (Expression type
, string name
, Modifier mod
, Attributes attrs
, Location loc
)
213 public Parameter (Type type
, string name
, Modifier mod
, Attributes attrs
, Location loc
)
218 parameter_type
= type
;
221 public override void ApplyAttributeBuilder (Attribute a
, CustomAttributeBuilder cb
)
223 if (a
.Type
== TypeManager
.in_attribute_type
&& ModFlags
== Modifier
.OUT
) {
224 Report
.Error (36, a
.Location
, "An out parameter cannot have the `In' attribute");
228 if (a
.Type
== TypeManager
.param_array_type
) {
229 Report
.Error (674, a
.Location
, "Do not use `System.ParamArrayAttribute'. Use the `params' keyword instead");
233 if (a
.Type
== TypeManager
.out_attribute_type
&& (ModFlags
& Modifier
.REF
) == Modifier
.REF
&&
234 !OptAttributes
.Contains (TypeManager
.in_attribute_type
, ec
)) {
235 Report
.Error (662, a
.Location
,
236 "Cannot specify only `Out' attribute on a ref parameter. Use both `In' and `Out' attributes or neither");
240 if (a
.Type
== TypeManager
.cls_compliant_attribute_type
) {
241 Report
.Warning (3022, 1, a
.Location
, "CLSCompliant attribute has no meaning when applied to parameters. Try putting it on the method instead");
244 base.ApplyAttributeBuilder (a
, cb
);
248 // Resolve is used in method definitions
250 public virtual bool Resolve (EmitContext ec
)
252 if (parameter_type
!= null)
257 TypeExpr texpr
= TypeName
.ResolveAsTypeTerminal (ec
, false);
261 parameter_type
= texpr
.ResolveType (ec
);
263 if (parameter_type
.IsAbstract
&& parameter_type
.IsSealed
) {
264 Report
.Error (721, Location
, "`{0}': static types cannot be used as parameters", GetSignatureForError ());
268 if (parameter_type
== TypeManager
.void_type
){
269 Report
.Error (1536, Location
, "Invalid parameter type 'void'");
273 if ((ModFlags
& Parameter
.Modifier
.ISBYREF
) != 0){
274 if (parameter_type
== TypeManager
.typed_reference_type
||
275 parameter_type
== TypeManager
.arg_iterator_type
){
276 Report
.Error (1601, Location
, "Method or delegate parameter cannot be of type `{0}'",
277 GetSignatureForError ());
285 public Type
ExternalType ()
287 if ((ModFlags
& Parameter
.Modifier
.ISBYREF
) != 0)
288 return TypeManager
.GetReferenceType (parameter_type
);
290 return parameter_type
;
293 public Type ParameterType
{
295 return parameter_type
;
299 public ParameterAttributes Attributes
{
303 return ParameterAttributes
.None
;
305 return ParameterAttributes
.None
;
307 return ParameterAttributes
.Out
;
308 case Modifier
.PARAMS
:
312 return ParameterAttributes
.None
;
316 public override AttributeTargets AttributeTargets
{
318 return AttributeTargets
.Parameter
;
322 public virtual string GetSignatureForError ()
325 if (parameter_type
!= null)
326 type_name
= TypeManager
.CSharpName (parameter_type
);
328 type_name
= TypeName
.GetSignatureForError ();
330 string mod
= GetModifierSignature (ModFlags
);
332 return String
.Concat (mod
, ' ', type_name
);
337 public static string GetModifierSignature (Modifier mod
)
342 case Modifier
.PARAMS
:
346 case Modifier
.ARGLIST
:
353 public void IsClsCompliant ()
355 if (AttributeTester
.IsClsCompliant (ExternalType ()))
358 Report
.Error (3001, Location
, "Argument type `{0}' is not CLS-compliant", GetSignatureForError ());
361 public virtual void ApplyAttributes (EmitContext ec
, MethodBuilder mb
, ConstructorBuilder cb
, int index
)
364 builder
= cb
.DefineParameter (index
, Attributes
, Name
);
366 builder
= mb
.DefineParameter (index
, Attributes
, Name
);
368 if (OptAttributes
!= null)
369 OptAttributes
.Emit (ec
, this);
372 public override string[] ValidAttributeTargets
{
374 return attribute_targets
;
380 /// Represents the methods parameters
382 public class Parameters
: ParameterData
{
383 // Null object pattern
384 public Parameter
[] FixedParameters
;
385 public readonly bool HasArglist
;
389 public static readonly Parameters EmptyReadOnlyParameters
= new Parameters ();
390 static readonly Parameter ArgList
= new ArglistParameter ();
392 private Parameters ()
394 FixedParameters
= new Parameter
[0];
395 types
= new Type
[0];
398 public Parameters (Parameter
[] parameters
)
400 if (parameters
== null)
401 throw new ArgumentException ("Use EmptyReadOnlyPatameters");
403 FixedParameters
= parameters
;
404 count
= parameters
.Length
;
407 public Parameters (Parameter
[] parameters
, bool has_arglist
):
410 HasArglist
= has_arglist
;
421 return HasArglist
? count
+ 1 : count
;
430 for (int i
= 0; i
< count
; i
++){
431 string base_name
= FixedParameters
[i
].Name
;
432 for (int j
= i
+ 1; j
< count
; j
++){
433 if (base_name
!= FixedParameters
[j
].Name
)
436 Report
.Error (100, FixedParameters
[i
].Location
,
437 "The parameter name `{0}' is a duplicate", base_name
);
446 /// Returns the paramenter information based on the name
448 public Parameter
GetParameterByName (string name
, out int idx
)
457 foreach (Parameter par
in FixedParameters
){
458 if (par
.Name
== name
){
467 public Parameter
GetParameterByName (string name
)
471 return GetParameterByName (name
, out idx
);
474 public bool Resolve (EmitContext ec
)
479 types
= new Type
[count
];
481 if (ec
!= null && !VerifyArgs ()){
487 for (int i
= 0; i
< FixedParameters
.Length
; ++i
) {
488 p
= FixedParameters
[i
];
489 if (!p
.Resolve (ec
)) {
493 types
[i
] = p
.ExternalType ();
499 public CallingConventions CallingConvention
503 return CallingConventions
.VarArgs
;
505 return CallingConventions
.Standard
;
509 // Define each type attribute (in/out/ref) and
510 // the argument names.
511 public void ApplyAttributes (EmitContext ec
, MethodBase builder
)
516 MethodBuilder mb
= builder
as MethodBuilder
;
517 ConstructorBuilder cb
= builder
as ConstructorBuilder
;
519 for (int i
= 0; i
< FixedParameters
.Length
; i
++) {
520 FixedParameters
[i
].ApplyAttributes (ec
, mb
, cb
, i
+ 1);
524 public void VerifyClsCompliance ()
526 foreach (Parameter p
in FixedParameters
)
530 public string GetSignatureForError ()
532 StringBuilder sb
= new StringBuilder ("(");
534 for (int i
= 0; i
< FixedParameters
.Length
; ++i
) {
535 sb
.Append (FixedParameters
[i
].GetSignatureForError ());
536 if (i
< FixedParameters
.Length
- 1)
545 sb
.Append ("__arglist");
550 return sb
.ToString ();
553 public Type
[] Types
{
559 Parameter
this [int pos
]
562 if (pos
>= count
&& (HasArglist
|| HasParams
)) {
563 if (HasArglist
&& (pos
== 0 || pos
>= count
))
568 return FixedParameters
[pos
];
572 #region ParameterData Members
574 public Type
ParameterType (int pos
)
576 return this [pos
].ExternalType ();
579 public bool HasParams
{
584 return FixedParameters
[count
- 1] is ParamsParameter
;
588 public string ParameterName (int pos
)
590 return this [pos
].Name
;
593 public string ParameterDesc (int pos
)
595 return this [pos
].GetSignatureForError ();
598 public Parameter
.Modifier
ParameterModifier (int pos
)
600 return this [pos
].ModFlags
;