2006-04-28 Marek Safar <marek.safar@seznam.cz>
[mono.git] / mcs / mcs / attribute.cs
index 372ab9e3dd64061018d419ec394fc2d2dfda7820..35a2c566e530987c9b429f4ee3974bab4c4ea3d2 100644 (file)
@@ -36,7 +36,8 @@ namespace Mono.CSharp {
 
                public Attributable (Attributes attrs)
                {
-                       OptAttributes = attrs;
+                       if (attrs != null)
+                               OptAttributes = attrs;
                }
 
                public Attributes OptAttributes 
@@ -92,7 +93,9 @@ namespace Mono.CSharp {
 
                bool resolve_error;
                readonly bool nameEscaped;
-               Attributable owner;
+
+               // It can contain more onwers when the attribute is applied to multiple fiels.
+               Attributable[] owners;
 
                static readonly AttributeUsageAttribute DefaultUsageAttribute = new AttributeUsageAttribute (AttributeTargets.All);
                static Assembly orig_sec_assembly;
@@ -105,10 +108,9 @@ namespace Mono.CSharp {
                object [] prop_values_arr;
                object [] pos_values;
 
-               static PtrHashtable usage_attr_cache = new PtrHashtable ();
-
+               static PtrHashtable usage_attr_cache;
                // Cache for parameter-less attributes
-               static PtrHashtable att_cache = new PtrHashtable ();
+               static PtrHashtable att_cache;
                
                public Attribute (string target, Expression left_expr, string identifier, object[] args, Location loc, bool nameEscaped)
                {
@@ -124,9 +126,33 @@ namespace Mono.CSharp {
                        this.nameEscaped = nameEscaped;
                }
 
+               static Attribute ()
+               {
+                       Reset ();
+               }
+
+               public static void Reset ()
+               {
+                       usage_attr_cache = new PtrHashtable ();
+                       att_cache = new PtrHashtable ();
+               }
+
                public void AttachTo (Attributable owner)
                {
-                       this.owner = owner;
+                       if (this.owners == null) {
+                               this.owners = new Attributable[1] { owner };
+                               return;
+                       }
+
+                       // When the same attribute is attached to multiple fiels
+                       // we use this extra_owners as a list of owners. The attribute
+                       // then can be removed because will be emitted when first owner
+                       // is served
+                       Attributable[] new_array = new Attributable [this.owners.Length + 1];
+                       owners.CopyTo (new_array, 0);
+                       new_array [owners.Length] = owner;
+                       this.owners = new_array;
+                       owner.OptAttributes = null;
                }
 
                void Error_InvalidNamedArgument (string name)
@@ -150,6 +176,11 @@ namespace Mono.CSharp {
                                      "expression or array creation expression");
                }               
 
+               public void Error_MissingGuidAttribute ()
+               {
+                       Report.Error (596, Location, "The Guid attribute must be specified with the ComImport attribute");
+               }
+
                /// <summary>
                /// This is rather hack. We report many emit attribute error with same error to be compatible with
                /// csc. But because csc has to report them this way because error came from ilasm we needn't.
@@ -165,6 +196,12 @@ namespace Mono.CSharp {
                        Error_AttributeEmitError ("it is attached to invalid parent");
                }
 
+               Attributable Owner {
+                       get {
+                               return owners [0];
+                       }
+               }
+
                protected virtual TypeExpr ResolveAsTypeTerminal (Expression expr, IResolveContext ec, bool silent)
                {
                        return expr.ResolveAsTypeTerminal (ec, silent);
@@ -172,13 +209,13 @@ namespace Mono.CSharp {
 
                Type ResolvePossibleAttributeType (string name, bool silent, ref bool is_attr)
                {
-                       IResolveContext rc = owner.ResolveContext;
+                       IResolveContext rc = Owner.ResolveContext;
 
                        TypeExpr te;
                        if (LeftExpr == null) {
                                te = ResolveAsTypeTerminal (new SimpleName (name, Location), rc, silent);
                        } else {
-                               te = ResolveAsTypeTerminal (new MemberAccess (LeftExpr, name, Location), rc, silent);
+                               te = ResolveAsTypeTerminal (new MemberAccess (LeftExpr, name), rc, silent);
                        }
 
                        if (te == null)
@@ -291,8 +328,10 @@ 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);
+                       ec.IsAnonymousMethodAllowed = false;
 
                        ConstructorInfo ctor = ResolveConstructor (ec);
                        if (ctor == null)
@@ -344,6 +383,9 @@ namespace Mono.CSharp {
                                BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
                                Location);
 
+                       if (mg == null)
+                               return null;
+
                        MethodBase constructor = Invocation.OverloadResolve (
                                ec, (MethodGroupExpr) mg, PosArguments, false, Location);
 
@@ -351,7 +393,7 @@ namespace Mono.CSharp {
                                return null;
 
                        ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (constructor);
-                       if (oa != null && !owner.ResolveContext.IsInObsoleteScope) {
+                       if (oa != null && !Owner.ResolveContext.IsInObsoleteScope) {
                                AttributeTester.Report_ObsoleteMessage (oa, mg.GetSignatureForError (), mg.Location);
                        }
 
@@ -381,15 +423,9 @@ namespace Mono.CSharp {
                        for (int j = 0; j < pos_arg_count; ++j) {
                                Argument a = (Argument) PosArguments [j];
 
-                               if (!a.Expr.GetAttributableValue (out pos_values [j]))
+                               if (!a.Expr.GetAttributableValue (a.Type, out pos_values [j]))
                                        return null;
                                
-                               if (TypeManager.IsPrimitiveType (a.Type) && a.Type != pos_values [j].GetType ()) {
-                                       bool fail;
-                                       // This can happen only for constants in same range
-                                       pos_values [j] = TypeManager.ChangeType (pos_values [j], a.Type, out fail);
-                               }
-
                                if (j < last_real_param)
                                        continue;
                                
@@ -425,10 +461,18 @@ namespace Mono.CSharp {
                        }
 
                        if (Type == TypeManager.attribute_usage_type && (int)pos_values [0] == 0) {
-                               Report.Error (591, Location, "Invalid value for argument to 'System.AttributeUsage' attribute");
+                               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])) {
+                                       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 &&
                                !System.Enum.IsDefined (typeof (MethodImplOptions), pos_values [0].ToString ())) {
@@ -508,12 +552,8 @@ namespace Mono.CSharp {
                                                return false;
                                        }
 
-                                       Expression e = Convert.ImplicitConversionRequired (ec, a.Expr, pi.PropertyType, a.Expr.Location);
-                                       if (e == null)
-                                               return false;
-
                                        object value;
-                                       if (!e.GetAttributableValue (out value))
+                                       if (!a.Expr.GetAttributableValue (pi.PropertyType, out value))
                                                return false;
 
                                        PropertyBase pb = TypeManager.GetProperty (pi);
@@ -539,12 +579,8 @@ namespace Mono.CSharp {
                                                return false;
                                        }
 
-                                       Expression e = Convert.ImplicitConversionRequired (ec, a.Expr, fi.FieldType, a.Expr.Location);
-                                       if (e == null)
-                                               return false;
-
                                        object value;
-                                       if (!e.GetAttributableValue (out value))
+                                       if (!a.Expr.GetAttributableValue (fi.FieldType, out value))
                                                return false;
 
                                        FieldBase fb = TypeManager.GetField (fi);
@@ -557,7 +593,7 @@ namespace Mono.CSharp {
                                        field_infos.Add (fi);
                                }
 
-                               if (obsolete_attr != null && !owner.ResolveContext.IsInObsoleteScope)
+                               if (obsolete_attr != null && !Owner.ResolveContext.IsInObsoleteScope)
                                        AttributeTester.Report_ObsoleteMessage (obsolete_attr, member.GetSignatureForError (), member.Location);
                        }
 
@@ -770,9 +806,9 @@ namespace Mono.CSharp {
 
                public bool CheckTarget ()
                {
-                       string[] valid_targets = owner.ValidAttributeTargets;
+                       string[] valid_targets = Owner.ValidAttributeTargets;
                        if (ExplicitTarget == null || ExplicitTarget == valid_targets [0]) {
-                               Target = owner.AttributeTargets;
+                               Target = Owner.AttributeTargets;
                                return true;
                        }
 
@@ -926,7 +962,7 @@ namespace Mono.CSharp {
                        ps.AddPermission (perm);
                }
 
-               object GetValue (object value)
+               static object GetValue (object value)
                {
                        if (value is EnumConstant)
                                return ((EnumConstant) value).GetValue ();
@@ -1073,6 +1109,11 @@ namespace Mono.CSharp {
                        return base.GetHashCode ();
                }
 
+               public object GetParameterDefaultValue ()
+               {
+                       return pos_values [0];
+               }
+
                /// <summary>
                /// Emit attribute for Attributable symbol
                /// </summary>
@@ -1091,7 +1132,8 @@ namespace Mono.CSharp {
                        }
 
                        try {
-                               owner.ApplyAttributeBuilder (this, cb);
+                               foreach (Attributable owner in owners)
+                                       owner.ApplyAttributeBuilder (this, cb);
                        }
                        catch (Exception e) {
                                Error_AttributeEmitError (e.Message);
@@ -1115,7 +1157,7 @@ namespace Mono.CSharp {
                                return;
 
                        // Here we are testing attribute arguments for array usage (error 3016)
-                       if (owner.IsClsComplianceRequired ()) {
+                       if (Owner.IsClsComplianceRequired ()) {
                                if (PosArguments != null) {
                                        foreach (Argument arg in PosArguments) { 
                                                // Type is undefined (was error 246)
@@ -1456,22 +1498,38 @@ namespace Mono.CSharp {
        /// </summary>
        sealed class AttributeTester
        {
-               static PtrHashtable analyzed_types = new PtrHashtable ();
-               static PtrHashtable analyzed_types_obsolete = new PtrHashtable ();
-               static PtrHashtable analyzed_member_obsolete = new PtrHashtable ();
-               static PtrHashtable analyzed_method_excluded = new PtrHashtable ();
+               static PtrHashtable analyzed_types;
+               static PtrHashtable analyzed_types_obsolete;
+               static PtrHashtable analyzed_member_obsolete;
+               static PtrHashtable analyzed_method_excluded;
 
 #if NET_2_0
-               static PtrHashtable fixed_buffer_cache = new PtrHashtable ();
+               static PtrHashtable fixed_buffer_cache;
 #endif
 
                static object TRUE = new object ();
                static object FALSE = new object ();
 
+               static AttributeTester ()
+               {
+                       Reset ();
+               }
+
                private AttributeTester ()
                {
                }
 
+               public static void Reset ()
+               {
+                       analyzed_types = new PtrHashtable ();
+                       analyzed_types_obsolete = new PtrHashtable ();
+                       analyzed_member_obsolete = new PtrHashtable ();
+                       analyzed_method_excluded = new PtrHashtable ();
+#if NET_2_0
+                       fixed_buffer_cache = new PtrHashtable ();
+#endif
+               }
+
                public enum Result {
                        Ok,
                        RefOutArrayError,