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