Skip to content

Commit f45d9f7

Browse files
authored
Merge pull request #65056 from hyp/eng/no-never-ever
[interop] do not import functions whose return type is not imported
2 parents 2a3e7ba + 8e0c17b commit f45d9f7

File tree

6 files changed

+97
-14
lines changed

6 files changed

+97
-14
lines changed

include/swift/AST/DiagnosticsClangImporter.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ NOTE(record_field_not_imported, none, "field %0 unavailable (cannot import)", (c
255255
NOTE(invoked_func_not_imported, none, "function %0 unavailable (cannot import)", (const clang::NamedDecl*))
256256
NOTE(record_method_not_imported, none, "method %0 unavailable (cannot import)", (const clang::NamedDecl*))
257257
NOTE(objc_property_not_imported, none, "property %0 unavailable (cannot import)", (const clang::NamedDecl*))
258+
NOTE(unsupported_return_type, none, "C++ function %0 is unavailable: return type is unavailable in Swift", (const clang::NamedDecl*))
258259

259260
NOTE(placeholder_for_forward_declared_interface_member_access_failure, none,
260261
"class '%0' will be imported as an opaque placeholder class and may be "

lib/ClangImporter/ClangImporter.cpp

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5622,13 +5622,7 @@ importName(const clang::NamedDecl *D,
56225622

56235623
Type ClangImporter::importFunctionReturnType(
56245624
const clang::FunctionDecl *clangDecl, DeclContext *dc) {
5625-
bool isInSystemModule =
5626-
cast<ClangModuleUnit>(dc->getModuleScopeContext())->isSystemModule();
5627-
bool allowNSUIntegerAsInt =
5628-
Impl.shouldAllowNSUIntegerAsInt(isInSystemModule, clangDecl);
5629-
if (auto imported =
5630-
Impl.importFunctionReturnType(dc, clangDecl, allowNSUIntegerAsInt)
5631-
.getType())
5625+
if (auto imported = Impl.importFunctionReturnType(clangDecl, dc).getType())
56325626
return imported;
56335627
return dc->getASTContext().getNeverType();
56345628
}

lib/ClangImporter/ImportDecl.cpp

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3064,13 +3064,16 @@ namespace {
30643064

30653065
if (auto recordType = dyn_cast<clang::RecordType>(
30663066
decl->getReturnType().getCanonicalType())) {
3067-
Impl.addImportDiagnostic(
3068-
decl, Diagnostic(diag::reference_passed_by_value,
3069-
Impl.SwiftContext.AllocateCopy(
3070-
recordType->getDecl()->getNameAsString()),
3071-
"the return"),
3072-
decl->getLocation());
3073-
return recordHasReferenceSemantics(recordType->getDecl());
3067+
if (recordHasReferenceSemantics(recordType->getDecl())) {
3068+
Impl.addImportDiagnostic(
3069+
decl,
3070+
Diagnostic(diag::reference_passed_by_value,
3071+
Impl.SwiftContext.AllocateCopy(
3072+
recordType->getDecl()->getNameAsString()),
3073+
"the return"),
3074+
decl->getLocation());
3075+
return true;
3076+
}
30743077
}
30753078

30763079
return false;
@@ -3407,6 +3410,14 @@ namespace {
34073410
func->setAccess(AccessLevel::Public);
34083411
}
34093412

3413+
if (!isa<clang::CXXConstructorDecl>(decl) && !importedType) {
3414+
if (!Impl.importFunctionReturnType(decl, result->getDeclContext())) {
3415+
Impl.addImportDiagnostic(
3416+
decl, Diagnostic(diag::unsupported_return_type, decl),
3417+
decl->getSourceRange().getBegin());
3418+
return nullptr;
3419+
}
3420+
}
34103421
result->setIsObjC(false);
34113422
result->setIsDynamic(false);
34123423

lib/ClangImporter/ImportType.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2074,6 +2074,15 @@ applyImportTypeAttrs(ImportTypeAttrs attrs, Type type,
20742074
return type;
20752075
}
20762076

2077+
ImportedType ClangImporter::Implementation::importFunctionReturnType(
2078+
const clang::FunctionDecl *clangDecl, DeclContext *dc) {
2079+
bool isInSystemModule =
2080+
cast<ClangModuleUnit>(dc->getModuleScopeContext())->isSystemModule();
2081+
bool allowNSUIntegerAsInt =
2082+
shouldAllowNSUIntegerAsInt(isInSystemModule, clangDecl);
2083+
return importFunctionReturnType(dc, clangDecl, allowNSUIntegerAsInt);
2084+
}
2085+
20772086
ImportedType ClangImporter::Implementation::importFunctionReturnType(
20782087
DeclContext *dc, const clang::FunctionDecl *clangDecl,
20792088
bool allowNSUIntegerAsInt) {

lib/ClangImporter/ImporterImpl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1340,6 +1340,9 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
13401340
const clang::FunctionDecl *clangDecl,
13411341
bool allowNSUIntegerAsInt);
13421342

1343+
ImportedType importFunctionReturnType(const clang::FunctionDecl *clangDecl,
1344+
DeclContext *dc);
1345+
13431346
/// Import the parameter list for a function
13441347
///
13451348
/// \param clangDecl The underlying declaration, if any; should only be
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
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+
// RUN: not %target-swift-frontend -typecheck -I %t/Inputs -enable-experimental-cxx-interop %t/test.swift 2>&1 | %FileCheck --check-prefix=NOTE %s
8+
9+
10+
//--- Inputs/module.modulemap
11+
module CxxTypes {
12+
header "types.h"
13+
requires cplusplus
14+
}
15+
16+
module CxxModule {
17+
header "header.h"
18+
requires cplusplus
19+
}
20+
21+
//--- Inputs/types.h
22+
23+
template<class T>
24+
class TemplateInTypesModule {
25+
public:
26+
T x, y;
27+
};
28+
29+
//--- Inputs/header.h
30+
31+
#pragma clang module import CxxTypes
32+
33+
class Struct {
34+
public:
35+
int x, y;
36+
37+
TemplateInTypesModule<int> returnsClassInTypesModules() const;
38+
39+
void takesClassInTypesModules(TemplateInTypesModule<int>) const;
40+
void takesClassInTypesModulesRef(const TemplateInTypesModule<int> &) const;
41+
};
42+
43+
// CHECK: struct Struct {
44+
// CHECK-NEXT: init()
45+
// CHECK-NEXT: init(x: Int32, y: Int32)
46+
// CHECK-NEXT: var x: Int32
47+
// CHECK-NEXT: var y: Int32
48+
// CHECK-NEXT: }
49+
50+
// CHECK-NOT: funcWithClass
51+
52+
TemplateInTypesModule<int> funcWithClassInTypesModules();
53+
void funcWithClassInTypesModulesParam(TemplateInTypesModule<int>);
54+
void funcWithClassInTypesModulesParamRef(const TemplateInTypesModule<int> &);
55+
56+
//--- test.swift
57+
58+
import CxxModule
59+
60+
func test() {
61+
funcWithClassInTypesModules() // expected-error {{cannot find 'funcWithClassInTypesModules' in scope}}
62+
Struct().returnsClassInTypesModules() // expected-error {{value of type 'Struct' has no member 'returnsClassInTypesModules'}}
63+
}
64+
65+
// NOTE: note: C++ function 'funcWithClassInTypesModules' is unavailable: return type is unavailable in Swift

0 commit comments

Comments
 (0)