diff --git a/include/swift/AST/DiagnosticsClangImporter.def b/include/swift/AST/DiagnosticsClangImporter.def index b8181271d4cab..5fdf7a41560f6 100644 --- a/include/swift/AST/DiagnosticsClangImporter.def +++ b/include/swift/AST/DiagnosticsClangImporter.def @@ -377,5 +377,9 @@ NOTE(ptr_to_nonescapable,none, "pointer to non-escapable type %0 cannot be imported", (const clang::Type*)) +NOTE(nonescapable_field_of_escapable, none, + "escapable record %0 cannot have non-escapable field '%1'", + (const clang::NamedDecl *, StringRef)) + #define UNDEFINE_DIAGNOSTIC_MACROS #include "DefineDiagnosticMacros.h" diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index dd95de89db4f2..c22a49bc18d84 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -2401,7 +2401,23 @@ namespace { continue; } - members.push_back(cast(member)); + auto *vd = cast(member); + if (!isNonEscapable) { + if (const auto *fd = dyn_cast(nd)) + if (evaluateOrDefault( + Impl.SwiftContext.evaluator, + ClangTypeEscapability({fd->getType().getTypePtr(), &Impl}), + CxxEscapability::Unknown) == + CxxEscapability::NonEscapable) { + Impl.addImportDiagnostic( + decl, + Diagnostic(diag::nonescapable_field_of_escapable, decl, + nd->getName()), + decl->getLocation()); + return nullptr; + } + } + members.push_back(vd); } bool hasReferenceableFields = !members.empty(); diff --git a/test/Interop/Cxx/class/nonescapable-errors.swift b/test/Interop/Cxx/class/nonescapable-errors.swift index 12ae97b0b6f88..dee07d54e7ece 100644 --- a/test/Interop/Cxx/class/nonescapable-errors.swift +++ b/test/Interop/Cxx/class/nonescapable-errors.swift @@ -95,12 +95,21 @@ const View* usedToCrash(const View* p) { return p; } +struct SWIFT_ESCAPABLE Invalid { + View v; +}; + //--- test.swift import Test import CxxStdlib +// CHECK: error: cannot find type 'Invalid' in scope +// CHECK: note: escapable record 'Invalid' cannot have non-escapable field 'v' +public func importInvalid(_ x: Invalid) { +} + // CHECK: error: a function with a ~Escapable result needs a parameter to depend on -// CHECK-NO-LIFETIMES: test.swift:6:32: error: a function with a ~Escapable result requires '-enable-experimental-feature LifetimeDependence' +// CHECK-NO-LIFETIMES: test.swift:11:32: error: a function with a ~Escapable result requires '-enable-experimental-feature LifetimeDependence' public func noAnnotations() -> View { // CHECK: nonescapable.h:16:7: warning: the returned type 'Owner' is annotated as escapable; it cannot have lifetime dependencies // CHECK-NO-LIFETIMES: nonescapable.h:16:7: warning: the returned type 'Owner' is annotated as escapable; it cannot have lifetime dependencies