Rework gc descriptor to include size information in more cases.
[mono.git] / mcs / mcs / import.cs
index 12cd52fc680a5dd1a3dde6311fa5e56aca43fb8c..7a3081c7cbbf8d660c279480fcf9446993c0a097 100644 (file)
@@ -5,7 +5,8 @@
 //
 // Dual licensed under the terms of the MIT X11 or GNU GPL
 //
-// Copyright 2009, 2010 Novell, Inc
+// Copyright 2009-2011 Novell, Inc
+// Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
 //
 
 using System;
@@ -87,10 +88,9 @@ namespace Mono.CSharp
                                }
 
                                if (cad.Count > 0) {
-                                       string ns, name;
                                        foreach (var ca in cad) {
-                                               importer.GetCustomAttributeTypeName (ca, out ns, out name);
-                                               if (name != "DynamicAttribute" && ns != CompilerServicesNamespace)
+                                               var dt = ca.Constructor.DeclaringType;
+                                               if (dt.Name != "DynamicAttribute" && dt.Namespace != CompilerServicesNamespace)
                                                        continue;
 
                                                if (ca.ConstructorArguments.Count == 0) {
@@ -149,7 +149,6 @@ namespace Mono.CSharp
                public abstract void AddCompiledType (TypeBuilder builder, TypeSpec spec);
                protected abstract MemberKind DetermineKindFromBaseType (MetaType baseType);
                protected abstract bool HasVolatileModifier (MetaType[] modifiers);
-               public abstract void GetCustomAttributeTypeName (CustomAttributeData cad, out string typeNamespace, out string typeName);
 
                public FieldSpec CreateField (FieldInfo fi, TypeSpec declaringType)
                {
@@ -170,7 +169,8 @@ namespace Mono.CSharp
                                        break;
                                default:
                                        // Ignore private fields (even for error reporting) to not require extra dependencies
-                                       if (IgnorePrivateMembers || HasAttribute (CustomAttributeData.GetCustomAttributes (fi), "CompilerGeneratedAttribute", CompilerServicesNamespace))
+                                       if ((IgnorePrivateMembers && !declaringType.IsStruct) ||
+                                               HasAttribute (CustomAttributeData.GetCustomAttributes (fi), "CompilerGeneratedAttribute", CompilerServicesNamespace))
                                                return null;
 
                                        mod = Modifiers.PRIVATE;
@@ -387,20 +387,30 @@ namespace Mono.CSharp
                                // Cannot set to OVERRIDE without full hierarchy checks
                                // this flag indicates that the method could be override
                                // but further validation is needed
-                               if ((mod & Modifiers.OVERRIDE) != 0 && kind == MemberKind.Method && declaringType.BaseType != null) {
-                                       var filter = MemberFilter.Method (name, tparams != null ? tparams.Length : 0, parameters, null);
-                                       var candidate = MemberCache.FindMember (declaringType.BaseType, filter, BindingRestriction.None);
+                               if ((mod & Modifiers.OVERRIDE) != 0) {
+                                       bool is_real_override = false;
+                                       if (kind == MemberKind.Method && declaringType.BaseType != null) {
+                                               var filter = MemberFilter.Method (name, tparams != null ? tparams.Length : 0, parameters, null);
+                                               var candidate = MemberCache.FindMember (declaringType.BaseType, filter, BindingRestriction.None);
 
-                                       //
-                                       // For imported class method do additional validation to be sure that metadata
-                                       // override flag was correct
-                                       // 
-                                       // Difference between protected internal and protected is ok
-                                       //
-                                       const Modifiers conflict_mask = Modifiers.AccessibilityMask & ~Modifiers.INTERNAL;
-                                       if (candidate == null || (candidate.Modifiers & conflict_mask) != (mod & conflict_mask) || candidate.IsStatic) {
+                                               //
+                                               // For imported class method do additional validation to be sure that metadata
+                                               // override flag was correct
+                                               // 
+                                               // Difference between protected internal and protected is ok
+                                               //
+                                               const Modifiers conflict_mask = Modifiers.AccessibilityMask & ~Modifiers.INTERNAL;
+                                               if (candidate != null && (candidate.Modifiers & conflict_mask) == (mod & conflict_mask) && !candidate.IsStatic) {
+                                                       is_real_override = true;
+                                               }
+                                       }
+
+                                       if (!is_real_override) {
                                                mod &= ~Modifiers.OVERRIDE;
-                                               mod |= Modifiers.VIRTUAL;
+                                               if ((mod & Modifiers.SEALED) != 0)
+                                                       mod &= ~Modifiers.SEALED;
+                                               else
+                                                       mod |= Modifiers.VIRTUAL;
                                        }
                                }
                        }
@@ -469,7 +479,7 @@ namespace Mono.CSharp
                                        if (!is_params && p.IsOptional) {
                                                object value = p.RawDefaultValue;
                                                var ptype = types[i];
-                                               if ((p.Attributes & ParameterAttributes.HasDefault) != 0 && ptype.Kind != MemberKind.TypeParameter && (value != null || TypeManager.IsReferenceType (ptype))) {
+                                               if ((p.Attributes & ParameterAttributes.HasDefault) != 0 && ptype.Kind != MemberKind.TypeParameter && (value != null || TypeSpec.IsReferenceType (ptype))) {
                                                        if (value == null) {
                                                                default_value = Constant.CreateConstant (ptype, null, Location.Null);
                                                        } else {
@@ -607,7 +617,7 @@ namespace Mono.CSharp
                                spec = new PropertySpec (MemberKind.Property, declaringType, new ImportedMemberDefinition (pi, type, this), type, pi, mod);
 
                        if (!is_valid_property) {
-                               spec.IsNotRealProperty = true;
+                               spec.IsNotCSharpCompatible = true;
                                return spec;
                        }
 
@@ -673,6 +683,11 @@ namespace Mono.CSharp
 
                        if (type.IsGenericType && !type.IsGenericTypeDefinition) {
                                var type_def = type.GetGenericTypeDefinition ();
+
+                               // Generic type definition can also be forwarded
+                               if (compiled_types.TryGetValue (type_def, out spec))
+                                       return spec;
+
                                var targs = CreateGenericArguments (0, type.GetGenericArguments (), dtype);
                                if (declaringType == null) {
                                        // Simple case, no nesting
@@ -713,6 +728,9 @@ namespace Mono.CSharp
                                                name = name.Substring (0, index);
 
                                        spec = MemberCache.FindNestedType (spec, name, targs.Length - targs_pos);
+                                       if (spec == null)
+                                               return null;
+
                                        if (spec.Arity > 0) {
                                                spec = spec.MakeGenericType (module, targs.Skip (targs_pos).ToArray ());
                                        }
@@ -835,7 +853,7 @@ namespace Mono.CSharp
                        if (!assembly_2_definition.TryGetValue (assembly, out found)) {
 
                                // This can happen in dynamic context only
-                               var def = new ImportedAssemblyDefinition (assembly, this);
+                               var def = new ImportedAssemblyDefinition (assembly);
                                assembly_2_definition.Add (assembly, def);
                                def.ReadAttributes ();
                                found = def;
@@ -899,10 +917,9 @@ namespace Mono.CSharp
                        if (attributesData.Count == 0)
                                return false;
 
-                       string ns, name;
                        foreach (var attr in attributesData) {
-                               GetCustomAttributeTypeName (attr, out ns, out name);
-                               if (name == attrName && ns == attrNamespace)
+                               var dt = attr.Constructor.DeclaringType;
+                               if (dt.Name == attrName && dt.Namespace == attrNamespace)
                                        return true;
                        }
 
@@ -929,9 +946,12 @@ namespace Mono.CSharp
                        if (ifaces.Length != 0) {
                                foreach (var iface in ifaces) {
                                        var it = CreateType (iface);
+                                       if (it == null)
+                                               continue;
+
                                        spec.AddInterface (it);
 
-                                       // Unfortunatelly not all languages inlcude inherited interfaces
+                                       // Unfortunately not all languages expand inherited interfaces
                                        var bifaces = it.Interfaces;
                                        if (bifaces != null) {
                                                foreach (var biface in bifaces) {
@@ -944,6 +964,15 @@ namespace Mono.CSharp
                        if (spec.BaseType != null) {
                                var bifaces = spec.BaseType.Interfaces;
                                if (bifaces != null) {
+                                       //
+                                       // Before adding base class interfaces close defined interfaces
+                                       // on type parameter
+                                       //
+                                       var tp = spec as TypeParameterSpec;
+                                       if (tp != null && tp.InterfacesDefined == null) {
+                                               tp.InterfacesDefined = TypeSpec.EmptyTypes;
+                                       }
+
                                        foreach (var iface in bifaces)
                                                spec.AddInterface (iface);
                                }
@@ -990,7 +1019,7 @@ namespace Mono.CSharp
                                        prev_namespace = t.Namespace;
                                }
 
-                               ns.AddType (it);
+                               ns.AddType (module, it);
 
                                if (it.IsStatic && hasExtensionTypes &&
                                        HasAttribute (CustomAttributeData.GetCustomAttributes (t), "ExtensionAttribute", CompilerServicesNamespace)) {
@@ -1112,10 +1141,9 @@ namespace Mono.CSharp
                        if (attrs.Count == 0)
                                return null;
 
-                       string name, ns;
                        foreach (var ca in attrs) {
-                               GetCustomAttributeTypeName (ca, out ns, out name);
-                               if (name != "DecimalConstantAttribute" || ns != CompilerServicesNamespace)
+                               var dt = ca.Constructor.DeclaringType;
+                               if (dt.Name != "DecimalConstantAttribute" || dt.Namespace != CompilerServicesNamespace)
                                        continue;
 
                                var value = new decimal (
@@ -1162,15 +1190,21 @@ namespace Mono.CSharp
                                return mod;
                        }
 
+                       // It can be sealed and override
                        if ((ma & MethodAttributes.Final) != 0)
                                mod |= Modifiers.SEALED;
 
-                       // It can be sealed and override
                        if ((ma & MethodAttributes.Virtual) != 0) {
-                               if ((ma & MethodAttributes.NewSlot) != 0 || !declaringType.IsClass) {
-                                       // No private virtual or sealed virtual
-                                       if ((mod & (Modifiers.PRIVATE | Modifiers.SEALED)) == 0)
+                               // Not every member can be detected based on MethodAttribute, we
+                               // set virtual or non-virtual only when we are certain. Further checks
+                               // to really find out what `virtual' means for this member are done
+                               // later
+                               if ((ma & MethodAttributes.NewSlot) != 0) {
+                                       if ((mod & Modifiers.SEALED) != 0) {
+                                               mod &= ~Modifiers.SEALED;
+                                       } else {
                                                mod |= Modifiers.VIRTUAL;
+                                       }
                                } else {
                                        mod |= Modifiers.OVERRIDE;
                                }
@@ -1201,11 +1235,11 @@ namespace Mono.CSharp
                                // It should not throw any loading exception
                                IList<CustomAttributeData> attrs = CustomAttributeData.GetCustomAttributes (mi);
 
-                               string ns, name;
                                foreach (var a in attrs) {
-                                       importer.GetCustomAttributeTypeName (a, out ns, out name);
+                                       var dt = a.Constructor.DeclaringType;
+                                       string name = dt.Name;
                                        if (name == "ObsoleteAttribute") {
-                                               if (ns != "System")
+                                               if (dt.Namespace != "System")
                                                        continue;
 
                                                if (bag == null)
@@ -1225,7 +1259,7 @@ namespace Mono.CSharp
                                        }
 
                                        if (name == "ConditionalAttribute") {
-                                               if (ns != "System.Diagnostics")
+                                               if (dt.Namespace != "System.Diagnostics")
                                                        continue;
 
                                                if (bag == null)
@@ -1239,7 +1273,7 @@ namespace Mono.CSharp
                                        }
 
                                        if (name == "CLSCompliantAttribute") {
-                                               if (ns != "System")
+                                               if (dt.Namespace != "System")
                                                        continue;
 
                                                if (bag == null)
@@ -1252,7 +1286,7 @@ namespace Mono.CSharp
                                        // Type only attributes
                                        if (mi.MemberType == MemberTypes.TypeInfo || mi.MemberType == MemberTypes.NestedType) {
                                                if (name == "DefaultMemberAttribute") {
-                                                       if (ns != "System.Reflection")
+                                                       if (dt.Namespace != "System.Reflection")
                                                                continue;
 
                                                        if (bag == null)
@@ -1263,7 +1297,7 @@ namespace Mono.CSharp
                                                }
 
                                                if (name == "AttributeUsageAttribute") {
-                                                       if (ns != "System")
+                                                       if (dt.Namespace != "System")
                                                                continue;
 
                                                        if (bag == null)
@@ -1281,7 +1315,7 @@ namespace Mono.CSharp
 
                                                // Interface only attribute
                                                if (name == "CoClassAttribute") {
-                                                       if (ns != "System.Runtime.InteropServices")
+                                                       if (dt.Namespace != "System.Runtime.InteropServices")
                                                                continue;
 
                                                        if (bag == null)
@@ -1374,12 +1408,10 @@ namespace Mono.CSharp
        {
                readonly Module module;
                bool cls_compliant;
-               readonly MetadataImporter importer;
                
-               public ImportedModuleDefinition (Module module, MetadataImporter importer)
+               public ImportedModuleDefinition (Module module)
                {
                        this.module = module;
-                       this.importer = importer;
                }
 
                #region Properties
@@ -1402,11 +1434,10 @@ namespace Mono.CSharp
                {
                        IList<CustomAttributeData> attrs = CustomAttributeData.GetCustomAttributes (module);
 
-                       string ns, name;
                        foreach (var a in attrs) {
-                               importer.GetCustomAttributeTypeName (a, out ns, out name);
-                               if (name == "CLSCompliantAttribute") {
-                                       if (ns != "System")
+                               var dt = a.Constructor.DeclaringType;
+                               if (dt.Name == "CLSCompliantAttribute") {
+                                       if (dt.Namespace != "System")
                                                continue;
 
                                        cls_compliant = (bool) a.ConstructorArguments[0].Value;
@@ -1455,18 +1486,16 @@ namespace Mono.CSharp
        {
                readonly Assembly assembly;
                readonly AssemblyName aname;
-               readonly MetadataImporter importer;
                bool cls_compliant;
                bool contains_extension_methods;
 
                List<AssemblyName> internals_visible_to;
                Dictionary<IAssemblyDefinition, AssemblyName> internals_visible_to_cache;
 
-               public ImportedAssemblyDefinition (Assembly assembly, MetadataImporter importer)
+               public ImportedAssemblyDefinition (Assembly assembly)
                {
                        this.assembly = assembly;
                        this.aname = assembly.GetName ();
-                       this.importer = importer;
                }
 
                #region Properties
@@ -1581,31 +1610,21 @@ namespace Mono.CSharp
 
                        IList<CustomAttributeData> attrs = CustomAttributeData.GetCustomAttributes (assembly);
 
-                       string ns, name;
                        foreach (var a in attrs) {
-                               importer.GetCustomAttributeTypeName (a, out ns, out name);
-
+                               var dt = a.Constructor.DeclaringType;
+                               var name = dt.Name;
                                if (name == "CLSCompliantAttribute") {
-                                       if (ns == "System") {
-                                               try {
-                                                       cls_compliant = (bool) a.ConstructorArguments[0].Value;
-                                               } catch {
-                                               }
+                                       if (dt.Namespace == "System") {
+                                               cls_compliant = (bool) a.ConstructorArguments[0].Value;
                                        }
                                        continue;
                                }
 
                                if (name == "InternalsVisibleToAttribute") {
-                                       if (ns != MetadataImporter.CompilerServicesNamespace)
+                                       if (dt.Namespace != MetadataImporter.CompilerServicesNamespace)
                                                continue;
 
-                                       string s;
-                                       try {
-                                               s = a.ConstructorArguments[0].Value as string;
-                                       } catch {
-                                               s = null;
-                                       }
-
+                                       string s = a.ConstructorArguments[0].Value as string;
                                        if (s == null)
                                                continue;
 
@@ -1618,7 +1637,7 @@ namespace Mono.CSharp
                                }
 
                                if (name == "ExtensionAttribute") {
-                                       if (ns == MetadataImporter.CompilerServicesNamespace)
+                                       if (dt.Namespace == MetadataImporter.CompilerServicesNamespace)
                                                contains_extension_methods = true;
 
                                        continue;
@@ -1869,7 +1888,13 @@ namespace Mono.CSharp
                                        if ((t.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPrivate && importer.IgnorePrivateMembers)
                                                continue;
 
-                                       imported = importer.CreateNestedType (t, declaringType);
+                                       try {
+                                               imported = importer.CreateNestedType (t, declaringType);
+                                       } catch (Exception e) {
+                                               throw new InternalErrorException (e, "Could not import nested type `{0}' from `{1}'",
+                                                       t.FullName, declaringType.MemberDefinition.DeclaringAssembly.FullName);
+                                       }
+
                                        cache.AddMemberImported (imported);
                                }
 
@@ -1886,6 +1911,15 @@ namespace Mono.CSharp
                                }
                        }
 
+                       //
+                       // Load base interfaces first to minic behaviour of compiled members
+                       //
+                       if (declaringType.IsInterface && declaringType.Interfaces != null) {
+                               foreach (var iface in declaringType.Interfaces) {
+                                       cache.AddInterface (iface);
+                               }
+                       }
+
                        if (!onlyTypes) {
                                //
                                // The logic here requires methods to be returned first which seems to work for both Mono and .NET
@@ -2016,12 +2050,6 @@ namespace Mono.CSharp
                                        cache.AddMemberImported (imported);
                                }
                        }
-
-                       if (declaringType.IsInterface && declaringType.Interfaces != null) {
-                               foreach (var iface in declaringType.Interfaces) {
-                                       cache.AddInterface (iface);
-                               }
-                       }
                }
        }