diff --git a/src/linker/Linker.Steps/MarkStep.cs b/src/linker/Linker.Steps/MarkStep.cs index 5d34c9c57e36..8defc1962ea2 100644 --- a/src/linker/Linker.Steps/MarkStep.cs +++ b/src/linker/Linker.Steps/MarkStep.cs @@ -1385,6 +1385,11 @@ void MarkEntireAssembly (AssemblyDefinition assembly) MarkingHelpers.MarkForwardedScope (new TypeReference (exportedType.Namespace, exportedType.Name, module, exportedType.Scope)); } + // Mark scopes of type references by traversing the assembly. + new TypeReferenceMarker (assembly, MarkingHelpers).Process (); + + // Also mark the scopes of metadata typeref rows to cover any not discovered by the traversal. + // This can happen when the compiler emits typerefs into IL which aren't strictly necessary per ECMA 335. foreach (TypeReference typeReference in module.GetTypeReferences ()) MarkingHelpers.MarkForwardedScope (typeReference); } diff --git a/src/linker/Linker/TypeReferenceMarker.cs b/src/linker/Linker/TypeReferenceMarker.cs new file mode 100644 index 000000000000..df150f248459 --- /dev/null +++ b/src/linker/Linker/TypeReferenceMarker.cs @@ -0,0 +1,343 @@ +// Licensed to the.NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using Mono.Cecil; +using Mono.Cecil.Cil; +using Mono.Collections.Generic; + +namespace Mono.Linker +{ + struct TypeReferenceMarker + { + readonly AssemblyDefinition assembly; + readonly MarkingHelpers markingHelpers; + HashSet visited; + + public TypeReferenceMarker (AssemblyDefinition assembly, MarkingHelpers markingHelpers) + { + this.assembly = assembly; + this.markingHelpers = markingHelpers; + visited = null; + } + + // Traverse the assembly and mark the scopes of discovered type references (but not exported types). + // This includes scopes referenced by Cecil TypeReference objects that don't represent rows in the typeref table, + // such as references to built-in types, or attribute arguments which encode type references as strings. + public void Process () + { + visited = new HashSet (); + + WalkCustomAttributesTypesScopes (assembly); + WalkSecurityAttributesTypesScopes (assembly); + + foreach (var module in assembly.Modules) + WalkCustomAttributesTypesScopes (module); + + var mmodule = assembly.MainModule; + if (mmodule.HasTypes) { + foreach (var type in mmodule.Types) { + WalkScopes (type); + } + } + + visited = null; + } + + void WalkScopes (TypeDefinition typeDefinition) + { + WalkCustomAttributesTypesScopes (typeDefinition); + WalkSecurityAttributesTypesScopes (typeDefinition); + + if (typeDefinition.BaseType != null) + WalkScopeOfTypeReference (typeDefinition.BaseType); + + if (typeDefinition.HasInterfaces) { + foreach (var iface in typeDefinition.Interfaces) { + WalkCustomAttributesTypesScopes (iface); + WalkScopeOfTypeReference (iface.InterfaceType); + } + } + + if (typeDefinition.HasGenericParameters) + WalkTypeScope (typeDefinition.GenericParameters); + + if (typeDefinition.HasEvents) { + foreach (var e in typeDefinition.Events) { + WalkCustomAttributesTypesScopes (e); + // e.EventType is not saved + } + } + + if (typeDefinition.HasFields) { + foreach (var f in typeDefinition.Fields) { + WalkCustomAttributesTypesScopes (f); + WalkScopeOfTypeReference (f.FieldType); + WalkMarshalInfoTypeScope (f); + } + } + + if (typeDefinition.HasMethods) { + foreach (var m in typeDefinition.Methods) { + WalkCustomAttributesTypesScopes (m); + WalkSecurityAttributesTypesScopes (m); + if (m.HasGenericParameters) + WalkTypeScope (m.GenericParameters); + + WalkCustomAttributesTypesScopes (m.MethodReturnType); + WalkScopeOfTypeReference (m.MethodReturnType.ReturnType); + WalkMarshalInfoTypeScope (m.MethodReturnType); + if (m.HasOverrides) { + foreach (var mo in m.Overrides) + WalkMethodReference (mo); + } + + if (m.HasParameters) + WalkTypeScope (m.Parameters); + + if (m.HasBody) + WalkTypeScope (m.Body); + } + } + + if (typeDefinition.HasProperties) { + foreach (var p in typeDefinition.Properties) { + WalkCustomAttributesTypesScopes (p); + // p.PropertyType is not saved + } + } + + if (typeDefinition.HasNestedTypes) { + foreach (var nestedType in typeDefinition.NestedTypes) { + WalkScopes (nestedType); + } + } + } + + void WalkTypeScope (Collection genericParameters) + { + foreach (var gp in genericParameters) { + WalkCustomAttributesTypesScopes (gp); + if (gp.HasConstraints) + WalkTypeScope (gp.Constraints); + } + } + + void WalkTypeScope (Collection constraints) + { + foreach (var gc in constraints) { + WalkCustomAttributesTypesScopes (gc); + WalkScopeOfTypeReference (gc.ConstraintType); + } + } + + void WalkTypeScope (Collection parameters) + { + foreach (var p in parameters) { + WalkCustomAttributesTypesScopes (p); + WalkScopeOfTypeReference (p.ParameterType); + WalkMarshalInfoTypeScope (p); + } + } + + void WalkTypeScope (MethodBody body) + { + if (body.HasVariables) { + foreach (var v in body.Variables) { + WalkScopeOfTypeReference (v.VariableType); + } + } + + if (body.HasExceptionHandlers) { + foreach (var eh in body.ExceptionHandlers) { + if (eh.CatchType != null) + WalkScopeOfTypeReference (eh.CatchType); + } + } + + foreach (var instr in body.Instructions) { + switch (instr.OpCode.OperandType) { + + case OperandType.InlineMethod: { + var mr = (MethodReference) instr.Operand; + WalkMethodReference (mr); + break; + } + + case OperandType.InlineField: { + var fr = (FieldReference) instr.Operand; + WalkFieldReference (fr); + break; + } + + case OperandType.InlineTok: { + switch (instr.Operand) { + case TypeReference tr: + WalkScopeOfTypeReference (tr); + break; + case FieldReference fr: + WalkFieldReference (fr); + break; + case MethodReference mr: + WalkMethodReference (mr); + break; + } + + break; + } + + case OperandType.InlineType: { + var tr = (TypeReference) instr.Operand; + WalkScopeOfTypeReference (tr); + break; + } + } + } + } + + void WalkMethodReference (MethodReference mr) + { + WalkScopeOfTypeReference (mr.ReturnType); + WalkScopeOfTypeReference (mr.DeclaringType); + + if (mr is GenericInstanceMethod gim) { + foreach (var tr in gim.GenericArguments) + WalkScopeOfTypeReference (tr); + } + + if (mr.HasParameters) { + WalkTypeScope (mr.Parameters); + } + } + + void WalkFieldReference (FieldReference fr) + { + WalkScopeOfTypeReference (fr.FieldType); + WalkScopeOfTypeReference (fr.DeclaringType); + } + + void WalkMarshalInfoTypeScope (IMarshalInfoProvider provider) + { + if (!provider.HasMarshalInfo) + return; + + if (provider.MarshalInfo is CustomMarshalInfo cmi) + WalkScopeOfTypeReference (cmi.ManagedType); + } + + void WalkCustomAttributesTypesScopes (ICustomAttributeProvider customAttributeProvider) + { + if (!customAttributeProvider.HasCustomAttributes) + return; + + foreach (var ca in customAttributeProvider.CustomAttributes) + WalkForwardedTypesScope (ca); + } + + void WalkSecurityAttributesTypesScopes (ISecurityDeclarationProvider securityAttributeProvider) + { + if (!securityAttributeProvider.HasSecurityDeclarations) + return; + + foreach (var ca in securityAttributeProvider.SecurityDeclarations) { + if (!ca.HasSecurityAttributes) + continue; + + foreach (var securityAttribute in ca.SecurityAttributes) + WalkForwardedTypesScope (securityAttribute); + } + } + + void WalkForwardedTypesScope (CustomAttribute attribute) + { + WalkMethodReference (attribute.Constructor); + + if (attribute.HasConstructorArguments) { + foreach (var ca in attribute.ConstructorArguments) + WalkForwardedTypesScope (ca); + } + + if (attribute.HasFields) { + foreach (var field in attribute.Fields) + WalkForwardedTypesScope (field.Argument); + } + + if (attribute.HasProperties) { + foreach (var property in attribute.Properties) + WalkForwardedTypesScope (property.Argument); + } + } + + void WalkForwardedTypesScope (SecurityAttribute attribute) + { + if (attribute.HasFields) { + foreach (var field in attribute.Fields) + WalkForwardedTypesScope (field.Argument); + } + + if (attribute.HasProperties) { + foreach (var property in attribute.Properties) + WalkForwardedTypesScope (property.Argument); + } + } + + void WalkForwardedTypesScope (CustomAttributeArgument attributeArgument) + { + WalkScopeOfTypeReference (attributeArgument.Type); + + switch (attributeArgument.Value) { + case TypeReference tr: + WalkScopeOfTypeReference (tr); + break; + case CustomAttributeArgument caa: + WalkForwardedTypesScope (caa); + break; + case CustomAttributeArgument[] array: + foreach (var item in array) + WalkForwardedTypesScope (item); + break; + } + } + + void WalkScopeOfTypeReference (TypeReference type) + { + if (type == null) + return; + + if (!visited.Add (type)) + return; + + // Don't walk the scope of windows runtime projections + if (type.IsWindowsRuntimeProjection) + return; + + switch (type) { + case GenericInstanceType git: + WalkScopeOfTypeReference (git.ElementType); + foreach (var ga in git.GenericArguments) + WalkScopeOfTypeReference (ga); + return; + case FunctionPointerType fpt: + WalkScopeOfTypeReference (fpt.ReturnType); + if (fpt.HasParameters) + WalkTypeScope (fpt.Parameters); + return; + case IModifierType imt: + WalkScopeOfTypeReference (imt.ModifierType); + WalkScopeOfTypeReference (imt.ElementType); + return; + case TypeSpecification ts: + WalkScopeOfTypeReference (ts.ElementType); + return; + case TypeDefinition: + case GenericParameter: + // Nothing to walk + return; + } + + markingHelpers.MarkForwardedScope (type); + } + } + +} \ No newline at end of file diff --git a/test/Mono.Linker.Tests.Cases/BCLFeatures/ETW/CustomEventSource.cs b/test/Mono.Linker.Tests.Cases/BCLFeatures/ETW/CustomEventSource.cs index 06de7d17180f..8aa02759e06a 100644 --- a/test/Mono.Linker.Tests.Cases/BCLFeatures/ETW/CustomEventSource.cs +++ b/test/Mono.Linker.Tests.Cases/BCLFeatures/ETW/CustomEventSource.cs @@ -1,9 +1,10 @@ -using System; -using System.Diagnostics.Tracing; +using System.Diagnostics.Tracing; using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; namespace Mono.Linker.Tests.Cases.BCLFeatures.ETW { + [Reference ("System.Diagnostics.Tracing.dll")] public class CustomEventSource { public static void Main () diff --git a/test/Mono.Linker.Tests.Cases/BCLFeatures/ETW/CustomLibraryEventSource.cs b/test/Mono.Linker.Tests.Cases/BCLFeatures/ETW/CustomLibraryEventSource.cs index c4d0e2fabfed..0d544e9bf276 100644 --- a/test/Mono.Linker.Tests.Cases/BCLFeatures/ETW/CustomLibraryEventSource.cs +++ b/test/Mono.Linker.Tests.Cases/BCLFeatures/ETW/CustomLibraryEventSource.cs @@ -1,10 +1,10 @@ -using System; -using System.Diagnostics.Tracing; +using System.Diagnostics.Tracing; using Mono.Linker.Tests.Cases.Expectations.Assertions; using Mono.Linker.Tests.Cases.Expectations.Metadata; namespace Mono.Linker.Tests.Cases.BCLFeatures.ETW { + [Reference ("System.Diagnostics.Tracing.dll")] [SetupLinkerArgument ("-a", "test.exe", "library")] [KeptMember (".ctor()")] public class CustomLibraryEventSource diff --git a/test/Mono.Linker.Tests.Cases/DataFlow/MemberTypes.cs b/test/Mono.Linker.Tests.Cases/DataFlow/MemberTypes.cs index a5cccb869025..2a1bfc75a522 100644 --- a/test/Mono.Linker.Tests.Cases/DataFlow/MemberTypes.cs +++ b/test/Mono.Linker.Tests.Cases/DataFlow/MemberTypes.cs @@ -300,14 +300,14 @@ public void HideMethod () { } [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] public event EventHandler PublicEventOnBase; protected event EventHandler ProtectedEventOnBase; private event EventHandler PrivateEventOnBase; [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] public event EventHandler HideEvent; [Kept] @@ -367,14 +367,14 @@ public void HideMethod () { } [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] public event EventHandler PublicEvent; protected event EventHandler ProtectedEvent; private event EventHandler PrivateEvent; [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] public event EventHandler HideEvent; [Kept] @@ -435,7 +435,7 @@ public void HideMethod () { } [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] protected event EventHandler ProtectedEventOnBase; private event EventHandler PrivateEventOnBase; public event EventHandler HideEvent; @@ -491,12 +491,12 @@ public void HideMethod () { } [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] protected event EventHandler ProtectedEvent; [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] private event EventHandler PrivateEvent; public event EventHandler HideEvent; @@ -563,18 +563,18 @@ public void HideMethod () { } [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] public event EventHandler PublicEventOnBase; [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] protected event EventHandler ProtectedEventOnBase; private event EventHandler PrivateEventOnBase; [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] public event EventHandler HideEvent; [Kept] @@ -646,22 +646,22 @@ public void HideMethod () { } [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] public event EventHandler PublicEvent; [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] protected event EventHandler ProtectedEvent; [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] private event EventHandler PrivateEvent; [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] public event EventHandler HideEvent; [Kept] @@ -1372,14 +1372,14 @@ class PublicEventsBaseType [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] public event EventHandler PublicEventOnBase; protected event EventHandler ProtectedEventOnBase; private event EventHandler PrivateEventOnBase; [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] public event EventHandler HideEvent; [Kept] @@ -1403,14 +1403,14 @@ class PublicEventsType : PublicEventsBaseType [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] public event EventHandler PublicEvent; protected event EventHandler ProtectedEvent; private event EventHandler PrivateEvent; [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] public event EventHandler HideEvent; [Kept] @@ -1443,7 +1443,7 @@ class NonPublicEventsBaseType [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] protected event EventHandler ProtectedEventOnBase; private event EventHandler PrivateEventOnBase; public event EventHandler HideEvent; @@ -1466,12 +1466,12 @@ class NonPublicEventsType : NonPublicEventsBaseType [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] protected event EventHandler ProtectedEvent; [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] private event EventHandler PrivateEvent; public event EventHandler HideEvent; @@ -1503,18 +1503,18 @@ class AllEventsBaseType [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] public event EventHandler PublicEventOnBase; [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] protected event EventHandler ProtectedEventOnBase; private event EventHandler PrivateEventOnBase; [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] public event EventHandler HideEvent; [Kept] @@ -1542,22 +1542,22 @@ class AllEventsType : AllEventsBaseType [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] public event EventHandler PublicEvent; [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] protected event EventHandler ProtectedEvent; [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] private event EventHandler PrivateEvent; [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] public event EventHandler HideEvent; [Kept] diff --git a/test/Mono.Linker.Tests.Cases/DynamicDependencies/DynamicDependencyMemberTypes.cs b/test/Mono.Linker.Tests.Cases/DynamicDependencies/DynamicDependencyMemberTypes.cs index 5ba9d6c25a66..f0829fa1a6e9 100644 --- a/test/Mono.Linker.Tests.Cases/DynamicDependencies/DynamicDependencyMemberTypes.cs +++ b/test/Mono.Linker.Tests.Cases/DynamicDependencies/DynamicDependencyMemberTypes.cs @@ -212,7 +212,7 @@ class TypeWithPublicEvent [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] public event EventHandler PublicEvent; event EventHandler NonPublicEvent; @@ -225,7 +225,7 @@ class TypeWithNonPublicEvent [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] event EventHandler NonPublicEvent; public event EventHandler PublicEven; diff --git a/test/Mono.Linker.Tests.Cases/Extensibility/CustomStepCanResolveTypesAfterSweep.cs b/test/Mono.Linker.Tests.Cases/Extensibility/CustomStepCanResolveTypesAfterSweep.cs new file mode 100644 index 000000000000..5078037cf18b --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/Extensibility/CustomStepCanResolveTypesAfterSweep.cs @@ -0,0 +1,33 @@ +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; + +namespace Mono.Linker.Tests.Cases.Extensibility +{ + // Repro for https://github.com/dotnet/linker/issues/2267. +#if !NETCOREAPP + [IgnoreTestCase ("Specific to the illink build")] +#endif + [SetupCompileBefore ("ResolveTypesSubStep.dll", new[] { "Dependencies/ResolveTypesSubStep.cs" }, new[] { "illink.dll", "Mono.Cecil.dll", "netstandard.dll" })] + [SetupLinkerArgument ("--custom-step", "+OutputStep:ResolveTypesSubStep,ResolveTypesSubStep.dll")] + [SetupLinkerAction ("copy", "test")] + [SetupLinkerTrimMode ("link")] + [KeptMember (".ctor()")] + public class CustomStepCanResolveTypesAfterSweep + { + public static void Main () + { + var f = TypeWithFields.primitiveField; + } + + [Kept] + [KeptMember (".ctor()")] + class TypeWithFields + { + [Kept] + public static int primitiveField; + + [Kept] + public static float unusedPrimitiveField; + } + } +} \ No newline at end of file diff --git a/test/Mono.Linker.Tests.Cases/Extensibility/Dependencies/ResolveTypesSubStep.cs b/test/Mono.Linker.Tests.Cases/Extensibility/Dependencies/ResolveTypesSubStep.cs new file mode 100644 index 000000000000..9327d2152dee --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/Extensibility/Dependencies/ResolveTypesSubStep.cs @@ -0,0 +1,34 @@ +using System; +using Mono.Cecil; +using Mono.Linker.Steps; + +class ResolveTypesSubStep : BaseStep +{ + + protected override void Process () + { + foreach (var assembly in Context.GetAssemblies ()) { + foreach (var type in assembly.MainModule.Types) + ProcessType (type); + } + } + + void ProcessType (TypeDefinition type) + { + if (type.HasNestedTypes) { + foreach (var nested in type.NestedTypes) + ProcessType (nested); + } + + if (type.Name == "TypeWithFields") { + foreach (var field in type.Fields) + ProcessField (field); + } + } + + public void ProcessField (FieldDefinition field) + { + if (field.FieldType.Resolve () == null) + throw new Exception($"Unresolved field type {field.FieldType} for field {field}!"); + } +} diff --git a/test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingWithCsc.cs b/test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingWithCsc.cs index 7be38642a9ae..75c930d64de0 100644 --- a/test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingWithCsc.cs +++ b/test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingWithCsc.cs @@ -21,7 +21,7 @@ namespace Mono.Linker.Tests.Cases.References // We library should be gone. The `using` statement leaves no traces in the IL so nothing in `library` will be marked [RemovedAssembly ("library.dll")] - [KeptReferencesInAssembly ("copied.dll", new[] { PlatformAssemblies.CoreLib, "library" })] + [KeptReferencesInAssembly ("copied.dll", new[] { "System.Runtime", "library" })] public class AssemblyOnlyUsedByUsingWithCsc { public static void Main () diff --git a/test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingWithCscWithKeepFacades.cs b/test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingWithCscWithKeepFacades.cs index 2fcbb6a6c588..3be6aa4e7757 100644 --- a/test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingWithCscWithKeepFacades.cs +++ b/test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingWithCscWithKeepFacades.cs @@ -23,7 +23,7 @@ namespace Mono.Linker.Tests.Cases.References // We library should be gone. The `using` statement leaves no traces in the IL so nothing in `library` will be marked [RemovedAssembly ("library.dll")] - [KeptReferencesInAssembly ("copied.dll", new[] { PlatformAssemblies.CoreLib, "library" })] + [KeptReferencesInAssembly ("copied.dll", new[] { "System.Runtime", "library" })] public class AssemblyOnlyUsedByUsingWithCscWithKeepFacades { public static void Main () diff --git a/test/Mono.Linker.Tests.Cases/Reflection/EventUsedViaReflection.cs b/test/Mono.Linker.Tests.Cases/Reflection/EventUsedViaReflection.cs index 7d9e9ebfcd3c..ba33cdc4e76a 100644 --- a/test/Mono.Linker.Tests.Cases/Reflection/EventUsedViaReflection.cs +++ b/test/Mono.Linker.Tests.Cases/Reflection/EventUsedViaReflection.cs @@ -192,7 +192,7 @@ class Bar [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] private event EventHandler PrivateEvent; public event EventHandler PublicEvent; } @@ -202,7 +202,7 @@ class UnknownBindingFlags [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] internal event EventHandler InternalEvent; [Kept] [KeptBackingField] @@ -212,12 +212,12 @@ class UnknownBindingFlags [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] private event EventHandler PrivateEvent; [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] public event EventHandler PublicEvent; } @@ -226,12 +226,12 @@ class IfClass [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] public event EventHandler IfEvent; [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] public event EventHandler ElseEvent; } @@ -245,7 +245,7 @@ class ElseClass [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] public event EventHandler IfEvent; } @@ -256,7 +256,7 @@ class BaseClass [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] public event EventHandler PublicEventOnBase; } [KeptBaseType (typeof (BaseClass))] @@ -269,13 +269,13 @@ class IgnoreCaseBindingFlagsClass [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] public event EventHandler PublicEvent; [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] private event EventHandler MarkedDueToIgnoreCaseEvent; } @@ -291,13 +291,13 @@ class PutRefDispPropertyBindingFlagsClass [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] public event EventHandler PublicEvent; [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] private event EventHandler MarkedDueToPutRefDispPropertyEvent; } } diff --git a/test/Mono.Linker.Tests.Cases/Reflection/RuntimeReflectionExtensionsCalls.cs b/test/Mono.Linker.Tests.Cases/Reflection/RuntimeReflectionExtensionsCalls.cs index 53eb1fd62b31..068975d4c48e 100644 --- a/test/Mono.Linker.Tests.Cases/Reflection/RuntimeReflectionExtensionsCalls.cs +++ b/test/Mono.Linker.Tests.Cases/Reflection/RuntimeReflectionExtensionsCalls.cs @@ -83,7 +83,7 @@ class ClassWithKeptMembers [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] public event EventHandler PublicEvent; [Kept] @@ -158,7 +158,7 @@ class Base [Kept] [KeptEventAddMethod] [KeptEventRemoveMethod] - [method: ExpectBodyModified, ExpectLocalsModified] + [method: ExpectBodyModified] public event EventHandler Event; [Kept] diff --git a/test/Mono.Linker.Tests.Cases/Serialization/CanDisableSerializationDiscovery.cs b/test/Mono.Linker.Tests.Cases/Serialization/CanDisableSerializationDiscovery.cs index 9bb44d051646..a0045e52f07c 100644 --- a/test/Mono.Linker.Tests.Cases/Serialization/CanDisableSerializationDiscovery.cs +++ b/test/Mono.Linker.Tests.Cases/Serialization/CanDisableSerializationDiscovery.cs @@ -7,8 +7,8 @@ namespace Mono.Linker.Tests.Cases.Serialization { + [Reference ("System.Xml.ReaderWriter.dll")] [Reference ("System.Xml.XmlSerializer.dll")] - [Reference ("System.Private.Xml.dll")] [SetupLinkerArgument ("--disable-serialization-discovery")] public class CanDisableSerializationDiscovery { diff --git a/test/Mono.Linker.Tests.Cases/Serialization/DataContractJsonSerialization.cs b/test/Mono.Linker.Tests.Cases/Serialization/DataContractJsonSerialization.cs index 6fa286e71cf4..232e3a7b29b6 100644 --- a/test/Mono.Linker.Tests.Cases/Serialization/DataContractJsonSerialization.cs +++ b/test/Mono.Linker.Tests.Cases/Serialization/DataContractJsonSerialization.cs @@ -7,7 +7,6 @@ namespace Mono.Linker.Tests.Cases.Serialization { [Reference ("System.Runtime.Serialization.dll")] - [Reference ("System.Private.DataContractSerialization.dll")] [Reference ("System.Runtime.Serialization.Primitives.dll")] [Reference ("System.Runtime.Serialization.Json.dll")] public class DataContractJsonSerialization diff --git a/test/Mono.Linker.Tests.Cases/Serialization/DataContractSerialization.cs b/test/Mono.Linker.Tests.Cases/Serialization/DataContractSerialization.cs index 9e95d87c5faa..75f8ae8e7ce9 100644 --- a/test/Mono.Linker.Tests.Cases/Serialization/DataContractSerialization.cs +++ b/test/Mono.Linker.Tests.Cases/Serialization/DataContractSerialization.cs @@ -9,7 +9,6 @@ namespace Mono.Linker.Tests.Cases.Serialization { [Reference ("System.Runtime.Serialization.dll")] [Reference ("System.Runtime.Serialization.Xml.dll")] - [Reference ("System.Private.DataContractSerialization.dll")] [Reference ("System.Runtime.Serialization.Primitives.dll")] public class DataContractSerialization { diff --git a/test/Mono.Linker.Tests.Cases/Serialization/DataContractSerializationUnused.cs b/test/Mono.Linker.Tests.Cases/Serialization/DataContractSerializationUnused.cs index 0a8ea78a6f76..908e1e8aa0e8 100644 --- a/test/Mono.Linker.Tests.Cases/Serialization/DataContractSerializationUnused.cs +++ b/test/Mono.Linker.Tests.Cases/Serialization/DataContractSerializationUnused.cs @@ -7,10 +7,8 @@ namespace Mono.Linker.Tests.Cases.Serialization { [Reference ("System.Runtime.Serialization.dll")] [Reference ("System.Runtime.Serialization.Xml.dll")] - [Reference ("System.Private.DataContractSerialization.dll")] [Reference ("System.Runtime.Serialization.Primitives.dll")] [Reference ("System.Xml.XmlSerializer.dll")] - [Reference ("System.Private.Xml.dll")] public class DataContractSerializationUnused { public static void Main () diff --git a/test/Mono.Linker.Tests.Cases/Serialization/SerializationTypeRecursion.cs b/test/Mono.Linker.Tests.Cases/Serialization/SerializationTypeRecursion.cs index b659b6a37b32..dfad711bad2b 100644 --- a/test/Mono.Linker.Tests.Cases/Serialization/SerializationTypeRecursion.cs +++ b/test/Mono.Linker.Tests.Cases/Serialization/SerializationTypeRecursion.cs @@ -6,8 +6,8 @@ namespace Mono.Linker.Tests.Cases.Serialization { + [Reference ("System.Xml.ReaderWriter.dll")] [Reference ("System.Xml.XmlSerializer.dll")] - [Reference ("System.Private.Xml.dll")] [SetupCompileArgument ("/unsafe")] public class SerializationTypeRecursion { diff --git a/test/Mono.Linker.Tests.Cases/Serialization/XmlSerialization.cs b/test/Mono.Linker.Tests.Cases/Serialization/XmlSerialization.cs index 60458747c565..7fb27cd96796 100644 --- a/test/Mono.Linker.Tests.Cases/Serialization/XmlSerialization.cs +++ b/test/Mono.Linker.Tests.Cases/Serialization/XmlSerialization.cs @@ -7,8 +7,8 @@ namespace Mono.Linker.Tests.Cases.Serialization { + [Reference ("System.Xml.ReaderWriter.dll")] [Reference ("System.Xml.XmlSerializer.dll")] - [Reference ("System.Private.Xml.dll")] public class XmlSerialization { public static void Main () diff --git a/test/Mono.Linker.Tests.Cases/Serialization/XmlSerializationUnused.cs b/test/Mono.Linker.Tests.Cases/Serialization/XmlSerializationUnused.cs index 65a8aa17b577..367c8cb7cd5c 100644 --- a/test/Mono.Linker.Tests.Cases/Serialization/XmlSerializationUnused.cs +++ b/test/Mono.Linker.Tests.Cases/Serialization/XmlSerializationUnused.cs @@ -5,11 +5,9 @@ namespace Mono.Linker.Tests.Cases.Serialization { - [Reference ("System.Xml.XmlSerializer.dll")] - [Reference ("System.Private.Xml.dll")] - [Reference ("System.Runtime.Serialization.dll")] [Reference ("System.Runtime.Serialization.Xml.dll")] - [Reference ("System.Private.DataContractSerialization.dll")] + [Reference ("System.Xml.ReaderWriter.dll")] + [Reference ("System.Xml.XmlSerializer.dll")] public class XmlSerializationUnused { public static void Main () diff --git a/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedAndUnusedForwarderWithAssemblyCopy.cs b/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedAndUnusedForwarderWithAssemblyCopy.cs index c1b63ce8cb5c..d21d34e02152 100644 --- a/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedAndUnusedForwarderWithAssemblyCopy.cs +++ b/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedAndUnusedForwarderWithAssemblyCopy.cs @@ -23,7 +23,7 @@ namespace Mono.Linker.Tests.Cases.TypeForwarding // The whole assembly is kept as is, since it is marked with the `copy` action. [KeptTypeInAssembly ("Forwarder.dll", typeof (ImplementationLibrary))] [KeptTypeInAssembly ("Forwarder.dll", "Mono.Linker.Tests.Cases.TypeForwarding.Dependencies.AnotherLibrary`1")] - [KeptReferencesInAssembly ("Forwarder.dll", new[] { "System.Private.CoreLib", "Implementation", "Unused" })] + [KeptReferencesInAssembly ("Forwarder.dll", new[] { "System.Runtime", "Implementation", "Unused" })] // Even though `Forwarder` references this assembly, none of its members are marked (none is used) and, since `Unused` // has `link` action, it is removed. [RemovedAssembly ("Unused.dll")] diff --git a/test/Mono.Linker.Tests.Cases/UnreachableBlock/ComplexConditions.cs b/test/Mono.Linker.Tests.Cases/UnreachableBlock/ComplexConditions.cs index 2900168f8bab..476bb6641773 100644 --- a/test/Mono.Linker.Tests.Cases/UnreachableBlock/ComplexConditions.cs +++ b/test/Mono.Linker.Tests.Cases/UnreachableBlock/ComplexConditions.cs @@ -5,6 +5,7 @@ namespace Mono.Linker.Tests.Cases.UnreachableBlock { + [Reference ("System.Reflection.Emit.dll")] [SetupCompileArgument ("/optimize-")] // Relying on debug csc behaviour [SetupLinkerArgument ("--enable-opt", "ipconstprop")] public class ComplexConditions diff --git a/test/Mono.Linker.Tests/TestCasesRunner/TestCaseMetadaProvider.cs b/test/Mono.Linker.Tests/TestCasesRunner/TestCaseMetadaProvider.cs index 12735c6e3e10..df9dd235066b 100644 --- a/test/Mono.Linker.Tests/TestCasesRunner/TestCaseMetadaProvider.cs +++ b/test/Mono.Linker.Tests/TestCasesRunner/TestCaseMetadaProvider.cs @@ -160,20 +160,30 @@ bool ValidatesLogMessages (TypeDefinition testCaseTypeDefinition) return false; } +#if NETCOREAPP + static string GetReferenceDir () + { + string runtimeDir = Path.GetDirectoryName (typeof (object).Assembly.Location); + string ncaVersion = Path.GetFileName (runtimeDir); + var dotnetDir = Path.GetDirectoryName (Path.GetDirectoryName (Path.GetDirectoryName (runtimeDir))); + return Path.Combine (dotnetDir, "packs", "Microsoft.NETCore.App.Ref", ncaVersion, "ref", PathUtilities.TFMDirectoryName); + } +#endif + public virtual IEnumerable GetCommonReferencedAssemblies (NPath workingDirectory) { yield return workingDirectory.Combine ("Mono.Linker.Tests.Cases.Expectations.dll").ToString (); #if NETCOREAPP - string frameworkDir = Path.GetDirectoryName (typeof (object).Assembly.Location); - - yield return typeof (object).Assembly.Location; - yield return Path.Combine (frameworkDir, "System.Runtime.dll"); - yield return Path.Combine (frameworkDir, "System.Linq.Expressions.dll"); - yield return Path.Combine (frameworkDir, "System.ComponentModel.TypeConverter.dll"); - yield return Path.Combine (frameworkDir, "System.Console.dll"); - yield return Path.Combine (frameworkDir, "mscorlib.dll"); - yield return Path.Combine (frameworkDir, "System.ObjectModel.dll"); - yield return Path.Combine (frameworkDir, "System.Runtime.Extensions.dll"); + var referenceDir = GetReferenceDir (); + yield return Path.Combine (referenceDir, "mscorlib.dll"); + yield return Path.Combine (referenceDir, "System.Collections.dll"); + yield return Path.Combine (referenceDir, "System.ComponentModel.TypeConverter.dll"); + yield return Path.Combine (referenceDir, "System.Console.dll"); + yield return Path.Combine (referenceDir, "System.Linq.Expressions.dll"); + yield return Path.Combine (referenceDir, "System.ObjectModel.dll"); + yield return Path.Combine (referenceDir, "System.Runtime.dll"); + yield return Path.Combine (referenceDir, "System.Runtime.Extensions.dll"); + yield return Path.Combine (referenceDir, "System.Runtime.InteropServices.dll"); #else yield return "mscorlib.dll"; #endif @@ -185,9 +195,8 @@ public virtual IEnumerable GetReferencedAssemblies (NPath workingDirecto if (fileName.StartsWith ("System.", StringComparison.Ordinal) || fileName.StartsWith ("Mono.", StringComparison.Ordinal) || fileName.StartsWith ("Microsoft.", StringComparison.Ordinal)) { #if NETCOREAPP - // Try to find the assembly alongside the host's framework dependencies - var frameworkDir = Path.GetFullPath (Path.GetDirectoryName (typeof (object).Assembly.Location)); - var filePath = Path.Combine (frameworkDir, fileName); + var referenceDir = GetReferenceDir (); + var filePath = Path.Combine (referenceDir, fileName); if (File.Exists (filePath)) { yield return filePath;