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;