aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/clang14/lib/Format/MacroExpander.cpp
diff options
context:
space:
mode:
authorvitalyisaev <vitalyisaev@yandex-team.com>2023-06-29 10:00:50 +0300
committervitalyisaev <vitalyisaev@yandex-team.com>2023-06-29 10:00:50 +0300
commit6ffe9e53658409f212834330e13564e4952558f6 (patch)
tree85b1e00183517648b228aafa7c8fb07f5276f419 /contrib/libs/clang14/lib/Format/MacroExpander.cpp
parent726057070f9c5a91fc10fde0d5024913d10f1ab9 (diff)
downloadydb-6ffe9e53658409f212834330e13564e4952558f6.tar.gz
YQ Connector: support managed ClickHouse
Со стороны dqrun можно обратиться к инстансу коннектора, который работает на streaming стенде, и извлечь данные из облачного CH.
Diffstat (limited to 'contrib/libs/clang14/lib/Format/MacroExpander.cpp')
-rw-r--r--contrib/libs/clang14/lib/Format/MacroExpander.cpp223
1 files changed, 223 insertions, 0 deletions
diff --git a/contrib/libs/clang14/lib/Format/MacroExpander.cpp b/contrib/libs/clang14/lib/Format/MacroExpander.cpp
new file mode 100644
index 0000000000..de96cb24ba
--- /dev/null
+++ b/contrib/libs/clang14/lib/Format/MacroExpander.cpp
@@ -0,0 +1,223 @@
+//===--- MacroExpander.cpp - Format C++ code --------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains the implementation of MacroExpander, which handles macro
+/// configuration and expansion while formatting.
+///
+//===----------------------------------------------------------------------===//
+
+#include "Macros.h"
+
+#include "Encoding.h"
+#include "FormatToken.h"
+#include "FormatTokenLexer.h"
+#include "clang/Basic/TokenKinds.h"
+#include "clang/Format/Format.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/HeaderSearchOptions.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/ModuleLoader.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/PreprocessorOptions.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/Support/ErrorHandling.h"
+
+namespace clang {
+namespace format {
+
+struct MacroExpander::Definition {
+ StringRef Name;
+ SmallVector<FormatToken *, 8> Params;
+ SmallVector<FormatToken *, 8> Body;
+
+ // Map from each argument's name to its position in the argument list.
+ // With "M(x, y) x + y":
+ // x -> 0
+ // y -> 1
+ llvm::StringMap<size_t> ArgMap;
+
+ bool ObjectLike = true;
+};
+
+class MacroExpander::DefinitionParser {
+public:
+ DefinitionParser(ArrayRef<FormatToken *> Tokens) : Tokens(Tokens) {
+ assert(!Tokens.empty());
+ Current = Tokens[0];
+ }
+
+ // Parse the token stream and return the corresponding Definition object.
+ // Returns an empty definition object with a null-Name on error.
+ MacroExpander::Definition parse() {
+ if (!Current->is(tok::identifier))
+ return {};
+ Def.Name = Current->TokenText;
+ nextToken();
+ if (Current->is(tok::l_paren)) {
+ Def.ObjectLike = false;
+ if (!parseParams())
+ return {};
+ }
+ if (!parseExpansion())
+ return {};
+
+ return Def;
+ }
+
+private:
+ bool parseParams() {
+ assert(Current->is(tok::l_paren));
+ nextToken();
+ while (Current->is(tok::identifier)) {
+ Def.Params.push_back(Current);
+ Def.ArgMap[Def.Params.back()->TokenText] = Def.Params.size() - 1;
+ nextToken();
+ if (Current->isNot(tok::comma))
+ break;
+ nextToken();
+ }
+ if (Current->isNot(tok::r_paren))
+ return false;
+ nextToken();
+ return true;
+ }
+
+ bool parseExpansion() {
+ if (!Current->isOneOf(tok::equal, tok::eof))
+ return false;
+ if (Current->is(tok::equal))
+ nextToken();
+ parseTail();
+ return true;
+ }
+
+ void parseTail() {
+ while (Current->isNot(tok::eof)) {
+ Def.Body.push_back(Current);
+ nextToken();
+ }
+ Def.Body.push_back(Current);
+ }
+
+ void nextToken() {
+ if (Pos + 1 < Tokens.size())
+ ++Pos;
+ Current = Tokens[Pos];
+ Current->Finalized = true;
+ }
+
+ size_t Pos = 0;
+ FormatToken *Current = nullptr;
+ Definition Def;
+ ArrayRef<FormatToken *> Tokens;
+};
+
+MacroExpander::MacroExpander(
+ const std::vector<std::string> &Macros, clang::SourceManager &SourceMgr,
+ const FormatStyle &Style,
+ llvm::SpecificBumpPtrAllocator<FormatToken> &Allocator,
+ IdentifierTable &IdentTable)
+ : SourceMgr(SourceMgr), Style(Style), Allocator(Allocator),
+ IdentTable(IdentTable) {
+ for (const std::string &Macro : Macros) {
+ parseDefinition(Macro);
+ }
+}
+
+MacroExpander::~MacroExpander() = default;
+
+void MacroExpander::parseDefinition(const std::string &Macro) {
+ Buffers.push_back(
+ llvm::MemoryBuffer::getMemBufferCopy(Macro, "<scratch space>"));
+ clang::FileID FID = SourceMgr.createFileID(Buffers.back()->getMemBufferRef());
+ FormatTokenLexer Lex(SourceMgr, FID, 0, Style, encoding::Encoding_UTF8,
+ Allocator, IdentTable);
+ const auto Tokens = Lex.lex();
+ if (!Tokens.empty()) {
+ DefinitionParser Parser(Tokens);
+ auto Definition = Parser.parse();
+ Definitions[Definition.Name] = std::move(Definition);
+ }
+}
+
+bool MacroExpander::defined(llvm::StringRef Name) const {
+ return Definitions.find(Name) != Definitions.end();
+}
+
+bool MacroExpander::objectLike(llvm::StringRef Name) const {
+ return Definitions.find(Name)->second.ObjectLike;
+}
+
+llvm::SmallVector<FormatToken *, 8> MacroExpander::expand(FormatToken *ID,
+ ArgsList Args) const {
+ assert(defined(ID->TokenText));
+ SmallVector<FormatToken *, 8> Result;
+ const Definition &Def = Definitions.find(ID->TokenText)->second;
+
+ // Expand each argument at most once.
+ llvm::StringSet<> ExpandedArgs;
+
+ // Adds the given token to Result.
+ auto pushToken = [&](FormatToken *Tok) {
+ Tok->MacroCtx->ExpandedFrom.push_back(ID);
+ Result.push_back(Tok);
+ };
+
+ // If Tok references a parameter, adds the corresponding argument to Result.
+ // Returns false if Tok does not reference a parameter.
+ auto expandArgument = [&](FormatToken *Tok) -> bool {
+ // If the current token references a parameter, expand the corresponding
+ // argument.
+ if (!Tok->is(tok::identifier) || ExpandedArgs.contains(Tok->TokenText))
+ return false;
+ ExpandedArgs.insert(Tok->TokenText);
+ auto I = Def.ArgMap.find(Tok->TokenText);
+ if (I == Def.ArgMap.end())
+ return false;
+ // If there are fewer arguments than referenced parameters, treat the
+ // parameter as empty.
+ // FIXME: Potentially fully abort the expansion instead.
+ if (I->getValue() >= Args.size())
+ return true;
+ for (FormatToken *Arg : Args[I->getValue()]) {
+ // A token can be part of a macro argument at multiple levels.
+ // For example, with "ID(x) x":
+ // in ID(ID(x)), 'x' is expanded first as argument to the inner
+ // ID, then again as argument to the outer ID. We keep the macro
+ // role the token had from the inner expansion.
+ if (!Arg->MacroCtx)
+ Arg->MacroCtx = MacroExpansion(MR_ExpandedArg);
+ pushToken(Arg);
+ }
+ return true;
+ };
+
+ // Expand the definition into Result.
+ for (FormatToken *Tok : Def.Body) {
+ if (expandArgument(Tok))
+ continue;
+ // Create a copy of the tokens from the macro body, i.e. were not provided
+ // by user code.
+ FormatToken *New = new (Allocator.Allocate()) FormatToken;
+ New->copyFrom(*Tok);
+ assert(!New->MacroCtx);
+ // Tokens that are not part of the user code are not formatted.
+ New->MacroCtx = MacroExpansion(MR_Hidden);
+ pushToken(New);
+ }
+ assert(Result.size() >= 1 && Result.back()->is(tok::eof));
+ if (Result.size() > 1) {
+ ++Result[0]->MacroCtx->StartOfExpansion;
+ ++Result[Result.size() - 2]->MacroCtx->EndOfExpansion;
+ }
+ return Result;
+}
+
+} // namespace format
+} // namespace clang