2006-04-06 Marek Safar <marek.safar@seznam.cz>
authorMarek Safar <marek.safar@gmail.com>
Thu, 6 Apr 2006 20:54:28 +0000 (20:54 -0000)
committerMarek Safar <marek.safar@gmail.com>
Thu, 6 Apr 2006 20:54:28 +0000 (20:54 -0000)
A fix for #78020.

* attribute.cs (Attribute.AttachTo): The attribute can have multiple
sources (it's composite) so hold them in extra array as they are used in
Emit phase only. It worked in the previous versions by mistake.
(Attribute.Emit): Emit attribute for more owners when exist.

* codegen.cs, class.cs: Updated to don't re-attach attribute twice as now
it has now different behaviour.

svn path=/trunk/mcs/; revision=59143

mcs/gmcs/ChangeLog
mcs/gmcs/attribute.cs
mcs/gmcs/class.cs
mcs/gmcs/codegen.cs
mcs/mcs/ChangeLog
mcs/mcs/attribute.cs
mcs/mcs/class.cs
mcs/mcs/codegen.cs
mcs/tests/test-500.cs [new file with mode: 0644]

index 2e0eacaff5c4988f807b6065d67d3357a635b0cf..3427f069f78bc357ab20a8a3a33b07984b120b06 100644 (file)
@@ -1,3 +1,15 @@
+2006-04-06  Marek Safar  <marek.safar@seznam.cz>
+
+       A fix for #78020.
+
+       * attribute.cs (Attribute.AttachTo): The attribute can have multiple
+       sources (it's composite) so hold them in extra array as they are used in
+       Emit phase only. It worked in the previous versions by mistake.
+       (Attribute.Emit): Emit attribute for more owners when exist.
+
+       * codegen.cs, class.cs: Updated to don't re-attach attribute twice as now
+       it has now different behaviour.
+
 2006-04-04  Marek Safar  <marek.safar@seznam.cz>
 
        * constant.cs (Constant.IsDefaultInitializer): New method.
index 5c350d0e1d38a3a64bf3954aef0b87e574cc55a6..8feb1379876007907cb16db3f038c8b373c5c355 100644 (file)
@@ -36,7 +36,8 @@ namespace Mono.CSharp {
 
                public Attributable (Attributes attrs)
                {
-                       OptAttributes = attrs;
+                       if (attrs != null)
+                               OptAttributes = attrs;
                }
 
                public Attributes OptAttributes 
@@ -92,7 +93,9 @@ namespace Mono.CSharp {
 
                bool resolve_error;
                readonly bool nameEscaped;
-               Attributable owner;
+
+               // It can contain more onwers when the attribute is applied to multiple fiels.
+               Attributable[] owners;
 
                static readonly AttributeUsageAttribute DefaultUsageAttribute = new AttributeUsageAttribute (AttributeTargets.All);
                static Assembly orig_sec_assembly;
@@ -136,7 +139,20 @@ namespace Mono.CSharp {
 
                public void AttachTo (Attributable owner)
                {
-                       this.owner = owner;
+                       if (this.owners == null) {
+                               this.owners = new Attributable[1] { owner };
+                               return;
+                       }
+
+                       // When the same attribute is attached to multiple fiels
+                       // we use this extra_owners as a list of owners. The attribute
+                       // then can be removed because will be emitted when first owner
+                       // is served
+                       Attributable[] new_array = new Attributable [this.owners.Length + 1];
+                       owners.CopyTo (new_array, 0);
+                       new_array [owners.Length] = owner;
+                       this.owners = new_array;
+                       owner.OptAttributes = null;
                }
 
                void Error_InvalidNamedArgument (string name)
@@ -181,6 +197,12 @@ namespace Mono.CSharp {
                        Error_AttributeEmitError ("it is attached to invalid parent");
                }
 
+               Attributable Owner {
+                       get {
+                               return owners [0];
+                       }
+               }
+
                protected virtual TypeExpr ResolveAsTypeTerminal (Expression expr, IResolveContext ec, bool silent)
                {
                        return expr.ResolveAsTypeTerminal (ec, silent);
@@ -188,7 +210,7 @@ namespace Mono.CSharp {
 
                Type ResolvePossibleAttributeType (string name, bool silent, ref bool is_attr)
                {
-                       IResolveContext rc = owner.ResolveContext;
+                       IResolveContext rc = Owner.ResolveContext;
 
                        TypeExpr te;
                        if (LeftExpr == null) {
@@ -307,6 +329,7 @@ namespace Mono.CSharp {
                                }
                        }
 
+                       Attributable owner = Owner;
                        EmitContext ec = new EmitContext (owner.ResolveContext, owner.ResolveContext.DeclContainer, owner.ResolveContext.DeclContainer,
                                Location, null, null, owner.ResolveContext.DeclContainer.ModFlags, false);
 
@@ -376,7 +399,7 @@ namespace Mono.CSharp {
                                return null;
 
                        ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (constructor);
-                       if (oa != null && !owner.ResolveContext.IsInObsoleteScope) {
+                       if (oa != null && !Owner.ResolveContext.IsInObsoleteScope) {
                                AttributeTester.Report_ObsoleteMessage (oa, mg.GetSignatureForError (), mg.Location);
                        }
 
@@ -581,7 +604,7 @@ namespace Mono.CSharp {
                                        field_infos.Add (fi);
                                }
 
-                               if (obsolete_attr != null && !owner.ResolveContext.IsInObsoleteScope)
+                               if (obsolete_attr != null && !Owner.ResolveContext.IsInObsoleteScope)
                                        AttributeTester.Report_ObsoleteMessage (obsolete_attr, member.GetSignatureForError (), member.Location);
                        }
 
@@ -792,9 +815,9 @@ namespace Mono.CSharp {
 
                public bool CheckTarget ()
                {
-                       string[] valid_targets = owner.ValidAttributeTargets;
+                       string[] valid_targets = Owner.ValidAttributeTargets;
                        if (ExplicitTarget == null || ExplicitTarget == valid_targets [0]) {
-                               Target = owner.AttributeTargets;
+                               Target = Owner.AttributeTargets;
                                return true;
                        }
 
@@ -1126,7 +1149,8 @@ namespace Mono.CSharp {
                        }
 
                        try {
-                               owner.ApplyAttributeBuilder (this, cb);
+                               foreach (Attributable owner in owners)
+                                       owner.ApplyAttributeBuilder (this, cb);
                        }
                        catch (Exception e) {
                                Error_AttributeEmitError (e.Message);
@@ -1150,7 +1174,7 @@ namespace Mono.CSharp {
                                return;
 
                        // Here we are testing attribute arguments for array usage (error 3016)
-                       if (owner.IsClsComplianceRequired ()) {
+                       if (Owner.IsClsComplianceRequired ()) {
                                if (PosArguments != null) {
                                        foreach (Argument arg in PosArguments) { 
                                                // Type is undefined (was error 246)
index 2fa11b4ec761c19cca92a576a135e7330b9dba54..b6337a8c9dbff8935b7c28ac1f1f832093fa08bf 100644 (file)
@@ -7331,9 +7331,12 @@ namespace Mono.CSharp {
                                 int mod_flags, Parameters parameters,
                                 ToplevelBlock block, Attributes attrs, Location loc)
                        : base (parent, null, ret_type, mod_flags, AllowedModifiers, false,
-                               new MemberName ("op_" + type, loc), attrs, parameters)
+                               new MemberName ("op_" + type, loc), null, parameters)
                {
                        OperatorType = type;
+                       // TODO: As operator breaks all our rules, don't attach the attributes
+                       // to fake owner, will finally need to rewrite it
+                       attributes = attrs;
                        Block = block;
                }
 
index 203a876ca9aecf6f3027db6efd3b105779ccaaa4..2fa917936d82bd504e221d3c3c316080a4d67759 100644 (file)
@@ -991,11 +991,14 @@ namespace Mono.CSharp {
 
                public void AddAttributes (ArrayList attrs)
                {
-                       if (OptAttributes == null) {
-                               OptAttributes = new Attributes (attrs);
+                       foreach (Attribute a in attrs)
+                               a.AttachTo (this);
+
+                       if (attributes == null) {
+                               attributes = new Attributes (attrs);
                                return;
                        }
-                       OptAttributes.AddAttributes (attrs);
+                       attributes.AddAttributes (attrs);
                }
 
                public virtual void Emit (TypeContainer tc) 
@@ -1012,7 +1015,6 @@ namespace Mono.CSharp {
                                return null;
 
                        // Ensure that we only have GlobalAttributes, since the Search below isn't safe with other types.
-                       OptAttributes.AttachTo (this);
                        if (!OptAttributes.CheckTargets ())
                                return null;
 
@@ -1097,9 +1099,6 @@ namespace Mono.CSharp {
 
                public void Resolve ()
                {
-                       if (OptAttributes != null)
-                               OptAttributes.AttachTo (this);
-
                        ClsCompliantAttribute = ResolveAttribute (TypeManager.cls_compliant_attribute_type);
                        if (ClsCompliantAttribute != null) {
                                is_cls_compliant = ClsCompliantAttribute.GetClsCompliantAttributeValue ();
@@ -1398,9 +1397,6 @@ namespace Mono.CSharp {
 
                public override void Emit (TypeContainer tc) 
                {
-                       if (OptAttributes != null)
-                               OptAttributes.AttachTo (this);
-
                        base.Emit (tc);
 
                        if (!m_module_is_unsafe)
index 852e42ac472f7dba459d2aeaf1849a8249c6e9b5..223939ffcfa75b9c8684c78e98a91eed3a2d6add 100644 (file)
@@ -1,3 +1,15 @@
+2006-04-06  Marek Safar  <marek.safar@seznam.cz>
+
+       A fix for #78020.
+
+       * attribute.cs (Attribute.AttachTo): The attribute can have multiple
+       sources (it's composite) so hold them in extra array as they are used in
+       Emit phase only. It worked in the previous versions by mistake.
+       (Attribute.Emit): Emit attribute for more owners when exist.
+
+       * codegen.cs, class.cs: Updated to don't re-attach attribute twice as now
+       it has now different behaviour.
+
 2006-04-04  Marek Safar  <marek.safar@seznam.cz>
 
        * constant.cs (Constant.IsDefaultInitializer): New method.
index 83c5a1ecec98e519f00b213c37c25ce65b5616ea..1f80a1f14983864f42a5f49a1d872f1f142aac0b 100644 (file)
@@ -36,7 +36,8 @@ namespace Mono.CSharp {
 
                public Attributable (Attributes attrs)
                {
-                       OptAttributes = attrs;
+                       if (attrs != null)
+                               OptAttributes = attrs;
                }
 
                public Attributes OptAttributes 
@@ -92,7 +93,9 @@ namespace Mono.CSharp {
 
                bool resolve_error;
                readonly bool nameEscaped;
-               Attributable owner;
+
+               // It can contain more onwers when the attribute is applied to multiple fiels.
+               Attributable[] owners;
 
                static readonly AttributeUsageAttribute DefaultUsageAttribute = new AttributeUsageAttribute (AttributeTargets.All);
                static Assembly orig_sec_assembly;
@@ -136,7 +139,20 @@ namespace Mono.CSharp {
 
                public void AttachTo (Attributable owner)
                {
-                       this.owner = owner;
+                       if (this.owners == null) {
+                               this.owners = new Attributable[1] { owner };
+                               return;
+                       }
+
+                       // When the same attribute is attached to multiple fiels
+                       // we use this extra_owners as a list of owners. The attribute
+                       // then can be removed because will be emitted when first owner
+                       // is served
+                       Attributable[] new_array = new Attributable [this.owners.Length + 1];
+                       owners.CopyTo (new_array, 0);
+                       new_array [owners.Length] = owner;
+                       this.owners = new_array;
+                       owner.OptAttributes = null;
                }
 
                void Error_InvalidNamedArgument (string name)
@@ -175,6 +191,12 @@ namespace Mono.CSharp {
                        Error_AttributeEmitError ("it is attached to invalid parent");
                }
 
+               Attributable Owner {
+                       get {
+                               return owners [0];
+                       }
+               }
+
                protected virtual TypeExpr ResolveAsTypeTerminal (Expression expr, IResolveContext ec, bool silent)
                {
                        return expr.ResolveAsTypeTerminal (ec, silent);
@@ -182,7 +204,7 @@ namespace Mono.CSharp {
 
                Type ResolvePossibleAttributeType (string name, bool silent, ref bool is_attr)
                {
-                       IResolveContext rc = owner.ResolveContext;
+                       IResolveContext rc = Owner.ResolveContext;
 
                        TypeExpr te;
                        if (LeftExpr == null) {
@@ -301,6 +323,7 @@ namespace Mono.CSharp {
                                }
                        }
 
+                       Attributable owner = Owner;
                        EmitContext ec = new EmitContext (owner.ResolveContext, owner.ResolveContext.DeclContainer, owner.ResolveContext.DeclContainer,
                                Location, null, null, owner.ResolveContext.DeclContainer.ModFlags, false);
 
@@ -364,7 +387,7 @@ namespace Mono.CSharp {
                                return null;
 
                        ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (constructor);
-                       if (oa != null && !owner.ResolveContext.IsInObsoleteScope) {
+                       if (oa != null && !Owner.ResolveContext.IsInObsoleteScope) {
                                AttributeTester.Report_ObsoleteMessage (oa, mg.GetSignatureForError (), mg.Location);
                        }
 
@@ -564,7 +587,7 @@ namespace Mono.CSharp {
                                        field_infos.Add (fi);
                                }
 
-                               if (obsolete_attr != null && !owner.ResolveContext.IsInObsoleteScope)
+                               if (obsolete_attr != null && !Owner.ResolveContext.IsInObsoleteScope)
                                        AttributeTester.Report_ObsoleteMessage (obsolete_attr, member.GetSignatureForError (), member.Location);
                        }
 
@@ -777,9 +800,9 @@ namespace Mono.CSharp {
 
                public bool CheckTarget ()
                {
-                       string[] valid_targets = owner.ValidAttributeTargets;
+                       string[] valid_targets = Owner.ValidAttributeTargets;
                        if (ExplicitTarget == null || ExplicitTarget == valid_targets [0]) {
-                               Target = owner.AttributeTargets;
+                               Target = Owner.AttributeTargets;
                                return true;
                        }
 
@@ -1103,7 +1126,8 @@ namespace Mono.CSharp {
                        }
 
                        try {
-                               owner.ApplyAttributeBuilder (this, cb);
+                               foreach (Attributable owner in owners)
+                                       owner.ApplyAttributeBuilder (this, cb);
                        }
                        catch (Exception e) {
                                Error_AttributeEmitError (e.Message);
@@ -1127,7 +1151,7 @@ namespace Mono.CSharp {
                                return;
 
                        // Here we are testing attribute arguments for array usage (error 3016)
-                       if (owner.IsClsComplianceRequired ()) {
+                       if (Owner.IsClsComplianceRequired ()) {
                                if (PosArguments != null) {
                                        foreach (Argument arg in PosArguments) { 
                                                // Type is undefined (was error 246)
index 51c92fa8451863e22a2a6fe24dc5fb3985c3accb..a4e97b0984bf76ebf250a2d03d5443ca7f38e2f6 100644 (file)
@@ -6973,9 +6973,12 @@ namespace Mono.CSharp {
                                 int mod_flags, Parameters parameters,
                                 ToplevelBlock block, Attributes attrs, Location loc)
                        : base (parent, ret_type, mod_flags, AllowedModifiers, false,
-                               new MemberName ("op_" + type, loc), attrs, parameters)
+                               new MemberName ("op_" + type, loc), null, parameters)
                {
                        OperatorType = type;
+                       // TODO: As operator breaks all our rules, don't attach the attributes
+                       // to fake owner, will finally need to rewrite it
+                       attributes = attrs;
                        Block = block;
                }
 
index da0ee9f340eb37888b44b5358b5e55c59a6091a2..d1b42da88e45de6fb8e60dc8248cfb901e626b1c 100644 (file)
@@ -977,11 +977,14 @@ namespace Mono.CSharp {
 
                public void AddAttributes (ArrayList attrs)
                {
-                       if (OptAttributes == null) {
-                               OptAttributes = new Attributes (attrs);
+                       foreach (Attribute a in attrs)
+                               a.AttachTo (this);
+
+                       if (attributes == null) {
+                               attributes = new Attributes (attrs);
                                return;
                        }
-                       OptAttributes.AddAttributes (attrs);
+                       attributes.AddAttributes (attrs);
                }
 
                public virtual void Emit (TypeContainer tc) 
@@ -1073,16 +1076,13 @@ namespace Mono.CSharp {
                        }
                }
 
-               public override bool IsClsComplianceRequired()
+               public override bool IsClsComplianceRequired ()
                {
                        return is_cls_compliant;
                }
 
                public void Resolve ()
                {
-                       if (OptAttributes != null)
-                               OptAttributes.AttachTo (this);
-
                        ClsCompliantAttribute = ResolveAttribute (TypeManager.cls_compliant_attribute_type);
                        if (ClsCompliantAttribute != null) {
                                is_cls_compliant = ClsCompliantAttribute.GetClsCompliantAttributeValue ();
@@ -1330,16 +1330,13 @@ namespace Mono.CSharp {
                        }
                }
 
-               public override bool IsClsComplianceRequired()
+               public override bool IsClsComplianceRequired ()
                {
                        return CodeGen.Assembly.IsClsCompliant;
                }
 
                public override void Emit (TypeContainer tc) 
                {
-                       if (OptAttributes != null)
-                               OptAttributes.AttachTo (this);
-
                        base.Emit (tc);
 
                        if (!m_module_is_unsafe)
diff --git a/mcs/tests/test-500.cs b/mcs/tests/test-500.cs
new file mode 100644 (file)
index 0000000..4fc55f1
--- /dev/null
@@ -0,0 +1,35 @@
+using System;\r
+using System.Reflection;\r
+\r
+[AttributeUsage(AttributeTargets.Field, AllowMultiple=false)]\r
+class SomeCustomAttribute : Attribute {\r
+       public SomeCustomAttribute ()\r
+       {\r
+       }\r
+}\r
+\r
+class MainClass {\r
+\r
+       [SomeCustomAttribute]\r
+       public int a;\r
+\r
+       [SomeCustomAttribute]\r
+       public int x, y;\r
+\r
+       public static int Main ()\r
+       {\r
+               Type t = typeof (MainClass);\r
+               FieldInfo[] fia = t.GetFields();\r
+\r
+               foreach (FieldInfo fi in fia) {\r
+                       object[] ca = fi.GetCustomAttributes(typeof (SomeCustomAttribute), false);\r
+                       System.Console.WriteLine ("Field: {0} [{1}]", fi.Name, ca.Length);\r
+                       if (ca.Length != 1)\r
+                               return 1;\r
+               }\r
+               \r
+               Console.WriteLine ("OK");\r
+               \r
+               return 0;\r
+       }\r
+}
\ No newline at end of file