[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