diff --git a/src/ILLink.Tasks/LinkTask.cs b/src/ILLink.Tasks/LinkTask.cs index 8f1da1572638..11da51673d5b 100644 --- a/src/ILLink.Tasks/LinkTask.cs +++ b/src/ILLink.Tasks/LinkTask.cs @@ -67,6 +67,25 @@ public class ILLink : ToolTask /// public string Warn { get; set; } + /// + /// Treat all warnings as errors. + /// Maps to '--warnaserror' if true, '--warnaserror-' if false. + /// + public bool TreatWarningsAsErrors { set => _treatWarningsAsErrors = value; } + bool? _treatWarningsAsErrors; + + /// + /// The list of warnings to report as errors. + /// Maps to '--warnaserror LIST-OF-WARNINGS'. + /// + public string WarningsAsErrors { get; set; } + + /// + /// The list of warnings to report as usual. + /// Maps to '--warnaserror- LIST-OF-WARNINGS'. + /// + public string WarningsNotAsErrors { get; set; } + /// /// A list of XML root descriptor files specifying linker /// roots at a granular level. See the mono/linker @@ -315,6 +334,17 @@ protected override string GenerateResponseFileCommands () if (Warn != null) args.Append ("--warn ").AppendLine (Quote (Warn)); + if (_treatWarningsAsErrors is bool treatWarningsAsErrors && treatWarningsAsErrors) + args.Append ("--warnaserror "); + else + args.Append ("--warnaserror- "); + + if (WarningsAsErrors != null) + args.Append ("--warnaserror ").AppendLine (Quote (WarningsAsErrors)); + + if (WarningsNotAsErrors != null) + args.Append ("--warnaserror- ").AppendLine (Quote (WarningsNotAsErrors)); + // Add global optimization arguments if (_beforeFieldInit is bool beforeFieldInit) SetOpt (args, "beforefieldinit", beforeFieldInit); diff --git a/src/linker/Linker/Driver.cs b/src/linker/Linker/Driver.cs index 2635fce7fd96..e75553021d63 100644 --- a/src/linker/Linker/Driver.cs +++ b/src/linker/Linker/Driver.cs @@ -777,7 +777,7 @@ string Unquote (string arg) value = Unquote (value); string[] values = value.Split (new char[] { ',', ';', ' ' }, StringSplitOptions.RemoveEmptyEntries); - HashSet noWarnCodes = new HashSet (); + HashSet warningCodes = new HashSet (); foreach (string id in values) { if (!id.StartsWith ("IL", StringComparison.Ordinal)) continue; @@ -785,10 +785,10 @@ string Unquote (string arg) var warningCode = id.Substring (2); if (ushort.TryParse (warningCode, out ushort code) && code > 2000 && code <= 6000) - noWarnCodes.Add (code); + warningCodes.Add (code); } - return noWarnCodes; + return warningCodes; } private static Assembly GetCustomAssembly (string arg) diff --git a/test/ILLink.Tasks.Tests/ILLink.Tasks.Tests.cs b/test/ILLink.Tasks.Tests/ILLink.Tasks.Tests.cs index 0822da7635b2..42c52f12ff06 100644 --- a/test/ILLink.Tasks.Tests/ILLink.Tasks.Tests.cs +++ b/test/ILLink.Tasks.Tests/ILLink.Tasks.Tests.cs @@ -4,13 +4,9 @@ using System.Linq; using System.Reflection; using Xunit; -using Xunit.Abstractions; -using Xunit.Sdk; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; -using ILLink.Tasks; using Mono.Linker; -using Mono.Linker.Steps; namespace ILLink.Tasks.Tests { @@ -306,6 +302,43 @@ public void TestWarn (string warnArg, WarnVersion expectedVersion) } } +#nullable enable + [Theory] + [InlineData (true, null, null, new uint[] { }, new uint[] { })] + [InlineData (false, "IL1001,IL####,IL2000,IL2021,IL2022", null, + new uint[] { 2021, 2022 }, new uint[] { })] + [InlineData (false, "IL2023,IL6000;IL5042 IL2040", "IL4000,IL4001;IL4002 IL4003", + new uint[] { 2023, 2040, 5042, 6000 }, new uint[] { 4000, 4001, 4002, 4003 })] + [InlineData (false, "IL3000;IL3000;ABCD", "IL2005 il3000 IL2005", + new uint[] { 3000 }, new uint[] { 2005 })] + [InlineData (true, null, "IL2006", new uint[] { }, new uint[] { 2006 })] + [InlineData (true, "IL2001", "IL2001", new uint[] { }, new uint[] { 2001 })] + public void TestWarningsAsErrors (bool treatWarningsAsErrors, string? warningsAsErrors, string? warningsNotAsErrors, uint[] warnAsError, uint[] warnNotAsError) + { + var task = new MockTask () { + TreatWarningsAsErrors = treatWarningsAsErrors, + WarningsAsErrors = warningsAsErrors, + WarningsNotAsErrors = warningsNotAsErrors + }; + + using (var driver = task.CreateDriver ()) { + var actualWarnAsError = driver.Context.WarnAsError; + var actualGeneralWarnAsError = driver.Context.GeneralWarnAsError; + Assert.Equal (actualWarnAsError.Count, warnAsError.Distinct ().Count () + warnNotAsError.Distinct ().Count ()); + Assert.Equal (actualGeneralWarnAsError, treatWarningsAsErrors); + if (warnAsError.Length > 0) { + foreach (var warningCode in warnAsError) + Assert.True (actualWarnAsError.ContainsKey (warningCode) && actualWarnAsError[warningCode] == true); + } + + if (warnNotAsError.Length > 0) { + foreach (var warningCode in warnNotAsError) + Assert.True (actualWarnAsError.ContainsKey (warningCode) && actualWarnAsError[warningCode] == false); + } + } + } +#nullable disable + public static IEnumerable CustomDataCases => new List { new object [] { new ITaskItem [] { diff --git a/test/ILLink.Tasks.Tests/Mock.cs b/test/ILLink.Tasks.Tests/Mock.cs index 4b912f3a77e5..c62447986196 100644 --- a/test/ILLink.Tasks.Tests/Mock.cs +++ b/test/ILLink.Tasks.Tests/Mock.cs @@ -45,7 +45,8 @@ public void SetOptimization (string optimization, bool enabled) static readonly string[] nonOptimizationBooleanProperties = new string[] { "DumpDependencies", - "RemoveSymbols" + "RemoveSymbols", + "TreatWarningsAsErrors" }; public static IEnumerable GetOptimizationPropertyNames ()