[ilasm] Adds noautoinherit option
[mono.git] / mcs / ilasm / codegen / TypeDef.cs
index 2f62229b5d8ec98ef2350395bd4270dcecb404d1..f35dca0bd4a4216d1a8a9f7cdca45ec62799c43c 100644 (file)
 
 using System;
 using System.Collections;
+using System.Security;
 
 namespace Mono.ILASM {
 
-        public class TypeDef : ICustomAttrTarget {
-
-                protected class GenericInfo {
-                        public string Id;
-                        public ArrayList ConstraintList;
-                }
+        public class TypeDef : ICustomAttrTarget, IDeclSecurityTarget, IComparable {
 
                 private PEAPI.TypeAttr attr;
                 private string name_space;
                 private string name;
                 private bool is_defined;
                 private bool is_intransit;
-                private IClassRef parent;
+                private BaseClassRef parent;
                 private ArrayList impl_list;
                 private PEAPI.ClassDef classdef;
                 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;
                 private ArrayList property_list;
-                private ArrayList typar_list;
+                private GenericParameters gen_params;
                 private ArrayList override_list;
                 private ArrayList override_long_list;
                 private TypeDef outer;
@@ -48,19 +46,23 @@ 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,
-                                IClassRef parent, ArrayList impl_list, Location location)
+                                BaseClassRef parent, ArrayList impl_list, Location location, GenericParameters gen_params, TypeDef outer)
                 {
                         this.attr = attr;
-                        this.name_space = name_space;
-                        this.name = name;
                         this.parent = parent;
                         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;
@@ -70,8 +72,29 @@ namespace Mono.ILASM {
 
                         is_value_class = false;
                         is_enum_class = false;
+
+                        ResolveGenParams ();
+
+                        int lastdot = name.LastIndexOf ('.');
+                        /* Namespace . name split should not be done for nested classes */
+                        if (lastdot >= 0 && outer == null) {
+                                if (name_space == null || name_space == "")
+                                        this.name_space = name.Substring (0, lastdot);
+                                else
+                                        this.name_space = name_space + "." + name.Substring (0, lastdot);
+                                this.name = name.Substring (lastdot + 1);
+                        } else {
+                                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; }
                 }
@@ -80,9 +103,12 @@ namespace Mono.ILASM {
                         get { return MakeFullName (); }
                 }
 
+               public string NestedFullName {
+                       get { return (outer == null ? FullName : (outer.NestedFullName + "/" + FullName)); }
+               }
+
                 public TypeDef OuterType {
                         get { return outer; }
-                        set { outer = value; }
                 }
 
                 public PEAPI.ClassDef PeapiType {
@@ -94,7 +120,7 @@ namespace Mono.ILASM {
                 }
 
                 public bool IsGenericType {
-                        get { return (typar_list == null); }
+                        get { return (gen_params == null); }
                 }
 
                 public bool IsDefined {
@@ -113,7 +139,23 @@ namespace Mono.ILASM {
                         get { return (attr & PEAPI.TypeAttr.Interface) != 0; }
                 }
 
-                public void AddOverride (MethodDef body, ITypeRef parent, string name)
+                public bool IsAbstract {
+                        get { return (attr & PEAPI.TypeAttr.Abstract) != 0; }
+                }
+
+                public GenericParameters TypeParameters {
+                        get { return gen_params; }
+                }
+
+                public DeclSecurity DeclSecurity {
+                        get {
+                                if (decl_sec == null)
+                                        decl_sec = new DeclSecurity ();
+                                return decl_sec;
+                        }
+                }
+
+                public void AddOverride (MethodDef body, BaseTypeRef parent, string name)
                 {
                         if (override_list == null)
                                 override_list = new ArrayList ();
@@ -121,7 +163,7 @@ namespace Mono.ILASM {
                                            new DictionaryEntry (parent, name)));
                 }
 
-                public void AddOverride (string sig, IMethodRef decl)
+                public void AddOverride (string sig, BaseMethodRef decl)
                 {
                         if (override_long_list == null)
                                 override_long_list = new ArrayList ();
@@ -152,28 +194,35 @@ 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;
                         }
 
-                        field_table.Add (fielddef.Name, fielddef);
+                        DictionaryEntry entry = new DictionaryEntry (fielddef.Name, fielddef.Type.FullName);
+                        if (field_table [entry] != null)
+                                Report.Error ("Duplicate field declaration: " + fielddef.Type.FullName + " " + fielddef.Name);
+                        field_table.Add (entry, fielddef);
                         field_list.Add (fielddef);
                 }
 
                 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 (methoddef.StartLocation, "Duplicate method declaration: " + methoddef.Signature);
+
                         method_table.Add (methoddef.Signature, methoddef);
+                        method_list.Add (methoddef);
                 }
 
                 public void BeginEventDef (EventDef event_def)
                 {
                         if (current_event != null)
-                                throw new Exception ("An event definition was not closed.");
+                                Report.Error ("An event definition was not closed.");
 
                         current_event = event_def;
                 }
@@ -190,7 +239,7 @@ namespace Mono.ILASM {
                 public void BeginPropertyDef (PropertyDef property_def)
                 {
                         if (current_property != null)
-                                throw new Exception ("A property definition was not closed.");
+                                Report.Error ("A property definition was not closed.");
 
                         current_property = property_def;
                 }
@@ -212,24 +261,60 @@ namespace Mono.ILASM {
                         customattr_list.Add (customattr);
                 }
 
-                public void AddGenericParam (string id)
+                public GenericParameter GetGenericParam (string id)
+                {
+                        if (gen_params == null)
+                                return null;
+                        
+                        return gen_params.GetGenericParam (id);
+                }
+
+                public GenericParameter GetGenericParam (int index)
+                {
+                        if (gen_params == null || index < 0 || index >= gen_params.Count)
+                                return null;
+                        
+                        return gen_params [index];
+                }
+
+                public int GetGenericParamNum (string id)
                 {
-                        if (typar_list == null)
-                                typar_list = new ArrayList ();
+                        if (gen_params == null)
+                                return -1;
+                        
+                        return gen_params.GetGenericParamNum (id);
+                }
 
-                        GenericInfo gi = new GenericInfo ();
-                        gi.Id = id;
+                /* Resolve any GenParams in constraints, parent & impl_list */
+                private void ResolveGenParams ()
+                {
+                        if (gen_params == null)
+                                return;
+
+                        gen_params.ResolveConstraints (gen_params, null);
 
-                        typar_list.Add (gi);
+                        BaseGenericTypeRef gtr = parent as BaseGenericTypeRef;
+                        if (gtr != null)
+                                gtr.Resolve (gen_params, null);
+                        
+                        if (impl_list == null)
+                                return;
+                                
+                        foreach (BaseClassRef impl in impl_list) {
+                                gtr = impl as BaseGenericTypeRef;
+                                if (gtr != null)
+                                        gtr.Resolve (gen_params, null);
+                        }
                 }
 
-                public void AddGenericConstraint (int index, ITypeRef constraint)
+                private bool IsValueType (string ns, string name)
                 {
-                        GenericInfo gi = (GenericInfo) typar_list[index];
+                        return (ns == "System" && name == "ValueType");
+                }
 
-                        if (gi.ConstraintList == null)
-                                gi.ConstraintList = new ArrayList ();
-                        gi.ConstraintList.Add (constraint);
+                private bool IsEnumType (string ns, string name)
+                {
+                        return (ns == "System" && name == "Enum");
                 }
 
                 public void Define (CodeGen code_gen)
@@ -239,27 +324,42 @@ namespace Mono.ILASM {
 
                         if (is_intransit) {
                                 // Circular definition
-                                throw new Exception ("Circular definition of class: " + FullName);
+                                Report.Error ("Circular definition of class: " + FullName);
                         }
 
+                        if (outer != null) {
+                               PEAPI.TypeAttr vis = attr & PEAPI.TypeAttr.VisibilityMask;
+
+                               if (vis == PEAPI.TypeAttr.Private || vis == PEAPI.TypeAttr.Public) {
+                                       /* Nested class, but attr not set accordingly. */
+                                       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);
+                               }               
+                        }
+                        
                         if (parent != null) {
                                 is_intransit = true;
                                 parent.Resolve (code_gen);
+
                                 is_intransit = false;
                                 if (parent.PeapiClass == null) {
-                                        throw new Exception ("this type can not be a base type: "
+                                        Report.Error ("this type can not be a base type: "
                                                         + 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 (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;
+                                }
 
                                 if (outer != null) {
                                         if (!outer.IsDefined)
@@ -291,35 +391,26 @@ namespace Mono.ILASM {
                                                         name_space, name);
                                         }
                                 }
-                                if (FullName == "System.Object")
+                                if (FullName == "System.Object" || NoAutoInherit)
                                         classdef.SpecialNoSuper ();
                         }
 
-                        if (size != -1)
-                                classdef.AddLayoutInfo (pack, size);
+                        is_defined = true;
+
+                        if (size != -1 || pack != -1)
+                                classdef.AddLayoutInfo ( (pack == -1) ? 1 : pack, (size == -1) ? 0 : size);
 
                         if (impl_list != null) {
-                                foreach (IClassRef impl in impl_list) {
+                                foreach (BaseClassRef impl in impl_list) {
                                         impl.Resolve (code_gen);
                                         classdef.AddImplementedInterface (impl.PeapiClass);
                                 }
                         }
 
-                        if (typar_list != null) {
-                                short index = 0;
-                                foreach (GenericInfo gi in typar_list) {
-                                        PEAPI.GenericParameter gp = classdef.AddGenericParameter (index++, gi.Id);
-                                        if (gi.ConstraintList != null) {
-                                                foreach (ITypeRef cnst in gi.ConstraintList) {
-                                                        cnst.Resolve (code_gen);
-                                                        gp.AddConstraint (cnst.PeapiType);
-                                                }
-                                        }
-                                }
-                        }
+                        if (gen_params != null)
+                                gen_params.Resolve (code_gen, classdef);
 
                         is_intransit = false;
-                        is_defined = true;
 
                         code_gen.AddToDefineContentsList (this);
                 }
@@ -328,14 +419,18 @@ 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) {
-                                methoddef.Define (code_gen, this);
+                        foreach (MethodDef methoddef in method_list) {
+                                methoddef.Define (code_gen);
                         }
 
                         if (event_list != null) {
@@ -352,19 +447,28 @@ namespace Mono.ILASM {
                         }
 
                         if (customattr_list != null) {
-                                foreach (CustomAttr customattr in customattr_list)
+                                foreach (CustomAttr customattr in customattr_list) {
                                         customattr.AddTo (code_gen, classdef);
+                                        if (customattr.IsSuppressUnmanaged (code_gen))
+                                                classdef.AddAttribute (PEAPI.TypeAttr.HasSecurity);
+                               }
                         }
+                        
+                        /// Add declarative security to this class
+                        if (decl_sec != null) {
+                                decl_sec.AddTo (code_gen, classdef);
+                                classdef.AddAttribute (PEAPI.TypeAttr.HasSecurity);
+                       }       
 
                         if (override_list != null) {
                                 foreach (DictionaryEntry entry in override_list) {
                                         MethodDef body = (MethodDef) entry.Key;
                                         DictionaryEntry decl = (DictionaryEntry) entry.Value;
-                                        ITypeRef parent_type = (ITypeRef) decl.Key;
+                                        BaseTypeRef parent_type = (BaseTypeRef) decl.Key;
                                         parent_type.Resolve (code_gen);
                                         string over_name = (string) decl.Value;
-                                        IMethodRef over_meth = parent_type.GetMethodRef (body.RetType,
-                                                        body.CallConv, over_name, body.ParamTypeList ());
+                                        BaseMethodRef over_meth = parent_type.GetMethodRef (body.RetType,
+                                                        body.CallConv, over_name, body.ParamTypeList (), body.GenParamCount);
                                         over_meth.Resolve (code_gen);
                                         classdef.AddMethodOverride (over_meth.PeapiMethod,
                                                         body.PeapiMethodDef);
@@ -374,7 +478,7 @@ namespace Mono.ILASM {
                         if (override_long_list != null) {
                                 foreach (DictionaryEntry entry in override_long_list) {
                                         string sig = (string) entry.Key;
-                                        IMethodRef decl = (IMethodRef) entry.Value;
+                                        BaseMethodRef decl = (BaseMethodRef) entry.Value;
                                         MethodDef body = (MethodDef) method_table[sig];
                                         decl.Resolve (code_gen);
                                         classdef.AddMethodOverride (decl.PeapiMethod,
@@ -383,37 +487,54 @@ namespace Mono.ILASM {
                         }
                 }
 
-                public PEAPI.MethodDef ResolveMethod (string signature, CodeGen code_gen)
+                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, call_conv, name, param, gen_param_count, false);
                         MethodDef methoddef = (MethodDef) method_table[signature];
 
-                        if (methoddef == null) {
-                                code_gen.Report.Error ("Unable to resolve method: " + signature);
-                                Environment.Exit (1);
-                        }
-
-                        return methoddef.Resolve (code_gen, classdef);
+                        if (methoddef != null)
+                                return methoddef.Resolve (code_gen, classdef);
+                        return ResolveAsMethodRef (ret_type, call_conv, name, param, gen_param_count, code_gen);
                 }
 
-                public PEAPI.Method ResolveVarargMethod (string signature,
-                                CodeGen code_gen, PEAPI.Type[] opt)
+                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)
                 {
+                        // 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) {
-                                code_gen.Report.Error ("Unable to resolve method: " + signature);
-                                Environment.Exit (1);
+                        if (methoddef != null) {
+                                methoddef.Resolve (code_gen, classdef);
+                                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);
+                }
 
-                        methoddef.Resolve (code_gen, classdef);
-                        return methoddef.GetVarargSig (opt);
+                private PEAPI.Method ResolveAsMethodRef (BaseTypeRef ret_type, PEAPI.CallConv call_conv,
+                        string name, BaseTypeRef [] param, int gen_param_count, CodeGen code_gen)
+                {
+                        ExternTypeRef type_ref = code_gen.ThisModule.GetTypeRef (FullName, false);
+                        ExternMethodRef methodref = (ExternMethodRef) type_ref.GetMethodRef (ret_type, call_conv, name, param, gen_param_count);
+                        methodref.Resolve (code_gen);
+
+                        return methodref.PeapiMethod;
                 }
 
-                public PEAPI.Field ResolveField (string name, CodeGen code_gen)
+                public PEAPI.Field ResolveField (string name, BaseTypeRef ret_type, CodeGen code_gen)
                 {
-                        FieldDef fielddef = (FieldDef) field_table[name];
+                        FieldDef fielddef = (FieldDef) field_table[new DictionaryEntry (name, ret_type.FullName)];
+                        if (fielddef !=null)
+                                return fielddef.Resolve (code_gen, classdef);
 
-                        return fielddef.Resolve (code_gen, classdef);
+                        ExternTypeRef type_ref = code_gen.ThisModule.GetTypeRef (FullName, false);
+                        IFieldRef fieldref = type_ref.GetFieldRef (ret_type, name);
+                        fieldref.Resolve (code_gen);
+
+                        return fieldref.PeapiField;
                 }
 
                 private string MakeFullName ()
@@ -423,6 +544,13 @@ namespace Mono.ILASM {
 
                         return name_space + "." + name;
                 }
+
+                public int CompareTo (object obj)
+                {
+                        TypeDef type_def = (TypeDef) obj; 
+
+                        return FullName.CompareTo (type_def.FullName);
+                }
         }
 
 }