Skip to content

Commit

Permalink
Always show IL2026 for IsTrimmable assemblies (dotnet/linker#2087)
Browse files Browse the repository at this point in the history
Commit migrated from dotnet/linker@caeaf2a
  • Loading branch information
sbomer authored Jun 10, 2021
1 parent 6e2e0c9 commit 5ec83a4
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 15 deletions.
14 changes: 10 additions & 4 deletions src/tools/illink/src/linker/Linker/LinkContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ public class LinkContext : IMetadataResolver, IDisposable
readonly CustomAttributeSource _customAttributes;
readonly List<MessageContainer> _cachedWarningMessageContainers;
readonly ILogger _logger;
readonly Dictionary<AssemblyDefinition, bool> _isTrimmable;

public Pipeline Pipeline {
get { return _pipeline; }
Expand Down Expand Up @@ -210,6 +211,7 @@ public LinkContext (Pipeline pipeline, ILogger logger)
_parameters = new Dictionary<string, string> (StringComparer.Ordinal);
_customAttributes = new CustomAttributeSource (this);
_cachedWarningMessageContainers = new List<MessageContainer> ();
_isTrimmable = new Dictionary<AssemblyDefinition, bool> ();
FeatureSettings = new Dictionary<string, bool> (StringComparer.Ordinal);

SymbolReaderProvider = new DefaultSymbolReaderProvider (false);
Expand Down Expand Up @@ -424,12 +426,15 @@ static bool IsCPPCLIAssembly (ModuleDefinition module)
}
}

bool IsTrimmable (AssemblyDefinition assembly)
public bool IsTrimmable (AssemblyDefinition assembly)
{
if (!assembly.HasCustomAttributes)
return false;
if (_isTrimmable.TryGetValue (assembly, out bool isTrimmable))
return isTrimmable;

bool isTrimmable = false;
if (!assembly.HasCustomAttributes) {
_isTrimmable.Add (assembly, false);
return false;
}

foreach (var ca in assembly.CustomAttributes) {
if (!ca.AttributeType.IsTypeOf<AssemblyMetadataAttribute> ())
Expand All @@ -450,6 +455,7 @@ bool IsTrimmable (AssemblyDefinition assembly)
isTrimmable = true;
}

_isTrimmable.Add (assembly, isTrimmable);
return isTrimmable;
}

Expand Down
41 changes: 30 additions & 11 deletions src/tools/illink/src/linker/Linker/MessageContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,24 +132,43 @@ private static MessageContainer CreateWarningMessageContainer (LinkContext conte
if (version > context.WarnVersion)
return Empty;

if (subcategory == MessageSubCategory.TrimAnalysis) {
Debug.Assert (origin.MemberDefinition != null);
var declaringType = origin.MemberDefinition?.DeclaringType ?? (origin.MemberDefinition as TypeDefinition);
var assembly = declaringType.Module.Assembly;
var assemblyName = assembly?.Name.Name;
if (assemblyName != null && context.IsSingleWarn (assemblyName)) {
if (context.AssembliesWithGeneratedSingleWarning.Add (assemblyName))
context.LogWarning ($"Assembly '{assemblyName}' produced trim warnings. For more information see https://aka.ms/dotnet-illink/libraries", 2104, context.GetAssemblyLocation (assembly));
return Empty;
}
}
if (TryLogSingleWarning (context, code, origin, subcategory))
return Empty;

if (context.IsWarningAsError (code))
return new MessageContainer (MessageCategory.WarningAsError, text, code, subcategory, origin);

return new MessageContainer (MessageCategory.Warning, text, code, subcategory, origin);
}

static bool TryLogSingleWarning (LinkContext context, int code, MessageOrigin origin, string subcategory)
{
if (subcategory != MessageSubCategory.TrimAnalysis)
return false;

Debug.Assert (origin.MemberDefinition != null);
var declaringType = origin.MemberDefinition?.DeclaringType ?? (origin.MemberDefinition as TypeDefinition);
var assembly = declaringType.Module.Assembly;

Debug.Assert (assembly != null);
if (assembly == null)
return false;

// Any IL2026 warnings left in an assembly with an IsTrimmable attribute are considered intentional
// and should not be collapsed, so that the user-visible RUC message gets printed.
if (code == 2026 && context.IsTrimmable (assembly))
return false;

var assemblyName = assembly.Name.Name;
if (!context.IsSingleWarn (assemblyName))
return false;

if (context.AssembliesWithGeneratedSingleWarning.Add (assemblyName))
context.LogWarning ($"Assembly '{assemblyName}' produced trim warnings. For more information see https://aka.ms/dotnet-illink/libraries", 2104, context.GetAssemblyLocation (assembly));

return true;
}

/// <summary>
/// Create a info message.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;

[assembly: AssemblyMetadata ("IsTrimmable", "True")]

namespace Mono.Linker.Tests.Cases.Warnings.Dependencies
{
public class TriggerWarnings_TrimmableLib
{
public static void Main ()
{
RequirePublicMethods (UnknownType ());
RUCIntentional ();
}

static Type UnknownType () => null;

static void RequirePublicMethods ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type) { }

[RequiresUnreferencedCode ("RUC warning left in the trimmable assembly.")]
static void RUCIntentional () { }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using System;
using System.Diagnostics.CodeAnalysis;
using Mono.Linker.Tests.Cases.Expectations.Assertions;
using Mono.Linker.Tests.Cases.Expectations.Metadata;
using Mono.Linker.Tests.Cases.Warnings.Dependencies;

namespace Mono.Linker.Tests.Cases.Warnings
{
[SkipKeptItemsValidation]
[SetupCompileBefore ("library.dll", new[] { typeof (TriggerWarnings_TrimmableLib) })]
[SetupLinkerArgument ("--singlewarn")]
[LogContains (".*warning IL2026: .*TriggerWarnings_TrimmableLib.RUCIntentional.*RUC warning left in the trimmable assembly.*", regexMatch: true)]
[LogDoesNotContain ("IL2072")]
[LogContains ("warning IL2104: Assembly 'library' produced trim warnings")]
[LogDoesNotContain ("IL2026")]
public class WarningsFromTrimmableAssembliesCanSurviveSingleWarn
{
public static void Main ()
{
TriggerWarnings_TrimmableLib.Main ();
}
}
}

0 comments on commit 5ec83a4

Please sign in to comment.