Skip to content

Commit 5a2d1f4

Browse files
authored
Merge pull request #69262 from hyp/eng/non-trivial-objc-disallow
[cxx-interop] disallow use of non-trivial C++ types in @objc declarat…
2 parents ed105d0 + c2e15d6 commit 5a2d1f4

File tree

4 files changed

+80
-0
lines changed

4 files changed

+80
-0
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6088,6 +6088,8 @@ NOTE(not_objc_error_protocol_composition,none,
60886088
"in Objective-C", ())
60896089
NOTE(not_objc_empty_tuple,none,
60906090
"empty tuple type cannot be represented in Objective-C", ())
6091+
NOTE(not_objc_non_trivial_cxx_class,none,
6092+
"non-trivial C++ classes cannot be represented in Objective-C", ())
60916093
NOTE(not_objc_tuple,none,
60926094
"tuples cannot be represented in Objective-C", ())
60936095
NOTE(not_objc_swift_class,none,

lib/AST/Type.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3145,6 +3145,17 @@ getForeignRepresentable(Type type, ForeignLanguage language,
31453145

31463146
case ForeignLanguage::ObjectiveC:
31473147
if (isa<StructDecl>(nominal) || isa<EnumDecl>(nominal)) {
3148+
// Non-trivial C++ classes and structures are not
3149+
// supported by @objc attribute, even though they can
3150+
// be represented in Objective-C++.
3151+
if (auto *cxxRec = dyn_cast_or_null<clang::CXXRecordDecl>(
3152+
nominal->getClangDecl())) {
3153+
if (cxxRec->hasNonTrivialCopyConstructor() ||
3154+
cxxRec->hasNonTrivialMoveConstructor() ||
3155+
cxxRec->hasNonTrivialDestructor())
3156+
return failure();
3157+
}
3158+
31483159
// Optional structs are not representable in (Objective-)C if they
31493160
// originally came from C, whether or not they are bridged, unless they
31503161
// came from swift_newtype. If they are defined in Swift, they are only

lib/Sema/TypeCheckDeclObjC.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,13 @@ static void diagnoseTypeNotRepresentableInObjC(const DeclContext *DC,
179179

180180
// Special diagnostic for structs.
181181
if (auto *SD = T->getStructOrBoundGenericStruct()) {
182+
if (isa_and_nonnull<clang::CXXRecordDecl>(SD->getClangDecl())) {
183+
// This can be a non-trivial C++ record.
184+
diags.diagnose(TypeRange.Start, diag::not_objc_non_trivial_cxx_class)
185+
.highlight(TypeRange)
186+
.limitBehavior(behavior);
187+
return;
188+
}
182189
diags.diagnose(TypeRange.Start, diag::not_objc_swift_struct)
183190
.highlight(TypeRange)
184191
.limitBehavior(behavior);
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: split-file %s %t
3+
4+
// RUN: %target-swift-frontend -typecheck -I %t/Inputs -cxx-interoperability-mode=default -verify %t/test.swift
5+
6+
// REQUIRES: objc_interop
7+
8+
//--- Inputs/header.h
9+
10+
class Trivial {
11+
public:
12+
int x;
13+
};
14+
15+
class NonTrivial {
16+
public:
17+
NonTrivial(const NonTrivial &other) : x(other.x) {}
18+
~NonTrivial() { }
19+
20+
private:
21+
int x;
22+
};
23+
24+
struct NonTrivialDestrOnly {
25+
~NonTrivialDestrOnly() { }
26+
27+
private:
28+
int x;
29+
};
30+
31+
//--- Inputs/module.modulemap
32+
33+
module NonTrivial {
34+
header "header.h"
35+
export *
36+
}
37+
38+
//--- test.swift
39+
40+
import Foundation
41+
import NonTrivial
42+
43+
@objc
44+
class ObjCObject: NSObject {
45+
@objc var prop: NonTrivial // expected-error {{property cannot be marked @objc because its type cannot be represented in Objective-C}}
46+
// expected-note@-1 {{non-trivial C++ classes cannot be represented in Objective-C}}
47+
48+
@objc var trivProp: Trivial
49+
50+
override init() { fatalError() }
51+
52+
@objc func getNonTrivial() -> NonTrivialDestrOnly { // expected-error {{method cannot be marked @objc because its result type cannot be represented in Objective-C}}
53+
// expected-note@-1 {{non-trivial C++ classes cannot be represented in Objective-C}}
54+
fatalError()
55+
}
56+
57+
@objc func getTrivial() -> Trivial {
58+
return Trivial(x: 11)
59+
}
60+
}

0 commit comments

Comments
 (0)