Coverage Report

Created: 2020-02-25 14:32

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/utils/TableGen/ASTTableGen.cpp
Line
Count
Source (jump to first uncovered line)
1
//=== ASTTableGen.cpp - Helper functions for working with AST records -----===//
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
// This file defines some helper functions for working with tblegen reocrds
10
// for the Clang AST: that is, the contents of files such as DeclNodes.td,
11
// StmtNodes.td, and TypeNodes.td.
12
//
13
//===----------------------------------------------------------------------===//
14
15
#include "ASTTableGen.h"
16
#include "llvm/TableGen/Record.h"
17
#include "llvm/TableGen/Error.h"
18
19
using namespace llvm;
20
using namespace clang;
21
using namespace clang::tblgen;
22
23
0
llvm::StringRef clang::tblgen::HasProperties::getName() const {
24
0
  if (auto node = getAs<ASTNode>()) {
25
0
    return node.getName();
26
0
  } else if (auto typeCase = getAs<TypeCase>()) {
27
0
    return typeCase.getCaseName();
28
0
  } else {
29
0
    PrintFatalError(getLoc(), "unexpected node declaring properties");
30
0
  }
31
0
}
32
33
0
static StringRef removeExpectedNodeNameSuffix(Record *node, StringRef suffix) {
34
0
  StringRef nodeName = node->getName();
35
0
  if (!nodeName.endswith(suffix)) {
36
0
    PrintFatalError(node->getLoc(),
37
0
                    Twine("name of node doesn't end in ") + suffix);
38
0
  }
39
0
  return nodeName.drop_back(suffix.size());
40
0
}
41
42
// Decl node names don't end in Decl for historical reasons, and it would
43
// be somewhat annoying to fix now.  Conveniently, this means the ID matches
44
// is exactly the node name, and the class name is simply that plus Decl.
45
0
std::string clang::tblgen::DeclNode::getClassName() const {
46
0
  return (Twine(getName()) + "Decl").str();
47
0
}
48
0
StringRef clang::tblgen::DeclNode::getId() const {
49
0
  return getName();
50
0
}
51
52
// Type nodes are all named ending in Type, just like the corresponding
53
// C++ class, and the ID just strips this suffix.
54
0
StringRef clang::tblgen::TypeNode::getClassName() const {
55
0
  return getName();
56
0
}
57
0
StringRef clang::tblgen::TypeNode::getId() const {
58
0
  return removeExpectedNodeNameSuffix(getRecord(), "Type");
59
0
}
60
61
// Stmt nodes are named the same as the C++ class, which has no regular
62
// naming convention (all the non-expression statements end in Stmt,
63
// and *many* expressions end in Expr, but there are also several
64
// core expression classes like IntegerLiteral and BinaryOperator with
65
// no standard suffix).  The ID adds "Class" for historical reasons.
66
0
StringRef clang::tblgen::StmtNode::getClassName() const {
67
0
  return getName();
68
0
}
69
0
std::string clang::tblgen::StmtNode::getId() const {
70
0
  return (Twine(getName()) + "Class").str();
71
0
}
72
73
/// Emit a string spelling out the C++ value type.
74
0
void PropertyType::emitCXXValueTypeName(bool forRead, raw_ostream &out) const {
75
0
  if (!isGenericSpecialization()) {
76
0
    if (!forRead && isConstWhenWriting())
77
0
      out << "const ";
78
0
    out << getCXXTypeName();
79
0
  } else if (auto elementType = getArrayElementType()) {
80
0
    out << "llvm::ArrayRef<";
81
0
    elementType.emitCXXValueTypeName(forRead, out);
82
0
    out << ">";
83
0
  } else if (auto valueType = getOptionalElementType()) {
84
0
    out << "llvm::Optional<";
85
0
    valueType.emitCXXValueTypeName(forRead, out);
86
0
    out << ">";
87
0
  } else {
88
0
    //PrintFatalError(getLoc(), "unexpected generic property type");
89
0
    abort();
90
0
  }
91
0
}
92
93
// A map from a node to each of its child nodes.
94
using ChildMap = std::multimap<ASTNode, ASTNode>;
95
96
static void visitASTNodeRecursive(ASTNode node, ASTNode base,
97
                                  const ChildMap &map,
98
0
                                  ASTNodeHierarchyVisitor<ASTNode> visit) {
99
0
  visit(node, base);
100
0
101
0
  auto i = map.lower_bound(node), e = map.upper_bound(node);
102
0
  for (; i != e; ++i) {
103
0
    visitASTNodeRecursive(i->second, node, map, visit);
104
0
  }
105
0
}
106
107
static void visitHierarchy(RecordKeeper &records,
108
                           StringRef nodeClassName,
109
0
                           ASTNodeHierarchyVisitor<ASTNode> visit) {
110
0
  // Check for the node class, just as a sanity check.
111
0
  if (!records.getClass(nodeClassName)) {
112
0
    PrintFatalError(Twine("cannot find definition for node class ")
113
0
                      + nodeClassName);
114
0
  }
115
0
116
0
  // Find all the nodes in the hierarchy.
117
0
  auto nodes = records.getAllDerivedDefinitions(nodeClassName);
118
0
119
0
  // Derive the child map.
120
0
  ChildMap hierarchy;
121
0
  ASTNode root;
122
0
  for (ASTNode node : nodes) {
123
0
    if (auto base = node.getBase())
124
0
      hierarchy.insert(std::make_pair(base, node));
125
0
    else if (root)
126
0
      PrintFatalError(node.getLoc(),
127
0
                      "multiple root nodes in " + nodeClassName + " hierarchy");
128
0
    else
129
0
      root = node;
130
0
  }
131
0
  if (!root)
132
0
    PrintFatalError(Twine("no root node in ") + nodeClassName + " hierarchy");
133
0
134
0
  // Now visit the map recursively, starting at the root node.
135
0
  visitASTNodeRecursive(root, ASTNode(), hierarchy, visit);
136
0
}
137
138
void clang::tblgen::visitASTNodeHierarchyImpl(RecordKeeper &records,
139
                                              StringRef nodeClassName,
140
0
                                      ASTNodeHierarchyVisitor<ASTNode> visit) {
141
0
  visitHierarchy(records, nodeClassName, visit);
142
0
}