Skip to content

Commit 678b0fc

Browse files
authored
Merge pull request #67235 from hyp/eng/5.9/never-ever
[cxx-interop] Mark C++ functions with unavailable return type as unav…
2 parents e6dc45a + 709ca9a commit 678b0fc

File tree

5 files changed

+100
-8
lines changed

5 files changed

+100
-8
lines changed

include/swift/AST/ClangModuleLoader.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,8 +283,9 @@ class ClangModuleLoader : public ModuleLoader {
283283

284284
virtual bool isUnsafeCXXMethod(const FuncDecl *func) = 0;
285285

286-
virtual Type importFunctionReturnType(const clang::FunctionDecl *clangDecl,
287-
DeclContext *dc) = 0;
286+
virtual llvm::Optional<Type>
287+
importFunctionReturnType(const clang::FunctionDecl *clangDecl,
288+
DeclContext *dc) = 0;
288289

289290
virtual Type importVarDeclType(const clang::VarDecl *clangDecl,
290291
VarDecl *swiftDecl,

include/swift/ClangImporter/ClangImporter.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -520,8 +520,9 @@ class ClangImporter final : public ClangModuleLoader {
520520
const clang::NamedDecl *D,
521521
clang::DeclarationName givenName = clang::DeclarationName()) override;
522522

523-
Type importFunctionReturnType(const clang::FunctionDecl *clangDecl,
524-
DeclContext *dc) override;
523+
llvm::Optional<Type>
524+
importFunctionReturnType(const clang::FunctionDecl *clangDecl,
525+
DeclContext *dc) override;
525526

526527
Type importVarDeclType(const clang::VarDecl *clangDecl,
527528
VarDecl *swiftDecl,

lib/ClangImporter/ClangImporter.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5648,8 +5648,9 @@ importName(const clang::NamedDecl *D,
56485648
getDeclName();
56495649
}
56505650

5651-
Type ClangImporter::importFunctionReturnType(
5652-
const clang::FunctionDecl *clangDecl, DeclContext *dc) {
5651+
llvm::Optional<Type>
5652+
ClangImporter::importFunctionReturnType(const clang::FunctionDecl *clangDecl,
5653+
DeclContext *dc) {
56535654
bool isInSystemModule =
56545655
cast<ClangModuleUnit>(dc->getModuleScopeContext())->isSystemModule();
56555656
bool allowNSUIntegerAsInt =
@@ -5658,7 +5659,7 @@ Type ClangImporter::importFunctionReturnType(
56585659
Impl.importFunctionReturnType(dc, clangDecl, allowNSUIntegerAsInt)
56595660
.getType())
56605661
return imported;
5661-
return dc->getASTContext().getNeverType();
5662+
return {};
56625663
}
56635664

56645665
Type ClangImporter::importVarDeclType(

lib/Sema/TypeCheckDecl.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2129,8 +2129,21 @@ ResultTypeRequest::evaluate(Evaluator &evaluator, ValueDecl *decl) const {
21292129
if (!resultTyRepr && decl->getClangDecl() &&
21302130
isa<clang::FunctionDecl>(decl->getClangDecl())) {
21312131
auto clangFn = cast<clang::FunctionDecl>(decl->getClangDecl());
2132-
return ctx.getClangModuleLoader()->importFunctionReturnType(
2132+
auto returnType = ctx.getClangModuleLoader()->importFunctionReturnType(
21332133
clangFn, decl->getDeclContext());
2134+
if (returnType)
2135+
return *returnType;
2136+
// Mark the imported Swift function as unavailable.
2137+
// That will ensure that the function will not be
2138+
// usable from Swift, even though it is imported.
2139+
if (!decl->getAttrs().isUnavailable(ctx)) {
2140+
StringRef unavailabilityMsgRef = "return type is unavailable in Swift";
2141+
auto ua =
2142+
AvailableAttr::createPlatformAgnostic(ctx, unavailabilityMsgRef);
2143+
decl->getAttrs().add(ua);
2144+
}
2145+
2146+
return ctx.getNeverType();
21342147
}
21352148

21362149
// Nothing to do if there's no result type.
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// RUN: rm -rf %t
2+
// RUN: split-file %s %t
3+
// RUN: %target-swift-ide-test -print-module -module-to-print=CxxModule -I %t/Inputs -source-filename=x -enable-experimental-cxx-interop | %FileCheck %s
4+
5+
// RUN: %target-swift-frontend -typecheck -verify -I %t/Inputs -enable-experimental-cxx-interop %t/test.swift
6+
7+
//--- Inputs/module.modulemap
8+
module CxxTypes {
9+
header "types.h"
10+
requires cplusplus
11+
}
12+
13+
module CxxModule {
14+
header "header.h"
15+
requires cplusplus
16+
}
17+
18+
//--- Inputs/types.h
19+
20+
template<class T>
21+
class TemplateInTypesModule {
22+
public:
23+
T x, y;
24+
};
25+
26+
//--- Inputs/header.h
27+
28+
#pragma clang module import CxxTypes
29+
30+
class Struct {
31+
public:
32+
int x, y;
33+
34+
TemplateInTypesModule<int> returnsClassInTypesModules() const;
35+
36+
void takesClassInTypesModules(TemplateInTypesModule<int>) const;
37+
void takesClassInTypesModulesRef(const TemplateInTypesModule<int> &) const;
38+
};
39+
40+
// CHECK: struct Struct {
41+
// CHECK-NEXT: init()
42+
// CHECK-NEXT: init(x: Int32, y: Int32)
43+
// CHECK-NEXT: func returnsClassInTypesModules() -> Never
44+
// CHECK-NEXT: var x: Int32
45+
// CHECK-NEXT: var y: Int32
46+
// CHECK-NEXT: }
47+
48+
TemplateInTypesModule<int> funcWithClassInTypesModules();
49+
void funcWithClassInTypesModulesParam(TemplateInTypesModule<int>);
50+
void funcWithClassInTypesModulesParamRef(const TemplateInTypesModule<int> &);
51+
52+
class StructPrivateDestructor {
53+
public:
54+
StructPrivateDestructor();
55+
private:
56+
~StructPrivateDestructor();
57+
};
58+
59+
StructPrivateDestructor returnsStructPrivateDestructor();
60+
61+
//--- test.swift
62+
63+
import CxxModule
64+
65+
func test() {
66+
funcWithClassInTypesModules() // expected-error {{'funcWithClassInTypesModules()' is unavailable: return type is unavailable in Swift}}
67+
Struct().returnsClassInTypesModules() // expected-error {{'returnsClassInTypesModules()' is unavailable: return type is unavailable in Swift}}
68+
}
69+
70+
func test2() {
71+
funcWithClassInTypesModules() // expected-error {{'funcWithClassInTypesModules()' is unavailable: return type is unavailable in Swift}}
72+
}
73+
74+
func testPrivateDesType() {
75+
returnsStructPrivateDestructor() // expected-error {{'returnsStructPrivateDestructor()' is unavailable: return type is unavailable in Swift}}
76+
}

0 commit comments

Comments
 (0)