diff options
author | Vitek Karas <10670590+vitek-karas@users.noreply.github.com> | 2022-07-29 23:18:27 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-07-29 23:18:27 +0300 |
commit | 463997e35e52578343fb87f53df8d62248efa83f (patch) | |
tree | 6f444d6ef625618a9c096cdbb28ae11e74a31a77 | |
parent | 27b0c91329125f07e73d5c366b8a0cd9fdd12bb7 (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
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> |