https://github.com/StoeckOverflow created 
https://github.com/llvm/llvm-project/pull/203227

Add YAML parser/model support for `Where.Parameters` on function-like API notes 
entries. This keeps `Name` as the required entry key and allows top-level 
`Functions` and C++ `Tags` / `Methods` to parse and round-trip an optional 
ordered list of explicit parameter type spellings. 

Binary API notes serialization, lookup, and overload matching are intentionally 
left for follow-up patches. Notes using `Where.Parameters` are diagnosed during 
binary conversion for now.

>From b154eed5122c80ac434df7d23c86b5bc7590843a Mon Sep 17 00:00:00 2001
From: stoeckoverflow <[email protected]>
Date: Thu, 11 Jun 2026 10:32:28 +0200
Subject: [PATCH] [clang][APINotes] Parse function-like Where.Parameters

---
 clang/lib/APINotes/APINotesYAMLCompiler.cpp   | 26 +++++++++
 .../WhereParametersMapElement.apinotes        |  8 +++
 ...hereParametersMethodWhereSequence.apinotes |  9 +++
 .../WhereParametersMissingName.apinotes       |  7 +++
 .../Headers/WhereParametersParser.apinotes    | 50 +++++++++++++++++
 .../Headers/WhereParametersScalar.apinotes    |  7 +++
 .../WhereParametersUnknownWhereKey.apinotes   |  7 +++
 .../WhereParametersWhereSequence.apinotes     |  8 +++
 .../test/APINotes/where-parameters-yaml.test  | 56 +++++++++++++++++++
 9 files changed, 178 insertions(+)
 create mode 100644 
clang/test/APINotes/Inputs/Headers/WhereParametersMapElement.apinotes
 create mode 100644 
clang/test/APINotes/Inputs/Headers/WhereParametersMethodWhereSequence.apinotes
 create mode 100644 
clang/test/APINotes/Inputs/Headers/WhereParametersMissingName.apinotes
 create mode 100644 
clang/test/APINotes/Inputs/Headers/WhereParametersParser.apinotes
 create mode 100644 
clang/test/APINotes/Inputs/Headers/WhereParametersScalar.apinotes
 create mode 100644 
clang/test/APINotes/Inputs/Headers/WhereParametersUnknownWhereKey.apinotes
 create mode 100644 
clang/test/APINotes/Inputs/Headers/WhereParametersWhereSequence.apinotes
 create mode 100644 clang/test/APINotes/where-parameters-yaml.test

diff --git a/clang/lib/APINotes/APINotesYAMLCompiler.cpp 
b/clang/lib/APINotes/APINotesYAMLCompiler.cpp
index 390dd428d55e3..0ff1367e7de28 100644
--- a/clang/lib/APINotes/APINotesYAMLCompiler.cpp
+++ b/clang/lib/APINotes/APINotesYAMLCompiler.cpp
@@ -338,8 +338,15 @@ template <> struct MappingTraits<Class> {
 } // namespace llvm
 
 namespace {
+typedef std::vector<StringRef> WhereParamsSeq;
+
+struct FunctionWhere {
+  std::optional<WhereParamsSeq> Parameters;
+};
+
 struct Function {
   StringRef Name;
+  std::optional<FunctionWhere> Where;
   ParamsSeq Params;
   NullabilitySeq Nullability;
   std::optional<NullabilityKind> NullabilityOfRet;
@@ -361,9 +368,16 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(Function)
 
 namespace llvm {
 namespace yaml {
+template <> struct MappingTraits<FunctionWhere> {
+  static void mapping(IO &IO, FunctionWhere &W) {
+    IO.mapOptional("Parameters", W.Parameters);
+  }
+};
+
 template <> struct MappingTraits<Function> {
   static void mapping(IO &IO, Function &F) {
     IO.mapRequired("Name", F.Name);
+    IO.mapOptional("Where", F.Where);
     IO.mapOptional("Parameters", F.Params);
     IO.mapOptional("Nullability", F.Nullability);
     IO.mapOptional("NullabilityOfRet", F.NullabilityOfRet, std::nullopt);
@@ -1137,6 +1151,12 @@ class YAMLConverter {
     }
 
     for (const auto &CXXMethod : T.Methods) {
+      if (CXXMethod.Where && CXXMethod.Where->Parameters) {
+        emitError(
+            "'Where.Parameters' is not supported by binary API notes yet");
+        continue;
+      }
+
       CXXMethodInfo MI;
       convertFunction(CXXMethod, MI);
       Writer.addCXXMethod(TagCtxID, CXXMethod.Name, MI, SwiftVersion);
@@ -1210,6 +1230,12 @@ class YAMLConverter {
     // Write all global functions.
     llvm::StringSet<> KnownFunctions;
     for (const auto &Function : TLItems.Functions) {
+      if (Function.Where && Function.Where->Parameters) {
+        emitError(
+            "'Where.Parameters' is not supported by binary API notes yet");
+        continue;
+      }
+
       // Check for duplicate global functions.
       if (!KnownFunctions.insert(Function.Name).second) {
         emitError(llvm::Twine("multiple definitions of global function '") +
diff --git 
a/clang/test/APINotes/Inputs/Headers/WhereParametersMapElement.apinotes 
b/clang/test/APINotes/Inputs/Headers/WhereParametersMapElement.apinotes
new file mode 100644
index 0000000000000..13d5d0e73378d
--- /dev/null
+++ b/clang/test/APINotes/Inputs/Headers/WhereParametersMapElement.apinotes
@@ -0,0 +1,8 @@
+---
+Name: WhereParametersMapElement
+Functions:
+- Name: makeWidget
+  Where:
+    Parameters:
+      - Type: int
+  SwiftName: makeWidget(_:)
diff --git 
a/clang/test/APINotes/Inputs/Headers/WhereParametersMethodWhereSequence.apinotes
 
b/clang/test/APINotes/Inputs/Headers/WhereParametersMethodWhereSequence.apinotes
new file mode 100644
index 0000000000000..f55d7c1577b53
--- /dev/null
+++ 
b/clang/test/APINotes/Inputs/Headers/WhereParametersMethodWhereSequence.apinotes
@@ -0,0 +1,9 @@
+---
+Name: WhereParametersMethodWhereSequence
+Tags:
+- Name: Widget
+  Methods:
+  - Name: setValue
+    Where:
+      - Parameters:
+        - int
diff --git 
a/clang/test/APINotes/Inputs/Headers/WhereParametersMissingName.apinotes 
b/clang/test/APINotes/Inputs/Headers/WhereParametersMissingName.apinotes
new file mode 100644
index 0000000000000..dd2ee3ed7fa03
--- /dev/null
+++ b/clang/test/APINotes/Inputs/Headers/WhereParametersMissingName.apinotes
@@ -0,0 +1,7 @@
+---
+Name: WhereParametersMissingName
+Functions:
+- Where:
+    Parameters:
+      - int
+  SwiftName: makeWidget(_:)
diff --git a/clang/test/APINotes/Inputs/Headers/WhereParametersParser.apinotes 
b/clang/test/APINotes/Inputs/Headers/WhereParametersParser.apinotes
new file mode 100644
index 0000000000000..90dfb555259a3
--- /dev/null
+++ b/clang/test/APINotes/Inputs/Headers/WhereParametersParser.apinotes
@@ -0,0 +1,50 @@
+---
+Name: WhereParametersParser
+Functions:
+- Name: makeWidget
+  Where:
+    Parameters:
+      - int
+  SwiftName: makeWidget(_:)
+- Name: makeWidget
+  Where:
+    Parameters:
+      - double
+      - const char *
+  SwiftName: makeWidget(_:_:)
+- Name: currentWidget
+  Where:
+    Parameters: []
+  SwiftName: currentWidget()
+- Name: makeWidget
+  SwiftName: makeWidget(_:)
+- Name: legacyFunction
+  Parameters:
+  - Position: 0
+    Type: int
+  SwiftName: legacyFunction(_:)
+Tags:
+- Name: Widget
+  Methods:
+  - Name: setValue
+    Where:
+      Parameters:
+        - int
+    SwiftName: setIntValue(_:)
+  - Name: setValue
+    Where:
+      Parameters:
+        - double
+        - const char *
+    SwiftName: setValue(_:_:)
+  - Name: reset
+    Where:
+      Parameters: []
+    SwiftName: reset()
+  - Name: setValue
+    SwiftName: setValue(_:)
+  - Name: legacy
+    Parameters:
+    - Position: 0
+      Type: int
+    SwiftName: legacy(_:)
diff --git a/clang/test/APINotes/Inputs/Headers/WhereParametersScalar.apinotes 
b/clang/test/APINotes/Inputs/Headers/WhereParametersScalar.apinotes
new file mode 100644
index 0000000000000..e116af3ed28be
--- /dev/null
+++ b/clang/test/APINotes/Inputs/Headers/WhereParametersScalar.apinotes
@@ -0,0 +1,7 @@
+---
+Name: WhereParametersScalar
+Functions:
+- Name: makeWidget
+  Where:
+    Parameters: int
+  SwiftName: makeWidget(_:)
diff --git 
a/clang/test/APINotes/Inputs/Headers/WhereParametersUnknownWhereKey.apinotes 
b/clang/test/APINotes/Inputs/Headers/WhereParametersUnknownWhereKey.apinotes
new file mode 100644
index 0000000000000..55d676400c23c
--- /dev/null
+++ b/clang/test/APINotes/Inputs/Headers/WhereParametersUnknownWhereKey.apinotes
@@ -0,0 +1,7 @@
+---
+Name: WhereParametersUnknownWhereKey
+Functions:
+- Name: makeWidget
+  Where:
+    ResultType: int
+  SwiftName: makeWidget(_:)
diff --git 
a/clang/test/APINotes/Inputs/Headers/WhereParametersWhereSequence.apinotes 
b/clang/test/APINotes/Inputs/Headers/WhereParametersWhereSequence.apinotes
new file mode 100644
index 0000000000000..3ba8a5295e29b
--- /dev/null
+++ b/clang/test/APINotes/Inputs/Headers/WhereParametersWhereSequence.apinotes
@@ -0,0 +1,8 @@
+---
+Name: WhereParametersWhereSequence
+Functions:
+- Name: makeWidget
+  Where:
+    - Parameters:
+        - int
+  SwiftName: makeWidget(_:)
diff --git a/clang/test/APINotes/where-parameters-yaml.test 
b/clang/test/APINotes/where-parameters-yaml.test
new file mode 100644
index 0000000000000..0c657ac0e15ea
--- /dev/null
+++ b/clang/test/APINotes/where-parameters-yaml.test
@@ -0,0 +1,56 @@
+RUN: apinotes-test %S/Inputs/Headers/WhereParametersParser.apinotes | 
FileCheck %s
+RUN: apinotes-test %S/Inputs/Headers/WhereParametersMissingName.apinotes 2>&1 
| FileCheck %s --check-prefix=MISSING-NAME
+RUN: apinotes-test %S/Inputs/Headers/WhereParametersWhereSequence.apinotes 
2>&1 | FileCheck %s --check-prefix=WHERE-SEQUENCE
+RUN: apinotes-test %S/Inputs/Headers/WhereParametersScalar.apinotes 2>&1 | 
FileCheck %s --check-prefix=PARAMETERS-SCALAR
+RUN: apinotes-test %S/Inputs/Headers/WhereParametersMapElement.apinotes 2>&1 | 
FileCheck %s --check-prefix=PARAMETERS-MAP-ELEMENT
+RUN: apinotes-test %S/Inputs/Headers/WhereParametersUnknownWhereKey.apinotes 
2>&1 | FileCheck %s --check-prefix=UNKNOWN-WHERE-KEY
+RUN: apinotes-test 
%S/Inputs/Headers/WhereParametersMethodWhereSequence.apinotes 2>&1 | FileCheck 
%s --check-prefix=METHOD-WHERE-SEQUENCE
+
+CHECK:      Name:            WhereParametersParser
+CHECK:      Functions:
+CHECK:      - Name:            makeWidget
+CHECK-NEXT:   Where:
+CHECK-NEXT:     Parameters:
+CHECK-NEXT:       - int
+CHECK:      - Name:            makeWidget
+CHECK-NEXT:   Where:
+CHECK-NEXT:     Parameters:
+CHECK-NEXT:       - double
+CHECK-NEXT:       - 'const char *'
+CHECK:      - Name:            currentWidget
+CHECK-NEXT:   Where:
+CHECK-NEXT:     Parameters:      []
+CHECK:      - Name:            makeWidget
+CHECK-NEXT:   SwiftName:       'makeWidget(_:)'
+CHECK:      - Name:            legacyFunction
+CHECK-NEXT:   Parameters:
+CHECK-NEXT:     - Position:        0
+CHECK-NEXT:       Type:            int
+CHECK:      Tags:
+CHECK:      - Name:            Widget
+CHECK:      Methods:
+CHECK:      - Name:            setValue
+CHECK-NEXT:   Where:
+CHECK-NEXT:     Parameters:
+CHECK-NEXT:       - int
+CHECK:      - Name:            setValue
+CHECK-NEXT:   Where:
+CHECK-NEXT:     Parameters:
+CHECK-NEXT:       - double
+CHECK-NEXT:       - 'const char *'
+CHECK:      - Name:            reset
+CHECK-NEXT:   Where:
+CHECK-NEXT:     Parameters:      []
+CHECK:      - Name:            setValue
+CHECK-NEXT:   SwiftName:       'setValue(_:)'
+CHECK:      - Name:            legacy
+CHECK-NEXT:   Parameters:
+CHECK-NEXT:     - Position:        0
+CHECK-NEXT:       Type:            int
+
+MISSING-NAME: missing required key 'Name'
+WHERE-SEQUENCE: not a mapping
+PARAMETERS-SCALAR: not a sequence
+PARAMETERS-MAP-ELEMENT: unexpected scalar
+UNKNOWN-WHERE-KEY: unknown key 'ResultType'
+METHOD-WHERE-SEQUENCE: not a mapping

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

Reply via email to