20 #include "llvm/ADT/DenseSet.h"
21 #include "llvm/Support/Debug.h"
24 #define DEBUG_TYPE "format-reconstruct"
35 for (
const auto &N : Line.Tokens) {
38 for (
const auto &Child : N.Children)
45 const llvm::DenseMap<
FormatToken *, std::unique_ptr<UnwrappedLine>>
47 : Result(
Level), IdToReconstructed(ActiveExpansions) {
48 Result.Tokens.push_back(std::make_unique<LineNode>());
49 ActiveReconstructedLines.push_back(&Result);
53 assert(State != Finalized);
54 LLVM_DEBUG(llvm::dbgs() <<
"MCR: new line...\n");
62 assert(Result.Tokens.size() == 1 &&
63 Result.Tokens.front()->Children.size() == 1);
65 *Result.Tokens.front()->Children.front(), Result.Level);
66 assert(!Final.Tokens.empty());
77 llvm::dbgs() <<
"MCR: Token: " <<
Token->TokenText <<
", Parent: "
78 << (ExpandedParent ? ExpandedParent->
TokenText :
"<null>")
79 <<
", First: " << First <<
"\n");
98 if (!ActiveExpansions.empty() &&
Token->MacroCtx &&
100 ActiveExpansions.size() !=
Token->MacroCtx->ExpandedFrom.size())) {
101 if ( reconstructActiveCallUntil(
Token))
105 prepareParent(ExpandedParent, First,
Level);
107 if (
Token->MacroCtx) {
131 void MacroCallReconstructor::prepareParent(FormatToken *ExpandedParent,
134 llvm::dbgs() <<
"ParentMap:\n";
139 FormatToken *
Parent = getParentInResult(ExpandedParent);
140 LLVM_DEBUG(llvm::dbgs() <<
"MCR: New parent: "
143 FormatToken *OpenMacroParent =
nullptr;
144 if (!MacroCallStructure.empty()) {
153 getParentInResult(MacroCallStructure.back().MacroCallLParen);
154 LLVM_DEBUG(llvm::dbgs()
155 <<
"MacroCallLParen: "
156 << MacroCallStructure.back().MacroCallLParen->TokenText
157 <<
", OpenMacroParent: "
158 << (OpenMacroParent ? OpenMacroParent->TokenText :
"<null>")
162 (!ActiveReconstructedLines.back()->Tokens.empty() &&
163 Parent == ActiveReconstructedLines.back()->Tokens.back()->Tok)) {
166 while (ActiveReconstructedLines.back()->Tokens.empty() ||
167 (
Parent != ActiveReconstructedLines.back()->Tokens.back()->Tok &&
168 ActiveReconstructedLines.back()->Tokens.back()->Tok !=
170 ActiveReconstructedLines.pop_back();
171 assert(!ActiveReconstructedLines.empty());
173 assert(!ActiveReconstructedLines.empty());
174 ActiveReconstructedLines.back()->Tokens.back()->Children.push_back(
175 std::make_unique<ReconstructedLine>(
Level));
176 ActiveReconstructedLines.push_back(
177 &*ActiveReconstructedLines.back()->Tokens.back()->Children.back());
178 }
else if (parentLine().Tokens.back()->Tok !=
Parent) {
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());
188 assert(!ActiveReconstructedLines.empty());
193 FormatToken *MacroCallReconstructor::getParentInResult(FormatToken *
Parent) {
194 FormatToken *Mapped = SpelledParentToReconstructedParent.lookup(
Parent);
197 for (; Mapped; Mapped = SpelledParentToReconstructedParent.lookup(
Parent))
202 Parent->MacroParent =
true;
207 void MacroCallReconstructor::reconstruct(FormatToken *Token) {
208 assert(Token->MacroCtx);
213 if (Token->MacroCtx->StartOfExpansion) {
214 startReconstruction(Token);
219 reconstructActiveCallUntil(Token);
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) {
230 assert(ActiveExpansions.back().SpelledI->Tok == Token);
231 processNextReconstructed();
232 }
else if (!currentLine()->Tokens.empty()) {
236 SpelledParentToReconstructedParent[Token] =
237 currentLine()->Tokens.back()->Tok;
239 for (
auto I = ActiveReconstructedLines.rbegin(),
240 E = ActiveReconstructedLines.rend();
242 if (!(*I)->Tokens.empty()) {
243 SpelledParentToReconstructedParent[Token] = (*I)->Tokens.back()->Tok;
249 if (Token->MacroCtx->EndOfExpansion)
250 endReconstruction(Token);
258 void MacroCallReconstructor::startReconstruction(FormatToken *Token) {
259 assert(Token->MacroCtx);
260 assert(!Token->MacroCtx->ExpandedFrom.empty());
261 assert(ActiveExpansions.size() <= Token->MacroCtx->ExpandedFrom.size());
265 for (
size_t I = 0; I < ActiveExpansions.size(); ++I) {
266 assert(ActiveExpansions[I].
ID ==
268 ->ExpandedFrom[Token->MacroCtx->ExpandedFrom.size() - 1 - I]);
275 ArrayRef<FormatToken *> StartedMacros =
276 ArrayRef(Token->MacroCtx->ExpandedFrom)
277 .drop_back(ActiveExpansions.size());
278 assert(StartedMacros.size() == Token->MacroCtx->StartOfExpansion);
280 for (FormatToken *
ID : llvm::reverse(StartedMacros)) {
287 auto IU = IdToReconstructed.find(
ID);
288 assert(IU != IdToReconstructed.end());
289 ActiveExpansions.push_back(
290 {
ID, IU->second->Tokens.begin(), IU->second->Tokens.end()});
292 processNextReconstructed();
293 if (ActiveExpansions.back().SpelledI == ActiveExpansions.back().SpelledE)
295 if (ActiveExpansions.back().SpelledI->Tok->is(tok::l_paren)) {
297 processNextReconstructed();
304 bool MacroCallReconstructor::reconstructActiveCallUntil(FormatToken *Token) {
305 assert(!ActiveExpansions.empty());
306 bool PassedMacroComma =
false;
310 while (ActiveExpansions.back().SpelledI != ActiveExpansions.back().SpelledE &&
311 ActiveExpansions.back().SpelledI->Tok != Token) {
312 PassedMacroComma = processNextReconstructed() || PassedMacroComma;
314 return PassedMacroComma;
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) {
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();
335 (ActiveExpansions.size() < Token->MacroCtx->ExpandedFrom.size());
336 if (!ClosingParen && !TrailingComment && !PreviousLevel)
337 llvm::dbgs() <<
"At token: " << Token->TokenText <<
"\n";
359 for (
auto T = ActiveExpansions.back().SpelledI;
360 T != ActiveExpansions.back().SpelledE; ++
T) {
361 processNextReconstructed();
363 ActiveExpansions.pop_back();
367 void MacroCallReconstructor::debugParentMap()
const {
369 for (
const auto &
P : SpelledParentToReconstructedParent)
370 Values.insert(
P.second);
372 for (
const auto &
P : SpelledParentToReconstructedParent) {
373 if (Values.contains(
P.first))
375 llvm::dbgs() << (
P.first ?
P.first->TokenText :
"<null>");
376 for (
auto I = SpelledParentToReconstructedParent.find(
P.first),
377 E = SpelledParentToReconstructedParent.end();
378 I != E; I = SpelledParentToReconstructedParent.find(I->second)) {
379 llvm::dbgs() <<
" -> " << (I->second ? I->second->TokenText :
"<null>");
381 llvm::dbgs() <<
"\n";
388 bool MacroCallReconstructor::processNextReconstructed() {
389 FormatToken *Token = ActiveExpansions.back().SpelledI->Tok;
390 ++ActiveExpansions.back().SpelledI;
391 if (Token->MacroCtx) {
403 if (ActiveExpansions.size() < Token->MacroCtx->ExpandedFrom.size())
408 if (!Token->MacroCtx) {
413 if (Token->is(tok::l_paren)) {
414 MacroCallStructure.push_back(MacroCallState(
415 currentLine(), parentLine().Tokens.back()->Tok, Token));
424 SpelledParentToReconstructedParent[MacroCallStructure.back()
425 .ParentLastToken] = Token;
427 prepareParent(Token,
true,
428 MacroCallStructure.back().Line->Level);
429 Token->MacroParent =
true;
432 if (!MacroCallStructure.empty()) {
433 if (Token->is(tok::comma)) {
435 SpelledParentToReconstructedParent
436 [MacroCallStructure.back().Line->Tokens.back()->Tok] = Token;
437 Token->MacroParent =
true;
438 appendToken(Token, MacroCallStructure.back().Line);
439 prepareParent(Token,
true,
440 MacroCallStructure.back().Line->Level);
443 if (Token->is(tok::r_paren)) {
444 appendToken(Token, MacroCallStructure.back().Line);
445 SpelledParentToReconstructedParent.erase(
446 MacroCallStructure.back().ParentLastToken);
447 MacroCallStructure.pop_back();
465 void MacroCallReconstructor::finalize() {
467 assert(State != Finalized &&
finished());
473 assert(Result.Tokens.size() == 1 && !Result.Tokens.front()->Children.empty());
475 llvm::dbgs() <<
"Finalizing reconstructed lines:\n";
480 LineNode &Top = *Result.Tokens.front();
481 auto *I = Top.Children.begin();
484 LineNode *
Last = (*I)->Tokens.back().get();
486 for (
auto *E = Top.Children.end(); I != E; ++I) {
487 assert(
Last->Children.empty());
488 Last->Children.push_back(std::move(*I));
492 Last->Tok->MacroParent =
true;
494 Last =
Last->Children.back()->Tokens.back().get();
496 Top.Children.resize(1);
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(std::make_unique<LineNode>(Token));
507 MacroCallReconstructor::createUnwrappedLine(
const ReconstructedLine &Line,
509 UnwrappedLine Result;
510 Result.Level =
Level;
511 for (
const auto &N : Line.Tokens) {
512 Result.Tokens.push_back(N->Tok);
513 UnwrappedLineNode &Current = Result.Tokens.back();
515 std::count_if(N->Children.begin(), N->Children.end(),
516 [](
const auto &Child) { return !Child->Tokens.empty(); });
517 if (NumChildren == 1 && Current.Tok->isOneOf(tok::l_paren, tok::comma)) {
521 auto *Child = std::find_if(
522 N->Children.begin(), N->Children.end(),
523 [](
const auto &Child) { return !Child->Tokens.empty(); });
524 auto Line = createUnwrappedLine(**Child,
Level);
525 Result.Tokens.splice(Result.Tokens.end(), Line.Tokens);
526 }
else if (NumChildren > 0) {
531 unsigned MinChildLevel =
532 std::min_element(N->Children.begin(), N->Children.end(),
533 [](
const auto &E1,
const auto &E2) {
534 return E1->Level < E2->Level;
538 for (
const auto &Child : N->Children) {
539 if (Child->Tokens.empty())
541 Current.Children.push_back(createUnwrappedLine(
542 *Child,
Level + 1 + (Child->Level - MinChildLevel)));
549 void MacroCallReconstructor::debug(
const ReconstructedLine &Line,
int Level) {
550 for (
int i = 0; i <
Level; ++i)
552 for (
const auto &N : Line.Tokens) {
556 llvm::dbgs() << N->Tok->TokenText <<
" ";
557 for (
const auto &Child : N->Children) {
558 llvm::dbgs() <<
"\n";
559 debug(*Child,
Level + 1);
560 for (
int i = 0; i <
Level; ++i)
564 llvm::dbgs() <<
"\n";
567 MacroCallReconstructor::ReconstructedLine &
568 MacroCallReconstructor::parentLine() {
569 return **std::prev(std::prev(ActiveReconstructedLines.end()));
572 MacroCallReconstructor::ReconstructedLine *
573 MacroCallReconstructor::currentLine() {
574 return ActiveReconstructedLines.back();
577 MacroCallReconstructor::MacroCallState::MacroCallState(
578 MacroCallReconstructor::ReconstructedLine *Line,
579 FormatToken *ParentLastToken, FormatToken *MacroCallLParen)
580 : Line(Line), ParentLastToken(ParentLastToken),
581 MacroCallLParen(MacroCallLParen) {
583 llvm::dbgs() <<
"ParentLastToken: "
584 << (ParentLastToken ? ParentLastToken->TokenText :
"<null>")
587 assert(MacroCallLParen->is(tok::l_paren));
This file contains the main building blocks of macro support in clang-format.
Defines the clang::TokenKind enum and support functions.
This file contains the declaration of the UnwrappedLineParser, which turns a stream of tokens into Un...
Token - This structure provides full information about a lexed token.
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T
void finalize(TemplateInstantiationCallbackPtrs &Callbacks, const Sema &TheSema)