Skip to content

Commit c0e9ebe

Browse files
authored
Merge pull request #63058 from apple/egorzhdan/cxx-templated-static-member
[cxx-interop] Emit IR for templated static members with an out-of-line definition
2 parents c06eccc + 1965e74 commit c0e9ebe

File tree

4 files changed

+48
-3
lines changed

4 files changed

+48
-3
lines changed

lib/IRGen/GenClangDecl.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -178,17 +178,27 @@ void IRGenModule::emitClangDecl(const clang::Decl *decl) {
178178

179179
ClangDeclFinder refFinder(callback);
180180

181+
auto &clangSema = Context.getClangModuleLoader()->getClangSema();
182+
181183
while (!stack.empty()) {
182184
auto *next = const_cast<clang::Decl *>(stack.pop_back_val());
183185

186+
// If this is a static member of a class, it might be defined out of line.
187+
// If the class is templated, the definition of its static member might be
188+
// templated as well. If it is, instantiate it here.
189+
if (auto var = dyn_cast<clang::VarDecl>(next)) {
190+
if (var->isStaticDataMember() &&
191+
var->getTemplateSpecializationKind() ==
192+
clang::TemplateSpecializationKind::TSK_ImplicitInstantiation)
193+
clangSema.InstantiateVariableDefinition(var->getLocation(), var);
194+
}
195+
184196
// If a function calls another method in a class template specialization, we
185197
// need to instantiate that other function. Do that here.
186198
if (auto *fn = dyn_cast<clang::FunctionDecl>(next)) {
187199
// Make sure that this method is part of a class template specialization.
188200
if (fn->getTemplateInstantiationPattern())
189-
Context.getClangModuleLoader()
190-
->getClangSema()
191-
.InstantiateFunctionDefinition(fn->getLocation(), fn);
201+
clangSema.InstantiateFunctionDefinition(fn->getLocation(), fn);
192202
}
193203

194204
if (clang::Decl *executableDecl = getDeclWithExecutableCode(next)) {
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#ifndef TEST_INTEROP_CXX_TEMPLATES_INPUTS_CLASS_TEMPLATE_WITH_STATIC_OUT_OF_LINE_MEMBER_H
2+
#define TEST_INTEROP_CXX_TEMPLATES_INPUTS_CLASS_TEMPLATE_WITH_STATIC_OUT_OF_LINE_MEMBER_H
3+
4+
template <class T>
5+
struct HasStaticOutOfLineMember {
6+
static int values[];
7+
8+
static int getFirstValue() {
9+
return values[0];
10+
}
11+
};
12+
13+
template <class T>
14+
int HasStaticOutOfLineMember<T>::values[123];
15+
16+
typedef HasStaticOutOfLineMember<int> HasStaticOutOfLineMemberInt;
17+
18+
#endif // TEST_INTEROP_CXX_TEMPLATES_INPUTS_CLASS_TEMPLATE_WITH_STATIC_OUT_OF_LINE_MEMBER_H

test/Interop/Cxx/templates/Inputs/module.modulemap

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ module ClassTemplateWithPrimitiveArgument {
88
requires cplusplus
99
}
1010

11+
module ClassTemplateWithOutOfLineMember {
12+
header "class-template-with-static-out-of-line-member.h"
13+
requires cplusplus
14+
}
15+
1116
module NotPreDefinedClassTemplate {
1217
header "not-pre-defined-class-template.h"
1318
requires cplusplus
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// RUN: %target-swift-emit-ir %s -I %S/Inputs -enable-experimental-cxx-interop -disable-availability-checking | %FileCheck %s
2+
3+
import ClassTemplateWithOutOfLineMember
4+
5+
public func usesStaticMember() {
6+
HasStaticOutOfLineMemberInt.getFirstValue()
7+
}
8+
9+
// CHECK: @{{_ZN24HasStaticOutOfLineMemberIiE6valuesE|"\?values@\?\$HasStaticOutOfLineMember@H@@2PAHA"}} = linkonce_odr{{.*}} global {{.*}} zeroinitializer
10+
11+
// CHECK: define {{.*}}i32 @{{_ZN24HasStaticOutOfLineMemberIiE13getFirstValueEv|"\?getFirstValue@\?\$HasStaticOutOfLineMember@H@@SAHXZ"}}()
12+
// CHECK: %0 = {{.*}} @{{_ZN24HasStaticOutOfLineMemberIiE6valuesE|"\?values@\?\$HasStaticOutOfLineMember@H@@2PAHA"}}

0 commit comments

Comments
 (0)