Author: StoeckOverflow Date: 2026-08-13T11:52:13Z New Revision: e67c6a8316dffc0aab581f773f189bfd6273f0ef
URL: https://github.com/llvm/llvm-project/commit/e67c6a8316dffc0aab581f773f189bfd6273f0ef DIFF: https://github.com/llvm/llvm-project/commit/e67c6a8316dffc0aab581f773f189bfd6273f0ef.diff LOG: [APINotes] Strip selector volatile and nested nullability from parameter selectors (#215266) Address @Xazax-hun's comments about volatile and nullability stripping from https://github.com/llvm/llvm-project/pull/213043#pullrequestreview-4830763715. This strips top-level `volatile` like top-level `const` when building `Where.Parameters` selector spellings, and recursively strips nullability through pointer-like layers such as `int * _Nullable * _Nullable`. This is a prequel PR to https://github.com/llvm/llvm-project/pull/213043. Reviewers: @Xazax-hun @j-hui @egorzhdan Added: Modified: clang/include/clang/AST/TypeBase.h clang/lib/AST/Type.cpp clang/lib/Sema/SemaAPINotes.cpp clang/test/APINotes/Inputs/Headers/WhereParametersSema.apinotes clang/test/APINotes/Inputs/Headers/WhereParametersSema.h clang/test/APINotes/where-parameters-sema.cpp Removed: ################################################################################ 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
