Skip to content

Commit d5e11bd

Browse files
committed
stash
1 parent abd403f commit d5e11bd

File tree

6 files changed

+73
-62
lines changed

6 files changed

+73
-62
lines changed

include/swift/ClangImporter/ClangImporterRequests.h

Lines changed: 17 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -241,44 +241,36 @@ class CxxRecordSemantics
241241
evaluate(Evaluator &evaluator, CxxRecordSemanticsDescriptor) const;
242242
};
243243

244-
enum class CxxRecordUseKind {
245-
Global,
246-
CReturnType,
247-
CxxReturnType
248-
};
249-
250-
struct SafeUseOfCxxRecordDescriptor final {
251-
const clang::CXXRecordDecl *recordDecl;
252-
CxxRecordUseKind kind;
244+
struct SafeUseOfCxxDeclDescriptor final {
245+
const clang::Decl *decl;
253246

254-
SafeUseOfCxxRecordDescriptor(const clang::CXXRecordDecl *recordDecl,
255-
CxxRecordUseKind kind)
256-
: recordDecl(recordDecl), kind(kind) {}
247+
SafeUseOfCxxDeclDescriptor(const clang::Decl *decl)
248+
: decl(decl) {}
257249

258250
friend llvm::hash_code
259-
hash_value(const SafeUseOfCxxRecordDescriptor &desc) {
260-
return llvm::hash_combine(desc.kind, desc.recordDecl);
251+
hash_value(const SafeUseOfCxxDeclDescriptor &desc) {
252+
return llvm::hash_combine(desc.decl);
261253
}
262254

263-
friend bool operator==(const SafeUseOfCxxRecordDescriptor &lhs,
264-
const SafeUseOfCxxRecordDescriptor &rhs) {
265-
return lhs.kind == rhs.kind && lhs.recordDecl == rhs.recordDecl;
255+
friend bool operator==(const SafeUseOfCxxDeclDescriptor &lhs,
256+
const SafeUseOfCxxDeclDescriptor &rhs) {
257+
return lhs.decl == rhs.decl;
266258
}
267259

268-
friend bool operator!=(const SafeUseOfCxxRecordDescriptor &lhs,
269-
const SafeUseOfCxxRecordDescriptor &rhs) {
260+
friend bool operator!=(const SafeUseOfCxxDeclDescriptor &lhs,
261+
const SafeUseOfCxxDeclDescriptor &rhs) {
270262
return !(lhs == rhs);
271263
}
272264
};
273265

274266
void simple_display(llvm::raw_ostream &out,
275-
SafeUseOfCxxRecordDescriptor desc);
267+
SafeUseOfCxxDeclDescriptor desc);
276268
SourceLoc
277-
extractNearestSourceLoc(SafeUseOfCxxRecordDescriptor desc);
269+
extractNearestSourceLoc(SafeUseOfCxxDeclDescriptor desc);
278270

279-
class IsSafeUseOfCxxRecord
280-
: public SimpleRequest<IsSafeUseOfCxxRecord,
281-
bool(SafeUseOfCxxRecordDescriptor),
271+
class IsSafeUseOfCxxDecl
272+
: public SimpleRequest<IsSafeUseOfCxxDecl,
273+
bool(SafeUseOfCxxDeclDescriptor),
282274
RequestFlags::Cached> {
283275
public:
284276
using SimpleRequest::SimpleRequest;
@@ -294,7 +286,7 @@ class IsSafeUseOfCxxRecord
294286

295287
// Evaluation.
296288
bool
297-
evaluate(Evaluator &evaluator, SafeUseOfCxxRecordDescriptor desc) const;
289+
evaluate(Evaluator &evaluator, SafeUseOfCxxDeclDescriptor desc) const;
298290
};
299291

300292

include/swift/ClangImporter/ClangImporterTypeIDZone.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,6 @@ SWIFT_REQUEST(ClangImporter, ClangRecordMemberLookup,
2727
SWIFT_REQUEST(ClangImporter, CxxRecordSemantics,
2828
CxxRecordSemanticsKind(const clang::CXXRecordDecl *), Cached,
2929
NoLocationInfo)
30-
SWIFT_REQUEST(ClangImporter, IsSafeUseOfCxxRecord,
30+
SWIFT_REQUEST(ClangImporter, IsSafeUseOfCxxDecl,
3131
bool(SafeUseOfCxxRecordDescriptor), Cached,
3232
NoLocationInfo)

lib/ClangImporter/ClangImporter.cpp

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6015,12 +6015,34 @@ CxxRecordSemantics::evaluate(Evaluator &evaluator,
60156015

60166016
// TODO: rename to "is acceptable use of cxx record" (as some unsafe uses are OK).
60176017
bool
6018-
IsSafeUseOfCxxRecord::evaluate(Evaluator &evaluator,
6019-
SafeUseOfCxxRecordDescriptor desc) const {
6020-
const clang::CXXRecordDecl *decl = desc.recordDecl;
6018+
IsSafeUseOfCxxDecl::evaluate(Evaluator &evaluator,
6019+
SafeUseOfCxxDeclDescriptor desc) const {
6020+
const clang::Decl *decl = desc.decl;
6021+
const clang::CXXRecordDecl *recordDecl = nullptr;
6022+
bool isCxxMethod = false;
6023+
6024+
if (auto method = dyn_cast<clang::CXXMethodDecl>(decl)) {
6025+
if (hasUnsafeAPIAttr(method))
6026+
return true;
6027+
6028+
if (method->isOverloadedOperator() ||
6029+
isa<clang::CXXConstructorDecl>(decl))
6030+
return true;
6031+
6032+
if (method->getReturnType()->isPointerType() ||
6033+
method->getReturnType()->isReferenceType())
6034+
return false;
6035+
6036+
isCxxMethod = true;
6037+
recordDecl = method->getParent();
6038+
} else if (auto cxxRecordDecl = dyn_cast<clang::CXXRecordDecl>(decl)) {
6039+
recordDecl = cxxRecordDecl;
6040+
} else {
6041+
llvm_unreachable("decl must be a C++ method or C++ record.");
6042+
}
60216043

60226044
auto semanticsKind = evaluateOrDefault(evaluator,
6023-
CxxRecordSemantics({decl}), {});
6045+
CxxRecordSemantics({recordDecl}), {});
60246046

60256047
// Always unsafe.
60266048
if (semanticsKind == CxxRecordSemanticsKind::UnsafeLifetimeOperation)
@@ -6029,16 +6051,19 @@ IsSafeUseOfCxxRecord::evaluate(Evaluator &evaluator,
60296051
// Always OK.
60306052
if (semanticsKind == CxxRecordSemanticsKind::Trivial ||
60316053
semanticsKind == CxxRecordSemanticsKind::Reference ||
6032-
semanticsKind == CxxRecordSemanticsKind::Owned ||
6033-
// Maybe in the future this should warn.
6034-
semanticsKind == CxxRecordSemanticsKind::ExplicitlyUnsafe)
6054+
semanticsKind == CxxRecordSemanticsKind::Owned)
60356055
return true;
60366056

6057+
// Methods themselves must be explicitly marked unsafe. The parents explicit
6058+
// unsafety really doens't matter.
6059+
if (semanticsKind == CxxRecordSemanticsKind::ExplicitlyUnsafe)
6060+
return !isCxxMethod;
6061+
60376062
assert(semanticsKind == CxxRecordSemanticsKind::UnsafePointerMember);
60386063
// We can't dis-allow *all* APIs that potentially return unsafe projections
60396064
// because this would break ObjC interop. So only do this when it's a known
60406065
// C++ API (maybe this could warn in a specific compiler mode, though).
6041-
return desc.kind != CxxRecordUseKind::CxxReturnType;
6066+
return !isCxxMethod;
60426067
}
60436068

60446069
void swift::simple_display(llvm::raw_ostream &out,
@@ -6054,13 +6079,16 @@ swift::extractNearestSourceLoc(CxxRecordSemanticsDescriptor desc) {
60546079
}
60556080

60566081
void swift::simple_display(llvm::raw_ostream &out,
6057-
SafeUseOfCxxRecordDescriptor desc) {
6058-
out << "Checking if '"
6059-
<< desc.recordDecl->getNameAsString()
6060-
<< "' is safe to use in context.\n";
6082+
SafeUseOfCxxDeclDescriptor desc) {
6083+
out << "Checking if '";
6084+
if (auto namedDecl = dyn_cast<clang::NamedDecl>(desc.decl))
6085+
out << namedDecl->getNameAsString();
6086+
else
6087+
out << "<invalid decl>";
6088+
out << "' is safe to use in context.\n";
60616089
}
60626090

60636091
SourceLoc
6064-
swift::extractNearestSourceLoc(SafeUseOfCxxRecordDescriptor desc) {
6092+
swift::extractNearestSourceLoc(SafeUseOfCxxDeclDescriptor desc) {
60656093
return SourceLoc();
60666094
}

lib/ClangImporter/ImportName.cpp

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1481,21 +1481,9 @@ addEmptyArgNamesForClangFunction(const clang::FunctionDecl *funcDecl,
14811481
static StringRef renameUnsafeMethod(ASTContext &ctx,
14821482
const clang::NamedDecl *decl,
14831483
StringRef name) {
1484-
auto method = dyn_cast<clang::CXXMethodDecl>(decl);
1485-
if (!method)
1486-
return name;
1487-
1488-
if (method->isOverloadedOperator() ||
1489-
isa<clang::CXXConstructorDecl>(decl))
1490-
return name;
1491-
1492-
if (auto recordType = dyn_cast<clang::RecordType>(method->getReturnType())) {
1493-
if (auto recordDecl = dyn_cast<clang::CXXRecordDecl>(recordType->getDecl())) {
1494-
if (!evaluateOrDefault(ctx.evaluator, IsSafeUseOfCxxRecord({recordDecl, CxxRecordUseKind::CxxReturnType}), {})) {
1495-
return ctx.getIdentifier(("__" + name + "Unsafe").str()).str();
1496-
}
1497-
}
1498-
}
1484+
if (isa<clang::CXXMethodDecl>(decl) &&
1485+
!evaluateOrDefault(ctx.evaluator, IsSafeUseOfCxxDecl({decl}), {}))
1486+
return ctx.getIdentifier(("__" + name + "Unsafe").str()).str();
14991487

15001488
return name;
15011489
}

stdlib/public/Cxx/CxxSequence.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,10 @@ public protocol CxxSequence: Sequence {
7373
// methods _have_ to be mutating.
7474

7575
/// Do not implement this function manually in Swift.
76-
mutating func begin() -> RawIterator
76+
mutating func __beginUnsafe() -> RawIterator
7777

7878
/// Do not implement this function manually in Swift.
79-
mutating func end() -> RawIterator
79+
mutating func __endUnsafe() -> RawIterator
8080
}
8181

8282
public class CxxIterator<T>: IteratorProtocol where T: CxxSequence {
@@ -90,8 +90,8 @@ public class CxxIterator<T>: IteratorProtocol where T: CxxSequence {
9090

9191
public init(sequence: T) {
9292
self.sequence = sequence
93-
self.rawIterator = self.sequence.begin()
94-
self.endIterator = self.sequence.end()
93+
self.rawIterator = self.sequence.__beginUnsafe()
94+
self.endIterator = self.sequence.__endUnsafe()
9595
}
9696

9797
public func next() -> Element? {

stdlib/public/Cxx/std/String.swift

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,19 @@
1212

1313
extension std.string {
1414
public init(_ string: String) {
15-
self.init()
16-
for char in string.utf8 {
17-
self.push_back(value_type(char))
15+
let count = string.count
16+
self.init(count, value_type(0))
17+
var string = string
18+
string.withUTF8 {
19+
memcpy(UnsafeMutableRawPointer(mutating: UnsafeRawPointer(__dataUnsafe()!)),
20+
UnsafeMutableRawPointer(mutating: $0.baseAddress), count)
1821
}
1922
}
2023
}
2124

2225
extension String {
2326
public init(cxxString: std.string) {
24-
self.init(cString: cxxString.c_str())
27+
self.init(cString: cxxString.__c_strUnsafe())
2528
withExtendedLifetime(cxxString) {}
2629
}
2730
}

0 commit comments

Comments
 (0)