Skip to content

Commit 304d558

Browse files
authored
Merge pull request swiftlang#82203 from swiftlang/gaborh/shared-references-are-safe
[cxx-interop] Shared references are considered safe
2 parents b8f5a36 + ddacdf4 commit 304d558

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
@@ -1244,9 +1244,10 @@ ExplicitSafety Decl::getExplicitSafety() const {
12441244
// If this declaration is from C, ask the Clang importer.
12451245
if (auto clangDecl = getClangDecl()) {
12461246
ASTContext &ctx = getASTContext();
1247-
return evaluateOrDefault(ctx.evaluator,
1248-
ClangDeclExplicitSafety({clangDecl}),
1249-
ExplicitSafety::Unspecified);
1247+
return evaluateOrDefault(
1248+
ctx.evaluator,
1249+
ClangDeclExplicitSafety({clangDecl, isa<ClassDecl>(this)}),
1250+
ExplicitSafety::Unspecified);
12501251
}
12511252

12521253
// 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"
@@ -8407,6 +8408,20 @@ SourceLoc swift::extractNearestSourceLoc(SafeUseOfCxxDeclDescriptor desc) {
84078408
return SourceLoc();
84088409
}
84098410

8411+
void swift::simple_display(llvm::raw_ostream &out,
8412+
CxxDeclExplicitSafetyDescriptor desc) {
8413+
out << "Checking if '";
8414+
if (auto namedDecl = dyn_cast<clang::NamedDecl>(desc.decl))
8415+
out << namedDecl->getNameAsString();
8416+
else
8417+
out << "<invalid decl>";
8418+
out << "' is explicitly safe.\n";
8419+
}
8420+
8421+
SourceLoc swift::extractNearestSourceLoc(CxxDeclExplicitSafetyDescriptor desc) {
8422+
return SourceLoc();
8423+
}
8424+
84108425
CustomRefCountingOperationResult CustomRefCountingOperation::evaluate(
84118426
Evaluator &evaluator, CustomRefCountingOperationDescriptor desc) const {
84128427
auto swiftDecl = desc.decl;
@@ -8484,9 +8499,11 @@ static bool hasUnsafeType(Evaluator &evaluator, clang::QualType clangType) {
84848499

84858500
// Handle records recursively.
84868501
if (auto recordDecl = clangType->getAsTagDecl()) {
8487-
auto safety =
8488-
evaluateOrDefault(evaluator, ClangDeclExplicitSafety({recordDecl}),
8489-
ExplicitSafety::Unspecified);
8502+
// If we reached this point the types is not imported as a shared reference,
8503+
// so we don't need to check the bases whether they are shared references.
8504+
auto safety = evaluateOrDefault(
8505+
evaluator, ClangDeclExplicitSafety({recordDecl, false}),
8506+
ExplicitSafety::Unspecified);
84908507
switch (safety) {
84918508
case ExplicitSafety::Unsafe:
84928509
return true;
@@ -8501,10 +8518,9 @@ static bool hasUnsafeType(Evaluator &evaluator, clang::QualType clangType) {
85018518
return false;
85028519
}
85038520

8504-
ExplicitSafety ClangDeclExplicitSafety::evaluate(
8505-
Evaluator &evaluator,
8506-
SafeUseOfCxxDeclDescriptor desc
8507-
) const {
8521+
ExplicitSafety
8522+
ClangDeclExplicitSafety::evaluate(Evaluator &evaluator,
8523+
CxxDeclExplicitSafetyDescriptor desc) const {
85088524
// FIXME: Somewhat duplicative with importAsUnsafe.
85098525
// FIXME: Also similar to hasPointerInSubobjects
85108526
// FIXME: should probably also subsume IsSafeUseOfCxxDecl
@@ -8517,7 +8533,11 @@ ExplicitSafety ClangDeclExplicitSafety::evaluate(
85178533
// Explicitly safe.
85188534
if (hasSwiftAttribute(decl, "safe"))
85198535
return ExplicitSafety::Safe;
8520-
8536+
8537+
// Shared references are considered safe.
8538+
if (desc.isClass)
8539+
return ExplicitSafety::Safe;
8540+
85218541
// Enums are always safe.
85228542
if (isa<clang::EnumDecl>(decl))
85238543
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)