public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PR c++/78572] handle array self references in intializers
@ 2016-12-20 16:42 Aldy Hernandez
  2016-12-20 17:21 ` Nathan Sidwell
  0 siblings, 1 reply; 6+ messages in thread
From: Aldy Hernandez @ 2016-12-20 16:42 UTC (permalink / raw)
  To: jason merrill, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1563 bytes --]

The problem in this PR is that we're trying to initialize an array with 
members of itself:

	int array[10] = { array[3]=5, array[7]=3 };

The C++ front-end, in store_init_value() via cxx_constant_value() and 
friends will transform:

	{array[3] = 5, array[7] = 3}

into:

	{[3]=5, [0]=5, [7]=3, [1]=3}

which looks invalid to output_constructor*(), presumably because it 
isn't sorted by increasing index.

Jakub has even gone further to show that for the following:

	... = { array[3]=5, array[7]=3, array[7]=8, array[7] = 9 };

things get even worse, because we generate code to write twice into [3]:

	{[3]=5, [0]=5, [7]=9, [1]=3, [2]=8, [3]=9}

I took the easy way in cxx_eval_store_expression() and marked the 
expression as non_constant_p if we're trying to set an array from 
members of itself.  This causes us to to generate the initialization of 
the self-referencing array[sub] elements as a CLEANUP_POINT_EXPR:

<<cleanup_point <<< Unknown tree: expr_stmt
   array[0] = array[3] = 5 >>>>>;
<<cleanup_point <<< Unknown tree: expr_stmt
   array[1] = array[7] = 3 >>>>>;

Ultimately this yields correct code:

array:
         .zero   40
...
...

_GLOBAL__sub_I_array:
.LFB1:
         .cfi_startproc
         movl    $5, array+12(%rip)
         movl    $5, array(%rip)
         movl    $3, array+28(%rip)
         movl    $3, array+4(%rip)
	ret

Is this approach acceptable, or should we be marking this as 
non-constant somewhere else in the chain?  Or perhaps another approach 
would be to handle such constructor holes in the in the varasm code?

Aldy

[-- Attachment #2: curr --]
[-- Type: text/plain, Size: 1248 bytes --]

commit 295d93f60bcbec5b9959a7b3656f10aa0df71c9f
Author: Aldy Hernandez <aldyh@redhat.com>
Date:   Tue Dec 20 06:13:26 2016 -0500

            PR c++/78572
            * constexpr.c (cxx_eval_store_expression): Avoid array self
            references in initialization.

diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index aedd004..ac279ad 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -3313,6 +3313,15 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
 	}
     }
 
+  /* Initializing an array from a variant of itself is a non-constant.
+     This avoids attemps at generating incorrect self references in
+     something like: int foo[10] = { stuff[3]=8 }.  */
+  if (TREE_CODE (target) == ARRAY_REF && object == ctx->object)
+    {
+      *non_constant_p = true;
+      return t;
+    }
+
   /* And then find/build up our initializer for the path to the subobject
      we're initializing.  */
   tree *valp;
diff --git a/gcc/testsuite/g++.dg/pr78572.C b/gcc/testsuite/g++.dg/pr78572.C
new file mode 100644
index 0000000..82ab4e3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr78572.C
@@ -0,0 +1,9 @@
+// { dg-do compile } */
+
+static int array[10] = { array[3]=5, array[7]=3 };
+
+int
+main ()
+{
+  return 0;
+}

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2016-12-21 17:41 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-12-20 16:42 [PR c++/78572] handle array self references in intializers Aldy Hernandez
2016-12-20 17:21 ` Nathan Sidwell
2016-12-20 18:58   ` Aldy Hernandez
2016-12-20 20:30     ` Nathan Sidwell
2016-12-21 17:41       ` Aldy Hernandez
2016-12-21 17:47         ` Jakub Jelinek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).