1 //===--- APINotesManager.h - Manage API Notes Files -------------*- 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 #ifndef LLVM_CLANG_APINOTES_APINOTESMANAGER_H 10 #define LLVM_CLANG_APINOTES_APINOTESMANAGER_H 11 12 #include "clang/Basic/SourceLocation.h" 13 #include "llvm/ADT/ArrayRef.h" 14 #include "llvm/ADT/DenseMap.h" 15 #include "llvm/ADT/PointerUnion.h" 16 #include "llvm/ADT/StringRef.h" 17 #include "llvm/Support/VersionTuple.h" 18 #include <memory> 19 #include <string> 20 21 namespace clang { 22 23 class DirectoryEntry; 24 class FileEntry; 25 class LangOptions; 26 class Module; 27 class SourceManager; 28 29 namespace api_notes { 30 31 class APINotesReader; 32 33 /// The API notes manager helps find API notes associated with declarations. 34 /// 35 /// API notes are externally-provided annotations for declarations that can 36 /// introduce new attributes (covering availability, nullability of 37 /// parameters/results, and so on) for specific declarations without directly 38 /// modifying the headers that contain those declarations. 39 /// 40 /// The API notes manager is responsible for finding and loading the 41 /// external API notes files that correspond to a given header. Its primary 42 /// operation is \c findAPINotes(), which finds the API notes reader that 43 /// provides information about the declarations at that location. 44 class APINotesManager { 45 using ReaderEntry = llvm::PointerUnion<DirectoryEntryRef, APINotesReader *>; 46 47 SourceManager &SM; 48 49 /// Whether to implicitly search for API notes files based on the 50 /// source file from which an entity was declared. 51 bool ImplicitAPINotes; 52 53 /// The Swift version to use when interpreting versioned API notes. 54 llvm::VersionTuple SwiftVersion; 55 56 enum ReaderKind : unsigned { Public = 0, Private = 1 }; 57 58 /// API notes readers for the current module. 59 /// 60 /// There can be up to two of these, one for public headers and one 61 /// for private headers. 62 /// 63 /// Not using std::unique_ptr to store these, since the reader pointers are 64 /// also stored in llvm::PointerUnion below. 65 APINotesReader *CurrentModuleReaders[2] = {nullptr, nullptr}; 66 67 /// A mapping from header file directories to the API notes reader for 68 /// that directory, or a redirection to another directory entry that may 69 /// have more information, or NULL to indicate that there is no API notes 70 /// reader for this directory. 71 llvm::DenseMap<const DirectoryEntry *, ReaderEntry> Readers; 72 73 /// Load the API notes associated with the given file, whether it is 74 /// the binary or source form of API notes. 75 /// 76 /// \returns the API notes reader for this file, or null if there is 77 /// a failure. 78 std::unique_ptr<APINotesReader> loadAPINotes(FileEntryRef APINotesFile); 79 80 /// Load the API notes associated with the given buffer, whether it is 81 /// the binary or source form of API notes. 82 /// 83 /// \returns the API notes reader for this file, or null if there is 84 /// a failure. 85 std::unique_ptr<APINotesReader> loadAPINotes(StringRef Buffer); 86 87 /// Load the given API notes file for the given header directory. 88 /// 89 /// \param HeaderDir The directory at which we 90 /// 91 /// \returns true if an error occurred. 92 bool loadAPINotes(const DirectoryEntry *HeaderDir, FileEntryRef APINotesFile); 93 94 /// Look for API notes in the given directory. 95 /// 96 /// This might find either a binary or source API notes. 97 OptionalFileEntryRef findAPINotesFile(DirectoryEntryRef Directory, 98 StringRef FileName, 99 bool WantPublic = true); 100 101 /// Attempt to load API notes for the given framework. A framework will have 102 /// the API notes file under either {FrameworkPath}/APINotes, 103 /// {FrameworkPath}/Headers or {FrameworkPath}/PrivateHeaders, while a 104 /// library will have the API notes simply in its directory. 105 /// 106 /// \param FrameworkPath The path to the framework. 107 /// \param Public Whether to load the public API notes. Otherwise, attempt 108 /// to load the private API notes. 109 /// 110 /// \returns the header directory entry (e.g., for Headers or PrivateHeaders) 111 /// for which the API notes were successfully loaded, or NULL if API notes 112 /// could not be loaded for any reason. 113 OptionalDirectoryEntryRef loadFrameworkAPINotes(llvm::StringRef FrameworkPath, 114 llvm::StringRef FrameworkName, 115 bool Public); 116 117 public: 118 APINotesManager(SourceManager &SM, const LangOptions &LangOpts); 119 ~APINotesManager(); 120 121 /// Set the Swift version to use when filtering API notes. setSwiftVersion(llvm::VersionTuple Version)122 void setSwiftVersion(llvm::VersionTuple Version) { 123 this->SwiftVersion = Version; 124 } 125 126 /// Load the API notes for the current module. 127 /// 128 /// \param M The current module. 129 /// \param LookInModule Whether to look inside the module itself. 130 /// \param SearchPaths The paths in which we should search for API notes 131 /// for the current module. 132 /// 133 /// \returns true if API notes were successfully loaded, \c false otherwise. 134 bool loadCurrentModuleAPINotes(Module *M, bool LookInModule, 135 ArrayRef<std::string> SearchPaths); 136 137 /// Get FileEntry for the APINotes of the module that is currently being 138 /// compiled. 139 /// 140 /// \param M The current module. 141 /// \param LookInModule Whether to look inside the directory of the current 142 /// module. 143 /// \param SearchPaths The paths in which we should search for API 144 /// notes for the current module. 145 /// 146 /// \returns a vector of FileEntry where APINotes files are. 147 llvm::SmallVector<FileEntryRef, 2> 148 getCurrentModuleAPINotes(Module *M, bool LookInModule, 149 ArrayRef<std::string> SearchPaths); 150 151 /// Load Compiled API notes for current module. 152 /// 153 /// \param Buffers Array of compiled API notes. 154 /// 155 /// \returns true if API notes were successfully loaded, \c false otherwise. 156 bool loadCurrentModuleAPINotesFromBuffer(ArrayRef<StringRef> Buffers); 157 158 /// Retrieve the set of API notes readers for the current module. getCurrentModuleReaders()159 ArrayRef<APINotesReader *> getCurrentModuleReaders() const { 160 bool HasPublic = CurrentModuleReaders[ReaderKind::Public]; 161 bool HasPrivate = CurrentModuleReaders[ReaderKind::Private]; 162 assert((!HasPrivate || HasPublic) && "private module requires public module"); 163 if (!HasPrivate && !HasPublic) 164 return {}; 165 return ArrayRef(CurrentModuleReaders).slice(0, HasPrivate ? 2 : 1); 166 } 167 168 /// Find the API notes readers that correspond to the given source location. 169 llvm::SmallVector<APINotesReader *, 2> findAPINotes(SourceLocation Loc); 170 }; 171 172 } // end namespace api_notes 173 } // end namespace clang 174 175 #endif 176