1 /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 file Copyright.txt or https://cmake.org/licensing for details. */
5 #include "cmConfigure.h" // IWYU pragma: keep
13 #include <cm/optional>
15 #include "cmConstStack.h"
16 #include "cmSystemTools.h"
18 /** \class cmListFileCache
19 * \brief A class to cache list file contents.
21 * cmListFileCache is a class used to cache the contents of parsed
27 struct cmListFileArgument
35 cmListFileArgument() = default;
36 cmListFileArgument(std::string v, Delimiter d, long line)
42 bool operator==(const cmListFileArgument& r) const
44 return (this->Value == r.Value) && (this->Delim == r.Delim);
46 bool operator!=(const cmListFileArgument& r) const { return !(*this == r); }
48 Delimiter Delim = Unquoted;
52 class cmListFileFunction
55 cmListFileFunction(std::string name, long line, long lineEnd,
56 std::vector<cmListFileArgument> args)
57 : Impl{ std::make_shared<Implementation>(std::move(name), line, lineEnd,
62 std::string const& OriginalName() const noexcept
64 return this->Impl->OriginalName;
67 std::string const& LowerCaseName() const noexcept
69 return this->Impl->LowerCaseName;
72 long Line() const noexcept { return this->Impl->Line; }
73 long LineEnd() const noexcept { return this->Impl->LineEnd; }
75 std::vector<cmListFileArgument> const& Arguments() const noexcept
77 return this->Impl->Arguments;
83 Implementation(std::string name, long line, long lineEnd,
84 std::vector<cmListFileArgument> args)
85 : OriginalName{ std::move(name) }
86 , LowerCaseName{ cmSystemTools::LowerCase(this->OriginalName) }
89 , Arguments{ std::move(args) }
93 std::string OriginalName;
94 std::string LowerCaseName;
97 std::vector<cmListFileArgument> Arguments;
100 std::shared_ptr<Implementation const> Impl;
103 class cmListFileContext
107 std::string FilePath;
109 static long const DeferPlaceholderLine = -1;
110 cm::optional<std::string> DeferId;
112 cmListFileContext() = default;
113 // This move constructor is marked `noexcept` yet `clang-tidy` 14 reports it
114 // as being able to throw an exception. Suppress the warning as there doesn't
115 // seem to be any way for this to happen given the member types.
116 // NOLINTNEXTLINE(bugprone-exception-escape)
117 cmListFileContext(cmListFileContext&& /*other*/) noexcept = default;
118 cmListFileContext(const cmListFileContext& /*other*/) = default;
119 cmListFileContext& operator=(const cmListFileContext& /*other*/) = default;
120 #if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
121 cmListFileContext& operator=(cmListFileContext&& /*other*/) noexcept =
124 // The move assignment operators for several STL classes did not become
125 // noexcept until C++17, which causes some tools to warn about this move
126 // assignment operator throwing an exception when it shouldn't.
127 cmListFileContext& operator=(cmListFileContext&& /*other*/) noexcept =
131 cmListFileContext(std::string name, std::string filePath, long line)
132 : Name(std::move(name))
133 , FilePath(std::move(filePath))
138 static cmListFileContext FromListFilePath(std::string const& filePath)
140 // We are entering a file-level scope but have not yet reached
141 // any specific line or command invocation within it. This context
142 // is useful to print when it is at the top but otherwise can be
143 // skipped during call stack printing.
144 cmListFileContext lfc;
145 lfc.FilePath = filePath;
149 static cmListFileContext FromListFileFunction(
150 cmListFileFunction const& lff, std::string const& fileName,
151 cm::optional<std::string> deferId = {})
153 cmListFileContext lfc;
154 lfc.FilePath = fileName;
155 lfc.Line = lff.Line();
156 lfc.Name = lff.OriginalName();
157 lfc.DeferId = std::move(deferId);
162 std::ostream& operator<<(std::ostream&, cmListFileContext const&);
163 bool operator<(const cmListFileContext& lhs, const cmListFileContext& rhs);
164 bool operator==(cmListFileContext const& lhs, cmListFileContext const& rhs);
165 bool operator!=(cmListFileContext const& lhs, cmListFileContext const& rhs);
167 // Represent a backtrace (call stack) with efficient value semantics.
168 class cmListFileBacktrace
169 : public cmConstStack<cmListFileContext, cmListFileBacktrace>
171 using cmConstStack::cmConstStack;
172 friend class cmConstStack<cmListFileContext, cmListFileBacktrace>;
174 #ifndef cmListFileCache_cxx
175 extern template class cmConstStack<cmListFileContext, cmListFileBacktrace>;
178 // Wrap type T as a value with a backtrace. For purposes of
179 // ordering and equality comparison, only the original value is
180 // used. The backtrace is considered incidental.
181 template <typename T>
185 BT(T v = T(), cmListFileBacktrace bt = cmListFileBacktrace())
186 : Value(std::move(v))
187 , Backtrace(std::move(bt))
191 cmListFileBacktrace Backtrace;
192 friend bool operator==(BT<T> const& l, BT<T> const& r)
194 return l.Value == r.Value;
196 friend bool operator<(BT<T> const& l, BT<T> const& r)
198 return l.Value < r.Value;
200 friend bool operator==(BT<T> const& l, T const& r) { return l.Value == r; }
201 friend bool operator==(T const& l, BT<T> const& r) { return l == r.Value; }
204 std::ostream& operator<<(std::ostream& os, BT<std::string> const& s);
206 // Wrap type T as a value with potentially multiple backtraces. For purposes
207 // of ordering and equality comparison, only the original value is used. The
208 // backtrace is considered incidental.
209 template <typename T>
213 BTs(T v = T(), cmListFileBacktrace bt = cmListFileBacktrace())
214 : Value(std::move(v))
216 this->Backtraces.emplace_back(std::move(bt));
219 std::vector<cmListFileBacktrace> Backtraces;
220 friend bool operator==(BTs<T> const& l, BTs<T> const& r)
222 return l.Value == r.Value;
224 friend bool operator<(BTs<T> const& l, BTs<T> const& r)
226 return l.Value < r.Value;
228 friend bool operator==(BTs<T> const& l, T const& r) { return l.Value == r; }
229 friend bool operator==(T const& l, BTs<T> const& r) { return l == r.Value; }
232 std::vector<BT<std::string>> cmExpandListWithBacktrace(
233 std::string const& list,
234 cmListFileBacktrace const& bt = cmListFileBacktrace(),
235 bool emptyArgs = false);
239 bool ParseFile(const char* path, cmMessenger* messenger,
240 cmListFileBacktrace const& lfbt);
242 bool ParseString(const char* str, const char* virtual_filename,
243 cmMessenger* messenger, cmListFileBacktrace const& lfbt);
245 std::vector<cmListFileFunction> Functions;