Coverage Report

Created: 2022-07-16 07:03

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/AST/ParentMapContext.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- ParentMapContext.cpp - 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.cpp, but generalizes to non-Stmt nodes, which can have
10
// multiple parents.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "clang/AST/ParentMapContext.h"
15
#include "clang/AST/RecursiveASTVisitor.h"
16
#include "clang/AST/Decl.h"
17
#include "clang/AST/Expr.h"
18
#include "clang/AST/TemplateBase.h"
19
20
using namespace clang;
21
22
21.8k
ParentMapContext::ParentMapContext(ASTContext &Ctx) : ASTCtx(Ctx) {}
23
24
21.7k
ParentMapContext::~ParentMapContext() = default;
25
26
112
void ParentMapContext::clear() { Parents.reset(); }
27
28
599k
const Expr *ParentMapContext::traverseIgnored(const Expr *E) const {
29
599k
  return traverseIgnored(const_cast<Expr *>(E));
30
599k
}
31
32
648k
Expr *ParentMapContext::traverseIgnored(Expr *E) const {
33
648k
  if (!E)
34
0
    return nullptr;
35
36
648k
  switch (Traversal) {
37
612k
  case TK_AsIs:
38
612k
    return E;
39
35.7k
  case TK_IgnoreUnlessSpelledInSource:
40
35.7k
    return E->IgnoreUnlessSpelledInSource();
41
648k
  }
42
0
  llvm_unreachable("Invalid Traversal type!");
43
0
}
44
45
1.41M
DynTypedNode ParentMapContext::traverseIgnored(const DynTypedNode &N) const {
46
1.41M
  if (const auto *E = N.get<Expr>()) {
47
599k
    return DynTypedNode::create(*traverseIgnored(E));
48
599k
  }
49
820k
  return N;
50
1.41M
}
51
52
template <typename T, typename... U>
53
std::tuple<bool, DynTypedNodeList, const T *, const U *...>
54
matchParents(const DynTypedNodeList &NodeList,
55
             ParentMapContext::ParentMap *ParentMap);
56
57
template <typename, typename...> struct MatchParents;
58
59
class ParentMapContext::ParentMap {
60
61
  template <typename, typename...> friend struct ::MatchParents;
62
63
  /// Contains parents of a node.
64
  using ParentVector = llvm::SmallVector<DynTypedNode, 2>;
65
66
  /// Maps from a node to its parents. This is used for nodes that have
67
  /// pointer identity only, which are more common and we can save space by
68
  /// only storing a unique pointer to them.
69
  using ParentMapPointers =
70
      llvm::DenseMap<const void *,
71
                     llvm::PointerUnion<const Decl *, const Stmt *,
72
                                        DynTypedNode *, ParentVector *>>;
73
74
  /// Parent map for nodes without pointer identity. We store a full
75
  /// DynTypedNode for all keys.
76
  using ParentMapOtherNodes =
77
      llvm::DenseMap<DynTypedNode,
78
                     llvm::PointerUnion<const Decl *, const Stmt *,
79
                                        DynTypedNode *, ParentVector *>>;
80
81
  ParentMapPointers PointerParents;
82
  ParentMapOtherNodes OtherParents;
83
  class ASTVisitor;
84
85
  static DynTypedNode
86
51.2k
  getSingleDynTypedNodeFromParentMap(ParentMapPointers::mapped_type U) {
87
51.2k
    if (const auto *D = U.dyn_cast<const Decl *>())
88
18.7k
      return DynTypedNode::create(*D);
89
32.4k
    if (const auto *S = U.dyn_cast<const Stmt *>())
90
18.5k
      return DynTypedNode::create(*S);
91
13.9k
    return *U.get<DynTypedNode *>();
92
32.4k
  }
93
94
  template <typename NodeTy, typename MapTy>
95
  static DynTypedNodeList getDynNodeFromMap(const NodeTy &Node,
96
32.2k
                                                        const MapTy &Map) {
97
32.2k
    auto I = Map.find(Node);
98
32.2k
    if (I == Map.end()) {
99
957
      return llvm::ArrayRef<DynTypedNode>();
100
957
    }
101
31.2k
    if (const auto *V = I->second.template dyn_cast<ParentVector *>()) {
102
134
      return llvm::makeArrayRef(*V);
103
134
    }
104
31.1k
    return getSingleDynTypedNodeFromParentMap(I->second);
105
31.2k
  }
clang::DynTypedNodeList clang::ParentMapContext::ParentMap::getDynNodeFromMap<void const*, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > >(void const* const&, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > const&)
Line
Count
Source
96
24.3k
                                                        const MapTy &Map) {
97
24.3k
    auto I = Map.find(Node);
98
24.3k
    if (I == Map.end()) {
99
906
      return llvm::ArrayRef<DynTypedNode>();
100
906
    }
101
23.4k
    if (const auto *V = I->second.template dyn_cast<ParentVector *>()) {
102
119
      return llvm::makeArrayRef(*V);
103
119
    }
104
23.3k
    return getSingleDynTypedNodeFromParentMap(I->second);
105
23.4k
  }
clang::DynTypedNodeList clang::ParentMapContext::ParentMap::getDynNodeFromMap<clang::Stmt const*, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > >(clang::Stmt const* const&, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > const&)
Line
Count
Source
96
2.09k
                                                        const MapTy &Map) {
97
2.09k
    auto I = Map.find(Node);
98
2.09k
    if (I == Map.end()) {
99
0
      return llvm::ArrayRef<DynTypedNode>();
100
0
    }
101
2.09k
    if (const auto *V = I->second.template dyn_cast<ParentVector *>()) {
102
4
      return llvm::makeArrayRef(*V);
103
4
    }
104
2.08k
    return getSingleDynTypedNodeFromParentMap(I->second);
105
2.09k
  }
clang::DynTypedNodeList clang::ParentMapContext::ParentMap::getDynNodeFromMap<clang::DeclStmt const*, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > >(clang::DeclStmt const* const&, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > const&)
Line
Count
Source
96
62
                                                        const MapTy &Map) {
97
62
    auto I = Map.find(Node);
98
62
    if (I == Map.end()) {
99
0
      return llvm::ArrayRef<DynTypedNode>();
100
0
    }
101
62
    if (const auto *V = I->second.template dyn_cast<ParentVector *>()) {
102
0
      return llvm::makeArrayRef(*V);
103
0
    }
104
62
    return getSingleDynTypedNodeFromParentMap(I->second);
105
62
  }
clang::DynTypedNodeList clang::ParentMapContext::ParentMap::getDynNodeFromMap<clang::CXXForRangeStmt const*, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > >(clang::CXXForRangeStmt const* const&, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > const&)
Line
Count
Source
96
6
                                                        const MapTy &Map) {
97
6
    auto I = Map.find(Node);
98
6
    if (I == Map.end()) {
99
0
      return llvm::ArrayRef<DynTypedNode>();
100
0
    }
101
6
    if (const auto *V = I->second.template dyn_cast<ParentVector *>()) {
102
0
      return llvm::makeArrayRef(*V);
103
0
    }
104
6
    return getSingleDynTypedNodeFromParentMap(I->second);
105
6
  }
clang::DynTypedNodeList clang::ParentMapContext::ParentMap::getDynNodeFromMap<clang::VarDecl const*, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > >(clang::VarDecl const* const&, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > const&)
Line
Count
Source
96
31
                                                        const MapTy &Map) {
97
31
    auto I = Map.find(Node);
98
31
    if (I == Map.end()) {
99
0
      return llvm::ArrayRef<DynTypedNode>();
100
0
    }
101
31
    if (const auto *V = I->second.template dyn_cast<ParentVector *>()) {
102
0
      return llvm::makeArrayRef(*V);
103
0
    }
104
31
    return getSingleDynTypedNodeFromParentMap(I->second);
105
31
  }
clang::DynTypedNodeList clang::ParentMapContext::ParentMap::getDynNodeFromMap<clang::CXXMethodDecl const*, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > >(clang::CXXMethodDecl const* const&, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > const&)
Line
Count
Source
96
6
                                                        const MapTy &Map) {
97
6
    auto I = Map.find(Node);
98
6
    if (I == Map.end()) {
99
0
      return llvm::ArrayRef<DynTypedNode>();
100
0
    }
101
6
    if (const auto *V = I->second.template dyn_cast<ParentVector *>()) {
102
0
      return llvm::makeArrayRef(*V);
103
0
    }
104
6
    return getSingleDynTypedNodeFromParentMap(I->second);
105
6
  }
clang::DynTypedNodeList clang::ParentMapContext::ParentMap::getDynNodeFromMap<clang::CXXRecordDecl const*, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > >(clang::CXXRecordDecl const* const&, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > const&)
Line
Count
Source
96
6
                                                        const MapTy &Map) {
97
6
    auto I = Map.find(Node);
98
6
    if (I == Map.end()) {
99
0
      return llvm::ArrayRef<DynTypedNode>();
100
0
    }
101
6
    if (const auto *V = I->second.template dyn_cast<ParentVector *>()) {
102
0
      return llvm::makeArrayRef(*V);
103
0
    }
104
6
    return getSingleDynTypedNodeFromParentMap(I->second);
105
6
  }
clang::DynTypedNodeList clang::ParentMapContext::ParentMap::getDynNodeFromMap<clang::LambdaExpr const*, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > >(clang::LambdaExpr const* const&, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > const&)
Line
Count
Source
96
6
                                                        const MapTy &Map) {
97
6
    auto I = Map.find(Node);
98
6
    if (I == Map.end()) {
99
0
      return llvm::ArrayRef<DynTypedNode>();
100
0
    }
101
6
    if (const auto *V = I->second.template dyn_cast<ParentVector *>()) {
102
0
      return llvm::makeArrayRef(*V);
103
0
    }
104
6
    return getSingleDynTypedNodeFromParentMap(I->second);
105
6
  }
clang::DynTypedNodeList clang::ParentMapContext::ParentMap::getDynNodeFromMap<clang::FunctionTemplateDecl const*, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > >(clang::FunctionTemplateDecl const* const&, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > const&)
Line
Count
Source
96
2
                                                        const MapTy &Map) {
97
2
    auto I = Map.find(Node);
98
2
    if (I == Map.end()) {
99
0
      return llvm::ArrayRef<DynTypedNode>();
100
0
    }
101
2
    if (const auto *V = I->second.template dyn_cast<ParentVector *>()) {
102
0
      return llvm::makeArrayRef(*V);
103
0
    }
104
2
    return getSingleDynTypedNodeFromParentMap(I->second);
105
2
  }
clang::DynTypedNodeList clang::ParentMapContext::ParentMap::getDynNodeFromMap<clang::DynTypedNode, llvm::DenseMap<clang::DynTypedNode, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<clang::DynTypedNode, void>, llvm::detail::DenseMapPair<clang::DynTypedNode, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > >(clang::DynTypedNode const&, llvm::DenseMap<clang::DynTypedNode, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<clang::DynTypedNode, void>, llvm::detail::DenseMapPair<clang::DynTypedNode, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > const&)
Line
Count
Source
96
5.62k
                                                        const MapTy &Map) {
97
5.62k
    auto I = Map.find(Node);
98
5.62k
    if (I == Map.end()) {
99
51
      return llvm::ArrayRef<DynTypedNode>();
100
51
    }
101
5.57k
    if (const auto *V = I->second.template dyn_cast<ParentVector *>()) {
102
11
      return llvm::makeArrayRef(*V);
103
11
    }
104
5.56k
    return getSingleDynTypedNodeFromParentMap(I->second);
105
5.57k
  }
106
107
public:
108
  ParentMap(ASTContext &Ctx);
109
1.69k
  ~ParentMap() {
110
526k
    for (const auto &Entry : PointerParents) {
111
526k
      if (Entry.second.is<DynTypedNode *>()) {
112
62.2k
        delete Entry.second.get<DynTypedNode *>();
113
464k
      } else if (Entry.second.is<ParentVector *>()) {
114
3.11k
        delete Entry.second.get<ParentVector *>();
115
3.11k
      }
116
526k
    }
117
719k
    for (const auto &Entry : OtherParents) {
118
719k
      if (Entry.second.is<DynTypedNode *>()) {
119
482k
        delete Entry.second.get<DynTypedNode *>();
120
482k
      } else 
if (236k
Entry.second.is<ParentVector *>()236k
) {
121
16.9k
        delete Entry.second.get<ParentVector *>();
122
16.9k
      }
123
719k
    }
124
1.69k
  }
125
126
30.0k
  DynTypedNodeList getParents(TraversalKind TK, const DynTypedNode &Node) {
127
30.0k
    if (Node.getNodeKind().hasPointerIdentity()) {
128
24.3k
      auto ParentList =
129
24.3k
          getDynNodeFromMap(Node.getMemoizationData(), PointerParents);
130
24.3k
      if (ParentList.size() > 0 && 
TK == TK_IgnoreUnlessSpelledInSource23.4k
) {
131
132
3.73k
        const auto *ChildExpr = Node.get<Expr>();
133
134
3.73k
        {
135
          // Don't match explicit node types because different stdlib
136
          // implementations implement this in different ways and have
137
          // different intermediate nodes.
138
          // Look up 4 levels for a cxxRewrittenBinaryOperator as that is
139
          // enough for the major stdlib implementations.
140
3.73k
          auto RewrittenBinOpParentsList = ParentList;
141
3.73k
          int I = 0;
142
5.82k
          while (ChildExpr && 
RewrittenBinOpParentsList.size() == 13.18k
&&
143
5.82k
                 
I++ < 43.18k
) {
144
3.16k
            const auto *S = RewrittenBinOpParentsList[0].get<Stmt>();
145
3.16k
            if (!S)
146
1.06k
              break;
147
148
2.09k
            const auto *RWBO = dyn_cast<CXXRewrittenBinaryOperator>(S);
149
2.09k
            if (!RWBO) {
150
2.09k
              RewrittenBinOpParentsList = getDynNodeFromMap(S, PointerParents);
151
2.09k
              continue;
152
2.09k
            }
153
4
            if (RWBO->getLHS()->IgnoreUnlessSpelledInSource() != ChildExpr &&
154
4
                
RWBO->getRHS()->IgnoreUnlessSpelledInSource() != ChildExpr2
)
155
0
              break;
156
4
            return DynTypedNode::create(*RWBO);
157
4
          }
158
3.73k
        }
159
160
3.73k
        const auto *ParentExpr = ParentList[0].get<Expr>();
161
3.73k
        if (ParentExpr && 
ChildExpr57
)
162
55
          return AscendIgnoreUnlessSpelledInSource(ParentExpr, ChildExpr);
163
164
3.67k
        {
165
3.67k
          auto AncestorNodes =
166
3.67k
              matchParents<DeclStmt, CXXForRangeStmt>(ParentList, this);
167
3.67k
          if (std::get<bool>(AncestorNodes) &&
168
3.67k
              std::get<const CXXForRangeStmt *>(AncestorNodes)
169
2
                      ->getLoopVarStmt() ==
170
2
                  std::get<const DeclStmt *>(AncestorNodes))
171
2
            return std::get<DynTypedNodeList>(AncestorNodes);
172
3.67k
        }
173
3.67k
        {
174
3.67k
          auto AncestorNodes = matchParents<VarDecl, DeclStmt, CXXForRangeStmt>(
175
3.67k
              ParentList, this);
176
3.67k
          if (std::get<bool>(AncestorNodes) &&
177
3.67k
              std::get<const CXXForRangeStmt *>(AncestorNodes)
178
4
                      ->getRangeStmt() ==
179
4
                  std::get<const DeclStmt *>(AncestorNodes))
180
4
            return std::get<DynTypedNodeList>(AncestorNodes);
181
3.67k
        }
182
3.67k
        {
183
3.67k
          auto AncestorNodes =
184
3.67k
              matchParents<CXXMethodDecl, CXXRecordDecl, LambdaExpr>(ParentList,
185
3.67k
                                                                     this);
186
3.67k
          if (std::get<bool>(AncestorNodes))
187
4
            return std::get<DynTypedNodeList>(AncestorNodes);
188
3.67k
        }
189
3.66k
        {
190
3.66k
          auto AncestorNodes =
191
3.66k
              matchParents<FunctionTemplateDecl, CXXRecordDecl, LambdaExpr>(
192
3.66k
                  ParentList, this);
193
3.66k
          if (std::get<bool>(AncestorNodes))
194
2
            return std::get<DynTypedNodeList>(AncestorNodes);
195
3.66k
        }
196
3.66k
      }
197
24.3k
      return ParentList;
198
24.3k
    }
199
5.62k
    return getDynNodeFromMap(Node, OtherParents);
200
30.0k
  }
201
202
  DynTypedNodeList AscendIgnoreUnlessSpelledInSource(const Expr *E,
203
55
                                                     const Expr *Child) {
204
205
90
    auto ShouldSkip = [](const Expr *E, const Expr *Child) {
206
90
      if (isa<ImplicitCastExpr>(E))
207
41
        return true;
208
209
49
      if (isa<FullExpr>(E))
210
1
        return true;
211
212
48
      if (isa<MaterializeTemporaryExpr>(E))
213
1
        return true;
214
215
47
      if (isa<CXXBindTemporaryExpr>(E))
216
0
        return true;
217
218
47
      if (isa<ParenExpr>(E))
219
2
        return true;
220
221
45
      if (isa<ExprWithCleanups>(E))
222
0
        return true;
223
224
45
      auto SR = Child->getSourceRange();
225
226
45
      if (const auto *C = dyn_cast<CXXFunctionalCastExpr>(E)) {
227
2
        if (C->getSourceRange() == SR)
228
2
          return true;
229
2
      }
230
231
43
      if (const auto *C = dyn_cast<CXXConstructExpr>(E)) {
232
25
        if (C->getSourceRange() == SR || 
C->isElidable()12
)
233
13
          return true;
234
25
      }
235
236
30
      if (const auto *C = dyn_cast<CXXMemberCallExpr>(E)) {
237
2
        if (C->getSourceRange() == SR)
238
2
          return true;
239
2
      }
240
241
28
      if (const auto *C = dyn_cast<MemberExpr>(E)) {
242
2
        if (C->getSourceRange() == SR)
243
2
          return true;
244
2
      }
245
26
      return false;
246
28
    };
247
248
90
    while (ShouldSkip(E, Child)) {
249
64
      auto It = PointerParents.find(E);
250
64
      if (It == PointerParents.end())
251
0
        break;
252
64
      const auto *S = It->second.dyn_cast<const Stmt *>();
253
64
      if (!S) {
254
13
        if (auto *Vec = It->second.dyn_cast<ParentVector *>())
255
4
          return llvm::makeArrayRef(*Vec);
256
9
        return getSingleDynTypedNodeFromParentMap(It->second);
257
13
      }
258
51
      const auto *P = dyn_cast<Expr>(S);
259
51
      if (!P)
260
16
        return DynTypedNode::create(*S);
261
35
      Child = E;
262
35
      E = P;
263
35
    }
264
26
    return DynTypedNode::create(*E);
265
55
  }
266
};
267
268
template <typename Tuple, std::size_t... Is>
269
44
auto tuple_pop_front_impl(const Tuple &tuple, std::index_sequence<Is...>) {
270
44
  return std::make_tuple(std::get<1 + Is>(tuple)...);
271
44
}
auto tuple_pop_front_impl<std::__1::tuple<clang::DynTypedNodeList, clang::CXXForRangeStmt const*>, 0ul>(std::__1::tuple<clang::DynTypedNodeList, clang::CXXForRangeStmt const*> const&, std::__1::integer_sequence<unsigned long, 0ul>)
Line
Count
Source
269
6
auto tuple_pop_front_impl(const Tuple &tuple, std::index_sequence<Is...>) {
270
6
  return std::make_tuple(std::get<1 + Is>(tuple)...);
271
6
}
auto tuple_pop_front_impl<std::__1::tuple<bool, clang::DynTypedNodeList, clang::CXXForRangeStmt const*>, 0ul, 1ul>(std::__1::tuple<bool, clang::DynTypedNodeList, clang::CXXForRangeStmt const*> const&, std::__1::integer_sequence<unsigned long, 0ul, 1ul>)
Line
Count
Source
269
6
auto tuple_pop_front_impl(const Tuple &tuple, std::index_sequence<Is...>) {
270
6
  return std::make_tuple(std::get<1 + Is>(tuple)...);
271
6
}
auto tuple_pop_front_impl<std::__1::tuple<clang::DynTypedNodeList, clang::DeclStmt const*, clang::CXXForRangeStmt const*>, 0ul, 1ul>(std::__1::tuple<clang::DynTypedNodeList, clang::DeclStmt const*, clang::CXXForRangeStmt const*> const&, std::__1::integer_sequence<unsigned long, 0ul, 1ul>)
Line
Count
Source
269
4
auto tuple_pop_front_impl(const Tuple &tuple, std::index_sequence<Is...>) {
270
4
  return std::make_tuple(std::get<1 + Is>(tuple)...);
271
4
}
auto tuple_pop_front_impl<std::__1::tuple<bool, clang::DynTypedNodeList, clang::DeclStmt const*, clang::CXXForRangeStmt const*>, 0ul, 1ul, 2ul>(std::__1::tuple<bool, clang::DynTypedNodeList, clang::DeclStmt const*, clang::CXXForRangeStmt const*> const&, std::__1::integer_sequence<unsigned long, 0ul, 1ul, 2ul>)
Line
Count
Source
269
4
auto tuple_pop_front_impl(const Tuple &tuple, std::index_sequence<Is...>) {
270
4
  return std::make_tuple(std::get<1 + Is>(tuple)...);
271
4
}
auto tuple_pop_front_impl<std::__1::tuple<clang::DynTypedNodeList, clang::LambdaExpr const*>, 0ul>(std::__1::tuple<clang::DynTypedNodeList, clang::LambdaExpr const*> const&, std::__1::integer_sequence<unsigned long, 0ul>)
Line
Count
Source
269
6
auto tuple_pop_front_impl(const Tuple &tuple, std::index_sequence<Is...>) {
270
6
  return std::make_tuple(std::get<1 + Is>(tuple)...);
271
6
}
auto tuple_pop_front_impl<std::__1::tuple<bool, clang::DynTypedNodeList, clang::LambdaExpr const*>, 0ul, 1ul>(std::__1::tuple<bool, clang::DynTypedNodeList, clang::LambdaExpr const*> const&, std::__1::integer_sequence<unsigned long, 0ul, 1ul>)
Line
Count
Source
269
6
auto tuple_pop_front_impl(const Tuple &tuple, std::index_sequence<Is...>) {
270
6
  return std::make_tuple(std::get<1 + Is>(tuple)...);
271
6
}
auto tuple_pop_front_impl<std::__1::tuple<clang::DynTypedNodeList, clang::CXXRecordDecl const*, clang::LambdaExpr const*>, 0ul, 1ul>(std::__1::tuple<clang::DynTypedNodeList, clang::CXXRecordDecl const*, clang::LambdaExpr const*> const&, std::__1::integer_sequence<unsigned long, 0ul, 1ul>)
Line
Count
Source
269
6
auto tuple_pop_front_impl(const Tuple &tuple, std::index_sequence<Is...>) {
270
6
  return std::make_tuple(std::get<1 + Is>(tuple)...);
271
6
}
auto tuple_pop_front_impl<std::__1::tuple<bool, clang::DynTypedNodeList, clang::CXXRecordDecl const*, clang::LambdaExpr const*>, 0ul, 1ul, 2ul>(std::__1::tuple<bool, clang::DynTypedNodeList, clang::CXXRecordDecl const*, clang::LambdaExpr const*> const&, std::__1::integer_sequence<unsigned long, 0ul, 1ul, 2ul>)
Line
Count
Source
269
6
auto tuple_pop_front_impl(const Tuple &tuple, std::index_sequence<Is...>) {
270
6
  return std::make_tuple(std::get<1 + Is>(tuple)...);
271
6
}
272
273
44
template <typename Tuple> auto tuple_pop_front(const Tuple &tuple) {
274
44
  return tuple_pop_front_impl(
275
44
      tuple, std::make_index_sequence<std::tuple_size<Tuple>::value - 1>());
276
44
}
auto tuple_pop_front<std::__1::tuple<clang::DynTypedNodeList, clang::CXXForRangeStmt const*> >(std::__1::tuple<clang::DynTypedNodeList, clang::CXXForRangeStmt const*> const&)
Line
Count
Source
273
6
template <typename Tuple> auto tuple_pop_front(const Tuple &tuple) {
274
6
  return tuple_pop_front_impl(
275
6
      tuple, std::make_index_sequence<std::tuple_size<Tuple>::value - 1>());
276
6
}
auto tuple_pop_front<std::__1::tuple<bool, clang::DynTypedNodeList, clang::CXXForRangeStmt const*> >(std::__1::tuple<bool, clang::DynTypedNodeList, clang::CXXForRangeStmt const*> const&)
Line
Count
Source
273
6
template <typename Tuple> auto tuple_pop_front(const Tuple &tuple) {
274
6
  return tuple_pop_front_impl(
275
6
      tuple, std::make_index_sequence<std::tuple_size<Tuple>::value - 1>());
276
6
}
auto tuple_pop_front<std::__1::tuple<clang::DynTypedNodeList, clang::DeclStmt const*, clang::CXXForRangeStmt const*> >(std::__1::tuple<clang::DynTypedNodeList, clang::DeclStmt const*, clang::CXXForRangeStmt const*> const&)
Line
Count
Source
273
4
template <typename Tuple> auto tuple_pop_front(const Tuple &tuple) {
274
4
  return tuple_pop_front_impl(
275
4
      tuple, std::make_index_sequence<std::tuple_size<Tuple>::value - 1>());
276
4
}
auto tuple_pop_front<std::__1::tuple<bool, clang::DynTypedNodeList, clang::DeclStmt const*, clang::CXXForRangeStmt const*> >(std::__1::tuple<bool, clang::DynTypedNodeList, clang::DeclStmt const*, clang::CXXForRangeStmt const*> const&)
Line
Count
Source
273
4
template <typename Tuple> auto tuple_pop_front(const Tuple &tuple) {
274
4
  return tuple_pop_front_impl(
275
4
      tuple, std::make_index_sequence<std::tuple_size<Tuple>::value - 1>());
276
4
}
auto tuple_pop_front<std::__1::tuple<clang::DynTypedNodeList, clang::LambdaExpr const*> >(std::__1::tuple<clang::DynTypedNodeList, clang::LambdaExpr const*> const&)
Line
Count
Source
273
6
template <typename Tuple> auto tuple_pop_front(const Tuple &tuple) {
274
6
  return tuple_pop_front_impl(
275
6
      tuple, std::make_index_sequence<std::tuple_size<Tuple>::value - 1>());
276
6
}
auto tuple_pop_front<std::__1::tuple<bool, clang::DynTypedNodeList, clang::LambdaExpr const*> >(std::__1::tuple<bool, clang::DynTypedNodeList, clang::LambdaExpr const*> const&)
Line
Count
Source
273
6
template <typename Tuple> auto tuple_pop_front(const Tuple &tuple) {
274
6
  return tuple_pop_front_impl(
275
6
      tuple, std::make_index_sequence<std::tuple_size<Tuple>::value - 1>());
276
6
}
auto tuple_pop_front<std::__1::tuple<clang::DynTypedNodeList, clang::CXXRecordDecl const*, clang::LambdaExpr const*> >(std::__1::tuple<clang::DynTypedNodeList, clang::CXXRecordDecl const*, clang::LambdaExpr const*> const&)
Line
Count
Source
273
6
template <typename Tuple> auto tuple_pop_front(const Tuple &tuple) {
274
6
  return tuple_pop_front_impl(
275
6
      tuple, std::make_index_sequence<std::tuple_size<Tuple>::value - 1>());
276
6
}
auto tuple_pop_front<std::__1::tuple<bool, clang::DynTypedNodeList, clang::CXXRecordDecl const*, clang::LambdaExpr const*> >(std::__1::tuple<bool, clang::DynTypedNodeList, clang::CXXRecordDecl const*, clang::LambdaExpr const*> const&)
Line
Count
Source
273
6
template <typename Tuple> auto tuple_pop_front(const Tuple &tuple) {
274
6
  return tuple_pop_front_impl(
275
6
      tuple, std::make_index_sequence<std::tuple_size<Tuple>::value - 1>());
276
6
}
277
278
template <typename T, typename... U> struct MatchParents {
279
  static std::tuple<bool, DynTypedNodeList, const T *, const U *...>
280
  match(const DynTypedNodeList &NodeList,
281
14.7k
        ParentMapContext::ParentMap *ParentMap) {
282
14.7k
    if (const auto *TypedNode = NodeList[0].get<T>()) {
283
107
      auto NextParentList =
284
107
          ParentMap->getDynNodeFromMap(TypedNode, ParentMap->PointerParents);
285
107
      if (NextParentList.size() == 1) {
286
107
        auto TailTuple = MatchParents<U...>::match(NextParentList, ParentMap);
287
107
        if (std::get<bool>(TailTuple)) {
288
22
          return std::tuple_cat(
289
22
              std::make_tuple(true, std::get<DynTypedNodeList>(TailTuple),
290
22
                              TypedNode),
291
22
              tuple_pop_front(tuple_pop_front(TailTuple)));
292
22
        }
293
107
      }
294
107
    }
295
14.7k
    return std::tuple_cat(std::make_tuple(false, NodeList),
296
14.7k
                          std::tuple<const T *, const U *...>());
297
14.7k
  }
MatchParents<clang::DeclStmt, clang::CXXForRangeStmt>::match(clang::DynTypedNodeList const&, clang::ParentMapContext::ParentMap*)
Line
Count
Source
281
3.70k
        ParentMapContext::ParentMap *ParentMap) {
282
3.70k
    if (const auto *TypedNode = NodeList[0].get<T>()) {
283
62
      auto NextParentList =
284
62
          ParentMap->getDynNodeFromMap(TypedNode, ParentMap->PointerParents);
285
62
      if (NextParentList.size() == 1) {
286
62
        auto TailTuple = MatchParents<U...>::match(NextParentList, ParentMap);
287
62
        if (std::get<bool>(TailTuple)) {
288
6
          return std::tuple_cat(
289
6
              std::make_tuple(true, std::get<DynTypedNodeList>(TailTuple),
290
6
                              TypedNode),
291
6
              tuple_pop_front(tuple_pop_front(TailTuple)));
292
6
        }
293
62
      }
294
62
    }
295
3.70k
    return std::tuple_cat(std::make_tuple(false, NodeList),
296
3.70k
                          std::tuple<const T *, const U *...>());
297
3.70k
  }
MatchParents<clang::VarDecl, clang::DeclStmt, clang::CXXForRangeStmt>::match(clang::DynTypedNodeList const&, clang::ParentMapContext::ParentMap*)
Line
Count
Source
281
3.67k
        ParentMapContext::ParentMap *ParentMap) {
282
3.67k
    if (const auto *TypedNode = NodeList[0].get<T>()) {
283
31
      auto NextParentList =
284
31
          ParentMap->getDynNodeFromMap(TypedNode, ParentMap->PointerParents);
285
31
      if (NextParentList.size() == 1) {
286
31
        auto TailTuple = MatchParents<U...>::match(NextParentList, ParentMap);
287
31
        if (std::get<bool>(TailTuple)) {
288
4
          return std::tuple_cat(
289
4
              std::make_tuple(true, std::get<DynTypedNodeList>(TailTuple),
290
4
                              TypedNode),
291
4
              tuple_pop_front(tuple_pop_front(TailTuple)));
292
4
        }
293
31
      }
294
31
    }
295
3.67k
    return std::tuple_cat(std::make_tuple(false, NodeList),
296
3.67k
                          std::tuple<const T *, const U *...>());
297
3.67k
  }
MatchParents<clang::CXXMethodDecl, clang::CXXRecordDecl, clang::LambdaExpr>::match(clang::DynTypedNodeList const&, clang::ParentMapContext::ParentMap*)
Line
Count
Source
281
3.67k
        ParentMapContext::ParentMap *ParentMap) {
282
3.67k
    if (const auto *TypedNode = NodeList[0].get<T>()) {
283
6
      auto NextParentList =
284
6
          ParentMap->getDynNodeFromMap(TypedNode, ParentMap->PointerParents);
285
6
      if (NextParentList.size() == 1) {
286
6
        auto TailTuple = MatchParents<U...>::match(NextParentList, ParentMap);
287
6
        if (std::get<bool>(TailTuple)) {
288
4
          return std::tuple_cat(
289
4
              std::make_tuple(true, std::get<DynTypedNodeList>(TailTuple),
290
4
                              TypedNode),
291
4
              tuple_pop_front(tuple_pop_front(TailTuple)));
292
4
        }
293
6
      }
294
6
    }
295
3.66k
    return std::tuple_cat(std::make_tuple(false, NodeList),
296
3.66k
                          std::tuple<const T *, const U *...>());
297
3.67k
  }
MatchParents<clang::CXXRecordDecl, clang::LambdaExpr>::match(clang::DynTypedNodeList const&, clang::ParentMapContext::ParentMap*)
Line
Count
Source
281
8
        ParentMapContext::ParentMap *ParentMap) {
282
8
    if (const auto *TypedNode = NodeList[0].get<T>()) {
283
6
      auto NextParentList =
284
6
          ParentMap->getDynNodeFromMap(TypedNode, ParentMap->PointerParents);
285
6
      if (NextParentList.size() == 1) {
286
6
        auto TailTuple = MatchParents<U...>::match(NextParentList, ParentMap);
287
6
        if (std::get<bool>(TailTuple)) {
288
6
          return std::tuple_cat(
289
6
              std::make_tuple(true, std::get<DynTypedNodeList>(TailTuple),
290
6
                              TypedNode),
291
6
              tuple_pop_front(tuple_pop_front(TailTuple)));
292
6
        }
293
6
      }
294
6
    }
295
2
    return std::tuple_cat(std::make_tuple(false, NodeList),
296
2
                          std::tuple<const T *, const U *...>());
297
8
  }
MatchParents<clang::FunctionTemplateDecl, clang::CXXRecordDecl, clang::LambdaExpr>::match(clang::DynTypedNodeList const&, clang::ParentMapContext::ParentMap*)
Line
Count
Source
281
3.66k
        ParentMapContext::ParentMap *ParentMap) {
282
3.66k
    if (const auto *TypedNode = NodeList[0].get<T>()) {
283
2
      auto NextParentList =
284
2
          ParentMap->getDynNodeFromMap(TypedNode, ParentMap->PointerParents);
285
2
      if (NextParentList.size() == 1) {
286
2
        auto TailTuple = MatchParents<U...>::match(NextParentList, ParentMap);
287
2
        if (std::get<bool>(TailTuple)) {
288
2
          return std::tuple_cat(
289
2
              std::make_tuple(true, std::get<DynTypedNodeList>(TailTuple),
290
2
                              TypedNode),
291
2
              tuple_pop_front(tuple_pop_front(TailTuple)));
292
2
        }
293
2
      }
294
2
    }
295
3.66k
    return std::tuple_cat(std::make_tuple(false, NodeList),
296
3.66k
                          std::tuple<const T *, const U *...>());
297
3.66k
  }
298
};
299
300
template <typename T> struct MatchParents<T> {
301
  static std::tuple<bool, DynTypedNodeList, const T *>
302
  match(const DynTypedNodeList &NodeList,
303
68
        ParentMapContext::ParentMap *ParentMap) {
304
68
    if (const auto *TypedNode = NodeList[0].get<T>()) {
305
12
      auto NextParentList =
306
12
          ParentMap->getDynNodeFromMap(TypedNode, ParentMap->PointerParents);
307
12
      if (NextParentList.size() == 1)
308
12
        return std::make_tuple(true, NodeList, TypedNode);
309
12
    }
310
56
    return std::make_tuple(false, NodeList, nullptr);
311
68
  }
MatchParents<clang::CXXForRangeStmt>::match(clang::DynTypedNodeList const&, clang::ParentMapContext::ParentMap*)
Line
Count
Source
303
62
        ParentMapContext::ParentMap *ParentMap) {
304
62
    if (const auto *TypedNode = NodeList[0].get<T>()) {
305
6
      auto NextParentList =
306
6
          ParentMap->getDynNodeFromMap(TypedNode, ParentMap->PointerParents);
307
6
      if (NextParentList.size() == 1)
308
6
        return std::make_tuple(true, NodeList, TypedNode);
309
6
    }
310
56
    return std::make_tuple(false, NodeList, nullptr);
311
62
  }
MatchParents<clang::LambdaExpr>::match(clang::DynTypedNodeList const&, clang::ParentMapContext::ParentMap*)
Line
Count
Source
303
6
        ParentMapContext::ParentMap *ParentMap) {
304
6
    if (const auto *TypedNode = NodeList[0].get<T>()) {
305
6
      auto NextParentList =
306
6
          ParentMap->getDynNodeFromMap(TypedNode, ParentMap->PointerParents);
307
6
      if (NextParentList.size() == 1)
308
6
        return std::make_tuple(true, NodeList, TypedNode);
309
6
    }
310
0
    return std::make_tuple(false, NodeList, nullptr);
311
6
  }
312
};
313
314
template <typename T, typename... U>
315
std::tuple<bool, DynTypedNodeList, const T *, const U *...>
316
matchParents(const DynTypedNodeList &NodeList,
317
14.6k
             ParentMapContext::ParentMap *ParentMap) {
318
14.6k
  return MatchParents<T, U...>::match(NodeList, ParentMap);
319
14.6k
}
std::__1::tuple<bool, clang::DynTypedNodeList, clang::DeclStmt const*, clang::CXXForRangeStmt const*> matchParents<clang::DeclStmt, clang::CXXForRangeStmt>(clang::DynTypedNodeList const&, clang::ParentMapContext::ParentMap*)
Line
Count
Source
317
3.67k
             ParentMapContext::ParentMap *ParentMap) {
318
3.67k
  return MatchParents<T, U...>::match(NodeList, ParentMap);
319
3.67k
}
std::__1::tuple<bool, clang::DynTypedNodeList, clang::VarDecl const*, clang::DeclStmt const*, clang::CXXForRangeStmt const*> matchParents<clang::VarDecl, clang::DeclStmt, clang::CXXForRangeStmt>(clang::DynTypedNodeList const&, clang::ParentMapContext::ParentMap*)
Line
Count
Source
317
3.67k
             ParentMapContext::ParentMap *ParentMap) {
318
3.67k
  return MatchParents<T, U...>::match(NodeList, ParentMap);
319
3.67k
}
std::__1::tuple<bool, clang::DynTypedNodeList, clang::CXXMethodDecl const*, clang::CXXRecordDecl const*, clang::LambdaExpr const*> matchParents<clang::CXXMethodDecl, clang::CXXRecordDecl, clang::LambdaExpr>(clang::DynTypedNodeList const&, clang::ParentMapContext::ParentMap*)
Line
Count
Source
317
3.67k
             ParentMapContext::ParentMap *ParentMap) {
318
3.67k
  return MatchParents<T, U...>::match(NodeList, ParentMap);
319
3.67k
}
std::__1::tuple<bool, clang::DynTypedNodeList, clang::FunctionTemplateDecl const*, clang::CXXRecordDecl const*, clang::LambdaExpr const*> matchParents<clang::FunctionTemplateDecl, clang::CXXRecordDecl, clang::LambdaExpr>(clang::DynTypedNodeList const&, clang::ParentMapContext::ParentMap*)
Line
Count
Source
317
3.66k
             ParentMapContext::ParentMap *ParentMap) {
318
3.66k
  return MatchParents<T, U...>::match(NodeList, ParentMap);
319
3.66k
}
320
321
/// Template specializations to abstract away from pointers and TypeLocs.
322
/// @{
323
352k
template <typename T> static DynTypedNode createDynTypedNode(const T &Node) {
324
352k
  return DynTypedNode::create(*Node);
325
352k
}
ParentMapContext.cpp:clang::DynTypedNode createDynTypedNode<clang::Decl*>(clang::Decl* const&)
Line
Count
Source
323
350k
template <typename T> static DynTypedNode createDynTypedNode(const T &Node) {
324
350k
  return DynTypedNode::create(*Node);
325
350k
}
ParentMapContext.cpp:clang::DynTypedNode createDynTypedNode<clang::Attr*>(clang::Attr* const&)
Line
Count
Source
323
1.85k
template <typename T> static DynTypedNode createDynTypedNode(const T &Node) {
324
1.85k
  return DynTypedNode::create(*Node);
325
1.85k
}
326
620k
template <> DynTypedNode createDynTypedNode(const TypeLoc &Node) {
327
620k
  return DynTypedNode::create(Node);
328
620k
}
329
template <>
330
122k
DynTypedNode createDynTypedNode(const NestedNameSpecifierLoc &Node) {
331
122k
  return DynTypedNode::create(Node);
332
122k
}
333
6
template <> DynTypedNode createDynTypedNode(const ObjCProtocolLoc &Node) {
334
6
  return DynTypedNode::create(Node);
335
6
}
336
/// @}
337
338
/// A \c RecursiveASTVisitor that builds a map from nodes to their
339
/// parents as defined by the \c RecursiveASTVisitor.
340
///
341
/// Note that the relationship described here is purely in terms of AST
342
/// traversal - there are other relationships (for example declaration context)
343
/// in the AST that are better modeled by special matchers.
344
class ParentMapContext::ParentMap::ASTVisitor
345
    : public RecursiveASTVisitor<ASTVisitor> {
346
public:
347
1.69k
  ASTVisitor(ParentMap &Map) : Map(Map) {}
348
349
private:
350
  friend class RecursiveASTVisitor<ASTVisitor>;
351
352
  using VisitorBase = RecursiveASTVisitor<ASTVisitor>;
353
354
54.6k
  bool shouldVisitTemplateInstantiations() const { return true; }
355
356
370k
  bool shouldVisitImplicitCode() const { return true; }
357
358
  /// Record the parent of the node we're visiting.
359
  /// MapNode is the child, the parent is on top of ParentStack.
360
  /// Parents is the parent storage (either PointerParents or OtherParents).
361
  template <typename MapNodeTy, typename MapTy>
362
1.27M
  void addParent(MapNodeTy MapNode, MapTy *Parents) {
363
1.27M
    if (ParentStack.empty())
364
1.69k
      return;
365
366
    // FIXME: Currently we add the same parent multiple times, but only
367
    // when no memoization data is available for the type.
368
    // For example when we visit all subexpressions of template
369
    // instantiations; this is suboptimal, but benign: the only way to
370
    // visit those is with hasAncestor / hasParent, and those do not create
371
    // new matches.
372
    // The plan is to enable DynTypedNode to be storable in a map or hash
373
    // map. The main problem there is to implement hash functions /
374
    // comparison operators for all types that DynTypedNode supports that
375
    // do not have pointer identity.
376
1.27M
    auto &NodeOrVector = (*Parents)[MapNode];
377
1.27M
    if (NodeOrVector.isNull()) {
378
1.24M
      if (const auto *D = ParentStack.back().get<Decl>())
379
500k
        NodeOrVector = D;
380
745k
      else if (const auto *S = ParentStack.back().get<Stmt>())
381
189k
        NodeOrVector = S;
382
556k
      else
383
556k
        NodeOrVector = new DynTypedNode(ParentStack.back());
384
1.24M
    } else {
385
28.4k
      if (!NodeOrVector.template is<ParentVector *>()) {
386
20.0k
        auto *Vector = new ParentVector(
387
20.0k
            1, getSingleDynTypedNodeFromParentMap(NodeOrVector));
388
20.0k
        delete NodeOrVector.template dyn_cast<DynTypedNode *>();
389
20.0k
        NodeOrVector = Vector;
390
20.0k
      }
391
392
28.4k
      auto *Vector = NodeOrVector.template get<ParentVector *>();
393
      // Skip duplicates for types that have memoization data.
394
      // We must check that the type has memoization data before calling
395
      // llvm::is_contained() because DynTypedNode::operator== can't compare all
396
      // types.
397
28.4k
      bool Found = ParentStack.back().getMemoizationData() &&
398
28.4k
                   
llvm::is_contained(*Vector, ParentStack.back())13.9k
;
399
28.4k
      if (!Found)
400
27.7k
        Vector->push_back(ParentStack.back());
401
28.4k
    }
402
1.27M
  }
void clang::ParentMapContext::ParentMap::ASTVisitor::addParent<clang::Decl*, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > >(clang::Decl*, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > >*)
Line
Count
Source
362
350k
  void addParent(MapNodeTy MapNode, MapTy *Parents) {
363
350k
    if (ParentStack.empty())
364
1.69k
      return;
365
366
    // FIXME: Currently we add the same parent multiple times, but only
367
    // when no memoization data is available for the type.
368
    // For example when we visit all subexpressions of template
369
    // instantiations; this is suboptimal, but benign: the only way to
370
    // visit those is with hasAncestor / hasParent, and those do not create
371
    // new matches.
372
    // The plan is to enable DynTypedNode to be storable in a map or hash
373
    // map. The main problem there is to implement hash functions /
374
    // comparison operators for all types that DynTypedNode supports that
375
    // do not have pointer identity.
376
348k
    auto &NodeOrVector = (*Parents)[MapNode];
377
348k
    if (NodeOrVector.isNull()) {
378
348k
      if (const auto *D = ParentStack.back().get<Decl>())
379
309k
        NodeOrVector = D;
380
38.9k
      else if (const auto *S = ParentStack.back().get<Stmt>())
381
2.55k
        NodeOrVector = S;
382
36.3k
      else
383
36.3k
        NodeOrVector = new DynTypedNode(ParentStack.back());
384
348k
    } else {
385
306
      if (!NodeOrVector.template is<ParentVector *>()) {
386
184
        auto *Vector = new ParentVector(
387
184
            1, getSingleDynTypedNodeFromParentMap(NodeOrVector));
388
184
        delete NodeOrVector.template dyn_cast<DynTypedNode *>();
389
184
        NodeOrVector = Vector;
390
184
      }
391
392
306
      auto *Vector = NodeOrVector.template get<ParentVector *>();
393
      // Skip duplicates for types that have memoization data.
394
      // We must check that the type has memoization data before calling
395
      // llvm::is_contained() because DynTypedNode::operator== can't compare all
396
      // types.
397
306
      bool Found = ParentStack.back().getMemoizationData() &&
398
306
                   
llvm::is_contained(*Vector, ParentStack.back())158
;
399
306
      if (!Found)
400
306
        Vector->push_back(ParentStack.back());
401
306
    }
402
348k
  }
void clang::ParentMapContext::ParentMap::ASTVisitor::addParent<clang::DynTypedNode, llvm::DenseMap<clang::DynTypedNode, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<clang::DynTypedNode, void>, llvm::detail::DenseMapPair<clang::DynTypedNode, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > >(clang::DynTypedNode, llvm::DenseMap<clang::DynTypedNode, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<clang::DynTypedNode, void>, llvm::detail::DenseMapPair<clang::DynTypedNode, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > >*)
Line
Count
Source
362
743k
  void addParent(MapNodeTy MapNode, MapTy *Parents) {
363
743k
    if (ParentStack.empty())
364
0
      return;
365
366
    // FIXME: Currently we add the same parent multiple times, but only
367
    // when no memoization data is available for the type.
368
    // For example when we visit all subexpressions of template
369
    // instantiations; this is suboptimal, but benign: the only way to
370
    // visit those is with hasAncestor / hasParent, and those do not create
371
    // new matches.
372
    // The plan is to enable DynTypedNode to be storable in a map or hash
373
    // map. The main problem there is to implement hash functions /
374
    // comparison operators for all types that DynTypedNode supports that
375
    // do not have pointer identity.
376
743k
    auto &NodeOrVector = (*Parents)[MapNode];
377
743k
    if (NodeOrVector.isNull()) {
378
719k
      if (const auto *D = ParentStack.back().get<Decl>())
379
169k
        NodeOrVector = D;
380
550k
      else if (const auto *S = ParentStack.back().get<Stmt>())
381
56.3k
        NodeOrVector = S;
382
494k
      else
383
494k
        NodeOrVector = new DynTypedNode(ParentStack.back());
384
719k
    } else {
385
23.8k
      if (!NodeOrVector.template is<ParentVector *>()) {
386
16.9k
        auto *Vector = new ParentVector(
387
16.9k
            1, getSingleDynTypedNodeFromParentMap(NodeOrVector));
388
16.9k
        delete NodeOrVector.template dyn_cast<DynTypedNode *>();
389
16.9k
        NodeOrVector = Vector;
390
16.9k
      }
391
392
23.8k
      auto *Vector = NodeOrVector.template get<ParentVector *>();
393
      // Skip duplicates for types that have memoization data.
394
      // We must check that the type has memoization data before calling
395
      // llvm::is_contained() because DynTypedNode::operator== can't compare all
396
      // types.
397
23.8k
      bool Found = ParentStack.back().getMemoizationData() &&
398
23.8k
                   
llvm::is_contained(*Vector, ParentStack.back())9.47k
;
399
23.8k
      if (!Found)
400
23.5k
        Vector->push_back(ParentStack.back());
401
23.8k
    }
402
743k
  }
void clang::ParentMapContext::ParentMap::ASTVisitor::addParent<clang::Stmt*, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > >(clang::Stmt*, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > >*)
Line
Count
Source
362
180k
  void addParent(MapNodeTy MapNode, MapTy *Parents) {
363
180k
    if (ParentStack.empty())
364
0
      return;
365
366
    // FIXME: Currently we add the same parent multiple times, but only
367
    // when no memoization data is available for the type.
368
    // For example when we visit all subexpressions of template
369
    // instantiations; this is suboptimal, but benign: the only way to
370
    // visit those is with hasAncestor / hasParent, and those do not create
371
    // new matches.
372
    // The plan is to enable DynTypedNode to be storable in a map or hash
373
    // map. The main problem there is to implement hash functions /
374
    // comparison operators for all types that DynTypedNode supports that
375
    // do not have pointer identity.
376
180k
    auto &NodeOrVector = (*Parents)[MapNode];
377
180k
    if (NodeOrVector.isNull()) {
378
176k
      if (const auto *D = ParentStack.back().get<Decl>())
379
19.9k
        NodeOrVector = D;
380
156k
      else if (const auto *S = ParentStack.back().get<Stmt>())
381
130k
        NodeOrVector = S;
382
25.9k
      else
383
25.9k
        NodeOrVector = new DynTypedNode(ParentStack.back());
384
176k
    } else {
385
4.28k
      if (!NodeOrVector.template is<ParentVector *>()) {
386
2.92k
        auto *Vector = new ParentVector(
387
2.92k
            1, getSingleDynTypedNodeFromParentMap(NodeOrVector));
388
2.92k
        delete NodeOrVector.template dyn_cast<DynTypedNode *>();
389
2.92k
        NodeOrVector = Vector;
390
2.92k
      }
391
392
4.28k
      auto *Vector = NodeOrVector.template get<ParentVector *>();
393
      // Skip duplicates for types that have memoization data.
394
      // We must check that the type has memoization data before calling
395
      // llvm::is_contained() because DynTypedNode::operator== can't compare all
396
      // types.
397
4.28k
      bool Found = ParentStack.back().getMemoizationData() &&
398
4.28k
                   llvm::is_contained(*Vector, ParentStack.back());
399
4.28k
      if (!Found)
400
3.96k
        Vector->push_back(ParentStack.back());
401
4.28k
    }
402
180k
  }
void clang::ParentMapContext::ParentMap::ASTVisitor::addParent<clang::Attr*, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > >(clang::Attr*, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > >*)
Line
Count
Source
362
1.85k
  void addParent(MapNodeTy MapNode, MapTy *Parents) {
363
1.85k
    if (ParentStack.empty())
364
0
      return;
365
366
    // FIXME: Currently we add the same parent multiple times, but only
367
    // when no memoization data is available for the type.
368
    // For example when we visit all subexpressions of template
369
    // instantiations; this is suboptimal, but benign: the only way to
370
    // visit those is with hasAncestor / hasParent, and those do not create
371
    // new matches.
372
    // The plan is to enable DynTypedNode to be storable in a map or hash
373
    // map. The main problem there is to implement hash functions /
374
    // comparison operators for all types that DynTypedNode supports that
375
    // do not have pointer identity.
376
1.85k
    auto &NodeOrVector = (*Parents)[MapNode];
377
1.85k
    if (NodeOrVector.isNull()) {
378
1.85k
      if (const auto *D = ParentStack.back().get<Decl>())
379
1.85k
        NodeOrVector = D;
380
0
      else if (const auto *S = ParentStack.back().get<Stmt>())
381
0
        NodeOrVector = S;
382
0
      else
383
0
        NodeOrVector = new DynTypedNode(ParentStack.back());
384
1.85k
    } else {
385
0
      if (!NodeOrVector.template is<ParentVector *>()) {
386
0
        auto *Vector = new ParentVector(
387
0
            1, getSingleDynTypedNodeFromParentMap(NodeOrVector));
388
0
        delete NodeOrVector.template dyn_cast<DynTypedNode *>();
389
0
        NodeOrVector = Vector;
390
0
      }
391
392
0
      auto *Vector = NodeOrVector.template get<ParentVector *>();
393
      // Skip duplicates for types that have memoization data.
394
      // We must check that the type has memoization data before calling
395
      // llvm::is_contained() because DynTypedNode::operator== can't compare all
396
      // types.
397
0
      bool Found = ParentStack.back().getMemoizationData() &&
398
0
                   llvm::is_contained(*Vector, ParentStack.back());
399
0
      if (!Found)
400
0
        Vector->push_back(ParentStack.back());
401
0
    }
402
1.85k
  }
403
404
1.30M
  template <typename T> static bool isNull(T Node) { return !Node; }
bool clang::ParentMapContext::ParentMap::ASTVisitor::isNull<clang::Decl*>(clang::Decl*)
Line
Count
Source
404
351k
  template <typename T> static bool isNull(T Node) { return !Node; }
bool clang::ParentMapContext::ParentMap::ASTVisitor::isNull<clang::NestedNameSpecifierLoc>(clang::NestedNameSpecifierLoc)
Line
Count
Source
404
333k
  template <typename T> static bool isNull(T Node) { return !Node; }
bool clang::ParentMapContext::ParentMap::ASTVisitor::isNull<clang::TypeLoc>(clang::TypeLoc)
Line
Count
Source
404
620k
  template <typename T> static bool isNull(T Node) { return !Node; }
bool clang::ParentMapContext::ParentMap::ASTVisitor::isNull<clang::Attr*>(clang::Attr*)
Line
Count
Source
404
1.85k
  template <typename T> static bool isNull(T Node) { return !Node; }
405
6
  static bool isNull(ObjCProtocolLoc Node) { return false; }
406
407
  template <typename T, typename MapNodeTy, typename BaseTraverseFn,
408
            typename MapTy>
409
  bool TraverseNode(T Node, MapNodeTy MapNode, BaseTraverseFn BaseTraverse,
410
1.30M
                    MapTy *Parents) {
411
1.30M
    if (isNull(Node))
412
211k
      return true;
413
1.09M
    addParent(MapNode, Parents);
414
1.09M
    ParentStack.push_back(createDynTypedNode(Node));
415
1.09M
    bool Result = BaseTraverse();
416
1.09M
    ParentStack.pop_back();
417
1.09M
    return Result;
418
1.30M
  }
bool clang::ParentMapContext::ParentMap::ASTVisitor::TraverseNode<clang::Decl*, clang::Decl*, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseDecl(clang::Decl*)::'lambda'(), llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > >(clang::Decl*, clang::Decl*, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseDecl(clang::Decl*)::'lambda'(), llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > >*)
Line
Count
Source
410
351k
                    MapTy *Parents) {
411
351k
    if (isNull(Node))
412
960
      return true;
413
350k
    addParent(MapNode, Parents);
414
350k
    ParentStack.push_back(createDynTypedNode(Node));
415
350k
    bool Result = BaseTraverse();
416
350k
    ParentStack.pop_back();
417
350k
    return Result;
418
351k
  }
bool clang::ParentMapContext::ParentMap::ASTVisitor::TraverseNode<clang::NestedNameSpecifierLoc, clang::DynTypedNode, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseNestedNameSpecifierLoc(clang::NestedNameSpecifierLoc)::'lambda'(), llvm::DenseMap<clang::DynTypedNode, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<clang::DynTypedNode, void>, llvm::detail::DenseMapPair<clang::DynTypedNode, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > >(clang::NestedNameSpecifierLoc, clang::DynTypedNode, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseNestedNameSpecifierLoc(clang::NestedNameSpecifierLoc)::'lambda'(), llvm::DenseMap<clang::DynTypedNode, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<clang::DynTypedNode, void>, llvm::detail::DenseMapPair<clang::DynTypedNode, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > >*)
Line
Count
Source
410
333k
                    MapTy *Parents) {
411
333k
    if (isNull(Node))
412
210k
      return true;
413
122k
    addParent(MapNode, Parents);
414
122k
    ParentStack.push_back(createDynTypedNode(Node));
415
122k
    bool Result = BaseTraverse();
416
122k
    ParentStack.pop_back();
417
122k
    return Result;
418
333k
  }
bool clang::ParentMapContext::ParentMap::ASTVisitor::TraverseNode<clang::TypeLoc, clang::DynTypedNode, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseTypeLoc(clang::TypeLoc)::'lambda'(), llvm::DenseMap<clang::DynTypedNode, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<clang::DynTypedNode, void>, llvm::detail::DenseMapPair<clang::DynTypedNode, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > >(clang::TypeLoc, clang::DynTypedNode, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseTypeLoc(clang::TypeLoc)::'lambda'(), llvm::DenseMap<clang::DynTypedNode, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<clang::DynTypedNode, void>, llvm::detail::DenseMapPair<clang::DynTypedNode, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > >*)
Line
Count
Source
410
620k
                    MapTy *Parents) {
411
620k
    if (isNull(Node))
412
0
      return true;
413
620k
    addParent(MapNode, Parents);
414
620k
    ParentStack.push_back(createDynTypedNode(Node));
415
620k
    bool Result = BaseTraverse();
416
620k
    ParentStack.pop_back();
417
620k
    return Result;
418
620k
  }
bool clang::ParentMapContext::ParentMap::ASTVisitor::TraverseNode<clang::ObjCProtocolLoc, clang::DynTypedNode, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseObjCProtocolLoc(clang::ObjCProtocolLoc)::'lambda'(), llvm::DenseMap<clang::DynTypedNode, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<clang::DynTypedNode, void>, llvm::detail::DenseMapPair<clang::DynTypedNode, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > >(clang::ObjCProtocolLoc, clang::DynTypedNode, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseObjCProtocolLoc(clang::ObjCProtocolLoc)::'lambda'(), llvm::DenseMap<clang::DynTypedNode, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<clang::DynTypedNode, void>, llvm::detail::DenseMapPair<clang::DynTypedNode, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > >*)
Line
Count
Source
410
6
                    MapTy *Parents) {
411
6
    if (isNull(Node))
412
0
      return true;
413
6
    addParent(MapNode, Parents);
414
6
    ParentStack.push_back(createDynTypedNode(Node));
415
6
    bool Result = BaseTraverse();
416
6
    ParentStack.pop_back();
417
6
    return Result;
418
6
  }
bool clang::ParentMapContext::ParentMap::ASTVisitor::TraverseNode<clang::Attr*, clang::Attr*, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseAttr(clang::Attr*)::'lambda'(), llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > >(clang::Attr*, clang::Attr*, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseAttr(clang::Attr*)::'lambda'(), llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > >*)
Line
Count
Source
410
1.85k
                    MapTy *Parents) {
411
1.85k
    if (isNull(Node))
412
0
      return true;
413
1.85k
    addParent(MapNode, Parents);
414
1.85k
    ParentStack.push_back(createDynTypedNode(Node));
415
1.85k
    bool Result = BaseTraverse();
416
1.85k
    ParentStack.pop_back();
417
1.85k
    return Result;
418
1.85k
  }
419
420
351k
  bool TraverseDecl(Decl *DeclNode) {
421
351k
    return TraverseNode(
422
351k
        DeclNode, DeclNode, [&] 
{ return VisitorBase::TraverseDecl(DeclNode); }350k
,
423
351k
        &Map.PointerParents);
424
351k
  }
425
620k
  bool TraverseTypeLoc(TypeLoc TypeLocNode) {
426
620k
    return TraverseNode(
427
620k
        TypeLocNode, DynTypedNode::create(TypeLocNode),
428
620k
        [&] { return VisitorBase::TraverseTypeLoc(TypeLocNode); },
429
620k
        &Map.OtherParents);
430
620k
  }
431
333k
  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSLocNode) {
432
333k
    return TraverseNode(
433
333k
        NNSLocNode, DynTypedNode::create(NNSLocNode),
434
333k
        [&] 
{ return VisitorBase::TraverseNestedNameSpecifierLoc(NNSLocNode); }122k
,
435
333k
        &Map.OtherParents);
436
333k
  }
437
1.85k
  bool TraverseAttr(Attr *AttrNode) {
438
1.85k
    return TraverseNode(
439
1.85k
        AttrNode, AttrNode, [&] { return VisitorBase::TraverseAttr(AttrNode); },
440
1.85k
        &Map.PointerParents);
441
1.85k
  }
442
6
  bool TraverseObjCProtocolLoc(ObjCProtocolLoc ProtocolLocNode) {
443
6
    return TraverseNode(
444
6
        ProtocolLocNode, DynTypedNode::create(ProtocolLocNode),
445
6
        [&] { return VisitorBase::TraverseObjCProtocolLoc(ProtocolLocNode); },
446
6
        &Map.OtherParents);
447
6
  }
448
449
  // Using generic TraverseNode for Stmt would prevent data-recursion.
450
180k
  bool dataTraverseStmtPre(Stmt *StmtNode) {
451
180k
    addParent(StmtNode, &Map.PointerParents);
452
180k
    ParentStack.push_back(DynTypedNode::create(*StmtNode));
453
180k
    return true;
454
180k
  }
455
180k
  bool dataTraverseStmtPost(Stmt *StmtNode) {
456
180k
    ParentStack.pop_back();
457
180k
    return true;
458
180k
  }
459
460
  ParentMap &Map;
461
  llvm::SmallVector<DynTypedNode, 16> ParentStack;
462
};
463
464
1.69k
ParentMapContext::ParentMap::ParentMap(ASTContext &Ctx) {
465
1.69k
  ASTVisitor(*this).TraverseAST(Ctx);
466
1.69k
}
467
468
30.0k
DynTypedNodeList ParentMapContext::getParents(const DynTypedNode &Node) {
469
30.0k
  if (!Parents)
470
    // We build the parent map for the traversal scope (usually whole TU), as
471
    // hasAncestor can escape any subtree.
472
1.69k
    Parents = std::make_unique<ParentMap>(ASTCtx);
473
30.0k
  return Parents->getParents(getTraversalKind(), Node);
474
30.0k
}