brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.0 KiB · 39c1995 Raw
240 lines · cpp
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-exception6//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 it39// 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} // namespace203 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 expand222    // 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