1 | //===--- StandardLibrary.h --------------------------------------*- 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 | /// \file |
10 | /// Provides an interface for querying information about C and C++ Standard |
11 | /// Library headers and symbols. |
12 | /// |
13 | //===----------------------------------------------------------------------===// |
14 | |
15 | #ifndef LLVM_CLANG_TOOLING_INCLUSIONS_STANDARDLIBRARY_H |
16 | #define LLVM_CLANG_TOOLING_INCLUSIONS_STANDARDLIBRARY_H |
17 | |
18 | #include "llvm/ADT/DenseMap.h" |
19 | #include "llvm/ADT/Hashing.h" |
20 | #include "llvm/ADT/StringRef.h" |
21 | #include "llvm/Support/raw_ostream.h" |
22 | #include <optional> |
23 | #include <string> |
24 | |
25 | namespace clang { |
26 | class Decl; |
27 | class NamespaceDecl; |
28 | class DeclContext; |
29 | namespace tooling { |
30 | namespace stdlib { |
31 | |
32 | class Symbol; |
33 | enum class Lang { C = 0, CXX, LastValue = CXX }; |
34 | |
35 | // A standard library header, such as <iostream> |
36 | // Lightweight class, in fact just an index into a table. |
37 | // C++ and C Library compatibility headers are considered different: e.g. |
38 | // "<cstdio>" and "<stdio.h>" (and their symbols) are treated differently. |
39 | class { |
40 | public: |
41 | static std::vector<Header> (Lang L = Lang::CXX); |
42 | // Name should contain the angle brackets, e.g. "<vector>". |
43 | static std::optional<Header> (llvm::StringRef Name, |
44 | Lang Language = Lang::CXX); |
45 | |
46 | friend llvm::raw_ostream &(llvm::raw_ostream &OS, const Header &H) { |
47 | return OS << H.name(); |
48 | } |
49 | llvm::StringRef () const; |
50 | |
51 | private: |
52 | (unsigned ID, Lang Language) : ID(ID), Language(Language) {} |
53 | unsigned ; |
54 | Lang ; |
55 | |
56 | friend Symbol; |
57 | friend llvm::DenseMapInfo<Header>; |
58 | friend bool (const Header &L, const Header &R) { |
59 | return L.ID == R.ID; |
60 | } |
61 | }; |
62 | |
63 | // A top-level standard library symbol, such as std::vector |
64 | // Lightweight class, in fact just an index into a table. |
65 | // C++ and C Standard Library symbols are considered distinct: e.g. std::printf |
66 | // and ::printf are not treated as the same symbol. |
67 | // The symbols do not contain macros right now, we don't have a reliable index |
68 | // for them. |
69 | class Symbol { |
70 | public: |
71 | static std::vector<Symbol> all(Lang L = Lang::CXX); |
72 | /// \p Scope should have the trailing "::", for example: |
73 | /// named("std::chrono::", "system_clock") |
74 | static std::optional<Symbol> |
75 | named(llvm::StringRef Scope, llvm::StringRef Name, Lang Language = Lang::CXX); |
76 | |
77 | friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Symbol &S) { |
78 | return OS << S.qualifiedName(); |
79 | } |
80 | llvm::StringRef scope() const; |
81 | llvm::StringRef name() const; |
82 | llvm::StringRef qualifiedName() const; |
83 | // The preferred header for this symbol (e.g. the suggested insertion). |
84 | std::optional<Header> () const; |
85 | // Some symbols may be provided by multiple headers. |
86 | llvm::SmallVector<Header> () const; |
87 | |
88 | private: |
89 | Symbol(unsigned ID, Lang Language) : ID(ID), Language(Language) {} |
90 | unsigned ID; |
91 | Lang Language; |
92 | |
93 | friend class Recognizer; |
94 | friend llvm::DenseMapInfo<Symbol>; |
95 | friend bool operator==(const Symbol &L, const Symbol &R) { |
96 | return L.ID == R.ID; |
97 | } |
98 | }; |
99 | |
100 | // A functor to find the stdlib::Symbol associated with a decl. |
101 | // |
102 | // For non-top-level decls (std::vector<int>::iterator), returns the top-level |
103 | // symbol (std::vector). |
104 | class Recognizer { |
105 | public: |
106 | Recognizer(); |
107 | std::optional<Symbol> operator()(const Decl *D); |
108 | |
109 | private: |
110 | using NSSymbolMap = llvm::DenseMap<llvm::StringRef, unsigned>; |
111 | NSSymbolMap *namespaceSymbols(const DeclContext *DC, Lang L); |
112 | llvm::DenseMap<const DeclContext *, NSSymbolMap *> NamespaceCache; |
113 | }; |
114 | |
115 | } // namespace stdlib |
116 | } // namespace tooling |
117 | } // namespace clang |
118 | |
119 | namespace llvm { |
120 | |
121 | template <> struct DenseMapInfo<clang::tooling::stdlib::Header> { |
122 | static inline clang::tooling::stdlib::Header () { |
123 | return clang::tooling::stdlib::Header(-1, |
124 | clang::tooling::stdlib::Lang::CXX); |
125 | } |
126 | static inline clang::tooling::stdlib::Header () { |
127 | return clang::tooling::stdlib::Header(-2, |
128 | clang::tooling::stdlib::Lang::CXX); |
129 | } |
130 | static unsigned (const clang::tooling::stdlib::Header &H) { |
131 | return hash_value(value: H.ID); |
132 | } |
133 | static bool (const clang::tooling::stdlib::Header &LHS, |
134 | const clang::tooling::stdlib::Header &RHS) { |
135 | return LHS == RHS; |
136 | } |
137 | }; |
138 | |
139 | template <> struct DenseMapInfo<clang::tooling::stdlib::Symbol> { |
140 | static inline clang::tooling::stdlib::Symbol getEmptyKey() { |
141 | return clang::tooling::stdlib::Symbol(-1, |
142 | clang::tooling::stdlib::Lang::CXX); |
143 | } |
144 | static inline clang::tooling::stdlib::Symbol getTombstoneKey() { |
145 | return clang::tooling::stdlib::Symbol(-2, |
146 | clang::tooling::stdlib::Lang::CXX); |
147 | } |
148 | static unsigned getHashValue(const clang::tooling::stdlib::Symbol &S) { |
149 | return hash_value(value: S.ID); |
150 | } |
151 | static bool isEqual(const clang::tooling::stdlib::Symbol &LHS, |
152 | const clang::tooling::stdlib::Symbol &RHS) { |
153 | return LHS == RHS; |
154 | } |
155 | }; |
156 | } // namespace llvm |
157 | |
158 | #endif // LLVM_CLANG_TOOLING_INCLUSIONS_STANDARDLIBRARY_H |
159 | |