c++: Fix up modules handling of namespace scope structured bindings

Message ID Z32FFFxadxZSLZu1@tucnak
State New
Headers
Series c++: Fix up modules handling of namespace scope structured bindings |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_gcc_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_gcc_check--master-arm success Test passed

Commit Message

Jakub Jelinek Jan. 7, 2025, 7:48 p.m. UTC
  Hi!

With the following patch I actually get a simple namespace scope structured
binding working with modules.

The core_vals change ensure we actually save/restore DECL_VALUE_EXPR even
for namespace scope vars, the get_merge_kind is based on the assumption
that structured bindings are always unique, one can't redeclare them and
without it we really ICE because their base vars have no name.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2025-01-07  Jakub Jelinek  <jakub@redhat.com>

	* module.cc (trees_out::core_vals): Note DECL_VALUE_EXPR even for
	vars outside of functions.
	(trees_in::core_vals): Read in DECL_VALUE_EXPR even for vars outside
	of functions.
	(trees_out::get_merge_kind): Make DECL_DECOMPOSITION_P MK_unique.

	* g++.dg/modules/decomp-2_b.C: New test.
	* g++.dg/modules/decomp-2_a.H: New file.


	Jakub
  

Comments

Jason Merrill Jan. 10, 2025, 2:21 a.m. UTC | #1
On 1/7/25 2:48 PM, Jakub Jelinek wrote:
> Hi!
> 
> With the following patch I actually get a simple namespace scope structured
> binding working with modules.
> 
> The core_vals change ensure we actually save/restore DECL_VALUE_EXPR even
> for namespace scope vars, the get_merge_kind is based on the assumption
> that structured bindings are always unique, one can't redeclare them and
> without it we really ICE because their base vars have no name.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

OK.

> 2025-01-07  Jakub Jelinek  <jakub@redhat.com>
> 
> 	* module.cc (trees_out::core_vals): Note DECL_VALUE_EXPR even for
> 	vars outside of functions.
> 	(trees_in::core_vals): Read in DECL_VALUE_EXPR even for vars outside
> 	of functions.
> 	(trees_out::get_merge_kind): Make DECL_DECOMPOSITION_P MK_unique.
> 
> 	* g++.dg/modules/decomp-2_b.C: New test.
> 	* g++.dg/modules/decomp-2_a.H: New file.
> 
> --- gcc/cp/module.cc.jj	2025-01-03 17:54:12.411905971 +0100
> +++ gcc/cp/module.cc	2025-01-07 13:42:45.495623879 +0100
> @@ -6313,7 +6313,11 @@ trees_out::core_vals (tree t)
>       case VAR_DECL:
>         if (DECL_CONTEXT (t)
>   	  && TREE_CODE (DECL_CONTEXT (t)) != FUNCTION_DECL)
> -	break;
> +	{
> +	  if (DECL_HAS_VALUE_EXPR_P (t))
> +	    WT (DECL_VALUE_EXPR (t));
> +	  break;
> +	}
>         /* FALLTHROUGH  */
>   
>       case RESULT_DECL:
> @@ -6843,7 +6847,14 @@ trees_in::core_vals (tree t)
>       case VAR_DECL:
>         if (DECL_CONTEXT (t)
>   	  && TREE_CODE (DECL_CONTEXT (t)) != FUNCTION_DECL)
> -	break;
> +	{
> +	  if (DECL_HAS_VALUE_EXPR_P (t))
> +	    {
> +	      tree val = tree_node ();
> +	      SET_DECL_VALUE_EXPR (t, val);
> +	    }
> +	  break;
> +	}
>         /* FALLTHROUGH  */
>   
>       case RESULT_DECL:
> @@ -10985,6 +10996,12 @@ trees_out::get_merge_kind (tree decl, de
>   		break;
>   	      }
>   
> +	    if (DECL_DECOMPOSITION_P (decl))
> +	      {
> +		mk = MK_unique;
> +		break;
> +	      }
> +
>   	    if (IDENTIFIER_ANON_P (DECL_NAME (decl)))
>   	      {
>   		if (RECORD_OR_UNION_TYPE_P (ctx))
> --- gcc/testsuite/g++.dg/modules/decomp-2_b.C.jj	2025-01-07 13:27:32.352323501 +0100
> +++ gcc/testsuite/g++.dg/modules/decomp-2_b.C	2025-01-07 13:27:32.352323501 +0100
> @@ -0,0 +1,11 @@
> +// { dg-do run }
> +// { dg-additional-options "-fmodules-ts" }
> +
> +import "decomp-2_a.H";
> +
> +int
> +main ()
> +{
> +  if (a != 1 || b != 2 || c != 3)
> +    __builtin_abort ();
> +}
> --- gcc/testsuite/g++.dg/modules/decomp-2_a.H.jj	2025-01-07 13:27:32.352323501 +0100
> +++ gcc/testsuite/g++.dg/modules/decomp-2_a.H	2025-01-07 13:27:32.352323501 +0100
> @@ -0,0 +1,11 @@
> +// { dg-additional-options -fmodule-header }
> +// { dg-module-cmi {} }
> +
> +struct A {
> +  int a, b, c;
> +};
> +
> +namespace {
> +A d = { 1, 2, 3 };
> +auto [a, b, c] = d;
> +}
> 
> 	Jakub
>
  

Patch

--- gcc/cp/module.cc.jj	2025-01-03 17:54:12.411905971 +0100
+++ gcc/cp/module.cc	2025-01-07 13:42:45.495623879 +0100
@@ -6313,7 +6313,11 @@  trees_out::core_vals (tree t)
     case VAR_DECL:
       if (DECL_CONTEXT (t)
 	  && TREE_CODE (DECL_CONTEXT (t)) != FUNCTION_DECL)
-	break;
+	{
+	  if (DECL_HAS_VALUE_EXPR_P (t))
+	    WT (DECL_VALUE_EXPR (t));
+	  break;
+	}
       /* FALLTHROUGH  */
 
     case RESULT_DECL:
@@ -6843,7 +6847,14 @@  trees_in::core_vals (tree t)
     case VAR_DECL:
       if (DECL_CONTEXT (t)
 	  && TREE_CODE (DECL_CONTEXT (t)) != FUNCTION_DECL)
-	break;
+	{
+	  if (DECL_HAS_VALUE_EXPR_P (t))
+	    {
+	      tree val = tree_node ();
+	      SET_DECL_VALUE_EXPR (t, val);
+	    }
+	  break;
+	}
       /* FALLTHROUGH  */
 
     case RESULT_DECL:
@@ -10985,6 +10996,12 @@  trees_out::get_merge_kind (tree decl, de
 		break;
 	      }
 
+	    if (DECL_DECOMPOSITION_P (decl))
+	      {
+		mk = MK_unique;
+		break;
+	      }
+
 	    if (IDENTIFIER_ANON_P (DECL_NAME (decl)))
 	      {
 		if (RECORD_OR_UNION_TYPE_P (ctx))
--- gcc/testsuite/g++.dg/modules/decomp-2_b.C.jj	2025-01-07 13:27:32.352323501 +0100
+++ gcc/testsuite/g++.dg/modules/decomp-2_b.C	2025-01-07 13:27:32.352323501 +0100
@@ -0,0 +1,11 @@ 
+// { dg-do run }
+// { dg-additional-options "-fmodules-ts" }
+
+import "decomp-2_a.H";
+
+int
+main ()
+{
+  if (a != 1 || b != 2 || c != 3)
+    __builtin_abort ();
+}
--- gcc/testsuite/g++.dg/modules/decomp-2_a.H.jj	2025-01-07 13:27:32.352323501 +0100
+++ gcc/testsuite/g++.dg/modules/decomp-2_a.H	2025-01-07 13:27:32.352323501 +0100
@@ -0,0 +1,11 @@ 
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+struct A {
+  int a, b, c;
+};
+
+namespace {
+A d = { 1, 2, 3 };
+auto [a, b, c] = d;
+}