mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[cxx-interop] Add UnsafeCxxContiguousIterator & UnsafeCxxMutableContiguousIterator protocols
This adds a pair of Swift protocols that represents C++ iterator types conforming to `std::contiguous_iterator_tag` requirements. These are random access iterators that guarantee that the values are stored in consequent memory addresses. This will be used to optimize usage of C++ containers such as `std::vector` from Swift, for instance, by providing an overload of `withContiguousStorageIfAvailable` for contiguous containers. rdar://137877849
This commit is contained in:
@@ -142,6 +142,8 @@ PROTOCOL(UnsafeCxxInputIterator)
|
|||||||
PROTOCOL(UnsafeCxxMutableInputIterator)
|
PROTOCOL(UnsafeCxxMutableInputIterator)
|
||||||
PROTOCOL(UnsafeCxxRandomAccessIterator)
|
PROTOCOL(UnsafeCxxRandomAccessIterator)
|
||||||
PROTOCOL(UnsafeCxxMutableRandomAccessIterator)
|
PROTOCOL(UnsafeCxxMutableRandomAccessIterator)
|
||||||
|
PROTOCOL(UnsafeCxxContiguousIterator)
|
||||||
|
PROTOCOL(UnsafeCxxMutableContiguousIterator)
|
||||||
|
|
||||||
PROTOCOL(AsyncSequence)
|
PROTOCOL(AsyncSequence)
|
||||||
PROTOCOL(AsyncIteratorProtocol)
|
PROTOCOL(AsyncIteratorProtocol)
|
||||||
|
|||||||
@@ -1444,6 +1444,8 @@ ProtocolDecl *ASTContext::getProtocol(KnownProtocolKind kind) const {
|
|||||||
case KnownProtocolKind::UnsafeCxxMutableInputIterator:
|
case KnownProtocolKind::UnsafeCxxMutableInputIterator:
|
||||||
case KnownProtocolKind::UnsafeCxxRandomAccessIterator:
|
case KnownProtocolKind::UnsafeCxxRandomAccessIterator:
|
||||||
case KnownProtocolKind::UnsafeCxxMutableRandomAccessIterator:
|
case KnownProtocolKind::UnsafeCxxMutableRandomAccessIterator:
|
||||||
|
case KnownProtocolKind::UnsafeCxxContiguousIterator:
|
||||||
|
case KnownProtocolKind::UnsafeCxxMutableContiguousIterator:
|
||||||
M = getLoadedModule(Id_Cxx);
|
M = getLoadedModule(Id_Cxx);
|
||||||
break;
|
break;
|
||||||
case KnownProtocolKind::Copyable:
|
case KnownProtocolKind::Copyable:
|
||||||
|
|||||||
@@ -462,12 +462,16 @@ void swift::conformToCxxIteratorIfNeeded(
|
|||||||
auto isRandomAccessIteratorDecl = [&](const clang::CXXRecordDecl *base) {
|
auto isRandomAccessIteratorDecl = [&](const clang::CXXRecordDecl *base) {
|
||||||
return isIteratorCategoryDecl(base, "random_access_iterator_tag");
|
return isIteratorCategoryDecl(base, "random_access_iterator_tag");
|
||||||
};
|
};
|
||||||
|
auto isContiguousIteratorDecl = [&](const clang::CXXRecordDecl *base) {
|
||||||
|
return isIteratorCategoryDecl(base, "contiguous_iterator_tag"); // C++20
|
||||||
|
};
|
||||||
|
|
||||||
// Traverse all transitive bases of `underlyingDecl` to check if
|
// Traverse all transitive bases of `underlyingDecl` to check if
|
||||||
// it inherits from `std::input_iterator_tag`.
|
// it inherits from `std::input_iterator_tag`.
|
||||||
bool isInputIterator = isInputIteratorDecl(underlyingCategoryDecl);
|
bool isInputIterator = isInputIteratorDecl(underlyingCategoryDecl);
|
||||||
bool isRandomAccessIterator =
|
bool isRandomAccessIterator =
|
||||||
isRandomAccessIteratorDecl(underlyingCategoryDecl);
|
isRandomAccessIteratorDecl(underlyingCategoryDecl);
|
||||||
|
bool isContiguousIterator = isContiguousIteratorDecl(underlyingCategoryDecl);
|
||||||
underlyingCategoryDecl->forallBases([&](const clang::CXXRecordDecl *base) {
|
underlyingCategoryDecl->forallBases([&](const clang::CXXRecordDecl *base) {
|
||||||
if (isInputIteratorDecl(base)) {
|
if (isInputIteratorDecl(base)) {
|
||||||
isInputIterator = true;
|
isInputIterator = true;
|
||||||
@@ -475,6 +479,11 @@ void swift::conformToCxxIteratorIfNeeded(
|
|||||||
if (isRandomAccessIteratorDecl(base)) {
|
if (isRandomAccessIteratorDecl(base)) {
|
||||||
isRandomAccessIterator = true;
|
isRandomAccessIterator = true;
|
||||||
isInputIterator = true;
|
isInputIterator = true;
|
||||||
|
}
|
||||||
|
if (isContiguousIteratorDecl(base)) {
|
||||||
|
isContiguousIterator = true;
|
||||||
|
isRandomAccessIterator = true;
|
||||||
|
isInputIterator = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -594,6 +603,15 @@ void swift::conformToCxxIteratorIfNeeded(
|
|||||||
else
|
else
|
||||||
impl.addSynthesizedProtocolAttrs(
|
impl.addSynthesizedProtocolAttrs(
|
||||||
decl, {KnownProtocolKind::UnsafeCxxRandomAccessIterator});
|
decl, {KnownProtocolKind::UnsafeCxxRandomAccessIterator});
|
||||||
|
|
||||||
|
if (isContiguousIterator) {
|
||||||
|
if (pointeeSettable)
|
||||||
|
impl.addSynthesizedProtocolAttrs(
|
||||||
|
decl, {KnownProtocolKind::UnsafeCxxMutableContiguousIterator});
|
||||||
|
else
|
||||||
|
impl.addSynthesizedProtocolAttrs(
|
||||||
|
decl, {KnownProtocolKind::UnsafeCxxContiguousIterator});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void swift::conformToCxxConvertibleToBoolIfNeeded(
|
void swift::conformToCxxConvertibleToBoolIfNeeded(
|
||||||
|
|||||||
@@ -6967,6 +6967,8 @@ SpecialProtocol irgen::getSpecialProtocolID(ProtocolDecl *P) {
|
|||||||
case KnownProtocolKind::UnsafeCxxMutableInputIterator:
|
case KnownProtocolKind::UnsafeCxxMutableInputIterator:
|
||||||
case KnownProtocolKind::UnsafeCxxRandomAccessIterator:
|
case KnownProtocolKind::UnsafeCxxRandomAccessIterator:
|
||||||
case KnownProtocolKind::UnsafeCxxMutableRandomAccessIterator:
|
case KnownProtocolKind::UnsafeCxxMutableRandomAccessIterator:
|
||||||
|
case KnownProtocolKind::UnsafeCxxContiguousIterator:
|
||||||
|
case KnownProtocolKind::UnsafeCxxMutableContiguousIterator:
|
||||||
case KnownProtocolKind::Executor:
|
case KnownProtocolKind::Executor:
|
||||||
case KnownProtocolKind::SerialExecutor:
|
case KnownProtocolKind::SerialExecutor:
|
||||||
case KnownProtocolKind::TaskExecutor:
|
case KnownProtocolKind::TaskExecutor:
|
||||||
|
|||||||
@@ -87,3 +87,15 @@ public protocol UnsafeCxxMutableRandomAccessIterator:
|
|||||||
UnsafeCxxRandomAccessIterator, UnsafeCxxMutableInputIterator {}
|
UnsafeCxxRandomAccessIterator, UnsafeCxxMutableInputIterator {}
|
||||||
|
|
||||||
extension UnsafeMutablePointer: UnsafeCxxMutableRandomAccessIterator {}
|
extension UnsafeMutablePointer: UnsafeCxxMutableRandomAccessIterator {}
|
||||||
|
|
||||||
|
/// Bridged C++ iterator that allows traversing elements of a random access
|
||||||
|
/// collection that are stored in contiguous memory segments.
|
||||||
|
///
|
||||||
|
/// Mostly useful for optimizing operations with containers that conform to
|
||||||
|
/// `CxxRandomAccessCollection` and should not generally be used directly.
|
||||||
|
///
|
||||||
|
/// - SeeAlso: https://en.cppreference.com/w/cpp/named_req/ContiguousIterator
|
||||||
|
public protocol UnsafeCxxContiguousIterator: UnsafeCxxRandomAccessIterator {}
|
||||||
|
|
||||||
|
public protocol UnsafeCxxMutableContiguousIterator:
|
||||||
|
UnsafeCxxContiguousIterator, UnsafeCxxMutableRandomAccessIterator {}
|
||||||
|
|||||||
@@ -286,6 +286,229 @@ struct HasTypedefIteratorTag {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct MutableRACIterator {
|
||||||
|
private:
|
||||||
|
int *value;
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct iterator_category : std::random_access_iterator_tag,
|
||||||
|
std::output_iterator_tag {};
|
||||||
|
using value_type = int;
|
||||||
|
using pointer = int *;
|
||||||
|
using reference = const int &;
|
||||||
|
using difference_type = int;
|
||||||
|
|
||||||
|
MutableRACIterator(int *value) : value(value) {}
|
||||||
|
MutableRACIterator(const MutableRACIterator &other) = default;
|
||||||
|
|
||||||
|
const int &operator*() const { return *value; }
|
||||||
|
int &operator*() { return *value; }
|
||||||
|
|
||||||
|
MutableRACIterator &operator++() {
|
||||||
|
value++;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
MutableRACIterator operator++(int) {
|
||||||
|
auto tmp = MutableRACIterator(value);
|
||||||
|
value++;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator+=(difference_type v) { value += v; }
|
||||||
|
void operator-=(difference_type v) { value -= v; }
|
||||||
|
MutableRACIterator operator+(difference_type v) const {
|
||||||
|
return MutableRACIterator(value + v);
|
||||||
|
}
|
||||||
|
MutableRACIterator operator-(difference_type v) const {
|
||||||
|
return MutableRACIterator(value - v);
|
||||||
|
}
|
||||||
|
friend MutableRACIterator operator+(difference_type v,
|
||||||
|
const MutableRACIterator &it) {
|
||||||
|
return it + v;
|
||||||
|
}
|
||||||
|
int operator-(const MutableRACIterator &other) const {
|
||||||
|
return value - other.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<(const MutableRACIterator &other) const {
|
||||||
|
return value < other.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const MutableRACIterator &other) const {
|
||||||
|
return value == other.value;
|
||||||
|
}
|
||||||
|
bool operator!=(const MutableRACIterator &other) const {
|
||||||
|
return value != other.value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#if __cplusplus >= 202002L
|
||||||
|
struct ConstContiguousIterator {
|
||||||
|
private:
|
||||||
|
const int *value;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using iterator_category = std::contiguous_iterator_tag;
|
||||||
|
using value_type = int;
|
||||||
|
using pointer = int *;
|
||||||
|
using reference = const int &;
|
||||||
|
using difference_type = int;
|
||||||
|
|
||||||
|
ConstContiguousIterator(const int *value) : value(value) {}
|
||||||
|
ConstContiguousIterator(const ConstContiguousIterator &other) = default;
|
||||||
|
|
||||||
|
const int &operator*() const { return *value; }
|
||||||
|
|
||||||
|
ConstContiguousIterator &operator++() {
|
||||||
|
value++;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
ConstContiguousIterator operator++(int) {
|
||||||
|
auto tmp = ConstContiguousIterator(value);
|
||||||
|
value++;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator+=(difference_type v) { value += v; }
|
||||||
|
void operator-=(difference_type v) { value -= v; }
|
||||||
|
ConstContiguousIterator operator+(difference_type v) const {
|
||||||
|
return ConstContiguousIterator(value + v);
|
||||||
|
}
|
||||||
|
ConstContiguousIterator operator-(difference_type v) const {
|
||||||
|
return ConstContiguousIterator(value - v);
|
||||||
|
}
|
||||||
|
friend ConstContiguousIterator operator+(difference_type v,
|
||||||
|
const ConstContiguousIterator &it) {
|
||||||
|
return it + v;
|
||||||
|
}
|
||||||
|
int operator-(const ConstContiguousIterator &other) const {
|
||||||
|
return value - other.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<(const ConstContiguousIterator &other) const {
|
||||||
|
return value < other.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const ConstContiguousIterator &other) const {
|
||||||
|
return value == other.value;
|
||||||
|
}
|
||||||
|
bool operator!=(const ConstContiguousIterator &other) const {
|
||||||
|
return value != other.value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HasCustomContiguousIteratorTag {
|
||||||
|
private:
|
||||||
|
const int *value;
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct CustomTag : std::contiguous_iterator_tag {};
|
||||||
|
using iterator_category = CustomTag;
|
||||||
|
using value_type = int;
|
||||||
|
using pointer = int *;
|
||||||
|
using reference = const int &;
|
||||||
|
using difference_type = int;
|
||||||
|
|
||||||
|
HasCustomContiguousIteratorTag(const int *value) : value(value) {}
|
||||||
|
HasCustomContiguousIteratorTag(const HasCustomContiguousIteratorTag &other) =
|
||||||
|
default;
|
||||||
|
|
||||||
|
const int &operator*() const { return *value; }
|
||||||
|
|
||||||
|
HasCustomContiguousIteratorTag &operator++() {
|
||||||
|
value++;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
HasCustomContiguousIteratorTag operator++(int) {
|
||||||
|
auto tmp = HasCustomContiguousIteratorTag(value);
|
||||||
|
value++;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator+=(difference_type v) { value += v; }
|
||||||
|
void operator-=(difference_type v) { value -= v; }
|
||||||
|
HasCustomContiguousIteratorTag operator+(difference_type v) const {
|
||||||
|
return HasCustomContiguousIteratorTag(value + v);
|
||||||
|
}
|
||||||
|
HasCustomContiguousIteratorTag operator-(difference_type v) const {
|
||||||
|
return HasCustomContiguousIteratorTag(value - v);
|
||||||
|
}
|
||||||
|
friend HasCustomContiguousIteratorTag
|
||||||
|
operator+(difference_type v, const HasCustomContiguousIteratorTag &it) {
|
||||||
|
return it + v;
|
||||||
|
}
|
||||||
|
int operator-(const HasCustomContiguousIteratorTag &other) const {
|
||||||
|
return value - other.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<(const HasCustomContiguousIteratorTag &other) const {
|
||||||
|
return value < other.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const HasCustomContiguousIteratorTag &other) const {
|
||||||
|
return value == other.value;
|
||||||
|
}
|
||||||
|
bool operator!=(const HasCustomContiguousIteratorTag &other) const {
|
||||||
|
return value != other.value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MutableContiguousIterator {
|
||||||
|
private:
|
||||||
|
int *value;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using iterator_category = std::contiguous_iterator_tag;
|
||||||
|
using value_type = int;
|
||||||
|
using pointer = int *;
|
||||||
|
using reference = const int &;
|
||||||
|
using difference_type = int;
|
||||||
|
|
||||||
|
MutableContiguousIterator(int *value) : value(value) {}
|
||||||
|
MutableContiguousIterator(const MutableContiguousIterator &other) = default;
|
||||||
|
|
||||||
|
const int &operator*() const { return *value; }
|
||||||
|
int &operator*() { return *value; }
|
||||||
|
|
||||||
|
MutableContiguousIterator &operator++() {
|
||||||
|
value++;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
MutableContiguousIterator operator++(int) {
|
||||||
|
auto tmp = MutableContiguousIterator(value);
|
||||||
|
value++;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator+=(difference_type v) { value += v; }
|
||||||
|
void operator-=(difference_type v) { value -= v; }
|
||||||
|
MutableContiguousIterator operator+(difference_type v) const {
|
||||||
|
return MutableContiguousIterator(value + v);
|
||||||
|
}
|
||||||
|
MutableContiguousIterator operator-(difference_type v) const {
|
||||||
|
return MutableContiguousIterator(value - v);
|
||||||
|
}
|
||||||
|
friend MutableContiguousIterator
|
||||||
|
operator+(difference_type v, const MutableContiguousIterator &it) {
|
||||||
|
return it + v;
|
||||||
|
}
|
||||||
|
int operator-(const MutableContiguousIterator &other) const {
|
||||||
|
return value - other.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<(const MutableContiguousIterator &other) const {
|
||||||
|
return value < other.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const MutableContiguousIterator &other) const {
|
||||||
|
return value == other.value;
|
||||||
|
}
|
||||||
|
bool operator!=(const MutableContiguousIterator &other) const {
|
||||||
|
return value != other.value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
// MARK: Types that are not actually iterators
|
// MARK: Types that are not actually iterators
|
||||||
|
|
||||||
struct HasNoIteratorCategory {
|
struct HasNoIteratorCategory {
|
||||||
@@ -916,62 +1139,6 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MutableRACIterator {
|
|
||||||
private:
|
|
||||||
int *value;
|
|
||||||
|
|
||||||
public:
|
|
||||||
struct iterator_category : std::random_access_iterator_tag,
|
|
||||||
std::output_iterator_tag {};
|
|
||||||
using value_type = int;
|
|
||||||
using pointer = int *;
|
|
||||||
using reference = const int &;
|
|
||||||
using difference_type = int;
|
|
||||||
|
|
||||||
MutableRACIterator(int *value) : value(value) {}
|
|
||||||
MutableRACIterator(const MutableRACIterator &other) = default;
|
|
||||||
|
|
||||||
const int &operator*() const { return *value; }
|
|
||||||
int &operator*() { return *value; }
|
|
||||||
|
|
||||||
MutableRACIterator &operator++() {
|
|
||||||
value++;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
MutableRACIterator operator++(int) {
|
|
||||||
auto tmp = MutableRACIterator(value);
|
|
||||||
value++;
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator+=(difference_type v) { value += v; }
|
|
||||||
void operator-=(difference_type v) { value -= v; }
|
|
||||||
MutableRACIterator operator+(difference_type v) const {
|
|
||||||
return MutableRACIterator(value + v);
|
|
||||||
}
|
|
||||||
MutableRACIterator operator-(difference_type v) const {
|
|
||||||
return MutableRACIterator(value - v);
|
|
||||||
}
|
|
||||||
friend MutableRACIterator operator+(difference_type v,
|
|
||||||
const MutableRACIterator &it) {
|
|
||||||
return it + v;
|
|
||||||
}
|
|
||||||
int operator-(const MutableRACIterator &other) const {
|
|
||||||
return value - other.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator<(const MutableRACIterator &other) const {
|
|
||||||
return value < other.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const MutableRACIterator &other) const {
|
|
||||||
return value == other.value;
|
|
||||||
}
|
|
||||||
bool operator!=(const MutableRACIterator &other) const {
|
|
||||||
return value != other.value;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// clang::StmtIteratorBase
|
/// clang::StmtIteratorBase
|
||||||
class ProtectedIteratorBase {
|
class ProtectedIteratorBase {
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
// RUN: %target-swift-ide-test -print-module -module-to-print=CustomIterator -source-filename=x -I %S/Inputs -cxx-interoperability-mode=swift-6 -Xcc -std=c++20 | %FileCheck %s
|
||||||
|
// RUN: %target-swift-ide-test -print-module -module-to-print=CustomIterator -source-filename=x -I %S/Inputs -cxx-interoperability-mode=upcoming-swift -Xcc -std=c++20 | %FileCheck %s
|
||||||
|
|
||||||
|
// Ubuntu 20.04 ships with an old version of libstdc++, which does not provide
|
||||||
|
// std::contiguous_iterator_tag from C++20.
|
||||||
|
// UNSUPPORTED: LinuxDistribution=ubuntu-20.04
|
||||||
|
// UNSUPPORTED: LinuxDistribution=amzn-2
|
||||||
|
|
||||||
|
// CHECK: struct ConstContiguousIterator : UnsafeCxxContiguousIterator, UnsafeCxxRandomAccessIterator, UnsafeCxxInputIterator {
|
||||||
|
// CHECK: func successor() -> ConstContiguousIterator
|
||||||
|
// CHECK: var pointee: Int32
|
||||||
|
// CHECK: typealias Pointee = Int32
|
||||||
|
// CHECK: typealias Distance = Int32
|
||||||
|
// CHECK: }
|
||||||
|
|
||||||
|
// CHECK: struct HasCustomContiguousIteratorTag : UnsafeCxxContiguousIterator, UnsafeCxxRandomAccessIterator, UnsafeCxxInputIterator {
|
||||||
|
// CHECK: func successor() -> HasCustomContiguousIteratorTag
|
||||||
|
// CHECK: var pointee: Int32
|
||||||
|
// CHECK: typealias Pointee = Int32
|
||||||
|
// CHECK: typealias Distance = Int32
|
||||||
|
// CHECK: }
|
||||||
|
|
||||||
|
// CHECK: struct MutableContiguousIterator : UnsafeCxxMutableContiguousIterator, UnsafeCxxMutableRandomAccessIterator, UnsafeCxxMutableInputIterator {
|
||||||
|
// CHECK: func successor() -> MutableContiguousIterator
|
||||||
|
// CHECK: var pointee: Int32
|
||||||
|
// CHECK: typealias Pointee = Int32
|
||||||
|
// CHECK: typealias Distance = Int32
|
||||||
|
// CHECK: }
|
||||||
@@ -80,6 +80,13 @@
|
|||||||
// CHECK: static func == (lhs: HasTypedefIteratorTag, other: HasTypedefIteratorTag) -> Bool
|
// CHECK: static func == (lhs: HasTypedefIteratorTag, other: HasTypedefIteratorTag) -> Bool
|
||||||
// CHECK: }
|
// CHECK: }
|
||||||
|
|
||||||
|
// CHECK: struct MutableRACIterator : UnsafeCxxMutableRandomAccessIterator, UnsafeCxxMutableInputIterator {
|
||||||
|
// CHECK: func successor() -> MutableRACIterator
|
||||||
|
// CHECK: var pointee: Int32
|
||||||
|
// CHECK: typealias Pointee = Int32
|
||||||
|
// CHECK: typealias Distance = Int32
|
||||||
|
// CHECK: }
|
||||||
|
|
||||||
// CHECK-NOT: struct HasNoIteratorCategory : UnsafeCxxInputIterator
|
// CHECK-NOT: struct HasNoIteratorCategory : UnsafeCxxInputIterator
|
||||||
// CHECK-NOT: struct HasInvalidIteratorCategory : UnsafeCxxInputIterator
|
// CHECK-NOT: struct HasInvalidIteratorCategory : UnsafeCxxInputIterator
|
||||||
// CHECK-NOT: struct HasNoEqualEqual : UnsafeCxxInputIterator
|
// CHECK-NOT: struct HasNoEqualEqual : UnsafeCxxInputIterator
|
||||||
@@ -139,10 +146,3 @@
|
|||||||
// CHECK: var pointee: Int32 { get nonmutating set }
|
// CHECK: var pointee: Int32 { get nonmutating set }
|
||||||
// CHECK: typealias Pointee = Int32
|
// CHECK: typealias Pointee = Int32
|
||||||
// CHECK: }
|
// CHECK: }
|
||||||
|
|
||||||
// CHECK: struct MutableRACIterator : UnsafeCxxMutableRandomAccessIterator, UnsafeCxxMutableInputIterator {
|
|
||||||
// CHECK: func successor() -> MutableRACIterator
|
|
||||||
// CHECK: var pointee: Int32
|
|
||||||
// CHECK: typealias Pointee = Int32
|
|
||||||
// CHECK: typealias Distance = Int32
|
|
||||||
// CHECK: }
|
|
||||||
|
|||||||
Reference in New Issue
Block a user