2004-05-24 Anders Carlsson <andersca@gnome.org>
[mono.git] / mcs / mcs / class.cs
index c013bfad7392c988b6c6803f8db8fc9aa6313807..151d912828b85c9e803522cc6ec660def725f224 100755 (executable)
@@ -111,6 +111,7 @@ namespace Mono.CSharp {
                // from classes from the arraylist `type_bases' 
                //
                string     base_class_name;
+               public Type base_classs_type;
 
                ArrayList type_bases;
 
@@ -427,7 +428,7 @@ namespace Mono.CSharp {
                        }
                        
                        base.ApplyAttributeBuilder (a, cb);
-                       
+               } 
 
                public override AttributeTargets AttributeTargets {
                        get {
@@ -817,11 +818,8 @@ namespace Mono.CSharp {
 
                        TypeAttributes type_attributes = TypeAttr;
 
-                       Type ptype;
                        if (parent != null)
-                               ptype = parent.ResolveType (ec);
-                       else
-                               ptype = null;
+                               base_classs_type = parent.ResolveType (ec);
 
                        if (IsTopLevel){
                                if (TypeManager.NamespaceClash (Name, Location)) {
@@ -831,14 +829,15 @@ namespace Mono.CSharp {
                                
                                ModuleBuilder builder = CodeGen.Module.Builder;
                                TypeBuilder = builder.DefineType (
-                                       Name, type_attributes, ptype, null);
+                                       Name, type_attributes, base_classs_type, null);
+                               
                        } else {
                                TypeBuilder builder = Parent.DefineType ();
                                if (builder == null)
                                        return null;
                                
                                TypeBuilder = builder.DefineNestedType (
-                                       Basename, type_attributes, ptype, null);
+                                       Basename, type_attributes, base_classs_type, null);
                        }
                                
                        //
@@ -1001,12 +1000,6 @@ namespace Mono.CSharp {
 
                        // Invariant maintained by AddIndexer(): All explicit interface indexers precede normal indexers
                        bool seen_normal_indexers = false;
-                       foreach (Indexer i in Indexers) {
-                               if (i.ExplicitInterfaceName == null)
-                                       seen_normal_indexers = true;
-                               else if (seen_normal_indexers)
-                                       throw new Exception ("Internal Error: 'Indexers' array not sorted properly.");
-                       }
 
                        foreach (Indexer i in Indexers) {
                                string name;
@@ -1015,20 +1008,19 @@ namespace Mono.CSharp {
 
                                name = i.IndexerName;
 
-                               if (i.InterfaceType != null)
+                               if (i.InterfaceType != null) {
+                                       if (seen_normal_indexers)
+                                               throw new Exception ("Internal Error: 'Indexers' array not sorted properly.");
                                        continue;
+                               }
+
+                               seen_normal_indexers = true;
 
-                               if (class_indexer_name == null){
+                               if (class_indexer_name == null)
                                        class_indexer_name = name;
-                                       continue;
-                               }
-                               
-                               if (name == class_indexer_name)
-                                       continue;
-                               
-                               Report.Error (
-                                       668, "Two indexers have different names, " +
-                                       " you should use the same name for all your indexers");
+                               else if (name != class_indexer_name)
+                                       Report.Error (668, "Two indexers have different names, " +
+                                                     " you should use the same name for all your indexers");
                        }
 
                        if (seen_normal_indexers && class_indexer_name == null)
@@ -1729,7 +1721,7 @@ namespace Mono.CSharp {
                        return;
                }
 
-               protected virtual void VerifyMembers ()
+               protected virtual void VerifyMembers (EmitContext ec)
                {
                        //
                        // Check for internal or private fields that were never assigned
@@ -1846,7 +1838,7 @@ namespace Mono.CSharp {
                                if (Pending.VerifyPendingMethods ())
                                        return;
 
-                       VerifyMembers ();
+                       VerifyMembers (ec);
                        
 //                     if (types != null)
 //                             foreach (TypeContainer tc in types)
@@ -2329,7 +2321,7 @@ namespace Mono.CSharp {
                {
                }
 
-               protected override void VerifyMembers () 
+               protected override void VerifyMembers (EmitContext ec
                {
                        if (Fields != null) {
                                foreach (Field f in Fields) {
@@ -2337,7 +2329,7 @@ namespace Mono.CSharp {
                                                continue;
                                        if (hasExplicitLayout) {
                                                if (f.OptAttributes == null 
-                                                   || !f.OptAttributes.Contains (TypeManager.field_offset_attribute_type, this)) {
+                                                   || !f.OptAttributes.Contains (TypeManager.field_offset_attribute_type, ec)) {
                                                        Report.Error (625, f.Location,
                                                                      "Instance field of type marked with" 
                                                                      + " StructLayout(LayoutKind.Explicit) must have a"
@@ -2346,7 +2338,7 @@ namespace Mono.CSharp {
                                        }
                                        else {
                                                if (f.OptAttributes != null 
-                                                   && f.OptAttributes.Contains (TypeManager.field_offset_attribute_type, this)) {
+                                                   && f.OptAttributes.Contains (TypeManager.field_offset_attribute_type, ec)) {
                                                        Report.Error (636, f.Location,
                                                                      "The FieldOffset attribute can only be placed on members of "
                                                                      + "types marked with the StructLayout(LayoutKind.Explicit)");
@@ -2354,7 +2346,7 @@ namespace Mono.CSharp {
                                        }
                                }
                        }
-                       base.VerifyMembers ();
+                       base.VerifyMembers (ec);
                }
 
                public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
@@ -2544,6 +2536,8 @@ namespace Mono.CSharp {
                // Whether this is an operator method.
                public bool IsOperator;
 
+               static string[] attribute_targets = new string [] { "method", "return" };
+
                public MethodCore (DeclSpace ds, Expression type, int mod, int allowed_mod,
                                   bool is_interface, string name, Attributes attrs,
                                   Parameters parameters, Location loc)
@@ -2600,6 +2594,12 @@ namespace Mono.CSharp {
                        return true;
                }
 
+               protected override string[] ValidAttributeTargets {
+                       get {
+                               return attribute_targets;
+                       }
+               }
+
                protected override bool VerifyClsCompliance (DeclSpace ds)
                {
                        if (!base.VerifyClsCompliance (ds)) {
@@ -2671,6 +2671,7 @@ namespace Mono.CSharp {
        public class Method : MethodCore, IIteratorContainer, IMethodData {
                public MethodBuilder MethodBuilder;
                public MethodData MethodData;
+               ReturnParameter return_attributes;
 
                /// <summary>
                ///   Modifiers allowed in a class declaration
@@ -2766,6 +2767,14 @@ namespace Mono.CSharp {
 
                public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
                {
+                       if (a.Target == "return") {
+                               if (return_attributes == null)
+                                       return_attributes = new ReturnParameter (MethodBuilder, Location);
+
+                               return_attributes.ApplyAttributeBuilder (a, cb);
+                               return;
+                       }
+
                        if (a.Type == TypeManager.methodimpl_attr_type && a.IsInternalCall) {
                                MethodBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall | MethodImplAttributes.Runtime);
                        }
@@ -2976,12 +2985,16 @@ namespace Mono.CSharp {
                        return new EmitContext (tc, ds, Location, ig, ReturnType, ModFlags, false);
                }
 
+               public ObsoleteAttribute GetObsoleteAttribute ()
+               {
+                       return GetObsoleteAttribute (ds);
+               }
                #endregion
        }
 
        public abstract class ConstructorInitializer {
                ArrayList argument_list;
-               ConstructorInfo parent_constructor;
+               protected ConstructorInfo parent_constructor;
                Parameters parameters;
                Location loc;
                
@@ -3076,6 +3089,49 @@ namespace Mono.CSharp {
                                        Invocation.EmitCall (ec, true, false, ec.GetThis (loc), parent_constructor, argument_list, loc);
                        }
                }
+
+               /// <summary>
+               /// Method search for base ctor. (We do not cache it).
+               /// </summary>
+               Constructor GetOverloadedConstructor (TypeContainer tc)
+               {
+                       if (tc.InstanceConstructors == null)
+                               return null;
+
+                       foreach (Constructor c in tc.InstanceConstructors) {
+                               if (Arguments == null) {
+                                       if (c.ParameterTypes.Length == 0)
+                                               return c;
+
+                                       continue;
+                               }
+
+                               if (c.ParameterTypes.Length != Arguments.Count)
+                                       continue;
+
+                               for (int i = 0; i < Arguments.Count; ++i)
+                                       if (c.ParameterTypes [i] != ((Argument)Arguments [i]).Type)
+                                               continue;
+
+                               return c;
+                       }
+
+                       throw new InternalErrorException ();
+               }
+
+               //TODO: implement caching when it will be necessary
+               public virtual void CheckObsoleteAttribute (TypeContainer tc, Location loc)
+               {
+                       Constructor ctor = GetOverloadedConstructor (tc);
+                       if (ctor == null)
+                               return;
+
+                       ObsoleteAttribute oa = ctor.GetObsoleteAttribute (tc);
+                       if (oa == null)
+                               return;
+
+                       AttributeTester.Report_ObsoleteMessage (oa, ctor.GetSignatureForError (), loc);
+               }
        }
 
        public class ConstructorBaseInitializer : ConstructorInitializer {
@@ -3083,6 +3139,24 @@ namespace Mono.CSharp {
                        base (argument_list, pars, l)
                {
                }
+
+               public override void CheckObsoleteAttribute(TypeContainer tc, Location loc) {
+                       if (parent_constructor == null)
+                               return;
+
+                       TypeContainer type_ds = TypeManager.LookupTypeContainer (tc.base_classs_type);
+                       if (type_ds == null) {
+                               ObsoleteAttribute oa = AttributeTester.GetMemberObsoleteAttribute (parent_constructor);
+
+                               if (oa != null)
+                                       AttributeTester.Report_ObsoleteMessage (oa, TypeManager.CSharpSignature (parent_constructor), loc);
+
+                               return;
+                       }
+
+                       base.CheckObsoleteAttribute (type_ds, loc);
+               }
+
        }
 
        public class ConstructorThisInitializer : ConstructorInitializer {
@@ -3283,8 +3357,7 @@ namespace Mono.CSharp {
                                ec.IsStatic = false;
                        }
 
-                       Parameters.LabelParameters (ec, ConstructorBuilder,
-                                                    OptAttributes, Location);
+                       Parameters.LabelParameters (ec, ConstructorBuilder, Location);
                        
                        SymbolWriter sw = CodeGen.SymbolWriter;
                        bool generate_debugging = false;
@@ -3312,8 +3385,10 @@ namespace Mono.CSharp {
                                                container.EmitFieldInitializers (ec);
                                }
                        }
-                       if (Initializer != null)
+                       if (Initializer != null) {
+                               Initializer.CheckObsoleteAttribute (container, Location);
                                Initializer.Emit (ec);
+                       }
                        
                        if ((ModFlags & Modifiers.STATIC) != 0)
                                container.EmitFieldInitializers (ec);
@@ -3419,6 +3494,7 @@ namespace Mono.CSharp {
                Block Block { get; }
 
                EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig);
+               ObsoleteAttribute GetObsoleteAttribute ();
        }
 
        //
@@ -3474,34 +3550,25 @@ namespace Mono.CSharp {
                // Attributes.
                //
                Attribute dllimport_attribute = null;
-               string obsolete = null;
-               bool obsolete_error = false;
 
-               public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method, DeclSpace ds)
+               public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method,
+                                                    EmitContext ec)
                {
-                       if ((opt_attrs == null) || (opt_attrs.AttributeSections == null))
+                       if ((opt_attrs == null) || (opt_attrs.Attrs == null))
                                return true;
 
-                       foreach (AttributeSection asec in opt_attrs.AttributeSections) {
-                               if (asec.Attributes == null)
-                                       continue;
-                                       
-                               foreach (Attribute a in asec.Attributes) {
-                                       Type attr_type = a.ResolveType (ds, true);
-                                       if (attr_type == TypeManager.conditional_attribute_type) {
-                                               if (!ApplyConditionalAttribute (a))
-                                                       return false;
-                                       } else if (attr_type == TypeManager.obsolete_attribute_type) {
-                                               if (!ApplyObsoleteAttribute (a))
-                                                       return false;
-                                       } else if (attr_type == TypeManager.dllimport_type) {
-                                               if (!is_method) {
-                                                       Attribute.Error_AttributeNotValidForElement (a, method.Location);
-                                                       return false;
-                                               }
-                                               if (!ApplyDllImportAttribute (a))
-                                                       return false;
+                       foreach (Attribute a in opt_attrs.Attrs) {
+                               Type attr_type = a.ResolveType (ec, true);
+                               if (attr_type == TypeManager.conditional_attribute_type) {
+                                       if (!ApplyConditionalAttribute (a))
+                                               return false;
+                               } else if (attr_type == TypeManager.dllimport_type) {
+                                       if (!is_method) {
+                                               Attribute.Error_AttributeNotValidForElement (a, method.Location);
+                                               return false;
                                        }
+                                       if (!ApplyDllImportAttribute (a))
+                                               return false;
                                }
                        }
 
@@ -3526,20 +3593,6 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               //
-               // Applies the `Obsolete' attribute to the method.
-               //
-               protected virtual bool ApplyObsoleteAttribute (Attribute a)
-               {
-                       if (obsolete != null) {
-                               Report.Error (579, method.Location, "Duplicate `Obsolete' attribute");
-                               return false;
-                       }
-
-                       obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
-                       return obsolete != null;
-               }
-
                //
                // Applies the `Conditional' attribute to the method.
                //
@@ -3636,18 +3689,6 @@ namespace Mono.CSharp {
                {
                        TypeManager.MethodFlags flags = 0;
 
-                       if (obsolete != null) {
-                               if (obsolete_error) {
-                                       Report.Error (619, loc, "Method `" + member.Name +
-                                                     "' is obsolete: `" + obsolete + "'");
-                                       return TypeManager.MethodFlags.IsObsoleteError;
-                               } else
-                                       Report.Warning (618, loc, "Method `" + member.Name +
-                                                       "' is obsolete: `" + obsolete + "'");
-
-                               flags |= TypeManager.MethodFlags.IsObsolete;
-                       }
-
                        if (ShouldIgnore (loc))
                                flags |= TypeManager.MethodFlags.ShouldIgnore;
 
@@ -3659,8 +3700,10 @@ namespace Mono.CSharp {
                        MethodInfo implementing = null;
                        string prefix;
 
+                       EmitContext ec = method.CreateEmitContext (container, null);
+                               
                        if (method.OptAttributes != null)
-                               if (!ApplyAttributes (method.OptAttributes, is_method, container))
+                               if (!ApplyAttributes (method.OptAttributes, is_method, ec))
                                        return false;
 
                        if (member.IsExplicitImpl)
@@ -3770,8 +3813,6 @@ namespace Mono.CSharp {
                                        return false;
                                }
                                
-                               EmitContext ec = method.CreateEmitContext (container, null);
-                               
                                builder = dllimport_attribute.DefinePInvokeMethod (
                                        ec, container.TypeBuilder, method_name, flags,
                                        method.ReturnType, ParameterTypes);
@@ -3815,6 +3856,7 @@ namespace Mono.CSharp {
                        }
 
                        TypeManager.AddMethod (builder, this);
+                       TypeManager.AddMethod2 (builder, method);
 
                        return true;
                }
@@ -3834,11 +3876,11 @@ namespace Mono.CSharp {
                        Location loc = method.Location;
                        Attributes OptAttributes = method.OptAttributes;
 
-                       if (OptAttributes != null) 
+                       if (OptAttributes != null)
                                OptAttributes.Emit (ec, kind);
 
                        if (member is MethodCore)
-                               ((MethodCore) member).Parameters.LabelParameters (ec, MethodBuilder,OptAttributes, loc);
+                               ((MethodCore) member).Parameters.LabelParameters (ec, MethodBuilder, loc);
 
                        SymbolWriter sw = CodeGen.SymbolWriter;
                        Block block = method.Block;
@@ -4356,6 +4398,8 @@ namespace Mono.CSharp {
                [Flags]
                public enum Status : byte { ASSIGNED = 1, USED = 2 }
 
+               static string[] attribute_targets = new string [] { "field" };
+
                //
                // The constructor is only exposed to our children
                //
@@ -4445,6 +4489,12 @@ namespace Mono.CSharp {
                        return TypeManager.GetFullNameSignature (FieldBuilder);
                }
 
+               protected override string[] ValidAttributeTargets {
+                       get {
+                               return attribute_targets;
+                       }
+               }
+
                protected override bool VerifyClsCompliance (DeclSpace ds)
                {
                        if (!base.VerifyClsCompliance (ds))
@@ -4493,22 +4543,22 @@ namespace Mono.CSharp {
 
                public override bool Define (TypeContainer container)
                {
-                       Type t = container.ResolveType (Type, false, Location);
+                       MemberType = container.ResolveType (Type, false, Location);
                        
-                       if (t == null)
+                       if (MemberType == null)
                                return false;
 
                        CheckBase (container);
                        
-                       if (!container.AsAccessible (t, ModFlags)) {
+                       if (!container.AsAccessible (MemberType, ModFlags)) {
                                Report.Error (52, Location,
                                              "Inconsistent accessibility: field type `" +
-                                             TypeManager.CSharpName (t) + "' is less " +
+                                             TypeManager.CSharpName (MemberType) + "' is less " +
                                              "accessible than field `" + Name + "'");
                                return false;
                        }
 
-                       if (t.IsPointer && !UnsafeOK (container))
+                       if (MemberType.IsPointer && !UnsafeOK (container))
                                return false;
                        
                        if (RootContext.WarningLevel > 1){
@@ -4525,11 +4575,11 @@ namespace Mono.CSharp {
                        }
 
                        if ((ModFlags & Modifiers.VOLATILE) != 0){
-                               if (!t.IsClass){
-                                       Type vt = t;
+                               if (!MemberType.IsClass){
+                                       Type vt = MemberType;
                                        
                                        if (TypeManager.IsEnumType (vt))
-                                               vt = TypeManager.EnumToUnderlying (t);
+                                               vt = TypeManager.EnumToUnderlying (MemberType);
 
                                        if (!((vt == TypeManager.bool_type) ||
                                              (vt == TypeManager.sbyte_type) ||
@@ -4561,8 +4611,8 @@ namespace Mono.CSharp {
 
                        if (container is Struct && 
                            ((fa & FieldAttributes.Static) == 0) &&
-                           t == container.TypeBuilder &&
-                           !TypeManager.IsBuiltinType (t)){
+                           MemberType == container.TypeBuilder &&
+                           !TypeManager.IsBuiltinType (MemberType)){
                                Report.Error (523, Location, "Struct member `" + container.Name + "." + Name + 
                                              "' causes a cycle in the structure layout");
                                return false;
@@ -4570,7 +4620,7 @@ namespace Mono.CSharp {
 
                        try {
                                FieldBuilder = container.TypeBuilder.DefineField (
-                                       Name, t, Modifiers.FieldAttr (ModFlags));
+                                       Name, MemberType, Modifiers.FieldAttr (ModFlags));
 
                                TypeManager.RegisterFieldBase (FieldBuilder, this);
                        }
@@ -4618,6 +4668,8 @@ namespace Mono.CSharp {
 
                public class GetMethod: PropertyMethod
                {
+                       static string[] attribute_targets = new string [] { "method", "return" };
+
                        public GetMethod (MethodCore method, Accessor accessor):
                                base (method, accessor)
                        {
@@ -4644,14 +4696,37 @@ namespace Mono.CSharp {
                                        return method.MemberType;
                                }
                        }
+
+                       protected override string[] ValidAttributeTargets {
+                               get {
+                                       return attribute_targets;
+                               }
+                       }
                }
 
                public class SetMethod: PropertyMethod {
+
+                       static string[] attribute_targets = new string [] { "method", "param", "return" };
+                       ImplicitParameter param_attr;
+
                        public SetMethod (MethodCore method, Accessor accessor):
                                base (method, accessor)
                        {
                        }
 
+                       public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
+                       {
+                               if (a.Target == "param") {
+                                       if (param_attr == null)
+                                               param_attr = new ImplicitParameter (method_data.MethodBuilder);
+
+                                       param_attr.ApplyAttributeBuilder (a, cb);
+                                       return;
+                               }
+
+                               base.ApplyAttributeBuilder (a, cb);
+                       }
+
                        protected virtual InternalParameters GetParameterInfo (TypeContainer container)
                        {
                                Parameter [] parms = new Parameter [1];
@@ -4687,14 +4762,25 @@ namespace Mono.CSharp {
                                        return TypeManager.void_type;
                                }
                        }
+
+                       protected override string[] ValidAttributeTargets {
+                               get {
+                                       return attribute_targets;
+                               }
+                       }
                }
 
 
-               public abstract class PropertyMethod: Attributable, IMethodData {
+               static string[] attribute_targets = new string [] { "property" };
+
+               public abstract class PropertyMethod: Attributable, IMethodData 
+               {
                        protected readonly MethodCore method;
                        protected MethodData method_data;
                        Block block;
 
+                       ReturnParameter return_attributes;
+
                        public PropertyMethod (MethodCore method, Accessor accessor):
                                base (accessor.Attributes)
                        {
@@ -4708,6 +4794,7 @@ namespace Mono.CSharp {
                                }
                        }
 
+
                        public override bool IsClsCompliaceRequired(DeclSpace ds)
                        {
                                return method.IsClsCompliaceRequired (ds);
@@ -4740,11 +4827,18 @@ namespace Mono.CSharp {
                        {
                                method_data.Emit (container, this);
                                block = null;
-
                        }
 
                        public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
                        {
+                               if (a.Target == "return") {
+                                       if (return_attributes == null)
+                                               return_attributes = new ReturnParameter (method_data.MethodBuilder, Location);
+
+                                       return_attributes.ApplyAttributeBuilder (a, cb);
+                                       return;
+                               }
+
                                method_data.MethodBuilder.SetCustomAttribute (cb);
                        }
 
@@ -4769,6 +4863,10 @@ namespace Mono.CSharp {
                                return new EmitContext (tc, method.ds, method.Location, ig, ReturnType, method.ModFlags, false);
                        }
 
+                       public ObsoleteAttribute GetObsoleteAttribute ()
+                       {
+                               return method.GetObsoleteAttribute (method.ds);
+                       }
                        #endregion
                }
 
@@ -4976,6 +5074,12 @@ namespace Mono.CSharp {
 
                        base.Emit (tc);
                }
+
+               protected override string[] ValidAttributeTargets {
+                       get {
+                               return attribute_targets;
+                       }
+               }
        }
                        
        public class Property : PropertyBase, IIteratorContainer {
@@ -5233,9 +5337,69 @@ namespace Mono.CSharp {
                }
        }
        
-       public class Event : FieldBase {
+       /// <summary>
+       /// For case when event is declared like property (with add and remove accessors).
+       /// </summary>
+       public class EventProperty: Event {
+
+               static string[] attribute_targets = new string [] { "event", "property" };
+
+               public EventProperty (DeclSpace ds, Expression type, int mod_flags, bool is_iface, string name,
+                       Object init, Attributes attrs, Accessor add, Accessor remove, Location loc)
+                       : base (ds, type, mod_flags, is_iface, name, init, attrs, loc)
+               {
+                       Add = new AddDelegateMethod (this, add);
+                       Remove = new RemoveDelegateMethod (this, remove);
+               }
+
+               protected override string[] ValidAttributeTargets {
+                       get {
+                               return attribute_targets;
+                       }
+               }
+       }
+
+       /// <summary>
+       /// Event is declared like field.
+       /// </summary>
+       public class EventField: Event {
+
+               static string[] attribute_targets = new string [] { "method", "field", "event" };
+
+               public EventField (DeclSpace ds, Expression type, int mod_flags, bool is_iface, string name,
+                       Object init, Attributes attrs, Location loc)
+                       : base (ds, type, mod_flags, is_iface, name, init, attrs, loc)
+               {
+                       Add = new AddDelegateMethod (this);
+                       Remove = new RemoveDelegateMethod (this);
+               }
+
+               public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
+               {
+                       if (a.Target == "field") {
+                               FieldBuilder.SetCustomAttribute (cb);
+                               return;
+                       }
 
-               sealed class AddDelegateMethod: DelegateMethod
+                       if (a.Target == "method") {
+                               AddBuilder.SetCustomAttribute (cb);
+                               RemoveBuilder.SetCustomAttribute (cb);
+                               return;
+                       }
+
+                       base.ApplyAttributeBuilder (a, cb);
+               }
+
+               protected override string[] ValidAttributeTargets {
+                       get {
+                               return attribute_targets;
+                       }
+               }
+       }
+
+       public abstract class Event : FieldBase {
+
+               protected sealed class AddDelegateMethod: DelegateMethod
                {
                        public AddDelegateMethod (Event method):
                                base (method)
@@ -5261,7 +5425,7 @@ namespace Mono.CSharp {
 
                }
 
-               sealed class RemoveDelegateMethod: DelegateMethod
+               protected sealed class RemoveDelegateMethod: DelegateMethod
                {
                        public RemoveDelegateMethod (Event method):
                                base (method)
@@ -5292,6 +5456,10 @@ namespace Mono.CSharp {
                        protected readonly Event method;
                        protected MethodData method_data;
                        Block block;
+                       ReturnParameter return_attributes;
+                       ImplicitParameter param_attr;
+
+                       static string[] attribute_targets = new string [] { "method", "param", "return" };
 
                        public DelegateMethod (Event method):
                                base (null)
@@ -5308,6 +5476,22 @@ namespace Mono.CSharp {
 
                        public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
                        {
+                               if (a.Target == "return") {
+                                       if (return_attributes == null)
+                                               return_attributes = new ReturnParameter (method_data.MethodBuilder, Location);
+
+                                       return_attributes.ApplyAttributeBuilder (a, cb);
+                                       return;
+                               }
+
+                               if (a.Target == "param") {
+                                       if (param_attr == null)
+                                               param_attr = new ImplicitParameter (method_data.MethodBuilder);
+
+                                       param_attr.ApplyAttributeBuilder (a, cb);
+                                       return;
+                               }
+
                                method_data.MethodBuilder.SetCustomAttribute (cb);
                        }
 
@@ -5401,13 +5585,23 @@ namespace Mono.CSharp {
 
                        public EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig)
                        {
-                               return new EmitContext (tc, method.ds, method.Location, ig, ReturnType, method.ModFlags, false);
+                               return new EmitContext (tc, method.ds, Location, ig, ReturnType, method.ModFlags, false);
+                       }
+
+                       public ObsoleteAttribute GetObsoleteAttribute ()
+                       {
+                               return method.GetObsoleteAttribute (method.ds);
                        }
 
                        public abstract string MethodName { get; }
 
                        #endregion
 
+                       protected override string[] ValidAttributeTargets {
+                               get {
+                                       return attribute_targets;
+                               }
+                       }
                }
 
 
@@ -5427,23 +5621,11 @@ namespace Mono.CSharp {
                const int AllowedInterfaceModifiers =
                        Modifiers.NEW;
 
-               readonly DelegateMethod Add, Remove;
+               protected DelegateMethod Add, Remove;
                public MyEventBuilder     EventBuilder;
                public MethodBuilder AddBuilder, RemoveBuilder;
                public DeclSpace ds;
 
-               public Event (DeclSpace ds, Expression type, int mod_flags, bool is_iface, string name,
-                               Object init, Attributes attrs, Accessor add, Accessor remove, Location loc)
-                       : base (type, mod_flags, is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
-                               name, init, attrs, loc)
-               {
-                       IsInterface = is_iface;
-                       this.ds = ds;
-
-                       Add = new AddDelegateMethod (this, add);
-                       Remove = new RemoveDelegateMethod (this, remove);
-               }
-
                public Event (DeclSpace ds, Expression type, int mod_flags, bool is_iface, string name,
                                Object init, Attributes attrs, Location loc)
                        : base (type, mod_flags, is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
@@ -5451,9 +5633,6 @@ namespace Mono.CSharp {
                {
                        IsInterface = is_iface;
                        this.ds = ds;
-
-                       Add = new AddDelegateMethod (this);
-                       Remove = new RemoveDelegateMethod (this);
                }
 
                public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
@@ -5554,7 +5733,6 @@ namespace Mono.CSharp {
 
                        base.Emit (tc);
                }
-               
        }
 
        //
@@ -5684,7 +5862,9 @@ namespace Mono.CSharp {
                        if (!DoDefine (container))
                                return false;
 
-                       IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
+                       if (OptAttributes != null)
+                               IndexerName = OptAttributes.ScanForIndexerName (ec);
+
                        if (IndexerName == null)
                                IndexerName = "Item";
                        else {
@@ -5695,9 +5875,7 @@ namespace Mono.CSharp {
                                
                                if (IsExplicitImpl) {
                                        Report.Error (592, Location,
-                                                     "Attribute 'IndexerName' is not valid on explicit " +
-                                                     "implementations.");
-                                       
+                                                     "Attribute 'IndexerName' is not valid on explicit implementations.");
                                        return false;
                                }
                        }
@@ -5894,6 +6072,8 @@ namespace Mono.CSharp {
                public string MethodName;
                public Method OperatorMethod;
 
+               static string[] attribute_targets = new string [] { "method", "return" };
+
                public Operator (OpType type, Expression ret_type, int mod_flags,
                                 Expression arg1type, string arg1name,
                                 Expression arg2type, string arg2name,
@@ -6154,6 +6334,12 @@ namespace Mono.CSharp {
                                        param_types [0], param_types [1]);
                }
 
+               protected override string[] ValidAttributeTargets {
+                       get {
+                               return attribute_targets;
+                       }
+               }
+
                public void SetYields ()
                {
                        ModFlags |= Modifiers.METHOD_YIELDS;