xref: /freebsd/contrib/llvm-project/clang/lib/Format/QualifierAlignmentFixer.cpp (revision 770cf0a5f02dc8983a89c6568d741fbc25baa999)
1 //===--- QualifierAlignmentFixer.cpp ----------------------------*- C++--*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// This file implements QualifierAlignmentFixer, a TokenAnalyzer that
11 /// enforces either left or right const depending on the style.
12 ///
13 //===----------------------------------------------------------------------===//
14 
15 #include "QualifierAlignmentFixer.h"
16 #include "FormatToken.h"
17 #include "llvm/Support/Debug.h"
18 #include "llvm/Support/Regex.h"
19 
20 #define DEBUG_TYPE "format-qualifier-alignment-fixer"
21 
22 namespace clang {
23 namespace format {
24 
25 void addQualifierAlignmentFixerPasses(const FormatStyle &Style,
26                                       SmallVectorImpl<AnalyzerPass> &Passes) {
27   std::vector<std::string> LeftOrder;
28   std::vector<std::string> RightOrder;
29   std::vector<tok::TokenKind> ConfiguredQualifierTokens;
30   prepareLeftRightOrderingForQualifierAlignmentFixer(
31       Style.QualifierOrder, LeftOrder, RightOrder, ConfiguredQualifierTokens);
32 
33   // Handle the left and right alignment separately.
34   for (const auto &Qualifier : LeftOrder) {
35     Passes.emplace_back(
36         [&, Qualifier, ConfiguredQualifierTokens](const Environment &Env) {
37           return LeftRightQualifierAlignmentFixer(Env, Style, Qualifier,
38                                                   ConfiguredQualifierTokens,
39                                                   /*RightAlign=*/false)
40               .process();
41         });
42   }
43   for (const auto &Qualifier : RightOrder) {
44     Passes.emplace_back(
45         [&, Qualifier, ConfiguredQualifierTokens](const Environment &Env) {
46           return LeftRightQualifierAlignmentFixer(Env, Style, Qualifier,
47                                                   ConfiguredQualifierTokens,
48                                                   /*RightAlign=*/true)
49               .process();
50         });
51   }
52 }
53 
54 static void replaceToken(const SourceManager &SourceMgr,
55                          tooling::Replacements &Fixes,
56                          const CharSourceRange &Range, std::string NewText) {
57   auto Replacement = tooling::Replacement(SourceMgr, Range, NewText);
58   auto Err = Fixes.add(Replacement);
59 
60   if (Err) {
61     llvm::errs() << "Error while rearranging Qualifier : "
62                  << llvm::toString(std::move(Err)) << "\n";
63   }
64 }
65 
66 static void removeToken(const SourceManager &SourceMgr,
67                         tooling::Replacements &Fixes,
68                         const FormatToken *First) {
69   auto Range = CharSourceRange::getCharRange(First->getStartOfNonWhitespace(),
70                                              First->Tok.getEndLoc());
71   replaceToken(SourceMgr, Fixes, Range, "");
72 }
73 
74 static void insertQualifierAfter(const SourceManager &SourceMgr,
75                                  tooling::Replacements &Fixes,
76                                  const FormatToken *First,
77                                  const std::string &Qualifier) {
78   auto Range = CharSourceRange::getCharRange(First->Tok.getLocation(),
79                                              First->Tok.getEndLoc());
80 
81   std::string NewText{};
82   NewText += First->TokenText;
83   NewText += " " + Qualifier;
84   replaceToken(SourceMgr, Fixes, Range, NewText);
85 }
86 
87 static void insertQualifierBefore(const SourceManager &SourceMgr,
88                                   tooling::Replacements &Fixes,
89                                   const FormatToken *First,
90                                   const std::string &Qualifier) {
91   auto Range = CharSourceRange::getCharRange(First->getStartOfNonWhitespace(),
92                                              First->Tok.getEndLoc());
93 
94   std::string NewText = " " + Qualifier + " ";
95   NewText += First->TokenText;
96 
97   replaceToken(SourceMgr, Fixes, Range, NewText);
98 }
99 
100 static bool endsWithSpace(const std::string &s) {
101   if (s.empty())
102     return false;
103   return isspace(s.back());
104 }
105 
106 static bool startsWithSpace(const std::string &s) {
107   if (s.empty())
108     return false;
109   return isspace(s.front());
110 }
111 
112 static void rotateTokens(const SourceManager &SourceMgr,
113                          tooling::Replacements &Fixes, const FormatToken *First,
114                          const FormatToken *Last, bool Left) {
115   auto *End = Last;
116   auto *Begin = First;
117   if (!Left) {
118     End = Last->Next;
119     Begin = First->Next;
120   }
121 
122   std::string NewText;
123   // If we are rotating to the left we move the Last token to the front.
124   if (Left) {
125     NewText += Last->TokenText;
126     NewText += " ";
127   }
128 
129   // Then move through the other tokens.
130   auto *Tok = Begin;
131   while (Tok != End) {
132     if (!NewText.empty() && !endsWithSpace(NewText) &&
133         Tok->isNot(tok::coloncolon)) {
134       NewText += " ";
135     }
136 
137     NewText += Tok->TokenText;
138     Tok = Tok->Next;
139   }
140 
141   // If we are rotating to the right we move the first token to the back.
142   if (!Left) {
143     if (!NewText.empty() && !startsWithSpace(NewText))
144       NewText += " ";
145     NewText += First->TokenText;
146   }
147 
148   auto Range = CharSourceRange::getCharRange(First->getStartOfNonWhitespace(),
149                                              Last->Tok.getEndLoc());
150 
151   replaceToken(SourceMgr, Fixes, Range, NewText);
152 }
153 
154 static bool
155 isConfiguredQualifier(const FormatToken *const Tok,
156                       const std::vector<tok::TokenKind> &Qualifiers) {
157   return Tok && llvm::is_contained(Qualifiers, Tok->Tok.getKind());
158 }
159 
160 static bool isQualifier(const FormatToken *const Tok) {
161   if (!Tok)
162     return false;
163 
164   switch (Tok->Tok.getKind()) {
165   case tok::kw_const:
166   case tok::kw_volatile:
167   case tok::kw_static:
168   case tok::kw_inline:
169   case tok::kw_constexpr:
170   case tok::kw_restrict:
171   case tok::kw_friend:
172     return true;
173   default:
174     return false;
175   }
176 }
177 
178 const FormatToken *LeftRightQualifierAlignmentFixer::analyzeRight(
179     const SourceManager &SourceMgr, const AdditionalKeywords &Keywords,
180     tooling::Replacements &Fixes, const FormatToken *const Tok,
181     const std::string &Qualifier, tok::TokenKind QualifierType) {
182   // We only need to think about streams that begin with a qualifier.
183   if (Tok->isNot(QualifierType))
184     return Tok;
185   // Don't concern yourself if nothing follows the qualifier.
186   if (!Tok->Next)
187     return Tok;
188 
189   // Skip qualifiers to the left to find what preceeds the qualifiers.
190   // Use isQualifier rather than isConfiguredQualifier to cover all qualifiers.
191   const FormatToken *PreviousCheck = Tok->getPreviousNonComment();
192   while (isQualifier(PreviousCheck))
193     PreviousCheck = PreviousCheck->getPreviousNonComment();
194 
195   // Examples given in order of ['type', 'const', 'volatile']
196   const bool IsRightQualifier = PreviousCheck && [PreviousCheck]() {
197     // The cases:
198     // `Foo() const` -> `Foo() const`
199     // `Foo() const final` -> `Foo() const final`
200     // `Foo() const override` -> `Foo() const final`
201     // `Foo() const volatile override` -> `Foo() const volatile override`
202     // `Foo() volatile const final` -> `Foo() const volatile final`
203     if (PreviousCheck->is(tok::r_paren))
204       return true;
205 
206     // The cases:
207     // `struct {} volatile const a;` -> `struct {} const volatile a;`
208     // `class {} volatile const a;` -> `class {} const volatile a;`
209     if (PreviousCheck->is(tok::r_brace))
210       return true;
211 
212     // The case:
213     // `template <class T> const Bar Foo()` ->
214     // `template <class T> Bar const Foo()`
215     // The cases:
216     // `Foo<int> const foo` -> `Foo<int> const foo`
217     // `Foo<int> volatile const` -> `Foo<int> const volatile`
218     // The case:
219     // ```
220     // template <class T>
221     //   requires Concept1<T> && requires Concept2<T>
222     // const Foo f();
223     // ```
224     // ->
225     // ```
226     // template <class T>
227     //   requires Concept1<T> && requires Concept2<T>
228     // Foo const f();
229     // ```
230     if (PreviousCheck->is(TT_TemplateCloser)) {
231       // If the token closes a template<> or requires clause, then it is a left
232       // qualifier and should be moved to the right.
233       return !(PreviousCheck->ClosesTemplateDeclaration ||
234                PreviousCheck->ClosesRequiresClause);
235     }
236 
237     // The case  `Foo* const` -> `Foo* const`
238     // The case  `Foo* volatile const` -> `Foo* const volatile`
239     // The case  `int32_t const` -> `int32_t const`
240     // The case  `auto volatile const` -> `auto const volatile`
241     if (PreviousCheck->isOneOf(TT_PointerOrReference, tok::identifier,
242                                tok::kw_auto)) {
243       return true;
244     }
245 
246     return false;
247   }();
248 
249   // Find the last qualifier to the right.
250   const FormatToken *LastQual = Tok;
251   while (isQualifier(LastQual->getNextNonComment()))
252     LastQual = LastQual->getNextNonComment();
253 
254   // If this qualifier is to the right of a type or pointer do a partial sort
255   // and return.
256   if (IsRightQualifier) {
257     if (LastQual != Tok)
258       rotateTokens(SourceMgr, Fixes, Tok, LastQual, /*Left=*/false);
259     return Tok;
260   }
261 
262   const FormatToken *TypeToken = LastQual->getNextNonComment();
263   if (!TypeToken)
264     return Tok;
265 
266   // Stay safe and don't move past macros, also don't bother with sorting.
267   if (isPossibleMacro(TypeToken))
268     return Tok;
269 
270   // The case `const long long int volatile` -> `long long int const volatile`
271   // The case `long const long int volatile` -> `long long int const volatile`
272   // The case `long long volatile int const` -> `long long int const volatile`
273   // The case `const long long volatile int` -> `long long int const volatile`
274   if (TypeToken->isTypeName(LangOpts)) {
275     // The case `const decltype(foo)` -> `const decltype(foo)`
276     // The case `const typeof(foo)` -> `const typeof(foo)`
277     // The case `const _Atomic(foo)` -> `const _Atomic(foo)`
278     if (TypeToken->isOneOf(tok::kw_decltype, tok::kw_typeof, tok::kw__Atomic))
279       return Tok;
280 
281     const FormatToken *LastSimpleTypeSpecifier = TypeToken;
282     while (isQualifierOrType(LastSimpleTypeSpecifier->getNextNonComment(),
283                              LangOpts)) {
284       LastSimpleTypeSpecifier = LastSimpleTypeSpecifier->getNextNonComment();
285     }
286 
287     rotateTokens(SourceMgr, Fixes, Tok, LastSimpleTypeSpecifier,
288                  /*Left=*/false);
289     return LastSimpleTypeSpecifier;
290   }
291 
292   // The case  `unsigned short const` -> `unsigned short const`
293   // The case:
294   // `unsigned short volatile const` -> `unsigned short const volatile`
295   if (PreviousCheck && PreviousCheck->isTypeName(LangOpts)) {
296     if (LastQual != Tok)
297       rotateTokens(SourceMgr, Fixes, Tok, LastQual, /*Left=*/false);
298     return Tok;
299   }
300 
301   // Skip the typename keyword.
302   // The case `const typename C::type` -> `typename C::type const`
303   if (TypeToken->is(tok::kw_typename))
304     TypeToken = TypeToken->getNextNonComment();
305 
306   // Skip the initial :: of a global-namespace type.
307   // The case `const ::...` -> `::... const`
308   if (TypeToken->is(tok::coloncolon)) {
309     // The case `const ::template Foo...` -> `::template Foo... const`
310     TypeToken = TypeToken->getNextNonComment();
311     if (TypeToken && TypeToken->is(tok::kw_template))
312       TypeToken = TypeToken->getNextNonComment();
313   }
314 
315   // Don't change declarations such as
316   // `foo(const struct Foo a);` -> `foo(const struct Foo a);`
317   // as they would currently change code such as
318   // `const struct my_struct_t {} my_struct;` -> `struct my_struct_t const {}
319   // my_struct;`
320   if (TypeToken->isOneOf(tok::kw_struct, tok::kw_class))
321     return Tok;
322 
323   if (TypeToken->isOneOf(tok::kw_auto, tok::identifier)) {
324     // The case  `const auto` -> `auto const`
325     // The case  `const Foo` -> `Foo const`
326     // The case  `const ::Foo` -> `::Foo const`
327     // The case  `const Foo *` -> `Foo const *`
328     // The case  `const Foo &` -> `Foo const &`
329     // The case  `const Foo &&` -> `Foo const &&`
330     // The case  `const std::Foo &&` -> `std::Foo const &&`
331     // The case  `const std::Foo<T> &&` -> `std::Foo<T> const &&`
332     // The case  `const ::template Foo` -> `::template Foo const`
333     // The case  `const T::template Foo` -> `T::template Foo const`
334     const FormatToken *Next = nullptr;
335     while ((Next = TypeToken->getNextNonComment()) &&
336            (Next->is(TT_TemplateOpener) ||
337             Next->startsSequence(tok::coloncolon, tok::identifier) ||
338             Next->startsSequence(tok::coloncolon, tok::kw_template,
339                                  tok::identifier))) {
340       if (Next->is(TT_TemplateOpener)) {
341         assert(Next->MatchingParen && "Missing template closer");
342         TypeToken = Next->MatchingParen;
343       } else if (Next->startsSequence(tok::coloncolon, tok::identifier)) {
344         TypeToken = Next->getNextNonComment();
345       } else {
346         TypeToken = Next->getNextNonComment()->getNextNonComment();
347       }
348     }
349 
350     if (Next && Next->is(tok::kw_auto))
351       TypeToken = Next;
352 
353     // Place the Qualifier at the end of the list of qualifiers.
354     while (isQualifier(TypeToken->getNextNonComment())) {
355       // The case `volatile Foo::iter const` -> `Foo::iter const volatile`
356       TypeToken = TypeToken->getNextNonComment();
357     }
358 
359     insertQualifierAfter(SourceMgr, Fixes, TypeToken, Qualifier);
360     // Remove token and following whitespace.
361     auto Range = CharSourceRange::getCharRange(
362         Tok->getStartOfNonWhitespace(), Tok->Next->getStartOfNonWhitespace());
363     replaceToken(SourceMgr, Fixes, Range, "");
364   }
365 
366   return Tok;
367 }
368 
369 const FormatToken *LeftRightQualifierAlignmentFixer::analyzeLeft(
370     const SourceManager &SourceMgr, const AdditionalKeywords &Keywords,
371     tooling::Replacements &Fixes, const FormatToken *const Tok,
372     const std::string &Qualifier, tok::TokenKind QualifierType) {
373   // We only need to think about streams that begin with a qualifier.
374   if (Tok->isNot(QualifierType))
375     return Tok;
376   // Don't concern yourself if nothing preceeds the qualifier.
377   if (!Tok->getPreviousNonComment())
378     return Tok;
379 
380   // Skip qualifiers to the left to find what preceeds the qualifiers.
381   const FormatToken *TypeToken = Tok->getPreviousNonComment();
382   while (isQualifier(TypeToken))
383     TypeToken = TypeToken->getPreviousNonComment();
384 
385   // For left qualifiers preceeded by nothing, a template declaration, or *,&,&&
386   // we only perform sorting.
387   if (!TypeToken || TypeToken->isPointerOrReference() ||
388       TypeToken->ClosesRequiresClause || TypeToken->ClosesTemplateDeclaration ||
389       TypeToken->is(tok::r_square)) {
390 
391     // Don't sort past a non-configured qualifier token.
392     const FormatToken *FirstQual = Tok;
393     while (isConfiguredQualifier(FirstQual->getPreviousNonComment(),
394                                  ConfiguredQualifierTokens)) {
395       FirstQual = FirstQual->getPreviousNonComment();
396     }
397 
398     if (FirstQual != Tok)
399       rotateTokens(SourceMgr, Fixes, FirstQual, Tok, /*Left=*/true);
400     return Tok;
401   }
402 
403   // Stay safe and don't move past macros, also don't bother with sorting.
404   if (isPossibleMacro(TypeToken))
405     return Tok;
406 
407   // Examples given in order of ['const', 'volatile', 'type']
408 
409   // The case `volatile long long int const` -> `const volatile long long int`
410   // The case `volatile long long const int` -> `const volatile long long int`
411   // The case `const long long volatile int` -> `const volatile long long int`
412   // The case `long volatile long int const` -> `const volatile long long int`
413   if (TypeToken->isTypeName(LangOpts)) {
414     for (const auto *Prev = TypeToken->Previous;
415          Prev && Prev->is(tok::coloncolon); Prev = Prev->Previous) {
416       TypeToken = Prev;
417       Prev = Prev->Previous;
418       if (!(Prev && Prev->is(tok::identifier)))
419         break;
420       TypeToken = Prev;
421     }
422     const FormatToken *LastSimpleTypeSpecifier = TypeToken;
423     while (isConfiguredQualifierOrType(
424         LastSimpleTypeSpecifier->getPreviousNonComment(),
425         ConfiguredQualifierTokens, LangOpts)) {
426       LastSimpleTypeSpecifier =
427           LastSimpleTypeSpecifier->getPreviousNonComment();
428     }
429 
430     rotateTokens(SourceMgr, Fixes, LastSimpleTypeSpecifier, Tok,
431                  /*Left=*/true);
432     return Tok;
433   }
434 
435   if (TypeToken->isOneOf(tok::kw_auto, tok::identifier, TT_TemplateCloser)) {
436     const auto IsStartOfType = [](const FormatToken *const Tok) -> bool {
437       if (!Tok)
438         return true;
439 
440       // A template closer is not the start of a type.
441       // The case `?<> const` -> `const ?<>`
442       if (Tok->is(TT_TemplateCloser))
443         return false;
444 
445       const FormatToken *const Previous = Tok->getPreviousNonComment();
446       if (!Previous)
447         return true;
448 
449       // An identifier preceeded by :: is not the start of a type.
450       // The case `?::Foo const` -> `const ?::Foo`
451       if (Tok->is(tok::identifier) && Previous->is(tok::coloncolon))
452         return false;
453 
454       const FormatToken *const PrePrevious = Previous->getPreviousNonComment();
455       // An identifier preceeded by ::template is not the start of a type.
456       // The case `?::template Foo const` -> `const ?::template Foo`
457       if (Tok->is(tok::identifier) && Previous->is(tok::kw_template) &&
458           PrePrevious && PrePrevious->is(tok::coloncolon)) {
459         return false;
460       }
461 
462       if (Tok->endsSequence(tok::kw_auto, tok::identifier))
463         return false;
464 
465       return true;
466     };
467 
468     while (!IsStartOfType(TypeToken)) {
469       // The case `?<>`
470       if (TypeToken->is(TT_TemplateCloser)) {
471         assert(TypeToken->MatchingParen && "Missing template opener");
472         TypeToken = TypeToken->MatchingParen->getPreviousNonComment();
473       } else {
474         // The cases
475         // `::Foo`
476         // `?>::Foo`
477         // `?Bar::Foo`
478         // `::template Foo`
479         // `?>::template Foo`
480         // `?Bar::template Foo`
481         if (TypeToken->getPreviousNonComment()->is(tok::kw_template))
482           TypeToken = TypeToken->getPreviousNonComment();
483 
484         const FormatToken *const ColonColon =
485             TypeToken->getPreviousNonComment();
486         const FormatToken *const PreColonColon =
487             ColonColon->getPreviousNonComment();
488         if (PreColonColon &&
489             PreColonColon->isOneOf(TT_TemplateCloser, tok::identifier)) {
490           TypeToken = PreColonColon;
491         } else {
492           TypeToken = ColonColon;
493         }
494       }
495     }
496 
497     assert(TypeToken && "Should be auto or identifier");
498 
499     // Place the Qualifier at the start of the list of qualifiers.
500     const FormatToken *Previous = nullptr;
501     while ((Previous = TypeToken->getPreviousNonComment()) &&
502            (isConfiguredQualifier(Previous, ConfiguredQualifierTokens) ||
503             Previous->is(tok::kw_typename))) {
504       // The case `volatile Foo::iter const` -> `const volatile Foo::iter`
505       // The case `typename C::type const` -> `const typename C::type`
506       TypeToken = Previous;
507     }
508 
509     // Don't change declarations such as
510     // `foo(struct Foo const a);` -> `foo(struct Foo const a);`
511     if (!Previous || !Previous->isOneOf(tok::kw_struct, tok::kw_class)) {
512       insertQualifierBefore(SourceMgr, Fixes, TypeToken, Qualifier);
513       removeToken(SourceMgr, Fixes, Tok);
514     }
515   }
516 
517   return Tok;
518 }
519 
520 tok::TokenKind LeftRightQualifierAlignmentFixer::getTokenFromQualifier(
521     const std::string &Qualifier) {
522   // Don't let 'type' be an identifier, but steal typeof token.
523   return llvm::StringSwitch<tok::TokenKind>(Qualifier)
524       .Case("type", tok::kw_typeof)
525       .Case("const", tok::kw_const)
526       .Case("volatile", tok::kw_volatile)
527       .Case("static", tok::kw_static)
528       .Case("inline", tok::kw_inline)
529       .Case("constexpr", tok::kw_constexpr)
530       .Case("restrict", tok::kw_restrict)
531       .Case("friend", tok::kw_friend)
532       .Default(tok::identifier);
533 }
534 
535 LeftRightQualifierAlignmentFixer::LeftRightQualifierAlignmentFixer(
536     const Environment &Env, const FormatStyle &Style,
537     const std::string &Qualifier,
538     const std::vector<tok::TokenKind> &QualifierTokens, bool RightAlign)
539     : TokenAnalyzer(Env, Style), Qualifier(Qualifier), RightAlign(RightAlign),
540       ConfiguredQualifierTokens(QualifierTokens) {}
541 
542 std::pair<tooling::Replacements, unsigned>
543 LeftRightQualifierAlignmentFixer::analyze(
544     TokenAnnotator & /*Annotator*/,
545     SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
546     FormatTokenLexer &Tokens) {
547   tooling::Replacements Fixes;
548   AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
549   fixQualifierAlignment(AnnotatedLines, Tokens, Fixes);
550   return {Fixes, 0};
551 }
552 
553 void LeftRightQualifierAlignmentFixer::fixQualifierAlignment(
554     SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, FormatTokenLexer &Tokens,
555     tooling::Replacements &Fixes) {
556   const AdditionalKeywords &Keywords = Tokens.getKeywords();
557   const SourceManager &SourceMgr = Env.getSourceManager();
558   tok::TokenKind QualifierToken = getTokenFromQualifier(Qualifier);
559   assert(QualifierToken != tok::identifier && "Unrecognised Qualifier");
560 
561   for (AnnotatedLine *Line : AnnotatedLines) {
562     fixQualifierAlignment(Line->Children, Tokens, Fixes);
563     if (!Line->Affected || Line->InPPDirective)
564       continue;
565     FormatToken *First = Line->First;
566     assert(First);
567     if (First->Finalized)
568       continue;
569 
570     const auto *Last = Line->Last;
571 
572     for (const auto *Tok = First; Tok && Tok != Last && Tok->Next;
573          Tok = Tok->Next) {
574       if (Tok->MustBreakBefore)
575         break;
576       if (Tok->is(tok::comment))
577         continue;
578       if (RightAlign) {
579         Tok = analyzeRight(SourceMgr, Keywords, Fixes, Tok, Qualifier,
580                            QualifierToken);
581       } else {
582         Tok = analyzeLeft(SourceMgr, Keywords, Fixes, Tok, Qualifier,
583                           QualifierToken);
584       }
585     }
586   }
587 }
588 
589 void prepareLeftRightOrderingForQualifierAlignmentFixer(
590     const std::vector<std::string> &Order, std::vector<std::string> &LeftOrder,
591     std::vector<std::string> &RightOrder,
592     std::vector<tok::TokenKind> &Qualifiers) {
593 
594   // Depending on the position of type in the order you need
595   // To iterate forward or backward through the order list as qualifier
596   // can push through each other.
597   // The Order list must define the position of "type" to signify
598   assert(llvm::is_contained(Order, "type") &&
599          "QualifierOrder must contain type");
600   // Split the Order list by type and reverse the left side.
601 
602   bool left = true;
603   for (const auto &s : Order) {
604     if (s == "type") {
605       left = false;
606       continue;
607     }
608 
609     tok::TokenKind QualifierToken =
610         LeftRightQualifierAlignmentFixer::getTokenFromQualifier(s);
611     if (QualifierToken != tok::kw_typeof && QualifierToken != tok::identifier)
612       Qualifiers.push_back(QualifierToken);
613 
614     if (left) {
615       // Reverse the order for left aligned items.
616       LeftOrder.insert(LeftOrder.begin(), s);
617     } else {
618       RightOrder.push_back(s);
619     }
620   }
621 }
622 
623 bool isQualifierOrType(const FormatToken *Tok, const LangOptions &LangOpts) {
624   return Tok && (Tok->isTypeName(LangOpts) || Tok->is(tok::kw_auto) ||
625                  isQualifier(Tok));
626 }
627 
628 bool isConfiguredQualifierOrType(const FormatToken *Tok,
629                                  const std::vector<tok::TokenKind> &Qualifiers,
630                                  const LangOptions &LangOpts) {
631   return Tok && (Tok->isTypeName(LangOpts) || Tok->is(tok::kw_auto) ||
632                  isConfiguredQualifier(Tok, Qualifiers));
633 }
634 
635 // If a token is an identifier and it's upper case, it could
636 // be a macro and hence we need to be able to ignore it.
637 bool isPossibleMacro(const FormatToken *Tok) {
638   assert(Tok);
639   if (Tok->isNot(tok::identifier))
640     return false;
641 
642   const auto Text = Tok->TokenText;
643   assert(!Text.empty());
644 
645   // T,K,U,V likely could be template arguments
646   if (Text.size() == 1)
647     return false;
648 
649   // It's unlikely that qualified names are object-like macros.
650   const auto *Prev = Tok->getPreviousNonComment();
651   if (Prev && Prev->is(tok::coloncolon))
652     return false;
653   const auto *Next = Tok->getNextNonComment();
654   if (Next && Next->is(tok::coloncolon))
655     return false;
656 
657   return Text == Text.upper();
658 }
659 
660 } // namespace format
661 } // namespace clang
662