cmGeneratorExpressionEvaluator: Short-circuit boolean operators
parent
49e2a4a0a7
commit
634079b86d
|
@ -195,6 +195,12 @@ Two forms of conditional generator expressions are supported:
|
|||
if ``condition`` is ``0``. Any other value for ``condition`` results in an
|
||||
error.
|
||||
|
||||
.. versionadded:: 3.28
|
||||
|
||||
This generator expression short-circuits such that generator expressions in
|
||||
``false_string`` will not evaluate when ``condition`` is ``1``, and generator
|
||||
expressions in ``true_string`` will not evaluate when condition is ``0``.
|
||||
|
||||
Typically, the ``condition`` is itself a generator expression. For instance,
|
||||
the following expression expands to ``DEBUG_MODE`` when the ``Debug``
|
||||
configuration is used, and the empty string for all other configurations:
|
||||
|
@ -252,6 +258,11 @@ The common boolean logic operators are supported:
|
|||
``condition`` must be ``0`` or ``1``. The result of the expression is
|
||||
``0`` if ``condition`` is ``1``, else ``1``.
|
||||
|
||||
.. versionadded:: 3.28
|
||||
|
||||
Logical operators short-circuit such that generator expressions in the
|
||||
arguments list will not be evaluated once a return value can be determined.
|
||||
|
||||
.. _`Comparison Expressions`:
|
||||
|
||||
Primary Comparison Expressions
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
genexp-no-eval
|
||||
--------------
|
||||
|
||||
* :manual:`generator expressions <cmake-generator-expressions(7)>`
|
||||
short-circuit to avoid unnecessary evaluation of parameters.
|
|
@ -153,10 +153,12 @@ std::string GeneratorExpressionContent::EvaluateParameters(
|
|||
return std::string();
|
||||
}
|
||||
std::string parameter;
|
||||
for (const auto& pExprEval : *pit) {
|
||||
parameter += pExprEval->Evaluate(context, dagChecker);
|
||||
if (context->HadError) {
|
||||
return std::string();
|
||||
if (node->ShouldEvaluateNextParameter(parameters, parameter)) {
|
||||
for (const auto& pExprEval : *pit) {
|
||||
parameter += pExprEval->Evaluate(context, dagChecker);
|
||||
if (context->HadError) {
|
||||
return std::string();
|
||||
}
|
||||
}
|
||||
}
|
||||
parameters.push_back(std::move(parameter));
|
||||
|
|
|
@ -128,6 +128,16 @@ struct BooleanOpNode : public cmGeneratorExpressionNode
|
|||
|
||||
int NumExpectedParameters() const override { return OneOrMoreParameters; }
|
||||
|
||||
bool ShouldEvaluateNextParameter(const std::vector<std::string>& parameters,
|
||||
std::string& def_value) const override
|
||||
{
|
||||
if (!parameters.empty() && parameters[0] == failureVal) {
|
||||
def_value = failureVal;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string Evaluate(const std::vector<std::string>& parameters,
|
||||
cmGeneratorExpressionContext* context,
|
||||
const GeneratorExpressionContent* content,
|
||||
|
@ -195,6 +205,13 @@ static const struct IfNode : public cmGeneratorExpressionNode
|
|||
|
||||
int NumExpectedParameters() const override { return 3; }
|
||||
|
||||
bool ShouldEvaluateNextParameter(const std::vector<std::string>& parameters,
|
||||
std::string&) const override
|
||||
{
|
||||
return (parameters.empty() ||
|
||||
parameters[0] != cmStrCat(parameters.size() - 1, ""));
|
||||
}
|
||||
|
||||
std::string Evaluate(const std::vector<std::string>& parameters,
|
||||
cmGeneratorExpressionContext* context,
|
||||
const GeneratorExpressionContent* content,
|
||||
|
|
|
@ -33,6 +33,12 @@ struct cmGeneratorExpressionNode
|
|||
|
||||
virtual int NumExpectedParameters() const { return 1; }
|
||||
|
||||
virtual bool ShouldEvaluateNextParameter(const std::vector<std::string>&,
|
||||
std::string&) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual std::string Evaluate(
|
||||
const std::vector<std::string>& parameters,
|
||||
cmGeneratorExpressionContext* context,
|
||||
|
|
|
@ -393,6 +393,7 @@ add_RunCMake_test(GenEx-PATH)
|
|||
add_RunCMake_test(GenEx-PATH_EQUAL)
|
||||
add_RunCMake_test(GenEx-LIST)
|
||||
add_RunCMake_test(GeneratorExpression)
|
||||
add_RunCMake_test(GeneratorExpressionShortCircuit)
|
||||
add_RunCMake_test(GeneratorInstance)
|
||||
add_RunCMake_test(GeneratorPlatform)
|
||||
if(XCODE_VERSION)
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -0,0 +1,8 @@
|
|||
CMake Error at BadAND.cmake:2 \(add_custom_target\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<0>
|
||||
|
||||
\$<0> expression requires a parameter.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
|
@ -0,0 +1,4 @@
|
|||
set(error $<0>)
|
||||
add_custom_target(check ALL COMMAND check
|
||||
$<AND:1,${error}>
|
||||
)
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -0,0 +1,8 @@
|
|||
CMake Error at BadIF.cmake:2 \(add_custom_target\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<0>
|
||||
|
||||
\$<0> expression requires a parameter.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
|
@ -0,0 +1,4 @@
|
|||
set(error $<0>)
|
||||
add_custom_target(check ALL COMMAND check
|
||||
$<IF:0,1,${error}>
|
||||
)
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -0,0 +1,8 @@
|
|||
CMake Error at BadOR.cmake:2 \(add_custom_target\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<0>
|
||||
|
||||
\$<0> expression requires a parameter.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
|
@ -0,0 +1,4 @@
|
|||
set(error $<0>)
|
||||
add_custom_target(check ALL COMMAND check
|
||||
$<OR:0,${error}>
|
||||
)
|
|
@ -0,0 +1,3 @@
|
|||
cmake_minimum_required(VERSION 3.26)
|
||||
project(${RunCMake_TEST} NONE)
|
||||
include(${RunCMake_TEST}.cmake)
|
|
@ -0,0 +1,4 @@
|
|||
set(error $<0>)
|
||||
add_custom_target(check ALL COMMAND check
|
||||
$<AND:0,${error}>
|
||||
)
|
|
@ -0,0 +1,5 @@
|
|||
set(error $<0>)
|
||||
add_custom_target(check ALL
|
||||
COMMAND check $<IF:1,1,${error}>
|
||||
COMMAND Check $<IF:0,${error},1>
|
||||
)
|
|
@ -0,0 +1,4 @@
|
|||
set(error $<0>)
|
||||
add_custom_target(check ALL COMMAND check
|
||||
$<OR:1,${error}>
|
||||
)
|
|
@ -0,0 +1,9 @@
|
|||
include(RunCMake)
|
||||
|
||||
run_cmake(GoodIF)
|
||||
run_cmake(GoodAND)
|
||||
run_cmake(GoodOR)
|
||||
|
||||
run_cmake(BadIF)
|
||||
run_cmake(BadAND)
|
||||
run_cmake(BadOR)
|
Loading…
Reference in New Issue