1*e038c9c4Sjoerg //===--- MacroExpander.cpp - Format C++ code --------------------*- C++ -*-===//
2*e038c9c4Sjoerg //
3*e038c9c4Sjoerg // The LLVM Compiler Infrastructure
4*e038c9c4Sjoerg //
5*e038c9c4Sjoerg // This file is distributed under the University of Illinois Open Source
6*e038c9c4Sjoerg // License. See LICENSE.TXT for details.
7*e038c9c4Sjoerg //
8*e038c9c4Sjoerg //===----------------------------------------------------------------------===//
9*e038c9c4Sjoerg ///
10*e038c9c4Sjoerg /// \file
11*e038c9c4Sjoerg /// This file contains the implementation of MacroExpander, which handles macro
12*e038c9c4Sjoerg /// configuration and expansion while formatting.
13*e038c9c4Sjoerg ///
14*e038c9c4Sjoerg //===----------------------------------------------------------------------===//
15*e038c9c4Sjoerg
16*e038c9c4Sjoerg #include "Macros.h"
17*e038c9c4Sjoerg
18*e038c9c4Sjoerg #include "Encoding.h"
19*e038c9c4Sjoerg #include "FormatToken.h"
20*e038c9c4Sjoerg #include "FormatTokenLexer.h"
21*e038c9c4Sjoerg #include "clang/Basic/TokenKinds.h"
22*e038c9c4Sjoerg #include "clang/Format/Format.h"
23*e038c9c4Sjoerg #include "clang/Lex/HeaderSearch.h"
24*e038c9c4Sjoerg #include "clang/Lex/HeaderSearchOptions.h"
25*e038c9c4Sjoerg #include "clang/Lex/Lexer.h"
26*e038c9c4Sjoerg #include "clang/Lex/ModuleLoader.h"
27*e038c9c4Sjoerg #include "clang/Lex/Preprocessor.h"
28*e038c9c4Sjoerg #include "clang/Lex/PreprocessorOptions.h"
29*e038c9c4Sjoerg #include "llvm/ADT/StringSet.h"
30*e038c9c4Sjoerg #include "llvm/Support/ErrorHandling.h"
31*e038c9c4Sjoerg
32*e038c9c4Sjoerg namespace clang {
33*e038c9c4Sjoerg namespace format {
34*e038c9c4Sjoerg
35*e038c9c4Sjoerg struct MacroExpander::Definition {
36*e038c9c4Sjoerg StringRef Name;
37*e038c9c4Sjoerg SmallVector<FormatToken *, 8> Params;
38*e038c9c4Sjoerg SmallVector<FormatToken *, 8> Body;
39*e038c9c4Sjoerg
40*e038c9c4Sjoerg // Map from each argument's name to its position in the argument list.
41*e038c9c4Sjoerg // With "M(x, y) x + y":
42*e038c9c4Sjoerg // x -> 0
43*e038c9c4Sjoerg // y -> 1
44*e038c9c4Sjoerg llvm::StringMap<size_t> ArgMap;
45*e038c9c4Sjoerg
46*e038c9c4Sjoerg bool ObjectLike = true;
47*e038c9c4Sjoerg };
48*e038c9c4Sjoerg
49*e038c9c4Sjoerg class MacroExpander::DefinitionParser {
50*e038c9c4Sjoerg public:
DefinitionParser(ArrayRef<FormatToken * > Tokens)51*e038c9c4Sjoerg DefinitionParser(ArrayRef<FormatToken *> Tokens) : Tokens(Tokens) {
52*e038c9c4Sjoerg assert(!Tokens.empty());
53*e038c9c4Sjoerg Current = Tokens[0];
54*e038c9c4Sjoerg }
55*e038c9c4Sjoerg
56*e038c9c4Sjoerg // Parse the token stream and return the corresonding Definition object.
57*e038c9c4Sjoerg // Returns an empty definition object with a null-Name on error.
parse()58*e038c9c4Sjoerg MacroExpander::Definition parse() {
59*e038c9c4Sjoerg if (!Current->is(tok::identifier))
60*e038c9c4Sjoerg return {};
61*e038c9c4Sjoerg Def.Name = Current->TokenText;
62*e038c9c4Sjoerg nextToken();
63*e038c9c4Sjoerg if (Current->is(tok::l_paren)) {
64*e038c9c4Sjoerg Def.ObjectLike = false;
65*e038c9c4Sjoerg if (!parseParams())
66*e038c9c4Sjoerg return {};
67*e038c9c4Sjoerg }
68*e038c9c4Sjoerg if (!parseExpansion())
69*e038c9c4Sjoerg return {};
70*e038c9c4Sjoerg
71*e038c9c4Sjoerg return Def;
72*e038c9c4Sjoerg }
73*e038c9c4Sjoerg
74*e038c9c4Sjoerg private:
parseParams()75*e038c9c4Sjoerg bool parseParams() {
76*e038c9c4Sjoerg assert(Current->is(tok::l_paren));
77*e038c9c4Sjoerg nextToken();
78*e038c9c4Sjoerg while (Current->is(tok::identifier)) {
79*e038c9c4Sjoerg Def.Params.push_back(Current);
80*e038c9c4Sjoerg Def.ArgMap[Def.Params.back()->TokenText] = Def.Params.size() - 1;
81*e038c9c4Sjoerg nextToken();
82*e038c9c4Sjoerg if (Current->isNot(tok::comma))
83*e038c9c4Sjoerg break;
84*e038c9c4Sjoerg nextToken();
85*e038c9c4Sjoerg }
86*e038c9c4Sjoerg if (Current->isNot(tok::r_paren))
87*e038c9c4Sjoerg return false;
88*e038c9c4Sjoerg nextToken();
89*e038c9c4Sjoerg return true;
90*e038c9c4Sjoerg }
91*e038c9c4Sjoerg
parseExpansion()92*e038c9c4Sjoerg bool parseExpansion() {
93*e038c9c4Sjoerg if (!Current->isOneOf(tok::equal, tok::eof))
94*e038c9c4Sjoerg return false;
95*e038c9c4Sjoerg if (Current->is(tok::equal))
96*e038c9c4Sjoerg nextToken();
97*e038c9c4Sjoerg parseTail();
98*e038c9c4Sjoerg return true;
99*e038c9c4Sjoerg }
100*e038c9c4Sjoerg
parseTail()101*e038c9c4Sjoerg void parseTail() {
102*e038c9c4Sjoerg while (Current->isNot(tok::eof)) {
103*e038c9c4Sjoerg Def.Body.push_back(Current);
104*e038c9c4Sjoerg nextToken();
105*e038c9c4Sjoerg }
106*e038c9c4Sjoerg Def.Body.push_back(Current);
107*e038c9c4Sjoerg }
108*e038c9c4Sjoerg
nextToken()109*e038c9c4Sjoerg void nextToken() {
110*e038c9c4Sjoerg if (Pos + 1 < Tokens.size())
111*e038c9c4Sjoerg ++Pos;
112*e038c9c4Sjoerg Current = Tokens[Pos];
113*e038c9c4Sjoerg Current->Finalized = true;
114*e038c9c4Sjoerg }
115*e038c9c4Sjoerg
116*e038c9c4Sjoerg size_t Pos = 0;
117*e038c9c4Sjoerg FormatToken *Current = nullptr;
118*e038c9c4Sjoerg Definition Def;
119*e038c9c4Sjoerg ArrayRef<FormatToken *> Tokens;
120*e038c9c4Sjoerg };
121*e038c9c4Sjoerg
MacroExpander(const std::vector<std::string> & Macros,clang::SourceManager & SourceMgr,const FormatStyle & Style,llvm::SpecificBumpPtrAllocator<FormatToken> & Allocator,IdentifierTable & IdentTable)122*e038c9c4Sjoerg MacroExpander::MacroExpander(
123*e038c9c4Sjoerg const std::vector<std::string> &Macros, clang::SourceManager &SourceMgr,
124*e038c9c4Sjoerg const FormatStyle &Style,
125*e038c9c4Sjoerg llvm::SpecificBumpPtrAllocator<FormatToken> &Allocator,
126*e038c9c4Sjoerg IdentifierTable &IdentTable)
127*e038c9c4Sjoerg : SourceMgr(SourceMgr), Style(Style), Allocator(Allocator),
128*e038c9c4Sjoerg IdentTable(IdentTable) {
129*e038c9c4Sjoerg for (const std::string &Macro : Macros) {
130*e038c9c4Sjoerg parseDefinition(Macro);
131*e038c9c4Sjoerg }
132*e038c9c4Sjoerg }
133*e038c9c4Sjoerg
134*e038c9c4Sjoerg MacroExpander::~MacroExpander() = default;
135*e038c9c4Sjoerg
parseDefinition(const std::string & Macro)136*e038c9c4Sjoerg void MacroExpander::parseDefinition(const std::string &Macro) {
137*e038c9c4Sjoerg Buffers.push_back(
138*e038c9c4Sjoerg llvm::MemoryBuffer::getMemBufferCopy(Macro, "<scratch space>"));
139*e038c9c4Sjoerg clang::FileID FID = SourceMgr.createFileID(Buffers.back()->getMemBufferRef());
140*e038c9c4Sjoerg FormatTokenLexer Lex(SourceMgr, FID, 0, Style, encoding::Encoding_UTF8,
141*e038c9c4Sjoerg Allocator, IdentTable);
142*e038c9c4Sjoerg const auto Tokens = Lex.lex();
143*e038c9c4Sjoerg if (!Tokens.empty()) {
144*e038c9c4Sjoerg DefinitionParser Parser(Tokens);
145*e038c9c4Sjoerg auto Definition = Parser.parse();
146*e038c9c4Sjoerg Definitions[Definition.Name] = std::move(Definition);
147*e038c9c4Sjoerg }
148*e038c9c4Sjoerg }
149*e038c9c4Sjoerg
defined(llvm::StringRef Name) const150*e038c9c4Sjoerg bool MacroExpander::defined(llvm::StringRef Name) const {
151*e038c9c4Sjoerg return Definitions.find(Name) != Definitions.end();
152*e038c9c4Sjoerg }
153*e038c9c4Sjoerg
objectLike(llvm::StringRef Name) const154*e038c9c4Sjoerg bool MacroExpander::objectLike(llvm::StringRef Name) const {
155*e038c9c4Sjoerg return Definitions.find(Name)->second.ObjectLike;
156*e038c9c4Sjoerg }
157*e038c9c4Sjoerg
expand(FormatToken * ID,ArgsList Args) const158*e038c9c4Sjoerg llvm::SmallVector<FormatToken *, 8> MacroExpander::expand(FormatToken *ID,
159*e038c9c4Sjoerg ArgsList Args) const {
160*e038c9c4Sjoerg assert(defined(ID->TokenText));
161*e038c9c4Sjoerg SmallVector<FormatToken *, 8> Result;
162*e038c9c4Sjoerg const Definition &Def = Definitions.find(ID->TokenText)->second;
163*e038c9c4Sjoerg
164*e038c9c4Sjoerg // Expand each argument at most once.
165*e038c9c4Sjoerg llvm::StringSet<> ExpandedArgs;
166*e038c9c4Sjoerg
167*e038c9c4Sjoerg // Adds the given token to Result.
168*e038c9c4Sjoerg auto pushToken = [&](FormatToken *Tok) {
169*e038c9c4Sjoerg Tok->MacroCtx->ExpandedFrom.push_back(ID);
170*e038c9c4Sjoerg Result.push_back(Tok);
171*e038c9c4Sjoerg };
172*e038c9c4Sjoerg
173*e038c9c4Sjoerg // If Tok references a parameter, adds the corresponding argument to Result.
174*e038c9c4Sjoerg // Returns false if Tok does not reference a parameter.
175*e038c9c4Sjoerg auto expandArgument = [&](FormatToken *Tok) -> bool {
176*e038c9c4Sjoerg // If the current token references a parameter, expand the corresponding
177*e038c9c4Sjoerg // argument.
178*e038c9c4Sjoerg if (!Tok->is(tok::identifier) || ExpandedArgs.contains(Tok->TokenText))
179*e038c9c4Sjoerg return false;
180*e038c9c4Sjoerg ExpandedArgs.insert(Tok->TokenText);
181*e038c9c4Sjoerg auto I = Def.ArgMap.find(Tok->TokenText);
182*e038c9c4Sjoerg if (I == Def.ArgMap.end())
183*e038c9c4Sjoerg return false;
184*e038c9c4Sjoerg // If there are fewer arguments than referenced parameters, treat the
185*e038c9c4Sjoerg // parameter as empty.
186*e038c9c4Sjoerg // FIXME: Potentially fully abort the expansion instead.
187*e038c9c4Sjoerg if (I->getValue() >= Args.size())
188*e038c9c4Sjoerg return true;
189*e038c9c4Sjoerg for (FormatToken *Arg : Args[I->getValue()]) {
190*e038c9c4Sjoerg // A token can be part of a macro argument at multiple levels.
191*e038c9c4Sjoerg // For example, with "ID(x) x":
192*e038c9c4Sjoerg // in ID(ID(x)), 'x' is expanded first as argument to the inner
193*e038c9c4Sjoerg // ID, then again as argument to the outer ID. We keep the macro
194*e038c9c4Sjoerg // role the token had from the inner expansion.
195*e038c9c4Sjoerg if (!Arg->MacroCtx)
196*e038c9c4Sjoerg Arg->MacroCtx = MacroExpansion(MR_ExpandedArg);
197*e038c9c4Sjoerg pushToken(Arg);
198*e038c9c4Sjoerg }
199*e038c9c4Sjoerg return true;
200*e038c9c4Sjoerg };
201*e038c9c4Sjoerg
202*e038c9c4Sjoerg // Expand the definition into Result.
203*e038c9c4Sjoerg for (FormatToken *Tok : Def.Body) {
204*e038c9c4Sjoerg if (expandArgument(Tok))
205*e038c9c4Sjoerg continue;
206*e038c9c4Sjoerg // Create a copy of the tokens from the macro body, i.e. were not provided
207*e038c9c4Sjoerg // by user code.
208*e038c9c4Sjoerg FormatToken *New = new (Allocator.Allocate()) FormatToken;
209*e038c9c4Sjoerg New->copyFrom(*Tok);
210*e038c9c4Sjoerg assert(!New->MacroCtx);
211*e038c9c4Sjoerg // Tokens that are not part of the user code are not formatted.
212*e038c9c4Sjoerg New->MacroCtx = MacroExpansion(MR_Hidden);
213*e038c9c4Sjoerg pushToken(New);
214*e038c9c4Sjoerg }
215*e038c9c4Sjoerg assert(Result.size() >= 1 && Result.back()->is(tok::eof));
216*e038c9c4Sjoerg if (Result.size() > 1) {
217*e038c9c4Sjoerg ++Result[0]->MacroCtx->StartOfExpansion;
218*e038c9c4Sjoerg ++Result[Result.size() - 2]->MacroCtx->EndOfExpansion;
219*e038c9c4Sjoerg }
220*e038c9c4Sjoerg return Result;
221*e038c9c4Sjoerg }
222*e038c9c4Sjoerg
223*e038c9c4Sjoerg } // namespace format
224*e038c9c4Sjoerg } // namespace clang
225