diff mbox

[committed] Fix ICE with lambda in OpenMP for loop iterator dependent init (PR c++/58706)

Message ID 20160808200014.GS14857@tucnak.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Aug. 8, 2016, 8 p.m. UTC
Hi!

When parsing lambdas, the C++ FE emits DECL_EXPRs with TYPE_DECLs for the
lambda structs, which confuse the OpenMP iterator init handling.

Fixed by moving those over into the for block.

Bootstrapped/regtested on x86_64-linux and i686-linux, committed to trunk.

2016-08-08  Jakub Jelinek  <jakub@redhat.com>

	PR c++/58706
	* parser.c: Include tree-iterator.h.
	(cp_parser_omp_for_loop_init): Move lambda DECL_EXPRs from init
	to FOR_BLOCK.
	(cp_parser_omp_for_loop): Handle non-STATEMENT_LIST FOR_BLOCK
	entries.

	* testsuite/libgomp.c++/pr58706.C: New test.


	Jakub
diff mbox

Patch

--- gcc/cp/parser.c.jj	2016-08-06 12:11:45.000000000 +0200
+++ gcc/cp/parser.c	2016-08-08 18:12:06.335194885 +0200
@@ -41,6 +41,7 @@  along with GCC; see the file COPYING3.
 #include "context.h"
 #include "cp-cilkplus.h"
 #include "gcc-rich-location.h"
+#include "tree-iterator.h"
 
 
 /* The lexer.  */
@@ -33495,7 +33496,33 @@  cp_parser_omp_for_loop_init (cp_parser *
 		  init = NULL_TREE;
 		}
 	      else
-		init = pop_stmt_list (this_pre_body);
+		{
+		  init = pop_stmt_list (this_pre_body);
+		  if (init && TREE_CODE (init) == STATEMENT_LIST)
+		    {
+		      tree_stmt_iterator i = tsi_start (init);
+		      /* Move lambda DECL_EXPRs to FOR_BLOCK.  */
+		      while (!tsi_end_p (i))
+			{
+			  tree t = tsi_stmt (i);
+			  if (TREE_CODE (t) == DECL_EXPR
+			      && TREE_CODE (DECL_EXPR_DECL (t)) == TYPE_DECL)
+			    {
+			      tsi_delink (&i);
+			      vec_safe_push (for_block, t);
+			      continue;
+			    }
+			  break;
+			}
+		      if (tsi_one_before_end_p (i))
+			{
+			  tree t = tsi_stmt (i);
+			  tsi_delink (&i);
+			  free_stmt_list (init);
+			  init = t;
+			}
+		    }
+		}
 	      this_pre_body = NULL_TREE;
 	    }
 	  else
@@ -33899,7 +33926,13 @@  cp_parser_omp_for_loop (cp_parser *parse
     }
 
   while (!for_block->is_empty ())
-    add_stmt (pop_stmt_list (for_block->pop ()));
+    {
+      tree t = for_block->pop ();
+      if (TREE_CODE (t) == STATEMENT_LIST)
+	add_stmt (pop_stmt_list (t));
+      else
+	add_stmt (t);
+    }
   release_tree_vector (for_block);
 
   return ret;
--- libgomp/testsuite/libgomp.c++/pr58706.C.jj	2016-08-08 18:41:08.129276653 +0200
+++ libgomp/testsuite/libgomp.c++/pr58706.C	2016-08-08 18:47:44.014521578 +0200
@@ -0,0 +1,47 @@ 
+// PR c++/58706
+// { dg-do run }
+// { dg-options "-std=c++11" }
+
+template <typename T>
+T
+foo ()
+{
+  T n = T ();
+#pragma omp parallel for reduction (+: n)
+  for (T i = [](){ return 3; }(); i < 10; ++i)
+    n++;
+  return n;
+}
+
+template <typename T>
+T
+bar ()
+{
+  T n = T ();
+#pragma omp parallel for reduction (+: n)
+  for (T i = [](){ return 1; }() + [](){ return 4; }(); i < 10; ++i)
+    n++;
+  return n;
+}
+
+template <typename T>
+T
+baz ()
+{
+  T n = T ();
+#pragma omp parallel for reduction (+: n)
+  for (T i = T (); i < [](){ return 7; }() + [](){ return 11; }(); i += [](){ return 3; }() - [](){ return 1; }())
+    n++;
+  return n;
+}
+
+int
+main ()
+{
+  if (foo <int> () != 7 || foo <long long> () != 7)
+    __builtin_abort ();
+  if (bar <int> () != 5 || bar <char> () != 5)
+    __builtin_abort ();
+  if (baz <int> () != 9 || baz <long long> () != 9)
+    __builtin_abort ();
+}