Skip to content

Commit 7ed866e

Browse files
authored
Merge pull request #60254 from apple/egorzhdan/cxx-opaque
[cxx-interop] Do not try to import uninstantiatable templates
2 parents 9c3691f + 44f3478 commit 7ed866e

File tree

3 files changed

+38
-7
lines changed

3 files changed

+38
-7
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2647,11 +2647,20 @@ namespace {
26472647
return nullptr;
26482648
}
26492649

2650-
// `Sema::isCompleteType` will try to instantiate the class template as a
2651-
// side-effect and we rely on this here. `decl->getDefinition()` can
2652-
// return nullptr before the call to sema and return its definition
2653-
// afterwards.
2654-
if (!Impl.getClangSema().isCompleteType(
2650+
// `decl->getDefinition()` can return nullptr before the call to sema and
2651+
// return its definition afterwards.
2652+
clang::Sema &clangSema = Impl.getClangSema();
2653+
if (!decl->getDefinition()) {
2654+
bool notInstantiated = clangSema.InstantiateClassTemplateSpecialization(
2655+
decl->getLocation(),
2656+
const_cast<clang::ClassTemplateSpecializationDecl *>(decl),
2657+
clang::TemplateSpecializationKind::TSK_ImplicitInstantiation,
2658+
/*Complain*/ false);
2659+
// If the template can't be instantiated, bail.
2660+
if (notInstantiated)
2661+
return nullptr;
2662+
}
2663+
if (!clangSema.isCompleteType(
26552664
decl->getLocation(),
26562665
Impl.getClangASTContext().getRecordType(decl))) {
26572666
// If we got nullptr definition now it means the type is not complete.
@@ -2675,8 +2684,8 @@ namespace {
26752684
for (auto member : decl->decls()) {
26762685
if (auto varDecl = dyn_cast<clang::VarDecl>(member)) {
26772686
if (varDecl->getTemplateInstantiationPattern())
2678-
Impl.getClangSema()
2679-
.InstantiateVariableDefinition(varDecl->getLocation(), varDecl);
2687+
clangSema.InstantiateVariableDefinition(varDecl->getLocation(),
2688+
varDecl);
26802689
}
26812690
}
26822691

test/Interop/Cxx/templates/Inputs/member-templates.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,16 @@ struct HasTemplatedField {
5050
MyTemplatedStruct<int> x;
5151
};
5252

53+
template <typename A, typename R = TemplateClassWithMemberTemplates<A>>
54+
struct HasUninstantiatableTemplateMember {
55+
R *pointer; // R cannot be instantiated here, because R is an incomplete type,
56+
// so this should be imported as OpaquePointer.
57+
};
58+
59+
struct HasTemplateInstantiationWithForwardDecl {
60+
class NoDefinition;
61+
62+
HasUninstantiatableTemplateMember<NoDefinition> noDefMember;
63+
};
64+
5365
#endif // TEST_INTEROP_CXX_TEMPLATES_INPUTS_MEMBER_TEMPLATES_H

test/Interop/Cxx/templates/member-templates-module-interface.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,13 @@
3535
// CHECK: init(x: __CxxTemplateInst17MyTemplatedStructIiE)
3636
// CHECK: var x: __CxxTemplateInst17MyTemplatedStructIiE
3737
// CHECK: }
38+
39+
// CHECK: struct __CxxTemplateInst33HasUninstantiatableTemplateMemberIN39HasTemplateInstantiationWithForwardDecl12NoDefinitionE32TemplateClassWithMemberTemplatesIS1_EE {
40+
// CHECK: init(pointer: OpaquePointer!)
41+
// CHECK: var pointer: OpaquePointer!
42+
// CHECK: }
43+
44+
// CHECK: struct HasTemplateInstantiationWithForwardDecl {
45+
// CHECK: init(noDefMember: __CxxTemplateInst33HasUninstantiatableTemplateMemberIN39HasTemplateInstantiationWithForwardDecl12NoDefinitionE32TemplateClassWithMemberTemplatesIS1_EE)
46+
// CHECK: var noDefMember: __CxxTemplateInst33HasUninstantiatableTemplateMemberIN39HasTemplateInstantiationWithForwardDecl12NoDefinitionE32TemplateClassWithMemberTemplatesIS1_EE
47+
// CHECK: }

0 commit comments

Comments
 (0)