Skip to content

Commit b07f059

Browse files
authored
Merge pull request #42506 from zoecarver/ufo-with-base
[cxx-interop] Add support for calling members of base classes on UFOs.
2 parents 66d267e + 336cd29 commit b07f059

File tree

5 files changed

+76
-22
lines changed

5 files changed

+76
-22
lines changed

lib/ClangImporter/ClangImporter.cpp

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4382,6 +4382,11 @@ TinyPtrVector<ValueDecl *> CXXNamespaceMemberLookup::evaluate(
43824382
DeclRefExpr *getInteropStaticCastDeclRefExpr(ASTContext &ctx,
43834383
const clang::Module *owningModule,
43844384
Type base, Type derived) {
4385+
if (base->isForeignReferenceType() && derived->isForeignReferenceType()) {
4386+
base = base->wrapInPointer(PTK_UnsafePointer);
4387+
derived = derived->wrapInPointer(PTK_UnsafePointer);
4388+
}
4389+
43854390
// Lookup our static cast helper function.
43864391
// TODO: change this to stdlib or something.
43874392
auto wrapperModule =
@@ -4420,8 +4425,8 @@ DeclRefExpr *getInteropStaticCastDeclRefExpr(ASTContext &ctx,
44204425
// %3 = %2!
44214426
// return %3.pointee
44224427
MemberRefExpr *getInOutSelfInteropStaticCast(FuncDecl *funcDecl,
4423-
StructDecl *baseStruct,
4424-
StructDecl *derivedStruct) {
4428+
NominalTypeDecl *baseStruct,
4429+
NominalTypeDecl *derivedStruct) {
44254430
auto &ctx = funcDecl->getASTContext();
44264431

44274432
auto inoutSelf = [&ctx](FuncDecl *funcDecl) {
@@ -4485,18 +4490,13 @@ MemberRefExpr *getInOutSelfInteropStaticCast(FuncDecl *funcDecl,
44854490
->getResult());
44864491
casted->setThrows(false);
44874492

4488-
// Now force unwrap the casted pointer.
4489-
auto unwrapped = new (ctx) ForceValueExpr(casted, SourceLoc());
4490-
unwrapped->setType(baseStruct->getSelfInterfaceType()->wrapInPointer(
4491-
PTK_UnsafeMutablePointer));
4492-
44934493
SubstitutionMap pointeeSubst = SubstitutionMap::get(
44944494
ctx.getUnsafeMutablePointerDecl()->getGenericSignature(),
44954495
{baseStruct->getSelfInterfaceType()}, {});
44964496
VarDecl *pointeePropertyDecl =
44974497
ctx.getPointerPointeePropertyDecl(PTK_UnsafeMutablePointer);
44984498
auto pointeePropertyRefExpr = new (ctx) MemberRefExpr(
4499-
unwrapped, SourceLoc(),
4499+
casted, SourceLoc(),
45004500
ConcreteDeclRef(pointeePropertyDecl, pointeeSubst), DeclNameLoc(),
45014501
/*implicit=*/true);
45024502
pointeePropertyRefExpr->setType(
@@ -4521,9 +4521,9 @@ synthesizeBaseClassMethodBody(AbstractFunctionDecl *afd, void *context) {
45214521

45224522
auto funcDecl = cast<FuncDecl>(afd);
45234523
auto derivedStruct =
4524-
cast<StructDecl>(funcDecl->getDeclContext()->getAsDecl());
4524+
cast<NominalTypeDecl>(funcDecl->getDeclContext()->getAsDecl());
45254525
auto baseMember = static_cast<FuncDecl *>(context);
4526-
auto baseStruct = cast<StructDecl>(baseMember->getDeclContext()->getAsDecl());
4526+
auto baseStruct = cast<NominalTypeDecl>(baseMember->getDeclContext()->getAsDecl());
45274527
auto baseType = baseStruct->getDeclaredType();
45284528

45294529
SmallVector<Expr *, 8> forwardingParams;
@@ -4591,10 +4591,10 @@ synthesizeBaseClassFieldGetterBody(AbstractFunctionDecl *afd, void *context) {
45914591

45924592
AccessorDecl *getterDecl = cast<AccessorDecl>(afd);
45934593
AbstractStorageDecl *baseClassVar = static_cast<AbstractStorageDecl *>(context);
4594-
StructDecl *baseStruct =
4595-
cast<StructDecl>(baseClassVar->getDeclContext()->getAsDecl());
4596-
StructDecl *derivedStruct =
4597-
cast<StructDecl>(getterDecl->getDeclContext()->getAsDecl());
4594+
NominalTypeDecl *baseStruct =
4595+
cast<NominalTypeDecl>(baseClassVar->getDeclContext()->getAsDecl());
4596+
NominalTypeDecl *derivedStruct =
4597+
cast<NominalTypeDecl>(getterDecl->getDeclContext()->getAsDecl());
45984598

45994599
auto selfDecl = getterDecl->getImplicitSelfDecl();
46004600
auto selfExpr = new (ctx) DeclRefExpr(selfDecl, DeclNameLoc(),
@@ -4654,10 +4654,10 @@ synthesizeBaseClassFieldSetterBody(AbstractFunctionDecl *afd, void *context) {
46544654
AbstractStorageDecl *baseClassVar = static_cast<AbstractStorageDecl *>(context);
46554655
ASTContext &ctx = setterDecl->getASTContext();
46564656

4657-
StructDecl *baseStruct =
4658-
cast<StructDecl>(baseClassVar->getDeclContext()->getAsDecl());
4659-
StructDecl *derivedStruct =
4660-
cast<StructDecl>(setterDecl->getDeclContext()->getAsDecl());
4657+
NominalTypeDecl *baseStruct =
4658+
cast<NominalTypeDecl>(baseClassVar->getDeclContext()->getAsDecl());
4659+
NominalTypeDecl *derivedStruct =
4660+
cast<NominalTypeDecl>(setterDecl->getDeclContext()->getAsDecl());
46614661

46624662
auto *pointeePropertyRefExpr =
46634663
getInOutSelfInteropStaticCast(setterDecl, baseStruct, derivedStruct);
@@ -4894,7 +4894,7 @@ TinyPtrVector<ValueDecl *> ClangRecordMemberLookup::evaluate(
48944894
if (cast<ValueDecl>(import)->getName() == name)
48954895
continue;
48964896

4897-
auto baseResults = cast<StructDecl>(import)->lookupDirect(name);
4897+
auto baseResults = cast<NominalTypeDecl>(import)->lookupDirect(name);
48984898
for (auto foundInBase : baseResults) {
48994899
if (auto newDecl = cloneBaseMemberDecl(foundInBase, recordDecl)) {
49004900
result.push_back(newDecl);

lib/ClangImporter/ImportType.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "clang/AST/ASTContext.h"
3939
#include "clang/AST/DeclCXX.h"
4040
#include "clang/AST/DeclObjCCommon.h"
41+
#include "clang/AST/DeclTemplate.h"
4142
#include "clang/AST/TypeVisitor.h"
4243
#include "clang/Basic/Builtins.h"
4344
#include "clang/Lex/Preprocessor.h"
@@ -2077,6 +2078,17 @@ ImportedType ClangImporter::Implementation::importFunctionReturnType(
20772078
OptionalityOfReturn = OTK_ImplicitlyUnwrappedOptional;
20782079
}
20792080

2081+
// Specialized templates need to match the args/result exactly (i.e.,
2082+
// ptr -> ptr not ptr -> Optional<ptr>).
2083+
if (clangDecl->getReturnType()->isPointerType() &&
2084+
clangDecl->getPrimaryTemplate() &&
2085+
clangDecl
2086+
->getPrimaryTemplate()
2087+
->getAsFunction()
2088+
->getReturnType()
2089+
->isTemplateTypeParmType())
2090+
OptionalityOfReturn = OTK_None;
2091+
20802092
// Import the result type.
20812093
return importType(clangDecl->getReturnType(),
20822094
(isAuditedResult ? ImportTypeKind::AuditedResult
@@ -2240,9 +2252,12 @@ ParameterList *ClangImporter::Implementation::importFunctionParameterList(
22402252
continue;
22412253
}
22422254

2255+
bool knownNonNull = !nonNullArgs.empty() && nonNullArgs[index];
2256+
// Specialized templates need to match the args/result exactly.
2257+
knownNonNull |= clangDecl->isFunctionTemplateSpecialization();
2258+
22432259
// Check nullability of the parameter.
2244-
OptionalTypeKind OptionalityOfParam =
2245-
getParamOptionality(param, !nonNullArgs.empty() && nonNullArgs[index]);
2260+
OptionalTypeKind OptionalityOfParam = getParamOptionality(param, knownNonNull);
22462261

22472262
ImportTypeKind importKind = ImportTypeKind::Parameter;
22482263
if (param->hasAttr<clang::CFReturnsRetainedAttr>())

lib/SILGen/SILGenApply.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1072,7 +1072,10 @@ class SILGenApply : public Lowering::ExprVisitor<SILGenApply> {
10721072
isObjCDirect = objcDecl->isDirectMethod();
10731073
}
10741074

1075-
if (isObjCDirect) {
1075+
// Methods on unsafe foreign objects are always called directly.
1076+
bool isUFO = isa_and_nonnull<ClassDecl>(afd->getDeclContext()) &&
1077+
cast<ClassDecl>(afd->getDeclContext())->isForeignReferenceType();
1078+
if (isObjCDirect || isUFO) {
10761079
setCallee(Callee::forDirect(SGF, constant, subs, e));
10771080
} else {
10781081
setCallee(Callee::forClassMethod(SGF, constant, subs, e));

test/Interop/Cxx/foreign-reference/Inputs/pod.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55

66
#include "visibility.h"
77

8+
template <class From, class To>
9+
To __swift_interopStaticCast(From from) { return from; }
10+
811
inline void *operator new(size_t, void *p) { return p; }
912

1013
SWIFT_BEGIN_NULLABILITY_ANNOTATIONS
@@ -117,6 +120,25 @@ void mutateIt(BigType &x) {
117120
}
118121
BigType passThroughByValue(BigType x) { return x; }
119122

123+
struct __attribute__((swift_attr("import_as_ref"))) BaseRef {
124+
int a = 1;
125+
int b = 2;
126+
127+
int test() const { return b - a; }
128+
int test() { return b - a; }
129+
130+
static BaseRef *create() { return new (malloc(sizeof(BaseRef))) BaseRef(); }
131+
};
132+
133+
struct __attribute__((swift_attr("import_as_ref"))) DerivedRef : BaseRef {
134+
int c = 1;
135+
136+
int testDerived() const { return test() + c; }
137+
int testDerived() { return test() + c; }
138+
139+
static DerivedRef *create() { return new (malloc(sizeof(DerivedRef))) DerivedRef(); }
140+
};
141+
120142
SWIFT_END_NULLABILITY_ANNOTATIONS
121143

122144
#endif // TEST_INTEROP_CXX_FOREIGN_REFERENCE_INPUTS_POD_H

test/Interop/Cxx/foreign-reference/pod.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,4 +148,18 @@ PODTestSuite.test("BigType") {
148148
expectEqual(x.test(), 1)
149149
}
150150

151+
PODTestSuite.test("DerivedRef") {
152+
var x = DerivedRef.create()
153+
expectEqual(x.test(), 1)
154+
expectEqual(x.testMutating(), 1)
155+
expectEqual(x.testDerived(), 2)
156+
expectEqual(x.testDerivedMutating(), 2)
157+
}
158+
159+
PODTestSuite.test("BaseRef") {
160+
var x = BaseRef.create()
161+
expectEqual(x.test(), 1)
162+
expectEqual(x.testMutating(), 1)
163+
}
164+
151165
runAllTests()

0 commit comments

Comments
 (0)