From b3873b8272f4773bc25eb2bbad3e332c33ba5716 Mon Sep 17 00:00:00 2001 From: Matthew Woehlke Date: Tue, 29 Jul 2025 10:55:38 -0400 Subject: [PATCH] cmFindPackageStack: Allow controlled mutation As mentioned in the previous commit, we would like to record additional information in the find-package stack, but we don't have the information at the point a stack entry is created. This necessitates making the stack mutable. However, in order to restrict mutation, do not directly expose the mutable value, and instead arrange for it to be accessible only via cmFindPackageStackRAII (renamed and extracted from cmMakefile). This ensures that mutation can only happen while the stack is being built. --- Source/cmFindPackageCommand.cxx | 4 ++-- Source/cmFindPackageStack.cxx | 11 +++++++-- Source/cmFindPackageStack.h | 40 ++++++++++++++++++++++++++++++--- Source/cmMakefile.cxx | 19 +++++++++++++--- Source/cmMakefile.h | 12 +--------- 5 files changed, 65 insertions(+), 21 deletions(-) diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index 24f713a7fa..243061edb8 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -28,6 +28,7 @@ #include "cmDependencyProvider.h" #include "cmExecutionStatus.h" #include "cmExperimental.h" +#include "cmFindPackageStack.h" #include "cmList.h" #include "cmListFileCache.h" #include "cmMakefile.h" @@ -1221,8 +1222,7 @@ bool cmFindPackageCommand::FindPackage( FlushDebugBufferOnExit flushDebugBufferOnExit(*this); PushPopRootPathStack pushPopRootPathStack(*this); SetRestoreFindDefinitions setRestoreFindDefinitions(*this); - cmMakefile::FindPackageStackRAII findPackageStackRAII(this->Makefile, - this->Name); + cmFindPackageStackRAII findPackageStackRAII(this->Makefile, this->Name); // See if we have been told to delegate to FetchContent or some other // redirected config package first. We have to check all names that diff --git a/Source/cmFindPackageStack.cxx b/Source/cmFindPackageStack.cxx index 4a824bae23..6f5045ae74 100644 --- a/Source/cmFindPackageStack.cxx +++ b/Source/cmFindPackageStack.cxx @@ -4,5 +4,12 @@ #include "cmFindPackageStack.h" #include "cmStack.tcc" // IWYU pragma: keep -template class cmStack; +template class cmStack; + +template cmFindPackageCall& +cmStack::Top(); + +cmFindPackageCall const& cmFindPackageStack::Top() const +{ + return this->cmStack::Top(); +} diff --git a/Source/cmFindPackageStack.h b/Source/cmFindPackageStack.h index 0f7be25187..f2bb6c6bc9 100644 --- a/Source/cmFindPackageStack.h +++ b/Source/cmFindPackageStack.h @@ -9,6 +9,8 @@ #include "cmStack.h" +class cmMakefile; + /** * Represents one call to find_package. */ @@ -19,16 +21,48 @@ public: unsigned int Index; }; +/** + * RAII type to manage the find_package call stack. + */ +// Note: implemented in cmMakefile.cxx +class cmFindPackageStackRAII +{ + cmMakefile* Makefile; + cmFindPackageCall** Value = nullptr; + +public: + cmFindPackageStackRAII(cmMakefile* mf, std::string const& pkg); + ~cmFindPackageStackRAII(); + + cmFindPackageStackRAII(cmFindPackageStackRAII const&) = delete; + cmFindPackageStackRAII& operator=(cmFindPackageStackRAII const&) = delete; + + /** Get a mutable pointer to the top of the stack. + The pointer is invalidated if BindTop is called again or when the + cmFindPackageStackRAII goes out of scope. */ + void BindTop(cmFindPackageCall*& value); +}; + /** * Represents a stack of find_package calls with efficient value semantics. */ class cmFindPackageStack - : public cmConstStack + : protected cmStack { using cmStack::cmStack; friend cmFindPackageStack::Base; + friend class cmFindPackageStackRAII; + +public: + using cmStack::Push; + using cmStack::Pop; + using cmStack::Empty; + + cmFindPackageCall const& Top() const; }; #ifndef cmFindPackageStack_cxx -extern template class cmStack; +extern template class cmStack; + +extern template cmFindPackageCall& +cmStack::Top(); #endif diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index bc947e9548..5ceb35e4cb 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -4231,8 +4231,8 @@ cmMakefile::MacroPushPop::~MacroPushPop() this->Makefile->PopMacroScope(this->ReportError); } -cmMakefile::FindPackageStackRAII::FindPackageStackRAII(cmMakefile* mf, - std::string const& name) +cmFindPackageStackRAII::cmFindPackageStackRAII(cmMakefile* mf, + std::string const& name) : Makefile(mf) { this->Makefile->FindPackageStack = @@ -4243,8 +4243,21 @@ cmMakefile::FindPackageStackRAII::FindPackageStackRAII(cmMakefile* mf, this->Makefile->FindPackageStackNextIndex++; } -cmMakefile::FindPackageStackRAII::~FindPackageStackRAII() +void cmFindPackageStackRAII::BindTop(cmFindPackageCall*& value) { + if (this->Value) { + *this->Value = nullptr; + } + this->Value = &value; + value = &this->Makefile->FindPackageStack.cmStack::Top(); +} + +cmFindPackageStackRAII::~cmFindPackageStackRAII() +{ + if (this->Value) { + *this->Value = nullptr; + } + this->Makefile->FindPackageStackNextIndex = this->Makefile->FindPackageStack.Top().Index + 1; this->Makefile->FindPackageStack = this->Makefile->FindPackageStack.Pop(); diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index ab0c75f4f9..17904182d4 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -1034,17 +1034,7 @@ public: // searches std::deque> FindPackageRootPathStack; - class FindPackageStackRAII - { - cmMakefile* Makefile; - - public: - FindPackageStackRAII(cmMakefile* mf, std::string const& pkg); - ~FindPackageStackRAII(); - - FindPackageStackRAII(FindPackageStackRAII const&) = delete; - FindPackageStackRAII& operator=(FindPackageStackRAII const&) = delete; - }; + friend class cmFindPackageStackRAII; class DebugFindPkgRAII {