Skip to content

Commit 27ad938

Browse files
authored
Merge pull request swiftlang#42222 from apple/egorzhdan/cxx-template-linker-error
[cxx-interop] Fix linker errors when a template is used from different modules
2 parents 622eb49 + e9b0c8d commit 27ad938

File tree

7 files changed

+85
-5
lines changed

7 files changed

+85
-5
lines changed

lib/IRGen/GenClangDecl.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -86,15 +86,15 @@ class ClangDeclFinder
8686
// the initializer of the variable.
8787
clang::Decl *getDeclWithExecutableCode(clang::Decl *decl) {
8888
if (auto fd = dyn_cast<clang::FunctionDecl>(decl)) {
89-
// If this is a potentially not-yet-instanciated template, we might
90-
// still have a body.
91-
if (fd->getTemplateInstantiationPattern())
92-
return fd;
93-
9489
const clang::FunctionDecl *definition;
9590
if (fd->hasBody(definition)) {
9691
return const_cast<clang::FunctionDecl *>(definition);
9792
}
93+
94+
// If this is a potentially not-yet-instanciated template, we might
95+
// still have a body.
96+
if (fd->getTemplateInstantiationPattern())
97+
return fd;
9898
} else if (auto vd = dyn_cast<clang::VarDecl>(decl)) {
9999
clang::VarDecl *initializingDecl = vd->getInitializingDeclaration();
100100
if (initializingDecl) {
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#ifndef TEST_INTEROP_CXX_TEMPLATES_INPUTS_MULTIPLE_MODULES_A_H
2+
#define TEST_INTEROP_CXX_TEMPLATES_INPUTS_MULTIPLE_MODULES_A_H
3+
4+
#include "wrapper.h"
5+
6+
WrapperInt getWrapperIntA() {
7+
return WrapperInt();
8+
}
9+
10+
#endif // TEST_INTEROP_CXX_TEMPLATES_INPUTS_MULTIPLE_MODULES_A_H
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#ifndef TEST_INTEROP_CXX_TEMPLATES_INPUTS_MULTIPLE_MODULES_B_H
2+
#define TEST_INTEROP_CXX_TEMPLATES_INPUTS_MULTIPLE_MODULES_B_H
3+
4+
#include "wrapper.h"
5+
6+
WrapperInt getWrapperIntB() {
7+
return WrapperInt();
8+
}
9+
10+
#endif // TEST_INTEROP_CXX_TEMPLATES_INPUTS_MULTIPLE_MODULES_B_H
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
module Wrapper {
2+
header "wrapper.h"
3+
export *
4+
requires cplusplus
5+
}
6+
7+
module A {
8+
header "a.h"
9+
export *
10+
requires cplusplus
11+
}
12+
13+
module B {
14+
header "b.h"
15+
export *
16+
requires cplusplus
17+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#ifndef TEST_INTEROP_CXX_TEMPLATES_INPUTS_MULTIPLE_MODULES_WRAPPER_H
2+
#define TEST_INTEROP_CXX_TEMPLATES_INPUTS_MULTIPLE_MODULES_WRAPPER_H
3+
4+
template <typename T>
5+
struct Wrapper {
6+
T t;
7+
int i = 0;
8+
9+
void foo() { i++; }
10+
11+
Wrapper() { foo(); }
12+
};
13+
14+
typedef Wrapper<int> WrapperInt;
15+
16+
#endif // TEST_INTEROP_CXX_TEMPLATES_INPUTS_MULTIPLE_MODULES_WRAPPER_H
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// RUN: %target-swift-emit-ir %s -I %S/Inputs -enable-cxx-interop | %FileCheck %s
2+
3+
import A
4+
import B
5+
// Both A and B reference WrapperInt, and clang will instantiate two different redecls for WrapperInt.
6+
7+
let w = WrapperInt()
8+
// The constructor of Wrapper calls Wrapper::foo, we need to make sure that Wrapper::foo is emitted,
9+
// otherwise a linker error occurs.
10+
// CHECK: define linkonce_odr{{( dso_local)?}} void @{{_ZN7WrapperIiE3fooEv|"\?foo@\?\$Wrapper@H@@QEAAXXZ"}}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -enable-cxx-interop)
2+
//
3+
// REQUIRES: executable_test
4+
5+
import A
6+
import B
7+
import StdlibUnittest
8+
9+
var TemplatesTestSuite = TestSuite("TemplatesTestSuite")
10+
11+
TemplatesTestSuite.test("instantiation-in-multiple-modules") {
12+
var w = WrapperInt()
13+
// Make sure that WrapperInt::foo gets called.
14+
expectEqual(w.i, 1)
15+
}
16+
17+
runAllTests()

0 commit comments

Comments
 (0)