Skip to content

Commit b8e7c8e

Browse files
authored
Merge pull request #7244 from apple/egorzhdan/apinotes-namespaces-20221013
🍒[APINotes] Support C++ namespaces
2 parents 1503a15 + a2383f7 commit b8e7c8e

File tree

14 files changed

+611
-130
lines changed

14 files changed

+611
-130
lines changed

clang/include/clang/APINotes/APINotesReader.h

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -175,14 +175,18 @@ class APINotesReader {
175175
/// \param name The name of the global variable.
176176
///
177177
/// \returns information about the global variable, if known.
178-
VersionedInfo<GlobalVariableInfo> lookupGlobalVariable(llvm::StringRef name);
178+
VersionedInfo<GlobalVariableInfo>
179+
lookupGlobalVariable(llvm::StringRef name,
180+
std::optional<Context> context = std::nullopt);
179181

180182
/// Look for information regarding the given global function.
181183
///
182184
/// \param name The name of the global function.
183185
///
184186
/// \returns information about the global function, if known.
185-
VersionedInfo<GlobalFunctionInfo> lookupGlobalFunction(llvm::StringRef name);
187+
VersionedInfo<GlobalFunctionInfo>
188+
lookupGlobalFunction(llvm::StringRef name,
189+
std::optional<Context> context = std::nullopt);
186190

187191
/// Look for information regarding the given enumerator.
188192
///
@@ -197,14 +201,27 @@ class APINotesReader {
197201
/// \param name The name of the tag.
198202
///
199203
/// \returns information about the tag, if known.
200-
VersionedInfo<TagInfo> lookupTag(llvm::StringRef name);
204+
VersionedInfo<TagInfo>
205+
lookupTag(llvm::StringRef name,
206+
std::optional<Context> context = std::nullopt);
201207

202208
/// Look for information regarding the given typedef.
203209
///
204210
/// \param name The name of the typedef.
205211
///
206212
/// \returns information about the typedef, if known.
207-
VersionedInfo<TypedefInfo> lookupTypedef(llvm::StringRef name);
213+
VersionedInfo<TypedefInfo>
214+
lookupTypedef(llvm::StringRef name,
215+
std::optional<Context> context = std::nullopt);
216+
217+
/// Look for the context ID of the given C++ namespace.
218+
///
219+
/// \param name The name of the class we're looking for.
220+
///
221+
/// \returns The ID, if known.
222+
llvm::Optional<ContextID>
223+
lookupNamespaceID(llvm::StringRef name,
224+
llvm::Optional<ContextID> parentNamespaceID = llvm::None);
208225
};
209226

210227
} // end namespace api_notes

clang/include/clang/APINotes/APINotesWriter.h

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,17 @@ class APINotesWriter {
4646
/// Write the API notes data to the given stream.
4747
void writeToStream(llvm::raw_ostream &os);
4848

49-
/// Add information about a specific Objective-C class or protocol.
49+
/// Add information about a specific Objective-C class or protocol or a C++
50+
/// namespace.
5051
///
51-
/// \param name The name of this class/protocol.
52-
/// \param isClass Whether this is a class (vs. a protocol).
53-
/// \param info Information about this class/protocol.
52+
/// \param name The name of this class/protocol/namespace.
53+
/// \param contextKind Whether this is a class, a protocol, or a namespace.
54+
/// \param info Information about this class/protocol/namespace.
5455
///
55-
/// \returns the ID of the class or protocol, which can be used to add
56-
/// properties and methods to the class/protocol.
57-
ContextID addObjCContext(llvm::StringRef name, bool isClass,
56+
/// \returns the ID of the class, protocol, or namespace, which can be used to
57+
/// add properties and methods to the class/protocol/namespace.
58+
ContextID addObjCContext(std::optional<ContextID> parentContextID,
59+
llvm::StringRef name, ContextKind contextKind,
5860
const ObjCContextInfo &info,
5961
llvm::VersionTuple swiftVersion);
6062

@@ -83,14 +85,16 @@ class APINotesWriter {
8385
///
8486
/// \param name The name of this global variable.
8587
/// \param info Information about this global variable.
86-
void addGlobalVariable(llvm::StringRef name, const GlobalVariableInfo &info,
88+
void addGlobalVariable(std::optional<Context> context, llvm::StringRef name,
89+
const GlobalVariableInfo &info,
8790
llvm::VersionTuple swiftVersion);
8891

8992
/// Add information about a global function.
9093
///
9194
/// \param name The name of this global function.
9295
/// \param info Information about this global function.
93-
void addGlobalFunction(llvm::StringRef name, const GlobalFunctionInfo &info,
96+
void addGlobalFunction(std::optional<Context> context, llvm::StringRef name,
97+
const GlobalFunctionInfo &info,
9498
llvm::VersionTuple swiftVersion);
9599

96100
/// Add information about an enumerator.
@@ -104,15 +108,15 @@ class APINotesWriter {
104108
///
105109
/// \param name The name of this tag.
106110
/// \param info Information about this tag.
107-
void addTag(llvm::StringRef name, const TagInfo &info,
108-
llvm::VersionTuple swiftVersion);
111+
void addTag(std::optional<Context> context, llvm::StringRef name,
112+
const TagInfo &info, llvm::VersionTuple swiftVersion);
109113

110114
/// Add information about a typedef.
111115
///
112116
/// \param name The name of this typedef.
113117
/// \param info Information about this typedef.
114-
void addTypedef(llvm::StringRef name, const TypedefInfo &info,
115-
llvm::VersionTuple swiftVersion);
118+
void addTypedef(std::optional<Context> context, llvm::StringRef name,
119+
const TypedefInfo &info, llvm::VersionTuple swiftVersion);
116120

117121
/// Add module options
118122
void addModuleOptions(ModuleOptions opts);

clang/include/clang/APINotes/Types.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -735,14 +735,28 @@ namespace api_notes {
735735
/// The file extension used for the source representation of API notes.
736736
static const char SOURCE_APINOTES_EXTENSION[] = "apinotes";
737737

738-
/// Opaque context ID used to refer to an Objective-C class or protocol.
738+
/// Opaque context ID used to refer to an Objective-C class or protocol or a C++
739+
/// namespace.
739740
class ContextID {
740741
public:
741742
unsigned Value;
742743

743744
explicit ContextID(unsigned value) : Value(value) { }
744745
};
745746

747+
enum class ContextKind : uint8_t {
748+
ObjCClass = 0,
749+
ObjCProtocol = 1,
750+
Namespace = 2
751+
};
752+
753+
struct Context {
754+
ContextID id;
755+
ContextKind kind;
756+
757+
Context(ContextID id, ContextKind kind) : id(id), kind(kind) {}
758+
};
759+
746760
/// A temporary reference to an Objective-C selector, suitable for
747761
/// referencing selector data on the stack.
748762
///

clang/lib/APINotes/APINotesFormat.h

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,38 @@ struct StoredObjCSelector {
249249
unsigned NumPieces;
250250
llvm::SmallVector<IdentifierID, 2> Identifiers;
251251
};
252+
253+
/// A stored Objective-C or C++ context, represented by the ID of its parent
254+
/// context, the kind of this context (Objective-C class / C++ namespace / etc),
255+
/// and the ID of this context.
256+
struct ContextTableKey {
257+
uint32_t parentContextID;
258+
uint8_t contextKind;
259+
uint32_t contextID;
260+
261+
ContextTableKey() : parentContextID(-1), contextKind(-1), contextID(-1) {}
262+
263+
ContextTableKey(uint32_t parentContextID, uint8_t contextKind,
264+
uint32_t contextID)
265+
: parentContextID(parentContextID), contextKind(contextKind),
266+
contextID(contextID) {}
267+
268+
ContextTableKey(std::optional<Context> context, IdentifierID nameID)
269+
: parentContextID(context ? context->id.Value : (uint32_t)-1),
270+
contextKind(context ? (uint8_t)context->kind : (uint8_t)-1),
271+
contextID(nameID) {}
272+
273+
llvm::hash_code hashValue() const {
274+
return llvm::hash_value(
275+
std::tuple{parentContextID, contextKind, contextID});
276+
}
277+
};
278+
279+
inline bool operator==(const ContextTableKey &lhs, const ContextTableKey &rhs) {
280+
return lhs.parentContextID == rhs.parentContextID &&
281+
lhs.contextKind == rhs.contextKind && lhs.contextID == rhs.contextID;
282+
}
283+
252284
} // namespace api_notes
253285
} // namespace clang
254286

@@ -284,6 +316,29 @@ namespace llvm {
284316
lhs.Identifiers == rhs.Identifiers;
285317
}
286318
};
287-
}
319+
320+
template <> struct DenseMapInfo<clang::api_notes::ContextTableKey> {
321+
static inline clang::api_notes::ContextTableKey getEmptyKey() {
322+
return clang::api_notes::ContextTableKey();
323+
}
324+
325+
static inline clang::api_notes::ContextTableKey getTombstoneKey() {
326+
return clang::api_notes::ContextTableKey{
327+
DenseMapInfo<uint32_t>::getTombstoneKey(),
328+
DenseMapInfo<uint8_t>::getTombstoneKey(),
329+
DenseMapInfo<uint32_t>::getTombstoneKey()};
330+
}
331+
332+
static unsigned
333+
getHashValue(const clang::api_notes::ContextTableKey &value) {
334+
return value.hashValue();
335+
}
336+
337+
static bool isEqual(const clang::api_notes::ContextTableKey &lhs,
338+
const clang::api_notes::ContextTableKey &rhs) {
339+
return lhs == rhs;
340+
}
341+
};
342+
} // namespace llvm
288343

289344
#endif

0 commit comments

Comments
 (0)