/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Format/MacroCallReconstructor.cpp
Line | Count | Source (jump to first uncovered line) |
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 | 744 | FormatToken *Parent = nullptr) { |
34 | 744 | bool First = true; |
35 | 3.46k | for (const auto &N : Line.Tokens) { |
36 | 3.46k | Call(N.Tok, Parent, First); |
37 | 3.46k | First = false; |
38 | 3.46k | for (const auto &Child : N.Children) |
39 | 137 | forEachToken(Child, Call, N.Tok); |
40 | 3.46k | } |
41 | 744 | } |
42 | | |
43 | | MacroCallReconstructor::MacroCallReconstructor( |
44 | | unsigned Level, |
45 | | const llvm::DenseMap<FormatToken *, std::unique_ptr<UnwrappedLine>> |
46 | | &ActiveExpansions) |
47 | 377 | : Level(Level), IdToReconstructed(ActiveExpansions) { |
48 | 377 | Result.Tokens.push_back(std::make_unique<LineNode>()); |
49 | 377 | ActiveReconstructedLines.push_back(&Result); |
50 | 377 | } |
51 | | |
52 | 607 | void MacroCallReconstructor::addLine(const UnwrappedLine &Line) { |
53 | 607 | assert(State != Finalized); |
54 | 607 | LLVM_DEBUG(llvm::dbgs() << "MCR: new line...\n"); |
55 | 3.46k | forEachToken(Line, [&](FormatToken *Token, FormatToken *Parent, bool First) { |
56 | 3.46k | add(Token, Parent, First); |
57 | 3.46k | }); |
58 | 607 | assert(InProgress || finished()); |
59 | 607 | } |
60 | | |
61 | 377 | UnwrappedLine MacroCallReconstructor::takeResult() && { |
62 | 377 | finalize(); |
63 | 377 | assert(Result.Tokens.size() == 1 && |
64 | 377 | Result.Tokens.front()->Children.size() == 1); |
65 | 377 | UnwrappedLine Final = |
66 | 377 | createUnwrappedLine(*Result.Tokens.front()->Children.front(), Level); |
67 | 377 | assert(!Final.Tokens.empty()); |
68 | 377 | return Final; |
69 | 377 | } |
70 | | |
71 | | // Reconstruct the position of the next \p Token, given its parent \p |
72 | | // ExpandedParent in the incoming unwrapped line. \p First specifies whether it |
73 | | // is the first token in a given unwrapped line. |
74 | | void MacroCallReconstructor::add(FormatToken *Token, |
75 | 3.46k | FormatToken *ExpandedParent, bool First) { |
76 | 3.46k | LLVM_DEBUG( |
77 | 3.46k | llvm::dbgs() << "MCR: Token: " << Token->TokenText << ", Parent: " |
78 | 3.46k | << (ExpandedParent ? ExpandedParent->TokenText : "<null>") |
79 | 3.46k | << ", 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 | 3.46k | if (!ActiveExpansions.empty() && Token->MacroCtx2.62k && |
99 | 3.46k | (2.62k Token->MacroCtx->Role != MR_Hidden2.62k || |
100 | 2.62k | ActiveExpansions.size() != Token->MacroCtx->ExpandedFrom.size()929 )) { |
101 | 1.71k | if (/*PassedMacroComma = */ reconstructActiveCallUntil(Token)) |
102 | 153 | First = true; |
103 | 1.71k | } |
104 | | |
105 | 3.46k | prepareParent(ExpandedParent, First); |
106 | | |
107 | 3.46k | if (Token->MacroCtx) { |
108 | | // If this token was generated by a macro call, add the reconstructed |
109 | | // equivalent of the token. |
110 | 3.04k | reconstruct(Token); |
111 | 3.04k | } else { |
112 | | // Otherwise, we add it to the current line. |
113 | 416 | appendToken(Token); |
114 | 416 | } |
115 | 3.46k | } |
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 | 3.91k | bool NewLine) { |
133 | 3.91k | LLVM_DEBUG({ |
134 | 3.91k | llvm::dbgs() << "ParentMap:\n"; |
135 | 3.91k | debugParentMap(); |
136 | 3.91k | }); |
137 | | // We want to find the parent in the new unwrapped line, where the expanded |
138 | | // parent might have been replaced during reconstruction. |
139 | 3.91k | FormatToken *Parent = getParentInResult(ExpandedParent); |
140 | 3.91k | LLVM_DEBUG(llvm::dbgs() << "MCR: New parent: " |
141 | 3.91k | << (Parent ? Parent->TokenText : "<null>") << "\n"); |
142 | | |
143 | 3.91k | FormatToken *OpenMacroParent = nullptr; |
144 | 3.91k | 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 | 2.70k | OpenMacroParent = |
153 | 2.70k | getParentInResult(MacroCallStructure.back().MacroCallLParen); |
154 | 2.70k | LLVM_DEBUG(llvm::dbgs() |
155 | 2.70k | << "MacroCallLParen: " |
156 | 2.70k | << MacroCallStructure.back().MacroCallLParen->TokenText |
157 | 2.70k | << ", OpenMacroParent: " |
158 | 2.70k | << (OpenMacroParent ? OpenMacroParent->TokenText : "<null>") |
159 | 2.70k | << "\n"); |
160 | 2.70k | } |
161 | 3.91k | if (NewLine || |
162 | 3.91k | (2.57k !ActiveReconstructedLines.back()->Tokens.empty()2.57k && |
163 | 2.57k | Parent == ActiveReconstructedLines.back()->Tokens.back()->Tok2.35k )) { |
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 | 1.97k | while (ActiveReconstructedLines.back()->Tokens.empty() || |
167 | 1.97k | (1.73k Parent != ActiveReconstructedLines.back()->Tokens.back()->Tok1.73k && |
168 | 1.73k | ActiveReconstructedLines.back()->Tokens.back()->Tok != |
169 | 635 | OpenMacroParent)) { |
170 | 635 | ActiveReconstructedLines.pop_back(); |
171 | 635 | assert(!ActiveReconstructedLines.empty()); |
172 | 635 | } |
173 | 1.33k | assert(!ActiveReconstructedLines.empty()); |
174 | 1.33k | ActiveReconstructedLines.back()->Tokens.back()->Children.push_back( |
175 | 1.33k | std::make_unique<ReconstructedLine>()); |
176 | 1.33k | ActiveReconstructedLines.push_back( |
177 | 1.33k | &*ActiveReconstructedLines.back()->Tokens.back()->Children.back()); |
178 | 2.57k | } 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 | 478 | while (Parent != parentLine().Tokens.back()->Tok && |
182 | 478 | parentLine().Tokens.back()->Tok248 && |
183 | 478 | parentLine().Tokens.back()->Tok != OpenMacroParent243 ) { |
184 | 241 | ActiveReconstructedLines.pop_back(); |
185 | 241 | assert(!ActiveReconstructedLines.empty()); |
186 | 241 | } |
187 | 237 | } |
188 | 3.91k | assert(!ActiveReconstructedLines.empty()); |
189 | 3.91k | } |
190 | | |
191 | | // For a given \p Parent in the incoming expanded token stream, find the |
192 | | // corresponding parent in the output. |
193 | 6.62k | FormatToken *MacroCallReconstructor::getParentInResult(FormatToken *Parent) { |
194 | 6.62k | FormatToken *Mapped = SpelledParentToReconstructedParent.lookup(Parent); |
195 | 6.62k | if (!Mapped) |
196 | 3.26k | return Parent; |
197 | 8.94k | for (; 3.35k Mapped; Mapped = SpelledParentToReconstructedParent.lookup(Parent)5.59k ) |
198 | 5.59k | 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 | 3.35k | Parent->MacroParent = true; |
203 | 3.35k | return Parent; |
204 | 6.62k | } |
205 | | |
206 | | // Reconstruct a \p Token that was expanded from a macro call. |
207 | 3.04k | void MacroCallReconstructor::reconstruct(FormatToken *Token) { |
208 | 3.04k | 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 | 3.04k | if (Token->MacroCtx->StartOfExpansion) { |
214 | 471 | 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 | 471 | if (Token->MacroCtx->Role != MR_Hidden) |
219 | 261 | reconstructActiveCallUntil(Token); |
220 | 471 | } |
221 | 3.04k | assert(!ActiveExpansions.empty()); |
222 | 3.04k | if (ActiveExpansions.back().SpelledI != ActiveExpansions.back().SpelledE) { |
223 | 2.46k | assert(ActiveExpansions.size() == Token->MacroCtx->ExpandedFrom.size()); |
224 | 2.46k | 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 | 1.92k | assert(ActiveExpansions.back().SpelledI->Tok == Token); |
231 | 1.92k | processNextReconstructed(); |
232 | 1.92k | } else if (535 !currentLine()->Tokens.empty()535 ) { |
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 | 258 | SpelledParentToReconstructedParent[Token] = |
237 | 258 | currentLine()->Tokens.back()->Tok; |
238 | 277 | } else { |
239 | 277 | for (auto I = ActiveReconstructedLines.rbegin(), |
240 | 277 | E = ActiveReconstructedLines.rend(); |
241 | 554 | I != E; ++I277 ) { |
242 | 554 | if (!(*I)->Tokens.empty()) { |
243 | 277 | SpelledParentToReconstructedParent[Token] = (*I)->Tokens.back()->Tok; |
244 | 277 | break; |
245 | 277 | } |
246 | 554 | } |
247 | 277 | } |
248 | 2.46k | } |
249 | 3.04k | if (Token->MacroCtx->EndOfExpansion) |
250 | 467 | endReconstruction(Token); |
251 | 3.04k | } |
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 | 471 | void MacroCallReconstructor::startReconstruction(FormatToken *Token) { |
259 | 471 | assert(Token->MacroCtx); |
260 | 471 | assert(!Token->MacroCtx->ExpandedFrom.empty()); |
261 | 471 | assert(ActiveExpansions.size() <= Token->MacroCtx->ExpandedFrom.size()); |
262 | 471 | #ifndef NDEBUG |
263 | | // Check that the token's reconstruction stack matches our current |
264 | | // reconstruction stack. |
265 | 528 | for (size_t I = 0; 471 I < ActiveExpansions.size(); ++I57 ) { |
266 | 57 | assert(ActiveExpansions[I].ID == |
267 | 57 | Token->MacroCtx |
268 | 57 | ->ExpandedFrom[Token->MacroCtx->ExpandedFrom.size() - 1 - I]); |
269 | 57 | } |
270 | 471 | #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 | 471 | ArrayRef<FormatToken *> StartedMacros = |
276 | 471 | ArrayRef(Token->MacroCtx->ExpandedFrom) |
277 | 471 | .drop_back(ActiveExpansions.size()); |
278 | 471 | assert(StartedMacros.size() == Token->MacroCtx->StartOfExpansion); |
279 | | // We reconstruct macro calls outside-to-inside. |
280 | 480 | for (FormatToken *ID : llvm::reverse(StartedMacros))471 { |
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 | 480 | #ifndef NDEBUG |
284 | 480 | State = InProgress; |
285 | 480 | #endif |
286 | | // Put the reconstructed macro call's token into our reconstruction stack. |
287 | 480 | auto IU = IdToReconstructed.find(ID); |
288 | 480 | assert(IU != IdToReconstructed.end()); |
289 | 480 | ActiveExpansions.push_back( |
290 | 480 | {ID, IU->second->Tokens.begin(), IU->second->Tokens.end()}); |
291 | | // Process the macro call's identifier. |
292 | 480 | processNextReconstructed(); |
293 | 480 | if (ActiveExpansions.back().SpelledI == ActiveExpansions.back().SpelledE) |
294 | 184 | continue; |
295 | 296 | if (ActiveExpansions.back().SpelledI->Tok->is(tok::l_paren)) { |
296 | | // Process the optional opening parenthesis. |
297 | 296 | processNextReconstructed(); |
298 | 296 | } |
299 | 296 | } |
300 | 471 | } |
301 | | |
302 | | // Add all tokens in the reconstruction stream to the output until we find the |
303 | | // given \p Token. |
304 | 1.97k | bool MacroCallReconstructor::reconstructActiveCallUntil(FormatToken *Token) { |
305 | 1.97k | assert(!ActiveExpansions.empty()); |
306 | 1.97k | 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 | 2.25k | while (ActiveExpansions.back().SpelledI != ActiveExpansions.back().SpelledE && |
311 | 2.25k | ActiveExpansions.back().SpelledI->Tok != Token2.25k ) { |
312 | 277 | PassedMacroComma = processNextReconstructed() || PassedMacroComma123 ; |
313 | 277 | } |
314 | 1.97k | return PassedMacroComma; |
315 | 1.97k | } |
316 | | |
317 | | // End all reconstructions for which \p Token is the final token. |
318 | 467 | void MacroCallReconstructor::endReconstruction(FormatToken *Token) { |
319 | 467 | assert(Token->MacroCtx && |
320 | 467 | (ActiveExpansions.size() >= Token->MacroCtx->EndOfExpansion)); |
321 | 947 | for (size_t I = 0; 467 I < Token->MacroCtx->EndOfExpansion; ++I480 ) { |
322 | 480 | 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 | 480 | for (auto T = ActiveExpansions.back().SpelledI; |
327 | 480 | T != ActiveExpansions.back().SpelledE; ++T) { |
328 | 480 | FormatToken *Token = T->Tok; |
329 | 480 | bool ClosingParen = (std::next(T) == ActiveExpansions.back().SpelledE || |
330 | 480 | std::next(T)->Tok->isTrailingComment()) && |
331 | 480 | !Token->MacroCtx && Token->is(tok::r_paren); |
332 | 480 | bool TrailingComment = Token->isTrailingComment(); |
333 | 480 | bool PreviousLevel = |
334 | 480 | Token->MacroCtx && |
335 | 480 | (ActiveExpansions.size() < Token->MacroCtx->ExpandedFrom.size()); |
336 | 480 | if (!ClosingParen && !TrailingComment && !PreviousLevel) |
337 | 480 | 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 | 480 | } |
346 | 480 | }()); |
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 | 480 | for (auto T = ActiveExpansions.back().SpelledI; |
360 | 1.07k | T != ActiveExpansions.back().SpelledE; ++T593 ) { |
361 | 593 | processNextReconstructed(); |
362 | 593 | } |
363 | 480 | ActiveExpansions.pop_back(); |
364 | 480 | } |
365 | 467 | } |
366 | | |
367 | 0 | void MacroCallReconstructor::debugParentMap() const { |
368 | 0 | llvm::DenseSet<FormatToken *> Values; |
369 | 0 | for (const auto &P : SpelledParentToReconstructedParent) |
370 | 0 | Values.insert(P.second); |
371 | |
|
372 | 0 | for (const auto &P : SpelledParentToReconstructedParent) { |
373 | 0 | if (Values.contains(P.first)) |
374 | 0 | continue; |
375 | 0 | llvm::dbgs() << (P.first ? P.first->TokenText : "<null>"); |
376 | 0 | for (auto I = SpelledParentToReconstructedParent.find(P.first), |
377 | 0 | E = SpelledParentToReconstructedParent.end(); |
378 | 0 | I != E; I = SpelledParentToReconstructedParent.find(I->second)) { |
379 | 0 | llvm::dbgs() << " -> " << (I->second ? I->second->TokenText : "<null>"); |
380 | 0 | } |
381 | 0 | llvm::dbgs() << "\n"; |
382 | 0 | } |
383 | 0 | } |
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 | 3.57k | bool MacroCallReconstructor::processNextReconstructed() { |
389 | 3.57k | FormatToken *Token = ActiveExpansions.back().SpelledI->Tok; |
390 | 3.57k | ++ActiveExpansions.back().SpelledI; |
391 | 3.57k | if (Token->MacroCtx) { |
392 | | // Skip tokens that are not part of the macro call. |
393 | 2.34k | if (Token->MacroCtx->Role == MR_Hidden) |
394 | 257 | 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 | 2.08k | if (ActiveExpansions.size() < Token->MacroCtx->ExpandedFrom.size()) |
404 | 158 | return false; |
405 | 2.08k | } |
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 | 3.16k | 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 | 1.23k | if (Token->is(tok::l_paren)) { |
414 | 296 | MacroCallStructure.push_back(MacroCallState( |
415 | 296 | 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 | 296 | SpelledParentToReconstructedParent[MacroCallStructure.back() |
425 | 296 | .ParentLastToken] = Token; |
426 | 296 | appendToken(Token); |
427 | 296 | prepareParent(Token, /*NewLine=*/true); |
428 | 296 | Token->MacroParent = true; |
429 | 296 | return false; |
430 | 296 | } |
431 | 934 | if (!MacroCallStructure.empty()) { |
432 | 507 | if (Token->is(tok::comma)) { |
433 | | // Make new lines inside the next argument children of the comma token. |
434 | 155 | SpelledParentToReconstructedParent |
435 | 155 | [MacroCallStructure.back().Line->Tokens.back()->Tok] = Token; |
436 | 155 | Token->MacroParent = true; |
437 | 155 | appendToken(Token, MacroCallStructure.back().Line); |
438 | 155 | prepareParent(Token, /*NewLine=*/true); |
439 | 155 | return true; |
440 | 155 | } |
441 | 352 | if (Token->is(tok::r_paren)) { |
442 | 296 | appendToken(Token, MacroCallStructure.back().Line); |
443 | 296 | SpelledParentToReconstructedParent.erase( |
444 | 296 | MacroCallStructure.back().ParentLastToken); |
445 | 296 | MacroCallStructure.pop_back(); |
446 | 296 | return false; |
447 | 296 | } |
448 | 352 | } |
449 | 934 | } |
450 | | // Note that any tokens that are tagged with MR_None have been passed as |
451 | | // arguments to the macro that have not been expanded, for example: |
452 | | // Given: #define ID(X) x |
453 | | // When calling: ID(a, b) |
454 | | // 'b' will be part of the reconstructed token stream, but tagged MR_None. |
455 | | // Given that erroring out in this case would be disruptive, we continue |
456 | | // pushing the (unformatted) token. |
457 | | // FIXME: This can lead to unfortunate formatting decisions - give the user |
458 | | // a hint that their macro definition is broken. |
459 | 2.41k | appendToken(Token); |
460 | 2.41k | return false; |
461 | 3.16k | } |
462 | | |
463 | 377 | void MacroCallReconstructor::finalize() { |
464 | 377 | #ifndef NDEBUG |
465 | 377 | assert(State != Finalized && finished()); |
466 | 377 | State = Finalized; |
467 | 377 | #endif |
468 | | |
469 | | // We created corresponding unwrapped lines for each incoming line as children |
470 | | // the the toplevel null token. |
471 | 377 | assert(Result.Tokens.size() == 1 && !Result.Tokens.front()->Children.empty()); |
472 | 377 | LLVM_DEBUG({ |
473 | 377 | llvm::dbgs() << "Finalizing reconstructed lines:\n"; |
474 | 377 | debug(Result, 0); |
475 | 377 | }); |
476 | | |
477 | | // The first line becomes the top level line in the resulting unwrapped line. |
478 | 377 | LineNode &Top = *Result.Tokens.front(); |
479 | 377 | auto *I = Top.Children.begin(); |
480 | | // Every subsequent line will become a child of the last token in the previous |
481 | | // line, which is the token prior to the first token in the line. |
482 | 377 | LineNode *Last = (*I)->Tokens.back().get(); |
483 | 377 | ++I; |
484 | 396 | for (auto *E = Top.Children.end(); I != E; ++I19 ) { |
485 | 19 | assert(Last->Children.empty()); |
486 | 19 | Last->Children.push_back(std::move(*I)); |
487 | | |
488 | | // Mark the previous line's last token as generated by a macro expansion |
489 | | // so the formatting algorithm can take that into account. |
490 | 19 | Last->Tok->MacroParent = true; |
491 | | |
492 | 19 | Last = Last->Children.back()->Tokens.back().get(); |
493 | 19 | } |
494 | 377 | Top.Children.resize(1); |
495 | 377 | } |
496 | | |
497 | | void MacroCallReconstructor::appendToken(FormatToken *Token, |
498 | 3.57k | ReconstructedLine *L) { |
499 | 3.57k | L = L ? L451 : currentLine()3.12k ; |
500 | 3.57k | LLVM_DEBUG(llvm::dbgs() << "-> " << Token->TokenText << "\n"); |
501 | 3.57k | L->Tokens.push_back(std::make_unique<LineNode>(Token)); |
502 | 3.57k | } |
503 | | |
504 | | UnwrappedLine |
505 | | MacroCallReconstructor::createUnwrappedLine(const ReconstructedLine &Line, |
506 | 1.09k | int Level) { |
507 | 1.09k | UnwrappedLine Result; |
508 | 1.09k | Result.Level = Level; |
509 | 3.57k | for (const auto &N : Line.Tokens) { |
510 | 3.57k | Result.Tokens.push_back(N->Tok); |
511 | 3.57k | UnwrappedLineNode &Current = Result.Tokens.back(); |
512 | 3.57k | for (const auto &Child : N->Children) { |
513 | 959 | if (Child->Tokens.empty()) |
514 | 240 | continue; |
515 | 719 | Current.Children.push_back(createUnwrappedLine(*Child, Level + 1)); |
516 | 719 | } |
517 | 3.57k | if (Current.Children.size() == 1 && |
518 | 3.57k | Current.Tok->isOneOf(tok::l_paren, tok::comma)366 ) { |
519 | 328 | Result.Tokens.splice(Result.Tokens.end(), |
520 | 328 | Current.Children.front().Tokens); |
521 | 328 | Current.Children.clear(); |
522 | 328 | } |
523 | 3.57k | } |
524 | 1.09k | return Result; |
525 | 1.09k | } |
526 | | |
527 | 0 | void MacroCallReconstructor::debug(const ReconstructedLine &Line, int Level) { |
528 | 0 | for (int i = 0; i < Level; ++i) |
529 | 0 | llvm::dbgs() << " "; |
530 | 0 | for (const auto &N : Line.Tokens) { |
531 | 0 | if (!N) |
532 | 0 | continue; |
533 | 0 | if (N->Tok) |
534 | 0 | llvm::dbgs() << N->Tok->TokenText << " "; |
535 | 0 | for (const auto &Child : N->Children) { |
536 | 0 | llvm::dbgs() << "\n"; |
537 | 0 | debug(*Child, Level + 1); |
538 | 0 | for (int i = 0; i < Level; ++i) |
539 | 0 | llvm::dbgs() << " "; |
540 | 0 | } |
541 | 0 | } |
542 | 0 | llvm::dbgs() << "\n"; |
543 | 0 | } |
544 | | |
545 | | MacroCallReconstructor::ReconstructedLine & |
546 | 3.84k | MacroCallReconstructor::parentLine() { |
547 | 3.84k | return **std::prev(std::prev(ActiveReconstructedLines.end())); |
548 | 3.84k | } |
549 | | |
550 | | MacroCallReconstructor::ReconstructedLine * |
551 | 4.21k | MacroCallReconstructor::currentLine() { |
552 | 4.21k | return ActiveReconstructedLines.back(); |
553 | 4.21k | } |
554 | | |
555 | | MacroCallReconstructor::MacroCallState::MacroCallState( |
556 | | MacroCallReconstructor::ReconstructedLine *Line, |
557 | | FormatToken *ParentLastToken, FormatToken *MacroCallLParen) |
558 | 296 | : Line(Line), ParentLastToken(ParentLastToken), |
559 | 296 | MacroCallLParen(MacroCallLParen) { |
560 | 296 | LLVM_DEBUG( |
561 | 296 | llvm::dbgs() << "ParentLastToken: " |
562 | 296 | << (ParentLastToken ? ParentLastToken->TokenText : "<null>") |
563 | 296 | << "\n"); |
564 | | |
565 | 296 | assert(MacroCallLParen->is(tok::l_paren)); |
566 | 296 | } |
567 | | |
568 | | } // namespace format |
569 | | } // namespace clang |