https://github.com/StoeckOverflow updated 
https://github.com/llvm/llvm-project/pull/204147

>From 9a0d376597fe0ce04f5af1350ecced91679af5dd Mon Sep 17 00:00:00 2001
From: stoeckoverflow <[email protected]>
Date: Tue, 16 Jun 2026 14:08:09 +0200
Subject: [PATCH 1/2] [APINotes] Serialize function-like Where.Parameters

---
 clang/include/clang/APINotes/APINotesReader.h |  19 +++
 clang/include/clang/APINotes/APINotesWriter.h |  20 ++++
 clang/lib/APINotes/APINotesFormat.h           |  70 ++++++++++-
 clang/lib/APINotes/APINotesReader.cpp         | 112 +++++++++++++++---
 clang/lib/APINotes/APINotesWriter.cpp         |  95 +++++++++++----
 clang/lib/APINotes/APINotesYAMLCompiler.cpp   |  40 +++++--
 .../APINotes.apinotes                         |   9 +-
 .../WhereParametersConvertDiag.h              |   2 +
 .../APINotes.apinotes                         |  12 ++
 .../WhereParametersConvertDiag.h              |  10 ++
 .../where-parameters-convert-diags.cpp        |   5 +-
 11 files changed, 341 insertions(+), 53 deletions(-)
 create mode 100644 
clang/test/APINotes/Inputs/WhereParametersEmptyWhereDiag/APINotes.apinotes
 create mode 100644 
clang/test/APINotes/Inputs/WhereParametersEmptyWhereDiag/WhereParametersConvertDiag.h

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::little);
-    writer.write<uint32_t>(Key.parentContextID);
-    writer.write<uint32_t>(Key.nameID);
+    emitFunctionTableKey(OS, Key);
   }
 
   hash_value_type ComputeHash(key_type_ref key) {
@@ -1176,17 +1218,15 @@ void emitFunctionInfo(raw_ostream &OS, const 
FunctionInfo &FI) {
 
 /// Used to serialize the on-disk global function table.
 class GlobalFunctionTableInfo
-    : public VersionedTableInfo<GlobalFunctionTableInfo, SingleDeclTableKey,
+    : public VersionedTableInfo<GlobalFunctionTableInfo, FunctionTableKey,
                                 GlobalFunctionInfo> {
 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::little);
-    writer.write<uint32_t>(Key.parentContextID);
-    writer.write<uint32_t>(Key.nameID);
+    emitFunctionTableKey(OS, Key);
   }
 
   hash_value_type ComputeHash(key_type_ref Key) {
@@ -1567,8 +1607,15 @@ void APINotesWriter::addObjCMethod(ContextID CtxID, 
ObjCSelectorRef Selector,
 void APINotesWriter::addCXXMethod(ContextID CtxID, llvm::StringRef Name,
                                   const CXXMethodInfo &Info,
                                   VersionTuple SwiftVersion) {
-  IdentifierID NameID = Implementation->getIdentifier(Name);
-  SingleDeclTableKey Key(CtxID.Value, NameID);
+  addCXXMethod(CtxID, Name, std::nullopt, Info, SwiftVersion);
+}
+
+void APINotesWriter::addCXXMethod(
+    ContextID CtxID, llvm::StringRef Name,
+    std::optional<llvm::ArrayRef<llvm::StringRef>> Parameters,
+    const CXXMethodInfo &Info, VersionTuple SwiftVersion) {
+  FunctionTableKey Key =
+      Implementation->getFunctionKey(CtxID.Value, Name, Parameters);
   Implementation->CXXMethods[Key].push_back({SwiftVersion, Info});
 }
 
@@ -1593,8 +1640,14 @@ void 
APINotesWriter::addGlobalFunction(std::optional<Context> Ctx,
                                        llvm::StringRef Name,
                                        const GlobalFunctionInfo &Info,
                                        VersionTuple SwiftVersion) {
-  IdentifierID NameID = Implementation->getIdentifier(Name);
-  SingleDeclTableKey Key(Ctx, NameID);
+  addGlobalFunction(Ctx, Name, std::nullopt, Info, SwiftVersion);
+}
+
+void APINotesWriter::addGlobalFunction(
+    std::optional<Context> Ctx, llvm::StringRef Name,
+    std::optional<llvm::ArrayRef<llvm::StringRef>> Parameters,
+    const GlobalFunctionInfo &Info, VersionTuple SwiftVersion) {
+  FunctionTableKey Key = Implementation->getFunctionKey(Ctx, Name, Parameters);
   Implementation->GlobalFunctions[Key].push_back({SwiftVersion, Info});
 }
 
diff --git a/clang/lib/APINotes/APINotesYAMLCompiler.cpp 
b/clang/lib/APINotes/APINotesYAMLCompiler.cpp
index e17549f33d219..d02cd3a3f3c56 100644
--- a/clang/lib/APINotes/APINotesYAMLCompiler.cpp
+++ b/clang/lib/APINotes/APINotesYAMLCompiler.cpp
@@ -1043,6 +1043,22 @@ class YAMLConverter {
                          TheNamespace.Items, SwiftVersion);
   }
 
+  bool getWhereParameters(
+      const Function &Function,
+      std::optional<llvm::ArrayRef<llvm::StringRef>> &WhereParameters) {
+    WhereParameters = std::nullopt;
+    if (!Function.Where)
+      return true;
+
+    if (!Function.Where->Parameters) {
+      emitError("'Where' requires 'Parameters'");
+      return false;
+    }
+    WhereParameters =
+        llvm::ArrayRef<llvm::StringRef>(*Function.Where->Parameters);
+    return true;
+  }
+
   template <typename FuncOrMethodInfo>
   void convertFunction(const Function &Function, FuncOrMethodInfo &FI) {
     convertAvailability(Function.Availability, FI, Function.Name);
@@ -1151,14 +1167,14 @@ class YAMLConverter {
     }
 
     for (const auto &CXXMethod : T.Methods) {
-      if (CXXMethod.Where) {
-        emitError("'Where' is not supported by binary API notes yet");
+      std::optional<llvm::ArrayRef<llvm::StringRef>> WhereParameters;
+      if (!getWhereParameters(CXXMethod, WhereParameters))
         continue;
-      }
 
       CXXMethodInfo MI;
       convertFunction(CXXMethod, MI);
-      Writer.addCXXMethod(TagCtxID, CXXMethod.Name, MI, SwiftVersion);
+      Writer.addCXXMethod(TagCtxID, CXXMethod.Name, WhereParameters, MI,
+                          SwiftVersion);
     }
 
     // Convert nested tags.
@@ -1227,15 +1243,16 @@ class YAMLConverter {
     }
 
     // Write all global functions.
-    llvm::StringSet<> KnownFunctions;
+    llvm::StringSet<> KnownNameOnlyFunctions;
     for (const auto &Function : TLItems.Functions) {
-      if (Function.Where) {
-        emitError("'Where' is not supported by binary API notes yet");
+      std::optional<llvm::ArrayRef<llvm::StringRef>> WhereParameters;
+      if (!getWhereParameters(Function, WhereParameters))
         continue;
-      }
 
-      // Check for duplicate global functions.
-      if (!KnownFunctions.insert(Function.Name).second) {
+      // Check for duplicate name-only global functions. Selector-aware
+      // duplicate diagnostics are handled by a later overload-matching PR.
+      if (!WhereParameters &&
+          !KnownNameOnlyFunctions.insert(Function.Name).second) {
         emitError(llvm::Twine("multiple definitions of global function '") +
                   Function.Name + "'");
         continue;
@@ -1243,7 +1260,8 @@ class YAMLConverter {
 
       GlobalFunctionInfo GFI;
       convertFunction(Function, GFI);
-      Writer.addGlobalFunction(Ctx, Function.Name, GFI, SwiftVersion);
+      Writer.addGlobalFunction(Ctx, Function.Name, WhereParameters, GFI,
+                               SwiftVersion);
     }
 
     // Write all enumerators.
diff --git 
a/clang/test/APINotes/Inputs/WhereParametersConvertDiag/APINotes.apinotes 
b/clang/test/APINotes/Inputs/WhereParametersConvertDiag/APINotes.apinotes
index c1eca20d96e89..f6451eab24544 100644
--- a/clang/test/APINotes/Inputs/WhereParametersConvertDiag/APINotes.apinotes
+++ b/clang/test/APINotes/Inputs/WhereParametersConvertDiag/APINotes.apinotes
@@ -1,8 +1,15 @@
 ---
 Name: WhereParametersConvertDiag
+Functions:
+- Name: makeWidget
+  Where:
+    Parameters:
+      - int
+  SwiftName: makeWidget(_:)
 Tags:
 - Name: Widget
   Methods:
   - Name: reset
-    Where: {}
+    Where:
+      Parameters: []
     SwiftName: reset()
diff --git 
a/clang/test/APINotes/Inputs/WhereParametersConvertDiag/WhereParametersConvertDiag.h
 
b/clang/test/APINotes/Inputs/WhereParametersConvertDiag/WhereParametersConvertDiag.h
index 32dc081bfc036..6807ce279f99a 100644
--- 
a/clang/test/APINotes/Inputs/WhereParametersConvertDiag/WhereParametersConvertDiag.h
+++ 
b/clang/test/APINotes/Inputs/WhereParametersConvertDiag/WhereParametersConvertDiag.h
@@ -1,6 +1,8 @@
 #ifndef WHERE_PARAMETERS_CONVERT_DIAG_H
 #define WHERE_PARAMETERS_CONVERT_DIAG_H
 
+void makeWidget(int);
+
 struct Widget {
   void reset();
 };
diff --git 
a/clang/test/APINotes/Inputs/WhereParametersEmptyWhereDiag/APINotes.apinotes 
b/clang/test/APINotes/Inputs/WhereParametersEmptyWhereDiag/APINotes.apinotes
new file mode 100644
index 0000000000000..5017c5737e13a
--- /dev/null
+++ b/clang/test/APINotes/Inputs/WhereParametersEmptyWhereDiag/APINotes.apinotes
@@ -0,0 +1,12 @@
+---
+Name: WhereParametersConvertDiag
+Functions:
+- Name: makeWidget
+  Where: {}
+  SwiftName: makeWidget(_:)
+Tags:
+- Name: Widget
+  Methods:
+  - Name: reset
+    Where: {}
+    SwiftName: reset()
diff --git 
a/clang/test/APINotes/Inputs/WhereParametersEmptyWhereDiag/WhereParametersConvertDiag.h
 
b/clang/test/APINotes/Inputs/WhereParametersEmptyWhereDiag/WhereParametersConvertDiag.h
new file mode 100644
index 0000000000000..6807ce279f99a
--- /dev/null
+++ 
b/clang/test/APINotes/Inputs/WhereParametersEmptyWhereDiag/WhereParametersConvertDiag.h
@@ -0,0 +1,10 @@
+#ifndef WHERE_PARAMETERS_CONVERT_DIAG_H
+#define WHERE_PARAMETERS_CONVERT_DIAG_H
+
+void makeWidget(int);
+
+struct Widget {
+  void reset();
+};
+
+#endif // WHERE_PARAMETERS_CONVERT_DIAG_H
diff --git a/clang/test/APINotes/where-parameters-convert-diags.cpp 
b/clang/test/APINotes/where-parameters-convert-diags.cpp
index ee40efeaa865b..ed0b804a5385e 100644
--- a/clang/test/APINotes/where-parameters-convert-diags.cpp
+++ b/clang/test/APINotes/where-parameters-convert-diags.cpp
@@ -1,5 +1,6 @@
-// RUN: not %clang_cc1 -fsyntax-only -fapinotes %s -I 
%S/Inputs/WhereParametersConvertDiag 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -fsyntax-only -fapinotes %s -I 
%S/Inputs/WhereParametersConvertDiag
+// RUN: not %clang_cc1 -fsyntax-only -fapinotes %s -I 
%S/Inputs/WhereParametersEmptyWhereDiag 2>&1 | FileCheck %s 
--check-prefix=EMPTY-WHERE
 
 #include "WhereParametersConvertDiag.h"
 
-// CHECK: error: 'Where' is not supported by binary API notes yet
+// EMPTY-WHERE-COUNT-2: error: 'Where' requires 'Parameters'

>From d94367712b8065500a7401a5e1c8a8f3a25babf4 Mon Sep 17 00:00:00 2001
From: stoeckoverflow <[email protected]>
Date: Fri, 19 Jun 2026 10:47:20 +0200
Subject: [PATCH 2/2] [APINotes] Clean up function selector key APIs

---
 clang/include/clang/APINotes/APINotesReader.h |  38 ++++---
 clang/include/clang/APINotes/APINotesWriter.h |  25 ++---
 clang/lib/APINotes/APINotesFormat.h           |  46 +++++++-
 clang/lib/APINotes/APINotesReader.cpp         | 105 +++++++++++++-----
 clang/lib/APINotes/APINotesWriter.cpp         |  67 ++++++-----
 clang/lib/APINotes/APINotesYAMLCompiler.cpp   |  14 ++-
 6 files changed, 205 insertions(+), 90 deletions(-)

diff --git a/clang/include/clang/APINotes/APINotesReader.h 
b/clang/include/clang/APINotes/APINotesReader.h
index c5e32dc6a51c7..8e748b5803189 100644
--- a/clang/include/clang/APINotes/APINotesReader.h
+++ b/clang/include/clang/APINotes/APINotesReader.h
@@ -161,13 +161,12 @@ 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.
+  /// Look for information regarding the given C++ method with an exact
+  /// parameter selector. 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);
+                  llvm::ArrayRef<llvm::StringRef> Parameters);
 
   /// Look for information regarding the given global variable.
   ///
@@ -187,14 +186,13 @@ 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 global function with an exact
+  /// parameter selector. 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,
+                       llvm::ArrayRef<llvm::StringRef> Parameters,
+                       std::optional<Context> Ctx = std::nullopt);
 
   /// Look for information regarding the given enumerator.
   ///
@@ -240,6 +238,20 @@ class APINotesReader {
   std::optional<ContextID>
   lookupNamespaceID(llvm::StringRef Name,
                     std::optional<ContextID> ParentNamespaceID = std::nullopt);
+
+private:
+  VersionedInfo<CXXMethodInfo> lookupCXXMethodImpl(ContextID CtxID,
+                                                   llvm::StringRef Name);
+  VersionedInfo<CXXMethodInfo>
+  lookupCXXMethodImpl(ContextID CtxID, llvm::StringRef Name,
+                      llvm::ArrayRef<llvm::StringRef> Parameters);
+
+  VersionedInfo<GlobalFunctionInfo>
+  lookupGlobalFunctionImpl(llvm::StringRef Name, std::optional<Context> Ctx);
+  VersionedInfo<GlobalFunctionInfo>
+  lookupGlobalFunctionImpl(llvm::StringRef Name,
+                           llvm::ArrayRef<llvm::StringRef> Parameters,
+                           std::optional<Context> Ctx);
 };
 
 } // end namespace api_notes
diff --git a/clang/include/clang/APINotes/APINotesWriter.h 
b/clang/include/clang/APINotes/APINotesWriter.h
index 5abea950aac14..5ed6686e1bb85 100644
--- a/clang/include/clang/APINotes/APINotesWriter.h
+++ b/clang/include/clang/APINotes/APINotesWriter.h
@@ -88,12 +88,11 @@ 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.
+  /// Add information about a C++ method with an exact parameter selector. 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,
+                    llvm::ArrayRef<llvm::StringRef> Parameters,
                     const CXXMethodInfo &Info, llvm::VersionTuple 
SwiftVersion);
 
   /// Add information about a specific C record field.
@@ -120,15 +119,13 @@ 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 a global function with an exact parameter selector.
+  /// 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,
+                         llvm::ArrayRef<llvm::StringRef> Parameters,
+                         const GlobalFunctionInfo &Info,
+                         llvm::VersionTuple SwiftVersion);
 
   /// Add information about an enumerator.
   ///
diff --git a/clang/lib/APINotes/APINotesFormat.h 
b/clang/lib/APINotes/APINotesFormat.h
index 6f78ede4f608f..df67da0845baf 100644
--- a/clang/lib/APINotes/APINotesFormat.h
+++ b/clang/lib/APINotes/APINotesFormat.h
@@ -10,12 +10,12 @@
 #define LLVM_CLANG_LIB_APINOTES_APINOTESFORMAT_H
 
 #include "clang/APINotes/Types.h"
+#include "llvm/ADT/ArrayRef.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 {
@@ -376,9 +376,10 @@ struct FunctionTableKey {
       : parentContextID(ParentContextID), nameID(NameID) {}
 
   FunctionTableKey(uint32_t ParentContextID, uint32_t NameID,
-                   llvm::SmallVector<IdentifierID, 2> ParameterTypeIDs)
-      : parentContextID(ParentContextID), nameID(NameID),
-        parameterTypeIDs(std::move(ParameterTypeIDs)) {}
+                   const llvm::SmallVectorImpl<IdentifierID> &ParameterTypeIDs)
+      : parentContextID(ParentContextID), nameID(NameID) {
+    parameterTypeIDs.emplace(ParameterTypeIDs.begin(), ParameterTypeIDs.end());
+  }
 
   FunctionTableKey(std::optional<Context> ParentCtx, IdentifierID NameID)
       : parentContextID(ParentCtx ? ParentCtx->id.Value
@@ -386,10 +387,12 @@ struct FunctionTableKey {
         nameID(NameID) {}
 
   FunctionTableKey(std::optional<Context> ParentCtx, IdentifierID NameID,
-                   llvm::SmallVector<IdentifierID, 2> ParameterTypeIDs)
+                   const llvm::SmallVectorImpl<IdentifierID> &ParameterTypeIDs)
       : parentContextID(ParentCtx ? ParentCtx->id.Value
                                   : static_cast<uint32_t>(-1)),
-        nameID(NameID), parameterTypeIDs(std::move(ParameterTypeIDs)) {}
+        nameID(NameID) {
+    parameterTypeIDs.emplace(ParameterTypeIDs.begin(), ParameterTypeIDs.end());
+  }
 
   llvm::hash_code hashValue() const {
     auto Hash = llvm::hash_combine(parentContextID, nameID,
@@ -403,6 +406,37 @@ struct FunctionTableKey {
   }
 };
 
+template <typename GetIdentifierFn>
+std::optional<FunctionTableKey>
+getFunctionKeyImpl(uint32_t ParentContextID, llvm::StringRef Name,
+                   GetIdentifierFn GetIdentifier) {
+  std::optional<IdentifierID> NameID = GetIdentifier(Name);
+  if (!NameID)
+    return std::nullopt;
+
+  return FunctionTableKey(ParentContextID, *NameID);
+}
+
+template <typename GetIdentifierFn>
+std::optional<FunctionTableKey>
+getFunctionKeyImpl(uint32_t ParentContextID, llvm::StringRef Name,
+                   llvm::ArrayRef<llvm::StringRef> Parameters,
+                   GetIdentifierFn GetIdentifier) {
+  std::optional<IdentifierID> NameID = GetIdentifier(Name);
+  if (!NameID)
+    return std::nullopt;
+
+  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, ParameterTypeIDs);
+}
+
 inline bool operator==(const FunctionTableKey &lhs,
                        const FunctionTableKey &rhs) {
   return lhs.parentContextID == rhs.parentContextID &&
diff --git a/clang/lib/APINotes/APINotesReader.cpp 
b/clang/lib/APINotes/APINotesReader.cpp
index 5ac172b369444..9305a5f10b4e8 100644
--- a/clang/lib/APINotes/APINotesReader.cpp
+++ b/clang/lib/APINotes/APINotesReader.cpp
@@ -71,7 +71,7 @@ static FunctionTableKey readFunctionTableKey(const uint8_t 
*Data,
   assert((FunctionKeyFlags & ~FunctionKeyHasParameterSelector) == 0 &&
          "Unexpected function table key flags");
   if (FunctionKeyFlags & FunctionKeyHasParameterSelector)
-    return {CtxID, NameID, std::move(ParameterTypeIDs)};
+    return {CtxID, NameID, ParameterTypeIDs};
 
   assert(ParameterTypeIDs.empty() &&
          "Broad function table key should not store parameters");
@@ -855,12 +855,16 @@ 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<FunctionTableKey>
   getFunctionKey(uint32_t ParentContextID, llvm::StringRef Name,
-                 std::optional<llvm::ArrayRef<llvm::StringRef>> Parameters);
+                 llvm::ArrayRef<llvm::StringRef> Parameters);
+  std::optional<FunctionTableKey>
+  getFunctionKey(std::optional<Context> ParentContext, llvm::StringRef Name);
   std::optional<FunctionTableKey>
   getFunctionKey(std::optional<Context> ParentContext, llvm::StringRef Name,
-                 std::optional<llvm::ArrayRef<llvm::StringRef>> Parameters);
+                 llvm::ArrayRef<llvm::StringRef> Parameters);
 
   llvm::Error readGlobalFunctionBlock(llvm::BitstreamCursor &Cursor,
                                       llvm::SmallVectorImpl<uint64_t> 
&Scratch);
@@ -887,31 +891,32 @@ 
APINotesReader::Implementation::getIdentifier(llvm::StringRef Str) {
   return *Known;
 }
 
+std::optional<FunctionTableKey>
+APINotesReader::Implementation::getFunctionKey(uint32_t ParentContextID,
+                                               llvm::StringRef Name) {
+  return getFunctionKeyImpl(ParentContextID, Name, [this](llvm::StringRef S) {
+    return getIdentifier(S);
+  });
+}
+
 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::ArrayRef<llvm::StringRef> Parameters) {
+  return getFunctionKeyImpl(
+      ParentContextID, Name, Parameters,
+      [this](llvm::StringRef S) { return getIdentifier(S); });
+}
 
-  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) {
+  uint32_t ParentContextID =
+      ParentContext ? ParentContext->id.Value : static_cast<uint32_t>(-1);
+  return getFunctionKey(ParentContextID, Name);
 }
 
 std::optional<FunctionTableKey> APINotesReader::Implementation::getFunctionKey(
     std::optional<Context> ParentContext, llvm::StringRef Name,
-    std::optional<llvm::ArrayRef<llvm::StringRef>> Parameters) {
+    llvm::ArrayRef<llvm::StringRef> Parameters) {
   uint32_t ParentContextID =
       ParentContext ? ParentContext->id.Value : static_cast<uint32_t>(-1);
   return getFunctionKey(ParentContextID, Name, Parameters);
@@ -2333,12 +2338,35 @@ auto APINotesReader::lookupField(ContextID CtxID, 
llvm::StringRef Name)
 
 auto APINotesReader::lookupCXXMethod(ContextID CtxID, llvm::StringRef Name)
     -> VersionedInfo<CXXMethodInfo> {
-  return lookupCXXMethod(CtxID, Name, std::nullopt);
+  return lookupCXXMethodImpl(CtxID, Name);
 }
 
-auto APINotesReader::lookupCXXMethod(
+auto APINotesReader::lookupCXXMethod(ContextID CtxID, llvm::StringRef Name,
+                                     llvm::ArrayRef<llvm::StringRef> 
Parameters)
+    -> VersionedInfo<CXXMethodInfo> {
+  return lookupCXXMethodImpl(CtxID, Name, Parameters);
+}
+
+auto APINotesReader::lookupCXXMethodImpl(ContextID CtxID, llvm::StringRef Name)
+    -> VersionedInfo<CXXMethodInfo> {
+  if (!Implementation->CXXMethodTable)
+    return std::nullopt;
+
+  std::optional<FunctionTableKey> Key =
+      Implementation->getFunctionKey(CtxID.Value, Name);
+  if (!Key)
+    return std::nullopt;
+
+  auto Known = Implementation->CXXMethodTable->find(*Key);
+  if (Known == Implementation->CXXMethodTable->end())
+    return std::nullopt;
+
+  return {Implementation->SwiftVersion, *Known};
+}
+
+auto APINotesReader::lookupCXXMethodImpl(
     ContextID CtxID, llvm::StringRef Name,
-    std::optional<llvm::ArrayRef<llvm::StringRef>> Parameters)
+    llvm::ArrayRef<llvm::StringRef> Parameters)
     -> VersionedInfo<CXXMethodInfo> {
   if (!Implementation->CXXMethodTable)
     return std::nullopt;
@@ -2377,12 +2405,35 @@ auto 
APINotesReader::lookupGlobalVariable(llvm::StringRef Name,
 auto APINotesReader::lookupGlobalFunction(llvm::StringRef Name,
                                           std::optional<Context> Ctx)
     -> VersionedInfo<GlobalFunctionInfo> {
-  return lookupGlobalFunction(Name, std::nullopt, Ctx);
+  return lookupGlobalFunctionImpl(Name, Ctx);
 }
 
 auto APINotesReader::lookupGlobalFunction(
-    llvm::StringRef Name,
-    std::optional<llvm::ArrayRef<llvm::StringRef>> Parameters,
+    llvm::StringRef Name, llvm::ArrayRef<llvm::StringRef> Parameters,
+    std::optional<Context> Ctx) -> VersionedInfo<GlobalFunctionInfo> {
+  return lookupGlobalFunctionImpl(Name, Parameters, Ctx);
+}
+
+auto APINotesReader::lookupGlobalFunctionImpl(llvm::StringRef Name,
+                                              std::optional<Context> Ctx)
+    -> VersionedInfo<GlobalFunctionInfo> {
+  if (!Implementation->GlobalFunctionTable)
+    return std::nullopt;
+
+  std::optional<FunctionTableKey> Key =
+      Implementation->getFunctionKey(Ctx, Name);
+  if (!Key)
+    return std::nullopt;
+
+  auto Known = Implementation->GlobalFunctionTable->find(*Key);
+  if (Known == Implementation->GlobalFunctionTable->end())
+    return std::nullopt;
+
+  return {Implementation->SwiftVersion, *Known};
+}
+
+auto APINotesReader::lookupGlobalFunctionImpl(
+    llvm::StringRef Name, llvm::ArrayRef<llvm::StringRef> Parameters,
     std::optional<Context> Ctx) -> VersionedInfo<GlobalFunctionInfo> {
   if (!Implementation->GlobalFunctionTable)
     return std::nullopt;
diff --git a/clang/lib/APINotes/APINotesWriter.cpp 
b/clang/lib/APINotes/APINotesWriter.cpp
index 48abeced839fc..0aa9812693386 100644
--- a/clang/lib/APINotes/APINotesWriter.cpp
+++ b/clang/lib/APINotes/APINotesWriter.cpp
@@ -137,24 +137,37 @@ 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) 
{
+  FunctionTableKey getFunctionKey(uint32_t ParentContextID, StringRef Name) {
+    std::optional<FunctionTableKey> Key =
+        getFunctionKeyImpl(ParentContextID, Name,
+                           [this](StringRef S) -> std::optional<IdentifierID> {
+                             return getIdentifier(S);
+                           });
+    assert(Key && "Writer identifier lookup should not fail");
+    return *Key;
+  }
+
+  FunctionTableKey getFunctionKey(uint32_t ParentContextID, StringRef Name,
+                                  ArrayRef<StringRef> Parameters) {
+    std::optional<FunctionTableKey> Key =
+        getFunctionKeyImpl(ParentContextID, Name, Parameters,
+                           [this](StringRef S) -> std::optional<IdentifierID> {
+                             return getIdentifier(S);
+                           });
+    assert(Key && "Writer identifier lookup should not fail");
+    return *Key;
+  }
+
+  FunctionTableKey getFunctionKey(std::optional<Context> ParentContext,
+                                  StringRef Name) {
+    uint32_t ParentContextID =
+        ParentContext ? ParentContext->id.Value : static_cast<uint32_t>(-1);
+    return getFunctionKey(ParentContextID, Name);
+  }
+
+  FunctionTableKey getFunctionKey(std::optional<Context> ParentContext,
+                                  StringRef Name,
+                                  ArrayRef<StringRef> Parameters) {
     uint32_t ParentContextID =
         ParentContext ? ParentContext->id.Value : static_cast<uint32_t>(-1);
     return getFunctionKey(ParentContextID, Name, Parameters);
@@ -1607,13 +1620,14 @@ void APINotesWriter::addObjCMethod(ContextID CtxID, 
ObjCSelectorRef Selector,
 void APINotesWriter::addCXXMethod(ContextID CtxID, llvm::StringRef Name,
                                   const CXXMethodInfo &Info,
                                   VersionTuple SwiftVersion) {
-  addCXXMethod(CtxID, Name, std::nullopt, Info, SwiftVersion);
+  FunctionTableKey Key = Implementation->getFunctionKey(CtxID.Value, Name);
+  Implementation->CXXMethods[Key].push_back({SwiftVersion, Info});
 }
 
-void APINotesWriter::addCXXMethod(
-    ContextID CtxID, llvm::StringRef Name,
-    std::optional<llvm::ArrayRef<llvm::StringRef>> Parameters,
-    const CXXMethodInfo &Info, VersionTuple SwiftVersion) {
+void APINotesWriter::addCXXMethod(ContextID CtxID, llvm::StringRef Name,
+                                  llvm::ArrayRef<llvm::StringRef> Parameters,
+                                  const CXXMethodInfo &Info,
+                                  VersionTuple SwiftVersion) {
   FunctionTableKey Key =
       Implementation->getFunctionKey(CtxID.Value, Name, Parameters);
   Implementation->CXXMethods[Key].push_back({SwiftVersion, Info});
@@ -1640,13 +1654,14 @@ void 
APINotesWriter::addGlobalFunction(std::optional<Context> Ctx,
                                        llvm::StringRef Name,
                                        const GlobalFunctionInfo &Info,
                                        VersionTuple SwiftVersion) {
-  addGlobalFunction(Ctx, Name, std::nullopt, Info, SwiftVersion);
+  FunctionTableKey Key = Implementation->getFunctionKey(Ctx, Name);
+  Implementation->GlobalFunctions[Key].push_back({SwiftVersion, Info});
 }
 
 void APINotesWriter::addGlobalFunction(
     std::optional<Context> Ctx, llvm::StringRef Name,
-    std::optional<llvm::ArrayRef<llvm::StringRef>> Parameters,
-    const GlobalFunctionInfo &Info, VersionTuple SwiftVersion) {
+    llvm::ArrayRef<llvm::StringRef> Parameters, const GlobalFunctionInfo &Info,
+    VersionTuple SwiftVersion) {
   FunctionTableKey Key = Implementation->getFunctionKey(Ctx, Name, Parameters);
   Implementation->GlobalFunctions[Key].push_back({SwiftVersion, Info});
 }
diff --git a/clang/lib/APINotes/APINotesYAMLCompiler.cpp 
b/clang/lib/APINotes/APINotesYAMLCompiler.cpp
index d02cd3a3f3c56..8e947711dec2f 100644
--- a/clang/lib/APINotes/APINotesYAMLCompiler.cpp
+++ b/clang/lib/APINotes/APINotesYAMLCompiler.cpp
@@ -1173,8 +1173,11 @@ class YAMLConverter {
 
       CXXMethodInfo MI;
       convertFunction(CXXMethod, MI);
-      Writer.addCXXMethod(TagCtxID, CXXMethod.Name, WhereParameters, MI,
-                          SwiftVersion);
+      if (WhereParameters)
+        Writer.addCXXMethod(TagCtxID, CXXMethod.Name, *WhereParameters, MI,
+                            SwiftVersion);
+      else
+        Writer.addCXXMethod(TagCtxID, CXXMethod.Name, MI, SwiftVersion);
     }
 
     // Convert nested tags.
@@ -1260,8 +1263,11 @@ class YAMLConverter {
 
       GlobalFunctionInfo GFI;
       convertFunction(Function, GFI);
-      Writer.addGlobalFunction(Ctx, Function.Name, WhereParameters, GFI,
-                               SwiftVersion);
+      if (WhereParameters)
+        Writer.addGlobalFunction(Ctx, Function.Name, *WhereParameters, GFI,
+                                 SwiftVersion);
+      else
+        Writer.addGlobalFunction(Ctx, Function.Name, GFI, SwiftVersion);
     }
 
     // Write all enumerators.

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to