mirror of
https://github.com/Kitware/CMake.git
synced 2025-10-14 19:08:07 +08:00
string(GENEX_STRIP): Fix regression on nested generator expressions
Since commit 13c7bb5b0c
(cmGeneratorExpression: Update strip function to
collect parsed expressions, 2025-04-08), the logic to strip generator
expressions from a string made incorrect assumptions about the contents of
generator expressions, leading certain cases to be stripped incorrectly.
Clean up the logic and fix broken behavior, and add test coverage with
`string(GENEX_STRIP)`.
Fixes: #27133
This commit is contained in:
@@ -164,33 +164,36 @@ static std::string extractAllGeneratorExpressions(
|
||||
std::string result;
|
||||
std::string::size_type pos = 0;
|
||||
std::string::size_type lastPos = pos;
|
||||
// stack of { Generator Expression Name, Start Position of Value }
|
||||
std::stack<std::pair<std::string, std::string::size_type>> genexps;
|
||||
std::stack<char const*> starts; // indices of "$<"
|
||||
std::stack<char const*> colons; // indices of ":"
|
||||
while ((pos = input.find("$<", lastPos)) != std::string::npos) {
|
||||
result += input.substr(lastPos, pos - lastPos);
|
||||
starts.push(input.c_str() + pos);
|
||||
pos += 2;
|
||||
char const* c = input.c_str() + pos;
|
||||
char const* cName = c;
|
||||
char const* const cStart = c;
|
||||
for (; *c; ++c) {
|
||||
if (cmGeneratorExpression::StartsWithGeneratorExpression(c)) {
|
||||
starts.push(c);
|
||||
++c;
|
||||
cName = c + 1;
|
||||
continue;
|
||||
}
|
||||
if (c[0] == ':' && cName) {
|
||||
genexps.push({ input.substr(pos + (cName - cStart), c - cName),
|
||||
pos + (c + 1 - cStart) });
|
||||
cName = nullptr;
|
||||
} else if (c[0] == '>') {
|
||||
if (!cName && !genexps.empty()) {
|
||||
if (collected) {
|
||||
(*collected)[genexps.top().first].push_back(input.substr(
|
||||
genexps.top().second, pos + c - cStart - genexps.top().second));
|
||||
}
|
||||
genexps.pop();
|
||||
if (c[0] == ':') {
|
||||
if (colons.size() < starts.size()) {
|
||||
colons.push(c);
|
||||
}
|
||||
if (genexps.empty()) {
|
||||
} else if (c[0] == '>') {
|
||||
if (collected && !starts.empty() && !colons.empty()) {
|
||||
(*collected)[std::string(starts.top() + 2, colons.top())].push_back(
|
||||
std::string(colons.top() + 1, c));
|
||||
}
|
||||
if (!starts.empty()) {
|
||||
starts.pop();
|
||||
}
|
||||
if (!colons.empty()) {
|
||||
colons.pop();
|
||||
}
|
||||
if (starts.empty()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -202,7 +205,7 @@ static std::string extractAllGeneratorExpressions(
|
||||
pos += traversed;
|
||||
lastPos = pos;
|
||||
}
|
||||
if (genexps.empty()) {
|
||||
if (starts.empty()) {
|
||||
result += input.substr(lastPos);
|
||||
}
|
||||
return cmGeneratorExpression::StripEmptyListElements(result);
|
||||
|
37
Tests/RunCMake/string/GenexpStrip.cmake
Normal file
37
Tests/RunCMake/string/GenexpStrip.cmake
Normal file
@@ -0,0 +1,37 @@
|
||||
function(test_strip input expected)
|
||||
string(GENEX_STRIP "${input}" strip)
|
||||
if (NOT strip STREQUAL expected)
|
||||
message(FATAL_ERROR "message(GENEXP_STRIP \"${input}\")
|
||||
evaluated to \"${strip}\"
|
||||
expected \"${expected}\"")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
test_strip( # Simple case
|
||||
"$<BOOL:1>"
|
||||
""
|
||||
)
|
||||
test_strip( # LHS contains generator expression
|
||||
"$<$<CONFIG:Release>:NDEBUG>;DEBUG"
|
||||
"DEBUG"
|
||||
)
|
||||
test_strip( # RHS contains generator expression
|
||||
"$<AND:1,$<BOOL:TRUE>>"
|
||||
""
|
||||
)
|
||||
test_strip( # Empty and unfinished expressions
|
||||
"$<>$<$<>"
|
||||
"$<$<>"
|
||||
)
|
||||
test_strip( # Multiple independent expressions
|
||||
"$<IF:TRUE,TRUE,FALSE> / $<IF:TRUE,TRUE,FALSE>"
|
||||
" / "
|
||||
)
|
||||
test_strip( # Multiple : in one expression
|
||||
"$<1:2:3>"
|
||||
""
|
||||
)
|
||||
test_strip( # Multiple case
|
||||
"1$<AND:1,0>2$<IF:$<$<BOOL:1>:$<CONFIG:RELEASE>>,TRUE,FALSE>3"
|
||||
"123"
|
||||
)
|
@@ -56,3 +56,5 @@ run_cmake(RepeatNegativeCount)
|
||||
run_cmake(Hex)
|
||||
run_cmake(HexTooManyArgs)
|
||||
run_cmake(HexNotEnoughArgs)
|
||||
|
||||
run_cmake(GenexpStrip)
|
||||
|
Reference in New Issue
Block a user