Skip to content

Commit 9224f32

Browse files
committed
stash
1 parent d5e11bd commit 9224f32

File tree

9 files changed

+59
-23
lines changed

9 files changed

+59
-23
lines changed

include/swift/ClangImporter/ClangImporterRequests.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ enum class CxxRecordSemanticsKind {
182182
Trivial,
183183
Owned,
184184
Reference,
185+
Iterator,
185186
// An API that has be annotated as explicitly unsafe, but still importable.
186187
// TODO: we should rename these APIs.
187188
ExplicitlyUnsafe,

lib/ClangImporter/ClangImporter.cpp

Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5859,6 +5859,14 @@ static bool hasUnsafeAPIAttr(const clang::Decl *decl) {
58595859
});
58605860
}
58615861

5862+
static bool hasIteratorAPIAttr(const clang::Decl *decl) {
5863+
return decl->hasAttrs() && llvm::any_of(decl->getAttrs(), [](auto *attr) {
5864+
if (auto swiftAttr = dyn_cast<clang::SwiftAttrAttr>(attr))
5865+
return swiftAttr->getAttribute() == "import_iterator";
5866+
return false;
5867+
});
5868+
}
5869+
58625870
/// Recursively checks that there are no pointers in any fields or base classes.
58635871
/// Does not check C++ records with specific API annotations.
58645872
static bool hasPointerInSubobjects(const clang::CXXRecordDecl *decl) {
@@ -5870,7 +5878,7 @@ static bool hasPointerInSubobjects(const clang::CXXRecordDecl *decl) {
58705878
if (t->isPointerType())
58715879
return true;
58725880

5873-
if (auto recordType = dyn_cast<clang::RecordType>(t)) {
5881+
if (auto recordType = dyn_cast<clang::RecordType>(t.getCanonicalType())) {
58745882
if (auto cxxRecord =
58755883
dyn_cast<clang::CXXRecordDecl>(recordType->getDecl())) {
58765884
if (hasImportAsRefAttr(cxxRecord) || hasOwnedValueAttr(cxxRecord) ||
@@ -5882,7 +5890,7 @@ static bool hasPointerInSubobjects(const clang::CXXRecordDecl *decl) {
58825890
}
58835891
}
58845892

5885-
return true;
5893+
return false;
58865894
};
58875895

58885896
for (auto field : decl->fields()) {
@@ -5931,7 +5939,7 @@ static bool isSufficientlyTrivial(const clang::CXXRecordDecl *decl) {
59315939
return false;
59325940

59335941
auto checkType = [](clang::QualType t) {
5934-
if (auto recordType = dyn_cast<clang::RecordType>(t)) {
5942+
if (auto recordType = dyn_cast<clang::RecordType>(t.getCanonicalType())) {
59355943
if (auto cxxRecord =
59365944
dyn_cast<clang::CXXRecordDecl>(recordType->getDecl())) {
59375945
if (hasImportAsRefAttr(cxxRecord) || hasOwnedValueAttr(cxxRecord) ||
@@ -6002,6 +6010,10 @@ CxxRecordSemantics::evaluate(Evaluator &evaluator,
60026010
return CxxRecordSemanticsKind::Owned;
60036011
}
60046012

6013+
if (hasIteratorAPIAttr(decl)) {
6014+
return CxxRecordSemanticsKind::Iterator;
6015+
}
6016+
60056017
if (!isSufficientlyTrivial(decl)) {
60066018
return CxxRecordSemanticsKind::UnsafeLifetimeOperation;
60076019
}
@@ -6020,18 +6032,37 @@ IsSafeUseOfCxxDecl::evaluate(Evaluator &evaluator,
60206032
const clang::Decl *decl = desc.decl;
60216033
const clang::CXXRecordDecl *recordDecl = nullptr;
60226034
bool isCxxMethod = false;
6035+
bool cxxMethodIsSafe = true;
6036+
6037+
auto remark = [](bool v, std::string s) {
6038+
// llvm::dbgs() << (v ? "TRUE -- " : "FALSE -- ") << s << "\n";
6039+
return v;
6040+
};
60236041

60246042
if (auto method = dyn_cast<clang::CXXMethodDecl>(decl)) {
60256043
if (hasUnsafeAPIAttr(method))
6026-
return true;
6044+
return remark(true, "METHOD: UNSAFE ATTR");
60276045

60286046
if (method->isOverloadedOperator() ||
60296047
isa<clang::CXXConstructorDecl>(decl))
6030-
return true;
6048+
return remark(true, "METHOD: OP | CTOR");
60316049

60326050
if (method->getReturnType()->isPointerType() ||
60336051
method->getReturnType()->isReferenceType())
6034-
return false;
6052+
cxxMethodIsSafe = false;
6053+
6054+
if (auto returnType = dyn_cast<clang::RecordType>(method->getReturnType().getCanonicalType())) {
6055+
if (auto cxxRecordReturnType = dyn_cast<clang::CXXRecordDecl>(returnType->getDecl())) {
6056+
auto semanticsKind = evaluateOrDefault(
6057+
evaluator, CxxRecordSemantics({cxxRecordReturnType}), {});
6058+
6059+
if (semanticsKind == CxxRecordSemanticsKind::UnsafePointerMember ||
6060+
// Pretend all methods that return iterators are unsafe so protocol
6061+
// conformances work.
6062+
semanticsKind == CxxRecordSemanticsKind::Iterator)
6063+
return remark(false, "METHOD: RETURNS ITER | PTR");
6064+
}
6065+
}
60356066

60366067
isCxxMethod = true;
60376068
recordDecl = method->getParent();
@@ -6046,24 +6077,25 @@ IsSafeUseOfCxxDecl::evaluate(Evaluator &evaluator,
60466077

60476078
// Always unsafe.
60486079
if (semanticsKind == CxxRecordSemanticsKind::UnsafeLifetimeOperation)
6049-
return false;
6080+
return remark(false, "PARENT: UNSAFE LIFE");
60506081

60516082
// Always OK.
6083+
if (semanticsKind == CxxRecordSemanticsKind::Reference)
6084+
return remark(true, "PARENT: REF");
6085+
6086+
// Cannot return projections.
60526087
if (semanticsKind == CxxRecordSemanticsKind::Trivial ||
6053-
semanticsKind == CxxRecordSemanticsKind::Reference ||
60546088
semanticsKind == CxxRecordSemanticsKind::Owned)
6055-
return true;
6089+
return remark(cxxMethodIsSafe, "PARENT: TRIVIAL | OWNED");
60566090

6057-
// Methods themselves must be explicitly marked unsafe. The parents explicit
6058-
// unsafety really doens't matter.
60596091
if (semanticsKind == CxxRecordSemanticsKind::ExplicitlyUnsafe)
6060-
return !isCxxMethod;
6092+
return remark(cxxMethodIsSafe, "PARENT: EXPLICIT UNSAFE");
60616093

60626094
assert(semanticsKind == CxxRecordSemanticsKind::UnsafePointerMember);
60636095
// We can't dis-allow *all* APIs that potentially return unsafe projections
60646096
// because this would break ObjC interop. So only do this when it's a known
60656097
// C++ API (maybe this could warn in a specific compiler mode, though).
6066-
return !isCxxMethod;
6098+
return remark(!isCxxMethod, "PARENT: UNSAFE POINTER");
60676099
}
60686100

60696101
void swift::simple_display(llvm::raw_ostream &out,

lib/ClangImporter/ImportName.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1481,9 +1481,12 @@ addEmptyArgNamesForClangFunction(const clang::FunctionDecl *funcDecl,
14811481
static StringRef renameUnsafeMethod(ASTContext &ctx,
14821482
const clang::NamedDecl *decl,
14831483
StringRef name) {
1484+
1485+
// llvm::dbgs() << "IS SAFE: " << name << "?\n";
14841486
if (isa<clang::CXXMethodDecl>(decl) &&
1485-
!evaluateOrDefault(ctx.evaluator, IsSafeUseOfCxxDecl({decl}), {}))
1487+
!evaluateOrDefault(ctx.evaluator, IsSafeUseOfCxxDecl({decl}), {})) {
14861488
return ctx.getIdentifier(("__" + name + "Unsafe").str()).str();
1489+
}
14871490

14881491
return name;
14891492
}

test/Interop/Cxx/foreign-reference/Inputs/pod.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ struct ValueHoldingPair {
100100
int test() const { return otherValue - pair.test(); }
101101
int testMutable() { return otherValue - pair.test(); }
102102

103-
static ValueHoldingPair *create() {
103+
static ValueHoldingPair *create() __attribute__((swift_attr("import_unsafe"))) {
104104
return new (malloc(sizeof(ValueHoldingPair))) ValueHoldingPair();
105105
}
106106
};

test/Interop/Cxx/static/Inputs/inline-static-member-var.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class WithInlineStaticMember {
1010
// inline static int staticMemberInitializedAtRuntime = init();
1111

1212
static int getStaticMemberFromCxx();
13-
static int *getStaticMemberAddress();
13+
static int *getStaticMemberAddress() __attribute__((swift_attr("import_unsafe")));
1414
static void setStaticMemberFromCxx(int);
1515
};
1616

test/Interop/Cxx/static/Inputs/static-member-func.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ class WithStaticMemberFunc {
55
public:
66
static int staticMemberFunc();
77
typedef int (*Func)();
8-
static Func getStaticMemberFuncAddress();
8+
static Func getStaticMemberFuncAddress() __attribute__((swift_attr("import_unsafe")));
99
};
1010

1111
#endif

test/Interop/Cxx/static/Inputs/static-member-var.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
class WithStaticMember {
55
public:
66
static int staticMember;
7-
static int *getStaticMemberAddress();
7+
static int *getStaticMemberAddress() __attribute__((swift_attr("import_unsafe")));
88
static int getStaticMemberFromCxx();
99
static void setStaticMemberFromCxx(int);
1010
};
@@ -15,7 +15,7 @@ class WithIncompleteStaticMember {
1515
static WithIncompleteStaticMember selfMember;
1616
int id = 3;
1717

18-
static WithIncompleteStaticMember *getStaticMemberFromCxx();
18+
static WithIncompleteStaticMember *getStaticMemberFromCxx() __attribute__((swift_attr("import_unsafe")));
1919
static void setStaticMemberFromCxx(WithIncompleteStaticMember);
2020
};
2121

test/Interop/Cxx/stdlib/overlay/Inputs/custom-sequence.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#include <iterator>
66

77
struct SimpleSequence {
8-
struct ConstIterator {
8+
struct __attribute__((swift_attr("import_iterator"))) ConstIterator {
99
private:
1010
int value;
1111

test/Interop/Cxx/stdlib/overlay/std-string-overlay.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-run-simple-swift(-Xfrontend -enable-experimental-cxx-interop -Xfrontend -validate-tbd-against-ir=none)
1+
// RUN: %target-run-simple-swift(-Xfrontend -enable-experimental-cxx-interop -Xfrontend -validate-tbd-against-ir=none -g)
22
//
33
// REQUIRES: executable_test
44
// REQUIRES: OS=macosx || OS=linux-gnu
@@ -24,10 +24,10 @@ extension std.string.const_iterator: UnsafeCxxInputIterator {
2424
rhs: std.string.const_iterator) -> Bool {
2525
#if os(Linux)
2626
// In libstdc++, `base()` returns UnsafePointer<Optional<UnsafePointer<CChar>>>.
27-
return lhs.base().pointee == rhs.base().pointee
27+
return lhs.__baseUnsafe().pointee == rhs.__baseUnsafe().pointee
2828
#else
2929
// In libc++, `base()` returns UnsafePointer<CChar>.
30-
return lhs.base() == rhs.base()
30+
return lhs.__baseUnsafe() == rhs.__baseUnsafe()
3131
#endif
3232
}
3333
}

0 commit comments

Comments
 (0)