**** Merged r40732-r40872 from MCS ****
[mono.git] / mcs / gmcs / attribute.cs
index 73985960ea92685e702ef9d3d4ced01339e25984..1e6a5e7137de37b6d05da6e358f8c85cbe364144 100644 (file)
@@ -2,6 +2,7 @@
 // attribute.cs: Attribute Handler
 //
 // Author: Ravi Pratap (ravi@ximian.com)
+//         Marek Safar (marek.safar@seznam.cz)
 //
 // Licensed under the terms of the GNU GPL
 //
@@ -17,6 +18,8 @@ using System.Reflection;
 using System.Reflection.Emit;
 using System.Runtime.InteropServices;
 using System.Runtime.CompilerServices;
+using System.Security; 
+using System.Security.Permissions;
 using System.Text;
 
 namespace Mono.CSharp {
@@ -30,11 +33,9 @@ namespace Mono.CSharp {
                /// </summary>
                Attributes attributes;
 
-               public Attributable(Attributes attrs)
+               public Attributable (Attributes attrs)
                {
                        attributes = attrs;
-                       if (attributes != null)
-                               attributes.CheckTargets (ValidAttributeTargets);
                }
 
                public Attributes OptAttributes 
@@ -44,8 +45,6 @@ namespace Mono.CSharp {
                        }
                        set {
                                attributes = value;
-                               if (attributes != null)
-                                       attributes.CheckTargets (ValidAttributeTargets);
                        }
                }
 
@@ -55,7 +54,7 @@ namespace Mono.CSharp {
                public abstract void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb);
 
                /// <summary>
-               /// Returns combination of enabled AttributeTargets
+               /// Returns one AttributeTarget for this element.
                /// </summary>
                public abstract AttributeTargets AttributeTargets { get; }
 
@@ -65,18 +64,25 @@ namespace Mono.CSharp {
                /// Gets list of valid attribute targets for explicit target declaration.
                /// The first array item is default target. Don't break this rule.
                /// </summary>
-               protected abstract string[] ValidAttributeTargets { get; }
+               public abstract string[] ValidAttributeTargets { get; }
        };
 
        public class Attribute {
-               public string Target;
+               public readonly string ExplicitTarget;
+               public AttributeTargets Target;
+
                public readonly string    Name;
+               public readonly Expression LeftExpr;
+               public readonly string Identifier;
+
                public readonly ArrayList Arguments;
 
                public readonly Location Location;
 
                public Type Type;
                
+               bool resolve_error;
+
                // Is non-null if type is AttributeUsageAttribute
                AttributeUsageAttribute usage_attribute;
 
@@ -99,87 +105,143 @@ namespace Mono.CSharp {
 
                static PtrHashtable usage_attr_cache = new PtrHashtable ();
                
-               public Attribute (string target, string name, ArrayList args, Location loc)
+               public Attribute (string target, Expression left_expr, string identifier, ArrayList args, Location loc)
                {
-                       Name = name;
+                       LeftExpr = left_expr;
+                       Identifier = identifier;
+                       Name = LeftExpr == null ? identifier : LeftExpr + "." + identifier;
                        Arguments = args;
                        Location = loc;
-                       Target = target;
+                       ExplicitTarget = target;
                }
 
                void Error_InvalidNamedArgument (string name)
                {
-                       Report.Error (617, Location, "'" + name + "' is not a valid named attribute " +
-                                     "argument. Named attribute arguments must be fields which are not " +
-                                     "readonly, static or const, or properties with a set accessor which "+
-                                     "are not static.");
+                       Report.Error (617, Location, "Invalid attribute argument: '{0}'.  Argument must be fields " +
+                                     "fields which are not readonly, static or const;  or read-write instance properties.",
+                                     name);
                }
 
-               static void Error_AttributeArgumentNotValid (Location loc)
+               static void Error_AttributeArgumentNotValid (string extra, Location loc)
                {
                        Report.Error (182, loc,
                                      "An attribute argument must be a constant expression, typeof " +
-                                     "expression or array creation expression");
+                                     "expression or array creation expression" + extra);
                }
 
+               static void Error_AttributeArgumentNotValid (Location loc)
+               {
+                       Error_AttributeArgumentNotValid ("", loc);
+               }
+               
                static void Error_TypeParameterInAttribute (Location loc)
                {
                        Report.Error (
                                -202, loc, "Can not use a type parameter in an attribute");
                }
 
+               /// <summary>
+               /// This is rather hack. We report many emit attribute error with same error to be compatible with
+               /// csc. But because csc has to report them this way because error came from ilasm we needn't.
+               /// </summary>
+               public void Error_AttributeEmitError (string inner)
+               {
+                       Report.Error (647, Location, "Error emitting '{0}' attribute because '{1}'", Name, inner);
+               }
+
+               public void Error_InvalidSecurityParent ()
+               {
+                       Error_AttributeEmitError ("it is attached to invalid parent");
+               }
+
                void Error_AttributeConstructorMismatch ()
                {
                        Report.Error (-6, Location,
                                       "Could not find a constructor for this argument list.");
                }
 
+               void ResolvePossibleAttributeTypes (EmitContext ec, out Type t1, out Type t2)
+               {
+                       t1 = null;
+                       t2 = null;
+
+                       FullNamedExpression n1 = null;
+                       FullNamedExpression n2 = null;
+                       string IdentifierAttribute = Identifier + "Attribute";
+                       if (LeftExpr == null) {
+                               n1 = new SimpleName (Identifier, Location).ResolveAsTypeStep (ec);
+
+                               // FIXME: Shouldn't do this for quoted attributes: [@A]
+                               n2 = new SimpleName (IdentifierAttribute, Location).ResolveAsTypeStep (ec);
+                       } else {
+                               FullNamedExpression l = LeftExpr.ResolveAsTypeStep (ec);
+                               if (l == null) {
+                                       Report.Error (246, Location, "Couldn't find namespace or type '{0}'", LeftExpr);
+                                       return;
+                               }
+                               n1 = new MemberAccess (l, Identifier, Location).ResolveNamespaceOrType (ec, true);
+
+                               // FIXME: Shouldn't do this for quoted attributes: [X.@A]
+                               n2 = new MemberAccess (l, IdentifierAttribute, Location).ResolveNamespaceOrType (ec, true);
+                       }
+
+                       TypeExpr te1 = n1 == null ? null : n1 as TypeExpr;
+                       TypeExpr te2 = n2 == null ? null : n2 as TypeExpr;                      
+
+                       if (te1 != null)
+                               t1 = te1.ResolveType (ec);
+                       if (te2 != null)
+                               t2 = te2.ResolveType (ec);
+               }
+
                /// <summary>
                 ///   Tries to resolve the type of the attribute. Flags an error if it can't, and complain is true.
                 /// </summary>
-               protected virtual Type CheckAttributeType (EmitContext ec, bool complain)
+               Type CheckAttributeType (EmitContext ec)
                {
-                       TypeExpr t1 = RootContext.LookupType (ec.DeclSpace, Name, true, Location);
-                       // FIXME: Shouldn't do this for quoted attributes: [@A]
-                       TypeExpr t2 = RootContext.LookupType (ec.DeclSpace, Name + "Attribute", true, Location);
+                       Type t1, t2;
+                       ResolvePossibleAttributeTypes (ec, out t1, out t2);
+
+                       string NameAttribute = Name + "Attribute";
 
                        String err0616 = null;
-                       if (t1 != null && ! t1.IsAttribute) {
+                       if (t1 != null && ! t1.IsSubclassOf (TypeManager.attribute_type)) {
                                t1 = null;
                                err0616 = "'" + Name + "': is not an attribute class";
                        }
-                       if (t2 != null && ! t2.IsAttribute) {
+                       if (t2 != null && ! t2.IsSubclassOf (TypeManager.attribute_type)) {
                                t2 = null;
                                err0616 = (err0616 != null) 
-                                       ? "Neither '" + Name + "' nor '" + Name + "Attribute' is an attribute class"
+                                       ? "Neither '" + Name + "' nor '" + NameAttribute +"' is an attribute class"
                                        : "'" + Name + "Attribute': is not an attribute class";
                        }
 
                        if (t1 != null && t2 != null) {
                                Report.Error(1614, Location, "'" + Name + "': is ambiguous; " 
-                                            + " use either '@" + Name + "' or '" + Name + "Attribute'");
+                                            + " use either '@" + Name + "' or '" + NameAttribute + "'");
                                return null;
                        }
                        if (t1 != null)
-                               return t1.ResolveType (ec);
+                               return t1;
                        if (t2 != null)
-                               return t2.ResolveType (ec);
+                               return t2;
                        if (err0616 != null) {
                                Report.Error (616, Location, err0616);
                                return null;
                        }
 
-                       if (complain)
-                               Report.Error (246, Location, 
-                                             "Could not find attribute '" + Name 
-                                             + "' (are you missing a using directive or an assembly reference ?)");
+                       Report.Error (246, Location, 
+                                     "Could not find attribute '" + Name 
+                                     + "' (are you missing a using directive or an assembly reference ?)");
+
+                       resolve_error = true;
                        return null;
                }
 
-               public Type ResolveType (EmitContext ec, bool complain)
+               public virtual Type ResolveType (EmitContext ec)
                {
                        if (Type == null)
-                               Type = CheckAttributeType (ec, complain);
+                               Type = CheckAttributeType (ec);
                        return Type;
                }
 
@@ -206,10 +268,28 @@ namespace Mono.CSharp {
                // 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, out object result)
+               public static bool GetAttributeArgumentExpression (Expression e, Location loc, Type arg_type, out object result)
                {
-                       if (e is Constant) {
-                               result = ((Constant) e).GetValue ();
+                       if (e is EnumConstant) {
+                               if (RootContext.StdLib)
+                                       result = ((EnumConstant)e).GetValueAsEnumType ();
+                               else
+                                       result = ((EnumConstant)e).GetValue ();
+
+                               return true;
+                       }
+
+                       Constant constant = e as Constant;
+                       if (constant != null) {
+                               if (e.Type != arg_type) {
+                                       constant = Const.ChangeType (loc, constant, arg_type);
+                                       if (constant == null) {
+                                               result = null;
+                                               Error_AttributeArgumentNotValid (loc);
+                                               return false;
+                                       }
+                               }
+                               result = constant.GetValue ();
                                return true;
                        } else if (e is TypeOf) {
                                result = ((TypeOf) e).TypeArg;
@@ -219,11 +299,8 @@ namespace Mono.CSharp {
                                if (result != null)
                                        return true;
                        } else if (e is EmptyCast) {
-                               result = e;
-                               if (((EmptyCast) e).Child is Constant) {
-                                       result = ((Constant) ((EmptyCast)e).Child).GetValue();
-                               }
-                               return true;
+                               Expression child = ((EmptyCast)e).Child;
+                               return GetAttributeArgumentExpression (child, loc, child.Type, out result);
                        }
 
                        result = null;
@@ -231,21 +308,32 @@ namespace Mono.CSharp {
                        return false;
                }
                
-               public CustomAttributeBuilder Resolve (EmitContext ec)
+               public virtual CustomAttributeBuilder Resolve (EmitContext ec)
                {
+                       if (resolve_error)
+                               return null;
+
+                       resolve_error = true;
+
                        Type oldType = Type;
                        
                        // Sanity check.
-                       Type = CheckAttributeType (ec, true);
+                       Type = CheckAttributeType (ec);
+
                        if (oldType == null && Type == null)
                                return null;
-                       if (oldType != null && oldType != Type) {
-                               Report.Error (-6, Location,
+                       if (oldType != null && oldType != Type){
+                               Report.Error (-27, Location,
                                              "Attribute {0} resolved to different types at different times: {1} vs. {2}",
                                              Name, oldType, Type);
                                return null;
                        }
 
+                       if (Type.IsAbstract) {
+                               Report.Error (653, Location, "Cannot apply attribute class '{0}' because it is abstract", Name);
+                               return null;
+                       }
+
                        bool MethodImplAttr = false;
                        bool MarshalAsAttr = false;
                        bool GuidAttr = false;
@@ -300,27 +388,32 @@ namespace Mono.CSharp {
                                e = a.Expr;
 
                                object val;
-                               if (!GetAttributeArgumentExpression (e, Location, out val))
+                               if (!GetAttributeArgumentExpression (e, Location, a.Type, out val))
                                        return null;
                                
                                pos_values [i] = val;
+
                                if (DoCompares){
-                                       if (usage_attr)
-                                               usage_attribute = new AttributeUsageAttribute ((AttributeTargets) pos_values [0]);
-                                       else if (MethodImplAttr)
-                                               this.ImplOptions = (MethodImplOptions) pos_values [0];
-                                       else if (GuidAttr){
+                                       if (usage_attr) {
+                                               if ((int)val == 0) {
+                                                       Report.Error (591, Location, "Invalid value for argument to 'System.AttributeUsage' attribute");
+                                                       return null;
+                                               }
+                                               usage_attribute = new AttributeUsageAttribute ((AttributeTargets)val);
+                                       } else if (MethodImplAttr) {
+                                               this.ImplOptions = (MethodImplOptions) val;
+                                       } else if (GuidAttr){
                                                //
                                                // we will later check the validity of the type
                                                //
-                                               if (pos_values [0] is string){
-                                                       if (!ValidateGuid ((string) pos_values [0]))
+                                               if (val is string){
+                                                       if (!ValidateGuid ((string) val))
                                                                return null;
                                                }
                                                
                                        } else if (MarshalAsAttr)
                                                this.UnmanagedType =
-                                               (System.Runtime.InteropServices.UnmanagedType) pos_values [0];
+                                               (System.Runtime.InteropServices.UnmanagedType) val;
                                }
                        }
 
@@ -369,12 +462,18 @@ namespace Mono.CSharp {
                                                Location);
 
                                        if (member != null) {
-                                               Report.Error_T (122, Location, GetFullMemberName (member_name));
+                                               Report.Error (122, Location, "'{0}' is inaccessible due to its protection level", GetFullMemberName (member_name));
                                                return null;
                                        }
                                }
 
-                               if (member == null || !(member is PropertyExpr || member is FieldExpr)) {
+                               if (member == null){
+                                       Report.Error (117, Location, "Attribute `{0}' does not contain a definition for `{1}'",
+                                                     Type, member_name);
+                                       return null;
+                               }
+                               
+                               if (!(member is PropertyExpr || member is FieldExpr)) {
                                        Error_InvalidNamedArgument (member_name);
                                        return null;
                                }
@@ -389,38 +488,24 @@ namespace Mono.CSharp {
                                        PropertyExpr pe = (PropertyExpr) member;
                                        PropertyInfo pi = pe.PropertyInfo;
 
-                                       if (!pi.CanWrite) {
+                                       if (!pi.CanWrite || !pi.CanRead) {
+                                               Report.SymbolRelatedToPreviousError (pi);
                                                Error_InvalidNamedArgument (member_name);
                                                return null;
                                        }
 
-                                       Constant c = e as Constant;
-                                       if (c != null) {
-                                               if (c.Type != pi.PropertyType) {
-                                                       c = Const.ChangeType (Location, c, pi.PropertyType);
-                                                       if (c == null)
+                                       object value;
+                                       if (!GetAttributeArgumentExpression (e, Location, pi.PropertyType, out value))
                                                                return null;
-                                               }
-                                               
-                                               object o = c.GetValue ();
-                                               prop_values.Add (o);
                                                
                                                if (usage_attribute != null) {
                                                        if (member_name == "AllowMultiple")
-                                                               usage_attribute.AllowMultiple = (bool) o;
+                                                       usage_attribute.AllowMultiple = (bool) value;
                                                        if (member_name == "Inherited")
-                                                               usage_attribute.Inherited = (bool) o;
-                                               }
-                                               
-                                       } else if (e is TypeOf) {
-                                               prop_values.Add (((TypeOf) e).TypeArg);
-                                       } else if (e is ArrayCreation) {
-                                               prop_values.Add (((ArrayCreation) e).EncodeAsAttribute());
-                                       } else {
-                                               Error_AttributeArgumentNotValid (Location);
-                                               return null;
+                                                       usage_attribute.Inherited = (bool) value;
                                        }
                                        
+                                       prop_values.Add (value);
                                        prop_infos.Add (pi);
                                        
                                } else if (member is FieldExpr) {
@@ -432,26 +517,12 @@ namespace Mono.CSharp {
                                                return null;
                                        }
 
-                                       //
-                                       // Handle charset here, and set the TypeAttributes
-                                       
-                                       Constant c = e as Constant;
-                                       if (c != null) {
-                                               if (c.Type != fi.FieldType){
-                                                       c = Const.ChangeType (Location, c, fi.FieldType);
-                                                       if (c == null)
-                                                               return null;
-                                               } 
-                                               
-                                               object value = c.GetValue ();
-                                               field_values.Add (value);
-                                       } else if (e is TypeOf) {
-                                               field_values.Add (((TypeOf) e).TypeArg);
-                                       } else {
-                                               Error_AttributeArgumentNotValid (Location);
+                                       object value;
+                                       if (!GetAttributeArgumentExpression (e, Location, fi.FieldType, out value))
                                                return null;
-                                       }
-                                       
+
+                                       field_values.Add (value);
+
                                        field_infos.Add (fi);
                                }
                        }
@@ -470,7 +541,6 @@ namespace Mono.CSharp {
                                ec, (MethodGroupExpr) mg, pos_args, false, Location);
 
                        if (constructor == null) {
-                               Error_AttributeConstructorMismatch ();
                                return null;
                        }
 
@@ -480,12 +550,19 @@ namespace Mono.CSharp {
                        // of type object
                        //
 
-                       ParameterData pd = Invocation.GetParameterData (constructor);
+                       ParameterData pd = TypeManager.GetParameterData (constructor);
 
-                       int group_in_params_array = Int32.MaxValue;
-                       int pc = pd.Count;
-                       if (pc > 0 && pd.ParameterModifier (pc-1) == Parameter.Modifier.PARAMS)
-                               group_in_params_array = pc-1;
+                       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];
@@ -495,32 +572,34 @@ namespace Mono.CSharp {
                                        return null;
                                }
 
-                               if (j < group_in_params_array)
+                               object value = pos_values [j];
+                               if (value != null && a.Type != value.GetType () && a.Type.IsPrimitive) {
+                                       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 == group_in_params_array){
-                                       object v = pos_values [j];
-                                       int count = pos_arg_count - j;
-
-                                       object [] array = new object [count];
+                               if (j == last_real_param) {
+                                       object [] array = new object [pos_arg_count - last_real_param];
+                                       array [0] = pos_values [j];
                                        pos_values [j] = array;
-                                       array [0] = v;
-                               } else {
-                                       object [] array = (object []) pos_values [group_in_params_array];
-
-                                       array [j - group_in_params_array] = pos_values [j];
+                                       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 (group_in_params_array != Int32.MaxValue){
-                               int argc = group_in_params_array+1;
-                               object [] new_pos_values = new object [argc];
-
-                               for (int p = 0; p < argc; p++)
-                                       new_pos_values [p] = pos_values [p];
+                       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;
                        }
 
@@ -545,13 +624,6 @@ namespace Mono.CSharp {
                                else
                                        cb = new CustomAttributeBuilder (
                                                (ConstructorInfo) constructor, pos_values);
-                       } catch (NullReferenceException) {
-                               // 
-                               // Don't know what to do here
-                               //
-                               Report.Warning (
-                                       -101, Location, "NullReferenceException while trying to create attribute." +
-                                        "Something's wrong!");
                        } catch (Exception e) {
                                //
                                // Sample:
@@ -559,20 +631,21 @@ namespace Mono.CSharp {
                                // [DefaultValue (CollectionChangeAction.Add)]
                                // class X { static void Main () {} }
                                //
-                               Report.Warning (
-                                       -23, Location, "The compiler can not encode this attribute in .NET due to a bug in the .NET runtime. Try the Mono runtime. The exception was: " + e.Message);
+                               Error_AttributeArgumentNotValid (Location);
+                               return null;
                        }
                        
+                       resolve_error = false;
                        return cb;
                }
 
                /// <summary>
                ///   Get a string containing a list of valid targets for the attribute 'attr'
                /// </summary>
-               static string GetValidTargets (Attribute attr)
+               public string GetValidTargets ()
                {
                        StringBuilder sb = new StringBuilder ();
-                       AttributeTargets targets = attr.GetAttributeUsage ().ValidOn;
+                       AttributeTargets targets = GetAttributeUsage ().ValidOn;
 
                        if ((targets & AttributeTargets.Assembly) != 0)
                                sb.Append ("'assembly' ");
@@ -620,15 +693,6 @@ namespace Mono.CSharp {
 
                }
 
-               public static void Error_AttributeNotValidForElement (Attribute a, Location loc)
-               {
-                       Report.Error (
-                               592, loc, "Attribute '" + a.Name +
-                               "' is not valid on this declaration type. " +
-                               "It is valid on " + GetValidTargets (a) + "declarations only.");
-               }
-
-
                /// <summary>
                /// Returns AttributeUsage attribute for this type
                /// </summary>
@@ -650,72 +714,45 @@ namespace Mono.CSharp {
                        return attr_class.AttributeUsage;
                }
 
-
-               //
-               // This pulls the condition name out of a Conditional attribute
-               //
-               public string Conditional_GetConditionName ()
+               /// <summary>
+               /// Returns custom name of indexer
+               /// </summary>
+               public string GetIndexerAttributeValue (EmitContext ec)
                {
-                       //
-                       // So we have a Conditional, pull the data out.
-                       //
-                       if (Arguments == null || Arguments [0] == null){
-                               Error_AttributeConstructorMismatch ();
-                               return null;
-                       }
-
-                       ArrayList pos_args = (ArrayList) Arguments [0];
-                       if (pos_args.Count != 1){
-                               Error_AttributeConstructorMismatch ();
-                               return null;
-                       }
-
-                       Argument arg = (Argument) pos_args [0]; 
-                       if (!(arg.Expr is StringConstant)){
-                               Error_AttributeConstructorMismatch ();
-                               return null;
-                       }
-
-                       return ((StringConstant) arg.Expr).Value;
+                       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);
+                       
+                       return pos_values [0] as string;
                }
 
-               public string IndexerName_GetIndexerName (EmitContext ec)
+               /// <summary>
+               /// Returns condition of ConditionalAttribute
+               /// </summary>
+               public string GetConditionalAttributeValue (EmitContext ec)
                {
-                       if (Arguments == null || Arguments [0] == null){
-                               Error_AttributeConstructorMismatch ();
-                               return null;
-                       }
-                       ArrayList pos_args = (ArrayList) Arguments [0];
-                       if (pos_args.Count != 1) {
-                               Error_AttributeConstructorMismatch ();
-                               return null;
-                       }
-                       
-                       Argument arg = (Argument) pos_args [0];
-                       if (!arg.Resolve (ec, Location))
-                               return null;
-                       
-                       StringConstant sc = arg.Expr as StringConstant;
-                       if (sc == null){
-                               Error_AttributeConstructorMismatch ();
+                       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);
+
+                       // Some error occurred
+                       if (pos_values [0] == null)
                                return null;
-                       }
-                       
-                       return sc.Value;
+
+                       return (string)pos_values [0];
                }
 
                /// <summary>
                /// Creates the instance of ObsoleteAttribute from this attribute instance
                /// </summary>
-               public ObsoleteAttribute GetObsoleteAttribute (DeclSpace ds)
+               public ObsoleteAttribute GetObsoleteAttribute (EmitContext ec)
                {
-                       if (pos_values == null) {
-                               EmitContext ec = new EmitContext (ds, ds, Location, null, null, 0, false);
-
+                       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);
-                       }
 
                        // Some error occurred
                        if (pos_values == null)
@@ -735,15 +772,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 (DeclSpace ds)
+               public bool GetClsCompliantAttributeValue (EmitContext ec)
                {
-                       if (pos_values == null) {
-                               EmitContext ec = new EmitContext (ds, ds, Location, null, null, 0, false);
-
+                       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);
-                       }
 
                        // Some error occurred
                        if (pos_values [0] == null)
@@ -752,6 +786,125 @@ namespace Mono.CSharp {
                        return (bool)pos_values [0];
                }
 
+               /// <summary>
+               /// Tests permitted SecurityAction for assembly or other types
+               /// </summary>
+               public bool CheckSecurityActionValidity (bool for_assembly)
+               {
+                       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)
+                                       return true;
+                       }
+
+                       Error_AttributeEmitError (String.Concat ("SecurityAction '", action, "' is not valid for this declaration"));
+                       return false;
+               }
+
+               System.Security.Permissions.SecurityAction GetSecurityActionValue ()
+               {
+                       return (SecurityAction)pos_values [0];
+               }
+
+               /// <summary>
+               /// Creates instance of SecurityAttribute class and add result of CreatePermission method to permission table.
+               /// </summary>
+               /// <returns></returns>
+               public void ExtractSecurityPermissionSet (ListDictionary permissions)
+               {
+                       if (TypeManager.LookupDeclSpace (Type) != null && RootContext.StdLib) {
+                               Error_AttributeEmitError ("security custom attributes can not be referenced from defining assembly");
+                               return;
+                       }
+
+                       SecurityAttribute sa;
+                       // For all assemblies except corlib we can avoid all hacks
+                       if (RootContext.StdLib) {
+                               sa = (SecurityAttribute) Activator.CreateInstance (Type, pos_values);
+
+                               if (prop_info_arr != null) {
+                                       for (int i = 0; i < prop_info_arr.Length; ++i) {
+                                               PropertyInfo pi = prop_info_arr [i];
+                                               pi.SetValue (sa, prop_values_arr [i], null);
+                                       }
+                               }
+                       } else {
+                               Type temp_type = Type.GetType (Type.FullName);
+                               // HACK: All mscorlib attributes have same ctor syntax
+                               sa = (SecurityAttribute) Activator.CreateInstance (temp_type, new object[] { GetSecurityActionValue () } );
+
+                               // All types are from newly created corlib but for invocation with old we need to convert them
+                               if (prop_info_arr != null) {
+                                       for (int i = 0; i < prop_info_arr.Length; ++i) {
+                                               PropertyInfo emited_pi = prop_info_arr [i];
+                                               PropertyInfo pi = temp_type.GetProperty (emited_pi.Name, emited_pi.PropertyType);
+
+                                               object old_instance = pi.PropertyType.IsEnum ?
+                                                       System.Enum.ToObject (pi.PropertyType, prop_values_arr [i]) :
+                                                       prop_values_arr [i];
+
+                                               pi.SetValue (sa, old_instance, null);
+                                       }
+                               }
+                       }
+
+                       IPermission perm;
+                       try {
+                               perm = sa.CreatePermission ();
+                       }
+                       catch (Exception e) {
+                               Error_AttributeEmitError (String.Format ("{0} was thrown during attribute processing: {1}", e.GetType (), e.Message));
+                               return;
+                       }
+                       SecurityAction action = GetSecurityActionValue ();
+
+                       // IS is correct because for corlib we are using an instance from old corlib
+                       if (!(perm is System.Security.CodeAccessPermission)) {
+                               switch (action) {
+                                       case SecurityAction.Demand:
+                                               action = (SecurityAction)13;
+                                               break;
+                                       case SecurityAction.LinkDemand:
+                                               action = (SecurityAction)14;
+                                               break;
+                                       case SecurityAction.InheritanceDemand:
+                                               action = (SecurityAction)15;
+                                               break;
+                               }
+                       }
+
+                       PermissionSet ps = (PermissionSet)permissions [action];
+                       if (ps == null) {
+                               if (sa is PermissionSetAttribute)
+                                       ps = new PermissionSet (sa.Unrestricted ? PermissionState.Unrestricted : PermissionState.None);
+                               else
+                                       ps = new PermissionSet (PermissionState.None);
+
+                               permissions.Add (action, ps);
+                       } else if (!ps.IsUnrestricted () && sa.Unrestricted) {
+                               ps = ps.Union (new PermissionSet (PermissionState.Unrestricted));
+                               permissions [action] = ps;
+                       }
+                       ps.AddPermission (perm);
+               }
+
+               object GetValue (object value)
+               {
+                       if (value is EnumConstant)
+                               return ((EnumConstant) value).GetValue ();
+                       else
+                               return value;                           
+               }
+
                public object GetPositionalValue (int i)
                {
                        return (pos_values == null) ? null : pos_values[i];
@@ -765,14 +918,20 @@ namespace Mono.CSharp {
                        i = 0;
                        foreach (FieldInfo fi in field_info_arr) {
                                if (fi.Name == name)
-                                       return field_values_arr [i];
+                                       return GetValue (field_values_arr [i]);
                                i++;
                        }
                        return null;
                }
 
-               public UnmanagedMarshal GetMarshal ()
+               public UnmanagedMarshal GetMarshal (Attributable attr)
                {
+                       object value = GetFieldValue ("SizeParamIndex");
+                       if (value != null && UnmanagedType != UnmanagedType.LPArray) {
+                               Error_AttributeEmitError ("SizeParamIndex field is not valid for the specified unmanaged type");
+                               return null;
+                       }
+
                        object o = GetFieldValue ("ArraySubType");
                        UnmanagedType array_sub_type = o == null ? UnmanagedType.I4 : (UnmanagedType) o;
                        
@@ -780,8 +939,10 @@ namespace Mono.CSharp {
                        case UnmanagedType.CustomMarshaler:
                                MethodInfo define_custom = typeof (UnmanagedMarshal).GetMethod ("DefineCustom",
                                                                        BindingFlags.Static | BindingFlags.Public);
-                               if (define_custom == null)
+                               if (define_custom == null) {
+                                       Report.RuntimeMissingSupport (Location, "set marshal info");
                                        return null;
+                               }
                                
                                object [] args = new object [4];
                                args [0] = GetFieldValue ("MarshalTypeRef");
@@ -797,6 +958,11 @@ namespace Mono.CSharp {
                                return UnmanagedMarshal.DefineSafeArray (array_sub_type);
                        
                        case UnmanagedType.ByValArray:
+                               FieldMember fm = attr as FieldMember;
+                               if (fm == null) {
+                                       Error_AttributeEmitError ("Specified unmanaged type is only valid on fields");
+                                       return null;
+                               }
                                return UnmanagedMarshal.DefineByValArray ((int) GetFieldValue ("SizeConst"));
                        
                        case UnmanagedType.ByValTStr:
@@ -822,18 +988,27 @@ namespace Mono.CSharp {
                                return;
 
                        AttributeUsageAttribute usage_attr = GetAttributeUsage ();
-                       if ((usage_attr.ValidOn & ias.AttributeTargets) == 0) {
-                                       Error_AttributeNotValidForElement (this, Location);
+                       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.", Name, GetValidTargets ());
                                return;
                        }
 
                        ias.ApplyAttributeBuilder (this, cb);
 
-                       if (!usage_attr.AllowMultiple && emitted_attr.Contains (Target)) {
+                       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 '" + Name + "' attribute");
+                                       return;
+                               }
+                               emitted_targets.Add (Target);
                        }
 
-                       emitted_attr [Type] = Target;
+                       if (!RootContext.VerifyClsCompliance)
+                               return;
 
                        // Here we are testing attribute arguments for array usage (error 3016)
                        if (ias.IsClsCompliaceRequired (ec.DeclSpace)) {
@@ -848,7 +1023,7 @@ namespace Mono.CSharp {
                                                        return;
 
                                                if (arg.Type.IsArray) {
-                                                       Report.Error_T (3016, Location);
+                                                       Report.Error (3016, Location, "Arrays as attribute arguments are not CLS-compliant");
                                                        return;
                                                }
                                        }
@@ -866,7 +1041,7 @@ namespace Mono.CSharp {
                                                return;
 
                                        if (arg.Type.IsArray) {
-                                               Report.Error_T (3016, Location);
+                                               Report.Error (3016, Location, "Arrays as attribute arguments are not CLS-compliant");
                                                return;
                                        }
                                }
@@ -894,7 +1069,7 @@ namespace Mono.CSharp {
                                return null;
                        }
 
-                       ResolveType (ec, true);
+                       ResolveType (ec);
                        if (Type == null)
                                return null;
                        
@@ -918,7 +1093,11 @@ namespace Mono.CSharp {
                                Error_AttributeArgumentNotValid (Location);
                                return null;
                        }
-
+                       if (dll_name == null || dll_name == ""){
+                               Error_AttributeArgumentNotValid (": DllImport requires a non-empty string", Location);
+                               return null;
+                       }
+                       
                        // Now we process the named arguments
                        CallingConvention cc = CallingConvention.Winapi;
                        CharSet charset = CharSet.Ansi;
@@ -1050,18 +1229,47 @@ namespace Mono.CSharp {
        {
                public readonly NamespaceEntry ns;
 
-               public GlobalAttribute (TypeContainer container, string target, string name, ArrayList args, Location loc):
-                       base (target, name, args, loc)
+               public GlobalAttribute (TypeContainer container, string target, 
+                                       Expression left_expr, string identifier, ArrayList args, Location loc):
+                       base (target, left_expr, identifier, args, loc)
                {
                        ns = container.NamespaceEntry;
                }
 
-               protected override Type CheckAttributeType (EmitContext ec, bool complain)
+               void Enter ()
+               {
+                       // RootContext.Tree.Types 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
+
+                       if (RootContext.Tree.Types.NamespaceEntry != null)
+                               throw new InternalErrorException (Location + " non-null NamespaceEntry");
+
+                       RootContext.Tree.Types.NamespaceEntry = ns;
+               }
+
+               void Leave ()
+               {
+                       RootContext.Tree.Types.NamespaceEntry = null;
+               }
+
+               public override Type ResolveType (EmitContext ec)
                {
-                       NamespaceEntry old = ec.DeclSpace.NamespaceEntry;
-                       if (old == null || old.NS == null || old.NS == Namespace.Root) 
-                               ec.DeclSpace.NamespaceEntry = ns;
-                       return base.CheckAttributeType (ec, complain);
+                       Enter ();
+                       Type retval = base.ResolveType (ec);
+                       Leave ();
+                       return retval;
+               }
+
+               public override CustomAttributeBuilder Resolve (EmitContext ec)
+               {
+                       Enter ();
+                       CustomAttributeBuilder retval = base.Resolve (ec);
+                       Leave ();
+                       return retval;
                }
        }
 
@@ -1087,43 +1295,71 @@ namespace Mono.CSharp {
                /// <summary>
                /// Checks whether attribute target is valid for the current element
                /// </summary>
-               public void CheckTargets (string[] possible_targets)
+               public bool CheckTargets (Attributable member)
                {
+                       string[] valid_targets = member.ValidAttributeTargets;
                        foreach (Attribute a in Attrs) {
-                               if (a.Target == null) {
-                                       a.Target = possible_targets [0];
+                               if (a.ExplicitTarget == null || a.ExplicitTarget == valid_targets [0]) {
+                                       a.Target = member.AttributeTargets;
                                        continue;
                                }
 
-                               if (((IList) possible_targets).Contains (a.Target))
-                                       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 possible_targets) {
+                               foreach (string s in valid_targets) {
                                        sb.Append (s);
                                        sb.Append (", ");
                                }
                                sb.Remove (sb.Length - 2, 2);
-                               Report.Error_T (657, a.Location, a.Target, sb.ToString ());
+                               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;
                        }
+                       return true;
                }
 
-               private Attribute Search (Type t, EmitContext ec, bool complain)
+               public Attribute Search (Type t, EmitContext ec)
                {
                        foreach (Attribute a in Attrs) {
-                               if (a.ResolveType (ec, false) == t)
+                               if (a.ResolveType (ec) == t)
                                        return a;
                        }
                        return null;
                }
 
-               public Attribute Search (Type t, EmitContext ec)
+               /// <summary>
+               /// Returns all attributes of type 't'. Use it when attribute is AllowMultiple = true
+               /// </summary>
+               public Attribute[] SearchMulti (Type t, EmitContext ec)
                {
-                       return Search (t, ec, true);
+                       ArrayList ar = null;
+
+                       foreach (Attribute a in Attrs) {
+                               if (a.ResolveType (ec) == t) {
+                                       if (ar == null)
+                                               ar = new ArrayList ();
+                                       ar.Add (a);
+                               }
+                       }
+
+                       return ar == null ? null : ar.ToArray (typeof (Attribute)) as Attribute[];
                }
 
                public void Emit (EmitContext ec, Attributable ias)
                {
+                       if (!CheckTargets (ias))
+                               return;
+
                        ListDictionary ld = new ListDictionary ();
 
                        foreach (Attribute a in Attrs)
@@ -1134,28 +1370,6 @@ namespace Mono.CSharp {
                {
                         return Search (t, ec) != null;
                }
-
-               public Attribute GetClsCompliantAttribute (EmitContext ec)
-               {
-                       return Search (TypeManager.cls_compliant_attribute_type, ec, false);
-               }
-
-               /// <summary>
-               /// Pulls the IndexerName attribute from an Indexer if it exists.
-               /// </summary>
-               public string ScanForIndexerName (EmitContext ec)
-               {
-                       Attribute a = Search (TypeManager.indexer_name_type, ec);
-                       if (a == null)
-                               return null;
-
-                       // Remove the attribute from the list
-                       //TODO: It is very close to hack and it can crash here
-                       Attrs.Remove (a);
-
-                       return a.IndexerName_GetIndexerName (ec);
-               }
-
        }
 
        /// <summary>
@@ -1166,6 +1380,11 @@ namespace Mono.CSharp {
                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 fixed_buffer_cache = new PtrHashtable ();
+
+               static object TRUE = new object ();
+               static object FALSE = new object ();
 
                private AttributeTester ()
                {
@@ -1225,7 +1444,7 @@ namespace Mono.CSharp {
 
                        foreach (Parameter arg in fixedParameters) {
                                if (!AttributeTester.IsClsCompliant (arg.ParameterType)) {
-                                       Report.Error_T (3001, loc, arg.GetSignatureForError ());
+                                       Report.Error (3001, loc, "Argument type '{0}' is not CLS-compliant", arg.GetSignatureForError ());
                                        return false;
                                }
                        }
@@ -1258,33 +1477,38 @@ namespace Mono.CSharp {
                        }
                        analyzed_types.Add (type, result ? TRUE : FALSE);
                        return result;
-               }                
-
-               static object TRUE = new object ();
-               static object FALSE = new object ();
-
+               }        
+        
                /// <summary>
-               /// Non-hierarchical CLS Compliance analyzer
+               /// Returns IFixedBuffer implementation if field is fixed buffer else null.
                /// </summary>
-               public static bool IsComplianceRequired (MemberInfo mi, DeclSpace ds)
+               public static IFixedBuffer GetFixedBuffer (FieldInfo fi)
                {
-                       DeclSpace temp_ds = TypeManager.LookupDeclSpace (mi.DeclaringType);
+                       FieldBase fb = TypeManager.GetField (fi);
+                       if (fb != null) {
+                               return fb as IFixedBuffer;
+                       }
 
-                       // Type is external, we can get attribute directly
-                       if (temp_ds == null) {
-                               object[] cls_attribute = mi.GetCustomAttributes (TypeManager.cls_compliant_attribute_type, false);
-                               return (cls_attribute.Length == 1 && ((CLSCompliantAttribute)cls_attribute[0]).IsCompliant);
+#if NET_2_0
+                       object o = fixed_buffer_cache [fi];
+                       if (o == null) {
+                               if (System.Attribute.GetCustomAttribute (fi, TypeManager.fixed_buffer_attr_type) == null) {
+                                       fixed_buffer_cache.Add (fi, FALSE);
+                                       return null;
+                               }
+                               
+                               IFixedBuffer iff = new FixedFieldExternal (fi);
+                               fixed_buffer_cache.Add (fi, iff);
+                               return iff;
                        }
 
-                       string tmp_name;
-                       // Interface doesn't store full name
-                       if (temp_ds is Interface)
-                               tmp_name = mi.Name;
-                       else
-                               tmp_name = String.Concat (temp_ds.Name, ".", mi.Name);
+                       if (o == FALSE)
+                               return null;
 
-                       MemberCore mc = temp_ds.GetDefinition (tmp_name) as MemberCore;
-                       return mc.IsClsCompliaceRequired (ds);
+                       return (IFixedBuffer)o;
+#else
+                       return null;
+#endif
                }
 
                public static void VerifyModulesClsCompliance ()
@@ -1297,12 +1521,49 @@ namespace Mono.CSharp {
                        for (int i = 1; i < modules.Length; ++i) {
                                Module module = modules [i];
                                if (!IsClsCompliant (module)) {
-                                       Report.Error_T (3013, module.Name);
+                                       Report.Error (3013, "Added modules must be marked with the CLSCompliant attribute to match the assembly", module.Name);
                                        return;
                                }
                        }
                }
 
+               /// <summary>
+               /// Tests container name for CLS-Compliant name (differing only in case)
+               /// </summary>
+               public static void VerifyTopLevelNameClsCompliance ()
+               {
+                       Hashtable locase_table = new Hashtable ();
+
+                       // Convert imported type names to lower case and ignore not cls compliant
+                       foreach (DictionaryEntry de in TypeManager.all_imported_types) {
+                               Type t = (Type)de.Value;
+                               if (!AttributeTester.IsClsCompliant (t))
+                                       continue;
+
+                               locase_table.Add (((string)de.Key).ToLower (System.Globalization.CultureInfo.InvariantCulture), t);
+                       }
+
+                       foreach (DictionaryEntry de in RootContext.Tree.Decls) {
+                               DeclSpace decl = (DeclSpace)de.Value;
+                               if (!decl.IsClsCompliaceRequired (decl))
+                                       continue;
+
+                               string lcase = decl.Name.ToLower (System.Globalization.CultureInfo.InvariantCulture);
+                               if (!locase_table.Contains (lcase)) {
+                                       locase_table.Add (lcase, decl);
+                                       continue;
+                               }
+
+                               object conflict = locase_table [lcase];
+                               if (conflict is Type)
+                                       Report.SymbolRelatedToPreviousError ((Type)conflict);
+                               else
+                                       Report.SymbolRelatedToPreviousError ((MemberCore)conflict);
+
+                               Report.Error (3005, decl.Location, "Identifier '{0}' differing only in case is not CLS-compliant", decl.GetSignatureForError ());
+                       }
+               }
+
                static bool IsClsCompliant (ICustomAttributeProvider attribute_provider) 
                {
                        object[] CompliantAttribute = attribute_provider.GetCustomAttributes (TypeManager.cls_compliant_attribute_type, false);
@@ -1319,7 +1580,7 @@ namespace Mono.CSharp {
                                return ds.IsClsCompliaceRequired (ds.Parent);
                        }
 
-                       if (type.IsGenericParameter)
+                       if (type.IsGenericParameter || type.IsGenericInstance)
                                return false;
 
                        object[] CompliantAttribute = type.GetCustomAttributes (TypeManager.cls_compliant_attribute_type, false);
@@ -1344,7 +1605,9 @@ namespace Mono.CSharp {
                        ObsoleteAttribute result = null;
                        if (type.IsByRef || type.IsArray || type.IsPointer) {
                                result = GetObsoleteAttribute (TypeManager.GetElementType (type));
-                       } else {
+                       } else if (type.IsGenericParameter || type.IsGenericInstance)
+                               return null;
+                       else {
                                DeclSpace type_ds = TypeManager.LookupDeclSpace (type);
 
                                // Type is external, we can get attribute directly
@@ -1370,10 +1633,14 @@ namespace Mono.CSharp {
                        if (mc != null) 
                                return mc.GetObsoleteAttribute ();
 
-                       // TODO: remove after Constructor will be ready for IMethodData
-                       if ((mb.DeclaringType is TypeBuilder) || mb.DeclaringType.IsGenericInstance)
+                       // compiler generated methods are not registered by AddMethod
+                       if (mb.DeclaringType is TypeBuilder)
                                return null;
 
+                       PropertyInfo pi = PropertyExpr.AccessorTable [mb] as PropertyInfo;
+                       if (pi != null)
+                               return GetMemberObsoleteAttribute (pi);
+
                        return GetMemberObsoleteAttribute (mb);
                }
 
@@ -1389,6 +1656,9 @@ namespace Mono.CSharp {
                        if (type_obsolete != null)
                                return (ObsoleteAttribute)type_obsolete;
 
+                       if ((mi.DeclaringType is TypeBuilder) || mi.DeclaringType.IsGenericInstance)
+                               return null;
+
                        ObsoleteAttribute oa = System.Attribute.GetCustomAttribute (mi, TypeManager.obsolete_attribute_type, false) as ObsoleteAttribute;
                        analyzed_member_obsolete.Add (mi, oa == null ? FALSE : oa);
                        return oa;
@@ -1400,15 +1670,41 @@ namespace Mono.CSharp {
                public static void Report_ObsoleteMessage (ObsoleteAttribute oa, string member, Location loc)
                {
                        if (oa.IsError) {
-                               Report.Error_T (619, loc, member, oa.Message);
+                               Report.Error (619, loc, "'{0}' is obsolete: '{1}'", member, oa.Message);
                                return;
                        }
 
                        if (oa.Message == null) {
-                               Report.Warning_T (612, loc, member);
+                               Report.Warning (612, loc, "'{0}' is obsolete", member);
                                return;
                        }
-                       Report.Warning_T (618, loc, member, oa.Message);
+                       if (RootContext.WarningLevel >= 2)
+                               Report.Warning (618, loc, "'{0}' is obsolete: '{1}'", member, oa.Message);
+               }
+
+               public static bool IsConditionalMethodExcluded (MethodBase mb)
+               {
+                       object excluded = analyzed_method_excluded [mb];
+                       if (excluded != null)
+                               return excluded == TRUE ? true : false;
+
+                       if (mb.Mono_IsInflatedMethod)
+                               return false;
+                       
+                       ConditionalAttribute[] attrs = mb.GetCustomAttributes (TypeManager.conditional_attribute_type, true) as ConditionalAttribute[];
+                       if (attrs.Length == 0) {
+                               analyzed_method_excluded.Add (mb, FALSE);
+                               return false;
+                       }
+
+                       foreach (ConditionalAttribute a in attrs) {
+                               if (RootContext.AllDefines.Contains (a.ConditionString)) {
+                                       analyzed_method_excluded.Add (mb, FALSE);
+                                       return false;
+                               }
+                       }
+                       analyzed_method_excluded.Add (mb, TRUE);
+                       return true;
                }
        }
 }