[Mono.CSharp] Fix bug where overwriting variables cleared the wrong value
[mono.git] / mcs / mcs / class.cs
index 981dcd5cc9dae8492340df6a0b6d94381a9a7362..943db46deabceb0b05b664c0a6372b029a967052 100644 (file)
@@ -13,8 +13,6 @@
 
 using System;
 using System.Collections.Generic;
-using System.Reflection;
-using System.Reflection.Emit;
 using System.Runtime.InteropServices;
 using System.Security;
 using System.Security.Permissions;
@@ -22,10 +20,17 @@ using System.Linq;
 
 #if NET_2_1
 using XmlElement = System.Object;
-#else
-
 #endif
 
+#if STATIC
+using SecurityType = System.Collections.Generic.List<IKVM.Reflection.Emit.CustomAttributeBuilder>;
+using IKVM.Reflection;
+using IKVM.Reflection.Emit;
+#else
+using SecurityType = System.Collections.Generic.Dictionary<System.Security.Permissions.SecurityAction, System.Security.PermissionSet>;
+using System.Reflection;
+using System.Reflection.Emit;
+#endif
 
 namespace Mono.CSharp {
 
@@ -82,6 +87,10 @@ namespace Mono.CSharp {
                                get { return tc.IsStatic; }
                        }
 
+                       public ModuleContainer Module {
+                               get { return tc.Module; }
+                       }
+
                        public string GetSignatureForError ()
                        {
                                return tc.GetSignatureForError ();
@@ -647,7 +656,7 @@ namespace Mono.CSharp {
 
                protected override TypeAttributes TypeAttr {
                        get {
-                               return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel) | base.TypeAttr;
+                               return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel);
                        }
                }
 
@@ -674,7 +683,7 @@ namespace Mono.CSharp {
                                if (OptAttributes == null)
                                        return false;
 
-                               return OptAttributes.Contains (Compiler.PredefinedAttributes.ComImport);
+                               return OptAttributes.Contains (Module.PredefinedAttributes.ComImport);
                        }
                }
 
@@ -788,7 +797,7 @@ namespace Mono.CSharp {
                        if (OptAttributes == null)
                                return null;
 
-                       Attribute a = OptAttributes.Search (Compiler.PredefinedAttributes.CoClass);
+                       Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CoClass);
                        if (a == null)
                                return null;
 
@@ -1017,6 +1026,9 @@ namespace Mono.CSharp {
                                TypeBuilder = Parent.TypeBuilder.DefineNestedType (Basename, TypeAttr, null, type_size);
                        }
 
+                       if (DeclaringAssembly.Importer != null)
+                               DeclaringAssembly.Importer.AddCompiledType (TypeBuilder, spec);
+
                        spec.SetMetaInfo (TypeBuilder);
                        spec.MemberCache = new MemberCache (this);
                        spec.DeclaringType = Parent.CurrentType;
@@ -1070,7 +1082,7 @@ namespace Mono.CSharp {
                                var cloned_params = ParametersCompiled.CreateFullyResolved (base_parameters, method.Parameters.Types);
                                if (method.Parameters.HasArglist) {
                                        cloned_params.FixedParameters[0] = new Parameter (null, "__arglist", Parameter.Modifier.NONE, null, Location);
-                                       cloned_params.Types[0] = TypeManager.runtime_argument_handle_type;
+                                       cloned_params.Types[0] = Module.PredefinedTypes.RuntimeArgumentHandle.Resolve (Location);
                                }
 
                                GenericMethod generic_method;
@@ -1210,6 +1222,8 @@ namespace Mono.CSharp {
 
                                // Set base type after type creation
                                TypeBuilder.SetParent (base_type.GetMetaInfo ());
+                       } else {
+                               TypeBuilder.SetParent (null);
                        }
 
                        return true;
@@ -1335,9 +1349,22 @@ namespace Mono.CSharp {
                // Replaces normal spec with predefined one when compiling corlib
                // and this type container defines predefined type
                //
-               public void SetPredefinedSpec (PredefinedTypeSpec spec)
-               {
+               public void SetPredefinedSpec (BuildinTypeSpec spec)
+               {
+                       // When compiling build-in types we start with two
+                       // version of same type. One is of BuildinTypeSpec and
+                       // second one is ordinary TypeSpec. The unification
+                       // happens at later stage when we know which type
+                       // really matches the buildin type signature. However
+                       // that means TypeSpec create during CreateType of this
+                       // type has to be replaced with buildin one
+                       // 
+                       spec.SetMetaInfo (TypeBuilder);
+                       spec.MemberCache = this.spec.MemberCache;
+                       spec.DeclaringType = this.spec.DeclaringType;
+
                        this.spec = spec;
+                       current_type = null;
                }
 
                void UpdateTypeParameterConstraints (TypeContainer part)
@@ -1505,6 +1532,11 @@ namespace Mono.CSharp {
                                if (ct != null)
                                        ct.CheckConstraints (this);
 
+                               if (base_type.Interfaces != null) {
+                                       foreach (var iface in base_type.Interfaces)
+                                               spec.AddInterface (iface);
+                               }
+
                                var baseContainer = base_type.MemberDefinition as ClassOrStruct;
                                if (baseContainer != null) {
                                        baseContainer.Define ();
@@ -1555,6 +1587,10 @@ namespace Mono.CSharp {
                        ComputeIndexerName();
                        CheckEqualsAndGetHashCode();
 
+                       if (Kind == MemberKind.Interface && iface_exprs != null) {
+                               MemberCache.RemoveHiddenMembers (spec);
+                       }
+
                        return true;
                }
 
@@ -1613,12 +1649,12 @@ namespace Mono.CSharp {
                        if (!seen_normal_indexers)
                                return;
 
-                       PredefinedAttribute pa = Compiler.PredefinedAttributes.DefaultMember;
+                       PredefinedAttribute pa = Module.PredefinedAttributes.DefaultMember;
                        if (pa.Constructor == null &&
                                !pa.ResolveConstructor (Location, TypeManager.string_type))
                                return;
 
-                       var encoder = new AttributeEncoder (false);
+                       var encoder = new AttributeEncoder ();
                        encoder.Encode (GetAttributeDefaultMember ());
                        encoder.EncodeEmptyNamedArguments ();
 
@@ -1755,7 +1791,12 @@ namespace Mono.CSharp {
                        }
 
                        if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
-                               Compiler.PredefinedAttributes.CompilerGenerated.EmitAttribute (TypeBuilder);
+                               Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (TypeBuilder);
+
+#if STATIC
+                       if ((TypeBuilder.Attributes & TypeAttributes.StringFormatMask) == 0 && Module.HasDefaultCharSet)
+                               TypeBuilder.__SetAttributes (TypeBuilder.Attributes | Module.DefaultCharSetType);
+#endif
 
                        base.Emit ();
                }
@@ -1861,7 +1902,7 @@ namespace Mono.CSharp {
                        }
                }
 
-               public void CloseType ()
+               public virtual void CloseType ()
                {
                        if ((caching_flags & Flags.CloseTypeCreated) != 0)
                                return;
@@ -1869,8 +1910,12 @@ namespace Mono.CSharp {
                        // Close base type container first to avoid TypeLoadException
                        if (spec.BaseType != null) {
                                var btype = spec.BaseType.MemberDefinition as TypeContainer;
-                               if (btype != null)
+                               if (btype != null) {
                                        btype.CloseType ();
+
+                                       if ((caching_flags & Flags.CloseTypeCreated) != 0)
+                                               return;
+                               }
                        }
 
                        try {
@@ -2191,7 +2236,7 @@ namespace Mono.CSharp {
 
        public abstract class ClassOrStruct : TypeContainer
        {
-               Dictionary<SecurityAction, PermissionSet> declarative_security;
+               SecurityType declarative_security;
 
                public ClassOrStruct (NamespaceEntry ns, DeclSpace parent,
                                      MemberName name, Attributes attrs, MemberKind kind)
@@ -2233,15 +2278,17 @@ namespace Mono.CSharp {
                                                Report.Warning (67, 3, e.Location, "The event `{0}' is never used", e.GetSignatureForError ());
                                }
                        }
+
+                       if (types != null) {
+                               foreach (var t in types)
+                                       t.VerifyMembers ();
+                       }
                }
 
                public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
                {
                        if (a.IsValidSecurityAttribute ()) {
-                               if (declarative_security == null)
-                                       declarative_security = new Dictionary<SecurityAction, PermissionSet> ();
-
-                               a.ExtractSecurityPermissionSet (declarative_security);
+                               a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
                                return;
                        }
 
@@ -2307,7 +2354,11 @@ namespace Mono.CSharp {
 
                        if (declarative_security != null) {
                                foreach (var de in declarative_security) {
+#if STATIC
+                                       TypeBuilder.__AddDeclarativeSecurity (de);
+#else
                                        TypeBuilder.AddDeclarativeSecurity (de.Key, de.Value);
+#endif
                                }
                        }
                }
@@ -2478,10 +2529,10 @@ namespace Mono.CSharp {
                        base.Emit ();
 
                        if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
-                               Compiler.PredefinedAttributes.Extension.EmitAttribute (TypeBuilder);
+                               Module.PredefinedAttributes.Extension.EmitAttribute (TypeBuilder);
 
                        if (base_type != null && base_type.HasDynamicElement) {
-                               Compiler.PredefinedAttributes.Dynamic.EmitAttribute (TypeBuilder, base_type);
+                               Module.PredefinedAttributes.Dynamic.EmitAttribute (TypeBuilder, base_type, Location);
                        }
                }
 
@@ -2513,7 +2564,7 @@ namespace Mono.CSharp {
                                                GetSignatureForError (), base_class.GetSignatureForError ());
                                }
 
-                               if (base_type is PredefinedTypeSpec && !(spec is PredefinedTypeSpec) &&
+                               if (base_type is BuildinTypeSpec && !(spec is BuildinTypeSpec) &&
                                        (base_type == TypeManager.enum_type || base_type == TypeManager.value_type || base_type == TypeManager.multicast_delegate_type ||
                                        base_type == TypeManager.delegate_type || base_type == TypeManager.array_type)) {
                                        Report.Error (644, Location, "`{0}' cannot derive from special class `{1}'",
@@ -2550,7 +2601,7 @@ namespace Mono.CSharp {
                        if (OptAttributes == null)
                                return null;
 
-                       Attribute[] attrs = OptAttributes.SearchMulti (Compiler.PredefinedAttributes.Conditional);
+                       Attribute[] attrs = OptAttributes.SearchMulti (Module.PredefinedAttributes.Conditional);
                        if (attrs == null)
                                return null;
 
@@ -2645,7 +2696,7 @@ namespace Mono.CSharp {
                                if (!ftype.IsStruct)
                                        continue;
 
-                               if (ftype is PredefinedTypeSpec)
+                               if (ftype is BuildinTypeSpec)
                                        continue;
 
                                foreach (var targ in ftype.TypeArguments) {
@@ -2960,13 +3011,13 @@ namespace Mono.CSharp {
 
                                ObsoleteAttribute oa = base_member.GetAttributeObsolete ();
                                if (oa != null) {
-                                       if (OptAttributes == null || !OptAttributes.Contains (Compiler.PredefinedAttributes.Obsolete)) {
+                                       if (OptAttributes == null || !OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
                                                Report.SymbolRelatedToPreviousError (base_member);
                                                Report.Warning (672, 1, Location, "Member `{0}' overrides obsolete member `{1}'. Add the Obsolete attribute to `{0}'",
                                                        GetSignatureForError (), TypeManager.GetFullNameSignature (base_member));
                                        }
                                } else {
-                                       if (OptAttributes != null && OptAttributes.Contains (Compiler.PredefinedAttributes.Obsolete)) {
+                                       if (OptAttributes != null && OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
                                                Report.SymbolRelatedToPreviousError (base_member);
                                                Report.Warning (809, 1, Location, "Obsolete member `{0}' overrides non-obsolete member `{1}'",
                                                        GetSignatureForError (), TypeManager.GetFullNameSignature (base_member));
@@ -3063,34 +3114,30 @@ namespace Mono.CSharp {
                        var base_classp = base_member.Modifiers & Modifiers.AccessibilityMask;
 
                        if ((base_classp & (Modifiers.PROTECTED | Modifiers.INTERNAL)) == (Modifiers.PROTECTED | Modifiers.INTERNAL)) {
+                               //
+                               // It must be at least "protected"
+                               //
+                               if ((thisp & Modifiers.PROTECTED) == 0) {
+                                       return false;
+                               }
+
                                //
                                // when overriding protected internal, the method can be declared
                                // protected internal only within the same assembly or assembly
                                // which has InternalsVisibleTo
                                //
-                               if ((thisp & (Modifiers.PROTECTED | Modifiers.INTERNAL)) == (Modifiers.PROTECTED | Modifiers.INTERNAL)) {
+                               if ((thisp & Modifiers.INTERNAL) != 0) {
                                        return base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly);
-                               } 
-                               if ((thisp & Modifiers.PROTECTED) != Modifiers.PROTECTED) {
-                                       //
-                                       // if it's not "protected internal", it must be "protected"
-                                       //
-
-                                       return false;
                                }
-                               if (this_member.Parent.PartialContainer.DeclaringAssembly == base_member.DeclaringType.MemberDefinition.DeclaringAssembly) {
-                                       //
-                                       // protected within the same assembly - an error
-                                       //
-                                       return false;
-                               }
-                               if ((thisp & ~(Modifiers.PROTECTED | Modifiers.INTERNAL)) !=
-                                          (base_classp & ~(Modifiers.PROTECTED | Modifiers.INTERNAL))) {
-                                       //
-                                       // protected ok, but other attributes differ - report an error
-                                       //
+
+                               //
+                               // protected overriding protected internal inside same assembly
+                               // requires internal modifier as well
+                               //
+                               if (base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly)) {
                                        return false;
                                }
+
                                return true;
                        }
 
@@ -3211,11 +3258,18 @@ namespace Mono.CSharp {
 
                protected void Error_CannotChangeAccessModifiers (MemberCore member, MemberSpec base_member)
                {
+                       var base_modifiers = base_member.Modifiers;
+
+                       // Remove internal modifier from types which are not internally accessible
+                       if ((base_modifiers & Modifiers.AccessibilityMask) == (Modifiers.PROTECTED | Modifiers.INTERNAL) &&
+                               !base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (member.Module.DeclaringAssembly))
+                               base_modifiers = Modifiers.PROTECTED;
+
                        Report.SymbolRelatedToPreviousError (base_member);
                        Report.Error (507, member.Location,
                                "`{0}': cannot change access modifiers when overriding `{1}' inherited member `{2}'",
                                member.GetSignatureForError (),
-                               ModifiersExtensions.AccessibilityName (base_member.Modifiers),
+                               ModifiersExtensions.AccessibilityName (base_modifiers),
                                base_member.GetSignatureForError ());
                }