// Copyright Epic Games, Inc. All Rights Reserved. using System; using System.Collections.Generic; using EpicGames.Core; namespace UnrealBuildTool { /// /// Denotes the position of a resolved compile warnings argument relative to other warnings. /// public enum ArgPosition { /// /// At the beginning of the argument list. /// Beginning, /// /// In the middle of the argument list. /// Middle, /// /// At the end of the argument list. /// End } /// /// Attribute used to mark fields which describes a set of arguments. /// [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] internal abstract class ApplyWarningsAttribute : Attribute { private readonly string[]? _offArgs; private readonly string[]? _warningArgs; private readonly string[]? _errorArgs; protected readonly List ActiveFilters = []; public readonly ArgPosition Position; /// /// Defines the argument metadata around a property. /// /// The arguments to use when the property is defined as . /// The arguments to use when the property is defined as . /// The arguments to use when the property is defined as . /// The applicable filter criteria. /// The phase of when to apply the warning. internal ApplyWarningsAttribute(string[]? offArgs = null, string[]? warningArgs = null, string[]? errorArgs = null, string[]? applicableFilters = null, ArgPosition argPosition = ArgPosition.Middle) { _offArgs = offArgs; _warningArgs = warningArgs; _errorArgs = errorArgs; AppendNewFilters(applicableFilters); Position = argPosition; } /// /// Applies the warnings to the provided arguments list. /// /// The warning level to use when applying. /// The toolchain context to use in application. /// The arugments list to add values to. internal void ApplyWarningsToArguments(WarningLevel level, CompilerWarningsToolChainContext toolChainContext, List arguments) { ApplyWarningsToArgumentsInternal(level, toolChainContext, arguments); } /// /// Applies the warnings to the provided arguments list. /// /// The warning level to use when applying. /// The toolchain context to use in application. /// The arugments list to add values to. /// Used to provide custom overriding logic. protected virtual void ApplyWarningsToArgumentsInternal(WarningLevel level, CompilerWarningsToolChainContext toolChainContext, List arguments) { switch (level) { case WarningLevel.Off: if (_offArgs != null) { arguments.AddRange(_offArgs); } break; case WarningLevel.Warning: if (_warningArgs != null) { arguments.AddRange(_warningArgs); } break; case WarningLevel.Error: if (_errorArgs != null) { arguments.AddRange(_errorArgs); } break; } } /// /// Whether the given can be applied to the provided context. /// /// The toolchain context to be applied to. /// True if applicable, false otherwise. internal virtual bool CanApplyToContext(CompilerWarningsToolChainContext toolChainContext) { return (ActiveFilters == null || ActiveFilters.TrueForAll(x => x.CanApply(toolChainContext))); } protected bool TryAppendNewFilter(string rawFilterName) { IApplyWarningsFilter? filter = ApplyWarningsFilterRegistry.RequestFilter(rawFilterName); if (filter != null && !ActiveFilters.Contains(filter)) { ActiveFilters.Add(filter); return true; } return false; } protected void AppendNewFilters(IEnumerable? newFilters) { if (newFilters != null) { foreach (string rawFilterName in newFilters) { TryAppendNewFilter(rawFilterName); } } } protected void AppendNewFilters(IEnumerable? newFilters) { if (newFilters != null) { foreach (FilterID filterID in newFilters) { TryAppendNewFilter(filterID.ToString()); } } } /// /// The list of off arugments corresponding to /// internal string[]? OffArgs => _offArgs; /// /// The list of off arugments corresponding to /// internal string[]? WarningArgs => _warningArgs; /// /// The list of off arugments corresponding to /// internal string[]? ErrorArgs => _errorArgs; } #region -- ToolChains -- #pragma warning disable CA1813 internal class WarningsVCToolChainAttribute : ApplyWarningsAttribute #pragma warning restore CA1813 { /// internal WarningsVCToolChainAttribute(string[]? offArgs = null, string[]? warningArgs = null, string[]? errorArgs = null, string[]? filterNames = null, ArgPosition argPosition = ArgPosition.Middle) : base(offArgs, warningArgs, errorArgs, filterNames, argPosition) { AppendNewFilters([nameof(FilterID.VCToolChain)]); } } #pragma warning disable CA1813 internal class WarningsClangToolChainAttribute : ApplyWarningsAttribute { #pragma warning restore CA1813 /// internal WarningsClangToolChainAttribute(string[]? offArgs = null, string[]? warningArgs = null, string[]? errorArgs = null, string[]? filterNames = null, ArgPosition argPosition = ArgPosition.Middle) : base(offArgs, warningArgs, errorArgs, filterNames, argPosition) { AppendNewFilters([nameof(FilterID.ClangToolChain)]); } } #pragma warning disable CA1813 internal class WarningsIntelCompilerAttribute : ApplyWarningsAttribute #pragma warning restore CA1813 { /// internal WarningsIntelCompilerAttribute(string[]? offArgs = null, string[]? warningArgs = null, string[]? errorArgs = null, string[]? filterNames = null, ArgPosition argPosition = ArgPosition.Middle) : base(offArgs, warningArgs, errorArgs, filterNames, argPosition) { AppendNewFilters([nameof(StandardFilters.IntelCompilerFilter)]); } } #endregion -- ToolChains -- #region -- Compiler Specializations -- /// /// Specialized for MSVC compiler within the . /// internal sealed class WarningsMSCVAttribute : WarningsVCToolChainAttribute { /// internal WarningsMSCVAttribute(string[]? offArgs = null, string[]? warningArgs = null, string[]? errorArgs = null, string[]? filterNames = null, ArgPosition argPosition = ArgPosition.Middle) : base(offArgs, warningArgs, errorArgs, filterNames, argPosition) { AppendNewFilters([nameof(StandardFilters.MSVCCompilerFilter)]); } } /// /// Specialized for Clang compiler within the . /// internal sealed class WarningsVCClangAttribute : WarningsVCToolChainAttribute { /// internal WarningsVCClangAttribute(string[]? offArgs = null, string[]? warningArgs = null, string[]? errorArgs = null, ArgPosition argPosition = ArgPosition.Middle) : base(offArgs, warningArgs, errorArgs, argPosition: argPosition) { AppendNewFilters([nameof(StandardFilters.VCClangCompilerFilter)]); } } #endregion -- Compiler Specializations -- #region -- ToolChain Specializations -- /// /// / Specialized for Unused Value. /// internal sealed class UnusedValueClangToolChainAttribute : WarningsClangToolChainAttribute { /// internal UnusedValueClangToolChainAttribute(string[]? offArgs = null, string[]? warningArgs = null, string[]? errorArgs = null) : base(offArgs, warningArgs, errorArgs) { AppendNewFilters([FilterID.ConfigShipping]); } /// internal override bool CanApplyToContext(CompilerWarningsToolChainContext toolChainContext) { return base.CanApplyToContext(toolChainContext) || (toolChainContext._analyzer != StaticAnalyzer.None); } } /// /// Specialized for Shadow Variable Warnings. /// internal sealed class ShadowVariableWarningsClangToolChainAttribute : WarningsClangToolChainAttribute { /// internal ShadowVariableWarningsClangToolChainAttribute(string[]? offArgs, string[]? warningArgs, string[]? errorArgs) : base(offArgs, warningArgs, errorArgs) { } /// /// No matter what our is, in the clang 17-18.1.3 range we always disable. protected override void ApplyWarningsToArgumentsInternal(WarningLevel level, CompilerWarningsToolChainContext toolChainContext, List arguments) { if (toolChainContext._toolChainVersion == null || (toolChainContext._toolChainVersion >= new EpicGames.Core.VersionNumber(17) && toolChainContext._toolChainVersion < new VersionNumber(18, 1, 3))) { if (OffArgs != null) { arguments.AddRange(OffArgs); } } else { // Explicitly remove the OffArgs for consideration switch (level) { case WarningLevel.Warning: if (WarningArgs != null) { arguments.AddRange(WarningArgs); } break; case WarningLevel.Error: if (ErrorArgs != null) { arguments.AddRange(ErrorArgs); } break; } } } } /// /// Specialized for Undefined identifier. /// internal sealed class UndefinedIdentifierWarningsVCToolChainAttribute : WarningsVCToolChainAttribute { /// internal UndefinedIdentifierWarningsVCToolChainAttribute(string[]? offArgs, string[]? warningArgs, string[]? errorArgs) : base(offArgs, warningArgs, errorArgs) { } /// protected override void ApplyWarningsToArgumentsInternal(WarningLevel level, CompilerWarningsToolChainContext toolChainContext, List arguments) { if (!toolChainContext._compileEnvironment.bPreprocessOnly) { base.ApplyWarningsToArgumentsInternal(level, toolChainContext, arguments); } } } /// /// Specialized for Unsafe Type Casts. /// internal sealed class UnsafeTypeCastWarningsVCToolChainAttribute : WarningsVCToolChainAttribute { /// internal UnsafeTypeCastWarningsVCToolChainAttribute(string[] offArgs, string[] warningArgs, string[] errorArgs) : base(offArgs, warningArgs, errorArgs) { } /// protected override void ApplyWarningsToArgumentsInternal(WarningLevel level, CompilerWarningsToolChainContext toolChainContext, List arguments) { WarningLevel effectiveCastWarningLevel = (toolChainContext._buildSystemContext.GetReadOnlyTargetRules()?.Platform == UnrealTargetPlatform.Win64) ? level : WarningLevel.Off; base.ApplyWarningsToArgumentsInternal(effectiveCastWarningLevel, toolChainContext, arguments); } } #endregion -- ToolChain Specializations -- }