[gomp] Fix omp for scoping in templates

Jakub Jelinek jakub@redhat.com
Wed Oct 26 08:45:00 GMT 2005


Hi!

do_poplevel when processing_template_decl doesn't create a BIND_EXPR.
Therefore if processing_template_decl, we need to stick the DECL_EXPR
somewhere into the OMP_FOR (OMP_FOR_PRE_BODY sounds like a good choice to me)
and when tsubsting it expand it.

I'm attaching 2 alternative patches.  The first one touches just the C++
FE, on the other side will not report diagnostics for omp for loops
in templates that are never instantiated and where the loop header
is not template dependent.

Ok for gomp?  First or second patch?

	Jakub
-------------- next part --------------
2005-10-26  Jakub Jelinek  <jakub@redhat.com>

	PR c++/24512
	* cp-tree.h (finish_omp_for): Add PRE_BODY argument.
	* semantics.c (finish_omp_for): Likewise.  If processing template
	and PRE_BODY is not empty, also defer it.  Set OMP_FOR_PRE_BODY
	to PRE_BODY if deferring or add it into the current statement list.
	* parser.c (cp_parser_omp_for_loop): Expand optional DECL_EXPRs
	into PRE_BODY statement list.  Pass it to finish_omp_for.
	* pt.c (tsubst_expr) <case OMP_FOR>: tsubst_expr also OMP_FOR_PRE_BODY
	into PRE_BODY stmt list, pass it to finish_omp_for.  Put all the
	statements into sk_omp scope.

	* g++.dg/gomp/for-15.C: New test.

--- gcc/cp/cp-tree.h.jj	2005-10-24 16:29:22.000000000 +0200
+++ gcc/cp/cp-tree.h	2005-10-26 09:19:28.000000000 +0200
@@ -4256,7 +4256,7 @@ extern tree finish_omp_structured_block	
 extern tree begin_omp_parallel			(void);
 extern tree finish_omp_parallel			(tree, tree);
 extern tree finish_omp_for			(location_t, tree, tree,
-						 tree, tree, tree);
+						 tree, tree, tree, tree);
 extern void finish_omp_atomic			(enum tree_code, tree, tree);
 extern enum omp_clause_default_kind cxx_omp_predetermined_sharing (tree);
 extern tree cxx_omp_clause_default_ctor		(tree);
--- gcc/cp/semantics.c.jj	2005-10-25 22:20:37.000000000 +0200
+++ gcc/cp/semantics.c	2005-10-26 09:38:46.000000000 +0200
@@ -3662,11 +3662,13 @@ finish_omp_parallel (tree clauses, tree 
 /* Build and validate an OMP_FOR statement.  CLAUSES, BODY, COND, INCR
    are directly for their associated operands in the statement.  DECL
    and INIT are a combo; if DECL is NULL then INIT ought to be a
-   MODIFY_EXPR, and the DECL should be extracted.  */
+   MODIFY_EXPR, and the DECL should be extracted.  PRE_BODY are
+   optional statements that need to go before the loop into its
+   sk_omp scope.  */
 
 tree
 finish_omp_for (location_t locus, tree decl, tree init, tree cond,
-		tree incr, tree body)
+		tree incr, tree body, tree pre_body)
 {
   if (decl == NULL)
     {
@@ -3698,7 +3700,8 @@ finish_omp_for (location_t locus, tree d
   if (type_dependent_expression_p (decl)
       || type_dependent_expression_p (init)
       || type_dependent_expression_p (cond)
-      || type_dependent_expression_p (incr))
+      || type_dependent_expression_p (incr)
+      || (processing_template_decl && ! IS_EMPTY_STMT (pre_body)))
     {
       tree stmt = make_node (OMP_FOR);
 
@@ -3712,6 +3715,7 @@ finish_omp_for (location_t locus, tree d
       OMP_FOR_COND (stmt) = cond;
       OMP_FOR_INCR (stmt) = incr;
       OMP_FOR_BODY (stmt) = body;
+      OMP_FOR_PRE_BODY (stmt) = pre_body;
 
       SET_EXPR_LOCATION (stmt, locus);
       return add_stmt (stmt);
@@ -3723,6 +3727,8 @@ finish_omp_for (location_t locus, tree d
       return NULL;
     }
 
+  if (! IS_EMPTY_STMT (pre_body))
+    add_stmt (pre_body);
   init = build_modify_expr (decl, NOP_EXPR, init);
   return c_finish_omp_for (locus, decl, init, cond, incr, body);
 }
--- gcc/cp/parser.c.jj	2005-10-25 22:20:37.000000000 +0200
+++ gcc/cp/parser.c	2005-10-26 09:19:04.000000000 +0200
@@ -18238,7 +18238,7 @@ cp_parser_omp_flush (cp_parser *parser, 
 static tree
 cp_parser_omp_for_loop (cp_parser *parser)
 {
-  tree init, cond, incr, body, decl;
+  tree init, cond, incr, body, decl, pre_body;
   location_t loc;
 
   if (!cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR))
@@ -18251,6 +18251,7 @@ cp_parser_omp_for_loop (cp_parser *parse
     return NULL;
 
   init = decl = NULL;
+  pre_body = push_stmt_list ();
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
     {
       cp_decl_specifier_seq type_specifiers;
@@ -18303,6 +18304,7 @@ cp_parser_omp_for_loop (cp_parser *parse
 	}
     }
   cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+  pre_body = pop_stmt_list (pre_body);
 
   cond = NULL;
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
@@ -18328,7 +18330,7 @@ cp_parser_omp_for_loop (cp_parser *parse
   cp_parser_statement (parser, NULL_TREE, false);
   body = pop_stmt_list (body);
 
-  return finish_omp_for (loc, decl, init, cond, incr, body);
+  return finish_omp_for (loc, decl, init, cond, incr, body, pre_body);
 }
 
 /* OpenMP 2.5:
--- gcc/cp/pt.c.jj	2005-10-25 10:59:05.000000000 +0200
+++ gcc/cp/pt.c	2005-10-26 10:03:17.000000000 +0200
@@ -8456,7 +8456,7 @@ tsubst_expr (tree t, tree args, tsubst_f
 
     case OMP_FOR:
       {
-	tree clauses, decl, init, cond, incr;
+	tree clauses, decl, init, cond, incr, body, pre_body;
 
 	clauses = tsubst_omp_clauses (OMP_FOR_CLAUSES (t),
 				      args, complain, in_decl);
@@ -8467,13 +8467,22 @@ tsubst_expr (tree t, tree args, tsubst_f
 	cond = tsubst_expr (OMP_FOR_COND (t), args, complain, in_decl);
 	incr = tsubst_expr (OMP_FOR_INCR (t), args, complain, in_decl);
 
-	stmt = push_stmt_list ();
+	stmt = begin_omp_structured_block ();
+
+	pre_body = push_stmt_list ();
+	tsubst_expr (OMP_FOR_PRE_BODY (t), args, complain, in_decl);
+	pre_body = pop_stmt_list (pre_body);
+
+	body = push_stmt_list ();
 	tsubst_expr (OMP_FOR_BODY (t), args, complain, in_decl);
-	stmt = pop_stmt_list (stmt);
+	body = pop_stmt_list (body);
 
-	t = finish_omp_for (EXPR_LOCATION (t), decl, init, cond, incr, stmt);
+	t = finish_omp_for (EXPR_LOCATION (t), decl, init, cond, incr, body,
+			    pre_body);
 	if (t)
 	  OMP_FOR_CLAUSES (t) = clauses;
+
+	add_stmt (finish_omp_structured_block (stmt));
       }
       break;
 
--- gcc/testsuite/g++.dg/gomp/for-15.C.jj	2005-10-26 10:09:27.000000000 +0200
+++ gcc/testsuite/g++.dg/gomp/for-15.C	2005-10-26 10:09:05.000000000 +0200
@@ -0,0 +1,35 @@
+// PR c++/24512
+// { dg-do compile }
+
+template<typename T> void foo ()
+{
+#pragma omp for
+  for (int i = 0; i < 10; i++);
+
+#pragma omp for
+  for (int i = 0; i < 10; i++);
+
+#pragma omp for
+  for (T j = 0; j < 10; j++);
+
+#pragma omp for
+  for (T j = 0; j < 10; j++);
+
+#pragma omp parallel for
+  for (int k = 0; k < 10; k++);
+
+#pragma omp parallel for
+  for (int k = 0; k < 10; k++);
+
+#pragma omp parallel for
+  for (T l = 0; l < 10; l++);
+
+#pragma omp parallel for
+  for (T l = 0; l < 10; l++);
+}
+
+void bar ()
+{
+  foo<int> ();
+  foo<long> ();
+}
-------------- next part --------------
2005-10-26  Jakub Jelinek  <jakub@redhat.com>

	PR c++/24512
	* c-common.h (c_finish_omp_for): Add PRE_BODY argument.
	* c-omp.c (c_finish_omp_for): Likewise.  Set OMP_FOR_PRE_BODY
	to that argument.
	* c-parser.c (c_parser_omp_for_loop): Adjust c_finish_omp_for
	caller.
cp/
	* cp-tree.h (finish_omp_for): Add PRE_BODY argument.
	* semantics.c (finish_omp_for): Likewise.  Set OMP_FOR_PRE_BODY
	to PRE_BODY if deferring, add it into the current statement list
	if not processing template decl or pass it to c_finish_omp_for.
	* parser.c (cp_parser_omp_for_loop): Expand optional DECL_EXPRs
	into PRE_BODY statement list.  Pass it to finish_omp_for.
	* pt.c (tsubst_expr) <case OMP_FOR>: tsubst_expr also OMP_FOR_PRE_BODY
	into PRE_BODY stmt list, pass it to finish_omp_for.  Put all the
	statements into sk_omp scope.
testsuite/
	* g++.dg/gomp/for-15.C: New test.

--- gcc/c-common.h.jj	2005-10-20 11:12:34.000000000 +0200
+++ gcc/c-common.h	2005-10-26 10:34:10.000000000 +0200
@@ -939,7 +939,7 @@ extern tree c_finish_omp_ordered (tree);
 extern void c_finish_omp_barrier (void);
 extern void c_finish_omp_atomic (enum tree_code, tree, tree);
 extern void c_finish_omp_flush (void);
-extern tree c_finish_omp_for (location_t, tree, tree, tree, tree, tree);
+extern tree c_finish_omp_for (location_t, tree, tree, tree, tree, tree, tree);
 extern void c_split_parallel_clauses (tree, tree *, tree *);
 extern enum omp_clause_default_kind c_omp_predetermined_sharing (tree);
 
--- gcc/c-omp.c.jj	2005-10-20 11:12:34.000000000 +0200
+++ gcc/c-omp.c	2005-10-26 10:36:10.000000000 +0200
@@ -144,13 +144,14 @@ c_finish_omp_flush (void)
 
 
 /* Validate and emit code for the OpenMP directive #pragma omp for.
-   INIT, COND, INCR and BODY are the four basic elements of the loop
-   (initialization expression, controlling predicate, increment
-   expression and body of the loop).  DECL is the iteration variable.  */
+   INIT, COND, INCR, BODY and PRE_BODY are the five basic elements
+   of the loop (initialization expression, controlling predicate, increment
+   expression, body of the loop and statements to go before the loop).
+   DECL is the iteration variable.  */
 
 tree
 c_finish_omp_for (location_t locus, tree decl, tree init, tree cond,
-		  tree incr, tree body)
+		  tree incr, tree body, tree pre_body)
 {
   location_t elocus = locus;
   bool fail = false;
@@ -276,6 +277,7 @@ c_finish_omp_for (location_t locus, tree
       OMP_FOR_COND (t) = cond;
       OMP_FOR_INCR (t) = incr;
       OMP_FOR_BODY (t) = body;
+      OMP_FOR_PRE_BODY (t) = pre_body;
 
       SET_EXPR_LOCATION (t, locus);
       return add_stmt (t);
--- gcc/cp/semantics.c.jj	2005-10-25 22:20:37.000000000 +0200
+++ gcc/cp/semantics.c	2005-10-26 10:37:35.000000000 +0200
@@ -3662,11 +3662,13 @@ finish_omp_parallel (tree clauses, tree 
 /* Build and validate an OMP_FOR statement.  CLAUSES, BODY, COND, INCR
    are directly for their associated operands in the statement.  DECL
    and INIT are a combo; if DECL is NULL then INIT ought to be a
-   MODIFY_EXPR, and the DECL should be extracted.  */
+   MODIFY_EXPR, and the DECL should be extracted.  PRE_BODY are
+   optional statements that need to go before the loop into its
+   sk_omp scope.  */
 
 tree
 finish_omp_for (location_t locus, tree decl, tree init, tree cond,
-		tree incr, tree body)
+		tree incr, tree body, tree pre_body)
 {
   if (decl == NULL)
     {
@@ -3712,6 +3714,7 @@ finish_omp_for (location_t locus, tree d
       OMP_FOR_COND (stmt) = cond;
       OMP_FOR_INCR (stmt) = incr;
       OMP_FOR_BODY (stmt) = body;
+      OMP_FOR_PRE_BODY (stmt) = pre_body;
 
       SET_EXPR_LOCATION (stmt, locus);
       return add_stmt (stmt);
@@ -3723,8 +3726,15 @@ finish_omp_for (location_t locus, tree d
       return NULL;
     }
 
+  if (pre_body == NULL || IS_EMPTY_STMT (pre_body))
+    pre_body = NULL;
+  else if (! processing_template_decl)
+    {
+      add_stmt (pre_body);
+      pre_body = NULL;
+    }
   init = build_modify_expr (decl, NOP_EXPR, init);
-  return c_finish_omp_for (locus, decl, init, cond, incr, body);
+  return c_finish_omp_for (locus, decl, init, cond, incr, body, pre_body);
 }
 
 void
--- gcc/cp/parser.c.jj	2005-10-25 22:20:37.000000000 +0200
+++ gcc/cp/parser.c	2005-10-26 09:19:04.000000000 +0200
@@ -18238,7 +18238,7 @@ cp_parser_omp_flush (cp_parser *parser, 
 static tree
 cp_parser_omp_for_loop (cp_parser *parser)
 {
-  tree init, cond, incr, body, decl;
+  tree init, cond, incr, body, decl, pre_body;
   location_t loc;
 
   if (!cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR))
@@ -18251,6 +18251,7 @@ cp_parser_omp_for_loop (cp_parser *parse
     return NULL;
 
   init = decl = NULL;
+  pre_body = push_stmt_list ();
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
     {
       cp_decl_specifier_seq type_specifiers;
@@ -18303,6 +18304,7 @@ cp_parser_omp_for_loop (cp_parser *parse
 	}
     }
   cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+  pre_body = pop_stmt_list (pre_body);
 
   cond = NULL;
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
@@ -18328,7 +18330,7 @@ cp_parser_omp_for_loop (cp_parser *parse
   cp_parser_statement (parser, NULL_TREE, false);
   body = pop_stmt_list (body);
 
-  return finish_omp_for (loc, decl, init, cond, incr, body);
+  return finish_omp_for (loc, decl, init, cond, incr, body, pre_body);
 }
 
 /* OpenMP 2.5:
--- gcc/cp/cp-tree.h.jj	2005-10-24 16:29:22.000000000 +0200
+++ gcc/cp/cp-tree.h	2005-10-26 09:19:28.000000000 +0200
@@ -4256,7 +4256,7 @@ extern tree finish_omp_structured_block	
 extern tree begin_omp_parallel			(void);
 extern tree finish_omp_parallel			(tree, tree);
 extern tree finish_omp_for			(location_t, tree, tree,
-						 tree, tree, tree);
+						 tree, tree, tree, tree);
 extern void finish_omp_atomic			(enum tree_code, tree, tree);
 extern enum omp_clause_default_kind cxx_omp_predetermined_sharing (tree);
 extern tree cxx_omp_clause_default_ctor		(tree);
--- gcc/cp/pt.c.jj	2005-10-25 10:59:05.000000000 +0200
+++ gcc/cp/pt.c	2005-10-26 10:03:17.000000000 +0200
@@ -8456,7 +8456,7 @@ tsubst_expr (tree t, tree args, tsubst_f
 
     case OMP_FOR:
       {
-	tree clauses, decl, init, cond, incr;
+	tree clauses, decl, init, cond, incr, body, pre_body;
 
 	clauses = tsubst_omp_clauses (OMP_FOR_CLAUSES (t),
 				      args, complain, in_decl);
@@ -8467,13 +8467,22 @@ tsubst_expr (tree t, tree args, tsubst_f
 	cond = tsubst_expr (OMP_FOR_COND (t), args, complain, in_decl);
 	incr = tsubst_expr (OMP_FOR_INCR (t), args, complain, in_decl);
 
-	stmt = push_stmt_list ();
+	stmt = begin_omp_structured_block ();
+
+	pre_body = push_stmt_list ();
+	tsubst_expr (OMP_FOR_PRE_BODY (t), args, complain, in_decl);
+	pre_body = pop_stmt_list (pre_body);
+
+	body = push_stmt_list ();
 	tsubst_expr (OMP_FOR_BODY (t), args, complain, in_decl);
-	stmt = pop_stmt_list (stmt);
+	body = pop_stmt_list (body);
 
-	t = finish_omp_for (EXPR_LOCATION (t), decl, init, cond, incr, stmt);
+	t = finish_omp_for (EXPR_LOCATION (t), decl, init, cond, incr, body,
+			    pre_body);
 	if (t)
 	  OMP_FOR_CLAUSES (t) = clauses;
+
+	add_stmt (finish_omp_structured_block (stmt));
       }
       break;
 
--- gcc/c-parser.c.jj	2005-10-22 09:00:37.000000000 +0200
+++ gcc/c-parser.c	2005-10-26 10:34:25.000000000 +0200
@@ -7345,7 +7345,7 @@ c_parser_omp_for_loop (c_parser *parser)
   /* Only bother calling c_finish_omp_for if we havn't already generated
      an error from the initialization parsing.  */
   if (decl != NULL)
-    return c_finish_omp_for (loc, decl, init, cond, incr, body);
+    return c_finish_omp_for (loc, decl, init, cond, incr, body, NULL);
   return NULL;
 
  error_init:
--- gcc/testsuite/g++.dg/gomp/for-15.C.jj	2005-10-26 10:09:27.000000000 +0200
+++ gcc/testsuite/g++.dg/gomp/for-15.C	2005-10-26 10:09:05.000000000 +0200
@@ -0,0 +1,35 @@
+// PR c++/24512
+// { dg-do compile }
+
+template<typename T> void foo ()
+{
+#pragma omp for
+  for (int i = 0; i < 10; i++);
+
+#pragma omp for
+  for (int i = 0; i < 10; i++);
+
+#pragma omp for
+  for (T j = 0; j < 10; j++);
+
+#pragma omp for
+  for (T j = 0; j < 10; j++);
+
+#pragma omp parallel for
+  for (int k = 0; k < 10; k++);
+
+#pragma omp parallel for
+  for (int k = 0; k < 10; k++);
+
+#pragma omp parallel for
+  for (T l = 0; l < 10; l++);
+
+#pragma omp parallel for
+  for (T l = 0; l < 10; l++);
+}
+
+void bar ()
+{
+  foo<int> ();
+  foo<long> ();
+}


More information about the Gcc-patches mailing list