Skip to content

[Clang][Modules] FE crashes when constructor using-decl are built in header units #134739

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
yuxuanchen1997 opened this issue Apr 7, 2025 · 8 comments
Assignees
Labels
c++20 clang:modules C++20 modules and Clang Header Modules crash-on-valid

Comments

@yuxuanchen1997
Copy link
Member

When upstream clang has assertion turned on, we crash on the following input:

File: RelaxedAtomic.h

struct relaxed_atomic_base {
  relaxed_atomic_base(int) {}
};

struct relaxed_atomic : relaxed_atomic_base {
  using relaxed_atomic_base::relaxed_atomic_base; // constructor
};

File: SharedMutex.h

import "RelaxedAtomic.h";

inline void getMaxDeferredReaders() {
  static relaxed_atomic cache{0};
}

File: ThreadLocalDetail.h

import "RelaxedAtomic.h";

struct noncopyable {
  noncopyable(const noncopyable&) = delete;
};

struct StaticMetaBase {
  relaxed_atomic nextId_{0};
  noncopyable ncp;
};

Repro commands:

CXXFLAGS="-std=c++20 -Wno-experimental-header-units"

clang++ $(CXXFLAGS) -fmodule-header RelaxedAtomic.h -o RelaxedAtomic.pcm
clang++ $(CXXFLAGS) -fmodule-header -fmodule-file=RelaxedAtomic.pcm SharedMutex.h -o SharedMutex.pcm
clang++ $(CXXFLAGS) -fmodule-header -fmodule-file=SharedMutex.pcm -fmodule-file=RelaxedAtomic.pcm ThreadLocalDetail.h -o ThreadLocalDetail.pcm

On the third invocation of clang, we crash with the following back trace:

clang-21: /home/ych/llvm-project/clang/lib/Serialization/ASTWriter.cpp:4662: void clang::ASTWriter::GenerateNameLookupTable(ASTContext &, const DeclContext *, llvm::SmallVectorImpl<char> &, llvm::SmallVectorImpl<char> &, llvm::SmallVectorImpl<char> &): Assertion `ConstructorNameSet.empty() && "Failed to find all of the visible " "constructors by walking all the " "lexical members of the context."' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0.      Program arguments: /data/users/ych/server-llvm/llvm-project/build/bin/clang-21 -std=c++20 -Wno-experimental-header-units -fmodule-header -fmodule-file=SharedMutex.pcm -fmodule-file=RelaxedAtomic.pcm ThreadLocalDetail.h -o ThreadLocalDetail.pcm
1.      <eof> parser at end of file
 #0 0x000000000723967d llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) /home/ych/llvm-project/llvm/lib/Support/Unix/Signals.inc:804:11
 #1 0x0000000007239b3b PrintStackTraceSignalHandler(void*) /home/ych/llvm-project/llvm/lib/Support/Unix/Signals.inc:880:1
 #2 0x0000000007237cdf llvm::sys::RunSignalHandlers() /home/ych/llvm-project/llvm/lib/Support/Signals.cpp:105:5
 #3 0x0000000007238f89 llvm::sys::CleanupOnSignal(unsigned long) /home/ych/llvm-project/llvm/lib/Support/Unix/Signals.inc:370:1
 #4 0x0000000007164cb2 (anonymous namespace)::CrashRecoveryContextImpl::HandleCrash(int, unsigned long) CrashRecoveryContext.cpp:0:0
 #5 0x0000000007165016 CrashRecoverySignalHandler(int) /home/ych/llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp:391:1
 #6 0x00007f5b30a3ebf0 __restore_rt (/lib64/libc.so.6+0x3ebf0)
 #7 0x00007f5b30a8be0c __pthread_kill_implementation (/lib64/libc.so.6+0x8be0c)
 #8 0x00007f5b30a3eb46 gsignal (/lib64/libc.so.6+0x3eb46)
 #9 0x00007f5b30a28833 abort (/lib64/libc.so.6+0x28833)
#10 0x00007f5b30a2875b _nl_load_domain.cold (/lib64/libc.so.6+0x2875b)
#11 0x00007f5b30a37886 (/lib64/libc.so.6+0x37886)
#12 0x0000000008cd3f0f clang::ASTWriter::GenerateNameLookupTable(clang::ASTContext&, clang::DeclContext const*, llvm::SmallVectorImpl<char>&, llvm::SmallVectorImpl<char>&, llvm::SmallVectorImpl<char>&) /home/ych/llvm-project/clang/lib/Serialization/ASTWriter.cpp:4663:5
#13 0x0000000008cd6687 clang::ASTWriter::WriteDeclContextVisibleUpdate(clang::ASTContext&, clang::DeclContext const*) /home/ych/llvm-project/clang/lib/Serialization/ASTWriter.cpp:4912:7
#14 0x0000000008cf0c71 clang::ASTWriter::WriteDeclAndTypes(clang::ASTContext&) /home/ych/llvm-project/clang/lib/Serialization/ASTWriter.cpp:6321:17
#15 0x0000000008cec5c0 clang::ASTWriter::WriteASTCore(clang::Sema*, llvm::StringRef, clang::Module*) (/data/users/ych/server-llvm/llvm-project/build/bin/clang-21+0x8cec5c0)
#16 0x0000000008ceb87c clang::ASTWriter::WriteAST(llvm::PointerUnion<clang::Sema*, clang::Preprocessor*>, llvm::StringRef, clang::Module*, llvm::StringRef, bool) /home/ych/llvm-project/clang/lib/Serialization/ASTWriter.cpp:5377:32
#17 0x0000000008db6617 clang::PCHGenerator::HandleTranslationUnit(clang::ASTContext&) /home/ych/llvm-project/clang/lib/Serialization/GeneratePCH.cpp:86:30
#18 0x0000000008a2c3fc clang::MultiplexConsumer::HandleTranslationUnit(clang::ASTContext&) /home/ych/llvm-project/clang/lib/Frontend/MultiplexConsumer.cpp:338:23
#19 0x000000000a9c29ab clang::ParseAST(clang::Sema&, bool, bool) /home/ych/llvm-project/clang/lib/Parse/ParseAST.cpp:191:12
#20 0x00000000088c0777 clang::ASTFrontendAction::ExecuteAction() /home/ych/llvm-project/clang/lib/Frontend/FrontendAction.cpp:1188:1
#21 0x00000000088c01d6 clang::FrontendAction::Execute() /home/ych/llvm-project/clang/lib/Frontend/FrontendAction.cpp:1076:7
#22 0x00000000087e3211 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) /home/ych/llvm-project/clang/lib/Frontend/CompilerInstance.cpp:1056:23
#23 0x0000000008a842aa clang::ExecuteCompilerInvocation(clang::CompilerInstance*) /home/ych/llvm-project/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp:280:8
#24 0x000000000539731e cc1_main(llvm::ArrayRef<char const*>, char const*, void*) /home/ych/llvm-project/clang/tools/driver/cc1_main.cpp:290:13
#25 0x000000000538a3ae ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) /home/ych/llvm-project/clang/tools/driver/driver.cpp:218:5
#26 0x000000000538ae20 clang_main(int, char**, llvm::ToolContext const&)::$_0::operator()(llvm::SmallVectorImpl<char const*>&) const /home/ych/llvm-project/clang/tools/driver/driver.cpp:364:9
#27 0x000000000538aded int llvm::function_ref<int (llvm::SmallVectorImpl<char const*>&)>::callback_fn<clang_main(int, char**, llvm::ToolContext const&)::$_0>(long, llvm::SmallVectorImpl<char const*>&) /home/ych/llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:46:5
#28 0x0000000008657b61 llvm::function_ref<int (llvm::SmallVectorImpl<char const*>&)>::operator()(llvm::SmallVectorImpl<char const*>&) const /home/ych/llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:69:5
#29 0x00000000086546d8 clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const::$_0::operator()() const /home/ych/llvm-project/clang/lib/Driver/Job.cpp:437:34
#30 0x00000000086546a5 void llvm::function_ref<void ()>::callback_fn<clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const::$_0>(long) /home/ych/llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:46:5
#31 0x0000000005e95649 llvm::function_ref<void ()>::operator()() const /home/ych/llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:69:5
#32 0x0000000007164acf llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) /home/ych/llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp:427:3
#33 0x0000000008654093 clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const /home/ych/llvm-project/clang/lib/Driver/Job.cpp:437:7
#34 0x00000000085ee322 clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const /home/ych/llvm-project/clang/lib/Driver/Compilation.cpp:196:15
#35 0x00000000085ee4fc clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&, bool) const /home/ych/llvm-project/clang/lib/Driver/Compilation.cpp:251:13
#36 0x0000000008609c91 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&) /home/ych/llvm-project/clang/lib/Driver/Driver.cpp:2166:7
#37 0x0000000005389ec7 clang_main(int, char**, llvm::ToolContext const&) /home/ych/llvm-project/clang/tools/driver/driver.cpp:402:9
#38 0x00000000053bbfb5 main /home/ych/llvm-project/build/tools/clang/tools/driver/clang-driver.cpp:17:3
#39 0x00007f5b30a295d0 __libc_start_call_main (/lib64/libc.so.6+0x295d0)
#40 0x00007f5b30a29680 __libc_start_main@GLIBC_2.2.5 (/lib64/libc.so.6+0x29680)
#41 0x0000000005388c25 _start (/data/users/ych/server-llvm/llvm-project/build/bin/clang-21+0x5388c25)

Note that ThreadLocalDetail.h doesn't actually import "SharedMutex.h". If you remove -fmodule-file=SharedMutex.pcm part this compilation succeeds. I also can't get it to repro when the using decl in relaxed_atomic is replaced with its own constructor.

@llvmbot llvmbot added the clang Clang issues not falling into any other category label Apr 7, 2025
@yuxuanchen1997 yuxuanchen1997 added c++20 clang:modules C++20 modules and Clang Header Modules and removed clang Clang issues not falling into any other category labels Apr 7, 2025
@llvmbot
Copy link
Member

llvmbot commented Apr 7, 2025

@llvm/issue-subscribers-c-20

Author: Yuxuan Chen (yuxuanchen1997)

When upstream clang has assertion turned on, we crash on the following input:

File: RelaxedAtomic.h

struct relaxed_atomic_base {
  relaxed_atomic_base(int) {}
};

struct relaxed_atomic : relaxed_atomic_base {
  using relaxed_atomic_base::relaxed_atomic_base; // constructor
};

File: SharedMutex.h

import "RelaxedAtomic.h";

inline void getMaxDeferredReaders() {
  static relaxed_atomic cache{0};
}

File: ThreadLocalDetail.h

import "RelaxedAtomic.h";

struct noncopyable {
  noncopyable(const noncopyable&amp;) = delete;
};

struct StaticMetaBase {
  relaxed_atomic nextId_{0};
  noncopyable ncp;
};

Repro commands:

CXXFLAGS="-std=c++20 -Wno-experimental-header-units"

clang++ $(CXXFLAGS) -fmodule-header RelaxedAtomic.h -o RelaxedAtomic.pcm
clang++ $(CXXFLAGS) -fmodule-header -fmodule-file=RelaxedAtomic.pcm SharedMutex.h -o SharedMutex.pcm
clang++ $(CXXFLAGS) -fmodule-header -fmodule-file=SharedMutex.pcm -fmodule-file=RelaxedAtomic.pcm ThreadLocalDetail.h -o ThreadLocalDetail.pcm

On the third invocation of clang, we crash with the following back trace:

clang-21: /home/ych/llvm-project/clang/lib/Serialization/ASTWriter.cpp:4662: void clang::ASTWriter::GenerateNameLookupTable(ASTContext &amp;, const DeclContext *, llvm::SmallVectorImpl&lt;char&gt; &amp;, llvm::SmallVectorImpl&lt;char&gt; &amp;, llvm::SmallVectorImpl&lt;char&gt; &amp;): Assertion `ConstructorNameSet.empty() &amp;&amp; "Failed to find all of the visible " "constructors by walking all the " "lexical members of the context."' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0.      Program arguments: /data/users/ych/server-llvm/llvm-project/build/bin/clang-21 -std=c++20 -Wno-experimental-header-units -fmodule-header -fmodule-file=SharedMutex.pcm -fmodule-file=RelaxedAtomic.pcm ThreadLocalDetail.h -o ThreadLocalDetail.pcm
1.      &lt;eof&gt; parser at end of file
 #<!-- -->0 0x000000000723967d llvm::sys::PrintStackTrace(llvm::raw_ostream&amp;, int) /home/ych/llvm-project/llvm/lib/Support/Unix/Signals.inc:804:11
 #<!-- -->1 0x0000000007239b3b PrintStackTraceSignalHandler(void*) /home/ych/llvm-project/llvm/lib/Support/Unix/Signals.inc:880:1
 #<!-- -->2 0x0000000007237cdf llvm::sys::RunSignalHandlers() /home/ych/llvm-project/llvm/lib/Support/Signals.cpp:105:5
 #<!-- -->3 0x0000000007238f89 llvm::sys::CleanupOnSignal(unsigned long) /home/ych/llvm-project/llvm/lib/Support/Unix/Signals.inc:370:1
 #<!-- -->4 0x0000000007164cb2 (anonymous namespace)::CrashRecoveryContextImpl::HandleCrash(int, unsigned long) CrashRecoveryContext.cpp:0:0
 #<!-- -->5 0x0000000007165016 CrashRecoverySignalHandler(int) /home/ych/llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp:391:1
 #<!-- -->6 0x00007f5b30a3ebf0 __restore_rt (/lib64/libc.so.6+0x3ebf0)
 #<!-- -->7 0x00007f5b30a8be0c __pthread_kill_implementation (/lib64/libc.so.6+0x8be0c)
 #<!-- -->8 0x00007f5b30a3eb46 gsignal (/lib64/libc.so.6+0x3eb46)
 #<!-- -->9 0x00007f5b30a28833 abort (/lib64/libc.so.6+0x28833)
#<!-- -->10 0x00007f5b30a2875b _nl_load_domain.cold (/lib64/libc.so.6+0x2875b)
#<!-- -->11 0x00007f5b30a37886 (/lib64/libc.so.6+0x37886)
#<!-- -->12 0x0000000008cd3f0f clang::ASTWriter::GenerateNameLookupTable(clang::ASTContext&amp;, clang::DeclContext const*, llvm::SmallVectorImpl&lt;char&gt;&amp;, llvm::SmallVectorImpl&lt;char&gt;&amp;, llvm::SmallVectorImpl&lt;char&gt;&amp;) /home/ych/llvm-project/clang/lib/Serialization/ASTWriter.cpp:4663:5
#<!-- -->13 0x0000000008cd6687 clang::ASTWriter::WriteDeclContextVisibleUpdate(clang::ASTContext&amp;, clang::DeclContext const*) /home/ych/llvm-project/clang/lib/Serialization/ASTWriter.cpp:4912:7
#<!-- -->14 0x0000000008cf0c71 clang::ASTWriter::WriteDeclAndTypes(clang::ASTContext&amp;) /home/ych/llvm-project/clang/lib/Serialization/ASTWriter.cpp:6321:17
#<!-- -->15 0x0000000008cec5c0 clang::ASTWriter::WriteASTCore(clang::Sema*, llvm::StringRef, clang::Module*) (/data/users/ych/server-llvm/llvm-project/build/bin/clang-21+0x8cec5c0)
#<!-- -->16 0x0000000008ceb87c clang::ASTWriter::WriteAST(llvm::PointerUnion&lt;clang::Sema*, clang::Preprocessor*&gt;, llvm::StringRef, clang::Module*, llvm::StringRef, bool) /home/ych/llvm-project/clang/lib/Serialization/ASTWriter.cpp:5377:32
#<!-- -->17 0x0000000008db6617 clang::PCHGenerator::HandleTranslationUnit(clang::ASTContext&amp;) /home/ych/llvm-project/clang/lib/Serialization/GeneratePCH.cpp:86:30
#<!-- -->18 0x0000000008a2c3fc clang::MultiplexConsumer::HandleTranslationUnit(clang::ASTContext&amp;) /home/ych/llvm-project/clang/lib/Frontend/MultiplexConsumer.cpp:338:23
#<!-- -->19 0x000000000a9c29ab clang::ParseAST(clang::Sema&amp;, bool, bool) /home/ych/llvm-project/clang/lib/Parse/ParseAST.cpp:191:12
#<!-- -->20 0x00000000088c0777 clang::ASTFrontendAction::ExecuteAction() /home/ych/llvm-project/clang/lib/Frontend/FrontendAction.cpp:1188:1
#<!-- -->21 0x00000000088c01d6 clang::FrontendAction::Execute() /home/ych/llvm-project/clang/lib/Frontend/FrontendAction.cpp:1076:7
#<!-- -->22 0x00000000087e3211 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&amp;) /home/ych/llvm-project/clang/lib/Frontend/CompilerInstance.cpp:1056:23
#<!-- -->23 0x0000000008a842aa clang::ExecuteCompilerInvocation(clang::CompilerInstance*) /home/ych/llvm-project/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp:280:8
#<!-- -->24 0x000000000539731e cc1_main(llvm::ArrayRef&lt;char const*&gt;, char const*, void*) /home/ych/llvm-project/clang/tools/driver/cc1_main.cpp:290:13
#<!-- -->25 0x000000000538a3ae ExecuteCC1Tool(llvm::SmallVectorImpl&lt;char const*&gt;&amp;, llvm::ToolContext const&amp;) /home/ych/llvm-project/clang/tools/driver/driver.cpp:218:5
#<!-- -->26 0x000000000538ae20 clang_main(int, char**, llvm::ToolContext const&amp;)::$_0::operator()(llvm::SmallVectorImpl&lt;char const*&gt;&amp;) const /home/ych/llvm-project/clang/tools/driver/driver.cpp:364:9
#<!-- -->27 0x000000000538aded int llvm::function_ref&lt;int (llvm::SmallVectorImpl&lt;char const*&gt;&amp;)&gt;::callback_fn&lt;clang_main(int, char**, llvm::ToolContext const&amp;)::$_0&gt;(long, llvm::SmallVectorImpl&lt;char const*&gt;&amp;) /home/ych/llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:46:5
#<!-- -->28 0x0000000008657b61 llvm::function_ref&lt;int (llvm::SmallVectorImpl&lt;char const*&gt;&amp;)&gt;::operator()(llvm::SmallVectorImpl&lt;char const*&gt;&amp;) const /home/ych/llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:69:5
#<!-- -->29 0x00000000086546d8 clang::driver::CC1Command::Execute(llvm::ArrayRef&lt;std::optional&lt;llvm::StringRef&gt;&gt;, std::__cxx11::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt;&gt;*, bool*) const::$_0::operator()() const /home/ych/llvm-project/clang/lib/Driver/Job.cpp:437:34
#<!-- -->30 0x00000000086546a5 void llvm::function_ref&lt;void ()&gt;::callback_fn&lt;clang::driver::CC1Command::Execute(llvm::ArrayRef&lt;std::optional&lt;llvm::StringRef&gt;&gt;, std::__cxx11::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt;&gt;*, bool*) const::$_0&gt;(long) /home/ych/llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:46:5
#<!-- -->31 0x0000000005e95649 llvm::function_ref&lt;void ()&gt;::operator()() const /home/ych/llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:69:5
#<!-- -->32 0x0000000007164acf llvm::CrashRecoveryContext::RunSafely(llvm::function_ref&lt;void ()&gt;) /home/ych/llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp:427:3
#<!-- -->33 0x0000000008654093 clang::driver::CC1Command::Execute(llvm::ArrayRef&lt;std::optional&lt;llvm::StringRef&gt;&gt;, std::__cxx11::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt;&gt;*, bool*) const /home/ych/llvm-project/clang/lib/Driver/Job.cpp:437:7
#<!-- -->34 0x00000000085ee322 clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&amp;, clang::driver::Command const*&amp;, bool) const /home/ych/llvm-project/clang/lib/Driver/Compilation.cpp:196:15
#<!-- -->35 0x00000000085ee4fc clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&amp;, llvm::SmallVectorImpl&lt;std::pair&lt;int, clang::driver::Command const*&gt;&gt;&amp;, bool) const /home/ych/llvm-project/clang/lib/Driver/Compilation.cpp:251:13
#<!-- -->36 0x0000000008609c91 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&amp;, llvm::SmallVectorImpl&lt;std::pair&lt;int, clang::driver::Command const*&gt;&gt;&amp;) /home/ych/llvm-project/clang/lib/Driver/Driver.cpp:2166:7
#<!-- -->37 0x0000000005389ec7 clang_main(int, char**, llvm::ToolContext const&amp;) /home/ych/llvm-project/clang/tools/driver/driver.cpp:402:9
#<!-- -->38 0x00000000053bbfb5 main /home/ych/llvm-project/build/tools/clang/tools/driver/clang-driver.cpp:17:3
#<!-- -->39 0x00007f5b30a295d0 __libc_start_call_main (/lib64/libc.so.6+0x295d0)
#<!-- -->40 0x00007f5b30a29680 __libc_start_main@<!-- -->GLIBC_2.2.5 (/lib64/libc.so.6+0x29680)
#<!-- -->41 0x0000000005388c25 _start (/data/users/ych/server-llvm/llvm-project/build/bin/clang-21+0x5388c25)

Note that ThreadLocalDetail.h doesn't actually import "SharedMutex.h". If you remove -fmodule-file=SharedMutex.pcm part this compilation succeeds. I also can't get it to repro when the using decl in relaxed_atomic is replaced with its own constructor.

@llvmbot
Copy link
Member

llvmbot commented Apr 7, 2025

@llvm/issue-subscribers-clang-modules

Author: Yuxuan Chen (yuxuanchen1997)

When upstream clang has assertion turned on, we crash on the following input:

File: RelaxedAtomic.h

struct relaxed_atomic_base {
  relaxed_atomic_base(int) {}
};

struct relaxed_atomic : relaxed_atomic_base {
  using relaxed_atomic_base::relaxed_atomic_base; // constructor
};

File: SharedMutex.h

import "RelaxedAtomic.h";

inline void getMaxDeferredReaders() {
  static relaxed_atomic cache{0};
}

File: ThreadLocalDetail.h

import "RelaxedAtomic.h";

struct noncopyable {
  noncopyable(const noncopyable&amp;) = delete;
};

struct StaticMetaBase {
  relaxed_atomic nextId_{0};
  noncopyable ncp;
};

Repro commands:

CXXFLAGS="-std=c++20 -Wno-experimental-header-units"

clang++ $(CXXFLAGS) -fmodule-header RelaxedAtomic.h -o RelaxedAtomic.pcm
clang++ $(CXXFLAGS) -fmodule-header -fmodule-file=RelaxedAtomic.pcm SharedMutex.h -o SharedMutex.pcm
clang++ $(CXXFLAGS) -fmodule-header -fmodule-file=SharedMutex.pcm -fmodule-file=RelaxedAtomic.pcm ThreadLocalDetail.h -o ThreadLocalDetail.pcm

On the third invocation of clang, we crash with the following back trace:

clang-21: /home/ych/llvm-project/clang/lib/Serialization/ASTWriter.cpp:4662: void clang::ASTWriter::GenerateNameLookupTable(ASTContext &amp;, const DeclContext *, llvm::SmallVectorImpl&lt;char&gt; &amp;, llvm::SmallVectorImpl&lt;char&gt; &amp;, llvm::SmallVectorImpl&lt;char&gt; &amp;): Assertion `ConstructorNameSet.empty() &amp;&amp; "Failed to find all of the visible " "constructors by walking all the " "lexical members of the context."' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0.      Program arguments: /data/users/ych/server-llvm/llvm-project/build/bin/clang-21 -std=c++20 -Wno-experimental-header-units -fmodule-header -fmodule-file=SharedMutex.pcm -fmodule-file=RelaxedAtomic.pcm ThreadLocalDetail.h -o ThreadLocalDetail.pcm
1.      &lt;eof&gt; parser at end of file
 #<!-- -->0 0x000000000723967d llvm::sys::PrintStackTrace(llvm::raw_ostream&amp;, int) /home/ych/llvm-project/llvm/lib/Support/Unix/Signals.inc:804:11
 #<!-- -->1 0x0000000007239b3b PrintStackTraceSignalHandler(void*) /home/ych/llvm-project/llvm/lib/Support/Unix/Signals.inc:880:1
 #<!-- -->2 0x0000000007237cdf llvm::sys::RunSignalHandlers() /home/ych/llvm-project/llvm/lib/Support/Signals.cpp:105:5
 #<!-- -->3 0x0000000007238f89 llvm::sys::CleanupOnSignal(unsigned long) /home/ych/llvm-project/llvm/lib/Support/Unix/Signals.inc:370:1
 #<!-- -->4 0x0000000007164cb2 (anonymous namespace)::CrashRecoveryContextImpl::HandleCrash(int, unsigned long) CrashRecoveryContext.cpp:0:0
 #<!-- -->5 0x0000000007165016 CrashRecoverySignalHandler(int) /home/ych/llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp:391:1
 #<!-- -->6 0x00007f5b30a3ebf0 __restore_rt (/lib64/libc.so.6+0x3ebf0)
 #<!-- -->7 0x00007f5b30a8be0c __pthread_kill_implementation (/lib64/libc.so.6+0x8be0c)
 #<!-- -->8 0x00007f5b30a3eb46 gsignal (/lib64/libc.so.6+0x3eb46)
 #<!-- -->9 0x00007f5b30a28833 abort (/lib64/libc.so.6+0x28833)
#<!-- -->10 0x00007f5b30a2875b _nl_load_domain.cold (/lib64/libc.so.6+0x2875b)
#<!-- -->11 0x00007f5b30a37886 (/lib64/libc.so.6+0x37886)
#<!-- -->12 0x0000000008cd3f0f clang::ASTWriter::GenerateNameLookupTable(clang::ASTContext&amp;, clang::DeclContext const*, llvm::SmallVectorImpl&lt;char&gt;&amp;, llvm::SmallVectorImpl&lt;char&gt;&amp;, llvm::SmallVectorImpl&lt;char&gt;&amp;) /home/ych/llvm-project/clang/lib/Serialization/ASTWriter.cpp:4663:5
#<!-- -->13 0x0000000008cd6687 clang::ASTWriter::WriteDeclContextVisibleUpdate(clang::ASTContext&amp;, clang::DeclContext const*) /home/ych/llvm-project/clang/lib/Serialization/ASTWriter.cpp:4912:7
#<!-- -->14 0x0000000008cf0c71 clang::ASTWriter::WriteDeclAndTypes(clang::ASTContext&amp;) /home/ych/llvm-project/clang/lib/Serialization/ASTWriter.cpp:6321:17
#<!-- -->15 0x0000000008cec5c0 clang::ASTWriter::WriteASTCore(clang::Sema*, llvm::StringRef, clang::Module*) (/data/users/ych/server-llvm/llvm-project/build/bin/clang-21+0x8cec5c0)
#<!-- -->16 0x0000000008ceb87c clang::ASTWriter::WriteAST(llvm::PointerUnion&lt;clang::Sema*, clang::Preprocessor*&gt;, llvm::StringRef, clang::Module*, llvm::StringRef, bool) /home/ych/llvm-project/clang/lib/Serialization/ASTWriter.cpp:5377:32
#<!-- -->17 0x0000000008db6617 clang::PCHGenerator::HandleTranslationUnit(clang::ASTContext&amp;) /home/ych/llvm-project/clang/lib/Serialization/GeneratePCH.cpp:86:30
#<!-- -->18 0x0000000008a2c3fc clang::MultiplexConsumer::HandleTranslationUnit(clang::ASTContext&amp;) /home/ych/llvm-project/clang/lib/Frontend/MultiplexConsumer.cpp:338:23
#<!-- -->19 0x000000000a9c29ab clang::ParseAST(clang::Sema&amp;, bool, bool) /home/ych/llvm-project/clang/lib/Parse/ParseAST.cpp:191:12
#<!-- -->20 0x00000000088c0777 clang::ASTFrontendAction::ExecuteAction() /home/ych/llvm-project/clang/lib/Frontend/FrontendAction.cpp:1188:1
#<!-- -->21 0x00000000088c01d6 clang::FrontendAction::Execute() /home/ych/llvm-project/clang/lib/Frontend/FrontendAction.cpp:1076:7
#<!-- -->22 0x00000000087e3211 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&amp;) /home/ych/llvm-project/clang/lib/Frontend/CompilerInstance.cpp:1056:23
#<!-- -->23 0x0000000008a842aa clang::ExecuteCompilerInvocation(clang::CompilerInstance*) /home/ych/llvm-project/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp:280:8
#<!-- -->24 0x000000000539731e cc1_main(llvm::ArrayRef&lt;char const*&gt;, char const*, void*) /home/ych/llvm-project/clang/tools/driver/cc1_main.cpp:290:13
#<!-- -->25 0x000000000538a3ae ExecuteCC1Tool(llvm::SmallVectorImpl&lt;char const*&gt;&amp;, llvm::ToolContext const&amp;) /home/ych/llvm-project/clang/tools/driver/driver.cpp:218:5
#<!-- -->26 0x000000000538ae20 clang_main(int, char**, llvm::ToolContext const&amp;)::$_0::operator()(llvm::SmallVectorImpl&lt;char const*&gt;&amp;) const /home/ych/llvm-project/clang/tools/driver/driver.cpp:364:9
#<!-- -->27 0x000000000538aded int llvm::function_ref&lt;int (llvm::SmallVectorImpl&lt;char const*&gt;&amp;)&gt;::callback_fn&lt;clang_main(int, char**, llvm::ToolContext const&amp;)::$_0&gt;(long, llvm::SmallVectorImpl&lt;char const*&gt;&amp;) /home/ych/llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:46:5
#<!-- -->28 0x0000000008657b61 llvm::function_ref&lt;int (llvm::SmallVectorImpl&lt;char const*&gt;&amp;)&gt;::operator()(llvm::SmallVectorImpl&lt;char const*&gt;&amp;) const /home/ych/llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:69:5
#<!-- -->29 0x00000000086546d8 clang::driver::CC1Command::Execute(llvm::ArrayRef&lt;std::optional&lt;llvm::StringRef&gt;&gt;, std::__cxx11::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt;&gt;*, bool*) const::$_0::operator()() const /home/ych/llvm-project/clang/lib/Driver/Job.cpp:437:34
#<!-- -->30 0x00000000086546a5 void llvm::function_ref&lt;void ()&gt;::callback_fn&lt;clang::driver::CC1Command::Execute(llvm::ArrayRef&lt;std::optional&lt;llvm::StringRef&gt;&gt;, std::__cxx11::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt;&gt;*, bool*) const::$_0&gt;(long) /home/ych/llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:46:5
#<!-- -->31 0x0000000005e95649 llvm::function_ref&lt;void ()&gt;::operator()() const /home/ych/llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:69:5
#<!-- -->32 0x0000000007164acf llvm::CrashRecoveryContext::RunSafely(llvm::function_ref&lt;void ()&gt;) /home/ych/llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp:427:3
#<!-- -->33 0x0000000008654093 clang::driver::CC1Command::Execute(llvm::ArrayRef&lt;std::optional&lt;llvm::StringRef&gt;&gt;, std::__cxx11::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt;&gt;*, bool*) const /home/ych/llvm-project/clang/lib/Driver/Job.cpp:437:7
#<!-- -->34 0x00000000085ee322 clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&amp;, clang::driver::Command const*&amp;, bool) const /home/ych/llvm-project/clang/lib/Driver/Compilation.cpp:196:15
#<!-- -->35 0x00000000085ee4fc clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&amp;, llvm::SmallVectorImpl&lt;std::pair&lt;int, clang::driver::Command const*&gt;&gt;&amp;, bool) const /home/ych/llvm-project/clang/lib/Driver/Compilation.cpp:251:13
#<!-- -->36 0x0000000008609c91 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&amp;, llvm::SmallVectorImpl&lt;std::pair&lt;int, clang::driver::Command const*&gt;&gt;&amp;) /home/ych/llvm-project/clang/lib/Driver/Driver.cpp:2166:7
#<!-- -->37 0x0000000005389ec7 clang_main(int, char**, llvm::ToolContext const&amp;) /home/ych/llvm-project/clang/tools/driver/driver.cpp:402:9
#<!-- -->38 0x00000000053bbfb5 main /home/ych/llvm-project/build/tools/clang/tools/driver/clang-driver.cpp:17:3
#<!-- -->39 0x00007f5b30a295d0 __libc_start_call_main (/lib64/libc.so.6+0x295d0)
#<!-- -->40 0x00007f5b30a29680 __libc_start_main@<!-- -->GLIBC_2.2.5 (/lib64/libc.so.6+0x29680)
#<!-- -->41 0x0000000005388c25 _start (/data/users/ych/server-llvm/llvm-project/build/bin/clang-21+0x5388c25)

Note that ThreadLocalDetail.h doesn't actually import "SharedMutex.h". If you remove -fmodule-file=SharedMutex.pcm part this compilation succeeds. I also can't get it to repro when the using decl in relaxed_atomic is replaced with its own constructor.

@yuxuanchen1997 yuxuanchen1997 changed the title [Clang][Modules] FE crashes when constructor using-decl are build in header units [Clang][Modules] FE crashes when constructor using-decl are built in header units Apr 7, 2025
@shafik
Copy link
Collaborator

shafik commented Apr 8, 2025

Maybe related: #105994 but this is fixed in trunk, maybe you can take their godbolt example and produce a godbolt reproducer for this code?

@shafik
Copy link
Collaborator

shafik commented Apr 8, 2025

CC @ChuanqiXu9 @mpark

@yuxuanchen1997
Copy link
Member Author

Maybe related: #105994 but this is fixed in trunk, maybe you can take their godbolt example and produce a godbolt reproducer for this code?

I am not sure if the godbolt template is going to work for me. The issue arises with header units only. CMake also automatically scans for dependencies, which will make the issue no longer repro here.

@ChuanqiXu9
Copy link
Member

Maybe you can debug for how ConstructorNameSet is constructed and why there are something missing.

It may be helpful to investigate if this is a problem in named module and clang modules and if not, to figure out what's the difference.

@yuxuanchen1997 yuxuanchen1997 self-assigned this Apr 8, 2025
@yuxuanchen1997
Copy link
Member Author

Maybe you can debug for how ConstructorNameSet is constructed and why there are something missing.

I do understand why ConstructorNameSet has this constructor name entry while you don't find them by just walking the named decls in CXXRecordDecl. I am not sure whether Names should contain such a constructor inherited from the base class with a using-decl. I feel that it's not all that useful to be included in the name lookup table because you don't refer to its constructor name directly any more.

@hokein
Copy link
Collaborator

hokein commented May 9, 2025

I think this is #61065 (confirmed that the assertion failure no longer occurs with the change 67b298f)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++20 clang:modules C++20 modules and Clang Header Modules crash-on-valid
Projects
None yet
Development

No branches or pull requests

5 participants