diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 7885af0dff..a8f5fd1c7e 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -148,8 +148,6 @@ add_library( cmComputeTargetDepends.cxx cmConfigureLog.h cmConfigureLog.cxx - cmConstStack.h - cmConstStack.tcc cmCPackPropertiesGenerator.h cmCPackPropertiesGenerator.cxx cmCryptoHash.cxx @@ -458,6 +456,8 @@ add_library( cmSourceFileLocationKind.h cmSourceGroup.cxx cmSourceGroup.h + cmStack.h + cmStack.tcc cmStandardLevel.h cmStandardLevelResolver.cxx cmStandardLevelResolver.h diff --git a/Source/cmConstStack.tcc b/Source/cmConstStack.tcc deleted file mode 100644 index ee69c9c478..0000000000 --- a/Source/cmConstStack.tcc +++ /dev/null @@ -1,62 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file LICENSE.rst or https://cmake.org/licensing for details. */ - -#include -#include -#include - -template -struct cmConstStack::Entry -{ - Entry(std::shared_ptr parent, T value) - : Value(std::move(value)) - , Parent(std::move(parent)) - { - } - - T Value; - std::shared_ptr Parent; -}; - -template -cmConstStack::cmConstStack() = default; - -template -Stack cmConstStack::Push(T value) const -{ - return Stack(this->TopEntry, std::move(value)); -} - -template -Stack cmConstStack::Pop() const -{ - assert(this->TopEntry); - return Stack(this->TopEntry->Parent); -} - -template -T const& cmConstStack::Top() const -{ - assert(this->TopEntry); - return this->TopEntry->Value; -} - -template -bool cmConstStack::Empty() const -{ - return !this->TopEntry; -} - -template -cmConstStack::cmConstStack(std::shared_ptr parent, - T value) - : TopEntry( - std::make_shared(std::move(parent), std::move(value))) -{ -} - -template -cmConstStack::cmConstStack(std::shared_ptr top) - : TopEntry(std::move(top)) -{ -} diff --git a/Source/cmFindPackageStack.cxx b/Source/cmFindPackageStack.cxx index 0803049a06..4a824bae23 100644 --- a/Source/cmFindPackageStack.cxx +++ b/Source/cmFindPackageStack.cxx @@ -3,5 +3,6 @@ #define cmFindPackageStack_cxx #include "cmFindPackageStack.h" -#include "cmConstStack.tcc" // IWYU pragma: keep -template class cmConstStack; +#include "cmStack.tcc" // IWYU pragma: keep +template class cmStack; diff --git a/Source/cmFindPackageStack.h b/Source/cmFindPackageStack.h index e281b5149d..0f7be25187 100644 --- a/Source/cmFindPackageStack.h +++ b/Source/cmFindPackageStack.h @@ -7,7 +7,7 @@ #include #include -#include "cmConstStack.h" +#include "cmStack.h" /** * Represents one call to find_package. @@ -25,9 +25,10 @@ public: class cmFindPackageStack : public cmConstStack { - using cmConstStack::cmConstStack; - friend class cmConstStack; + using cmStack::cmStack; + friend cmFindPackageStack::Base; }; #ifndef cmFindPackageStack_cxx -extern template class cmConstStack; +extern template class cmStack; #endif diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx index 9aa5b20919..4de723e294 100644 --- a/Source/cmListFileCache.cxx +++ b/Source/cmListFileCache.cxx @@ -456,8 +456,9 @@ bool cmListFile::ParseString(char const* str, char const* virtual_filename, return !parseError; } -#include "cmConstStack.tcc" -template class cmConstStack; +#include "cmStack.tcc" +template class cmStack; std::ostream& operator<<(std::ostream& os, cmListFileContext const& lfc) { diff --git a/Source/cmListFileCache.h b/Source/cmListFileCache.h index ad78c51b0f..fe2ee08ecc 100644 --- a/Source/cmListFileCache.h +++ b/Source/cmListFileCache.h @@ -12,8 +12,8 @@ #include -#include "cmConstStack.h" #include "cmList.h" +#include "cmStack.h" #include "cmSystemTools.h" /** \class cmListFileCache @@ -169,11 +169,12 @@ bool operator!=(cmListFileContext const& lhs, cmListFileContext const& rhs); class cmListFileBacktrace : public cmConstStack { - using cmConstStack::cmConstStack; - friend class cmConstStack; + using cmStack::cmStack; + friend cmListFileBacktrace::Base; }; #ifndef cmListFileCache_cxx -extern template class cmConstStack; +extern template class cmStack; #endif // Wrap type T as a value with a backtrace. For purposes of diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 5bf8d16198..bc947e9548 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -50,6 +50,7 @@ #include "cmRange.h" #include "cmSourceFile.h" #include "cmSourceFileLocation.h" +#include "cmStack.h" #include "cmState.h" #include "cmStateDirectory.h" #include "cmStateTypes.h" diff --git a/Source/cmConstStack.h b/Source/cmStack.h similarity index 50% rename from Source/cmConstStack.h rename to Source/cmStack.h index d6059e7022..1c11090a98 100644 --- a/Source/cmConstStack.h +++ b/Source/cmStack.h @@ -5,19 +5,31 @@ #include "cmConfigure.h" // IWYU pragma: keep #include +#include -/** Base class template for CRTP to represent a stack of constant values. - Provide value semantics, but use efficient reference-counting underneath - to avoid copies. */ -template -class cmConstStack +enum class cmStackType { - struct Entry; + Const, + Mutable, +}; + +template +struct cmStackEntry; + +/** Base class template for CRTP to represent a stack of values. + Copies of the stack share data; mutating data on one copy will + change the data on all copies. */ +template +class cmStack +{ + using Entry = cmStackEntry; + std::shared_ptr TopEntry; public: /** Default-construct an empty stack. */ - cmConstStack(); + cmStack(); /** Get a stack with the given call context added to the top. */ Stack Push(T value) const; @@ -29,11 +41,21 @@ public: /** Get the value at the top of the stack. This may be called only if Empty() would return false. */ T const& Top() const; + template + typename std::enable_if::type& Top(); /** Return true if this stack is empty. */ bool Empty() const; protected: - cmConstStack(std::shared_ptr parent, T value); - cmConstStack(std::shared_ptr top); + using Base = cmStack; + + cmStack(std::shared_ptr parent, T value); + cmStack(std::shared_ptr top); }; + +/** Specialization of cmStack for CRTP to represent a stack of constant values. + Provide value semantics, but use efficient reference-counting underneath + to avoid copies. */ +template +using cmConstStack = cmStack; diff --git a/Source/cmStack.tcc b/Source/cmStack.tcc new file mode 100644 index 0000000000..210833b453 --- /dev/null +++ b/Source/cmStack.tcc @@ -0,0 +1,85 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file LICENSE.rst or https://cmake.org/licensing for details. */ + +#include +#include +#include + +template +struct cmStackEntry +{ + cmStackEntry(std::shared_ptr parent, T value) + : Value(std::move(value)) + , Parent(std::move(parent)) + { + } + + T mutable Value; + std::shared_ptr Parent; +}; + +template +struct cmStackEntry +{ + cmStackEntry(std::shared_ptr parent, T value) + : Value(std::move(value)) + , Parent(std::move(parent)) + { + } + + T Value; + std::shared_ptr Parent; +}; + +template +cmStack::cmStack() = default; + +template +Stack cmStack::Push(T value) const +{ + return Stack(this->TopEntry, std::move(value)); +} + +template +Stack cmStack::Pop() const +{ + assert(this->TopEntry); + return Stack(this->TopEntry->Parent); +} + +template +T const& cmStack::Top() const +{ + assert(this->TopEntry); + return this->TopEntry->Value; +} + +template +template +typename std::enable_if::type& cmStack::Top() +{ + static_assert(Mutable == cmStackType::Mutable, + "T& cmStack::Top should only exist for mutable cmStack"); + assert(this->TopEntry); + return this->TopEntry->Value; +} + +template +bool cmStack::Empty() const +{ + return !this->TopEntry; +} + +template +cmStack::cmStack(std::shared_ptr parent, + T value) + : TopEntry( + std::make_shared(std::move(parent), std::move(value))) +{ +} + +template +cmStack::cmStack(std::shared_ptr top) + : TopEntry(std::move(top)) +{ +} diff --git a/Utilities/IWYU/mapping.imp b/Utilities/IWYU/mapping.imp index 60560307ef..51ec37a68b 100644 --- a/Utilities/IWYU/mapping.imp +++ b/Utilities/IWYU/mapping.imp @@ -92,8 +92,12 @@ { include: [ "\"form.h\"", private, "\"cmCursesStandardIncludes.h\"", public ] }, { include: [ "", private, "\"cmCursesStandardIncludes.h\"", public ] }, - # Help IWYU understand our explicit instantiation for cmConstStack. - { symbol: [ "cmConstStack::cmConstStack", private, "\"cmConstStack.h\"", public ] }, + # Help IWYU understand our explicit instantiation for cmStack. + { symbol: [ "cmStack::cmStack", private, "\"cmStack.h\"", public ] }, + { symbol: [ "cmStack::Empty", private, "\"cmStack.h\"", public ] }, + { symbol: [ "cmStack::Top", private, "\"cmStack.h\"", public ] }, + { symbol: [ "cmStack::Pop", private, "\"cmStack.h\"", public ] }, + { symbol: [ "cmStack::Push", private, "\"cmStack.h\"", public ] }, ] # vim: set ft=toml: