Skip to content

Commit 2f7ea38

Browse files
authored
Merge pull request #82305 from swiftlang/gaborh/shared-references-are-safe-on-6.2
[6.2][cxx-interop] Shared references are considered safe
2 parents 70f1a0f + 7575b1f commit 2f7ea38

File tree

5 files changed

+83
-14
lines changed

5 files changed

+83
-14
lines changed

include/swift/ClangImporter/ClangImporterRequests.h

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -576,10 +576,37 @@ class ClangTypeEscapability
576576
void simple_display(llvm::raw_ostream &out, EscapabilityLookupDescriptor desc);
577577
SourceLoc extractNearestSourceLoc(EscapabilityLookupDescriptor desc);
578578

579+
struct CxxDeclExplicitSafetyDescriptor final {
580+
const clang::Decl *decl;
581+
bool isClass;
582+
583+
CxxDeclExplicitSafetyDescriptor(const clang::Decl *decl, bool isClass)
584+
: decl(decl), isClass(isClass) {}
585+
586+
friend llvm::hash_code
587+
hash_value(const CxxDeclExplicitSafetyDescriptor &desc) {
588+
return llvm::hash_combine(desc.decl, desc.isClass);
589+
}
590+
591+
friend bool operator==(const CxxDeclExplicitSafetyDescriptor &lhs,
592+
const CxxDeclExplicitSafetyDescriptor &rhs) {
593+
return lhs.decl == rhs.decl && lhs.isClass == rhs.isClass;
594+
}
595+
596+
friend bool operator!=(const CxxDeclExplicitSafetyDescriptor &lhs,
597+
const CxxDeclExplicitSafetyDescriptor &rhs) {
598+
return !(lhs == rhs);
599+
}
600+
};
601+
602+
void simple_display(llvm::raw_ostream &out,
603+
CxxDeclExplicitSafetyDescriptor desc);
604+
SourceLoc extractNearestSourceLoc(CxxDeclExplicitSafetyDescriptor desc);
605+
579606
/// Determine the safety of the given Clang declaration.
580607
class ClangDeclExplicitSafety
581608
: public SimpleRequest<ClangDeclExplicitSafety,
582-
ExplicitSafety(SafeUseOfCxxDeclDescriptor),
609+
ExplicitSafety(CxxDeclExplicitSafetyDescriptor),
583610
RequestFlags::Cached> {
584611
public:
585612
using SimpleRequest::SimpleRequest;
@@ -592,7 +619,8 @@ class ClangDeclExplicitSafety
592619
friend SimpleRequest;
593620

594621
// Evaluation.
595-
ExplicitSafety evaluate(Evaluator &evaluator, SafeUseOfCxxDeclDescriptor desc) const;
622+
ExplicitSafety evaluate(Evaluator &evaluator,
623+
CxxDeclExplicitSafetyDescriptor desc) const;
596624
};
597625

598626
#define SWIFT_TYPEID_ZONE ClangImporter

include/swift/ClangImporter/ClangImporterTypeIDZone.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,5 +46,5 @@ SWIFT_REQUEST(ClangImporter, ClangTypeEscapability,
4646
CxxEscapability(EscapabilityLookupDescriptor), Cached,
4747
NoLocationInfo)
4848
SWIFT_REQUEST(ClangImporter, ClangDeclExplicitSafety,
49-
ExplicitSafety(SafeUseOfCxxDeclDescriptor), Cached,
49+
ExplicitSafety(CxxDeclExplicitSafetyDescriptor), Cached,
5050
NoLocationInfo)

lib/AST/Decl.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1240,9 +1240,10 @@ ExplicitSafety Decl::getExplicitSafety() const {
12401240
// If this declaration is from C, ask the Clang importer.
12411241
if (auto clangDecl = getClangDecl()) {
12421242
ASTContext &ctx = getASTContext();
1243-
return evaluateOrDefault(ctx.evaluator,
1244-
ClangDeclExplicitSafety({clangDecl}),
1245-
ExplicitSafety::Unspecified);
1243+
return evaluateOrDefault(
1244+
ctx.evaluator,
1245+
ClangDeclExplicitSafety({clangDecl, isa<ClassDecl>(this)}),
1246+
ExplicitSafety::Unspecified);
12461247
}
12471248

12481249
// Inference: Check the enclosing context, unless this is a type.

lib/ClangImporter/ClangImporter.cpp

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "swift/AST/Builtins.h"
2525
#include "swift/AST/ClangModuleLoader.h"
2626
#include "swift/AST/ConcreteDeclRef.h"
27+
#include "swift/AST/Decl.h"
2728
#include "swift/AST/DiagnosticEngine.h"
2829
#include "swift/AST/DiagnosticsClangImporter.h"
2930
#include "swift/AST/DiagnosticsSema.h"
@@ -8392,6 +8393,20 @@ SourceLoc swift::extractNearestSourceLoc(SafeUseOfCxxDeclDescriptor desc) {
83928393
return SourceLoc();
83938394
}
83948395

8396+
void swift::simple_display(llvm::raw_ostream &out,
8397+
CxxDeclExplicitSafetyDescriptor desc) {
8398+
out << "Checking if '";
8399+
if (auto namedDecl = dyn_cast<clang::NamedDecl>(desc.decl))
8400+
out << namedDecl->getNameAsString();
8401+
else
8402+
out << "<invalid decl>";
8403+
out << "' is explicitly safe.\n";
8404+
}
8405+
8406+
SourceLoc swift::extractNearestSourceLoc(CxxDeclExplicitSafetyDescriptor desc) {
8407+
return SourceLoc();
8408+
}
8409+
83958410
CustomRefCountingOperationResult CustomRefCountingOperation::evaluate(
83968411
Evaluator &evaluator, CustomRefCountingOperationDescriptor desc) const {
83978412
auto swiftDecl = desc.decl;
@@ -8469,9 +8484,11 @@ static bool hasUnsafeType(Evaluator &evaluator, clang::QualType clangType) {
84698484

84708485
// Handle records recursively.
84718486
if (auto recordDecl = clangType->getAsTagDecl()) {
8472-
auto safety =
8473-
evaluateOrDefault(evaluator, ClangDeclExplicitSafety({recordDecl}),
8474-
ExplicitSafety::Unspecified);
8487+
// If we reached this point the types is not imported as a shared reference,
8488+
// so we don't need to check the bases whether they are shared references.
8489+
auto safety = evaluateOrDefault(
8490+
evaluator, ClangDeclExplicitSafety({recordDecl, false}),
8491+
ExplicitSafety::Unspecified);
84758492
switch (safety) {
84768493
case ExplicitSafety::Unsafe:
84778494
return true;
@@ -8486,10 +8503,9 @@ static bool hasUnsafeType(Evaluator &evaluator, clang::QualType clangType) {
84868503
return false;
84878504
}
84888505

8489-
ExplicitSafety ClangDeclExplicitSafety::evaluate(
8490-
Evaluator &evaluator,
8491-
SafeUseOfCxxDeclDescriptor desc
8492-
) const {
8506+
ExplicitSafety
8507+
ClangDeclExplicitSafety::evaluate(Evaluator &evaluator,
8508+
CxxDeclExplicitSafetyDescriptor desc) const {
84938509
// FIXME: Somewhat duplicative with importAsUnsafe.
84948510
// FIXME: Also similar to hasPointerInSubobjects
84958511
// FIXME: should probably also subsume IsSafeUseOfCxxDecl
@@ -8502,7 +8518,11 @@ ExplicitSafety ClangDeclExplicitSafety::evaluate(
85028518
// Explicitly safe.
85038519
if (hasSwiftAttribute(decl, "safe"))
85048520
return ExplicitSafety::Safe;
8505-
8521+
8522+
// Shared references are considered safe.
8523+
if (desc.isClass)
8524+
return ExplicitSafety::Safe;
8525+
85068526
// Enums are always safe.
85078527
if (isa<clang::EnumDecl>(decl))
85088528
return ExplicitSafety::Safe;

test/Interop/Cxx/class/safe-interop-mode.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,16 @@ View safeFunc(View v1 [[clang::noescape]], View v2 [[clang::lifetimebound]]);
6363
// Second non-escapable type is not annotated in any way.
6464
void unsafeFunc(View v1 [[clang::noescape]], View v2);
6565

66+
class SharedObject {
67+
private:
68+
int *p;
69+
} SWIFT_SHARED_REFERENCE(retainSharedObject, releaseSharedObject);
70+
71+
inline void retainSharedObject(SharedObject *) {}
72+
inline void releaseSharedObject(SharedObject *) {}
73+
74+
struct DerivedFromSharedObject : SharedObject {};
75+
6676
//--- test.swift
6777

6878
import Test
@@ -134,3 +144,13 @@ func useUnsafeLifetimeAnnotated(v: View) {
134144
// expected-warning@+1{{expression uses unsafe constructs but is not marked with 'unsafe'}}
135145
unsafeFunc(v, v) // expected-note{{reference to unsafe global function 'unsafeFunc'}}
136146
}
147+
148+
@available(SwiftStdlib 5.8, *)
149+
func useSharedReference(frt: SharedObject) {
150+
let _ = frt
151+
}
152+
153+
@available(SwiftStdlib 5.8, *)
154+
func useSharedReference(frt: DerivedFromSharedObject) {
155+
let _ = frt
156+
}

0 commit comments

Comments
 (0)