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