if: Add DIAGNOSTIC <category> condition

Add an existence check to the `if` command for diagnostic categories,
mirroring the check for policies. Aside from being desirable for
consistency's sake, this will make it easier for users to write logic to
manipulate diagnostics from newer versions of CMake that don't exist
today.
This commit is contained in:
Matthew Woehlke
2026-06-16 15:14:13 -04:00
parent adcfdb6d3c
commit 597c573d7d
5 changed files with 30 additions and 2 deletions

View File

@@ -43,8 +43,9 @@ Compound conditions are evaluated in the following order of precedence:
2. Unary tests such as:
* The `Existence Checks`_ :cref:`COMMAND`, :cref:`POLICY`, :cref:`TARGET`,
:cref:`TEST`, :cref:`EXISTS`, and :cref:`DEFINED`.
* The `Existence Checks`_ :cref:`COMMAND`, :cref:`DEFINED`,
:cref:`DIAGNOSTIC`, :cref:`EXISTS`, :cref:`POLICY`, :cref:`TARGET`, and
:cref:`TEST`.
* The `File Operations`_ :cref:`IS_READABLE`, :cref:`IS_WRITABLE`,
:cref:`IS_EXECUTABLE`, :cref:`IS_DIRECTORY`, :cref:`IS_SYMLINK`, and
:cref:`IS_ABSOLUTE`.
@@ -131,6 +132,12 @@ Existence Checks
True if the given name is a command, macro or function that can be
invoked.
.. signature:: if(DIAGNOSTIC <category>)
.. versionadded:: 4.4
True if the given name is an existing diagnostic category.
.. signature:: if(POLICY <policy-id>)
True if the given name is an existing policy (of the form ``CMP<NNNN>``).

View File

@@ -186,6 +186,9 @@ Commands
* The :command:`file(READ_SYMLINK)` command gained a ``RESULT``
option to capture errors without failing.
* The :command:`if` command gained a new ``DIAGNOSTIC`` operator that evaluates
to true if a given diagnostic category name is known to CMake.
* The :command:`include` command now has a ``NO_DIAGNOSTIC_SCOPE`` option.
* The :command:`list(FILTER)` command gained a new ``PREDICATE`` mode

View File

@@ -11,12 +11,14 @@
#include <sstream>
#include <utility>
#include <cm/optional>
#include <cm/string_view>
#include <cmext/algorithm>
#include "cmsys/RegularExpression.hxx"
#include "cmCMakePath.h"
#include "cmDiagnostics.h"
#include "cmExpandedCommandArgument.h"
#include "cmList.h"
#include "cmMakefile.h"
@@ -30,6 +32,7 @@ namespace {
auto const keyAND = "AND"_s;
auto const keyCOMMAND = "COMMAND"_s;
auto const keyDEFINED = "DEFINED"_s;
auto const keyDIAGNOSTIC = "DIAGNOSTIC"_s;
auto const keyEQUAL = "EQUAL"_s;
auto const keyEXISTS = "EXISTS"_s;
auto const keyIS_READABLE = "IS_READABLE"_s;
@@ -479,6 +482,13 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&,
this->Makefile.GetState()->GetCommand(args.next->GetValue())),
args);
}
// does a diagnostic exist
else if (this->IsKeyword(keyDIAGNOSTIC, *args.current)) {
newArgs.ReduceOneArg(
cmDiagnostics::GetDiagnosticCategory(args.next->GetValue())
.has_value(),
args);
}
// does a policy exist
else if (this->IsKeyword(keyPOLICY, *args.current)) {
cmPolicies::PolicyID pid;

View File

@@ -0,0 +1,7 @@
if(NOT DIAGNOSTIC CMD_AUTHOR)
message(SEND_ERROR "existence check for CMD_AUTHOR failed?!")
endif()
if(DIAGNOSTIC BOGUS)
message(SEND_ERROR "existence check for bogus category succeeded?!")
endif()

View File

@@ -1,6 +1,7 @@
include(RunCMake)
run_cmake(Actions)
run_cmake(ExistenceCheck)
run_cmake_with_options(
CacheInit