Skip to content

Commit 92b7417

Browse files
committed
[cxx-interop] Warning unannotated C++ APIs returning SWIFT_SHARED_REFERENCE types
1 parent e362264 commit 92b7417

File tree

6 files changed

+58
-18
lines changed

6 files changed

+58
-18
lines changed

include/swift/AST/DiagnosticsClangImporter.def

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,8 +258,16 @@ ERROR(failed_base_method_call_synthesis,none,
258258
"failed to synthesize call to the base method %0 of type %0",
259259
(ValueDecl *, ValueDecl *))
260260

261-
ERROR(both_returns_retained_returns_unretained,none,
262-
"%0 cannot be annotated with both swift_attr('returns_retained') and swift_attr('returns_unretained') attributes", (const clang::NamedDecl*))
261+
ERROR(both_returns_retained_returns_unretained, none,
262+
"%0 cannot be annotated with both swift_attr('returns_retained') and "
263+
"swift_attr('returns_unretained') attributes",
264+
(const clang::NamedDecl *))
265+
266+
WARNING(no_returns_retained_returns_unretained, none,
267+
"%0 is returning a 'SWIFT_SHARED_REFERENCE' type but is not annotated "
268+
"with either swift_attr('returns_retained') or "
269+
"swift_attr('returns_unretained') attributes",
270+
(const clang::NamedDecl *))
263271

264272
NOTE(unsupported_builtin_type, none, "built-in type '%0' not supported", (StringRef))
265273
NOTE(record_field_not_imported, none, "field %0 unavailable (cannot import)", (const clang::NamedDecl*))

include/swift/ClangImporter/ClangImporter.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,9 @@ bool isCxxConstReferenceType(const clang::Type *type);
705705
/// Determine whether this typedef is a CF type.
706706
bool isCFTypeDecl(const clang::TypedefNameDecl *Decl);
707707

708+
// Determine whether type is a c++ foreign reference type.
709+
bool isForeignReferenceType(const clang::QualType type);
710+
708711
/// Determine the imported CF type for the given typedef-name, or the empty
709712
/// string if this is not an imported CF type name.
710713
llvm::StringRef getCFTypeName(const clang::TypedefNameDecl *decl);

lib/ClangImporter/ClangImporter.cpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7440,17 +7440,21 @@ static bool hasImportAsRefAttr(const clang::RecordDecl *decl) {
74407440
});
74417441
}
74427442

7443-
// Is this a pointer to a foreign reference type.
7444-
static bool isForeignReferenceType(const clang::QualType type) {
7445-
if (!type->isPointerType())
7446-
return false;
7443+
namespace swift {
7444+
namespace importer {
7445+
// Is this a pointer to a foreign reference type.
7446+
bool isForeignReferenceType(const clang::QualType type) {
7447+
if (!type->isPointerType())
7448+
return false;
74477449

7448-
auto pointeeType =
7449-
dyn_cast<clang::RecordType>(type->getPointeeType().getCanonicalType());
7450-
if (pointeeType == nullptr)
7451-
return false;
7450+
auto pointeeType =
7451+
dyn_cast<clang::RecordType>(type->getPointeeType().getCanonicalType());
7452+
if (pointeeType == nullptr)
7453+
return false;
74527454

7453-
return hasImportAsRefAttr(pointeeType->getDecl());
7455+
return hasImportAsRefAttr(pointeeType->getDecl());
7456+
}
7457+
}
74547458
}
74557459

74567460
static bool hasSwiftAttribute(const clang::Decl *decl, StringRef attr) {

lib/ClangImporter/ImportDecl.cpp

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "swift/AST/ConformanceLookup.h"
2626
#include "swift/AST/Decl.h"
2727
#include "swift/AST/DiagnosticsClangImporter.h"
28+
#include "swift/ClangImporter/ClangImporter.h"
2829
#include "swift/AST/ExistentialLayout.h"
2930
#include "swift/AST/Expr.h"
3031
#include "swift/AST/GenericEnvironment.h"
@@ -96,6 +97,8 @@ struct AccessorInfo {
9697

9798
} // end anonymous namespace
9899

100+
// extern bool isForeignReferenceType(const clang::QualType type);
101+
99102
static bool isInSystemModule(const DeclContext *D) {
100103
return cast<ClangModuleUnit>(D->getModuleScopeContext())->isSystemModule();
101104
}
@@ -2685,7 +2688,7 @@ namespace {
26852688
Impl.diagnoseTopLevelValue(
26862689
DeclName(Impl.SwiftContext.getIdentifier(releaseOperation.name)));
26872690
}
2688-
}else if (releaseOperation.kind ==
2691+
} else if (releaseOperation.kind ==
26892692
CustomRefCountingOperationResult::tooManyFound) {
26902693
HeaderLoc loc(decl->getLocation());
26912694
Impl.diagnose(loc,
@@ -3357,9 +3360,9 @@ namespace {
33573360
// swift_attr("returns_unretained") then emit an error in the swift
33583361
// compiler. Note: this error is not emitted in the clang compiler because
33593362
// these attributes are used only for swift interop.
3363+
bool returnsRetainedAttrIsPresent = false;
3364+
bool returnsUnretainedAttrIsPresent = false;
33603365
if (decl->hasAttrs()) {
3361-
bool returnsRetainedAttrIsPresent = false;
3362-
bool returnsUnretainedAttrIsPresent = false;
33633366
for (const auto *attr : decl->getAttrs()) {
33643367
if (const auto *swiftAttr = dyn_cast<clang::SwiftAttrAttr>(attr)) {
33653368
if (swiftAttr->getAttribute() == "returns_unretained") {
@@ -3369,18 +3372,26 @@ namespace {
33693372
}
33703373
}
33713374
}
3375+
}
33723376

3373-
if (returnsRetainedAttrIsPresent && returnsUnretainedAttrIsPresent) {
3374-
HeaderLoc loc(decl->getLocation());
3375-
Impl.diagnose(loc, diag::both_returns_retained_returns_unretained,
3376-
decl);
3377+
HeaderLoc loc(decl->getLocation());
3378+
if (returnsRetainedAttrIsPresent && returnsUnretainedAttrIsPresent) {
3379+
Impl.diagnose(loc, diag::both_returns_retained_returns_unretained,
3380+
decl);
3381+
}
3382+
3383+
if ((!returnsRetainedAttrIsPresent) && (!returnsUnretainedAttrIsPresent)) {
3384+
if (isForeignReferenceType(decl->getReturnType())) {
3385+
Impl.diagnose(loc, diag::no_returns_retained_returns_unretained,
3386+
decl);
33773387
}
33783388
}
33793389

33803390
return importFunctionDecl(decl, importedName, correctSwiftName,
33813391
std::nullopt);
33823392
}
33833393

3394+
33843395
/// Handles special functions such as subscripts and dereference operators.
33853396
bool
33863397
processSpecialImportedFunc(FuncDecl *func, ImportedName importedName,

test/Interop/Cxx/foreign-reference/Inputs/cxx-functions-and-methods-returning-frt.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,14 @@ struct
158158
__attribute__((swift_attr("returns_unretained")));
159159
};
160160

161+
// C++ APIs returning FRTs but not having annotations
162+
struct
163+
StructWithoutReturnsAnnotations {
164+
static FRTStruct *_Nonnull StaticMethodReturningFRT();
165+
};
166+
167+
FRTStruct *_Nonnull global_function_returning_FRT_WithoutReturnsAnnotations();
168+
161169
struct NonFRTStruct {};
162170

163171
// Global/free C++ functions returning non-FRT

test/Interop/Cxx/foreign-reference/frt-retained-unretained-attributes-error.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,9 @@ let frtLocalVar1 = global_function_returning_FRT_with_both_attrs_returns_retaine
88

99
let frtLocalVar2 = StructWithStaticMethodsReturningFRTWithBothAttributesReturnsRetainedAndReturnsUnretained.StaticMethodReturningFRT()
1010
// CHECK: error: 'StaticMethodReturningFRT' cannot be annotated with both swift_attr('returns_retained') and swift_attr('returns_unretained') attributes
11+
12+
let frtLocalVar3 = global_function_returning_FRT_WithoutReturnsAnnotations()
13+
// CHECK: warning: 'global_function_returning_FRT_WithoutReturnsAnnotations' is returning a 'SWIFT_SHARED_REFERENCE' type but is not annotated with either swift_attr('returns_retained') or swift_attr('returns_unretained') attributes
14+
15+
let frtLocalVar4 = StructWithoutReturnsAnnotations.StaticMethodReturningFRT()
16+
// CHECK: warning: 'StaticMethodReturningFRT' is returning a 'SWIFT_SHARED_REFERENCE' type but is not annotated with either swift_attr('returns_retained') or swift_attr('returns_unretained') attributes

0 commit comments

Comments
 (0)