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-05-02 22:15:42 +0300
committerGitHub <noreply@github.com>2022-05-02 22:15:42 +0300
commit05a3b652d525acaac1307221b62db979d0108692 (patch)
treea022115eb1dfde9ec5ba2b1dc3e6acf4aa6b73c9
parent2375cba1a60713f83da1ba09c44faa17e9ad432c (diff)
Add ability for the analyzer to recognize const fields (#2774)
This means the value of the fields is tracked as a const value instead of a field reference. This is to support some additional code patterns as well as align the behavior with the linker. Compiler will inline the const fields into the IL effectively removing the field refernce in these cases and linker only sees the constant. So ideally the analyzer should have a similar behavior.
-rw-r--r--src/ILLink.RoslynAnalyzer/TrimAnalysis/TrimAnalysisVisitor.cs44
-rw-r--r--test/Mono.Linker.Tests.Cases/DataFlow/GetTypeDataFlow.cs17
2 files changed, 47 insertions, 14 deletions
diff --git a/src/ILLink.RoslynAnalyzer/TrimAnalysis/TrimAnalysisVisitor.cs b/src/ILLink.RoslynAnalyzer/TrimAnalysis/TrimAnalysisVisitor.cs
index 0225087e8..24b81e832 100644
--- a/src/ILLink.RoslynAnalyzer/TrimAnalysis/TrimAnalysisVisitor.cs
+++ b/src/ILLink.RoslynAnalyzer/TrimAnalysis/TrimAnalysisVisitor.cs
@@ -55,19 +55,8 @@ namespace ILLink.RoslynAnalyzer.TrimAnalysis
// If the return value is empty (TopValue basically) and the Operation tree
// reports it as having a constant value, use that as it will automatically cover
// cases we don't need/want to handle.
- if (operation != null && returnValue.IsEmpty () && operation.ConstantValue.HasValue) {
- object? constantValue = operation.ConstantValue.Value;
- if (constantValue == null)
- return NullValue.Instance;
- else if (operation.Type?.SpecialType == SpecialType.System_String && constantValue is string stringConstantValue)
- return new KnownStringValue (stringConstantValue);
- else if (operation.Type?.TypeKind == TypeKind.Enum && constantValue is int enumConstantValue)
- return new ConstIntValue (enumConstantValue);
- else if (operation.Type?.SpecialType == SpecialType.System_Int32 && constantValue is int intConstantValue)
- return new ConstIntValue (intConstantValue);
- else if (operation.Type?.SpecialType == SpecialType.System_Boolean && constantValue is bool boolConstantValue)
- return new ConstIntValue (boolConstantValue ? 1 : 0);
- }
+ if (operation != null && returnValue.IsEmpty () && TryGetConstantValue (operation, out var constValue))
+ return constValue;
return returnValue;
}
@@ -139,6 +128,9 @@ namespace ILLink.RoslynAnalyzer.TrimAnalysis
}
}
+ if (TryGetConstantValue (fieldRef, out var constValue))
+ return constValue;
+
if (fieldRef.Field.Type.IsTypeInterestingForDataflow ())
return new FieldValue (fieldRef.Field);
@@ -297,5 +289,31 @@ namespace ILLink.RoslynAnalyzer.TrimAnalysis
);
}
}
+
+ static bool TryGetConstantValue (IOperation operation, out MultiValue constValue)
+ {
+ if (operation.ConstantValue.HasValue) {
+ object? constantValue = operation.ConstantValue.Value;
+ if (constantValue == null) {
+ constValue = NullValue.Instance;
+ return true;
+ } else if (operation.Type?.SpecialType == SpecialType.System_String && constantValue is string stringConstantValue) {
+ constValue = new KnownStringValue (stringConstantValue);
+ return true;
+ } else if (operation.Type?.TypeKind == TypeKind.Enum && constantValue is int enumConstantValue) {
+ constValue = new ConstIntValue (enumConstantValue);
+ return true;
+ } else if (operation.Type?.SpecialType == SpecialType.System_Int32 && constantValue is int intConstantValue) {
+ constValue = new ConstIntValue (intConstantValue);
+ return true;
+ } else if (operation.Type?.SpecialType == SpecialType.System_Boolean && constantValue is bool boolConstantValue) {
+ constValue = new ConstIntValue (boolConstantValue ? 1 : 0);
+ return true;
+ }
+ }
+
+ constValue = default;
+ return false;
+ }
}
}
diff --git a/test/Mono.Linker.Tests.Cases/DataFlow/GetTypeDataFlow.cs b/test/Mono.Linker.Tests.Cases/DataFlow/GetTypeDataFlow.cs
index dff625716..ef58eac31 100644
--- a/test/Mono.Linker.Tests.Cases/DataFlow/GetTypeDataFlow.cs
+++ b/test/Mono.Linker.Tests.Cases/DataFlow/GetTypeDataFlow.cs
@@ -34,6 +34,7 @@ namespace Mono.Linker.Tests.Cases.DataFlow
TestStringEmpty ();
TypeWithWarnings.Test ();
+ OverConstTypeName.Test ();
// TODO:
// Test multi-value returns
@@ -163,7 +164,6 @@ namespace Mono.Linker.Tests.Cases.DataFlow
class TypeWithWarnings
{
-
[RequiresUnreferencedCode ("--Method1--")]
public void Method1 () { }
@@ -179,6 +179,21 @@ namespace Mono.Linker.Tests.Cases.DataFlow
}
}
+ class OverConstTypeName
+ {
+ private const string s_ConstTypeName = "Mono.Linker.Tests.Cases.DataFlow." + nameof (GetTypeDataFlow) + "+" + nameof (OverConstTypeName);
+
+ [RequiresUnreferencedCode ("--Method1--")]
+ public void Method1 () { }
+
+ // https://github.com/dotnet/linker/issues/2273
+ [ExpectedWarning ("IL2026", "--Method1--", ProducedBy = ProducedBy.Trimmer)]
+ public static void Test ()
+ {
+ Type.GetType (s_ConstTypeName).RequiresPublicMethods ();
+ }
+ }
+
[return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
private static string GetStringTypeWithPublicParameterlessConstructor ()
{