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

>From 22253b63f0a7827c58fec6499bf49800ffb7146a Mon Sep 17 00:00:00 2001
From: stoeckoverflow <[email protected]>
Date: Thu, 13 Aug 2026 12:59:16 +0200
Subject: [PATCH] [APINotes] Strip selector volatile and nested nullability

---
 clang/include/clang/AST/TypeBase.h            |  3 ++
 clang/lib/AST/Type.cpp                        | 26 ++++++++++++
 clang/lib/Sema/SemaAPINotes.cpp               | 10 +----
 .../Headers/WhereParametersSema.apinotes      | 40 +++++++++++++++++++
 .../Inputs/Headers/WhereParametersSema.h      |  9 +++++
 clang/test/APINotes/where-parameters-sema.cpp | 32 +++++++++++++++
 6 files changed, 112 insertions(+), 8 deletions(-)

diff --git a/clang/include/clang/AST/TypeBase.h 
b/clang/include/clang/AST/TypeBase.h
index a344402e90c17..eb05a068934ea 100644
--- a/clang/include/clang/AST/TypeBase.h
+++ b/clang/include/clang/AST/TypeBase.h
@@ -1635,6 +1635,9 @@ class QualType {
   /// Strip Objective-C "__kindof" types from the given type.
   QualType stripObjCKindOfType(const ASTContext &ctx) const;
 
+  /// Strip nullability attributes from the given type.
+  QualType stripNullability(const ASTContext &ctx) const;
+
   /// Remove all qualifiers including _Atomic.
   ///
   /// Like getUnqualifiedType(), the type may still be qualified if it is a
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index cc5b7d944129b..5069b587c1f8b 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -1639,6 +1639,24 @@ struct SubstObjCTypeArgsVisitor
   }
 };
 
+struct StripNullabilityTypeVisitor
+    : public SimpleTransformVisitor<StripNullabilityTypeVisitor> {
+  using BaseType = SimpleTransformVisitor<StripNullabilityTypeVisitor>;
+
+  explicit StripNullabilityTypeVisitor(ASTContext &ctx) : BaseType(ctx) {}
+
+  QualType VisitAttributedType(const AttributedType *attrType) {
+    QualType type(attrType, 0);
+    if (AttributedType::stripOuterNullability(type)) {
+      while (AttributedType::stripOuterNullability(type)) {
+      }
+      return BaseType::recurse(type);
+    }
+
+    return BaseType::VisitAttributedType(attrType);
+  }
+};
+
 struct StripObjCKindOfTypeVisitor
     : public SimpleTransformVisitor<StripObjCKindOfTypeVisitor> {
   using BaseType = SimpleTransformVisitor<StripObjCKindOfTypeVisitor>;
@@ -1716,6 +1734,14 @@ QualType QualType::stripObjCKindOfType(const ASTContext 
&constCtx) const {
   return visitor.recurse(*this);
 }
 
+QualType QualType::stripNullability(const ASTContext &constCtx) const {
+  // FIXME: SimpleTransformVisitor currently takes a non-const ASTContext
+  // because some rebuild paths use non-const ASTContext factory APIs.
+  auto &ctx = const_cast<ASTContext &>(constCtx);
+  StripNullabilityTypeVisitor visitor(ctx);
+  return visitor.recurse(*this);
+}
+
 QualType QualType::getAtomicUnqualifiedType() const {
   QualType T = *this;
   if (const auto AT = T.getTypePtr()->getAs<AtomicType>())
diff --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp
index 2499104d697a8..78153d9ddf39d 100644
--- a/clang/lib/Sema/SemaAPINotes.cpp
+++ b/clang/lib/Sema/SemaAPINotes.cpp
@@ -1001,13 +1001,6 @@ UnwindTagContext(TagDecl *DC, api_notes::APINotesManager 
&APINotes) {
   return std::nullopt;
 }
 
-static void stripAPINotesParameterNullability(QualType &ParamType) {
-  while (true) {
-    if (!AttributedType::stripOuterNullability(ParamType))
-      return;
-  }
-}
-
 namespace clang {
 struct APINotesParameterSelector {
   SmallVector<std::string, 4> Parameters;
@@ -1050,7 +1043,8 @@ static std::string getAPINotesParameterSelectorSpelling(
     ParamType = ParamType.getDesugaredType(Context);
 
   ParamType.removeLocalConst();
-  stripAPINotesParameterNullability(ParamType);
+  ParamType.removeLocalVolatile();
+  ParamType = ParamType.stripNullability(Context);
 
   return ParamType.getAsString(Policy);
 }
diff --git a/clang/test/APINotes/Inputs/Headers/WhereParametersSema.apinotes 
b/clang/test/APINotes/Inputs/Headers/WhereParametersSema.apinotes
index 7ffee9223f8c3..9287318253295 100644
--- a/clang/test/APINotes/Inputs/Headers/WhereParametersSema.apinotes
+++ b/clang/test/APINotes/Inputs/Headers/WhereParametersSema.apinotes
@@ -64,6 +64,46 @@ Functions:
     Parameters:
     - int
   SwiftName: constValueGlobal(_:)
+- Name: volatileValueGlobal
+  Where:
+    Parameters:
+    - int
+  SwiftName: volatileValueGlobal(_:)
+- Name: pointerVolatileGlobal
+  Where:
+    Parameters:
+    - 'int *'
+  SwiftName: pointerVolatileGlobal(_:)
+- Name: pointeeVolatileMismatchGlobal
+  Where:
+    Parameters:
+    - 'int *'
+  SwiftName: shouldNotApplyPointeeVolatile(_:)
+- Name: nestedNullableGlobal
+  Where:
+    Parameters:
+    - 'int **'
+  SwiftName: nestedNullableGlobal(_:)
+- Name: nullableArrayGlobal
+  Where:
+    Parameters:
+    - 'int **'
+  SwiftName: nullableArrayGlobal(_:)
+- Name: nullableFunctionPointerItselfGlobal
+  Where:
+    Parameters:
+    - 'void (*)(int *)'
+  SwiftName: nullableFunctionPointerItselfGlobal(_:)
+- Name: nullableFunctionPointerGlobal
+  Where:
+    Parameters:
+    - 'void (*)(int *)'
+  SwiftName: nullableFunctionPointerGlobal(_:)
+- Name: nullableNonnullFunctionPointerGlobal
+  Where:
+    Parameters:
+    - 'void (*)(int *, int *)'
+  SwiftName: nullableNonnullFunctionPointerGlobal(_:)
 Namespaces:
 - Name: SelectorNamespace
   Functions:
diff --git a/clang/test/APINotes/Inputs/Headers/WhereParametersSema.h 
b/clang/test/APINotes/Inputs/Headers/WhereParametersSema.h
index 8226fa287b115..a302c5ddb18e3 100644
--- a/clang/test/APINotes/Inputs/Headers/WhereParametersSema.h
+++ b/clang/test/APINotes/Inputs/Headers/WhereParametersSema.h
@@ -22,6 +22,15 @@ void multiAliasGlobal(DeepAliasInt);
 void nullableGlobal(char * _Nonnull);
 void rawIntGlobal(int);
 void constValueGlobal(const int);
+void volatileValueGlobal(volatile int);
+void pointerVolatileGlobal(int *volatile);
+void pointeeVolatileMismatchGlobal(volatile int *);
+void nestedNullableGlobal(int * _Nullable * _Nullable);
+void nullableArrayGlobal(int * _Nullable values[4]);
+void nullableFunctionPointerItselfGlobal(void (* _Nullable callback)(int *));
+void nullableFunctionPointerGlobal(void (*callback)(int * _Nullable));
+void nullableNonnullFunctionPointerGlobal(void (*callback)(int * _Nullable,
+                                                          int * _Nonnull));
 
 namespace SelectorNamespace {
 void makeNamespaced(int);
diff --git a/clang/test/APINotes/where-parameters-sema.cpp 
b/clang/test/APINotes/where-parameters-sema.cpp
index fbb7cb45b9441..089778efc3b7e 100644
--- a/clang/test/APINotes/where-parameters-sema.cpp
+++ b/clang/test/APINotes/where-parameters-sema.cpp
@@ -10,6 +10,14 @@
 // 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 
volatileValueGlobal -x c++ | FileCheck --check-prefix=CHECK-GLOBAL-VOLATILE %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 
pointerVolatileGlobal -x c++ | FileCheck 
--check-prefix=CHECK-GLOBAL-POINTER-VOLATILE %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 
pointeeVolatileMismatchGlobal -x c++ | FileCheck 
--check-prefix=CHECK-GLOBAL-POINTEE-VOLATILE-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 
nestedNullableGlobal -x c++ | FileCheck 
--check-prefix=CHECK-GLOBAL-NESTED-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 
nullableArrayGlobal -x c++ | FileCheck 
--check-prefix=CHECK-GLOBAL-NULLABLE-ARRAY %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 
nullableFunctionPointerItselfGlobal -x c++ | FileCheck 
--check-prefix=CHECK-GLOBAL-NULLABLE-FUNCTION-POINTER-ITSELF %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 
nullableFunctionPointerGlobal -x c++ | FileCheck 
--check-prefix=CHECK-GLOBAL-NULLABLE-FUNCTION-POINTER %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 
nullableNonnullFunctionPointerGlobal -x c++ | FileCheck 
--check-prefix=CHECK-GLOBAL-NULLABLE-NONNULL-FUNCTION-POINTER %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
@@ -27,6 +35,30 @@
 
 #include "WhereParametersSema.h"
 
+// CHECK-GLOBAL-VOLATILE: FunctionDecl {{.+}} volatileValueGlobal 'void 
(volatile int)'
+// CHECK-GLOBAL-VOLATILE: SwiftNameAttr {{.+}} "volatileValueGlobal(_:)"
+
+// CHECK-GLOBAL-POINTER-VOLATILE: FunctionDecl {{.+}} pointerVolatileGlobal 
'void (int *volatile)'
+// CHECK-GLOBAL-POINTER-VOLATILE: SwiftNameAttr {{.+}} 
"pointerVolatileGlobal(_:)"
+
+// CHECK-GLOBAL-POINTEE-VOLATILE-MISMATCH: FunctionDecl {{.+}} 
pointeeVolatileMismatchGlobal 'void (volatile int *)'
+// CHECK-GLOBAL-POINTEE-VOLATILE-MISMATCH-NOT: SwiftNameAttr
+
+// CHECK-GLOBAL-NESTED-NULLABILITY: FunctionDecl {{.+}} nestedNullableGlobal 
'void (int * _Nullable * _Nullable)'
+// CHECK-GLOBAL-NESTED-NULLABILITY: SwiftNameAttr {{.+}} 
"nestedNullableGlobal(_:)"
+
+// CHECK-GLOBAL-NULLABLE-ARRAY: FunctionDecl {{.+}} nullableArrayGlobal 'void 
(int * _Nullable *)'
+// CHECK-GLOBAL-NULLABLE-ARRAY: SwiftNameAttr {{.+}} "nullableArrayGlobal(_:)"
+
+// CHECK-GLOBAL-NULLABLE-FUNCTION-POINTER-ITSELF: FunctionDecl {{.+}} 
nullableFunctionPointerItselfGlobal 'void (void (* _Nullable)(int *))'
+// CHECK-GLOBAL-NULLABLE-FUNCTION-POINTER-ITSELF: SwiftNameAttr {{.+}} 
"nullableFunctionPointerItselfGlobal(_:)"
+
+// CHECK-GLOBAL-NULLABLE-FUNCTION-POINTER: FunctionDecl {{.+}} 
nullableFunctionPointerGlobal 'void (void (*)(int * _Nullable))'
+// CHECK-GLOBAL-NULLABLE-FUNCTION-POINTER: SwiftNameAttr {{.+}} 
"nullableFunctionPointerGlobal(_:)"
+
+// CHECK-GLOBAL-NULLABLE-NONNULL-FUNCTION-POINTER: FunctionDecl {{.+}} 
nullableNonnullFunctionPointerGlobal 'void (void (*)(int * _Nullable, int * 
_Nonnull))'
+// CHECK-GLOBAL-NULLABLE-NONNULL-FUNCTION-POINTER: SwiftNameAttr {{.+}} 
"nullableNonnullFunctionPointerGlobal(_:)"
+
 // CHECK-GLOBAL-OVERLOADS: FunctionDecl {{.+}} makeWidget 'void (int)'
 // CHECK-GLOBAL-OVERLOADS-NEXT: ParmVarDecl {{.+}} 'int'
 // CHECK-GLOBAL-OVERLOADS-NEXT: SwiftNameAttr {{.+}} "makeIntWidget(_:)"

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

Reply via email to