Skip to content

Commit f8d9332

Browse files
authored
Merge pull request swiftlang#78084 from swiftlang/egorzhdan/6.1-relax-cxx-resilience
🍒[cxx-interop] Allow more C++ decls in public Swift interfaces
2 parents fd0aa62 + 099eade commit f8d9332

File tree

4 files changed

+72
-7
lines changed

4 files changed

+72
-7
lines changed

lib/Sema/TypeCheckAccess.cpp

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1828,6 +1828,8 @@ class UsableFromInlineChecker : public AccessControlCheckerBase,
18281828
}
18291829
};
18301830

1831+
bool isFragileClangDecl(const clang::Decl *decl);
1832+
18311833
bool isFragileClangType(clang::QualType type) {
18321834
if (type.isNull())
18331835
return true;
@@ -1842,20 +1844,21 @@ bool isFragileClangType(clang::QualType type) {
18421844
// Pointers to non-fragile types are non-fragile.
18431845
if (underlyingTypePtr->isPointerType())
18441846
return isFragileClangType(underlyingTypePtr->getPointeeType());
1847+
if (auto tagDecl = underlyingTypePtr->getAsTagDecl())
1848+
return isFragileClangDecl(tagDecl);
18451849
return true;
18461850
}
18471851

1848-
bool isFragileClangNode(const ClangNode &node) {
1849-
auto *decl = node.getAsDecl();
1850-
if (!decl)
1851-
return false;
1852+
bool isFragileClangDecl(const clang::Decl *decl) {
18521853
// Namespaces by themselves don't impact ABI.
18531854
if (isa<clang::NamespaceDecl>(decl))
18541855
return false;
18551856
// Objective-C type declarations are compatible with library evolution.
18561857
if (isa<clang::ObjCContainerDecl>(decl))
18571858
return false;
18581859
if (auto *fd = dyn_cast<clang::FunctionDecl>(decl)) {
1860+
if (auto *ctorDecl = dyn_cast<clang::CXXConstructorDecl>(fd))
1861+
return isFragileClangDecl(ctorDecl->getParent());
18591862
if (!isa<clang::CXXMethodDecl>(decl) &&
18601863
!isFragileClangType(fd->getDeclaredReturnType())) {
18611864
for (const auto *param : fd->parameters()) {
@@ -1885,13 +1888,27 @@ bool isFragileClangNode(const ClangNode &node) {
18851888
if (auto *typedefDecl = dyn_cast<clang::TypedefNameDecl>(decl))
18861889
return isFragileClangType(typedefDecl->getUnderlyingType());
18871890
if (auto *rd = dyn_cast<clang::RecordDecl>(decl)) {
1888-
if (!isa<clang::CXXRecordDecl>(rd))
1891+
auto cxxRecordDecl = dyn_cast<clang::CXXRecordDecl>(rd);
1892+
if (!cxxRecordDecl)
18891893
return false;
1890-
return !rd->getDeclContext()->isExternCContext();
1891-
}
1894+
return !cxxRecordDecl->isCLike() &&
1895+
!cxxRecordDecl->getDeclContext()->isExternCContext();
1896+
}
1897+
if (auto *varDecl = dyn_cast<clang::VarDecl>(decl))
1898+
return isFragileClangType(varDecl->getType());
1899+
if (auto *fieldDecl = dyn_cast<clang::FieldDecl>(decl))
1900+
return isFragileClangType(fieldDecl->getType()) ||
1901+
isFragileClangDecl(fieldDecl->getParent());
18921902
return true;
18931903
}
18941904

1905+
bool isFragileClangNode(const ClangNode &node) {
1906+
auto *decl = node.getAsDecl();
1907+
if (!decl)
1908+
return false;
1909+
return isFragileClangDecl(decl);
1910+
}
1911+
18951912
} // end anonymous namespace
18961913

18971914
/// Returns the kind of origin, implementation-only import or SPI declaration,
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module MyCLibrary {
2+
header "my_c_header.h"
3+
export *
4+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
struct MyCStruct {
2+
int x;
3+
};
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: split-file %s %t
3+
4+
// Build a Swift library that uses symbols from a C library without enabling C++ interop.
5+
// RUN: %target-build-swift %t/uses-c-library.swift -emit-module -emit-library -enable-library-evolution -module-name UsesCLibrary -emit-module-path %t/artifacts/UsesCLibrary.swiftmodule -emit-module-interface-path %t/artifacts/UsesCLibrary.swiftinterface -I %S/Inputs
6+
7+
// Make sure the module interface can be type-checked with C++ interop enabled.
8+
// RUN: %target-swift-frontend -typecheck-module-from-interface -cxx-interoperability-mode=default %t/artifacts/UsesCLibrary.swiftinterface -I %S/Inputs
9+
10+
// Make sure we can build a Swift executable that uses the library and enables C++ interop.
11+
// RUN: %target-swift-frontend -typecheck -cxx-interoperability-mode=default -module-name Main %t/main.swift -I %t/artifacts -I %S/Inputs
12+
13+
//--- uses-c-library.swift
14+
15+
import MyCLibrary
16+
17+
public func getMyCStruct() -> MyCStruct {
18+
return MyCStruct()
19+
}
20+
21+
extension MyCStruct {
22+
@inlinable public var y: CInt {
23+
get {
24+
return self.x
25+
}
26+
}
27+
28+
@inlinable public var anotherInstanceOfSelf: MyCStruct {
29+
get {
30+
return MyCStruct(x: self.x + 1)
31+
}
32+
}
33+
}
34+
35+
//--- main.swift
36+
37+
import UsesCLibrary
38+
39+
let _ = getMyCStruct()
40+
let _ = getMyCStruct().y
41+
let _ = getMyCStruct().anotherInstanceOfSelf

0 commit comments

Comments
 (0)