[gomp] structured blocks, part trey

Richard Henderson rth@redhat.com
Thu Oct 20 10:03:00 GMT 2005


The C++ part of the OpenMP spec has rules about exceptions and
how they may propagate.  While obviously we cannot diagnose these
at compile-time, we can certainly force the program to die if it
violates them.

So I wrap all of the grammar elements that say "structured-block"
with a MUST_NOT_THROW.  Which means that violations proceed to
std::terminate, ne'er to return.


r~


        * semantics.c (begin_omp_structured_block): New.
        (finish_omp_structured_block): New.
        (begin_omp_parallel, finish_omp_parallel): Use them.
        * parser.c (cp_parser_omp_structured_block): Likewise.
        (cp_parser_omp_for): Likewise.
        (cp_parser_omp_sections_scope): Likewise.
        * cp-tree.h: Declare them.

Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.1144.4.11
diff -u -p -d -r1.1144.4.11 cp-tree.h
--- cp/cp-tree.h	19 Oct 2005 09:44:07 -0000	1.1144.4.11
+++ cp/cp-tree.h	20 Oct 2005 09:50:08 -0000
@@ -4236,6 +4236,8 @@ extern void finalize_nrv			(tree *, tree
 extern void note_decl_for_pch			(tree);
 extern tree finish_omp_clauses			(tree);
 extern void finish_omp_threadprivate		(tree);
+extern tree begin_omp_structured_block		(void);
+extern tree finish_omp_structured_block		(tree);
 extern tree begin_omp_parallel			(void);
 extern tree finish_omp_parallel			(tree, tree);
 extern tree finish_omp_for			(location_t, tree, tree,
Index: cp/parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.340.4.15
diff -u -p -d -r1.340.4.15 parser.c
--- cp/parser.c	20 Oct 2005 09:02:10 -0000	1.340.4.15
+++ cp/parser.c	20 Oct 2005 09:50:11 -0000
@@ -18013,9 +18013,9 @@ cp_parser_omp_all_clauses (cp_parser *pa
 static tree
 cp_parser_omp_structured_block (cp_parser *parser)
 {
-  tree stmt = push_stmt_list ();
+  tree stmt = begin_omp_structured_block ();
   cp_parser_statement (parser, NULL_TREE, false);
-  return pop_stmt_list (stmt);
+  return finish_omp_structured_block (stmt);
 }
 
 /* OpenMP 2.5:
@@ -18255,6 +18255,8 @@ cp_parser_omp_for_loop (cp_parser *parse
   in_iteration_statement_p = parser->in_iteration_statement_p;
   parser->in_iteration_statement_p = true;
 
+  /* Note that the grammar doesn't call for a structured block here,
+     though the loop as a whole is a structured block.  */
   body = push_stmt_list ();
   cp_parser_statement (parser, NULL_TREE, false);
   body = pop_stmt_list (body);
@@ -18281,15 +18283,19 @@ cp_parser_omp_for_loop (cp_parser *parse
 static tree
 cp_parser_omp_for (cp_parser *parser, cp_token *pragma_tok)
 {
-  tree block, clauses, ret;
+  tree block, clauses, sb, ret;
 
   clauses = cp_parser_omp_all_clauses (parser, OMP_FOR_CLAUSE_MASK,
 				       "#pragma omp for", pragma_tok);
 
   block = begin_compound_stmt (0);
+  sb = begin_omp_structured_block ();
+
   ret = cp_parser_omp_for_loop (parser);
   if (ret)
     OMP_FOR_CLAUSES (ret) = clauses;
+
+  add_stmt (finish_omp_structured_block (sb));
   finish_compound_stmt (block);
 
   return ret;
@@ -18342,7 +18348,7 @@ cp_parser_omp_sections_scope (cp_parser 
 
   if (cp_lexer_peek_token (parser->lexer)->pragma_kind != PRAGMA_OMP_SECTION)
     {
-      substmt = push_stmt_list ();
+      substmt = begin_omp_structured_block ();
 
       while (1)
 	{
@@ -18357,7 +18363,7 @@ cp_parser_omp_sections_scope (cp_parser 
 	    break;
 	}
 
-      substmt = pop_stmt_list (substmt);
+      substmt = finish_omp_structured_block (substmt);
       substmt = build1 (OMP_SECTION, void_type_node, substmt);
       add_stmt (substmt);
     }
Index: cp/semantics.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/semantics.c,v
retrieving revision 1.475.4.11
diff -u -p -d -r1.475.4.11 semantics.c
--- cp/semantics.c	19 Oct 2005 23:33:59 -0000	1.475.4.11
+++ cp/semantics.c	20 Oct 2005 09:50:12 -0000
@@ -3541,36 +3541,58 @@ finish_omp_threadprivate (tree vars)
     }
 }
 
+/* Build a structured block.  Mostly we just want to wrap the thing
+   in a MUST_NOT_THROW_EXPR, which will enforce the constraint in
+   OpenMP 2.5 section 1.2.2 that throw may not violate the entry/exit
+   criteria of the structured block.  That is, an exception thrown
+   within the block must be caught within the block.  */
+
+tree
+begin_omp_structured_block (void)
+{
+  return push_stmt_list ();
+}
+
+tree
+finish_omp_structured_block (tree block)
+{
+  return build1 (MUST_NOT_THROW_EXPR, void_type_node, pop_stmt_list (block));
+}
+
 /* Like c_begin_compound_stmt, except force the retension of the BLOCK.  */
 
 tree
 begin_omp_parallel (void)
 {
-  tree outer, inner;
-  outer = push_stmt_list ();
+  tree l1, l2, l3;
+
   keep_next_level (true);
-  inner = begin_compound_stmt (0);
+  l1 = push_stmt_list ();
+  l2 = begin_compound_stmt (0);
+  l3 = begin_omp_structured_block ();
 
-  /* In order to pass two values to finish_omp_parallel without extra
+  /* In order to pass three values to finish_omp_parallel without extra
      complication in the interface here, wrap them in a cons node.  */
-  return tree_cons (outer, inner, NULL);
+  return tree_cons (l1, l2, l3);
 }
 
 tree
 finish_omp_parallel (tree clauses, tree cons)
 {
-  tree stmt, outer, inner;
+  tree stmt, l1, l2, l3;
 
-  outer = TREE_PURPOSE (cons);
-  inner = TREE_VALUE (cons);
+  l1 = TREE_PURPOSE (cons);
+  l2 = TREE_VALUE (cons);
+  l3 = TREE_CHAIN (cons);
   
-  finish_compound_stmt (inner);
-  outer = pop_stmt_list (outer);
+  add_stmt (finish_omp_structured_block (l3));
+  finish_compound_stmt (l2);
+  l1 = pop_stmt_list (l1);
 
   stmt = make_node (OMP_PARALLEL);
   TREE_TYPE (stmt) = void_type_node;
   OMP_PARALLEL_CLAUSES (stmt) = clauses;
-  OMP_PARALLEL_BODY (stmt) = outer;
+  OMP_PARALLEL_BODY (stmt) = l1;
 
   return add_stmt (stmt);
 }
Index: testsuite/g++.dg/gomp/block-1.C
===================================================================
RCS file: testsuite/g++.dg/gomp/block-1.C
diff -N testsuite/g++.dg/gomp/block-1.C
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/g++.dg/gomp/block-1.C	20 Oct 2005 09:50:12 -0000
@@ -0,0 +1,32 @@
+// { dg-do compile }
+// { dg-options "-fopenmp -fdump-tree-gimple" }
+
+void bar();
+void foo()
+{
+  #pragma omp critical
+    bar ();
+  #pragma omp master
+    bar ();
+  #pragma omp single
+    bar ();
+  #pragma omp for
+  for (int i = 0; i < 10; ++i)
+    bar ();
+  #pragma omp sections
+    { bar(); }
+  #pragma omp parallel
+    bar ();
+  #pragma omp parallel for
+  for (int i = 0; i < 10; ++i)
+    bar ();
+  #pragma omp parallel sections
+    {
+      bar ();
+      bar ();
+    #pragma omp section
+      bar ();
+    }
+}
+
+// { dg-final { scan-tree-dump-times "terminate" 10 "gimple" } }



More information about the Gcc-patches mailing list