Coverage Report

Created: 2021-09-21 08:58

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/AST/ASTImporterLookupTable.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- ASTImporterLookupTable.cpp - ASTImporter specific lookup -----------===//
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 the ASTImporterLookupTable class which implements a
10
//  lookup procedure for the import mechanism.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "clang/AST/ASTImporterLookupTable.h"
15
#include "clang/AST/Decl.h"
16
#include "clang/AST/RecursiveASTVisitor.h"
17
18
namespace clang {
19
20
namespace {
21
22
struct Builder : RecursiveASTVisitor<Builder> {
23
  ASTImporterLookupTable &LT;
24
2.27k
  Builder(ASTImporterLookupTable &LT) : LT(LT) {}
25
26
11.7k
  bool VisitTypedefNameDecl(TypedefNameDecl *D) {
27
11.7k
    QualType Ty = D->getUnderlyingType();
28
11.7k
    Ty = Ty.getCanonicalType();
29
11.7k
    if (const auto *RTy = dyn_cast<RecordType>(Ty)) {
30
2.13k
      LT.add(RTy->getAsRecordDecl());
31
      // iterate over the field decls, adding them
32
8.47k
      for (auto *it : RTy->getAsRecordDecl()->fields()) {
33
8.47k
        LT.add(it);
34
8.47k
      }
35
2.13k
    }
36
11.7k
    return true;
37
11.7k
  }
38
39
17.5k
  bool VisitNamedDecl(NamedDecl *D) {
40
17.5k
    LT.add(D);
41
17.5k
    return true;
42
17.5k
  }
43
  // In most cases the FriendDecl contains the declaration of the befriended
44
  // class as a child node, so it is discovered during the recursive
45
  // visitation. However, there are cases when the befriended class is not a
46
  // child, thus it must be fetched explicitly from the FriendDecl, and only
47
  // then can we add it to the lookup table.
48
132
  bool VisitFriendDecl(FriendDecl *D) {
49
132
    if (D->getFriendType()) {
50
76
      QualType Ty = D->getFriendType()->getType();
51
76
      if (isa<ElaboratedType>(Ty))
52
52
        Ty = cast<ElaboratedType>(Ty)->getNamedType();
53
      // A FriendDecl with a dependent type (e.g. ClassTemplateSpecialization)
54
      // always has that decl as child node.
55
      // However, there are non-dependent cases which does not have the
56
      // type as a child node. We have to dig up that type now.
57
76
      if (!Ty->isDependentType()) {
58
64
        if (const auto *RTy = dyn_cast<RecordType>(Ty))
59
44
          LT.add(RTy->getAsCXXRecordDecl());
60
20
        else if (const auto *SpecTy = dyn_cast<TemplateSpecializationType>(Ty))
61
8
          LT.add(SpecTy->getAsCXXRecordDecl());
62
12
        else if (const auto *SubstTy =
63
12
                     dyn_cast<SubstTemplateTypeParmType>(Ty)) {
64
4
          if (SubstTy->getAsCXXRecordDecl())
65
4
            LT.add(SubstTy->getAsCXXRecordDecl());
66
8
        } else if (isa<TypedefType>(Ty)) {
67
          // We do not put friend typedefs to the lookup table because
68
          // ASTImporter does not organize typedefs into redecl chains.
69
8
        } else {
70
0
          llvm_unreachable("Unhandled type of friend class");
71
0
        }
72
64
      }
73
76
    }
74
132
    return true;
75
132
  }
76
77
  // Override default settings of base.
78
416
  bool shouldVisitTemplateInstantiations() const { return true; }
79
20.6k
  bool shouldVisitImplicitCode() const { return true; }
80
};
81
82
} // anonymous namespace
83
84
2.27k
ASTImporterLookupTable::ASTImporterLookupTable(TranslationUnitDecl &TU) {
85
2.27k
  Builder B(*this);
86
2.27k
  B.TraverseDecl(&TU);
87
2.27k
}
88
89
44.6k
void ASTImporterLookupTable::add(DeclContext *DC, NamedDecl *ND) {
90
44.6k
  DeclList &Decls = LookupTable[DC][ND->getDeclName()];
91
  // Inserts if and only if there is no element in the container equal to it.
92
44.6k
  Decls.insert(ND);
93
44.6k
}
94
95
1.99k
void ASTImporterLookupTable::remove(DeclContext *DC, NamedDecl *ND) {
96
1.99k
  DeclList &Decls = LookupTable[DC][ND->getDeclName()];
97
1.99k
  bool EraseResult = Decls.remove(ND);
98
1.99k
  (void)EraseResult;
99
1.99k
  assert(EraseResult == true && "Trying to remove not contained Decl");
100
1.99k
}
101
102
44.5k
void ASTImporterLookupTable::add(NamedDecl *ND) {
103
44.5k
  assert(ND);
104
0
  DeclContext *DC = ND->getDeclContext()->getPrimaryContext();
105
44.5k
  add(DC, ND);
106
44.5k
  DeclContext *ReDC = DC->getRedeclContext()->getPrimaryContext();
107
44.5k
  if (DC != ReDC)
108
111
    add(ReDC, ND);
109
44.5k
}
110
111
125
void ASTImporterLookupTable::remove(NamedDecl *ND) {
112
125
  assert(ND);
113
0
  DeclContext *DC = ND->getDeclContext()->getPrimaryContext();
114
125
  remove(DC, ND);
115
125
  DeclContext *ReDC = DC->getRedeclContext()->getPrimaryContext();
116
125
  if (DC != ReDC)
117
0
    remove(ReDC, ND);
118
125
}
119
120
1.86k
void ASTImporterLookupTable::update(NamedDecl *ND, DeclContext *OldDC) {
121
1.86k
  assert(OldDC != ND->getDeclContext() &&
122
1.86k
         "DeclContext should be changed before update");
123
1.86k
  if (contains(ND->getDeclContext(), ND)) {
124
0
    assert(!contains(OldDC, ND) &&
125
0
           "Decl should not be found in the old context if already in the new");
126
0
    return;
127
0
  }
128
129
1.86k
  remove(OldDC, ND);
130
1.86k
  add(ND);
131
1.86k
}
132
133
ASTImporterLookupTable::LookupResult
134
13.0k
ASTImporterLookupTable::lookup(DeclContext *DC, DeclarationName Name) const {
135
13.0k
  auto DCI = LookupTable.find(DC->getPrimaryContext());
136
13.0k
  if (DCI == LookupTable.end())
137
3.11k
    return {};
138
139
9.95k
  const auto &FoundNameMap = DCI->second;
140
9.95k
  auto NamesI = FoundNameMap.find(Name);
141
9.95k
  if (NamesI == FoundNameMap.end())
142
5.69k
    return {};
143
144
4.25k
  return NamesI->second;
145
9.95k
}
146
147
1.90k
bool ASTImporterLookupTable::contains(DeclContext *DC, NamedDecl *ND) const {
148
1.90k
  return 0 < lookup(DC, ND->getDeclName()).count(ND);
149
1.90k
}
150
151
0
void ASTImporterLookupTable::dump(DeclContext *DC) const {
152
0
  auto DCI = LookupTable.find(DC->getPrimaryContext());
153
0
  if (DCI == LookupTable.end())
154
0
    llvm::errs() << "empty\n";
155
0
  const auto &FoundNameMap = DCI->second;
156
0
  for (const auto &Entry : FoundNameMap) {
157
0
    DeclarationName Name = Entry.first;
158
0
    llvm::errs() << "==== Name: ";
159
0
    Name.dump();
160
0
    const DeclList& List = Entry.second;
161
0
    for (NamedDecl *ND : List) {
162
0
      ND->dump();
163
0
    }
164
0
  }
165
0
}
166
167
0
void ASTImporterLookupTable::dump() const {
168
0
  for (const auto &Entry : LookupTable) {
169
0
    DeclContext *DC = Entry.first;
170
0
    StringRef Primary = DC->getPrimaryContext() ? " primary" : "";
171
0
    llvm::errs() << "== DC:" << cast<Decl>(DC) << Primary << "\n";
172
0
    dump(DC);
173
0
  }
174
0
}
175
176
} // namespace clang