https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108620
Bug ID: 108620 Summary: internal compiler error: in instantiate_type, at cp/class.cc:8742 when assign the return value of co_yield to a member of class/struct Product: gcc Version: 12.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: owt5008137 at live dot com Target Milestone: --- ## GCC Version ``` $ gcc -v Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/opt/gcc-12/libexec/gcc/x86_64-pc-linux-gnu/12.2.0/lto-wrapper Target: x86_64-pc-linux-gnu Configured with: ../gcc-12.2.0/configure --prefix=/opt/gcc-12 --with-gmp=/opt/gcc-12 --with-mpc=/opt/gcc-12 --with-mpfr=/opt/gcc-12 --with-isl=/opt/gcc-12 --with-zstd=/opt/gcc-12 --with-target-bdw-gc=/opt/gcc-12/multilib/64,32=/opt/gcc-12/multilib/32 --enable-shared --enable-static --enable-gnu-unique-object --enable-bootstrap --enable-build-with-cxx --disable-libjava-multilib --enable-checking=release --enable-gold --enable-ld --enable-libada --enable-lto --enable-objc-gc --enable-vtable-verify --enable-linker-build-id --enable-rpath --enable-multilib Thread model: posix Supported LTO compression algorithms: zlib zstd gcc version 12.2.0 (GCC) ``` ## Command and output ``` $ g++ test.cpp -std=c++20 -freport-bug test.cpp: In instantiation of ‘task<std::__cxx11::basic_string<char> > call2(TArg&&, container&) [with TArg = std::__cxx11::basic_string<char>]’: test.cpp:91:21: required from here test.cpp:79:16: internal compiler error: in instantiate_type, at cp/class.cc:8742 79 | output.ptr = co_yield task<TArg>::yield_private_data(); | ~~~~~~~~~~~^~~~~~~~~~ 0x68984f instantiate_type(tree_node*, tree_node*, int) ../../gcc-12.2.0/gcc/cp/class.cc:8742 0x8a6a6c convert_for_assignment ../../gcc-12.2.0/gcc/cp/typeck.cc:9863 0x8a8ce3 cp_build_modify_expr(unsigned int, tree_node*, tree_code, tree_node*, int) ../../gcc-12.2.0/gcc/cp/typeck.cc:9277 0x8a95bb build_x_modify_expr(unsigned int, tree_node*, tree_code, tree_node*, tree_node*, int) ../../gcc-12.2.0/gcc/cp/typeck.cc:9373 0x83b8aa tsubst_copy_and_build(tree_node*, tree_node*, int, tree_node*, bool, bool) ../../gcc-12.2.0/gcc/cp/pt.cc:20588 0x84b468 tsubst_expr(tree_node*, tree_node*, int, tree_node*, bool) ../../gcc-12.2.0/gcc/cp/pt.cc:19576 0x84c417 tsubst_expr(tree_node*, tree_node*, int, tree_node*, bool) ../../gcc-12.2.0/gcc/cp/pt.cc:18547 0x84c417 tsubst_expr(tree_node*, tree_node*, int, tree_node*, bool) ../../gcc-12.2.0/gcc/cp/pt.cc:18589 0x84c9b2 tsubst_expr(tree_node*, tree_node*, int, tree_node*, bool) ../../gcc-12.2.0/gcc/cp/pt.cc:18547 0x84c9b2 tsubst_expr(tree_node*, tree_node*, int, tree_node*, bool) ../../gcc-12.2.0/gcc/cp/pt.cc:18561 0x84bfa8 tsubst_expr(tree_node*, tree_node*, int, tree_node*, bool) ../../gcc-12.2.0/gcc/cp/pt.cc:18547 0x84bfa8 tsubst_expr(tree_node*, tree_node*, int, tree_node*, bool) ../../gcc-12.2.0/gcc/cp/pt.cc:18918 0x84a9cc tsubst_expr(tree_node*, tree_node*, int, tree_node*, bool) ../../gcc-12.2.0/gcc/cp/pt.cc:26532 0x84a9cc instantiate_body ../../gcc-12.2.0/gcc/cp/pt.cc:26532 0x84b289 instantiate_decl(tree_node*, bool, bool) ../../gcc-12.2.0/gcc/cp/pt.cc:26824 0x85fd6b instantiate_pending_templates(int) ../../gcc-12.2.0/gcc/cp/pt.cc:26903 0x76539f c_parse_final_cleanups() ../../gcc-12.2.0/gcc/cp/decl2.cc:5128 Please submit a full bug report, with preprocessed source. Please include the complete backtrace with any bug report. See <https://gcc.gnu.org/bugs/> for instructions. Preprocessed source stored into /tmp/ccblstmc.out file, please attach this to your bugreport. ``` ## Source ``` #include <iostream> #include <memory> #include <coroutine> template<class PrivateDataType> struct task; template <class PrivateDataType> struct task_private_data { inline task_private_data() noexcept : data_(nullptr) {} inline task_private_data(PrivateDataType* input) noexcept : data_(input) {} inline task_private_data(task_private_data&& other) noexcept = default; inline task_private_data& operator=(task_private_data&&) noexcept = default; inline task_private_data(const task_private_data&) = delete; inline task_private_data& operator=(const task_private_data&) = delete; inline ~task_private_data() {} inline bool await_ready() const noexcept { return true; } inline PrivateDataType* await_resume() const noexcept { return data_; } inline void await_suspend(std::coroutine_handle<>) noexcept {} PrivateDataType* data_; }; template<class PrivateDataType> struct task_context { PrivateDataType data_; }; template<class PrivateDataType> struct task { using self_type = task<PrivateDataType>; std::shared_ptr<task_context<PrivateDataType>> context_; task(const std::shared_ptr<task_context<PrivateDataType>>& input): context_(input) {} static auto yield_private_data() noexcept { return task_private_data<PrivateDataType>{}; } struct promise_type { std::shared_ptr<task_context<PrivateDataType>> context_; template<class Input, class... Rest> promise_type(Input&& input, Rest&&...) { context_ = std::make_shared<task_context<PrivateDataType>>(); context_->data_ = std::forward<Input>(input); } auto get_return_object() noexcept { return self_type{context_}; } std::suspend_never initial_suspend() noexcept { return {}; } std::suspend_never final_suspend() noexcept { return {}; } void unhandled_exception() { throw; } template<class ReturnType> void return_value(ReturnType&&) {} template <class InputPrivateDataType> inline task_private_data<InputPrivateDataType> yield_value( task_private_data<InputPrivateDataType>&& input) noexcept { input.data_ = &context_->data_; return task_private_data<InputPrivateDataType>(input.data_); } }; }; template<class TArg, class OutputType> task<std::string> call1(TArg&& arg, OutputType& output) { OutputType* ptr = co_yield task<TArg>::yield_private_data(); output = *ptr; co_return 0; } struct container { task_private_data<std::string>* ptr; }; template<class TArg> task<std::string> call2(TArg&& arg, container& output) { output.ptr = co_yield task<TArg>::yield_private_data(); co_return 0; } int main() { // success std::string output1; call1(std::string("hello1"), output1); std::cout<< "output1: "<< output1<< std::endl; // crash container output2; auto task2 = call2(std::string("hello2"), output2); std::cout<< "output2: "<< output2.ptr->data_<< std::endl; return 0; } ```