+2004-05-18 Marek Safar <marek.safar@seznam.cz>
+
+ Fix bug #52585 (Implemented explicit attribute declaration)
+
+ * attribute.cs:
+ (Attributable.ValidAttributeTargets): New abstract method. It gets
+ list of valid attribute targets for explicit target declaration.
+ (Attribute.Target): It holds target itself.
+ (AttributeSection): Removed.
+ (Attribute.CheckTargets): New method. It checks whether attribute
+ target is valid for the current element.
+
+ * class.cs:
+ (EventProperty): New class. For events that are declared like
+ property (with add and remove accessors).
+ (EventField): New class. For events that are declared like field.
+ class.cs
+
+ * cs-parser.jay: Implemented explicit attribute target declaration.
+
+ * class.cs, decl.cs, delegate.cs, enum.cs, parameter.cs:
+ Override ValidAttributeTargets.
+
+ * parameter.cs:
+ (ReturnParameter): Class for applying custom attributes on
+ the return type.
+ (ParameterAtribute): New class. Class for applying custom
+ attributes on the parameter type.
+
2004-05-17 Miguel de Icaza <miguel@ximian.com>
* class.cs (MemberBase.DoDefine): Pass UNSAFE on interface
parameter.
Fixes #56442.
+2004-04-08 Martin Baulig <martin@ximian.com>
+
+ Merged latest changes into gmcs. Please keep this comment in
+ here, it makes it easier for me to see what changed in MCS since
+ the last time I merged.
+
2004-04-16 Raja R Harinath <rharinath@novell.com>
* class.cs (TypeContainer.AddIndexer): Use
public Attributable(Attributes attrs)\r
{\r
attributes = attrs;\r
+ if (attributes != null)\r
+ attributes.CheckTargets (ValidAttributeTargets);\r
}\r
\r
public Attributes OptAttributes \r
public abstract AttributeTargets AttributeTargets { get; }\r
\r
public abstract bool IsClsCompliaceRequired (DeclSpace ds);\r
- };\r
\r
+ /// <summary>\r
+ /// Gets list of valid attribute targets for explicit target declaration\r
+ /// </summary>\r
+ protected abstract string[] ValidAttributeTargets { get; }\r
+ };\r
\r
public class Attribute {\r
+ public readonly string Target;\r
public readonly string Name;\r
public readonly ArrayList Arguments;\r
\r
\r
static PtrHashtable usage_attr_cache = new PtrHashtable ();\r
\r
- public Attribute (string name, ArrayList args, Location loc)\r
+ public Attribute (string target, string name, ArrayList args, Location loc)\r
{\r
Name = name;\r
Arguments = args;\r
Location = loc;\r
+ Target = target;\r
}\r
\r
void Error_InvalidNamedArgument (string name)\r
/// <summary>\r
/// Tries to resolve the type of the attribute. Flags an error if it can't, and complain is true.\r
/// </summary>\r
- private Type CheckAttributeType (EmitContext ec, bool complain) {\r
+ protected virtual Type CheckAttributeType (EmitContext ec, bool complain)\r
+ {\r
TypeExpr t1 = RootContext.LookupType (ec.DeclSpace, Name, true, Location);\r
// FIXME: Shouldn't do this for quoted attributes: [@A]\r
TypeExpr t2 = RootContext.LookupType (ec.DeclSpace, Name + "Attribute", true, Location);\r
if (opt_attrs.AttributeSections == null)\r
return null;\r
\r
- foreach (AttributeSection asec in opt_attrs.AttributeSections) {\r
- if (asec.Attributes == null)\r
- continue;\r
-\r
- foreach (Attribute a in asec.Attributes){\r
- if (a.ResolveType (ec, true) == null)\r
- return null;\r
+ foreach (Attribute a in opt_attrs.AttributeSections) {\r
+ if (a.ResolveType (ec, true) == null)\r
+ return null;\r
\r
- if (a.Type != TypeManager.indexer_name_type)\r
- continue;\r
+ if (a.Type != TypeManager.indexer_name_type)\r
+ continue;\r
\r
- //\r
- // So we have found an IndexerName, pull the data out.\r
- //\r
- if (a.Arguments == null || a.Arguments [0] == null){\r
- Error_AttributeConstructorMismatch (a.Location);\r
- return null;\r
- }\r
- ArrayList pos_args = (ArrayList) a.Arguments [0];\r
- if (pos_args.Count == 0){\r
- Error_AttributeConstructorMismatch (a.Location);\r
- return null;\r
- }\r
+ //\r
+ // So we have found an IndexerName, pull the data out.\r
+ //\r
+ if (a.Arguments == null || a.Arguments [0] == null){\r
+ Error_AttributeConstructorMismatch (a.Location);\r
+ return null;\r
+ }\r
+ ArrayList pos_args = (ArrayList) a.Arguments [0];\r
+ if (pos_args.Count == 0){\r
+ Error_AttributeConstructorMismatch (a.Location);\r
+ return null;\r
+ }\r
\r
- Argument arg = (Argument) pos_args [0];\r
- if (!arg.Resolve (ec, a.Location))\r
- return null;\r
+ Argument arg = (Argument) pos_args [0];\r
+ if (!arg.Resolve (ec, a.Location))\r
+ return null;\r
\r
- Expression e = arg.Expr;\r
- if (!(e is StringConstant)){\r
- Error_AttributeConstructorMismatch (a.Location);\r
- return null;\r
- }\r
+ Expression e = arg.Expr;\r
+ if (!(e is StringConstant)){\r
+ Error_AttributeConstructorMismatch (a.Location);\r
+ return null;\r
+ }\r
\r
- //\r
- // Remove the attribute from the list\r
- //\r
- asec.Attributes.Remove (a);\r
+ //\r
+ // Remove the attribute from the list\r
+ //\r
\r
- return (((StringConstant) e).Value);\r
- }\r
+ //TODO: It is very close to hack and it can crash here\r
+ opt_attrs.AttributeSections.Remove (a);\r
+\r
+ return (((StringConstant) e).Value);\r
}\r
return null;\r
}\r
/// <summary>\r
/// Emit attribute for Attributable symbol\r
/// </summary>\r
- public void Emit (EmitContext ec, Attributable ias, ListDictionary emitted_attr, string target)\r
+ public void Emit (EmitContext ec, Attributable ias, ListDictionary emitted_attr)\r
{\r
CustomAttributeBuilder cb = Resolve (ec);\r
if (cb == null) \r
ias.ApplyAttributeBuilder (this, cb);\r
\r
string emitted = emitted_attr [Type] as string;\r
- if (target != null && emitted == target && !usage_attr.AllowMultiple) {\r
+ if (Target != null && emitted == Target && !usage_attr.AllowMultiple) {\r
Report.Error (579, Location, "Duplicate '" + Name + "' attribute");\r
}\r
\r
- emitted_attr [Type] = target;\r
+ emitted_attr [Type] = Target;\r
\r
// Here we are testing attribute arguments for array usage (error 3016)\r
if (ias.IsClsCompliaceRequired (ec.DeclSpace)) {\r
}\r
}\r
\r
- /// <summary>\r
/// For global attributes (assembly, module) we need special handling.\r
/// Attributes can be located in the several files\r
/// </summary>\r
- public class GlobalAttributeSection: AttributeSection\r
+ public class GlobalAttribute: Attribute\r
{\r
public readonly NamespaceEntry ns;\r
\r
- public GlobalAttributeSection (TypeContainer container, AttributeSection attrsec):\r
- base (attrsec.Target, attrsec.Attributes)\r
+ public GlobalAttribute (TypeContainer container, string target, string name, ArrayList args, Location loc):\r
+ base (target, name, args, loc)\r
{\r
ns = container.NamespaceEntry;\r
}\r
\r
- public override void Emit(EmitContext ec, Attributable ias, ListDictionary ld)\r
+ protected override Type CheckAttributeType (EmitContext ec, bool complain)\r
{\r
ec.DeclSpace.NamespaceEntry = ns;\r
- base.Emit (ec, ias, ld);\r
- }\r
-\r
- public override Attribute Search(Type t, EmitContext ec)\r
- {\r
- ec.DeclSpace.NamespaceEntry = ns;\r
- return base.Search (t, ec);\r
+ return base.CheckAttributeType (ec, complain);\r
}\r
}\r
\r
- public class AttributeSection {\r
- public readonly string Target;\r
- public readonly ArrayList Attributes;\r
- \r
- public AttributeSection (string target, ArrayList attrs)\r
+ public class Attributes {\r
+ public ArrayList AttributeSections;\r
+\r
+ public Attributes (Attribute a)\r
{\r
- Target = target;\r
- Attributes = attrs;\r
+ AttributeSections = new ArrayList ();\r
+ AttributeSections.Add (a);\r
}\r
\r
- public virtual void Emit (EmitContext ec, Attributable ias, ListDictionary ld)\r
+ public Attributes (ArrayList attrs)\r
{\r
- foreach (Attribute a in Attributes) {\r
- a.Emit (ec, ias, ld, Target);\r
- }\r
+ AttributeSections = attrs;\r
}\r
\r
- public virtual Attribute Search (Type t, EmitContext ec)\r
+ public void AddAttributes (ArrayList attrs)\r
{\r
- foreach (Attribute a in Attributes) {\r
- if (a.ResolveType (ec, false) == t)\r
- return a;\r
- }\r
- return null;\r
+ AttributeSections.AddRange (attrs);\r
}\r
- }\r
\r
- public class Attributes {\r
- public ArrayList AttributeSections;\r
-\r
- public Attributes (AttributeSection a)\r
+ /// <summary>\r
+ /// Checks whether attribute target is valid for the current element\r
+ /// </summary>\r
+ public void CheckTargets (string[] possible_targets)\r
{\r
- AttributeSections = new ArrayList ();\r
- AttributeSections.Add (a);\r
+ foreach (Attribute a in AttributeSections) {\r
+ if (a.Target == null)\r
+ continue;\r
\r
- }\r
+ bool valid_target = false;\r
+ for (int i = 0; i < possible_targets.Length; ++i) {\r
+ if (a.Target == possible_targets [i]) {\r
+ valid_target = true;\r
+ break;\r
+ }\r
+ }\r
\r
- public void AddAttributeSection (AttributeSection a)\r
- {\r
- if (a != null && !AttributeSections.Contains (a))\r
- AttributeSections.Add (a);\r
+ if (valid_target)\r
+ continue;\r
+\r
+ StringBuilder sb = new StringBuilder ();\r
+ foreach (string s in possible_targets) {\r
+ sb.Append (s);\r
+ sb.Append (", ");\r
+ }\r
+ sb.Remove (sb.Length - 2, 2);\r
+ Report.Error_T (657, a.Location, a.Target, sb.ToString ());\r
+ }\r
}\r
\r
public Attribute Search (Type t, EmitContext ec)\r
{\r
- foreach (AttributeSection attr_section in AttributeSections){\r
- Attribute a = attr_section.Search (t, ec);\r
- if (a != null)\r
- return a;\r
+ foreach (Attribute attr_section in AttributeSections) {\r
+ if (attr_section.ResolveType (ec, false) == t)\r
+ return attr_section;\r
}\r
return null;\r
}\r
{\r
ListDictionary ld = new ListDictionary ();\r
\r
- foreach (AttributeSection attr_section in AttributeSections) {\r
- attr_section.Emit (ec, ias, ld);\r
+ foreach (Attribute a in AttributeSections) {\r
+ a.Emit (ec, ias, ld);\r
}\r
}\r
\r
// 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, MemberName name, Attributes attrs,
Parameters parameters, Location loc)
return true;
}
+ protected override string[] ValidAttributeTargets {
+ get {
+ return attribute_targets;
+ }
+ }
+
protected override bool VerifyClsCompliance (DeclSpace ds)
{
if (!base.VerifyClsCompliance (ds)) {
public class Method : MethodCore, IIteratorContainer, IMethodData {
public MethodBuilder MethodBuilder;
public MethodData MethodData;
+ ReturnParameter return_attributes;
/// <summary>
/// Modifiers allowed in a class declaration
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);
}
ec.IsStatic = false;
}
- Parameters.LabelParameters (ec, ConstructorBuilder,
- OptAttributes, Location);
+ Parameters.LabelParameters (ec, ConstructorBuilder, Location);
SymbolWriter sw = CodeGen.SymbolWriter;
bool generate_debugging = false;
if ((opt_attrs == null) || (opt_attrs.AttributeSections == 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 (ec, 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.AttributeSections) {
+ Type attr_type = a.ResolveType (ec, 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;
}
}
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;
[Flags]
public enum Status : byte { ASSIGNED = 1, USED = 2 }
+ static string[] attribute_targets = new string [] { "field" };
+
//
// The constructor is only exposed to our children
//
return TypeManager.GetFullNameSignature (FieldBuilder);
}
+ protected override string[] ValidAttributeTargets {
+ get {
+ return attribute_targets;
+ }
+ }
+
protected override bool VerifyClsCompliance (DeclSpace ds)
{
if (!base.VerifyClsCompliance (ds))
public class GetMethod: PropertyMethod
{
+ static string[] attribute_targets = new string [] { "method", "return" };
+
public GetMethod (MethodCore method, Accessor accessor):
base (method, accessor)
{
return method.MemberType;
}
}
+
+ protected override string[] ValidAttributeTargets {
+ get {
+ return attribute_targets;
+ }
+ }
}
public class SetMethod: PropertyMethod {
+
+ static string[] attribute_targets = new string [] { "method", "param", "return" };
+ ParameterAtribute 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 ParameterAtribute (method_data.MethodBuilder);
+
+ param_attr.ApplyAttributeBuilder (a, cb);
+ return;
+ }
+
+ base.ApplyAttributeBuilder (a, cb);
+ }
+
protected virtual InternalParameters GetParameterInfo (TypeContainer container)
{
Parameter [] parms = new Parameter [1];
return TypeManager.void_type;
}
}
+
+ protected override string[] ValidAttributeTargets {
+ get {
+ return attribute_targets;
+ }
+ }
}
+ 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)
{
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);
}
base.Emit (tc);
}
+
+ protected override string[] ValidAttributeTargets {
+ get {
+ return attribute_targets;
+ }
+ }
}
public class Property : PropertyBase, IIteratorContainer {
}
}
- public class Event : FieldBase {
+ /// <summary>
+ /// For case when event is declared like property (with add and remove accessors).
+ /// </summary>
+ public class EventProperty: Event {
- sealed class AddDelegateMethod: DelegateMethod
+ static string[] attribute_targets = new string [] { "event", "property" };
+
+ public EventProperty (DeclSpace ds, Expression type, int mod_flags,
+ bool is_iface, MemberName 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,
+ MemberName 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;
+ }
+
+ 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)
}
- sealed class RemoveDelegateMethod: DelegateMethod
+ protected sealed class RemoveDelegateMethod: DelegateMethod
{
public RemoveDelegateMethod (Event method):
base (method)
protected readonly Event method;
protected MethodData method_data;
Block block;
+ ReturnParameter return_attributes;
+ ParameterAtribute param_attr;
+
+ static string[] attribute_targets = new string [] { "method", "param", "return" };
public DelegateMethod (Event method):
base (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;
+ }
+
+ if (a.Target == "param") {
+ if (param_attr == null)
+ param_attr = new ParameterAtribute (method_data.MethodBuilder);
+
+ param_attr.ApplyAttributeBuilder (a, cb);
+ return;
+ }
+
method_data.MethodBuilder.SetCustomAttribute (cb);
}
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 abstract string MethodName { get; }
#endregion
+ protected override string[] ValidAttributeTargets {
+ get {
+ return attribute_targets;
+ }
+ }
}
const int AllowedInterfaceModifiers =
Modifiers.NEW;
- readonly DelegateMethod Add, Remove;
+ protected DelegateMethod Add, Remove;
public MyEventBuilder EventBuilder;
public MethodBuilder AddBuilder, RemoveBuilder;
public DeclSpace ds;
MethodData AddData, RemoveData;
- public Event (DeclSpace ds, Expression type, int mod_flags, bool is_iface,
- MemberName 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,
MemberName name, Object init, Attributes attrs, Location loc)
: base (type, mod_flags,
{
IsInterface = is_iface;
this.ds = ds;
-
- Add = new AddDelegateMethod (this);
- Remove = new RemoveDelegateMethod (this);
}
public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
base.Emit (tc);
}
-
}
//
public string MethodName;
public Method OperatorMethod;
+ static string[] attribute_targets = new string [] { "param" };
+
public Operator (OpType type, Expression ret_type, int mod_flags,
Expression arg1type, string arg1name,
Expression arg2type, string arg2name,
param_types [0], param_types [1]);
}
+ protected override string[] ValidAttributeTargets {
+ get {
+ return attribute_targets;
+ }
+ }
+
public void SetYields ()
{
ModFlags |= Modifiers.METHOD_YIELDS;
public abstract class CommonAssemblyModulClass: Attributable {
+ static string[] attribute_targets = new string [] { "assembly", "module" };
protected CommonAssemblyModulClass ():
base (null)
{
}
- public void AddAttribute (AttributeSection attr)
+ // TODO: The error can be reported more than once
+ public void AddAttributes (ArrayList attrs)
{
if (OptAttributes == null) {
- OptAttributes = new Attributes (attr);
+ OptAttributes = new Attributes (attrs);
+ OptAttributes.CheckTargets (ValidAttributeTargets);
return;
}
- OptAttributes.AddAttributeSection (attr);
+ OptAttributes.AddAttributes (attrs);
+ OptAttributes.CheckTargets (ValidAttributeTargets);
}
public virtual void Emit (TypeContainer tc)
}
return a;
}
+
+ protected override string[] ValidAttributeTargets {
+ get {
+ return attribute_targets;
+ }
+ }
}
public class AssemblyClass: CommonAssemblyModulClass {
public AssemblyName GetAssemblyName (string name, string output)
{
if (OptAttributes != null) {
- foreach (AttributeSection asect in OptAttributes.AttributeSections) {
- if (asect.Target != "assembly")
+ foreach (Attribute a in OptAttributes.AttributeSections) {
+ if (a.Target != "assembly")
continue;
// strongname attributes don't support AllowMultiple
- Attribute a = (Attribute) asect.Attributes [0];
+ //Attribute a = (Attribute) asect.Attributes [0];
switch (a.Name) {
case "AssemblyKeyFile":
if (RootContext.StrongNameKeyFile != null) {
public class ModuleClass: CommonAssemblyModulClass {
// TODO: make it private and move all builder based methods here
public ModuleBuilder Builder;
-
bool m_module_is_unsafe;
public ModuleClass (bool is_unsafe)
/// The current file.
///
SourceFile file;
+
+
+ /// Current attribute target
+ string current_attr_target;
+
+ /// assembly and module attribute definition is enabled
+ bool global_attrs_enabled = true;
%}
%token EOF
namespace_declaration
: opt_attributes NAMESPACE namespace_name
{
- Attributes attrs = (Attributes) $1;
-
- if (attrs != null) {
- foreach (AttributeSection asec in attrs.AttributeSections)
- if (asec.Target == "assembly")
- CodeGen.Assembly.AddAttribute (new GlobalAttributeSection (current_container, asec));
- else
- Report.Error(1518, Lexer.Location,
- "Attributes cannot be applied to namespaces."
+ if ($1 != null) {
+ Report.Error(1518, Lexer.Location, "Attributes cannot be applied to namespaces."
+ " Expected class, delegate, enum, interface, or struct");
}
opt_attributes
: /* empty */
- | attribute_sections { $$ = $1; }
+ {
+ global_attrs_enabled = false;
+ $$ = null;
+ }
+ | attribute_sections
+ {
+ global_attrs_enabled = false;
+ $$ = $1;
+ }
;
+
attribute_sections
: attribute_section
{
- AttributeSection sect = (AttributeSection) $1;
+ ArrayList sect = (ArrayList) $1;
- if (sect.Target == "assembly") {
- CodeGen.Assembly.AddAttribute (new GlobalAttributeSection (current_container, sect));
+ if (global_attrs_enabled) {
+ if (current_attr_target == "module") {
+ CodeGen.Module.AddAttributes (sect);
$$ = null;
- }
- else if (sect.Target == "module") {
- CodeGen.Module.AddAttribute (new GlobalAttributeSection (current_container, sect));
+ } else if (current_attr_target == "assembly") {
+ CodeGen.Assembly.AddAttributes (sect);
$$ = null;
+ } else {
+
+ // Because we don't know if target should be on assembly or type
+ // we add it to both. This leads error CS0657 is reported twice
+ // for this case but it is better than mistification.
+ CodeGen.Assembly.AddAttributes (sect);
+ $$ = new Attributes (sect);
}
- else
+ } else {
$$ = new Attributes (sect);
}
+ current_attr_target = null;
+ }
| attribute_sections attribute_section
{
Attributes attrs = $1 as Attributes;
- AttributeSection sect = (AttributeSection) $2;
+ ArrayList sect = (ArrayList) $2;
- if (sect.Target == "assembly") {
- CodeGen.Assembly.AddAttribute (new GlobalAttributeSection (current_container, sect));
- }
- else if (sect.Target == "module") {
- CodeGen.Module.AddAttribute (new GlobalAttributeSection (current_container, sect));
+ if (global_attrs_enabled) {
+ if (current_attr_target == "module") {
+ CodeGen.Module.AddAttributes (sect);
+ $$ = null;
+ } else if (current_attr_target == "assembly") {
+ CodeGen.Assembly.AddAttributes (sect);
+ $$ = null;
+ } else {
+ if (attrs == null)
+ attrs = new Attributes (sect);
+ else
+ attrs.AddAttributes (sect);
}
- else {
+ } else {
if (attrs == null)
attrs = new Attributes (sect);
else
- attrs.AddAttributeSection (sect);
+ attrs.AddAttributes (sect);
}
-
$$ = attrs;
+ current_attr_target = null;
}
;
attribute_section
: OPEN_BRACKET attribute_target_specifier attribute_list opt_comma CLOSE_BRACKET
{
- string target = null;
-
- if ($2 != null)
- target = (string) $2;
-
- $$ = new AttributeSection (target, (ArrayList) $3);
+ $$ = $3;
}
| OPEN_BRACKET attribute_list opt_comma CLOSE_BRACKET
{
- $$ = new AttributeSection (null, (ArrayList) $2);
+ $$ = $2;
}
;
attribute_target_specifier
: attribute_target COLON
{
+ current_attr_target = (string)$1;
$$ = $1;
}
;
//
// Attributes need a string, not an expression: generic types will fail here.
//
- $$ = new Attribute (((Expression) $1).ToString (), (ArrayList) $3, (Location) $2);
+ if (current_attr_target == "assembly" || current_attr_target == "module")
+ $$ = new GlobalAttribute (current_container, current_attr_target,
+ ((Expression) $1).ToString (),
+ (ArrayList) $3, (Location) $2);
+ else
+ $$ = new Attribute (current_attr_target, ((Expression) $1).ToString (),
+ (ArrayList) $3, (Location) $2);
}
;
interface_event_declaration
: opt_attributes opt_new EVENT type IDENTIFIER SEMICOLON
{
- $$ = new Event (current_container, (Expression) $4, (int) $2, true,
- new MemberName ((string) $5), null,
- (Attributes) $1, lexer.Location);
+ $$ = new EventField (current_container, (Expression) $4, (int) $2, true,
+ new MemberName ((string) $5), null,
+ (Attributes) $1, lexer.Location);
}
| opt_attributes opt_new EVENT type error {
CheckIdentifierToken (yyToken);
MemberName name = new MemberName (var.identifier);
- Event e = new Event (current_container, (Expression) $4, (int) $2,
- false, name, var.expression_or_array_initializer,
- (Attributes) $1, lexer.Location);
+ Event e = new EventField (current_container, (Expression) $4, (int) $2,
+ false, name,
+ var.expression_or_array_initializer,
+ (Attributes) $1, lexer.Location);
CheckDef (current_container.AddEvent (e), e.Name, e.Location);
MemberName name = type_name.GetMemberName ();
- Event e = new Event (current_container, (Expression) $4, (int) $2, false,
- name, null, (Attributes) $1, (Accessor) pair.First,
- (Accessor) pair.Second, loc);
+ Event e = new EventProperty (current_container, (Expression) $4, (int) $2,
+ false, name, null, (Attributes) $1,
+ (Accessor) pair.First, (Accessor) pair.Second,
+ loc);
CheckDef (current_container.AddEvent (e), e.Name, loc);
implicit_value_parameter_type = null;
TypeContainer parent;
+ static string[] attribute_targets = new string [] { "type" };
+
public DeclSpace (NamespaceEntry ns, TypeContainer parent, MemberName name,
Attributes attrs, Location l)
: base (name, attrs, l)
return new TypeExpression (TypeBuilder, Location);
}
}
+
+ protected override string[] ValidAttributeTargets {
+ get {
+ return attribute_targets;
+ }
+ }
}
/// <summary>
Type [] param_types;\r
Type ret_type;\r
\r
+ static string[] attribute_targets = new string [] { "type", "return" };\r
+\r
Expression instance_expr;\r
MethodBase delegate_method;\r
+ ReturnParameter return_attributes;\r
\r
const int AllowedModifiers =\r
Modifiers.NEW |\r
Parameters = param_list;\r
}\r
\r
+ public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)\r
+ {\r
+ if (a.Target == "return") {\r
+ if (return_attributes == null)\r
+ return_attributes = new ReturnParameter (InvokeBuilder, Location);\r
+\r
+ return_attributes.ApplyAttributeBuilder (a, cb);\r
+ return;\r
+ }\r
+\r
+ base.ApplyAttributeBuilder (a, cb);\r
+ }\r
+\r
public override TypeBuilder DefineType ()\r
{\r
if (TypeBuilder != null)\r
{\r
if (OptAttributes != null) {\r
EmitContext ec = new EmitContext (tc, this, Location, null, null, ModFlags, false);\r
+ Parameters.LabelParameters (ec, InvokeBuilder, Location);\r
OptAttributes.Emit (ec, this);\r
}\r
\r
base.Emit (tc);\r
}\r
\r
+ protected override string[] ValidAttributeTargets {\r
+ get {\r
+ return attribute_targets;\r
+ }\r
+ }\r
+\r
//TODO: duplicate\r
protected override bool VerifyClsCompliance (DeclSpace ds)\r
{\r
Enum parent;
Location loc;
+ static string[] attribute_targets = new string [] { "field" };
+
public FieldBuilder builder;
public EnumMember (string name, Enum parent, Location loc, Attributes attrs):
OptAttributes.Emit (ec, this);
}
+ protected override string[] ValidAttributeTargets {
+ get {
+ return attribute_targets;
+ }
+ }
}
/// <summary>
{
return false;
}
-
}
+ /// <summary>
+ /// Class for applying custom attributes on the return type
+ /// </summary>
public class ReturnParameter: ParameterBase {
- public ReturnParameter (Attributes attrs):
- base (attrs)
+ 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 {
}
}
- public void DefineParameter (EmitContext ec, MethodBuilder mb, Location loc)
+ /// <summary>
+ /// Is never called
+ /// </summary>
+ protected override string[] ValidAttributeTargets {
+ get {
+ return null;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Class for applying custom attributes on the parameter type.
+ /// ! Now it works only with 1st parameter (for properties and events)
+ /// </summary>
+ public class ParameterAtribute: ParameterBase {
+ public ParameterAtribute (MethodBuilder mb):
+ base (null)
{
- try {
- builder = mb.DefineParameter (0, ParameterAttributes.None, "");
- OptAttributes.Emit (ec, this);
- } catch (ArgumentOutOfRangeException) {
- Report.Warning (
- -24, loc,
- ".NET SDK 1.0 does not permit setting custom attributes" +
- " on the return type of a method");
+ 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>
ISBYREF = 8
}
+ static string[] attribute_targets = new string [] { "param" };
+
public readonly Expression TypeName;
public readonly Modifier ModFlags;
public readonly string Name;
}
}
}
+
+ protected override string[] ValidAttributeTargets {
+ get {
+ return attribute_targets;
+ }
+ }
}
/// <summary>
//
public void LabelParameters (EmitContext ec,
MethodBase builder,
- Attributes method_attrs,
Location loc) {
//
// Define each type attribute (in/out/ref) and
pb.SetCustomAttribute (a);
}
-
- //
- // And now for the return type attribute decoration
- //
-
- if (mb == null || method_attrs == null)
- return;
-
- Attributes ret_attrs = null;
- foreach (AttributeSection asec in method_attrs.AttributeSections) {
-
- if (asec.Target != "return")
- continue;
-
- if (ret_attrs == null)
- ret_attrs = new Attributes (asec);
- else
- ret_attrs.AddAttributeSection (asec);
- }
-
- if (ret_attrs != null) {
- ReturnParameter ret = new ReturnParameter (ret_attrs);
- ret.DefineParameter (ec, mb, loc);
- }
}
-
}
}
-
-
-
static string GetErrorMsg (int error_no)
{
switch (error_no) {
+ case 0657: return "'{0}' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are '{1}'";
case 3001: return "Argument type '{0}' is not CLS-compliant";
case 3002: return "Return type of '{0}' is not CLS-compliant";
case 3003: return "Type of '{0}' is not CLS-compliant";
{
switch (warn_no) {
case -24: return new WarningData (1, "The Microsoft Runtime cannot set this marshal info. Please use the Mono runtime instead.");
+ case -28: return new WarningData (1, "The Microsoft .NET Runtime 1.x does not permit setting custom attributes on the return type");
case 3012: return new WarningData (1, "You must specify the CLSCompliant attribute on the assembly, not the module, to enable CLS compliance checking");
case 3019: return new WarningData (2, "CLS compliance checking will not be performed on '{0}' because it is private or internal");
}