* ILTokenizer.cs: Handle comments first, handle whitespace in hex
[mono.git] / mcs / mcs / delegate.cs
index 8923d32a0c417eea933f30a8c549adff6f469f43..a829c61e27532494fbdbdf9f075a3ac0dc8a4ced 100644 (file)
@@ -33,9 +33,12 @@ namespace Mono.CSharp {
                
                Type [] param_types;
                Type ret_type;
+
+               static string[] attribute_targets = new string [] { "type", "return" };
                
                Expression instance_expr;
                MethodBase delegate_method;
+               ReturnParameter return_attributes;
        
                const int AllowedModifiers =
                        Modifiers.NEW |
@@ -55,7 +58,21 @@ namespace Mono.CSharp {
                        ModFlags        = Modifiers.Check (AllowedModifiers, mod_flags,
                                                           IsTopLevel ? Modifiers.INTERNAL :
                                                           Modifiers.PRIVATE, l);
-                       Parameters      = param_list;\r          }
+                       Parameters      = param_list;
+               }
+
+               public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
+               {
+                       if (a.Target == "return") {
+                               if (return_attributes == null)
+                                       return_attributes = new ReturnParameter (InvokeBuilder, Location);
+
+                               return_attributes.ApplyAttributeBuilder (a, cb);
+                               return;
+                       }
+
+                       base.ApplyAttributeBuilder (a, cb);
+               }
 
                public override TypeBuilder DefineType ()
                {
@@ -95,8 +112,6 @@ namespace Mono.CSharp {
                {
                        MethodAttributes mattr;
                        int i;
-                       ParameterBuilder pb;
-                       Attributes cattr;
                        EmitContext ec = new EmitContext (this, this, Location, null,
                                                          null, ModFlags, false);
 
@@ -208,10 +223,7 @@ namespace Mono.CSharp {
                                
                                for (; i < top; i++) {
                                        p = Parameters.FixedParameters [i];
-                                       pb = InvokeBuilder.DefineParameter (i+1, p.Attributes, p.Name);
-                                       cattr = p.OptAttributes;
-                                       if (cattr != null)
-                                               Attribute.ApplyAttributes (ec, pb, pb, cattr);
+                                       p.DefineParameter (ec, InvokeBuilder, null, i + 1, Location);
 
                                        if ((p.ModFlags & Parameter.Modifier.ISBYREF) != 0)
                                                out_params++;
@@ -219,12 +231,7 @@ namespace Mono.CSharp {
                        }
                        if (Parameters.ArrayParameter != null){
                                Parameter p = Parameters.ArrayParameter;
-                               
-                               pb = InvokeBuilder.DefineParameter (
-                                       i+1, p.Attributes, p.Name);
-                               cattr = p.OptAttributes;
-                               if (cattr != null)
-                                       Attribute.ApplyAttributes (ec, pb, pb, cattr);
+                               p.DefineParameter (ec, InvokeBuilder, null, i + 1, Location);
                        }
                        
                        InvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
@@ -261,19 +268,13 @@ namespace Mono.CSharp {
                                for (i = 0 ; i < top; i++) {
                                        p = Parameters.FixedParameters [i];
 
-                                       pb = BeginInvokeBuilder.DefineParameter (i+1, p.Attributes, p.Name);
-                                       cattr = p.OptAttributes;
-                                       if (cattr != null)
-                                               Attribute.ApplyAttributes (ec, pb, pb, cattr);
+                                       p.DefineParameter (ec, BeginInvokeBuilder, null, i + 1, Location);
                                }
                        }
                        if (Parameters.ArrayParameter != null){
                                Parameter p = Parameters.ArrayParameter;
-                               
-                               pb = BeginInvokeBuilder.DefineParameter (i+1, p.Attributes, p.Name);
-                               cattr = p.OptAttributes;
-                               if (cattr != null)
-                                       Attribute.ApplyAttributes (ec, pb, pb, cattr);
+                               p.DefineParameter (ec, BeginInvokeBuilder, null, i + 1, Location);
+
                                i++;
                        }
 
@@ -358,12 +359,19 @@ namespace Mono.CSharp {
                {
                        if (OptAttributes != null) {
                                EmitContext ec = new EmitContext (tc, this, Location, null, null, ModFlags, false);
-                               Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes);
+                               Parameters.LabelParameters (ec, InvokeBuilder, Location);
+                               OptAttributes.Emit (ec, this);
                        }
 
                        base.Emit (tc);
                }
 
+               protected override string[] ValidAttributeTargets {
+                       get {
+                               return attribute_targets;
+                       }
+               }
+
                //TODO: duplicate
                protected override bool VerifyClsCompliance (DeclSpace ds)
                {
@@ -451,18 +459,37 @@ namespace Mono.CSharp {
 
                        int pd_count = pd.Count;
 
-                       bool not_params_method = (pd_count == 0) ||
-                               (pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS);
+                       bool params_method = (pd_count != 0) &&
+                               (pd.ParameterModifier (pd_count - 1) == Parameter.Modifier.PARAMS);
 
-                       if (not_params_method && pd_count != arg_count) {
+                       if (!params_method && pd_count != arg_count) {
                                Report.Error (1593, loc,
                                              "Delegate '" + delegate_type.ToString ()
                                              + "' does not take '" + arg_count + "' arguments");
                                return false;
                        }
 
-                       return Invocation.VerifyArgumentsCompat (ec, args, arg_count, mb, !not_params_method,
-                                                                delegate_type, loc);
+                       //
+                       // Consider the case:
+                       //   delegate void FOO(param object[] args);
+                       //   FOO f = new FOO(...);
+                       //   f(new object[] {1, 2, 3});
+                       //
+                       // This should be treated like f(1,2,3).  This is done by ignoring the 
+                       // 'param' modifier for that invocation.  If that fails, then the
+                       // 'param' modifier is considered.
+                       //
+                       // One issue is that 'VerifyArgumentsCompat' modifies the elements of
+                       // the 'args' array.  However, the modifications appear idempotent.
+                       // Normal 'Invocation's also have the same behaviour, implicitly.
+                       //
+
+                       bool ans = false;
+                       if (arg_count == pd_count)
+                               ans = Invocation.VerifyArgumentsCompat (ec, args, arg_count, mb, false, delegate_type, loc);
+                       if (!ans && params_method)
+                               ans = Invocation.VerifyArgumentsCompat (ec, args, arg_count, mb, true,  delegate_type, loc);
+                       return ans;
                }
                
                /// <summary>
@@ -594,7 +621,21 @@ namespace Mono.CSharp {
                                return param_types;
                        }
                }
-               
+
+               public override AttributeTargets AttributeTargets {
+                       get {
+                               return AttributeTargets.Delegate | AttributeTargets.ReturnValue;
+                       }
+               }
+
+               protected override void VerifyObsoleteAttribute()
+               {
+                       CheckUsageOfObsoleteAttribute (ret_type);
+
+                       foreach (Type type in param_types) {
+                               CheckUsageOfObsoleteAttribute (type);
+                       }
+               }
        }
 
        //