2007-03-15 Jonathan Pobst <monkey@jpobst.com>
[mono.git] / mcs / mcs / attribute.cs
index 49726e940920d48f7f12d8c83b4730b5731ec939..c92254c81d07442e755f1f219939389aba30922d 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;
+               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,19 +108,53 @@ 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 " +
@@ -124,18 +169,28 @@ namespace Mono.CSharp {
                                      "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_TypeParameterInAttribute (Location loc)
+               {
+                       Report.Error (
+                               -202, loc, "Can not use a type parameter in an attribute");
                }
 
-               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");
+               }
+
+               public void Error_MisusedExtensionAttribute ()
+               {
+                       Report.Error (1112, Location, "Do not use `{0}' directly. Use parameter modifier `this' instead", GetSignatureForError ());
                }
-               
 
                /// <summary>
                /// This is rather hack. We report many emit attribute error with same error to be compatible with
@@ -152,34 +207,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);
@@ -191,14 +245,14 @@ 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);
 
                        bool t2_is_attr = false;
                        Type t2 = nameEscaped ? null :
-                               ResolvePossibleAttributeType (ec, Identifier + "Attribute", true, ref t2_is_attr);
+                               ResolvePossibleAttributeType (Identifier + "Attribute", true, ref t2_is_attr);
 
                        if (t1_is_attr && t2_is_attr) {
                                Report.Error (1614, Location, "`{0}' is ambiguous between `{0}' and `{0}Attribute'. " +
@@ -218,60 +272,28 @@ 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);
-                       } else if (e is As) {
-                               As as_e = (As) e;
-                               return GetAttributeArgumentExpression (as_e.Expr, loc, as_e.ProbeType.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)
@@ -286,10 +308,30 @@ namespace Mono.CSharp {
                                t == TypeManager.type_type;
                }
 
-               // Cache for parameter-less attributes
-               static PtrHashtable att_cache = new PtrHashtable ();
+               [Conditional ("GMCS_SOURCE")]
+               void ApplyModuleCharSet ()
+               {
+                       if (Type != TypeManager.dllimport_type)
+                               return;
 
-               public CustomAttributeBuilder Resolve (EmitContext ec)
+                       if (!CodeGen.Module.HasDefaultCharSet)
+                               return;
+
+                       const string CharSetEnumMember = "CharSet";
+                       if (NamedArguments == null) {
+                               NamedArguments = new ArrayList (1);
+                       } else {
+                               foreach (DictionaryEntry de in NamedArguments) {
+                                       if ((string)de.Key == CharSetEnumMember)
+                                               return;
+                               }
+                       }
+                       
+                       NamedArguments.Add (new DictionaryEntry (CharSetEnumMember,
+                               new Argument (Constant.CreateConstant (typeof (CharSet), CodeGen.Module.DefaultCharSet, Location))));
+               }
+
+               public CustomAttributeBuilder Resolve ()
                {
                        if (resolve_error)
                                return null;
@@ -297,7 +339,7 @@ namespace Mono.CSharp {
                        resolve_error = true;
 
                        if (Type == null) {
-                               ResolveAttributeType (ec);
+                               ResolveAttributeType ();
                                if (Type == null)
                                        return null;
                        }
@@ -312,7 +354,7 @@ namespace Mono.CSharp {
                                AttributeTester.Report_ObsoleteMessage (obsolete_attr, TypeManager.CSharpName (Type), Location);
                        }
 
-                       if (Arguments == null) {
+                       if (PosArguments == null && NamedArguments == null) {
                                object o = att_cache [Type];
                                if (o != null) {
                                        resolve_error = false;
@@ -320,298 +362,299 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       ConstructorInfo ctor = ResolveArguments (ec);
-                       if (ctor == null)
+                       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) {
+                               if (Type is TypeBuilder && 
+                                   TypeManager.LookupDeclSpace (Type).MemberCache == null)
+                                       // The attribute type has been DefineType'd, but not Defined.  Let's not treat it as an error.
+                                       // It'll be resolved again when the attached-to entity is emitted.
+                                       resolve_error = false;
                                return null;
+                       }
 
-                       CustomAttributeBuilder cb;
+                       ApplyModuleCharSet ();
 
+                       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 = ((MethodGroupExpr)mg).OverloadResolve (
+                               ec, 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;
+                               }
 
-                               e = a.Expr;
+                               object [] params_array = (object []) pos_values [last_real_param];
+                               params_array [j - last_real_param] = pos_values [j];
+                       }
 
-                               object val;
-                               if (!GetAttributeArgumentExpression (e, Location, a.Type, out val))
+                       // 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;
+                       }
+
+                       // 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;
+                       }
 
-                       ArrayList field_infos = null;
-                       ArrayList prop_infos  = null;
-                       ArrayList field_values = null;
-                       ArrayList prop_values = null;
-                       Hashtable seen_names = null;
+                       return (ConstructorInfo)constructor;
+               }
 
-                       if (named_arg_count > 0) {
-                               field_infos = new ArrayList ();
-                               prop_infos  = new ArrayList ();
-                               field_values = new ArrayList ();
-                               prop_values = new ArrayList ();
+               protected virtual bool ResolveNamedArguments (EmitContext ec)
+               {
+                       int named_arg_count = NamedArguments.Count;
 
-                               seen_names = new Hashtable();
-                       }
+                       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);
+
+                       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) {
+                                               Report.SymbolRelatedToPreviousError (member.Type);
                                                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;
+                                       Expression.Error_TypeDoesNotContainDefinition (Location, Type, member_name);
+                                       return false;
                                }
                                
                                if (!(member is PropertyExpr || member is FieldExpr)) {
                                        Error_InvalidNamedArgument (member_name);
-                                       return null;
+                                       return false;
                                }
 
-                               e = a.Expr;
+                               if (a.Expr is TypeParameterExpr){
+                                       Error_TypeParameterInAttribute (Location);
+                                       return false;
+                               }
+
+                               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);
-                                       return null;
-                               }
-                       }
-
-                       if (Type == TypeManager.methodimpl_attr_type &&
-                               pos_values.Length == 1 && ((Argument)pos_args [0]).Type == TypeManager.short_type &&
-                               !System.Enum.IsDefined (typeof (MethodImplOptions), pos_values [0])) {
-                                       Error_AttributeEmitError ("Incorrect argument value.");
-                               return null;
-                       }
-
-                       //
-                       // Now we perform some checks on the positional args as they
-                       // cannot be null for a constructor which expects a parameter
-                       // of type object
-                       //
-
-                       ParameterData pd = 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];
-                       }
-
-                       // 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;
+                               if (obsolete_attr != null && !Owner.ResolveContext.IsInObsoleteScope)
+                                       AttributeTester.Report_ObsoleteMessage (obsolete_attr, member.GetSignatureForError (), member.Location);
                        }
 
-                       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];
+                       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>
@@ -620,7 +663,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, ");
@@ -674,7 +717,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)
@@ -691,22 +734,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;
@@ -727,12 +770,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;
@@ -743,12 +786,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;
@@ -759,12 +802,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;
@@ -783,12 +826,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;
@@ -796,29 +839,79 @@ 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>
                public bool CheckSecurityActionValidity (bool for_assembly)
                {
-                       SecurityAction action  = GetSecurityActionValue ();
+                       SecurityAction action = GetSecurityActionValue ();
 
-                       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)
+                       switch (action) {
+                       case SecurityAction.Demand:
+                       case SecurityAction.Assert:
+                       case SecurityAction.Deny:
+                       case SecurityAction.PermitOnly:
+                       case SecurityAction.LinkDemand:
+                       case SecurityAction.InheritanceDemand:
+                               if (!for_assembly)
+                                       return true;
+                               break;
+
+                       case SecurityAction.RequestMinimum:
+                       case SecurityAction.RequestOptional:
+                       case SecurityAction.RequestRefuse:
+                               if (for_assembly)
                                        return true;
+                               break;
+
+                       default:
+                               Error_AttributeEmitError ("SecurityAction is out of range");
+                               return false;
                        }
 
-                       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;
                }
 
@@ -923,7 +1016,7 @@ namespace Mono.CSharp {
                        ps.AddPermission (perm);
                }
 
-               object GetValue (object value)
+               static object GetValue (object value)
                {
                        if (value is EnumConstant)
                                return ((EnumConstant) value).GetValue ();
@@ -1021,7 +1114,7 @@ namespace Mono.CSharp {
                                return UnmanagedMarshal.DefineSafeArray (array_sub_type);
 
                        case UnmanagedType.ByValArray:
-                               FieldMember fm = attr as FieldMember;
+                               FieldBase fm = attr as FieldBase;
                                if (fm == null) {
                                        Error_AttributeEmitError ("Specified unmanaged type is only valid on fields");
                                        return null;
@@ -1041,11 +1134,19 @@ namespace Mono.CSharp {
                        return (CharSet)System.Enum.Parse (typeof (CharSet), pos_values [0].ToString ());
                }
 
-               public MethodImplOptions GetMethodImplOptions ()
-               {
-                       if (pos_values [0].GetType () != typeof (MethodImplOptions))
-                               return (MethodImplOptions)System.Enum.ToObject (typeof (MethodImplOptions), pos_values [0]);
-                       return (MethodImplOptions)pos_values [0];
+               public bool IsInternalMethodImplAttribute {
+                       get {
+                               if (Type != TypeManager.methodimpl_attr_type)
+                                       return false;
+
+                               MethodImplOptions options;
+                               if (pos_values[0].GetType () != typeof (MethodImplOptions))
+                                       options = (MethodImplOptions)System.Enum.ToObject (typeof (MethodImplOptions), pos_values[0]);
+                               else
+                                       options = (MethodImplOptions)pos_values[0];
+
+                               return (options & MethodImplOptions.InternalCall) != 0;
+                       }
                }
 
                public LayoutKind GetLayoutKindValue ()
@@ -1056,54 +1157,71 @@ namespace Mono.CSharp {
                        return (LayoutKind)pos_values [0];
                }
 
+               public object GetParameterDefaultValue ()
+               {
+                       return 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 ();
+               }
+
                /// <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. " +
+                               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;
@@ -1115,11 +1233,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)
@@ -1133,133 +1250,13 @@ namespace Mono.CSharp {
                                }
                        }
                }
-               
-               public MethodBuilder DefinePInvokeMethod (EmitContext ec, 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);
-
-                       if (resolve_error)
-                               return null;
-                       
-                       string dll_name = (string)pos_values [0];
-
-                       // Default settings
-                       CallingConvention cc = CallingConvention.Winapi;
-                       CharSet charset = CodeGen.Module.DefaultCharSet;
-                       bool preserve_sig = true;
-                       string entry_point = name;
-                       bool best_fit_mapping = false;
-                       bool throw_on_unmappable = false;
-                       bool exact_spelling = false;
-                       bool set_last_error = false;
-
-                       bool best_fit_mapping_set = false;
-                       bool throw_on_unmappable_set = false;
-                       bool exact_spelling_set = false;
-                       bool set_last_error_set = false;
-
-                       MethodInfo set_best_fit = null;
-                       MethodInfo set_throw_on = null;
-                       MethodInfo set_exact_spelling = null;
-                       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 ());
-                                       }
-                               }
-                       }
-                       
-                       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)) {
-                                       Report.Error (-1, Location,
-                                                                 "The ThrowOnUnmappableChar, BestFitMapping, SetLastError, " +
-                                                     "and ExactSpelling attributes can only be emitted when running on the mono runtime.");
-                                       return null;
-                               }
-                       }
-
-                       try {
-                               MethodBuilder mb = builder.DefinePInvokeMethod (
-                                       name, dll_name, entry_point, flags | MethodAttributes.HideBySig | MethodAttributes.PinvokeImpl,
-                                       CallingConventions.Standard, ret_type, param_types, cc, charset);
-
-                               if (preserve_sig)
-                                       mb.SetImplementationFlags (MethodImplAttributes.PreserveSig);
-
-                               if (throw_on_unmappable_set)
-                                       set_throw_on.Invoke (mb, 0, null, new object [] { throw_on_unmappable }, null);
-                               if (best_fit_mapping_set)
-                                       set_best_fit.Invoke (mb, 0, null, new object [] { best_fit_mapping }, null);
-                               if (exact_spelling_set)
-                                       set_exact_spelling.Invoke  (mb, 0, null, new object [] { exact_spelling }, null);
-                               if (set_last_error_set)
-                                       set_set_last_error.Invoke  (mb, 0, null, new object [] { set_last_error }, null);
-                       
-                               return mb;
-                       }
-                       catch (ArgumentException e) {
-                               Error_AttributeEmitError (e.Message);
-                               return null;
-                       }
-               }
 
                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 () 
@@ -1277,6 +1274,14 @@ namespace Mono.CSharp {
                                return (e as BoolLiteral).Value;
                        return false;
                }
+
+               public Type GetArgumentType ()
+               {
+                       TypeOf e = GetValue () as TypeOf;
+                       if (e == null)
+                               return null;
+                       return e.TypeArgument;
+               }
        }
        
 
@@ -1288,61 +1293,60 @@ namespace Mono.CSharp {
        {
                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 ()
                {
-                       // RootContext.Tree.Types has a single NamespaceEntry which gets overwritten
+                       // RootContext.ToplevelTypes has a single NamespaceEntry which gets overwritten
                        // each time a new file is parsed.  However, we need to use the NamespaceEntry
                        // in effect where the attribute was used.  Since code elsewhere cannot assume
                        // that the NamespaceEntry is right, just overwrite it.
                        //
-                       // Precondition: RootContext.Tree.Types == null
+                       // Precondition: RootContext.ToplevelTypes == null
 
-                       if (RootContext.Tree.Types.NamespaceEntry != null)
+                       if (RootContext.ToplevelTypes.NamespaceEntry != null)
                                throw new InternalErrorException (Location + " non-null NamespaceEntry");
 
-                       RootContext.Tree.Types.NamespaceEntry = ns;
+                       RootContext.ToplevelTypes.NamespaceEntry = ns;
                }
 
                void Leave ()
                {
-                       RootContext.Tree.Types.NamespaceEntry = null;
+                       RootContext.ToplevelTypes.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 ();
@@ -1351,7 +1355,7 @@ namespace Mono.CSharp {
        }
 
        public class Attributes {
-               public ArrayList Attrs;
+               public readonly ArrayList Attrs;
 
                public Attributes (Attribute a)
                {
@@ -1369,47 +1373,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;
@@ -1418,12 +1403,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);
@@ -1433,19 +1418,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;
                }
        }
 
@@ -1454,22 +1453,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,
@@ -1531,24 +1546,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>
@@ -1581,6 +1578,10 @@ namespace Mono.CSharp {
                /// </summary>
                public static IFixedBuffer GetFixedBuffer (FieldInfo fi)
                {
+                       // Fixed buffer helper type is generated as value type
+                       if (!fi.FieldType.IsValueType)
+                               return null;
+
                        FieldBase fb = TypeManager.GetField (fi);
                        if (fb != null) {
                                return fb as IFixedBuffer;
@@ -1605,7 +1606,7 @@ namespace Mono.CSharp {
                        return (IFixedBuffer)o;
 #else
                        return null;
-#endif
+#endif         
                }
 
                public static void VerifyModulesClsCompliance ()
@@ -1649,11 +1650,15 @@ namespace Mono.CSharp {
 
                static bool AnalyzeTypeCompliance (Type type)
                {
+                       type = TypeManager.DropGenericTypeArguments (type);
                        DeclSpace ds = TypeManager.LookupDeclSpace (type);
                        if (ds != null) {
-                               return ds.IsClsCompliaceRequired (ds.Parent);
+                               return ds.IsClsComplianceRequired ();
                        }
 
+                       if (TypeManager.IsGenericParameter (type))
+                               return true;
+
                        object[] CompliantAttribute = type.GetCustomAttributes (TypeManager.cls_compliant_attribute_type, false);
                        if (CompliantAttribute.Length == 0) 
                                return IsClsCompliant (type.Assembly);
@@ -1661,6 +1666,13 @@ namespace Mono.CSharp {
                        return ((CLSCompliantAttribute)CompliantAttribute[0]).IsCompliant;
                }
 
+               // Registers the core type as we assume that they will never be obsolete which
+               // makes things easier for bootstrap and faster (we don't need to query Obsolete attribute).
+               public static void RegisterNonObsoleteType (Type type)
+               {
+                       analyzed_types_obsolete [type] = FALSE;
+               }
+
                /// <summary>
                /// Returns instance of ObsoleteAttribute when type is obsolete
                /// </summary>
@@ -1674,9 +1686,11 @@ namespace Mono.CSharp {
                                return (ObsoleteAttribute)type_obsolete;
 
                        ObsoleteAttribute result = null;
-                       if (type.IsByRef || type.IsArray || type.IsPointer) {
+                       if (TypeManager.HasElementType (type)) {
                                result = GetObsoleteAttribute (TypeManager.GetElementType (type));
-                       } else {
+                       } else if (TypeManager.IsGenericParameter (type) || TypeManager.IsGenericType (type))
+                               return null;
+                       else {
                                DeclSpace type_ds = TypeManager.LookupDeclSpace (type);
 
                                // Type is external, we can get attribute directly
@@ -1707,14 +1721,13 @@ namespace Mono.CSharp {
                        if (mb.DeclaringType is TypeBuilder)
                                return null;
 
-                       if (mb.IsSpecialName) {
-                               PropertyInfo pi = PropertyExpr.AccessorTable [mb] as PropertyInfo;
-                               if (pi != null) {
-                                       // FIXME: This is buggy as properties from this assembly are included as well
-                                       return null;
-                                       //return GetMemberObsoleteAttribute (pi);
-                               }
-                       }
+                       MemberInfo mi = TypeManager.GetPropertyFromAccessor (mb);
+                       if (mi != null)
+                               return GetMemberObsoleteAttribute (mi);
+
+                       mi = TypeManager.GetEventFromAccessor (mb);
+                       if (mi != null)
+                               return GetMemberObsoleteAttribute (mi);
 
                        return GetMemberObsoleteAttribute (mb);
                }
@@ -1731,6 +1744,9 @@ namespace Mono.CSharp {
                        if (type_obsolete != null)
                                return (ObsoleteAttribute)type_obsolete;
 
+                       if ((mi.DeclaringType is TypeBuilder) || TypeManager.IsGenericType (mi.DeclaringType))
+                               return null;
+
                        ObsoleteAttribute oa = System.Attribute.GetCustomAttribute (mi, TypeManager.obsolete_attribute_type, false)
                                as ObsoleteAttribute;
                        analyzed_member_obsolete.Add (mi, oa == null ? FALSE : oa);
@@ -1748,19 +1764,22 @@ 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)
                {
+                       mb = TypeManager.DropGenericMethodArguments (mb);
+                       if ((mb is MethodBuilder) || (mb is ConstructorBuilder))
+                               return false;
+
                        object excluded = analyzed_method_excluded [mb];
                        if (excluded != null)
                                return excluded == TRUE ? true : false;
-                       
+
                        ConditionalAttribute[] attrs = mb.GetCustomAttributes (TypeManager.conditional_attribute_type, true)
                                as ConditionalAttribute[];
                        if (attrs.Length == 0) {
@@ -1802,5 +1821,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 ();
+               }
        }
 }