2009-02-09 Marek Safar <marek.safar@gmail.com>
[mono.git] / mcs / mcs / attribute.cs
index 84e29b78a80ec8eb7df6f90bce12f7699a6a9c28..da6717218380af100ea14fe489e9feaa02be002f 100644 (file)
@@ -4,10 +4,10 @@
 // Author: Ravi Pratap (ravi@ximian.com)
 //         Marek Safar (marek.safar@seznam.cz)
 //
-// Licensed under the terms of the GNU GPL
-//
-// (C) 2001 Ximian, Inc (http://www.ximian.com)
+// Dual licensed under the terms of the MIT X11 or GNU GPL
 //
+// Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
+// Copyright 2003-2008 Novell, Inc.
 //
 
 using System;
@@ -123,6 +123,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 ();
@@ -376,8 +384,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);
@@ -449,26 +457,19 @@ namespace Mono.CSharp {
                                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;
                        }
 
@@ -491,7 +492,8 @@ namespace Mono.CSharp {
                        }
 
                        if (Type == TypeManager.indexer_name_type || Type == TypeManager.conditional_attribute_type) {
-                               if (!Tokenizer.IsValidIdentifier ((string)pos_values [0])) {
+                               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;
@@ -499,7 +501,7 @@ namespace Mono.CSharp {
                        }
 
                        if (Type == TypeManager.methodimpl_attr_type && pos_values.Length == 1 &&
-                               pd.ParameterType (0) == TypeManager.short_type &&
+                               pd.Types [0] == TypeManager.short_type &&
                                !System.Enum.IsDefined (typeof (MethodImplOptions), pos_values [0].ToString ())) {
                                Error_AttributeEmitError ("Incorrect argument value.");
                                return null;
@@ -523,7 +525,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 +585,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 +612,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);
@@ -850,11 +852,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);
                        }
@@ -960,9 +962,11 @@ namespace Mono.CSharp {
                                if (prop_info_arr != null) {
                                        for (int i = 0; i < prop_info_arr.Length; ++i) {
                                                PropertyInfo emited_pi = prop_info_arr [i];
-                                               PropertyInfo pi = orig_assembly_type.GetProperty (emited_pi.Name, emited_pi.PropertyType);
+                                               // FIXME: We are missing return type filter
+                                               // 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];
 
@@ -978,15 +982,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;
                                }
                        }
 
@@ -1005,14 +1009,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)
@@ -1026,25 +1022,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;
@@ -1118,11 +1101,48 @@ 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)
@@ -1216,7 +1236,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;
                                                }
                                        }
@@ -1233,7 +1253,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;
                                        }
                                }
@@ -1272,6 +1292,11 @@ namespace Mono.CSharp {
                        return e.TypeArgument;
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       throw new NotSupportedException ("ET");
+               }
+
                public override Expression DoResolve (EmitContext ec)
                {
                        throw new NotImplementedException ();
@@ -1397,6 +1422,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>
@@ -1509,8 +1543,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;
 
@@ -1523,8 +1559,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;
@@ -1536,25 +1572,10 @@ 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)
+                               if (pa.FixedParameters [i].ModFlags != pb.FixedParameters [i].ModFlags)
                                        result = Result.RefOutArrayError;
                        }
                        return result;
@@ -1573,12 +1594,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]);
@@ -1595,7 +1616,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);
@@ -1687,13 +1708,6 @@ namespace Mono.CSharp {
                        return GetClsCompliantAttributeValue (type, type.Assembly);
                }
 
-               // Registers the core type as we assume that they will never be obsolete which
-               // makes things easier for bootstrap and faster (we don't need to query Obsolete attribute).
-               public static void RegisterNonObsoleteType (Type type)
-               {
-                       analyzed_types_obsolete [type] = FALSE;
-               }
-
                /// <summary>
                /// Returns instance of ObsoleteAttribute when type is obsolete
                /// </summary>
@@ -1709,17 +1723,19 @@ 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);
+                                               object[] attribute = type.GetCustomAttributes (TypeManager.obsolete_attribute_type, false);
                                                if (attribute.Length == 1)
-                                                       result = (ObsoleteAttribute) attribute [0];
+                                                       result = (ObsoleteAttribute) attribute[0];
                                        }
                                } else {
                                        result = type_ds.GetObsoleteAttribute ();
@@ -1796,7 +1812,7 @@ 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)
@@ -1813,11 +1829,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 +1843,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;
@@ -1838,7 +1855,7 @@ namespace Mono.CSharp {
                        if (class_decl == null && TypeManager.conditional_attribute_type != null) {
                                object[] attributes = type.GetCustomAttributes (TypeManager.conditional_attribute_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;