+ }
+
+ public const TypeAttributes DefaultTypeAttributes =
+ TypeAttributes.AutoLayout |
+ TypeAttributes.Abstract |
+ TypeAttributes.Interface;
+
+ public override TypeAttributes TypeAttr {
+ get {
+ return base.TypeAttr | DefaultTypeAttributes;
+ }
+ }
+ }
+
+ public abstract class MethodCore : MemberBase {
+ public readonly Parameters Parameters;
+ public readonly GenericMethod GenericMethod;
+ public readonly DeclSpace ds;
+ protected Block block;
+
+ //
+ // Parameters, cached for semantic analysis.
+ //
+ protected InternalParameters parameter_info;
+ protected Type [] parameter_types;
+
+ // Whether this is an operator method.
+ public bool IsOperator;
+
+ //
+ // The method we're overriding if this is an override method.
+ //
+ protected MethodInfo parent_method = null;
+
+ static string[] attribute_targets = new string [] { "method", "return" };
+
+ public MethodCore (TypeContainer parent, GenericMethod generic,
+ Expression type, int mod, int allowed_mod, bool is_iface,
+ MemberName name, Attributes attrs, Parameters parameters,
+ Location loc)
+ : base (parent, type, mod, allowed_mod, Modifiers.PRIVATE, name,
+ attrs, loc)
+ {
+ Parameters = parameters;
+ IsInterface = is_iface;
+ this.GenericMethod = generic;
+
+ if (generic != null)
+ ds = generic;
+ else
+ ds = parent;
+ }
+
+ //
+ // Returns the System.Type array for the parameters of this method
+ //
+ public Type [] ParameterTypes {
+ get {
+ return parameter_types;
+ }
+ }
+
+ public InternalParameters ParameterInfo
+ {
+ get {
+ return parameter_info;
+ }
+ }
+
+ public Block Block {
+ get {
+ return block;
+ }
+
+ set {
+ block = value;
+ }
+ }
+
+ protected override bool CheckBase ()
+ {
+ if (!base.CheckBase ())
+ return false;
+
+ // Check whether arguments were correct.
+ if (!DoDefineParameters ())
+ return false;
+
+ if ((caching_flags & Flags.TestMethodDuplication) != 0 && !CheckForDuplications ())
+ return false;
+
+ if (IsExplicitImpl)
+ return true;
+
+ // Is null for System.Object while compiling corlib and base interfaces
+ if (Parent.ParentContainer == null) {
+ if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0)) {
+ Report.Warning (109, Location, "The member '{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError (Parent));
+ }
+ return true;
+ }
+
+ Type parent_ret_type = null;
+ parent_method = FindOutParentMethod (Parent, ref parent_ret_type);
+
+ // method is override
+ if (parent_method != null) {
+
+ if (!CheckMethodAgainstBase ())
+ return false;
+
+ if ((ModFlags & Modifiers.NEW) == 0) {
+ if (!MemberType.Equals (TypeManager.TypeToCoreType (parent_ret_type))) {
+ Report.SymbolRelatedToPreviousError (parent_method);
+ Report.Error (508, Location, GetSignatureForError (Parent) + ": cannot " +
+ "change return type when overriding inherited member");
+ return false;
+ }
+ }
+
+ if (RootContext.WarningLevel > 2) {
+ if (Name == "Equals" && parameter_types.Length == 1 && parameter_types [0] == TypeManager.object_type)
+ Parent.Methods.HasEquals = true;
+ else if (Name == "GetHashCode" && parameter_types.Length == 0)
+ Parent.Methods.HasGetHashCode = true;
+ }
+
+ ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (parent_method);
+ if (oa != null) {
+ EmitContext ec = new EmitContext (this.Parent, this.Parent, Location, null, null, ModFlags, false);
+ if (OptAttributes == null || !OptAttributes.Contains (TypeManager.obsolete_attribute_type, ec)) {
+ Report.SymbolRelatedToPreviousError (parent_method);
+ Report.Warning (672, 1, Location, "Member '{0}' overrides obsolete member. Add the Obsolete attribute to '{0}'", GetSignatureForError (Parent));
+ }
+ }
+ return true;
+ }
+
+ if ((ModFlags & Modifiers.OVERRIDE) != 0) {
+ Report.Error (115, Location, "'{0}': no suitable methods found to override", GetSignatureForError (Parent));
+ return false;
+ }
+
+ MemberInfo conflict_symbol = Parent.FindMemberWithSameName (Name, !(this is Property));
+ if (conflict_symbol == null) {
+ if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0)) {
+ Report.Warning (109, Location, "The member '{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError (Parent));
+ }
+ return true;
+ }
+
+ if ((ModFlags & Modifiers.NEW) == 0) {
+ if (this is Method && conflict_symbol is MethodBase)
+ return true;
+
+ Report.SymbolRelatedToPreviousError (conflict_symbol);
+ Report.Warning (108, Location, "The keyword new is required on '{0}' because it hides inherited member", GetSignatureForError (Parent));
+ }
+
+ return true;
+ }
+
+
+ //
+ // Performs various checks on the MethodInfo `mb' regarding the modifier flags
+ // that have been defined.
+ //
+ // `name' is the user visible name for reporting errors (this is used to
+ // provide the right name regarding method names and properties)
+ //
+ bool CheckMethodAgainstBase ()
+ {
+ bool ok = true;
+
+ // TODO: replace with GetSignatureForError
+ string name = parent_method.DeclaringType.Name + "." + parent_method.Name;
+
+ if ((ModFlags & Modifiers.OVERRIDE) != 0){
+ if (!(parent_method.IsAbstract || parent_method.IsVirtual)){
+ Report.Error (
+ 506, Location, Parent.MakeName (Name) +
+ ": cannot override inherited member `" +
+ name + "' because it is not " +
+ "virtual, abstract or override");
+ ok = false;
+ }
+
+ // Now we check that the overriden method is not final
+
+ if (parent_method.IsFinal) {
+ // This happens when implementing interface methods.
+ if (parent_method.IsHideBySig && parent_method.IsVirtual) {
+ Report.Error (
+ 506, Location, Parent.MakeName (Name) +
+ ": cannot override inherited member `" +
+ name + "' because it is not " +
+ "virtual, abstract or override");
+ } else
+ Report.Error (239, Location, Parent.MakeName (Name) + " : cannot " +
+ "override inherited member `" + name +
+ "' because it is sealed.");
+ ok = false;
+ }
+ //
+ // Check that the permissions are not being changed
+ //
+ MethodAttributes thisp = flags & MethodAttributes.MemberAccessMask;
+ MethodAttributes parentp = parent_method.Attributes & MethodAttributes.MemberAccessMask;
+
+ //
+ // special case for "protected internal"
+ //
+
+ if ((parentp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
+ //
+ // when overriding protected internal, the method can be declared
+ // protected internal only within the same assembly
+ //
+
+ if ((thisp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
+ if (Parent.TypeBuilder.Assembly != parent_method.DeclaringType.Assembly){
+ //
+ // assemblies differ - report an error
+ //
+
+ Error_CannotChangeAccessModifiers (Parent, parent_method, name);
+ ok = false;
+ } else if (thisp != parentp) {
+ //
+ // same assembly, but other attributes differ - report an error
+ //
+
+ Error_CannotChangeAccessModifiers (Parent, parent_method, name);
+ ok = false;
+ };
+ } else if ((thisp & MethodAttributes.Family) != MethodAttributes.Family) {
+ //
+ // if it's not "protected internal", it must be "protected"
+ //
+
+ Error_CannotChangeAccessModifiers (Parent, parent_method, name);
+ ok = false;
+ } else if (Parent.TypeBuilder.Assembly == parent_method.DeclaringType.Assembly) {
+ //
+ // protected within the same assembly - an error
+ //
+ Error_CannotChangeAccessModifiers (Parent, parent_method, name);
+ ok = false;
+ } else if ((thisp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem)) !=
+ (parentp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem))) {
+ //
+ // protected ok, but other attributes differ - report an error
+ //
+ Error_CannotChangeAccessModifiers (Parent, parent_method, name);
+ ok = false;
+ }
+ } else {
+ if (thisp != parentp){
+ Error_CannotChangeAccessModifiers (Parent, parent_method, name);
+ ok = false;
+ }
+ }
+ }