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

>From ad76085780d755900971db13c1e468be68663153 Mon Sep 17 00:00:00 2001
From: stoeckoverflow <[email protected]>
Date: Fri, 19 Jun 2026 11:17:22 +0200
Subject: [PATCH 1/5] [APINotes] Apply Where.Parameters selectors in Sema

---
 clang/lib/Sema/SemaAPINotes.cpp               |  45 +++++++
 .../Headers/WhereParametersSema.apinotes      | 126 ++++++++++++++++++
 .../Inputs/Headers/WhereParametersSema.h      |  51 +++++++
 .../APINotes/Inputs/Headers/module.modulemap  |   5 +
 clang/test/APINotes/where-parameters-sema.cpp | 110 +++++++++++++++
 5 files changed, 337 insertions(+)
 create mode 100644 
clang/test/APINotes/Inputs/Headers/WhereParametersSema.apinotes
 create mode 100644 clang/test/APINotes/Inputs/Headers/WhereParametersSema.h
 create mode 100644 clang/test/APINotes/where-parameters-sema.cpp

diff --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp
index 67c08d239e758..269b96a57fa4b 100644
--- a/clang/lib/Sema/SemaAPINotes.cpp
+++ b/clang/lib/Sema/SemaAPINotes.cpp
@@ -993,6 +993,29 @@ UnwindTagContext(TagDecl *DC, api_notes::APINotesManager 
&APINotes) {
   return std::nullopt;
 }
 
+static std::optional<SmallVector<std::string, 4>>
+getAPINotesParameterSelector(const Sema &S, const FunctionDecl *FD) {
+  const auto *FPT = FD->getType()->getAs<FunctionProtoType>();
+  if (!FPT)
+    return std::nullopt;
+
+  SmallVector<std::string, 4> Parameters;
+  Parameters.reserve(FPT->getNumParams());
+  for (QualType ParamType : FPT->param_types())
+    Parameters.push_back(ParamType.getUnqualifiedType().getAsString(
+        S.Context.getPrintingPolicy()));
+  return Parameters;
+}
+
+static SmallVector<StringRef, 4>
+getAPINotesParameterSelectorRefs(ArrayRef<std::string> Strings) {
+  SmallVector<StringRef, 4> Refs;
+  Refs.reserve(Strings.size());
+  for (const std::string &String : Strings)
+    Refs.push_back(String);
+  return Refs;
+}
+
 /// Process API notes that are associated with this declaration, mapping them
 /// to attributes as appropriate.
 void Sema::ProcessAPINotes(Decl *D) {
@@ -1024,10 +1047,21 @@ void Sema::ProcessAPINotes(Decl *D) {
     // Global functions.
     if (auto FD = dyn_cast<FunctionDecl>(D)) {
       if (FD->getDeclName().isIdentifier()) {
+        std::optional<SmallVector<std::string, 4>> ParameterStrings =
+            getAPINotesParameterSelector(*this, FD);
+        SmallVector<StringRef, 4> Parameters;
+        if (ParameterStrings)
+          Parameters = getAPINotesParameterSelectorRefs(*ParameterStrings);
         for (auto Reader : Readers) {
           auto Info =
               Reader->lookupGlobalFunction(FD->getName(), APINotesContext);
           ProcessVersionedAPINotes(*this, FD, Info);
+
+          if (ParameterStrings) {
+            Info = Reader->lookupGlobalFunction(FD->getName(), Parameters,
+                                                APINotesContext);
+            ProcessVersionedAPINotes(*this, FD, Info);
+          }
         }
       }
 
@@ -1211,6 +1245,11 @@ void Sema::ProcessAPINotes(Decl *D) {
       if (!isa<CXXConstructorDecl>(CXXMethod) &&
           !isa<CXXDestructorDecl>(CXXMethod) &&
           !isa<CXXConversionDecl>(CXXMethod)) {
+        std::optional<SmallVector<std::string, 4>> ParameterStrings =
+            getAPINotesParameterSelector(*this, CXXMethod);
+        SmallVector<StringRef, 4> Parameters;
+        if (ParameterStrings)
+          Parameters = getAPINotesParameterSelectorRefs(*ParameterStrings);
         for (auto Reader : Readers) {
           if (auto Context = UnwindTagContext(TagContext, APINotes)) {
             std::string MethodName;
@@ -1223,6 +1262,12 @@ void Sema::ProcessAPINotes(Decl *D) {
 
             auto Info = Reader->lookupCXXMethod(Context->id, MethodName);
             ProcessVersionedAPINotes(*this, CXXMethod, Info);
+
+            if (ParameterStrings) {
+              Info =
+                  Reader->lookupCXXMethod(Context->id, MethodName, Parameters);
+              ProcessVersionedAPINotes(*this, CXXMethod, Info);
+            }
           }
         }
       }
diff --git a/clang/test/APINotes/Inputs/Headers/WhereParametersSema.apinotes 
b/clang/test/APINotes/Inputs/Headers/WhereParametersSema.apinotes
new file mode 100644
index 0000000000000..2a9f9c921347b
--- /dev/null
+++ b/clang/test/APINotes/Inputs/Headers/WhereParametersSema.apinotes
@@ -0,0 +1,126 @@
+---
+Name: WhereParametersSema
+Functions:
+- Name: makeWidget
+  Where:
+    Parameters:
+    - int
+  SwiftName: makeIntWidget(_:)
+- Name: makeWidget
+  Where:
+    Parameters:
+    - double
+  SwiftName: makeDoubleWidget(_:)
+- Name: makeWidget
+  Where:
+    Parameters: []
+  SwiftName: makeCurrentWidget()
+- Name: broadGlobal
+  SwiftPrivate: true
+- Name: coexistGlobal
+  SwiftPrivate: true
+- Name: coexistGlobal
+  Where:
+    Parameters:
+    - int
+  SwiftName: coexistGlobalInt(_:)
+- Name: mismatchGlobal
+  Where:
+    Parameters:
+    - int
+  SwiftName: shouldNotApplyGlobal(_:)
+- Name: aliasGlobal
+  Where:
+    Parameters:
+    - int
+  SwiftName: shouldNotApplyAliasGlobal(_:)
+- Name: rawIntGlobal
+  Where:
+    Parameters:
+    - int
+  SwiftName: rawIntGlobal(_:)
+- Name: constValueGlobal
+  Where:
+    Parameters:
+    - int
+  SwiftName: constValueGlobal(_:)
+Namespaces:
+- Name: SelectorNamespace
+  Functions:
+  - Name: makeNamespaced
+    Where:
+      Parameters:
+      - int
+    SwiftName: makeNamespacedInt(_:)
+  - Name: makeNamespaced
+    Where:
+      Parameters:
+      - double
+    SwiftName: makeNamespacedDouble(_:)
+Tags:
+- Name: SelectorWidget
+  Methods:
+  - Name: setValue
+    Where:
+      Parameters:
+      - int
+    SwiftName: setIntValue(_:)
+  - Name: setValue
+    Where:
+      Parameters:
+      - double
+    SwiftName: setDoubleValue(_:)
+  - Name: setValue
+    Where:
+      Parameters: []
+    SwiftName: currentValue()
+  - Name: broad
+    SwiftPrivate: true
+  - Name: coexist
+    SwiftPrivate: true
+  - Name: coexist
+    Where:
+      Parameters:
+      - int
+    SwiftName: coexistInt(_:)
+  - Name: defaults
+    Where:
+      Parameters:
+      - int
+      - double
+    SwiftName: defaultsWithTwoParameters(_:_:)
+  - Name: configure
+    Where:
+      Parameters:
+      - int
+    SwiftName: configureInt(_:)
+  - Name: mismatch
+    Where:
+      Parameters:
+      - int
+    SwiftName: shouldNotApplyMethod(_:)
+  - Name: alias
+    Where:
+      Parameters:
+      - int
+    SwiftName: shouldNotApplyAliasMethod(_:)
+  - Name: rawInt
+    Where:
+      Parameters:
+      - int
+    SwiftName: rawInt(_:)
+  - Name: constValue
+    Where:
+      Parameters:
+      - int
+    SwiftName: constValue(_:)
+  - Name: operator+
+    Where:
+      Parameters:
+      - int
+    SwiftName: plusInt(_:)
+  - Name: operator+
+    Where:
+      Parameters:
+      - double
+    SwiftName: plusDouble(_:)
diff --git a/clang/test/APINotes/Inputs/Headers/WhereParametersSema.h 
b/clang/test/APINotes/Inputs/Headers/WhereParametersSema.h
new file mode 100644
index 0000000000000..1cd10676e5533
--- /dev/null
+++ b/clang/test/APINotes/Inputs/Headers/WhereParametersSema.h
@@ -0,0 +1,51 @@
+#ifndef WHERE_PARAMETERS_SEMA_H
+#define WHERE_PARAMETERS_SEMA_H
+
+using AliasInt = int;
+
+void makeWidget(int);
+void makeWidget(double);
+void makeWidget();
+
+void broadGlobal(int);
+void broadGlobal(double);
+
+void coexistGlobal(int);
+void coexistGlobal(double);
+
+void mismatchGlobal(float);
+void aliasGlobal(AliasInt);
+void rawIntGlobal(int);
+void constValueGlobal(const int);
+
+namespace SelectorNamespace {
+void makeNamespaced(int);
+void makeNamespaced(double);
+}
+
+struct SelectorWidget {
+  void setValue(int);
+  void setValue(double);
+  void setValue();
+
+  void broad(int);
+  void broad(double);
+
+  void coexist(int);
+  void coexist(double);
+
+  void defaults(int, double = 0);
+  void defaults(int);
+
+  static void configure(int);
+
+  void mismatch(float);
+  void alias(AliasInt);
+  void rawInt(int);
+  void constValue(const int);
+
+  SelectorWidget operator+(int);
+  SelectorWidget operator+(double);
+};
+
+#endif // WHERE_PARAMETERS_SEMA_H
diff --git a/clang/test/APINotes/Inputs/Headers/module.modulemap 
b/clang/test/APINotes/Inputs/Headers/module.modulemap
index 7bcf33644a14f..592d482ea7a57 100644
--- a/clang/test/APINotes/Inputs/Headers/module.modulemap
+++ b/clang/test/APINotes/Inputs/Headers/module.modulemap
@@ -70,3 +70,8 @@ module UnsafeBufferUsage {
   header "UnsafeBufferUsage.h"
   export *
 }
+
+module WhereParametersSema {
+  header "WhereParametersSema.h"
+  export *
+}
diff --git a/clang/test/APINotes/where-parameters-sema.cpp 
b/clang/test/APINotes/where-parameters-sema.cpp
new file mode 100644
index 0000000000000..7d1dcf7b61abb
--- /dev/null
+++ b/clang/test/APINotes/where-parameters-sema.cpp
@@ -0,0 +1,110 @@
+// RUN: rm -rf %t && mkdir -p %t
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -fsyntax-only -I %S/Inputs/Headers %s -x c++
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
makeWidget -x c++ | FileCheck --check-prefix=CHECK-GLOBAL-OVERLOADS %s
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
broadGlobal -x c++ | FileCheck --check-prefix=CHECK-GLOBAL-BROAD %s
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
coexistGlobal -x c++ | FileCheck --check-prefix=CHECK-GLOBAL-COEXIST %s
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
mismatchGlobal -x c++ | FileCheck --check-prefix=CHECK-GLOBAL-MISMATCH %s
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
aliasGlobal -x c++ | FileCheck --check-prefix=CHECK-GLOBAL-ALIAS %s
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
rawIntGlobal -x c++ | FileCheck --check-prefix=CHECK-GLOBAL-RAW-INT %s
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
constValueGlobal -x c++ | FileCheck --check-prefix=CHECK-GLOBAL-CONST %s
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
SelectorNamespace::makeNamespaced -x c++ | FileCheck 
--check-prefix=CHECK-GLOBAL-NAMESPACE %s
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
SelectorWidget::setValue -x c++ | FileCheck 
--check-prefix=CHECK-METHOD-OVERLOADS %s
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
SelectorWidget::broad -x c++ | FileCheck --check-prefix=CHECK-METHOD-BROAD %s
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
SelectorWidget::coexist -x c++ | FileCheck --check-prefix=CHECK-METHOD-COEXIST 
%s
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
SelectorWidget::defaults -x c++ | FileCheck 
--check-prefix=CHECK-METHOD-DEFAULTS %s
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
SelectorWidget::configure -x c++ | FileCheck --check-prefix=CHECK-METHOD-STATIC 
%s
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
SelectorWidget::mismatch -x c++ | FileCheck 
--check-prefix=CHECK-METHOD-MISMATCH %s
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
SelectorWidget::alias -x c++ | FileCheck --check-prefix=CHECK-METHOD-ALIAS %s
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
SelectorWidget::rawInt -x c++ | FileCheck --check-prefix=CHECK-METHOD-RAW-INT %s
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
SelectorWidget::constValue -x c++ | FileCheck --check-prefix=CHECK-METHOD-CONST 
%s
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
SelectorWidget::operator+ -x c++ | FileCheck 
--check-prefix=CHECK-METHOD-OPERATOR %s
+
+#include "WhereParametersSema.h"
+
+// CHECK-GLOBAL-OVERLOADS: FunctionDecl {{.+}} makeWidget 'void (int)'
+// CHECK-GLOBAL-OVERLOADS-NEXT: ParmVarDecl {{.+}} 'int'
+// CHECK-GLOBAL-OVERLOADS-NEXT: SwiftNameAttr {{.+}} "makeIntWidget(_:)"
+// CHECK-GLOBAL-OVERLOADS: FunctionDecl {{.+}} makeWidget 'void (double)'
+// CHECK-GLOBAL-OVERLOADS-NEXT: ParmVarDecl {{.+}} 'double'
+// CHECK-GLOBAL-OVERLOADS-NEXT: SwiftNameAttr {{.+}} "makeDoubleWidget(_:)"
+// CHECK-GLOBAL-OVERLOADS: FunctionDecl {{.+}} makeWidget 'void ()'
+// CHECK-GLOBAL-OVERLOADS-NEXT: SwiftNameAttr {{.+}} "makeCurrentWidget()"
+
+// CHECK-GLOBAL-BROAD: FunctionDecl {{.+}} broadGlobal 'void (int)'
+// CHECK-GLOBAL-BROAD: SwiftPrivateAttr
+// CHECK-GLOBAL-BROAD: FunctionDecl {{.+}} broadGlobal 'void (double)'
+// CHECK-GLOBAL-BROAD: SwiftPrivateAttr
+
+// CHECK-GLOBAL-COEXIST: FunctionDecl {{.+}} coexistGlobal 'void (int)'
+// CHECK-GLOBAL-COEXIST: SwiftPrivateAttr
+// CHECK-GLOBAL-COEXIST: SwiftNameAttr {{.+}} "coexistGlobalInt(_:)"
+// CHECK-GLOBAL-COEXIST: FunctionDecl {{.+}} coexistGlobal 'void (double)'
+// CHECK-GLOBAL-COEXIST: SwiftPrivateAttr
+// CHECK-GLOBAL-COEXIST-NOT: SwiftNameAttr
+
+// CHECK-GLOBAL-MISMATCH: FunctionDecl {{.+}} mismatchGlobal 'void (float)'
+// CHECK-GLOBAL-MISMATCH-NOT: SwiftNameAttr
+
+// CHECK-GLOBAL-ALIAS: FunctionDecl {{.+}} aliasGlobal 'void (AliasInt)'
+// CHECK-GLOBAL-ALIAS-NOT: SwiftNameAttr
+
+// CHECK-GLOBAL-RAW-INT: FunctionDecl {{.+}} rawIntGlobal 'void (int)'
+// CHECK-GLOBAL-RAW-INT: SwiftNameAttr {{.+}} "rawIntGlobal(_:)"
+
+// CHECK-GLOBAL-CONST: FunctionDecl {{.+}} constValueGlobal 'void (const int)'
+// CHECK-GLOBAL-CONST: SwiftNameAttr {{.+}} "constValueGlobal(_:)"
+
+// CHECK-GLOBAL-NAMESPACE: FunctionDecl {{.+}} makeNamespaced 'void (int)'
+// CHECK-GLOBAL-NAMESPACE-NEXT: ParmVarDecl {{.+}} 'int'
+// CHECK-GLOBAL-NAMESPACE-NEXT: SwiftNameAttr {{.+}} "makeNamespacedInt(_:)"
+// CHECK-GLOBAL-NAMESPACE: FunctionDecl {{.+}} makeNamespaced 'void (double)'
+// CHECK-GLOBAL-NAMESPACE-NEXT: ParmVarDecl {{.+}} 'double'
+// CHECK-GLOBAL-NAMESPACE-NEXT: SwiftNameAttr {{.+}} "makeNamespacedDouble(_:)"
+
+// CHECK-METHOD-OVERLOADS: CXXMethodDecl {{.+}} setValue 'void (int)'
+// CHECK-METHOD-OVERLOADS-NEXT: ParmVarDecl {{.+}} 'int'
+// CHECK-METHOD-OVERLOADS-NEXT: SwiftNameAttr {{.+}} "setIntValue(_:)"
+// CHECK-METHOD-OVERLOADS: CXXMethodDecl {{.+}} setValue 'void (double)'
+// CHECK-METHOD-OVERLOADS-NEXT: ParmVarDecl {{.+}} 'double'
+// CHECK-METHOD-OVERLOADS-NEXT: SwiftNameAttr {{.+}} "setDoubleValue(_:)"
+// CHECK-METHOD-OVERLOADS: CXXMethodDecl {{.+}} setValue 'void ()'
+// CHECK-METHOD-OVERLOADS-NEXT: SwiftNameAttr {{.+}} "currentValue()"
+
+// CHECK-METHOD-BROAD: CXXMethodDecl {{.+}} broad 'void (int)'
+// CHECK-METHOD-BROAD: SwiftPrivateAttr
+// CHECK-METHOD-BROAD: CXXMethodDecl {{.+}} broad 'void (double)'
+// CHECK-METHOD-BROAD: SwiftPrivateAttr
+
+// CHECK-METHOD-COEXIST: CXXMethodDecl {{.+}} coexist 'void (int)'
+// CHECK-METHOD-COEXIST: SwiftPrivateAttr
+// CHECK-METHOD-COEXIST: SwiftNameAttr {{.+}} "coexistInt(_:)"
+// CHECK-METHOD-COEXIST: CXXMethodDecl {{.+}} coexist 'void (double)'
+// CHECK-METHOD-COEXIST: SwiftPrivateAttr
+// CHECK-METHOD-COEXIST-NOT: SwiftNameAttr
+
+// CHECK-METHOD-DEFAULTS: CXXMethodDecl {{.+}} defaults 'void (int, double)'
+// CHECK-METHOD-DEFAULTS: SwiftNameAttr {{.+}} 
"defaultsWithTwoParameters(_:_:)"
+// CHECK-METHOD-DEFAULTS: CXXMethodDecl {{.+}} defaults 'void (int)'
+// CHECK-METHOD-DEFAULTS-NOT: SwiftNameAttr
+
+// CHECK-METHOD-STATIC: CXXMethodDecl {{.+}} configure 'void (int)' static
+// CHECK-METHOD-STATIC: SwiftNameAttr {{.+}} "configureInt(_:)"
+
+// CHECK-METHOD-MISMATCH: CXXMethodDecl {{.+}} mismatch 'void (float)'
+// CHECK-METHOD-MISMATCH-NOT: SwiftNameAttr
+
+// CHECK-METHOD-ALIAS: CXXMethodDecl {{.+}} alias 'void (AliasInt)'
+// CHECK-METHOD-ALIAS-NOT: SwiftNameAttr
+
+// CHECK-METHOD-RAW-INT: CXXMethodDecl {{.+}} rawInt 'void (int)'
+// CHECK-METHOD-RAW-INT: SwiftNameAttr {{.+}} "rawInt(_:)"
+
+// CHECK-METHOD-CONST: CXXMethodDecl {{.+}} constValue 'void (const int)'
+// CHECK-METHOD-CONST: SwiftNameAttr {{.+}} "constValue(_:)"
+
+// CHECK-METHOD-OPERATOR: CXXMethodDecl {{.+}} operator+ 'SelectorWidget (int)'
+// CHECK-METHOD-OPERATOR-NEXT: ParmVarDecl {{.+}} 'int'
+// CHECK-METHOD-OPERATOR-NEXT: SwiftNameAttr {{.+}} "plusInt(_:)"
+// CHECK-METHOD-OPERATOR: CXXMethodDecl {{.+}} operator+ 'SelectorWidget 
(double)'
+// CHECK-METHOD-OPERATOR-NEXT: ParmVarDecl {{.+}} 'double'
+// CHECK-METHOD-OPERATOR-NEXT: SwiftNameAttr {{.+}} "plusDouble(_:)"

>From f704aa74f2751e803d59aa7223ed5c2ce4cbb686 Mon Sep 17 00:00:00 2001
From: stoeckoverflow <[email protected]>
Date: Thu, 2 Jul 2026 11:31:45 +0200
Subject: [PATCH 2/5] [APINotes] Add permissive alias and nullability matching
 for Where.Parameters

---
 clang/lib/Sema/SemaAPINotes.cpp               | 114 +++++++++++++-----
 .../Headers/WhereParametersSema.apinotes      |  34 +++++-
 .../Inputs/Headers/WhereParametersSema.h      |   4 +
 clang/test/APINotes/where-parameters-sema.cpp |  22 +++-
 4 files changed, 142 insertions(+), 32 deletions(-)

diff --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp
index 269b96a57fa4b..cae73fe3f4e3b 100644
--- a/clang/lib/Sema/SemaAPINotes.cpp
+++ b/clang/lib/Sema/SemaAPINotes.cpp
@@ -993,18 +993,56 @@ UnwindTagContext(TagDecl *DC, api_notes::APINotesManager 
&APINotes) {
   return std::nullopt;
 }
 
-static std::optional<SmallVector<std::string, 4>>
-getAPINotesParameterSelector(const Sema &S, const FunctionDecl *FD) {
+static void stripAPINotesParameterNullability(QualType &ParamType) {
+  while (true) {
+    if (!AttributedType::stripOuterNullability(ParamType))
+      return;
+  }
+}
+
+// Print the APINotes selector spelling for one parameter. The source-spelled
+// selector is tried first. The desugared spelling is only a permissive
+// fallback.
+static std::string getAPINotesParameterSelectorSpelling(
+    QualType ParamType, const ASTContext &Context, const PrintingPolicy 
&Policy,
+    bool Desugar) {
+  ParamType.removeLocalConst();
+  stripAPINotesParameterNullability(ParamType);
+
+  if (Desugar) {
+    ParamType = ParamType.getDesugaredType(Context);
+    ParamType.removeLocalConst();
+    stripAPINotesParameterNullability(ParamType);
+  }
+
+  return ParamType.getAsString(Policy);
+}
+
+static std::optional<SmallVector<SmallVector<std::string, 4>, 2>>
+getAPINotesParameterSelectorCandidates(const Sema &S, const FunctionDecl *FD) {
   const auto *FPT = FD->getType()->getAs<FunctionProtoType>();
   if (!FPT)
     return std::nullopt;
 
-  SmallVector<std::string, 4> Parameters;
-  Parameters.reserve(FPT->getNumParams());
-  for (QualType ParamType : FPT->param_types())
-    Parameters.push_back(ParamType.getUnqualifiedType().getAsString(
-        S.Context.getPrintingPolicy()));
-  return Parameters;
+  SmallVector<std::string, 4> SourceParameters;
+  SmallVector<std::string, 4> DesugaredParameters;
+  SourceParameters.reserve(FPT->getNumParams());
+  DesugaredParameters.reserve(FPT->getNumParams());
+
+  const PrintingPolicy &Policy = S.Context.getPrintingPolicy();
+  for (QualType ParamType : FPT->param_types()) {
+    SourceParameters.push_back(getAPINotesParameterSelectorSpelling(
+        ParamType, S.Context, Policy, /*Desugar=*/false));
+    DesugaredParameters.push_back(getAPINotesParameterSelectorSpelling(
+        ParamType, S.Context, Policy, /*Desugar=*/true));
+  }
+
+  SmallVector<SmallVector<std::string, 4>, 2> Candidates;
+  Candidates.push_back(std::move(SourceParameters));
+  if (Candidates.front() != DesugaredParameters)
+    Candidates.push_back(std::move(DesugaredParameters));
+
+  return Candidates;
 }
 
 static SmallVector<StringRef, 4>
@@ -1016,6 +1054,26 @@ getAPINotesParameterSelectorRefs(ArrayRef<std::string> 
Strings) {
   return Refs;
 }
 
+// Apply the first exact selector entry found. This preserves source-spelling
+// precedence over the desugared fallback and avoids applying multiple exact
+// entries for the same declaration.
+template <typename SpecificDecl, typename LookupExactFn>
+static void processExactAPINotes(
+    Sema &S, SpecificDecl *D,
+    ArrayRef<SmallVector<std::string, 4>> ParameterSelectorCandidates,
+    LookupExactFn LookupExact) {
+  for (ArrayRef<std::string> ParameterStrings : ParameterSelectorCandidates) {
+    SmallVector<StringRef, 4> Parameters =
+        getAPINotesParameterSelectorRefs(ParameterStrings);
+    auto Info = LookupExact(Parameters);
+    if (Info.size() == 0)
+      continue;
+
+    ProcessVersionedAPINotes(S, D, Info);
+    return;
+  }
+}
+
 /// Process API notes that are associated with this declaration, mapping them
 /// to attributes as appropriate.
 void Sema::ProcessAPINotes(Decl *D) {
@@ -1047,21 +1105,21 @@ void Sema::ProcessAPINotes(Decl *D) {
     // Global functions.
     if (auto FD = dyn_cast<FunctionDecl>(D)) {
       if (FD->getDeclName().isIdentifier()) {
-        std::optional<SmallVector<std::string, 4>> ParameterStrings =
-            getAPINotesParameterSelector(*this, FD);
-        SmallVector<StringRef, 4> Parameters;
-        if (ParameterStrings)
-          Parameters = getAPINotesParameterSelectorRefs(*ParameterStrings);
+        std::optional<SmallVector<SmallVector<std::string, 4>, 2>>
+            ParameterSelectorCandidates =
+                getAPINotesParameterSelectorCandidates(*this, FD);
         for (auto Reader : Readers) {
           auto Info =
               Reader->lookupGlobalFunction(FD->getName(), APINotesContext);
           ProcessVersionedAPINotes(*this, FD, Info);
 
-          if (ParameterStrings) {
-            Info = Reader->lookupGlobalFunction(FD->getName(), Parameters,
-                                                APINotesContext);
-            ProcessVersionedAPINotes(*this, FD, Info);
-          }
+          if (ParameterSelectorCandidates)
+            processExactAPINotes(*this, FD, *ParameterSelectorCandidates,
+                                 [&](ArrayRef<StringRef> Parameters) {
+                                   return Reader->lookupGlobalFunction(
+                                       FD->getName(), Parameters,
+                                       APINotesContext);
+                                 });
         }
       }
 
@@ -1245,11 +1303,9 @@ void Sema::ProcessAPINotes(Decl *D) {
       if (!isa<CXXConstructorDecl>(CXXMethod) &&
           !isa<CXXDestructorDecl>(CXXMethod) &&
           !isa<CXXConversionDecl>(CXXMethod)) {
-        std::optional<SmallVector<std::string, 4>> ParameterStrings =
-            getAPINotesParameterSelector(*this, CXXMethod);
-        SmallVector<StringRef, 4> Parameters;
-        if (ParameterStrings)
-          Parameters = getAPINotesParameterSelectorRefs(*ParameterStrings);
+        std::optional<SmallVector<SmallVector<std::string, 4>, 2>>
+            ParameterSelectorCandidates =
+                getAPINotesParameterSelectorCandidates(*this, CXXMethod);
         for (auto Reader : Readers) {
           if (auto Context = UnwindTagContext(TagContext, APINotes)) {
             std::string MethodName;
@@ -1263,11 +1319,13 @@ void Sema::ProcessAPINotes(Decl *D) {
             auto Info = Reader->lookupCXXMethod(Context->id, MethodName);
             ProcessVersionedAPINotes(*this, CXXMethod, Info);
 
-            if (ParameterStrings) {
-              Info =
-                  Reader->lookupCXXMethod(Context->id, MethodName, Parameters);
-              ProcessVersionedAPINotes(*this, CXXMethod, Info);
-            }
+            if (ParameterSelectorCandidates)
+              processExactAPINotes(*this, CXXMethod,
+                                   *ParameterSelectorCandidates,
+                                   [&](ArrayRef<StringRef> Parameters) {
+                                     return Reader->lookupCXXMethod(
+                                         Context->id, MethodName, Parameters);
+                                   });
           }
         }
       }
diff --git a/clang/test/APINotes/Inputs/Headers/WhereParametersSema.apinotes 
b/clang/test/APINotes/Inputs/Headers/WhereParametersSema.apinotes
index 2a9f9c921347b..2f3b31148661f 100644
--- a/clang/test/APINotes/Inputs/Headers/WhereParametersSema.apinotes
+++ b/clang/test/APINotes/Inputs/Headers/WhereParametersSema.apinotes
@@ -33,7 +33,22 @@ Functions:
   Where:
     Parameters:
     - int
-  SwiftName: shouldNotApplyAliasGlobal(_:)
+  SwiftName: aliasGlobal(_:)
+- Name: aliasPrecedenceGlobal
+  Where:
+    Parameters:
+    - int
+  SwiftName: fallbackAliasPrecedenceGlobal(_:)
+- Name: aliasPrecedenceGlobal
+  Where:
+    Parameters:
+    - AliasInt
+  SwiftName: aliasPrecedenceGlobal(_:)
+- Name: nullableGlobal
+  Where:
+    Parameters:
+    - 'char *'
+  SwiftName: nullableGlobal(_:)
 - Name: rawIntGlobal
   Where:
     Parameters:
@@ -103,7 +118,22 @@ Tags:
     Where:
       Parameters:
       - int
-    SwiftName: shouldNotApplyAliasMethod(_:)
+    SwiftName: alias(_:)
+  - Name: aliasPrecedence
+    Where:
+      Parameters:
+      - int
+    SwiftName: fallbackAliasPrecedence(_:)
+  - Name: aliasPrecedence
+    Where:
+      Parameters:
+      - AliasInt
+    SwiftName: aliasPrecedence(_:)
+  - Name: nullable
+    Where:
+      Parameters:
+      - 'char *'
+    SwiftName: nullable(_:)
   - Name: rawInt
     Where:
       Parameters:
diff --git a/clang/test/APINotes/Inputs/Headers/WhereParametersSema.h 
b/clang/test/APINotes/Inputs/Headers/WhereParametersSema.h
index 1cd10676e5533..85990e4ad7434 100644
--- a/clang/test/APINotes/Inputs/Headers/WhereParametersSema.h
+++ b/clang/test/APINotes/Inputs/Headers/WhereParametersSema.h
@@ -15,6 +15,8 @@ void coexistGlobal(double);
 
 void mismatchGlobal(float);
 void aliasGlobal(AliasInt);
+void aliasPrecedenceGlobal(AliasInt);
+void nullableGlobal(char * _Nonnull);
 void rawIntGlobal(int);
 void constValueGlobal(const int);
 
@@ -41,6 +43,8 @@ struct SelectorWidget {
 
   void mismatch(float);
   void alias(AliasInt);
+  void aliasPrecedence(AliasInt);
+  void nullable(char * _Nonnull);
   void rawInt(int);
   void constValue(const int);
 
diff --git a/clang/test/APINotes/where-parameters-sema.cpp 
b/clang/test/APINotes/where-parameters-sema.cpp
index 7d1dcf7b61abb..6e19719593197 100644
--- a/clang/test/APINotes/where-parameters-sema.cpp
+++ b/clang/test/APINotes/where-parameters-sema.cpp
@@ -5,6 +5,8 @@
 // RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
coexistGlobal -x c++ | FileCheck --check-prefix=CHECK-GLOBAL-COEXIST %s
 // RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
mismatchGlobal -x c++ | FileCheck --check-prefix=CHECK-GLOBAL-MISMATCH %s
 // RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
aliasGlobal -x c++ | FileCheck --check-prefix=CHECK-GLOBAL-ALIAS %s
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
aliasPrecedenceGlobal -x c++ | FileCheck 
--check-prefix=CHECK-GLOBAL-ALIAS-PRECEDENCE %s
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
nullableGlobal -x c++ | FileCheck --check-prefix=CHECK-GLOBAL-NULLABILITY %s
 // RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
rawIntGlobal -x c++ | FileCheck --check-prefix=CHECK-GLOBAL-RAW-INT %s
 // RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
constValueGlobal -x c++ | FileCheck --check-prefix=CHECK-GLOBAL-CONST %s
 // RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
SelectorNamespace::makeNamespaced -x c++ | FileCheck 
--check-prefix=CHECK-GLOBAL-NAMESPACE %s
@@ -15,6 +17,8 @@
 // RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
SelectorWidget::configure -x c++ | FileCheck --check-prefix=CHECK-METHOD-STATIC 
%s
 // RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
SelectorWidget::mismatch -x c++ | FileCheck 
--check-prefix=CHECK-METHOD-MISMATCH %s
 // RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
SelectorWidget::alias -x c++ | FileCheck --check-prefix=CHECK-METHOD-ALIAS %s
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
SelectorWidget::aliasPrecedence -x c++ | FileCheck 
--check-prefix=CHECK-METHOD-ALIAS-PRECEDENCE %s
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
SelectorWidget::nullable -x c++ | FileCheck 
--check-prefix=CHECK-METHOD-NULLABILITY %s
 // RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
SelectorWidget::rawInt -x c++ | FileCheck --check-prefix=CHECK-METHOD-RAW-INT %s
 // RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
SelectorWidget::constValue -x c++ | FileCheck --check-prefix=CHECK-METHOD-CONST 
%s
 // RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
SelectorWidget::operator+ -x c++ | FileCheck 
--check-prefix=CHECK-METHOD-OPERATOR %s
@@ -46,7 +50,14 @@
 // CHECK-GLOBAL-MISMATCH-NOT: SwiftNameAttr
 
 // CHECK-GLOBAL-ALIAS: FunctionDecl {{.+}} aliasGlobal 'void (AliasInt)'
-// CHECK-GLOBAL-ALIAS-NOT: SwiftNameAttr
+// CHECK-GLOBAL-ALIAS: SwiftNameAttr {{.+}} "aliasGlobal(_:)"
+
+// CHECK-GLOBAL-ALIAS-PRECEDENCE: FunctionDecl {{.+}} aliasPrecedenceGlobal 
'void (AliasInt)'
+// CHECK-GLOBAL-ALIAS-PRECEDENCE-NOT: fallbackAliasPrecedenceGlobal
+// CHECK-GLOBAL-ALIAS-PRECEDENCE: SwiftNameAttr {{.+}} 
"aliasPrecedenceGlobal(_:)"
+
+// CHECK-GLOBAL-NULLABILITY: FunctionDecl {{.+}} nullableGlobal 'void (char * 
_Nonnull)'
+// CHECK-GLOBAL-NULLABILITY: SwiftNameAttr {{.+}} "nullableGlobal(_:)"
 
 // CHECK-GLOBAL-RAW-INT: FunctionDecl {{.+}} rawIntGlobal 'void (int)'
 // CHECK-GLOBAL-RAW-INT: SwiftNameAttr {{.+}} "rawIntGlobal(_:)"
@@ -94,7 +105,14 @@
 // CHECK-METHOD-MISMATCH-NOT: SwiftNameAttr
 
 // CHECK-METHOD-ALIAS: CXXMethodDecl {{.+}} alias 'void (AliasInt)'
-// CHECK-METHOD-ALIAS-NOT: SwiftNameAttr
+// CHECK-METHOD-ALIAS: SwiftNameAttr {{.+}} "alias(_:)"
+
+// CHECK-METHOD-ALIAS-PRECEDENCE: CXXMethodDecl {{.+}} aliasPrecedence 'void 
(AliasInt)'
+// CHECK-METHOD-ALIAS-PRECEDENCE-NOT: fallbackAliasPrecedence
+// CHECK-METHOD-ALIAS-PRECEDENCE: SwiftNameAttr {{.+}} "aliasPrecedence(_:)"
+
+// CHECK-METHOD-NULLABILITY: CXXMethodDecl {{.+}} nullable 'void (char * 
_Nonnull)'
+// CHECK-METHOD-NULLABILITY: SwiftNameAttr {{.+}} "nullable(_:)"
 
 // CHECK-METHOD-RAW-INT: CXXMethodDecl {{.+}} rawInt 'void (int)'
 // CHECK-METHOD-RAW-INT: SwiftNameAttr {{.+}} "rawInt(_:)"

>From 06e6217d3f09728c67e7e6ec00ccd9e84abc3b95 Mon Sep 17 00:00:00 2001
From: StoeckOverflow <[email protected]>
Date: Fri, 3 Jul 2026 08:48:03 +0200
Subject: [PATCH 3/5] Update clang/lib/Sema/SemaAPINotes.cpp

Co-authored-by: John Hui <[email protected]>
---
 clang/lib/Sema/SemaAPINotes.cpp | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp
index cae73fe3f4e3b..448c6b410fbfc 100644
--- a/clang/lib/Sema/SemaAPINotes.cpp
+++ b/clang/lib/Sema/SemaAPINotes.cpp
@@ -1105,9 +1105,8 @@ void Sema::ProcessAPINotes(Decl *D) {
     // Global functions.
     if (auto FD = dyn_cast<FunctionDecl>(D)) {
       if (FD->getDeclName().isIdentifier()) {
-        std::optional<SmallVector<SmallVector<std::string, 4>, 2>>
-            ParameterSelectorCandidates =
-                getAPINotesParameterSelectorCandidates(*this, FD);
+        auto ParameterSelectorCandidates =
+            getAPINotesParameterSelectorCandidates(*this, FD);
         for (auto Reader : Readers) {
           auto Info =
               Reader->lookupGlobalFunction(FD->getName(), APINotesContext);

>From 75d4bc723bbd9ae515c49c9c9b5f5f001bd255db Mon Sep 17 00:00:00 2001
From: stoeckoverflow <[email protected]>
Date: Fri, 3 Jul 2026 15:48:42 +0200
Subject: [PATCH 4/5] [APINotes] Refine Where.Parameters selector matching

---
 clang/lib/Sema/SemaAPINotes.cpp               | 121 +++++++++++-------
 .../Headers/WhereParametersSema.apinotes      |  10 ++
 .../Inputs/Headers/WhereParametersSema.h      |   4 +
 clang/test/APINotes/where-parameters-sema.cpp |   8 ++
 4 files changed, 98 insertions(+), 45 deletions(-)

diff --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp
index 448c6b410fbfc..a2176a3b8b976 100644
--- a/clang/lib/Sema/SemaAPINotes.cpp
+++ b/clang/lib/Sema/SemaAPINotes.cpp
@@ -1000,6 +1000,40 @@ static void stripAPINotesParameterNullability(QualType 
&ParamType) {
   }
 }
 
+struct APINotesParameterSelector {
+  SmallVector<std::string, 4> Parameters;
+
+  SmallVector<StringRef, 4> getParameterRefs() const {
+    SmallVector<StringRef, 4> Refs;
+    Refs.reserve(Parameters.size());
+    for (const std::string &Parameter : Parameters)
+      Refs.push_back(Parameter);
+    return Refs;
+  }
+
+  bool operator==(const APINotesParameterSelector &Other) const {
+    return Parameters == Other.Parameters;
+  }
+};
+
+struct APINotesParameterSelectorCandidates {
+  APINotesParameterSelector Source;
+  std::optional<APINotesParameterSelector> Desugared;
+};
+
+static PrintingPolicy
+getAPINotesParameterSelectorPrintingPolicy(const ASTContext &Context) {
+  PrintingPolicy Policy(Context.getLangOpts());
+  Policy.PrintAsCanonical = false;
+  Policy.FullyQualifiedName = false;
+  Policy.SuppressScope = false;
+  Policy.UsePreferredNames = false;
+  Policy.MSVCFormatting = false;
+  Policy.SplitTemplateClosers = false;
+  Policy.IncludeNewlines = false;
+  return Policy;
+}
+
 // Print the APINotes selector spelling for one parameter. The source-spelled
 // selector is tried first. The desugared spelling is only a permissive
 // fallback.
@@ -1018,60 +1052,58 @@ static std::string getAPINotesParameterSelectorSpelling(
   return ParamType.getAsString(Policy);
 }
 
-static std::optional<SmallVector<SmallVector<std::string, 4>, 2>>
+static std::optional<APINotesParameterSelectorCandidates>
 getAPINotesParameterSelectorCandidates(const Sema &S, const FunctionDecl *FD) {
   const auto *FPT = FD->getType()->getAs<FunctionProtoType>();
   if (!FPT)
     return std::nullopt;
 
-  SmallVector<std::string, 4> SourceParameters;
-  SmallVector<std::string, 4> DesugaredParameters;
-  SourceParameters.reserve(FPT->getNumParams());
-  DesugaredParameters.reserve(FPT->getNumParams());
+  APINotesParameterSelectorCandidates Candidates;
+  APINotesParameterSelector Desugared;
+  Candidates.Source.Parameters.reserve(FPT->getNumParams());
+  Desugared.Parameters.reserve(FPT->getNumParams());
 
-  const PrintingPolicy &Policy = S.Context.getPrintingPolicy();
+  const PrintingPolicy Policy =
+      getAPINotesParameterSelectorPrintingPolicy(S.Context);
   for (QualType ParamType : FPT->param_types()) {
-    SourceParameters.push_back(getAPINotesParameterSelectorSpelling(
-        ParamType, S.Context, Policy, /*Desugar=*/false));
-    DesugaredParameters.push_back(getAPINotesParameterSelectorSpelling(
+    Candidates.Source.Parameters.push_back(
+        getAPINotesParameterSelectorSpelling(ParamType, S.Context, Policy,
+                                             /*Desugar=*/false));
+    Desugared.Parameters.push_back(getAPINotesParameterSelectorSpelling(
         ParamType, S.Context, Policy, /*Desugar=*/true));
   }
 
-  SmallVector<SmallVector<std::string, 4>, 2> Candidates;
-  Candidates.push_back(std::move(SourceParameters));
-  if (Candidates.front() != DesugaredParameters)
-    Candidates.push_back(std::move(DesugaredParameters));
+  if (!(Candidates.Source == Desugared))
+    Candidates.Desugared = std::move(Desugared);
 
   return Candidates;
 }
 
-static SmallVector<StringRef, 4>
-getAPINotesParameterSelectorRefs(ArrayRef<std::string> Strings) {
-  SmallVector<StringRef, 4> Refs;
-  Refs.reserve(Strings.size());
-  for (const std::string &String : Strings)
-    Refs.push_back(String);
-  return Refs;
-}
-
 // Apply the first exact selector entry found. This preserves source-spelling
 // precedence over the desugared fallback and avoids applying multiple exact
 // entries for the same declaration.
-template <typename SpecificDecl, typename LookupExactFn>
+template <typename SpecificInfo, typename SpecificDecl>
 static void processExactAPINotes(
     Sema &S, SpecificDecl *D,
-    ArrayRef<SmallVector<std::string, 4>> ParameterSelectorCandidates,
-    LookupExactFn LookupExact) {
-  for (ArrayRef<std::string> ParameterStrings : ParameterSelectorCandidates) {
-    SmallVector<StringRef, 4> Parameters =
-        getAPINotesParameterSelectorRefs(ParameterStrings);
+    const APINotesParameterSelectorCandidates &ParameterSelectorCandidates,
+    llvm::function_ref<api_notes::APINotesReader::VersionedInfo<SpecificInfo>(
+        ArrayRef<StringRef>)>
+        LookupExact) {
+  auto ProcessSelector = [&](const APINotesParameterSelector &Selector) {
+    SmallVector<StringRef, 4> Parameters = Selector.getParameterRefs();
     auto Info = LookupExact(Parameters);
     if (Info.size() == 0)
-      continue;
+      return false;
 
     ProcessVersionedAPINotes(S, D, Info);
+    return true;
+  };
+
+  if (ProcessSelector(ParameterSelectorCandidates.Source))
     return;
-  }
+
+  if (ParameterSelectorCandidates.Desugared)
+    ProcessSelector(*ParameterSelectorCandidates.Desugared);
 }
 
 /// Process API notes that are associated with this declaration, mapping them
@@ -1113,12 +1145,12 @@ void Sema::ProcessAPINotes(Decl *D) {
           ProcessVersionedAPINotes(*this, FD, Info);
 
           if (ParameterSelectorCandidates)
-            processExactAPINotes(*this, FD, *ParameterSelectorCandidates,
-                                 [&](ArrayRef<StringRef> Parameters) {
-                                   return Reader->lookupGlobalFunction(
-                                       FD->getName(), Parameters,
-                                       APINotesContext);
-                                 });
+            processExactAPINotes<api_notes::GlobalFunctionInfo>(
+                *this, FD, *ParameterSelectorCandidates,
+                [&](ArrayRef<StringRef> Parameters) {
+                  return Reader->lookupGlobalFunction(FD->getName(), 
Parameters,
+                                                      APINotesContext);
+                });
         }
       }
 
@@ -1302,9 +1334,8 @@ void Sema::ProcessAPINotes(Decl *D) {
       if (!isa<CXXConstructorDecl>(CXXMethod) &&
           !isa<CXXDestructorDecl>(CXXMethod) &&
           !isa<CXXConversionDecl>(CXXMethod)) {
-        std::optional<SmallVector<SmallVector<std::string, 4>, 2>>
-            ParameterSelectorCandidates =
-                getAPINotesParameterSelectorCandidates(*this, CXXMethod);
+        auto ParameterSelectorCandidates =
+            getAPINotesParameterSelectorCandidates(*this, CXXMethod);
         for (auto Reader : Readers) {
           if (auto Context = UnwindTagContext(TagContext, APINotes)) {
             std::string MethodName;
@@ -1319,12 +1350,12 @@ void Sema::ProcessAPINotes(Decl *D) {
             ProcessVersionedAPINotes(*this, CXXMethod, Info);
 
             if (ParameterSelectorCandidates)
-              processExactAPINotes(*this, CXXMethod,
-                                   *ParameterSelectorCandidates,
-                                   [&](ArrayRef<StringRef> Parameters) {
-                                     return Reader->lookupCXXMethod(
-                                         Context->id, MethodName, Parameters);
-                                   });
+              processExactAPINotes<api_notes::CXXMethodInfo>(
+                  *this, CXXMethod, *ParameterSelectorCandidates,
+                  [&](ArrayRef<StringRef> Parameters) {
+                    return Reader->lookupCXXMethod(Context->id, MethodName,
+                                                   Parameters);
+                  });
           }
         }
       }
diff --git a/clang/test/APINotes/Inputs/Headers/WhereParametersSema.apinotes 
b/clang/test/APINotes/Inputs/Headers/WhereParametersSema.apinotes
index 2f3b31148661f..7ffee9223f8c3 100644
--- a/clang/test/APINotes/Inputs/Headers/WhereParametersSema.apinotes
+++ b/clang/test/APINotes/Inputs/Headers/WhereParametersSema.apinotes
@@ -44,6 +44,11 @@ Functions:
     Parameters:
     - AliasInt
   SwiftName: aliasPrecedenceGlobal(_:)
+- Name: multiAliasGlobal
+  Where:
+    Parameters:
+    - int
+  SwiftName: multiAliasGlobal(_:)
 - Name: nullableGlobal
   Where:
     Parameters:
@@ -129,6 +134,11 @@ Tags:
       Parameters:
       - AliasInt
     SwiftName: aliasPrecedence(_:)
+  - Name: multiAlias
+    Where:
+      Parameters:
+      - int
+    SwiftName: multiAlias(_:)
   - Name: nullable
     Where:
       Parameters:
diff --git a/clang/test/APINotes/Inputs/Headers/WhereParametersSema.h 
b/clang/test/APINotes/Inputs/Headers/WhereParametersSema.h
index 85990e4ad7434..8226fa287b115 100644
--- a/clang/test/APINotes/Inputs/Headers/WhereParametersSema.h
+++ b/clang/test/APINotes/Inputs/Headers/WhereParametersSema.h
@@ -2,6 +2,8 @@
 #define WHERE_PARAMETERS_SEMA_H
 
 using AliasInt = int;
+using AliasAliasInt = AliasInt;
+using DeepAliasInt = AliasAliasInt;
 
 void makeWidget(int);
 void makeWidget(double);
@@ -16,6 +18,7 @@ void coexistGlobal(double);
 void mismatchGlobal(float);
 void aliasGlobal(AliasInt);
 void aliasPrecedenceGlobal(AliasInt);
+void multiAliasGlobal(DeepAliasInt);
 void nullableGlobal(char * _Nonnull);
 void rawIntGlobal(int);
 void constValueGlobal(const int);
@@ -44,6 +47,7 @@ struct SelectorWidget {
   void mismatch(float);
   void alias(AliasInt);
   void aliasPrecedence(AliasInt);
+  void multiAlias(DeepAliasInt);
   void nullable(char * _Nonnull);
   void rawInt(int);
   void constValue(const int);
diff --git a/clang/test/APINotes/where-parameters-sema.cpp 
b/clang/test/APINotes/where-parameters-sema.cpp
index 6e19719593197..fbb7cb45b9441 100644
--- a/clang/test/APINotes/where-parameters-sema.cpp
+++ b/clang/test/APINotes/where-parameters-sema.cpp
@@ -6,6 +6,7 @@
 // RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
mismatchGlobal -x c++ | FileCheck --check-prefix=CHECK-GLOBAL-MISMATCH %s
 // RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
aliasGlobal -x c++ | FileCheck --check-prefix=CHECK-GLOBAL-ALIAS %s
 // RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
aliasPrecedenceGlobal -x c++ | FileCheck 
--check-prefix=CHECK-GLOBAL-ALIAS-PRECEDENCE %s
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
multiAliasGlobal -x c++ | FileCheck --check-prefix=CHECK-GLOBAL-MULTI-ALIAS %s
 // RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
nullableGlobal -x c++ | FileCheck --check-prefix=CHECK-GLOBAL-NULLABILITY %s
 // RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
rawIntGlobal -x c++ | FileCheck --check-prefix=CHECK-GLOBAL-RAW-INT %s
 // RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
constValueGlobal -x c++ | FileCheck --check-prefix=CHECK-GLOBAL-CONST %s
@@ -18,6 +19,7 @@
 // RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
SelectorWidget::mismatch -x c++ | FileCheck 
--check-prefix=CHECK-METHOD-MISMATCH %s
 // RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
SelectorWidget::alias -x c++ | FileCheck --check-prefix=CHECK-METHOD-ALIAS %s
 // RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
SelectorWidget::aliasPrecedence -x c++ | FileCheck 
--check-prefix=CHECK-METHOD-ALIAS-PRECEDENCE %s
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
SelectorWidget::multiAlias -x c++ | FileCheck 
--check-prefix=CHECK-METHOD-MULTI-ALIAS %s
 // RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
SelectorWidget::nullable -x c++ | FileCheck 
--check-prefix=CHECK-METHOD-NULLABILITY %s
 // RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
SelectorWidget::rawInt -x c++ | FileCheck --check-prefix=CHECK-METHOD-RAW-INT %s
 // RUN: %clang_cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter 
SelectorWidget::constValue -x c++ | FileCheck --check-prefix=CHECK-METHOD-CONST 
%s
@@ -56,6 +58,9 @@
 // CHECK-GLOBAL-ALIAS-PRECEDENCE-NOT: fallbackAliasPrecedenceGlobal
 // CHECK-GLOBAL-ALIAS-PRECEDENCE: SwiftNameAttr {{.+}} 
"aliasPrecedenceGlobal(_:)"
 
+// CHECK-GLOBAL-MULTI-ALIAS: FunctionDecl {{.+}} multiAliasGlobal 'void 
(DeepAliasInt)'
+// CHECK-GLOBAL-MULTI-ALIAS: SwiftNameAttr {{.+}} "multiAliasGlobal(_:)"
+
 // CHECK-GLOBAL-NULLABILITY: FunctionDecl {{.+}} nullableGlobal 'void (char * 
_Nonnull)'
 // CHECK-GLOBAL-NULLABILITY: SwiftNameAttr {{.+}} "nullableGlobal(_:)"
 
@@ -111,6 +116,9 @@
 // CHECK-METHOD-ALIAS-PRECEDENCE-NOT: fallbackAliasPrecedence
 // CHECK-METHOD-ALIAS-PRECEDENCE: SwiftNameAttr {{.+}} "aliasPrecedence(_:)"
 
+// CHECK-METHOD-MULTI-ALIAS: CXXMethodDecl {{.+}} multiAlias 'void 
(DeepAliasInt)'
+// CHECK-METHOD-MULTI-ALIAS: SwiftNameAttr {{.+}} "multiAlias(_:)"
+
 // CHECK-METHOD-NULLABILITY: CXXMethodDecl {{.+}} nullable 'void (char * 
_Nonnull)'
 // CHECK-METHOD-NULLABILITY: SwiftNameAttr {{.+}} "nullable(_:)"
 

>From 778b61cf434fbeb310b4107a8d283c4a984d491c Mon Sep 17 00:00:00 2001
From: stoeckoverflow <[email protected]>
Date: Wed, 8 Jul 2026 18:54:53 +0200
Subject: [PATCH 5/5] [APINotes] Clean up Where.Parameters Sema matching

---
 clang/include/clang/APINotes/APINotesReader.h | 11 ++++---
 clang/lib/APINotes/APINotesFormat.h           |  9 +++---
 clang/lib/APINotes/APINotesReader.cpp         | 22 ++++++++-----
 clang/lib/Sema/SemaAPINotes.cpp               | 32 +++++++------------
 4 files changed, 38 insertions(+), 36 deletions(-)

diff --git a/clang/include/clang/APINotes/APINotesReader.h 
b/clang/include/clang/APINotes/APINotesReader.h
index 8e748b5803189..761745e20b61a 100644
--- a/clang/include/clang/APINotes/APINotesReader.h
+++ b/clang/include/clang/APINotes/APINotesReader.h
@@ -22,6 +22,7 @@
 #include "llvm/Support/VersionTuple.h"
 #include <memory>
 #include <optional>
+#include <string>
 
 namespace clang {
 namespace api_notes {
@@ -166,7 +167,7 @@ class APINotesReader {
   /// key, and a non-empty list uses an exact ordered parameter key.
   VersionedInfo<CXXMethodInfo>
   lookupCXXMethod(ContextID CtxID, llvm::StringRef Name,
-                  llvm::ArrayRef<llvm::StringRef> Parameters);
+                  llvm::ArrayRef<std::string> Parameters);
 
   /// Look for information regarding the given global variable.
   ///
@@ -191,7 +192,7 @@ class APINotesReader {
   /// key, and a non-empty list uses an exact ordered parameter key.
   VersionedInfo<GlobalFunctionInfo>
   lookupGlobalFunction(llvm::StringRef Name,
-                       llvm::ArrayRef<llvm::StringRef> Parameters,
+                       llvm::ArrayRef<std::string> Parameters,
                        std::optional<Context> Ctx = std::nullopt);
 
   /// Look for information regarding the given enumerator.
@@ -242,15 +243,17 @@ class APINotesReader {
 private:
   VersionedInfo<CXXMethodInfo> lookupCXXMethodImpl(ContextID CtxID,
                                                    llvm::StringRef Name);
+  template <typename ParameterT>
   VersionedInfo<CXXMethodInfo>
   lookupCXXMethodImpl(ContextID CtxID, llvm::StringRef Name,
-                      llvm::ArrayRef<llvm::StringRef> Parameters);
+                      llvm::ArrayRef<ParameterT> Parameters);
 
   VersionedInfo<GlobalFunctionInfo>
   lookupGlobalFunctionImpl(llvm::StringRef Name, std::optional<Context> Ctx);
+  template <typename ParameterT>
   VersionedInfo<GlobalFunctionInfo>
   lookupGlobalFunctionImpl(llvm::StringRef Name,
-                           llvm::ArrayRef<llvm::StringRef> Parameters,
+                           llvm::ArrayRef<ParameterT> Parameters,
                            std::optional<Context> Ctx);
 };
 
diff --git a/clang/lib/APINotes/APINotesFormat.h 
b/clang/lib/APINotes/APINotesFormat.h
index df67da0845baf..f34ca2e2e363f 100644
--- a/clang/lib/APINotes/APINotesFormat.h
+++ b/clang/lib/APINotes/APINotesFormat.h
@@ -417,10 +417,10 @@ getFunctionKeyImpl(uint32_t ParentContextID, 
llvm::StringRef Name,
   return FunctionTableKey(ParentContextID, *NameID);
 }
 
-template <typename GetIdentifierFn>
+template <typename ParameterT, typename GetIdentifierFn>
 std::optional<FunctionTableKey>
 getFunctionKeyImpl(uint32_t ParentContextID, llvm::StringRef Name,
-                   llvm::ArrayRef<llvm::StringRef> Parameters,
+                   llvm::ArrayRef<ParameterT> Parameters,
                    GetIdentifierFn GetIdentifier) {
   std::optional<IdentifierID> NameID = GetIdentifier(Name);
   if (!NameID)
@@ -428,8 +428,9 @@ getFunctionKeyImpl(uint32_t ParentContextID, 
llvm::StringRef Name,
 
   llvm::SmallVector<IdentifierID, 2> ParameterTypeIDs;
   ParameterTypeIDs.reserve(Parameters.size());
-  for (llvm::StringRef Parameter : Parameters) {
-    std::optional<IdentifierID> ParameterID = GetIdentifier(Parameter);
+  for (const ParameterT &Parameter : Parameters) {
+    std::optional<IdentifierID> ParameterID =
+        GetIdentifier(llvm::StringRef(Parameter));
     if (!ParameterID)
       return std::nullopt;
     ParameterTypeIDs.push_back(*ParameterID);
diff --git a/clang/lib/APINotes/APINotesReader.cpp 
b/clang/lib/APINotes/APINotesReader.cpp
index 9305a5f10b4e8..c51ced8f27448 100644
--- a/clang/lib/APINotes/APINotesReader.cpp
+++ b/clang/lib/APINotes/APINotesReader.cpp
@@ -857,14 +857,16 @@ class APINotesReader::Implementation {
                                       llvm::SmallVectorImpl<uint64_t> 
&Scratch);
   std::optional<FunctionTableKey> getFunctionKey(uint32_t ParentContextID,
                                                  llvm::StringRef Name);
+  template <typename ParameterT>
   std::optional<FunctionTableKey>
   getFunctionKey(uint32_t ParentContextID, llvm::StringRef Name,
-                 llvm::ArrayRef<llvm::StringRef> Parameters);
+                 llvm::ArrayRef<ParameterT> Parameters);
   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<llvm::StringRef> Parameters);
+                 llvm::ArrayRef<ParameterT> Parameters);
 
   llvm::Error readGlobalFunctionBlock(llvm::BitstreamCursor &Cursor,
                                       llvm::SmallVectorImpl<uint64_t> 
&Scratch);
@@ -899,9 +901,10 @@ APINotesReader::Implementation::getFunctionKey(uint32_t 
ParentContextID,
   });
 }
 
+template <typename ParameterT>
 std::optional<FunctionTableKey> APINotesReader::Implementation::getFunctionKey(
     uint32_t ParentContextID, llvm::StringRef Name,
-    llvm::ArrayRef<llvm::StringRef> Parameters) {
+    llvm::ArrayRef<ParameterT> Parameters) {
   return getFunctionKeyImpl(
       ParentContextID, Name, Parameters,
       [this](llvm::StringRef S) { return getIdentifier(S); });
@@ -914,9 +917,10 @@ std::optional<FunctionTableKey> 
APINotesReader::Implementation::getFunctionKey(
   return getFunctionKey(ParentContextID, Name);
 }
 
+template <typename ParameterT>
 std::optional<FunctionTableKey> APINotesReader::Implementation::getFunctionKey(
     std::optional<Context> ParentContext, llvm::StringRef Name,
-    llvm::ArrayRef<llvm::StringRef> Parameters) {
+    llvm::ArrayRef<ParameterT> Parameters) {
   uint32_t ParentContextID =
       ParentContext ? ParentContext->id.Value : static_cast<uint32_t>(-1);
   return getFunctionKey(ParentContextID, Name, Parameters);
@@ -2342,7 +2346,7 @@ auto APINotesReader::lookupCXXMethod(ContextID CtxID, 
llvm::StringRef Name)
 }
 
 auto APINotesReader::lookupCXXMethod(ContextID CtxID, llvm::StringRef Name,
-                                     llvm::ArrayRef<llvm::StringRef> 
Parameters)
+                                     llvm::ArrayRef<std::string> Parameters)
     -> VersionedInfo<CXXMethodInfo> {
   return lookupCXXMethodImpl(CtxID, Name, Parameters);
 }
@@ -2364,9 +2368,10 @@ auto APINotesReader::lookupCXXMethodImpl(ContextID 
CtxID, llvm::StringRef Name)
   return {Implementation->SwiftVersion, *Known};
 }
 
+template <typename ParameterT>
 auto APINotesReader::lookupCXXMethodImpl(
     ContextID CtxID, llvm::StringRef Name,
-    llvm::ArrayRef<llvm::StringRef> Parameters)
+    llvm::ArrayRef<ParameterT> Parameters)
     -> VersionedInfo<CXXMethodInfo> {
   if (!Implementation->CXXMethodTable)
     return std::nullopt;
@@ -2409,7 +2414,7 @@ auto APINotesReader::lookupGlobalFunction(llvm::StringRef 
Name,
 }
 
 auto APINotesReader::lookupGlobalFunction(
-    llvm::StringRef Name, llvm::ArrayRef<llvm::StringRef> Parameters,
+    llvm::StringRef Name, llvm::ArrayRef<std::string> Parameters,
     std::optional<Context> Ctx) -> VersionedInfo<GlobalFunctionInfo> {
   return lookupGlobalFunctionImpl(Name, Parameters, Ctx);
 }
@@ -2432,8 +2437,9 @@ auto 
APINotesReader::lookupGlobalFunctionImpl(llvm::StringRef Name,
   return {Implementation->SwiftVersion, *Known};
 }
 
+template <typename ParameterT>
 auto APINotesReader::lookupGlobalFunctionImpl(
-    llvm::StringRef Name, llvm::ArrayRef<llvm::StringRef> Parameters,
+    llvm::StringRef Name, llvm::ArrayRef<ParameterT> Parameters,
     std::optional<Context> Ctx) -> VersionedInfo<GlobalFunctionInfo> {
   if (!Implementation->GlobalFunctionTable)
     return std::nullopt;
diff --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp
index a2176a3b8b976..1ab1eac4a5434 100644
--- a/clang/lib/Sema/SemaAPINotes.cpp
+++ b/clang/lib/Sema/SemaAPINotes.cpp
@@ -1003,17 +1003,13 @@ static void stripAPINotesParameterNullability(QualType 
&ParamType) {
 struct APINotesParameterSelector {
   SmallVector<std::string, 4> Parameters;
 
-  SmallVector<StringRef, 4> getParameterRefs() const {
-    SmallVector<StringRef, 4> Refs;
-    Refs.reserve(Parameters.size());
-    for (const std::string &Parameter : Parameters)
-      Refs.push_back(Parameter);
-    return Refs;
-  }
-
   bool operator==(const APINotesParameterSelector &Other) const {
     return Parameters == Other.Parameters;
   }
+
+  bool operator!=(const APINotesParameterSelector &Other) const {
+    return !(*this == Other);
+  }
 };
 
 struct APINotesParameterSelectorCandidates {
@@ -1040,15 +1036,12 @@ getAPINotesParameterSelectorPrintingPolicy(const 
ASTContext &Context) {
 static std::string getAPINotesParameterSelectorSpelling(
     QualType ParamType, const ASTContext &Context, const PrintingPolicy 
&Policy,
     bool Desugar) {
+  if (Desugar)
+    ParamType = ParamType.getDesugaredType(Context);
+
   ParamType.removeLocalConst();
   stripAPINotesParameterNullability(ParamType);
 
-  if (Desugar) {
-    ParamType = ParamType.getDesugaredType(Context);
-    ParamType.removeLocalConst();
-    stripAPINotesParameterNullability(ParamType);
-  }
-
   return ParamType.getAsString(Policy);
 }
 
@@ -1073,7 +1066,7 @@ getAPINotesParameterSelectorCandidates(const Sema &S, 
const FunctionDecl *FD) {
         ParamType, S.Context, Policy, /*Desugar=*/true));
   }
 
-  if (!(Candidates.Source == Desugared))
+  if (Candidates.Source != Desugared)
     Candidates.Desugared = std::move(Desugared);
 
   return Candidates;
@@ -1087,11 +1080,10 @@ static void processExactAPINotes(
     Sema &S, SpecificDecl *D,
     const APINotesParameterSelectorCandidates &ParameterSelectorCandidates,
     llvm::function_ref<api_notes::APINotesReader::VersionedInfo<SpecificInfo>(
-        ArrayRef<StringRef>)>
+        ArrayRef<std::string>)>
         LookupExact) {
   auto ProcessSelector = [&](const APINotesParameterSelector &Selector) {
-    SmallVector<StringRef, 4> Parameters = Selector.getParameterRefs();
-    auto Info = LookupExact(Parameters);
+    auto Info = LookupExact(Selector.Parameters);
     if (Info.size() == 0)
       return false;
 
@@ -1147,7 +1139,7 @@ void Sema::ProcessAPINotes(Decl *D) {
           if (ParameterSelectorCandidates)
             processExactAPINotes<api_notes::GlobalFunctionInfo>(
                 *this, FD, *ParameterSelectorCandidates,
-                [&](ArrayRef<StringRef> Parameters) {
+                [&](ArrayRef<std::string> Parameters) {
                   return Reader->lookupGlobalFunction(FD->getName(), 
Parameters,
                                                       APINotesContext);
                 });
@@ -1352,7 +1344,7 @@ void Sema::ProcessAPINotes(Decl *D) {
             if (ParameterSelectorCandidates)
               processExactAPINotes<api_notes::CXXMethodInfo>(
                   *this, CXXMethod, *ParameterSelectorCandidates,
-                  [&](ArrayRef<StringRef> Parameters) {
+                  [&](ArrayRef<std::string> Parameters) {
                     return Reader->lookupCXXMethod(Context->id, MethodName,
                                                    Parameters);
                   });

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

Reply via email to