Coverage Report

Created: 2020-11-24 06:42

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/utils/TableGen/ASTTableGen.h
Line
Count
Source (jump to first uncovered line)
1
//=== ASTTableGen.h - Common definitions for AST node tablegen --*- 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
9
#ifndef CLANG_AST_TABLEGEN_H
10
#define CLANG_AST_TABLEGEN_H
11
12
#include "llvm/TableGen/Record.h"
13
#include "llvm/ADT/STLExtras.h"
14
15
// These are spellings in the tblgen files.
16
17
#define HasPropertiesClassName "HasProperties"
18
19
// ASTNodes and their common fields.  `Base` is actually defined
20
// in subclasses, but it's still common across the hierarchies.
21
0
#define ASTNodeClassName "ASTNode"
22
224
#define BaseFieldName "Base"
23
0
#define AbstractFieldName "Abstract"
24
25
// Comment node hierarchy.
26
0
#define CommentNodeClassName "CommentNode"
27
28
// Decl node hierarchy.
29
1
#define DeclNodeClassName "DeclNode"
30
0
#define DeclContextNodeClassName "DeclContext"
31
32
// Stmt node hierarchy.
33
0
#define StmtNodeClassName "StmtNode"
34
35
// Type node hierarchy.
36
0
#define TypeNodeClassName "TypeNode"
37
0
#define AlwaysDependentClassName "AlwaysDependent"
38
0
#define NeverCanonicalClassName "NeverCanonical"
39
0
#define NeverCanonicalUnlessDependentClassName "NeverCanonicalUnlessDependent"
40
0
#define LeafTypeClassName "LeafType"
41
42
// Cases of various non-ASTNode structured types like DeclarationName.
43
0
#define TypeKindClassName "PropertyTypeKind"
44
0
#define KindTypeFieldName "KindType"
45
0
#define KindPropertyNameFieldName "KindPropertyName"
46
0
#define TypeCaseClassName "PropertyTypeCase"
47
48
// Properties of AST nodes.
49
0
#define PropertyClassName "Property"
50
0
#define ClassFieldName "Class"
51
0
#define NameFieldName "Name"
52
0
#define TypeFieldName "Type"
53
0
#define ReadFieldName "Read"
54
55
// Types of properties.
56
0
#define PropertyTypeClassName "PropertyType"
57
0
#define CXXTypeNameFieldName "CXXName"
58
0
#define PassByReferenceFieldName "PassByReference"
59
0
#define ConstWhenWritingFieldName "ConstWhenWriting"
60
0
#define ConditionalCodeFieldName "Conditional"
61
0
#define PackOptionalCodeFieldName "PackOptional"
62
0
#define UnpackOptionalCodeFieldName "UnpackOptional"
63
0
#define BufferElementTypesFieldName "BufferElementTypes"
64
0
#define ArrayTypeClassName "Array"
65
0
#define ArrayElementTypeFieldName "Element"
66
0
#define OptionalTypeClassName "Optional"
67
0
#define OptionalElementTypeFieldName "Element"
68
0
#define SubclassPropertyTypeClassName "SubclassPropertyType"
69
0
#define SubclassBaseTypeFieldName "Base"
70
0
#define SubclassClassNameFieldName "SubclassName"
71
0
#define EnumPropertyTypeClassName "EnumPropertyType"
72
73
// Write helper rules.
74
0
#define ReadHelperRuleClassName "ReadHelper"
75
0
#define HelperCodeFieldName "Code"
76
77
// Creation rules.
78
0
#define CreationRuleClassName "Creator"
79
0
#define CreateFieldName "Create"
80
81
// Override rules.
82
0
#define OverrideRuleClassName "Override"
83
0
#define IgnoredPropertiesFieldName "IgnoredProperties"
84
85
namespace clang {
86
namespace tblgen {
87
88
class WrappedRecord {
89
  llvm::Record *Record;
90
91
protected:
92
0
  WrappedRecord(llvm::Record *record = nullptr) : Record(record) {}
93
94
0
  llvm::Record *get() const {
95
0
    assert(Record && "accessing null record");
96
0
    return Record;
97
0
  }
98
99
public:
100
0
  llvm::Record *getRecord() const { return Record; }
101
102
0
  explicit operator bool() const { return Record != nullptr; }
103
104
0
  llvm::ArrayRef<llvm::SMLoc> getLoc() const {
105
0
    return get()->getLoc();
106
0
  }
107
108
  /// Does the node inherit from the given TableGen class?
109
0
  bool isSubClassOf(llvm::StringRef className) const {
110
0
    return get()->isSubClassOf(className);
111
0
  }
112
113
  template <class NodeClass>
114
0
  NodeClass getAs() const {
115
0
    return (isSubClassOf(NodeClass::getTableGenNodeClassName())
116
0
              ? NodeClass(get()) : NodeClass());
117
0
  }
Unexecuted instantiation: clang::tblgen::ASTNode clang::tblgen::WrappedRecord::getAs<clang::tblgen::ASTNode>() const
Unexecuted instantiation: clang::tblgen::TypeCase clang::tblgen::WrappedRecord::getAs<clang::tblgen::TypeCase>() const
118
119
0
  friend bool operator<(WrappedRecord lhs, WrappedRecord rhs) {
120
0
    assert(lhs && rhs && "sorting null nodes");
121
0
    return lhs.get()->getName() < rhs.get()->getName();
122
0
  }
123
0
  friend bool operator>(WrappedRecord lhs, WrappedRecord rhs) {
124
0
    return rhs < lhs;
125
0
  }
126
0
  friend bool operator<=(WrappedRecord lhs, WrappedRecord rhs) {
127
0
    return !(rhs < lhs);
128
0
  }
129
0
  friend bool operator>=(WrappedRecord lhs, WrappedRecord rhs) {
130
0
    return !(lhs < rhs);
131
0
  }
132
0
  friend bool operator==(WrappedRecord lhs, WrappedRecord rhs) {
133
    // This should handle null nodes.
134
0
    return lhs.getRecord() == rhs.getRecord();
135
0
  }
136
0
  friend bool operator!=(WrappedRecord lhs, WrappedRecord rhs) {
137
0
    return !(lhs == rhs);
138
0
  }
139
};
140
141
/// Anything in the AST that has properties.
142
class HasProperties : public WrappedRecord {
143
public:
144
  static constexpr llvm::StringRef ClassName = HasPropertiesClassName;
145
146
0
  HasProperties(llvm::Record *record = nullptr) : WrappedRecord(record) {}
147
148
  llvm::StringRef getName() const;
149
150
0
  static llvm::StringRef getTableGenNodeClassName() {
151
0
    return HasPropertiesClassName;
152
0
  }
153
};
154
155
/// An (optional) reference to a TableGen node representing a class
156
/// in one of Clang's AST hierarchies.
157
class ASTNode : public HasProperties {
158
public:
159
0
  ASTNode(llvm::Record *record = nullptr) : HasProperties(record) {}
160
161
0
  llvm::StringRef getName() const {
162
0
    return get()->getName();
163
0
  }
164
165
  /// Return the node for the base, if there is one.
166
0
  ASTNode getBase() const {
167
0
    return get()->getValueAsOptionalDef(BaseFieldName);
168
0
  }
169
170
  /// Is the corresponding class abstract?
171
0
  bool isAbstract() const {
172
0
    return get()->getValueAsBit(AbstractFieldName);
173
0
  }
174
175
0
  static llvm::StringRef getTableGenNodeClassName() {
176
0
    return ASTNodeClassName;
177
0
  }
178
};
179
180
class DeclNode : public ASTNode {
181
public:
182
0
  DeclNode(llvm::Record *record = nullptr) : ASTNode(record) {}
183
184
  llvm::StringRef getId() const;
185
  std::string getClassName() const;
186
0
  DeclNode getBase() const { return DeclNode(ASTNode::getBase().getRecord()); }
187
188
0
  static llvm::StringRef getASTHierarchyName() {
189
0
    return "Decl";
190
0
  }
191
0
  static llvm::StringRef getASTIdTypeName() {
192
0
    return "Decl::Kind";
193
0
  }
194
0
  static llvm::StringRef getASTIdAccessorName() {
195
0
    return "getKind";
196
0
  }
197
0
  static llvm::StringRef getTableGenNodeClassName() {
198
0
    return DeclNodeClassName;
199
0
  }
200
};
201
202
class TypeNode : public ASTNode {
203
public:
204
0
  TypeNode(llvm::Record *record = nullptr) : ASTNode(record) {}
205
206
  llvm::StringRef getId() const;
207
  llvm::StringRef getClassName() const;
208
0
  TypeNode getBase() const { return TypeNode(ASTNode::getBase().getRecord()); }
209
210
0
  static llvm::StringRef getASTHierarchyName() {
211
0
    return "Type";
212
0
  }
213
0
  static llvm::StringRef getASTIdTypeName() {
214
0
    return "Type::TypeClass";
215
0
  }
216
0
  static llvm::StringRef getASTIdAccessorName() {
217
0
    return "getTypeClass";
218
0
  }
219
0
  static llvm::StringRef getTableGenNodeClassName() {
220
0
    return TypeNodeClassName;
221
0
  }
222
};
223
224
class StmtNode : public ASTNode {
225
public:
226
0
  StmtNode(llvm::Record *record = nullptr) : ASTNode(record) {}
227
228
  std::string getId() const;
229
  llvm::StringRef getClassName() const;
230
0
  StmtNode getBase() const { return StmtNode(ASTNode::getBase().getRecord()); }
231
232
0
  static llvm::StringRef getASTHierarchyName() {
233
0
    return "Stmt";
234
0
  }
235
0
  static llvm::StringRef getASTIdTypeName() {
236
0
    return "Stmt::StmtClass";
237
0
  }
238
0
  static llvm::StringRef getASTIdAccessorName() {
239
0
    return "getStmtClass";
240
0
  }
241
0
  static llvm::StringRef getTableGenNodeClassName() {
242
0
    return StmtNodeClassName;
243
0
  }
244
};
245
246
/// The type of a property.
247
class PropertyType : public WrappedRecord {
248
public:
249
0
  PropertyType(llvm::Record *record = nullptr) : WrappedRecord(record) {}
250
251
  /// Is this a generic specialization (i.e. `Array<T>` or `Optional<T>`)?
252
0
  bool isGenericSpecialization() const {
253
0
    return get()->isAnonymous();
254
0
  }
255
256
  /// The abstract type name of the property.  Doesn't work for generic
257
  /// specializations.
258
0
  llvm::StringRef getAbstractTypeName() const {
259
0
    return get()->getName();
260
0
  }
261
262
  /// The C++ type name of the property.  Doesn't work for generic
263
  /// specializations.
264
0
  llvm::StringRef getCXXTypeName() const {
265
0
    return get()->getValueAsString(CXXTypeNameFieldName);
266
0
  }
267
  void emitCXXValueTypeName(bool forRead, llvm::raw_ostream &out) const;
268
269
  /// Whether the C++ type should be passed around by reference.
270
0
  bool shouldPassByReference() const {
271
0
    return get()->getValueAsBit(PassByReferenceFieldName);
272
0
  }
273
274
  /// Whether the C++ type should have 'const' prepended when working with
275
  /// a value of the type being written.
276
0
  bool isConstWhenWriting() const {
277
0
    return get()->getValueAsBit(ConstWhenWritingFieldName);
278
0
  }
279
280
  /// If this is `Array<T>`, return `T`; otherwise return null.
281
0
  PropertyType getArrayElementType() const {
282
0
    if (isSubClassOf(ArrayTypeClassName))
283
0
      return get()->getValueAsDef(ArrayElementTypeFieldName);
284
0
    return nullptr;
285
0
  }
286
287
  /// If this is `Optional<T>`, return `T`; otherwise return null.
288
0
  PropertyType getOptionalElementType() const {
289
0
    if (isSubClassOf(OptionalTypeClassName))
290
0
      return get()->getValueAsDef(OptionalElementTypeFieldName);
291
0
    return nullptr;
292
0
  }
293
294
  /// If this is a subclass type, return its superclass type.
295
0
  PropertyType getSuperclassType() const {
296
0
    if (isSubClassOf(SubclassPropertyTypeClassName))
297
0
      return get()->getValueAsDef(SubclassBaseTypeFieldName);
298
0
    return nullptr;
299
0
  }
300
301
  // Given that this is a subclass type, return the C++ name of its
302
  // subclass type.  This is just the bare class name, suitable for
303
  // use in `cast<>`.
304
0
  llvm::StringRef getSubclassClassName() const {
305
0
    return get()->getValueAsString(SubclassClassNameFieldName);
306
0
  }
307
308
  /// Does this represent an enum type?
309
0
  bool isEnum() const {
310
0
    return isSubClassOf(EnumPropertyTypeClassName);
311
0
  }
312
313
0
  llvm::StringRef getPackOptionalCode() const {
314
0
    return get()->getValueAsString(PackOptionalCodeFieldName);
315
0
  }
316
317
0
  llvm::StringRef getUnpackOptionalCode() const {
318
0
    return get()->getValueAsString(UnpackOptionalCodeFieldName);
319
0
  }
320
321
0
  std::vector<llvm::Record*> getBufferElementTypes() const {
322
0
    return get()->getValueAsListOfDefs(BufferElementTypesFieldName);
323
0
  }
324
325
0
  static llvm::StringRef getTableGenNodeClassName() {
326
0
    return PropertyTypeClassName;
327
0
  }
328
};
329
330
/// A rule for returning the kind of a type.
331
class TypeKindRule : public WrappedRecord {
332
public:
333
0
  TypeKindRule(llvm::Record *record = nullptr) : WrappedRecord(record) {}
334
335
  /// Return the type to which this applies.
336
0
  PropertyType getParentType() const {
337
0
    return get()->getValueAsDef(TypeFieldName);
338
0
  }
339
340
  /// Return the type of the kind.
341
0
  PropertyType getKindType() const {
342
0
    return get()->getValueAsDef(KindTypeFieldName);
343
0
  }
344
345
  /// Return the name to use for the kind property.
346
0
  llvm::StringRef getKindPropertyName() const {
347
0
    return get()->getValueAsString(KindPropertyNameFieldName);
348
0
  }
349
350
  /// Return the code for reading the kind value.
351
0
  llvm::StringRef getReadCode() const {
352
0
    return get()->getValueAsString(ReadFieldName);
353
0
  }
354
355
0
  static llvm::StringRef getTableGenNodeClassName() {
356
0
    return TypeKindClassName;
357
0
  }
358
};
359
360
/// An implementation case of a property type.
361
class TypeCase : public HasProperties {
362
public:
363
0
  TypeCase(llvm::Record *record = nullptr) : HasProperties(record) {}
364
365
  /// Return the name of this case.
366
0
  llvm::StringRef getCaseName() const {
367
0
    return get()->getValueAsString(NameFieldName);
368
0
  }
369
370
  /// Return the type of which this is a case.
371
0
  PropertyType getParentType() const {
372
0
    return get()->getValueAsDef(TypeFieldName);
373
0
  }
374
375
0
  static llvm::StringRef getTableGenNodeClassName() {
376
0
    return TypeCaseClassName;
377
0
  }
378
};
379
380
/// A property of an AST node.
381
class Property : public WrappedRecord {
382
public:
383
0
  Property(llvm::Record *record = nullptr) : WrappedRecord(record) {}
384
385
  /// Return the name of this property.
386
0
  llvm::StringRef getName() const {
387
0
    return get()->getValueAsString(NameFieldName);
388
0
  }
389
390
  /// Return the type of this property.
391
0
  PropertyType getType() const {
392
0
    return get()->getValueAsDef(TypeFieldName);
393
0
  }
394
395
  /// Return the class of which this is a property.
396
0
  HasProperties getClass() const {
397
0
    return get()->getValueAsDef(ClassFieldName);
398
0
  }
399
400
  /// Return the code for reading this property.
401
0
  llvm::StringRef getReadCode() const {
402
0
    return get()->getValueAsString(ReadFieldName);
403
0
  }
404
405
  /// Return the code for determining whether to add this property.
406
0
  llvm::StringRef getCondition() const {
407
0
    return get()->getValueAsString(ConditionalCodeFieldName);
408
0
  }
409
410
0
  static llvm::StringRef getTableGenNodeClassName() {
411
0
    return PropertyClassName;
412
0
  }
413
};
414
415
/// A rule for running some helper code for reading properties from
416
/// a value (which is actually done when writing the value out).
417
class ReadHelperRule : public WrappedRecord {
418
public:
419
0
  ReadHelperRule(llvm::Record *record = nullptr) : WrappedRecord(record) {}
420
421
  /// Return the class for which this is a creation rule.
422
  /// Should never be abstract.
423
0
  HasProperties getClass() const {
424
0
    return get()->getValueAsDef(ClassFieldName);
425
0
  }
426
427
0
  llvm::StringRef getHelperCode() const {
428
0
    return get()->getValueAsString(HelperCodeFieldName);
429
0
  }
430
431
0
  static llvm::StringRef getTableGenNodeClassName() {
432
0
    return ReadHelperRuleClassName;
433
0
  }
434
};
435
436
/// A rule for how to create an AST node from its properties.
437
class CreationRule : public WrappedRecord {
438
public:
439
0
  CreationRule(llvm::Record *record = nullptr) : WrappedRecord(record) {}
440
441
  /// Return the class for which this is a creation rule.
442
  /// Should never be abstract.
443
0
  HasProperties getClass() const {
444
0
    return get()->getValueAsDef(ClassFieldName);
445
0
  }
446
447
0
  llvm::StringRef getCreationCode() const {
448
0
    return get()->getValueAsString(CreateFieldName);
449
0
  }
450
451
0
  static llvm::StringRef getTableGenNodeClassName() {
452
0
    return CreationRuleClassName;
453
0
  }
454
};
455
456
/// A rule which overrides the standard rules for serializing an AST node.
457
class OverrideRule : public WrappedRecord {
458
public:
459
0
  OverrideRule(llvm::Record *record = nullptr) : WrappedRecord(record) {}
460
461
  /// Return the class for which this is an override rule.
462
  /// Should never be abstract.
463
0
  HasProperties getClass() const {
464
0
    return get()->getValueAsDef(ClassFieldName);
465
0
  }
466
467
  /// Return a set of properties that are unnecessary when serializing
468
  /// this AST node.  Generally this is used for inherited properties
469
  /// that are derived for this subclass.
470
0
  std::vector<llvm::StringRef> getIgnoredProperties() const {
471
0
    return get()->getValueAsListOfStrings(IgnoredPropertiesFieldName);
472
0
  }
473
474
0
  static llvm::StringRef getTableGenNodeClassName() {
475
0
    return OverrideRuleClassName;
476
0
  }
477
};
478
479
/// A visitor for an AST node hierarchy.  Note that `base` can be null for
480
/// the root class.
481
template <class NodeClass>
482
using ASTNodeHierarchyVisitor =
483
  llvm::function_ref<void(NodeClass node, NodeClass base)>;
484
485
void visitASTNodeHierarchyImpl(llvm::RecordKeeper &records,
486
                               llvm::StringRef nodeClassName,
487
                               ASTNodeHierarchyVisitor<ASTNode> visit);
488
489
template <class NodeClass>
490
void visitASTNodeHierarchy(llvm::RecordKeeper &records,
491
0
                           ASTNodeHierarchyVisitor<NodeClass> visit) {
492
0
  visitASTNodeHierarchyImpl(records, NodeClass::getTableGenNodeClassName(),
493
0
                            [visit](ASTNode node, ASTNode base) {
494
0
                              visit(NodeClass(node.getRecord()),
495
0
                                    NodeClass(base.getRecord()));
496
0
                            });
497
0
}
498
499
} // end namespace clang::tblgen
500
} // end namespace clang
501
502
#endif