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