clang: lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

12#include "llvm/ADT/ArrayRef.h"

13#include "llvm/ADT/DenseSet.h"

14#include "llvm/ADT/STLExtras.h"

15#include "llvm/ADT/StringRef.h"

16#include "llvm/Support/Casting.h"

17#include

18

22

23namespace {

24

25using NSSymbolMap = llvm::DenseMap<llvm::StringRef, unsigned>;

26

27

28struct SymbolHeaderMapping {

29 llvm::StringRef *HeaderNames = nullptr;

30

31 llvm::DenseMap<llvm::StringRef, unsigned> *HeaderIDs;

32

33 unsigned SymbolCount = 0;

34

35 struct SymbolName {

36 const char *Data;

37 unsigned ScopeLen;

38 unsigned NameLen;

39 StringRef scope() const { return StringRef(Data, ScopeLen); }

40 StringRef name() const { return StringRef(Data + ScopeLen, NameLen); }

41 StringRef qualifiedName() const {

42 return StringRef(Data, ScopeLen + NameLen);

43 }

44 } *SymbolNames = nullptr;

45

46 llvm::DenseMap<llvm::StringRef, NSSymbolMap *> *NamespaceSymbols = nullptr;

47

48 llvm::SmallVector *SymbolHeaderIDs = nullptr;

49};

50}

51static SymbolHeaderMapping

56

59#define SYMBOL(Name, NS, Header) #NS #Name,

62 static constexpr const char *CSymbols[] = {

65 };

66 Symbols = CSymbols;

67 break;

68 }

70 static constexpr const char *CXXSymbols[] = {

74 };

75 Symbols = CXXSymbols;

76 break;

77 }

78 }

79#undef SYMBOL

80 return llvm::DenseSet(llvm::from_range, Symbols).size();

81}

82

84 SymbolHeaderMapping *Mapping = new SymbolHeaderMapping();

86

88 Mapping->SymbolCount = SymCount;

89 Mapping->SymbolNames =

90 new std::remove_reference_t<decltype(*Mapping->SymbolNames)>[SymCount];

91 Mapping->SymbolHeaderIDs = new std::remove_reference_t<

92 decltype(*Mapping->SymbolHeaderIDs)>[SymCount];

93 Mapping->NamespaceSymbols =

94 new std::remove_reference_t<decltype(*Mapping->NamespaceSymbols)>;

95 Mapping->HeaderIDs =

96 new std::remove_reference_t<decltype(*Mapping->HeaderIDs)>;

97 auto AddNS = [&](llvm::StringRef NS) -> NSSymbolMap & {

98 auto R = Mapping->NamespaceSymbols->try_emplace(NS, nullptr);

99 if (R.second)

100 R.first->second = new NSSymbolMap();

101 return *R.first->second;

102 };

103

104 auto AddHeader = [&](llvm::StringRef Header) -> unsigned {

105 return Mapping->HeaderIDs->try_emplace(Header, Mapping->HeaderIDs->size())

106 .first->second;

107 };

108

109 auto Add = [&, SymIndex(-1)](llvm::StringRef QName, unsigned NSLen,

110 llvm::StringRef HeaderName) mutable {

111

112

113 if (QName.take_front(NSLen) == "None") {

114 QName = QName.drop_front(NSLen);

115 NSLen = 0;

116 }

117

118 if (SymIndex > 0) {

119 assert(llvm::none_of(llvm::ArrayRef(Mapping->SymbolNames, SymIndex),

120 [&QName](const SymbolHeaderMapping::SymbolName &S) {

121 return S.qualifiedName() == QName;

122 }) &&

123 "The symbol has been added before, make sure entries in the .inc "

124 "file are grouped by symbol name!");

125 }

126 if (SymIndex < 0 ||

127 Mapping->SymbolNames[SymIndex].qualifiedName() != QName) {

128

129 ++SymIndex;

130 }

131 Mapping->SymbolNames[SymIndex] = {

132 QName.data(), NSLen, static_cast<unsigned int>(QName.size() - NSLen)};

133 if (!HeaderName.empty())

134 Mapping->SymbolHeaderIDs[SymIndex].push_back(AddHeader(HeaderName));

135

136 NSSymbolMap &NSSymbols = AddNS(QName.take_front(NSLen));

137 NSSymbols.try_emplace(QName.drop_front(NSLen), SymIndex);

138 };

139

141 const char *QName;

142 unsigned NSLen;

143 const char *HeaderName;

144 };

145#define SYMBOL(Name, NS, Header) \

146 {#NS #Name, static_cast<decltype(Symbol::NSLen)>(StringRef(#NS).size()), \

147 #Header},

150 static constexpr Symbol CSymbols[] = {

153 };

154 for (const Symbol &S : CSymbols)

155 Add(S.QName, S.NSLen, S.HeaderName);

156 break;

157 }

159 static constexpr Symbol CXXSymbols[] = {

163 };

164 for (const Symbol &S : CXXSymbols)

165 Add(S.QName, S.NSLen, S.HeaderName);

166 break;

167 }

168 }

169#undef SYMBOL

170

171 Mapping->HeaderNames = new llvm::StringRef[Mapping->HeaderIDs->size()];

172 for (const auto &E : *Mapping->HeaderIDs)

173 Mapping->HeaderNames[E.second] = E.first;

174

175 return 0;

176}

177

179 static int Dummy = []() {

180 for (unsigned L = 0; L <= static_cast(Lang::LastValue); ++L)

182 return 0;

183 }();

184 (void)Dummy;

185}

186

189 std::vector

Result;

191 Result.reserve(Mapping->HeaderIDs->size());

192 for (unsigned I = 0, E = Mapping->HeaderIDs->size(); I < E; ++I)

193 Result.push_back(Header(I, L));

195}

199 auto It = Mapping->HeaderIDs->find(Name);

200 if (It == Mapping->HeaderIDs->end())

201 return std::nullopt;

202 return Header(It->second, L);

203}

207

210 std::vector Result;

212 Result.reserve(Mapping->SymbolCount);

213 for (unsigned I = 0, E = Mapping->SymbolCount; I < E; ++I)

214 Result.push_back(Symbol(I, L));

216}

229

230 if (NSSymbolMap *NSSymbols =

232 auto It = NSSymbols->find(Name);

233 if (It != NSSymbols->end())

234 return Symbol(It->second, L);

235 }

236 return std::nullopt;

237}

239 const auto &Headers = getMappingPerLang(Language)->SymbolHeaderIDs[ID];

240 if (Headers.empty())

241 return std::nullopt;

242 return Header(Headers.front(), Language);

243}

246 for (auto HeaderID : getMappingPerLang(Language)->SymbolHeaderIDs[ID])

247 Results.emplace_back(Header(HeaderID, Language));

248 return Results;

249}

250

252

253NSSymbolMap *Recognizer::namespaceSymbols(const DeclContext *DC, Lang L) {

256

257 auto It = NamespaceCache.find(DC);

258 if (It != NamespaceCache.end())

259 return It->second;

260 const NamespaceDecl *D = llvm::cast(DC);

261 NSSymbolMap *Result = [&]() -> NSSymbolMap * {

263 return nullptr;

264

265 std::string Scope;

266 for (const auto *ND = D; ND;

267 ND = llvm::dyn_cast_or_null(ND->getParent()))

268 if (!ND->isInlineNamespace() && !ND->isAnonymousNamespace())

269 Scope = ND->getName().str() + "::" + Scope;

271 }();

272 NamespaceCache.try_emplace(D, Result);

274}

275

282 else

283 return std::nullopt;

284

285

286

287

290 if (!DC)

291 return std::nullopt;

294 IntermediateDecl.push_back(DC);

296 }

297 NSSymbolMap *Symbols = namespaceSymbols(DC, L);

298 if (!Symbols)

299 return std::nullopt;

300

301 llvm::StringRef Name = [&]() -> llvm::StringRef {

302 for (const auto *SymDC : llvm::reverse(IntermediateDecl)) {

305 return II->getName();

307 return "";

308 }

309 if (const auto *ND = llvm::dyn_cast(D))

310 if (const auto *II = ND->getIdentifier())

311 return II->getName();

312 return "";

313 }();

314 if (Name.empty())

315 return std::nullopt;

316

317 auto It = Symbols->find(Name);

318 if (It == Symbols->end())

319 return std::nullopt;

320 return Symbol(It->second, L);

321}

322

323}

324}

325}

Defines the clang::LangOptions interface.

Provides an interface for querying information about C and C++ Standard Library headers and symbols.

DeclContext - This is used only as base class of specific decl types that can act as declaration cont...

DeclContext * getParent()

getParent - Returns the containing DeclContext.

bool isTranslationUnit() const

Decl::Kind getDeclKind() const

Decl - This represents one declaration (or definition), e.g.

DeclContext * getDeclContext()

const LangOptions & getLangOpts() const LLVM_READONLY

Helper to get the language options from the ASTContext.

The name of a declaration.

IdentifierInfo * getAsIdentifierInfo() const

Retrieve the IdentifierInfo * stored in this declaration name, or null if this declaration name isn't...

bool isEmpty() const

Evaluates true when this declaration name is empty.

static bool classofKind(Kind K)

Represent a C++ namespace.

bool isAnonymousNamespace() const

Returns true if this is an anonymous namespace declaration.

Scope - A scope is a transient data structure that is used while parsing the program.

RangeSelector name(std::string ID)

Given a node with a "name", (like NamedDecl, DeclRefExpr, CxxCtorInitializer, and TypeLoc) selects th...

The JSON file list parser is used to communicate input to InstallAPI.

Language

The language for the input, used to select and validate the language standard and possible actions.

@ Result

The result type of a method or function.

U cast(CodeGen::Address addr)