Coverage Report

Created: 2022-07-16 07:03

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