diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets
index e54323ccb4040..38890b1f7e3d0 100644
--- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets
+++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets
@@ -28,6 +28,7 @@ The .NET Foundation licenses this file to you under the MIT license.
true
true
false
+ $(TreatWarningsAsErrors)
<_IsiOSLikePlatform Condition="'$(_targetOS)' == 'maccatalyst' or $(_targetOS.StartsWith('ios')) or $(_targetOS.StartsWith('tvos'))">true
<_IsApplePlatform Condition="'$(_targetOS)' == 'osx' or '$(_IsiOSLikePlatform)' == 'true'">true
@@ -268,6 +269,9 @@ The .NET Foundation licenses this file to you under the MIT license.
+
+
+
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/BodySubstitutionParser.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/BodySubstitutionParser.cs
index 8903274162f53..979ade817b3d2 100644
--- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/BodySubstitutionParser.cs
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/BodySubstitutionParser.cs
@@ -72,11 +72,15 @@ protected override void ProcessMethod(TypeDesc type, XPathNavigator methodNav, o
_methodSubstitutions.Add(method, BodySubstitution.ThrowingBody);
break;
case "stub":
- BodySubstitution stubBody;
+ BodySubstitution stubBody = null;
if (method.Signature.ReturnType.IsVoid)
stubBody = BodySubstitution.EmptyBody;
else
- stubBody = BodySubstitution.Create(TryCreateSubstitution(method.Signature.ReturnType, GetAttribute(methodNav, "value")));
+ {
+ object substitution = TryCreateSubstitution(method.Signature.ReturnType, GetAttribute(methodNav, "value"));
+ if (substitution != null)
+ stubBody = BodySubstitution.Create(substitution);
+ }
if (stubBody != null)
{
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Logger.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Logger.cs
index aa7a3ccad51f1..182d84900f57e 100644
--- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Logger.cs
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Logger.cs
@@ -34,6 +34,9 @@ public class Logger
private readonly HashSet _trimWarnedAssemblies = new HashSet(StringComparer.OrdinalIgnoreCase);
private readonly HashSet _aotWarnedAssemblies = new HashSet(StringComparer.OrdinalIgnoreCase);
+ private readonly bool _treatWarningsAsErrors;
+ private readonly Dictionary _warningsAsErrors;
+
public static Logger Null = new Logger(new TextLogWriter(TextWriter.Null), null, false);
public bool IsVerbose { get; }
@@ -46,7 +49,9 @@ public Logger(
bool singleWarn,
IEnumerable singleWarnEnabledModules,
IEnumerable singleWarnDisabledModules,
- IEnumerable suppressedCategories)
+ IEnumerable suppressedCategories,
+ bool treatWarningsAsErrors,
+ IDictionary warningsAsErrors)
{
_logWriter = writer;
IsVerbose = isVerbose;
@@ -55,17 +60,19 @@ public Logger(
_singleWarnEnabledAssemblies = new HashSet(singleWarnEnabledModules, StringComparer.OrdinalIgnoreCase);
_singleWarnDisabledAssemblies = new HashSet(singleWarnDisabledModules, StringComparer.OrdinalIgnoreCase);
_suppressedCategories = new HashSet(suppressedCategories, StringComparer.Ordinal);
+ _treatWarningsAsErrors = treatWarningsAsErrors;
+ _warningsAsErrors = new Dictionary(warningsAsErrors);
_compilerGeneratedState = ilProvider == null ? null : new CompilerGeneratedState(ilProvider, this);
_unconditionalSuppressMessageAttributeState = new UnconditionalSuppressMessageAttributeState(_compilerGeneratedState, this);
}
- public Logger(TextWriter writer, ILProvider ilProvider, bool isVerbose, IEnumerable suppressedWarnings, bool singleWarn, IEnumerable singleWarnEnabledModules, IEnumerable singleWarnDisabledModules, IEnumerable suppressedCategories)
- : this(new TextLogWriter(writer), ilProvider, isVerbose, suppressedWarnings, singleWarn, singleWarnEnabledModules, singleWarnDisabledModules, suppressedCategories)
+ public Logger(TextWriter writer, ILProvider ilProvider, bool isVerbose, IEnumerable suppressedWarnings, bool singleWarn, IEnumerable singleWarnEnabledModules, IEnumerable singleWarnDisabledModules, IEnumerable suppressedCategories, bool treatWarningsAsErrors, IDictionary warningsAsErrors)
+ : this(new TextLogWriter(writer), ilProvider, isVerbose, suppressedWarnings, singleWarn, singleWarnEnabledModules, singleWarnDisabledModules, suppressedCategories, treatWarningsAsErrors, warningsAsErrors)
{
}
public Logger(ILogWriter writer, ILProvider ilProvider, bool isVerbose)
- : this(writer, ilProvider, isVerbose, Array.Empty(), singleWarn: false, Array.Empty(), Array.Empty(), Array.Empty())
+ : this(writer, ilProvider, isVerbose, Array.Empty(), singleWarn: false, Array.Empty(), Array.Empty(), Array.Empty(), false, new Dictionary())
{
}
@@ -155,10 +162,13 @@ internal bool IsWarningSuppressed(int code, MessageOrigin origin)
return _unconditionalSuppressMessageAttributeState.IsSuppressed(code, origin);
}
- internal static bool IsWarningAsError(int _/*code*/)
+ internal bool IsWarningAsError(int warningCode)
{
- // TODO: warnaserror
- return false;
+ bool value;
+ if (_treatWarningsAsErrors)
+ return !_warningsAsErrors.TryGetValue(warningCode, out value) || value;
+
+ return _warningsAsErrors.TryGetValue(warningCode, out value) && value;
}
internal bool IsSingleWarn(ModuleDesc owningModule, string messageSubcategory)
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Logging/MessageContainer.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Logging/MessageContainer.cs
index 0d7f824599a00..78a1f8da4429c 100644
--- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Logging/MessageContainer.cs
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Logging/MessageContainer.cs
@@ -131,7 +131,7 @@ internal static MessageContainer CreateErrorMessage(MessageOrigin? origin, Diagn
if (TryLogSingleWarning(context, code, origin, subcategory))
return null;
- if (Logger.IsWarningAsError(code))
+ if (context.IsWarningAsError(code))
return new MessageContainer(MessageCategory.WarningAsError, text, code, subcategory, origin);
return new MessageContainer(MessageCategory.Warning, text, code, subcategory, origin);
@@ -148,7 +148,7 @@ internal static MessageContainer CreateErrorMessage(MessageOrigin? origin, Diagn
if (TryLogSingleWarning(context, (int)id, origin, subcategory))
return null;
- if (Logger.IsWarningAsError((int)id))
+ if (context.IsWarningAsError((int)id))
return new MessageContainer(MessageCategory.WarningAsError, id, subcategory, origin, args);
return new MessageContainer(MessageCategory.Warning, id, subcategory, origin, args);
diff --git a/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/ILCompilerOptions.cs b/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/ILCompilerOptions.cs
index d7ae07095635a..e23c1902ee5ae 100644
--- a/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/ILCompilerOptions.cs
+++ b/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/ILCompilerOptions.cs
@@ -16,5 +16,8 @@ public class ILCompilerOptions
public List Descriptors = new List ();
public bool FrameworkCompilation;
public bool SingleWarn;
+ public List SubstitutionFiles = new List ();
+ public bool TreatWarningsAsErrors;
+ public Dictionary WarningsAsErrors = new Dictionary ();
}
}
diff --git a/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/TrimmingArgumentBuilder.cs b/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/TrimmingArgumentBuilder.cs
index b32391dad4b17..1d075aeffeb35 100644
--- a/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/TrimmingArgumentBuilder.cs
+++ b/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/TrimmingArgumentBuilder.cs
@@ -147,6 +147,7 @@ public virtual void AddStripLinkAttributes (bool stripLinkAttributes)
public virtual void AddSubstitutions (string file)
{
+ Options.SubstitutionFiles.Add (file);
}
public virtual void AddLinkAttributes (string file)
@@ -161,6 +162,30 @@ public virtual void AddAdditionalArgument (string flag, string[] values)
else if (flag == "--singlewarn") {
Options.SingleWarn = true;
}
+ else if (flag.StartsWith("--warnaserror"))
+ {
+ if (flag == "--warnaserror" || flag == "--warnaserror+")
+ {
+ if (values.Length == 0)
+ Options.TreatWarningsAsErrors = true;
+ else
+ {
+ foreach (int warning in ProcessWarningCodes(values))
+ Options.WarningsAsErrors[warning] = true;
+ }
+
+ }
+ else if (flag == "--warnaserror-")
+ {
+ if (values.Length == 0)
+ Options.TreatWarningsAsErrors = false;
+ else
+ {
+ foreach (int warning in ProcessWarningCodes(values))
+ Options.WarningsAsErrors[warning] = false;
+ }
+ }
+ }
}
public virtual void ProcessTestInputAssembly (NPath inputAssemblyPath)
@@ -261,6 +286,23 @@ private static void AppendExpandedPaths (Dictionary dictionary,
}
}
+ private static readonly char[] s_separator = new char[] { ',', ';', ' ' };
+
+ private static IEnumerable ProcessWarningCodes(IEnumerable warningCodes)
+ {
+ foreach (string value in warningCodes)
+ {
+ string[] values = value.Split(s_separator, StringSplitOptions.RemoveEmptyEntries);
+ foreach (string id in values)
+ {
+ if (!id.StartsWith("IL", StringComparison.Ordinal) || !ushort.TryParse(id.AsSpan(2), out ushort code))
+ continue;
+
+ yield return code;
+ }
+ }
+ }
+
public ILCompilerOptions Build ()
{
var options = Options;
diff --git a/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/TrimmingDriver.cs b/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/TrimmingDriver.cs
index f141e8e998212..9000ee5b2475c 100644
--- a/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/TrimmingDriver.cs
+++ b/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/TrimmingDriver.cs
@@ -7,6 +7,7 @@
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
+using System.Xml;
using ILCompiler;
using ILCompiler.Dataflow;
using ILLink.Shared.TrimAnalysis;
@@ -84,15 +85,33 @@ public ILScanResults Trim (ILCompilerOptions options, TrimmingCustomizations? cu
options.SingleWarn,
singleWarnEnabledModules: Enumerable.Empty (),
singleWarnDisabledModules: Enumerable.Empty (),
- suppressedCategories: Enumerable.Empty ());
+ suppressedCategories: Enumerable.Empty (),
+ treatWarningsAsErrors: options.TreatWarningsAsErrors,
+ warningsAsErrors: options.WarningsAsErrors);
foreach (var descriptor in options.Descriptors) {
if (!File.Exists (descriptor))
throw new FileNotFoundException ($"'{descriptor}' doesn't exist");
compilationRoots.Add (new ILCompiler.DependencyAnalysis.TrimmingDescriptorNode (descriptor));
}
-
- ilProvider = new FeatureSwitchManager (ilProvider, logger, options.FeatureSwitches, default);
+
+ var featureSwitches = options.FeatureSwitches;
+ BodyAndFieldSubstitutions substitutions = default;
+ IReadOnlyDictionary>? resourceBlocks = default;
+ foreach (string substitutionFilePath in options.SubstitutionFiles)
+ {
+ using FileStream fs = File.OpenRead(substitutionFilePath);
+ substitutions.AppendFrom(BodySubstitutionsParser.GetSubstitutions(
+ logger, typeSystemContext, XmlReader.Create(fs), substitutionFilePath, featureSwitches));
+
+ fs.Seek(0, SeekOrigin.Begin);
+
+ resourceBlocks = ManifestResourceBlockingPolicy.UnionBlockings(resourceBlocks,
+ ManifestResourceBlockingPolicy.SubstitutionsReader.GetSubstitutions(
+ logger, typeSystemContext, XmlReader.Create(fs), substitutionFilePath, featureSwitches));
+ }
+
+ ilProvider = new FeatureSwitchManager(ilProvider, logger, featureSwitches, substitutions);
CompilerGeneratedState compilerGeneratedState = new CompilerGeneratedState (ilProvider, logger);
diff --git a/src/coreclr/tools/aot/ILCompiler/ILCompilerRootCommand.cs b/src/coreclr/tools/aot/ILCompiler/ILCompilerRootCommand.cs
index 84f9c5acd9444..917f1b612942e 100644
--- a/src/coreclr/tools/aot/ILCompiler/ILCompilerRootCommand.cs
+++ b/src/coreclr/tools/aot/ILCompiler/ILCompilerRootCommand.cs
@@ -129,6 +129,12 @@ internal sealed class ILCompilerRootCommand : CliRootCommand
new("--singlewarnassembly") { DefaultValueFactory = _ => Array.Empty(), Description = "Generate single AOT/trimming warning for given assembly" };
public CliOption SingleWarnDisabledAssemblies { get; } =
new("--nosinglewarnassembly") { DefaultValueFactory = _ => Array.Empty(), Description = "Expand AOT/trimming warnings for given assembly" };
+ public CliOption TreatWarningsAsErrors { get; } =
+ new("--warnaserror") { Description = "Treat warnings as errors" };
+ public CliOption WarningsAsErrorsEnable { get; } =
+ new("--warnaserr") { Description = "Enable treating specific warnings as errors" };
+ public CliOption WarningsAsErrorsDisable { get; } =
+ new("--nowarnaserr") { Description = "Disable treating specific warnings as errors" };
public CliOption DirectPInvokes { get; } =
new("--directpinvoke") { DefaultValueFactory = _ => Array.Empty(), Description = "PInvoke to call directly" };
public CliOption DirectPInvokeLists { get; } =
@@ -225,6 +231,9 @@ public ILCompilerRootCommand(string[] args) : base(".NET Native IL Compiler")
Options.Add(NoAotWarn);
Options.Add(SingleWarnEnabledAssemblies);
Options.Add(SingleWarnDisabledAssemblies);
+ Options.Add(TreatWarningsAsErrors);
+ Options.Add(WarningsAsErrorsEnable);
+ Options.Add(WarningsAsErrorsDisable);
Options.Add(DirectPInvokes);
Options.Add(DirectPInvokeLists);
Options.Add(MaxGenericCycleDepth);
diff --git a/src/coreclr/tools/aot/ILCompiler/Program.cs b/src/coreclr/tools/aot/ILCompiler/Program.cs
index 0ff5cd87b5ffe..09ec67cfd2a14 100644
--- a/src/coreclr/tools/aot/ILCompiler/Program.cs
+++ b/src/coreclr/tools/aot/ILCompiler/Program.cs
@@ -75,8 +75,18 @@ public int Run()
ILProvider ilProvider = new NativeAotILProvider();
+ Dictionary warningsAsErrors = new Dictionary();
+ foreach (int warning in ProcessWarningCodes(Get(_command.WarningsAsErrorsEnable)))
+ {
+ warningsAsErrors[warning] = true;
+ }
+ foreach (int warning in ProcessWarningCodes(Get(_command.WarningsAsErrorsDisable)))
+ {
+ warningsAsErrors[warning] = false;
+ }
var logger = new Logger(Console.Out, ilProvider, Get(_command.IsVerbose), ProcessWarningCodes(Get(_command.SuppressedWarnings)),
- Get(_command.SingleWarn), Get(_command.SingleWarnEnabledAssemblies), Get(_command.SingleWarnDisabledAssemblies), suppressedWarningCategories);
+ Get(_command.SingleWarn), Get(_command.SingleWarnEnabledAssemblies), Get(_command.SingleWarnDisabledAssemblies), suppressedWarningCategories,
+ Get(_command.TreatWarningsAsErrors), warningsAsErrors);
// NativeAOT is full AOT and its pre-compiled methods can not be
// thrown away at runtime if they mismatch in required ISAs or
diff --git a/src/tests/Directory.Build.targets b/src/tests/Directory.Build.targets
index 4352e3a798d7c..e49657c6b8146 100644
--- a/src/tests/Directory.Build.targets
+++ b/src/tests/Directory.Build.targets
@@ -555,6 +555,8 @@
so the default for the test tree is partial. -->
partial
+ false
+
$(CoreCLRILCompilerDir)
$(CoreCLRCrossILCompilerDir)
$(CoreCLRILCompilerDir)netstandard/ILCompiler.Build.Tasks.dll
diff --git a/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/DeadCodeElimination.cs b/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/DeadCodeElimination.cs
index 858ecbbbe4804..58f4e47a69997 100644
--- a/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/DeadCodeElimination.cs
+++ b/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/DeadCodeElimination.cs
@@ -625,6 +625,8 @@ private static void ThrowIfPresent(Type testType, string typeName)
}
}
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2072:UnrecognizedReflectionPattern",
+ Justification = "That's the point")]
private static void ThrowIfPresentWithUsableMethodTable(Type testType, string typeName)
{
Type t = GetTypeSecretly(testType, typeName);
diff --git a/src/tests/nativeaot/SmokeTests/UnitTests/Devirtualization.cs b/src/tests/nativeaot/SmokeTests/UnitTests/Devirtualization.cs
index 5954c6118e669..f2c70d7b1ee60 100644
--- a/src/tests/nativeaot/SmokeTests/UnitTests/Devirtualization.cs
+++ b/src/tests/nativeaot/SmokeTests/UnitTests/Devirtualization.cs
@@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
+using System.Diagnostics.CodeAnalysis;
class Devirtualization
{
@@ -103,6 +104,7 @@ static void AssertEqual(T expected, T actual)
[MethodImpl(MethodImplOptions.NoInlining)]
static void TestIntf2(IIntf2 o, int expected) => AssertEqual(expected, o.GetValue());
+ [UnconditionalSuppressMessage("AOT", "IL3050", Justification = "MakeGenericType - Intentional")]
public static void Run()
{
TestIntf1(new Intf1Impl(), 123);
diff --git a/src/tests/nativeaot/SmokeTests/UnitTests/Generics.cs b/src/tests/nativeaot/SmokeTests/UnitTests/Generics.cs
index 7b414ac3dd183..145d7b3d0c3ea 100644
--- a/src/tests/nativeaot/SmokeTests/UnitTests/Generics.cs
+++ b/src/tests/nativeaot/SmokeTests/UnitTests/Generics.cs
@@ -5,7 +5,12 @@
using System.Reflection;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
+using System.Diagnostics.CodeAnalysis;
+[UnconditionalSuppressMessage("Trimming", "IL2055", Justification = "MakeGenericType - Intentional")]
+[UnconditionalSuppressMessage("Trimming", "IL2060", Justification = "MakeGenericMethod - Intentional")]
+[UnconditionalSuppressMessage("AOT", "IL3050", Justification = "MakeGenericType/MakeGenericMethod - Intentional")]
+[UnconditionalSuppressMessage("AOT", "IL3054", Justification = "Generic expansion aborted - Intentional")]
class Generics
{
internal static int Run()
diff --git a/src/tests/nativeaot/SmokeTests/UnitTests/Interfaces.cs b/src/tests/nativeaot/SmokeTests/UnitTests/Interfaces.cs
index 6c70d13c31a5f..4f34959be84b3 100644
--- a/src/tests/nativeaot/SmokeTests/UnitTests/Interfaces.cs
+++ b/src/tests/nativeaot/SmokeTests/UnitTests/Interfaces.cs
@@ -6,6 +6,7 @@
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
+using System.Diagnostics.CodeAnalysis;
public class Interfaces
{
@@ -1225,6 +1226,7 @@ public static int CallIndirect()
static Type s_fooType = typeof(Foo);
+ [UnconditionalSuppressMessage("AOT", "IL3050", Justification = "MakeGenericType - Intentional")]
public static void Run()
{
Type t = typeof(FrobCaller<>).MakeGenericType(s_fooType);
@@ -1289,6 +1291,7 @@ class Atom { }
static Type s_atomType = typeof(Atom);
+ [UnconditionalSuppressMessage("AOT", "IL3050", Justification = "MakeGenericType - Intentional")]
public static void Run()
{
Type t = typeof(Wrapper<>).MakeGenericType(s_atomType);
@@ -1354,6 +1357,7 @@ class Atom : AtomBase { }
static Type s_atomType = typeof(Atom);
static Type s_atomBaseType = typeof(AtomBase);
+ [UnconditionalSuppressMessage("AOT", "IL3050", Justification = "MakeGenericType - Intentional")]
public static void Run()
{
Type t = typeof(FrobCaller<,>).MakeGenericType(typeof(AbjectFail), s_atomType);
@@ -1576,6 +1580,7 @@ class Gen where T : IFoo
public static string GrabCookie() => T.ImHungryGiveMeCookie();
}
+ [UnconditionalSuppressMessage("AOT", "IL3050", Justification = "MakeGenericType - Intentional")]
public static void Run()
{
var r = (string)typeof(Gen<>).MakeGenericType(typeof(Baz)).GetMethod("GrabCookie").Invoke(null, Array.Empty