Flush
[mono.git] / mcs / gmcs / attribute.cs
index b276aa0d0bafbd6ef67658652a6542329bea35df..c998dbe9bbe25d2c41f283d88c495ea6e8ac0d74 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
 //
@@ -20,6 +21,7 @@ using System.Runtime.CompilerServices;
 using System.Text;
 
 namespace Mono.CSharp {
+
        /// <summary>
        ///   Base class for objects that can have Attributes applied to them.
        /// </summary>
@@ -43,6 +45,8 @@ namespace Mono.CSharp {
                        }
                        set {
                                attributes = value;
+                               if (attributes != null)
+                                       attributes.CheckTargets (ValidAttributeTargets);
                        }
                }
 
@@ -59,13 +63,14 @@ namespace Mono.CSharp {
                public abstract bool IsClsCompliaceRequired (DeclSpace ds);
 
                /// <summary>
-               /// Gets list of valid attribute targets for explicit target declaration
+               /// 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 class Attribute {
-               public readonly string Target;
+               public string Target;
                public readonly string    Name;
                public readonly ArrayList Arguments;
 
@@ -81,7 +86,7 @@ namespace Mono.CSharp {
                                return usage_attribute;
                        }
                }
-
+               
                MethodImplOptions ImplOptions;
                UnmanagedType     UnmanagedType;
                CustomAttributeBuilder cb;
@@ -91,11 +96,10 @@ namespace Mono.CSharp {
                FieldInfo [] field_info_arr;
                object [] field_values_arr;
                object [] prop_values_arr;
-               
-               object [] pos_values;
+               object [] pos_values;
 
                static PtrHashtable usage_attr_cache = new PtrHashtable ();
-
+               
                public Attribute (string target, string name, ArrayList args, Location loc)
                {
                        Name = name;
@@ -119,18 +123,18 @@ namespace Mono.CSharp {
                                      "expression or array creation expression");
                }
 
-               void Error_AttributeConstructorMismatch ()
-               {
-                       Report.Error (-6, Location,
-                                      "Could not find a constructor for this argument list.");
-               }
-
                static void Error_TypeParameterInAttribute (Location loc)
                {
                        Report.Error (
                                -202, loc, "Can not use a type parameter in an attribute");
                }
 
+               void Error_AttributeConstructorMismatch ()
+               {
+                       Report.Error (-6, Location,
+                                      "Could not find a constructor for this argument list.");
+               }
+
                /// <summary>
                 ///   Tries to resolve the type of the attribute. Flags an error if it can't, and complain is true.
                 /// </summary>
@@ -156,8 +160,7 @@ namespace Mono.CSharp {
                                Report.Error(1614, Location, "'" + Name + "': is ambiguous; " 
                                             + " use either '@" + Name + "' or '" + Name + "Attribute'");
                                return null;
-                       }
-
+                       }
                        if (t1 != null)
                                return t1.ResolveType (ec);
                        if (t2 != null)
@@ -166,10 +169,11 @@ namespace Mono.CSharp {
                                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 ?)");
                        return null;
                }
 
@@ -194,6 +198,11 @@ namespace Mono.CSharp {
                        }
                }
 
+               string GetFullMemberName (string member)
+               {
+                       return Type.FullName + '.' + member;
+               }
+
                //
                // 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.
@@ -226,7 +235,7 @@ namespace Mono.CSharp {
                public CustomAttributeBuilder Resolve (EmitContext ec)
                {
                        Type oldType = Type;
-
+                       
                        // Sanity check.
                        Type = CheckAttributeType (ec, true);
                        if (oldType == null && Type == null)
@@ -325,14 +334,14 @@ namespace Mono.CSharp {
                        ArrayList field_values = null;
                        ArrayList prop_values = null;
 
-                       Hashtable seen_names = new Hashtable();
-
                        if (named_args.Count > 0) {
                                field_infos = new ArrayList ();
                                prop_infos  = new ArrayList ();
                                field_values = new ArrayList ();
                                prop_values = new ArrayList ();
                        }
+
+                       Hashtable seen_names = new Hashtable();
                        
                        for (i = 0; i < named_args.Count; i++) {
                                DictionaryEntry de = (DictionaryEntry) named_args [i];
@@ -343,9 +352,9 @@ namespace Mono.CSharp {
                                if (seen_names.Contains(member_name)) {
                                        Report.Error(643, Location, "'" + member_name + "' duplicate named attribute argument");
                                        return null;
-                               }
+                               }                               
                                seen_names.Add(member_name, 1);
-
+                               
                                if (!a.Resolve (ec, Location))
                                        return null;
 
@@ -355,6 +364,17 @@ namespace Mono.CSharp {
                                        BindingFlags.Public | BindingFlags.Instance,
                                        Location);
 
+                               if (member == null) {
+                                       member = Expression.MemberLookup (ec, Type, member_name,
+                                               MemberTypes.Field | MemberTypes.Property, BindingFlags.NonPublic | BindingFlags.Instance,
+                                               Location);
+
+                                       if (member != null) {
+                                               Report.Error_T (122, Location, GetFullMemberName (member_name));
+                                               return null;
+                                       }
+                               }
+
                                if (member == null || !(member is PropertyExpr || member is FieldExpr)) {
                                        Error_InvalidNamedArgument (member_name);
                                        return null;
@@ -375,16 +395,14 @@ namespace Mono.CSharp {
                                                return null;
                                        }
 
-                                       if (e is Constant) {
-                                               Constant c;
-
-                                               if (e.Type != pi.PropertyType){
-                                                       c = Const.ChangeType (Location, (Constant) e, pi.PropertyType);
+                                       Constant c = e as Constant;
+                                       if (c != null) {
+                                               if (c.Type != pi.PropertyType) {
+                                                       c = Const.ChangeType (Location, c, pi.PropertyType);
                                                        if (c == null)
                                                                return null;
-                                               } else
-                                                       c = (Constant) e;
-
+                                               }
+                                               
                                                object o = c.GetValue ();
                                                prop_values.Add (o);
                                                
@@ -418,15 +436,14 @@ namespace Mono.CSharp {
                                        //
                                        // Handle charset here, and set the TypeAttributes
                                        
-                                       if (e is Constant){
-                                               Constant c = (Constant) e;;
-
+                                       Constant c = e as Constant;
+                                       if (c != null) {
                                                if (c.Type != fi.FieldType){
-                                                       c = Const.ChangeType (Location, (Constant) e, 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) {
@@ -470,7 +487,7 @@ namespace Mono.CSharp {
                        int pc = pd.Count;
                        if (pc > 0 && pd.ParameterModifier (pc-1) == Parameter.Modifier.PARAMS)
                                group_in_params_array = pc-1;
-                       
+
                        for (int j = 0; j < pos_arg_count; ++j) {
                                Argument a = (Argument) pos_args [j];
                                
@@ -544,22 +561,20 @@ namespace Mono.CSharp {
                                // class X { static void Main () {} }
                                //
                                Report.Warning (
-                                       -23, Location,
-                                       "The compiler can not encode this attribute in .NET due to\n" +
-                                       "\ta bug in the .NET runtime.  Try the Mono runtime.\nThe error was: " + e.Message);
+                                       -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);
                        }
                        
                        return cb;
                }
 
-                /// <summary>
-                ///   Get a string containing a list of valid targets for the attribute 'attr'
-                /// </summary>
+               /// <summary>
+               ///   Get a string containing a list of valid targets for the attribute 'attr'
+               /// </summary>
                static string GetValidTargets (Attribute attr)
                {
                        StringBuilder sb = new StringBuilder ();
                        AttributeTargets targets = attr.GetAttributeUsage ().ValidOn;
-                       
+
                        if ((targets & AttributeTargets.Assembly) != 0)
                                sb.Append ("'assembly' ");
 
@@ -614,9 +629,10 @@ namespace Mono.CSharp {
                                "It is valid on " + GetValidTargets (a) + "declarations only.");
                }
 
-                /// <summary>
+
+               /// <summary>
                /// Returns AttributeUsage attribute for this type
-                /// </summary>
+               /// </summary>
                public AttributeUsageAttribute GetAttributeUsage ()
                {
                        AttributeUsageAttribute ua = usage_attr_cache [Type] as AttributeUsageAttribute;
@@ -631,10 +647,11 @@ namespace Mono.CSharp {
                                usage_attr_cache.Add (Type, ua);
                                return ua;
                        }
-
+               
                        return attr_class.AttributeUsage;
                }
 
+
                //
                // This pulls the condition name out of a Conditional attribute
                //
@@ -663,44 +680,6 @@ namespace Mono.CSharp {
                        return ((StringConstant) arg.Expr).Value;
                }
 
-               //
-               // This pulls the obsolete message and error flag out of an Obsolete attribute
-               //
-               public string Obsolete_GetObsoleteMessage (out bool is_error)
-               {
-                       is_error = false;
-                       //
-                       // So we have an Obsolete, pull the data out.
-                       //
-                       if (Arguments == null || Arguments [0] == null)
-                               return "";
-
-                       ArrayList pos_args = (ArrayList) Arguments [0];
-                       if (pos_args.Count == 0)
-                               return "";
-                       else if (pos_args.Count > 2){
-                               Error_AttributeConstructorMismatch ();
-                               return null;
-                       }
-
-                       Argument arg = (Argument) pos_args [0]; 
-                       if (!(arg.Expr is StringConstant)){
-                               Error_AttributeConstructorMismatch ();
-                               return null;
-                       }
-
-                       if (pos_args.Count == 2){
-                               Argument arg2 = (Argument) pos_args [1];
-                               if (!(arg2.Expr is BoolConstant)){
-                                       Error_AttributeConstructorMismatch ();
-                                       return null;
-                               }
-                               is_error = ((BoolConstant) arg2.Expr).Value;
-                       }
-
-                       return ((StringConstant) arg.Expr).Value;
-               }
-
                public string IndexerName_GetIndexerName (EmitContext ec)
                {
                        if (Arguments == null || Arguments [0] == null){
@@ -712,42 +691,87 @@ namespace Mono.CSharp {
                                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 ();
                                return null;
                        }
-
+                       
                        return sc.Value;
                }
 
-               /// <summary>
-               /// Returns value of CLSCompliantAttribute contructor parameter but because the method can be called
-               /// 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)
-               {
-                       if (pos_values == null) {
-                               EmitContext ec = new EmitContext (ds, ds, Location, null, null, 0, false);
+               /// <summary>
+               /// Returns condition of ConditionalAttribute
+               /// </summary>
+               public string GetConditionalAttributeValue (DeclSpace ds)
+               {
+                       if (pos_values == null) {
+                               EmitContext ec = new EmitContext (ds, ds, Location, null, null, 0, false);
 
                                // 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...
+                               // But because a lot of attribute class code must be rewritten will be better to wait...
+                               Resolve (ec);
+                       }
 
-                               Resolve (ec);
-                       }
+                       // Some error occurred
+                       if (pos_values [0] == null)
+                               return null;
+
+                       return (string)pos_values [0];
+               }
+
+               /// <summary>
+               /// Creates the instance of ObsoleteAttribute from this attribute instance
+               /// </summary>
+               public ObsoleteAttribute GetObsoleteAttribute (DeclSpace ds)
+               {
+                       if (pos_values == null) {
+                               EmitContext ec = new EmitContext (ds, ds, Location, null, null, 0, false);
+
+                               // 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)
+                               return null;
+
+                       if (pos_values.Length == 0)
+                               return new ObsoleteAttribute ();
+
+                       if (pos_values.Length == 1)
+                               return new ObsoleteAttribute ((string)pos_values [0]);
+
+                       return new ObsoleteAttribute ((string)pos_values [0], (bool)pos_values [1]);
+               }
+
+               /// <summary>
+               /// Returns value of CLSCompliantAttribute contructor parameter but because the method can be called
+               /// 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)
+               {
+                       if (pos_values == null) {
+                               EmitContext ec = new EmitContext (ds, ds, Location, null, null, 0, false);
+
+                               // 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 false;
+                       if (pos_values [0] == null)
+                               return false;
 
                        return (bool)pos_values [0];
-               }
+               }
 
                public object GetPositionalValue (int i)
                {
@@ -769,35 +793,36 @@ namespace Mono.CSharp {
                }
 
                public UnmanagedMarshal GetMarshal ()
-                {
+               {
                        object o = GetFieldValue ("ArraySubType");
                        UnmanagedType array_sub_type = o == null ? UnmanagedType.I4 : (UnmanagedType) o;
+                       
                        switch (UnmanagedType) {
                        case UnmanagedType.CustomMarshaler:
                                MethodInfo define_custom = typeof (UnmanagedMarshal).GetMethod ("DefineCustom",
                                                                        BindingFlags.Static | BindingFlags.Public);
                                if (define_custom == null)
                                        return null;
-
+                               
                                object [] args = new object [4];
                                args [0] = GetFieldValue ("MarshalTypeRef");
                                args [1] = GetFieldValue ("MarshalCookie");
                                args [2] = GetFieldValue ("MarshalType");
                                args [3] = Guid.Empty;
                                return (UnmanagedMarshal) define_custom.Invoke (null, args);
-
+                               
                        case UnmanagedType.LPArray:                             
                                return UnmanagedMarshal.DefineLPArray (array_sub_type);
-
+                       
                        case UnmanagedType.SafeArray:
                                return UnmanagedMarshal.DefineSafeArray (array_sub_type);
-
+                       
                        case UnmanagedType.ByValArray:
                                return UnmanagedMarshal.DefineByValArray ((int) GetFieldValue ("SizeConst"));
-
+                       
                        case UnmanagedType.ByValTStr:
                                return UnmanagedMarshal.DefineByValTStr ((int) GetFieldValue ("SizeConst"));
-
+                       
                        default:
                                return UnmanagedMarshal.DefineUnmanagedMarshal (UnmanagedType);
                        }
@@ -808,40 +833,28 @@ namespace Mono.CSharp {
                        get { return ImplOptions == MethodImplOptions.InternalCall; }
                }
 
-               protected virtual bool CanIgnoreInvalidAttribute (Attributable ias)
-               {
-                       return false;
-               }
-
-               /// <summary>
+               /// <summary>
                /// Emit attribute for Attributable symbol
-               /// </summary>
+               /// </summary>
                public void Emit (EmitContext ec, Attributable ias, ListDictionary emitted_attr)
                {
                        CustomAttributeBuilder cb = Resolve (ec);
-                       if (cb == null) 
+                       if (cb == null)
                                return;
 
                        AttributeUsageAttribute usage_attr = GetAttributeUsage ();
                        if ((usage_attr.ValidOn & ias.AttributeTargets) == 0) {
-                               // The parser applies toplevel attributes both to the assembly and
-                               // to a top-level class, if any.  So, be silent about them.
-                               if (! CanIgnoreInvalidAttribute (ias))
                                        Error_AttributeNotValidForElement (this, Location);
                                return;
                        }
 
                        ias.ApplyAttributeBuilder (this, cb);
 
-                       // Because default target is null (we save some space). We need to transform it here
-                       // for distinction between "default" and "doesn't exist"
-                       string target = Target == null ? "default" : Target;
-                       string emitted = emitted_attr [Type] as string;
-                       if (emitted == target && !usage_attr.AllowMultiple) {
+                       if (!usage_attr.AllowMultiple && emitted_attr.Contains (Target)) {
                                Report.Error (579, Location, "Duplicate '" + Name + "' attribute");
                        }
 
-                       emitted_attr [Type] = target;
+                       emitted_attr [Type] = Target;
 
                        // Here we are testing attribute arguments for array usage (error 3016)
                        if (ias.IsClsCompliaceRequired (ec.DeclSpace)) {
@@ -849,7 +862,6 @@ namespace Mono.CSharp {
                                        return;
 
                                ArrayList pos_args = (ArrayList) Arguments [0];
-
                                if (pos_args != null) {
                                        foreach (Argument arg in pos_args) { 
                                                // Type is undefined (was error 246)
@@ -862,12 +874,11 @@ namespace Mono.CSharp {
                                                }
                                        }
                                }
-
+                       
                                if (Arguments.Count < 2)
                                        return;
-
+                       
                                ArrayList named_args = (ArrayList) Arguments [1];
-
                                foreach (DictionaryEntry de in named_args) {
                                        Argument arg  = (Argument) de.Value;
 
@@ -884,14 +895,14 @@ namespace Mono.CSharp {
                }
 
                public object GetValue (EmitContext ec, Constant c, Type target)
-               {
-                       if (Convert.ImplicitConversionExists (ec, c, target))
-                               return c.GetValue ();
+               {
+                       if (Convert.ImplicitConversionExists (ec, c, target))
+                               return c.GetValue ();
 
                        Convert.Error_CannotImplicitConversion (Location, c.Type, target);
-                       return null;
+                       return null;
                }
-
+               
                public MethodBuilder DefinePInvokeMethod (EmitContext ec, TypeBuilder builder, string name,
                                                          MethodAttributes flags, Type ret_type, Type [] param_types)
                {
@@ -972,15 +983,15 @@ namespace Mono.CSharp {
                                        if (a.Expr is Constant) {
                                                Constant c = (Constant) a.Expr;
 
-                                               try {
-                                                       if (member_name == "CallingConvention"){
-                                                               object val = GetValue (ec, c, typeof (CallingConvention));
+                                               try {
+                                                       if (member_name == "CallingConvention"){
+                                                               object val = GetValue (ec, c, typeof (CallingConvention));
                                                                if (val == null)
-                                                                       return null;
-                                                               cc = (CallingConvention) val;
+                                                                       return null;
+                                                               cc = (CallingConvention) val;
                                                        } else if (member_name == "CharSet"){
                                                                charset = (CharSet) c.GetValue ();
-                                                       } else if (member_name == "EntryPoint")
+                                                       } else if (member_name == "EntryPoint")
                                                                entry_point = (string) c.GetValue ();
                                                        else if (member_name == "SetLastError")
                                                                set_last_err = (bool) c.GetValue ();
@@ -991,9 +1002,9 @@ namespace Mono.CSharp {
                                                        else if (member_name == "PreserveSig")
                                                                preserve_sig = (bool) c.GetValue ();
                                                } catch (InvalidCastException){
-                                                       Error_InvalidNamedArgument (member_name);
-                                                       Error_AttributeArgumentNotValid (Location);
-                                               }
+                                                       Error_InvalidNamedArgument (member_name);
+                                                       Error_AttributeArgumentNotValid (Location);
+                                               }
                                        } else { 
                                                Error_AttributeArgumentNotValid (Location);
                                                return null;
@@ -1021,36 +1032,38 @@ namespace Mono.CSharp {
                        return mb;
                }
 
-               private Expression GetValue () 
-               {
-                       if ((Arguments == null) || (Arguments.Count < 1))
-                               return null;
-                       ArrayList al = (ArrayList) Arguments [0];
+               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))
-                               return null;
-                       return arg.Expr;
-               }
+                               return null;
+                       Argument arg = (Argument) al [0];
+                       if ((arg == null) || (arg.Expr == null))
+                               return null;
+                       return arg.Expr;
+               }
 
                public string GetString () 
-               {
-                       Expression e = GetValue ();
-                       if (e is StringLiteral)
-                               return (e as StringLiteral).Value;
-                       return null;
-               }
+               {
+                       Expression e = GetValue ();
+                       if (e is StringLiteral)
+                               return (e as StringLiteral).Value;
+                       return null;
+               }
 
                public bool GetBoolean () 
-               {
-                       Expression e = GetValue ();
-                       if (e is BoolLiteral)
-                               return (e as BoolLiteral).Value;
-                       return false;
-               }
+               {
+                       Expression e = GetValue ();
+                       if (e is BoolLiteral)
+                               return (e as BoolLiteral).Value;
+                       return false;
+               }
        }
        
+
+       /// <summary>
        /// For global attributes (assembly, module) we need special handling.
        /// Attributes can be located in the several files
        /// </summary>
@@ -1071,16 +1084,6 @@ namespace Mono.CSharp {
                                ec.DeclSpace.NamespaceEntry = ns;
                        return base.CheckAttributeType (ec, complain);
                }
-
-               protected override bool CanIgnoreInvalidAttribute (Attributable ias)
-               {
-                       // Ignore error if this attribute is shared between the Assembly
-                       // and a top-level class.  The parser couldn't figure out which entity
-                       // this attribute belongs to.  If this attribute is erroneous, it should
-                       // be caught when it is processed by the top-level class.
-
-                       return (Target == null && ias is CommonAssemblyModulClass);
-               }
        }
 
        public class Attributes {
@@ -1108,8 +1111,10 @@ namespace Mono.CSharp {
                public void CheckTargets (string[] possible_targets)
                {
                        foreach (Attribute a in Attrs) {
-                               if (a.Target == null)
+                               if (a.Target == null) {
+                                       a.Target = possible_targets [0];
                                        continue;
+                               }
 
                                if (((IList) possible_targets).Contains (a.Target))
                                        continue;
@@ -1138,13 +1143,30 @@ namespace Mono.CSharp {
                        return Search (t, ec, true);
                }
 
+               /// <summary>
+               /// Returns all attributes of type 't'. Use it when attribute is AllowMultiple = true
+               /// </summary>
+               public Attribute[] SearchMulti (Type t, EmitContext ec)
+               {
+                       ArrayList ar = null;
+
+                       foreach (Attribute a in Attrs) {
+                               if (a.ResolveType (ec, false) == 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)
                {
                        ListDictionary ld = new ListDictionary ();
 
-                       foreach (Attribute a in Attrs) {
+                       foreach (Attribute a in Attrs)
                                a.Emit (ec, ias, ld);
-                       }
                }
 
                public bool Contains (Type t, EmitContext ec)
@@ -1172,7 +1194,8 @@ namespace Mono.CSharp {
 
                        return a.IndexerName_GetIndexerName (ec);
                }
-       }
+
+       }
 
        /// <summary>
        /// Helper class for attribute verification routine.
@@ -1180,6 +1203,9 @@ namespace Mono.CSharp {
        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 ();
 
                private AttributeTester ()
                {
@@ -1342,5 +1368,113 @@ namespace Mono.CSharp {
 
                        return ((CLSCompliantAttribute)CompliantAttribute[0]).IsCompliant;
                }
+
+               /// <summary>
+               /// Returns instance of ObsoleteAttribute when type is obsolete
+               /// </summary>
+               public static ObsoleteAttribute GetObsoleteAttribute (Type type)
+               {
+                       object type_obsolete = analyzed_types_obsolete [type];
+                       if (type_obsolete == FALSE)
+                               return null;
+
+                       if (type_obsolete != null)
+                               return (ObsoleteAttribute)type_obsolete;
+
+                       ObsoleteAttribute result = null;
+                       if (type.IsByRef || type.IsArray || type.IsPointer) {
+                               result = GetObsoleteAttribute (TypeManager.GetElementType (type));
+                       } else if (type.IsGenericParameter || type.IsGenericInstance)
+                               return null;
+                       else {
+                               DeclSpace type_ds = TypeManager.LookupDeclSpace (type);
+
+                               // Type is external, we can get attribute directly
+                               if (type_ds == null) {
+                                       object[] attribute = type.GetCustomAttributes (TypeManager.obsolete_attribute_type, false);
+                                       if (attribute.Length == 1)
+                                               result = (ObsoleteAttribute)attribute [0];
+                               } else {
+                                       result = type_ds.GetObsoleteAttribute (type_ds);
+                               }
+                       }
+
+                       analyzed_types_obsolete.Add (type, result == null ? FALSE : result);
+                       return result;
+               }
+
+               /// <summary>
+               /// Returns instance of ObsoleteAttribute when method is obsolete
+               /// </summary>
+               public static ObsoleteAttribute GetMethodObsoleteAttribute (MethodBase mb)
+               {
+                       IMethodData mc = TypeManager.GetMethod (mb);
+                       if (mc != null) 
+                               return mc.GetObsoleteAttribute ();
+
+                       return GetMemberObsoleteAttribute (mb);
+               }
+
+               /// <summary>
+               /// Returns instance of ObsoleteAttribute when member is obsolete
+               /// </summary>
+               public static ObsoleteAttribute GetMemberObsoleteAttribute (MemberInfo mi)
+               {
+                       object type_obsolete = analyzed_member_obsolete [mi];
+                       if (type_obsolete == FALSE)
+                               return null;
+
+                       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;
+               }
+
+               /// <summary>
+               /// Common method for Obsolete error/warning reporting.
+               /// </summary>
+               public static void Report_ObsoleteMessage (ObsoleteAttribute oa, string member, Location loc)
+               {
+                       if (oa.IsError) {
+                               Report.Error_T (619, loc, member, oa.Message);
+                               return;
+                       }
+
+                       if (oa.Message == null) {
+                               Report.Warning_T (612, loc, member);
+                               return;
+                       }
+                       Report.Warning_T (618, loc, 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;
+               }
        }
 }