2003-07-16 Gonzalo Paniagua Javier <gonzalo@ximian.com>
[mono.git] / mcs / mbas / attribute.cs
index f714a5602b3bf72585273fd86858d7ac432edf89..bfe5a39da1d315cb6acddfeb61f9cb4724fc7f4d 100644 (file)
-//\r
-// attribute.cs: Attribute Handler\r
-//\r
-// Author: Ravi Pratap (ravi@ximian.com)\r
-//\r
-// Licensed under the terms of the GNU GPL\r
-//\r
-// (C) 2001 Ximian, Inc (http://www.ximian.com)\r
-//\r
-//\r
-\r
-using System;\r
-using System.Collections;\r
-using System.Reflection;\r
-using System.Reflection.Emit;\r
-using System.Runtime.InteropServices;\r
-using System.Runtime.CompilerServices;\r
-using System.Text;\r
-\r
-namespace Mono.CSharp {\r
-\r
-       public class Attribute {\r
-               public readonly string    Name;\r
-               public readonly ArrayList Arguments;\r
-\r
-               Location Location;\r
-\r
-               public Type Type;\r
-               \r
-               //\r
-               // The following are only meaningful when the attribute\r
-               // being emitted is one of the builtin ones\r
-               //\r
-               public AttributeTargets Targets;\r
-               public bool AllowMultiple;\r
-               public bool Inherited;\r
-\r
-               public bool UsageAttr = false;\r
-               \r
-               public MethodImplOptions ImplOptions;\r
-               public UnmanagedType     UnmanagedType;\r
-               \r
-               public Attribute (string name, ArrayList args, Location loc)\r
-               {\r
-                       Name = name;\r
-                       Arguments = args;\r
-                       Location = loc;\r
-               }\r
-\r
-               void error617 (string name)\r
-               {\r
-                       Report.Error (617, Location, "'" + name + "' is not a valid named attribute " +\r
-                                     "argument. Named attribute arguments must be fields which are not " +\r
-                                     "readonly, static or const, or properties with a set accessor which "+\r
-                                     "are not static.");\r
-               }\r
-\r
-               void error182 ()\r
-               {\r
-                       Report.Error (182, Location,\r
-                                     "An attribute argument must be a constant expression, typeof " +\r
-                                     "expression or array creation expression");\r
-               }\r
-\r
-               public CustomAttributeBuilder Resolve (EmitContext ec)\r
-               {\r
-                       string name = Name;\r
-                       bool MethodImplAttr = false;\r
-                       bool MarshalAsAttr = false;\r
-\r
-                       UsageAttr = false;\r
-\r
-                       if (Name.IndexOf ("Attribute") == -1)\r
-                               name = Name + "Attribute";\r
-                       else if (Name.LastIndexOf ("Attribute") == 0)\r
-                               name = Name + "Attribute";\r
-\r
-                       Type = RootContext.LookupType (ec.DeclSpace, name, false, Location);\r
-\r
-                       if (Type == null) {\r
-                               Report.Error (\r
-                                       246, Location, "Could not find attribute '" + Name + "' (are you" +\r
-                                       " missing a using directive or an assembly reference ?)");\r
-                               return null;\r
-                       }\r
-\r
-                       if (Type == TypeManager.attribute_usage_type)\r
-                               UsageAttr = true;\r
-                       if (Type == TypeManager.methodimpl_attr_type)\r
-                               MethodImplAttr = true;\r
-                       if (Type == TypeManager.marshal_as_attr_type)\r
-                               MarshalAsAttr = true;\r
-                       \r
-\r
-                       // Now we extract the positional and named arguments\r
-                       \r
-                       ArrayList pos_args = new ArrayList ();\r
-                       ArrayList named_args = new ArrayList ();\r
-                       \r
-                       if (Arguments != null) {\r
-                               pos_args = (ArrayList) Arguments [0];\r
-                               if (Arguments.Count > 1)\r
-                                       named_args = (ArrayList) Arguments [1];\r
-                       }\r
-                               \r
-                       object [] pos_values = new object [pos_args.Count];\r
-\r
-                       //\r
-                       // First process positional arguments \r
-                       //\r
-                       \r
-                       int i;\r
-                       for (i = 0; i < pos_args.Count; i++) {\r
-                               Argument a = (Argument) pos_args [i];\r
-                               Expression e;\r
-\r
-                               if (!a.Resolve (ec, Location))\r
-                                       return null;\r
-\r
-                               e = a.Expr;\r
-                               if (e is Constant) {\r
-                                       pos_values [i] = ((Constant) e).GetValue ();\r
-\r
-                                       if (UsageAttr)\r
-                                               this.Targets = (AttributeTargets) pos_values [0];\r
-\r
-                                       if (MethodImplAttr)\r
-                                               this.ImplOptions = (MethodImplOptions) pos_values [0];\r
-\r
-                                       if (MarshalAsAttr)\r
-                                               this.UnmanagedType = (System.Runtime.InteropServices.UnmanagedType) pos_values [0];\r
-                                       \r
-                               } else { \r
-                                       error182 ();\r
-                                       return null;\r
-                               }\r
-                       }\r
-\r
-                       //\r
-                       // Now process named arguments\r
-                       //\r
-\r
-                       ArrayList field_infos = new ArrayList ();\r
-                       ArrayList prop_infos  = new ArrayList ();\r
-                       ArrayList field_values = new ArrayList ();\r
-                       ArrayList prop_values = new ArrayList ();\r
-                       \r
-                       for (i = 0; i < named_args.Count; i++) {\r
-                               DictionaryEntry de = (DictionaryEntry) named_args [i];\r
-                               string member_name = (string) de.Key;\r
-                               Argument a  = (Argument) de.Value;\r
-                               Expression e;\r
-                               \r
-                               if (!a.Resolve (ec, Location))\r
-                                       return null;\r
-\r
-                               Expression member = Expression.MemberLookup (\r
-                                       ec, Type, member_name,\r
-                                       MemberTypes.Field | MemberTypes.Property,\r
-                                       BindingFlags.Public | BindingFlags.Instance,\r
-                                       Location);\r
-\r
-                               if (member == null || !(member is PropertyExpr || member is FieldExpr)) {\r
-                                       error617 (member_name);\r
-                                       return null;\r
-                               }\r
-\r
-                               e = a.Expr;\r
-                               if (member is PropertyExpr) {\r
-                                       PropertyExpr pe = (PropertyExpr) member;\r
-                                       PropertyInfo pi = pe.PropertyInfo;\r
-\r
-                                       if (!pi.CanWrite) {\r
-                                               error617 (member_name);\r
-                                               return null;\r
-                                       }\r
-\r
-                                       if (e is Constant) {\r
-                                               object o = ((Constant) e).GetValue ();\r
-                                               prop_values.Add (o);\r
-                                               \r
-                                               if (UsageAttr) {\r
-                                                       if (member_name == "AllowMultiple")\r
-                                                               this.AllowMultiple = (bool) o;\r
-                                                       if (member_name == "Inherited")\r
-                                                               this.Inherited = (bool) o;\r
-                                               }\r
-                                               \r
-                                       } else { \r
-                                               error182 ();\r
-                                               return null;\r
-                                       }\r
-                                       \r
-                                       prop_infos.Add (pi);\r
-                                       \r
-                               } else if (member is FieldExpr) {\r
-                                       FieldExpr fe = (FieldExpr) member;\r
-                                       FieldInfo fi = fe.FieldInfo;\r
-\r
-                                       if (fi.IsInitOnly) {\r
-                                               error617 (member_name);\r
-                                               return null;\r
-                                       }\r
-\r
-                                       if (e is Constant)\r
-                                               field_values.Add (((Constant) e).GetValue ());\r
-                                       else { \r
-                                               error182 ();\r
-                                               return null;\r
-                                       }\r
-                                       \r
-                                       field_infos.Add (fi);\r
-                               }\r
-                       }\r
-                       \r
-                       Expression mg = Expression.MemberLookup (\r
-                               ec, Type, ".ctor", MemberTypes.Constructor,\r
-                               BindingFlags.Public | BindingFlags.Instance, Location);\r
-\r
-                       if (mg == null) {\r
-                               Report.Error (\r
-                                       -6, Location,\r
-                                       "Could not find a constructor for this argument list.");\r
-                               return null;\r
-                       }\r
-\r
-                       MethodBase constructor = Invocation.OverloadResolve (\r
-                               ec, (MethodGroupExpr) mg, pos_args, Location);\r
-\r
-                       if (constructor == null) {\r
-                               Report.Error (\r
-                                       -6, Location,\r
-                                       "Could not find a constructor for this argument list.");\r
-                               return null;\r
-                       }\r
-                       \r
-                       PropertyInfo [] prop_info_arr = new PropertyInfo [prop_infos.Count];\r
-                       FieldInfo [] field_info_arr = new FieldInfo [field_infos.Count];\r
-                       object [] field_values_arr = new object [field_values.Count];\r
-                       object [] prop_values_arr = new object [prop_values.Count];\r
-\r
-                       field_infos.CopyTo  (field_info_arr, 0);\r
-                       field_values.CopyTo (field_values_arr, 0);\r
-\r
-                       prop_values.CopyTo  (prop_values_arr, 0);\r
-                       prop_infos.CopyTo   (prop_info_arr, 0);\r
-                       \r
-                       CustomAttributeBuilder cb = new CustomAttributeBuilder (\r
-                               (ConstructorInfo) constructor, pos_values,\r
-                               prop_info_arr, prop_values_arr,\r
-                               field_info_arr, field_values_arr); \r
-                       \r
-                       return cb;\r
-               }\r
-\r
-               static string GetValidPlaces (Attribute attr)\r
-               {\r
-                       StringBuilder sb = new StringBuilder ();\r
-                       AttributeTargets targets = 0;\r
-                       \r
-                       TypeContainer a = TypeManager.LookupAttr (attr.Type);\r
-\r
-                       if (a == null) {\r
-                               System.Attribute [] attrs = System.Attribute.GetCustomAttributes (attr.Type);\r
-                               \r
-                               foreach (System.Attribute tmp in attrs)\r
-                                       if (tmp is AttributeUsageAttribute) \r
-                                               targets = ((AttributeUsageAttribute) tmp).ValidOn;\r
-                       } else\r
-                               targets = a.Targets;\r
-\r
-                       \r
-                       if ((targets & AttributeTargets.Assembly) != 0)\r
-                               sb.Append ("'assembly' ");\r
-\r
-                       if ((targets & AttributeTargets.Class) != 0)\r
-                               sb.Append ("'class' ");\r
-\r
-                       if ((targets & AttributeTargets.Constructor) != 0)\r
-                               sb.Append ("'constructor' ");\r
-\r
-                       if ((targets & AttributeTargets.Delegate) != 0)\r
-                               sb.Append ("'delegate' ");\r
-\r
-                       if ((targets & AttributeTargets.Enum) != 0)\r
-                               sb.Append ("'enum' ");\r
-\r
-                       if ((targets & AttributeTargets.Event) != 0)\r
-                               sb.Append ("'event' ");\r
-\r
-                       if ((targets & AttributeTargets.Field) != 0)\r
-                               sb.Append ("'field' ");\r
-\r
-                       if ((targets & AttributeTargets.Interface) != 0)\r
-                               sb.Append ("'interface' ");\r
-\r
-                       if ((targets & AttributeTargets.Method) != 0)\r
-                               sb.Append ("'method' ");\r
-\r
-                       if ((targets & AttributeTargets.Module) != 0)\r
-                               sb.Append ("'module' ");\r
-\r
-                       if ((targets & AttributeTargets.Parameter) != 0)\r
-                               sb.Append ("'parameter' ");\r
-\r
-                       if ((targets & AttributeTargets.Property) != 0)\r
-                               sb.Append ("'property' ");\r
-\r
-                       if ((targets & AttributeTargets.ReturnValue) != 0)\r
-                               sb.Append ("'return value' ");\r
-\r
-                       if ((targets & AttributeTargets.Struct) != 0)\r
-                               sb.Append ("'struct' ");\r
-\r
-                       return sb.ToString ();\r
-\r
-               }\r
-\r
-               public static void error592 (Attribute a, Location loc)\r
-               {\r
-                       Report.Error (\r
-                               592, loc, "Attribute '" + a.Name +\r
-                               "' is not valid on this declaration type. " +\r
-                               "It is valid on " + GetValidPlaces (a) + "declarations only.");\r
-               }\r
-\r
-               public static bool CheckAttribute (Attribute a, object element)\r
-               {\r
-                       TypeContainer attr = TypeManager.LookupAttr (a.Type);\r
-                       AttributeTargets targets = 0;\r
-                       \r
-                       if (attr == null) {\r
-                               System.Attribute [] attrs = System.Attribute.GetCustomAttributes (a.Type);\r
-\r
-                               foreach (System.Attribute tmp in attrs)\r
-                                       if (tmp is AttributeUsageAttribute) \r
-                                               targets = ((AttributeUsageAttribute) tmp).ValidOn;\r
-                       } else\r
-                               targets = attr.Targets;\r
-\r
-                       if (element is Class) {\r
-                               if ((targets & AttributeTargets.Class) != 0)\r
-                                       return true;\r
-                               else\r
-                                       return false;\r
-                               \r
-                       } else if (element is Struct) {\r
-                               if ((targets & AttributeTargets.Struct) != 0)\r
-                                       return true;\r
-                               else\r
-                                       return false;\r
-                       } else if (element is Constructor) {\r
-                               if ((targets & AttributeTargets.Constructor) != 0)\r
-                                       return true;\r
-                               else\r
-                                       return false;\r
-                       } else if (element is Delegate) {\r
-                               if ((targets & AttributeTargets.Delegate) != 0)\r
-                                       return true;\r
-                               else\r
-                                       return false;\r
-                       } else if (element is Enum) {\r
-                               if ((targets & AttributeTargets.Enum) != 0)\r
-                                       return true;\r
-                               else\r
-                                       return false;\r
-                       } else if (element is Event) {\r
-                               if ((targets & AttributeTargets.Event) != 0)\r
-                                       return true;\r
-                               else\r
-                                       return false;\r
-                       } else if (element is Field) {\r
-                               if ((targets & AttributeTargets.Field) != 0)\r
-                                       return true;\r
-                               else\r
-                                       return false;\r
-                       } else if (element is Interface) {\r
-                               if ((targets & AttributeTargets.Interface) != 0)\r
-                                       return true;\r
-                               else\r
-                                       return false;\r
-                       } else if (element is Method || element is Operator) {\r
-                               if ((targets & AttributeTargets.Method) != 0)\r
-                                       return true;\r
-                               else\r
-                                       return false;\r
-                       } else if (element is ParameterBuilder) {\r
-                               if ((targets & AttributeTargets.Parameter) != 0)\r
-                                       return true;\r
-                               else\r
-                                       return false;\r
-                       } else if (element is Property) {\r
-                               if ((targets & AttributeTargets.Property) != 0)\r
-                                       return true;\r
-                               else\r
-                                       return false;\r
-                       } else if (element is AssemblyBuilder){\r
-                               if ((targets & AttributeTargets.Assembly) != 0)\r
-                                       return true;\r
-                               else\r
-                                       return false;\r
-                       }\r
-\r
-                       return false;\r
-               }\r
-\r
-               public static void ApplyAttributes (EmitContext ec, object builder, object kind,\r
-                                                   Attributes opt_attrs, Location loc)\r
-               {\r
-                       if (opt_attrs == null)\r
-                               return;\r
-\r
-                       if (opt_attrs.AttributeSections == null)\r
-                               return;\r
-\r
-                       foreach (AttributeSection asec in opt_attrs.AttributeSections) {\r
-\r
-                               if (asec.Attributes == null)\r
-                                       continue;\r
-\r
-                               foreach (Attribute a in asec.Attributes) {\r
-                                       CustomAttributeBuilder cb = a.Resolve (ec);\r
-                                       if (cb == null)\r
-                                               continue;\r
-\r
-                                       if (!(kind is TypeContainer))\r
-                                               if (!CheckAttribute (a, kind)) {\r
-                                                       error592 (a, loc);\r
-                                                       return;\r
-                                               }\r
-\r
-                                       \r
-                                       if (kind is Method || kind is Operator) {\r
-\r
-                                               if (a.Type == TypeManager.methodimpl_attr_type) {\r
-                                                       if (a.ImplOptions == MethodImplOptions.InternalCall)\r
-                                                               ((MethodBuilder) builder).SetImplementationFlags (\r
-                                                                          MethodImplAttributes.InternalCall |\r
-                                                                          MethodImplAttributes.Runtime);\r
-                                               } else if (a.Type != TypeManager.dllimport_type)\r
-                                                       ((MethodBuilder) builder).SetCustomAttribute (cb);\r
-\r
-                                       } else if (kind is Constructor) {\r
-                                               ((ConstructorBuilder) builder).SetCustomAttribute (cb);\r
-                                       } else if (kind is Field) {\r
-                                               ((FieldBuilder) builder).SetCustomAttribute (cb);\r
-                                       } else if (kind is Property || kind is Indexer) {\r
-                                               ((PropertyBuilder) builder).SetCustomAttribute (cb);\r
-                                       } else if (kind is Event) {\r
-                                               ((EventBuilder) builder).SetCustomAttribute (cb);\r
-                                       } else if (kind is ParameterBuilder) {\r
-\r
-                                               if (a.Type == TypeManager.marshal_as_attr_type) {\r
-                                                       UnmanagedMarshal marshal =\r
-                                                               UnmanagedMarshal.DefineUnmanagedMarshal (a.UnmanagedType);\r
-                                                       \r
-                                                       ((ParameterBuilder) builder).SetMarshal (marshal);\r
-                                               } else \r
-                                                       ((ParameterBuilder) builder).SetCustomAttribute (cb);\r
-                                               \r
-                                       } else if (kind is Enum) {\r
-                                               ((TypeBuilder) builder).SetCustomAttribute (cb); \r
-\r
-                                       } else if (kind is TypeContainer) {\r
-\r
-                                               TypeContainer tc = (TypeContainer) kind;\r
-                                               \r
-                                               if (a.UsageAttr) {\r
-                                                       tc.Targets = a.Targets;\r
-                                                       tc.AllowMultiple = a.AllowMultiple;\r
-                                                       tc.Inherited = a.Inherited;\r
-                                                       \r
-                                                       RootContext.TypeManager.RegisterAttrType (\r
-                                                                                (TypeBuilder) builder, tc);\r
-\r
-                                               } else if (a.Type == TypeManager.default_member_type) {\r
-                                                       if (tc.Indexers != null) {\r
-                                                               Report.Error (646, loc,\r
-                                                                     "Cannot specify the DefaultMember attribute on " +\r
-                                                                     " a type containing an indexer");\r
-                                                               return;\r
-                                                       }\r
-\r
-                                               } else {\r
-                                                       if (!CheckAttribute (a, kind)) {\r
-                                                               error592 (a, loc);\r
-                                                               return;\r
-                                                       }\r
-                                               }\r
-                                               \r
-                                               ((TypeBuilder) builder).SetCustomAttribute (cb);\r
-                                               \r
-                                       } else if (kind is AssemblyBuilder){\r
-                                               ((AssemblyBuilder) builder).SetCustomAttribute (cb);\r
-                                       } else if (kind is ModuleBuilder) {\r
-                                               ((ModuleBuilder) builder).SetCustomAttribute (cb);\r
-                                       } else\r
-                                               throw new Exception ("Unknown kind: " + kind);\r
-                               }\r
-                       }\r
-               }\r
-\r
-               public MethodBuilder DefinePInvokeMethod (EmitContext ec, TypeBuilder builder, string name,\r
-                                                         MethodAttributes flags, Type ret_type, Type [] param_types)\r
-               {\r
-                       //\r
-                       // We extract from the attribute the information we need \r
-                       //\r
-\r
-                       if (Arguments == null) {\r
-                               Console.WriteLine ("Internal error : this is not supposed to happen !");\r
-                               return null;\r
-                       }\r
-\r
-                       string attr_name = Name;\r
-\r
-                       if (Name.IndexOf ("Attribute") == -1)\r
-                               attr_name = Name + "Attribute";\r
-                       else if (Name.LastIndexOf ("Attribute") == 0)\r
-                               attr_name = Name + "Attribute";\r
-                       \r
-                       Type = RootContext.LookupType (ec.DeclSpace, attr_name, false, Location);\r
-\r
-                       if (Type == null) {\r
-                               Report.Error (246, Location, "Could not find attribute '" + Name + "' (are you" +\r
-                                             " missing a using directive or an assembly reference ?)");\r
-                               return null;\r
-                       }\r
-                       \r
-                       ArrayList named_args = new ArrayList ();\r
-                       \r
-                       ArrayList pos_args = (ArrayList) Arguments [0];\r
-                       if (Arguments.Count > 1)\r
-                               named_args = (ArrayList) Arguments [1];\r
-                       \r
-\r
-                       string dll_name = null;\r
-                       \r
-                       Argument tmp = (Argument) pos_args [0];\r
-\r
-                       if (!tmp.Resolve (ec, Location))\r
-                               return null;\r
-                       \r
-                       if (tmp.Expr is Constant)\r
-                               dll_name = (string) ((Constant) tmp.Expr).GetValue ();\r
-                       else { \r
-                               error182 ();\r
-                               return null;\r
-                       }\r
-\r
-                       // Now we process the named arguments\r
-                       CallingConvention cc = CallingConvention.Winapi;\r
-                       CharSet charset = CharSet.Ansi;\r
-                       bool preserve_sig = true;\r
-                       bool exact_spelling = false;\r
-                       bool set_last_err = false;\r
-                       string entry_point = null;\r
-\r
-                       for (int i = 0; i < named_args.Count; i++) {\r
-\r
-                               DictionaryEntry de = (DictionaryEntry) named_args [i];\r
-\r
-                               string member_name = (string) de.Key;\r
-                               Argument a  = (Argument) de.Value;\r
-\r
-                               if (!a.Resolve (ec, Location))\r
-                                       return null;\r
-\r
-                               Expression member = Expression.MemberLookup (\r
-                                       ec, Type, member_name, \r
-                                       MemberTypes.Field | MemberTypes.Property,\r
-                                       BindingFlags.Public | BindingFlags.Instance,\r
-                                       Location);\r
-\r
-                               if (member == null || !(member is FieldExpr)) {\r
-                                       error617 (member_name);\r
-                                       return null;\r
-                               }\r
-\r
-                               if (member is FieldExpr) {\r
-                                       FieldExpr fe = (FieldExpr) member;\r
-                                       FieldInfo fi = fe.FieldInfo;\r
-\r
-                                       if (fi.IsInitOnly) {\r
-                                               error617 (member_name);\r
-                                               return null;\r
-                                       }\r
-\r
-                                       if (a.Expr is Constant) {\r
-                                               Constant c = (Constant) a.Expr;\r
-                                               \r
-                                               if (member_name == "CallingConvention")\r
-                                                       cc = (CallingConvention) c.GetValue ();\r
-                                               else if (member_name == "CharSet")\r
-                                                       charset = (CharSet) c.GetValue ();\r
-                                               else if (member_name == "EntryPoint")\r
-                                                       entry_point = (string) c.GetValue ();\r
-                                               else if (member_name == "SetLastError")\r
-                                                       set_last_err = (bool) c.GetValue ();\r
-                                               else if (member_name == "ExactSpelling")\r
-                                                       exact_spelling = (bool) c.GetValue ();\r
-                                               else if (member_name == "PreserveSig")\r
-                                                       preserve_sig = (bool) c.GetValue ();\r
-                                       } else { \r
-                                               error182 ();\r
-                                               return null;\r
-                                       }\r
-                                       \r
-                               }\r
-                       }\r
-\r
-                       MethodBuilder mb = builder.DefinePInvokeMethod (\r
-                               name, dll_name, flags | MethodAttributes.HideBySig,\r
-                               CallingConventions.Standard,\r
-                               ret_type,\r
-                               param_types,\r
-                               cc,\r
-                               charset);\r
-\r
-                       if (preserve_sig)\r
-                               mb.SetImplementationFlags (MethodImplAttributes.PreserveSig);\r
-                       \r
-                       return mb;\r
-               }\r
-               \r
-       }\r
-       \r
-       public class AttributeSection {\r
-               \r
-               public readonly string    Target;\r
-               public readonly ArrayList Attributes;\r
-               \r
-               public AttributeSection (string target, ArrayList attrs)\r
-               {\r
-                       Target = target;\r
-                       Attributes = attrs;\r
-               }\r
-               \r
-       }\r
-\r
-       public class Attributes {\r
-               public ArrayList AttributeSections;\r
-               public Location Location;\r
-\r
-               public Attributes (AttributeSection a, Location loc)\r
-               {\r
-                       AttributeSections = new ArrayList ();\r
-                       AttributeSections.Add (a);\r
-\r
-               }\r
-\r
-               public void AddAttribute (AttributeSection a)\r
-               {\r
-                       if (a != null)\r
-                               AttributeSections.Add (a);\r
-               }\r
-       }\r
-}\r
+//
+// attribute.cs: Attribute Handler
+//
+// Author: Ravi Pratap (ravi@ximian.com)
+//
+// Licensed under the terms of the GNU GPL
+//
+// (C) 2001 Ximian, Inc (http://www.ximian.com)
+//
+//
+
+using System;
+using System.Diagnostics;
+using System.Collections;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using System.Text;
+
+namespace Mono.CSharp {
+
+       public class Attribute {
+               public readonly string    Name;
+               public readonly ArrayList Arguments;
+
+               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;
+               
+               MethodImplOptions ImplOptions;
+               UnmanagedType     UnmanagedType;
+               CustomAttributeBuilder cb;
+               
+               public Attribute (string name, ArrayList args, Location loc)
+               {
+                       Name = name;
+                       Arguments = args;
+                       Location = loc;
+               }
+
+               void Error_InvalidNamedArgument (string name)
+               {
+                       Report.Error (617, Location, "'" + name + "' is not a valid named attribute " +
+                                     "argument. Named attribute arguments must be fields which are not " +
+                                     "readonly, static or const, or properties with a set accessor which "+
+                                     "are not static.");
+               }
+
+               void Error_AttributeArgumentNotValid ()
+               {
+                       Report.Error (182, Location,
+                                     "An attribute argument must be a constant expression, typeof " +
+                                     "expression or array creation expression");
+               }
+
+               static void Error_AttributeConstructorMismatch (Location loc)
+               {
+                       Report.Error (
+                                       -6, loc,
+                                       "Could not find a constructor for this argument list.");
+               }
+               
+               private Type CheckAttributeType (EmitContext ec) {
+                       Type t;
+                       bool isattributeclass = true;
+                       
+                       t = RootContext.LookupType (ec.DeclSpace, Name, true, Location);
+                       if (t != null) {
+                               isattributeclass = t.IsSubclassOf (TypeManager.attribute_type);
+                               if (isattributeclass)
+                                       return t;
+                       }
+                       t = RootContext.LookupType (ec.DeclSpace, Name + "Attribute", true, Location);
+                       if (t != null) {
+                               if (t.IsSubclassOf (TypeManager.attribute_type))
+                                       return t;
+                       }
+                       if (!isattributeclass) {
+                               Report.Error (616, Location, "'" + Name + "': is not an attribute class");
+                               return null;
+                       }
+                       if (t != null) {
+                               Report.Error (616, Location, "'" + Name + "Attribute': is not an attribute class");
+                               return null;
+                       }
+                       Report.Error (
+                               246, Location, "Could not find attribute '" + Name + "' (are you" +
+                               " missing a using directive or an assembly reference ?)");
+                       return null;
+               }
+
+               public Type ResolveType (EmitContext ec)
+               {
+                       Type = CheckAttributeType (ec);
+                       return Type;
+               }
+
+               
+               public CustomAttributeBuilder Resolve (EmitContext ec)
+               {
+                       if (Type == null)
+                               Type = CheckAttributeType (ec);
+                       if (Type == null)
+                               return null;
+
+                       bool MethodImplAttr = false;
+                       bool MarshalAsAttr = false;
+
+                       UsageAttr = false;
+
+                       if (Type == TypeManager.attribute_usage_type)
+                               UsageAttr = true;
+                       if (Type == TypeManager.methodimpl_attr_type)
+                               MethodImplAttr = true;
+                       if (Type == TypeManager.marshal_as_attr_type)
+                               MarshalAsAttr = true;
+
+                       // Now we extract the positional and named arguments
+                       
+                       ArrayList pos_args = new ArrayList ();
+                       ArrayList named_args = new ArrayList ();
+                       int pos_arg_count = 0;
+                       
+                       if (Arguments != null) {
+                               pos_args = (ArrayList) Arguments [0];
+                               if (pos_args != null)
+                                       pos_arg_count = pos_args.Count;
+                               if (Arguments.Count > 1)
+                                       named_args = (ArrayList) Arguments [1];
+                       }
+
+                       object [] pos_values = new object [pos_arg_count];
+
+                       //
+                       // First process positional arguments 
+                       //
+
+                       int i;
+                       for (i = 0; i < pos_arg_count; i++) {
+                               Argument a = (Argument) pos_args [i];
+                               Expression e;
+
+                               if (!a.Resolve (ec, Location))
+                                       return null;
+
+                               e = a.Expr;
+
+                               if (e is Constant) {
+                                       pos_values [i] = ((Constant) e).GetValue ();
+                               } else if (e is TypeOf) {
+                                       pos_values [i] = ((TypeOf) e).TypeArg;
+                               } else {
+                                       Error_AttributeArgumentNotValid ();
+                                       return null;
+                               }
+                               
+                               if (UsageAttr)
+                                       this.Targets = (AttributeTargets) pos_values [0];
+                               
+                               if (MethodImplAttr)
+                                       this.ImplOptions = (MethodImplOptions) pos_values [0];
+                               
+                               if (MarshalAsAttr)
+                                       this.UnmanagedType =
+                                       (System.Runtime.InteropServices.UnmanagedType) pos_values [0];
+                       }
+
+                       //
+                       // Now process named arguments
+                       //
+
+                       ArrayList field_infos = new ArrayList ();
+                       ArrayList prop_infos  = new ArrayList ();
+                       ArrayList field_values = new ArrayList ();
+                       ArrayList prop_values = new ArrayList ();
+                       
+                       for (i = 0; i < named_args.Count; i++) {
+                               DictionaryEntry de = (DictionaryEntry) named_args [i];
+                               string member_name = (string) de.Key;
+                               Argument a  = (Argument) de.Value;
+                               Expression e;
+                               
+                               if (!a.Resolve (ec, Location))
+                                       return null;
+
+                               Expression member = Expression.MemberLookup (
+                                       ec, Type, member_name,
+                                       MemberTypes.Field | MemberTypes.Property,
+                                       BindingFlags.Public | BindingFlags.Instance,
+                                       Location);
+
+                               if (member == null || !(member is PropertyExpr || member is FieldExpr)) {
+                                       Error_InvalidNamedArgument (member_name);
+                                       return null;
+                               }
+
+                               e = a.Expr;
+                               if (member is PropertyExpr) {
+                                       PropertyExpr pe = (PropertyExpr) member;
+                                       PropertyInfo pi = pe.PropertyInfo;
+
+                                       if (!pi.CanWrite) {
+                                               Error_InvalidNamedArgument (member_name);
+                                               return null;
+                                       }
+
+                                       if (e is Constant) {
+                                               object o = ((Constant) e).GetValue ();
+                                               prop_values.Add (o);
+                                               
+                                               if (UsageAttr) {
+                                                       if (member_name == "AllowMultiple")
+                                                               this.AllowMultiple = (bool) o;
+                                                       if (member_name == "Inherited")
+                                                               this.Inherited = (bool) o;
+                                               }
+                                               
+                                       } else if (e is TypeOf) {
+                                               prop_values.Add (((TypeOf) e).TypeArg);
+                                       } else {
+                                               Error_AttributeArgumentNotValid ();
+                                               return null;
+                                       }
+                                       
+                                       prop_infos.Add (pi);
+                                       
+                               } else if (member is FieldExpr) {
+                                       FieldExpr fe = (FieldExpr) member;
+                                       FieldInfo fi = fe.FieldInfo;
+
+                                       if (fi.IsInitOnly) {
+                                               Error_InvalidNamedArgument (member_name);
+                                               return null;
+                                       }
+
+                                       //
+                                       // Handle charset here, and set the TypeAttributes
+                                       
+                                       if (e is Constant){
+                                               object value = ((Constant) e).GetValue ();
+                                               
+                                               field_values.Add (value);
+                                       } else if (e is TypeOf) {
+                                               field_values.Add (((TypeOf) e).TypeArg);
+                                       } else {
+                                               Error_AttributeArgumentNotValid ();
+                                               return null;
+                                       }
+                                       
+                                       field_infos.Add (fi);
+                               }
+                       }
+
+                       Expression mg = Expression.MemberLookup (
+                               ec, Type, ".ctor", MemberTypes.Constructor,
+                               BindingFlags.Public | BindingFlags.Instance, Location);
+
+                       if (mg == null) {
+                               Error_AttributeConstructorMismatch (Location);
+                               return null;
+                       }
+
+                       MethodBase constructor = Invocation.OverloadResolve (
+                               ec, (MethodGroupExpr) mg, pos_args, Location);
+
+                       if (constructor == null) {
+                               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];
+                       object [] field_values_arr = new object [field_values.Count];
+                       object [] prop_values_arr = new object [prop_values.Count];
+
+                       field_infos.CopyTo  (field_info_arr, 0);
+                       field_values.CopyTo (field_values_arr, 0);
+
+                       prop_values.CopyTo  (prop_values_arr, 0);
+                       prop_infos.CopyTo   (prop_info_arr, 0);
+
+                       try {
+                               cb = new CustomAttributeBuilder (
+                                       (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:
+                               // using System.ComponentModel;
+                               // [DefaultValue (CollectionChangeAction.Add)]
+                               // class X { static void Main () {} }
+                               //
+                               Report.Warning (
+                                       -23, Location,
+                                       "The compiler can not encode this attribute in .NET due to\n" +
+                                       "\ta bug in the .NET runtime.  Try the Mono runtime");
+                       }
+                       
+                       return cb;
+               }
+
+               static string GetValidPlaces (Attribute attr)
+               {
+                       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;
+                                               break;
+                                       }
+                       } else
+                               targets = a.Targets;
+
+                       
+                       if ((targets & AttributeTargets.Assembly) != 0)
+                               sb.Append ("'assembly' ");
+
+                       if ((targets & AttributeTargets.Class) != 0)
+                               sb.Append ("'class' ");
+
+                       if ((targets & AttributeTargets.Constructor) != 0)
+                               sb.Append ("'constructor' ");
+
+                       if ((targets & AttributeTargets.Delegate) != 0)
+                               sb.Append ("'delegate' ");
+
+                       if ((targets & AttributeTargets.Enum) != 0)
+                               sb.Append ("'enum' ");
+
+                       if ((targets & AttributeTargets.Event) != 0)
+                               sb.Append ("'event' ");
+
+                       if ((targets & AttributeTargets.Field) != 0)
+                               sb.Append ("'field' ");
+
+                       if ((targets & AttributeTargets.Interface) != 0)
+                               sb.Append ("'interface' ");
+
+                       if ((targets & AttributeTargets.Method) != 0)
+                               sb.Append ("'method' ");
+
+                       if ((targets & AttributeTargets.Module) != 0)
+                               sb.Append ("'module' ");
+
+                       if ((targets & AttributeTargets.Parameter) != 0)
+                               sb.Append ("'parameter' ");
+
+                       if ((targets & AttributeTargets.Property) != 0)
+                               sb.Append ("'property' ");
+
+                       if ((targets & AttributeTargets.ReturnValue) != 0)
+                               sb.Append ("'return value' ");
+
+                       if ((targets & AttributeTargets.Struct) != 0)
+                               sb.Append ("'struct' ");
+
+                       return sb.ToString ();
+
+               }
+
+               public static void Error_AttributeNotValidForElement (Attribute a, Location loc)
+               {
+                       Report.Error (
+                               592, loc, "Attribute '" + a.Name +
+                               "' is not valid on this declaration type. " +
+                               "It is valid on " + GetValidPlaces (a) + "declarations only.");
+               }
+
+               public static bool CheckAttribute (Attribute a, object element)
+               {
+                       TypeContainer attr = TypeManager.LookupAttr (a.Type);
+                       AttributeTargets targets = 0;
+
+                       
+                       if (attr == null) {
+
+                               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)
+                                       return true;
+                               else
+                                       return false;
+                               
+                       } else if (element is Struct) {
+                               if ((targets & AttributeTargets.Struct) != 0)
+                                       return true;
+                               else
+                                       return false;
+                       } else if (element is Constructor) {
+                               if ((targets & AttributeTargets.Constructor) != 0)
+                                       return true;
+                               else
+                                       return false;
+                       } else if (element is Delegate) {
+                               if ((targets & AttributeTargets.Delegate) != 0)
+                                       return true;
+                               else
+                                       return false;
+                       } else if (element is Enum) {
+                               if ((targets & AttributeTargets.Enum) != 0)
+                                       return true;
+                               else
+                                       return false;
+                       } else if (element is Event || element is InterfaceEvent) {
+                               if ((targets & AttributeTargets.Event) != 0)
+                                       return true;
+                               else
+                                       return false;
+                       } else if (element is Field || element is FieldBuilder) {
+                               if ((targets & AttributeTargets.Field) != 0)
+                                       return true;
+                               else
+                                       return false;
+                       } else if (element is Interface) {
+                               if ((targets & AttributeTargets.Interface) != 0)
+                                       return true;
+                               else
+                                       return false;
+                       } else if (element is Method || element is Operator || element is InterfaceMethod || element is Accessor) {
+                               if ((targets & AttributeTargets.Method) != 0)
+                                       return true;
+                               else
+                                       return false;
+                       } else if (element is ParameterBuilder) {
+                               if ((targets & AttributeTargets.Parameter) != 0)
+                                       return true;
+                               else
+                                       return false;
+                       } else if (element is Property || element is Indexer ||
+                                  element is InterfaceProperty || element is InterfaceIndexer) {
+                               if ((targets & AttributeTargets.Property) != 0)
+                                       return true;
+                               else
+                                       return false;
+                       } else if (element is AssemblyBuilder){
+                               if ((targets & AttributeTargets.Assembly) != 0)
+                                       return true;
+                               else
+                                       return false;
+                       }
+
+                       return false;
+               }
+
+               //
+               // This method should be invoked to pull the IndexerName 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;
+                                       
+                                       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;
+                                       }
+                                       
+                                       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;
+                                       }
+
+                                       //
+                                       // Remove the attribute from the list
+                                       //
+                                       asec.Attributes.Remove (a);
+
+                                       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;
+               }
+
+               //
+               // 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;
+
+                               if (asec.Target == "assembly" && !(builder is AssemblyBuilder))
+                                       continue;
+                               
+                               foreach (Attribute a in asec.Attributes) {
+                                       CustomAttributeBuilder cb = a.Resolve (ec);
+
+                                       if (cb == null)
+                                               continue;
+
+                                       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){
+                                                       ((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 Interface) {
+                                               Interface iface = (Interface) kind;
+
+                                               if ((a.Type == TypeManager.default_member_type) &&
+                                                   (iface.InterfaceIndexers != null)) {
+                                                       Report.Error (
+                                                               646, loc,
+                                                               "Cannot specify the DefaultMember attribute on" +
+                                                               " a type containing an indexer");
+                                                       return;
+                                               }
+
+                                               if (!CheckAttribute (a, kind)) {
+                                                       Error_AttributeNotValidForElement (a, loc);
+                                                       return;
+                                               }
+
+                                               ((TypeBuilder) builder).SetCustomAttribute (cb);
+                                       } 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);
+                               }
+                       }
+               }
+
+               public MethodBuilder DefinePInvokeMethod (EmitContext ec, TypeBuilder builder, string name,
+                                                         MethodAttributes flags, Type ret_type, Type [] param_types)
+               {
+                       //
+                       // We extract from the attribute the information we need 
+                       //
+
+                       if (Arguments == null) {
+                               Console.WriteLine ("Internal error : this is not supposed to happen !");
+                               return null;
+                       }
+
+                       Type = CheckAttributeType (ec);
+                       if (Type == null)
+                               return null;
+                       
+                       ArrayList named_args = new ArrayList ();
+                       
+                       ArrayList pos_args = (ArrayList) Arguments [0];
+                       if (Arguments.Count > 1)
+                               named_args = (ArrayList) Arguments [1];
+                       
+
+                       string dll_name = null;
+                       
+                       Argument tmp = (Argument) pos_args [0];
+
+                       if (!tmp.Resolve (ec, Location))
+                               return null;
+                       
+                       if (tmp.Expr is Constant)
+                               dll_name = (string) ((Constant) tmp.Expr).GetValue ();
+                       else { 
+                               Error_AttributeArgumentNotValid ();
+                               return null;
+                       }
+
+                       // Now we process the named arguments
+                       CallingConvention cc = CallingConvention.Winapi;
+                       CharSet charset = CharSet.Ansi;
+                       bool preserve_sig = true;
+                       bool exact_spelling = false;
+                       bool set_last_err = false;
+                       string entry_point = null;
+
+                       for (int i = 0; i < named_args.Count; i++) {
+
+                               DictionaryEntry de = (DictionaryEntry) named_args [i];
+
+                               string member_name = (string) de.Key;
+                               Argument a  = (Argument) de.Value;
+
+                               if (!a.Resolve (ec, Location))
+                                       return null;
+
+                               Expression member = Expression.MemberLookup (
+                                       ec, Type, member_name, 
+                                       MemberTypes.Field | MemberTypes.Property,
+                                       BindingFlags.Public | BindingFlags.Instance,
+                                       Location);
+
+                               if (member == null || !(member is FieldExpr)) {
+                                       Error_InvalidNamedArgument (member_name);
+                                       return null;
+                               }
+
+                               if (member is FieldExpr) {
+                                       FieldExpr fe = (FieldExpr) member;
+                                       FieldInfo fi = fe.FieldInfo;
+
+                                       if (fi.IsInitOnly) {
+                                               Error_InvalidNamedArgument (member_name);
+                                               return null;
+                                       }
+
+                                       if (a.Expr is Constant) {
+                                               Constant c = (Constant) a.Expr;
+                                               
+                                               if (member_name == "CallingConvention")
+                                                       cc = (CallingConvention) c.GetValue ();
+                                               else if (member_name == "CharSet")
+                                                       charset = (CharSet) c.GetValue ();
+                                               else if (member_name == "EntryPoint")
+                                                       entry_point = (string) c.GetValue ();
+                                               else if (member_name == "SetLastError")
+                                                       set_last_err = (bool) c.GetValue ();
+                                               else if (member_name == "ExactSpelling")
+                                                       exact_spelling = (bool) c.GetValue ();
+                                               else if (member_name == "PreserveSig")
+                                                       preserve_sig = (bool) c.GetValue ();
+                                       } else { 
+                                               Error_AttributeArgumentNotValid ();
+                                               return null;
+                                       }
+                                       
+                               }
+                       }
+
+                       if (entry_point == null)
+                               entry_point = name;
+                       
+                       MethodBuilder mb = builder.DefinePInvokeMethod (
+                               name, dll_name, entry_point, flags | MethodAttributes.HideBySig,
+                               CallingConventions.Standard,
+                               ret_type,
+                               param_types,
+                               cc,
+                               charset);
+
+                       if (preserve_sig)
+                               mb.SetImplementationFlags (MethodImplAttributes.PreserveSig);
+                       
+                       return mb;
+               }                       
+       }
+       
+       public class AttributeSection {
+               
+               public readonly string    Target;
+               public readonly ArrayList Attributes;
+               
+               public AttributeSection (string target, ArrayList attrs)
+               {
+                       Target = target;
+                       Attributes = attrs;
+               }
+               
+       }
+
+       public class Attributes {
+               public ArrayList AttributeSections;
+               public Location Location;
+
+               public Attributes (AttributeSection a, Location loc)
+               {
+                       AttributeSections = new ArrayList ();
+                       AttributeSections.Add (a);
+
+               }
+
+               public void AddAttribute (AttributeSection a)
+               {
+                       if (a != null)
+                               AttributeSections.Add (a);
+               }
+               
+               public void AddAttributeSection (AttributeSection a)
+               {
+                       if (a != null && !AttributeSections.Contains (a))
+                               AttributeSections.Add (a);
+               }
+               
+               public bool Contains (Type t)
+               {
+                       foreach (AttributeSection attr_section in AttributeSections){
+                               foreach (Attribute a in attr_section.Attributes){
+                                       if (a.Type == t)
+                                               return true;
+                               }
+                       }
+                       return false;
+               }                       
+       }
+}