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