aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/Tooling/Syntax/Synthesis.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/Tooling/Syntax/Synthesis.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/Tooling/Syntax/Synthesis.cpp224
1 files changed, 205 insertions, 19 deletions
diff --git a/contrib/llvm-project/clang/lib/Tooling/Syntax/Synthesis.cpp b/contrib/llvm-project/clang/lib/Tooling/Syntax/Synthesis.cpp
index aa01a34c761f..ef6492882be6 100644
--- a/contrib/llvm-project/clang/lib/Tooling/Syntax/Synthesis.cpp
+++ b/contrib/llvm-project/clang/lib/Tooling/Syntax/Synthesis.cpp
@@ -5,13 +5,15 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
+#include "clang/Basic/TokenKinds.h"
#include "clang/Tooling/Syntax/BuildTree.h"
+#include "clang/Tooling/Syntax/Tree.h"
using namespace clang;
/// Exposes private syntax tree APIs required to implement node synthesis.
/// Should not be used for anything else.
-class syntax::FactoryImpl {
+class clang::syntax::FactoryImpl {
public:
static void setCanModify(syntax::Node *N) { N->CanModify = true; }
@@ -19,27 +21,211 @@ public:
syntax::NodeRole R) {
T->prependChildLowLevel(Child, R);
}
+ static void appendChildLowLevel(syntax::Tree *T, syntax::Node *Child,
+ syntax::NodeRole R) {
+ T->appendChildLowLevel(Child, R);
+ }
+
+ static std::pair<FileID, ArrayRef<Token>>
+ lexBuffer(syntax::Arena &A, std::unique_ptr<llvm::MemoryBuffer> Buffer) {
+ return A.lexBuffer(std::move(Buffer));
+ }
};
-clang::syntax::Leaf *syntax::createPunctuation(clang::syntax::Arena &A,
- clang::tok::TokenKind K) {
- auto Tokens = A.lexBuffer(llvm::MemoryBuffer::getMemBuffer(
- clang::tok::getPunctuatorSpelling(K)))
- .second;
+// FIXME: `createLeaf` is based on `syntax::tokenize` internally, as such it
+// doesn't support digraphs or line continuations.
+syntax::Leaf *clang::syntax::createLeaf(syntax::Arena &A, tok::TokenKind K,
+ StringRef Spelling) {
+ auto Tokens =
+ FactoryImpl::lexBuffer(A, llvm::MemoryBuffer::getMemBufferCopy(Spelling))
+ .second;
assert(Tokens.size() == 1);
- assert(Tokens.front().kind() == K);
- auto *L = new (A.allocator()) clang::syntax::Leaf(Tokens.begin());
- FactoryImpl::setCanModify(L);
- L->assertInvariants();
- return L;
+ assert(Tokens.front().kind() == K &&
+ "spelling is not lexed into the expected kind of token");
+
+ auto *Leaf = new (A.getAllocator()) syntax::Leaf(Tokens.begin());
+ syntax::FactoryImpl::setCanModify(Leaf);
+ Leaf->assertInvariants();
+ return Leaf;
+}
+
+syntax::Leaf *clang::syntax::createLeaf(syntax::Arena &A, tok::TokenKind K) {
+ const auto *Spelling = tok::getPunctuatorSpelling(K);
+ if (!Spelling)
+ Spelling = tok::getKeywordSpelling(K);
+ assert(Spelling &&
+ "Cannot infer the spelling of the token from its token kind.");
+ return createLeaf(A, K, Spelling);
+}
+
+namespace {
+// Allocates the concrete syntax `Tree` according to its `NodeKind`.
+syntax::Tree *allocateTree(syntax::Arena &A, syntax::NodeKind Kind) {
+ switch (Kind) {
+ case syntax::NodeKind::Leaf:
+ assert(false);
+ break;
+ case syntax::NodeKind::TranslationUnit:
+ return new (A.getAllocator()) syntax::TranslationUnit;
+ case syntax::NodeKind::UnknownExpression:
+ return new (A.getAllocator()) syntax::UnknownExpression;
+ case syntax::NodeKind::ParenExpression:
+ return new (A.getAllocator()) syntax::ParenExpression;
+ case syntax::NodeKind::ThisExpression:
+ return new (A.getAllocator()) syntax::ThisExpression;
+ case syntax::NodeKind::IntegerLiteralExpression:
+ return new (A.getAllocator()) syntax::IntegerLiteralExpression;
+ case syntax::NodeKind::CharacterLiteralExpression:
+ return new (A.getAllocator()) syntax::CharacterLiteralExpression;
+ case syntax::NodeKind::FloatingLiteralExpression:
+ return new (A.getAllocator()) syntax::FloatingLiteralExpression;
+ case syntax::NodeKind::StringLiteralExpression:
+ return new (A.getAllocator()) syntax::StringLiteralExpression;
+ case syntax::NodeKind::BoolLiteralExpression:
+ return new (A.getAllocator()) syntax::BoolLiteralExpression;
+ case syntax::NodeKind::CxxNullPtrExpression:
+ return new (A.getAllocator()) syntax::CxxNullPtrExpression;
+ case syntax::NodeKind::IntegerUserDefinedLiteralExpression:
+ return new (A.getAllocator()) syntax::IntegerUserDefinedLiteralExpression;
+ case syntax::NodeKind::FloatUserDefinedLiteralExpression:
+ return new (A.getAllocator()) syntax::FloatUserDefinedLiteralExpression;
+ case syntax::NodeKind::CharUserDefinedLiteralExpression:
+ return new (A.getAllocator()) syntax::CharUserDefinedLiteralExpression;
+ case syntax::NodeKind::StringUserDefinedLiteralExpression:
+ return new (A.getAllocator()) syntax::StringUserDefinedLiteralExpression;
+ case syntax::NodeKind::PrefixUnaryOperatorExpression:
+ return new (A.getAllocator()) syntax::PrefixUnaryOperatorExpression;
+ case syntax::NodeKind::PostfixUnaryOperatorExpression:
+ return new (A.getAllocator()) syntax::PostfixUnaryOperatorExpression;
+ case syntax::NodeKind::BinaryOperatorExpression:
+ return new (A.getAllocator()) syntax::BinaryOperatorExpression;
+ case syntax::NodeKind::UnqualifiedId:
+ return new (A.getAllocator()) syntax::UnqualifiedId;
+ case syntax::NodeKind::IdExpression:
+ return new (A.getAllocator()) syntax::IdExpression;
+ case syntax::NodeKind::CallExpression:
+ return new (A.getAllocator()) syntax::CallExpression;
+ case syntax::NodeKind::UnknownStatement:
+ return new (A.getAllocator()) syntax::UnknownStatement;
+ case syntax::NodeKind::DeclarationStatement:
+ return new (A.getAllocator()) syntax::DeclarationStatement;
+ case syntax::NodeKind::EmptyStatement:
+ return new (A.getAllocator()) syntax::EmptyStatement;
+ case syntax::NodeKind::SwitchStatement:
+ return new (A.getAllocator()) syntax::SwitchStatement;
+ case syntax::NodeKind::CaseStatement:
+ return new (A.getAllocator()) syntax::CaseStatement;
+ case syntax::NodeKind::DefaultStatement:
+ return new (A.getAllocator()) syntax::DefaultStatement;
+ case syntax::NodeKind::IfStatement:
+ return new (A.getAllocator()) syntax::IfStatement;
+ case syntax::NodeKind::ForStatement:
+ return new (A.getAllocator()) syntax::ForStatement;
+ case syntax::NodeKind::WhileStatement:
+ return new (A.getAllocator()) syntax::WhileStatement;
+ case syntax::NodeKind::ContinueStatement:
+ return new (A.getAllocator()) syntax::ContinueStatement;
+ case syntax::NodeKind::BreakStatement:
+ return new (A.getAllocator()) syntax::BreakStatement;
+ case syntax::NodeKind::ReturnStatement:
+ return new (A.getAllocator()) syntax::ReturnStatement;
+ case syntax::NodeKind::RangeBasedForStatement:
+ return new (A.getAllocator()) syntax::RangeBasedForStatement;
+ case syntax::NodeKind::ExpressionStatement:
+ return new (A.getAllocator()) syntax::ExpressionStatement;
+ case syntax::NodeKind::CompoundStatement:
+ return new (A.getAllocator()) syntax::CompoundStatement;
+ case syntax::NodeKind::UnknownDeclaration:
+ return new (A.getAllocator()) syntax::UnknownDeclaration;
+ case syntax::NodeKind::EmptyDeclaration:
+ return new (A.getAllocator()) syntax::EmptyDeclaration;
+ case syntax::NodeKind::StaticAssertDeclaration:
+ return new (A.getAllocator()) syntax::StaticAssertDeclaration;
+ case syntax::NodeKind::LinkageSpecificationDeclaration:
+ return new (A.getAllocator()) syntax::LinkageSpecificationDeclaration;
+ case syntax::NodeKind::SimpleDeclaration:
+ return new (A.getAllocator()) syntax::SimpleDeclaration;
+ case syntax::NodeKind::TemplateDeclaration:
+ return new (A.getAllocator()) syntax::TemplateDeclaration;
+ case syntax::NodeKind::ExplicitTemplateInstantiation:
+ return new (A.getAllocator()) syntax::ExplicitTemplateInstantiation;
+ case syntax::NodeKind::NamespaceDefinition:
+ return new (A.getAllocator()) syntax::NamespaceDefinition;
+ case syntax::NodeKind::NamespaceAliasDefinition:
+ return new (A.getAllocator()) syntax::NamespaceAliasDefinition;
+ case syntax::NodeKind::UsingNamespaceDirective:
+ return new (A.getAllocator()) syntax::UsingNamespaceDirective;
+ case syntax::NodeKind::UsingDeclaration:
+ return new (A.getAllocator()) syntax::UsingDeclaration;
+ case syntax::NodeKind::TypeAliasDeclaration:
+ return new (A.getAllocator()) syntax::TypeAliasDeclaration;
+ case syntax::NodeKind::SimpleDeclarator:
+ return new (A.getAllocator()) syntax::SimpleDeclarator;
+ case syntax::NodeKind::ParenDeclarator:
+ return new (A.getAllocator()) syntax::ParenDeclarator;
+ case syntax::NodeKind::ArraySubscript:
+ return new (A.getAllocator()) syntax::ArraySubscript;
+ case syntax::NodeKind::TrailingReturnType:
+ return new (A.getAllocator()) syntax::TrailingReturnType;
+ case syntax::NodeKind::ParametersAndQualifiers:
+ return new (A.getAllocator()) syntax::ParametersAndQualifiers;
+ case syntax::NodeKind::MemberPointer:
+ return new (A.getAllocator()) syntax::MemberPointer;
+ case syntax::NodeKind::GlobalNameSpecifier:
+ return new (A.getAllocator()) syntax::GlobalNameSpecifier;
+ case syntax::NodeKind::DecltypeNameSpecifier:
+ return new (A.getAllocator()) syntax::DecltypeNameSpecifier;
+ case syntax::NodeKind::IdentifierNameSpecifier:
+ return new (A.getAllocator()) syntax::IdentifierNameSpecifier;
+ case syntax::NodeKind::SimpleTemplateNameSpecifier:
+ return new (A.getAllocator()) syntax::SimpleTemplateNameSpecifier;
+ case syntax::NodeKind::NestedNameSpecifier:
+ return new (A.getAllocator()) syntax::NestedNameSpecifier;
+ case syntax::NodeKind::MemberExpression:
+ return new (A.getAllocator()) syntax::MemberExpression;
+ case syntax::NodeKind::CallArguments:
+ return new (A.getAllocator()) syntax::CallArguments;
+ case syntax::NodeKind::ParameterDeclarationList:
+ return new (A.getAllocator()) syntax::ParameterDeclarationList;
+ case syntax::NodeKind::DeclaratorList:
+ return new (A.getAllocator()) syntax::DeclaratorList;
+ }
+ llvm_unreachable("unknown node kind");
+}
+} // namespace
+
+syntax::Tree *clang::syntax::createTree(
+ syntax::Arena &A,
+ ArrayRef<std::pair<syntax::Node *, syntax::NodeRole>> Children,
+ syntax::NodeKind K) {
+ auto *T = allocateTree(A, K);
+ FactoryImpl::setCanModify(T);
+ for (const auto &Child : Children)
+ FactoryImpl::appendChildLowLevel(T, Child.first, Child.second);
+
+ T->assertInvariants();
+ return T;
+}
+
+syntax::Node *clang::syntax::deepCopyExpandingMacros(syntax::Arena &A,
+ const syntax::Node *N) {
+ if (const auto *L = dyn_cast<syntax::Leaf>(N))
+ // `L->getToken()` gives us the expanded token, thus we implicitly expand
+ // any macros here.
+ return createLeaf(A, L->getToken()->kind(),
+ L->getToken()->text(A.getSourceManager()));
+
+ const auto *T = cast<syntax::Tree>(N);
+ std::vector<std::pair<syntax::Node *, syntax::NodeRole>> Children;
+ for (const auto *Child = T->getFirstChild(); Child;
+ Child = Child->getNextSibling())
+ Children.push_back({deepCopyExpandingMacros(A, Child), Child->getRole()});
+
+ return createTree(A, Children, N->getKind());
}
-clang::syntax::EmptyStatement *
-syntax::createEmptyStatement(clang::syntax::Arena &A) {
- auto *S = new (A.allocator()) clang::syntax::EmptyStatement;
- FactoryImpl::setCanModify(S);
- FactoryImpl::prependChildLowLevel(S, createPunctuation(A, clang::tok::semi),
- NodeRole::Unknown);
- S->assertInvariants();
- return S;
+syntax::EmptyStatement *clang::syntax::createEmptyStatement(syntax::Arena &A) {
+ return cast<EmptyStatement>(
+ createTree(A, {{createLeaf(A, tok::semi), NodeRole::Unknown}},
+ NodeKind::EmptyStatement));
}