clang 20.0.0git
MacroExpander.cpp
Go to the documentation of this file.
1//===--- MacroExpander.cpp - Format C++ code --------------------*- 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 contains the implementation of MacroExpander, which handles macro
11/// configuration and expansion while formatting.
12///
13//===----------------------------------------------------------------------===//
14
15#include "Macros.h"
16
17#include "Encoding.h"
18#include "FormatToken.h"
19#include "FormatTokenLexer.h"
21#include "clang/Format/Format.h"
24#include "clang/Lex/Lexer.h"
28#include "llvm/ADT/StringSet.h"
29#include "llvm/Support/ErrorHandling.h"
30
31namespace clang {
32namespace format {
33
35 StringRef Name;
38
39 // Map from each argument's name to its position in the argument list.
40 // With "M(x, y) x + y":
41 // x -> 0
42 // y -> 1
43 llvm::StringMap<size_t> ArgMap;
44
45 bool ObjectLike = true;
46};
47
49public:
50 DefinitionParser(ArrayRef<FormatToken *> Tokens) : Tokens(Tokens) {
51 assert(!Tokens.empty());
52 Current = Tokens[0];
53 }
54
55 // Parse the token stream and return the corresponding Definition object.
56 // Returns an empty definition object with a null-Name on error.
58 if (Current->isNot(tok::identifier))
59 return {};
60 Def.Name = Current->TokenText;
61 nextToken();
62 if (Current->is(tok::l_paren)) {
63 Def.ObjectLike = false;
64 if (!parseParams())
65 return {};
66 }
67 if (!parseExpansion())
68 return {};
69
70 return Def;
71 }
72
73private:
74 bool parseParams() {
75 assert(Current->is(tok::l_paren));
76 nextToken();
77 while (Current->is(tok::identifier)) {
78 Def.Params.push_back(Current);
79 Def.ArgMap[Def.Params.back()->TokenText] = Def.Params.size() - 1;
80 nextToken();
81 if (Current->isNot(tok::comma))
82 break;
83 nextToken();
84 }
85 if (Current->isNot(tok::r_paren))
86 return false;
87 nextToken();
88 return true;
89 }
90
91 bool parseExpansion() {
92 if (!Current->isOneOf(tok::equal, tok::eof))
93 return false;
94 if (Current->is(tok::equal))
95 nextToken();
96 parseTail();
97 return true;
98 }
99
100 void parseTail() {
101 while (Current->isNot(tok::eof)) {
102 Def.Body.push_back(Current);
103 nextToken();
104 }
105 Def.Body.push_back(Current);
106 }
107
108 void nextToken() {
109 if (Pos + 1 < Tokens.size())
110 ++Pos;
111 Current = Tokens[Pos];
112 Current->Finalized = true;
113 }
114
115 size_t Pos = 0;
116 FormatToken *Current = nullptr;
117 Definition Def;
118 ArrayRef<FormatToken *> Tokens;
119};
120
122 const std::vector<std::string> &Macros, SourceManager &SourceMgr,
123 const FormatStyle &Style,
124 llvm::SpecificBumpPtrAllocator<FormatToken> &Allocator,
125