Author: martin
Date: 2005-03-22 04:58:37 -0500 (Tue, 22 Mar 2005)
New Revision: 42075

Modified:
   trunk/mcs/gmcs/ChangeLog
   trunk/mcs/gmcs/decl.cs
   trunk/mcs/gmcs/driver.cs
   trunk/mcs/gmcs/expression.cs
Log:
**** Merged r40402-r40410 from MCS ****


Modified: trunk/mcs/gmcs/ChangeLog
===================================================================
--- trunk/mcs/gmcs/ChangeLog    2005-03-22 09:54:25 UTC (rev 42074)
+++ trunk/mcs/gmcs/ChangeLog    2005-03-22 09:58:37 UTC (rev 42075)
@@ -1,3 +1,25 @@
+2005-02-10  Raja R Harinath  <[EMAIL PROTECTED]>
+
+       Fix #52586, cs0121-4.cs.
+       * decl.cs (MemberCache.DeepCopy): Rename from SetupCache.  Take
+       and return a hashtable.
+       (MemberCache.ClearDeclaredOnly): New.
+       (MemberCache.MemberCache): Update to change.  Make a deep copy of
+       the method_hash of a base type too.
+       (MemberCache.AddMethods): Adapt to having a deep copy of the base
+       type methods.  Overwrite entries with the same MethodHandle so
+       that the ReflectedType is correct.  The process leaves in base
+       virtual functions and their overrides as distinct entries.
+       (CacheEntry): Now a class instead of a struct.  It shouldn't alter
+       matters since it was boxed in a ArrayList before.
+       (CacheEntry.Member, CacheEntry.EntryType): Remove 'readonly'
+       modifier.
+       * expression.cs (Invocation.BetterFunction): Simplify.  Handle the
+       case of a virtual function and its override (choose the overload
+       as better).
+       (Invocation.OverloadResolve): Avoid 'override' members during
+       'applicable_type' calculation.
+
 2005-02-09  Raja R Harinath  <[EMAIL PROTECTED]>
 
        Combine two near-redundant caches.

Modified: trunk/mcs/gmcs/decl.cs
===================================================================
--- trunk/mcs/gmcs/decl.cs      2005-03-22 09:54:25 UTC (rev 42074)
+++ trunk/mcs/gmcs/decl.cs      2005-03-22 09:58:37 UTC (rev 42075)
@@ -1763,7 +1763,7 @@
                        // If we have a base class (we have a base class unless 
we're
                        // TypeManager.object_type), we deep-copy its 
MemberCache here.
                        if (Container.BaseCache != null)
-                               member_hash = SetupCache (Container.BaseCache);
+                               member_hash = DeepCopy 
(Container.BaseCache.member_hash);
                        else
                                member_hash = new Hashtable ();
 
@@ -1771,7 +1771,12 @@
                        // method cache with all declared and inherited methods.
                        Type type = container.Type;
                        if (!(type is TypeBuilder) && !type.IsInterface && 
!type.IsGenericParameter) {
-                               method_hash = new Hashtable ();
+                               if (Container.BaseCache != null) {
+                                       method_hash = DeepCopy 
(Container.BaseCache.method_hash);
+                                       ClearDeclaredOnly (method_hash);
+                               }
+                               else
+                                       method_hash = new Hashtable ();
                                AddMethods (type);
                        }
 
@@ -1798,16 +1803,16 @@
                }
 
                /// <summary>
-               ///   Bootstrap this member cache by doing a deep-copy of our 
base.
+               ///   Return a a deep-copy of the hashtable @other.
                /// </summary>
-               Hashtable SetupCache (MemberCache base_class)
+               Hashtable DeepCopy (Hashtable other)
                {
                        Hashtable hash = new Hashtable ();
 
-                       if (base_class == null)
+                       if (other == null)
                                return hash;
 
-                       IDictionaryEnumerator it = 
base_class.member_hash.GetEnumerator ();
+                       IDictionaryEnumerator it = other.GetEnumerator ();
                        while (it.MoveNext ()) {
                                hash [it.Key] = ((ArrayList) it.Value).Clone ();
                         }
@@ -1815,6 +1820,15 @@
                        return hash;
                }
 
+               void ClearDeclaredOnly (Hashtable hash)
+               {
+                       IDictionaryEnumerator it = hash.GetEnumerator ();
+                       while (it.MoveNext ()) {
+                               foreach (CacheEntry ce in (ArrayList) it.Value)
+                                       ce.EntryType &= ~EntryType.Declared;
+                       }
+               }
+
                /// <summary>
                ///   Add the contents of `cache' to the member_hash.
                /// </summary>
@@ -1913,7 +1927,16 @@
 
                void AddMethods (BindingFlags bf, Type type)
                {
-                       MemberInfo [] members = type.GetMethods (bf);
+                       //
+                       // Consider the case:
+                       //
+                       //   class X { public virtual int f() {} }
+                       //   class Y : X {}
+                       // 
+                       // When processing 'Y', the method_cache will already 
have a copy of 'f', 
+                       // with ReflectedType == X.  However, we want to ensure 
that its ReflectedType == Y
+                       // 
+                       MethodBase [] members = type.GetMethods (bf);
 
                        Array.Reverse (members);
 
@@ -1927,13 +1950,26 @@
                                        method_hash.Add (name, list);
                                }
 
-                               // Unfortunately, the elements returned by 
Type.GetMethods() aren't
-                               // sorted so we need to do this check for every 
member.
-                               BindingFlags new_bf = bf;
-                               if (member.DeclaringType == type)
-                                       new_bf |= BindingFlags.DeclaredOnly;
+                               Type declaring_type = member.DeclaringType;
+                               if (declaring_type == type) {
+                                       list.Add (new CacheEntry (Container, 
member, MemberTypes.Method, bf | BindingFlags.DeclaredOnly));
+                                       continue;
+                               }
 
-                               list.Add (new CacheEntry (Container, member, 
MemberTypes.Method, new_bf));
+                               int n = list.Count;
+                               while (n-- > 0) {
+                                       CacheEntry entry = (CacheEntry) list 
[n];
+                                       MethodBase old = entry.Member as 
MethodBase;
+
+                                       if (member.MethodHandle.Value == 
old.MethodHandle.Value && 
+                                           declaring_type == 
old.DeclaringType) {
+                                               entry.Member = member;
+                                               break;
+                                       }
+                               }
+
+                               if (n < 0)
+                                       throw new InternalErrorException 
("cannot find inherited member " + member + " in base classes of " + type);
                        }
                }
 
@@ -2022,10 +2058,10 @@
                        MaskType        = 
Constructor|Event|Field|Method|Property|NestedType
                }
 
-               protected struct CacheEntry {
+               protected class CacheEntry {
                        public readonly IMemberContainer Container;
-                       public readonly EntryType EntryType;
-                       public readonly MemberInfo Member;
+                       public EntryType EntryType;
+                       public MemberInfo Member;
 
                        public CacheEntry (IMemberContainer container, 
MemberInfo member,
                                           MemberTypes mt, BindingFlags bf)

Modified: trunk/mcs/gmcs/driver.cs
===================================================================
--- trunk/mcs/gmcs/driver.cs    2005-03-22 09:54:25 UTC (rev 42074)
+++ trunk/mcs/gmcs/driver.cs    2005-03-22 09:58:37 UTC (rev 42075)
@@ -255,7 +255,7 @@
                                "For more information on Mono, visit the 
project Web site\n" +
                                "   http://www.go-mono.com\n\n"; +
 
-                               "The compiler was written by Miguel de Icaza, 
Ravi Pratap, Martin Baulig and Marek Safar");
+                               "The compiler was written by Miguel de Icaza, 
Ravi Pratap, Martin Baulig, Marek Safar, Raja R Harinath");
                        Environment.Exit (0);
                }
 

Modified: trunk/mcs/gmcs/expression.cs
===================================================================
--- trunk/mcs/gmcs/expression.cs        2005-03-22 09:54:25 UTC (rev 42074)
+++ trunk/mcs/gmcs/expression.cs        2005-03-22 09:58:37 UTC (rev 42075)
@@ -4454,40 +4454,8 @@
                        ParameterData candidate_pd = 
TypeManager.GetParameterData (candidate);
                        ParameterData best_pd = TypeManager.GetParameterData 
(best);
                
-                       int cand_count = candidate_pd.Count;
-
-                       //
-                       // If there is no best method, than this one
-                       // is better, however, if we already found a
-                       // best method, we cant tell. This happens
-                       // if we have:
-                       // 
-                       //      interface IFoo {
-                       //              void DoIt ();
-                       //      }
-                       //      
-                       //      interface IBar {
-                       //              void DoIt ();
-                       //      }
-                       //      
-                       //      interface IFooBar : IFoo, IBar {}
-                       //
-                       // We cant tell if IFoo.DoIt is better than IBar.DoIt
-                       //
-                       // However, we have to consider that
-                       // Trim (); is better than Trim (params char[] chars);
-                        //
-                       if (cand_count == 0 && argument_count == 0)
-                               return !candidate_params && best_params;
-
-                       if ((candidate_pd.ParameterModifier (cand_count - 1) != 
Parameter.Modifier.PARAMS) &&
-                           (candidate_pd.ParameterModifier (cand_count - 1) != 
Parameter.Modifier.ARGLIST))
-                               if (cand_count != argument_count)
-                                       return false;
-
                        bool better_at_least_one = false;
-                       bool is_equal = true;
-
+                       bool same = true;
                        for (int j = 0; j < argument_count; ++j) {
                                Argument a = (Argument) args [j];
 
@@ -4502,9 +4470,10 @@
                                        if (best_params)
                                                bt = TypeManager.GetElementType 
(bt);
 
-                               if (!ct.Equals (bt))
-                                       is_equal = false;
+                               if (ct.Equals (bt))
+                                       continue;
 
+                               same = false;
                                Type better = BetterConversion (ec, a, ct, bt, 
loc);
                                // for each argument, the conversion to 'ct' 
should be no worse than 
                                // the conversion to 'bt'.
@@ -4517,28 +4486,48 @@
                                        better_at_least_one = true;
                        }
 
-                        //
-                        // If a method (in the normal form) with the
-                        // same signature as the expanded form of the
-                        // current best params method already exists,
-                        // the expanded form is not applicable so we
-                        // force it to select the candidate
-                        //
-                        if (!candidate_params && best_params && cand_count == 
argument_count)
-                                return true;
+                       if (better_at_least_one)
+                               return true;
 
+                       if (!same)
+                               return false;
+
                        //
                        // If two methods have equal parameter types, but
                        // only one of them is generic, the non-generic one 
wins.
                        //
-                       if (is_equal) {
-                               if (TypeManager.IsGenericMethod (best) && 
!TypeManager.IsGenericMethod (candidate))
-                                       return true;
-                               else if (!TypeManager.IsGenericMethod (best) && 
TypeManager.IsGenericMethod (candidate))
-                                       return false;
+                       if (TypeManager.IsGenericMethod (best) && 
!TypeManager.IsGenericMethod (candidate))
+                               return true;
+                       else if (!TypeManager.IsGenericMethod (best) && 
TypeManager.IsGenericMethod (candidate))
+                               return false;
+
+                       //
+                       // Note that this is not just an optimization.  This 
handles the case
+                       //
+                       //   Add (float f1, float f2, float f3);
+                       //   Add (params decimal [] foo);
+                       //
+                       // The call Add (3, 4, 5) should be ambiguous.  Without 
this check, the
+                       // first candidate would've chosen as better.
+                       //
+                       if (candidate_params == best_params) {
+                               //
+                               // We need to handle the case of a virtual 
function and its override.
+                               // The override is ignored during 
'applicable_type' calculation.  However,
+                               // it should be chosen over the base virtual 
function, especially when handling
+                               // value types.
+                               //
+                               return IsAncestralType (best.DeclaringType, 
candidate.DeclaringType);
                        }
 
-                       return better_at_least_one;
+                       //
+                       // This handles the following cases:
+                       //
+                       //   Trim () is better than Trim (params char[] chars)
+                       //   Concat (string s1, string s2, string s3) is better 
than
+                       //     Concat (string s1, params string [] srest)
+                       //
+                        return !candidate_params && best_params;
                }
 
                public static string FullMethodDesc (MethodBase mb)
@@ -4881,6 +4870,15 @@
 
                                candidates.Add (methods [i]);
 
+                               //
+                               // Methods marked 'override' don't take part in 
'applicable_type'
+                               // computation.
+                               //
+                               if (!me.IsBase &&
+                                   methods [i].IsVirtual &&
+                                   (methods [i].Attributes & 
MethodAttributes.NewSlot) == 0)
+                                       continue;
+
                                if (applicable_type == null)
                                        applicable_type = decl_type;
                                else if (applicable_type != decl_type) {
@@ -4892,7 +4890,7 @@
 
                        int candidate_top = candidates.Count;
 
-                       if (candidate_top == 0) {
+                       if (applicable_type == null) {
                                //
                                // Okay so we have failed to find anything so we
                                // return by providing info about the closest 
match
@@ -4965,11 +4963,12 @@
                                        int j = finalized; // where to put the 
next finalized candidate
                                        int k = finalized; // where to put the 
next undiscarded candidate
                                        for (int i = finalized; i < 
candidate_top; ++i) {
-                                               Type decl_type = ((MethodBase) 
candidates[i]).DeclaringType;
+                                               MethodBase candidate = 
(MethodBase) candidates [i];
+                                               Type decl_type = 
candidate.DeclaringType;
 
                                                if (decl_type == 
applicable_type) {
-                                                       candidates[k++] = 
candidates[j];
-                                                       candidates[j++] = 
candidates[i];
+                                                       candidates [k++] = 
candidates [j];
+                                                       candidates [j++] = 
candidates [i];
                                                        continue;
                                                }
 
@@ -4980,8 +4979,19 @@
                                                    IsAncestralType (decl_type, 
next_applicable_type))
                                                        continue;
 
-                                               candidates[k++] = candidates[i];
+                                               candidates [k++] = candidates 
[i];
 
+#if false
+                                               //
+                                               // Methods marked 'override' 
don't take part in 'applicable_type'
+                                               // computation.
+                                               //
+                                               if (!me.IsBase &&
+                                                   candidate.IsVirtual &&
+                                                   (candidate.Attributes & 
MethodAttributes.NewSlot) == 0)
+                                                       continue;
+#endif
+
                                                if (next_applicable_type == 
null ||
                                                    IsAncestralType 
(next_applicable_type, decl_type))
                                                        next_applicable_type = 
decl_type;
@@ -4997,10 +5007,14 @@
                         // Now we actually find the best method
                         //
 
-                       method = (MethodBase) candidates[0];
+                       method = (MethodBase) candidates [0];
                        method_params = candidate_to_form != null && 
candidate_to_form.Contains (method);
                        for (int ix = 1; ix < candidate_top; ix++){
                                MethodBase candidate = (MethodBase) candidates 
[ix];
+
+                               if (candidate == method)
+                                       continue;
+
                                bool cand_params = candidate_to_form != null && 
candidate_to_form.Contains (candidate);
 
                                if (BetterFunction (ec, Arguments, arg_count, 

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to