xref: /llvm-project/clang/lib/Format/Macros.h (revision 1c58208d899285318c89e069268145c85ec33368)
1d6d0dc1fSManuel Klimek //===--- Macros.h - Format C++ code -----------------------------*- C++ -*-===//
2e336b74cSManuel Klimek //
3c874dd53SChristopher Di Bella // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4c874dd53SChristopher Di Bella // See https://llvm.org/LICENSE.txt for license information.
5c874dd53SChristopher Di Bella // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e336b74cSManuel Klimek //
7e336b74cSManuel Klimek //===----------------------------------------------------------------------===//
8e336b74cSManuel Klimek ///
9e336b74cSManuel Klimek /// \file
10e336b74cSManuel Klimek /// This file contains the main building blocks of macro support in
11e336b74cSManuel Klimek /// clang-format.
12e336b74cSManuel Klimek ///
13e336b74cSManuel Klimek /// In order to not violate the requirement that clang-format can format files
14e336b74cSManuel Klimek /// in isolation, clang-format's macro support uses expansions users provide
15e336b74cSManuel Klimek /// as part of clang-format's style configuration.
16e336b74cSManuel Klimek ///
17e336b74cSManuel Klimek /// Macro definitions are of the form "MACRO(p1, p2)=p1 + p2", but only support
18e336b74cSManuel Klimek /// one level of expansion (\see MacroExpander for a full description of what
19e336b74cSManuel Klimek /// is supported).
20e336b74cSManuel Klimek ///
21e336b74cSManuel Klimek /// As part of parsing, clang-format uses the MacroExpander to expand the
22e336b74cSManuel Klimek /// spelled token streams into expanded token streams when it encounters a
23e336b74cSManuel Klimek /// macro call. The UnwrappedLineParser continues to parse UnwrappedLines
24e336b74cSManuel Klimek /// from the expanded token stream.
25d6d0dc1fSManuel Klimek /// After the expanded unwrapped lines are parsed, the MacroCallReconstructor
26d6d0dc1fSManuel Klimek /// matches the spelled token stream into unwrapped lines that best resemble the
27d6d0dc1fSManuel Klimek /// structure of the expanded unwrapped lines. These reconstructed unwrapped
28d6d0dc1fSManuel Klimek /// lines are aliasing the tokens in the expanded token stream, so that token
29d6d0dc1fSManuel Klimek /// annotations will be reused when formatting the spelled macro calls.
30e336b74cSManuel Klimek ///
31d6d0dc1fSManuel Klimek /// When formatting, clang-format annotates and formats the expanded unwrapped
32d6d0dc1fSManuel Klimek /// lines first, determining the token types. Next, it formats the spelled
33d6d0dc1fSManuel Klimek /// unwrapped lines, keeping the token types fixed, while allowing other
34d6d0dc1fSManuel Klimek /// formatting decisions to change.
35e336b74cSManuel Klimek ///
36e336b74cSManuel Klimek //===----------------------------------------------------------------------===//
37e336b74cSManuel Klimek 
38e336b74cSManuel Klimek #ifndef CLANG_LIB_FORMAT_MACROS_H
39e336b74cSManuel Klimek #define CLANG_LIB_FORMAT_MACROS_H
40e336b74cSManuel Klimek 
41d6d0dc1fSManuel Klimek #include <list>
42e336b74cSManuel Klimek 
43e336b74cSManuel Klimek #include "FormatToken.h"
44d6d0dc1fSManuel Klimek #include "llvm/ADT/DenseMap.h"
45e336b74cSManuel Klimek 
46e336b74cSManuel Klimek namespace clang {
47e336b74cSManuel Klimek namespace format {
48d6d0dc1fSManuel Klimek 
49d6d0dc1fSManuel Klimek struct UnwrappedLine;
50d6d0dc1fSManuel Klimek struct UnwrappedLineNode;
51e336b74cSManuel Klimek 
52e336b74cSManuel Klimek /// Takes a set of macro definitions as strings and allows expanding calls to
53e336b74cSManuel Klimek /// those macros.
54e336b74cSManuel Klimek ///
55e336b74cSManuel Klimek /// For example:
56e336b74cSManuel Klimek /// Definition: A(x, y)=x + y
57e336b74cSManuel Klimek /// Call      : A(int a = 1, 2)
58e336b74cSManuel Klimek /// Expansion : int a = 1 + 2
59e336b74cSManuel Klimek ///
60e336b74cSManuel Klimek /// Expansion does not check arity of the definition.
61e336b74cSManuel Klimek /// If fewer arguments than expected are provided, the remaining parameters
62e336b74cSManuel Klimek /// are considered empty:
63e336b74cSManuel Klimek /// Call     : A(a)
64e336b74cSManuel Klimek /// Expansion: a +
65e336b74cSManuel Klimek /// If more arguments than expected are provided, they will be discarded.
66e336b74cSManuel Klimek ///
67e336b74cSManuel Klimek /// The expander does not support:
68e336b74cSManuel Klimek /// - recursive expansion
69e336b74cSManuel Klimek /// - stringification
70e336b74cSManuel Klimek /// - concatenation
71e336b74cSManuel Klimek /// - variadic macros
72e336b74cSManuel Klimek ///
73e336b74cSManuel Klimek /// Furthermore, only a single expansion of each macro argument is supported,
74e336b74cSManuel Klimek /// so that we cannot get conflicting formatting decisions from different
75e336b74cSManuel Klimek /// expansions.
76e336b74cSManuel Klimek /// Definition: A(x)=x+x
77e336b74cSManuel Klimek /// Call      : A(id)
78e336b74cSManuel Klimek /// Expansion : id+x
79e336b74cSManuel Klimek ///
80e336b74cSManuel Klimek class MacroExpander {
81e336b74cSManuel Klimek public:
82*1c58208dSOwen Pan   using ArgsList = ArrayRef<SmallVector<FormatToken *, 8>>;
83e336b74cSManuel Klimek 
84e336b74cSManuel Klimek   /// Construct a macro expander from a set of macro definitions.
85e336b74cSManuel Klimek   /// Macro definitions must be encoded as UTF-8.
86e336b74cSManuel Klimek   ///
87e336b74cSManuel Klimek   /// Each entry in \p Macros must conform to the following simple
88e336b74cSManuel Klimek   /// macro-definition language:
89e336b74cSManuel Klimek   /// <definition> ::= <id> <expansion> | <id> "(" <params> ")" <expansion>
90e336b74cSManuel Klimek   /// <params>     ::= <id-list> | ""
91e336b74cSManuel Klimek   /// <id-list>    ::= <id> | <id> "," <params>
92e336b74cSManuel Klimek   /// <expansion>  ::= "=" <tail> | <eof>
93e336b74cSManuel Klimek   /// <tail>       ::= <tok> <tail> | <eof>
94e336b74cSManuel Klimek   ///
95e336b74cSManuel Klimek   /// Macros that cannot be parsed will be silently discarded.
96e336b74cSManuel Klimek   ///
97e336b74cSManuel Klimek   MacroExpander(const std::vector<std::string> &Macros,
98*1c58208dSOwen Pan                 SourceManager &SourceMgr, const FormatStyle &Style,
99e336b74cSManuel Klimek                 llvm::SpecificBumpPtrAllocator<FormatToken> &Allocator,
100e336b74cSManuel Klimek                 IdentifierTable &IdentTable);
101e336b74cSManuel Klimek   ~MacroExpander();
102e336b74cSManuel Klimek 
10301402831SManuel Klimek   /// Returns whether any macro \p Name is defined, regardless of overloads.
104*1c58208dSOwen Pan   bool defined(StringRef Name) const;
105e336b74cSManuel Klimek 
10601402831SManuel Klimek   /// Returns whetherh there is an object-like overload, i.e. where the macro
10701402831SManuel Klimek   /// has no arguments and should not consume subsequent parentheses.
108*1c58208dSOwen Pan   bool objectLike(StringRef Name) const;
109e336b74cSManuel Klimek 
11001402831SManuel Klimek   /// Returns whether macro \p Name provides an overload with the given arity.
111*1c58208dSOwen Pan   bool hasArity(StringRef Name, unsigned Arity) const;
11201402831SManuel Klimek 
113e336b74cSManuel Klimek   /// Returns the expanded stream of format tokens for \p ID, where
114e336b74cSManuel Klimek   /// each element in \p Args is a positional argument to the macro call.
11501402831SManuel Klimek   /// If \p Args is not set, the object-like overload is used.
11601402831SManuel Klimek   /// If \p Args is set, the overload with the arity equal to \c Args.size() is
11701402831SManuel Klimek   /// used.
118*1c58208dSOwen Pan   SmallVector<FormatToken *, 8>
11901402831SManuel Klimek   expand(FormatToken *ID, std::optional<ArgsList> OptionalArgs) const;
120e336b74cSManuel Klimek 
121e336b74cSManuel Klimek private:
122e336b74cSManuel Klimek   struct Definition;
123e336b74cSManuel Klimek   class DefinitionParser;
124e336b74cSManuel Klimek 
125e336b74cSManuel Klimek   void parseDefinition(const std::string &Macro);
126e336b74cSManuel Klimek 
127*1c58208dSOwen Pan   SourceManager &SourceMgr;
128e336b74cSManuel Klimek   const FormatStyle &Style;
129e336b74cSManuel Klimek   llvm::SpecificBumpPtrAllocator<FormatToken> &Allocator;
130e336b74cSManuel Klimek   IdentifierTable &IdentTable;
13136229fa3Sowenca   SmallVector<std::unique_ptr<llvm::MemoryBuffer>> Buffers;
13201402831SManuel Klimek   llvm::StringMap<llvm::DenseMap<int, Definition>> FunctionLike;
13301402831SManuel Klimek   llvm::StringMap<Definition> ObjectLike;
134e336b74cSManuel Klimek };
135e336b74cSManuel Klimek 
136d6d0dc1fSManuel Klimek /// Converts a sequence of UnwrappedLines containing expanded macros into a
137d6d0dc1fSManuel Klimek /// single UnwrappedLine containing the macro calls.  This UnwrappedLine may be
138d6d0dc1fSManuel Klimek /// broken into child lines, in a way that best conveys the structure of the
139d6d0dc1fSManuel Klimek /// expanded code.
140d6d0dc1fSManuel Klimek ///
141d6d0dc1fSManuel Klimek /// In the simplest case, a spelled UnwrappedLine contains one macro, and after
142d6d0dc1fSManuel Klimek /// expanding it we have one expanded UnwrappedLine.  In general, macro
143d6d0dc1fSManuel Klimek /// expansions can span UnwrappedLines, and multiple macros can contribute
144d6d0dc1fSManuel Klimek /// tokens to the same line.  We keep consuming expanded lines until:
145d6d0dc1fSManuel Klimek /// *   all expansions that started have finished (we're not chopping any macros
146d6d0dc1fSManuel Klimek ///     in half)
147d6d0dc1fSManuel Klimek /// *   *and* we've reached the end of a *spelled* unwrapped line.
148d6d0dc1fSManuel Klimek ///
149d6d0dc1fSManuel Klimek /// A single UnwrappedLine represents this chunk of code.
150d6d0dc1fSManuel Klimek ///
151d6d0dc1fSManuel Klimek /// After this point, the state of the spelled/expanded stream is "in sync"
152d6d0dc1fSManuel Klimek /// (both at the start of an UnwrappedLine, with no macros open), so the
15301402831SManuel Klimek /// Reconstructor can be thrown away and parsing can continue.
154d6d0dc1fSManuel Klimek ///
155d6d0dc1fSManuel Klimek /// Given a mapping from the macro name identifier token in the macro call
156d6d0dc1fSManuel Klimek /// to the tokens of the macro call, for example:
157d6d0dc1fSManuel Klimek /// CLASSA -> CLASSA({public: void x();})
158d6d0dc1fSManuel Klimek ///
159d6d0dc1fSManuel Klimek /// When getting the formatted lines of the expansion via the \c addLine method
160d6d0dc1fSManuel Klimek /// (each '->' specifies a call to \c addLine ):
161d6d0dc1fSManuel Klimek /// -> class A {
162d6d0dc1fSManuel Klimek /// -> public:
163d6d0dc1fSManuel Klimek /// ->   void x();
164d6d0dc1fSManuel Klimek /// -> };
165d6d0dc1fSManuel Klimek ///
166d6d0dc1fSManuel Klimek /// Creates the tree of unwrapped lines containing the macro call tokens so that
167d6d0dc1fSManuel Klimek /// the macro call tokens fit the semantic structure of the expanded formatted
168d6d0dc1fSManuel Klimek /// lines:
169d6d0dc1fSManuel Klimek /// -> CLASSA({
170d6d0dc1fSManuel Klimek /// -> public:
171d6d0dc1fSManuel Klimek /// ->   void x();
172d6d0dc1fSManuel Klimek /// -> })
173d6d0dc1fSManuel Klimek class MacroCallReconstructor {
174d6d0dc1fSManuel Klimek public:
175d6d0dc1fSManuel Klimek   /// Create an Reconstructor whose resulting \p UnwrappedLine will start at
176d6d0dc1fSManuel Klimek   /// \p Level, using the map from name identifier token to the corresponding
177d6d0dc1fSManuel Klimek   /// tokens of the spelled macro call.
178d6d0dc1fSManuel Klimek   MacroCallReconstructor(
179d6d0dc1fSManuel Klimek       unsigned Level,
180d6d0dc1fSManuel Klimek       const llvm::DenseMap<FormatToken *, std::unique_ptr<UnwrappedLine>>
181d6d0dc1fSManuel Klimek           &ActiveExpansions);
182d6d0dc1fSManuel Klimek 
183d6d0dc1fSManuel Klimek   /// For the given \p Line, match all occurences of tokens expanded from a
184d6d0dc1fSManuel Klimek   /// macro to unwrapped lines in the spelled macro call so that the resulting
185d6d0dc1fSManuel Klimek   /// tree of unwrapped lines best resembles the structure of unwrapped lines
186d6d0dc1fSManuel Klimek   /// passed in via \c addLine.
187d6d0dc1fSManuel Klimek   void addLine(const UnwrappedLine &Line);
188d6d0dc1fSManuel Klimek 
189d6d0dc1fSManuel Klimek   /// Check whether at the current state there is no open macro expansion
190d6d0dc1fSManuel Klimek   /// that needs to be processed to finish an macro call.
191d6d0dc1fSManuel Klimek   /// Only when \c finished() is true, \c takeResult() can be called to retrieve
192d6d0dc1fSManuel Klimek   /// the resulting \c UnwrappedLine.
193d6d0dc1fSManuel Klimek   /// If there are multiple subsequent macro calls within an unwrapped line in
194d6d0dc1fSManuel Klimek   /// the spelled token stream, the calling code may also continue to call
195d6d0dc1fSManuel Klimek   /// \c addLine() when \c finished() is true.
finished()196d6d0dc1fSManuel Klimek   bool finished() const { return ActiveExpansions.empty(); }
197d6d0dc1fSManuel Klimek 
198d6d0dc1fSManuel Klimek   /// Retrieve the formatted \c UnwrappedLine containing the orginal
199d6d0dc1fSManuel Klimek   /// macro calls, formatted according to the expanded token stream received
200d6d0dc1fSManuel Klimek   /// via \c addLine().
201d6d0dc1fSManuel Klimek   /// Generally, this line tries to have the same structure as the expanded,
202d6d0dc1fSManuel Klimek   /// formatted unwrapped lines handed in via \c addLine(), with the exception
203d6d0dc1fSManuel Klimek   /// that for multiple top-level lines, each subsequent line will be the
204d6d0dc1fSManuel Klimek   /// child of the last token in its predecessor. This representation is chosen
205d6d0dc1fSManuel Klimek   /// because it is a precondition to the formatter that we get what looks like
206d6d0dc1fSManuel Klimek   /// a single statement in a single \c UnwrappedLine (i.e. matching parens).
207d6d0dc1fSManuel Klimek   ///
208d6d0dc1fSManuel Klimek   /// If a token in a macro argument is a child of a token in the expansion,
209d6d0dc1fSManuel Klimek   /// the parent will be the corresponding token in the macro call.
210d6d0dc1fSManuel Klimek   /// For example:
211d6d0dc1fSManuel Klimek   ///   #define C(a, b) class C { a b
212d6d0dc1fSManuel Klimek   ///   C(int x;, int y;)
213d6d0dc1fSManuel Klimek   /// would expand to
214d6d0dc1fSManuel Klimek   ///   class C { int x; int y;
215d6d0dc1fSManuel Klimek   /// where in a formatted line "int x;" and "int y;" would both be new separate
216d6d0dc1fSManuel Klimek   /// lines.
217d6d0dc1fSManuel Klimek   ///
218d6d0dc1fSManuel Klimek   /// In the result, "int x;" will be a child of the opening parenthesis in "C("
219d6d0dc1fSManuel Klimek   /// and "int y;" will be a child of the "," token:
220d6d0dc1fSManuel Klimek   ///   C (
221d6d0dc1fSManuel Klimek   ///     \- int x;
222d6d0dc1fSManuel Klimek   ///     ,
223d6d0dc1fSManuel Klimek   ///     \- int y;
224d6d0dc1fSManuel Klimek   ///     )
225d6d0dc1fSManuel Klimek   UnwrappedLine takeResult() &&;
226d6d0dc1fSManuel Klimek 
227d6d0dc1fSManuel Klimek private:
228ddb4450aSr4nt   void add(FormatToken *Token, FormatToken *ExpandedParent, bool First,
229ddb4450aSr4nt            unsigned Level);
230ddb4450aSr4nt   void prepareParent(FormatToken *ExpandedParent, bool First, unsigned Level);
231d6d0dc1fSManuel Klimek   FormatToken *getParentInResult(FormatToken *Parent);
232d6d0dc1fSManuel Klimek   void reconstruct(FormatToken *Token);
233d6d0dc1fSManuel Klimek   void startReconstruction(FormatToken *Token);
234d6d0dc1fSManuel Klimek   bool reconstructActiveCallUntil(FormatToken *Token);
235d6d0dc1fSManuel Klimek   void endReconstruction(FormatToken *Token);
236d6d0dc1fSManuel Klimek   bool processNextReconstructed();
237d6d0dc1fSManuel Klimek   void finalize();
238d6d0dc1fSManuel Klimek 
239f44d28f8SManuel Klimek   struct ReconstructedLine;
240d6d0dc1fSManuel Klimek 
241f44d28f8SManuel Klimek   void appendToken(FormatToken *Token, ReconstructedLine *L = nullptr);
242f44d28f8SManuel Klimek   UnwrappedLine createUnwrappedLine(const ReconstructedLine &Line, int Level);
243f44d28f8SManuel Klimek   void debug(const ReconstructedLine &Line, int Level);
244f44d28f8SManuel Klimek   ReconstructedLine &parentLine();
245f44d28f8SManuel Klimek   ReconstructedLine *currentLine();
246d6d0dc1fSManuel Klimek   void debugParentMap() const;
247d6d0dc1fSManuel Klimek 
248d6d0dc1fSManuel Klimek #ifndef NDEBUG
249d6d0dc1fSManuel Klimek   enum ReconstructorState {
250d6d0dc1fSManuel Klimek     Start,      // No macro expansion was found in the input yet.
251d6d0dc1fSManuel Klimek     InProgress, // During a macro reconstruction.
252d6d0dc1fSManuel Klimek     Finalized,  // Past macro reconstruction, the result is finalized.
253d6d0dc1fSManuel Klimek   };
254d6d0dc1fSManuel Klimek   ReconstructorState State = Start;
255d6d0dc1fSManuel Klimek #endif
256d6d0dc1fSManuel Klimek 
257d6d0dc1fSManuel Klimek   // Node in which we build up the resulting unwrapped line; this type is
258d6d0dc1fSManuel Klimek   // analogous to UnwrappedLineNode.
259d6d0dc1fSManuel Klimek   struct LineNode {
260d6d0dc1fSManuel Klimek     LineNode() = default;
LineNodeLineNode261d6d0dc1fSManuel Klimek     LineNode(FormatToken *Tok) : Tok(Tok) {}
262d6d0dc1fSManuel Klimek     FormatToken *Tok = nullptr;
263*1c58208dSOwen Pan     SmallVector<std::unique_ptr<ReconstructedLine>> Children;
264d6d0dc1fSManuel Klimek   };
265d6d0dc1fSManuel Klimek 
266d6d0dc1fSManuel Klimek   // Line in which we build up the resulting unwrapped line.
267d6d0dc1fSManuel Klimek   // FIXME: Investigate changing UnwrappedLine to a pointer type and using it
268d6d0dc1fSManuel Klimek   // instead of rolling our own type.
269f44d28f8SManuel Klimek   struct ReconstructedLine {
ReconstructedLineReconstructedLine270ddb4450aSr4nt     explicit ReconstructedLine(unsigned Level) : Level(Level) {}
271ddb4450aSr4nt     unsigned Level;
272*1c58208dSOwen Pan     SmallVector<std::unique_ptr<LineNode>> Tokens;
273d6d0dc1fSManuel Klimek   };
274d6d0dc1fSManuel Klimek 
275d6d0dc1fSManuel Klimek   // The line in which we collect the resulting reconstructed output.
276d6d0dc1fSManuel Klimek   // To reduce special cases in the algorithm, the first level of the line
277d6d0dc1fSManuel Klimek   // contains a single null token that has the reconstructed incoming
278d6d0dc1fSManuel Klimek   // lines as children.
279d6d0dc1fSManuel Klimek   // In the end, we stich the lines together so that each subsequent line
280d6d0dc1fSManuel Klimek   // is a child of the last token of the previous line. This is necessary
281d6d0dc1fSManuel Klimek   // in order to format the overall expression as a single logical line -
282d6d0dc1fSManuel Klimek   // if we created separate lines, we'd format them with their own top-level
283d6d0dc1fSManuel Klimek   // indent depending on the semantic structure, which is not desired.
284f44d28f8SManuel Klimek   ReconstructedLine Result;
285d6d0dc1fSManuel Klimek 
286d6d0dc1fSManuel Klimek   // Stack of currently "open" lines, where each line's predecessor's last
287d6d0dc1fSManuel Klimek   // token is the parent token for that line.
288*1c58208dSOwen Pan   SmallVector<ReconstructedLine *> ActiveReconstructedLines;
289d6d0dc1fSManuel Klimek 
290d6d0dc1fSManuel Klimek   // Maps from the expanded token to the token that takes its place in the
291d6d0dc1fSManuel Klimek   // reconstructed token stream in terms of parent-child relationships.
292d6d0dc1fSManuel Klimek   // Note that it might take multiple steps to arrive at the correct
293d6d0dc1fSManuel Klimek   // parent in the output.
294d6d0dc1fSManuel Klimek   // Given: #define C(a, b) []() { a; b; }
295d6d0dc1fSManuel Klimek   // And a call: C(f(), g())
296d6d0dc1fSManuel Klimek   // The structure in the incoming formatted unwrapped line will be:
297d6d0dc1fSManuel Klimek   // []() {
298d6d0dc1fSManuel Klimek   //      |- f();
299d6d0dc1fSManuel Klimek   //      \- g();
300d6d0dc1fSManuel Klimek   // }
301d6d0dc1fSManuel Klimek   // with f and g being children of the opening brace.
302d6d0dc1fSManuel Klimek   // In the reconstructed call:
303d6d0dc1fSManuel Klimek   // C(f(), g())
304d6d0dc1fSManuel Klimek   //  \- f()
305d6d0dc1fSManuel Klimek   //      \- g()
306d6d0dc1fSManuel Klimek   // We want f to be a child of the opening parenthesis and g to be a child
307d6d0dc1fSManuel Klimek   // of the comma token in the macro call.
308d6d0dc1fSManuel Klimek   // Thus, we map
309d6d0dc1fSManuel Klimek   // { -> (
310d6d0dc1fSManuel Klimek   // and add
311d6d0dc1fSManuel Klimek   // ( -> ,
312d6d0dc1fSManuel Klimek   // once we're past the comma in the reconstruction.
313d6d0dc1fSManuel Klimek   llvm::DenseMap<FormatToken *, FormatToken *>
314d6d0dc1fSManuel Klimek       SpelledParentToReconstructedParent;
315d6d0dc1fSManuel Klimek 
316d6d0dc1fSManuel Klimek   // Keeps track of a single expansion while we're reconstructing tokens it
317d6d0dc1fSManuel Klimek   // generated.
318d6d0dc1fSManuel Klimek   struct Expansion {
319d6d0dc1fSManuel Klimek     // The identifier token of the macro call.
320d6d0dc1fSManuel Klimek     FormatToken *ID;
321d6d0dc1fSManuel Klimek     // Our current position in the reconstruction.
322d6d0dc1fSManuel Klimek     std::list<UnwrappedLineNode>::iterator SpelledI;
323d6d0dc1fSManuel Klimek     // The end of the reconstructed token sequence.
324d6d0dc1fSManuel Klimek     std::list<UnwrappedLineNode>::iterator SpelledE;
325d6d0dc1fSManuel Klimek   };
326d6d0dc1fSManuel Klimek 
327d6d0dc1fSManuel Klimek   // Stack of macro calls for which we're in the middle of an expansion.
328*1c58208dSOwen Pan   SmallVector<Expansion> ActiveExpansions;
329d6d0dc1fSManuel Klimek 
330d6d0dc1fSManuel Klimek   struct MacroCallState {
331f44d28f8SManuel Klimek     MacroCallState(ReconstructedLine *Line, FormatToken *ParentLastToken,
332d6d0dc1fSManuel Klimek                    FormatToken *MacroCallLParen);
333d6d0dc1fSManuel Klimek 
334f44d28f8SManuel Klimek     ReconstructedLine *Line;
335d6d0dc1fSManuel Klimek 
336d6d0dc1fSManuel Klimek     // The last token in the parent line or expansion, or nullptr if the macro
337d6d0dc1fSManuel Klimek     // expansion is on a top-level line.
338d6d0dc1fSManuel Klimek     //
339d6d0dc1fSManuel Klimek     // For example, in the macro call:
340d6d0dc1fSManuel Klimek     //   auto f = []() { ID(1); };
341d6d0dc1fSManuel Klimek     // The MacroCallState for ID will have '{' as ParentLastToken.
342d6d0dc1fSManuel Klimek     //
343d6d0dc1fSManuel Klimek     // In the macro call:
344d6d0dc1fSManuel Klimek     //   ID(ID(void f()));
345d6d0dc1fSManuel Klimek     // The MacroCallState of the outer ID will have nullptr as ParentLastToken,
346d6d0dc1fSManuel Klimek     // while the MacroCallState for the inner ID will have the '(' of the outer
347d6d0dc1fSManuel Klimek     // ID as ParentLastToken.
348d6d0dc1fSManuel Klimek     //
349d6d0dc1fSManuel Klimek     // In the macro call:
350d6d0dc1fSManuel Klimek     //   ID2(a, ID(b));
351d6d0dc1fSManuel Klimek     // The MacroCallState of ID will have ',' as ParentLastToken.
352d6d0dc1fSManuel Klimek     FormatToken *ParentLastToken;
353d6d0dc1fSManuel Klimek 
354d6d0dc1fSManuel Klimek     // The l_paren of this MacroCallState's macro call.
355d6d0dc1fSManuel Klimek     FormatToken *MacroCallLParen;
356d6d0dc1fSManuel Klimek   };
357d6d0dc1fSManuel Klimek 
358d6d0dc1fSManuel Klimek   // Keeps track of the lines into which the opening brace/parenthesis &
359d6d0dc1fSManuel Klimek   // argument separating commas for each level in the macro call go in order to
360d6d0dc1fSManuel Klimek   // put the corresponding closing brace/parenthesis into the same line in the
361d6d0dc1fSManuel Klimek   // output and keep track of which parents in the expanded token stream map to
362d6d0dc1fSManuel Klimek   // which tokens in the reconstructed stream.
363d6d0dc1fSManuel Klimek   // When an opening brace/parenthesis has children, we want the structure of
364d6d0dc1fSManuel Klimek   // the output line to be:
365d6d0dc1fSManuel Klimek   // |- MACRO
366d6d0dc1fSManuel Klimek   // |- (
367d6d0dc1fSManuel Klimek   // |  \- <argument>
368d6d0dc1fSManuel Klimek   // |- ,
369d6d0dc1fSManuel Klimek   // |  \- <argument>
370d6d0dc1fSManuel Klimek   // \- )
371*1c58208dSOwen Pan   SmallVector<MacroCallState> MacroCallStructure;
372d6d0dc1fSManuel Klimek 
373d6d0dc1fSManuel Klimek   // Maps from identifier of the macro call to an unwrapped line containing
374d6d0dc1fSManuel Klimek   // all tokens of the macro call.
375d6d0dc1fSManuel Klimek   const llvm::DenseMap<FormatToken *, std::unique_ptr<UnwrappedLine>>
376d6d0dc1fSManuel Klimek       &IdToReconstructed;
377d6d0dc1fSManuel Klimek };
378d6d0dc1fSManuel Klimek 
379e336b74cSManuel Klimek } // namespace format
380e336b74cSManuel Klimek } // namespace clang
381e336b74cSManuel Klimek 
382e336b74cSManuel Klimek #endif
383