2009-03-17 Marek Safar <marek.safar@gmail.com>
[mono.git] / mcs / mcs / attribute.cs
index 202c78e23948b9101e7b235f38fdf85fc77396e0..cedc83550dfad99b00c4c2214bb68f669d89d689 100644 (file)
@@ -57,7 +57,7 @@ namespace Mono.CSharp {
                /// <summary>
                /// Use member-specific procedure to apply attribute @a in @cb to the entity being built in @builder
                /// </summary>
-               public abstract void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb);
+               public abstract void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa);
 
                /// <summary>
                /// Returns one AttributeTarget for this element.
@@ -77,6 +77,46 @@ namespace Mono.CSharp {
 
        public class Attribute : Expression
        {
+               //
+               // Wraps owner resolve context, the owner is an attribute
+               // parent and the rest is exactly same
+               //
+               struct AttributeResolveContext : IResolveContext
+               {
+                       readonly IResolveContext rc;
+
+                       public AttributeResolveContext (IResolveContext rc)
+                       {
+                               this.rc = rc;
+                       }
+
+                       #region IResolveContext Members
+
+                       public DeclSpace DeclContainer {
+                               get {
+                                       DeclSpace ds = rc as DeclSpace;
+                                       if (ds == null)
+                                               return rc.DeclContainer;
+
+                                       return ds;
+                               }
+                       }
+
+                       public bool IsInObsoleteScope {
+                               get { return rc.IsInObsoleteScope; }
+                       }
+
+                       public bool IsInUnsafeScope {
+                               get { return rc.IsInUnsafeScope; }
+                       }
+
+                       public DeclSpace GenericDeclContainer {
+                               get { return rc.GenericDeclContainer; }
+                       }
+
+                       #endregion
+               }
+
                public readonly string ExplicitTarget;
                public AttributeTargets Target;
 
@@ -123,6 +163,14 @@ namespace Mono.CSharp {
                        this.nameEscaped = nameEscaped;
                }
 
+               public Attribute Clone ()
+               {
+                       Attribute a = new Attribute (ExplicitTarget, LeftExpr, Identifier, null, loc, nameEscaped);
+                       a.PosArguments = PosArguments;
+                       a.NamedArguments = NamedArguments;
+                       return a;
+               }
+
                static Attribute ()
                {
                        Reset ();
@@ -217,7 +265,7 @@ namespace Mono.CSharp {
 
                Type ResolvePossibleAttributeType (string name, bool silent, ref bool is_attr)
                {
-                       IResolveContext rc = Owner.ResolveContext;
+                       IResolveContext rc = new AttributeResolveContext (Owner.ResolveContext);
 
                        TypeExpr te;
                        if (LeftExpr == null) {
@@ -295,8 +343,8 @@ namespace Mono.CSharp {
 
                public bool HasSecurityAttribute {
                        get {
-                               return TypeManager.security_attr_type != null &&
-                               TypeManager.IsSubclassOf (type, TypeManager.security_attr_type);
+                               PredefinedAttribute pa = PredefinedAttributes.Get.Security;
+                               return pa.IsDefined && TypeManager.IsSubclassOf (type, pa.Type);
                        }
                }
 
@@ -320,10 +368,10 @@ namespace Mono.CSharp {
                [Conditional ("GMCS_SOURCE")]
                void ApplyModuleCharSet ()
                {
-                       if (Type != TypeManager.dllimport_type)
+                       if (Type != PredefinedAttributes.Get.DllImport)
                                return;
 
-                       if (!CodeGen.Module.HasDefaultCharSet)
+                       if (!RootContext.ToplevelTypes.HasDefaultCharSet)
                                return;
 
                        const string CharSetEnumMember = "CharSet";
@@ -337,7 +385,7 @@ namespace Mono.CSharp {
                        }
                        
                        NamedArguments.Add (new DictionaryEntry (CharSetEnumMember,
-                               new Argument (Constant.CreateConstant (typeof (CharSet), CodeGen.Module.DefaultCharSet, Location))));
+                               new Argument (Constant.CreateConstant (typeof (CharSet), RootContext.ToplevelTypes.DefaultCharSet, Location))));
                }
 
                public CustomAttributeBuilder Resolve ()
@@ -376,8 +424,8 @@ namespace Mono.CSharp {
                        if (ds == null)
                                ds = owner.ResolveContext.DeclContainer;
                        
-                       EmitContext ec = new EmitContext (owner.ResolveContext, ds, owner.ResolveContext.DeclContainer,
-                               Location, null, typeof (Attribute), owner.ResolveContext.DeclContainer.ModFlags, false);
+                       EmitContext ec = new EmitContext (owner.ResolveContext, ds, ds,
+                               Location, null, typeof (Attribute), ds.ModFlags, false);
                        ec.IsAnonymousMethodAllowed = false;
 
                        ConstructorInfo ctor = ResolveConstructor (ec);
@@ -437,45 +485,38 @@ namespace Mono.CSharp {
                        }
                        
                        MethodGroupExpr mg = MemberLookupFinal (ec, ec.ContainerType,
-                               Type, ".ctor", MemberTypes.Constructor,
+                               Type, ConstructorInfo.ConstructorName, MemberTypes.Constructor,
                                BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
                                Location) as MethodGroupExpr;
 
                        if (mg == null)
-                               return null;
+                               throw new NotImplementedException ();
 
                        mg = mg.OverloadResolve (ec, ref PosArguments, false, Location);
                        if (mg == null)
                                return null;
                        
                        ConstructorInfo constructor = (ConstructorInfo)mg;
-
-                       // TODO: move to OverloadResolve
-                       ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (constructor);
-                       if (oa != null && !Owner.ResolveContext.IsInObsoleteScope) {
-                               AttributeTester.Report_ObsoleteMessage (oa, mg.GetSignatureForError (), mg.Location);
-                       }
-
                        if (PosArguments == null) {
                                pos_values = EmptyObject;
                                return constructor;
                        }
 
-                       ParameterData pd = TypeManager.GetParameterData (constructor);
+                       AParametersCollection pd = TypeManager.GetParameterData (constructor);
 
                        int pos_arg_count = PosArguments.Count;
                        pos_values = new object [pos_arg_count];
                        for (int j = 0; j < pos_arg_count; ++j) {
                                Argument a = (Argument) PosArguments [j];
 
-                               if (!a.Expr.GetAttributableValue (a.Type, out pos_values [j]))
+                               if (!a.Expr.GetAttributableValue (ec, a.Type, out pos_values [j]))
                                        return null;
                        }
 
                        // Here we do the checks which should be done by corlib or by runtime.
                        // However Zoltan doesn't like it and every Mono compiler has to do it again.
-                       
-                       if (Type == TypeManager.guid_attr_type) {
+                       PredefinedAttributes pa = PredefinedAttributes.Get;
+                       if (Type == pa.Guid) {
                                try {
                                        new Guid ((string)pos_values [0]);
                                }
@@ -485,21 +526,22 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       if (Type == TypeManager.attribute_usage_type && (int)pos_values [0] == 0) {
+                       if (Type == pa.AttributeUsage && (int)pos_values [0] == 0) {
                                Report.Error (591, Location, "Invalid value for argument to `System.AttributeUsage' attribute");
                                return null;
                        }
 
-                       if (Type == TypeManager.indexer_name_type || Type == TypeManager.conditional_attribute_type) {
-                               if (!Tokenizer.IsValidIdentifier ((string)pos_values [0])) {
+                       if (Type == pa.IndexerName || Type == pa.Conditional) {
+                               string v = pos_values [0] as string;
+                               if (!Tokenizer.IsValidIdentifier (v) || Tokenizer.IsKeyword (v)) {
                                        Report.Error (633, ((Argument)PosArguments[0]).Expr.Location,
                                                "The argument to the `{0}' attribute must be a valid identifier", GetSignatureForError ());
                                        return null;
                                }
                        }
 
-                       if (Type == TypeManager.methodimpl_attr_type && pos_values.Length == 1 &&
-                               pd.ParameterType (0) == TypeManager.short_type &&
+                       if (Type == pa.MethodImpl && pos_values.Length == 1 &&
+                               pd.Types [0] == TypeManager.short_type &&
                                !System.Enum.IsDefined (typeof (MethodImplOptions), pos_values [0].ToString ())) {
                                Error_AttributeEmitError ("Incorrect argument value.");
                                return null;
@@ -523,7 +565,7 @@ namespace Mono.CSharp {
                                string member_name = (string) de.Key;
 
                                if (seen_names.Contains(member_name)) {
-                                       Report.Error(643, Location, "'" + member_name + "' duplicate named attribute argument");
+                                       Report.Error(643, Location, "'{0}' duplicate named attribute argument", member_name);
                                        return false;
                                }                               
                                seen_names.Add(member_name);
@@ -583,7 +625,7 @@ namespace Mono.CSharp {
                                        }
 
                                        object value;
-                                       if (!a.Expr.GetAttributableValue (member.Type, out value))
+                                       if (!a.Expr.GetAttributableValue (ec, member.Type, out value))
                                                return false;
 
                                        PropertyBase pb = TypeManager.GetProperty (pi);
@@ -610,7 +652,7 @@ namespace Mono.CSharp {
                                        }
 
                                        object value;
-                                       if (!a.Expr.GetAttributableValue (member.Type, out value))
+                                       if (!a.Expr.GetAttributableValue (ec, member.Type, out value))
                                                return false;
 
                                        FieldBase fb = TypeManager.GetField (fi);
@@ -708,9 +750,13 @@ namespace Mono.CSharp {
                                return ua;
 
                        Class attr_class = TypeManager.LookupClass (type);
+                       PredefinedAttribute pa = PredefinedAttributes.Get.AttributeUsage;
 
                        if (attr_class == null) {
-                               object[] usage_attr = type.GetCustomAttributes (TypeManager.attribute_usage_type, true);
+                               if (!pa.IsDefined)
+                                       return new AttributeUsageAttribute (0);
+
+                               object[] usage_attr = type.GetCustomAttributes (pa.Type, true);
                                ua = (AttributeUsageAttribute)usage_attr [0];
                                usage_attr_cache.Add (type, ua);
                                return ua;
@@ -718,7 +764,7 @@ namespace Mono.CSharp {
 
                        Attribute a = null;
                        if (attr_class.OptAttributes != null)
-                               a = attr_class.OptAttributes.Search (TypeManager.attribute_usage_type);
+                               a = attr_class.OptAttributes.Search (pa);
 
                        if (a == null) {
                                if (attr_class.TypeBuilder.BaseType != TypeManager.attribute_type)
@@ -850,11 +896,11 @@ namespace Mono.CSharp {
                        // TODO: we can skip the first item
                        if (((IList) valid_targets).Contains (ExplicitTarget)) {
                                switch (ExplicitTarget) {
-                                       case "return": Target = AttributeTargets.ReturnValue; return true;
-                                       case "param": Target = AttributeTargets.Parameter; return true;
-                                       case "field": Target = AttributeTargets.Field; return true;
-                                       case "method": Target = AttributeTargets.Method; return true;
-                                       case "property": Target = AttributeTargets.Property; return true;
+                               case "return": Target = AttributeTargets.ReturnValue; return true;
+                               case "param": Target = AttributeTargets.Parameter; return true;
+                               case "field": Target = AttributeTargets.Field; return true;
+                               case "method": Target = AttributeTargets.Method; return true;
+                               case "property": Target = AttributeTargets.Property; return true;
                                }
                                throw new InternalErrorException ("Unknown explicit target: " + ExplicitTarget);
                        }
@@ -964,7 +1010,7 @@ namespace Mono.CSharp {
                                                // TODO: pi can be null
                                                PropertyInfo pi = orig_assembly_type.GetProperty (emited_pi.Name);
 
-                                               object old_instance = pi.PropertyType.IsEnum ?
+                                               object old_instance = TypeManager.IsEnumType (pi.PropertyType) ?
                                                        System.Enum.ToObject (pi.PropertyType, prop_values_arr [i]) :
                                                        prop_values_arr [i];
 
@@ -980,15 +1026,15 @@ namespace Mono.CSharp {
                        // 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;
+                               case SecurityAction.Demand:
+                                       action = (SecurityAction)13;
+                                       break;
+                               case SecurityAction.LinkDemand:
+                                       action = (SecurityAction)14;
+                                       break;
+                               case SecurityAction.InheritanceDemand:
+                                       action = (SecurityAction)15;
+                                       break;
                                }
                        }
 
@@ -1007,14 +1053,6 @@ namespace Mono.CSharp {
                        ps.AddPermission (perm);
                }
 
-               static object GetValue (object value)
-               {
-                       if (value is EnumConstant)
-                               return ((EnumConstant) value).GetValue ();
-                       else
-                               return value;                           
-               }
-
                public object GetPropertyValue (string name)
                {
                        if (prop_info_arr == null)
@@ -1028,25 +1066,12 @@ namespace Mono.CSharp {
                        return null;
                }
 
-               object GetFieldValue (string name)
-               {
-                       int i;
-                       if (field_info_arr == null)
-                               return null;
-                       i = 0;
-                       foreach (FieldInfo fi in field_info_arr) {
-                               if (fi.Name == name)
-                                       return GetValue (field_values_arr [i]);
-                               i++;
-                       }
-                       return null;
-               }
-
                //
                // Theoretically, we can get rid of this, since FieldBuilder.SetCustomAttribute()
                // and ParameterBuilder.SetCustomAttribute() are supposed to handle this attribute.
                // However, we can't, since it appears that the .NET 1.1 SRE hangs when given a MarshalAsAttribute.
                //
+#if !NET_2_0
                public UnmanagedMarshal GetMarshal (Attributable attr)
                {
                        UnmanagedType UnmanagedType;
@@ -1120,14 +1145,51 @@ namespace Mono.CSharp {
                        }
                }
 
+               object GetFieldValue (string name)
+               {
+                       int i;
+                       if (field_info_arr == null)
+                               return null;
+                       i = 0;
+                       foreach (FieldInfo fi in field_info_arr) {
+                               if (fi.Name == name)
+                                       return GetValue (field_values_arr [i]);
+                               i++;
+                       }
+                       return null;
+               }
+
+               static object GetValue (object value)
+               {
+                       if (value is EnumConstant)
+                               return ((EnumConstant) value).GetValue ();
+                       else
+                               return value;                           
+               }
+               
+#endif
+
                public CharSet GetCharSetValue ()
                {
                        return (CharSet)System.Enum.Parse (typeof (CharSet), pos_values [0].ToString ());
                }
 
+               public bool HasField (string fieldName)
+               {
+                       if (field_info_arr == null)
+                               return false;
+
+                       foreach (FieldInfo fi in field_info_arr) {
+                               if (fi.Name == fieldName)
+                                       return true;
+                       }
+
+                       return false;
+               }
+
                public bool IsInternalMethodImplAttribute {
                        get {
-                               if (Type != TypeManager.methodimpl_attr_type)
+                               if (Type != PredefinedAttributes.Get.MethodImpl)
                                        return false;
 
                                MethodImplOptions options;
@@ -1186,7 +1248,7 @@ namespace Mono.CSharp {
 
                        try {
                                foreach (Attributable owner in owners)
-                                       owner.ApplyAttributeBuilder (this, cb);
+                                       owner.ApplyAttributeBuilder (this, cb, PredefinedAttributes.Get);
                        }
                        catch (Exception e) {
                                Error_AttributeEmitError (e.Message);
@@ -1218,7 +1280,7 @@ namespace Mono.CSharp {
                                                        return;
 
                                                if (arg.Type.IsArray) {
-                                                       Report.Error (3016, Location, "Arrays as attribute arguments are not CLS-compliant");
+                                                       Report.Warning (3016, 1, Location, "Arrays as attribute arguments are not CLS-compliant");
                                                        return;
                                                }
                                        }
@@ -1235,7 +1297,7 @@ namespace Mono.CSharp {
                                                return;
 
                                        if (arg.Type.IsArray) {
-                                               Report.Error (3016, Location, "Arrays as attribute arguments are not CLS-compliant");
+                                               Report.Warning (3016, 1, Location, "Arrays as attribute arguments are not CLS-compliant");
                                                return;
                                        }
                                }
@@ -1314,7 +1376,7 @@ namespace Mono.CSharp {
                                return;
                        }
                        if (ExplicitTarget == "module") {
-                               owners [0] = CodeGen.Module;
+                               owners [0] = RootContext.ToplevelTypes;
                                return;
                        }
                        throw new NotImplementedException ("Unknown global explicit target " + ExplicitTarget);
@@ -1404,6 +1466,15 @@ namespace Mono.CSharp {
                                a.AttachTo (attributable);
                }
 
+               public Attributes Clone ()
+               {
+                       ArrayList al = new ArrayList (Attrs.Count);
+                       foreach (Attribute a in Attrs)
+                               al.Add (a.Clone ());
+
+                       return new Attributes (al);
+               }
+
                /// <summary>
                /// Checks whether attribute target is valid for the current element
                /// </summary>
@@ -1416,7 +1487,7 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               public Attribute Search (Type t)
+               public Attribute Search (PredefinedAttribute t)
                {
                        foreach (Attribute a in Attrs) {
                                if (a.ResolveType () == t)
@@ -1428,7 +1499,7 @@ namespace Mono.CSharp {
                /// <summary>
                /// Returns all attributes of type 't'. Use it when attribute is AllowMultiple = true
                /// </summary>
-               public Attribute[] SearchMulti (Type t)
+               public Attribute[] SearchMulti (PredefinedAttribute t)
                {
                        ArrayList ar = null;
 
@@ -1468,7 +1539,7 @@ namespace Mono.CSharp {
                        }
                }
 
-               public bool Contains (Type t)
+               public bool Contains (PredefinedAttribute t)
                {
                        return Search (t) != null;
                }
@@ -1516,8 +1587,10 @@ namespace Mono.CSharp {
                /// Returns true if parameters of two compared methods are CLS-Compliant.
                /// It tests differing only in ref or out, or in array rank.
                /// </summary>
-               public static Result AreOverloadedMethodParamsClsCompliant (Type[] types_a, Type[] types_b) 
+               public static Result AreOverloadedMethodParamsClsCompliant (AParametersCollection pa, AParametersCollection pb) 
                {
+                       Type [] types_a = pa.Types;
+                       Type [] types_b = pb.Types;
                        if (types_a == null || types_b == null)
                                return Result.Ok;
 
@@ -1530,8 +1603,8 @@ namespace Mono.CSharp {
                                Type bType = types_b [i];
 
                                if (aType.IsArray && bType.IsArray) {
-                                       Type a_el_type = aType.GetElementType ();
-                                       Type b_el_type = bType.GetElementType ();
+                                       Type a_el_type = TypeManager.GetElementType (aType);
+                                       Type b_el_type = TypeManager.GetElementType (bType);
                                        if (aType.GetArrayRank () != bType.GetArrayRank () && a_el_type == b_el_type) {
                                                result = Result.RefOutArrayError;
                                                continue;
@@ -1543,25 +1616,11 @@ namespace Mono.CSharp {
                                        }
                                }
 
-                               Type aBaseType = aType;
-                               bool is_either_ref_or_out = false;
-
-                               if (aType.IsByRef || aType.IsPointer) {
-                                       aBaseType = aType.GetElementType ();
-                                       is_either_ref_or_out = true;
-                               }
-
-                               Type bBaseType = bType;
-                               if (bType.IsByRef || bType.IsPointer) 
-                               {
-                                       bBaseType = bType.GetElementType ();
-                                       is_either_ref_or_out = !is_either_ref_or_out;
-                               }
-
-                               if (aBaseType != bBaseType)
+                               if (aType != bType)
                                        return Result.Ok;
 
-                               if (is_either_ref_or_out)
+                               const Parameter.Modifier out_ref_mod = (Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK);
+                               if ((pa.FixedParameters[i].ModFlags & out_ref_mod) != (pb.FixedParameters[i].ModFlags & out_ref_mod))
                                        result = Result.RefOutArrayError;
                        }
                        return result;
@@ -1580,12 +1639,12 @@ namespace Mono.CSharp {
                                return type_compliance == TRUE;
 
                        if (type.IsPointer) {
-                               analyzed_types.Add (type, null);
+                               analyzed_types.Add (type, FALSE);
                                return false;
                        }
 
                        bool result;
-                       if (type.IsArray || type.IsByRef) {
+                       if (type.IsArray) {
                                result = IsClsCompliant (TypeManager.GetElementType (type));
                        } else if (TypeManager.IsNullableType (type)) {
                                result = IsClsCompliant (TypeManager.GetTypeArguments (type) [0]);
@@ -1602,7 +1661,7 @@ namespace Mono.CSharp {
                public static IFixedBuffer GetFixedBuffer (FieldInfo fi)
                {
                        // Fixed buffer helper type is generated as value type
-                       if (!fi.FieldType.IsValueType)
+                       if (TypeManager.IsReferenceType (fi.FieldType))
                                return null;
 
                        FieldBase fb = TypeManager.GetField (fi);
@@ -1615,10 +1674,11 @@ namespace Mono.CSharp {
 
                        object o = fixed_buffer_cache [fi];
                        if (o == null) {
-                               if (TypeManager.fixed_buffer_attr_type == null)
+                               PredefinedAttribute pa = PredefinedAttributes.Get.FixedBuffer;
+                               if (!pa.IsDefined)
                                        return null;
 
-                               if (!fi.IsDefined (TypeManager.fixed_buffer_attr_type, false)) {
+                               if (!fi.IsDefined (pa.Type, false)) {
                                        fixed_buffer_cache.Add (fi, FALSE);
                                        return null;
                                }
@@ -1636,7 +1696,7 @@ namespace Mono.CSharp {
 
                public static void VerifyModulesClsCompliance ()
                {
-                       Module[] modules = RootNamespace.Global.Modules;
+                       Module[] modules = GlobalRootNamespace.Instance.Modules;
                        if (modules == null)
                                return;
 
@@ -1653,7 +1713,7 @@ namespace Mono.CSharp {
 
                public static Type GetImportedIgnoreCaseClsType (string name)
                {
-                       foreach (Assembly a in RootNamespace.Global.Assemblies) {
+                       foreach (Assembly a in GlobalRootNamespace.Instance.Assemblies) {
                                Type t = a.GetType (name, false, true);
                                if (t == null)
                                        continue;
@@ -1666,10 +1726,11 @@ namespace Mono.CSharp {
 
                static bool GetClsCompliantAttributeValue (ICustomAttributeProvider attribute_provider, Assembly a) 
                {
-                       if (TypeManager.cls_compliant_attribute_type == null)
+                       PredefinedAttribute pa = PredefinedAttributes.Get.CLSCompliant;
+                       if (!pa.IsDefined)
                                return false;
 
-                       object[] cls_attr = attribute_provider.GetCustomAttributes (TypeManager.cls_compliant_attribute_type, false);
+                       object[] cls_attr = attribute_provider.GetCustomAttributes (pa.Type, false);
                        if (cls_attr.Length == 0) {
                                if (a == null)
                                        return false;
@@ -1709,17 +1770,20 @@ namespace Mono.CSharp {
                        ObsoleteAttribute result = null;
                        if (TypeManager.HasElementType (type)) {
                                result = GetObsoleteAttribute (TypeManager.GetElementType (type));
-                       } else if (TypeManager.IsGenericParameter (type) || TypeManager.IsGenericType (type))
-                               return null;
-                       else {
+                       } else if (TypeManager.IsGenericParameter (type))
+                               result = null;  // TODO: throw new NotSupportedException ()
+                       else if (TypeManager.IsGenericType (type) && !TypeManager.IsGenericTypeDefinition (type)) {
+                               return GetObsoleteAttribute (TypeManager.DropGenericTypeArguments (type));
+                       } else {
                                DeclSpace type_ds = TypeManager.LookupDeclSpace (type);
 
                                // Type is external, we can get attribute directly
                                if (type_ds == null) {
-                                       if (TypeManager.obsolete_attribute_type != null) {
-                                               object [] attribute = type.GetCustomAttributes (TypeManager.obsolete_attribute_type, false);
+                                       PredefinedAttribute pa = PredefinedAttributes.Get.Obsolete;
+                                       if (pa.IsDefined) {
+                                               object[] attribute = type.GetCustomAttributes (pa.Type, false);
                                                if (attribute.Length == 1)
-                                                       result = (ObsoleteAttribute) attribute [0];
+                                                       result = (ObsoleteAttribute) attribute[0];
                                        }
                                } else {
                                        result = type_ds.GetObsoleteAttribute ();
@@ -1770,10 +1834,11 @@ namespace Mono.CSharp {
                        if ((mi.DeclaringType is TypeBuilder) || TypeManager.IsGenericType (mi.DeclaringType))
                                return null;
 
-                       if (TypeManager.obsolete_attribute_type == null)
+                       PredefinedAttribute pa = PredefinedAttributes.Get.Obsolete;
+                       if (!pa.IsDefined)
                                return null;
 
-                       ObsoleteAttribute oa = System.Attribute.GetCustomAttribute (mi, TypeManager.obsolete_attribute_type, false)
+                       ObsoleteAttribute oa = System.Attribute.GetCustomAttribute (mi, pa.Type, false)
                                as ObsoleteAttribute;
                        analyzed_member_obsolete.Add (mi, oa == null ? FALSE : oa);
                        return oa;
@@ -1796,16 +1861,17 @@ namespace Mono.CSharp {
                        Report.Warning (618, 2, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
                }
 
-               public static bool IsConditionalMethodExcluded (MethodBase mb)
+               public static bool IsConditionalMethodExcluded (MethodBase mb, Location loc)
                {
                        object excluded = analyzed_method_excluded [mb];
                        if (excluded != null)
                                return excluded == TRUE ? true : false;
 
-                       if (TypeManager.conditional_attribute_type == null)
+                       PredefinedAttribute pa = PredefinedAttributes.Get.Conditional;
+                       if (!pa.IsDefined)
                                return false;
 
-                       ConditionalAttribute[] attrs = mb.GetCustomAttributes (TypeManager.conditional_attribute_type, true)
+                       ConditionalAttribute[] attrs = mb.GetCustomAttributes (pa.Type, true)
                                as ConditionalAttribute[];
                        if (attrs.Length == 0) {
                                analyzed_method_excluded.Add (mb, FALSE);
@@ -1813,11 +1879,12 @@ namespace Mono.CSharp {
                        }
 
                        foreach (ConditionalAttribute a in attrs) {
-                               if (RootContext.AllDefines.Contains (a.ConditionString)) {
+                               if (loc.CompilationUnit.IsConditionalDefined (a.ConditionString)) {
                                        analyzed_method_excluded.Add (mb, FALSE);
                                        return false;
                                }
                        }
+
                        analyzed_method_excluded.Add (mb, TRUE);
                        return true;
                }
@@ -1826,7 +1893,7 @@ namespace Mono.CSharp {
                /// Analyzes class whether it has attribute which has ConditionalAttribute
                /// and its condition is not defined.
                /// </summary>
-               public static bool IsAttributeExcluded (Type type)
+               public static bool IsAttributeExcluded (Type type, Location loc)
                {
                        if (!type.IsClass)
                                return false;
@@ -1835,10 +1902,11 @@ namespace Mono.CSharp {
 
                        // TODO: add caching
                        // TODO: merge all Type bases attribute caching to one cache to save memory
-                       if (class_decl == null && TypeManager.conditional_attribute_type != null) {
-                               object[] attributes = type.GetCustomAttributes (TypeManager.conditional_attribute_type, false);
+                       PredefinedAttribute pa = PredefinedAttributes.Get.Conditional;
+                       if (class_decl == null && pa.IsDefined) {
+                               object[] attributes = type.GetCustomAttributes (pa.Type, false);
                                foreach (ConditionalAttribute ca in attributes) {
-                                       if (RootContext.AllDefines.Contains (ca.ConditionString))
+                                       if (loc.CompilationUnit.IsConditionalDefined (ca.ConditionString))
                                                return false;
                                }
                                return attributes.Length > 0;
@@ -1850,24 +1918,257 @@ namespace Mono.CSharp {
                public static Type GetCoClassAttribute (Type type)
                {
                        TypeContainer tc = TypeManager.LookupInterface (type);
+                       PredefinedAttribute pa = PredefinedAttributes.Get.CoClass;
                        if (tc == null) {
-                               if (TypeManager.coclass_attr_type == null)
+                               if (!pa.IsDefined)
                                        return null;
 
-                               object[] o = type.GetCustomAttributes (TypeManager.coclass_attr_type, false);
+                               object[] o = type.GetCustomAttributes (pa.Type, false);
                                if (o.Length < 1)
                                        return null;
                                return ((System.Runtime.InteropServices.CoClassAttribute)o[0]).CoClass;
                        }
 
-                       if (tc.OptAttributes == null || TypeManager.coclass_attr_type == null)
+                       if (tc.OptAttributes == null)
                                return null;
 
-                       Attribute a = tc.OptAttributes.Search (TypeManager.coclass_attr_type);
+                       Attribute a = tc.OptAttributes.Search (pa);
                        if (a == null)
                                return null;
 
                        return a.GetCoClassAttributeValue ();
                }
        }
+
+       public class PredefinedAttributes
+       {
+               // Core types
+               public readonly PredefinedAttribute ParamArray;
+               public readonly PredefinedAttribute Out;
+
+               // Optional types
+               public readonly PredefinedAttribute Obsolete;
+               public readonly PredefinedAttribute DllImport;
+               public readonly PredefinedAttribute MethodImpl;
+               public readonly PredefinedAttribute MarshalAs;
+               public readonly PredefinedAttribute In;
+               public readonly PredefinedAttribute IndexerName;
+               public readonly PredefinedAttribute Conditional;
+               public readonly PredefinedAttribute CLSCompliant;
+               public readonly PredefinedAttribute Security;
+               public readonly PredefinedAttribute Required;
+               public readonly PredefinedAttribute Guid;
+               public readonly PredefinedAttribute AssemblyCulture;
+               public readonly PredefinedAttribute AssemblyVersion;
+               public readonly PredefinedAttribute ComImport;
+               public readonly PredefinedAttribute CoClass;
+               public readonly PredefinedAttribute AttributeUsage;
+               public readonly PredefinedAttribute DefaultParameterValue;
+
+               // New in .NET 2.0
+               public readonly PredefinedAttribute DefaultCharset;
+               public readonly PredefinedAttribute TypeForwarder;
+               public readonly PredefinedAttribute FixedBuffer;
+               public readonly PredefinedAttribute CompilerGenerated;
+               public readonly PredefinedAttribute InternalsVisibleTo;
+               public readonly PredefinedAttribute RuntimeCompatibility;
+               public readonly PredefinedAttribute DebuggerHidden;
+               public readonly PredefinedAttribute UnsafeValueType;
+
+               // New in .NET 3.5
+               public readonly PredefinedAttribute Extension;
+
+               //
+               // Optional types which are used as types and for member lookup
+               //
+               public readonly PredefinedAttribute DefaultMember;
+               public readonly PredefinedAttribute DecimalConstant;
+               public readonly PredefinedAttribute StructLayout;
+               public readonly PredefinedAttribute FieldOffset;
+
+               public static PredefinedAttributes Get = new PredefinedAttributes ();
+
+               private PredefinedAttributes ()
+               {
+                       ParamArray = new PredefinedAttribute ("System", "ParamArrayAttribute");
+                       Out = new PredefinedAttribute ("System.Runtime.InteropServices", "OutAttribute");
+
+                       Obsolete = new PredefinedAttribute ("System", "ObsoleteAttribute");
+                       DllImport = new PredefinedAttribute ("System.Runtime.InteropServices", "DllImportAttribute");
+                       MethodImpl = new PredefinedAttribute ("System.Runtime.CompilerServices", "MethodImplAttribute");
+                       MarshalAs = new PredefinedAttribute ("System.Runtime.InteropServices", "MarshalAsAttribute");
+                       In = new PredefinedAttribute ("System.Runtime.InteropServices", "InAttribute");
+                       IndexerName = new PredefinedAttribute ("System.Runtime.CompilerServices", "IndexerNameAttribute");
+                       Conditional = new PredefinedAttribute ("System.Diagnostics", "ConditionalAttribute");
+                       CLSCompliant = new PredefinedAttribute ("System", "CLSCompliantAttribute");
+                       Security = new PredefinedAttribute ("System.Security.Permissions", "SecurityAttribute");
+                       Required = new PredefinedAttribute ("System.Runtime.CompilerServices", "RequiredAttributeAttribute");
+                       Guid = new PredefinedAttribute ("System.Runtime.InteropServices", "GuidAttribute");
+                       AssemblyCulture = new PredefinedAttribute ("System.Reflection", "AssemblyCultureAttribute");
+                       AssemblyVersion = new PredefinedAttribute ("System.Reflection", "AssemblyVersionAttribute");
+                       ComImport = new PredefinedAttribute ("System.Runtime.InteropServices", "ComImportAttribute");
+                       CoClass = new PredefinedAttribute ("System.Runtime.InteropServices", "CoClassAttribute");
+                       AttributeUsage = new PredefinedAttribute ("System", "AttributeUsageAttribute");
+                       DefaultParameterValue = new PredefinedAttribute ("System.Runtime.InteropServices", "DefaultParameterValueAttribute");
+
+                       DefaultCharset = new PredefinedAttribute ("System.Runtime.InteropServices", "DefaultCharSetAttribute");
+                       TypeForwarder = new PredefinedAttribute ("System.Runtime.CompilerServices", "TypeForwardedToAttribute");
+                       FixedBuffer = new PredefinedAttribute ("System.Runtime.CompilerServices", "FixedBufferAttribute");
+                       CompilerGenerated = new PredefinedAttribute ("System.Runtime.CompilerServices", "CompilerGeneratedAttribute");
+                       InternalsVisibleTo = new PredefinedAttribute ("System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
+                       RuntimeCompatibility = new PredefinedAttribute ("System.Runtime.CompilerServices", "RuntimeCompatibilityAttribute");
+                       DebuggerHidden = new PredefinedAttribute ("System.Diagnostics", "DebuggerHiddenAttribute");
+                       UnsafeValueType = new PredefinedAttribute ("System.Runtime.CompilerServices", "UnsafeValueTypeAttribute");
+
+                       Extension = new PredefinedAttribute ("System.Runtime.CompilerServices", "ExtensionAttribute");
+
+                       DefaultMember = new PredefinedAttribute ("System.Reflection", "DefaultMemberAttribute");
+                       DecimalConstant = new PredefinedAttribute ("System.Runtime.CompilerServices", "DecimalConstantAttribute");
+                       StructLayout = new PredefinedAttribute ("System.Runtime.InteropServices", "StructLayoutAttribute");
+                       FieldOffset = new PredefinedAttribute ("System.Runtime.InteropServices", "FieldOffsetAttribute");
+               }
+
+               public void Initialize ()
+               {
+                       foreach (FieldInfo fi in GetType ().GetFields (BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)) {
+                               ((PredefinedAttribute) fi.GetValue (this)).Resolve (true);
+                       }
+               }
+
+               public static void Reset ()
+               {
+                       Get = new PredefinedAttributes ();
+               }
+       }
+
+       public class PredefinedAttribute
+       {
+               Type type;
+               CustomAttributeBuilder cab;
+               ConstructorInfo ctor;
+               readonly string ns, name;
+
+               public PredefinedAttribute (string ns, string name)
+               {
+                       this.ns = ns;
+                       this.name = name;
+               }
+
+               public static bool operator == (Type type, PredefinedAttribute pa)
+               {
+                       return type == pa.type;
+               }
+
+               public static bool operator != (Type type, PredefinedAttribute pa)
+               {
+                       return type != pa.type;
+               }
+
+               public ConstructorInfo Constructor {
+                       get { return ctor; }
+               }
+
+               public override int GetHashCode ()
+               {
+                       return base.GetHashCode ();
+               }
+
+               public override bool Equals (object obj)
+               {
+                       throw new NotSupportedException ();
+               }
+
+               public void EmitAttribute (ConstructorBuilder builder)
+               {
+                       if (ResolveBuilder ())
+                               builder.SetCustomAttribute (cab);
+               }
+
+               public void EmitAttribute (MethodBuilder builder)
+               {
+                       if (ResolveBuilder ())
+                               builder.SetCustomAttribute (cab);
+               }
+
+               public void EmitAttribute (FieldBuilder builder)
+               {
+                       if (ResolveBuilder ())
+                               builder.SetCustomAttribute (cab);
+               }
+
+               public void EmitAttribute (TypeBuilder builder)
+               {
+                       if (ResolveBuilder ())
+                               builder.SetCustomAttribute (cab);
+               }
+
+               public void EmitAttribute (AssemblyBuilder builder)
+               {
+                       if (ResolveBuilder ())
+                               builder.SetCustomAttribute (cab);
+               }
+
+               public void EmitAttribute (ParameterBuilder builder, Location loc)
+               {
+                       if (ResolveBuilder ())
+                               builder.SetCustomAttribute (cab);
+               }
+
+               public bool IsDefined {
+                       get { return type != null && type != typeof (PredefinedAttribute); }
+               }
+
+               public bool Resolve (bool canFail)
+               {
+                       if (type != null) {
+                               if (IsDefined)
+                                       return true;
+                               if (canFail)
+                                       return false;
+                       }
+
+                       type = TypeManager.CoreLookupType (ns, name, Kind.Class, !canFail);
+                       if (type == null) {
+                               type = typeof (PredefinedAttribute);
+                               return false;
+                       }
+
+                       return true;
+               }
+
+               bool ResolveBuilder ()
+               {
+                       if (cab != null)
+                               return true;
+
+                       //
+                       // Handle all parameter-less attributes as optional
+                       //
+                       if (!Resolve (true))
+                               return false;
+
+                       ConstructorInfo ci = TypeManager.GetPredefinedConstructor (type, Location.Null, Type.EmptyTypes);
+                       if (ci == null)
+                               return false;
+
+                       cab = new CustomAttributeBuilder (ci, new object[0]);
+                       return true;
+               }
+
+               public bool ResolveConstructor (Location loc, params Type[] argType)
+               {
+                       if (ctor != null)
+                               throw new InternalErrorException ("Predefined ctor redefined");
+
+                       if (!Resolve (false))
+                               return false;
+
+                       ctor = TypeManager.GetPredefinedConstructor (type, loc, argType);
+                       return ctor != null;
+               }
+
+               public Type Type {
+                       get { return type; }
+               }
+       }
 }