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:
authorVitek Karas <10670590+vitek-karas@users.noreply.github.com>2022-07-29 23:18:27 +0300
committerGitHub <noreply@github.com>2022-07-29 23:18:27 +0300
commit463997e35e52578343fb87f53df8d62248efa83f (patch)
tree6f444d6ef625618a9c096cdbb28ae11e74a31a77
parent27b0c91329125f07e73d5c366b8a0cd9fdd12bb7 (diff)
Add an interesting test case for compiler generated code marking (#2928)
See the test for description of what it does. It's basically the linker repro for the case hit in https://github.com/dotnet/runtime/issues/73027#issuecomment-1199199943
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/DataFlowTests.g.cs6
-rw-r--r--test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeInPreservedAssembly.cs78
-rw-r--r--test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeInPreservedAssembly.xml4
3 files changed, 88 insertions, 0 deletions
diff --git a/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/DataFlowTests.g.cs b/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/DataFlowTests.g.cs
index 068327632..4a1848513 100644
--- a/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/DataFlowTests.g.cs
+++ b/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/DataFlowTests.g.cs
@@ -8,6 +8,12 @@ namespace ILLink.RoslynAnalyzer.Tests
{
[Fact]
+ public Task CompilerGeneratedCodeInPreservedAssembly ()
+ {
+ return RunTest (allowMissingWarnings: true);
+ }
+
+ [Fact]
public Task MethodByRefParameterDataFlow ()
{
return RunTest (allowMissingWarnings: true);
diff --git a/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeInPreservedAssembly.cs b/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeInPreservedAssembly.cs
new file mode 100644
index 000000000..6cf5fe3eb
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeInPreservedAssembly.cs
@@ -0,0 +1,78 @@
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Helpers;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.DataFlow
+{
+ // This test tries to hit a case where the entire assemly is preserved (via descriptor, NOT action)
+ // meaning we will go and mark all types and members in it.
+ // At the same time there's a compiler generated method (local function) which is called from
+ // a branch which will be removed due to constant propagation.
+ // And also the test is structured such that the caller of the local function is first seen
+ // by the compiler generated code caches after its body has been modified.
+ [SkipKeptItemsValidation]
+ [ExpectedNoWarnings]
+ [SetupLinkerArgument ("--enable-opt", "ipconstprop")]
+ [SetupLinkerDescriptorFile ("CompilerGeneratedCodeInPreservedAssembly.xml")]
+ class CompilerGeneratedCodeInPreservedAssembly
+ {
+ public static void Main ()
+ {
+ Inner.WithLocalFunctionInner ();
+ WithLocalFunction ();
+ }
+
+ class Inner
+ {
+ // In this case the compiler generated state will see the modified body
+ // and thus will see the local function as orphaned.
+ // The method will be marked (due to the descriptor), but its data flow processing
+ // will be skipped (it's compiler generated).
+ // The user method will also not be scanned for data flow since it won't
+ // see the local function as its child.
+ public static void WithLocalFunctionInner ()
+ {
+ if (AlwaysFalse) {
+ LocalWithWarning ();
+ }
+
+ // Analyzer doesn't implement constant propagation and branch removal, so it reaches this code
+ [ExpectedWarning ("IL2026", ProducedBy = ProducedBy.Analyzer)]
+ void LocalWithWarning ()
+ {
+ // No warning
+ Requires ();
+ }
+ }
+ }
+
+ // In this case the compiler generated state will currently see the original method body
+ // so if will treat LocalWithWarning local function as a "callee" of the user method.
+ // This will trigger data flow analysis for the WithLocalFunction, but no warning is produced
+ // because the local function is never reached during the interprocedural scan.
+ public static void WithLocalFunction ()
+ {
+ if (AlwaysFalse) {
+ LocalWithWarning ();
+ }
+
+ // Analyzer doesn't implement constant propagation and branch removal, so it reaches this code
+ [ExpectedWarning ("IL2026", ProducedBy = ProducedBy.Analyzer)]
+ void LocalWithWarning ()
+ {
+ Requires ();
+ }
+ }
+
+ public static bool AlwaysFalse => false;
+
+ [RequiresUnreferencedCode ("RUC")]
+ static void Requires () { }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeInPreservedAssembly.xml b/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeInPreservedAssembly.xml
new file mode 100644
index 000000000..4d6344db7
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeInPreservedAssembly.xml
@@ -0,0 +1,4 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ </assembly>
+</linker>