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);
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) {
131void MacroCallReconstructor::prepareParent(FormatToken *ExpandedParent,
132 bool NewLine,
unsigned Level) {
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());
193FormatToken *MacroCallReconstructor::getParentInResult(FormatToken *
Parent) {
194 FormatToken *Mapped = SpelledParentToReconstructedParent.lookup(
Parent);
197 for (; Mapped; Mapped = SpelledParentToReconstructedParent.lookup(
Parent))
202 Parent->MacroParent =
true;
207void 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);
258void 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();
304bool 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;
318void 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();
367void MacroCallReconstructor::debugParentMap()
const {
368 llvm::DenseSet<FormatToken *> Values;
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";
388bool 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();
465void 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);
499void 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));
507MacroCallReconstructor::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)));
549void 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";
567MacroCallReconstructor::ReconstructedLine &
568MacroCallReconstructor::parentLine() {
569 return **std::prev(std::prev(ActiveReconstructedLines.end()));
572MacroCallReconstructor::ReconstructedLine *
573MacroCallReconstructor::currentLine() {
574 return ActiveReconstructedLines.back();
577MacroCallReconstructor::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.
@ Result
The result type of a method or function.
const FunctionProtoType * T
void finalize(TemplateInstantiationCallbackPtrs &Callbacks, const Sema &TheSema)