Skip to content

Commit 9711ddd

Browse files
authored
Merge pull request #67234 from hyp/eng/never-ever-never-ever
[cxx-interop] Mark C++ functions with unavailable return type as unav…
2 parents 0f771c7 + 4d08410 commit 9711ddd

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
@@ -531,8 +531,9 @@ class ClangImporter final : public ClangModuleLoader {
531531
const clang::NamedDecl *D,
532532
clang::DeclarationName givenName = clang::DeclarationName()) override;
533533

534-
Type importFunctionReturnType(const clang::FunctionDecl *clangDecl,
535-
DeclContext *dc) override;
534+
llvm::Optional<Type>
535+
importFunctionReturnType(const clang::FunctionDecl *clangDecl,
536+
DeclContext *dc) override;
536537

537538
Type importVarDeclType(const clang::VarDecl *clangDecl,
538539
VarDecl *swiftDecl,

lib/ClangImporter/ClangImporter.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5707,8 +5707,9 @@ importName(const clang::NamedDecl *D,
57075707
getDeclName();
57085708
}
57095709

5710-
Type ClangImporter::importFunctionReturnType(
5711-
const clang::FunctionDecl *clangDecl, DeclContext *dc) {
5710+
llvm::Optional<Type>
5711+
ClangImporter::importFunctionReturnType(const clang::FunctionDecl *clangDecl,
5712+
DeclContext *dc) {
57125713
bool isInSystemModule =
57135714
cast<ClangModuleUnit>(dc->getModuleScopeContext())->isSystemModule();
57145715
bool allowNSUIntegerAsInt =
@@ -5717,7 +5718,7 @@ Type ClangImporter::importFunctionReturnType(
57175718
Impl.importFunctionReturnType(dc, clangDecl, allowNSUIntegerAsInt)
57185719
.getType())
57195720
return imported;
5720-
return dc->getASTContext().getNeverType();
5721+
return {};
57215722
}
57225723

57235724
Type ClangImporter::importVarDeclType(

lib/Sema/TypeCheckDecl.cpp

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

21352148
// 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)