[ilasm] Adds noautoinherit option
[mono.git] / mcs / ilasm / codegen / TypeDef.cs
index b391f838bdcc03c9c03dc919d7c9debfe82bcb42..f35dca0bd4a4216d1a8a9f7cdca45ec62799c43c 100644 (file)
@@ -27,6 +27,7 @@ namespace Mono.ILASM {
                 private Hashtable field_table;
                 private ArrayList field_list;
                 private Hashtable method_table;
+                private ArrayList method_list;
                 private ArrayList customattr_list;
                 private DeclSecurity decl_sec;
                 private ArrayList event_list;
@@ -45,6 +46,8 @@ namespace Mono.ILASM {
                 private bool is_value_class;
                 private bool is_enum_class;
 
+                private Location location;
+
                 public TypeDef (PEAPI.TypeAttr attr, string name_space, string name,
                                 BaseClassRef parent, ArrayList impl_list, Location location, GenericParameters gen_params, TypeDef outer)
                 {
@@ -53,11 +56,13 @@ namespace Mono.ILASM {
                         this.impl_list = impl_list;
                         this.gen_params = gen_params;
                         this.outer = outer;
+                        this.location = location;
 
                         field_table = new Hashtable ();
                         field_list = new ArrayList ();
 
                         method_table = new Hashtable ();
+                        method_list = new ArrayList ();
 
                         size = -1;
                         pack = -1;
@@ -82,8 +87,14 @@ namespace Mono.ILASM {
                                 this.name_space = name_space;
                                 this.name = name;
                         }
+
+                        //Fixup attributes
+                        if (IsInterface)
+                                this.attr |= PEAPI.TypeAttr.Abstract;
                 }
 
+                               public bool NoAutoInherit { get; set; }
+
                 public string Name {
                         get { return name; }
                 }
@@ -128,6 +139,10 @@ namespace Mono.ILASM {
                         get { return (attr & PEAPI.TypeAttr.Interface) != 0; }
                 }
 
+                public bool IsAbstract {
+                        get { return (attr & PEAPI.TypeAttr.Abstract) != 0; }
+                }
+
                 public GenericParameters TypeParameters {
                         get { return gen_params; }
                 }
@@ -179,7 +194,7 @@ namespace Mono.ILASM {
                 public void AddFieldDef (FieldDef fielddef)
                 {
                         if (IsInterface && !fielddef.IsStatic) {
-                                Console.WriteLine ("warning -- Non-static field in interface, set to such");
+                                Report.Warning ("Non-static field in interface, set to such");
                                 fielddef.Attributes |= PEAPI.FieldAttr.Static;
                         }
 
@@ -192,15 +207,16 @@ namespace Mono.ILASM {
 
                 public void AddMethodDef (MethodDef methoddef)
                 {
-                        if (IsInterface && !(methoddef.IsVirtual || methoddef.IsAbstract)) {
-                                Console.WriteLine ("warning -- Non-virtual, non-abstract instance method in interface, set to such");
+                        if (IsInterface && !methoddef.IsStatic && (!methoddef.IsVirtual || !methoddef.IsAbstract)) {
+                                Report.Warning (methoddef.StartLocation, "Non-virtual or non-abstract instance method in interface, set to such");
                                 methoddef.Attributes |= PEAPI.MethAttr.Abstract | PEAPI.MethAttr.Virtual;
                         }
 
                         if (method_table [methoddef.Signature] != null)
-                                Report.Error ("Duplicate method declaration: " + methoddef.Signature);
+                                Report.Error (methoddef.StartLocation, "Duplicate method declaration: " + methoddef.Signature);
 
                         method_table.Add (methoddef.Signature, methoddef);
+                        method_list.Add (methoddef);
                 }
 
                 public void BeginEventDef (EventDef event_def)
@@ -291,6 +307,16 @@ namespace Mono.ILASM {
                         }
                 }
 
+                private bool IsValueType (string ns, string name)
+                {
+                        return (ns == "System" && name == "ValueType");
+                }
+
+                private bool IsEnumType (string ns, string name)
+                {
+                        return (ns == "System" && name == "Enum");
+                }
+
                 public void Define (CodeGen code_gen)
                 {
                         if (is_defined)
@@ -306,8 +332,7 @@ namespace Mono.ILASM {
 
                                if (vis == PEAPI.TypeAttr.Private || vis == PEAPI.TypeAttr.Public) {
                                        /* Nested class, but attr not set accordingly. */
-                                       //FIXME: 'report' warning here
-                                       Console.WriteLine ("Warning -- Nested class '{0}' has non-nested visibility, set to such.", NestedFullName);
+                                       Report.Warning (location, String.Format ("Nested class '{0}' has non-nested visibility, set to such.", NestedFullName));
                                        attr = attr ^ vis;
                                        attr |= (vis == PEAPI.TypeAttr.Public ? PEAPI.TypeAttr.NestedPublic : PEAPI.TypeAttr.NestedPrivate);
                                }               
@@ -323,18 +348,16 @@ namespace Mono.ILASM {
                                                         + parent);
                                 }
 
-                                if (parent.PeapiClass.nameSpace != null && 
-                                        parent.PeapiClass.nameSpace.CompareTo ("System") == 0) {
-                                        
-                                        if (parent.PeapiClass.name.CompareTo ("ValueType") == 0)
-                                                is_value_class = true;
-                                        else
-                                        if (parent.PeapiClass.name.CompareTo ("Enum") == 0 )
-                                                is_enum_class = true;          
-                                } 
-
-                                if (is_value_class && (attr & PEAPI.TypeAttr.Sealed) == 0) {
-                                        Console.WriteLine ("Warning -- Non-sealed value class, made sealed.");
+                                if (IsValueType (parent.PeapiClass.nameSpace, parent.PeapiClass.name))
+                                        is_value_class = true;
+                                else if (IsEnumType (parent.PeapiClass.nameSpace, parent.PeapiClass.name)) {
+                                        is_enum_class = true;
+                                        is_value_class = false;
+                                }
+
+                                if (!IsValueType (name_space, name) && !IsEnumType (name_space, name) &&
+                                        is_value_class && (attr & PEAPI.TypeAttr.Sealed) == 0) {
+
                                         attr |= PEAPI.TypeAttr.Sealed;
                                 }
 
@@ -368,7 +391,7 @@ namespace Mono.ILASM {
                                                         name_space, name);
                                         }
                                 }
-                                if (FullName == "System.Object")
+                                if (FullName == "System.Object" || NoAutoInherit)
                                         classdef.SpecialNoSuper ();
                         }
 
@@ -396,13 +419,17 @@ namespace Mono.ILASM {
                 {
                         ArrayList fielddef_list = new ArrayList ();
                         foreach (FieldDef fielddef in field_list) {
+                                if (is_enum_class && fielddef.Name == "value__") {
+                                    fielddef.Attributes |= PEAPI.FieldAttr.SpecialName | PEAPI.FieldAttr.RTSpecialName;
+                                }
+
                                 fielddef.Define (code_gen, classdef);
                                 fielddef_list.Add (fielddef.PeapiFieldDef);
                         }
 
                         classdef.SetFieldOrder (fielddef_list);
 
-                        foreach (MethodDef methoddef in method_table.Values) {
+                        foreach (MethodDef methoddef in method_list) {
                                 methoddef.Define (code_gen);
                         }
 
@@ -463,7 +490,7 @@ namespace Mono.ILASM {
                 public PEAPI.Method ResolveMethod (BaseTypeRef ret_type, PEAPI.CallConv call_conv,
                         string name, BaseTypeRef [] param, int gen_param_count, CodeGen code_gen)
                 {
-                        string signature = MethodDef.CreateSignature (ret_type, name, param, gen_param_count);
+                        string signature = MethodDef.CreateSignature (ret_type, call_conv, name, param, gen_param_count, false);
                         MethodDef methoddef = (MethodDef) method_table[signature];
 
                         if (methoddef != null)
@@ -474,12 +501,14 @@ namespace Mono.ILASM {
                 public PEAPI.Method ResolveVarargMethod (BaseTypeRef ret_type, PEAPI.CallConv call_conv,
                         string name, BaseTypeRef [] param, int gen_param_count, PEAPI.Type [] opt, CodeGen code_gen)
                 {
-                        string signature = MethodDef.CreateVarargSignature (ret_type, name, param);
+                        // Only MethodDef sig required to lookup in the method_table
+                        string signature = MethodDef.CreateSignature (ret_type, call_conv, name, param, 0, false);
                         MethodDef methoddef = (MethodDef) method_table[signature];
-
                         if (methoddef != null) {
                                 methoddef.Resolve (code_gen, classdef);
-                                return methoddef.GetVarargSig (opt);
+                                return methoddef.GetVarargSig (
+                                                opt,
+                                                MethodDef.CreateSignature (ret_type, call_conv, name, param, 0, true));
                         }
                         
                         return ResolveAsMethodRef (ret_type, call_conv, name, param, gen_param_count, code_gen);