Skip to content

🍒[APINotes] Support annotating C++ methods #9014

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions clang/include/clang/APINotes/APINotesReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,16 @@ class APINotesReader {
ObjCSelectorRef Selector,
bool IsInstanceMethod);

/// Look for information regarding the given C++ method in the given C++ tag
/// context.
///
/// \param CtxID The ID that references the parent context, i.e. a C++ tag.
/// \param Name The name of the C++ method we're looking for.
///
/// \returns Information about the method, if known.
VersionedInfo<CXXMethodInfo> lookupCXXMethod(ContextID CtxID,
llvm::StringRef Name);

/// Look for information regarding the given global variable.
///
/// \param Name The name of the global variable.
Expand All @@ -173,6 +183,17 @@ class APINotesReader {
/// \returns information about the enumerator, if known.
VersionedInfo<EnumConstantInfo> lookupEnumConstant(llvm::StringRef Name);

/// Look for the context ID of the given C++ tag.
///
/// \param Name The name of the tag we're looking for.
/// \param ParentCtx The context in which this tag is declared, e.g. a C++
/// namespace.
///
/// \returns The ID, if known.
std::optional<ContextID>
lookupTagID(llvm::StringRef Name,
std::optional<Context> ParentCtx = std::nullopt);

/// Look for information regarding the given tag
/// (struct/union/enum/C++ class).
///
Expand Down
8 changes: 8 additions & 0 deletions clang/include/clang/APINotes/APINotesWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,14 @@ class APINotesWriter {
bool IsInstanceMethod, const ObjCMethodInfo &Info,
llvm::VersionTuple SwiftVersion);

/// Add information about a specific C++ method.
///
/// \param CtxID The context in which this method resides, i.e. a C++ tag.
/// \param Name The name of the method.
/// \param Info Information about this method.
void addCXXMethod(ContextID CtxID, llvm::StringRef Name,
const CXXMethodInfo &Info, llvm::VersionTuple SwiftVersion);

/// Add information about a global variable.
///
/// \param Name The name of this global variable.
Expand Down
7 changes: 7 additions & 0 deletions clang/include/clang/APINotes/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -659,6 +659,12 @@ class GlobalFunctionInfo : public FunctionInfo {
GlobalFunctionInfo() {}
};

/// Describes API notes data for a C++ method.
class CXXMethodInfo : public FunctionInfo {
public:
CXXMethodInfo() {}
};

/// Describes API notes data for an enumerator.
class EnumConstantInfo : public CommonEntityInfo {
public:
Expand Down Expand Up @@ -792,6 +798,7 @@ enum class ContextKind : uint8_t {
ObjCClass = 0,
ObjCProtocol = 1,
Namespace = 2,
Tag = 3,
};

struct Context {
Expand Down
84 changes: 78 additions & 6 deletions clang/lib/APINotes/APINotesFormat.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const uint16_t VERSION_MAJOR = 0;
/// API notes file minor version number.
///
/// When the format changes IN ANY WAY, this number should be incremented.
const uint16_t VERSION_MINOR = 26; // SwiftCopyable
const uint16_t VERSION_MINOR = 27; // SingleDeclTableKey

const uint8_t kSwiftCopyable = 1;
const uint8_t kSwiftNonCopyable = 2;
Expand Down Expand Up @@ -63,6 +63,10 @@ enum BlockID {
/// about the method.
OBJC_METHOD_BLOCK_ID,

/// The C++ method data block, which maps C++ (context id, method name) pairs
/// to information about the method.
CXX_METHOD_BLOCK_ID,

/// The Objective-C selector data block, which maps Objective-C
/// selector names (# of pieces, identifier IDs) to the selector ID
/// used in other tables.
Expand Down Expand Up @@ -181,6 +185,20 @@ using ObjCMethodDataLayout =
>;
} // namespace objc_method_block

namespace cxx_method_block {
enum {
CXX_METHOD_DATA = 1,
};

using CXXMethodDataLayout =
llvm::BCRecordLayout<CXX_METHOD_DATA, // record ID
llvm::BCVBR<16>, // table offset within the blob (see
// below)
llvm::BCBlob // map from C++ (context id, name)
// tuples to C++ method information
>;
} // namespace cxx_method_block

namespace objc_selector_block {
enum {
OBJC_SELECTOR_DATA = 1,
Expand Down Expand Up @@ -269,11 +287,16 @@ struct ContextTableKey {
: parentContextID(parentContextID), contextKind(contextKind),
contextID(contextID) {}

ContextTableKey(std::optional<Context> context, IdentifierID nameID)
: parentContextID(context ? context->id.Value : (uint32_t)-1),
contextKind(context ? static_cast<uint8_t>(context->kind)
: static_cast<uint8_t>(-1)),
contextID(nameID) {}
ContextTableKey(std::optional<ContextID> ParentContextID, ContextKind Kind,
uint32_t ContextID)
: parentContextID(ParentContextID ? ParentContextID->Value : -1),
contextKind(static_cast<uint8_t>(Kind)), contextID(ContextID) {}

ContextTableKey(std::optional<Context> ParentContext, ContextKind Kind,
uint32_t ContextID)
: ContextTableKey(ParentContext ? std::make_optional(ParentContext->id)
: std::nullopt,
Kind, ContextID) {}

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

/// A stored Objective-C or C++ declaration, represented by the ID of its parent
/// context, and the name of the declaration.
struct SingleDeclTableKey {
uint32_t parentContextID;
uint32_t nameID;

SingleDeclTableKey() : parentContextID(-1), nameID(-1) {}

SingleDeclTableKey(uint32_t ParentContextID, uint32_t NameID)
: parentContextID(ParentContextID), nameID(NameID) {}

SingleDeclTableKey(std::optional<Context> ParentCtx, IdentifierID NameID)
: parentContextID(ParentCtx ? ParentCtx->id.Value
: static_cast<uint32_t>(-1)),
nameID(NameID) {}

llvm::hash_code hashValue() const {
return llvm::hash_value(std::make_pair(parentContextID, nameID));
}
};

inline bool operator==(const SingleDeclTableKey &lhs,
const SingleDeclTableKey &rhs) {
return lhs.parentContextID == rhs.parentContextID && lhs.nameID == rhs.nameID;
}

} // namespace api_notes
} // namespace clang

Expand Down Expand Up @@ -341,6 +390,29 @@ template <> struct DenseMapInfo<clang::api_notes::ContextTableKey> {
return lhs == rhs;
}
};

template <> struct DenseMapInfo<clang::api_notes::SingleDeclTableKey> {
static inline clang::api_notes::SingleDeclTableKey getEmptyKey() {
return clang::api_notes::SingleDeclTableKey();
}

static inline clang::api_notes::SingleDeclTableKey getTombstoneKey() {
return clang::api_notes::SingleDeclTableKey{
DenseMapInfo<uint32_t>::getTombstoneKey(),
DenseMapInfo<uint32_t>::getTombstoneKey()};
}

static unsigned
getHashValue(const clang::api_notes::SingleDeclTableKey &value) {
return value.hashValue();
}

static bool isEqual(const clang::api_notes::SingleDeclTableKey &lhs,
const clang::api_notes::SingleDeclTableKey &rhs) {
return lhs == rhs;
}
};

} // namespace llvm

#endif
Loading