[clang] [C++20] [Modules] Ask for definition before calling isInlineDefinitionExternallyVisible (PR #201291)
Chuanqi Xu via cfe-commits
cfe-commits at lists.llvm.org
Wed Jun 3 01:15:01 PDT 2026
https://github.com/ChuanqiXu9 created https://github.com/llvm/llvm-project/pull/201291
Close https://github.com/llvm/llvm-project/issues/195905
The root cause of the problem is, after decl merging, one of the destructor for `base` (see test case) is chosen, and its body is not deserialized for performance as we alreday see its body in current TU. And then, the code call
FunctionDecl::isInlineDefinitionExternallyVisible from the destructor without a serialized body, but
FunctionDecl::isInlineDefinitionExternallyVisible's implementation requires to see a body. Then assertion failed.
Decl merging and function decl merging is common. We can't always make sure we find the definition without checking. It is much more fundamental. So the PR doesn't try to touch the decl merging mechanism or how we handle the result of lookups.
We tried to fix the issue at the calling point to make sure we have a definition for isInlineDefinitionExternallyVisible. Other use of isInlineDefinitionExternallyVisible the similar thing.
>From abb389950ef9a900bcf1ce1f7ff6992a90258e2a Mon Sep 17 00:00:00 2001
From: Chuanqi Xu <yedeng.yd at linux.alibaba.com>
Date: Wed, 3 Jun 2026 16:04:50 +0800
Subject: [PATCH] [C++20] [Modules] Ask for definition before calling
isInlineDefinitionExternallyVisible
Close https://github.com/llvm/llvm-project/issues/195905
The root cause of the problem is, after decl merging, one of the
destructor for `base` (see test case) is chosen, and its body is not
deserialized for performance as we alreday see its body in current TU.
And then, the code call
FunctionDecl::isInlineDefinitionExternallyVisible from the destructor
without a serialized body, but
FunctionDecl::isInlineDefinitionExternallyVisible's implementation
requires to see a body. Then assertion failed.
Decl merging and function decl merging is common. We can't always make
sure we find the definition without checking. It is much
more fundamental. So the PR doesn't try to touch the decl merging
mechanism or how we handle the result of lookups.
We tried to fix the issue at the calling point to make sure we have
a definition for isInlineDefinitionExternallyVisible. Other use of
isInlineDefinitionExternallyVisible the similar thing.
---
clang/lib/AST/ASTContext.cpp | 3 ++-
clang/test/Modules/pr195905.cppm | 42 ++++++++++++++++++++++++++++++++
2 files changed, 44 insertions(+), 1 deletion(-)
create mode 100644 clang/test/Modules/pr195905.cppm
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index a401a7471e6fc..1e35aba7b2b19 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -13064,7 +13064,8 @@ static GVALinkage basicGVALinkageForFunction(const ASTContext &Context,
// GNU or C99 inline semantics. Determine whether this symbol should be
// externally visible.
- if (FD->isInlineDefinitionExternallyVisible())
+ if (auto *Def = FD->getDefinition();
+ Def && Def->isInlineDefinitionExternallyVisible())
return External;
// C99 inline semantics, where the symbol is not externally visible.
diff --git a/clang/test/Modules/pr195905.cppm b/clang/test/Modules/pr195905.cppm
new file mode 100644
index 0000000000000..d107549ab10ea
--- /dev/null
+++ b/clang/test/Modules/pr195905.cppm
@@ -0,0 +1,42 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++26 %t/a.cppm \
+// RUN: -emit-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++26 %t/b.cppm \
+// RUN: -fmodule-file=a=%t/a.pcm -emit-llvm -Og -mconstructor-aliases \
+// RUN: -o - | FileCheck %t/b.cppm
+
+//--- base.hpp
+struct base {
+ [[__gnu__::__gnu_inline__]] inline ~base() {}
+};
+
+//--- a.cppm
+module;
+
+#include "base.hpp"
+
+export module a;
+
+export using ::base;
+
+//--- b.cppm
+module;
+
+#include "base.hpp"
+
+export module b;
+
+import a;
+
+struct derived : base {
+};
+
+void f() {
+ derived x;
+}
+
+// fine enough to check it won't crash
+// CHECK: define {{.*}}@_ZGIW1b
More information about the cfe-commits
mailing list