cmConstStack: Factor out of cmListFileBacktrace

This presents value semantics for a stack of constant values.
Internally it shares ownership to avoid copies.  Previously
this was implemented by `cmListFileBacktrace` explicitly,
but the approach can be re-used for other kinds of stacks.
This commit is contained in:
Brad King 2022-03-30 16:35:23 -04:00
parent 9123193758
commit 11cc728e75
27 changed files with 146 additions and 87 deletions

1
.gitattributes vendored
View File

@ -36,6 +36,7 @@ configure eol=lf
*.hpp our-c-style *.hpp our-c-style
*.hxx our-c-style *.hxx our-c-style
*.notcu our-c-style *.notcu our-c-style
*.tcc our-c-style
*.cmake whitespace=tab-in-indent *.cmake whitespace=tab-in-indent
*.rst whitespace=tab-in-indent conflict-marker-size=79 *.rst whitespace=tab-in-indent conflict-marker-size=79

View File

@ -182,6 +182,8 @@ set(SRCS
cmComputeTargetDepends.cxx cmComputeTargetDepends.cxx
cmConsoleBuf.h cmConsoleBuf.h
cmConsoleBuf.cxx cmConsoleBuf.cxx
cmConstStack.h
cmConstStack.tcc
cmCPackPropertiesGenerator.h cmCPackPropertiesGenerator.h
cmCPackPropertiesGenerator.cxx cmCPackPropertiesGenerator.cxx
cmCryptoHash.cxx cmCryptoHash.cxx

View File

@ -10,12 +10,12 @@
#include <vector> #include <vector>
#include "cmGraphAdjacencyList.h" #include "cmGraphAdjacencyList.h"
#include "cmListFileCache.h"
class cmComputeComponentGraph; class cmComputeComponentGraph;
class cmGeneratorTarget; class cmGeneratorTarget;
class cmGlobalGenerator; class cmGlobalGenerator;
class cmLinkItem; class cmLinkItem;
class cmListFileBacktrace;
class cmSourceFile; class cmSourceFile;
class cmTargetDependSet; class cmTargetDependSet;

39
Source/cmConstStack.h Normal file
View File

@ -0,0 +1,39 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#pragma once
#include "cmConfigure.h" // IWYU pragma: keep
#include <memory>
/** 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 <typename T, typename Stack>
class cmConstStack
{
struct Entry;
std::shared_ptr<Entry const> TopEntry;
public:
/** Default-construct an empty stack. */
cmConstStack();
/** Get a stack with the given call context added to the top. */
Stack Push(T value) const;
/** Get a stack with the top level removed.
May not be called until after a matching Push. */
Stack Pop() const;
/** Get the value at the top of the stack.
This may be called only if Empty() would return false. */
T const& Top() const;
/** Return true if this stack is empty. */
bool Empty() const;
protected:
cmConstStack(std::shared_ptr<Entry const> parent, T value);
cmConstStack(std::shared_ptr<Entry const> top);
};

62
Source/cmConstStack.tcc Normal file
View File

@ -0,0 +1,62 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#include <cassert>
#include <memory>
#include <utility>
template <typename T, typename Stack>
struct cmConstStack<T, Stack>::Entry
{
Entry(std::shared_ptr<Entry const> parent, T value)
: Value(std::move(value))
, Parent(std::move(parent))
{
}
T Value;
std::shared_ptr<Entry const> Parent;
};
template <typename T, typename Stack>
cmConstStack<T, Stack>::cmConstStack() = default;
template <typename T, typename Stack>
Stack cmConstStack<T, Stack>::Push(T value) const
{
return Stack(this->TopEntry, std::move(value));
}
template <typename T, typename Stack>
Stack cmConstStack<T, Stack>::Pop() const
{
assert(this->TopEntry);
return Stack(this->TopEntry->Parent);
}
template <typename T, typename Stack>
T const& cmConstStack<T, Stack>::Top() const
{
assert(this->TopEntry);
return this->TopEntry->Value;
}
template <typename T, typename Stack>
bool cmConstStack<T, Stack>::Empty() const
{
return !this->TopEntry;
}
template <typename T, typename Stack>
cmConstStack<T, Stack>::cmConstStack(std::shared_ptr<Entry const> parent,
T value)
: TopEntry(
std::make_shared<Entry const>(std::move(parent), std::move(value)))
{
}
template <typename T, typename Stack>
cmConstStack<T, Stack>::cmConstStack(std::shared_ptr<Entry const> top)
: TopEntry(std::move(top))
{
}

View File

@ -10,7 +10,6 @@
#include "cmCustomCommand.h" #include "cmCustomCommand.h"
#include "cmCustomCommandLines.h" #include "cmCustomCommandLines.h"
#include "cmExecutionStatus.h" #include "cmExecutionStatus.h"
#include "cmListFileCache.h"
#include "cmLocalGenerator.h" #include "cmLocalGenerator.h"
#include "cmMakefile.h" #include "cmMakefile.h"
#include "cmMessageType.h" #include "cmMessageType.h"
@ -20,6 +19,7 @@
#include "cmSystemTools.h" #include "cmSystemTools.h"
#include "cmake.h" #include "cmake.h"
class cmListFileBacktrace;
class cmTarget; class cmTarget;
static void FinalAction(cmMakefile& makefile, std::string const& name, static void FinalAction(cmMakefile& makefile, std::string const& name,

View File

@ -35,7 +35,6 @@
#include "cmInstallRuntimeDependencySetGenerator.h" #include "cmInstallRuntimeDependencySetGenerator.h"
#include "cmInstallScriptGenerator.h" #include "cmInstallScriptGenerator.h"
#include "cmInstallTargetGenerator.h" #include "cmInstallTargetGenerator.h"
#include "cmListFileCache.h"
#include "cmMakefile.h" #include "cmMakefile.h"
#include "cmMessageType.h" #include "cmMessageType.h"
#include "cmPolicies.h" #include "cmPolicies.h"
@ -49,6 +48,8 @@
#include "cmTargetExport.h" #include "cmTargetExport.h"
#include "cmValue.h" #include "cmValue.h"
class cmListFileBacktrace;
namespace { namespace {
struct RuntimeDependenciesArgs struct RuntimeDependenciesArgs

View File

@ -6,6 +6,7 @@
#include "cmGeneratorExpression.h" #include "cmGeneratorExpression.h"
#include "cmInstallType.h" #include "cmInstallType.h"
#include "cmListFileCache.h"
#include "cmLocalGenerator.h" #include "cmLocalGenerator.h"
#include "cmMakefile.h" #include "cmMakefile.h"
#include "cmStringAlgorithms.h" #include "cmStringAlgorithms.h"

View File

@ -9,9 +9,9 @@
#include <vector> #include <vector>
#include "cmInstallGenerator.h" #include "cmInstallGenerator.h"
#include "cmListFileCache.h"
#include "cmScriptGenerator.h" #include "cmScriptGenerator.h"
class cmListFileBacktrace;
class cmLocalGenerator; class cmLocalGenerator;
/** \class cmInstallDirectoryGenerator /** \class cmInstallDirectoryGenerator

View File

@ -15,6 +15,7 @@
#include "cmExportInstallFileGenerator.h" #include "cmExportInstallFileGenerator.h"
#include "cmExportSet.h" #include "cmExportSet.h"
#include "cmInstallType.h" #include "cmInstallType.h"
#include "cmListFileCache.h"
#include "cmLocalGenerator.h" #include "cmLocalGenerator.h"
#include "cmStringAlgorithms.h" #include "cmStringAlgorithms.h"
#include "cmSystemTools.h" #include "cmSystemTools.h"

View File

@ -11,11 +11,11 @@
#include <vector> #include <vector>
#include "cmInstallGenerator.h" #include "cmInstallGenerator.h"
#include "cmListFileCache.h"
#include "cmScriptGenerator.h" #include "cmScriptGenerator.h"
class cmExportInstallFileGenerator; class cmExportInstallFileGenerator;
class cmExportSet; class cmExportSet;
class cmListFileBacktrace;
class cmLocalGenerator; class cmLocalGenerator;
/** \class cmInstallExportGenerator /** \class cmInstallExportGenerator

View File

@ -11,6 +11,7 @@
#include "cmGeneratorExpression.h" #include "cmGeneratorExpression.h"
#include "cmGlobalGenerator.h" #include "cmGlobalGenerator.h"
#include "cmInstallType.h" #include "cmInstallType.h"
#include "cmListFileCache.h"
#include "cmLocalGenerator.h" #include "cmLocalGenerator.h"
#include "cmStringAlgorithms.h" #include "cmStringAlgorithms.h"

View File

@ -8,11 +8,11 @@
#include <vector> #include <vector>
#include "cmInstallGenerator.h" #include "cmInstallGenerator.h"
#include "cmListFileCache.h"
#include "cmScriptGenerator.h" #include "cmScriptGenerator.h"
class cmGeneratorTarget; class cmGeneratorTarget;
class cmFileSet; class cmFileSet;
class cmListFileBacktrace;
class cmLocalGenerator; class cmLocalGenerator;
class cmInstallFileSetGenerator : public cmInstallGenerator class cmInstallFileSetGenerator : public cmInstallGenerator

View File

@ -6,6 +6,7 @@
#include "cmGeneratorExpression.h" #include "cmGeneratorExpression.h"
#include "cmInstallType.h" #include "cmInstallType.h"
#include "cmListFileCache.h"
#include "cmStringAlgorithms.h" #include "cmStringAlgorithms.h"
class cmLocalGenerator; class cmLocalGenerator;

View File

@ -9,9 +9,9 @@
#include <vector> #include <vector>
#include "cmInstallGenerator.h" #include "cmInstallGenerator.h"
#include "cmListFileCache.h"
#include "cmScriptGenerator.h" #include "cmScriptGenerator.h"
class cmListFileBacktrace;
class cmLocalGenerator; class cmLocalGenerator;
/** \class cmInstallFilesGenerator /** \class cmInstallFilesGenerator

View File

@ -15,6 +15,7 @@
#include "cmGeneratorExpression.h" #include "cmGeneratorExpression.h"
#include "cmInstallRuntimeDependencySet.h" #include "cmInstallRuntimeDependencySet.h"
#include "cmListFileCache.h"
#include "cmLocalGenerator.h" #include "cmLocalGenerator.h"
#include "cmMakefile.h" #include "cmMakefile.h"
#include "cmOutputConverter.h" #include "cmOutputConverter.h"

View File

@ -7,9 +7,9 @@
#include <vector> #include <vector>
#include "cmInstallGenerator.h" #include "cmInstallGenerator.h"
#include "cmListFileCache.h"
#include "cmScriptGenerator.h" #include "cmScriptGenerator.h"
class cmListFileBacktrace;
class cmLocalGenerator; class cmLocalGenerator;
class cmInstallRuntimeDependencySet; class cmInstallRuntimeDependencySet;

View File

@ -7,10 +7,10 @@
#include <vector> #include <vector>
#include "cmInstallGenerator.h" #include "cmInstallGenerator.h"
#include "cmListFileCache.h"
#include "cmScriptGenerator.h" #include "cmScriptGenerator.h"
class cmInstallRuntimeDependencySet; class cmInstallRuntimeDependencySet;
class cmListFileBacktrace;
class cmLocalGenerator; class cmLocalGenerator;
class cmInstallRuntimeDependencySetGenerator : public cmInstallGenerator class cmInstallRuntimeDependencySetGenerator : public cmInstallGenerator

View File

@ -7,6 +7,7 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "cmListFileCache.h"
#include "cmLocalGenerator.h" #include "cmLocalGenerator.h"
#include "cmMakefile.h" #include "cmMakefile.h"
#include "cmPolicies.h" #include "cmPolicies.h"

View File

@ -8,8 +8,8 @@
#include <string> #include <string>
#include "cmInstallGenerator.h" #include "cmInstallGenerator.h"
#include "cmListFileCache.h"
class cmListFileBacktrace;
class cmLocalGenerator; class cmLocalGenerator;
class cmMakefile; class cmMakefile;

View File

@ -1,8 +1,8 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */ file Copyright.txt or https://cmake.org/licensing for details. */
#define cmListFileCache_cxx
#include "cmListFileCache.h" #include "cmListFileCache.h"
#include <cassert>
#include <memory> #include <memory>
#include <sstream> #include <sstream>
#include <utility> #include <utility>
@ -445,53 +445,8 @@ cm::optional<cmListFileContext> cmListFileParser::CheckNesting() const
return cm::nullopt; return cm::nullopt;
} }
// We hold a call/file context. #include "cmConstStack.tcc"
struct cmListFileBacktrace::Entry template class cmConstStack<cmListFileContext, cmListFileBacktrace>;
{
Entry(std::shared_ptr<Entry const> parent, cmListFileContext lfc)
: Context(std::move(lfc))
, Parent(std::move(parent))
{
}
cmListFileContext Context;
std::shared_ptr<Entry const> Parent;
};
/* NOLINTNEXTLINE(performance-unnecessary-value-param) */
cmListFileBacktrace::cmListFileBacktrace(std::shared_ptr<Entry const> parent,
cmListFileContext const& lfc)
: TopEntry(std::make_shared<Entry const>(std::move(parent), lfc))
{
}
cmListFileBacktrace::cmListFileBacktrace(std::shared_ptr<Entry const> top)
: TopEntry(std::move(top))
{
}
cmListFileBacktrace cmListFileBacktrace::Push(
cmListFileContext const& lfc) const
{
return cmListFileBacktrace(this->TopEntry, lfc);
}
cmListFileBacktrace cmListFileBacktrace::Pop() const
{
assert(this->TopEntry);
return cmListFileBacktrace(this->TopEntry->Parent);
}
cmListFileContext const& cmListFileBacktrace::Top() const
{
assert(this->TopEntry);
return this->TopEntry->Context;
}
bool cmListFileBacktrace::Empty() const
{
return !this->TopEntry;
}
std::ostream& operator<<(std::ostream& os, cmListFileContext const& lfc) std::ostream& operator<<(std::ostream& os, cmListFileContext const& lfc)
{ {

View File

@ -12,6 +12,7 @@
#include <cm/optional> #include <cm/optional>
#include "cmConstStack.h"
#include "cmSystemTools.h" #include "cmSystemTools.h"
/** \class cmListFileCache /** \class cmListFileCache
@ -157,35 +158,16 @@ bool operator<(const cmListFileContext& lhs, const cmListFileContext& rhs);
bool operator==(cmListFileContext const& lhs, cmListFileContext const& rhs); bool operator==(cmListFileContext const& lhs, cmListFileContext const& rhs);
bool operator!=(cmListFileContext const& lhs, cmListFileContext const& rhs); bool operator!=(cmListFileContext const& lhs, cmListFileContext const& rhs);
// Represent a backtrace (call stack). Provide value semantics // Represent a backtrace (call stack) with efficient value semantics.
// but use efficient reference-counting underneath to avoid copies.
class cmListFileBacktrace class cmListFileBacktrace
: public cmConstStack<cmListFileContext, cmListFileBacktrace>
{ {
public: using cmConstStack::cmConstStack;
// Default-constructed backtrace is empty. friend class cmConstStack<cmListFileContext, cmListFileBacktrace>;
cmListFileBacktrace() = default;
// Get a backtrace with the given call context added to the top.
cmListFileBacktrace Push(cmListFileContext const& lfc) const;
// Get a backtrace with the top level removed.
// May not be called until after a matching Push.
cmListFileBacktrace Pop() const;
// Get the context at the top of the backtrace.
// This may be called only if Empty() would return false.
cmListFileContext const& Top() const;
// Return true if this backtrace is empty.
bool Empty() const;
private:
struct Entry;
std::shared_ptr<Entry const> TopEntry;
cmListFileBacktrace(std::shared_ptr<Entry const> parent,
cmListFileContext const& lfc);
cmListFileBacktrace(std::shared_ptr<Entry const> top);
}; };
#ifndef cmListFileCache_cxx
extern template class cmConstStack<cmListFileContext, cmListFileBacktrace>;
#endif
// Wrap type T as a value with a backtrace. For purposes of // Wrap type T as a value with a backtrace. For purposes of
// ordering and equality comparison, only the original value is // ordering and equality comparison, only the original value is

View File

@ -10,7 +10,6 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "cmListFileCache.h"
#include "cmLocalCommonGenerator.h" #include "cmLocalCommonGenerator.h"
#include "cmNinjaTypes.h" #include "cmNinjaTypes.h"
#include "cmOutputConverter.h" #include "cmOutputConverter.h"
@ -21,6 +20,7 @@ class cmGeneratedFileStream;
class cmGeneratorTarget; class cmGeneratorTarget;
class cmGlobalGenerator; class cmGlobalGenerator;
class cmGlobalNinjaGenerator; class cmGlobalNinjaGenerator;
class cmListFileBacktrace;
class cmMakefile; class cmMakefile;
class cmRulePlaceholderExpander; class cmRulePlaceholderExpander;
class cmake; class cmake;

View File

@ -14,7 +14,6 @@
#include "cmDefinitions.h" #include "cmDefinitions.h"
#include "cmLinkedTree.h" #include "cmLinkedTree.h"
#include "cmListFileCache.h"
#include "cmPolicies.h" #include "cmPolicies.h"
#include "cmProperty.h" #include "cmProperty.h"
#include "cmPropertyDefinition.h" #include "cmPropertyDefinition.h"
@ -30,6 +29,11 @@ class cmMakefile;
class cmStateSnapshot; class cmStateSnapshot;
class cmMessenger; class cmMessenger;
class cmExecutionStatus; class cmExecutionStatus;
class cmListFileBacktrace;
struct cmListFileArgument;
template <typename T>
class BT;
class cmState class cmState
{ {

View File

@ -13,6 +13,7 @@
#include <cmext/string_view> #include <cmext/string_view>
#include "cmAlgorithms.h" #include "cmAlgorithms.h"
#include "cmListFileCache.h"
#include "cmProperty.h" #include "cmProperty.h"
#include "cmPropertyMap.h" #include "cmPropertyMap.h"
#include "cmRange.h" #include "cmRange.h"

View File

@ -10,11 +10,14 @@
#include "cmAlgorithms.h" #include "cmAlgorithms.h"
#include "cmLinkedTree.h" #include "cmLinkedTree.h"
#include "cmListFileCache.h"
#include "cmStatePrivate.h" #include "cmStatePrivate.h"
#include "cmStateSnapshot.h" #include "cmStateSnapshot.h"
#include "cmValue.h" #include "cmValue.h"
class cmListFileBacktrace;
template <typename T>
class BT;
class cmStateDirectory class cmStateDirectory
{ {
cmStateDirectory( cmStateDirectory(

View File

@ -131,6 +131,9 @@
{ include: [ "<curses.h>", private, "\"cmCursesStandardIncludes.h\"", public ] }, { include: [ "<curses.h>", private, "\"cmCursesStandardIncludes.h\"", public ] },
{ include: [ "\"form.h\"", private, "\"cmCursesStandardIncludes.h\"", public ] }, { include: [ "\"form.h\"", private, "\"cmCursesStandardIncludes.h\"", public ] },
{ include: [ "<form.h>", private, "\"cmCursesStandardIncludes.h\"", public ] }, { include: [ "<form.h>", private, "\"cmCursesStandardIncludes.h\"", public ] },
# Help IWYU understand our explicit instantiation for cmConstStack.
{ symbol: [ "cmConstStack::cmConstStack<T, Stack>", private, "\"cmConstStack.h\"", public ] },
] ]
# vim: set ft=toml: # vim: set ft=toml: