summaryrefslogtreecommitdiffstats
path: root/clang/utils/TableGen/ASTTableGen.h
blob: 3d623aa45b283e3626f3ecf1c2d80900ef3023d2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
//=== ASTTableGen.h - Common definitions for AST node tablegen --*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef CLANG_AST_TABLEGEN_H
#define CLANG_AST_TABLEGEN_H

#include "llvm/TableGen/Record.h"
#include "llvm/ADT/STLExtras.h"

// These are spellings in the tblgen files.

// Field names that are fortunately common across the hierarchies.
#define BaseFieldName "Base"
#define AbstractFieldName "Abstract"

// Comment node hierarchy.
#define CommentNodeClassName "CommentNode"

// Decl node hierarchy.
#define DeclNodeClassName "DeclNode"
#define DeclContextNodeClassName "DeclContext"

// Stmt node hierarchy.
#define StmtNodeClassName "StmtNode"

// Type node hierarchy.
#define TypeNodeClassName "TypeNode"
#define AlwaysDependentClassName "AlwaysDependent"
#define NeverCanonicalClassName "NeverCanonical"
#define NeverCanonicalUnlessDependentClassName "NeverCanonicalUnlessDependent"
#define LeafTypeClassName "LeafType"

// Property node hierarchy.
#define PropertyClassName "Property"
#define ClassFieldName "Class"

namespace clang {
namespace tblgen {

/// An (optional) reference to a TableGen node representing a class
/// in one of Clang's AST hierarchies.
class ASTNode {
  llvm::Record *Record;
public:
  ASTNode(llvm::Record *record = nullptr) : Record(record) {}

  explicit operator bool() const { return Record != nullptr; }

  llvm::Record *getRecord() const { return Record; }
  llvm::StringRef getName() const {
    assert(Record && "getting name of null record");
    return Record->getName();
  }
  llvm::ArrayRef<llvm::SMLoc> getLoc() const {
    assert(Record && "getting location of null record");
    return Record->getLoc();
  }

  /// Return the node for the base, if there is one.
  ASTNode getBase() const {
    assert(Record && "getting base of null record");
    return Record->getValueAsOptionalDef(BaseFieldName);
  }

  /// Is the corresponding class abstract?
  bool isAbstract() const {
    assert(Record && "querying null record");
    return Record->getValueAsBit(AbstractFieldName);
  }

  /// Does the node inherit from the given TableGen class?
  bool isSubClassOf(llvm::StringRef className) const {
    assert(Record && "querying null record");
    return Record->isSubClassOf(className);
  }

  friend bool operator<(ASTNode lhs, ASTNode rhs) {
    assert(lhs && rhs && "sorting null nodes");
    return lhs.getName() < rhs.getName();
  }
  friend bool operator>(ASTNode lhs, ASTNode rhs) { return rhs < lhs; }
  friend bool operator<=(ASTNode lhs, ASTNode rhs) { return !(rhs < lhs); }
  friend bool operator>=(ASTNode lhs, ASTNode rhs) { return !(lhs < rhs); }

  friend bool operator==(ASTNode lhs, ASTNode rhs) {
    // This should handle null nodes.
    return lhs.getRecord() == rhs.getRecord();
  }
  friend bool operator!=(ASTNode lhs, ASTNode rhs) { return !(lhs == rhs); }
};

class DeclNode : public ASTNode {
public:
  DeclNode(llvm::Record *record = nullptr) : ASTNode(record) {}

  llvm::StringRef getId() const;
  std::string getClassName() const;
  DeclNode getBase() const { return DeclNode(ASTNode::getBase().getRecord()); }
};

class TypeNode : public ASTNode {
public:
  TypeNode(llvm::Record *record = nullptr) : ASTNode(record) {}

  llvm::StringRef getId() const;
  llvm::StringRef getClassName() const;
  TypeNode getBase() const { return TypeNode(ASTNode::getBase().getRecord()); }
};

class StmtNode : public ASTNode {
public:
  StmtNode(llvm::Record *record = nullptr) : ASTNode(record) {}

  std::string getId() const;
  llvm::StringRef getClassName() const;
  StmtNode getBase() const { return StmtNode(ASTNode::getBase().getRecord()); }
};

/// A visitor for an AST node hierarchy.  Note that `base` can be null for
/// the root class.
template <class NodeClass>
using ASTNodeHierarchyVisitor =
  llvm::function_ref<void(NodeClass node, NodeClass base)>;

void visitASTNodeHierarchy(llvm::RecordKeeper &records,
                           llvm::StringRef nodeClassName,
                           ASTNodeHierarchyVisitor<ASTNode> visit);

void visitDeclNodeHierarchy(llvm::RecordKeeper &records,
                            ASTNodeHierarchyVisitor<DeclNode> visit);

void visitTypeNodeHierarchy(llvm::RecordKeeper &records,
                            ASTNodeHierarchyVisitor<TypeNode> visit);

void visitStmtNodeHierarchy(llvm::RecordKeeper &records,
                            ASTNodeHierarchyVisitor<StmtNode> visit);

} // end namespace clang::tblgen
} // end namespace clang

#endif
OpenPOWER on IntegriCloud