diff --git a/src/ILLink.RoslynAnalyzer/DiagnosticDescriptors.cs b/src/ILLink.RoslynAnalyzer/DiagnosticDescriptors.cs
index 533435031f6a..30cf74e15267 100644
--- a/src/ILLink.RoslynAnalyzer/DiagnosticDescriptors.cs
+++ b/src/ILLink.RoslynAnalyzer/DiagnosticDescriptors.cs
@@ -1,7 +1,6 @@
// 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 ILLink.Shared;
using Microsoft.CodeAnalysis;
@@ -15,7 +14,7 @@ public static DiagnosticDescriptor GetDiagnosticDescriptor (DiagnosticId diagnos
return new DiagnosticDescriptor (diagnosticId.AsString (),
diagnosticString.GetTitleFormat (),
diagnosticString.GetMessageFormat (),
- GetDiagnosticCategory (diagnosticId),
+ diagnosticId.GetDiagnosticCategory (),
DiagnosticSeverity.Warning,
true);
}
@@ -24,7 +23,7 @@ public static DiagnosticDescriptor GetDiagnosticDescriptor (DiagnosticId diagnos
=> new DiagnosticDescriptor (diagnosticId.AsString (),
diagnosticString.GetTitle (),
diagnosticString.GetMessage (),
- GetDiagnosticCategory (diagnosticId),
+ diagnosticId.GetDiagnosticCategory (),
DiagnosticSeverity.Warning,
true);
@@ -41,7 +40,7 @@ public static DiagnosticDescriptor GetDiagnosticDescriptor (DiagnosticId diagnos
return new DiagnosticDescriptor (diagnosticId.AsString (),
diagnosticString.GetTitleFormat (),
diagnosticString.GetMessageFormat (),
- diagnosticCategory ?? GetDiagnosticCategory (diagnosticId),
+ diagnosticCategory ?? diagnosticId.GetDiagnosticCategory (),
diagnosticSeverity,
isEnabledByDefault,
helpLinkUri);
@@ -50,29 +49,10 @@ public static DiagnosticDescriptor GetDiagnosticDescriptor (DiagnosticId diagnos
return new DiagnosticDescriptor (diagnosticId.AsString (),
lrsTitle!,
lrsMessage!,
- diagnosticCategory ?? GetDiagnosticCategory (diagnosticId),
+ diagnosticCategory ?? diagnosticId.GetDiagnosticCategory (),
diagnosticSeverity,
isEnabledByDefault,
helpLinkUri);
}
-
- static string GetDiagnosticCategory (DiagnosticId diagnosticId)
- {
- switch ((int) diagnosticId) {
- case > 2000 and < 3000:
- return DiagnosticCategory.Trimming;
-
- case >= 3000 and < 3050:
- return DiagnosticCategory.SingleFile;
-
- case >= 3050 and <= 6000:
- return DiagnosticCategory.AOT;
-
- default:
- break;
- }
-
- throw new ArgumentException ($"The provided diagnostic id '{diagnosticId}' does not fall into the range of supported warning codes 2001 to 6000 (inclusive).");
- }
}
}
diff --git a/src/ILLink.Shared/DiagnosticId.cs b/src/ILLink.Shared/DiagnosticId.cs
index cb82b9e0ce0f..c7f5028f2d9d 100644
--- a/src/ILLink.Shared/DiagnosticId.cs
+++ b/src/ILLink.Shared/DiagnosticId.cs
@@ -4,6 +4,8 @@
// This is needed due to NativeAOT which doesn't enable nullable globally yet
#nullable enable
+using System;
+
namespace ILLink.Shared
{
public enum DiagnosticId
@@ -224,5 +226,13 @@ public static string GetDiagnosticSubcategory (this DiagnosticId diagnosticId) =
>= 3054 and <= 3055 => MessageSubCategory.AotAnalysis,
_ => MessageSubCategory.None,
};
+
+ public static string GetDiagnosticCategory (this DiagnosticId diagnosticId) =>
+ (int) diagnosticId switch {
+ > 2000 and < 3000 => DiagnosticCategory.Trimming,
+ >= 3000 and < 3050 => DiagnosticCategory.SingleFile,
+ >= 3050 and <= 6000 => DiagnosticCategory.AOT,
+ _ => throw new ArgumentException ($"The provided diagnostic id '{diagnosticId}' does not fall into the range of supported warning codes 2001 to 6000 (inclusive).")
+ };
}
}
diff --git a/src/ILLink.Shared/TrimAnalysis/DiagnosticContext.cs b/src/ILLink.Shared/TrimAnalysis/DiagnosticContext.cs
index 06353c222852..95c984d7fda5 100644
--- a/src/ILLink.Shared/TrimAnalysis/DiagnosticContext.cs
+++ b/src/ILLink.Shared/TrimAnalysis/DiagnosticContext.cs
@@ -8,6 +8,17 @@ namespace ILLink.Shared.TrimAnalysis
{
readonly partial struct DiagnosticContext
{
+ ///
+ /// The diagnostic context may be entirely disabled or some kinds of warnings may be suppressed.
+ /// The suppressions are determined based on the .
+ /// Typically the suppressions will be based on diagnostic category :
+ /// - Trimmer warnings (suppressed by RequiresUnreferencedCodeAttribute)
+ /// - AOT warnings (suppressed by RequiresDynamicCodeAttribute)
+ /// - Single-file warnings (suppressed by RequiresAssemblyFilesAttribute)
+ /// Note that not all categories are used/supported by all tools, for example the ILLink only handles trimmer warnings and ignores the rest.
+ ///
+ /// The diagnostic ID, this will be used to determine the category of diagnostic (trimmer, AOT, single-file)
+ /// The arguments for diagnostic message.
public partial void AddDiagnostic (DiagnosticId id, params string[] args);
}
}
diff --git a/src/linker/Linker/CompilerGeneratedState.cs b/src/linker/Linker/CompilerGeneratedState.cs
index c019d73fec07..b4116e3ba752 100644
--- a/src/linker/Linker/CompilerGeneratedState.cs
+++ b/src/linker/Linker/CompilerGeneratedState.cs
@@ -104,8 +104,6 @@ public static bool TryGetStateMachineType (MethodDefinition method, [NotNullWhen
///
TypeDefinition? PopulateCacheForType (TypeDefinition type)
{
- var originalType = type;
-
// Look in the declaring type if this is a compiler-generated type (state machine or display class).
// State machines can be emitted into display classes, so we may also need to go one more level up.
// To avoid depending on implementation details, we go up until we see a non-compiler-generated type.
diff --git a/src/linker/Linker/MessageOrigin.cs b/src/linker/Linker/MessageOrigin.cs
index 8919e8e4539a..24d18c065df2 100644
--- a/src/linker/Linker/MessageOrigin.cs
+++ b/src/linker/Linker/MessageOrigin.cs
@@ -120,7 +120,7 @@ public bool Equals (MessageOrigin other) =>
(FileName, Provider, SourceLine, SourceColumn, ILOffset) == (other.FileName, other.Provider, other.SourceLine, other.SourceColumn, other.ILOffset);
public override bool Equals (object? obj) => obj is MessageOrigin messageOrigin && Equals (messageOrigin);
- public override int GetHashCode () => (FileName, Provider, SourceLine, SourceColumn).GetHashCode ();
+ public override int GetHashCode () => (FileName, Provider, SourceLine, SourceColumn, ILOffset).GetHashCode ();
public static bool operator == (MessageOrigin lhs, MessageOrigin rhs) => lhs.Equals (rhs);
public static bool operator != (MessageOrigin lhs, MessageOrigin rhs) => !lhs.Equals (rhs);
diff --git a/test/Mono.Linker.Tests.Cases/DataFlow/AttributeConstructorDataflow.cs b/test/Mono.Linker.Tests.Cases/DataFlow/AttributeConstructorDataflow.cs
index 7f73071d4386..46120679c31a 100644
--- a/test/Mono.Linker.Tests.Cases/DataFlow/AttributeConstructorDataflow.cs
+++ b/test/Mono.Linker.Tests.Cases/DataFlow/AttributeConstructorDataflow.cs
@@ -16,8 +16,10 @@ class AttributeConstructorDataflow
{
[KeptAttributeAttribute (typeof (KeepsPublicConstructorAttribute))]
[KeptAttributeAttribute (typeof (KeepsPublicMethodsAttribute))]
+ [KeptAttributeAttribute (typeof (TypeArrayAttribute))]
[KeepsPublicConstructor (typeof (ClassWithKeptPublicConstructor))]
[KeepsPublicMethods ("Mono.Linker.Tests.Cases.DataFlow.AttributeConstructorDataflow+ClassWithKeptPublicMethods")]
+ [TypeArray (new Type[] { typeof (AttributeConstructorDataflow) })]
// Trimmer only for now - https://github.com/dotnet/linker/issues/2273
[ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethods--", ProducedBy = ProducedBy.Trimmer)]
public static void Main ()
@@ -109,5 +111,15 @@ public void Method () { }
public int Field;
}
}
+
+ [Kept]
+ [KeptBaseType (typeof (Attribute))]
+ class TypeArrayAttribute : Attribute
+ {
+ [Kept]
+ public TypeArrayAttribute (Type[] types) // This should not trigger data flow analysis of the parameter
+ {
+ }
+ }
}
}
diff --git a/test/Mono.Linker.Tests.Cases/DataFlow/AttributeFieldDataflow.cs b/test/Mono.Linker.Tests.Cases/DataFlow/AttributeFieldDataflow.cs
index 44c857b74855..2cac037c5d80 100644
--- a/test/Mono.Linker.Tests.Cases/DataFlow/AttributeFieldDataflow.cs
+++ b/test/Mono.Linker.Tests.Cases/DataFlow/AttributeFieldDataflow.cs
@@ -16,8 +16,10 @@ class AttributeFieldDataflow
{
[KeptAttributeAttribute (typeof (KeepsPublicConstructorsAttribute))]
[KeptAttributeAttribute (typeof (KeepsPublicMethodsAttribute))]
+ [KeptAttributeAttribute (typeof (TypeArrayAttribute))]
[KeepsPublicConstructors (Type = typeof (ClassWithKeptPublicConstructor))]
- [KeepsPublicMethods ("Mono.Linker.Tests.Cases.DataFlow.AttributeFieldDataflow+ClassWithKeptPublicMethods")]
+ [KeepsPublicMethods (Type = "Mono.Linker.Tests.Cases.DataFlow.AttributeFieldDataflow+ClassWithKeptPublicMethods")]
+ [TypeArray (Types = new Type[] { typeof (AttributeFieldDataflow) })]
// Trimmer only for now - https://github.com/dotnet/linker/issues/2273
[ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethods--", ProducedBy = ProducedBy.Trimmer)]
public static void Main ()
@@ -46,12 +48,14 @@ public KeepsPublicConstructorsAttribute ()
class KeepsPublicMethodsAttribute : Attribute
{
[Kept]
- public KeepsPublicMethodsAttribute (
- [KeptAttributeAttribute (typeof (DynamicallyAccessedMembersAttribute))]
- [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
- string type)
+ public KeepsPublicMethodsAttribute ()
{
}
+
+ [Kept]
+ [KeptAttributeAttribute (typeof (DynamicallyAccessedMembersAttribute))]
+ [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
+ public string Type;
}
[Kept]
@@ -74,5 +78,18 @@ class ClassWithKeptPublicMethods
public static void KeptMethod () { }
static void Method () { }
}
+
+ [Kept]
+ [KeptBaseType (typeof (Attribute))]
+ class TypeArrayAttribute : Attribute
+ {
+ [Kept]
+ public TypeArrayAttribute ()
+ {
+ }
+
+ [Kept]
+ public Type[] Types;
+ }
}
}
diff --git a/test/Mono.Linker.Tests.Cases/DataFlow/AttributePropertyDataflow.cs b/test/Mono.Linker.Tests.Cases/DataFlow/AttributePropertyDataflow.cs
index e6848fa5da9a..1b10390ea1cb 100644
--- a/test/Mono.Linker.Tests.Cases/DataFlow/AttributePropertyDataflow.cs
+++ b/test/Mono.Linker.Tests.Cases/DataFlow/AttributePropertyDataflow.cs
@@ -16,8 +16,10 @@ class AttributePropertyDataflow
{
[KeptAttributeAttribute (typeof (KeepsPublicConstructorsAttribute))]
[KeptAttributeAttribute (typeof (KeepsPublicMethodsAttribute))]
+ [KeptAttributeAttribute (typeof (TypeArrayAttribute))]
[KeepsPublicConstructors (Type = typeof (ClassWithKeptPublicConstructor))]
- [KeepsPublicMethods ("Mono.Linker.Tests.Cases.DataFlow.AttributePropertyDataflow+ClassWithKeptPublicMethods")]
+ [KeepsPublicMethods (Type = "Mono.Linker.Tests.Cases.DataFlow.AttributePropertyDataflow+ClassWithKeptPublicMethods")]
+ [TypeArray (Types = new Type[] { typeof (AttributePropertyDataflow) })]
// Trimmer only for now - https://github.com/dotnet/linker/issues/2273
[ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethods--", ProducedBy = ProducedBy.Trimmer)]
public static void Main ()
@@ -47,12 +49,15 @@ public KeepsPublicConstructorsAttribute ()
class KeepsPublicMethodsAttribute : Attribute
{
[Kept]
- public KeepsPublicMethodsAttribute (
- [KeptAttributeAttribute (typeof (DynamicallyAccessedMembersAttribute))]
- [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
- string type)
+ public KeepsPublicMethodsAttribute ()
{
}
+
+ [field: Kept]
+ [Kept]
+ [KeptAttributeAttribute (typeof (DynamicallyAccessedMembersAttribute))]
+ [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
+ public string Type { get; [Kept] set; }
}
[Kept]
@@ -75,5 +80,19 @@ class ClassWithKeptPublicMethods
public static void KeptMethod () { }
static void Method () { }
}
+
+ [Kept]
+ [KeptBaseType (typeof (Attribute))]
+ class TypeArrayAttribute : Attribute
+ {
+ [Kept]
+ public TypeArrayAttribute ()
+ {
+ }
+
+ [field: Kept]
+ [Kept]
+ public Type[] Types { get; [Kept] set; }
+ }
}
}
diff --git a/test/Mono.Linker.Tests.Cases/DataFlow/ByRefDataflow.cs b/test/Mono.Linker.Tests.Cases/DataFlow/ByRefDataflow.cs
index 0b05ededcbc9..a16c455e8563 100644
--- a/test/Mono.Linker.Tests.Cases/DataFlow/ByRefDataflow.cs
+++ b/test/Mono.Linker.Tests.Cases/DataFlow/ByRefDataflow.cs
@@ -125,11 +125,29 @@ static unsafe void IntPtrDeref ()
[RequiresUnreferencedCode ("")]
static IntPtr GetDangerous () { return IntPtr.Zero; }
+ [Kept]
+ [ExpectedWarning ("IL2070")]
+ static unsafe void LocalStackAllocDeref (Type t)
+ {
+ // Code pattern from CoreLib which caused problems in AOT port
+ // so making sure we handle this correctly (that is without failing)
+ int buffSize = 256;
+ byte* stackSpace = stackalloc byte[buffSize];
+ byte* buffer = stackSpace;
+
+ byte* toFree = buffer;
+ buffer = null;
+
+ // IL2070 - this is to make sure that DataFlow ran on the method's body
+ t.GetProperties ();
+ }
+
[Kept]
[ExpectedWarning ("IL2026")]
public static void Test ()
{
IntPtrDeref ();
+ LocalStackAllocDeref (null);
}
}
}