**** Merged r40732-r40872 from MCS ****
[mono.git] / mcs / gmcs / attribute.cs
index 30d6a61dcced525a185d747c6f7662f4d3588d41..1e6a5e7137de37b6d05da6e358f8c85cbe364144 100644 (file)
@@ -72,6 +72,9 @@ namespace Mono.CSharp {
                public AttributeTargets Target;
 
                public readonly string    Name;
+               public readonly Expression LeftExpr;
+               public readonly string Identifier;
+
                public readonly ArrayList Arguments;
 
                public readonly Location Location;
@@ -102,9 +105,11 @@ namespace Mono.CSharp {
 
                static PtrHashtable usage_attr_cache = new PtrHashtable ();
                
-               public Attribute (string target, string name, ArrayList args, Location loc)
+               public Attribute (string target, Expression left_expr, string identifier, ArrayList args, Location loc)
                {
-                       Name = name;
+                       LeftExpr = left_expr;
+                       Identifier = identifier;
+                       Name = LeftExpr == null ? identifier : LeftExpr + "." + identifier;
                        Arguments = args;
                        Location = loc;
                        ExplicitTarget = target;
@@ -114,7 +119,7 @@ namespace Mono.CSharp {
                {
                        Report.Error (617, Location, "Invalid attribute argument: '{0}'.  Argument must be fields " +
                                      "fields which are not readonly, static or const;  or read-write instance properties.",
-                                     Name);
+                                     name);
                }
 
                static void Error_AttributeArgumentNotValid (string extra, Location loc)
@@ -155,26 +160,49 @@ namespace Mono.CSharp {
                                       "Could not find a constructor for this argument list.");
                }
 
+               void ResolvePossibleAttributeTypes (EmitContext ec, out Type t1, out Type t2)
+               {
+                       t1 = null;
+                       t2 = null;
+
+                       FullNamedExpression n1 = null;
+                       FullNamedExpression n2 = null;
+                       string IdentifierAttribute = Identifier + "Attribute";
+                       if (LeftExpr == null) {
+                               n1 = new SimpleName (Identifier, Location).ResolveAsTypeStep (ec);
+
+                               // FIXME: Shouldn't do this for quoted attributes: [@A]
+                               n2 = new SimpleName (IdentifierAttribute, Location).ResolveAsTypeStep (ec);
+                       } else {
+                               FullNamedExpression l = LeftExpr.ResolveAsTypeStep (ec);
+                               if (l == null) {
+                                       Report.Error (246, Location, "Couldn't find namespace or type '{0}'", LeftExpr);
+                                       return;
+                               }
+                               n1 = new MemberAccess (l, Identifier, Location).ResolveNamespaceOrType (ec, true);
+
+                               // FIXME: Shouldn't do this for quoted attributes: [X.@A]
+                               n2 = new MemberAccess (l, IdentifierAttribute, Location).ResolveNamespaceOrType (ec, true);
+                       }
+
+                       TypeExpr te1 = n1 == null ? null : n1 as TypeExpr;
+                       TypeExpr te2 = n2 == null ? null : n2 as TypeExpr;                      
+
+                       if (te1 != null)
+                               t1 = te1.ResolveType (ec);
+                       if (te2 != null)
+                               t2 = te2.ResolveType (ec);
+               }
+
                /// <summary>
                 ///   Tries to resolve the type of the attribute. Flags an error if it can't, and complain is true.
                 /// </summary>
-               protected virtual Type CheckAttributeType (EmitContext ec)
+               Type CheckAttributeType (EmitContext ec)
                {
-                       string NameAttribute = Name + "Attribute";
-                       FullNamedExpression n1 = ec.ResolvingTypeTree
-                               ? ec.DeclSpace.FindType (Location, Name)
-                               : ec.DeclSpace.LookupType (Name, true, Location);
-
-                       // FIXME: Shouldn't do this for quoted attributes: [@A]
-                       FullNamedExpression n2 = ec.ResolvingTypeTree
-                               ? ec.DeclSpace.FindType (Location, NameAttribute)
-                               : ec.DeclSpace.LookupType (NameAttribute, true, Location);
-
-                       TypeExpr e1 = n1 == null ? null : n1 as TypeExpr;
-                       TypeExpr e2 = n2 == null ? null : n2 as TypeExpr;                       
+                       Type t1, t2;
+                       ResolvePossibleAttributeTypes (ec, out t1, out t2);
 
-                       Type t1 = e1 == null ? null : e1.ResolveType (ec);
-                       Type t2 = e2 == null ? null : e2.ResolveType (ec);
+                       string NameAttribute = Name + "Attribute";
 
                        String err0616 = null;
                        if (t1 != null && ! t1.IsSubclassOf (TypeManager.attribute_type)) {
@@ -210,7 +238,7 @@ namespace Mono.CSharp {
                        return null;
                }
 
-               public Type ResolveType (EmitContext ec)
+               public virtual Type ResolveType (EmitContext ec)
                {
                        if (Type == null)
                                Type = CheckAttributeType (ec);
@@ -522,7 +550,7 @@ namespace Mono.CSharp {
                        // of type object
                        //
 
-                       ParameterData pd = Invocation.GetParameterData (constructor);
+                       ParameterData pd = TypeManager.GetParameterData (constructor);
 
                        int last_real_param = pd.Count;
                        if (pd.HasParams) {
@@ -544,6 +572,16 @@ namespace Mono.CSharp {
                                        return null;
                                }
 
+                               object value = pos_values [j];
+                               if (value != null && a.Type != value.GetType () && a.Type.IsPrimitive) {
+                                       bool fail;
+                                       pos_values [j] = TypeManager.ChangeType (value, a.Type, out fail);
+                                       if (fail) {
+                                               // TODO: Can failed ?
+                                               throw new NotImplementedException ();
+                                       }
+                               }
+
                                if (j < last_real_param)
                                        continue;
                                
@@ -1191,52 +1229,46 @@ namespace Mono.CSharp {
        {
                public readonly NamespaceEntry ns;
 
-               public GlobalAttribute (TypeContainer container, string target, string name, ArrayList args, Location loc):
-                       base (target, name, args, loc)
+               public GlobalAttribute (TypeContainer container, string target, 
+                                       Expression left_expr, string identifier, ArrayList args, Location loc):
+                       base (target, left_expr, identifier, args, loc)
                {
                        ns = container.NamespaceEntry;
                }
 
-               protected override Type CheckAttributeType (EmitContext ec)
+               void Enter ()
                {
                        // RootContext.Tree.Types has a single NamespaceEntry which gets overwritten
                        // each time a new file is parsed.  However, we need to use the NamespaceEntry
                        // in effect where the attribute was used.  Since code elsewhere cannot assume
                        // that the NamespaceEntry is right, just overwrite it.
                        //
-                       // Precondition: RootContext.Tree.Types == null || RootContext.Tree.Types == ns.
-                       //               The second case happens when we are recursively invoked from inside Emit.
-
-                       NamespaceEntry old = null;
-                       if (ec.DeclSpace == RootContext.Tree.Types) {
-                               old = ec.DeclSpace.NamespaceEntry;
-                               ec.DeclSpace.NamespaceEntry = ns;
-                               if (old != null && old != ns)
-                                       throw new InternalErrorException (Location + " non-null NamespaceEntry " + old);
-                       }
+                       // Precondition: RootContext.Tree.Types == null
+
+                       if (RootContext.Tree.Types.NamespaceEntry != null)
+                               throw new InternalErrorException (Location + " non-null NamespaceEntry");
 
-                       Type retval = base.CheckAttributeType (ec);
+                       RootContext.Tree.Types.NamespaceEntry = ns;
+               }
 
-                       if (ec.DeclSpace == RootContext.Tree.Types)
-                               ec.DeclSpace.NamespaceEntry = old;
+               void Leave ()
+               {
+                       RootContext.Tree.Types.NamespaceEntry = null;
+               }
 
+               public override Type ResolveType (EmitContext ec)
+               {
+                       Enter ();
+                       Type retval = base.ResolveType (ec);
+                       Leave ();
                        return retval;
                }
 
                public override CustomAttributeBuilder Resolve (EmitContext ec)
                {
-                       if (ec.DeclSpace == RootContext.Tree.Types) {
-                               NamespaceEntry old = ec.DeclSpace.NamespaceEntry;
-                               ec.DeclSpace.NamespaceEntry = ns;
-                               if (old != null)
-                                       throw new InternalErrorException (Location + " non-null NamespaceEntry " + old);
-                       }
-
+                       Enter ();
                        CustomAttributeBuilder retval = base.Resolve (ec);
-
-                       if (ec.DeclSpace == RootContext.Tree.Types)
-                               ec.DeclSpace.NamespaceEntry = null;
-
+                       Leave ();
                        return retval;
                }
        }
@@ -1349,6 +1381,10 @@ namespace Mono.CSharp {
                static PtrHashtable analyzed_types_obsolete = new PtrHashtable ();
                static PtrHashtable analyzed_member_obsolete = new PtrHashtable ();
                static PtrHashtable analyzed_method_excluded = new PtrHashtable ();
+               static PtrHashtable fixed_buffer_cache = new PtrHashtable ();
+
+               static object TRUE = new object ();
+               static object FALSE = new object ();
 
                private AttributeTester ()
                {
@@ -1441,10 +1477,39 @@ namespace Mono.CSharp {
                        }
                        analyzed_types.Add (type, result ? TRUE : FALSE);
                        return result;
-               }                
+               }        
+        
+               /// <summary>
+               /// Returns IFixedBuffer implementation if field is fixed buffer else null.
+               /// </summary>
+               public static IFixedBuffer GetFixedBuffer (FieldInfo fi)
+               {
+                       FieldBase fb = TypeManager.GetField (fi);
+                       if (fb != null) {
+                               return fb as IFixedBuffer;
+                       }
 
-               static object TRUE = new object ();
-               static object FALSE = new object ();
+#if NET_2_0
+                       object o = fixed_buffer_cache [fi];
+                       if (o == null) {
+                               if (System.Attribute.GetCustomAttribute (fi, TypeManager.fixed_buffer_attr_type) == null) {
+                                       fixed_buffer_cache.Add (fi, FALSE);
+                                       return null;
+                               }
+                               
+                               IFixedBuffer iff = new FixedFieldExternal (fi);
+                               fixed_buffer_cache.Add (fi, iff);
+                               return iff;
+                       }
+
+                       if (o == FALSE)
+                               return null;
+
+                       return (IFixedBuffer)o;
+#else
+                       return null;
+#endif
+               }
 
                public static void VerifyModulesClsCompliance ()
                {