]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: modules, generic lambda, constexpr if
authorJason Merrill <jason@redhat.com>
Tue, 26 Nov 2024 04:29:25 +0000 (23:29 -0500)
committerJason Merrill <jason@redhat.com>
Fri, 10 Jan 2025 02:43:11 +0000 (21:43 -0500)
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
gcc/testsuite/g++.dg/modules/constexpr-if-1_a.C [new file with mode: 0644]
gcc/testsuite/g++.dg/modules/constexpr-if-1_b.C [new file with mode: 0644]

index 5350e6c4badba1d3425fe3e622235fa2824acecc..0533a2bcf2c1f972c78ec66337d9238dd331ad8c 100644 (file)
@@ -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 (file)
index 0000000..80a064f
--- /dev/null
@@ -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 (file)
index 0000000..af285da
--- /dev/null
@@ -0,0 +1,8 @@
+// { dg-additional-options -fmodules }
+
+import M;
+
+int main()
+{
+  f<int>();
+}