llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: StoeckOverflow

<details>
<summary>Changes</summary>

This PR adds `Where.Object` selectors for C++ method API notes. They let API 
notes distinguish overloads by the implicit object parameter qualifiers, such 
as `const`, `volatile`, `&amp;`, and `&amp;&amp;`. Static methods are unchanged 
because they have no implicit object parameter.

```cpp
struct Builder {
  Result build() &amp;;
  Result build() &amp;&amp;;
  Result build() const &amp;;
};
```

To distinguish these declarations, the selector model includes an `Object` 
constraint:

```yaml
Tags:
- Name: Builder
  Methods:
  - Name: build
    Where:
      Parameters: []
      Object:
        Ref: lvalue
    SwiftName: buildFromLValue()
  - Name: build
    Where:
      Parameters: []
      Object:
        Ref: rvalue
    SwiftName: buildFromRValue()
  - Name: build
    Where:
      Parameters: []
      Object:
        Const: true
        Ref: lvalue
    SwiftName: buildFromConstLValue()
```

Changes:
- Adds `Where.Object` YAML support for C++ methods.
- Adds a shared object-selector representation with `Const`, `Volatile`, and 
`Ref`.
- Extends C++ method lookup/writer keys to include object selectors.
- Applies less-constrained object selectors before more-constrained selectors 
so specific notes can refine broader ones.
- Extends unmatched-selector diagnostics to track object-only and 
parameter-plus-object selectors.
- Keeps global functions and static C++ methods unchanged.

Tests:
- Matching `const`, `volatile`, lvalue-ref, and rvalue-ref qualified C++ 
methods.
- Combined object qualifiers such as `const volatile &amp;`, `const 
&amp;&amp;`, and `volatile &amp;&amp;`.
- Coexistence of broad method notes with object-qualified notes.
- Object selector diagnostics for malformed, duplicate, and unmatched entries.
- Static methods remain unaffected because they have no implicit object 
parameter.

Reviewers: @<!-- -->Xazax-hun @<!-- -->j-hui @<!-- -->egorzhdan


---

Patch is 60.26 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/216148.diff


15 Files Affected:

- (modified) clang/include/clang/APINotes/APINotesReader.h (+16-4) 
- (modified) clang/include/clang/APINotes/APINotesWriter.h (+6) 
- (modified) clang/include/clang/APINotes/Types.h (+137-13) 
- (modified) clang/lib/APINotes/APINotesFormat.h (+59-3) 
- (modified) clang/lib/APINotes/APINotesReader.cpp (+103-19) 
- (modified) clang/lib/APINotes/APINotesWriter.cpp (+75-2) 
- (modified) clang/lib/APINotes/APINotesYAMLCompiler.cpp (+88-44) 
- (modified) clang/lib/Sema/SemaAPINotes.cpp (+123-18) 
- (modified) clang/lib/Sema/SemaAPINotesInternal.h (+4-4) 
- (added) clang/test/APINotes/Inputs/Headers/WhereObjectQualifiers.apinotes 
(+96) 
- (added) clang/test/APINotes/Inputs/Headers/WhereObjectQualifiers.h (+30) 
- (modified) clang/test/APINotes/Inputs/Headers/module.modulemap (+5) 
- (added) 
clang/test/APINotes/Inputs/WhereObjectQualifiersDiag/APINotes.apinotes (+46) 
- (added) 
clang/test/APINotes/Inputs/WhereObjectQualifiersDiag/WhereObjectQualifiers.h 
(+14) 
- (added) clang/test/APINotes/where-object-qualifiers.cpp (+63) 


``````````diff
diff --git a/clang/include/clang/APINotes/APINotesReader.h 
b/clang/include/clang/APINotes/APINotesReader.h
index d74232bc334c6..99303c8a8ba02 100644
--- a/clang/include/clang/APINotes/APINotesReader.h
+++ b/clang/include/clang/APINotes/APINotesReader.h
@@ -170,6 +170,12 @@ class APINotesReader {
   lookupCXXMethod(ContextID CtxID, llvm::StringRef Name,
                   llvm::ArrayRef<std::string> Parameters);
 
+  /// Look for information regarding the given C++ method with a composed
+  /// selector. Omitted selector components use the broad name-based key.
+  VersionedInfo<CXXMethodInfo>
+  lookupCXXMethod(ContextID CtxID, llvm::StringRef Name,
+                  const FunctionSelector &Selector);
+
   /// Build the selector key for the given C++ method.
   std::optional<APINotesFunctionSelectorKey>
   getCXXMethodSelectorKey(ContextID CtxID, llvm::StringRef Name);
@@ -180,6 +186,12 @@ class APINotesReader {
   getCXXMethodSelectorKey(ContextID CtxID, llvm::StringRef Name,
                           llvm::ArrayRef<std::string> Parameters);
 
+  /// Build the selector key for the given C++ method with a composed
+  /// selector.
+  std::optional<APINotesFunctionSelectorKey>
+  getCXXMethodSelectorKey(ContextID CtxID, llvm::StringRef Name,
+                          const FunctionSelector &Selector);
+
   /// Look for information regarding the given global variable.
   ///
   /// \param Name The name of the global variable.
@@ -218,8 +230,9 @@ class APINotesReader {
                                llvm::ArrayRef<std::string> Parameters,
                                std::optional<Context> Ctx = std::nullopt);
 
-  /// Collect exact parameter selector keys stored by this reader.
-  void collectExactFunctionParameterSelectors(
+  /// Collect selector keys stored by this reader that should be diagnosed if
+  /// unmatched.
+  void collectFunctionSelectorsForDiagnostics(
       llvm::SmallVectorImpl<APINotesFunctionSelectorKey> &Selectors);
 
   /// Reconstruct parameter selector strings for a stored exact selector key.
@@ -275,10 +288,9 @@ class APINotesReader {
 private:
   VersionedInfo<CXXMethodInfo> lookupCXXMethodImpl(ContextID CtxID,
                                                    llvm::StringRef Name);
-  template <typename ParameterT>
   VersionedInfo<CXXMethodInfo>
   lookupCXXMethodImpl(ContextID CtxID, llvm::StringRef Name,
-                      llvm::ArrayRef<ParameterT> Parameters);
+                      const FunctionSelector &Selector);
 
   VersionedInfo<GlobalFunctionInfo>
   lookupGlobalFunctionImpl(llvm::StringRef Name, std::optional<Context> Ctx);
diff --git a/clang/include/clang/APINotes/APINotesWriter.h 
b/clang/include/clang/APINotes/APINotesWriter.h
index 5ed6686e1bb85..c0d07ceeb30cc 100644
--- a/clang/include/clang/APINotes/APINotesWriter.h
+++ b/clang/include/clang/APINotes/APINotesWriter.h
@@ -95,6 +95,12 @@ class APINotesWriter {
                     llvm::ArrayRef<llvm::StringRef> Parameters,
                     const CXXMethodInfo &Info, llvm::VersionTuple 
SwiftVersion);
 
+  /// Add information about a C++ method with a composed selector. Omitted
+  /// selector components use the broad name-based key.
+  void addCXXMethod(ContextID CtxID, llvm::StringRef Name,
+                    const FunctionSelector &Selector, 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.
diff --git a/clang/include/clang/APINotes/Types.h 
b/clang/include/clang/APINotes/Types.h
index af989d3a1b7f0..4151e26a98b45 100644
--- a/clang/include/clang/APINotes/Types.h
+++ b/clang/include/clang/APINotes/Types.h
@@ -1008,19 +1008,132 @@ struct Context {
 
 using IdentifierID = llvm::PointerEmbeddedInt<unsigned, 31>;
 
+/// Describes the C++ implicit-object ref-qualifier portion of a method
+/// selector.
+enum class FunctionObjectRefQualifier : uint8_t {
+  None,
+  LValue,
+  RValue,
+};
+
+/// Describes optional constraints on a C++ method's implicit object parameter.
+struct FunctionObjectSelector {
+  std::optional<bool> Const;
+  std::optional<bool> Volatile;
+  std::optional<FunctionObjectRefQualifier> Ref;
+};
+
+inline bool operator==(const FunctionObjectSelector &LHS,
+                       const FunctionObjectSelector &RHS) {
+  return LHS.Const == RHS.Const && LHS.Volatile == RHS.Volatile &&
+         LHS.Ref == RHS.Ref;
+}
+
+inline bool operator!=(const FunctionObjectSelector &LHS,
+                       const FunctionObjectSelector &RHS) {
+  return !(LHS == RHS);
+}
+
+inline std::string formatAPINotesObjectSelector(FunctionObjectSelector Object) 
{
+  std::string Result;
+  llvm::raw_string_ostream OS(Result);
+  llvm::SmallVector<std::string, 3> Parts;
+
+  if (Object.Const)
+    Parts.push_back(std::string("Const: ") +
+                    (*Object.Const ? "true" : "false"));
+  if (Object.Volatile)
+    Parts.push_back(std::string("Volatile: ") +
+                    (*Object.Volatile ? "true" : "false"));
+  if (Object.Ref) {
+    std::string Ref = "Ref: ";
+    switch (*Object.Ref) {
+    case FunctionObjectRefQualifier::None:
+      Ref += "none";
+      break;
+    case FunctionObjectRefQualifier::LValue:
+      Ref += "lvalue";
+      break;
+    case FunctionObjectRefQualifier::RValue:
+      Ref += "rvalue";
+      break;
+    }
+    Parts.push_back(Ref);
+  }
+
+  OS << "Object{";
+  llvm::interleaveComma(Parts, OS);
+  OS << "}";
+  return Result;
+}
+
+/// Describes a C++ function selector composed from optional exact explicit
+/// parameters plus optional implicit object constraints.
+struct FunctionSelector {
+  std::optional<llvm::SmallVector<std::string, 4>> Parameters;
+  std::optional<FunctionObjectSelector> Object;
+};
+
+inline bool operator==(const FunctionSelector &LHS,
+                       const FunctionSelector &RHS) {
+  return LHS.Parameters == RHS.Parameters && LHS.Object == RHS.Object;
+}
+
+inline bool operator!=(const FunctionSelector &LHS,
+                       const FunctionSelector &RHS) {
+  return !(LHS == RHS);
+}
+
+inline std::string formatAPINotesFunctionSelector(
+    std::optional<llvm::ArrayRef<std::string>> Parameters,
+    std::optional<FunctionObjectSelector> Object) {
+  std::string Result;
+  if (Parameters)
+    Result = (llvm::Twine("Where.Parameters ") +
+              formatAPINotesParameterSelector(*Parameters))
+                 .str();
+
+  if (Object) {
+    if (!Result.empty())
+      Result += " ";
+    else
+      Result = "Where.Object ";
+    Result += formatAPINotesObjectSelector(*Object);
+  }
+
+  return Result;
+}
+
+inline std::string
+formatAPINotesFunctionSelector(const FunctionSelector &Selector) {
+  std::optional<llvm::ArrayRef<std::string>> Parameters;
+  if (Selector.Parameters)
+    Parameters = llvm::ArrayRef<std::string>(*Selector.Parameters);
+  return formatAPINotesFunctionSelector(Parameters, Selector.Object);
+}
+
+struct FunctionTableSelectorKey {
+  std::optional<llvm::SmallVector<IdentifierID, 2>> Parameters;
+  std::optional<FunctionObjectSelector> Object;
+};
+
 /// A key for a stored global-function or C++-method API notes entry.
 ///
 /// The key is represented by the ID of its parent context, the declaration
-/// name, and optional exact parameter types.
+/// name, and optional exact parameter/object selector data.
 struct FunctionTableKey {
   uint32_t parentContextID;
   uint32_t nameID;
   std::optional<llvm::SmallVector<IdentifierID, 2>> parameterTypeIDs;
+  std::optional<FunctionObjectSelector> objectSelector;
 
   FunctionTableKey() : parentContextID(-1), nameID(-1) {}
 
-  FunctionTableKey(uint32_t ParentContextID, uint32_t NameID)
-      : parentContextID(ParentContextID), nameID(NameID) {}
+  FunctionTableKey(uint32_t ParentContextID, uint32_t NameID,
+                   FunctionTableSelectorKey Selector = {})
+      : parentContextID(ParentContextID), nameID(NameID),
+        parameterTypeIDs(std::move(Selector.Parameters)),
+        objectSelector(Selector.Object) {}
 
   FunctionTableKey(uint32_t ParentContextID, uint32_t NameID,
                    const llvm::SmallVectorImpl<IdentifierID> &ParameterTypeIDs)
@@ -1028,27 +1141,37 @@ struct FunctionTableKey {
     parameterTypeIDs.emplace(ParameterTypeIDs.begin(), ParameterTypeIDs.end());
   }
 
-  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,
+                   FunctionTableSelectorKey Selector = {})
+      : FunctionTableKey(ParentCtx ? ParentCtx->id.Value
+                                   : static_cast<uint32_t>(-1),
+                         NameID, std::move(Selector)) {}
 
   FunctionTableKey(std::optional<Context> ParentCtx, IdentifierID NameID,
                    const llvm::SmallVectorImpl<IdentifierID> &ParameterTypeIDs)
-      : parentContextID(ParentCtx ? ParentCtx->id.Value
-                                  : static_cast<uint32_t>(-1)),
-        nameID(NameID) {
+      : FunctionTableKey(ParentCtx ? ParentCtx->id.Value
+                                   : static_cast<uint32_t>(-1),
+                         NameID) {
     parameterTypeIDs.emplace(ParameterTypeIDs.begin(), ParameterTypeIDs.end());
   }
 
   llvm::hash_code hashValue() const {
     auto Hash = llvm::hash_combine(parentContextID, nameID,
-                                   static_cast<bool>(parameterTypeIDs));
+                                   static_cast<bool>(parameterTypeIDs),
+                                   static_cast<bool>(objectSelector));
     if (parameterTypeIDs) {
       Hash = llvm::hash_combine(Hash, parameterTypeIDs->size());
       for (IdentifierID TypeID : *parameterTypeIDs)
         Hash = llvm::hash_combine(Hash, static_cast<unsigned>(TypeID));
     }
+    if (objectSelector)
+      Hash = llvm::hash_combine(
+          Hash, objectSelector->Const.value_or(false),
+          static_cast<bool>(objectSelector->Const),
+          objectSelector->Volatile.value_or(false),
+          static_cast<bool>(objectSelector->Volatile),
+          objectSelector->Ref ? static_cast<unsigned>(*objectSelector->Ref) + 1
+                              : 0);
     return Hash;
   }
 };
@@ -1057,7 +1180,8 @@ inline bool operator==(const FunctionTableKey &LHS,
                        const FunctionTableKey &RHS) {
   return LHS.parentContextID == RHS.parentContextID &&
          LHS.nameID == RHS.nameID &&
-         LHS.parameterTypeIDs == RHS.parameterTypeIDs;
+         LHS.parameterTypeIDs == RHS.parameterTypeIDs &&
+         LHS.objectSelector == RHS.objectSelector;
 }
 
 /// Stable reader-facing identity for an API notes function selector entry.
@@ -1069,7 +1193,7 @@ struct APINotesFunctionSelectorKey {
   FunctionTableKey Key;
   bool IsCXXMethod = false;
 
-  APINotesFunctionSelectorKey getWithoutParameterSelector() const {
+  APINotesFunctionSelectorKey getNameOnlyKey() const {
     return {FunctionTableKey(Key.parentContextID, Key.nameID), IsCXXMethod};
   }
 
diff --git a/clang/lib/APINotes/APINotesFormat.h 
b/clang/lib/APINotes/APINotesFormat.h
index 30fc8599349bf..f0ea371e3ccef 100644
--- a/clang/lib/APINotes/APINotesFormat.h
+++ b/clang/lib/APINotes/APINotesFormat.h
@@ -16,6 +16,7 @@
 #include "llvm/Bitcode/BitcodeConvenience.h"
 
 #include <optional>
+#include <utility>
 
 namespace clang {
 namespace api_notes {
@@ -28,9 +29,10 @@ 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 = 41; // 39 for BoundsSafety;
+const uint16_t VERSION_MINOR = 42; // 39 for BoundsSafety;
                                    // 40 for UnsafeBufferUsageAttr
                                    // 41 for FunctionTableKey parameters
+                                   // 42 for FunctionTableKey object selectors
 
 const uint8_t kSwiftConforms = 1;
 const uint8_t kSwiftDoesNotConform = 2;
@@ -359,8 +361,21 @@ inline bool operator==(const SingleDeclTableKey &lhs,
 }
 
 /// 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.
+/// context, the name of the declaration, and optional exact parameter/object
+/// selector data.
 constexpr uint8_t FunctionKeyHasParameterSelector = 0x01;
+constexpr uint8_t FunctionKeyObjectConstPresent = 0x02;
+constexpr uint8_t FunctionKeyObjectConstValue = 0x04;
+constexpr uint8_t FunctionKeyObjectVolatilePresent = 0x08;
+constexpr uint8_t FunctionKeyObjectVolatileValue = 0x10;
+constexpr uint8_t FunctionKeyObjectRefPresent = 0x20;
+constexpr uint8_t FunctionKeyObjectRefLValue = 0x40;
+constexpr uint8_t FunctionKeyObjectRefRValue = 0x80;
+constexpr uint8_t FunctionKeyObjectSelectorMask =
+    FunctionKeyObjectConstPresent | FunctionKeyObjectConstValue |
+    FunctionKeyObjectVolatilePresent | FunctionKeyObjectVolatileValue |
+    FunctionKeyObjectRefPresent | FunctionKeyObjectRefLValue |
+    FunctionKeyObjectRefRValue;
 constexpr unsigned FunctionTableKeyBaseLength =
     sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint8_t) + sizeof(uint16_t);
 
@@ -375,10 +390,48 @@ getFunctionKeyImpl(uint32_t ParentContextID, 
llvm::StringRef Name,
   return FunctionTableKey(ParentContextID, *NameID);
 }
 
+template <typename GetIdentifierFn>
+std::optional<FunctionTableKey>
+getFunctionKeyImpl(uint32_t ParentContextID, llvm::StringRef Name,
+                   FunctionObjectSelector ObjectSelector,
+                   GetIdentifierFn GetIdentifier) {
+  std::optional<IdentifierID> NameID = GetIdentifier(Name);
+  if (!NameID)
+    return std::nullopt;
+
+  FunctionTableSelectorKey Selector;
+  Selector.Object = ObjectSelector;
+  return FunctionTableKey(ParentContextID, *NameID, std::move(Selector));
+}
+
+template <typename ParameterT, typename GetIdentifierFn>
+std::optional<FunctionTableKey>
+getFunctionKeyImpl(uint32_t ParentContextID, llvm::StringRef Name,
+                   llvm::ArrayRef<ParameterT> Parameters,
+                   GetIdentifierFn GetIdentifier) {
+  std::optional<IdentifierID> NameID = GetIdentifier(Name);
+  if (!NameID)
+    return std::nullopt;
+
+  llvm::SmallVector<IdentifierID, 2> ParameterTypeIDs;
+  ParameterTypeIDs.reserve(Parameters.size());
+  for (const ParameterT &Parameter : Parameters) {
+    std::optional<IdentifierID> ParameterID =
+        GetIdentifier(llvm::StringRef(Parameter));
+    if (!ParameterID)
+      return std::nullopt;
+    ParameterTypeIDs.push_back(*ParameterID);
+  }
+  FunctionTableSelectorKey Selector;
+  Selector.Parameters.emplace(ParameterTypeIDs.begin(), 
ParameterTypeIDs.end());
+  return FunctionTableKey(ParentContextID, *NameID, std::move(Selector));
+}
+
 template <typename ParameterT, typename GetIdentifierFn>
 std::optional<FunctionTableKey>
 getFunctionKeyImpl(uint32_t ParentContextID, llvm::StringRef Name,
                    llvm::ArrayRef<ParameterT> Parameters,
+                   FunctionObjectSelector ObjectSelector,
                    GetIdentifierFn GetIdentifier) {
   std::optional<IdentifierID> NameID = GetIdentifier(Name);
   if (!NameID)
@@ -393,7 +446,10 @@ getFunctionKeyImpl(uint32_t ParentContextID, 
llvm::StringRef Name,
       return std::nullopt;
     ParameterTypeIDs.push_back(*ParameterID);
   }
-  return FunctionTableKey(ParentContextID, *NameID, ParameterTypeIDs);
+  FunctionTableSelectorKey Selector;
+  Selector.Parameters.emplace(ParameterTypeIDs.begin(), 
ParameterTypeIDs.end());
+  Selector.Object = ObjectSelector;
+  return FunctionTableKey(ParentContextID, *NameID, std::move(Selector));
 }
 
 } // namespace api_notes
diff --git a/clang/lib/APINotes/APINotesReader.cpp 
b/clang/lib/APINotes/APINotesReader.cpp
index aad597d93d9ee..ab06d75826d1a 100644
--- a/clang/lib/APINotes/APINotesReader.cpp
+++ b/clang/lib/APINotes/APINotesReader.cpp
@@ -72,14 +72,47 @@ static FunctionTableKey readFunctionTableKey(const uint8_t 
*Data,
     ParameterTypeIDs.push_back(
         endian::readNext<uint32_t, llvm::endianness::little>(Data));
 
-  assert((FunctionKeyFlags & ~FunctionKeyHasParameterSelector) == 0 &&
-         "Unexpected function table key flags");
+  if (FunctionKeyFlags & FunctionKeyObjectRefLValue)
+    assert(!(FunctionKeyFlags & FunctionKeyObjectRefRValue) &&
+           "Unexpected function table key ref qualifier flags");
+  assert(((FunctionKeyFlags & FunctionKeyObjectConstValue) == 0 ||
+          (FunctionKeyFlags & FunctionKeyObjectConstPresent)) &&
+         "Function table key const value requires presence flag");
+  assert(((FunctionKeyFlags & FunctionKeyObjectVolatileValue) == 0 ||
+          (FunctionKeyFlags & FunctionKeyObjectVolatilePresent)) &&
+         "Function table key volatile value requires presence flag");
+  assert(((FunctionKeyFlags &
+           (FunctionKeyObjectRefLValue | FunctionKeyObjectRefRValue)) == 0 ||
+          (FunctionKeyFlags & FunctionKeyObjectRefPresent)) &&
+         "Function table key ref value requires presence flag");
+  std::optional<FunctionObjectSelector> ObjectSelector;
+  if (FunctionKeyFlags & FunctionKeyObjectSelectorMask) {
+    FunctionObjectSelector Selector;
+    if (FunctionKeyFlags & FunctionKeyObjectConstPresent)
+      Selector.Const = (FunctionKeyFlags & FunctionKeyObjectConstValue) != 0;
+    if (FunctionKeyFlags & FunctionKeyObjectVolatilePresent)
+      Selector.Volatile =
+          (FunctionKeyFlags & FunctionKeyObjectVolatileValue) != 0;
+    if (FunctionKeyFlags & FunctionKeyObjectRefPresent) {
+      if (FunctionKeyFlags & FunctionKeyObjectRefLValue)
+        Selector.Ref = FunctionObjectRefQualifier::LValue;
+      else if (FunctionKeyFlags & FunctionKeyObjectRefRValue)
+        Selector.Ref = FunctionObjectRefQualifier::RValue;
+      else
+        Selector.Ref = FunctionObjectRefQualifier::None;
+    }
+    ObjectSelector = Selector;
+  }
+
+  FunctionTableSelectorKey Selector;
   if (FunctionKeyFlags & FunctionKeyHasParameterSelector)
-    return {CtxID, NameID, ParameterTypeIDs};
-
-  assert(ParameterTypeIDs.empty() &&
-         "Broad function table key should not store parameters");
-  return {CtxID, NameID};
+    Selector.Parameters.emplace(ParameterTypeIDs.begin(),
+                                ParameterTypeIDs.end());
+  else
+    assert(ParameterTypeIDs.empty() &&
+           "Broad function table key should not store parameters");
+  Selector.Object = ObjectSelector;
+  return FunctionTableKey(CtxID, NameID, std::move(Selector));
 }
 
 /// An on-disk hash table whose data is versioned based on the Swift version.
@@ -844,10 +877,10 @@ class APINotesReader::Implementation {
   /// the ID is unknown.
   std::optional<llvm::StringRef> getIdentifierString(IdentifierID ID);
 
-  /// Collect exact parameter selector keys stored in the given function-like
-  /// table.
+  /// Collect selector keys stored in the given function-like table that
+  /// should be diagnosed if unmatched.
   template <typename TableT>
-  void collectExactFunctionParameterSelectors(
+  void collectFunctionSelectorsForDiagnostics(
       TableT &Table,
       llvm::SmallVectorImpl<APINotesFunctionSelectorKey> &Selectors);
 
@@ -880,11 +913,17 @@ class APINotesReader::Implementation {
   getFunctionKey(uint32_t ParentContextID, llvm::StringRef Name,
                  llvm::ArrayRef<ParameterT> Parameters);
   std::optional<FunctionTableKey>
+  getFunctionKey(uint32_t ParentContextID, llvm::StringRef Name,
+                 const FunctionSelector &Selector);
+  std::optional<FunctionTableKey>
   getFunctionKey(std::optional<Context> ParentContext, llvm::StringRef Name);
   template <typename ParameterT>
   std::optional<FunctionTableKey>
   getFunctionKey(std::optional<Context> ParentContext, llvm::StringRef Name,
                  llvm::ArrayRef<ParameterT> Parameters);
+  std::optional<FunctionTableKey>
+  getFunctionKey(std::optional<Context> ParentContext, llvm::StringRef Name,
+                 const FunctionSelector &Selector);
 
   llvm::Error readGlobalFunctionBlock(llvm::BitstreamCursor &Cursor,
                                       llvm::SmallVectorImpl<uint64_t> 
&Scratch);
@@ -944,7 +983,7 @@ APINotesReader::Implementation...
[truncated]

``````````

</details>


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

Reply via email to