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