Coverage Report

Created: 2022-01-25 06:29

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