The following valid code snippet triggers an ICE since GCC 4.0.0 (only with the C frontend): ======================================== struct A { int i; }; void foo() { ((struct A) { 0 }).i += 1; } ======================================== bug.c: In function 'foo': bug.c:5: internal compiler error: in gimple_add_tmp_var, at gimplify.c:720 Please submit a full bug report, [etc.]
First off this "((struct A) { 0 })" is not a temporary variable but instead an anonymous C99 variable.
Confirmed, we are gimplifying the compound literal expression twice which in turn calls gimple_add_tmp_var twice on the decl.
gcc generates two separate trees for compound literals in c and c++. As in this test case: struct S { int i,j; }; void foo (struct S); int main () { foo((struct S){1,1}); } In c it generates compound_literal_expr and in c++ it generates target_expr. But gimplifier treats them differently in the following areas: 1) in routine mostly_copy_tree_v we don;t copy target_expr but we do copy compound_literal_expr. I see the following comment there: / * Similar to copy_tree_r() but do not copy SAVE_EXPR or TARGET_EXPR nodes. These nodes model computations that should only be done once. If we were to unshare something like SAVE_EXPR(i++), the gimplification process would create wrong code. */ Shouldn't compound_literal_expr be treated same as target_expr here? 2) gimplify_target_expr can be called more than once on the same target_expr node because first time around its TARGET_EXPR_INITIAL is set to NULL. This works as a guard and prevents its temporary to be added to the temporary list more than once (when call is made to gimple_add_tmp_var). On the other hand, such a guard does not exist for a compound_literal_expr and when gimple_add_tmp_var is called, it asserts. So, I added check for !DECL_SEEN_IN_BIND_EXPR_P (decl) in gimplify_compound_literal_expr before call to gimple_add_tmp_var is made. As in the following diff: % svn diff c-gimplify.c Index: c-gimplify.c =================================================================== --- c-gimplify.c (revision 116462) +++ c-gimplify.c (working copy) @@ -538,7 +538,7 @@ /* This decl isn't mentioned in the enclosing block, so add it to the list of temps. FIXME it seems a bit of a kludge to say that anonymous artificial vars aren't pushed, but everything else is. */ - if (DECL_NAME (decl) == NULL_TREE) + if (DECL_NAME (decl) == NULL_TREE && !DECL_SEEN_IN_BIND_EXPR_P (decl)) gimple_add_tmp_var (decl); This fixes the problem I am encouterring as well as the test case in this PR.
Wait a minute the C front-end produces for this testcase: <<< Unknown tree: compound_literal_expr struct A D.1524 = {.i=0}; >>> .i = <<< Unknown tree: compound_literal_expr struct A D.1524 = {.i=0}; >>> .i + 1; so obviously we are going to gimplify the compound_literal_expr twice.
for +=/-= we could use PREINCREMENT_EXPR/PREDECREMENT_EXPR trees but for *=, /=, |=, ^=, we cannot use any of the above. I wonder if a SAVE_EXPR make this work?
The patch in comment#3 is OK if the testcase is added to gcc.c-torture/compile. Please post the final patch to gcc-patches.
Subject: Bug 28418 Author: jsm28 Date: Fri Aug 25 21:14:24 2006 New Revision: 116436 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=116436 Log: 2006-08-25 Fariborz Jahanian <fjahanian@apple.com> PR c/28418 * c-gimplify.c (gimplify_compound_literal_expr): Don't add variable again if DECL_SEEN_IN_BIND_EXPR_P. 2006-08-25 Joseph S. Myers <joseph@codesourcery.com> * gcc.c-torture/compile/compound-literal-1.c: New test. Added: trunk/gcc/testsuite/gcc.c-torture/compile/compound-literal-1.c Modified: trunk/gcc/ChangeLog trunk/gcc/c-gimplify.c trunk/gcc/testsuite/ChangeLog
I was about to sub mit the patch. Thank you for this patch. - Fariborz > Subject: Bug 28418 > > Author: jsm28 > Date: Fri Aug 25 21:14:24 2006 > New Revision: 116436 > > URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=116436 > Log: > 2006-08-25 Fariborz Jahanian <fjahanian@apple.com> > > PR c/28418 > * c-gimplify.c (gimplify_compound_literal_expr): Don't add > variable again if DECL_SEEN_IN_BIND_EXPR_P. > > 2006-08-25 Joseph S. Myers <joseph@codesourcery.com> > > * gcc.c-torture/compile/compound-literal-1.c: New test. > > Added: > trunk/gcc/testsuite/gcc.c-torture/compile/compound-literal-1.c > Modified: > trunk/gcc/ChangeLog > trunk/gcc/c-gimplify.c > trunk/gcc/testsuite/ChangeLog >
Subject: Bug 28418 Author: jsm28 Date: Fri Aug 25 22:52:40 2006 New Revision: 116446 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=116446 Log: 2006-08-25 Fariborz Jahanian <fjahanian@apple.com> PR c/28418 * c-gimplify.c (gimplify_compound_literal_expr): Don't add variable again if DECL_SEEN_IN_BIND_EXPR_P. 2006-08-25 Joseph S. Myers <joseph@codesourcery.com> * gcc.c-torture/compile/compound-literal-1.c: New test. Added: branches/gcc-4_1-branch/gcc/testsuite/gcc.c-torture/compile/compound-literal-1.c - copied unchanged from r116436, trunk/gcc/testsuite/gcc.c-torture/compile/compound-literal-1.c Modified: branches/gcc-4_1-branch/gcc/ChangeLog branches/gcc-4_1-branch/gcc/c-gimplify.c branches/gcc-4_1-branch/gcc/testsuite/ChangeLog
Subject: Bug 28418 Author: jsm28 Date: Sat Aug 26 00:24:31 2006 New Revision: 116461 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=116461 Log: 2006-08-25 Fariborz Jahanian <fjahanian@apple.com> PR c/28418 * c-gimplify.c (gimplify_compound_literal_expr): Don't add variable again if DECL_SEEN_IN_BIND_EXPR_P. testsuite: 2006-08-25 Joseph S. Myers <joseph@codesourcery.com> * gcc.c-torture/compile/compound-literal-1.c: New test. Added: branches/gcc-4_0-branch/gcc/testsuite/gcc.c-torture/compile/compound-literal-1.c - copied unchanged from r116436, trunk/gcc/testsuite/gcc.c-torture/compile/compound-literal-1.c Modified: branches/gcc-4_0-branch/gcc/ChangeLog branches/gcc-4_0-branch/gcc/c-gimplify.c branches/gcc-4_0-branch/gcc/testsuite/ChangeLog
Fixed.