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"
17 #include "cmSystemTools.h"
19 /** \class cmListFileCache
20 * \brief A class to cache list file contents.
22 * cmListFileCache is a class used to cache the contents of parsed
28 struct cmListFileArgument
36 cmListFileArgument() = default;
37 cmListFileArgument(std::string v
, Delimiter d
, long line
)
43 bool operator==(const cmListFileArgument
& r
) const
45 return (this->Value
== r
.Value
) && (this->Delim
== r
.Delim
);
47 bool operator!=(const cmListFileArgument
& r
) const { return !(*this == r
); }
49 Delimiter Delim
= Unquoted
;
53 class cmListFileFunction
56 cmListFileFunction(std::string name
, long line
, long lineEnd
,
57 std::vector
<cmListFileArgument
> args
)
58 : Impl
{ std::make_shared
<Implementation
>(std::move(name
), line
, lineEnd
,
63 std::string
const& OriginalName() const noexcept
65 return this->Impl
->OriginalName
;
68 std::string
const& LowerCaseName() const noexcept
70 return this->Impl
->LowerCaseName
;
73 long Line() const noexcept
{ return this->Impl
->Line
; }
74 long LineEnd() const noexcept
{ return this->Impl
->LineEnd
; }
76 std::vector
<cmListFileArgument
> const& Arguments() const noexcept
78 return this->Impl
->Arguments
;
84 Implementation(std::string name
, long line
, long lineEnd
,
85 std::vector
<cmListFileArgument
> args
)
86 : OriginalName
{ std::move(name
) }
87 , LowerCaseName
{ cmSystemTools::LowerCase(this->OriginalName
) }
90 , Arguments
{ std::move(args
) }
94 std::string OriginalName
;
95 std::string LowerCaseName
;
98 std::vector
<cmListFileArgument
> Arguments
;
101 std::shared_ptr
<Implementation
const> Impl
;
104 class cmListFileContext
108 std::string FilePath
;
110 static long const DeferPlaceholderLine
= -1;
111 cm::optional
<std::string
> DeferId
;
113 cmListFileContext() = default;
114 // This move constructor is marked `noexcept` yet `clang-tidy` 14 reports it
115 // as being able to throw an exception. Suppress the warning as there doesn't
116 // seem to be any way for this to happen given the member types.
117 // NOLINTNEXTLINE(bugprone-exception-escape)
118 cmListFileContext(cmListFileContext
&& /*other*/) noexcept
= default;
119 cmListFileContext(const cmListFileContext
& /*other*/) = default;
120 cmListFileContext
& operator=(const cmListFileContext
& /*other*/) = default;
121 #if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
122 cmListFileContext
& operator=(cmListFileContext
&& /*other*/) noexcept
=
125 // The move assignment operators for several STL classes did not become
126 // noexcept until C++17, which causes some tools to warn about this move
127 // assignment operator throwing an exception when it shouldn't.
128 cmListFileContext
& operator=(cmListFileContext
&& /*other*/) noexcept
=
132 cmListFileContext(std::string name
, std::string filePath
, long line
)
133 : Name(std::move(name
))
134 , FilePath(std::move(filePath
))
139 static cmListFileContext
FromListFilePath(std::string
const& filePath
)
141 // We are entering a file-level scope but have not yet reached
142 // any specific line or command invocation within it. This context
143 // is useful to print when it is at the top but otherwise can be
144 // skipped during call stack printing.
145 cmListFileContext lfc
;
146 lfc
.FilePath
= filePath
;
150 static cmListFileContext
FromListFileFunction(
151 cmListFileFunction
const& lff
, std::string
const& fileName
,
152 cm::optional
<std::string
> deferId
= {})
154 cmListFileContext lfc
;
155 lfc
.FilePath
= fileName
;
156 lfc
.Line
= lff
.Line();
157 lfc
.Name
= lff
.OriginalName();
158 lfc
.DeferId
= std::move(deferId
);
163 std::ostream
& operator<<(std::ostream
&, cmListFileContext
const&);
164 bool operator<(const cmListFileContext
& lhs
, const cmListFileContext
& rhs
);
165 bool operator==(cmListFileContext
const& lhs
, cmListFileContext
const& rhs
);
166 bool operator!=(cmListFileContext
const& lhs
, cmListFileContext
const& rhs
);
168 // Represent a backtrace (call stack) with efficient value semantics.
169 class cmListFileBacktrace
170 : public cmConstStack
<cmListFileContext
, cmListFileBacktrace
>
172 using cmConstStack::cmConstStack
;
173 friend class cmConstStack
<cmListFileContext
, cmListFileBacktrace
>;
175 #ifndef cmListFileCache_cxx
176 extern template class cmConstStack
<cmListFileContext
, cmListFileBacktrace
>;
179 // Wrap type T as a value with a backtrace. For purposes of
180 // ordering and equality comparison, only the original value is
181 // used. The backtrace is considered incidental.
182 template <typename T
>
186 BT(T v
= T(), cmListFileBacktrace bt
= cmListFileBacktrace())
187 : Value(std::move(v
))
188 , Backtrace(std::move(bt
))
192 cmListFileBacktrace Backtrace
;
193 friend bool operator==(BT
<T
> const& l
, BT
<T
> const& r
)
195 return l
.Value
== r
.Value
;
197 friend bool operator<(BT
<T
> const& l
, BT
<T
> const& r
)
199 return l
.Value
< r
.Value
;
201 friend bool operator==(BT
<T
> const& l
, T
const& r
) { return l
.Value
== r
; }
202 friend bool operator==(T
const& l
, BT
<T
> const& r
) { return l
== r
.Value
; }
205 std::ostream
& operator<<(std::ostream
& os
, BT
<std::string
> const& s
);
207 // Wrap type T as a value with potentially multiple backtraces. For purposes
208 // of ordering and equality comparison, only the original value is used. The
209 // backtrace is considered incidental.
210 template <typename T
>
214 BTs(T v
= T(), cmListFileBacktrace bt
= cmListFileBacktrace())
215 : Value(std::move(v
))
217 this->Backtraces
.emplace_back(std::move(bt
));
220 std::vector
<cmListFileBacktrace
> Backtraces
;
221 friend bool operator==(BTs
<T
> const& l
, BTs
<T
> const& r
)
223 return l
.Value
== r
.Value
;
225 friend bool operator<(BTs
<T
> const& l
, BTs
<T
> const& r
)
227 return l
.Value
< r
.Value
;
229 friend bool operator==(BTs
<T
> const& l
, T
const& r
) { return l
.Value
== r
; }
230 friend bool operator==(T
const& l
, BTs
<T
> const& r
) { return l
== r
.Value
; }
233 std::vector
<BT
<std::string
>> cmExpandListWithBacktrace(
234 std::string
const& list
,
235 cmListFileBacktrace
const& bt
= cmListFileBacktrace(),
236 cmList::EmptyElements emptyArgs
= cmList::EmptyElements::No
);
240 bool ParseFile(const char* path
, cmMessenger
* messenger
,
241 cmListFileBacktrace
const& lfbt
);
243 bool ParseString(const char* str
, const char* virtual_filename
,
244 cmMessenger
* messenger
, cmListFileBacktrace
const& lfbt
);
246 std::vector
<cmListFileFunction
> Functions
;