Coverage Report

Created: 2022-07-16 07:03

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Tooling/Inclusions/StandardLibrary.cpp
Line
Count
Source (jump to first uncovered line)
1
//===--- StandardLibrary.cpp ------------------------------------*- 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
#include "clang/Tooling/Inclusions/StandardLibrary.h"
10
#include "llvm/ADT/Optional.h"
11
#include "llvm/ADT/StringRef.h"
12
#include "llvm/Support/Casting.h"
13
14
namespace clang {
15
namespace tooling {
16
namespace stdlib {
17
18
static llvm::StringRef *HeaderNames;
19
static std::pair<llvm::StringRef, llvm::StringRef> *SymbolNames;
20
static unsigned *SymbolHeaderIDs;
21
static llvm::DenseMap<llvm::StringRef, unsigned> *HeaderIDs;
22
// Maps symbol name -> Symbol::ID, within a namespace.
23
using NSSymbolMap = llvm::DenseMap<llvm::StringRef, unsigned>;
24
static llvm::DenseMap<llvm::StringRef, NSSymbolMap *> *NamespaceSymbols;
25
26
2
static int initialize() {
27
2
  unsigned SymCount = 0;
28
4.92k
#define SYMBOL(Name, NS, Header) ++SymCount;
29
2
#include "clang/Tooling/Inclusions/CSymbolMap.inc"
30
2
#include "clang/Tooling/Inclusions/StdSymbolMap.inc"
31
2
#undef SYMBOL
32
2
  SymbolNames = new std::remove_reference_t<decltype(*SymbolNames)>[SymCount];
33
2
  SymbolHeaderIDs =
34
2
      new std::remove_reference_t<decltype(*SymbolHeaderIDs)>[SymCount];
35
2
  NamespaceSymbols = new std::remove_reference_t<decltype(*NamespaceSymbols)>;
36
2
  HeaderIDs = new std::remove_reference_t<decltype(*HeaderIDs)>;
37
38
4.92k
  auto AddNS = [&](llvm::StringRef NS) -> NSSymbolMap & {
39
4.92k
    auto R = NamespaceSymbols->try_emplace(NS, nullptr);
40
4.92k
    if (R.second)
41
14
      R.first->second = new NSSymbolMap();
42
4.92k
    return *R.first->second;
43
4.92k
  };
44
45
4.92k
  auto AddHeader = [&](llvm::StringRef Header) -> unsigned {
46
4.92k
    return HeaderIDs->try_emplace(Header, HeaderIDs->size()).first->second;
47
4.92k
  };
48
49
2
  auto Add = [&, SymIndex(0)](llvm::StringRef Name, llvm::StringRef NS,
50
4.92k
                              llvm::StringRef HeaderName) mutable {
51
4.92k
    if (NS == "None")
52
1.86k
      NS = "";
53
54
4.92k
    SymbolNames[SymIndex] = {NS, Name};
55
4.92k
    SymbolHeaderIDs[SymIndex] = AddHeader(HeaderName);
56
57
4.92k
    NSSymbolMap &NSSymbols = AddNS(NS);
58
4.92k
    NSSymbols.try_emplace(Name, SymIndex);
59
60
4.92k
    ++SymIndex;
61
4.92k
  };
62
4.92k
#define SYMBOL(Name, NS, Header) Add(#Name, #NS, #Header);
63
2
#include "clang/Tooling/Inclusions/CSymbolMap.inc"
64
2
#include "clang/Tooling/Inclusions/StdSymbolMap.inc"
65
2
#undef SYMBOL
66
67
2
  HeaderNames = new llvm::StringRef[HeaderIDs->size()];
68
2
  for (const auto &E : *HeaderIDs)
69
220
    HeaderNames[E.second] = E.first;
70
71
2
  return 0;
72
2
}
73
74
10
static void ensureInitialized() {
75
10
  static int Dummy = initialize();
76
10
  (void)Dummy;
77
10
}
78
79
2
llvm::Optional<Header> Header::named(llvm::StringRef Name) {
80
2
  ensureInitialized();
81
2
  auto It = HeaderIDs->find(Name);
82
2
  if (It == HeaderIDs->end())
83
1
    return llvm::None;
84
1
  return Header(It->second);
85
2
}
86
1
llvm::StringRef Header::name() const { return HeaderNames[ID]; }
87
1
llvm::StringRef Symbol::scope() const { return SymbolNames[ID].first; }
88
1
llvm::StringRef Symbol::name() const { return SymbolNames[ID].second; }
89
llvm::Optional<Symbol> Symbol::named(llvm::StringRef Scope,
90
7
                                     llvm::StringRef Name) {
91
7
  ensureInitialized();
92
7
  if (NSSymbolMap *NSSymbols = NamespaceSymbols->lookup(Scope)) {
93
6
    auto It = NSSymbols->find(Name);
94
6
    if (It != NSSymbols->end())
95
4
      return Symbol(It->second);
96
6
  }
97
3
  return llvm::None;
98
7
}
99
2
Header Symbol::header() const { return Header(SymbolHeaderIDs[ID]); }
100
1
llvm::SmallVector<Header> Symbol::headers() const {
101
1
  return {header()}; // FIXME: multiple in case of ambiguity
102
1
}
103
104
1
Recognizer::Recognizer() { ensureInitialized(); }
105
106
6
NSSymbolMap *Recognizer::namespaceSymbols(const NamespaceDecl *D) {
107
6
  auto It = NamespaceCache.find(D);
108
6
  if (It != NamespaceCache.end())
109
3
    return It->second;
110
111
3
  NSSymbolMap *Result = [&]() -> NSSymbolMap * {
112
3
    if (D && 
D->isAnonymousNamespace()2
)
113
0
      return nullptr;
114
    // Print the namespace and its parents ommitting inline scopes.
115
3
    std::string Scope;
116
9
    for (const auto *ND = D; ND;
117
6
         ND = llvm::dyn_cast_or_null<NamespaceDecl>(ND->getParent()))
118
6
      if (!ND->isInlineNamespace() && 
!ND->isAnonymousNamespace()3
)
119
3
        Scope = ND->getName().str() + "::" + Scope;
120
3
    return NamespaceSymbols->lookup(Scope);
121
3
  }();
122
3
  NamespaceCache.try_emplace(D, Result);
123
3
  return Result;
124
6
}
125
126
6
llvm::Optional<Symbol> Recognizer::operator()(const Decl *D) {
127
  // If D is std::vector::iterator, `vector` is the outer symbol to look up.
128
  // We keep all the candidate DCs as some may turn out to be anon enums.
129
  // Do this resolution lazily as we may turn out not to have a std namespace.
130
6
  llvm::SmallVector<const DeclContext *> IntermediateDecl;
131
6
  const DeclContext *DC = D->getDeclContext();
132
9
  while (DC && 
!DC->isNamespace()7
) {
133
3
    if (NamedDecl::classofKind(DC->getDeclKind()))
134
1
      IntermediateDecl.push_back(DC);
135
3
    DC = DC->getParent();
136
3
  }
137
6
  NSSymbolMap *Symbols = namespaceSymbols(cast_or_null<NamespaceDecl>(DC));
138
6
  if (!Symbols)
139
0
    return llvm::None;
140
141
6
  llvm::StringRef Name = [&]() -> llvm::StringRef {
142
6
    for (const auto *SymDC : llvm::reverse(IntermediateDecl)) {
143
1
      DeclarationName N = cast<NamedDecl>(SymDC)->getDeclName();
144
1
      if (const auto *II = N.getAsIdentifierInfo())
145
1
        return II->getName();
146
0
      if (!N.isEmpty())
147
0
        return ""; // e.g. operator<: give up
148
0
    }
149
5
    if (const auto *ND = llvm::dyn_cast<NamedDecl>(D))
150
5
      if (const auto *II = ND->getIdentifier())
151
5
        return II->getName();
152
0
    return "";
153
5
  }();
154
6
  if (Name.empty())
155
0
    return llvm::None;
156
157
6
  auto It = Symbols->find(Name);
158
6
  if (It == Symbols->end())
159
3
    return llvm::None;
160
3
  return Symbol(It->second);
161
6
}
162
163
} // namespace stdlib
164
} // namespace tooling
165
} // namespace clang