MacroExpander.cpp 6.7 KB

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