2006-04-28 Marek Safar <marek.safar@seznam.cz>
[mono.git] / mcs / mcs / attribute.cs
index 0e9d3dfc9a0362b579ea2646eb12d5c02d2f8ff1..35a2c566e530987c9b429f4ee3974bab4c4ea3d2 100644 (file)
@@ -32,11 +32,12 @@ namespace Mono.CSharp {
                /// <summary>
                ///   Attributes for this type
                /// </summary>
-               Attributes attributes;
+               protected Attributes attributes;
 
                public Attributable (Attributes attrs)
                {
-                       attributes = attrs;
+                       if (attrs != null)
+                               OptAttributes = attrs;
                }
 
                public Attributes OptAttributes 
@@ -46,6 +47,10 @@ namespace Mono.CSharp {
                        }
                        set {
                                attributes = value;
+
+                               if (attributes != null) {
+                                       attributes.AttachTo (this);
+                               }
                        }
                }
 
@@ -59,7 +64,9 @@ namespace Mono.CSharp {
                /// </summary>
                public abstract AttributeTargets AttributeTargets { get; }
 
-               public abstract bool IsClsCompliaceRequired (DeclSpace ds);
+               public abstract IResolveContext ResolveContext { get; }
+
+               public abstract bool IsClsComplianceRequired ();
 
                /// <summary>
                /// Gets list of valid attribute targets for explicit target declaration.
@@ -77,18 +84,22 @@ namespace Mono.CSharp {
                public readonly Expression LeftExpr;
                public readonly string Identifier;
 
-               public readonly ArrayList Arguments;
+               readonly ArrayList PosArguments;
+               readonly ArrayList NamedArguments;
 
                public readonly Location Location;
 
                public Type Type;
 
                bool resolve_error;
-
                readonly bool nameEscaped;
 
-               static AttributeUsageAttribute DefaultUsageAttribute = new AttributeUsageAttribute (AttributeTargets.All);
+               // It can contain more onwers when the attribute is applied to multiple fiels.
+               Attributable[] owners;
+
+               static readonly AttributeUsageAttribute DefaultUsageAttribute = new AttributeUsageAttribute (AttributeTargets.All);
                static Assembly orig_sec_assembly;
+               public static readonly object[] EmptyObject = new object [0];
 
                // non-null if named args present after Resolve () is called
                PropertyInfo [] prop_info_arr;
@@ -97,42 +108,78 @@ namespace Mono.CSharp {
                object [] prop_values_arr;
                object [] pos_values;
 
-               static PtrHashtable usage_attr_cache = new PtrHashtable ();
+               static PtrHashtable usage_attr_cache;
+               // Cache for parameter-less attributes
+               static PtrHashtable att_cache;
                
-               public Attribute (string target, Expression left_expr, string identifier, ArrayList args, Location loc, bool nameEscaped)
+               public Attribute (string target, Expression left_expr, string identifier, object[] args, Location loc, bool nameEscaped)
                {
                        LeftExpr = left_expr;
                        Identifier = identifier;
                        Name = LeftExpr == null ? identifier : LeftExpr + "." + identifier;
-                       Arguments = args;
+                       if (args != null) {
+                               PosArguments = (ArrayList)args [0];
+                               NamedArguments = (ArrayList)args [1];                           
+                       }
                        Location = loc;
                        ExplicitTarget = target;
                        this.nameEscaped = nameEscaped;
                }
 
+               static Attribute ()
+               {
+                       Reset ();
+               }
+
+               public static void Reset ()
+               {
+                       usage_attr_cache = new PtrHashtable ();
+                       att_cache = new PtrHashtable ();
+               }
+
+               public void AttachTo (Attributable owner)
+               {
+                       if (this.owners == null) {
+                               this.owners = new Attributable[1] { owner };
+                               return;
+                       }
+
+                       // When the same attribute is attached to multiple fiels
+                       // we use this extra_owners as a list of owners. The attribute
+                       // then can be removed because will be emitted when first owner
+                       // is served
+                       Attributable[] new_array = new Attributable [this.owners.Length + 1];
+                       owners.CopyTo (new_array, 0);
+                       new_array [owners.Length] = owner;
+                       this.owners = new_array;
+                       owner.OptAttributes = null;
+               }
+
                void Error_InvalidNamedArgument (string name)
                {
-                       Report.Error (617, Location, "`{0}' is not a valid named attribute argument. Named attribute arguments must be fields which are not readonly, static, const or read-write properties which are public and not static",
+                       Report.Error (617, Location, "`{0}' is not a valid named attribute argument. Named attribute arguments " +
+                                     "must be fields which are not readonly, static, const or read-write properties which are " +
+                                     "public and not static",
                              name);
                }
 
                void Error_InvalidNamedAgrumentType (string name)
                {
-                       Report.Error (655, Location, "`{0}' is not a valid named attribute argument because it is not a valid attribute parameter type", name);
+                       Report.Error (655, Location, "`{0}' is not a valid named attribute argument because it is not a valid " +
+                                     "attribute parameter type", name);
                }
 
-               static void Error_AttributeArgumentNotValid (string extra, Location loc)
+               public static void Error_AttributeArgumentNotValid (Location loc)
                {
                        Report.Error (182, loc,
                                      "An attribute argument must be a constant expression, typeof " +
-                                     "expression or array creation expression" + extra);
-               }
+                                     "expression or array creation expression");
+               }               
 
-               static void Error_AttributeArgumentNotValid (Location loc)
+               public void Error_MissingGuidAttribute ()
                {
-                       Error_AttributeArgumentNotValid ("", loc);
+                       Report.Error (596, Location, "The Guid attribute must be specified with the ComImport attribute");
                }
-               
 
                /// <summary>
                /// This is rather hack. We report many emit attribute error with same error to be compatible with
@@ -140,7 +187,8 @@ namespace Mono.CSharp {
                /// </summary>
                public void Error_AttributeEmitError (string inner)
                {
-                       Report.Error (647, Location, "Error during emitting `{0}' attribute. The reason is `{1}'", TypeManager.CSharpName (Type), inner);
+                       Report.Error (647, Location, "Error during emitting `{0}' attribute. The reason is `{1}'",
+                                     TypeManager.CSharpName (Type), inner);
                }
 
                public void Error_InvalidSecurityParent ()
@@ -148,34 +196,33 @@ namespace Mono.CSharp {
                        Error_AttributeEmitError ("it is attached to invalid parent");
                }
 
-               protected virtual FullNamedExpression ResolveAsTypeTerminal (Expression expr, EmitContext ec, bool silent)
-               {
-                       return expr.ResolveAsTypeTerminal (ec, silent);
+               Attributable Owner {
+                       get {
+                               return owners [0];
+                       }
                }
 
-               protected virtual FullNamedExpression ResolveAsTypeStep (Expression expr, EmitContext ec, bool silent)
+               protected virtual TypeExpr ResolveAsTypeTerminal (Expression expr, IResolveContext ec, bool silent)
                {
-                       return expr.ResolveAsTypeStep (ec, silent);
+                       return expr.ResolveAsTypeTerminal (ec, silent);
                }
 
-               Type ResolvePossibleAttributeType (EmitContext ec, string name, bool silent, ref bool is_attr)
+               Type ResolvePossibleAttributeType (string name, bool silent, ref bool is_attr)
                {
-                       FullNamedExpression fn;
+                       IResolveContext rc = Owner.ResolveContext;
+
+                       TypeExpr te;
                        if (LeftExpr == null) {
-                               fn = ResolveAsTypeTerminal (new SimpleName (name, Location), ec, silent);
+                               te = ResolveAsTypeTerminal (new SimpleName (name, Location), rc, silent);
                        } else {
-                               fn = ResolveAsTypeStep (LeftExpr, ec, silent);
-                               if (fn == null)
-                                       return null;
-                               fn = new MemberAccess (fn, name, Location).ResolveAsTypeTerminal (ec, silent);
+                               te = ResolveAsTypeTerminal (new MemberAccess (LeftExpr, name), rc, silent);
                        }
 
-                       TypeExpr te = fn as TypeExpr;
                        if (te == null)
                                return null;
 
                        Type t = te.Type;
-                       if (t.IsSubclassOf (TypeManager.attribute_type)) {
+                       if (TypeManager.IsSubclassOf (t, TypeManager.attribute_type)) {
                                is_attr = true;
                        } else if (!silent) {
                                Report.SymbolRelatedToPreviousError (t);
@@ -187,17 +234,18 @@ namespace Mono.CSharp {
                /// <summary>
                ///   Tries to resolve the type of the attribute. Flags an error if it can't, and complain is true.
                /// </summary>
-               void ResolveAttributeType (EmitContext ec)
+               void ResolveAttributeType ()
                {
                        bool t1_is_attr = false;
-                       Type t1 = ResolvePossibleAttributeType (ec, Identifier, true, ref t1_is_attr);
+                       Type t1 = ResolvePossibleAttributeType (Identifier, true, ref t1_is_attr);
 
-                       // FIXME: Shouldn't do this for quoted attributes: [@A]
                        bool t2_is_attr = false;
-                       Type t2 = ResolvePossibleAttributeType (ec, Identifier + "Attribute", true, ref t2_is_attr);
+                       Type t2 = nameEscaped ? null :
+                               ResolvePossibleAttributeType (Identifier + "Attribute", true, ref t2_is_attr);
 
-                       if (t1_is_attr && t2_is_attr && !nameEscaped) {
-                               Report.Error (1614, Location, "`{0}' is ambiguous between `{0}' and `{0}Attribute'. Use either `@{0}' or `{0}Attribute'", GetSignatureForError ());
+                       if (t1_is_attr && t2_is_attr) {
+                               Report.Error (1614, Location, "`{0}' is ambiguous between `{0}' and `{0}Attribute'. " +
+                                             "Use either `@{0}' or `{0}Attribute'", GetSignatureForError ());
                                resolve_error = true;
                                return;
                        }
@@ -213,73 +261,43 @@ namespace Mono.CSharp {
                        }
 
                        if (t1 == null && t2 == null)
-                               ResolvePossibleAttributeType (ec, Identifier, false, ref t1_is_attr);
+                               ResolvePossibleAttributeType (Identifier, false, ref t1_is_attr);
                        if (t1 != null)
-                               ResolvePossibleAttributeType (ec, Identifier, false, ref t1_is_attr);
+                               ResolvePossibleAttributeType (Identifier, false, ref t1_is_attr);
                        if (t2 != null)
-                               ResolvePossibleAttributeType (ec, Identifier + "Attribute", false, ref t2_is_attr);
+                               ResolvePossibleAttributeType (Identifier + "Attribute", false, ref t2_is_attr);
 
                        resolve_error = true;
                }
 
-               public virtual Type ResolveType (EmitContext ec)
+               public virtual Type ResolveType ()
                {
                        if (Type == null && !resolve_error)
-                               ResolveAttributeType (ec);
+                               ResolveAttributeType ();
                        return Type;
                }
 
                public string GetSignatureForError ()
                {
-                       return LeftExpr == null ? Identifier : LeftExpr.GetSignatureForError () + "." + Identifier;
-               }
-
-               //
-               // Given an expression, if the expression is a valid attribute-argument-expression
-               // returns an object that can be used to encode it, or null on failure.
-               //
-               public static bool GetAttributeArgumentExpression (Expression e, Location loc, Type arg_type, out object result)
-               {
-                       Constant constant = e as Constant;
-                       if (constant != null) {
-                               constant = constant.ToType (arg_type, loc);
-                               if (constant == null) {
-                                       result = null;
-                                       return false;
-                               }
-                               result = constant.GetTypedValue ();
-                               return true;
-                       } else if (e is TypeOf) {
-                               result = ((TypeOf) e).TypeArg;
-                               return true;
-                       } else if (e is ArrayCreation){
-                               result =  ((ArrayCreation) e).EncodeAsAttribute ();
-                               if (result != null)
-                                       return true;
-                       } else if (e is EmptyCast) {
-                               Expression child = ((EmptyCast)e).Child;
-                               return GetAttributeArgumentExpression (child, loc, child.Type, out result);
-                       }
+                       if (Type != null)
+                               return TypeManager.CSharpName (Type);
 
-                       result = null;
-                       Error_AttributeArgumentNotValid (loc);
-                       return false;
+                       return LeftExpr == null ? Identifier : LeftExpr.GetSignatureForError () + "." + Identifier;
                }
 
                bool IsValidArgumentType (Type t)
                {
+                       if (t.IsArray)
+                               t = t.GetElementType ();
+
                        return TypeManager.IsPrimitiveType (t) ||
-                               (t.IsArray && TypeManager.IsPrimitiveType (t.GetElementType ())) ||
                                TypeManager.IsEnumType (t) ||
                                t == TypeManager.string_type ||
                                t == TypeManager.object_type ||
                                t == TypeManager.type_type;
                }
 
-               // Cache for parameter-less attributes
-               static PtrHashtable att_cache = new PtrHashtable ();
-
-               public CustomAttributeBuilder Resolve (EmitContext ec)
+               public CustomAttributeBuilder Resolve ()
                {
                        if (resolve_error)
                                return null;
@@ -287,7 +305,7 @@ namespace Mono.CSharp {
                        resolve_error = true;
 
                        if (Type == null) {
-                               ResolveAttributeType (ec);
+                               ResolveAttributeType ();
                                if (Type == null)
                                        return null;
                        }
@@ -297,7 +315,12 @@ namespace Mono.CSharp {
                                return null;
                        }
 
-                       if (Arguments == null) {
+                       ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (Type);
+                       if (obsolete_attr != null) {
+                               AttributeTester.Report_ObsoleteMessage (obsolete_attr, TypeManager.CSharpName (Type), Location);
+                       }
+
+                       if (PosArguments == null && NamedArguments == null) {
                                object o = att_cache [Type];
                                if (o != null) {
                                        resolve_error = false;
@@ -305,296 +328,287 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       ConstructorInfo ctor = ResolveArguments (ec);
+                       Attributable owner = Owner;
+                       EmitContext ec = new EmitContext (owner.ResolveContext, owner.ResolveContext.DeclContainer, owner.ResolveContext.DeclContainer,
+                               Location, null, null, owner.ResolveContext.DeclContainer.ModFlags, false);
+                       ec.IsAnonymousMethodAllowed = false;
+
+                       ConstructorInfo ctor = ResolveConstructor (ec);
                        if (ctor == null)
                                return null;
 
                        CustomAttributeBuilder cb;
 
                        try {
-                               if (prop_info_arr != null || field_info_arr != null) {
-                                       cb = new CustomAttributeBuilder (
-                                               ctor, pos_values,
-                                               prop_info_arr, prop_values_arr,
-                                               field_info_arr, field_values_arr);
-                               } else {
-                                       cb = new CustomAttributeBuilder (
-                                               ctor, pos_values);
+                               if (NamedArguments == null) {
+                                       cb = new CustomAttributeBuilder (ctor, pos_values);
 
                                        if (pos_values.Length == 0)
                                                att_cache.Add (Type, cb);
+
+                                       resolve_error = false;
+                                       return cb;
+                               }
+
+                               if (!ResolveNamedArguments (ec)) {
+                                       return null;
                                }
+
+                               cb = new CustomAttributeBuilder (ctor, pos_values,
+                                               prop_info_arr, prop_values_arr,
+                                               field_info_arr, field_values_arr);
+
+                               resolve_error = false;
+                               return cb;
                        }
                        catch (Exception) {
                                Error_AttributeArgumentNotValid (Location);
                                return null;
                        }
-
-                       resolve_error = false;
-                       return cb;
                }
 
-               protected virtual ConstructorInfo ResolveArguments (EmitContext ec)
+               protected virtual ConstructorInfo ResolveConstructor (EmitContext ec)
                {
-                       // Now we extract the positional and named arguments
-                       
-                       ArrayList pos_args = null;
-                       ArrayList named_args = null;
-                       int pos_arg_count = 0;
-                       int named_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];
-                                       named_arg_count = named_args.Count;
+                       if (PosArguments != null) {
+                               for (int i = 0; i < PosArguments.Count; i++) {
+                                       Argument a = (Argument) PosArguments [i];
+
+                                       if (!a.Resolve (ec, Location))
+                                               return null;
                                }
                        }
 
+                       Expression mg = Expression.MemberLookup (ec.ContainerType,
+                               Type, ".ctor", MemberTypes.Constructor,
+                               BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
+                               Location);
+
+                       if (mg == null)
+                               return null;
+
+                       MethodBase constructor = Invocation.OverloadResolve (
+                               ec, (MethodGroupExpr) mg, PosArguments, false, Location);
+
+                       if (constructor == null)
+                               return null;
+
+                       ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (constructor);
+                       if (oa != null && !Owner.ResolveContext.IsInObsoleteScope) {
+                               AttributeTester.Report_ObsoleteMessage (oa, mg.GetSignatureForError (), mg.Location);
+                       }
+
+                       if (PosArguments == null) {
+                               pos_values = EmptyObject;
+                               return (ConstructorInfo)constructor;
+                       }
+
+                       ParameterData pd = TypeManager.GetParameterData (constructor);
+
+                       int pos_arg_count = PosArguments.Count;
+                       int last_real_param = pd.Count;
+
                        pos_values = new object [pos_arg_count];
 
-                       //
-                       // First process positional arguments 
-                       //
+                       if (pd.HasParams) {
+                               // When the params is not filled we need to put one
+                               if (last_real_param > pos_arg_count) {
+                                       object [] new_pos_values = new object [pos_arg_count + 1];
+                                       pos_values.CopyTo (new_pos_values, 0);
+                                       new_pos_values [pos_arg_count] = new object [] {} ;
+                                       pos_values = new_pos_values;
+                               }
+                               last_real_param--;
+                       }
 
-                       int i;
-                       for (i = 0; i < pos_arg_count; i++) {
-                               Argument a = (Argument) pos_args [i];
-                               Expression e;
+                       for (int j = 0; j < pos_arg_count; ++j) {
+                               Argument a = (Argument) PosArguments [j];
 
-                               if (!a.Resolve (ec, Location))
+                               if (!a.Expr.GetAttributableValue (a.Type, out pos_values [j]))
                                        return null;
+                               
+                               if (j < last_real_param)
+                                       continue;
+                               
+                               if (j == last_real_param) {
+                                       object [] array = new object [pos_arg_count - last_real_param];
+                                       array [0] = pos_values [j];
+                                       pos_values [j] = array;
+                                       continue;
+                               }
+
+                               object [] params_array = (object []) pos_values [last_real_param];
+                               params_array [j - last_real_param] = pos_values [j];
+                       }
 
-                               e = a.Expr;
+                       // Adjust the size of the pos_values if it had params
+                       if (last_real_param != pos_arg_count) {
+                               object [] new_pos_values = new object [last_real_param + 1];
+                               Array.Copy (pos_values, new_pos_values, last_real_param + 1);
+                               pos_values = new_pos_values;
+                       }
 
-                               object val;
-                               if (!GetAttributeArgumentExpression (e, Location, a.Type, out val))
+                       // Here we do the checks which should be done by corlib or by runtime.
+                       // However Zoltan doesn't like it and every Mono compiler has to do it again.
+                       
+                       if (Type == TypeManager.guid_attr_type) {
+                               try {
+                                       new Guid ((string)pos_values [0]);
+                               }
+                               catch (Exception e) {
+                                       Error_AttributeEmitError (e.Message);
                                        return null;
+                               }
+                       }
 
-                               pos_values [i] = val;
+                       if (Type == TypeManager.attribute_usage_type && (int)pos_values [0] == 0) {
+                               Report.Error (591, Location, "Invalid value for argument to `System.AttributeUsage' attribute");
+                               return null;
+                       }
 
-                               if (i == 0 && Type == TypeManager.attribute_usage_type && (int)val == 0) {
-                                       Report.Error (591, Location, "Invalid value for argument to 'System.AttributeUsage' attribute");
+                       if (Type == TypeManager.indexer_name_type || Type == TypeManager.conditional_attribute_type) {
+                               if (!Tokenizer.IsValidIdentifier ((string)pos_values [0])) {
+                                       Report.Error (633, ((Argument)PosArguments[0]).Expr.Location,
+                                               "The argument to the `{0}' attribute must be a valid identifier", GetSignatureForError ());
                                        return null;
                                }
                        }
 
-                       //
-                       // Now process named arguments
-                       //
+                       if (Type == TypeManager.methodimpl_attr_type && pos_values.Length == 1 &&
+                               pd.ParameterType (0) == TypeManager.short_type &&
+                               !System.Enum.IsDefined (typeof (MethodImplOptions), pos_values [0].ToString ())) {
+                               Error_AttributeEmitError ("Incorrect argument value.");
+                               return null;
+                       }
+
+                       return (ConstructorInfo)constructor;
+               }
 
-                       ArrayList field_infos = null;
-                       ArrayList prop_infos  = null;
-                       ArrayList field_values = null;
-                       ArrayList prop_values = null;
-                       Hashtable seen_names = null;
+               protected virtual bool ResolveNamedArguments (EmitContext ec)
+               {
+                       int named_arg_count = NamedArguments.Count;
 
-                       if (named_arg_count > 0) {
-                               field_infos = new ArrayList ();
-                               prop_infos  = new ArrayList ();
-                               field_values = new ArrayList ();
-                               prop_values = new ArrayList ();
+                       ArrayList field_infos = new ArrayList (named_arg_count);
+                       ArrayList prop_infos  = new ArrayList (named_arg_count);
+                       ArrayList field_values = new ArrayList (named_arg_count);
+                       ArrayList prop_values = new ArrayList (named_arg_count);
 
-                               seen_names = new Hashtable();
-                       }
+                       ArrayList seen_names = new ArrayList(named_arg_count);
                        
-                       for (i = 0; i < named_arg_count; i++) {
-                               DictionaryEntry de = (DictionaryEntry) named_args [i];
+                       foreach (DictionaryEntry de in NamedArguments) {
                                string member_name = (string) de.Key;
-                               Argument a  = (Argument) de.Value;
-                               Expression e;
 
                                if (seen_names.Contains(member_name)) {
                                        Report.Error(643, Location, "'" + member_name + "' duplicate named attribute argument");
-                                       return null;
+                                       return false;
                                }                               
-                               seen_names.Add(member_name, 1);
-                               
+                               seen_names.Add(member_name);
+
+                               Argument a = (Argument) de.Value;
                                if (!a.Resolve (ec, Location))
-                                       return null;
+                                       return false;
 
                                Expression member = Expression.MemberLookup (
-                                       ec, Type, member_name,
+                                       ec.ContainerType, Type, member_name,
                                        MemberTypes.Field | MemberTypes.Property,
                                        BindingFlags.Public | BindingFlags.Instance,
                                        Location);
 
                                if (member == null) {
-                                       member = Expression.MemberLookup (ec, Type, member_name,
+                                       member = Expression.MemberLookup (ec.ContainerType, Type, member_name,
                                                MemberTypes.Field | MemberTypes.Property, BindingFlags.NonPublic | BindingFlags.Instance,
                                                Location);
 
                                        if (member != null) {
                                                Expression.ErrorIsInaccesible (Location, member.GetSignatureForError ());
-                                               return null;
+                                               return false;
                                        }
                                }
 
                                if (member == null){
                                        Report.Error (117, Location, "`{0}' does not contain a definition for `{1}'",
-                                                     Type, member_name);
-                                       return null;
+                                                     TypeManager.CSharpName (Type), member_name);
+                                       return false;
                                }
                                
                                if (!(member is PropertyExpr || member is FieldExpr)) {
                                        Error_InvalidNamedArgument (member_name);
-                                       return null;
+                                       return false;
                                }
 
-                               e = a.Expr;
+                               ObsoleteAttribute obsolete_attr;
+
                                if (member is PropertyExpr) {
-                                       PropertyExpr pe = (PropertyExpr) member;
-                                       PropertyInfo pi = pe.PropertyInfo;
+                                       PropertyInfo pi = ((PropertyExpr) member).PropertyInfo;
 
                                        if (!pi.CanWrite || !pi.CanRead) {
                                                Report.SymbolRelatedToPreviousError (pi);
                                                Error_InvalidNamedArgument (member_name);
-                                               return null;
+                                               return false;
                                        }
 
                                        if (!IsValidArgumentType (pi.PropertyType)) {
                                                Report.SymbolRelatedToPreviousError (pi);
                                                Error_InvalidNamedAgrumentType (member_name);
-                                               return null;
+                                               return false;
                                        }
 
                                        object value;
-                                       if (!GetAttributeArgumentExpression (e, Location, pi.PropertyType, out value))
-                                               return null;
+                                       if (!a.Expr.GetAttributableValue (pi.PropertyType, out value))
+                                               return false;
+
+                                       PropertyBase pb = TypeManager.GetProperty (pi);
+                                       if (pb != null)
+                                               obsolete_attr = pb.GetObsoleteAttribute ();
+                                       else
+                                               obsolete_attr = AttributeTester.GetMemberObsoleteAttribute (pi);
 
                                        prop_values.Add (value);
                                        prop_infos.Add (pi);
                                        
-                               } else if (member is FieldExpr) {
-                                       FieldExpr fe = (FieldExpr) member;
-                                       FieldInfo fi = fe.FieldInfo;
+                               } else {
+                                       FieldInfo fi = ((FieldExpr) member).FieldInfo;
 
                                        if (fi.IsInitOnly) {
                                                Error_InvalidNamedArgument (member_name);
-                                               return null;
+                                               return false;
                                        }
 
                                        if (!IsValidArgumentType (fi.FieldType)) {
                                                Report.SymbolRelatedToPreviousError (fi);
                                                Error_InvalidNamedAgrumentType (member_name);
-                                               return null;
+                                               return false;
                                        }
 
                                        object value;
-                                       if (!GetAttributeArgumentExpression (e, Location, fi.FieldType, out value))
-                                               return null;
+                                       if (!a.Expr.GetAttributableValue (fi.FieldType, out value))
+                                               return false;
+
+                                       FieldBase fb = TypeManager.GetField (fi);
+                                       if (fb != null)
+                                               obsolete_attr = fb.GetObsoleteAttribute ();
+                                       else
+                                               obsolete_attr = AttributeTester.GetMemberObsoleteAttribute (fi);
 
                                        field_values.Add (value);                                       
                                        field_infos.Add (fi);
                                }
-                       }
-
-                       Expression mg = Expression.MemberLookup (
-                               ec, Type, ".ctor", MemberTypes.Constructor,
-                               BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
-                                Location);
-
-                       MethodBase constructor = Invocation.OverloadResolve (
-                               ec, (MethodGroupExpr) mg, pos_args, false, Location);
-
-                       if (constructor == null) {
-                               return null;
-                       }
-
-
-                       // Here we do the checks which should be done by corlib or by runtime.
-                       // However Zoltan doesn't like it and every Mono compiler has to do it again.
-                       
-                       if (Type == TypeManager.guid_attr_type) {
-                               try {
-                                       new Guid ((string)pos_values [0]);
-                               }
-                               catch (Exception e) {
-                                       Error_AttributeEmitError (e.Message);
-                               }
-                       }
-// TODO: reenable
-//                     if (Type == TypeManager.methodimpl_attr_type &&
-//                             pos_values.Length == 1 && ((Argument)pos_args [0]).Type == TypeManager.short_type &&
-//                             !System.Enum.IsDefined (TypeManager.method_impl_options, pos_values [0])) {
-//                                     Error_AttributeEmitError ("Incorrect argument value.");
-//                     }
-
-                       //
-                       // 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 = TypeManager.GetParameterData (constructor);
-
-                       int last_real_param = pd.Count;
-                       if (pd.HasParams) {
-                               // When the params is not filled we need to put one
-                               if (last_real_param > pos_arg_count) {
-                                       object [] new_pos_values = new object [pos_arg_count + 1];
-                                       pos_values.CopyTo (new_pos_values, 0);
-                                       new_pos_values [pos_arg_count] = new object [] {} ;
-                                       pos_values = new_pos_values;
-                               }
-                               last_real_param--;
-                       }
-
-                       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 (Location);
-                                       return null;
-                               }
-
-                               object value = pos_values [j];
-                               if (value != null && a.Type != value.GetType () && TypeManager.IsPrimitiveType (a.Type)) {
-                                       bool fail;
-                                       pos_values [j] = TypeManager.ChangeType (value, a.Type, out fail);
-                                       if (fail) {
-                                               // TODO: Can failed ?
-                                               throw new NotImplementedException ();
-                                       }
-                               }
-
-                               if (j < last_real_param)
-                                       continue;
-                               
-                               if (j == last_real_param) {
-                                       object [] array = new object [pos_arg_count - last_real_param];
-                                       array [0] = pos_values [j];
-                                       pos_values [j] = array;
-                                       continue;
-                               }
 
-                               object [] params_array = (object []) pos_values [last_real_param];
-                               params_array [j - last_real_param] = pos_values [j];
+                               if (obsolete_attr != null && !Owner.ResolveContext.IsInObsoleteScope)
+                                       AttributeTester.Report_ObsoleteMessage (obsolete_attr, member.GetSignatureForError (), member.Location);
                        }
 
-                       // Adjust the size of the pos_values if it had params
-                       if (last_real_param != pos_arg_count) {
-                               object [] new_pos_values = new object [last_real_param + 1];
-                               Array.Copy (pos_values, new_pos_values, last_real_param + 1);
-                               pos_values = new_pos_values;
-                       }
+                       prop_info_arr = new PropertyInfo [prop_infos.Count];
+                       field_info_arr = new FieldInfo [field_infos.Count];
+                       field_values_arr = new object [field_values.Count];
+                       prop_values_arr = new object [prop_values.Count];
 
-                       if (named_arg_count > 0) {
-                               prop_info_arr = new PropertyInfo [prop_infos.Count];
-                               field_info_arr = new FieldInfo [field_infos.Count];
-                               field_values_arr = new object [field_values.Count];
-                               prop_values_arr = new object [prop_values.Count];
+                       field_infos.CopyTo  (field_info_arr, 0);
+                       field_values.CopyTo (field_values_arr, 0);
 
-                               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);
-                       }
+                       prop_values.CopyTo  (prop_values_arr, 0);
+                       prop_infos.CopyTo   (prop_info_arr, 0);
 
-                       return (ConstructorInfo) constructor;
+                       return true;
                }
 
                /// <summary>
@@ -603,7 +617,7 @@ namespace Mono.CSharp {
                public string GetValidTargets ()
                {
                        StringBuilder sb = new StringBuilder ();
-                       AttributeTargets targets = GetAttributeUsage (null).ValidOn;
+                       AttributeTargets targets = GetAttributeUsage ().ValidOn;
 
                        if ((targets & AttributeTargets.Assembly) != 0)
                                sb.Append ("assembly, ");
@@ -657,7 +671,7 @@ namespace Mono.CSharp {
                /// <summary>
                /// Returns AttributeUsage attribute for this type
                /// </summary>
-               AttributeUsageAttribute GetAttributeUsage (EmitContext ec)
+               AttributeUsageAttribute GetAttributeUsage ()
                {
                        AttributeUsageAttribute ua = usage_attr_cache [Type] as AttributeUsageAttribute;
                        if (ua != null)
@@ -674,22 +688,22 @@ namespace Mono.CSharp {
 
                        Attribute a = attr_class.OptAttributes == null
                                ? null
-                               : attr_class.OptAttributes.Search (TypeManager.attribute_usage_type, attr_class.EmitContext);
+                               : attr_class.OptAttributes.Search (TypeManager.attribute_usage_type);
 
                        ua = a == null
                                ? DefaultUsageAttribute 
-                               : a.GetAttributeUsageAttribute (attr_class.EmitContext);
+                               : a.GetAttributeUsageAttribute ();
 
                        usage_attr_cache.Add (Type, ua);
                        return ua;
                }
 
-               AttributeUsageAttribute GetAttributeUsageAttribute (EmitContext ec)
+               AttributeUsageAttribute GetAttributeUsageAttribute ()
                {
                        if (pos_values == null)
                                // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
                                // But because a lot of attribute class code must be rewritten will be better to wait...
-                               Resolve (ec);
+                               Resolve ();
 
                        if (resolve_error)
                                return DefaultUsageAttribute;
@@ -710,12 +724,12 @@ namespace Mono.CSharp {
                /// <summary>
                /// Returns custom name of indexer
                /// </summary>
-               public string GetIndexerAttributeValue (EmitContext ec)
+               public string GetIndexerAttributeValue ()
                {
                        if (pos_values == null)
                                // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
                                // But because a lot of attribute class code must be rewritten will be better to wait...
-                               Resolve (ec);
+                               Resolve ();
 
                        if (resolve_error)
                                return null;
@@ -726,12 +740,12 @@ namespace Mono.CSharp {
                /// <summary>
                /// Returns condition of ConditionalAttribute
                /// </summary>
-               public string GetConditionalAttributeValue (EmitContext ec)
+               public string GetConditionalAttributeValue ()
                {
                        if (pos_values == null)
                                // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
                                // But because a lot of attribute class code must be rewritten will be better to wait...
-                               Resolve (ec);
+                               Resolve ();
 
                        if (resolve_error)
                                return null;
@@ -742,12 +756,12 @@ namespace Mono.CSharp {
                /// <summary>
                /// Creates the instance of ObsoleteAttribute from this attribute instance
                /// </summary>
-               public ObsoleteAttribute GetObsoleteAttribute (EmitContext ec)
+               public ObsoleteAttribute GetObsoleteAttribute ()
                {
                        if (pos_values == null)
                                // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
                                // But because a lot of attribute class code must be rewritten will be better to wait...
-                               Resolve (ec);
+                               Resolve ();
 
                        if (resolve_error)
                                return null;
@@ -766,12 +780,12 @@ namespace Mono.CSharp {
                /// before ApplyAttribute. We need to resolve the arguments.
                /// This situation occurs when class deps is differs from Emit order.  
                /// </summary>
-               public bool GetClsCompliantAttributeValue (EmitContext ec)
+               public bool GetClsCompliantAttributeValue ()
                {
                        if (pos_values == null)
                                // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
                                // But because a lot of attribute class code must be rewritten will be better to wait...
-                               Resolve (ec);
+                               Resolve ();
 
                        if (resolve_error)
                                return false;
@@ -779,6 +793,48 @@ namespace Mono.CSharp {
                        return (bool)pos_values [0];
                }
 
+               public Type GetCoClassAttributeValue ()
+               {
+                       if (pos_values == null)
+                               Resolve ();
+
+                       if (resolve_error)
+                               return null;
+
+                       return (Type)pos_values [0];
+               }
+
+               public bool CheckTarget ()
+               {
+                       string[] valid_targets = Owner.ValidAttributeTargets;
+                       if (ExplicitTarget == null || ExplicitTarget == valid_targets [0]) {
+                               Target = Owner.AttributeTargets;
+                               return true;
+                       }
+
+                       // TODO: we can skip the first item
+                       if (((IList) valid_targets).Contains (ExplicitTarget)) {
+                               switch (ExplicitTarget) {
+                                       case "return": Target = AttributeTargets.ReturnValue; return true;
+                                       case "param": Target = AttributeTargets.Parameter; return true;
+                                       case "field": Target = AttributeTargets.Field; return true;
+                                       case "method": Target = AttributeTargets.Method; return true;
+                                       case "property": Target = AttributeTargets.Property; return true;
+                               }
+                               throw new InternalErrorException ("Unknown explicit target: " + ExplicitTarget);
+                       }
+                               
+                       StringBuilder sb = new StringBuilder ();
+                       foreach (string s in valid_targets) {
+                               sb.Append (s);
+                               sb.Append (", ");
+                       }
+                       sb.Remove (sb.Length - 2, 2);
+                       Report.Error (657, Location, "`{0}' is not a valid attribute location for this declaration. " +
+                               "Valid attribute locations for this declaration are `{1}'", ExplicitTarget, sb.ToString ());
+                       return false;
+               }
+
                /// <summary>
                /// Tests permitted SecurityAction for assembly or other types
                /// </summary>
@@ -786,20 +842,22 @@ namespace Mono.CSharp {
                {
                        SecurityAction action  = GetSecurityActionValue ();
 
-                       if ((action == SecurityAction.RequestMinimum || action == SecurityAction.RequestOptional || action == SecurityAction.RequestRefuse) && for_assembly)
+                       if ((action == SecurityAction.RequestMinimum || action == SecurityAction.RequestOptional ||
+                            action == SecurityAction.RequestRefuse) && for_assembly)
                                return true;
-
+                       
                        if (!for_assembly) {
                                if (action < SecurityAction.Demand || action > SecurityAction.InheritanceDemand) {
                                        Error_AttributeEmitError ("SecurityAction is out of range");
                                        return false;
                                }
-
-                               if ((action != SecurityAction.RequestMinimum && action != SecurityAction.RequestOptional && action != SecurityAction.RequestRefuse) && !for_assembly)
+                               
+                               if ((action != SecurityAction.RequestMinimum && action != SecurityAction.RequestOptional &&
+                                    action != SecurityAction.RequestRefuse) && !for_assembly)
                                        return true;
                        }
 
-                       Error_AttributeEmitError (String.Concat ("SecurityAction '", action, "' is not valid for this declaration"));
+                       Error_AttributeEmitError (String.Concat ("SecurityAction `", action, "' is not valid for this declaration"));
                        return false;
                }
 
@@ -833,7 +891,8 @@ namespace Mono.CSharp {
 
                                        orig_assembly_type = orig_sec_assembly.GetType (Type.FullName, true);
                                        if (orig_assembly_type == null) {
-                                               Report.Warning (-112, 1, Location, "Self-referenced security attribute `{0}' was not found in previous version of assembly");
+                                               Report.Warning (-112, 1, Location, "Self-referenced security attribute `{0}' " +
+                                                               "was not found in previous version of assembly");
                                                return;
                                        }
                                }
@@ -903,7 +962,7 @@ namespace Mono.CSharp {
                        ps.AddPermission (perm);
                }
 
-               object GetValue (object value)
+               static object GetValue (object value)
                {
                        if (value is EnumConstant)
                                return ((EnumConstant) value).GetValue ();
@@ -911,7 +970,7 @@ namespace Mono.CSharp {
                                return value;                           
                }
 
-               object GetPropertyValue (string name)
+               public object GetPropertyValue (string name)
                {
                        if (prop_info_arr == null)
                                return null;
@@ -938,11 +997,16 @@ namespace Mono.CSharp {
                        return null;
                }
 
+               //
+               // Theoretically, we can get rid of this, since FieldBuilder.SetCustomAttribute()
+               // and ParameterBuilder.SetCustomAttribute() are supposed to handle this attribute.
+               // However, we can't, since it appears that the .NET 1.1 SRE hangs when given a MarshalAsAttribute.
+               //
                public UnmanagedMarshal GetMarshal (Attributable attr)
                {
                        UnmanagedType UnmanagedType;
                        if (!RootContext.StdLib || pos_values [0].GetType () != typeof (UnmanagedType))
-                               UnmanagedType = (UnmanagedType)System.Enum.ToObject (typeof (UnmanagedType), pos_values [0]);
+                               UnmanagedType = (UnmanagedType) System.Enum.ToObject (typeof (UnmanagedType), pos_values [0]);
                        else
                                UnmanagedType = (UnmanagedType) pos_values [0];
 
@@ -953,12 +1017,12 @@ namespace Mono.CSharp {
                        }
 
                        object o = GetFieldValue ("ArraySubType");
-                       UnmanagedType array_sub_type = o == null ? UnmanagedType.I4 : (UnmanagedType) o;
-                       
+                       UnmanagedType array_sub_type = o == null ? (UnmanagedType) 0x50 /* NATIVE_MAX */ : (UnmanagedType) o;
+
                        switch (UnmanagedType) {
                        case UnmanagedType.CustomMarshaler: {
                                MethodInfo define_custom = typeof (UnmanagedMarshal).GetMethod ("DefineCustom",
-                                                                       BindingFlags.Static | BindingFlags.Public);
+                                       BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
                                if (define_custom == null) {
                                        Report.RuntimeMissingSupport (Location, "set marshal info");
                                        return null;
@@ -976,7 +1040,8 @@ namespace Mono.CSharp {
                                object size_param_index = GetFieldValue ("SizeParamIndex");
 
                                if ((size_const != null) || (size_param_index != null)) {
-                                       MethodInfo define_array = typeof (UnmanagedMarshal).GetMethod ("DefineLPArrayInternal", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
+                                       MethodInfo define_array = typeof (UnmanagedMarshal).GetMethod ("DefineLPArrayInternal",
+                                               BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
                                        if (define_array == null) {
                                                Report.RuntimeMissingSupport (Location, "set marshal info");
                                                return null;
@@ -993,7 +1058,7 @@ namespace Mono.CSharp {
                        }
                        case UnmanagedType.SafeArray:
                                return UnmanagedMarshal.DefineSafeArray (array_sub_type);
-                       
+
                        case UnmanagedType.ByValArray:
                                FieldMember fm = attr as FieldMember;
                                if (fm == null) {
@@ -1001,10 +1066,10 @@ namespace Mono.CSharp {
                                        return null;
                                }
                                return UnmanagedMarshal.DefineByValArray ((int) GetFieldValue ("SizeConst"));
-                       
+
                        case UnmanagedType.ByValTStr:
                                return UnmanagedMarshal.DefineByValTStr ((int) GetFieldValue ("SizeConst"));
-                       
+
                        default:
                                return UnmanagedMarshal.DefineUnmanagedMarshal (UnmanagedType);
                        }
@@ -1030,53 +1095,71 @@ namespace Mono.CSharp {
                        return (LayoutKind)pos_values [0];
                }
 
+               public override bool Equals (object obj)
+               {
+                       Attribute a = obj as Attribute;
+                       if (a == null)
+                               return false;
+
+                       return Type == a.Type && Target == a.Target;
+               }
+
+               public override int GetHashCode ()
+               {
+                       return base.GetHashCode ();
+               }
+
+               public object GetParameterDefaultValue ()
+               {
+                       return pos_values [0];
+               }
+
                /// <summary>
                /// Emit attribute for Attributable symbol
                /// </summary>
-               public void Emit (EmitContext ec, Attributable ias, ListDictionary emitted_attr)
+               public void Emit (ListDictionary allEmitted)
                {
-                       CustomAttributeBuilder cb = Resolve (ec);
+                       CustomAttributeBuilder cb = Resolve ();
                        if (cb == null)
                                return;
 
-                       AttributeUsageAttribute usage_attr = GetAttributeUsage (ec);
+                       AttributeUsageAttribute usage_attr = GetAttributeUsage ();
                        if ((usage_attr.ValidOn & Target) == 0) {
-                               Report.Error (592, Location, "Attribute `{0}' is not valid on this declaration type. It is valid on `{1}' declarations only",
+                               Report.Error (592, Location, "The attribute `{0}' is not valid on this declaration type. " +
+                                             "It is valid on `{1}' declarations only",
                                        GetSignatureForError (), GetValidTargets ());
                                return;
                        }
 
                        try {
-                               ias.ApplyAttributeBuilder (this, cb);
+                               foreach (Attributable owner in owners)
+                                       owner.ApplyAttributeBuilder (this, cb);
                        }
                        catch (Exception e) {
                                Error_AttributeEmitError (e.Message);
                                return;
                        }
 
-                       if (!usage_attr.AllowMultiple) {
-                               ArrayList emitted_targets = (ArrayList)emitted_attr [Type];
-                               if (emitted_targets == null) {
-                                       emitted_targets = new ArrayList ();
-                                       emitted_attr.Add (Type, emitted_targets);
-                               } else if (emitted_targets.Contains (Target)) {
-                                       Report.Error (579, Location, "Duplicate `{0}' attribute", GetSignatureForError ());
-                                       return;
+                       if (!usage_attr.AllowMultiple && allEmitted != null) {
+                               if (allEmitted.Contains (this)) {
+                                       ArrayList a = allEmitted [this] as ArrayList;
+                                       if (a == null) {
+                                               a = new ArrayList (2);
+                                               allEmitted [this] = a;
+                                       }
+                                       a.Add (this);
+                               } else {
+                                       allEmitted.Add (this, null);
                                }
-                               emitted_targets.Add (Target);
                        }
 
                        if (!RootContext.VerifyClsCompliance)
                                return;
 
                        // Here we are testing attribute arguments for array usage (error 3016)
-                       if (ias.IsClsCompliaceRequired (ec.DeclSpace)) {
-                               if (Arguments == null)
-                                       return;
-
-                               ArrayList pos_args = (ArrayList) Arguments [0];
-                               if (pos_args != null) {
-                                       foreach (Argument arg in pos_args) { 
+                       if (Owner.IsClsComplianceRequired ()) {
+                               if (PosArguments != null) {
+                                       foreach (Argument arg in PosArguments) { 
                                                // Type is undefined (was error 246)
                                                if (arg.Type == null)
                                                        return;
@@ -1088,11 +1171,10 @@ namespace Mono.CSharp {
                                        }
                                }
                        
-                               if (Arguments.Count < 2)
+                               if (NamedArguments == null)
                                        return;
                        
-                               ArrayList named_args = (ArrayList) Arguments [1];
-                               foreach (DictionaryEntry de in named_args) {
+                               foreach (DictionaryEntry de in NamedArguments) {
                                        Argument arg  = (Argument) de.Value;
 
                                        // Type is undefined (was error 246)
@@ -1107,13 +1189,13 @@ namespace Mono.CSharp {
                        }
                }
                
-               public MethodBuilder DefinePInvokeMethod (EmitContext ec, TypeBuilder builder, string name,
+               public MethodBuilder DefinePInvokeMethod (TypeBuilder builder, string name,
                                                          MethodAttributes flags, Type ret_type, Type [] param_types)
                {
                        if (pos_values == null)
                                // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
                                // But because a lot of attribute class code must be rewritten will be better to wait...
-                               Resolve (ec);
+                               Resolve ();
 
                        if (resolve_error)
                                return null;
@@ -1141,52 +1223,58 @@ namespace Mono.CSharp {
                        MethodInfo set_set_last_error = null;
 
                        if (field_info_arr != null) {
-
+                               
                                for (int i = 0; i < field_info_arr.Length; i++) {
                                        switch (field_info_arr [i].Name) {
-                                               case "BestFitMapping":
-                                                       best_fit_mapping = (bool) field_values_arr [i];
-                                                       best_fit_mapping_set = true;
-                                                       break;
-                                               case "CallingConvention":
-                                                       cc = (CallingConvention) field_values_arr [i];
-                                                       break;
-                                               case "CharSet":
-                                                       charset = (CharSet) field_values_arr [i];
-                                                       break;
-                                               case "EntryPoint":
-                                                       entry_point = (string) field_values_arr [i];
-                                                       break;
-                                               case "ExactSpelling":
-                                                       exact_spelling = (bool) field_values_arr [i];
-                                                       exact_spelling_set = true;
-                                                       break;
-                                               case "PreserveSig":
-                                                       preserve_sig = (bool) field_values_arr [i];
-                                                       break;
-                                               case "SetLastError":
-                                                       set_last_error = (bool) field_values_arr [i];
-                                                       set_last_error_set = true;
-                                                       break;
-                                               case "ThrowOnUnmappableChar":
-                                                       throw_on_unmappable = (bool) field_values_arr [i];
-                                                       throw_on_unmappable_set = true;
-                                                       break;
-                                               default: 
-                                                       throw new InternalErrorException (field_info_arr [i].ToString ());
+                                       case "BestFitMapping":
+                                               best_fit_mapping = (bool) field_values_arr [i];
+                                               best_fit_mapping_set = true;
+                                               break;
+                                       case "CallingConvention":
+                                               cc = (CallingConvention) field_values_arr [i];
+                                               break;
+                                       case "CharSet":
+                                               charset = (CharSet) field_values_arr [i];
+                                               break;
+                                       case "EntryPoint":
+                                               entry_point = (string) field_values_arr [i];
+                                               break;
+                                       case "ExactSpelling":
+                                               exact_spelling = (bool) field_values_arr [i];
+                                               exact_spelling_set = true;
+                                               break;
+                                       case "PreserveSig":
+                                               preserve_sig = (bool) field_values_arr [i];
+                                               break;
+                                       case "SetLastError":
+                                               set_last_error = (bool) field_values_arr [i];
+                                               set_last_error_set = true;
+                                               break;
+                                       case "ThrowOnUnmappableChar":
+                                               throw_on_unmappable = (bool) field_values_arr [i];
+                                               throw_on_unmappable_set = true;
+                                               break;
+                                       default: 
+                                               throw new InternalErrorException (field_info_arr [i].ToString ());
                                        }
                                }
                        }
-
+                       
                        if (throw_on_unmappable_set || best_fit_mapping_set || exact_spelling_set || set_last_error_set) {
-                               set_best_fit = typeof (MethodBuilder).GetMethod ("set_BestFitMapping", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
-                               set_throw_on = typeof (MethodBuilder).GetMethod ("set_ThrowOnUnmappableChar", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
-                               set_exact_spelling = typeof (MethodBuilder).GetMethod ("set_ExactSpelling", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
-                               set_set_last_error = typeof (MethodBuilder).GetMethod ("set_SetLastError", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
-
-                               if ((set_best_fit == null) || (set_throw_on == null) || (set_exact_spelling == null) || (set_set_last_error == null)) {
+                               set_best_fit = typeof (MethodBuilder).
+                                       GetMethod ("set_BestFitMapping", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
+                               set_throw_on = typeof (MethodBuilder).
+                                       GetMethod ("set_ThrowOnUnmappableChar", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
+                               set_exact_spelling = typeof (MethodBuilder).
+                                       GetMethod ("set_ExactSpelling", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
+                               set_set_last_error = typeof (MethodBuilder).
+                                       GetMethod ("set_SetLastError", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
+
+                               if ((set_best_fit == null) || (set_throw_on == null) ||
+                                   (set_exact_spelling == null) || (set_set_last_error == null)) {
                                        Report.Error (-1, Location,
-                                                                 "The ThrowOnUnmappableChar, BestFitMapping, SetLastError, and ExactSpelling attributes can only be emitted when running on the mono runtime.");
+                                                                 "The ThrowOnUnmappableChar, BestFitMapping, SetLastError, " +
+                                                     "and ExactSpelling attributes can only be emitted when running on the mono runtime.");
                                        return null;
                                }
                        }
@@ -1218,15 +1306,10 @@ namespace Mono.CSharp {
 
                private Expression GetValue () 
                {
-                       if ((Arguments == null) || (Arguments.Count < 1))
-                               return null;
-                       ArrayList al = (ArrayList) Arguments [0];
-                       if ((al == null) || (al.Count < 1))
-                               return null;
-                       Argument arg = (Argument) al [0];
-                       if ((arg == null) || (arg.Expr == null))
+                       if (PosArguments == null || PosArguments.Count < 1)
                                return null;
-                       return arg.Expr;
+
+                       return ((Argument) PosArguments [0]).Expr;
                }
 
                public string GetString () 
@@ -1251,15 +1334,15 @@ namespace Mono.CSharp {
        /// For global attributes (assembly, module) we need special handling.
        /// Attributes can be located in the several files
        /// </summary>
-       public class GlobalAttribute: Attribute
+       public class GlobalAttribute : Attribute
        {
                public readonly NamespaceEntry ns;
 
-               public GlobalAttribute (TypeContainer container, string target, 
-                                       Expression left_expr, string identifier, ArrayList args, Location loc, bool nameEscaped):
+               public GlobalAttribute (NamespaceEntry ns, string target, 
+                                       Expression left_expr, string identifier, object[] args, Location loc, bool nameEscaped):
                        base (target, left_expr, identifier, args, loc, nameEscaped)
                {
-                       ns = container.NamespaceEntry;
+                       this.ns = ns;
                }
 
                void Enter ()
@@ -1282,34 +1365,33 @@ namespace Mono.CSharp {
                        RootContext.Tree.Types.NamespaceEntry = null;
                }
 
-               protected override FullNamedExpression ResolveAsTypeStep (Expression expr, EmitContext ec, bool silent)
+               protected override TypeExpr ResolveAsTypeTerminal (Expression expr, IResolveContext ec, bool silent)
                {
                        try {
                                Enter ();
-                               return base.ResolveAsTypeStep (expr, ec, silent);
+                               return base.ResolveAsTypeTerminal (expr, ec, silent);
                        }
                        finally {
                                Leave ();
                        }
                }
 
-
-               protected override FullNamedExpression ResolveAsTypeTerminal (Expression expr, EmitContext ec, bool silent)
+               protected override ConstructorInfo ResolveConstructor (EmitContext ec)
                {
                        try {
                                Enter ();
-                               return base.ResolveAsTypeTerminal (expr, ec, silent);
+                               return base.ResolveConstructor (ec);
                        }
                        finally {
                                Leave ();
                        }
                }
 
-               protected override ConstructorInfo ResolveArguments (EmitContext ec)
+               protected override bool ResolveNamedArguments (EmitContext ec)
                {
                        try {
                                Enter ();
-                               return base.ResolveArguments (ec);
+                               return base.ResolveNamedArguments (ec);
                        }
                        finally {
                                Leave ();
@@ -1318,7 +1400,7 @@ namespace Mono.CSharp {
        }
 
        public class Attributes {
-               public ArrayList Attrs;
+               public readonly ArrayList Attrs;
 
                public Attributes (Attribute a)
                {
@@ -1336,46 +1418,28 @@ namespace Mono.CSharp {
                        Attrs.AddRange (attrs);
                }
 
+               public void AttachTo (Attributable attributable)
+               {
+                       foreach (Attribute a in Attrs)
+                               a.AttachTo (attributable);
+               }
+
                /// <summary>
                /// Checks whether attribute target is valid for the current element
                /// </summary>
-               public bool CheckTargets (Attributable member)
+               public bool CheckTargets ()
                {
-                       string[] valid_targets = member.ValidAttributeTargets;
                        foreach (Attribute a in Attrs) {
-                               if (a.ExplicitTarget == null || a.ExplicitTarget == valid_targets [0]) {
-                                       a.Target = member.AttributeTargets;
-                                       continue;
-                               }
-
-                               // TODO: we can skip the first item
-                               if (((IList) valid_targets).Contains (a.ExplicitTarget)) {
-                                       switch (a.ExplicitTarget) {
-                                               case "return": a.Target = AttributeTargets.ReturnValue; continue;
-                                               case "param": a.Target = AttributeTargets.Parameter; continue;
-                                               case "field": a.Target = AttributeTargets.Field; continue;
-                                               case "method": a.Target = AttributeTargets.Method; continue;
-                                               case "property": a.Target = AttributeTargets.Property; continue;
-                                       }
-                                       throw new InternalErrorException ("Unknown explicit target: " + a.ExplicitTarget);
-                               }
-
-                               StringBuilder sb = new StringBuilder ();
-                               foreach (string s in valid_targets) {
-                                       sb.Append (s);
-                                       sb.Append (", ");
-                               }
-                               sb.Remove (sb.Length - 2, 2);
-                               Report.Error (657, a.Location, "`{0}' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are `{1}'", a.ExplicitTarget, sb.ToString ());
-                               return false;
+                               if (!a.CheckTarget ())
+                                       return false;
                        }
                        return true;
                }
 
-               public Attribute Search (Type t, EmitContext ec)
+               public Attribute Search (Type t)
                {
                        foreach (Attribute a in Attrs) {
-                               if (a.ResolveType (ec) == t)
+                               if (a.ResolveType () == t)
                                        return a;
                        }
                        return null;
@@ -1384,12 +1448,12 @@ namespace Mono.CSharp {
                /// <summary>
                /// Returns all attributes of type 't'. Use it when attribute is AllowMultiple = true
                /// </summary>
-               public Attribute[] SearchMulti (Type t, EmitContext ec)
+               public Attribute[] SearchMulti (Type t)
                {
                        ArrayList ar = null;
 
                        foreach (Attribute a in Attrs) {
-                               if (a.ResolveType (ec) == t) {
+                               if (a.ResolveType () == t) {
                                        if (ar == null)
                                                ar = new ArrayList ();
                                        ar.Add (a);
@@ -1399,19 +1463,33 @@ namespace Mono.CSharp {
                        return ar == null ? null : ar.ToArray (typeof (Attribute)) as Attribute[];
                }
 
-               public void Emit (EmitContext ec, Attributable ias)
+               public void Emit ()
                {
-                       CheckTargets (ias);
+                       CheckTargets ();
 
-                       ListDictionary ld = new ListDictionary ();
+                       ListDictionary ld = Attrs.Count > 1 ? new ListDictionary () : null;
 
                        foreach (Attribute a in Attrs)
-                               a.Emit (ec, ias, ld);
+                               a.Emit (ld);
+
+                       if (ld == null || ld.Count == 0)
+                               return;
+
+                       foreach (DictionaryEntry d in ld) {
+                               if (d.Value == null)
+                                       continue;
+
+                               foreach (Attribute collision in (ArrayList)d.Value)
+                                       Report.SymbolRelatedToPreviousError (collision.Location, "");
+
+                               Attribute a = (Attribute)d.Key;
+                               Report.Error (579, a.Location, "The attribute `{0}' cannot be applied multiple times", a.GetSignatureForError ());
+                       }
                }
 
-               public bool Contains (Type t, EmitContext ec)
+               public bool Contains (Type t)
                {
-                        return Search (t, ec) != null;
+                       return Search (t) != null;
                }
        }
 
@@ -1420,22 +1498,38 @@ namespace Mono.CSharp {
        /// </summary>
        sealed class AttributeTester
        {
-               static PtrHashtable analyzed_types = new PtrHashtable ();
-               static PtrHashtable analyzed_types_obsolete = new PtrHashtable ();
-               static PtrHashtable analyzed_member_obsolete = new PtrHashtable ();
-               static PtrHashtable analyzed_method_excluded = new PtrHashtable ();
+               static PtrHashtable analyzed_types;
+               static PtrHashtable analyzed_types_obsolete;
+               static PtrHashtable analyzed_member_obsolete;
+               static PtrHashtable analyzed_method_excluded;
 
 #if NET_2_0
-               static PtrHashtable fixed_buffer_cache = new PtrHashtable ();
+               static PtrHashtable fixed_buffer_cache;
 #endif
 
                static object TRUE = new object ();
                static object FALSE = new object ();
 
+               static AttributeTester ()
+               {
+                       Reset ();
+               }
+
                private AttributeTester ()
                {
                }
 
+               public static void Reset ()
+               {
+                       analyzed_types = new PtrHashtable ();
+                       analyzed_types_obsolete = new PtrHashtable ();
+                       analyzed_member_obsolete = new PtrHashtable ();
+                       analyzed_method_excluded = new PtrHashtable ();
+#if NET_2_0
+                       fixed_buffer_cache = new PtrHashtable ();
+#endif
+               }
+
                public enum Result {
                        Ok,
                        RefOutArrayError,
@@ -1497,24 +1591,6 @@ namespace Mono.CSharp {
                        return result;
                }
 
-               /// <summary>
-               /// Goes through all parameters and test if they are CLS-Compliant.
-               /// </summary>
-               public static bool AreParametersCompliant (Parameter[] fixedParameters, Location loc)
-               {
-                       if (fixedParameters == null)
-                               return true;
-
-                       foreach (Parameter arg in fixedParameters) {
-                               if (!AttributeTester.IsClsCompliant (arg.ParameterType)) {
-                                       Report.Error (3001, loc, "Argument type `{0}' is not CLS-compliant", arg.GetSignatureForError ());
-                                       return false;
-                               }
-                       }
-                       return true;
-               }
-
-
                /// <summary>
                /// This method tests the CLS compliance of external types. It doesn't test type visibility.
                /// </summary>
@@ -1576,7 +1652,7 @@ namespace Mono.CSharp {
 
                public static void VerifyModulesClsCompliance ()
                {
-                       Module[] modules = TypeManager.Modules;
+                       Module[] modules = RootNamespace.Global.Modules;
                        if (modules == null)
                                return;
 
@@ -1584,7 +1660,8 @@ namespace Mono.CSharp {
                        for (int i = 1; i < modules.Length; ++i) {
                                Module module = modules [i];
                                if (!IsClsCompliant (module)) {
-                                       Report.Error (3013, "Added modules must be marked with the CLSCompliant attribute to match the assembly", module.Name);
+                                       Report.Error (3013, "Added modules must be marked with the CLSCompliant attribute " +
+                                                     "to match the assembly", module.Name);
                                        return;
                                }
                        }
@@ -1592,7 +1669,7 @@ namespace Mono.CSharp {
 
                public static Type GetImportedIgnoreCaseClsType (string name)
                {
-                       foreach (Assembly a in TypeManager.GetAssemblies ()) {
+                       foreach (Assembly a in RootNamespace.Global.Assemblies) {
                                Type t = a.GetType (name, false, true);
                                if (t == null)
                                        continue;
@@ -1616,7 +1693,7 @@ namespace Mono.CSharp {
                {
                        DeclSpace ds = TypeManager.LookupDeclSpace (type);
                        if (ds != null) {
-                               return ds.IsClsCompliaceRequired (ds.Parent);
+                               return ds.IsClsComplianceRequired ();
                        }
 
                        object[] CompliantAttribute = type.GetCustomAttributes (TypeManager.cls_compliant_attribute_type, false);
@@ -1650,11 +1727,14 @@ namespace Mono.CSharp {
                                        if (attribute.Length == 1)
                                                result = (ObsoleteAttribute)attribute [0];
                                } else {
-                                       result = type_ds.GetObsoleteAttribute (type_ds);
+                                       // Is null during corlib bootstrap
+                                       if (TypeManager.obsolete_attribute_type != null)
+                                               result = type_ds.GetObsoleteAttribute ();
                                }
                        }
 
-                       analyzed_types_obsolete.Add (type, result == null ? FALSE : result);
+                       // Cannot use .Add because of corlib bootstrap
+                       analyzed_types_obsolete [type] = result == null ? FALSE : result;
                        return result;
                }
 
@@ -1695,7 +1775,8 @@ namespace Mono.CSharp {
                        if (type_obsolete != null)
                                return (ObsoleteAttribute)type_obsolete;
 
-                       ObsoleteAttribute oa = System.Attribute.GetCustomAttribute (mi, TypeManager.obsolete_attribute_type, false) as ObsoleteAttribute;
+                       ObsoleteAttribute oa = System.Attribute.GetCustomAttribute (mi, TypeManager.obsolete_attribute_type, false)
+                               as ObsoleteAttribute;
                        analyzed_member_obsolete.Add (mi, oa == null ? FALSE : oa);
                        return oa;
                }
@@ -1711,11 +1792,10 @@ namespace Mono.CSharp {
                        }
 
                        if (oa.Message == null) {
-                               Report.Warning (612, loc, "`{0}' is obsolete", member);
+                               Report.Warning (612, 1, loc, "`{0}' is obsolete", member);
                                return;
                        }
-                       if (RootContext.WarningLevel >= 2)
-                               Report.Warning (618, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
+                       Report.Warning (618, 2, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
                }
 
                public static bool IsConditionalMethodExcluded (MethodBase mb)
@@ -1724,7 +1804,8 @@ namespace Mono.CSharp {
                        if (excluded != null)
                                return excluded == TRUE ? true : false;
                        
-                       ConditionalAttribute[] attrs = mb.GetCustomAttributes (TypeManager.conditional_attribute_type, true) as ConditionalAttribute[];
+                       ConditionalAttribute[] attrs = mb.GetCustomAttributes (TypeManager.conditional_attribute_type, true)
+                               as ConditionalAttribute[];
                        if (attrs.Length == 0) {
                                analyzed_method_excluded.Add (mb, FALSE);
                                return false;
@@ -1764,5 +1845,25 @@ namespace Mono.CSharp {
 
                        return class_decl.IsExcluded ();
                }
+
+               public static Type GetCoClassAttribute (Type type)
+               {
+                       TypeContainer tc = TypeManager.LookupInterface (type);
+                       if (tc == null) {
+                               object[] o = type.GetCustomAttributes (TypeManager.coclass_attr_type, false);
+                               if (o.Length < 1)
+                                       return null;
+                               return ((System.Runtime.InteropServices.CoClassAttribute)o[0]).CoClass;
+                       }
+
+                       if (tc.OptAttributes == null)
+                               return null;
+
+                       Attribute a = tc.OptAttributes.Search (TypeManager.coclass_attr_type);
+                       if (a == null)
+                               return null;
+
+                       return a.GetCoClassAttributeValue ();
+               }
        }
 }