[sgen] Clear the card table in the finishing pause
[mono.git] / mcs / mcs / membercache.cs
index 3837af2c2d8779e36d7cb82a064f3f5fbaeeb0e6..6a555cf325c01a82086f67180543cc92657b9aa1 100644 (file)
@@ -354,7 +354,7 @@ namespace Mono.CSharp {
                //
                static bool AddInterfaceMember (MemberSpec member, ref IList<MemberSpec> existing)
                {
-                       var member_param = member is IParametersMember ? ((IParametersMember) member).Parameters : ParametersCompiled.EmptyReadOnlyParameters;
+                       var member_param = member is IParametersMember ? ((IParametersMember) member).Parameters : null;
 
                        //
                        // interface IA : IB { int Prop { set; } }
@@ -368,10 +368,14 @@ namespace Mono.CSharp {
                                if (entry.Arity != member.Arity)
                                        continue;
 
-                               if (entry is IParametersMember) {
-                                       var entry_param = ((IParametersMember) entry).Parameters;
-                                       if (!TypeSpecComparer.Override.IsEqual (entry_param, member_param))
-                                               continue;
+                               AParametersCollection entry_param = null;
+                               if (member_param != null) {
+                                       var entry_pm = entry as IParametersMember;
+                                       if (entry_pm != null) {
+                                               entry_param = entry_pm.Parameters;
+                                               if (!TypeSpecComparer.Override.IsEqual (entry_param, member_param))
+                                                       continue;
+                                       }
                                }
 
                                if (member.DeclaringType.ImplementsInterface (entry.DeclaringType, false)) {
@@ -384,8 +388,10 @@ namespace Mono.CSharp {
                                        continue;
                                }
 
-                               if ((entry.DeclaringType == member.DeclaringType && entry.IsAccessor == member.IsAccessor) ||
-                                       entry.DeclaringType.ImplementsInterface (member.DeclaringType, false))
+                               if ((entry.DeclaringType == member.DeclaringType && entry.IsAccessor == member.IsAccessor))
+                                       return false;
+
+                               if (entry.DeclaringType.ImplementsInterface (member.DeclaringType, false) && AParametersCollection.HasSameParameterDefaults (entry_param, member_param))
                                        return false;
                        }
 
@@ -637,6 +643,24 @@ namespace Mono.CSharp {
                        return ambig_candidate;
                }
 
+               public static List<TypeSpec> GetDeclaredNestedTypes (TypeSpec container)
+               {
+                       List<TypeSpec> found = null;
+                       foreach (var entry in container.MemberCache.member_hash) {
+                               foreach (var member in entry.Value) {
+                                       if ((member.Kind & MemberKind.NestedMask) == 0)
+                                               continue;
+
+                                       if (found == null)
+                                               found = new List<TypeSpec> ();
+
+                                       found.Add ((TypeSpec)member);
+                               }
+                       }
+
+                       return found;
+               }
+
                //
                // Returns inflated version of MemberSpec, it works similarly to
                // SRE TypeBuilder.GetMethod
@@ -686,9 +710,10 @@ namespace Mono.CSharp {
                        throw new NotImplementedException (member.GetType ().ToString ());
                }
 
-               public static List<FieldSpec> GetAllFieldsForDefiniteAssignment (TypeSpec container)
+               public static List<FieldSpec> GetAllFieldsForDefiniteAssignment (TypeSpec container, IMemberContext context)
                {
                        List<FieldSpec> fields = null;
+                       bool imported = container.MemberDefinition.IsImported;
                        foreach (var entry in container.MemberCache.member_hash) {
                                foreach (var name_entry in entry.Value) {
                                        if (name_entry.Kind != MemberKind.Field)
@@ -704,13 +729,7 @@ namespace Mono.CSharp {
                                                continue;
 
                                        var fs = (FieldSpec) name_entry;
-
-                                       //
-                                       // LAMESPEC: Very bizzare hack, definitive assignment is not done
-                                       // for imported non-public reference fields except array. No idea what the
-                                       // actual csc rule is
-                                       //
-                                       if (!fs.IsPublic && container.MemberDefinition.IsImported && (!fs.MemberType.IsArray && TypeSpec.IsReferenceType (fs.MemberType)))
+                                       if (imported && ShouldIgnoreFieldForDefiniteAssignment (fs, context))
                                                continue;
 
                                        //if ((fs.Modifiers & (Modifiers.BACKING_FIELD) != 0)
@@ -727,6 +746,29 @@ namespace Mono.CSharp {
                        return fields ?? new List<FieldSpec> (0);
                }
 
+               static bool ShouldIgnoreFieldForDefiniteAssignment (FieldSpec fs, IMemberContext context)
+               {
+                       //
+                       // LAMESPEC: This mimics csc quirk where definitive assignment is not done
+                       // for all kinds of imported non-public struct fields
+                       //
+                       var mod = fs.Modifiers;
+                       if ((mod & Modifiers.PRIVATE) == 0 && ((mod & Modifiers.INTERNAL) != 0 && fs.DeclaringType.MemberDefinition.IsInternalAsPublic (context.Module.DeclaringAssembly)))
+                               return false;
+
+                       //
+                       // Ignore reference type fields except when type is an array or type parameter
+                       //
+                       var type = fs.MemberType;
+                       switch (type.Kind) {
+                       case MemberKind.ArrayType:
+                       case MemberKind.TypeParameter:
+                               return false;
+                       default:
+                               return TypeSpec.IsReferenceType (type);
+                       }
+               }
+
                public static IList<MemberSpec> GetCompletitionMembers (IMemberContext ctx, TypeSpec container, string name)
                {
                        var matches = new List<MemberSpec> ();
@@ -1298,7 +1340,7 @@ namespace Mono.CSharp {
                        if (a.DeclaringType.MemberDefinition != b.DeclaringType.MemberDefinition)
                                return mc_b;
 
-                       if (mc_a.Location.File != mc_a.Location.File)
+                       if (mc_a.Location.File != mc_b.Location.File)
                                return mc_b;
 
                        return mc_b.Location.Row > mc_a.Location.Row ? mc_b : mc_a;