Skip to content

Commit dd7e068

Browse files
committed
[interop][SwiftToCxx] add a Swift stdlib overlay header
It currently provides begin and end functions for array iteration
1 parent 599874a commit dd7e068

File tree

8 files changed

+121
-11
lines changed

8 files changed

+121
-11
lines changed

lib/PrintAsClang/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
set(datafiles
22
_SwiftCxxInteroperability.h
3+
_SwiftStdlibCxxOverlay.h
34
)
45

56
set(SWIFTLIB_DIR

lib/PrintAsClang/ClangSyntaxPrinter.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,3 +333,24 @@ void ClangSyntaxPrinter::printPrimaryCxxTypeName(
333333
// FIXME: Print class qualifiers for nested class references.
334334
printBaseName(type);
335335
}
336+
337+
void ClangSyntaxPrinter::printIncludeForShimHeader(StringRef headerName) {
338+
os << "// Look for the C++ interop support header relative to clang's "
339+
"resource dir:\n";
340+
os << "// "
341+
"'<toolchain>/usr/lib/clang/<version>/include/../../../swift/"
342+
"swiftToCxx'.\n";
343+
os << "#if __has_include(<../../../swift/swiftToCxx/" << headerName << ">)\n";
344+
os << "#include <../../../swift/swiftToCxx/" << headerName << ">\n";
345+
os << "#elif __has_include(<../../../../lib/swift/swiftToCxx/" << headerName
346+
<< ">)\n";
347+
os << "// "
348+
"'<toolchain>/usr/local/lib/clang/<version>/include/../../../../lib/"
349+
"swift/swiftToCxx'.\n";
350+
os << "#include <../../../../lib/swift/swiftToCxx/" << headerName << ">\n";
351+
os << "// Alternatively, allow user to find the header using additional "
352+
"include path into '<toolchain>/lib/swift'.\n";
353+
os << "#elif __has_include(<swiftToCxx/" << headerName << ">)\n";
354+
os << "#include <swiftToCxx/" << headerName << ">\n";
355+
os << "#endif\n";
356+
}

lib/PrintAsClang/ClangSyntaxPrinter.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,9 @@ class ClangSyntaxPrinter {
184184
void printPrimaryCxxTypeName(const NominalTypeDecl *type,
185185
const ModuleDecl *moduleContext);
186186

187+
// Print the #include sequence for the specified C++ interop shim header.
188+
void printIncludeForShimHeader(StringRef headerName);
189+
187190
protected:
188191
raw_ostream &os;
189192
};

lib/PrintAsClang/ModuleContentsWriter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -759,6 +759,11 @@ EmittedClangHeaderDependencyInfo swift::printModuleContentsAsCxx(
759759
OutputLanguageMode::Cxx);
760760
writer.write();
761761
info.dependsOnStandardLibrary = writer.isStdlibRequired();
762+
if (M.isStdlibModule()) {
763+
// Embed an overlay for the standard library.
764+
ClangSyntaxPrinter(moduleOS).printIncludeForShimHeader(
765+
"_SwiftStdlibCxxOverlay.h");
766+
}
762767

763768
os << "#ifndef SWIFT_PRINTED_CORE\n";
764769
os << "#define SWIFT_PRINTED_CORE\n";

lib/PrintAsClang/PrintAsClang.cpp

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include "swift/PrintAsClang/PrintAsClang.h"
1414

15+
#include "ClangSyntaxPrinter.h"
1516
#include "ModuleContentsWriter.h"
1617
#include "SwiftToClangInteropContext.h"
1718

@@ -107,17 +108,8 @@ static void writePrologue(raw_ostream &out, ASTContext &ctx,
107108
out << "#include <stdlib.h>\n";
108109
out << "#include <new>\n";
109110
out << "#include <type_traits>\n";
110-
out << "// Look for the C++ interop support header relative to clang's resource dir:\n";
111-
out << "// '<toolchain>/usr/lib/clang/<version>/include/../../../swift/swiftToCxx'.\n";
112-
out << "#if __has_include(<../../../swift/swiftToCxx/_SwiftCxxInteroperability.h>)\n";
113-
out << "#include <../../../swift/swiftToCxx/_SwiftCxxInteroperability.h>\n";
114-
out << "#elif __has_include(<../../../../lib/swift/swiftToCxx/_SwiftCxxInteroperability.h>)\n";
115-
out << "// '<toolchain>/usr/local/lib/clang/<version>/include/../../../../lib/swift/swiftToCxx'.\n";
116-
out << "#include <../../../../lib/swift/swiftToCxx/_SwiftCxxInteroperability.h>\n";
117-
out << "// Alternatively, allow user to find the header using additional include path into '<toolchain>/lib/swift'.\n";
118-
out << "#elif __has_include(<swiftToCxx/_SwiftCxxInteroperability.h>)\n";
119-
out << "#include <swiftToCxx/_SwiftCxxInteroperability.h>\n";
120-
out << "#endif\n";
111+
ClangSyntaxPrinter(out).printIncludeForShimHeader(
112+
"_SwiftCxxInteroperability.h");
121113
},
122114
[&] {
123115
out << "#include <stdint.h>\n"
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
//===--- _SwiftStlibCxxOverlay.h - Additions for Stdlib ---------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2022 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef __cplusplus
14+
#error "no C++"
15+
#endif
16+
17+
static_assert(sizeof(_impl::_impl_String) >= 0,
18+
"included outside of stdlib bindings");
19+
20+
namespace cxxOverlay {
21+
22+
class IterationEndSentinel;
23+
24+
/// Abstract Swift collection iterator.
25+
template <class Collection, class T> class CollectionIterator {
26+
public:
27+
using Index =
28+
decltype(reinterpret_cast<Collection *>(0x123)->getStartIndex());
29+
30+
inline CollectionIterator(const Collection &collection)
31+
: collection(collection) {
32+
index = collection.getStartIndex();
33+
endIndex = collection.getEndIndex();
34+
// FIXME: Begin read access.
35+
}
36+
37+
inline ~CollectionIterator() {
38+
// FIXME: End read access.
39+
}
40+
41+
inline T operator*() const { return collection[index]; }
42+
inline void operator++() {
43+
++index;
44+
// FIXME: assert(index <= endIndex); // No need to go past the end.
45+
}
46+
47+
inline bool operator!=(const IterationEndSentinel &) const {
48+
return index != endIndex;
49+
}
50+
51+
private:
52+
Index index, endIndex;
53+
const Collection &collection;
54+
};
55+
56+
class IterationEndSentinel {};
57+
58+
template <class T> using ArrayIterator = CollectionIterator<Array<T>, T>;
59+
60+
} // namespace cxxOverlay
61+
62+
// FIXME: This should apply to more than the Array type.
63+
template <class T>
64+
inline cxxOverlay::ArrayIterator<T> begin(const Array<T> &array
65+
[[clang::lifetimebound]]) {
66+
return cxxOverlay::ArrayIterator<T>(array);
67+
}
68+
69+
template <class T>
70+
inline cxxOverlay::IterationEndSentinel end(const Array<T> &) {
71+
return {};
72+
}

test/Interop/SwiftToCxx/stdlib/array/array-execution.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ int main() {
3737
{
3838
Array<int> val = UseArray::createArray(2);
3939
UseArray::printArray(UseArray::passthroughArray(val));
40+
int count = 2;
41+
for (int x: val) {
42+
assert(x == 2);
43+
--count;
44+
}
45+
assert(count == 0);
4046
}
4147
// CHECK: [2, 2]
4248
{

test/Interop/SwiftToCxx/stdlib/swift-stdlib-in-cxx.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,14 @@
6969
// CHECK-NEXT: #endif
7070
// CHECK-NEXT: private:
7171

72+
// CHECK: #if __has_include(<../../../swift/swiftToCxx/_SwiftStdlibCxxOverlay.h>)
73+
// CHECK-NEXT: #include <../../../swift/swiftToCxx/_SwiftStdlibCxxOverlay.h>
74+
// CHECK-NEXT: #elif __has_include(<../../../../lib/swift/swiftToCxx/_SwiftStdlibCxxOverlay.h>)
75+
// CHECK-NEXT: // '<toolchain>/usr/local/lib/clang/<version>/include/../../../../lib/swift/swiftToCxx'.
76+
// CHECK-NEXT: #include <../../../../lib/swift/swiftToCxx/_SwiftStdlibCxxOverlay.h>
77+
// CHECK-NEXT: // Alternatively, allow user to find the header using additional include path into '<toolchain>/lib/swift'.
78+
// CHECK-NEXT: #elif __has_include(<swiftToCxx/_SwiftStdlibCxxOverlay.h>)
79+
// CHECK-NEXT: #include <swiftToCxx/_SwiftStdlibCxxOverlay.h>
80+
// CHECK-NEXT: #endif
81+
7282
// CHECK: } // namespace Swift

0 commit comments

Comments
 (0)