From 5a1af142f120ccc6834efcf786e346b06e0f05c6 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 22 May 2019 09:56:19 -0400 Subject: Genex: Fix value lifetimes in nested TARGET_PROPERTY evaluation For special properties like `INCLUDE_DIRECTORIES`, the pointer returned by `cmTarget::GetProperty` is only valid until the next time the same special property is queried on *any* target. When evaluating a nested `TARGET_PROPERTY` generator expression we may look up such a property more than once on different targets. Fix `TargetPropertyNode::Evaluate` to store the lookup result in locally owned memory earlier. Fixes: #19286 --- Source/cmGeneratorExpressionNode.cxx | 11 ++++++++--- Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake | 1 + .../TARGET_PROPERTY-INCLUDE_DIRECTORIES.cmake | 18 ++++++++++++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 Tests/RunCMake/GeneratorExpression/TARGET_PROPERTY-INCLUDE_DIRECTORIES.cmake diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index 709355a..68ef170 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -1215,7 +1215,12 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode break; } - const char* prop = target->GetProperty(propertyName); + std::string prop; + bool haveProp = false; + if (const char* p = target->GetProperty(propertyName)) { + prop = p; + haveProp = true; + } if (dagCheckerParent) { if (dagCheckerParent->EvaluatingGenexExpression() || @@ -1235,7 +1240,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode } #undef TRANSITIVE_PROPERTY_COMPARE - if (!prop) { + if (!haveProp) { return std::string(); } } else { @@ -1291,7 +1296,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode } } - if (!prop) { + if (!haveProp) { if (target->IsImported() || target->GetType() == cmStateEnums::INTERFACE_LIBRARY) { return linkedTargetsContent; diff --git a/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake index 8abf70d..68a0172 100644 --- a/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake +++ b/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake @@ -53,6 +53,7 @@ run_cmake_with_options(TARGET_FILE_BASE_NAME -DCMAKE_BUILD_TYPE:STRING=Debug) run_cmake_with_options(TARGET_FILE_BASE_NAME-imported-target -DCMAKE_BUILD_TYPE:STRING=Debug) run_cmake(TARGET_FILE_BASE_NAME-non-valid-target) run_cmake(TARGET_LINKER_FILE_BASE_NAME-non-valid-target) +run_cmake(TARGET_PROPERTY-INCLUDE_DIRECTORIES) run_cmake(TARGET_PROPERTY-LOCATION) run_cmake(TARGET_PROPERTY-SOURCES) run_cmake(LINK_ONLY-not-linking) diff --git a/Tests/RunCMake/GeneratorExpression/TARGET_PROPERTY-INCLUDE_DIRECTORIES.cmake b/Tests/RunCMake/GeneratorExpression/TARGET_PROPERTY-INCLUDE_DIRECTORIES.cmake new file mode 100644 index 0000000..cb6f4d8 --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/TARGET_PROPERTY-INCLUDE_DIRECTORIES.cmake @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.14) +enable_language(C) + +add_library(foo1 STATIC empty.c) +target_include_directories(foo1 PUBLIC include) +target_link_libraries(foo1 PRIVATE foo2 foo3 foo4) + +add_library(foo2 STATIC empty.c) +target_include_directories(foo2 PUBLIC $) + +add_library(foo3 STATIC empty.c) +target_include_directories(foo3 PUBLIC $) + +add_library(foo4 STATIC empty.c) +target_include_directories(foo4 PUBLIC $) + +# Evaluate a genex that looks up INCLUDE_DIRECTORIES on multiple targets. +file(GENERATE OUTPUT out.txt CONTENT "$") -- cgit v0.12