Tested x86_64-pc-linux-gnu, applying to trunk. -- 8< --
In std/ranges/concat/1.cc we end up instantiating concat_view::iterator::operator-, which has nested generic lambdas, where the innermost is all constexpr if. tsubst_lambda_expr propagates the returns_* flags for generic lambdas since we might not substitute into the whole function, as in this case with constexpr if. But the module wasn't preserving that flag, and so the importer gave a bogus "no return statement" diagnostic. gcc/cp/ChangeLog: * module.cc (trees_out::write_function_def): Write returns* flags. (struct post_process_data): Add returns_* flags. (trees_in::read_function_def): Set them. (module_state::read_cluster): Use them. gcc/testsuite/ChangeLog: * g++.dg/modules/constexpr-if-1_a.C: New test. * g++.dg/modules/constexpr-if-1_b.C: New test. --- gcc/cp/module.cc | 24 ++++++++++++++++--- .../g++.dg/modules/constexpr-if-1_a.C | 14 +++++++++++ .../g++.dg/modules/constexpr-if-1_b.C | 8 +++++++ 3 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/modules/constexpr-if-1_a.C create mode 100644 gcc/testsuite/g++.dg/modules/constexpr-if-1_b.C diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index 5350e6c4bad..0533a2bcf2c 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -2929,6 +2929,10 @@ struct post_process_data { tree decl; location_t start_locus; location_t end_locus; + bool returns_value; + bool returns_null; + bool returns_abnormally; + bool infinite_loop; }; /* Tree stream reader. Note that reading a stream doesn't mark the @@ -12263,10 +12267,16 @@ trees_out::write_function_def (tree decl) { unsigned flags = 0; + flags |= 1 * DECL_NOT_REALLY_EXTERN (decl); if (f) - flags |= 2; - if (DECL_NOT_REALLY_EXTERN (decl)) - flags |= 1; + { + flags |= 2; + /* These flags are needed in tsubst_lambda_expr. */ + flags |= 4 * f->language->returns_value; + flags |= 8 * f->language->returns_null; + flags |= 16 * f->language->returns_abnormally; + flags |= 32 * f->language->infinite_loop; + } u (flags); } @@ -12314,6 +12324,10 @@ trees_in::read_function_def (tree decl, tree maybe_template) { pdata.start_locus = state->read_location (*this); pdata.end_locus = state->read_location (*this); + pdata.returns_value = flags & 4; + pdata.returns_null = flags & 8; + pdata.returns_abnormally = flags & 16; + pdata.infinite_loop = flags & 32; } if (get_overrun ()) @@ -16232,6 +16246,10 @@ module_state::read_cluster (unsigned snum) cfun->language->base.x_stmt_tree.stmts_are_full_exprs_p = 1; cfun->function_start_locus = pdata.start_locus; cfun->function_end_locus = pdata.end_locus; + cfun->language->returns_value = pdata.returns_value; + cfun->language->returns_null = pdata.returns_null; + cfun->language->returns_abnormally = pdata.returns_abnormally; + cfun->language->infinite_loop = pdata.infinite_loop; if (abstract) ; diff --git a/gcc/testsuite/g++.dg/modules/constexpr-if-1_a.C b/gcc/testsuite/g++.dg/modules/constexpr-if-1_a.C new file mode 100644 index 00000000000..80a064f4d39 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/constexpr-if-1_a.C @@ -0,0 +1,14 @@ +// { dg-do compile { target c++20 } } +// { dg-additional-options -fmodules } + +export module M; + +export +template <class T> +inline void f() +{ + []<int M>() -> int { + if constexpr (M > 0) { return true; } + else { return false; } + }; +} diff --git a/gcc/testsuite/g++.dg/modules/constexpr-if-1_b.C b/gcc/testsuite/g++.dg/modules/constexpr-if-1_b.C new file mode 100644 index 00000000000..af285da79ac --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/constexpr-if-1_b.C @@ -0,0 +1,8 @@ +// { dg-additional-options -fmodules } + +import M; + +int main() +{ + f<int>(); +} base-commit: fab96de044f1f023f52d43af866205d17d8895fb -- 2.47.1