2005-05-03 Raja R Harinath <rharinath@novell.com>
+ * typemanager.cs (IsOverride, RegisterNonOverride): New.
+ * decl.cs (MemberCache.AddMethod): Register "non-override" methods
+ that used to trigger warning -28. Remove warning -28.
+ * expression.cs (Invocation.OverloadResolve): Use
+ TypeManager.IsOverride to distinguish override methods.
+
Fix #74773.
* pending.cs (VerifyPendingMethods): If a base type implements the
requested interface, don't bother checking individual methods of
void AddMethods (BindingFlags bf, Type type)
{
- //
- // 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);
MethodInfo base_method = curr.GetBaseDefinition ();
if (base_method == curr) {
- //
- // Both mcs and CSC 1.1 seem to emit a somewhat broken
- // ...Invoke () function for delegates: it's missing a 'newslot'.
- // CSC 2.0 emits a 'newslot' for a delegate's Invoke.
- //
- // Also, CSC 1.1 appears to emit 'Finalize' without a newslot.
- //
- if ((curr.Name == "Invoke" && TypeManager.IsDelegateType (curr.DeclaringType)) ||
- (curr.Name == "Finalize" && curr.GetParameters().Length == 0 && curr.DeclaringType == TypeManager.object_type))
- break;
-
- Report.SymbolRelatedToPreviousError (base_method);
- Report.Warning (-28,
- "The method '{0}' is marked 'override'," +
- " but doesn't appear to override any virtual or abstract method:" +
- " it may be ignored during overload resolution",
- TypeManager.CSharpSignature (base_method));
+ // Not every virtual function needs to have a NewSlot flag.
+ TypeManager.RegisterNonOverride (base_method);
break;
}
// We avoid doing the 'applicable' test here, since it'll anyway be applied
// to the base virtual function, and IsOverride is much faster than IsApplicable.
//
- if (!me.IsBase &&
- methods [i].IsVirtual &&
- (methods [i].Attributes & MethodAttributes.NewSlot) == 0) {
+ if (!me.IsBase && TypeManager.IsOverride (methods [i])) {
if (candidate_overrides == null)
candidate_overrides = new ArrayList ();
candidate_overrides.Add (methods [i]);
// If the method is a virtual function, pick an override closer to the LHS type.
//
if (!me.IsBase && method.IsVirtual) {
- if ((method.Attributes & MethodAttributes.NewSlot) != MethodAttributes.NewSlot)
+ if (TypeManager.IsOverride (method))
throw new InternalErrorException (
"Should not happen. An 'override' method took part in overload resolution: " + method);
-
+
if (candidate_overrides != null)
foreach (MethodBase candidate in candidate_overrides) {
if (IsOverride (candidate, method))
// <remarks>
static Hashtable method_params;
+ // <remarks>
+ // It is not straightforward, using reflection, to determine if a method overrides another.
+ // Oftentimes, a non-override is marked with both the 'virtual' and 'newslot' method attributes.
+ // However, it's not always the case. We use this table to store those non-override methods
+ // that aren't so conveniently marked.
+ // <remarks>
+ static Hashtable method_non_override;
+
// <remarks>
// Keeps track of methods
// </remarks>
builder_to_method = new PtrHashtable ();
method_arguments = new PtrHashtable ();
method_params = new PtrHashtable ();
+ method_non_override = new PtrHashtable ();
indexer_arguments = new PtrHashtable ();
builder_to_ifaces = new PtrHashtable ();
return (ParameterData) pd;
}
+ static public void RegisterNonOverride (MethodBase m)
+ {
+ method_non_override [m] = m;
+ }
+
+ static public bool IsOverride (MethodBase m)
+ {
+ return m.IsVirtual &&
+ (m.Attributes & MethodAttributes.NewSlot) == 0 &&
+ !method_non_override.Contains (m);
+ }
+
/// <summary>
/// Returns the argument types for a method based on its methodbase
///