| 1 | //===--- MacroCallReconstructor.cpp - Format C++ code -----------*- C++ -*-===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | /// |
| 10 | /// \file |
| 11 | /// This file contains the implementation of MacroCallReconstructor, which fits |
| 12 | /// an reconstructed macro call to a parsed set of UnwrappedLines. |
| 13 | /// |
| 14 | //===----------------------------------------------------------------------===// |
| 15 | |
| 16 | #include "Macros.h" |
| 17 | |
| 18 | #include "UnwrappedLineParser.h" |
| 19 | #include "clang/Basic/TokenKinds.h" |
| 20 | #include "llvm/ADT/DenseSet.h" |
| 21 | #include "llvm/Support/Debug.h" |
| 22 | #include <cassert> |
| 23 | |
| 24 | #define DEBUG_TYPE "format-reconstruct" |
| 25 | |
| 26 | namespace clang { |
| 27 | namespace format { |
| 28 | |
| 29 | // Call \p Call for each token in the unwrapped line given, passing |
| 30 | // the token, its parent and whether it is the first token in the line. |
| 31 | template <typename T> |
| 32 | void forEachToken(const UnwrappedLine &Line, const T &Call, |
| 33 | FormatToken *Parent = nullptr) { |
| 34 | bool First = true; |
| 35 | for (const auto &N : Line.Tokens) { |
| 36 | Call(N.Tok, Parent, First, Line.Level); |
| 37 | First = false; |
| 38 | for (const auto &Child : N.Children) |
| 39 | forEachToken(Child, Call, N.Tok); |
| 40 | } |
| 41 | } |
| 42 | |
| 43 | MacroCallReconstructor::MacroCallReconstructor( |
| 44 | unsigned Level, |
| 45 | const llvm::DenseMap<FormatToken *, std::unique_ptr<UnwrappedLine>> |
| 46 | &ActiveExpansions) |
| 47 | : Result(Level), IdToReconstructed(ActiveExpansions) { |
| 48 | Result.Tokens.push_back(Elt: std::make_unique<LineNode>()); |
| 49 | ActiveReconstructedLines.push_back(Elt: &Result); |
| 50 | } |
| 51 | |
| 52 | void MacroCallReconstructor::addLine(const UnwrappedLine &Line) { |
| 53 | assert(State != Finalized); |
| 54 | LLVM_DEBUG(llvm::dbgs() << "MCR: new line...\n" ); |
| 55 | forEachToken(Line, Call: [&](FormatToken *Token, FormatToken *Parent, bool First, |
| 56 | unsigned Level) { add(Token, ExpandedParent: Parent, First, Level); }); |
| 57 | assert(InProgress || finished()); |
| 58 | } |
| 59 | |
| 60 | UnwrappedLine MacroCallReconstructor::takeResult() && { |
| 61 | finalize(); |
| 62 | assert(Result.Tokens.size() == 1 && |
| 63 | Result.Tokens.front()->Children.size() == 1); |
| 64 | UnwrappedLine Final = createUnwrappedLine( |
| 65 | Line: *Result.Tokens.front()->Children.front(), Level: Result.Level); |
| 66 | assert(!Final.Tokens.empty()); |
| 67 | return Final; |
| 68 | } |
| 69 | |
| 70 | // Reconstruct the position of the next \p Token, given its parent \p |
| 71 | // ExpandedParent in the incoming unwrapped line. \p First specifies whether it |
| 72 | // is the first token in a given unwrapped line. |
| 73 | void MacroCallReconstructor::add(FormatToken *Token, |
| 74 | FormatToken *ExpandedParent, bool First, |
| 75 | unsigned Level) { |
| 76 | LLVM_DEBUG( |
| 77 | llvm::dbgs() << "MCR: Token: " << Token->TokenText << ", Parent: " |
| 78 | << (ExpandedParent ? ExpandedParent->TokenText : "<null>" ) |
| 79 | << ", First: " << First << "\n" ); |
| 80 | // In order to be able to find the correct parent in the reconstructed token |
| 81 | // stream, we need to continue the last open reconstruction until we find the |
| 82 | // given token if it is part of the reconstructed token stream. |
| 83 | // |
| 84 | // Note that hidden tokens can be part of the reconstructed stream in nested |
| 85 | // macro calls. |
| 86 | // For example, given |
| 87 | // #define C(x, y) x y |
| 88 | // #define B(x) {x} |
| 89 | // And the call: |
| 90 | // C(a, B(b)) |
| 91 | // The outer macro call will be C(a, {b}), and the hidden token '}' can be |
| 92 | // found in the reconstructed token stream of that expansion level. |
| 93 | // In the expanded token stream |
| 94 | // a {b} |
| 95 | // 'b' is a child of '{'. We need to continue the open expansion of the ',' |
| 96 | // in the call of 'C' in order to correctly set the ',' as the parent of '{', |
| 97 | // so we later set the spelled token 'b' as a child of the ','. |
| 98 | if (!ActiveExpansions.empty() && Token->MacroCtx && |
| 99 | (Token->MacroCtx->Role != MR_Hidden || |
| 100 | ActiveExpansions.size() != Token->MacroCtx->ExpandedFrom.size())) { |
| 101 | if (/*PassedMacroComma = */ reconstructActiveCallUntil(Token)) |
| 102 | First = true; |
| 103 | } |
| 104 | |
| 105 | prepareParent(ExpandedParent, First, Level); |
| 106 | |
| 107 | if (Token->MacroCtx) { |
| 108 | // If this token was generated by a macro call, add the reconstructed |
| 109 | // equivalent of the token. |
| 110 | reconstruct(Token); |
| 111 | } else { |
| 112 | // Otherwise, we add it to the current line. |
| 113 | appendToken(Token); |
| 114 | } |
| 115 | } |
| 116 | |
| 117 | // Adjusts the stack of active reconstructed lines so we're ready to push |
| 118 | // tokens. The tokens to be pushed are children of ExpandedParent in the |
| 119 | // expanded code. |
| 120 | // |
| 121 | // This may entail: |
| 122 | // - creating a new line, if the parent is on the active line |
| 123 | // - popping active lines, if the parent is further up the stack |
| 124 | // |
| 125 | // Postcondition: |
| 126 | // ActiveReconstructedLines.back() is the line that has \p ExpandedParent or its |
| 127 | // reconstructed replacement token as a parent (when possible) - that is, the |
| 128 | // last token in \c ActiveReconstructedLines[ActiveReconstructedLines.size()-2] |
| 129 | // is the parent of ActiveReconstructedLines.back() in the reconstructed |
| 130 | // unwrapped line. |
| 131 | void MacroCallReconstructor::prepareParent(FormatToken *ExpandedParent, |
| 132 | bool NewLine, unsigned Level) { |
| 133 | LLVM_DEBUG({ |
| 134 | llvm::dbgs() << "ParentMap:\n" ; |
| 135 | debugParentMap(); |
| 136 | }); |
| 137 | // We want to find the parent in the new unwrapped line, where the expanded |
| 138 | // parent might have been replaced during reconstruction. |
| 139 | FormatToken *Parent = getParentInResult(Parent: ExpandedParent); |
| 140 | LLVM_DEBUG(llvm::dbgs() << "MCR: New parent: " |
| 141 | << (Parent ? Parent->TokenText : "<null>" ) << "\n" ); |
| 142 | |
| 143 | FormatToken *OpenMacroParent = nullptr; |
| 144 | if (!MacroCallStructure.empty()) { |
| 145 | // Inside a macro expansion, it is possible to lose track of the correct |
| 146 | // parent - either because it is already popped, for example because it was |
| 147 | // in a different macro argument (e.g. M({, })), or when we work on invalid |
| 148 | // code. |
| 149 | // Thus, we use the innermost macro call's parent as the parent at which |
| 150 | // we stop; this allows us to stay within the macro expansion and keeps |
| 151 | // any problems confined to the extent of the macro call. |
| 152 | OpenMacroParent = |
| 153 | getParentInResult(Parent: MacroCallStructure.back().MacroCallLParen); |
| 154 | LLVM_DEBUG(llvm::dbgs() |
| 155 | << "MacroCallLParen: " |
| 156 | << MacroCallStructure.back().MacroCallLParen->TokenText |
| 157 | << ", OpenMacroParent: " |
| 158 | << (OpenMacroParent ? OpenMacroParent->TokenText : "<null>" ) |
| 159 | << "\n" ); |
| 160 | } |
| 161 | if (NewLine || |
| 162 | (!ActiveReconstructedLines.back()->Tokens.empty() && |
| 163 | Parent == ActiveReconstructedLines.back()->Tokens.back()->Tok)) { |
| 164 | // If we are at the first token in a new line, we want to also |
| 165 | // create a new line in the resulting reconstructed unwrapped line. |
| 166 | while (ActiveReconstructedLines.back()->Tokens.empty() || |
| 167 | (Parent != ActiveReconstructedLines.back()->Tokens.back()->Tok && |
| 168 | ActiveReconstructedLines.back()->Tokens.back()->Tok != |
| 169 | OpenMacroParent)) { |
| 170 | ActiveReconstructedLines.pop_back(); |
| 171 | assert(!ActiveReconstructedLines.empty()); |
| 172 | } |
| 173 | assert(!ActiveReconstructedLines.empty()); |
| 174 | ActiveReconstructedLines.back()->Tokens.back()->Children.push_back( |
| 175 | Elt: std::make_unique<ReconstructedLine>(args&: Level)); |
| 176 | ActiveReconstructedLines.push_back( |
| 177 | Elt: &*ActiveReconstructedLines.back()->Tokens.back()->Children.back()); |
| 178 | } else if (parentLine().Tokens.back()->Tok != Parent) { |
| 179 | // If we're not the first token in a new line, pop lines until we find |
| 180 | // the child of \c Parent in the stack. |
| 181 | while (Parent != parentLine().Tokens.back()->Tok && |
| 182 | parentLine().Tokens.back()->Tok && |
| 183 | parentLine().Tokens.back()->Tok != OpenMacroParent) { |
| 184 | ActiveReconstructedLines.pop_back(); |
| 185 | assert(!ActiveReconstructedLines.empty()); |
| 186 | } |
| 187 | } |
| 188 | assert(!ActiveReconstructedLines.empty()); |
| 189 | } |
| 190 | |
| 191 | // For a given \p Parent in the incoming expanded token stream, find the |
| 192 | // corresponding parent in the output. |
| 193 | FormatToken *MacroCallReconstructor::getParentInResult(FormatToken *Parent) { |
| 194 | FormatToken *Mapped = SpelledParentToReconstructedParent.lookup(Val: Parent); |
| 195 | if (!Mapped) |
| 196 | return Parent; |
| 197 | for (; Mapped; Mapped = SpelledParentToReconstructedParent.lookup(Val: Parent)) |
| 198 | Parent = Mapped; |
| 199 | // If we use a different token than the parent in the expanded token stream |
| 200 | // as parent, mark it as a special parent, so the formatting code knows it |
| 201 | // needs to have its children formatted. |
| 202 | Parent->MacroParent = true; |
| 203 | return Parent; |
| 204 | } |
| 205 | |
| 206 | // Reconstruct a \p Token that was expanded from a macro call. |
| 207 | void MacroCallReconstructor::reconstruct(FormatToken *Token) { |
| 208 | assert(Token->MacroCtx); |
| 209 | // A single token can be the only result of a macro call: |
| 210 | // Given: #define ID(x, y) ; |
| 211 | // And the call: ID(<some>, <tokens>) |
| 212 | // ';' in the expanded stream will reconstruct all of ID(<some>, <tokens>). |
| 213 | if (Token->MacroCtx->StartOfExpansion) { |
| 214 | startReconstruction(Token); |
| 215 | // If the order of tokens in the expanded token stream is not the |
| 216 | // same as the order of tokens in the reconstructed stream, we need |
| 217 | // to reconstruct tokens that arrive later in the stream. |
| 218 | if (Token->MacroCtx->Role != MR_Hidden) |
| 219 | reconstructActiveCallUntil(Token); |
| 220 | } |
| 221 | assert(!ActiveExpansions.empty()); |
| 222 | if (ActiveExpansions.back().SpelledI != ActiveExpansions.back().SpelledE) { |
| 223 | assert(ActiveExpansions.size() == Token->MacroCtx->ExpandedFrom.size()); |
| 224 | if (Token->MacroCtx->Role != MR_Hidden) { |
| 225 | // The current token in the reconstructed token stream must be the token |
| 226 | // we're looking for - we either arrive here after startReconstruction, |
| 227 | // which initiates the stream to the first token, or after |
| 228 | // continueReconstructionUntil skipped until the expected token in the |
| 229 | // reconstructed stream at the start of add(...). |
| 230 | assert(ActiveExpansions.back().SpelledI->Tok == Token); |
| 231 | processNextReconstructed(); |
| 232 | } else if (!currentLine()->Tokens.empty()) { |
| 233 | // Map all hidden tokens to the last visible token in the output. |
| 234 | // If the hidden token is a parent, we'll use the last visible |
| 235 | // token as the parent of the hidden token's children. |
| 236 | SpelledParentToReconstructedParent[Token] = |
| 237 | currentLine()->Tokens.back()->Tok; |
| 238 | } else { |
| 239 | for (auto I = ActiveReconstructedLines.rbegin(), |
| 240 | E = ActiveReconstructedLines.rend(); |
| 241 | I != E; ++I) { |
| 242 | if (!(*I)->Tokens.empty()) { |
| 243 | SpelledParentToReconstructedParent[Token] = (*I)->Tokens.back()->Tok; |
| 244 | break; |
| 245 | } |
| 246 | } |
| 247 | } |
| 248 | } |
| 249 | if (Token->MacroCtx->EndOfExpansion) |
| 250 | endReconstruction(Token); |
| 251 | } |
| 252 | |
| 253 | // Given a \p Token that starts an expansion, reconstruct the beginning of the |
| 254 | // macro call. |
| 255 | // For example, given: #define ID(x) x |
| 256 | // And the call: ID(int a) |
| 257 | // Reconstructs: ID( |
| 258 | void MacroCallReconstructor::startReconstruction(FormatToken *Token) { |
| 259 | assert(Token->MacroCtx); |
| 260 | assert(!Token->MacroCtx->ExpandedFrom.empty()); |
| 261 | assert(ActiveExpansions.size() <= Token->MacroCtx->ExpandedFrom.size()); |
| 262 | #ifndef NDEBUG |
| 263 | // Check that the token's reconstruction stack matches our current |
| 264 | // reconstruction stack. |
| 265 | for (size_t I = 0; I < ActiveExpansions.size(); ++I) { |
| 266 | assert(ActiveExpansions[I].ID == |
| 267 | Token->MacroCtx |
| 268 | ->ExpandedFrom[Token->MacroCtx->ExpandedFrom.size() - 1 - I]); |
| 269 | } |
| 270 | #endif |
| 271 | // Start reconstruction for all calls for which this token is the first token |
| 272 | // generated by the call. |
| 273 | // Note that the token's expanded from stack is inside-to-outside, and the |
| 274 | // expansions for which this token is not the first are the outermost ones. |
| 275 | ArrayRef<FormatToken *> StartedMacros = |
| 276 | ArrayRef(Token->MacroCtx->ExpandedFrom) |
| 277 | .drop_back(N: ActiveExpansions.size()); |
| 278 | assert(StartedMacros.size() == Token->MacroCtx->StartOfExpansion); |
| 279 | // We reconstruct macro calls outside-to-inside. |
| 280 | for (FormatToken *ID : llvm::reverse(C&: StartedMacros)) { |
| 281 | // We found a macro call to be reconstructed; the next time our |
| 282 | // reconstruction stack is empty we know we finished an reconstruction. |
| 283 | #ifndef NDEBUG |
| 284 | State = InProgress; |
| 285 | #endif |
| 286 | // Put the reconstructed macro call's token into our reconstruction stack. |
| 287 | auto IU = IdToReconstructed.find(Val: ID); |
| 288 | assert(IU != IdToReconstructed.end()); |
| 289 | ActiveExpansions.push_back( |
| 290 | Elt: {.ID: ID, .SpelledI: IU->second->Tokens.begin(), .SpelledE: IU->second->Tokens.end()}); |
| 291 | // Process the macro call's identifier. |
| 292 | processNextReconstructed(); |
| 293 | if (ActiveExpansions.back().SpelledI == ActiveExpansions.back().SpelledE) |
| 294 | continue; |
| 295 | if (ActiveExpansions.back().SpelledI->Tok->is(Kind: tok::l_paren)) { |
| 296 | // Process the optional opening parenthesis. |
| 297 | processNextReconstructed(); |
| 298 | } |
| 299 | } |
| 300 | } |
| 301 | |
| 302 | // Add all tokens in the reconstruction stream to the output until we find the |
| 303 | // given \p Token. |
| 304 | bool MacroCallReconstructor::reconstructActiveCallUntil(FormatToken *Token) { |
| 305 | assert(!ActiveExpansions.empty()); |
| 306 | bool PassedMacroComma = false; |
| 307 | // FIXME: If Token was already expanded earlier, due to |
| 308 | // a change in order, we will not find it, but need to |
| 309 | // skip it. |
| 310 | while (ActiveExpansions.back().SpelledI != ActiveExpansions.back().SpelledE && |
| 311 | ActiveExpansions.back().SpelledI->Tok != Token) { |
| 312 | PassedMacroComma = processNextReconstructed() || PassedMacroComma; |
| 313 | } |
| 314 | return PassedMacroComma; |
| 315 | } |
| 316 | |
| 317 | // End all reconstructions for which \p Token is the final token. |
| 318 | void MacroCallReconstructor::endReconstruction(FormatToken *Token) { |
| 319 | assert(Token->MacroCtx && |
| 320 | (ActiveExpansions.size() >= Token->MacroCtx->EndOfExpansion)); |
| 321 | for (size_t I = 0; I < Token->MacroCtx->EndOfExpansion; ++I) { |
| 322 | LLVM_DEBUG([&] { |
| 323 | // Check all remaining tokens but the final closing parenthesis and |
| 324 | // optional trailing comment were already reconstructed at an inner |
| 325 | // expansion level. |
| 326 | for (auto T = ActiveExpansions.back().SpelledI; |
| 327 | T != ActiveExpansions.back().SpelledE; ++T) { |
| 328 | FormatToken *Token = T->Tok; |
| 329 | bool ClosingParen = (std::next(T) == ActiveExpansions.back().SpelledE || |
| 330 | std::next(T)->Tok->isTrailingComment()) && |
| 331 | !Token->MacroCtx && Token->is(tok::r_paren); |
| 332 | bool TrailingComment = Token->isTrailingComment(); |
| 333 | bool PreviousLevel = |
| 334 | Token->MacroCtx && |
| 335 | (ActiveExpansions.size() < Token->MacroCtx->ExpandedFrom.size()); |
| 336 | if (!ClosingParen && !TrailingComment && !PreviousLevel) |
| 337 | llvm::dbgs() << "At token: " << Token->TokenText << "\n" ; |
| 338 | // In addition to the following cases, we can also run into this |
| 339 | // when a macro call had more arguments than expected; in that case, |
| 340 | // the comma and the remaining tokens in the macro call will |
| 341 | // potentially end up in the line when we finish the expansion. |
| 342 | // FIXME: Add the information which arguments are unused, and assert |
| 343 | // one of the cases below plus reconstructed macro argument tokens. |
| 344 | // assert(ClosingParen || TrailingComment || PreviousLevel); |
| 345 | } |
| 346 | }()); |
| 347 | // Handle the remaining open tokens: |
| 348 | // - expand the closing parenthesis, if it exists, including an optional |
| 349 | // trailing comment |
| 350 | // - handle tokens that were already reconstructed at an inner expansion |
| 351 | // level |
| 352 | // - handle tokens when a macro call had more than the expected number of |
| 353 | // arguments, i.e. when #define M(x) is called as M(a, b, c) we'll end |
| 354 | // up with the sequence ", b, c)" being open at the end of the |
| 355 | // reconstruction; we want to gracefully handle that case |
| 356 | // |
| 357 | // FIXME: See the above debug-check for what we will need to do to be |
| 358 | // able to assert this. |
| 359 | for (auto T = ActiveExpansions.back().SpelledI; |
| 360 | T != ActiveExpansions.back().SpelledE; ++T) { |
| 361 | processNextReconstructed(); |
| 362 | } |
| 363 | ActiveExpansions.pop_back(); |
| 364 | } |
| 365 | } |
| 366 | |
| 367 | void MacroCallReconstructor::debugParentMap() const { |
| 368 | llvm::DenseSet<FormatToken *> Values( |
| 369 | llvm::from_range, |
| 370 | llvm::make_second_range(c: SpelledParentToReconstructedParent)); |
| 371 | |
| 372 | for (const auto &P : SpelledParentToReconstructedParent) { |
| 373 | if (Values.contains(V: P.first)) |
| 374 | continue; |
| 375 | llvm::dbgs() << (P.first ? P.first->TokenText : "<null>" ); |
| 376 | for (auto I = SpelledParentToReconstructedParent.find(Val: P.first), |
| 377 | E = SpelledParentToReconstructedParent.end(); |
| 378 | I != E; I = SpelledParentToReconstructedParent.find(Val: I->second)) { |
| 379 | llvm::dbgs() << " -> " << (I->second ? I->second->TokenText : "<null>" ); |
| 380 | } |
| 381 | llvm::dbgs() << "\n" ; |
| 382 | } |
| 383 | } |
| 384 | |
| 385 | // If visible, add the next token of the reconstructed token sequence to the |
| 386 | // output. Returns whether reconstruction passed a comma that is part of a |
| 387 | // macro call. |
| 388 | bool MacroCallReconstructor::processNextReconstructed() { |
| 389 | FormatToken *Token = ActiveExpansions.back().SpelledI->Tok; |
| 390 | ++ActiveExpansions.back().SpelledI; |
| 391 | if (Token->MacroCtx) { |
| 392 | // Skip tokens that are not part of the macro call. |
| 393 | if (Token->MacroCtx->Role == MR_Hidden) |
| 394 | return false; |
| 395 | // Skip tokens we already expanded during an inner reconstruction. |
| 396 | // For example, given: #define ID(x) {x} |
| 397 | // And the call: ID(ID(f)) |
| 398 | // We get two reconstructions: |
| 399 | // ID(f) -> {f} |
| 400 | // ID({f}) -> {{f}} |
| 401 | // We reconstruct f during the first reconstruction, and skip it during the |
| 402 | // second reconstruction. |
| 403 | if (ActiveExpansions.size() < Token->MacroCtx->ExpandedFrom.size()) |
| 404 | return false; |
| 405 | } |
| 406 | // Tokens that do not have a macro context are tokens in that are part of the |
| 407 | // macro call that have not taken part in expansion. |
| 408 | if (!Token->MacroCtx) { |
| 409 | // Put the parentheses and commas of a macro call into the same line; |
| 410 | // if the arguments produce new unwrapped lines, they will become children |
| 411 | // of the corresponding opening parenthesis or comma tokens in the |
| 412 | // reconstructed call. |
| 413 | if (Token->is(Kind: tok::l_paren)) { |
| 414 | MacroCallStructure.push_back(Elt: MacroCallState( |
| 415 | currentLine(), parentLine().Tokens.back()->Tok, Token)); |
| 416 | // All tokens that are children of the previous line's last token in the |
| 417 | // reconstructed token stream will now be children of the l_paren token. |
| 418 | // For example, for the line containing the macro calls: |
| 419 | // auto x = ID({ID(2)}); |
| 420 | // We will build up a map <null> -> ( -> ( with the first and second |
| 421 | // l_paren of the macro call respectively. New lines that come in with a |
| 422 | // <null> parent will then become children of the l_paren token of the |
| 423 | // currently innermost macro call. |
| 424 | SpelledParentToReconstructedParent[MacroCallStructure.back() |
| 425 | .ParentLastToken] = Token; |
| 426 | appendToken(Token); |
| 427 | prepareParent(ExpandedParent: Token, /*NewLine=*/true, |
| 428 | Level: MacroCallStructure.back().Line->Level); |
| 429 | Token->MacroParent = true; |
| 430 | return false; |
| 431 | } |
| 432 | if (!MacroCallStructure.empty()) { |
| 433 | if (Token->is(Kind: tok::comma)) { |
| 434 | // Make new lines inside the next argument children of the comma token. |
| 435 | SpelledParentToReconstructedParent |
| 436 | [MacroCallStructure.back().Line->Tokens.back()->Tok] = Token; |
| 437 | Token->MacroParent = true; |
| 438 | appendToken(Token, L: MacroCallStructure.back().Line); |
| 439 | prepareParent(ExpandedParent: Token, /*NewLine=*/true, |
| 440 | Level: MacroCallStructure.back().Line->Level); |
| 441 | return true; |
| 442 | } |
| 443 | if (Token->is(Kind: tok::r_paren)) { |
| 444 | appendToken(Token, L: MacroCallStructure.back().Line); |
| 445 | SpelledParentToReconstructedParent.erase( |
| 446 | Val: MacroCallStructure.back().ParentLastToken); |
| 447 | MacroCallStructure.pop_back(); |
| 448 | return false; |
| 449 | } |
| 450 | } |
| 451 | } |
| 452 | // Note that any tokens that are tagged with MR_None have been passed as |
| 453 | // arguments to the macro that have not been expanded, for example: |
| 454 | // Given: #define ID(X) x |
| 455 | // When calling: ID(a, b) |
| 456 | // 'b' will be part of the reconstructed token stream, but tagged MR_None. |
| 457 | // Given that erroring out in this case would be disruptive, we continue |
| 458 | // pushing the (unformatted) token. |
| 459 | // FIXME: This can lead to unfortunate formatting decisions - give the user |
| 460 | // a hint that their macro definition is broken. |
| 461 | appendToken(Token); |
| 462 | return false; |
| 463 | } |
| 464 | |
| 465 | void MacroCallReconstructor::finalize() { |
| 466 | #ifndef NDEBUG |
| 467 | assert(State != Finalized && finished()); |
| 468 | State = Finalized; |
| 469 | #endif |
| 470 | |
| 471 | // We created corresponding unwrapped lines for each incoming line as children |
| 472 | // the the toplevel null token. |
| 473 | assert(Result.Tokens.size() == 1 && !Result.Tokens.front()->Children.empty()); |
| 474 | LLVM_DEBUG({ |
| 475 | llvm::dbgs() << "Finalizing reconstructed lines:\n" ; |
| 476 | debug(Result, 0); |
| 477 | }); |
| 478 | |
| 479 | // The first line becomes the top level line in the resulting unwrapped line. |
| 480 | LineNode &Top = *Result.Tokens.front(); |
| 481 | auto *I = Top.Children.begin(); |
| 482 | // Every subsequent line will become a child of the last token in the previous |
| 483 | // line, which is the token prior to the first token in the line. |
| 484 | LineNode *Last = (*I)->Tokens.back().get(); |
| 485 | ++I; |
| 486 | for (auto *E = Top.Children.end(); I != E; ++I) { |
| 487 | assert(Last->Children.empty()); |
| 488 | Last->Children.push_back(Elt: std::move(*I)); |
| 489 | |
| 490 | // Mark the previous line's last token as generated by a macro expansion |
| 491 | // so the formatting algorithm can take that into account. |
| 492 | Last->Tok->MacroParent = true; |
| 493 | |
| 494 | Last = Last->Children.back()->Tokens.back().get(); |
| 495 | } |
| 496 | Top.Children.resize(N: 1); |
| 497 | } |
| 498 | |
| 499 | void MacroCallReconstructor::appendToken(FormatToken *Token, |
| 500 | ReconstructedLine *L) { |
| 501 | L = L ? L : currentLine(); |
| 502 | LLVM_DEBUG(llvm::dbgs() << "-> " << Token->TokenText << "\n" ); |
| 503 | L->Tokens.push_back(Elt: std::make_unique<LineNode>(args&: Token)); |
| 504 | } |
| 505 | |
| 506 | UnwrappedLine |
| 507 | MacroCallReconstructor::createUnwrappedLine(const ReconstructedLine &Line, |
| 508 | int Level) { |
| 509 | UnwrappedLine Result; |
| 510 | Result.Level = Level; |
| 511 | for (const auto &N : Line.Tokens) { |
| 512 | Result.Tokens.push_back(x: N->Tok); |
| 513 | UnwrappedLineNode &Current = Result.Tokens.back(); |
| 514 | auto NumChildren = llvm::count_if( |
| 515 | Range&: N->Children, P: [](const auto &Child) { return !Child->Tokens.empty(); }); |
| 516 | if (NumChildren == 1 && Current.Tok->isOneOf(K1: tok::l_paren, K2: tok::comma)) { |
| 517 | // If we only have one child, and the child is due to a macro expansion |
| 518 | // (either attached to a left parenthesis or comma), merge the child into |
| 519 | // the current line to prevent forced breaks for macro arguments. |
| 520 | auto *Child = llvm::find_if(Range&: N->Children, P: [](const auto &Child) { |
| 521 | return !Child->Tokens.empty(); |
| 522 | }); |
| 523 | auto Line = createUnwrappedLine(Line: **Child, Level); |
| 524 | Result.Tokens.splice(position: Result.Tokens.end(), x&: Line.Tokens); |
| 525 | } else if (NumChildren > 0) { |
| 526 | // When there are multiple children with different indent, make sure that |
| 527 | // we indent them: |
| 528 | // 1. One level below the current line's level. |
| 529 | // 2. At the correct level relative to each other. |
| 530 | unsigned MinChildLevel = |
| 531 | llvm::min_element(Range&: N->Children, |
| 532 | C: [](const auto &E1, const auto &E2) { |
| 533 | return E1->Level < E2->Level; |
| 534 | }) |
| 535 | ->get() |
| 536 | ->Level; |
| 537 | for (const auto &Child : N->Children) { |
| 538 | if (Child->Tokens.empty()) |
| 539 | continue; |
| 540 | Current.Children.push_back(Elt: createUnwrappedLine( |
| 541 | Line: *Child, Level: Level + 1 + (Child->Level - MinChildLevel))); |
| 542 | } |
| 543 | } |
| 544 | } |
| 545 | return Result; |
| 546 | } |
| 547 | |
| 548 | void MacroCallReconstructor::debug(const ReconstructedLine &Line, int Level) { |
| 549 | for (int i = 0; i < Level; ++i) |
| 550 | llvm::dbgs() << " " ; |
| 551 | for (const auto &N : Line.Tokens) { |
| 552 | if (!N) |
| 553 | continue; |
| 554 | if (N->Tok) |
| 555 | llvm::dbgs() << N->Tok->TokenText << " " ; |
| 556 | for (const auto &Child : N->Children) { |
| 557 | llvm::dbgs() << "\n" ; |
| 558 | debug(Line: *Child, Level: Level + 1); |
| 559 | for (int i = 0; i < Level; ++i) |
| 560 | llvm::dbgs() << " " ; |
| 561 | } |
| 562 | } |
| 563 | llvm::dbgs() << "\n" ; |
| 564 | } |
| 565 | |
| 566 | MacroCallReconstructor::ReconstructedLine & |
| 567 | MacroCallReconstructor::parentLine() { |
| 568 | return **std::prev(x: std::prev(x: ActiveReconstructedLines.end())); |
| 569 | } |
| 570 | |
| 571 | MacroCallReconstructor::ReconstructedLine * |
| 572 | MacroCallReconstructor::currentLine() { |
| 573 | return ActiveReconstructedLines.back(); |
| 574 | } |
| 575 | |
| 576 | MacroCallReconstructor::MacroCallState::MacroCallState( |
| 577 | MacroCallReconstructor::ReconstructedLine *Line, |
| 578 | FormatToken *ParentLastToken, FormatToken *MacroCallLParen) |
| 579 | : Line(Line), ParentLastToken(ParentLastToken), |
| 580 | MacroCallLParen(MacroCallLParen) { |
| 581 | LLVM_DEBUG( |
| 582 | llvm::dbgs() << "ParentLastToken: " |
| 583 | << (ParentLastToken ? ParentLastToken->TokenText : "<null>" ) |
| 584 | << "\n" ); |
| 585 | |
| 586 | assert(MacroCallLParen->is(tok::l_paren)); |
| 587 | } |
| 588 | |
| 589 | } // namespace format |
| 590 | } // namespace clang |
| 591 | |