[clang] 79fa0ec - [C++20] [Modules] Make member functions with a in-class definition in HU implicitly inline
Chuanqi Xu via cfe-commits
cfe-commits at lists.llvm.org
Mon Sep 12 22:13:15 PDT 2022
Author: Chuanqi Xu
Date: 2022-09-13T13:11:56+08:00
New Revision: 79fa0ec8c4bfeeb21f7b44ebd9a66e7ec9781798
URL: https://github.com/llvm/llvm-project/commit/79fa0ec8c4bfeeb21f7b44ebd9a66e7ec9781798
DIFF: https://github.com/llvm/llvm-project/commit/79fa0ec8c4bfeeb21f7b44ebd9a66e7ec9781798.diff
LOG: [C++20] [Modules] Make member functions with a in-class definition in HU implicitly inline
According to [dcl.inline]p7/note4,
> In the global module, a function defined within a class definition is
> implicitly inline.
And the declarations in the header unit are attached to the global
module fragment. So the function defined within a class definition in
header units should be implicitly inline too.
This fixes https://github.com/llvm/llvm-project/issues/57571.
Added:
clang/test/CodeGenCXX/header-unit-friend-within-class-linkage.cpp
clang/test/CodeGenCXX/header-unit-member-func-linkage.cpp
Modified:
clang/lib/Sema/SemaDecl.cpp
clang/unittests/AST/DeclTest.cpp
Removed:
################################################################################
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 9d0e6769f0875..b1c453951f064 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -9503,7 +9503,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
bool ImplicitInlineCXX20 = !getLangOpts().CPlusPlusModules ||
!NewFD->getOwningModule() ||
NewFD->getOwningModule()->isGlobalModule() ||
- NewFD->getOwningModule()->isModuleMapModule();
+ NewFD->getOwningModule()->isHeaderLikeModule();
bool isInline = D.getDeclSpec().isInlineSpecified();
bool isVirtual = D.getDeclSpec().isVirtualSpecified();
bool hasExplicit = D.getDeclSpec().hasExplicitSpecifier();
diff --git a/clang/test/CodeGenCXX/header-unit-friend-within-class-linkage.cpp b/clang/test/CodeGenCXX/header-unit-friend-within-class-linkage.cpp
new file mode 100644
index 0000000000000..cfee317ba6b2d
--- /dev/null
+++ b/clang/test/CodeGenCXX/header-unit-friend-within-class-linkage.cpp
@@ -0,0 +1,27 @@
+// Tests that the friend function with-in an class definition in the header unit is still implicit inline.
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple -xc++-user-header -emit-header-unit %t/foo.h -o %t/foo.pcm
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple -fmodule-file=%t/foo.pcm %t/user.cpp \
+// RUN: -S -emit-llvm -disable-llvm-passes -o - | FileCheck %t/user.cpp
+
+//--- foo.h
+class foo {
+ int value;
+public:
+ foo(int v) : value(v) {}
+
+ friend int getFooValue(foo f) {
+ return f.value;
+ }
+};
+
+//--- user.cpp
+import "foo.h";
+int use() {
+ foo f(43);
+ return getFooValue(f);
+}
+
+// CHECK: define{{.*}}linkonce_odr{{.*}}@_Z11getFooValue3foo
diff --git a/clang/test/CodeGenCXX/header-unit-member-func-linkage.cpp b/clang/test/CodeGenCXX/header-unit-member-func-linkage.cpp
new file mode 100644
index 0000000000000..5ab15dff01589
--- /dev/null
+++ b/clang/test/CodeGenCXX/header-unit-member-func-linkage.cpp
@@ -0,0 +1,24 @@
+// Tests that the member function with-in an class definition in the header unit is still implicit inline.
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple -xc++-user-header -emit-header-unit %t/foo.h -o %t/foo.pcm
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple -fmodule-file=%t/foo.pcm %t/user.cpp \
+// RUN: -S -emit-llvm -disable-llvm-passes -o - | FileCheck %t/user.cpp
+
+//--- foo.h
+class foo {
+public:
+ int getValue() {
+ return 43;
+ }
+};
+
+//--- user.cpp
+import "foo.h";
+int use() {
+ foo f;
+ return f.getValue();
+}
+
+// CHECK: define{{.*}}linkonce_odr{{.*}}@_ZN3foo8getValueEv
diff --git a/clang/unittests/AST/DeclTest.cpp b/clang/unittests/AST/DeclTest.cpp
index 7fe715db52979..43a3798867f49 100644
--- a/clang/unittests/AST/DeclTest.cpp
+++ b/clang/unittests/AST/DeclTest.cpp
@@ -311,3 +311,46 @@ TEST(Decl, MemberFunctionInModules) {
EXPECT_TRUE(bar->isInlined());
}
+TEST(Decl, MemberFunctionInHeaderUnit) {
+ llvm::Annotations Code(R"(
+ class foo {
+ public:
+ int memFn() {
+ return 43;
+ }
+ };
+ )");
+
+ auto AST = tooling::buildASTFromCodeWithArgs(
+ Code.code(), {"-std=c++20", " -xc++-user-header ", "-emit-header-unit"});
+ ASTContext &Ctx = AST->getASTContext();
+
+ auto *memFn = selectFirst<FunctionDecl>(
+ "memFn", match(functionDecl(hasName("memFn")).bind("memFn"), Ctx));
+
+ EXPECT_TRUE(memFn->isInlined());
+}
+
+TEST(Decl, FriendFunctionWithinClassInHeaderUnit) {
+ llvm::Annotations Code(R"(
+ class foo {
+ int value;
+ public:
+ foo(int v) : value(v) {}
+
+ friend int getFooValue(foo f) {
+ return f.value;
+ }
+ };
+ )");
+
+ auto AST = tooling::buildASTFromCodeWithArgs(
+ Code.code(), {"-std=c++20", " -xc++-user-header ", "-emit-header-unit"});
+ ASTContext &Ctx = AST->getASTContext();
+
+ auto *getFooValue = selectFirst<FunctionDecl>(
+ "getFooValue",
+ match(functionDecl(hasName("getFooValue")).bind("getFooValue"), Ctx));
+
+ EXPECT_TRUE(getFooValue->isInlined());
+}
More information about the cfe-commits
mailing list