Skip to content

Commit 2ab23ae

Browse files
authored
Merge pull request #75369 from swiftlang/susmonteiro/cxx-span-nonconst
[cxx-interop] Implements CxxMutableSpan, created from an UnsafeMutableBufferPointer
2 parents 7522322 + 684e9eb commit 2ab23ae

File tree

7 files changed

+461
-105
lines changed

7 files changed

+461
-105
lines changed

include/swift/AST/KnownProtocols.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ PROTOCOL(CxxSequence)
136136
PROTOCOL(CxxUniqueSet)
137137
PROTOCOL(CxxVector)
138138
PROTOCOL(CxxSpan)
139+
PROTOCOL(CxxMutableSpan)
139140
PROTOCOL(UnsafeCxxInputIterator)
140141
PROTOCOL(UnsafeCxxMutableInputIterator)
141142
PROTOCOL(UnsafeCxxRandomAccessIterator)

lib/AST/ASTContext.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1406,6 +1406,7 @@ ProtocolDecl *ASTContext::getProtocol(KnownProtocolKind kind) const {
14061406
case KnownProtocolKind::CxxUniqueSet:
14071407
case KnownProtocolKind::CxxVector:
14081408
case KnownProtocolKind::CxxSpan:
1409+
case KnownProtocolKind::CxxMutableSpan:
14091410
case KnownProtocolKind::UnsafeCxxInputIterator:
14101411
case KnownProtocolKind::UnsafeCxxMutableInputIterator:
14111412
case KnownProtocolKind::UnsafeCxxRandomAccessIterator:

lib/ClangImporter/ClangDerivedConformances.cpp

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1164,23 +1164,22 @@ void swift::conformToCxxSpanIfNeeded(ClangImporter::Implementation &impl,
11641164
if (!elementType || !sizeType)
11651165
return;
11661166

1167-
auto constPointerTypeDecl =
1168-
lookupNestedClangTypeDecl(clangDecl, "const_pointer");
1167+
auto pointerTypeDecl = lookupNestedClangTypeDecl(clangDecl, "pointer");
11691168
auto countTypeDecl = lookupNestedClangTypeDecl(clangDecl, "size_type");
11701169

1171-
if (!constPointerTypeDecl || !countTypeDecl)
1170+
if (!pointerTypeDecl || !countTypeDecl)
11721171
return;
11731172

1174-
// create fake variable for constPointer (constructor arg 1)
1175-
auto constPointerType = clangCtx.getTypeDeclType(constPointerTypeDecl);
1176-
auto fakeConstPointerVarDecl = clang::VarDecl::Create(
1173+
// create fake variable for pointer (constructor arg 1)
1174+
clang::QualType pointerType = clangCtx.getTypeDeclType(pointerTypeDecl);
1175+
auto fakePointerVarDecl = clang::VarDecl::Create(
11771176
clangCtx, /*DC*/ clangCtx.getTranslationUnitDecl(),
11781177
clang::SourceLocation(), clang::SourceLocation(), /*Id*/ nullptr,
1179-
constPointerType, clangCtx.getTrivialTypeSourceInfo(constPointerType),
1178+
pointerType, clangCtx.getTrivialTypeSourceInfo(pointerType),
11801179
clang::StorageClass::SC_None);
11811180

1182-
auto fakeConstPointer = new (clangCtx) clang::DeclRefExpr(
1183-
clangCtx, fakeConstPointerVarDecl, false, constPointerType,
1181+
auto fakePointer = new (clangCtx) clang::DeclRefExpr(
1182+
clangCtx, fakePointerVarDecl, false, pointerType,
11841183
clang::ExprValueKind::VK_LValue, clang::SourceLocation());
11851184

11861185
// create fake variable for count (constructor arg 2)
@@ -1197,8 +1196,7 @@ void swift::conformToCxxSpanIfNeeded(ClangImporter::Implementation &impl,
11971196

11981197
// Use clangSema.BuildCxxTypeConstructExpr to create a CXXTypeConstructExpr,
11991198
// passing constPointer and count
1200-
SmallVector<clang::Expr *, 2> constructExprArgs = {fakeConstPointer,
1201-
fakeCount};
1199+
SmallVector<clang::Expr *, 2> constructExprArgs = {fakePointer, fakeCount};
12021200

12031201
auto clangDeclTyInfo = clangCtx.getTrivialTypeSourceInfo(
12041202
clang::QualType(clangDecl->getTypeForDecl(), 0));
@@ -1226,5 +1224,10 @@ void swift::conformToCxxSpanIfNeeded(ClangImporter::Implementation &impl,
12261224
elementType->getUnderlyingType());
12271225
impl.addSynthesizedTypealias(decl, ctx.getIdentifier("Size"),
12281226
sizeType->getUnderlyingType());
1229-
impl.addSynthesizedProtocolAttrs(decl, {KnownProtocolKind::CxxSpan});
1227+
1228+
if (pointerType->getPointeeType().isConstQualified()) {
1229+
impl.addSynthesizedProtocolAttrs(decl, {KnownProtocolKind::CxxSpan});
1230+
} else {
1231+
impl.addSynthesizedProtocolAttrs(decl, {KnownProtocolKind::CxxMutableSpan});
1232+
}
12301233
}

lib/IRGen/GenMeta.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6878,6 +6878,7 @@ SpecialProtocol irgen::getSpecialProtocolID(ProtocolDecl *P) {
68786878
case KnownProtocolKind::CxxUniqueSet:
68796879
case KnownProtocolKind::CxxVector:
68806880
case KnownProtocolKind::CxxSpan:
6881+
case KnownProtocolKind::CxxMutableSpan:
68816882
case KnownProtocolKind::UnsafeCxxInputIterator:
68826883
case KnownProtocolKind::UnsafeCxxMutableInputIterator:
68836884
case KnownProtocolKind::UnsafeCxxRandomAccessIterator:

stdlib/public/Cxx/CxxSpan.swift

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,29 @@ extension CxxSpan {
2929
"UnsafeBufferPointer should not point to nil")
3030
self.init(unsafeBufferPointer.baseAddress!, Size(unsafeBufferPointer.count))
3131
}
32+
33+
@inlinable
34+
public init(_ unsafeMutableBufferPointer: UnsafeMutableBufferPointer<Element>) {
35+
precondition(unsafeMutableBufferPointer.baseAddress != nil,
36+
"UnsafeMutableBufferPointer should not point to nil")
37+
self.init(unsafeMutableBufferPointer.baseAddress!, Size(unsafeMutableBufferPointer.count))
38+
}
39+
}
40+
41+
public protocol CxxMutableSpan<Element> {
42+
associatedtype Element
43+
associatedtype Size: BinaryInteger
44+
45+
init()
46+
init(_ unsafeMutablePointer : UnsafeMutablePointer<Element>, _ count: Size)
47+
}
48+
49+
extension CxxMutableSpan {
50+
/// Creates a C++ span from a Swift UnsafeMutableBufferPointer
51+
@inlinable
52+
public init(_ unsafeMutableBufferPointer: UnsafeMutableBufferPointer<Element>) {
53+
precondition(unsafeMutableBufferPointer.baseAddress != nil,
54+
"UnsafeMutableBufferPointer should not point to nil")
55+
self.init(unsafeMutableBufferPointer.baseAddress!, Size(unsafeMutableBufferPointer.count))
56+
}
3257
}

test/Interop/Cxx/stdlib/Inputs/std-span.h

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,51 @@
55
#include <string>
66
#include <span>
77

8-
using Span = std::span<const int>;
9-
using SpanOfString = std::span<const std::string>;
8+
using ConstSpan = std::span<const int>;
9+
using Span = std::span<int>;
10+
using ConstSpanOfString = std::span<const std::string>;
11+
using SpanOfString = std::span<std::string>;
1012

1113
static int iarray[]{1, 2, 3};
1214
static std::string sarray[]{"", "ab", "abc"};
15+
static ConstSpan icspan = {iarray};
1316
static Span ispan = {iarray};
17+
static ConstSpanOfString scspan = {sarray};
1418
static SpanOfString sspan = {sarray};
1519

1620
struct SpanBox {
17-
std::span<const int> ispan;
18-
std::span<const std::string> sspan;
21+
ConstSpan icspan;
22+
Span ispan;
23+
ConstSpanOfString scspan;
24+
SpanOfString sspan;
1925
};
2026

21-
inline Span initSpan() {
27+
class CppApi {
28+
public:
29+
ConstSpan getConstSpan();
30+
Span getSpan();
31+
};
32+
33+
ConstSpan CppApi::getConstSpan() {
34+
ConstSpan sp{new int[2], 2};
35+
return sp;
36+
}
37+
38+
Span CppApi::getSpan() {
39+
Span sp{new int[2], 2};
40+
return sp;
41+
}
42+
43+
inline ConstSpan initConstSpan() {
2244
const int a[]{1, 2, 3};
45+
return ConstSpan(a);
46+
}
47+
48+
inline Span initSpan() {
49+
int a[]{1, 2, 3};
2350
return Span(a);
2451
}
2552

26-
inline struct SpanBox getStructSpanBox() { return {iarray, sarray}; }
53+
inline struct SpanBox getStructSpanBox() { return {iarray, iarray, sarray, sarray}; }
2754

2855
#endif // TEST_INTEROP_CXX_STDLIB_INPUTS_STD_SPAN_H

0 commit comments

Comments
 (0)