Author: Chuanqi Xu
Date: 2026-06-03T17:19:41+08:00
New Revision: 74f1c9417e916aed314fd429ce2faee49668ffa6

URL: 
https://github.com/llvm/llvm-project/commit/74f1c9417e916aed314fd429ce2faee49668ffa6
DIFF: 
https://github.com/llvm/llvm-project/commit/74f1c9417e916aed314fd429ce2faee49668ffa6.diff

LOG: [C++20] [Modules] Ask for definition before calling 
isInlineDefinitionExternallyVisible (#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 does the similar thing.

Added: 
    clang/test/Modules/pr195905.cppm

Modified: 
    clang/lib/AST/ASTContext.cpp

Removed: 
    


################################################################################
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


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to