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
+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.
public Attributable (Attributes attrs)
{
- OptAttributes = attrs;
+ if (attrs != null)
+ OptAttributes = attrs;
}
public Attributes OptAttributes
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;
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)
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);
Type ResolvePossibleAttributeType (string name, bool silent, ref bool is_attr)
{
- IResolveContext rc = owner.ResolveContext;
+ IResolveContext rc = Owner.ResolveContext;
TypeExpr te;
if (LeftExpr == null) {
}
}
+ Attributable owner = Owner;
EmitContext ec = new EmitContext (owner.ResolveContext, owner.ResolveContext.DeclContainer, owner.ResolveContext.DeclContainer,
Location, null, null, owner.ResolveContext.DeclContainer.ModFlags, false);
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);
}
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);
}
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;
}
}
try {
- owner.ApplyAttributeBuilder (this, cb);
+ foreach (Attributable owner in owners)
+ owner.ApplyAttributeBuilder (this, cb);
}
catch (Exception e) {
Error_AttributeEmitError (e.Message);
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)
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;
}
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)
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;
public void Resolve ()
{
- if (OptAttributes != null)
- OptAttributes.AttachTo (this);
-
ClsCompliantAttribute = ResolveAttribute (TypeManager.cls_compliant_attribute_type);
if (ClsCompliantAttribute != null) {
is_cls_compliant = ClsCompliantAttribute.GetClsCompliantAttributeValue ();
public override void Emit (TypeContainer tc)
{
- if (OptAttributes != null)
- OptAttributes.AttachTo (this);
-
base.Emit (tc);
if (!m_module_is_unsafe)
+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.
public Attributable (Attributes attrs)
{
- OptAttributes = attrs;
+ if (attrs != null)
+ OptAttributes = attrs;
}
public Attributes OptAttributes
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;
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)
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);
Type ResolvePossibleAttributeType (string name, bool silent, ref bool is_attr)
{
- IResolveContext rc = owner.ResolveContext;
+ IResolveContext rc = Owner.ResolveContext;
TypeExpr te;
if (LeftExpr == null) {
}
}
+ Attributable owner = Owner;
EmitContext ec = new EmitContext (owner.ResolveContext, owner.ResolveContext.DeclContainer, owner.ResolveContext.DeclContainer,
Location, null, null, owner.ResolveContext.DeclContainer.ModFlags, false);
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);
}
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);
}
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;
}
}
try {
- owner.ApplyAttributeBuilder (this, cb);
+ foreach (Attributable owner in owners)
+ owner.ApplyAttributeBuilder (this, cb);
}
catch (Exception e) {
Error_AttributeEmitError (e.Message);
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)
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;
}
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)
}
}
- 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 ();
}
}
- 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)
--- /dev/null
+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