Files
UnrealEngine/Engine/Source/Programs/Shared/UnrealBuildTool.Tests/CppCompileWarningsTests.cs
2025-05-18 13:04:45 +08:00

691 lines
34 KiB
C#

// Copyright Epic Games, Inc. All Rights Reserved.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using EpicGames.Core;
using Microsoft.Extensions.Logging;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using UnrealBuildBase;
using UnrealBuildTool.Tests.TestUtilities;
namespace UnrealBuildTool.Tests
{
[TestClass]
public class CppCompileWarningsTests
{
internal class TestBuildSettingsProvider : IBuildContextProvider
{
internal BuildSettingsVersion _testBuildSettings = BuildSettingsVersion.V1;
public BuildSettingsVersion GetBuildSettings()
{
return _testBuildSettings;
}
}
[DataTestMethod]
[DataRow(WarningLevel.Default, null, true, WarningLevel.Default)] // Null applied, no overwrite
[DataRow(WarningLevel.Default, WarningLevel.Off, true, WarningLevel.Off)] // Overwrite with Off
[DataRow(WarningLevel.Default, WarningLevel.Warning, true, WarningLevel.Warning)] // Overwrite with Warning
[DataRow(WarningLevel.Default, WarningLevel.Error, true, WarningLevel.Error)] // Overwrite with Error
[DataRow(WarningLevel.Default, WarningLevel.Default, true, WarningLevel.Default)] // Applied is Default, no change
[DataRow(WarningLevel.Default, WarningLevel.Warning, false, WarningLevel.Warning)] // Default, non-overwrite, change
[DataRow(WarningLevel.Default, WarningLevel.Error, false, WarningLevel.Error)] // Default, non-overwrite, change
[DataRow(WarningLevel.Off, null, true, WarningLevel.Off)] // Null applied, no change
[DataRow(WarningLevel.Off, WarningLevel.Default, true, WarningLevel.Off)] // Applied Default, no change
[DataRow(WarningLevel.Off, WarningLevel.Warning, true, WarningLevel.Warning)] // Overwrite with Warning
[DataRow(WarningLevel.Off, WarningLevel.Error, true, WarningLevel.Error)] // Overwrite with Error
[DataRow(WarningLevel.Off, WarningLevel.Warning, false, WarningLevel.Off)] // No overwrite, no change
[DataRow(WarningLevel.Warning, WarningLevel.Error, true, WarningLevel.Error)] // Overwrite with Error
[DataRow(WarningLevel.Warning, WarningLevel.Off, true, WarningLevel.Off)] // Overwrite with Off
[DataRow(WarningLevel.Warning, WarningLevel.Off, false, WarningLevel.Warning)] // No overwrite, remains Warning
[DataRow(WarningLevel.Error, WarningLevel.Off, true, WarningLevel.Off)] // Overwrite with Off
[DataRow(WarningLevel.Error, WarningLevel.Warning, true, WarningLevel.Warning)] // Overwrite with Warning
[DataRow(WarningLevel.Error, WarningLevel.Off, false, WarningLevel.Error)] // No overwrite, remains Error
public void TestApplyWarnings(WarningLevel inSourceWarningLevel, WarningLevel? appliedWarningLevel, bool overwriteSourceValue, WarningLevel expected)
{
WarningLevel sourceWarningLevel = inSourceWarningLevel;
sourceWarningLevel.ApplyWarning(appliedWarningLevel, overwriteSourceValue);
Assert.AreEqual(expected, sourceWarningLevel);
}
[TestMethod]
public void TestDefaultBuildSettings()
{
CppCompileWarnings defaultBuildSettings = new CppCompileWarnings();
Assert.AreEqual(WarningLevel.Warning, defaultBuildSettings.ShadowVariableWarningLevel);
Assert.AreEqual(WarningLevel.Off, defaultBuildSettings.UndefinedIdentifierWarningLevel);
Assert.AreEqual(WarningLevel.Off, defaultBuildSettings.UnsafeTypeCastWarningLevel);
Assert.AreEqual(WarningLevel.Off, defaultBuildSettings.SwitchUnhandledEnumeratorWarningLevel);
}
[TestMethod]
public void TestClonedMutableReturn()
{
CppCompileWarnings defaultBuildSettings = new CppCompileWarnings();
defaultBuildSettings.ShadowVariableWarningLevel = WarningLevel.Error;
defaultBuildSettings.UndefinedIdentifierWarningLevel = WarningLevel.Warning;
defaultBuildSettings.UnsafeTypeCastWarningLevel = WarningLevel.Error;
defaultBuildSettings.SwitchUnhandledEnumeratorWarningLevel = WarningLevel.Warning;
ReadOnlyCppCompileWarnings wrapper = new ReadOnlyCppCompileWarnings(defaultBuildSettings);
CppCompileWarnings cloned = wrapper.CloneAsWriteable();
{
Assert.AreEqual(defaultBuildSettings.ShadowVariableWarningLevel, cloned.ShadowVariableWarningLevel);
Assert.AreEqual(defaultBuildSettings.UndefinedIdentifierWarningLevel, cloned.UndefinedIdentifierWarningLevel);
Assert.AreEqual(defaultBuildSettings.UnsafeTypeCastWarningLevel, cloned.UnsafeTypeCastWarningLevel);
Assert.AreEqual(defaultBuildSettings.SwitchUnhandledEnumeratorWarningLevel, cloned.SwitchUnhandledEnumeratorWarningLevel);
}
// Modify and assert != to each other - the same underyling reference has not been returned
{
cloned.ShadowVariableWarningLevel = WarningLevel.Warning;
cloned.UndefinedIdentifierWarningLevel = WarningLevel.Error;
cloned.UnsafeTypeCastWarningLevel = WarningLevel.Warning;
cloned.SwitchUnhandledEnumeratorWarningLevel = WarningLevel.Error;
Assert.AreNotEqual(defaultBuildSettings.ShadowVariableWarningLevel, cloned.ShadowVariableWarningLevel);
Assert.AreNotEqual(defaultBuildSettings.UndefinedIdentifierWarningLevel, cloned.UndefinedIdentifierWarningLevel);
Assert.AreNotEqual(defaultBuildSettings.UnsafeTypeCastWarningLevel, cloned.UnsafeTypeCastWarningLevel);
Assert.AreNotEqual(defaultBuildSettings.SwitchUnhandledEnumeratorWarningLevel, cloned.SwitchUnhandledEnumeratorWarningLevel);
}
}
[TestMethod]
public void TestContextBuildSettingsOverride()
{
TestBuildSettingsProvider buildContextProvider = new TestBuildSettingsProvider();
buildContextProvider._testBuildSettings = BuildSettingsVersion.V1;
CppCompileWarnings newWarnings = new CppCompileWarnings(buildContextProvider, null);
// Shadow Variable build setting defaults
{
Assert.AreEqual(WarningLevel.Default, newWarnings.ShadowVariableWarningLevel);
// Boundary analysis
buildContextProvider._testBuildSettings = BuildSettingsVersion.V2;
CppCompileWarnings.ApplyTargetDefaults(newWarnings, true);
Assert.AreEqual(WarningLevel.Error, newWarnings.ShadowVariableWarningLevel);
buildContextProvider._testBuildSettings = BuildSettingsVersion.V3;
CppCompileWarnings.ApplyTargetDefaults(newWarnings, true);
Assert.AreEqual(WarningLevel.Error, newWarnings.ShadowVariableWarningLevel);
}
}
[TestMethod]
public void TestParentSettings()
{
TestBuildSettingsProvider buildContextProvider = new TestBuildSettingsProvider();
buildContextProvider._testBuildSettings = BuildSettingsVersion.V1;
CppCompileWarnings parentWarnings = new CppCompileWarnings(buildContextProvider, null);
CppCompileWarnings newWarnings = new CppCompileWarnings(buildContextProvider, null, new ReadOnlyCppCompileWarnings(parentWarnings));
// Assert invariants
{
Assert.AreEqual(WarningLevel.Default, newWarnings.ShadowVariableWarningLevel);
Assert.AreEqual(WarningLevel.Default, newWarnings.UnsafeTypeCastWarningLevel);
Assert.AreEqual(WarningLevel.Default, newWarnings.UndefinedIdentifierWarningLevel);
}
// Assert new parent values
{
parentWarnings.ShadowVariableWarningLevel = WarningLevel.Error;
parentWarnings.UndefinedIdentifierWarningLevel = WarningLevel.Error;
parentWarnings.UnsafeTypeCastWarningLevel = WarningLevel.Error;
Assert.AreEqual(WarningLevel.Error, newWarnings.ShadowVariableWarningLevel);
Assert.AreEqual(WarningLevel.Error, newWarnings.UnsafeTypeCastWarningLevel);
Assert.AreEqual(WarningLevel.Error, newWarnings.UndefinedIdentifierWarningLevel);
}
}
[TestMethod]
public void TestReparentOperations()
{
TestBuildSettingsProvider buildContextProvider = new TestBuildSettingsProvider();
buildContextProvider._testBuildSettings = BuildSettingsVersion.V1;
CppCompileWarnings parentWarnings = new CppCompileWarnings(buildContextProvider, null);
CppCompileWarnings newWarnings = new CppCompileWarnings(buildContextProvider, null, new ReadOnlyCppCompileWarnings(parentWarnings));
// Assert invariant parent values
{
parentWarnings.ShadowVariableWarningLevel = WarningLevel.Error;
parentWarnings.UndefinedIdentifierWarningLevel = WarningLevel.Error;
parentWarnings.UnsafeTypeCastWarningLevel = WarningLevel.Error;
Assert.AreEqual(WarningLevel.Error, newWarnings.ShadowVariableWarningLevel);
Assert.AreEqual(WarningLevel.Error, newWarnings.UnsafeTypeCastWarningLevel);
Assert.AreEqual(WarningLevel.Error, newWarnings.UndefinedIdentifierWarningLevel);
}
// Assert reparenting
CppCompileWarnings parentWarnings2 = new CppCompileWarnings(buildContextProvider, null);
{
newWarnings.AddParent(parentWarnings2);
parentWarnings2.ShadowVariableWarningLevel = WarningLevel.Warning;
parentWarnings2.UndefinedIdentifierWarningLevel = WarningLevel.Warning;
parentWarnings2.UnsafeTypeCastWarningLevel = WarningLevel.Warning;
Assert.AreEqual(WarningLevel.Warning, newWarnings.ShadowVariableWarningLevel);
Assert.AreEqual(WarningLevel.Warning, newWarnings.UnsafeTypeCastWarningLevel);
Assert.AreEqual(WarningLevel.Warning, newWarnings.UndefinedIdentifierWarningLevel);
}
// Assert transitive to eldest ancestor
{
parentWarnings2.ShadowVariableWarningLevel = WarningLevel.Default;
Assert.AreEqual(parentWarnings.ShadowVariableWarningLevel, newWarnings.ShadowVariableWarningLevel);
}
// Assert removal of parentWarnings2 - UnsafeTypeCastWarningLevel & UndefinedIdentifierWarningLevel will now be the reoslved items
{
newWarnings.RemoveParent();
Assert.AreEqual(parentWarnings.UnsafeTypeCastWarningLevel, newWarnings.UnsafeTypeCastWarningLevel);
Assert.AreEqual(parentWarnings.UndefinedIdentifierWarningLevel, newWarnings.UndefinedIdentifierWarningLevel);
}
// Removal of only parent; should only be default values
{
newWarnings.RemoveParent();
Assert.AreEqual(WarningLevel.Default, newWarnings.ShadowVariableWarningLevel);
Assert.AreEqual(WarningLevel.Default, newWarnings.UnsafeTypeCastWarningLevel);
Assert.AreEqual(WarningLevel.Default, newWarnings.UndefinedIdentifierWarningLevel);
}
}
[TestMethod]
public void TestChildOverrides()
{
TestBuildSettingsProvider buildContextProvider = new TestBuildSettingsProvider();
buildContextProvider._testBuildSettings = BuildSettingsVersion.V1;
CppCompileWarnings parentWarnings = new CppCompileWarnings(buildContextProvider, null);
CppCompileWarnings newWarnings = new CppCompileWarnings(buildContextProvider, null, new ReadOnlyCppCompileWarnings(parentWarnings));
parentWarnings.ShadowVariableWarningLevel = WarningLevel.Error;
parentWarnings.UndefinedIdentifierWarningLevel = WarningLevel.Error;
parentWarnings.UnsafeTypeCastWarningLevel = WarningLevel.Error;
// Assert invariants
{
Assert.AreEqual(WarningLevel.Error, newWarnings.ShadowVariableWarningLevel);
Assert.AreEqual(WarningLevel.Error, newWarnings.UnsafeTypeCastWarningLevel);
Assert.AreEqual(WarningLevel.Error, newWarnings.UndefinedIdentifierWarningLevel);
}
// Child overrides;
newWarnings.ShadowVariableWarningLevel = WarningLevel.Warning;
newWarnings.UndefinedIdentifierWarningLevel = WarningLevel.Warning;
newWarnings.UnsafeTypeCastWarningLevel = WarningLevel.Warning;
// Assert new parent values
{
Assert.AreEqual(WarningLevel.Warning, newWarnings.ShadowVariableWarningLevel);
Assert.AreEqual(WarningLevel.Warning, newWarnings.UnsafeTypeCastWarningLevel);
Assert.AreEqual(WarningLevel.Warning, newWarnings.UndefinedIdentifierWarningLevel);
}
}
[TestMethod]
public void TestGenerateWarningCommandLineAgsOrder()
{
DirectoryReference programsDirectory = DirectoryReference.Combine(Unreal.EngineSourceDirectory, "Programs");
FileReference testStubsDirectory = FileReference.Combine(programsDirectory, "Shared", "UnrealBuildTool.Tests", "UBT");
// Generate ephemeral TargetRules & uproject files
using (SafeTestDirectory testRootDirectory = SafeTestDirectory.CreateTestDirectory(Path.Combine(StaticTargetRulesInitializer.UBTTestFolderRoot, $"{StaticTargetRulesInitializer.UBTTestFolderPrefix}{Guid.NewGuid().ToString()}")))
using (SafeTestDirectory testSourceDirectory = SafeTestDirectory.CreateTestDirectory(Path.Combine(testRootDirectory.TemporaryDirectory, "Source")))
using (SafeTestFile testEditorTargetTestFile = new SafeTestFile(File.ReadAllText(Path.Combine(testStubsDirectory.FullName, "TargetStubs", "TestStubEditor.Target.ubttest")), "TestStubEditor.Target.cs", testSourceDirectory.TemporaryDirectory))
using (SafeTestFile testTargetTestFile = new SafeTestFile(File.ReadAllText(Path.Combine(testStubsDirectory.FullName, "TargetStubs", "TestStub.Target.ubttest")), "TestStub.Target.cs", testSourceDirectory.TemporaryDirectory))
using (SafeTestFile testUprojectTestFile = new SafeTestFile(File.ReadAllText(Path.Combine(testStubsDirectory.FullName, "UprojectStubs", "TestStub.uproject.ubttest")), "TestStub.uproject", testRootDirectory.TemporaryDirectory))
{
CppCompileEnvironment newCompileEnvironment = new CppCompileEnvironment(UnrealTargetPlatform.Win64, CppConfiguration.Development, new UnrealArchitectures(UnrealArch.X64), null!);
FileReference testUproject = new FileReference(testUprojectTestFile.TemporaryFile);
IEnumerable<string> args = null!;
RulesAssembly generatedTestGameRulesAssembly = RulesCompiler.CreateTargetRulesAssembly(testUproject, "TestStub", false, false, false, null, false, new TestLogger());
TargetRules testTargetRulesNonWin64 = generatedTestGameRulesAssembly.CreateTargetRules("TestStub", UnrealTargetPlatform.Android, UnrealTargetConfiguration.Development, null, testUproject, null, new TestLogger());
CppCompileWarnings specializedWarnings = new CppCompileWarnings(testTargetRulesNonWin64, null);
// Verify the ordering
{
VersionNumber newVersionNumber = new VersionNumber(18, 9, 9);
specializedWarnings.DeprecatedCopyWarningLevel = WarningLevel.Off;
specializedWarnings.DeprecatedCopyWithUserProvidedCopyWarningLevel = WarningLevel.Error;
args = specializedWarnings.GenerateWarningCommandLineArgs(newCompileEnvironment, typeof(ClangToolChain), newVersionNumber);
Assert.IsTrue(args.Count() == 2);
Assert.IsTrue(args.First() == "-Wno-deprecated-copy");
Assert.IsTrue(args.Last() == "-Wdeprecated-copy-with-user-provided-copy");
}
}
}
[TestMethod]
public void TestGenerateWarningCommandLineAgs()
{
DirectoryReference programsDirectory = DirectoryReference.Combine(Unreal.EngineSourceDirectory, "Programs");
FileReference testStubsDirectory = FileReference.Combine(programsDirectory, "Shared", "UnrealBuildTool.Tests", "UBT");
// Generate ephemeral TargetRules & uproject files
using (SafeTestDirectory testRootDirectory = SafeTestDirectory.CreateTestDirectory(Path.Combine(StaticTargetRulesInitializer.UBTTestFolderRoot, $"{StaticTargetRulesInitializer.UBTTestFolderPrefix}{Guid.NewGuid().ToString()}")))
using (SafeTestDirectory testSourceDirectory = SafeTestDirectory.CreateTestDirectory(Path.Combine(testRootDirectory.TemporaryDirectory, "Source")))
using (SafeTestFile testEditorTargetTestFile = new SafeTestFile(File.ReadAllText(Path.Combine(testStubsDirectory.FullName, "TargetStubs", "TestStubEditor.Target.ubttest")), "TestStubEditor.Target.cs", testSourceDirectory.TemporaryDirectory))
using (SafeTestFile testTargetTestFile = new SafeTestFile(File.ReadAllText(Path.Combine(testStubsDirectory.FullName, "TargetStubs", "TestStub.Target.ubttest")), "TestStub.Target.cs", testSourceDirectory.TemporaryDirectory))
using (SafeTestFile testUprojectTestFile = new SafeTestFile(File.ReadAllText(Path.Combine(testStubsDirectory.FullName, "UprojectStubs", "TestStub.uproject.ubttest")), "TestStub.uproject", testRootDirectory.TemporaryDirectory))
{
CppCompileEnvironment newCompileEnvironment = new CppCompileEnvironment(UnrealTargetPlatform.Win64, CppConfiguration.Development, new UnrealArchitectures(UnrealArch.X64), null!);
FileReference testUproject = new FileReference(testUprojectTestFile.TemporaryFile);
// Generate rules assembly & subsequent targets
RulesAssembly generatedTestRulesAssembly = RulesCompiler.CreateTargetRulesAssembly(testUproject, "TestStubEditor", false, false, false, null, false, new TestLogger());
TargetRules testTargetRules = generatedTestRulesAssembly.CreateTargetRules("TestStubEditor", UnrealTargetPlatform.Win64, UnrealTargetConfiguration.Development, null, testUproject, null, new TestLogger());
testTargetRules.WindowsPlatform.Compiler = WindowsCompiler.VisualStudio2022;
CppCompileWarnings baseWarnings = new CppCompileWarnings(testTargetRules, null);
IEnumerable<string> args = null!;
// No args, base check
{
args = baseWarnings.GenerateWarningCommandLineArgs(newCompileEnvironment, typeof(VCToolChain));
Assert.IsFalse(args.Any());
}
// VC toolchain check;
{
baseWarnings.UnsafeTypeCastWarningLevel = WarningLevel.Warning;
args = baseWarnings.GenerateWarningCommandLineArgs(newCompileEnvironment, typeof(VCToolChain));
Assert.IsTrue(args.Count() == 2);
Assert.IsTrue(args.Contains("/w44244"));
Assert.IsTrue(args.Contains("/w44838"));
baseWarnings.UnsafeTypeCastWarningLevel = WarningLevel.Default;
}
// MSVC compiler check;
{
baseWarnings.ShadowVariableWarningLevel = WarningLevel.Error;
args = baseWarnings.GenerateWarningCommandLineArgs(newCompileEnvironment, typeof(VCToolChain));
Assert.IsTrue(args.Count() == 3);
Assert.IsTrue(args.Contains("/we4456"));
Assert.IsTrue(args.Contains("/we4458"));
Assert.IsTrue(args.Contains("/we4459"));
WindowsCompiler previousCompiler = testTargetRules.WindowsPlatform.Compiler;
testTargetRules.WindowsPlatform.Compiler = WindowsCompiler.Intel;
args = baseWarnings.GenerateWarningCommandLineArgs(newCompileEnvironment, typeof(VCToolChain));
Assert.IsFalse(args.Any());
testTargetRules.WindowsPlatform.Compiler = previousCompiler;
baseWarnings.ShadowVariableWarningLevel = WarningLevel.Default;
}
// Specialized VC toolchain check; UndefinedIdentifier
{
baseWarnings.UndefinedIdentifierWarningLevel = WarningLevel.Warning;
args = baseWarnings.GenerateWarningCommandLineArgs(newCompileEnvironment, typeof(VCToolChain));
Assert.IsTrue(args.Count() == 1);
Assert.IsTrue(args.Contains("/w44668"));
CppCompileEnvironment preprocessOnlyCompileEnvironment = new CppCompileEnvironment(newCompileEnvironment);
preprocessOnlyCompileEnvironment.bPreprocessOnly = true;
args = baseWarnings.GenerateWarningCommandLineArgs(preprocessOnlyCompileEnvironment, typeof(VCToolChain));
Assert.IsFalse(args.Any());
baseWarnings.UndefinedIdentifierWarningLevel = WarningLevel.Default;
}
{
// DeterministicWarningLevel
VersionNumber newVersionNumber = new VersionNumber(18, 9, 9);
CppCompileEnvironment deterministicCompileEnvironment = new CppCompileEnvironment(UnrealTargetPlatform.Win64, CppConfiguration.Debug, new UnrealArchitectures(UnrealArch.X64), null!);
deterministicCompileEnvironment.bDeterministic = false;
args = baseWarnings.GenerateWarningCommandLineArgs(deterministicCompileEnvironment, typeof(VCToolChain), newVersionNumber);
Assert.IsFalse(args.Any());
deterministicCompileEnvironment.bDeterministic = true;
args = baseWarnings.GenerateWarningCommandLineArgs(deterministicCompileEnvironment, typeof(VCToolChain), newVersionNumber);
Assert.IsFalse(args.Any());
baseWarnings.DeterministicWarningLevel = WarningLevel.Off;
args = baseWarnings.GenerateWarningCommandLineArgs(deterministicCompileEnvironment, typeof(VCToolChain), newVersionNumber);
Assert.AreEqual(1, args.Count());
Assert.IsTrue(args.Contains("/wd5048"));
baseWarnings.DeterministicWarningLevel = WarningLevel.Warning;
args = baseWarnings.GenerateWarningCommandLineArgs(deterministicCompileEnvironment, typeof(VCToolChain), newVersionNumber);
Assert.AreEqual(0, args.Count());
Assert.IsFalse(args.Any());
baseWarnings.DeterministicWarningLevel = WarningLevel.Error;
args = baseWarnings.GenerateWarningCommandLineArgs(deterministicCompileEnvironment, typeof(VCToolChain), newVersionNumber);
Assert.AreEqual(1, args.Count());
Assert.IsTrue(args.Contains("/we5048"));
}
// Specialized VC toolchain check; UnsafeTypeCast
{
RulesAssembly generatedTestGameRulesAssembly = RulesCompiler.CreateTargetRulesAssembly(testUproject, "TestStub", false, false, false, null, false, new TestLogger());
TargetRules testTargetRulesNonWin64 = generatedTestGameRulesAssembly.CreateTargetRules("TestStub", UnrealTargetPlatform.Android, UnrealTargetConfiguration.Development, null, testUproject, null, new TestLogger());
CppCompileWarnings specializedWarnings = new CppCompileWarnings(testTargetRulesNonWin64, null);
specializedWarnings.UnsafeTypeCastWarningLevel = WarningLevel.Warning;
args = specializedWarnings.GenerateWarningCommandLineArgs(newCompileEnvironment, typeof(VCToolChain));
Assert.IsTrue(args.Count() == 2);
Assert.IsTrue(args.Contains("/wd4244"));
Assert.IsTrue(args.Contains("/wd4838"));
baseWarnings.UnsafeTypeCastWarningLevel = WarningLevel.Warning;
args = baseWarnings.GenerateWarningCommandLineArgs(newCompileEnvironment, typeof(VCToolChain));
Assert.IsTrue(args.Count() == 2);
Assert.IsTrue(args.Contains("/w44244"));
Assert.IsTrue(args.Contains("/w44838"));
baseWarnings.UnsafeTypeCastWarningLevel = WarningLevel.Default;
}
// Clang toolchain version check - no version; should disable Shadow
{
testTargetRules.WindowsPlatform.Compiler = WindowsCompiler.Clang;
baseWarnings.ShadowVariableWarningLevel = WarningLevel.Error;
args = baseWarnings.GenerateWarningCommandLineArgs(newCompileEnvironment, typeof(ClangToolChain));
Assert.IsTrue(args.Count() == 1);
Assert.IsTrue(args.Contains("-Wno-shadow"));
baseWarnings.ShadowVariableWarningLevel = WarningLevel.Default;
}
// Clang toolchain version check - valid versions;
{
testTargetRules.WindowsPlatform.Compiler = WindowsCompiler.Clang;
baseWarnings.ShadowVariableWarningLevel = WarningLevel.Error;
VersionNumber newVersionNumber = new VersionNumber(16, 9, 5);
args = baseWarnings.GenerateWarningCommandLineArgs(newCompileEnvironment, typeof(ClangToolChain), newVersionNumber);
Assert.IsTrue(args.Count() == 1);
Assert.IsTrue(args.Contains("-Wshadow"));
newVersionNumber = new VersionNumber(17);
args = baseWarnings.GenerateWarningCommandLineArgs(newCompileEnvironment, typeof(ClangToolChain), newVersionNumber);
Assert.IsTrue(args.Count() == 1);
Assert.IsTrue(args.Contains("-Wno-shadow"));
newVersionNumber = new VersionNumber(17, 1);
args = baseWarnings.GenerateWarningCommandLineArgs(newCompileEnvironment, typeof(ClangToolChain), newVersionNumber);
Assert.IsTrue(args.Count() == 1);
Assert.IsTrue(args.Contains("-Wno-shadow"));
newVersionNumber = new VersionNumber(18, 1, 2);
args = baseWarnings.GenerateWarningCommandLineArgs(newCompileEnvironment, typeof(ClangToolChain), newVersionNumber);
Assert.IsTrue(args.Count() == 1);
Assert.IsTrue(args.Contains("-Wno-shadow"));
newVersionNumber = new VersionNumber(18, 1, 3);
args = baseWarnings.GenerateWarningCommandLineArgs(newCompileEnvironment, typeof(ClangToolChain), newVersionNumber);
Assert.IsTrue(args.Count() == 1);
Assert.IsTrue(args.Contains("-Wshadow"));
baseWarnings.ShadowVariableWarningLevel = WarningLevel.Default;
}
// ToolChainVersionConstrainedFilterAttribute
{
testTargetRules.WindowsPlatform.Compiler = WindowsCompiler.Clang;
baseWarnings.Shorten64To32WarningLevel = WarningLevel.Off;
VersionNumber newVersionNumber = new VersionNumber(18, 9, 9);
args = baseWarnings.GenerateWarningCommandLineArgs(newCompileEnvironment, typeof(ClangToolChain), newVersionNumber);
Assert.IsFalse(args.Any());
//
newVersionNumber = new VersionNumber(19, 0, 0);
args = baseWarnings.GenerateWarningCommandLineArgs(newCompileEnvironment, typeof(ClangToolChain), newVersionNumber);
Assert.IsTrue(args.Count() == 1);
Assert.IsTrue(args.Contains("-Wno-shorten-64-to-32"));
baseWarnings.Shorten64To32WarningLevel = WarningLevel.Default;
}
// ConfigurationFilterAttribute
{
testTargetRules.WindowsPlatform.Compiler = WindowsCompiler.Clang;
baseWarnings.UnusedValueWarningLevel = WarningLevel.Off;
VersionNumber newVersionNumber = new VersionNumber(18, 9, 9);
CppCompileEnvironment invalidCompileEnvironment = new CppCompileEnvironment(UnrealTargetPlatform.Win64, CppConfiguration.Debug, new UnrealArchitectures(UnrealArch.X64), null!);
CppCompileEnvironment validCompileEnvironment = new CppCompileEnvironment(UnrealTargetPlatform.Win64, CppConfiguration.Shipping, new UnrealArchitectures(UnrealArch.X64), null!);
args = baseWarnings.GenerateWarningCommandLineArgs(invalidCompileEnvironment, typeof(ClangToolChain), newVersionNumber);
Assert.IsFalse(args.Any());
args = baseWarnings.GenerateWarningCommandLineArgs(validCompileEnvironment, typeof(ClangToolChain), newVersionNumber);
Assert.IsTrue(args.Count() == 2);
Assert.IsTrue(args.Contains("-Wno-unused-value"));
baseWarnings.UnusedValueWarningLevel = WarningLevel.Default;
}
// CppStandardConstrainedFilterAttribute
{
testTargetRules.WindowsPlatform.Compiler = WindowsCompiler.Clang;
baseWarnings.AmbiguousReversedOperatorWarningLevel = WarningLevel.Off;
VersionNumber newVersionNumber = new VersionNumber(18, 9, 9);
CppCompileEnvironment cppStandardCompileEnvironment = new CppCompileEnvironment(UnrealTargetPlatform.Win64, CppConfiguration.Debug, new UnrealArchitectures(UnrealArch.X64), null!);
#pragma warning disable CS0618 // Type or member is obsolete
cppStandardCompileEnvironment.CppStandard = CppStandardVersion.Cpp17;
#pragma warning restore CS0618 // Type or member is obsolete
args = baseWarnings.GenerateWarningCommandLineArgs(cppStandardCompileEnvironment, typeof(ClangToolChain), newVersionNumber);
Assert.IsFalse(args.Any());
cppStandardCompileEnvironment.CppStandard = CppStandardVersion.Cpp20;
args = baseWarnings.GenerateWarningCommandLineArgs(cppStandardCompileEnvironment, typeof(ClangToolChain), newVersionNumber);
Assert.IsTrue(args.Count() == 1);
Assert.IsTrue(args.Contains("-Wno-ambiguous-reversed-operator"));
cppStandardCompileEnvironment.CppStandard = CppStandardVersion.Latest;
args = baseWarnings.GenerateWarningCommandLineArgs(cppStandardCompileEnvironment, typeof(ClangToolChain), newVersionNumber);
Assert.IsTrue(args.Count() == 1);
Assert.IsTrue(args.Contains("-Wno-ambiguous-reversed-operator"));
baseWarnings.AmbiguousReversedOperatorWarningLevel = WarningLevel.Default;
}
// DeterministcFlagSetFilter
{
testTargetRules.WindowsPlatform.Compiler = WindowsCompiler.Clang;
baseWarnings.DeterministicWarningLevel = WarningLevel.Off;
VersionNumber newVersionNumber = new VersionNumber(18, 9, 9);
CppCompileEnvironment deterministicCompileEnvironment = new CppCompileEnvironment(UnrealTargetPlatform.Win64, CppConfiguration.Debug, new UnrealArchitectures(UnrealArch.X64), null!);
deterministicCompileEnvironment.bDeterministic = false;
args = baseWarnings.GenerateWarningCommandLineArgs(deterministicCompileEnvironment, typeof(ClangToolChain), newVersionNumber);
Assert.IsFalse(args.Any());
deterministicCompileEnvironment.bDeterministic = true;
args = baseWarnings.GenerateWarningCommandLineArgs(deterministicCompileEnvironment, typeof(ClangToolChain), newVersionNumber);
Assert.IsTrue(args.Count() == 1);
Assert.IsTrue(args.Contains("-Wno-date-time"));
deterministicCompileEnvironment.bDeterministic = false;
baseWarnings.DeterministicWarningLevel = WarningLevel.Warning;
args = baseWarnings.GenerateWarningCommandLineArgs(deterministicCompileEnvironment, typeof(ClangToolChain), newVersionNumber);
Assert.IsFalse(args.Any());
deterministicCompileEnvironment.bDeterministic = true;
args = baseWarnings.GenerateWarningCommandLineArgs(deterministicCompileEnvironment, typeof(ClangToolChain), newVersionNumber);
Assert.IsTrue(args.Count() == 2);
Assert.IsTrue(args.Contains("-Wdate-time"));
Assert.IsTrue(args.Contains("-Wno-error=date-time"));
baseWarnings.DeterministicWarningLevel = WarningLevel.Error;
args = baseWarnings.GenerateWarningCommandLineArgs(deterministicCompileEnvironment, typeof(ClangToolChain), newVersionNumber);
Assert.IsTrue(args.Count() == 1);
Assert.IsTrue(args.Contains("-Wdate-time"));
baseWarnings.DeterministicWarningLevel = WarningLevel.Default;
}
// PGOOptimizedFilter
{
testTargetRules.WindowsPlatform.Compiler = WindowsCompiler.Clang;
baseWarnings.ProfileInstructWarningLevel = WarningLevel.Off;
VersionNumber newVersionNumber = new VersionNumber(18, 9, 9);
CppCompileEnvironment pgoOptimizedCompileEnvironment = new CppCompileEnvironment(UnrealTargetPlatform.Win64, CppConfiguration.Debug, new UnrealArchitectures(UnrealArch.X64), null!);
pgoOptimizedCompileEnvironment.bPGOOptimize = false;
args = baseWarnings.GenerateWarningCommandLineArgs(pgoOptimizedCompileEnvironment, typeof(ClangToolChain), newVersionNumber);
Assert.IsFalse(args.Any());
pgoOptimizedCompileEnvironment.bPGOOptimize = true;
args = baseWarnings.GenerateWarningCommandLineArgs(pgoOptimizedCompileEnvironment, typeof(ClangToolChain), newVersionNumber);
Assert.IsTrue(args.Count() == 2);
Assert.IsTrue(args.Contains("-Wno-profile-instr-out-of-date"));
Assert.IsTrue(args.Contains("-Wno-profile-instr-unprofiled"));
baseWarnings.ProfileInstructWarningLevel = WarningLevel.Off;
}
// AndroidNDKR28ToolChainVersionExclusion
{
testTargetRules.WindowsPlatform.Compiler = WindowsCompiler.Clang;
baseWarnings.CastFunctionTypeMismatchWarningLevel = WarningLevel.Off;
VersionNumber newVersionNumber = new VersionNumber(19, 0, 0);
CppCompileEnvironment androidCompileEnvironment = new CppCompileEnvironment(UnrealTargetPlatform.Android, CppConfiguration.Development, new UnrealArchitectures(UnrealArch.X64), null!);
args = baseWarnings.GenerateWarningCommandLineArgs(androidCompileEnvironment, typeof(ClangToolChain), newVersionNumber);
Assert.IsFalse(args.Any());
args = baseWarnings.GenerateWarningCommandLineArgs(newCompileEnvironment, typeof(ClangToolChain), newVersionNumber);
Assert.IsTrue(args.Count() == 1);
Assert.IsTrue(args.Contains("-Wno-cast-function-type-mismatch"));
newVersionNumber = new VersionNumber(19, 0, 1);
args = baseWarnings.GenerateWarningCommandLineArgs(androidCompileEnvironment, typeof(ClangToolChain), newVersionNumber);
Assert.IsTrue(args.Count() == 1);
Assert.IsTrue(args.Contains("-Wno-cast-function-type-mismatch"));
baseWarnings.CastFunctionTypeMismatchWarningLevel = WarningLevel.Default;
}
// AndroidNDKR26ToolChainVersionExclusion
{
testTargetRules.WindowsPlatform.Compiler = WindowsCompiler.Clang;
baseWarnings.InvalidUnevaluatedStringWarningLevel = WarningLevel.Off;
CppCompileEnvironment androidCompileEnvironment = new CppCompileEnvironment(UnrealTargetPlatform.Android, CppConfiguration.Development, new UnrealArchitectures(UnrealArch.X64), null!);
// Exclusion cases
{
VersionNumber newVersionNumber = new VersionNumber(17, 0, 2);
args = baseWarnings.GenerateWarningCommandLineArgs(androidCompileEnvironment, typeof(ClangToolChain), newVersionNumber);
Assert.IsTrue(args.Count() == 1 && args.Contains("-Wno-shadow"));
newVersionNumber = new VersionNumber(16);
args = baseWarnings.GenerateWarningCommandLineArgs(androidCompileEnvironment, typeof(ClangToolChain), newVersionNumber);
Assert.IsFalse(args.Any());
newVersionNumber = new VersionNumber(17, 1);
androidCompileEnvironment.CppStandard = CppStandardVersion.Latest;
args = baseWarnings.GenerateWarningCommandLineArgs(androidCompileEnvironment, typeof(ClangToolChain), newVersionNumber);
Assert.IsTrue(args.Count() == 1 && args.Contains("-Wno-shadow"));
}
// Inclusion cases
{
VersionNumber newVersionNumber = new VersionNumber(17, 1);
androidCompileEnvironment.CppStandard = CppStandardVersion.Cpp20;
args = baseWarnings.GenerateWarningCommandLineArgs(androidCompileEnvironment, typeof(ClangToolChain), newVersionNumber);
Assert.IsTrue(args.Contains("-Wno-invalid-unevaluated-string"));
newVersionNumber = new VersionNumber(17, 0, 2);
args = baseWarnings.GenerateWarningCommandLineArgs(newCompileEnvironment, typeof(ClangToolChain), newVersionNumber);
Assert.IsTrue(args.Contains("-Wno-invalid-unevaluated-string"));
}
baseWarnings.InvalidUnevaluatedStringWarningLevel = WarningLevel.Default;
}
// UnusedValueClangToolChainAttribute
{
testTargetRules.WindowsPlatform.Compiler = WindowsCompiler.Clang;
baseWarnings.UnusedValueWarningLevel = WarningLevel.Off;
VersionNumber newVersionNumber = new VersionNumber(18, 9, 9);
CppCompileEnvironment invalidCompileEnvironment = new CppCompileEnvironment(UnrealTargetPlatform.Win64, CppConfiguration.Debug, new UnrealArchitectures(UnrealArch.X64), null!);
CppCompileEnvironment validCompileEnvironment = new CppCompileEnvironment(UnrealTargetPlatform.Win64, CppConfiguration.Shipping, new UnrealArchitectures(UnrealArch.X64), null!);
args = baseWarnings.GenerateWarningCommandLineArgs(invalidCompileEnvironment, typeof(ClangToolChain), newVersionNumber, StaticAnalyzer.None);
Assert.IsFalse(args.Any());
args = baseWarnings.GenerateWarningCommandLineArgs(validCompileEnvironment, typeof(ClangToolChain), newVersionNumber, StaticAnalyzer.None);
Assert.IsTrue(args.Count() == 2 && args.Contains("-Wno-unused-value"));
args = baseWarnings.GenerateWarningCommandLineArgs(validCompileEnvironment, typeof(ClangToolChain), newVersionNumber, StaticAnalyzer.Clang);
Assert.IsTrue(args.Count() == 2 && args.Contains("-Wno-unused-value"));
}
// VCClangCompilerFilter
{
testTargetRules.WindowsPlatform.Compiler = WindowsCompiler.Clang;
baseWarnings.MicrosoftGroupWarningLevel = WarningLevel.Off;
args = baseWarnings.GenerateWarningCommandLineArgs(newCompileEnvironment, typeof(VCToolChain));
Assert.IsTrue(args.Any());
Assert.IsTrue(args.Contains("-Wno-microsoft"));
// make sure exclusively ONLY the clang stuff is in:
testTargetRules.WindowsPlatform.Compiler = WindowsCompiler.VisualStudio2022;
args = baseWarnings.GenerateWarningCommandLineArgs(newCompileEnvironment, typeof(VCToolChain));
Assert.IsFalse(args.Any());
}
}
}
}
}