Skip to content

[clang] Function body and its inner lambda are loaded from different module. #141582

Open
@hokein

Description

@hokein

See testcase: https://github.com/hokein/module-bugs/tree/main/color-bug

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: workspace/llvm-project/build/bin/clang -iquote . -Wuninitialized-const-reference -fmodules -Xclang=-fmodule-file=experiment_context/experiment_context.pic.pcm -std=gnu++20 -c experiment_context_test.cc -o experiment_context_test/experiment_context_test.pic.o
1.      <eof> parser at end of file
2.      experiment_context_test.cc:6:6: instantiating function definition 'c9::WaitForCoroutine<void>'
3.      workspace/module-bugs/color-bug/util/c9/lazy.h:8:7: instantiating function definition 'c9::MakeCo<void, (lambda at experiment_context_test.cc:7:13)>'
4.      workspace/module-bugs/color-bug/util/c9/co.h:45:12: instantiating function definition 'c9::internal::CoroutinePromise<void>::CoroutinePromise<(lambda at experiment_context_test.cc:7:13) &>'
 #0 0x000055bbff6ea8d8 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) workspace/llvm-project/llvm/lib/Support/Unix/Signals.inc:804:13
 #1 0x000055bbff6e87b0 llvm::sys::RunSignalHandlers() workspace/llvm-project/llvm/lib/Support/Signals.cpp:106:18
 #2 0x000055bbff63f786 (anonymous namespace)::CrashRecoveryContextImpl::HandleCrash(int, unsigned long) workspace/llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp:74:5
 #3 0x000055bbff63f786 CrashRecoverySignalHandler(int) workspace/llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp:391:51
 #4 0x00007f5f7ee49df0 (/lib/x86_64-linux-gnu/libc.so.6+0x3fdf0)
 #5 0x00007f5f7ee9e95c __pthread_kill_implementation ./nptl/pthread_kill.c:44:76
 #6 0x00007f5f7ee49cc2 raise ./signal/../sysdeps/posix/raise.c:27:6
 #7 0x00007f5f7ee324ac abort ./stdlib/abort.c:81:3
 #8 0x00007f5f7ee32420 __assert_perror_fail ./assert/assert-perr.c:31:1
 #9 0x000055bc01b29d0f decltype(auto) llvm::dyn_cast<clang::TagDecl, clang::Decl const>(clang::Decl const*) workspace/llvm-project/llvm/include/llvm/Support/Casting.h:662:3
#10 0x000055bc01b29d0f clang::LocalInstantiationScope::findInstantiationOf(clang::Decl const*) workspace/llvm-project/clang/lib/Sema/SemaTemplateInstantiate.cpp:4522:32
#11 0x000055bc01b6b587 clang::Sema::FindInstantiatedDecl(clang::SourceLocation, clang::NamedDecl*, clang::MultiLevelTemplateArgumentList const&, bool) workspace/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp:6756:16
#12 0x000055bc01b426bd clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformDeclRefExpr(clang::DeclRefExpr*) workspace/llvm-project/clang/lib/Sema/TreeTransform.h:0:44
#13 0x000055bc01b348f8 clang::ActionResult<clang::Expr*, true>::isInvalid() const workspace/llvm-project/clang/include/clang/Sema/Ownership.h:199:41
#14 0x000055bc01b348f8 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformCStyleCastExpr(clang::CStyleCastExpr*) workspace/llvm-project/clang/lib/Sema/TreeTransform.h:13680:15
#15 0x000055bc01b25f88 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformStmt(clang::Stmt*, clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::StmtDiscardKind) workspace/llvm-project/clang/lib/Sema/TreeTransform.h:4310:15
#16 0x000055bc01b3b21d clang::ActionResult<clang::Stmt*, true>::isInvalid() const workspace/llvm-project/clang/include/clang/Sema/Ownership.h:199:41
#17 0x000055bc01b3b21d clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformCompoundStmt(clang::CompoundStmt*, bool) workspace/llvm-project/clang/lib/Sema/TreeTransform.h:8108:16
#18 0x000055bc01b41c7f clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformLambdaBody(clang::LambdaExpr*, clang::Stmt*) workspace/llvm-project/clang/lib/Sema/TreeTransform.h:15802:10
#19 0x000055bc01b41c7f (anonymous namespace)::TemplateInstantiator::TransformLambdaBody(clang::LambdaExpr*, clang::Stmt*) workspace/llvm-project/clang/lib/Sema/SemaTemplateInstantiate.cpp:1792:25
#20 0x000055bc01b41c7f clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformLambdaExpr(clang::LambdaExpr*) workspace/llvm-project/clang/lib/Sema/TreeTransform.h:15733:44
#21 0x000055bc01b32123 (anonymous namespace)::TemplateInstantiator::TransformLambdaExpr(clang::LambdaExpr*) workspace/llvm-project/clang/lib/Sema/SemaTemplateInstantiate.cpp:1748:25
#22 0x000055bc01b34ac3 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformCallExpr(clang::CallExpr*) workspace/llvm-project/clang/lib/Sema/TreeTransform.h:0:36
#23 0x000055bc01b25f88 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformStmt(clang::Stmt*, clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::StmtDiscardKind) workspace/llvm-project/clang/lib/Sema/TreeTransform.h:4310:15
#24 0x000055bc01b3b21d clang::ActionResult<clang::Stmt*, true>::isInvalid() const workspace/llvm-project/clang/include/clang/Sema/Ownership.h:199:41
#25 0x000055bc01b3b21d clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformCompoundStmt(clang::CompoundStmt*, bool) workspace/llvm-project/clang/lib/Sema/TreeTransform.h:8108:16
#26 0x000055bc01b25f1a clang::Sema::SubstStmt(clang::Stmt*, clang::MultiLevelTemplateArgumentList const&) workspace/llvm-project/clang/lib/Sema/SemaTemplateInstantiate.cpp:4376:23
#27 0x000055bc01b7e25c clang::Sema::InstantiateFunctionDefinition(clang::SourceLocation, clang::FunctionDecl*, bool, bool, bool) workspace/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp:5819:14
#28 0x000055bc01b8181e clang::FunctionDecl::isDefined() const workspace/llvm-project/clang/include/clang/AST/Decl.h:2226:12
#29 0x000055bc01b8181e clang::Sema::PerformPendingInstantiations(bool, bool) workspace/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp:7065:23
#30 0x000055bc01b7e35b clang::Sema::InstantiateFunctionDefinition(clang::SourceLocation, clang::FunctionDecl*, bool, bool, bool) workspace/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp:0:24
#31 0x000055bc01b8181e clang::FunctionDecl::isDefined() const workspace/llvm-project/clang/include/clang/AST/Decl.h:2226:12
#32 0x000055bc01b8181e clang::Sema::PerformPendingInstantiations(bool, bool) workspace/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp:7065:23
#33 0x000055bc01b7e35b clang::Sema::InstantiateFunctionDefinition(clang::SourceLocation, clang::FunctionDecl*, bool, bool, bool) workspace/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp:0:24
#34 0x000055bc01b8181e clang::FunctionDecl::isDefined() const workspace/llvm-project/clang/include/clang/AST/Decl.h:2226:12
#35 0x000055bc01b8181e clang::Sema::PerformPendingInstantiations(bool, bool) workspace/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp:7065:23
#36 0x000055bc0138b91e llvm::TimeTraceScope::~TimeTraceScope() workspace/llvm-project/llvm/include/llvm/Support/TimeProfiler.h:198:9
#37 0x000055bc0138b91e clang::Sema::ActOnEndOfTranslationUnitFragment(clang::TUFragmentKind) workspace/llvm-project/clang/lib/Sema/Sema.cpp:1198:3
#38 0x000055bc0138c101 clang::Sema::ActOnEndOfTranslationUnit() workspace/llvm-project/clang/lib/Sema/Sema.cpp:1236:9
#39 0x000055bc012f3ef7 clang::Parser::ParseTopLevelDecl(clang::OpaquePtr<clang::DeclGroupRef>&, clang::Sema::ModuleImportState&) workspace/llvm-project/clang/lib/Parse/Parser.cpp:0:13
#40 0x000055bc012234ae clang::ParseAST(clang::Sema&, bool, bool) workspace/llvm-project/clang/lib/Parse/ParseAST.cpp:170:5
#41 0x000055bc00440076 clang::FrontendAction::Execute() workspace/llvm-project/clang/lib/Frontend/FrontendAction.cpp:1225:10
#42 0x000055bc003b6d1d llvm::Error::getPtr() const workspace/llvm-project/llvm/include/llvm/Support/Error.h:278:42
#43 0x000055bc003b6d1d llvm::Error::operator bool() workspace/llvm-project/llvm/include/llvm/Support/Error.h:241:16
#44 0x000055bc003b6d1d clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) workspace/llvm-project/clang/lib/Frontend/CompilerInstance.cpp:1057:23
#45 0x000055bc004d4452 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) workspace/llvm-project/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp:300:25
#46 0x000055bbfca56483 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) workspace/llvm-project/clang/tools/driver/cc1_main.cpp:297:15
#47 0x000055bbfca52865 ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) workspace/llvm-project/clang/tools/driver/driver.cpp:223:12
//--- bar.cppmap
module "bar" {
  export *
  header "util/c9/co.h"
}

//--- foo.cppmap
module "foo" {
  export *
  header "util/c9/co.h"
}

//--- experiment_context.cppmap
module "experiment_context" {
  export *
  header "util/c9/lazy.h"

  use "foo"
  use "bar"
}

//--- experiment_context_test.cc
#include "util/c9/lazy.h"

namespace c9 {

template <typename T>
void WaitForCoroutine() {
  MakeCo<T>([]() -> Co<void> {
    co_return;
  });
}

void test() {
  c9::WaitForCoroutine<void>();
}
}

//--- util/c9/lazy.h

#ifndef UTIL_C9_LAZY_H_
#define UTIL_C9_LAZY_H_

#include "util/c9/co.h"

namespace c9 {
template <typename T, typename F>
Co<T> MakeCo(F f)
{
  co_return co_await f();
}
}

inline c9::Co<void> DoNothing() { co_return; }

#endif  // UTIL_C9_LAZY_H_

//--- util/c9/co.h

#ifndef UTIL_C9_COROUTINE_H_
#define UTIL_C9_COROUTINE_H_

namespace std {

template <class _Ret, class... _Args>
struct coroutine_traits {};

template <typename Ret, typename... Args>
  requires requires { typename Ret::promise_type; }
struct coroutine_traits<Ret, Args...> {
  using promise_type = typename Ret::promise_type;
};

template <typename Promise = void>
struct coroutine_handle;

template <>
struct coroutine_handle<void> {};

template <typename Promise = void>
struct coroutine_handle : coroutine_handle<> {
  static coroutine_handle from_address(void *addr);
};

struct suspend_always {
  bool await_ready() noexcept;
  void await_suspend(coroutine_handle<>) noexcept;
  void await_resume() noexcept;
};

}  // namespace std

namespace c9 {

template <typename T>
class Co;

namespace internal {

template <typename T>
class CoroutinePromise {
 public:
  template <typename... Args>
  explicit CoroutinePromise(Args&&... args) {
    const int dummy_color = 1;
    [&]{ (void)dummy_color; }();
  }

  ~CoroutinePromise();
  void return_void();
  auto get_return_object() {
    return Co<T>();
  }
  void unhandled_exception();
  std::suspend_always  initial_suspend();

  struct result_t {
    ~result_t();
    bool await_ready() const noexcept;
    void await_suspend(std::coroutine_handle<void>) noexcept;
    void await_resume() const noexcept;
  };

  template <typename U>
  result_t await_transform(Co<U> co);

  std::suspend_always final_suspend() noexcept;
};
}  // namespace internal

template <typename T>
class Co {
 public:
  using promise_type = internal::CoroutinePromise<void>;
};

class CoIncomingModuleBase {
 public:
    Co<void> CoAfterFinish() { co_return; }
};
}  // namespace c9

#endif  // UTIL_C9_COROUTINE_H_

Metadata

Metadata

Assignees

No one assigned

    Labels

    clang:modulesC++20 modules and Clang Header ModulescrashPrefer [crash-on-valid] or [crash-on-invalid]

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions