Coverage Report

Created: 2020-11-24 06:42

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/include/clang/AST/ParentMapContext.h
Line
Count
Source
1
//===- ParentMapContext.h - Map of parents using DynTypedNode -------*- 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
// Similar to ParentMap.h, but generalizes to non-Stmt nodes, which can have
10
// multiple parents.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#ifndef LLVM_CLANG_AST_PARENTMAPCONTEXT_H
15
#define LLVM_CLANG_AST_PARENTMAPCONTEXT_H
16
17
#include "clang/AST/ASTContext.h"
18
#include "clang/AST/ASTTypeTraits.h"
19
20
namespace clang {
21
class DynTypedNodeList;
22
23
class ParentMapContext {
24
public:
25
  ParentMapContext(ASTContext &Ctx);
26
27
  ~ParentMapContext();
28
29
  /// Returns the parents of the given node (within the traversal scope).
30
  ///
31
  /// Note that this will lazily compute the parents of all nodes
32
  /// and store them for later retrieval. Thus, the first call is O(n)
33
  /// in the number of AST nodes.
34
  ///
35
  /// Caveats and FIXMEs:
36
  /// Calculating the parent map over all AST nodes will need to load the
37
  /// full AST. This can be undesirable in the case where the full AST is
38
  /// expensive to create (for example, when using precompiled header
39
  /// preambles). Thus, there are good opportunities for optimization here.
40
  /// One idea is to walk the given node downwards, looking for references
41
  /// to declaration contexts - once a declaration context is found, compute
42
  /// the parent map for the declaration context; if that can satisfy the
43
  /// request, loading the whole AST can be avoided. Note that this is made
44
  /// more complex by statements in templates having multiple parents - those
45
  /// problems can be solved by building closure over the templated parts of
46
  /// the AST, which also avoids touching large parts of the AST.
47
  /// Additionally, we will want to add an interface to already give a hint
48
  /// where to search for the parents, for example when looking at a statement
49
  /// inside a certain function.
50
  ///
51
  /// 'NodeT' can be one of Decl, Stmt, Type, TypeLoc,
52
  /// NestedNameSpecifier or NestedNameSpecifierLoc.
53
  template <typename NodeT> DynTypedNodeList getParents(const NodeT &Node);
54
55
  DynTypedNodeList getParents(const DynTypedNode &Node);
56
57
  /// Clear parent maps.
58
  void clear();
59
60
1.45M
  TraversalKind getTraversalKind() const { return Traversal; }
61
703k
  void setTraversalKind(TraversalKind TK) { Traversal = TK; }
62
63
  const Expr *traverseIgnored(const Expr *E) const;
64
  Expr *traverseIgnored(Expr *E) const;
65
  DynTypedNode traverseIgnored(const DynTypedNode &N) const;
66
67
private:
68
  ASTContext &ASTCtx;
69
  class ParentMap;
70
  TraversalKind Traversal = TK_AsIs;
71
  std::unique_ptr<ParentMap> Parents;
72
};
73
74
class TraversalKindScope {
75
  ParentMapContext &Ctx;
76
  TraversalKind TK = TK_AsIs;
77
78
public:
79
  TraversalKindScope(ASTContext &ASTCtx, llvm::Optional<TraversalKind> ScopeTK)
80
693k
      : Ctx(ASTCtx.getParentMapContext()) {
81
693k
    TK = Ctx.getTraversalKind();
82
693k
    if (ScopeTK)
83
9.95k
      Ctx.setTraversalKind(*ScopeTK);
84
693k
  }
85
86
693k
  ~TraversalKindScope() { Ctx.setTraversalKind(TK); }
87
};
88
89
/// Container for either a single DynTypedNode or for an ArrayRef to
90
/// DynTypedNode. For use with ParentMap.
91
class DynTypedNodeList {
92
  llvm::AlignedCharArrayUnion<DynTypedNode, ArrayRef<DynTypedNode>> Storage;
93
  bool IsSingleNode;
94
95
public:
96
13.9k
  DynTypedNodeList(const DynTypedNode &N) : IsSingleNode(true) {
97
13.9k
    new (Storage.buffer) DynTypedNode(N);
98
13.9k
  }
99
100
3.12k
  DynTypedNodeList(ArrayRef<DynTypedNode> A) : IsSingleNode(false) {
101
3.12k
    new (Storage.buffer) ArrayRef<DynTypedNode>(A);
102
3.12k
  }
103
104
56.9k
  const DynTypedNode *begin() const {
105
56.9k
    if (!IsSingleNode)
106
3.01k
      return reinterpret_cast<const ArrayRef<DynTypedNode> *>(Storage.buffer)
107
3.01k
          ->begin();
108
53.9k
    return reinterpret_cast<const DynTypedNode *>(Storage.buffer);
109
53.9k
  }
110
111
38.1k
  const DynTypedNode *end() const {
112
38.1k
    if (!IsSingleNode)
113
2.97k
      return reinterpret_cast<const ArrayRef<DynTypedNode> *>(Storage.buffer)
114
2.97k
          ->end();
115
35.1k
    return reinterpret_cast<const DynTypedNode *>(Storage.buffer) + 1;
116
35.1k
  }
117
118
29.5k
  size_t size() const { return end() - begin(); }
119
7.00k
  bool empty() const { return begin() == end(); }
120
121
13.0k
  const DynTypedNode &operator[](size_t N) const {
122
13.0k
    assert(N < size() && "Out of bounds!");
123
13.0k
    return *(begin() + N);
124
13.0k
  }
125
};
126
127
template <typename NodeT>
128
6.81k
inline DynTypedNodeList ParentMapContext::getParents(const NodeT &Node) {
129
6.81k
  return getParents(DynTypedNode::create(Node));
130
6.81k
}
clang::DynTypedNodeList clang::ParentMapContext::getParents<clang::TypeLoc>(clang::TypeLoc const&)
Line
Count
Source
128
5.42k
inline DynTypedNodeList ParentMapContext::getParents(const NodeT &Node) {
129
5.42k
  return getParents(DynTypedNode::create(Node));
130
5.42k
}
clang::DynTypedNodeList clang::ParentMapContext::getParents<clang::NestedNameSpecifierLoc>(clang::NestedNameSpecifierLoc const&)
Line
Count
Source
128
87
inline DynTypedNodeList ParentMapContext::getParents(const NodeT &Node) {
129
87
  return getParents(DynTypedNode::create(Node));
130
87
}
clang::DynTypedNodeList clang::ParentMapContext::getParents<clang::EnumConstantDecl>(clang::EnumConstantDecl const&)
Line
Count
Source
128
15
inline DynTypedNodeList ParentMapContext::getParents(const NodeT &Node) {
129
15
  return getParents(DynTypedNode::create(Node));
130
15
}
clang::DynTypedNodeList clang::ParentMapContext::getParents<clang::DeclRefExpr>(clang::DeclRefExpr const&)
Line
Count
Source
128
31
inline DynTypedNodeList ParentMapContext::getParents(const NodeT &Node) {
129
31
  return getParents(DynTypedNode::create(Node));
130
31
}
clang::DynTypedNodeList clang::ParentMapContext::getParents<clang::VarDecl>(clang::VarDecl const&)
Line
Count
Source
128
38
inline DynTypedNodeList ParentMapContext::getParents(const NodeT &Node) {
129
38
  return getParents(DynTypedNode::create(Node));
130
38
}
clang::DynTypedNodeList clang::ParentMapContext::getParents<clang::DeclStmt>(clang::DeclStmt const&)
Line
Count
Source
128
24
inline DynTypedNodeList ParentMapContext::getParents(const NodeT &Node) {
129
24
  return getParents(DynTypedNode::create(Node));
130
24
}
clang::DynTypedNodeList clang::ParentMapContext::getParents<clang::Stmt>(clang::Stmt const&)
Line
Count
Source
128
1.19k
inline DynTypedNodeList ParentMapContext::getParents(const NodeT &Node) {
129
1.19k
  return getParents(DynTypedNode::create(Node));
130
1.19k
}
131
132
template <typename NodeT>
133
6.81k
inline DynTypedNodeList ASTContext::getParents(const NodeT &Node) {
134
6.81k
  return getParentMapContext().getParents(Node);
135
6.81k
}
clang::DynTypedNodeList clang::ASTContext::getParents<clang::TypeLoc>(clang::TypeLoc const&)
Line
Count
Source
133
5.42k
inline DynTypedNodeList ASTContext::getParents(const NodeT &Node) {
134
5.42k
  return getParentMapContext().getParents(Node);
135
5.42k
}
clang::DynTypedNodeList clang::ASTContext::getParents<clang::NestedNameSpecifierLoc>(clang::NestedNameSpecifierLoc const&)
Line
Count
Source
133
87
inline DynTypedNodeList ASTContext::getParents(const NodeT &Node) {
134
87
  return getParentMapContext().getParents(Node);
135
87
}
clang::DynTypedNodeList clang::ASTContext::getParents<clang::EnumConstantDecl>(clang::EnumConstantDecl const&)
Line
Count
Source
133
15
inline DynTypedNodeList ASTContext::getParents(const NodeT &Node) {
134
15
  return getParentMapContext().getParents(Node);
135
15
}
clang::DynTypedNodeList clang::ASTContext::getParents<clang::DeclRefExpr>(clang::DeclRefExpr const&)
Line
Count
Source
133
31
inline DynTypedNodeList ASTContext::getParents(const NodeT &Node) {
134
31
  return getParentMapContext().getParents(Node);
135
31
}
clang::DynTypedNodeList clang::ASTContext::getParents<clang::VarDecl>(clang::VarDecl const&)
Line
Count
Source
133
38
inline DynTypedNodeList ASTContext::getParents(const NodeT &Node) {
134
38
  return getParentMapContext().getParents(Node);
135
38
}
clang::DynTypedNodeList clang::ASTContext::getParents<clang::DeclStmt>(clang::DeclStmt const&)
Line
Count
Source
133
24
inline DynTypedNodeList ASTContext::getParents(const NodeT &Node) {
134
24
  return getParentMapContext().getParents(Node);
135
24
}
clang::DynTypedNodeList clang::ASTContext::getParents<clang::Stmt>(clang::Stmt const&)
Line
Count
Source
133
1.19k
inline DynTypedNodeList ASTContext::getParents(const NodeT &Node) {
134
1.19k
  return getParentMapContext().getParents(Node);
135
1.19k
}
136
137
template <>
138
8.06k
inline DynTypedNodeList ASTContext::getParents(const DynTypedNode &Node) {
139
8.06k
  return getParentMapContext().getParents(Node);
140
8.06k
}
141
142
} // namespace clang
143
144
#endif