Path: blob/main/contrib/llvm-project/clang/lib/Tooling/Syntax/Synthesis.cpp
35271 views
//===- Synthesis.cpp ------------------------------------------*- C++ -*-=====//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7#include "clang/Basic/TokenKinds.h"8#include "clang/Tooling/Syntax/BuildTree.h"9#include "clang/Tooling/Syntax/Tree.h"10#include "clang/Tooling/Syntax/Tokens.h"11#include "clang/Tooling/Syntax/TokenBufferTokenManager.h"1213using namespace clang;1415/// Exposes private syntax tree APIs required to implement node synthesis.16/// Should not be used for anything else.17class clang::syntax::FactoryImpl {18public:19static void setCanModify(syntax::Node *N) { N->CanModify = true; }2021static void prependChildLowLevel(syntax::Tree *T, syntax::Node *Child,22syntax::NodeRole R) {23T->prependChildLowLevel(Child, R);24}25static void appendChildLowLevel(syntax::Tree *T, syntax::Node *Child,26syntax::NodeRole R) {27T->appendChildLowLevel(Child, R);28}2930static std::pair<FileID, ArrayRef<Token>>31lexBuffer(TokenBufferTokenManager &TBTM,32std::unique_ptr<llvm::MemoryBuffer> Buffer) {33return TBTM.lexBuffer(std::move(Buffer));34}35};3637// FIXME: `createLeaf` is based on `syntax::tokenize` internally, as such it38// doesn't support digraphs or line continuations.39syntax::Leaf *clang::syntax::createLeaf(syntax::Arena &A,40TokenBufferTokenManager &TBTM,41tok::TokenKind K, StringRef Spelling) {42auto Tokens =43FactoryImpl::lexBuffer(TBTM, llvm::MemoryBuffer::getMemBufferCopy(Spelling))44.second;45assert(Tokens.size() == 1);46assert(Tokens.front().kind() == K &&47"spelling is not lexed into the expected kind of token");4849auto *Leaf = new (A.getAllocator()) syntax::Leaf(50reinterpret_cast<TokenManager::Key>(Tokens.begin()));51syntax::FactoryImpl::setCanModify(Leaf);52Leaf->assertInvariants();53return Leaf;54}5556syntax::Leaf *clang::syntax::createLeaf(syntax::Arena &A,57TokenBufferTokenManager &TBTM,58tok::TokenKind K) {59const auto *Spelling = tok::getPunctuatorSpelling(K);60if (!Spelling)61Spelling = tok::getKeywordSpelling(K);62assert(Spelling &&63"Cannot infer the spelling of the token from its token kind.");64return createLeaf(A, TBTM, K, Spelling);65}6667namespace {68// Allocates the concrete syntax `Tree` according to its `NodeKind`.69syntax::Tree *allocateTree(syntax::Arena &A, syntax::NodeKind Kind) {70switch (Kind) {71case syntax::NodeKind::Leaf:72assert(false);73break;74case syntax::NodeKind::TranslationUnit:75return new (A.getAllocator()) syntax::TranslationUnit;76case syntax::NodeKind::UnknownExpression:77return new (A.getAllocator()) syntax::UnknownExpression;78case syntax::NodeKind::ParenExpression:79return new (A.getAllocator()) syntax::ParenExpression;80case syntax::NodeKind::ThisExpression:81return new (A.getAllocator()) syntax::ThisExpression;82case syntax::NodeKind::IntegerLiteralExpression:83return new (A.getAllocator()) syntax::IntegerLiteralExpression;84case syntax::NodeKind::CharacterLiteralExpression:85return new (A.getAllocator()) syntax::CharacterLiteralExpression;86case syntax::NodeKind::FloatingLiteralExpression:87return new (A.getAllocator()) syntax::FloatingLiteralExpression;88case syntax::NodeKind::StringLiteralExpression:89return new (A.getAllocator()) syntax::StringLiteralExpression;90case syntax::NodeKind::BoolLiteralExpression:91return new (A.getAllocator()) syntax::BoolLiteralExpression;92case syntax::NodeKind::CxxNullPtrExpression:93return new (A.getAllocator()) syntax::CxxNullPtrExpression;94case syntax::NodeKind::IntegerUserDefinedLiteralExpression:95return new (A.getAllocator()) syntax::IntegerUserDefinedLiteralExpression;96case syntax::NodeKind::FloatUserDefinedLiteralExpression:97return new (A.getAllocator()) syntax::FloatUserDefinedLiteralExpression;98case syntax::NodeKind::CharUserDefinedLiteralExpression:99return new (A.getAllocator()) syntax::CharUserDefinedLiteralExpression;100case syntax::NodeKind::StringUserDefinedLiteralExpression:101return new (A.getAllocator()) syntax::StringUserDefinedLiteralExpression;102case syntax::NodeKind::PrefixUnaryOperatorExpression:103return new (A.getAllocator()) syntax::PrefixUnaryOperatorExpression;104case syntax::NodeKind::PostfixUnaryOperatorExpression:105return new (A.getAllocator()) syntax::PostfixUnaryOperatorExpression;106case syntax::NodeKind::BinaryOperatorExpression:107return new (A.getAllocator()) syntax::BinaryOperatorExpression;108case syntax::NodeKind::UnqualifiedId:109return new (A.getAllocator()) syntax::UnqualifiedId;110case syntax::NodeKind::IdExpression:111return new (A.getAllocator()) syntax::IdExpression;112case syntax::NodeKind::CallExpression:113return new (A.getAllocator()) syntax::CallExpression;114case syntax::NodeKind::UnknownStatement:115return new (A.getAllocator()) syntax::UnknownStatement;116case syntax::NodeKind::DeclarationStatement:117return new (A.getAllocator()) syntax::DeclarationStatement;118case syntax::NodeKind::EmptyStatement:119return new (A.getAllocator()) syntax::EmptyStatement;120case syntax::NodeKind::SwitchStatement:121return new (A.getAllocator()) syntax::SwitchStatement;122case syntax::NodeKind::CaseStatement:123return new (A.getAllocator()) syntax::CaseStatement;124case syntax::NodeKind::DefaultStatement:125return new (A.getAllocator()) syntax::DefaultStatement;126case syntax::NodeKind::IfStatement:127return new (A.getAllocator()) syntax::IfStatement;128case syntax::NodeKind::ForStatement:129return new (A.getAllocator()) syntax::ForStatement;130case syntax::NodeKind::WhileStatement:131return new (A.getAllocator()) syntax::WhileStatement;132case syntax::NodeKind::ContinueStatement:133return new (A.getAllocator()) syntax::ContinueStatement;134case syntax::NodeKind::BreakStatement:135return new (A.getAllocator()) syntax::BreakStatement;136case syntax::NodeKind::ReturnStatement:137return new (A.getAllocator()) syntax::ReturnStatement;138case syntax::NodeKind::RangeBasedForStatement:139return new (A.getAllocator()) syntax::RangeBasedForStatement;140case syntax::NodeKind::ExpressionStatement:141return new (A.getAllocator()) syntax::ExpressionStatement;142case syntax::NodeKind::CompoundStatement:143return new (A.getAllocator()) syntax::CompoundStatement;144case syntax::NodeKind::UnknownDeclaration:145return new (A.getAllocator()) syntax::UnknownDeclaration;146case syntax::NodeKind::EmptyDeclaration:147return new (A.getAllocator()) syntax::EmptyDeclaration;148case syntax::NodeKind::StaticAssertDeclaration:149return new (A.getAllocator()) syntax::StaticAssertDeclaration;150case syntax::NodeKind::LinkageSpecificationDeclaration:151return new (A.getAllocator()) syntax::LinkageSpecificationDeclaration;152case syntax::NodeKind::SimpleDeclaration:153return new (A.getAllocator()) syntax::SimpleDeclaration;154case syntax::NodeKind::TemplateDeclaration:155return new (A.getAllocator()) syntax::TemplateDeclaration;156case syntax::NodeKind::ExplicitTemplateInstantiation:157return new (A.getAllocator()) syntax::ExplicitTemplateInstantiation;158case syntax::NodeKind::NamespaceDefinition:159return new (A.getAllocator()) syntax::NamespaceDefinition;160case syntax::NodeKind::NamespaceAliasDefinition:161return new (A.getAllocator()) syntax::NamespaceAliasDefinition;162case syntax::NodeKind::UsingNamespaceDirective:163return new (A.getAllocator()) syntax::UsingNamespaceDirective;164case syntax::NodeKind::UsingDeclaration:165return new (A.getAllocator()) syntax::UsingDeclaration;166case syntax::NodeKind::TypeAliasDeclaration:167return new (A.getAllocator()) syntax::TypeAliasDeclaration;168case syntax::NodeKind::SimpleDeclarator:169return new (A.getAllocator()) syntax::SimpleDeclarator;170case syntax::NodeKind::ParenDeclarator:171return new (A.getAllocator()) syntax::ParenDeclarator;172case syntax::NodeKind::ArraySubscript:173return new (A.getAllocator()) syntax::ArraySubscript;174case syntax::NodeKind::TrailingReturnType:175return new (A.getAllocator()) syntax::TrailingReturnType;176case syntax::NodeKind::ParametersAndQualifiers:177return new (A.getAllocator()) syntax::ParametersAndQualifiers;178case syntax::NodeKind::MemberPointer:179return new (A.getAllocator()) syntax::MemberPointer;180case syntax::NodeKind::GlobalNameSpecifier:181return new (A.getAllocator()) syntax::GlobalNameSpecifier;182case syntax::NodeKind::DecltypeNameSpecifier:183return new (A.getAllocator()) syntax::DecltypeNameSpecifier;184case syntax::NodeKind::IdentifierNameSpecifier:185return new (A.getAllocator()) syntax::IdentifierNameSpecifier;186case syntax::NodeKind::SimpleTemplateNameSpecifier:187return new (A.getAllocator()) syntax::SimpleTemplateNameSpecifier;188case syntax::NodeKind::NestedNameSpecifier:189return new (A.getAllocator()) syntax::NestedNameSpecifier;190case syntax::NodeKind::MemberExpression:191return new (A.getAllocator()) syntax::MemberExpression;192case syntax::NodeKind::CallArguments:193return new (A.getAllocator()) syntax::CallArguments;194case syntax::NodeKind::ParameterDeclarationList:195return new (A.getAllocator()) syntax::ParameterDeclarationList;196case syntax::NodeKind::DeclaratorList:197return new (A.getAllocator()) syntax::DeclaratorList;198}199llvm_unreachable("unknown node kind");200}201} // namespace202203syntax::Tree *clang::syntax::createTree(204syntax::Arena &A,205ArrayRef<std::pair<syntax::Node *, syntax::NodeRole>> Children,206syntax::NodeKind K) {207auto *T = allocateTree(A, K);208FactoryImpl::setCanModify(T);209for (const auto &Child : Children)210FactoryImpl::appendChildLowLevel(T, Child.first, Child.second);211212T->assertInvariants();213return T;214}215216syntax::Node *clang::syntax::deepCopyExpandingMacros(syntax::Arena &A,217TokenBufferTokenManager &TBTM,218const syntax::Node *N) {219if (const auto *L = dyn_cast<syntax::Leaf>(N))220// `L->getToken()` gives us the expanded token, thus we implicitly expand221// any macros here.222return createLeaf(A, TBTM, TBTM.getToken(L->getTokenKey())->kind(),223TBTM.getText(L->getTokenKey()));224225const auto *T = cast<syntax::Tree>(N);226std::vector<std::pair<syntax::Node *, syntax::NodeRole>> Children;227for (const auto *Child = T->getFirstChild(); Child;228Child = Child->getNextSibling())229Children.push_back({deepCopyExpandingMacros(A, TBTM, Child), Child->getRole()});230231return createTree(A, Children, N->getKind());232}233234syntax::EmptyStatement *clang::syntax::createEmptyStatement(syntax::Arena &A, TokenBufferTokenManager &TBTM) {235return cast<EmptyStatement>(236createTree(A, {{createLeaf(A, TBTM, tok::semi), NodeRole::Unknown}},237NodeKind::EmptyStatement));238}239240241