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