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 /// Whether to apply all APINotes as optionally-applied versioned 54 /// entities. This means that when building a Clang module, 55 /// we capture every note on a given decl wrapped in a SwiftVersionedAttr 56 /// (with an empty version field for unversioned notes), and have the 57 /// client apply the relevant version's notes. 58 bool VersionIndependentSwift; 59 60 /// The Swift version to use when interpreting versioned API notes. 61 llvm::VersionTuple SwiftVersion; 62 63 enum ReaderKind : unsigned { Public = 0, Private = 1 }; 64 65 /// API notes readers for the current module. 66 /// 67 /// There can be up to two of these, one for public headers and one 68 /// for private headers. 69 /// 70 /// Not using std::unique_ptr to store these, since the reader pointers are 71 /// also stored in llvm::PointerUnion below. 72 APINotesReader *CurrentModuleReaders[2] = {nullptr, nullptr}; 73 74 /// A mapping from header file directories to the API notes reader for 75 /// that directory, or a redirection to another directory entry that may 76 /// have more information, or NULL to indicate that there is no API notes 77 /// reader for this directory. 78 llvm::DenseMap<const DirectoryEntry *, ReaderEntry> Readers; 79 80 /// Load the API notes associated with the given file, 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(FileEntryRef APINotesFile); 86 87 /// Load the API notes associated with the given buffer, whether it is 88 /// the binary or source form of API notes. 89 /// 90 /// \returns the API notes reader for this file, or null if there is 91 /// a failure. 92 std::unique_ptr<APINotesReader> loadAPINotes(StringRef Buffer); 93 94 /// Load the given API notes file for the given header directory. 95 /// 96 /// \param HeaderDir The directory at which we 97 /// 98 /// \returns true if an error occurred. 99 bool loadAPINotes(const DirectoryEntry *HeaderDir, FileEntryRef APINotesFile); 100 101 /// Look for API notes in the given directory. 102 /// 103 /// This might find either a binary or source API notes. 104 OptionalFileEntryRef findAPINotesFile(DirectoryEntryRef Directory, 105 StringRef FileName, 106 bool WantPublic = true); 107 108 /// Attempt to load API notes for the given framework. A framework will have 109 /// the API notes file under either {FrameworkPath}/APINotes, 110 /// {FrameworkPath}/Headers or {FrameworkPath}/PrivateHeaders, while a 111 /// library will have the API notes simply in its directory. 112 /// 113 /// \param FrameworkPath The path to the framework. 114 /// \param Public Whether to load the public API notes. Otherwise, attempt 115 /// to load the private API notes. 116 /// 117 /// \returns the header directory entry (e.g., for Headers or PrivateHeaders) 118 /// for which the API notes were successfully loaded, or NULL if API notes 119 /// could not be loaded for any reason. 120 OptionalDirectoryEntryRef loadFrameworkAPINotes(llvm::StringRef FrameworkPath, 121 llvm::StringRef FrameworkName, 122 bool Public); 123 124 public: 125 APINotesManager(SourceManager &SM, const LangOptions &LangOpts); 126 ~APINotesManager(); 127 128 /// Set the Swift version to use when filtering API notes. setSwiftVersion(llvm::VersionTuple Version)129 void setSwiftVersion(llvm::VersionTuple Version) { 130 this->SwiftVersion = Version; 131 } 132 133 /// Load the API notes for the current module. 134 /// 135 /// \param M The current module. 136 /// \param LookInModule Whether to look inside the module itself. 137 /// \param SearchPaths The paths in which we should search for API notes 138 /// for the current module. 139 /// 140 /// \returns true if API notes were successfully loaded, \c false otherwise. 141 bool loadCurrentModuleAPINotes(Module *M, bool LookInModule, 142 ArrayRef<std::string> SearchPaths); 143 144 /// Get FileEntry for the APINotes of the module that is currently being 145 /// compiled. 146 /// 147 /// \param M The current module. 148 /// \param LookInModule Whether to look inside the directory of the current 149 /// module. 150 /// \param SearchPaths The paths in which we should search for API 151 /// notes for the current module. 152 /// 153 /// \returns a vector of FileEntry where APINotes files are. 154 llvm::SmallVector<FileEntryRef, 2> 155 getCurrentModuleAPINotes(Module *M, bool LookInModule, 156 ArrayRef<std::string> SearchPaths); 157 158 /// Load Compiled API notes for current module. 159 /// 160 /// \param Buffers Array of compiled API notes. 161 /// 162 /// \returns true if API notes were successfully loaded, \c false otherwise. 163 bool loadCurrentModuleAPINotesFromBuffer(ArrayRef<StringRef> Buffers); 164 165 /// Retrieve the set of API notes readers for the current module. getCurrentModuleReaders()166 ArrayRef<APINotesReader *> getCurrentModuleReaders() const { 167 bool HasPublic = CurrentModuleReaders[ReaderKind::Public]; 168 bool HasPrivate = CurrentModuleReaders[ReaderKind::Private]; 169 assert((!HasPrivate || HasPublic) && "private module requires public module"); 170 if (!HasPrivate && !HasPublic) 171 return {}; 172 return ArrayRef(CurrentModuleReaders).slice(0, HasPrivate ? 2 : 1); 173 } 174 175 /// Find the API notes readers that correspond to the given source location. 176 llvm::SmallVector<APINotesReader *, 2> findAPINotes(SourceLocation Loc); 177 captureVersionIndependentSwift()178 bool captureVersionIndependentSwift() { return VersionIndependentSwift; } 179 }; 180 181 } // end namespace api_notes 182 } // end namespace clang 183 184 #endif 185