Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/linker.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSven Boemer <sbomer@gmail.com>2022-06-15 19:28:50 +0300
committerGitHub <noreply@github.com>2022-06-15 19:28:50 +0300
commit226107b9117b9d166e38dd00e30f9ab54399e658 (patch)
tree410de8da2b0f1555d977b78938f7ced082a32c72 /test/Mono.Linker.Tests.Cases/DataFlow
parent2abcee1070e38d2994a25777023dfa61615ea498 (diff)
Analyze implicit indexer reference operations (#2839)
Adds support for `IImplicitIndexerReferenceOperation`, which represents an implicit access to an indexer that uses `System.Index`. Implicit means that there is no `System.Index` accessor in IL, but the compiler supports `System.Index` access via an existing indexer (for example one that takes int) for types that satisfy certain criteria. See https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-8.0/ranges#implicit-index-support for details. This operation only showed up in the CFG with a more recent version of the Roslyn APIs, so this includes an update to match the one used in dotnet/runtime. This resulted in a few changes to the generated code that required tweaking some of the test validation: - Delegate cache fields are emitted. This reuses an existing attribute originally designed for mcs, but it has been updated to check for these compiler-generated fields. - `<PrivateImplementationDetails>.ThrowSwitchExpressionException` is emitted for an implicit unhandled case in switch expressions. This change includes a new attribute to check that this is kept in a few of the tests.
Diffstat (limited to 'test/Mono.Linker.Tests.Cases/DataFlow')
-rw-r--r--test/Mono.Linker.Tests.Cases/DataFlow/NullableAnnotations.cs1
-rw-r--r--test/Mono.Linker.Tests.Cases/DataFlow/PropertyDataFlow.cs82
2 files changed, 83 insertions, 0 deletions
diff --git a/test/Mono.Linker.Tests.Cases/DataFlow/NullableAnnotations.cs b/test/Mono.Linker.Tests.Cases/DataFlow/NullableAnnotations.cs
index d19a1fb82..90c24fd9f 100644
--- a/test/Mono.Linker.Tests.Cases/DataFlow/NullableAnnotations.cs
+++ b/test/Mono.Linker.Tests.Cases/DataFlow/NullableAnnotations.cs
@@ -11,6 +11,7 @@ using DAMT = System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes;
namespace Mono.Linker.Tests.Cases.DataFlow
{
[ExpectedNoWarnings]
+ [KeptPrivateImplementationDetails ("ThrowSwitchExpressionException")]
class NullableAnnotations
{
[Kept]
diff --git a/test/Mono.Linker.Tests.Cases/DataFlow/PropertyDataFlow.cs b/test/Mono.Linker.Tests.Cases/DataFlow/PropertyDataFlow.cs
index 2128b8e41..15508baca 100644
--- a/test/Mono.Linker.Tests.Cases/DataFlow/PropertyDataFlow.cs
+++ b/test/Mono.Linker.Tests.Cases/DataFlow/PropertyDataFlow.cs
@@ -45,6 +45,9 @@ namespace Mono.Linker.Tests.Cases.DataFlow
BasePropertyAccess.Test ();
AccessReturnedInstanceProperty.Test ();
+
+ ExplicitIndexerAccess.Test ();
+ ImplicitIndexerAccess.Test ();
}
[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors)]
@@ -653,6 +656,85 @@ namespace Mono.Linker.Tests.Cases.DataFlow
}
}
+ class ExplicitIndexerAccess
+ {
+ [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
+ Type this[Index idx] {
+ get => throw new NotImplementedException ();
+ set => throw new NotImplementedException ();
+ }
+
+ [ExpectedWarning ("IL2072", "this[Index].get", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL2072", "Item.get", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = ProducedBy.Trimmer)]
+ static void TestRead (ExplicitIndexerAccess instance = null)
+ {
+ instance[new Index (1)].RequiresAll ();
+ }
+
+ [ExpectedWarning ("IL2072", nameof (GetTypeWithPublicConstructors), "this[Index].set", ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL2072", nameof (GetTypeWithPublicConstructors), "Item.set", ProducedBy = ProducedBy.Trimmer)]
+ static void TestWrite (ExplicitIndexerAccess instance = null)
+ {
+ instance[^1] = GetTypeWithPublicConstructors ();
+ }
+
+ public static void Test ()
+ {
+ TestRead ();
+ TestWrite ();
+ }
+ }
+
+ class ImplicitIndexerAccess
+ {
+ [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
+ Type this[int idx] {
+ get => throw new NotImplementedException ();
+ set => throw new NotImplementedException ();
+ }
+
+ int Length => throw new NotImplementedException ();
+
+ [ExpectedWarning ("IL2072", "this[Int32].get", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL2072", "Item.get", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = ProducedBy.Trimmer)]
+ static void TestRead (ImplicitIndexerAccess instance = null)
+ {
+ instance[new Index (1)].RequiresAll ();
+ }
+
+ [ExpectedWarning ("IL2072", nameof (GetTypeWithPublicConstructors), "this[Int32].set", ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL2072", nameof (GetTypeWithPublicConstructors), "Item.set", ProducedBy = ProducedBy.Trimmer)]
+ static void TestWrite (ImplicitIndexerAccess instance = null)
+ {
+ instance[^1] = GetTypeWithPublicConstructors ();
+ }
+
+ [ExpectedWarning ("IL2072", nameof (GetUnknownType), "this[Int32].set", ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL2072", nameof (GetUnknownType), "Item.set", ProducedBy = ProducedBy.Trimmer)]
+ static void TestNullCoalescingAssignment (ImplicitIndexerAccess instance = null)
+ {
+ instance[new Index (1)] ??= GetUnknownType ();
+ }
+
+ [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll))]
+ static void TestSpanIndexerAccess (int start = 0, int end = 3)
+ {
+ Span<byte> bytes = stackalloc byte[4] { 1, 2, 3, 4 };
+ bytes[^4] = 0; // This calls the get indexer which has a ref return.
+ int index = bytes[0];
+ Type[] types = new Type[] { GetUnknownType () };
+ types[index].RequiresAll ();
+ }
+
+ public static void Test ()
+ {
+ TestRead ();
+ TestWrite ();
+ TestNullCoalescingAssignment ();
+ TestSpanIndexerAccess ();
+ }
+ }
+
[return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
private static Type GetTypeWithPublicParameterlessConstructor ()
{