diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index ef626fb7ae02d..b1dd8f644f9cc 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -9214,10 +9214,28 @@ void ClangImporter::Implementation::swiftify(FuncDecl *MappedDecl) { attachMacro = true; printer.printAvailability(); printer.printTypeMapping(typeMapping); + } - if (attachMacro) - importNontrivialAttribute(MappedDecl, MacroString); + if (attachMacro) { + if (clang::RawComment *raw = + getClangASTContext().getRawCommentForDeclNoCache(ClangDecl)) { + // swift::RawDocCommentAttr doesn't contain its text directly, but instead + // references the source range of the parsed comment. Instead of creating + // a new source file just to parse the doc comment, we can add the + // comment to the macro invocation attribute, which the macro has access + // to. Waiting until we know that the macro will be attached before + // emitting the comment to the string, despite the comment occurring + // first, avoids copying a bunch of potentially long comments for nodes + // that don't end up with wrappers. + auto commentString = + raw->getRawText(getClangASTContext().getSourceManager()); + importNontrivialAttribute(MappedDecl, + (commentString + "\n" + MacroString).str()); + } else { + importNontrivialAttribute(MappedDecl, MacroString); + } + } } static bool isUsingMacroName(clang::SourceManager &SM, diff --git a/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift b/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift index df0e992b2d501..b9f7504bf5010 100644 --- a/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift +++ b/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift @@ -1554,6 +1554,7 @@ public struct SwiftifyImportMacro: PeerMacro { + availabilityAttr + lifetimeAttrs + disfavoredOverload) + .with(\.leadingTrivia, node.leadingTrivia + .docLineComment("/// This is an auto-generated wrapper for safer interop\n")) return [DeclSyntax(newFunc)] } catch let error as DiagnosticError { context.diagnose( diff --git a/test/Interop/C/swiftify-import/Inputs/comments.h b/test/Interop/C/swiftify-import/Inputs/comments.h new file mode 100644 index 0000000000000..900e240b070ef --- /dev/null +++ b/test/Interop/C/swiftify-import/Inputs/comments.h @@ -0,0 +1,30 @@ +#pragma once + +#define __counted_by(x) __attribute__((__counted_by__(x))) + +void begin(); + +// line comment +void lineComment(int len, int * __counted_by(len) p); + +/// line doc comment +/// +/// Here's a more complete description. +/// +/// @param len the buffer length +/// @param p the buffer +void lineDocComment(int len, int * __counted_by(len) p); + +/* + block comment + */ +void blockComment(int len, int * __counted_by(len) p); + +/** + * block doc comment + * + * NB: it's very important to pass the correct length to this function + * @param len don't mess this one up + * @param p some integers to play with + */ +void blockDocComment(int len, int * __counted_by(len) p); diff --git a/test/Interop/C/swiftify-import/Inputs/counted-by-lifetimebound.h b/test/Interop/C/swiftify-import/Inputs/counted-by-lifetimebound.h index d5f9f6059c9f5..2bfce825fda85 100644 --- a/test/Interop/C/swiftify-import/Inputs/counted-by-lifetimebound.h +++ b/test/Interop/C/swiftify-import/Inputs/counted-by-lifetimebound.h @@ -15,7 +15,4 @@ int * __counted_by(len) _Nonnull nonnull(int len, int len2, int * __counted_by(l int * __counted_by(len) _Nullable nullable(int len, int len2, int * __counted_by(len2) __lifetimebound _Nullable p); -typedef struct foo opaque_t; -opaque_t * __counted_by(len) opaque(int len, int len2, opaque_t * __counted_by(len2) __lifetimebound p); - int * __counted_by(len) noncountedLifetime(int len, int * __lifetimebound p); diff --git a/test/Interop/C/swiftify-import/Inputs/module.modulemap b/test/Interop/C/swiftify-import/Inputs/module.modulemap index bbbd7f133f7f0..9e4d82f3ef71c 100644 --- a/test/Interop/C/swiftify-import/Inputs/module.modulemap +++ b/test/Interop/C/swiftify-import/Inputs/module.modulemap @@ -22,3 +22,7 @@ module CountedByLifetimeboundClang { header "counted-by-lifetimebound.h" export * } +module CommentsClang { + header "comments.h" + export * +} diff --git a/test/Interop/C/swiftify-import/comments.swift b/test/Interop/C/swiftify-import/comments.swift new file mode 100644 index 0000000000000..fbb87b26e3823 --- /dev/null +++ b/test/Interop/C/swiftify-import/comments.swift @@ -0,0 +1,52 @@ +// REQUIRES: swift_feature_SafeInteropWrappers + +// RUN: %target-swift-ide-test -print-module -module-to-print=CommentsClang -plugin-path %swift-plugin-dir -I %S/Inputs -source-filename=x -enable-experimental-feature SafeInteropWrappers | %FileCheck %s --strict-whitespace --match-full-lines + +// Check that doc comments are carried over from clang to the safe macro expansion. + +// CHECK:func begin() +// CHECK-NEXT:func lineComment(_ len: Int32, _ p: UnsafeMutablePointer!) + +// CHECK-NEXT:/// line doc comment +// CHECK-NEXT:/// +// CHECK-NEXT:/// Here's a more complete description. +// CHECK-NEXT:/// +// CHECK-NEXT:/// @param len the buffer length +// CHECK-NEXT:/// @param p the buffer +// CHECK-NEXT:func lineDocComment(_ len: Int32, _ p: UnsafeMutablePointer!) + +// CHECK-NEXT:func blockComment(_ len: Int32, _ p: UnsafeMutablePointer!) + +// CHECK-NEXT:/** +// CHECK-NEXT: * block doc comment +// CHECK-NEXT: * +// CHECK-NEXT: * NB: it's very important to pass the correct length to this function +// CHECK-NEXT: * @param len don't mess this one up +// CHECK-NEXT: * @param p some integers to play with +// CHECK-NEXT: */ +// CHECK-NEXT:func blockDocComment(_ len: Int32, _ p: UnsafeMutablePointer!) + +// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop +// CHECK-NEXT:@_alwaysEmitIntoClient public func blockComment(_ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT:/** +// CHECK-NEXT: * block doc comment +// CHECK-NEXT: * +// CHECK-NEXT: * NB: it's very important to pass the correct length to this function +// CHECK-NEXT: * @param len don't mess this one up +// CHECK-NEXT: * @param p some integers to play with +// CHECK-NEXT: */ +// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop +// CHECK-NEXT:@_alwaysEmitIntoClient public func blockDocComment(_ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop +// CHECK-NEXT:@_alwaysEmitIntoClient public func lineComment(_ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT:/// line doc comment +// CHECK-NEXT:/// +// CHECK-NEXT:/// Here's a more complete description. +// CHECK-NEXT:/// +// CHECK-NEXT:/// @param len the buffer length +// CHECK-NEXT:/// @param p the buffer +// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop +// CHECK-NEXT:@_alwaysEmitIntoClient public func lineDocComment(_ p: UnsafeMutableBufferPointer) diff --git a/test/Interop/C/swiftify-import/counted-by-lifetimebound.swift b/test/Interop/C/swiftify-import/counted-by-lifetimebound.swift index da817761f5a73..2307998931356 100644 --- a/test/Interop/C/swiftify-import/counted-by-lifetimebound.swift +++ b/test/Interop/C/swiftify-import/counted-by-lifetimebound.swift @@ -11,35 +11,42 @@ import CountedByLifetimeboundClang -// CHECK: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) +// CHECK: /// This is an auto-generated wrapper for safer interop +// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(copy p) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func complexExpr(_ len: Int32, _ offset: Int32, _ len2: Int32, _ p: inout MutableSpan) -> MutableSpan +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(borrow p) // CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func noncountedLifetime(_ len: Int32, _ p: UnsafeMutablePointer!) -> MutableSpan +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(copy p) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func nonnull(_ len: Int32, _ p: inout MutableSpan) -> MutableSpan +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(copy p) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func nullUnspecified(_ len: Int32, _ p: inout MutableSpan) -> MutableSpan +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(copy p) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func nullable(_ len: Int32, _ p: inout MutableSpan?) -> MutableSpan? +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(copy p) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func shared(_ len: Int32, _ p: inout MutableSpan) -> MutableSpan +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(copy p) // CHECK-NEXT: @lifetime(p: copy p) diff --git a/test/Interop/C/swiftify-import/counted-by-noescape.swift b/test/Interop/C/swiftify-import/counted-by-noescape.swift index f0ffb4a660fa0..d230834b58679 100644 --- a/test/Interop/C/swiftify-import/counted-by-noescape.swift +++ b/test/Interop/C/swiftify-import/counted-by-noescape.swift @@ -11,33 +11,52 @@ import CountedByNoEscapeClang -// CHECK: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) +// CHECK: /// This is an auto-generated wrapper for safer interop +// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(_param1: copy _param1) // CHECK-NEXT: @_alwaysEmitIntoClient public func anonymous(_ _param1: inout MutableSpan?) -// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop +// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func complexExpr(_ len: Int32, _ offset: Int32, _ p: inout MutableSpan) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func nonnull(_ p: inout MutableSpan) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func nullUnspecified(_ p: inout MutableSpan) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func nullable(_ p: inout MutableSpan?) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(copy p) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func returnLifetimeBound(_ len1: Int32, _ p: inout MutableSpan) -> MutableSpan + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func returnPointer(_ len: Int32) -> UnsafeMutableBufferPointer + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(p1: copy p1) // CHECK-NEXT: @lifetime(p2: copy p2) // CHECK-NEXT: @_alwaysEmitIntoClient public func shared(_ len: Int32, _ p1: inout MutableSpan, _ p2: inout MutableSpan) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func simple(_ p: inout MutableSpan) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func swiftAttr(_ p: inout MutableSpan) diff --git a/test/Interop/C/swiftify-import/counted-by.swift b/test/Interop/C/swiftify-import/counted-by.swift index d77ce9d33475f..6623b7ccf9650 100644 --- a/test/Interop/C/swiftify-import/counted-by.swift +++ b/test/Interop/C/swiftify-import/counted-by.swift @@ -10,23 +10,59 @@ import CountedByClang -// CHECK: @_alwaysEmitIntoClient public func bitshift(_ m: Int32, _ n: Int32, _ o: Int32, _ p: UnsafeMutableBufferPointer) + +// CHECK: /// This is an auto-generated wrapper for safer interop +// CHECK-NEXT: @_alwaysEmitIntoClient public func bitshift(_ m: Int32, _ n: Int32, _ o: Int32, _ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func bitwise(_ m: Int32, _ n: Int32, _ o: Int32, _ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func complexExpr(_ len: Int{{.*}}, _ offset: Int{{.*}}, _ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func constFloatCastedToInt(_ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func constInt(_ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func nonnull(_ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func nullUnspecified(_ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func nullable(_ p: UnsafeMutableBufferPointer?) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func offByOne(_ len: Int32, _ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func offBySome(_ len: Int32, _ offset: Int32, _ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func returnPointer(_ len: Int{{.*}}) -> UnsafeMutableBufferPointer + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func scalar(_ m: Int32, _ n: Int32, _ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func shared(_ len: Int{{.*}}, _ p1: UnsafeMutableBufferPointer, _ p2: UnsafeMutableBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func simple(_ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func simpleFlipped(_ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func sizeofParam(_ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func sizeofType(_ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func swiftAttr(_ p: UnsafeMutableBufferPointer) @inlinable diff --git a/test/Interop/C/swiftify-import/sized-by-lifetimebound.swift b/test/Interop/C/swiftify-import/sized-by-lifetimebound.swift index d6830736ac4a1..8447f17211f47 100644 --- a/test/Interop/C/swiftify-import/sized-by-lifetimebound.swift +++ b/test/Interop/C/swiftify-import/sized-by-lifetimebound.swift @@ -11,34 +11,42 @@ import SizedByLifetimeboundClang -// CHECK: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) +// CHECK: /// This is an auto-generated wrapper for safer interop +// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func complexExpr(_ len: Int32, _ offset: Int32, _ len2: Int32, _ p: RawSpan) -> RawSpan +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func nonnull(_ len: Int32, _ p: RawSpan) -> RawSpan +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(borrow p) // CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func nonsizedLifetime(_ len: Int32, _ p: UnsafeRawPointer!) -> RawSpan +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func nullUnspecified(_ len: Int32, _ p: RawSpan) -> RawSpan +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func nullable(_ len: Int32, _ p: RawSpan?) -> RawSpan? +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func opaque(_ len: Int32, _ p: RawSpan) -> RawSpan +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func shared(_ len: Int32, _ p: RawSpan) -> RawSpan +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func simple(_ len: Int32, _ p: RawSpan) -> RawSpan diff --git a/test/Interop/C/swiftify-import/sized-by-noescape.swift b/test/Interop/C/swiftify-import/sized-by-noescape.swift index c2ff0a5647b3a..e8372becc5321 100644 --- a/test/Interop/C/swiftify-import/sized-by-noescape.swift +++ b/test/Interop/C/swiftify-import/sized-by-noescape.swift @@ -9,21 +9,39 @@ // Check that ClangImporter correctly infers and expands @_SwiftifyImport macros for functions with __sized_by __noescape parameters. import SizedByNoEscapeClang -// CHECK: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) + +// CHECK: /// This is an auto-generated wrapper for safer interop +// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func complexExpr(_ len: Int{{.*}}, _ offset: Int{{.*}}, _ p: RawSpan) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func nonnull(_ p: RawSpan) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func nullUnspecified(_ p: RawSpan) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func nullable(_ p: RawSpan?) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func opaque(_ p: RawSpan) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func returnPointer(_ len: Int{{.*}}) -> UnsafeRawBufferPointer + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func shared(_ len: Int{{.*}}, _ p1: RawSpan, _ p2: RawSpan) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func simple(_ p: RawSpan) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func swiftAttr(_ p: RawSpan) diff --git a/test/Interop/C/swiftify-import/sized-by.swift b/test/Interop/C/swiftify-import/sized-by.swift index b9435f2d89ab9..316fc0e6c791f 100644 --- a/test/Interop/C/swiftify-import/sized-by.swift +++ b/test/Interop/C/swiftify-import/sized-by.swift @@ -9,14 +9,32 @@ // Check that ClangImporter correctly infers and expands @_SwiftifyImport macros for functions with __sized_by parameters. import SizedByClang -// CHECK: @_alwaysEmitIntoClient public func complexExpr(_ len: Int{{.*}}, _ offset: Int{{.*}}, _ p: UnsafeMutableRawBufferPointer) + +// CHECK: /// This is an auto-generated wrapper for safer interop +// CHECK-NEXT: @_alwaysEmitIntoClient public func complexExpr(_ len: Int{{.*}}, _ offset: Int{{.*}}, _ p: UnsafeMutableRawBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func nonnull(_ p: UnsafeMutableRawBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func nullUnspecified(_ p: UnsafeMutableRawBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func nullable(_ p: UnsafeMutableRawBufferPointer?) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func opaque(_ p: UnsafeRawBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func returnPointer(_ len: Int{{.*}}) -> UnsafeMutableRawBufferPointer + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func shared(_ len: Int{{.*}}, _ p1: UnsafeMutableRawBufferPointer, _ p2: UnsafeMutableRawBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func simple(_ p: UnsafeMutableRawBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func swiftAttr(_ p: UnsafeMutableRawBufferPointer) @inlinable diff --git a/test/Interop/Cxx/stdlib/std-span-interface.swift b/test/Interop/Cxx/stdlib/std-span-interface.swift index 9a9f761a708f1..5b8704e891c45 100644 --- a/test/Interop/Cxx/stdlib/std-span-interface.swift +++ b/test/Interop/Cxx/stdlib/std-span-interface.swift @@ -23,70 +23,112 @@ import CxxStdlib // CHECK-NEXT: func funcWithSafeWrapper3(_ v: borrowing VecOfInt) -> ConstSpanOfInt // CHECK: struct X { // CHECK-NEXT: init() +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @_alwaysEmitIntoClient public mutating func methodWithSafeWrapper(_ s: Span) // CHECK-NEXT: mutating func methodWithSafeWrapper(_ s: ConstSpanOfInt) // CHECK-NEXT: } // CHECK: struct SpanWithoutTypeAlias { // CHECK-NEXT: init() +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(borrow self) // CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public mutating func bar() -> Span // CHECK-NEXT: mutating func bar() -> std.{{.*}}span<__cxxConst, _C{{.*}}_{{.*}}> +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @_alwaysEmitIntoClient public mutating func foo(_ s: Span) // CHECK-NEXT: mutating func foo(_ s: std.{{.*}}span<__cxxConst, _C{{.*}}_{{.*}}>) // CHECK-NEXT: } -// CHECK: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) +// CHECK: /// This is an auto-generated wrapper for safer interop +// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(s: copy s) // CHECK-NEXT: @_alwaysEmitIntoClient public func FuncWithMutableSafeWrapper(_ s: inout MutableSpan) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(copy s) // CHECK-NEXT: @lifetime(s: copy s) // CHECK-NEXT: @_alwaysEmitIntoClient public func FuncWithMutableSafeWrapper2(_ s: inout MutableSpan) -> MutableSpan + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(borrow v) // CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func FuncWithMutableSafeWrapper3(_ v: inout VecOfInt) -> MutableSpan + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(copy p) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func MixedFuncWithMutableSafeWrapper1(_ p: inout MutableSpan) -> MutableSpan + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(borrow v) // CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func MixedFuncWithMutableSafeWrapper2(_ v: inout VecOfInt, _ len: Int32) -> MutableSpan + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(s: copy s) // CHECK-NEXT: @_alwaysEmitIntoClient public func MixedFuncWithMutableSafeWrapper3(_ s: inout MutableSpan, _ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(s: copy s) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func MixedFuncWithMutableSafeWrapper4(_ s: inout MutableSpan, _ p: inout MutableSpan) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func MixedFuncWithMutableSafeWrapper5(_ s: SpanOfInt, _ p: inout MutableSpan) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func MixedFuncWithMutableSafeWrapper6(_ s: SpanOfInt, _ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func MixedFuncWithMutableSafeWrapper7(_ p: UnsafeMutableBufferPointer) -> SpanOfInt -// CHECK: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) + +// CHECK: /// This is an auto-generated wrapper for safer interop +// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func funcWithSafeWrapper(_ s: Span) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(copy s) // CHECK-NEXT: @_alwaysEmitIntoClient public func funcWithSafeWrapper2(_ s: Span) -> Span + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(borrow v) // CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func funcWithSafeWrapper3(_ v: borrowing VecOfInt) -> Span + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func mixedFuncWithSafeWrapper1(_ p: Span) -> Span + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(borrow v) // CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func mixedFuncWithSafeWrapper2(_ v: borrowing VecOfInt, _ len: Int32) -> Span + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func mixedFuncWithSafeWrapper3(_ s: Span, _ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func mixedFuncWithSafeWrapper4(_ s: Span, _ p: Span) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func mixedFuncWithSafeWrapper5(_ s: ConstSpanOfInt, _ p: Span) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func mixedFuncWithSafeWrapper6(_ s: ConstSpanOfInt, _ p: UnsafeMutableBufferPointer) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func mixedFuncWithSafeWrapper7(_ p: UnsafeBufferPointer) -> ConstSpanOfInt diff --git a/test/SourceKit/CursorInfo/cursor_doc_comment_from_clang_safe_wrapper.swift b/test/SourceKit/CursorInfo/cursor_doc_comment_from_clang_safe_wrapper.swift new file mode 100644 index 0000000000000..a9a69647c73ce --- /dev/null +++ b/test/SourceKit/CursorInfo/cursor_doc_comment_from_clang_safe_wrapper.swift @@ -0,0 +1,105 @@ +// REQUIRES: swift_feature_SafeInteropWrappers + +// RUN: %empty-directory(%t) +// RUN: split-file --leading-lines %s %t + +//--- header.h + +/** This comment contains `markup`. + * + * - And a list + */ +void testCDecl(const int * __attribute__((__counted_by__(len))) __attribute__((noescape)) p, int len); + +//--- module.modulemap + +module MyClangModule { header "header.h" } + +//--- test.swift + +import MyClangModule + +func test(_ s: Span) { + // RUN: %sourcekitd-test -req=cursor -pos=%(line + 1):4 -req-opts=retrieve_symbol_graph=1 %s -- %s -I %t -enable-experimental-feature SafeInteropWrappers | %FileCheck %s + testCDecl(s) +} + +// CHECK-LABEL: DOC COMMENT +// CHECK: This comment contains `markup`. +// CHECK: - And a list +// CHECK-LABEL: DOC COMMENT XML +// CHECK: testCDecl(_:)s:SC9testCDeclyys4SpanVys5Int32VGF@available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) +// CHECK-NEXT: public func testCDecl(_ p: Span<Int32>)This comment contains markup. *And a listThis is an auto-generated wrapper for safer interop + +// CHECK-LABEL: SYMBOL GRAPH BEGIN +// CHECK: "docComment": { +// CHECK-NEXT: "lines": [ +// CHECK-NEXT: { +// CHECK-NEXT: "range": { +// CHECK-NEXT: "end": { +// CHECK-NEXT: "character": 35, +// CHECK-NEXT: "line": 0 +// CHECK-NEXT: }, +// CHECK-NEXT: "start": { +// CHECK-NEXT: "character": 4, +// CHECK-NEXT: "line": 0 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "text": "This comment contains `markup`." +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "range": { +// CHECK-NEXT: "end": { +// CHECK-NEXT: "character": 2, +// CHECK-NEXT: "line": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "start": { +// CHECK-NEXT: "character": 1, +// CHECK-NEXT: "line": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "text": "*" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "range": { +// CHECK-NEXT: "end": { +// CHECK-NEXT: "character": 15, +// CHECK-NEXT: "line": 2 +// CHECK-NEXT: }, +// CHECK-NEXT: "start": { +// CHECK-NEXT: "character": 1, +// CHECK-NEXT: "line": 2 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "text": "* - And a list" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "range": { +// CHECK-NEXT: "end": { +// CHECK-NEXT: "character": 1, +// CHECK-NEXT: "line": 3 +// CHECK-NEXT: }, +// CHECK-NEXT: "start": { +// CHECK-NEXT: "character": 1, +// CHECK-NEXT: "line": 3 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "text": "" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "range": { +// CHECK-NEXT: "end": { +// CHECK-NEXT: "character": 55, +// CHECK-NEXT: "line": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "start": { +// CHECK-NEXT: "character": 4, +// CHECK-NEXT: "line": 4 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "text": "This is an auto-generated wrapper for safer interop" +// CHECK-NEXT: } +// CHECK-NEXT: ], +// CHECK-NEXT: "module": "MyClangModule", +// CHECK-NEXT: "uri": "file://@__swiftmacro_So9testCDecl15_SwiftifyImportfMp_.swift" +// CHECK-NEXT: }