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