| 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 | |
| 14 | using namespace clang; |
| 15 | |
| 16 | /// Exposes private syntax tree APIs required to implement node synthesis. |
| 17 | /// Should not be used for anything else. |
| 18 | class clang::syntax::FactoryImpl { |
| 19 | public: |
| 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, Role: R); |
| 25 | } |
| 26 | static void appendChildLowLevel(syntax::Tree *T, syntax::Node *Child, |
| 27 | syntax::NodeRole R) { |
| 28 | T->appendChildLowLevel(Child, Role: 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(Buffer: 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. |
| 40 | syntax::Leaf *clang::syntax::createLeaf(syntax::Arena &A, |
| 41 | TokenBufferTokenManager &TBTM, |
| 42 | tok::TokenKind K, StringRef Spelling) { |
| 43 | auto Tokens = |
| 44 | FactoryImpl::lexBuffer(TBTM, Buffer: llvm::MemoryBuffer::getMemBufferCopy(InputData: 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 | |
| 57 | syntax::Leaf *clang::syntax::createLeaf(syntax::Arena &A, |
| 58 | TokenBufferTokenManager &TBTM, |
| 59 | tok::TokenKind K) { |
| 60 | const auto *Spelling = tok::getPunctuatorSpelling(Kind: K); |
| 61 | if (!Spelling) |
| 62 | Spelling = tok::getKeywordSpelling(Kind: 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 | |
| 68 | namespace { |
| 69 | // Allocates the concrete syntax `Tree` according to its `NodeKind`. |
| 70 | syntax::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 | |
| 204 | syntax::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, Kind: K); |
| 209 | FactoryImpl::setCanModify(T); |
| 210 | for (const auto &Child : Children) |
| 211 | FactoryImpl::appendChildLowLevel(T, Child: Child.first, R: Child.second); |
| 212 | |
| 213 | T->assertInvariants(); |
| 214 | return T; |
| 215 | } |
| 216 | |
| 217 | syntax::Node *clang::syntax::deepCopyExpandingMacros(syntax::Arena &A, |
| 218 | TokenBufferTokenManager &TBTM, |
| 219 | const syntax::Node *N) { |
| 220 | if (const auto *L = dyn_cast<syntax::Leaf>(Val: N)) |
| 221 | // `L->getToken()` gives us the expanded token, thus we implicitly expand |
| 222 | // any macros here. |
| 223 | return createLeaf(A, TBTM, K: TBTM.getToken(I: L->getTokenKey())->kind(), |
| 224 | Spelling: TBTM.getText(I: L->getTokenKey())); |
| 225 | |
| 226 | const auto *T = cast<syntax::Tree>(Val: 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(x: {deepCopyExpandingMacros(A, TBTM, N: Child), Child->getRole()}); |
| 231 | |
| 232 | return createTree(A, Children, K: N->getKind()); |
| 233 | } |
| 234 | |
| 235 | syntax::EmptyStatement *clang::syntax::createEmptyStatement(syntax::Arena &A, TokenBufferTokenManager &TBTM) { |
| 236 | return cast<EmptyStatement>( |
| 237 | Val: createTree(A, Children: {{createLeaf(A, TBTM, K: tok::semi), NodeRole::Unknown}}, |
| 238 | K: NodeKind::EmptyStatement)); |
| 239 | } |
| 240 | |