Coverage Report

Created: 2020-02-18 08:44

/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
1.99k
  Builder(ASTImporterLookupTable &LT) : LT(LT) {}
25
14.5k
  bool VisitNamedDecl(NamedDecl *D) {
26
14.5k
    LT.add(D);
27
14.5k
    return true;
28
14.5k
  }
29
  // In most cases the FriendDecl contains the declaration of the befriended
30
  // class as a child node, so it is discovered during the recursive
31
  // visitation. However, there are cases when the befriended class is not a
32
  // child, thus it must be fetched explicitly from the FriendDecl, and only
33
  // then can we add it to the lookup table.
34
108
  bool VisitFriendDecl(FriendDecl *D) {
35
108
    if (D->getFriendType()) {
36
60
      QualType Ty = D->getFriendType()->getType();
37
60
      if (isa<ElaboratedType>(Ty))
38
44
        Ty = cast<ElaboratedType>(Ty)->getNamedType();
39
60
      // A FriendDecl with a dependent type (e.g. ClassTemplateSpecialization)
40
60
      // always has that decl as child node.
41
60
      // However, there are non-dependent cases which does not have the
42
60
      // type as a child node. We have to dig up that type now.
43
60
      if (!Ty->isDependentType()) {
44
52
        if (const auto *RTy = dyn_cast<RecordType>(Ty))
45
36
          LT.add(RTy->getAsCXXRecordDecl());
46
16
        else if (const auto *SpecTy = dyn_cast<TemplateSpecializationType>(Ty))
47
8
          LT.add(SpecTy->getAsCXXRecordDecl());
48
8
        else if (isa<TypedefType>(Ty)) {
49
8
          // We do not put friend typedefs to the lookup table because
50
8
          // ASTImporter does not organize typedefs into redecl chains.
51
8
        } else {
52
0
          llvm_unreachable("Unhandled type of friend class");
53
0
        }
54
108
      }
55
60
    }
56
108
    return true;
57
108
  }
58
59
  // Override default settings of base.
60
360
  bool shouldVisitTemplateInstantiations() const { return true; }
61
17.3k
  bool shouldVisitImplicitCode() const { return true; }
62
};
63
64
} // anonymous namespace
65
66
1.99k
ASTImporterLookupTable::ASTImporterLookupTable(TranslationUnitDecl &TU) {
67
1.99k
  Builder B(*this);
68
1.99k
  B.TraverseDecl(&TU);
69
1.99k
}
70
71
26.4k
void ASTImporterLookupTable::add(DeclContext *DC, NamedDecl *ND) {
72
26.4k
  DeclList &Decls = LookupTable[DC][ND->getDeclName()];
73
26.4k
  // Inserts if and only if there is no element in the container equal to it.
74
26.4k
  Decls.insert(ND);
75
26.4k
}
76
77
117
void ASTImporterLookupTable::remove(DeclContext *DC, NamedDecl *ND) {
78
117
  DeclList &Decls = LookupTable[DC][ND->getDeclName()];
79
117
  bool EraseResult = Decls.remove(ND);
80
117
  (void)EraseResult;
81
117
  assert(EraseResult == true && "Trying to remove not contained Decl");
82
117
}
83
84
26.3k
void ASTImporterLookupTable::add(NamedDecl *ND) {
85
26.3k
  assert(ND);
86
26.3k
  DeclContext *DC = ND->getDeclContext()->getPrimaryContext();
87
26.3k
  add(DC, ND);
88
26.3k
  DeclContext *ReDC = DC->getRedeclContext()->getPrimaryContext();
89
26.3k
  if (DC != ReDC)
90
103
    add(ReDC, ND);
91
26.3k
}
92
93
117
void ASTImporterLookupTable::remove(NamedDecl *ND) {
94
117
  assert(ND);
95
117
  DeclContext *DC = ND->getDeclContext()->getPrimaryContext();
96
117
  remove(DC, ND);
97
117
  DeclContext *ReDC = DC->getRedeclContext()->getPrimaryContext();
98
117
  if (DC != ReDC)
99
0
    remove(ReDC, ND);
100
117
}
101
102
ASTImporterLookupTable::LookupResult
103
9.90k
ASTImporterLookupTable::lookup(DeclContext *DC, DeclarationName Name) const {
104
9.90k
  auto DCI = LookupTable.find(DC->getPrimaryContext());
105
9.90k
  if (DCI == LookupTable.end())
106
1.59k
    return {};
107
8.31k
108
8.31k
  const auto &FoundNameMap = DCI->second;
109
8.31k
  auto NamesI = FoundNameMap.find(Name);
110
8.31k
  if (NamesI == FoundNameMap.end())
111
4.72k
    return {};
112
3.58k
113
3.58k
  return NamesI->second;
114
3.58k
}
115
116
0
void ASTImporterLookupTable::dump(DeclContext *DC) const {
117
0
  auto DCI = LookupTable.find(DC->getPrimaryContext());
118
0
  if (DCI == LookupTable.end())
119
0
    llvm::errs() << "empty\n";
120
0
  const auto &FoundNameMap = DCI->second;
121
0
  for (const auto &Entry : FoundNameMap) {
122
0
    DeclarationName Name = Entry.first;
123
0
    llvm::errs() << "==== Name: ";
124
0
    Name.dump();
125
0
    const DeclList& List = Entry.second;
126
0
    for (NamedDecl *ND : List) {
127
0
      ND->dump();
128
0
    }
129
0
  }
130
0
}
131
132
0
void ASTImporterLookupTable::dump() const {
133
0
  for (const auto &Entry : LookupTable) {
134
0
    DeclContext *DC = Entry.first;
135
0
    StringRef Primary = DC->getPrimaryContext() ? " primary" : "";
136
0
    llvm::errs() << "== DC:" << cast<Decl>(DC) << Primary << "\n";
137
0
    dump(DC);
138
0
  }
139
0
}
140
141
} // namespace clang