[linker] We need to mark nested types even if the declaring type isn't marked.
[mono.git] / mcs / tools / linker / Mono.Linker.Steps / MarkStep.cs
index c9b66af44ab1d6d16bed8dae33b598a1c3be3da0..bc04fc5c7c024087188ffee7b0c337305b6aae8f 100644 (file)
@@ -69,16 +69,21 @@ namespace Mono.Linker.Steps {
                protected virtual void InitializeAssembly (AssemblyDefinition assembly)
                {
                        MarkAssembly (assembly);
-                       foreach (TypeDefinition type in assembly.MainModule.Types) {
-                               if (!Annotations.IsMarked (type))
-                                       continue;
 
+                       foreach (TypeDefinition type in assembly.MainModule.Types)
                                InitializeType (type);
-                       }
                }
 
                void InitializeType (TypeDefinition type)
                {
+                       if (type.HasNestedTypes) {
+                               foreach (var nested in type.NestedTypes)
+                                       InitializeType (nested);
+                       }
+
+                       if (!Annotations.IsMarked (type))
+                               return;
+
                        MarkType (type);
 
                        if (type.HasFields)
@@ -123,7 +128,9 @@ namespace Mono.Linker.Steps {
                {
                        while (!QueueIsEmpty ()) {
                                MethodDefinition method = (MethodDefinition) _methods.Dequeue ();
+                               Annotations.Push (method);
                                ProcessMethod (method);
+                               Annotations.Pop ();
                        }
                }
 
@@ -139,8 +146,11 @@ namespace Mono.Linker.Steps {
 
                void ProcessVirtualMethods ()
                {
-                       foreach (MethodDefinition method in _virtual_methods)
+                       foreach (MethodDefinition method in _virtual_methods) {
+                               Annotations.Push (method);
                                ProcessVirtualMethod (method);
+                               Annotations.Pop ();
+                       }
                }
 
                void ProcessVirtualMethod (MethodDefinition method)
@@ -191,17 +201,21 @@ namespace Mono.Linker.Steps {
 
                protected virtual void MarkCustomAttribute (CustomAttribute ca)
                {
+                       Annotations.Push (ca);
                        MarkMethod (ca.Constructor);
 
                        MarkCustomAttributeArguments (ca);
 
                        TypeReference constructor_type = ca.Constructor.DeclaringType;
                        TypeDefinition type = constructor_type.Resolve ();
-                       if (type == null)
+                       if (type == null) {
+                               Annotations.Pop ();
                                throw new ResolutionException (constructor_type);
+                       }
 
                        MarkCustomAttributeProperties (ca, type);
                        MarkCustomAttributeFields (ca, type);
+                       Annotations.Pop ();
                }
 
                protected void MarkSecurityDeclarations (ISecurityDeclarationProvider provider)
@@ -266,10 +280,12 @@ namespace Mono.Linker.Steps {
                protected void MarkCustomAttributeProperty (CustomAttributeNamedArgument namedArgument, TypeDefinition attribute)
                {
                        PropertyDefinition property = GetProperty (attribute, namedArgument.Name);
+                       Annotations.Push (property);
                        if (property != null)
                                MarkMethod (property.SetMethod);
 
                        MarkIfType (namedArgument.Argument);
+                       Annotations.Pop ();
                }
 
                PropertyDefinition GetProperty (TypeDefinition type, string propertyname)
@@ -334,6 +350,9 @@ namespace Mono.Linker.Steps {
                                        return;
 
                                MarkType (et);
+                               if (argument.Value == null)
+                                       return;
+
                                foreach (var cac in (CustomAttributeArgument[]) argument.Value)
                                        MarkWithResolvedScope ((TypeReference) cac.Value);
                        } else if (at.Namespace == "System" && at.Name == "Type") {
@@ -355,7 +374,6 @@ namespace Mono.Linker.Steps {
                        if ((git != null) && git.HasGenericArguments) {
                                foreach (var ga in git.GenericArguments)
                                        MarkWithResolvedScope (ga);
-                               return;
                        }
                        // we cannot set the Scope of a TypeSpecification but it's element type can be set
                        // e.g. System.String[] -> System.String
@@ -483,6 +501,8 @@ namespace Mono.Linker.Steps {
                        if (CheckProcessed (type))
                                return null;
 
+                       Annotations.Push (type);
+
                        MarkScope (type.Scope);
                        MarkType (type.BaseType);
                        MarkType (type.DeclaringType);
@@ -505,17 +525,20 @@ namespace Mono.Linker.Steps {
                                MarkFields (type, type.IsEnum);
 
                        if (type.HasInterfaces) {
-                               foreach (TypeReference iface in type.Interfaces)
-                                       MarkType (iface);
+                               foreach (var iface in type.Interfaces)
+                                       MarkType (iface.InterfaceType);
                        }
 
                        if (type.HasMethods) {
                                MarkMethodsIf (type.Methods, IsVirtualAndHasPreservedParent);
                                MarkMethodsIf (type.Methods, IsStaticConstructorPredicate);
+                               MarkMethodsIf (type.Methods, HasSerializationAttribute);
                        }
 
                        DoAdditionalTypeProcessing (type);
 
+                       Annotations.Pop ();
+
                        Annotations.Mark (type);
 
                        ApplyPreserveInfo (type);
@@ -626,8 +649,10 @@ namespace Mono.Linker.Steps {
                                if (property.Name != property_name)
                                        continue;
 
+                               Annotations.Push (property);
                                MarkMethod (property.GetMethod);
                                MarkMethod (property.SetMethod);
+                               Annotations.Pop ();
                        }
                }
 
@@ -687,8 +712,11 @@ namespace Mono.Linker.Steps {
                void MarkMethodsIf (ICollection methods, MethodPredicate predicate)
                {
                        foreach (MethodDefinition method in methods)
-                               if (predicate (method))
+                               if (predicate (method)) {
+                                       Annotations.Push (predicate);
                                        MarkMethod (method);
+                                       Annotations.Pop ();
+                               }
                }
 
                static MethodPredicate IsDefaultConstructorPredicate = new MethodPredicate (IsDefaultConstructor);
@@ -718,6 +746,25 @@ namespace Mono.Linker.Steps {
                        return method.IsConstructor && method.IsStatic;
                }
 
+               static bool HasSerializationAttribute (MethodDefinition method)
+               {
+                       if (!method.HasCustomAttributes)
+                               return false;
+                       foreach (var ca in method.CustomAttributes) {
+                               var cat = ca.AttributeType;
+                               if (cat.Namespace != "System.Runtime.Serialization")
+                                       continue;
+                               switch (cat.Name) {
+                               case "OnDeserializedAttribute":
+                               case "OnDeserializingAttribute":
+                               case "OnSerializedAttribute":
+                               case "OnSerializingAttribute":
+                                       return true;
+                               }
+                       }
+                       return false;
+               }
+
                static bool IsSerializable (TypeDefinition td)
                {
                        return (td.Attributes & TypeAttributes.Serializable) != 0;
@@ -878,6 +925,7 @@ namespace Mono.Linker.Steps {
                        if (reference.DeclaringType is ArrayType)
                                return null;
 
+                       Annotations.Push (reference);
                        if (reference.DeclaringType is GenericInstanceType)
                                MarkType (reference.DeclaringType);
 
@@ -886,13 +934,19 @@ namespace Mono.Linker.Steps {
 
                        MethodDefinition method = ResolveMethodDefinition (reference);
 
-                       if (method == null)
+                       if (method == null) {
+                               Annotations.Pop ();
                                throw new ResolutionException (reference);
+                       }
 
                        if (Annotations.GetAction (method) == MethodAction.Nothing)
                                Annotations.SetAction (method, MethodAction.Parse);
 
                        EnqueueMethod (method);
+
+                       Annotations.Pop ();
+                       Annotations.AddDependency (method);
+
                        return method;
                }
 
@@ -930,6 +984,7 @@ namespace Mono.Linker.Steps {
                        if (CheckProcessed (method))
                                return;
 
+                       Annotations.Push (method);
                        MarkType (method.DeclaringType);
                        MarkCustomAttributes (method);
                        MarkSecurityDeclarations (method);
@@ -973,6 +1028,7 @@ namespace Mono.Linker.Steps {
                        Annotations.Mark (method);
 
                        ApplyPreserveMethods (method);
+                       Annotations.Pop ();
                }
 
                // Allow subclassers to mark additional things when marking a method