Skip to content

Commit 39016e3

Browse files
committed
[C++20] [Modules] Don't import non-inline function bodies even if it is always-inline
Recommit 1ecbab5 Close #80949 The new thing in this commit is to allow to import the function body from instantiations if it is marked with always-inline. See the discussion in #86893 for details.
1 parent edb0708 commit 39016e3

File tree

2 files changed

+40
-8
lines changed

2 files changed

+40
-8
lines changed

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3952,9 +3952,20 @@ bool CodeGenModule::shouldEmitFunction(GlobalDecl GD) {
39523952
// behavior may break ABI compatibility of the current unit.
39533953
if (const Module *M = F->getOwningModule();
39543954
M && M->getTopLevelModule()->isNamedModule() &&
3955-
getContext().getCurrentNamedModule() != M->getTopLevelModule() &&
3956-
!F->hasAttr<AlwaysInlineAttr>())
3957-
return false;
3955+
getContext().getCurrentNamedModule() != M->getTopLevelModule()) {
3956+
// There are practices to mark template member function as always-inline
3957+
// and mark the template as extern explicit instantiation but not give
3958+
// the definition for member function. So we have to emit the function
3959+
// from explicitly instantiation with always-inline.
3960+
//
3961+
// See https://github.com/llvm/llvm-project/issues/86893 for details.
3962+
//
3963+
// TODO: Maybe it is better to give it a warning if we call a non-inline
3964+
// function from other module units which is marked as always-inline.
3965+
if (!F->isTemplateInstantiation() || !F->hasAttr<AlwaysInlineAttr>()) {
3966+
return false;
3967+
}
3968+
}
39583969

39593970
if (F->hasAttr<NoInlineAttr>())
39603971
return false;

clang/test/CodeGenCXX/module-funcs-from-imports.cppm

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,21 @@ int func_in_gmf_not_called() {
2323
return 44;
2424
}
2525

26+
template <class T>
27+
class A {
28+
public:
29+
__attribute__((always_inline))
30+
inline constexpr int getValue() {
31+
return 43;
32+
}
33+
34+
inline constexpr int getValue2() {
35+
return 43;
36+
}
37+
};
38+
39+
extern template class A<char>;
40+
2641
//--- M.cppm
2742
module;
2843
#include "foo.h"
@@ -47,17 +62,21 @@ int always_inline_func() {
4762
return 45;
4863
}
4964

65+
export using ::A;
66+
5067
//--- Use.cpp
5168
import M;
5269
int use() {
53-
return exported_func() + always_inline_func();
70+
A<char> a;
71+
return exported_func() + always_inline_func() +
72+
a.getValue() + a.getValue2();
5473
}
5574

56-
// Checks that none of the function (except the always_inline_func) in the importees
57-
// are generated in the importer's code.
5875
// CHECK-O0: define{{.*}}_Z3usev(
5976
// CHECK-O0: declare{{.*}}_ZW1M13exported_funcv(
60-
// CHECK-O0: define{{.*}}available_externally{{.*}}_ZW1M18always_inline_funcv(
77+
// CHECK-O0: declare{{.*}}_ZW1M18always_inline_funcv(
78+
// CHECK-O0: define{{.*}}@_ZN1AIcE8getValueEv(
79+
// CHECK-O0: declare{{.*}}@_ZN1AIcE9getValue2Ev(
6180
// CHECK-O0-NOT: func_in_gmf
6281
// CHECK-O0-NOT: func_in_gmf_not_called
6382
// CHECK-O0-NOT: non_exported_func
@@ -68,7 +87,9 @@ int use() {
6887
// O0 to keep consistent ABI.
6988
// CHECK-O1: define{{.*}}_Z3usev(
7089
// CHECK-O1: declare{{.*}}_ZW1M13exported_funcv(
71-
// CHECK-O1: define{{.*}}available_externally{{.*}}_ZW1M18always_inline_funcv(
90+
// CHECK-O1: declare{{.*}}_ZW1M18always_inline_funcv(
91+
// CHECK-O1: define{{.*}}@_ZN1AIcE8getValueEv(
92+
// CHECK-O1: declare{{.*}}@_ZN1AIcE9getValue2Ev(
7293
// CHECK-O1-NOT: func_in_gmf
7394
// CHECK-O1-NOT: func_in_gmf_not_called
7495
// CHECK-O1-NOT: non_exported_func

0 commit comments

Comments
 (0)