Skip to content

Commit 8e0c17b

Browse files
committed
[interop] do not import functions whose return type is not imported
1 parent c28031c commit 8e0c17b

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
@@ -257,6 +257,7 @@ NOTE(record_field_not_imported, none, "field %0 unavailable (cannot import)", (c
257257
NOTE(invoked_func_not_imported, none, "function %0 unavailable (cannot import)", (const clang::NamedDecl*))
258258
NOTE(record_method_not_imported, none, "method %0 unavailable (cannot import)", (const clang::NamedDecl*))
259259
NOTE(objc_property_not_imported, none, "property %0 unavailable (cannot import)", (const clang::NamedDecl*))
260+
NOTE(unsupported_return_type, none, "C++ function %0 is unavailable: return type is unavailable in Swift", (const clang::NamedDecl*))
260261

261262
NOTE(placeholder_for_forward_declared_interface_member_access_failure, none,
262263
"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
@@ -3048,13 +3048,16 @@ namespace {
30483048

30493049
if (auto recordType = dyn_cast<clang::RecordType>(
30503050
decl->getReturnType().getCanonicalType())) {
3051-
Impl.addImportDiagnostic(
3052-
decl, Diagnostic(diag::reference_passed_by_value,
3053-
Impl.SwiftContext.AllocateCopy(
3054-
recordType->getDecl()->getNameAsString()),
3055-
"the return"),
3056-
decl->getLocation());
3057-
return recordHasReferenceSemantics(recordType->getDecl());
3051+
if (recordHasReferenceSemantics(recordType->getDecl())) {
3052+
Impl.addImportDiagnostic(
3053+
decl,
3054+
Diagnostic(diag::reference_passed_by_value,
3055+
Impl.SwiftContext.AllocateCopy(
3056+
recordType->getDecl()->getNameAsString()),
3057+
"the return"),
3058+
decl->getLocation());
3059+
return true;
3060+
}
30583061
}
30593062

30603063
return false;
@@ -3391,6 +3394,14 @@ namespace {
33913394
func->setAccess(AccessLevel::Public);
33923395
}
33933396

3397+
if (!isa<clang::CXXConstructorDecl>(decl) && !importedType) {
3398+
if (!Impl.importFunctionReturnType(decl, result->getDeclContext())) {
3399+
Impl.addImportDiagnostic(
3400+
decl, Diagnostic(diag::unsupported_return_type, decl),
3401+
decl->getSourceRange().getBegin());
3402+
return nullptr;
3403+
}
3404+
}
33943405
result->setIsObjC(false);
33953406
result->setIsDynamic(false);
33963407

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)