1 //===- Synthesis.cpp ------------------------------------------*- 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 #include "clang/Basic/TokenKinds.h" 9 #include "clang/Tooling/Syntax/BuildTree.h" 10 #include "clang/Tooling/Syntax/Tree.h" 11 12 using namespace clang; 13 14 /// Exposes private syntax tree APIs required to implement node synthesis. 15 /// Should not be used for anything else. 16 class clang::syntax::FactoryImpl { 17 public: 18 static void setCanModify(syntax::Node *N) { N->CanModify = true; } 19 20 static void prependChildLowLevel(syntax::Tree *T, syntax::Node *Child, 21 syntax::NodeRole R) { 22 T->prependChildLowLevel(Child, R); 23 } 24 25 static std::pair<FileID, ArrayRef<Token>> 26 lexBuffer(syntax::Arena &A, std::unique_ptr<llvm::MemoryBuffer> Buffer) { 27 return A.lexBuffer(std::move(Buffer)); 28 } 29 }; 30 31 syntax::Leaf *clang::syntax::createLeaf(syntax::Arena &A, tok::TokenKind K, 32 StringRef Spelling) { 33 auto Tokens = 34 FactoryImpl::lexBuffer(A, llvm::MemoryBuffer::getMemBuffer(Spelling)) 35 .second; 36 assert(Tokens.size() == 1); 37 assert(Tokens.front().kind() == K && 38 "spelling is not lexed into the expected kind of token"); 39 40 auto *Leaf = new (A.getAllocator()) syntax::Leaf(Tokens.begin()); 41 syntax::FactoryImpl::setCanModify(Leaf); 42 Leaf->assertInvariants(); 43 return Leaf; 44 } 45 46 syntax::Leaf *clang::syntax::createLeaf(syntax::Arena &A, tok::TokenKind K) { 47 const auto *Spelling = tok::getPunctuatorSpelling(K); 48 if (!Spelling) 49 Spelling = tok::getKeywordSpelling(K); 50 assert(Spelling && 51 "Cannot infer the spelling of the token from its token kind."); 52 return createLeaf(A, K, Spelling); 53 } 54 55 syntax::Tree *clang::syntax::createTree( 56 syntax::Arena &A, 57 std::vector<std::pair<syntax::Node *, syntax::NodeRole>> Children, 58 syntax::NodeKind K) { 59 auto *T = new (A.getAllocator()) syntax::Tree(K); 60 FactoryImpl::setCanModify(T); 61 for (auto ChildIt = Children.rbegin(); ChildIt != Children.rend(); 62 std::advance(ChildIt, 1)) 63 FactoryImpl::prependChildLowLevel(T, ChildIt->first, ChildIt->second); 64 65 T->assertInvariants(); 66 return T; 67 } 68 69 syntax::EmptyStatement *clang::syntax::createEmptyStatement(syntax::Arena &A) { 70 auto *S = new (A.getAllocator()) syntax::EmptyStatement; 71 FactoryImpl::setCanModify(S); 72 FactoryImpl::prependChildLowLevel(S, createLeaf(A, tok::semi), 73 NodeRole::Unknown); 74 S->assertInvariants(); 75 return S; 76 } 77