llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: StoeckOverflow
<details>
<summary>Changes</summary>
This PR builds on #<!-- -->203227 by serializing function-like
`Where.Parameters` selectors into binary API notes.
The selector remains declaration-selection data, separate from annotation
payloads. Existing Sema paths still use name-only lookup and keep legacy broad
matching. Exact overload matching is left to the follow-up Sema PR.
## Format
This bumps the API notes minor version because the global-function and C++
method table key layout changes.
Function-like entries now use a shared binary key containing:
- parent context ID
- declaration name ID
- selector flags
- parameter count
- zero or more parameter type string IDs
The parameter type strings are stored through the existing identifier table.
The selector flag records whether `Where.Parameters` was present. This is
needed because an absent selector and an explicitly empty selector would
otherwise both have parameter count `0`:
```yaml
- Name: currentWidget
```
versus:
```yaml
- Name: currentWidget
Where:
Parameters: []
```
The first entry is the legacy broad/name-only key. The second entry is an exact
zero-explicit-parameter selector.
## Implementation Details
This introduces a shared `FunctionTableKey` for global functions and C++
methods, so same-name entries can be distinguished by optional exact parameter
selectors.
Existing name-only reader/writer APIs are preserved as compatibility wrappers.
New selector-aware overloads accept optional parameter strings:
- `std::nullopt` means broad/name-only key
- empty parameter list means exact zero-parameter selector
- non-empty parameter list means exact ordered parameter selector
The selector remains outside
`FunctionInfo`/`GlobalFunctionInfo`/`CXXMethodInfo`, because it identifies
which declaration an entry applies to rather than changing the imported
declaration effect.
Malformed empty `Where: {}` entries are rejected during conversion so they do
not silently fall back to broad name-only storage.
## Testing caveat
This PR keeps testing in the ordinary `clang/test/APINotes` FileCheck path and
does not add an APINotes binary lookup helper. As a result, the tests cover
YAML conversion and malformed selector diagnostics, but they do not directly
prove binary reader round-trip lookup for same-name/different-parameter entries.
The binary reader/writer support is implemented here. Direct end-to-end lookup
coverage will come with the follow-up Sema matching PR.
Reviewers: @<!-- -->Xazax-hun @<!-- -->egorzhdan @<!-- -->j-hui
---
Patch is 35.87 KiB, truncated to 20.00 KiB below, full version:
https://github.com/llvm/llvm-project/pull/204147.diff
19 Files Affected:
- (modified) clang/include/clang/APINotes/APINotesReader.h (+19)
- (modified) clang/include/clang/APINotes/APINotesWriter.h (+20)
- (modified) clang/lib/APINotes/APINotesFormat.h (+69-1)
- (modified) clang/lib/APINotes/APINotesReader.cpp (+95-17)
- (modified) clang/lib/APINotes/APINotesWriter.cpp (+74-21)
- (modified) clang/lib/APINotes/APINotesYAMLCompiler.cpp (+47-5)
- (added) clang/test/APINotes/Inputs/Headers/WhereParametersMapElement.apinotes
(+8)
- (added)
clang/test/APINotes/Inputs/Headers/WhereParametersMethodWhereSequence.apinotes
(+9)
- (added)
clang/test/APINotes/Inputs/Headers/WhereParametersMissingName.apinotes (+7)
- (added) clang/test/APINotes/Inputs/Headers/WhereParametersParser.apinotes
(+50)
- (added) clang/test/APINotes/Inputs/Headers/WhereParametersScalar.apinotes
(+7)
- (added)
clang/test/APINotes/Inputs/Headers/WhereParametersUnknownWhereKey.apinotes (+7)
- (added)
clang/test/APINotes/Inputs/Headers/WhereParametersWhereSequence.apinotes (+8)
- (added)
clang/test/APINotes/Inputs/WhereParametersConvertDiag/APINotes.apinotes (+15)
- (added)
clang/test/APINotes/Inputs/WhereParametersConvertDiag/WhereParametersConvertDiag.h
(+10)
- (added)
clang/test/APINotes/Inputs/WhereParametersEmptyWhereDiag/APINotes.apinotes
(+12)
- (added)
clang/test/APINotes/Inputs/WhereParametersEmptyWhereDiag/WhereParametersConvertDiag.h
(+10)
- (added) clang/test/APINotes/where-parameters-convert-diags.cpp (+6)
- (added) clang/test/APINotes/where-parameters-yaml.test (+56)
``````````diff
diff --git a/clang/include/clang/APINotes/APINotesReader.h
b/clang/include/clang/APINotes/APINotesReader.h
index 875c314b284c1..c5e32dc6a51c7 100644
--- a/clang/include/clang/APINotes/APINotesReader.h
+++ b/clang/include/clang/APINotes/APINotesReader.h
@@ -16,10 +16,12 @@
#define LLVM_CLANG_APINOTES_READER_H
#include "clang/APINotes/Types.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/VersionTuple.h"
#include <memory>
+#include <optional>
namespace clang {
namespace api_notes {
@@ -159,6 +161,14 @@ class APINotesReader {
VersionedInfo<CXXMethodInfo> lookupCXXMethod(ContextID CtxID,
llvm::StringRef Name);
+ /// Look for information regarding the given C++ method with an optional
+ /// parameter selector. Passing std::nullopt uses the name-only key, an empty
+ /// parameter list uses an exact zero-parameter key, and a non-empty list
uses
+ /// an exact ordered parameter key.
+ VersionedInfo<CXXMethodInfo>
+ lookupCXXMethod(ContextID CtxID, llvm::StringRef Name,
+ std::optional<llvm::ArrayRef<llvm::StringRef>> Parameters);
+
/// Look for information regarding the given global variable.
///
/// \param Name The name of the global variable.
@@ -177,6 +187,15 @@ class APINotesReader {
lookupGlobalFunction(llvm::StringRef Name,
std::optional<Context> Ctx = std::nullopt);
+ /// Look for information regarding the given global function with an optional
+ /// parameter selector. Passing std::nullopt uses the name-only key, an empty
+ /// parameter list uses an exact zero-parameter key, and a non-empty list
uses
+ /// an exact ordered parameter key.
+ VersionedInfo<GlobalFunctionInfo> lookupGlobalFunction(
+ llvm::StringRef Name,
+ std::optional<llvm::ArrayRef<llvm::StringRef>> Parameters,
+ std::optional<Context> Ctx = std::nullopt);
+
/// Look for information regarding the given enumerator.
///
/// \param Name The name of the enumerator.
diff --git a/clang/include/clang/APINotes/APINotesWriter.h
b/clang/include/clang/APINotes/APINotesWriter.h
index 3cc16c3d959fa..5abea950aac14 100644
--- a/clang/include/clang/APINotes/APINotesWriter.h
+++ b/clang/include/clang/APINotes/APINotesWriter.h
@@ -16,11 +16,13 @@
#define LLVM_CLANG_APINOTES_WRITER_H
#include "clang/APINotes/Types.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/VersionTuple.h"
#include "llvm/Support/raw_ostream.h"
#include <memory>
+#include <optional>
namespace clang {
class FileEntry;
@@ -86,6 +88,14 @@ class APINotesWriter {
void addCXXMethod(ContextID CtxID, llvm::StringRef Name,
const CXXMethodInfo &Info, llvm::VersionTuple
SwiftVersion);
+ /// Add information about a C++ method with an optional parameter selector.
+ /// Passing std::nullopt uses the name-only key, an empty parameter list uses
+ /// an exact zero-parameter key, and a non-empty list uses an exact ordered
+ /// parameter key.
+ void addCXXMethod(ContextID CtxID, llvm::StringRef Name,
+ std::optional<llvm::ArrayRef<llvm::StringRef>> Parameters,
+ const CXXMethodInfo &Info, llvm::VersionTuple
SwiftVersion);
+
/// Add information about a specific C record field.
///
/// \param CtxID The context in which this field resides, i.e. a C/C++ tag.
@@ -110,6 +120,16 @@ class APINotesWriter {
const GlobalFunctionInfo &Info,
llvm::VersionTuple SwiftVersion);
+ /// Add information about a global function with an optional parameter
+ /// selector. Passing std::nullopt uses the name-only key, an empty parameter
+ /// list uses an exact zero-parameter key, and a non-empty list uses an exact
+ /// ordered parameter key.
+ void
+ addGlobalFunction(std::optional<Context> Ctx, llvm::StringRef Name,
+ std::optional<llvm::ArrayRef<llvm::StringRef>> Parameters,
+ const GlobalFunctionInfo &Info,
+ llvm::VersionTuple SwiftVersion);
+
/// Add information about an enumerator.
///
/// \param Name The name of this enumerator.
diff --git a/clang/lib/APINotes/APINotesFormat.h
b/clang/lib/APINotes/APINotesFormat.h
index 5679ae39e9900..6f78ede4f608f 100644
--- a/clang/lib/APINotes/APINotesFormat.h
+++ b/clang/lib/APINotes/APINotesFormat.h
@@ -11,8 +11,12 @@
#include "clang/APINotes/Types.h"
#include "llvm/ADT/PointerEmbeddedInt.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/Bitcode/BitcodeConvenience.h"
+#include <optional>
+#include <utility>
+
namespace clang {
namespace api_notes {
/// Magic number for API notes files.
@@ -24,8 +28,9 @@ 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 = 40; // 39 for BoundsSafety;
+const uint16_t VERSION_MINOR = 41; // 39 for BoundsSafety;
// 40 for UnsafeBufferUsageAttr
+ // 41 for FunctionTableKey parameters
const uint8_t kSwiftConforms = 1;
const uint8_t kSwiftDoesNotConform = 2;
@@ -354,6 +359,57 @@ inline bool operator==(const SingleDeclTableKey &lhs,
return lhs.parentContextID == rhs.parentContextID && lhs.nameID ==
rhs.nameID;
}
+/// A stored C or C++ function declaration, represented by the ID of its parent
+/// context, the name of the declaration, and optional exact parameter types.
+constexpr uint8_t FunctionKeyHasParameterSelector = 0x01;
+constexpr unsigned FunctionTableKeyBaseLength =
+ sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint8_t) + sizeof(uint16_t);
+
+struct FunctionTableKey {
+ uint32_t parentContextID;
+ uint32_t nameID;
+ std::optional<llvm::SmallVector<IdentifierID, 2>> parameterTypeIDs;
+
+ FunctionTableKey() : parentContextID(-1), nameID(-1) {}
+
+ FunctionTableKey(uint32_t ParentContextID, uint32_t NameID)
+ : parentContextID(ParentContextID), nameID(NameID) {}
+
+ FunctionTableKey(uint32_t ParentContextID, uint32_t NameID,
+ llvm::SmallVector<IdentifierID, 2> ParameterTypeIDs)
+ : parentContextID(ParentContextID), nameID(NameID),
+ parameterTypeIDs(std::move(ParameterTypeIDs)) {}
+
+ FunctionTableKey(std::optional<Context> ParentCtx, IdentifierID NameID)
+ : parentContextID(ParentCtx ? ParentCtx->id.Value
+ : static_cast<uint32_t>(-1)),
+ nameID(NameID) {}
+
+ FunctionTableKey(std::optional<Context> ParentCtx, IdentifierID NameID,
+ llvm::SmallVector<IdentifierID, 2> ParameterTypeIDs)
+ : parentContextID(ParentCtx ? ParentCtx->id.Value
+ : static_cast<uint32_t>(-1)),
+ nameID(NameID), parameterTypeIDs(std::move(ParameterTypeIDs)) {}
+
+ llvm::hash_code hashValue() const {
+ auto Hash = llvm::hash_combine(parentContextID, nameID,
+ static_cast<bool>(parameterTypeIDs));
+ if (parameterTypeIDs) {
+ Hash = llvm::hash_combine(Hash, parameterTypeIDs->size());
+ for (IdentifierID TypeID : *parameterTypeIDs)
+ Hash = llvm::hash_combine(Hash, static_cast<unsigned>(TypeID));
+ }
+ return Hash;
+ }
+};
+
+inline bool operator==(const FunctionTableKey &lhs,
+ const FunctionTableKey &rhs) {
+ return lhs.parentContextID == rhs.parentContextID &&
+ lhs.nameID == rhs.nameID &&
+ lhs.parameterTypeIDs == rhs.parameterTypeIDs;
+}
+
} // namespace api_notes
} // namespace clang
@@ -401,6 +457,18 @@ template <> struct
DenseMapInfo<clang::api_notes::SingleDeclTableKey> {
}
};
+template <> struct DenseMapInfo<clang::api_notes::FunctionTableKey> {
+ static unsigned
+ getHashValue(const clang::api_notes::FunctionTableKey &value) {
+ return value.hashValue();
+ }
+
+ static bool isEqual(const clang::api_notes::FunctionTableKey &lhs,
+ const clang::api_notes::FunctionTableKey &rhs) {
+ return lhs == rhs;
+ }
+};
+
} // namespace llvm
#endif
diff --git a/clang/lib/APINotes/APINotesReader.cpp
b/clang/lib/APINotes/APINotesReader.cpp
index 7713e47cba3a9..5ac172b369444 100644
--- a/clang/lib/APINotes/APINotesReader.cpp
+++ b/clang/lib/APINotes/APINotesReader.cpp
@@ -46,6 +46,38 @@ llvm::VersionTuple ReadVersionTuple(const uint8_t *&Data) {
return llvm::VersionTuple(Major, Minor, Subminor, Build);
}
+static FunctionTableKey readFunctionTableKey(const uint8_t *Data,
+ unsigned Length) {
+ assert(Length >= FunctionTableKeyBaseLength &&
+ "Unexpected function table key length");
+
+ auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
+ auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
+ uint8_t FunctionKeyFlags =
+ endian::readNext<uint8_t, llvm::endianness::little>(Data);
+ auto ParameterCount =
+ endian::readNext<uint16_t, llvm::endianness::little>(Data);
+
+ assert(Length ==
+ FunctionTableKeyBaseLength + ParameterCount * sizeof(uint32_t) &&
+ "Unexpected function table key length");
+
+ llvm::SmallVector<IdentifierID, 2> ParameterTypeIDs;
+ ParameterTypeIDs.reserve(ParameterCount);
+ for (unsigned I = 0; I != ParameterCount; ++I)
+ ParameterTypeIDs.push_back(
+ endian::readNext<uint32_t, llvm::endianness::little>(Data));
+
+ assert((FunctionKeyFlags & ~FunctionKeyHasParameterSelector) == 0 &&
+ "Unexpected function table key flags");
+ if (FunctionKeyFlags & FunctionKeyHasParameterSelector)
+ return {CtxID, NameID, std::move(ParameterTypeIDs)};
+
+ assert(ParameterTypeIDs.empty() &&
+ "Broad function table key should not store parameters");
+ return {CtxID, NameID};
+}
+
/// An on-disk hash table whose data is versioned based on the Swift version.
template <typename Derived, typename KeyType, typename UnversionedDataType>
class VersionedTableInfo {
@@ -527,13 +559,11 @@ class GlobalVariableTableInfo
/// Used to deserialize the on-disk global function table.
class GlobalFunctionTableInfo
- : public VersionedTableInfo<GlobalFunctionTableInfo, SingleDeclTableKey,
+ : public VersionedTableInfo<GlobalFunctionTableInfo, FunctionTableKey,
GlobalFunctionInfo> {
public:
static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
- auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
- auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
- return {CtxID, NameID};
+ return readFunctionTableKey(Data, Length);
}
hash_value_type ComputeHash(internal_key_type Key) {
@@ -550,13 +580,11 @@ class GlobalFunctionTableInfo
/// Used to deserialize the on-disk C++ method table.
class CXXMethodTableInfo
- : public VersionedTableInfo<CXXMethodTableInfo, SingleDeclTableKey,
+ : public VersionedTableInfo<CXXMethodTableInfo, FunctionTableKey,
CXXMethodInfo> {
public:
static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
- auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
- auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
- return {CtxID, NameID};
+ return readFunctionTableKey(Data, Length);
}
hash_value_type ComputeHash(internal_key_type Key) {
@@ -827,6 +855,13 @@ class APINotesReader::Implementation {
llvm::SmallVectorImpl<uint64_t> &Scratch);
llvm::Error readGlobalVariableBlock(llvm::BitstreamCursor &Cursor,
llvm::SmallVectorImpl<uint64_t>
&Scratch);
+ std::optional<FunctionTableKey>
+ getFunctionKey(uint32_t ParentContextID, llvm::StringRef Name,
+ std::optional<llvm::ArrayRef<llvm::StringRef>> Parameters);
+ std::optional<FunctionTableKey>
+ getFunctionKey(std::optional<Context> ParentContext, llvm::StringRef Name,
+ std::optional<llvm::ArrayRef<llvm::StringRef>> Parameters);
+
llvm::Error readGlobalFunctionBlock(llvm::BitstreamCursor &Cursor,
llvm::SmallVectorImpl<uint64_t>
&Scratch);
llvm::Error readEnumConstantBlock(llvm::BitstreamCursor &Cursor,
@@ -852,6 +887,36 @@
APINotesReader::Implementation::getIdentifier(llvm::StringRef Str) {
return *Known;
}
+std::optional<FunctionTableKey> APINotesReader::Implementation::getFunctionKey(
+ uint32_t ParentContextID, llvm::StringRef Name,
+ std::optional<llvm::ArrayRef<llvm::StringRef>> Parameters) {
+ std::optional<IdentifierID> NameID = getIdentifier(Name);
+ if (!NameID)
+ return std::nullopt;
+
+ if (!Parameters)
+ return FunctionTableKey(ParentContextID, *NameID);
+
+ llvm::SmallVector<IdentifierID, 2> ParameterTypeIDs;
+ ParameterTypeIDs.reserve(Parameters->size());
+ for (llvm::StringRef Parameter : *Parameters) {
+ std::optional<IdentifierID> ParameterID = getIdentifier(Parameter);
+ if (!ParameterID)
+ return std::nullopt;
+ ParameterTypeIDs.push_back(*ParameterID);
+ }
+ return FunctionTableKey(ParentContextID, *NameID,
+ std::move(ParameterTypeIDs));
+}
+
+std::optional<FunctionTableKey> APINotesReader::Implementation::getFunctionKey(
+ std::optional<Context> ParentContext, llvm::StringRef Name,
+ std::optional<llvm::ArrayRef<llvm::StringRef>> Parameters) {
+ uint32_t ParentContextID =
+ ParentContext ? ParentContext->id.Value : static_cast<uint32_t>(-1);
+ return getFunctionKey(ParentContextID, Name, Parameters);
+}
+
std::optional<SelectorID>
APINotesReader::Implementation::getSelector(ObjCSelectorRef Selector) {
if (!ObjCSelectorTable || !IdentifierTable)
@@ -2268,15 +2333,22 @@ auto APINotesReader::lookupField(ContextID CtxID,
llvm::StringRef Name)
auto APINotesReader::lookupCXXMethod(ContextID CtxID, llvm::StringRef Name)
-> VersionedInfo<CXXMethodInfo> {
+ return lookupCXXMethod(CtxID, Name, std::nullopt);
+}
+
+auto APINotesReader::lookupCXXMethod(
+ ContextID CtxID, llvm::StringRef Name,
+ std::optional<llvm::ArrayRef<llvm::StringRef>> Parameters)
+ -> VersionedInfo<CXXMethodInfo> {
if (!Implementation->CXXMethodTable)
return std::nullopt;
- std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
- if (!NameID)
+ std::optional<FunctionTableKey> Key =
+ Implementation->getFunctionKey(CtxID.Value, Name, Parameters);
+ if (!Key)
return std::nullopt;
- auto Known = Implementation->CXXMethodTable->find(
- SingleDeclTableKey(CtxID.Value, *NameID));
+ auto Known = Implementation->CXXMethodTable->find(*Key);
if (Known == Implementation->CXXMethodTable->end())
return std::nullopt;
@@ -2305,16 +2377,22 @@ auto
APINotesReader::lookupGlobalVariable(llvm::StringRef Name,
auto APINotesReader::lookupGlobalFunction(llvm::StringRef Name,
std::optional<Context> Ctx)
-> VersionedInfo<GlobalFunctionInfo> {
+ return lookupGlobalFunction(Name, std::nullopt, Ctx);
+}
+
+auto APINotesReader::lookupGlobalFunction(
+ llvm::StringRef Name,
+ std::optional<llvm::ArrayRef<llvm::StringRef>> Parameters,
+ std::optional<Context> Ctx) -> VersionedInfo<GlobalFunctionInfo> {
if (!Implementation->GlobalFunctionTable)
return std::nullopt;
- std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
- if (!NameID)
+ std::optional<FunctionTableKey> Key =
+ Implementation->getFunctionKey(Ctx, Name, Parameters);
+ if (!Key)
return std::nullopt;
- SingleDeclTableKey Key(Ctx, *NameID);
-
- auto Known = Implementation->GlobalFunctionTable->find(Key);
+ auto Known = Implementation->GlobalFunctionTable->find(*Key);
if (Known == Implementation->GlobalFunctionTable->end())
return std::nullopt;
diff --git a/clang/lib/APINotes/APINotesWriter.cpp
b/clang/lib/APINotes/APINotesWriter.cpp
index 61150669d8329..48abeced839fc 100644
--- a/clang/lib/APINotes/APINotesWriter.cpp
+++ b/clang/lib/APINotes/APINotesWriter.cpp
@@ -82,8 +82,8 @@ class APINotesWriter::Implementation {
/// Information about C++ methods.
///
- /// Indexed by the context ID and name ID.
- llvm::DenseMap<SingleDeclTableKey,
+ /// Indexed by the context ID, name ID, and optional parameter selector.
+ llvm::DenseMap<FunctionTableKey,
llvm::SmallVector<std::pair<VersionTuple, CXXMethodInfo>, 1>>
CXXMethods;
@@ -100,9 +100,9 @@ class APINotesWriter::Implementation {
/// Information about global functions.
///
- /// Indexed by the context ID, identifier ID.
+ /// Indexed by the context ID, identifier ID, and optional parameter
selector.
llvm::DenseMap<
- SingleDeclTableKey,
+ FunctionTableKey,
llvm::SmallVector<std::pair<VersionTuple, GlobalFunctionInfo>, 1>>
GlobalFunctions;
@@ -137,6 +137,29 @@ class APINotesWriter::Implementation {
.first->second;
}
+ FunctionTableKey
+ getFunctionKey(uint32_t ParentContextID, StringRef Name,
+ std::optional<ArrayRef<StringRef>> Parameters = std::nullopt)
{
+ IdentifierID NameID = getIdentifier(Name);
+ if (!Parameters)
+ return FunctionTableKey(ParentContextID, NameID);
+
+ llvm::SmallVector<IdentifierID, 2> ParameterTypeIDs;
+ ParameterTypeIDs.reserve(Parameters->size());
+ for (StringRef Parameter : *Parameters)
+ ParameterTypeIDs.push_back(getIdentifier(Parameter));
+ return FunctionTableKey(ParentContextID, NameID,
+ std::move(ParameterTypeIDs));
+ }
+
+ FunctionTableKey
+ getFunctionKey(std::optional<Context> ParentContext, StringRef Name,
+ std::optional<ArrayRef<StringRef>> Parameters = std::nullopt)
{
+ uint32_t ParentContextID =
+ ParentContext ? ParentContext->id.Value : static_cast<uint32_t>(-1);
+ return getFunctionKey(ParentContextID, Name, Parameters);
+ }
+
/// Retrieve the ID for the given selector.
SelectorID getSelector(ObjCSelectorRef SelectorRef) {
// Translate the selector reference into a stored selector.
@@ -387,7 +410,9 @@ class ContextIDTableInfo {
/// Localized helper to make a type dependent, thwarting template argument
/// deduction.
-template <typename T> struct MakeDependent { typedef T Type; };
+template <typename T> struct MakeDependent {
+ typedef T Type;
+};
/// Retrieve the serialized size of the given VersionTuple, for use in
/// on-disk hash tables.
@@ -465,6 +490,25 @@ void emitVersionedInfo(
}
}
+static unsigned getFunctionTableKeyLength(const FunctionTableKey &Key) {
+ return FunctionTableKeyBaseLength +
+ (Key.parameterTypeIDs ? Key.parameterTypeIDs->size() *
sizeof(uint32_t)
+ : 0);
+}
+
+static void emitFunctionTableKey(raw_ostream &OS, const FunctionTableKey &Key)
{
+ llvm::support::endian::Writer writer(OS, llvm::endianness::little);
+ writer.write<uint32_t>(Key.parentContextID);
+ writer.write<uint32_t>(Key.nameID);
+ writer.write<uint8_t>(Key.parameterTypeIDs ? FunctionKeyHasParameterSelector
+ : 0);
+ writer.write<uint16_t>(Key.parameterTypeIDs ? Key.parameterTypeIDs->size()
+ : 0);
+ if (Key.parameterTypeIDs)
+ for (IdentifierID TypeID : *Key.parameterTypeIDs)
+ writer.write<uint32_t>(TypeID);
+}
+
/// On-disk hash table info key base for handling versioned data.
template <typename Derived, typename KeyType, typename UnversionedDataType>
class VersionedTableInfo {
@@ -801,17 +845,15 @@ class ObjCMethodTableInfo
/// Used to serialize the on-disk C++ method table.
class CXXMethodTableInfo
- : public VersionedTableInfo<CXXMethodTableInfo, SingleDeclTableKey,
+ : public VersionedTableInfo<CXXMethodTableInfo, FunctionTableKey,
CXXMethodInfo> {
public:
- unsigned getKeyLength(key_type_ref) {
- return sizeof(uint32_t) + sizeof(uint32_t);
+ unsigned getKeyLength(key_type_ref Key) {
+ return getFunctionTableKeyLength(Key);
}
void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
- llvm::support::endian::Writer writer(OS, llvm::endianness::litt...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/204147
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits