xref: /netbsd-src/external/apache2/llvm/dist/clang/lib/Format/MacroExpander.cpp (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
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