2005-01-26 Martin Baulig <martin@ximian.com>
[mono.git] / mcs / mbas / attribute.cs
index f8ac803132f0e11febad91bf3071f7918eefb1fa..9011ee653997a919a51b3cdb76d1d177bec3d6e0 100644 (file)
 //
 
 using System;
+using System.Diagnostics;
 using System.Collections;
+using System.Collections.Specialized;
 using System.Reflection;
 using System.Reflection.Emit;
 using System.Runtime.InteropServices;
 using System.Runtime.CompilerServices;
 using System.Text;
 
-namespace Mono.CSharp {
+namespace Mono.MonoBASIC {
 
+       /// <summary>
+       ///   Base class for objects that can have Attributes applied to them.
+       /// </summary>
+       public abstract class Attributable {
+               /// <summary>
+               ///   Attributes for this type
+               /// </summary>
+               Attributes attributes;
+
+               public Attributable(Attributes attrs)
+               {
+                       attributes = attrs;
+               }
+
+               public Attributes OptAttributes 
+               {
+                       get {
+                               return attributes;
+                       }
+                       set {
+                               attributes = value;
+                       }
+               }
+
+               /// <summary>
+               /// Use member-specific procedure to apply attribute @a in @cb to the entity being built in @builder
+               /// </summary>
+               public abstract void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb);
+               /// <summary>
+               /// Returns one AttributeTarget for this element.
+               /// </summary>
+               public abstract AttributeTargets AttributeTargets { get; }
+       };
        public class Attribute {
+               public readonly string ExplicitTarget;
                public readonly string    Name;
                public readonly ArrayList Arguments;
 
-               Location Location;
+               public Location Location;
 
                public Type Type;
-               
-               //
-               // The following are only meaningful when the attribute
-               // being emitted is one of the builtin ones
-               //
-               AttributeTargets Targets;
-               bool AllowMultiple;
-               bool Inherited;
 
-               bool UsageAttr = false;
+               // Is non-null if type is AttributeUsageAttribute
+               AttributeUsageAttribute usage_attribute;
+
+               public AttributeUsageAttribute UsageAttribute {
+                       get {
+                               return usage_attribute;
+                       }
+               }
+               
+               bool usage_attr = false;
                
                MethodImplOptions ImplOptions;
-               UnmanagedType     UnmanagedType;
+               public UnmanagedType     UnmanagedType;
                CustomAttributeBuilder cb;
-               
+
                public Attribute (string name, ArrayList args, Location loc)
                {
                        Name = name;
                        Arguments = args;
                        Location = loc;
                }
+               
+               public Attribute (string target, string name, ArrayList args, Location loc) 
+               {
+                       ExplicitTarget = target;
+               }
 
                void Error_InvalidNamedArgument (string name)
                {
@@ -98,6 +140,7 @@ namespace Mono.CSharp {
                                " missing a using directive or an assembly reference ?)");
                        return null;
                }
+               
 
                public Type ResolveType (EmitContext ec)
                {
@@ -116,10 +159,10 @@ namespace Mono.CSharp {
                        bool MethodImplAttr = false;
                        bool MarshalAsAttr = false;
 
-                       UsageAttr = false;
+                       usage_attr = false;
 
                        if (Type == TypeManager.attribute_usage_type)
-                               UsageAttr = true;
+                               usage_attr = true;
                        if (Type == TypeManager.methodimpl_attr_type)
                                MethodImplAttr = true;
                        if (Type == TypeManager.marshal_as_attr_type)
@@ -154,6 +197,7 @@ namespace Mono.CSharp {
                                        return null;
 
                                e = a.Expr;
+
                                if (e is Constant) {
                                        pos_values [i] = ((Constant) e).GetValue ();
                                } else if (e is TypeOf) {
@@ -163,8 +207,8 @@ namespace Mono.CSharp {
                                        return null;
                                }
                                
-                               if (UsageAttr)
-                                       this.Targets = (AttributeTargets) pos_values [0];
+                               if (usage_attr)
+                                       usage_attribute = new AttributeUsageAttribute ((AttributeTargets) pos_values [0]);
                                
                                if (MethodImplAttr)
                                        this.ImplOptions = (MethodImplOptions) pos_values [0];
@@ -217,14 +261,16 @@ namespace Mono.CSharp {
                                                object o = ((Constant) e).GetValue ();
                                                prop_values.Add (o);
                                                
-                                               if (UsageAttr) {
+                                               if (usage_attr) {
                                                        if (member_name == "AllowMultiple")
-                                                               this.AllowMultiple = (bool) o;
+                                                               usage_attribute.AllowMultiple = (bool) o;
                                                        if (member_name == "Inherited")
-                                                               this.Inherited = (bool) o;
+                                                               usage_attribute.Inherited = (bool) o;
                                                }
                                                
-                                       } else { 
+                                       } else if (e is TypeOf) {
+                                               prop_values.Add (((TypeOf) e).TypeArg);
+                                       } else {
                                                Error_AttributeArgumentNotValid ();
                                                return null;
                                        }
@@ -247,7 +293,9 @@ namespace Mono.CSharp {
                                                object value = ((Constant) e).GetValue ();
                                                
                                                field_values.Add (value);
-                                       } else { 
+                                       } else if (e is TypeOf) {
+                                               field_values.Add (((TypeOf) e).TypeArg);
+                                       } else {
                                                Error_AttributeArgumentNotValid ();
                                                return null;
                                        }
@@ -272,6 +320,23 @@ namespace Mono.CSharp {
                                Error_AttributeConstructorMismatch (Location);
                                return null;
                        }
+
+                       //
+                       // Now we perform some checks on the positional args as they
+                       // cannot be null for a constructor which expects a parameter
+                       // of type object
+                       //
+
+                       ParameterData pd = Invocation.GetParameterData (constructor);
+
+                       for (int j = 0; j < pos_arg_count; ++j) {
+                               Argument a = (Argument) pos_args [j];
+                               
+                               if (a.Expr is NullLiteral && pd.ParameterType (j) == TypeManager.object_type) {
+                                       Error_AttributeArgumentNotValid ();
+                                       return null;
+                               }
+                       }
                        
                        PropertyInfo [] prop_info_arr = new PropertyInfo [prop_infos.Count];
                        FieldInfo [] field_info_arr = new FieldInfo [field_infos.Count];
@@ -289,6 +354,11 @@ namespace Mono.CSharp {
                                        (ConstructorInfo) constructor, pos_values,
                                        prop_info_arr, prop_values_arr,
                                        field_info_arr, field_values_arr); 
+
+                       } catch (NullReferenceException) {
+                               // 
+                               // Don't know what to do here
+                               //
                        } catch {
                                //
                                // Sample:
@@ -305,33 +375,10 @@ namespace Mono.CSharp {
                        return cb;
                }
 
-               static string GetValidPlaces (Attribute attr)
+               public string GetValidTargets ()
                {
                        StringBuilder sb = new StringBuilder ();
-                       AttributeTargets targets = 0;
-                       
-                       TypeContainer a = TypeManager.LookupAttr (attr.Type);
-
-                       if (a == null) {
-                               
-                               System.Attribute [] attrs = null;
-                               
-                               try {
-                                       attrs = System.Attribute.GetCustomAttributes (attr.Type);
-                                       
-                               } catch {
-                                       Report.Error (-20, attr.Location, "Cannot find attribute type " + attr.Name +
-                                                     " (maybe you forgot to set the usage using the" +
-                                                     " AttributeUsage attribute ?).");
-                                       return null;
-                               }
-                                       
-                               foreach (System.Attribute tmp in attrs)
-                                       if (tmp is AttributeUsageAttribute) 
-                                               targets = ((AttributeUsageAttribute) tmp).ValidOn;
-                       } else
-                               targets = a.Targets;
-
+                       AttributeTargets targets = GetAttributeUsage ().ValidOn;
                        
                        if ((targets & AttributeTargets.Assembly) != 0)
                                sb.Append ("'assembly' ");
@@ -384,34 +431,14 @@ namespace Mono.CSharp {
                        Report.Error (
                                592, loc, "Attribute '" + a.Name +
                                "' is not valid on this declaration type. " +
-                               "It is valid on " + GetValidPlaces (a) + "declarations only.");
+                               "It is valid on " + a.GetValidTargets () + "declarations only.");
                }
 
                public static bool CheckAttribute (Attribute a, object element)
                {
-                       TypeContainer attr = TypeManager.LookupAttr (a.Type);
-                       AttributeTargets targets = 0;
-
-                       
-                       if (attr == null) {
+                       //TypeContainer attr = TypeManager.LookupClass (a.Type);
+                       AttributeTargets targets = a.GetAttributeUsage ().ValidOn;
 
-                               System.Attribute [] attrs = null;
-                               
-                               try {
-                                       attrs = System.Attribute.GetCustomAttributes (a.Type);
-
-                               } catch {
-                                       Report.Error (-20, a.Location, "Cannot find attribute type " + a.Name +
-                                                     " (maybe you forgot to set the usage using the" +
-                                                     " AttributeUsage attribute ?).");
-                                       return false;
-                               }
-                                       
-                               foreach (System.Attribute tmp in attrs)
-                                       if (tmp is AttributeUsageAttribute) 
-                                               targets = ((AttributeUsageAttribute) tmp).ValidOn;
-                       } else
-                               targets = attr.Targets;
 
                        if (element is Class) {
                                if ((targets & AttributeTargets.Class) != 0)
@@ -439,7 +466,7 @@ namespace Mono.CSharp {
                                        return true;
                                else
                                        return false;
-                       } else if (element is Event || element is InterfaceEvent) {
+                       } else if (element is Event /*|| element is InterfaceEvent*/) {
                                if ((targets & AttributeTargets.Event) != 0)
                                        return true;
                                else
@@ -454,7 +481,7 @@ namespace Mono.CSharp {
                                        return true;
                                else
                                        return false;
-                       } else if (element is Method || element is Operator || element is InterfaceMethod || element is Accessor) {
+                       } else if (element is Method || element is Accessor) {
                                if ((targets & AttributeTargets.Method) != 0)
                                        return true;
                                else
@@ -464,8 +491,8 @@ namespace Mono.CSharp {
                                        return true;
                                else
                                        return false;
-                       } else if (element is Property || element is Indexer ||
-                                  element is InterfaceProperty || element is InterfaceIndexer) {
+                       } else if (element is Property /* || element is Indexer ||
+                                  element is InterfaceProperty || element is InterfaceIndexer*/) {
                                if ((targets & AttributeTargets.Property) != 0)
                                        return true;
                                else
@@ -475,174 +502,195 @@ namespace Mono.CSharp {
                                        return true;
                                else
                                        return false;
-                       }
+                       } else if (element is ModuleBuilder){
+                                       if ((targets & AttributeTargets.Module) != 0)
+                                               return true;
+                                       else
+                                               return false;
+                               }  
 
                        return false;
                }
 
+               /// <summary>
+               /// Returns AttributeUsage attribute for this type
+               /// </summary>
+               public AttributeUsageAttribute GetAttributeUsage ()
+               {
+                       Class attr_class = (Class) TypeManager.LookupClass (Type);
+
+                       if (attr_class == null) {
+                               object[] usage_attr = Type.GetCustomAttributes (TypeManager.attribute_usage_type, true);
+                               return (AttributeUsageAttribute)usage_attr [0];
+                       }
+               
+                       return attr_class.AttributeUsage;
+               }
+
                //
-               // This method should be invoked to pull the IndexerName attribute from an
+               // This method should be invoked to pull the DefaultPropName attribute from an
                // Indexer if it exists.
                //
                public static string ScanForIndexerName (EmitContext ec, Attributes opt_attrs)
                {
                        if (opt_attrs == null)
                                return null;
-                       if (opt_attrs.AttributeSections == null)
-                               return null;
 
-                       foreach (AttributeSection asec in opt_attrs.AttributeSections) {
-                               if (asec.Attributes == null)
-                                       continue;
-
-                               foreach (Attribute a in asec.Attributes){
-                                       if (a.ResolveType (ec) == null)
-                                               return null;
+                       foreach (Attribute a in opt_attrs.Attrs) {
+                               if (a.ResolveType (ec) == null)
+                                       return null;
                                        
-                                       if (a.Type != TypeManager.indexer_name_type)
-                                               continue;
+                               if (a.Type != TypeManager.indexer_name_type)
+                                       continue;
 
-                                       //
-                                       // So we have found an IndexerName, pull the data out.
-                                       //
-                                       if (a.Arguments == null || a.Arguments [0] == null){
-                                               Error_AttributeConstructorMismatch (a.Location);
-                                               return null;
-                                       }
-                                       ArrayList pos_args = (ArrayList) a.Arguments [0];
-                                       if (pos_args.Count == 0){
-                                               Error_AttributeConstructorMismatch (a.Location);
-                                               return null;
-                                       }
+                               //
+                               // So we have found an DefaultPropName, pull the data out.
+                               //
+                               if (a.Arguments == null || a.Arguments [0] == null){
+                                       Error_AttributeConstructorMismatch (a.Location);
+                                       return null;
+                               }
+                               ArrayList pos_args = (ArrayList) a.Arguments [0];
+                               if (pos_args.Count == 0){
+                                       Error_AttributeConstructorMismatch (a.Location);
+                                       return null;
+                               }
                                        
-                                       Argument arg = (Argument) pos_args [0];
-                                       if (!arg.Resolve (ec, a.Location))
-                                               return null;
+                               Argument arg = (Argument) pos_args [0];
+                               if (!arg.Resolve (ec, a.Location))
+                                       return null;
                                        
-                                       Expression e = arg.Expr;
-                                       if (!(e is StringConstant)){
-                                               Error_AttributeConstructorMismatch (a.Location);
-                                               return null;
-                                       }
+                               Expression e = arg.Expr;
+                               if (!(e is StringConstant)){
+                                       Error_AttributeConstructorMismatch (a.Location);
+                                       return null;
+                               }
 
-                                       //
-                                       // Remove the attribute from the list
-                                       //
-                                       asec.Attributes.Remove (a);
+                               //
+                               // Remove the attribute from the list
+                               //
+                               opt_attrs.Attrs.Remove (a);
 
-                                       return (((StringConstant) e).Value);
-                               }
+                               return (((StringConstant) e).Value);
                        }
                        return null;
                }
+
+               //
+               // This pulls the condition name out of a Conditional attribute
+               //
+               public string Conditional_GetConditionName ()
+               {
+                       //
+                       // So we have a Conditional, pull the data out.
+                       //
+                       if (Arguments == null || Arguments [0] == null){
+                               Error_AttributeConstructorMismatch (Location);
+                               return null;
+                       }
+
+                       ArrayList pos_args = (ArrayList) Arguments [0];
+                       if (pos_args.Count != 1){
+                               Error_AttributeConstructorMismatch (Location);
+                               return null;
+                       }
+
+                       Argument arg = (Argument) pos_args [0]; 
+                       if (!(arg.Expr is StringConstant)){
+                               Error_AttributeConstructorMismatch (Location);
+                               return null;
+                       }
+
+                       return ((StringConstant) arg.Expr).Value;
+               }
+
+               //
+               // This pulls the obsolete message and error flag out of an Obsolete attribute
+               //
+               public string Obsolete_GetObsoleteMessage (out bool is_error)
+               {
+                       is_error = false;
+                       //
+                       // So we have an Obsolete, pull the data out.
+                       //
+                       if (Arguments == null || Arguments [0] == null)
+                               return "";
+
+                       ArrayList pos_args = (ArrayList) Arguments [0];
+                       if (pos_args.Count == 0)
+                               return "";
+                       else if (pos_args.Count > 2){
+                               Error_AttributeConstructorMismatch (Location);
+                               return null;
+                       }
+
+                       Argument arg = (Argument) pos_args [0]; 
+                       if (!(arg.Expr is StringConstant)){
+                               Error_AttributeConstructorMismatch (Location);
+                               return null;
+                       }
+
+                       if (pos_args.Count == 2){
+                               Argument arg2 = (Argument) pos_args [1];
+                               if (!(arg2.Expr is BoolConstant)){
+                                       Error_AttributeConstructorMismatch (Location);
+                                       return null;
+                               }
+                               is_error = ((BoolConstant) arg2.Expr).Value;
+                       }
+
+                       return ((StringConstant) arg.Expr).Value;
+               }
+
+               
+               /// <summary>
+               /// Emit attribute for Attributable symbol
+               /// </summary>
+               public void Emit (EmitContext ec, Attributable ias, ListDictionary emitted_attr)
+               {
+                       CustomAttributeBuilder cb = Resolve (ec);
+                       if (cb == null)
+                               return;
+               
+                       AttributeUsageAttribute usage_attr = GetAttributeUsage ();
+                       if ((usage_attr.ValidOn & ias.AttributeTargets) == 0) {
+                               Report.Error (592, Location, "Attribute" + Name + "is not valid on this declaration type. It is valid on " + GetValidTargets () + " declarations only.");
+                               return;
+                       }
                
+                       ias.ApplyAttributeBuilder (this, cb);
+               }
+
                //
                // Applies the attributes to the `builder'.
-               //
+               //                                                                      
                public static void ApplyAttributes (EmitContext ec, object builder, object kind,
                                                    Attributes opt_attrs, Location loc)
                {
                        if (opt_attrs == null)
                                return;
-                       if (opt_attrs.AttributeSections == null)
-                               return;
 
-                       foreach (AttributeSection asec in opt_attrs.AttributeSections) {
-                               if (asec.Attributes == null)
-                                       continue;
+                       foreach (Attribute a in opt_attrs.Attrs) {
+                               CustomAttributeBuilder cb = a.Resolve (ec);
 
-                               if (asec.Target == "assembly" && !(builder is AssemblyBuilder))
+                               if (cb == null)
                                        continue;
-                               
-                               foreach (Attribute a in asec.Attributes) {
-                                       CustomAttributeBuilder cb = a.Resolve (ec);
 
-                                       if (cb == null)
-                                               continue;
-
-                                       if (!(kind is TypeContainer))
-                                               if (!CheckAttribute (a, kind)) {
+                               if (!(kind is TypeContainer))
+                                       if (!CheckAttribute (a, kind)) {
                                                        Error_AttributeNotValidForElement (a, loc);
                                                        return;
-                                               }
+                                       }
 
-                                       if (kind is Method || kind is Operator || kind is InterfaceMethod ||
-                                           kind is Accessor) {
-                                               if (a.Type == TypeManager.methodimpl_attr_type) {
-                                                       if (a.ImplOptions == MethodImplOptions.InternalCall)
-                                                               ((MethodBuilder) builder).
-                                                               SetImplementationFlags (
-                                                                       MethodImplAttributes.InternalCall |
-                                                                       MethodImplAttributes.Runtime);
-                                               } else if (a.Type != TypeManager.dllimport_type){
+                               if (kind is Method || kind is Accessor) {
+                                       if (a.Type == TypeManager.methodimpl_attr_type) {
+                                               if (a.ImplOptions == MethodImplOptions.InternalCall)
+                                                               ((MethodBuilder) builder).SetImplementationFlags (MethodImplAttributes.InternalCall |   MethodImplAttributes.Runtime);
+                                       } else if (a.Type != TypeManager.dllimport_type){
                                                        ((MethodBuilder) builder).SetCustomAttribute (cb);
-                                               }
-                                       } else if (kind is Constructor) {
-                                               ((ConstructorBuilder) builder).SetCustomAttribute (cb);
-                                       } else if (kind is Field) {
-                                               ((FieldBuilder) builder).SetCustomAttribute (cb);
-                                       } else if (kind is Property || kind is Indexer ||
-                                                  kind is InterfaceProperty || kind is InterfaceIndexer) {
-                                               ((PropertyBuilder) builder).SetCustomAttribute (cb);
-                                       } else if (kind is Event || kind is InterfaceEvent) {
-                                               ((MyEventBuilder) builder).SetCustomAttribute (cb);
-                                       } else if (kind is ParameterBuilder) {
-
-                                               if (a.Type == TypeManager.marshal_as_attr_type) {
-                                                       UnmanagedMarshal marshal =
-                                                               UnmanagedMarshal.DefineUnmanagedMarshal (a.UnmanagedType);
-                                                       
-                                                       ((ParameterBuilder) builder).SetMarshal (marshal);
-                                               } else 
-                                                       ((ParameterBuilder) builder).SetCustomAttribute (cb);
-                                               
-                                       } else if (kind is Enum) {
-                                               ((TypeBuilder) builder).SetCustomAttribute (cb); 
-
-                                       } else if (kind is TypeContainer) {
-                                               TypeContainer tc = (TypeContainer) kind;
-                                               
-                                               if (a.UsageAttr) {
-                                                       tc.Targets = a.Targets;
-                                                       tc.AllowMultiple = a.AllowMultiple;
-                                                       tc.Inherited = a.Inherited;
-                                                       
-                                               } else if (a.Type == TypeManager.default_member_type) {
-                                                       if (tc.Indexers != null) {
-                                                               Report.Error (646, loc,
-                                                                     "Cannot specify the DefaultMember attribute on" +
-                                                                     " a type containing an indexer");
-                                                               return;
-                                                       }
-
-                                               } else {
-                                                       if (!CheckAttribute (a, kind)) {
-                                                               Error_AttributeNotValidForElement (a, loc);
-                                                               return;
-                                                       }
-                                               }
-
-                                               try {
-                                                       ((TypeBuilder) builder).SetCustomAttribute (cb);
-                                               } catch (System.ArgumentException) {
-                                                       Report.Warning (
-                                                               -21, loc,
-                                               "The CharSet named property on StructLayout\n"+
-                                               "\tdoes not work correctly on Microsoft.NET\n"+
-                                               "\tYou might want to remove the CharSet declaration\n"+
-                                               "\tor compile using the Mono runtime instead of the\n"+
-                                               "\tMicrosoft .NET runtime");
-                                               }
-                                               
-                                       } else if (kind is AssemblyBuilder){
-                                               ((AssemblyBuilder) builder).SetCustomAttribute (cb);
-                                       } else if (kind is ModuleBuilder) {
-                                               ((ModuleBuilder) builder).SetCustomAttribute (cb);
-                                       } else if (kind is FieldBuilder) {
-                                               ((FieldBuilder) builder).SetCustomAttribute (cb);
-                                       } else
-                                               throw new Exception ("Unknown kind: " + kind);
-                               }
+                                       }
+                               }  else
+                                       throw new Exception ("Unknown kind: " + kind);
                        }
                }
 
@@ -687,8 +735,8 @@ namespace Mono.CSharp {
                        CallingConvention cc = CallingConvention.Winapi;
                        CharSet charset = CharSet.Ansi;
                        bool preserve_sig = true;
-                       bool exact_spelling = false;
-                       bool set_last_err = false;
+                       /*bool exact_spelling = false;
+                       bool set_last_err = false;*/
                        string entry_point = null;
 
                        for (int i = 0; i < named_args.Count; i++) {
@@ -730,10 +778,10 @@ namespace Mono.CSharp {
                                                        charset = (CharSet) c.GetValue ();
                                                else if (member_name == "EntryPoint")
                                                        entry_point = (string) c.GetValue ();
-                                               else if (member_name == "SetLastError")
+                                               /*else if (member_name == "SetLastError")
                                                        set_last_err = (bool) c.GetValue ();
                                                else if (member_name == "ExactSpelling")
-                                                       exact_spelling = (bool) c.GetValue ();
+                                                       exact_spelling = (bool) c.GetValue ();*/
                                                else if (member_name == "PreserveSig")
                                                        preserve_sig = (bool) c.GetValue ();
                                        } else { 
@@ -744,8 +792,11 @@ namespace Mono.CSharp {
                                }
                        }
 
+                       if (entry_point == null)
+                               entry_point = name;
+                       
                        MethodBuilder mb = builder.DefinePInvokeMethod (
-                               name, dll_name, flags | MethodAttributes.HideBySig,
+                               name, dll_name, entry_point, flags | MethodAttributes.HideBySig,
                                CallingConventions.Standard,
                                ret_type,
                                param_types,
@@ -757,37 +808,51 @@ namespace Mono.CSharp {
                        
                        return mb;
                }
-               
+
+               public bool IsAssemblyAttribute {
+                       get {
+                               return ExplicitTarget == "assembly";
+                       }
+               }
+
+               public bool IsModuleAttribute {
+                       get {
+                               return ExplicitTarget == "module";
+                       }
+               }
        }
        
-       public class AttributeSection {
-               
-               public readonly string    Target;
-               public readonly ArrayList Attributes;
+       public class Attributes {
+               public ArrayList Attrs;
+               public Location Location;
                
-               public AttributeSection (string target, ArrayList attrs)
+               public Attributes (Attribute a)
                {
-                       Target = target;
-                       Attributes = attrs;
+                       Attrs = new ArrayList ();
+                       Attrs.Add (a);
                }
-               
-       }
 
-       public class Attributes {
-               public ArrayList AttributeSections;
-               public Location Location;
-
-               public Attributes (AttributeSection a, Location loc)
+               public Attributes (ArrayList attrs)
                {
-                       AttributeSections = new ArrayList ();
-                       AttributeSections.Add (a);
+                       Attrs = attrs;
+               }
 
+               public void Add (Attribute attr)
+               {
+                       Attrs.Add (attr);
                }
 
-               public void AddAttribute (AttributeSection a)
+               public void Add (ArrayList attrs)
                {
-                       if (a != null)
-                               AttributeSections.Add (a);
+                       Attrs.AddRange (attrs);
                }
+
+               public void Emit (EmitContext ec, Attributable ias)
+               {
+                       ListDictionary ld = new ListDictionary ();
+       
+                       foreach (Attribute a in Attrs)
+                               a.Emit (ec, ias, ld);
+               }
        }
 }