Skip to content

Commit 8ea33e8

Browse files
authored
Merge pull request #9014 from swiftlang/egorzhdan/20240625-apinotes-methods
🍒[APINotes] Support annotating C++ methods
2 parents ecdd17a + 0aae94b commit 8ea33e8

File tree

15 files changed

+548
-129
lines changed

15 files changed

+548
-129
lines changed

clang/include/clang/APINotes/APINotesReader.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,16 @@ class APINotesReader {
148148
ObjCSelectorRef Selector,
149149
bool IsInstanceMethod);
150150

151+
/// Look for information regarding the given C++ method in the given C++ tag
152+
/// context.
153+
///
154+
/// \param CtxID The ID that references the parent context, i.e. a C++ tag.
155+
/// \param Name The name of the C++ method we're looking for.
156+
///
157+
/// \returns Information about the method, if known.
158+
VersionedInfo<CXXMethodInfo> lookupCXXMethod(ContextID CtxID,
159+
llvm::StringRef Name);
160+
151161
/// Look for information regarding the given global variable.
152162
///
153163
/// \param Name The name of the global variable.
@@ -173,6 +183,17 @@ class APINotesReader {
173183
/// \returns information about the enumerator, if known.
174184
VersionedInfo<EnumConstantInfo> lookupEnumConstant(llvm::StringRef Name);
175185

186+
/// Look for the context ID of the given C++ tag.
187+
///
188+
/// \param Name The name of the tag we're looking for.
189+
/// \param ParentCtx The context in which this tag is declared, e.g. a C++
190+
/// namespace.
191+
///
192+
/// \returns The ID, if known.
193+
std::optional<ContextID>
194+
lookupTagID(llvm::StringRef Name,
195+
std::optional<Context> ParentCtx = std::nullopt);
196+
176197
/// Look for information regarding the given tag
177198
/// (struct/union/enum/C++ class).
178199
///

clang/include/clang/APINotes/APINotesWriter.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,14 @@ class APINotesWriter {
7878
bool IsInstanceMethod, const ObjCMethodInfo &Info,
7979
llvm::VersionTuple SwiftVersion);
8080

81+
/// Add information about a specific C++ method.
82+
///
83+
/// \param CtxID The context in which this method resides, i.e. a C++ tag.
84+
/// \param Name The name of the method.
85+
/// \param Info Information about this method.
86+
void addCXXMethod(ContextID CtxID, llvm::StringRef Name,
87+
const CXXMethodInfo &Info, llvm::VersionTuple SwiftVersion);
88+
8189
/// Add information about a global variable.
8290
///
8391
/// \param Name The name of this global variable.

clang/include/clang/APINotes/Types.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,12 @@ class GlobalFunctionInfo : public FunctionInfo {
659659
GlobalFunctionInfo() {}
660660
};
661661

662+
/// Describes API notes data for a C++ method.
663+
class CXXMethodInfo : public FunctionInfo {
664+
public:
665+
CXXMethodInfo() {}
666+
};
667+
662668
/// Describes API notes data for an enumerator.
663669
class EnumConstantInfo : public CommonEntityInfo {
664670
public:
@@ -792,6 +798,7 @@ enum class ContextKind : uint8_t {
792798
ObjCClass = 0,
793799
ObjCProtocol = 1,
794800
Namespace = 2,
801+
Tag = 3,
795802
};
796803

797804
struct Context {

clang/lib/APINotes/APINotesFormat.h

Lines changed: 78 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const uint16_t VERSION_MAJOR = 0;
2424
/// API notes file minor version number.
2525
///
2626
/// When the format changes IN ANY WAY, this number should be incremented.
27-
const uint16_t VERSION_MINOR = 26; // SwiftCopyable
27+
const uint16_t VERSION_MINOR = 27; // SingleDeclTableKey
2828

2929
const uint8_t kSwiftCopyable = 1;
3030
const uint8_t kSwiftNonCopyable = 2;
@@ -63,6 +63,10 @@ enum BlockID {
6363
/// about the method.
6464
OBJC_METHOD_BLOCK_ID,
6565

66+
/// The C++ method data block, which maps C++ (context id, method name) pairs
67+
/// to information about the method.
68+
CXX_METHOD_BLOCK_ID,
69+
6670
/// The Objective-C selector data block, which maps Objective-C
6771
/// selector names (# of pieces, identifier IDs) to the selector ID
6872
/// used in other tables.
@@ -181,6 +185,20 @@ using ObjCMethodDataLayout =
181185
>;
182186
} // namespace objc_method_block
183187

188+
namespace cxx_method_block {
189+
enum {
190+
CXX_METHOD_DATA = 1,
191+
};
192+
193+
using CXXMethodDataLayout =
194+
llvm::BCRecordLayout<CXX_METHOD_DATA, // record ID
195+
llvm::BCVBR<16>, // table offset within the blob (see
196+
// below)
197+
llvm::BCBlob // map from C++ (context id, name)
198+
// tuples to C++ method information
199+
>;
200+
} // namespace cxx_method_block
201+
184202
namespace objc_selector_block {
185203
enum {
186204
OBJC_SELECTOR_DATA = 1,
@@ -269,11 +287,16 @@ struct ContextTableKey {
269287
: parentContextID(parentContextID), contextKind(contextKind),
270288
contextID(contextID) {}
271289

272-
ContextTableKey(std::optional<Context> context, IdentifierID nameID)
273-
: parentContextID(context ? context->id.Value : (uint32_t)-1),
274-
contextKind(context ? static_cast<uint8_t>(context->kind)
275-
: static_cast<uint8_t>(-1)),
276-
contextID(nameID) {}
290+
ContextTableKey(std::optional<ContextID> ParentContextID, ContextKind Kind,
291+
uint32_t ContextID)
292+
: parentContextID(ParentContextID ? ParentContextID->Value : -1),
293+
contextKind(static_cast<uint8_t>(Kind)), contextID(ContextID) {}
294+
295+
ContextTableKey(std::optional<Context> ParentContext, ContextKind Kind,
296+
uint32_t ContextID)
297+
: ContextTableKey(ParentContext ? std::make_optional(ParentContext->id)
298+
: std::nullopt,
299+
Kind, ContextID) {}
277300

278301
llvm::hash_code hashValue() const {
279302
return llvm::hash_value(
@@ -286,6 +309,32 @@ inline bool operator==(const ContextTableKey &lhs, const ContextTableKey &rhs) {
286309
lhs.contextKind == rhs.contextKind && lhs.contextID == rhs.contextID;
287310
}
288311

312+
/// A stored Objective-C or C++ declaration, represented by the ID of its parent
313+
/// context, and the name of the declaration.
314+
struct SingleDeclTableKey {
315+
uint32_t parentContextID;
316+
uint32_t nameID;
317+
318+
SingleDeclTableKey() : parentContextID(-1), nameID(-1) {}
319+
320+
SingleDeclTableKey(uint32_t ParentContextID, uint32_t NameID)
321+
: parentContextID(ParentContextID), nameID(NameID) {}
322+
323+
SingleDeclTableKey(std::optional<Context> ParentCtx, IdentifierID NameID)
324+
: parentContextID(ParentCtx ? ParentCtx->id.Value
325+
: static_cast<uint32_t>(-1)),
326+
nameID(NameID) {}
327+
328+
llvm::hash_code hashValue() const {
329+
return llvm::hash_value(std::make_pair(parentContextID, nameID));
330+
}
331+
};
332+
333+
inline bool operator==(const SingleDeclTableKey &lhs,
334+
const SingleDeclTableKey &rhs) {
335+
return lhs.parentContextID == rhs.parentContextID && lhs.nameID == rhs.nameID;
336+
}
337+
289338
} // namespace api_notes
290339
} // namespace clang
291340

@@ -341,6 +390,29 @@ template <> struct DenseMapInfo<clang::api_notes::ContextTableKey> {
341390
return lhs == rhs;
342391
}
343392
};
393+
394+
template <> struct DenseMapInfo<clang::api_notes::SingleDeclTableKey> {
395+
static inline clang::api_notes::SingleDeclTableKey getEmptyKey() {
396+
return clang::api_notes::SingleDeclTableKey();
397+
}
398+
399+
static inline clang::api_notes::SingleDeclTableKey getTombstoneKey() {
400+
return clang::api_notes::SingleDeclTableKey{
401+
DenseMapInfo<uint32_t>::getTombstoneKey(),
402+
DenseMapInfo<uint32_t>::getTombstoneKey()};
403+
}
404+
405+
static unsigned
406+
getHashValue(const clang::api_notes::SingleDeclTableKey &value) {
407+
return value.hashValue();
408+
}
409+
410+
static bool isEqual(const clang::api_notes::SingleDeclTableKey &lhs,
411+
const clang::api_notes::SingleDeclTableKey &rhs) {
412+
return lhs == rhs;
413+
}
414+
};
415+
344416
} // namespace llvm
345417

346418
#endif

0 commit comments

Comments
 (0)