Skip to content

Commit 0fff769

Browse files
committed
[interop] Ensure an FRT or a pointer to struct/class gets a Swift type name for a C++ template parameter
In the follow-up, I should also expand this to cover pointers to builtin types too, but for now lets go with a miminal fix here
1 parent 6e63015 commit 0fff769

File tree

4 files changed

+108
-15
lines changed

4 files changed

+108
-15
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,21 @@ void ClangImporter::Implementation::makeComputed(AbstractStorageDecl *storage,
135135
}
136136
}
137137

138+
bool ClangImporter::Implementation::recordHasReferenceSemantics(
139+
const clang::RecordDecl *decl, ASTContext &ctx) {
140+
if (!isa<clang::CXXRecordDecl>(decl) && !ctx.LangOpts.CForeignReferenceTypes)
141+
return false;
142+
143+
return decl->hasAttrs() && llvm::any_of(decl->getAttrs(), [](auto *attr) {
144+
if (auto swiftAttr = dyn_cast<clang::SwiftAttrAttr>(attr))
145+
return swiftAttr->getAttribute() == "import_reference" ||
146+
// TODO: Remove this once libSwift hosttools no longer
147+
// requires it.
148+
swiftAttr->getAttribute() == "import_as_ref";
149+
return false;
150+
});
151+
}
152+
138153
#ifndef NDEBUG
139154
static bool verifyNameMapping(MappedTypeNameKind NameMapping,
140155
StringRef left, StringRef right) {
@@ -1956,18 +1971,8 @@ namespace {
19561971
}
19571972

19581973
bool recordHasReferenceSemantics(const clang::RecordDecl *decl) {
1959-
if (!isa<clang::CXXRecordDecl>(decl) &&
1960-
!Impl.SwiftContext.LangOpts.CForeignReferenceTypes)
1961-
return false;
1962-
1963-
return decl->hasAttrs() && llvm::any_of(decl->getAttrs(), [](auto *attr) {
1964-
if (auto swiftAttr = dyn_cast<clang::SwiftAttrAttr>(attr))
1965-
return swiftAttr->getAttribute() == "import_reference" ||
1966-
// TODO: Remove this once libSwift hosttools no longer
1967-
// requires it.
1968-
swiftAttr->getAttribute() == "import_as_ref";
1969-
return false;
1970-
});
1974+
return ClangImporter::Implementation::recordHasReferenceSemantics(
1975+
decl, Impl.SwiftContext);
19711976
}
19721977

19731978
bool recordHasMoveOnlySemantics(const clang::RecordDecl *decl) {

lib/ClangImporter/ImportName.cpp

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2237,9 +2237,44 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
22372237
return;
22382238
}
22392239
}
2240-
} else if (auto namedArg = dyn_cast_or_null<clang::NamedDecl>(ty->getAsTagDecl())) {
2241-
importNameImpl(namedArg, version, clang::DeclarationName()).getDeclName().print(buffer);
2242-
return;
2240+
} else {
2241+
// FIXME: Generalize this to cover pointer to
2242+
// builtin type too.
2243+
// Check if this a struct/class
2244+
// or a pointer/reference to a struct/class.
2245+
auto *tagDecl = ty->getAsTagDecl();
2246+
enum class TagTypeDecorator {
2247+
None,
2248+
UnsafePointer,
2249+
UnsafeMutablePointer
2250+
};
2251+
TagTypeDecorator decorator = TagTypeDecorator::None;
2252+
if (!tagDecl && ty->isPointerType()) {
2253+
tagDecl = ty->getPointeeType()->getAsTagDecl();
2254+
if (tagDecl) {
2255+
bool isReferenceType = false;
2256+
if (auto *rd = dyn_cast<clang::RecordDecl>(tagDecl))
2257+
isReferenceType = ClangImporter::Implementation::
2258+
recordHasReferenceSemantics(rd, swiftCtx);
2259+
if (!isReferenceType)
2260+
decorator = ty->getPointeeType().isConstQualified()
2261+
? TagTypeDecorator::UnsafePointer
2262+
: TagTypeDecorator::UnsafeMutablePointer;
2263+
}
2264+
}
2265+
if (auto namedArg = dyn_cast_or_null<clang::NamedDecl>(tagDecl)) {
2266+
if (decorator != TagTypeDecorator::None)
2267+
buffer << (decorator == TagTypeDecorator::UnsafePointer
2268+
? "UnsafePointer"
2269+
: "UnsafeMutablePointer")
2270+
<< '<';
2271+
importNameImpl(namedArg, version, clang::DeclarationName())
2272+
.getDeclName()
2273+
.print(buffer);
2274+
if (decorator != TagTypeDecorator::None)
2275+
buffer << '>';
2276+
return;
2277+
}
22432278
}
22442279
}
22452280
buffer << "_";

lib/ClangImporter/ImporterImpl.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1763,6 +1763,11 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
17631763
return *SinglePCHImport;
17641764
return StringRef();
17651765
}
1766+
1767+
/// Returns true if the given C/C++ record should be imported as a reference
1768+
/// type into Swift.
1769+
static bool recordHasReferenceSemantics(const clang::RecordDecl *decl,
1770+
ASTContext &ctx);
17661771
};
17671772

17681773
class ImportDiagnosticAdder {
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: split-file %s %t
3+
4+
// RUN: %target-swift-ide-test -swift-version 5 -print-module -module-to-print=IncludesCxxStdlib -I %t/Inputs -source-filename=test.swift -enable-experimental-cxx-interop -tools-directory=%llvm_obj_root/bin -module-cache-path %t/cache | %FileCheck %s
5+
6+
// REQUIRES: OS=macosx || OS=linux-gnu
7+
8+
//--- Inputs/module.modulemap
9+
module IncludesCxxStdlib {
10+
header "header.h"
11+
export *
12+
}
13+
14+
//--- Inputs/header.h
15+
#include <vector>
16+
17+
class SimplePOD {
18+
public:
19+
int x;
20+
};
21+
22+
class __attribute__((swift_attr("import_reference"), swift_attr("retain:immortal"), swift_attr("release:immortal"))) FRTType {
23+
public:
24+
int y;
25+
};
26+
27+
// Type aliases are needed as a temporary workaround for
28+
// https://github.com/apple/swift/issues/65446.
29+
using T_1 = std::vector<SimplePOD> ;
30+
using T_2 = std::vector<FRTType *> ;
31+
using T_3 = std::vector<const SimplePOD *> ;
32+
using T_4 = std::vector<SimplePOD *> ;
33+
34+
class VecOwner {
35+
public:
36+
std::vector<SimplePOD> getPODItems() const;
37+
38+
std::vector<FRTType *> getFRTItems() const;
39+
40+
std::vector<const SimplePOD * _Nonnull> getPODPtrItems() const;
41+
42+
std::vector<SimplePOD * _Nullable> getMutPODPtrItems() const;
43+
};
44+
45+
// CHECK: func getPODItems() -> std{{\.__1\.|\.}}vector<SimplePOD, allocator<SimplePOD>>
46+
// CHECK: func getFRTItems() -> std{{\.__1\.|\.}}vector<FRTType, allocator<FRTType>>
47+
// CHECK: func getPODPtrItems() -> std{{\.__1\.|\.}}vector<UnsafePointer<SimplePOD>, allocator<UnsafePointer<SimplePOD>>>
48+
// CHECK: func getMutPODPtrItems() -> std{{\.__1\.|\.}}vector<UnsafeMutablePointer<SimplePOD>, allocator<UnsafeMutablePointer<SimplePOD>>>

0 commit comments

Comments
 (0)