11ad15046SIlya Biryukov //===- Synthesis.cpp ------------------------------------------*- C++ -*-=====//
21ad15046SIlya Biryukov //
31ad15046SIlya Biryukov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
41ad15046SIlya Biryukov // See https://llvm.org/LICENSE.txt for license information.
51ad15046SIlya Biryukov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61ad15046SIlya Biryukov //
71ad15046SIlya Biryukov //===----------------------------------------------------------------------===//
85d152127SEduardo Caldas #include "clang/Basic/TokenKinds.h"
91ad15046SIlya Biryukov #include "clang/Tooling/Syntax/BuildTree.h"
10515238d5SEduardo Caldas #include "clang/Tooling/Syntax/Tree.h"
11*263dcf45SHaojian Wu #include "clang/Tooling/Syntax/Tokens.h"
12*263dcf45SHaojian Wu #include "clang/Tooling/Syntax/TokenBufferTokenManager.h"
131ad15046SIlya Biryukov
141ad15046SIlya Biryukov using namespace clang;
151ad15046SIlya Biryukov
161ad15046SIlya Biryukov /// Exposes private syntax tree APIs required to implement node synthesis.
171ad15046SIlya Biryukov /// Should not be used for anything else.
185d152127SEduardo Caldas class clang::syntax::FactoryImpl {
191ad15046SIlya Biryukov public:
setCanModify(syntax::Node * N)2007a41018SIlya Biryukov static void setCanModify(syntax::Node *N) { N->CanModify = true; }
2107a41018SIlya Biryukov
prependChildLowLevel(syntax::Tree * T,syntax::Node * Child,syntax::NodeRole R)221ad15046SIlya Biryukov static void prependChildLowLevel(syntax::Tree *T, syntax::Node *Child,
231ad15046SIlya Biryukov syntax::NodeRole R) {
241ad15046SIlya Biryukov T->prependChildLowLevel(Child, R);
251ad15046SIlya Biryukov }
appendChildLowLevel(syntax::Tree * T,syntax::Node * Child,syntax::NodeRole R)2623657d9cSEduardo Caldas static void appendChildLowLevel(syntax::Tree *T, syntax::Node *Child,
2723657d9cSEduardo Caldas syntax::NodeRole R) {
2823657d9cSEduardo Caldas T->appendChildLowLevel(Child, R);
2923657d9cSEduardo Caldas }
30515238d5SEduardo Caldas
31515238d5SEduardo Caldas static std::pair<FileID, ArrayRef<Token>>
lexBuffer(TokenBufferTokenManager & TBTM,std::unique_ptr<llvm::MemoryBuffer> Buffer)32*263dcf45SHaojian Wu lexBuffer(TokenBufferTokenManager &TBTM,
33*263dcf45SHaojian Wu std::unique_ptr<llvm::MemoryBuffer> Buffer) {
34*263dcf45SHaojian Wu return TBTM.lexBuffer(std::move(Buffer));
35515238d5SEduardo Caldas }
361ad15046SIlya Biryukov };
371ad15046SIlya Biryukov
384a5cc389SEduardo Caldas // FIXME: `createLeaf` is based on `syntax::tokenize` internally, as such it
394a5cc389SEduardo Caldas // doesn't support digraphs or line continuations.
createLeaf(syntax::Arena & A,TokenBufferTokenManager & TBTM,tok::TokenKind K,StringRef Spelling)40*263dcf45SHaojian Wu syntax::Leaf *clang::syntax::createLeaf(syntax::Arena &A,
41*263dcf45SHaojian Wu TokenBufferTokenManager &TBTM,
42*263dcf45SHaojian Wu tok::TokenKind K, StringRef Spelling) {
43515238d5SEduardo Caldas auto Tokens =
44*263dcf45SHaojian Wu FactoryImpl::lexBuffer(TBTM, llvm::MemoryBuffer::getMemBufferCopy(Spelling))
45515238d5SEduardo Caldas .second;
461ad15046SIlya Biryukov assert(Tokens.size() == 1);
475d152127SEduardo Caldas assert(Tokens.front().kind() == K &&
485d152127SEduardo Caldas "spelling is not lexed into the expected kind of token");
495d152127SEduardo Caldas
50*263dcf45SHaojian Wu auto *Leaf = new (A.getAllocator()) syntax::Leaf(
51*263dcf45SHaojian Wu reinterpret_cast<TokenManager::Key>(Tokens.begin()));
525d152127SEduardo Caldas syntax::FactoryImpl::setCanModify(Leaf);
535d152127SEduardo Caldas Leaf->assertInvariants();
545d152127SEduardo Caldas return Leaf;
551ad15046SIlya Biryukov }
561ad15046SIlya Biryukov
createLeaf(syntax::Arena & A,TokenBufferTokenManager & TBTM,tok::TokenKind K)57*263dcf45SHaojian Wu syntax::Leaf *clang::syntax::createLeaf(syntax::Arena &A,
58*263dcf45SHaojian Wu TokenBufferTokenManager &TBTM,
59*263dcf45SHaojian Wu tok::TokenKind K) {
605d152127SEduardo Caldas const auto *Spelling = tok::getPunctuatorSpelling(K);
615d152127SEduardo Caldas if (!Spelling)
625d152127SEduardo Caldas Spelling = tok::getKeywordSpelling(K);
635d152127SEduardo Caldas assert(Spelling &&
645d152127SEduardo Caldas "Cannot infer the spelling of the token from its token kind.");
65*263dcf45SHaojian Wu return createLeaf(A, TBTM, K, Spelling);
665d152127SEduardo Caldas }
675d152127SEduardo Caldas
681e19165bSEduardo Caldas namespace {
691e19165bSEduardo Caldas // Allocates the concrete syntax `Tree` according to its `NodeKind`.
allocateTree(syntax::Arena & A,syntax::NodeKind Kind)701e19165bSEduardo Caldas syntax::Tree *allocateTree(syntax::Arena &A, syntax::NodeKind Kind) {
711e19165bSEduardo Caldas switch (Kind) {
721e19165bSEduardo Caldas case syntax::NodeKind::Leaf:
731e19165bSEduardo Caldas assert(false);
7403358becSVitaly Buka break;
751e19165bSEduardo Caldas case syntax::NodeKind::TranslationUnit:
761e19165bSEduardo Caldas return new (A.getAllocator()) syntax::TranslationUnit;
771e19165bSEduardo Caldas case syntax::NodeKind::UnknownExpression:
781e19165bSEduardo Caldas return new (A.getAllocator()) syntax::UnknownExpression;
791e19165bSEduardo Caldas case syntax::NodeKind::ParenExpression:
801e19165bSEduardo Caldas return new (A.getAllocator()) syntax::ParenExpression;
811e19165bSEduardo Caldas case syntax::NodeKind::ThisExpression:
821e19165bSEduardo Caldas return new (A.getAllocator()) syntax::ThisExpression;
831e19165bSEduardo Caldas case syntax::NodeKind::IntegerLiteralExpression:
841e19165bSEduardo Caldas return new (A.getAllocator()) syntax::IntegerLiteralExpression;
851e19165bSEduardo Caldas case syntax::NodeKind::CharacterLiteralExpression:
861e19165bSEduardo Caldas return new (A.getAllocator()) syntax::CharacterLiteralExpression;
871e19165bSEduardo Caldas case syntax::NodeKind::FloatingLiteralExpression:
881e19165bSEduardo Caldas return new (A.getAllocator()) syntax::FloatingLiteralExpression;
891e19165bSEduardo Caldas case syntax::NodeKind::StringLiteralExpression:
901e19165bSEduardo Caldas return new (A.getAllocator()) syntax::StringLiteralExpression;
911e19165bSEduardo Caldas case syntax::NodeKind::BoolLiteralExpression:
921e19165bSEduardo Caldas return new (A.getAllocator()) syntax::BoolLiteralExpression;
931e19165bSEduardo Caldas case syntax::NodeKind::CxxNullPtrExpression:
941e19165bSEduardo Caldas return new (A.getAllocator()) syntax::CxxNullPtrExpression;
951e19165bSEduardo Caldas case syntax::NodeKind::IntegerUserDefinedLiteralExpression:
961e19165bSEduardo Caldas return new (A.getAllocator()) syntax::IntegerUserDefinedLiteralExpression;
971e19165bSEduardo Caldas case syntax::NodeKind::FloatUserDefinedLiteralExpression:
981e19165bSEduardo Caldas return new (A.getAllocator()) syntax::FloatUserDefinedLiteralExpression;
991e19165bSEduardo Caldas case syntax::NodeKind::CharUserDefinedLiteralExpression:
1001e19165bSEduardo Caldas return new (A.getAllocator()) syntax::CharUserDefinedLiteralExpression;
1011e19165bSEduardo Caldas case syntax::NodeKind::StringUserDefinedLiteralExpression:
1021e19165bSEduardo Caldas return new (A.getAllocator()) syntax::StringUserDefinedLiteralExpression;
1031e19165bSEduardo Caldas case syntax::NodeKind::PrefixUnaryOperatorExpression:
1041e19165bSEduardo Caldas return new (A.getAllocator()) syntax::PrefixUnaryOperatorExpression;
1051e19165bSEduardo Caldas case syntax::NodeKind::PostfixUnaryOperatorExpression:
1061e19165bSEduardo Caldas return new (A.getAllocator()) syntax::PostfixUnaryOperatorExpression;
1071e19165bSEduardo Caldas case syntax::NodeKind::BinaryOperatorExpression:
1081e19165bSEduardo Caldas return new (A.getAllocator()) syntax::BinaryOperatorExpression;
1091e19165bSEduardo Caldas case syntax::NodeKind::UnqualifiedId:
1101e19165bSEduardo Caldas return new (A.getAllocator()) syntax::UnqualifiedId;
1111e19165bSEduardo Caldas case syntax::NodeKind::IdExpression:
1121e19165bSEduardo Caldas return new (A.getAllocator()) syntax::IdExpression;
1131e19165bSEduardo Caldas case syntax::NodeKind::CallExpression:
1141e19165bSEduardo Caldas return new (A.getAllocator()) syntax::CallExpression;
1151e19165bSEduardo Caldas case syntax::NodeKind::UnknownStatement:
1161e19165bSEduardo Caldas return new (A.getAllocator()) syntax::UnknownStatement;
1171e19165bSEduardo Caldas case syntax::NodeKind::DeclarationStatement:
1181e19165bSEduardo Caldas return new (A.getAllocator()) syntax::DeclarationStatement;
1191e19165bSEduardo Caldas case syntax::NodeKind::EmptyStatement:
1201e19165bSEduardo Caldas return new (A.getAllocator()) syntax::EmptyStatement;
1211e19165bSEduardo Caldas case syntax::NodeKind::SwitchStatement:
1221e19165bSEduardo Caldas return new (A.getAllocator()) syntax::SwitchStatement;
1231e19165bSEduardo Caldas case syntax::NodeKind::CaseStatement:
1241e19165bSEduardo Caldas return new (A.getAllocator()) syntax::CaseStatement;
1251e19165bSEduardo Caldas case syntax::NodeKind::DefaultStatement:
1261e19165bSEduardo Caldas return new (A.getAllocator()) syntax::DefaultStatement;
1271e19165bSEduardo Caldas case syntax::NodeKind::IfStatement:
1281e19165bSEduardo Caldas return new (A.getAllocator()) syntax::IfStatement;
1291e19165bSEduardo Caldas case syntax::NodeKind::ForStatement:
1301e19165bSEduardo Caldas return new (A.getAllocator()) syntax::ForStatement;
1311e19165bSEduardo Caldas case syntax::NodeKind::WhileStatement:
1321e19165bSEduardo Caldas return new (A.getAllocator()) syntax::WhileStatement;
1331e19165bSEduardo Caldas case syntax::NodeKind::ContinueStatement:
1341e19165bSEduardo Caldas return new (A.getAllocator()) syntax::ContinueStatement;
1351e19165bSEduardo Caldas case syntax::NodeKind::BreakStatement:
1361e19165bSEduardo Caldas return new (A.getAllocator()) syntax::BreakStatement;
1371e19165bSEduardo Caldas case syntax::NodeKind::ReturnStatement:
1381e19165bSEduardo Caldas return new (A.getAllocator()) syntax::ReturnStatement;
1391e19165bSEduardo Caldas case syntax::NodeKind::RangeBasedForStatement:
1401e19165bSEduardo Caldas return new (A.getAllocator()) syntax::RangeBasedForStatement;
1411e19165bSEduardo Caldas case syntax::NodeKind::ExpressionStatement:
1421e19165bSEduardo Caldas return new (A.getAllocator()) syntax::ExpressionStatement;
1431e19165bSEduardo Caldas case syntax::NodeKind::CompoundStatement:
1441e19165bSEduardo Caldas return new (A.getAllocator()) syntax::CompoundStatement;
1451e19165bSEduardo Caldas case syntax::NodeKind::UnknownDeclaration:
1461e19165bSEduardo Caldas return new (A.getAllocator()) syntax::UnknownDeclaration;
1471e19165bSEduardo Caldas case syntax::NodeKind::EmptyDeclaration:
1481e19165bSEduardo Caldas return new (A.getAllocator()) syntax::EmptyDeclaration;
1491e19165bSEduardo Caldas case syntax::NodeKind::StaticAssertDeclaration:
1501e19165bSEduardo Caldas return new (A.getAllocator()) syntax::StaticAssertDeclaration;
1511e19165bSEduardo Caldas case syntax::NodeKind::LinkageSpecificationDeclaration:
1521e19165bSEduardo Caldas return new (A.getAllocator()) syntax::LinkageSpecificationDeclaration;
1531e19165bSEduardo Caldas case syntax::NodeKind::SimpleDeclaration:
1541e19165bSEduardo Caldas return new (A.getAllocator()) syntax::SimpleDeclaration;
1551e19165bSEduardo Caldas case syntax::NodeKind::TemplateDeclaration:
1561e19165bSEduardo Caldas return new (A.getAllocator()) syntax::TemplateDeclaration;
1571e19165bSEduardo Caldas case syntax::NodeKind::ExplicitTemplateInstantiation:
1581e19165bSEduardo Caldas return new (A.getAllocator()) syntax::ExplicitTemplateInstantiation;
1591e19165bSEduardo Caldas case syntax::NodeKind::NamespaceDefinition:
1601e19165bSEduardo Caldas return new (A.getAllocator()) syntax::NamespaceDefinition;
1611e19165bSEduardo Caldas case syntax::NodeKind::NamespaceAliasDefinition:
1621e19165bSEduardo Caldas return new (A.getAllocator()) syntax::NamespaceAliasDefinition;
1631e19165bSEduardo Caldas case syntax::NodeKind::UsingNamespaceDirective:
1641e19165bSEduardo Caldas return new (A.getAllocator()) syntax::UsingNamespaceDirective;
1651e19165bSEduardo Caldas case syntax::NodeKind::UsingDeclaration:
1661e19165bSEduardo Caldas return new (A.getAllocator()) syntax::UsingDeclaration;
1671e19165bSEduardo Caldas case syntax::NodeKind::TypeAliasDeclaration:
1681e19165bSEduardo Caldas return new (A.getAllocator()) syntax::TypeAliasDeclaration;
1691e19165bSEduardo Caldas case syntax::NodeKind::SimpleDeclarator:
1701e19165bSEduardo Caldas return new (A.getAllocator()) syntax::SimpleDeclarator;
1711e19165bSEduardo Caldas case syntax::NodeKind::ParenDeclarator:
1721e19165bSEduardo Caldas return new (A.getAllocator()) syntax::ParenDeclarator;
1731e19165bSEduardo Caldas case syntax::NodeKind::ArraySubscript:
1741e19165bSEduardo Caldas return new (A.getAllocator()) syntax::ArraySubscript;
1751e19165bSEduardo Caldas case syntax::NodeKind::TrailingReturnType:
1761e19165bSEduardo Caldas return new (A.getAllocator()) syntax::TrailingReturnType;
1771e19165bSEduardo Caldas case syntax::NodeKind::ParametersAndQualifiers:
1781e19165bSEduardo Caldas return new (A.getAllocator()) syntax::ParametersAndQualifiers;
1791e19165bSEduardo Caldas case syntax::NodeKind::MemberPointer:
1801e19165bSEduardo Caldas return new (A.getAllocator()) syntax::MemberPointer;
1811e19165bSEduardo Caldas case syntax::NodeKind::GlobalNameSpecifier:
1821e19165bSEduardo Caldas return new (A.getAllocator()) syntax::GlobalNameSpecifier;
1831e19165bSEduardo Caldas case syntax::NodeKind::DecltypeNameSpecifier:
1841e19165bSEduardo Caldas return new (A.getAllocator()) syntax::DecltypeNameSpecifier;
1851e19165bSEduardo Caldas case syntax::NodeKind::IdentifierNameSpecifier:
1861e19165bSEduardo Caldas return new (A.getAllocator()) syntax::IdentifierNameSpecifier;
1871e19165bSEduardo Caldas case syntax::NodeKind::SimpleTemplateNameSpecifier:
1881e19165bSEduardo Caldas return new (A.getAllocator()) syntax::SimpleTemplateNameSpecifier;
1891e19165bSEduardo Caldas case syntax::NodeKind::NestedNameSpecifier:
1901e19165bSEduardo Caldas return new (A.getAllocator()) syntax::NestedNameSpecifier;
1911e19165bSEduardo Caldas case syntax::NodeKind::MemberExpression:
1921e19165bSEduardo Caldas return new (A.getAllocator()) syntax::MemberExpression;
1931e19165bSEduardo Caldas case syntax::NodeKind::CallArguments:
1941e19165bSEduardo Caldas return new (A.getAllocator()) syntax::CallArguments;
1951e19165bSEduardo Caldas case syntax::NodeKind::ParameterDeclarationList:
1961e19165bSEduardo Caldas return new (A.getAllocator()) syntax::ParameterDeclarationList;
1975011d431SEduardo Caldas case syntax::NodeKind::DeclaratorList:
1985011d431SEduardo Caldas return new (A.getAllocator()) syntax::DeclaratorList;
1991e19165bSEduardo Caldas }
2001e19165bSEduardo Caldas llvm_unreachable("unknown node kind");
2011e19165bSEduardo Caldas }
2021e19165bSEduardo Caldas } // namespace
2031e19165bSEduardo Caldas
createTree(syntax::Arena & A,ArrayRef<std::pair<syntax::Node *,syntax::NodeRole>> Children,syntax::NodeKind K)2047c37b82fSEduardo Caldas syntax::Tree *clang::syntax::createTree(
2057c37b82fSEduardo Caldas syntax::Arena &A,
2061dc7836aSEduardo Caldas ArrayRef<std::pair<syntax::Node *, syntax::NodeRole>> Children,
2077c37b82fSEduardo Caldas syntax::NodeKind K) {
2081e19165bSEduardo Caldas auto *T = allocateTree(A, K);
2097c37b82fSEduardo Caldas FactoryImpl::setCanModify(T);
21023657d9cSEduardo Caldas for (const auto &Child : Children)
21123657d9cSEduardo Caldas FactoryImpl::appendChildLowLevel(T, Child.first, Child.second);
2127c37b82fSEduardo Caldas
2137c37b82fSEduardo Caldas T->assertInvariants();
2147c37b82fSEduardo Caldas return T;
2157c37b82fSEduardo Caldas }
2167c37b82fSEduardo Caldas
deepCopyExpandingMacros(syntax::Arena & A,TokenBufferTokenManager & TBTM,const syntax::Node * N)21766bcb143SEduardo Caldas syntax::Node *clang::syntax::deepCopyExpandingMacros(syntax::Arena &A,
218*263dcf45SHaojian Wu TokenBufferTokenManager &TBTM,
21966bcb143SEduardo Caldas const syntax::Node *N) {
2204a5cc389SEduardo Caldas if (const auto *L = dyn_cast<syntax::Leaf>(N))
22166bcb143SEduardo Caldas // `L->getToken()` gives us the expanded token, thus we implicitly expand
22266bcb143SEduardo Caldas // any macros here.
223*263dcf45SHaojian Wu return createLeaf(A, TBTM, TBTM.getToken(L->getTokenKey())->kind(),
224*263dcf45SHaojian Wu TBTM.getText(L->getTokenKey()));
2254a5cc389SEduardo Caldas
2264a5cc389SEduardo Caldas const auto *T = cast<syntax::Tree>(N);
2274a5cc389SEduardo Caldas std::vector<std::pair<syntax::Node *, syntax::NodeRole>> Children;
2284a5cc389SEduardo Caldas for (const auto *Child = T->getFirstChild(); Child;
2294a5cc389SEduardo Caldas Child = Child->getNextSibling())
230*263dcf45SHaojian Wu Children.push_back({deepCopyExpandingMacros(A, TBTM, Child), Child->getRole()});
2314a5cc389SEduardo Caldas
2324a5cc389SEduardo Caldas return createTree(A, Children, N->getKind());
2334a5cc389SEduardo Caldas }
2344a5cc389SEduardo Caldas
createEmptyStatement(syntax::Arena & A,TokenBufferTokenManager & TBTM)235*263dcf45SHaojian Wu syntax::EmptyStatement *clang::syntax::createEmptyStatement(syntax::Arena &A, TokenBufferTokenManager &TBTM) {
2361e19165bSEduardo Caldas return cast<EmptyStatement>(
237*263dcf45SHaojian Wu createTree(A, {{createLeaf(A, TBTM, tok::semi), NodeRole::Unknown}},
2381e19165bSEduardo Caldas NodeKind::EmptyStatement));
2391ad15046SIlya Biryukov }
240