c++: modules, generic lambda, constexpr if
Checks
Commit Message
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
base-commit: fab96de044f1f023f52d43af866205d17d8895fb
@@ -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)
;
new file mode 100644
@@ -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; }
+ };
+}
new file mode 100644
@@ -0,0 +1,8 @@
+// { dg-additional-options -fmodules }
+
+import M;
+
+int main()
+{
+ f<int>();
+}