2007-11-16 Marek Safar <marek.safar@gmail.com>
[mono.git] / mcs / mcs / attribute.cs
index c92254c81d07442e755f1f219939389aba30922d..64ca04c520fba7cfeca088138ba694c1b1587b05 100644 (file)
@@ -75,7 +75,8 @@ namespace Mono.CSharp {
                public abstract string[] ValidAttributeTargets { get; }
        };
 
-       public class Attribute {
+       public class Attribute : Expression
+       {
                public readonly string ExplicitTarget;
                public AttributeTargets Target;
 
@@ -87,15 +88,11 @@ namespace Mono.CSharp {
                readonly ArrayList PosArguments;
                ArrayList NamedArguments;
 
-               public readonly Location Location;
-
-               public Type Type;
-
                bool resolve_error;
                readonly bool nameEscaped;
 
                // It can contain more onwers when the attribute is applied to multiple fiels.
-               Attributable[] owners;
+               protected Attributable[] owners;
 
                static readonly AttributeUsageAttribute DefaultUsageAttribute = new AttributeUsageAttribute (AttributeTargets.All);
                static Assembly orig_sec_assembly;
@@ -121,7 +118,7 @@ namespace Mono.CSharp {
                                PosArguments = (ArrayList)args [0];
                                NamedArguments = (ArrayList)args [1];                           
                        }
-                       Location = loc;
+                       this.loc = loc;
                        ExplicitTarget = target;
                        this.nameEscaped = nameEscaped;
                }
@@ -137,7 +134,7 @@ namespace Mono.CSharp {
                        att_cache = new PtrHashtable ();
                }
 
-               public void AttachTo (Attributable owner)
+               public virtual void AttachTo (Attributable owner)
                {
                        if (this.owners == null) {
                                this.owners = new Attributable[1] { owner };
@@ -288,7 +285,7 @@ namespace Mono.CSharp {
                        return Type;
                }
 
-               public string GetSignatureForError ()
+               public override string GetSignatureForError ()
                {
                        if (Type != null)
                                return TypeManager.CSharpName (Type);
@@ -363,8 +360,12 @@ namespace Mono.CSharp {
                        }
 
                        Attributable owner = Owner;
-                       EmitContext ec = new EmitContext (owner.ResolveContext, owner.ResolveContext.DeclContainer, owner.ResolveContext.DeclContainer,
-                               Location, null, null, owner.ResolveContext.DeclContainer.ModFlags, false);
+                       DeclSpace ds = owner.ResolveContext as DeclSpace;
+                       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);
                        ec.IsAnonymousMethodAllowed = false;
 
                        ConstructorInfo ctor = ResolveConstructor (ec);
@@ -381,6 +382,10 @@ namespace Mono.CSharp {
 
                        CustomAttributeBuilder cb;
                        try {
+                               // SRE does not allow private ctor but we want to report all source code errors
+                               if (ctor.IsPrivate)
+                                       return null;
+
                                if (NamedArguments == null) {
                                        cb = new CustomAttributeBuilder (ctor, pos_values);
 
@@ -418,21 +423,22 @@ namespace Mono.CSharp {
                                                return null;
                                }
                        }
-
-                       Expression mg = Expression.MemberLookup (ec.ContainerType,
+                       
+                       MethodGroupExpr mg = MemberLookupFinal (ec, ec.ContainerType,
                                Type, ".ctor", MemberTypes.Constructor,
                                BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
-                               Location);
+                               Location) as MethodGroupExpr;
 
                        if (mg == null)
                                return null;
 
-                       MethodBase constructor = ((MethodGroupExpr)mg).OverloadResolve (
-                               ec, PosArguments, false, Location);
-
-                       if (constructor == null)
+                       mg = mg.OverloadResolve (ec, 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);
@@ -440,7 +446,7 @@ namespace Mono.CSharp {
 
                        if (PosArguments == null) {
                                pos_values = EmptyObject;
-                               return (ConstructorInfo)constructor;
+                               return constructor;
                        }
 
                        ParameterData pd = TypeManager.GetParameterData (constructor);
@@ -663,7 +669,7 @@ namespace Mono.CSharp {
                public string GetValidTargets ()
                {
                        StringBuilder sb = new StringBuilder ();
-                       AttributeTargets targets = GetAttributeUsage ().ValidOn;
+                       AttributeTargets targets = GetAttributeUsage (Type).ValidOn;
 
                        if ((targets & AttributeTargets.Assembly) != 0)
                                sb.Append ("assembly, ");
@@ -715,32 +721,37 @@ namespace Mono.CSharp {
                }
 
                /// <summary>
-               /// Returns AttributeUsage attribute for this type
+               /// Returns AttributeUsage attribute based on types hierarchy
                /// </summary>
-               AttributeUsageAttribute GetAttributeUsage ()
+               static AttributeUsageAttribute GetAttributeUsage (Type type)
                {
-                       AttributeUsageAttribute ua = usage_attr_cache [Type] as AttributeUsageAttribute;
+                       AttributeUsageAttribute ua = usage_attr_cache [type] as AttributeUsageAttribute;
                        if (ua != null)
                                return ua;
 
-                       Class attr_class = TypeManager.LookupClass (Type);
+                       Class attr_class = TypeManager.LookupClass (type);
 
                        if (attr_class == null) {
-                               object[] usage_attr = Type.GetCustomAttributes (TypeManager.attribute_usage_type, true);
+                               object[] usage_attr = type.GetCustomAttributes (TypeManager.attribute_usage_type, true);
                                ua = (AttributeUsageAttribute)usage_attr [0];
-                               usage_attr_cache.Add (Type, ua);
+                               usage_attr_cache.Add (type, ua);
                                return ua;
                        }
 
-                       Attribute a = attr_class.OptAttributes == null
-                               ? null
-                               : attr_class.OptAttributes.Search (TypeManager.attribute_usage_type);
+                       Attribute a = null;
+                       if (attr_class.OptAttributes != null)
+                               a = attr_class.OptAttributes.Search (TypeManager.attribute_usage_type);
 
-                       ua = a == null
-                               ? DefaultUsageAttribute 
-                               : a.GetAttributeUsageAttribute ();
+                       if (a == null) {
+                               if (attr_class.TypeBuilder.BaseType != TypeManager.attribute_type)
+                                       ua = GetAttributeUsage (attr_class.TypeBuilder.BaseType);
+                               else
+                                       ua = DefaultUsageAttribute;
+                       } else {
+                               ua = a.GetAttributeUsageAttribute ();
+                       }
 
-                       usage_attr_cache.Add (Type, ua);
+                       usage_attr_cache.Add (type, ua);
                        return ua;
                }
 
@@ -1185,7 +1196,7 @@ namespace Mono.CSharp {
                        if (cb == null)
                                return;
 
-                       AttributeUsageAttribute usage_attr = GetAttributeUsage ();
+                       AttributeUsageAttribute usage_attr = GetAttributeUsage (Type);
                        if ((usage_attr.ValidOn & Target) == 0) {
                                Report.Error (592, Location, "The attribute `{0}' is not valid on this declaration type. " +
                                              "It is valid on `{1}' declarations only",
@@ -1262,16 +1273,16 @@ namespace Mono.CSharp {
                public string GetString () 
                {
                        Expression e = GetValue ();
-                       if (e is StringLiteral)
-                               return (e as StringLiteral).Value;
+                       if (e is StringConstant)
+                               return ((StringConstant)e).Value;
                        return null;
                }
 
                public bool GetBoolean () 
                {
                        Expression e = GetValue ();
-                       if (e is BoolLiteral)
-                               return (e as BoolLiteral).Value;
+                       if (e is BoolConstant)
+                               return ((BoolConstant)e).Value;
                        return false;
                }
 
@@ -1282,6 +1293,16 @@ namespace Mono.CSharp {
                                return null;
                        return e.TypeArgument;
                }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       throw new NotImplementedException ();
+               }
        }
        
 
@@ -1298,6 +1319,20 @@ namespace Mono.CSharp {
                        base (target, left_expr, identifier, args, loc, nameEscaped)
                {
                        this.ns = ns;
+                       this.owners = new Attributable[1];
+               }
+               
+               public override void AttachTo (Attributable owner)
+               {
+                       if (ExplicitTarget == "assembly") {
+                               owners [0] = CodeGen.Assembly;
+                               return;
+                       }
+                       if (ExplicitTarget == "module") {
+                               owners [0] = CodeGen.Module;
+                               return;
+                       }
+                       throw new NotImplementedException ("Unknown global explicit target " + ExplicitTarget);
                }
 
                void Enter ()
@@ -1438,7 +1473,8 @@ namespace Mono.CSharp {
                                        Report.SymbolRelatedToPreviousError (collision.Location, "");
 
                                Attribute a = (Attribute)d.Key;
-                               Report.Error (579, a.Location, "The attribute `{0}' cannot be applied multiple times", a.GetSignatureForError ());
+                               Report.Error (579, a.Location, "The attribute `{0}' cannot be applied multiple times",
+                                       a.GetSignatureForError ());
                        }
                }
 
@@ -1564,8 +1600,10 @@ namespace Mono.CSharp {
                        }
 
                        bool result;
-                       if (type.IsArray || type.IsByRef)       {
+                       if (type.IsArray || type.IsByRef) {
                                result = IsClsCompliant (TypeManager.GetElementType (type));
+                       } else if (TypeManager.IsNullableType (type)) {
+                               result = IsClsCompliant (TypeManager.GetTypeArguments (type) [0]);
                        } else {
                                result = AnalyzeTypeCompliance (type);
                        }
@@ -1586,11 +1624,14 @@ namespace Mono.CSharp {
                        if (fb != null) {
                                return fb as IFixedBuffer;
                        }
+                       
+                       if (TypeManager.GetConstant (fi) != null)
+                               return null;
 
 #if NET_2_0
                        object o = fixed_buffer_cache [fi];
                        if (o == null) {
-                               if (System.Attribute.GetCustomAttribute (fi, TypeManager.fixed_buffer_attr_type) == null) {
+                               if (!fi.IsDefined (TypeManager.fixed_buffer_attr_type, false)) {
                                        fixed_buffer_cache.Add (fi, FALSE);
                                        return null;
                                }
@@ -1763,7 +1804,7 @@ namespace Mono.CSharp {
                                return;
                        }
 
-                       if (oa.Message == null) {
+                       if (oa.Message == null || oa.Message.Length == 0) {
                                Report.Warning (612, 1, loc, "`{0}' is obsolete", member);
                                return;
                        }
@@ -1772,10 +1813,6 @@ namespace Mono.CSharp {
 
                public static bool IsConditionalMethodExcluded (MethodBase mb)
                {
-                       mb = TypeManager.DropGenericMethodArguments (mb);
-                       if ((mb is MethodBuilder) || (mb is ConstructorBuilder))
-                               return false;
-
                        object excluded = analyzed_method_excluded [mb];
                        if (excluded != null)
                                return excluded == TRUE ? true : false;