This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[gomp] Add some diagnostics
- From: Diego Novillo <dnovillo at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 22 Sep 2005 10:35:06 -0400
- Subject: [gomp] Add some diagnostics
Now that I could fix all the merge problems that had rth
chuckling to himself, I can commit some minor diagnostics for
parallel loops.
I have no idea whether the messages we are emitting are properly
formatted or follow the accepted style for error messages. Could
one of the FE folks take a look? The recovery is to emit a
sequential loop if we see a malformed parallel loop, otherwise we
get confused down the line if we end up with a half finished loop
structure.
This also adds a small test with valid and malformed parallel
loops.
* c-tree.h (c_finish_gomp_for): Declare
* c-typeck.c (c_finish_gomp_for): New.
* c-parser.c (c_parser_for_statement): Call it. If the
parallel loop was malformed, call c_finish_loop to emit a
sequential loop.
testsuite/ChangeLog.gomp:
* gcc.dg/gomp/omp-for-1.c: New test.
Index: c-parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-parser.c,v
retrieving revision 2.17.4.8
diff -d -u -p -r2.17.4.8 c-parser.c
--- c-parser.c 21 Sep 2005 23:44:45 -0000 2.17.4.8
+++ c-parser.c 22 Sep 2005 14:05:12 -0000
@@ -4174,8 +4174,14 @@ c_parser_for_statement (c_parser *parser
if (!is_omp_for)
c_finish_loop (loc, cond, incr, body, c_break_label, c_cont_label, true);
else
- add_stmt (build (GOMP_FOR, void_type_node, pop_omp_clauses (), init, cond,
- incr, body));
+ {
+ tree t = c_finish_gomp_for (init, cond, incr, body, pop_omp_clauses ());
+ if (t)
+ add_stmt (t);
+ else
+ c_finish_loop (loc, cond, incr, body, c_break_label, c_cont_label,
+ true);
+ }
add_stmt (c_end_compound_stmt (block, flag_isoc99));
c_break_label = save_break;
c_cont_label = save_cont;
Index: c-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-tree.h,v
retrieving revision 1.203.4.3
diff -d -u -p -r1.203.4.3 c-tree.h
--- c-tree.h 21 Sep 2005 23:44:46 -0000 1.203.4.3
+++ c-tree.h 22 Sep 2005 14:05:12 -0000
@@ -574,6 +574,7 @@ extern tree c_finish_goto_ptr (tree);
extern void c_begin_vm_scope (unsigned int);
extern void c_end_vm_scope (unsigned int);
extern tree c_expr_to_decl (tree, bool *, bool *, bool *);
+extern tree c_finish_gomp_for (tree, tree, tree, tree, tree);
/* Set to 0 at beginning of a function definition, set to 1 if
a return statement that specifies a return value is seen. */
Index: c-typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-typeck.c,v
retrieving revision 1.450.4.4
diff -d -u -p -r1.450.4.4 c-typeck.c
--- c-typeck.c 14 Sep 2005 12:43:07 -0000 1.450.4.4
+++ c-typeck.c 22 Sep 2005 14:05:14 -0000
@@ -8257,3 +8257,173 @@ c_expr_to_decl (tree expr, bool *tc ATTR
else
return expr;
}
+
+
+/* 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). CLAUSES is the set of data
+ sharing and copying clauses found at the start of the directive. */
+
+tree
+c_finish_gomp_for (tree init, tree cond, tree incr, tree body, tree clauses)
+{
+ bool found;
+ tree t, loop_ix = NULL_TREE;
+
+ /* Validate the form of the loop. It must be of the form (OpenMP
+ Public Draft v2.5)
+
+ for (init-expr; var relop b; incr-expr)
+
+ init-expr One of the following
+ var = lb
+ integer-type var = lb
+
+ incr-expr One of the following
+ ++var
+ var++
+ --var
+ var--
+ var += incr
+ var -= incr
+ var = var + incr
+ var = incr + var
+ var = var - incr
+
+ var A signed integer variable. If it was shared,
+ it is implicitly made private. It may only be
+ modified inside incr-expr. After the loop its
+ value is indeterminate, unles it is marked
+ lastprivate.
+
+ relop One of <, <=, > or >=
+
+ lb, b, incr Loop invariant integer expressions. There is
+ no synchronization during the evaluation of
+ these expressions. Th order, frequency and
+ side-effects of these expressions are
+ unspecified. */
+ if (cond == NULL_TREE)
+ {
+ error ("missing controlling predicate in %<omp for%> loop");
+ return NULL_TREE;
+ }
+ else
+ {
+ bool cond_ok = false;
+
+ if (TREE_CODE (cond) == LT_EXPR
+ || TREE_CODE (cond) == LE_EXPR
+ || TREE_CODE (cond) == GT_EXPR
+ || TREE_CODE (cond) == GE_EXPR)
+ {
+ loop_ix = TREE_OPERAND (cond, 0);
+ if (DECL_P (loop_ix))
+ cond_ok = true;
+ }
+
+ if (!cond_ok)
+ {
+ error ("invalid controlling predicate in %<omp for%> loop");
+ return NULL_TREE;
+ }
+ }
+
+ /* If we got to this point, we must have a loop index variable. */
+ gcc_assert (loop_ix);
+
+ if (incr == NULL_TREE)
+ {
+ error ("missing increment expression in %<omp for%> loop");
+ return NULL_TREE;
+ }
+ else
+ {
+ bool incr_ok = false;
+ enum tree_code code = TREE_CODE (incr);
+
+ /* Check all the valid increment expressions: v++, v--, ++v, --v,
+ v = v + incr, v = incr + v and v = v - incr. */
+ if ((code == POSTINCREMENT_EXPR && TREE_OPERAND (incr, 0) == loop_ix)
+ || (code == PREINCREMENT_EXPR && TREE_OPERAND (incr, 0) == loop_ix)
+ || (code == POSTDECREMENT_EXPR && TREE_OPERAND (incr, 0) == loop_ix)
+ || (code == PREDECREMENT_EXPR && TREE_OPERAND (incr, 0) == loop_ix)
+ || (code == MODIFY_EXPR
+ && TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
+ && (TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == loop_ix
+ || TREE_OPERAND (TREE_OPERAND (incr, 1), 1) == loop_ix))
+ || (code == MODIFY_EXPR
+ && TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR
+ && TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == loop_ix))
+ incr_ok = true;
+
+ if (!incr_ok)
+ {
+ error ("invalid increment expression in %<omp for%> loop");
+ return NULL_TREE;
+ }
+ }
+
+ if (init == NULL_TREE)
+ {
+ if (flag_isoc99)
+ {
+ /* Only in C99 may the init expression be empty. If the
+ loop index variable has a DECL_INITIAL expression, use it
+ to build the GOMP_FOR_INIT operand. */
+ if (DECL_INITIAL (loop_ix))
+ init = build (MODIFY_EXPR, TREE_TYPE (loop_ix),
+ loop_ix, DECL_INITIAL (loop_ix));
+ }
+
+ if (init == NULL_TREE)
+ {
+ error ("missing initialization expression in %<omp for%> loop");
+ return NULL_TREE;
+ }
+ }
+
+ /* The loop controlling variable is always private. Add it to the
+ list of private clauses. */
+ found = false;
+ for (t = clauses; t; t = TREE_CHAIN (t))
+ {
+ tree clause = TREE_VALUE (t);
+
+ if (TREE_CODE (clause) == GOMP_CLAUSE_PRIVATE)
+ {
+ tree n;
+
+ for (n = GOMP_PRIVATE_VARS (clause); n; n = TREE_CHAIN (n))
+ {
+ tree v = TREE_VALUE (n);
+ if (v == loop_ix)
+ {
+ found = true;
+ break;
+ }
+ }
+
+ /* If LOOP_IX is not mentioned in a private clause, add it. */
+ if (!found)
+ {
+ GOMP_PRIVATE_VARS (clause) =
+ tree_cons (NULL_TREE, loop_ix, GOMP_PRIVATE_VARS (clause));
+ found = true;
+ break;
+ }
+ }
+ }
+
+ /* If we did not even have a private clause, add one. */
+ if (!found)
+ clauses = tree_cons (NULL_TREE,
+ build (GOMP_CLAUSE_PRIVATE,
+ NULL_TREE,
+ tree_cons (NULL_TREE, loop_ix, NULL_TREE)),
+ clauses);
+
+ /* Build and return a GOMP_FOR tree. */
+ return (build (GOMP_FOR, void_type_node, clauses, init, cond, incr, body));
+}
Index: testsuite/gcc.dg/gomp/omp-for-1.c
===================================================================
RCS file: testsuite/gcc.dg/gomp/omp-for-1.c
diff -N testsuite/gcc.dg/gomp/omp-for-1.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/gomp/omp-for-1.c 22 Sep 2005 14:05:17 -0000
@@ -0,0 +1,48 @@
+/* { dg-do compile } */
+
+void foo (int j, int k)
+{
+ int i;
+
+ /* Valid loops. */
+ #pragma omp for
+ for (i = 0; i < 10; i++)
+ baz (i);
+
+ #pragma omp for
+ for (i = j; i <= 10; i+=4)
+ baz (i);
+
+ #pragma omp for
+ for (i = j; i > 0; i = i - 1)
+ baz (j);
+
+ #pragma omp for
+ for (i = j; i >= k; i--)
+ baz (i);
+
+ /* Malformed parallel loops. */
+ #pragma omp for
+ i = 0; /* { dg-error "for statement expected" } */
+ for ( ; i < 10; )
+ {
+ baz (i);
+ i++;
+ }
+
+ #pragma omp for
+ for (i = 0; ; i--)
+ {
+ if (i >= 10)
+ break;
+ baz (i);
+ } /* { dg-error "missing controlling predicate" } */
+
+ #pragma omp for
+ for (i = 0; i < 10 && j > 4; i-=3)
+ baz (i); /* { dg-error "invalid controlling predicate" } */
+
+ #pragma omp for
+ for (i = 0; i < 10; i-=3, j+=2)
+ baz (i); /* { dg-error "invalid increment expression" } */
+}