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/Module.h" |
13 | #include "clang/Basic/SourceLocation.h" |
14 | #include "llvm/ADT/ArrayRef.h" |
15 | #include "llvm/ADT/DenseMap.h" |
16 | #include "llvm/ADT/PointerUnion.h" |
17 | #include "llvm/ADT/StringRef.h" |
18 | #include "llvm/Support/VersionTuple.h" |
19 | #include <memory> |
20 | #include <string> |
21 | |
22 | namespace clang { |
23 | |
24 | class DirectoryEntry; |
25 | class FileEntry; |
26 | class LangOptions; |
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 *, 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. |
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. |
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(N: 0, M: 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 | |