**** Merged from MCS ****
[mono.git] / mcs / gmcs / parameter.cs
index a04a70482779a3bbd01d47bb14c347422fc97cbd..7bfc3d51560cc304e6c6df9e766c51712e71a309 100755 (executable)
@@ -17,44 +17,111 @@ using System.Collections;
 namespace Mono.CSharp {
 
        /// <summary>
-       ///   Base class for parameters of a method.  Can also be
-       ///   used to directly represent the return type of a method
+       ///   Abstract Base class for parameters of a method.
        /// </summary>
-       public class ParameterBase : Attributable {
+       public abstract class ParameterBase : Attributable {
+
+               protected ParameterBuilder builder;
+
                public ParameterBase (Attributes attrs)
                        : base (attrs)
                {
                }
 
-               public override void ApplyAttributeBuilder (object builder, Attribute a, CustomAttributeBuilder cb)
+               public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
                {
-                       ParameterBuilder pb = builder as ParameterBuilder;
-
                        if (a.Type == TypeManager.marshal_as_attr_type) {
                                UnmanagedMarshal marshal = a.GetMarshal ();
-                               if (marshal == null)
-                                       Report.Warning (-24, a.Location,
-                                                       "The Microsoft Runtime cannot set this marshal info. " +
-                                                       "Please use the Mono runtime instead.");
-                               else 
-                                       pb.SetMarshal (marshal);
-                       }
-                       else { 
-                               try {
-                                       pb.SetCustomAttribute (cb);
-                               } catch (System.ArgumentException) {
-                                       Report.Warning (-24, a.Location,
-                                                       "The Microsoft Runtime cannot set attributes \n" +
-                                                       "on the return type of a method. Please use the \n" +
-                                                       "Mono runtime instead.");
+                               if (marshal != null) {
+                                       builder.SetMarshal (marshal);
+                                       return;
+                       }
+                               Report.Warning_T (-24, a.Location);
+                               return;
+                       }
+
+                       builder.SetCustomAttribute (cb);
+               }
+
+               public override bool IsClsCompliaceRequired(DeclSpace ds)
+               {
+                       return false;
                                }
+       }
+
+       /// <summary>
+       /// Class for applying custom attributes on the return type
+       /// </summary>
+       public class ReturnParameter: ParameterBase {
+               public ReturnParameter (MethodBuilder mb, Location location):
+                       base (null)
+               {
+                       try {
+                               builder = mb.DefineParameter (0, ParameterAttributes.None, "");                 
+                       }
+                       catch (ArgumentOutOfRangeException) {
+                               Report.Warning_T (-28, location);
+                       }
+               }
+
+               public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
+               {
+                       // This occurs after Warning -28
+                       if (builder == null)
+                               return;
+
+                       base.ApplyAttributeBuilder (a, cb);
+               }
+
+               public override AttributeTargets AttributeTargets {
+                       get {
+                               return AttributeTargets.ReturnValue;
+                       }
+               }
+
+               /// <summary>
+               /// Is never called
+               /// </summary>
+               protected override string[] ValidAttributeTargets {
+                       get {
+                               return null;
+                       }
+               }
+       }
+
+       /// <summary>
+       /// Class for applying custom attributes on the implicit parameter type
+       /// of the 'set' method in properties, and the 'add' and 'remove' methods in events.
+       /// </summary>
+       public class ImplicitParameter: ParameterBase {
+               public ImplicitParameter (MethodBuilder mb):
+                       base (null)
+               {
+                       builder = mb.DefineParameter (1, ParameterAttributes.None, "");                 
+               }
+
+               public override AttributeTargets AttributeTargets {
+                       get {
+                               return AttributeTargets.Parameter;
                        }
                }
+
+               /// <summary>
+               /// Is never called
+               /// </summary>
+               protected override string[] ValidAttributeTargets {
+                       get {
+                               return null;
+                       }
        }
+       }
+
 
        /// <summary>
        ///   Represents a single method parameter
        /// </summary>
+
+       //TODO: Add location member to this or base class for better error location and all methods simplification.
        public class Parameter : ParameterBase {
                [Flags]
                public enum Modifier : byte {
@@ -66,6 +133,8 @@ namespace Mono.CSharp {
                        ISBYREF = 8
                }
 
+               static string[] attribute_targets = new string [] { "param" };
+
                public readonly Expression TypeName;
                public readonly Modifier ModFlags;
                public readonly string Name;
@@ -150,6 +219,12 @@ namespace Mono.CSharp {
                        }
                }
                
+               public override AttributeTargets AttributeTargets {
+                       get {
+                               return AttributeTargets.Parameter;
+                       }
+               }
+
                /// <summary>
                ///   Returns the signature for this parameter evaluating it on the
                ///   @tc context
@@ -177,6 +252,31 @@ namespace Mono.CSharp {
                        }
                        return typeName;
                }
+
+               public void DefineParameter (EmitContext ec, MethodBuilder mb, ConstructorBuilder cb, int index, Location loc)
+               {
+                       ParameterAttributes par_attr = Attributes;
+                                       
+                       if (mb == null)
+                               builder = cb.DefineParameter (index, par_attr, Name);
+                       else 
+                               builder = mb.DefineParameter (index, par_attr, Name);
+                                       
+                       if (OptAttributes != null) {
+                               OptAttributes.Emit (ec, this);
+       
+                               if (par_attr == ParameterAttributes.Out){
+                                       if (OptAttributes.Contains (TypeManager.in_attribute_type, ec))
+                                               Report.Error (36, loc,  "Can not use [In] attribute on out parameter");
+                               }
+                       }
+               }
+
+               protected override string[] ValidAttributeTargets {
+                       get {
+                               return attribute_targets;
+                       }
+               }
        }
 
        /// <summary>
@@ -480,8 +580,47 @@ namespace Mono.CSharp {
                        // For now this is the only correc thing to do
                        return CallingConventions.Standard;
                }
+
+               //
+               // The method's attributes are passed in because we need to extract
+               // the "return:" attribute from there to apply on the return type
+               //
+               public void LabelParameters (EmitContext ec,
+                       MethodBase builder,
+                       Location loc) {
+                       //
+                       // Define each type attribute (in/out/ref) and
+                       // the argument names.
+                       //
+                       int i = 0;
+                       
+                       MethodBuilder mb = builder as MethodBuilder;
+                       ConstructorBuilder cb = builder as ConstructorBuilder;
+
+                       if (FixedParameters != null) {
+                               for (i = 0; i < FixedParameters.Length; i++) {
+                                       FixedParameters [i].DefineParameter (ec, mb, cb, i + 1, loc);
+                               }
+                       }
+
+                       if (ArrayParameter != null){
+                               ParameterBuilder pb;
+                               Parameter array_param = ArrayParameter;
+
+                               if (mb == null)
+                                       pb = cb.DefineParameter (
+                                               i + 1, array_param.Attributes,
+                                               array_param.Name);
+                               else
+                                       pb = mb.DefineParameter (
+                                               i + 1, array_param.Attributes,
+                                               array_param.Name);
+                                       
+                               CustomAttributeBuilder a = new CustomAttributeBuilder (
+                                       TypeManager.cons_param_array_attribute, new object [0]);
+                               
+                               pb.SetCustomAttribute (a);
+                       }
+               }
        }
 }
-               
-       
-