/* This file contains routines to construct GNU OpenMP constructs,
called from parsing in the C and C++ front ends.
- Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
Contributed by Richard Henderson <rth@redhat.com>,
Diego Novillo <dnovillo@redhat.com>.
/* Complete a #pragma omp master construct. STMT is the structured-block
- that follows the pragma. */
+ that follows the pragma. LOC is the l*/
tree
-c_finish_omp_master (tree stmt)
+c_finish_omp_master (location_t loc, tree stmt)
{
- return add_stmt (build1 (OMP_MASTER, void_type_node, stmt));
+ tree t = add_stmt (build1 (OMP_MASTER, void_type_node, stmt));
+ SET_EXPR_LOCATION (t, loc);
+ return t;
}
/* Complete a #pragma omp critical construct. STMT is the structured-block
that follows the pragma, NAME is the identifier in the pragma, or null
- if it was omitted. */
+ if it was omitted. LOC is the location of the #pragma. */
tree
-c_finish_omp_critical (tree body, tree name)
+c_finish_omp_critical (location_t loc, tree body, tree name)
{
tree stmt = make_node (OMP_CRITICAL);
TREE_TYPE (stmt) = void_type_node;
OMP_CRITICAL_BODY (stmt) = body;
OMP_CRITICAL_NAME (stmt) = name;
+ SET_EXPR_LOCATION (stmt, loc);
return add_stmt (stmt);
}
/* Complete a #pragma omp ordered construct. STMT is the structured-block
- that follows the pragma. */
+ that follows the pragma. LOC is the location of the #pragma. */
tree
-c_finish_omp_ordered (tree stmt)
+c_finish_omp_ordered (location_t loc, tree stmt)
{
- return add_stmt (build1 (OMP_ORDERED, void_type_node, stmt));
+ tree t = build1 (OMP_ORDERED, void_type_node, stmt);
+ SET_EXPR_LOCATION (t, loc);
+ return add_stmt (t);
}
-/* Complete a #pragma omp barrier construct. */
+/* Complete a #pragma omp barrier construct. LOC is the location of
+ the #pragma. */
void
-c_finish_omp_barrier (void)
+c_finish_omp_barrier (location_t loc)
{
tree x;
x = built_in_decls[BUILT_IN_GOMP_BARRIER];
x = build_call_expr (x, 0);
+ SET_EXPR_LOCATION (x, loc);
add_stmt (x);
}
-/* Complete a #pragma omp taskwait construct. */
+/* Complete a #pragma omp taskwait construct. LOC is the location of the
+ pragma. */
void
-c_finish_omp_taskwait (void)
+c_finish_omp_taskwait (location_t loc)
{
tree x;
x = built_in_decls[BUILT_IN_GOMP_TASKWAIT];
x = build_call_expr (x, 0);
+ SET_EXPR_LOCATION (x, loc);
add_stmt (x);
}
-/* Complete a #pragma omp atomic construct. The expression to be
- implemented atomically is LHS code= RHS. The value returned is
- either error_mark_node (if the construct was erroneous) or an
- OMP_ATOMIC node which should be added to the current statement tree
- with add_stmt. */
+/* Complete a #pragma omp atomic construct. The expression to be
+ implemented atomically is LHS code= RHS. LOC is the location of
+ the atomic statement. The value returned is either error_mark_node
+ (if the construct was erroneous) or an OMP_ATOMIC node which should
+ be added to the current statement tree with add_stmt.*/
tree
-c_finish_omp_atomic (enum tree_code code, tree lhs, tree rhs)
+c_finish_omp_atomic (location_t loc, enum tree_code code, tree lhs, tree rhs)
{
tree x, type, addr;
&& !POINTER_TYPE_P (type)
&& !SCALAR_FLOAT_TYPE_P (type))
{
- error ("invalid expression type for %<#pragma omp atomic%>");
+ error_at (loc, "invalid expression type for %<#pragma omp atomic%>");
return error_mark_node;
}
/* Take and save the address of the lhs. From then on we'll reference it
via indirection. */
- addr = build_unary_op (input_location, ADDR_EXPR, lhs, 0);
+ addr = build_unary_op (loc, ADDR_EXPR, lhs, 0);
if (addr == error_mark_node)
return error_mark_node;
addr = save_expr (addr);
tree var = create_tmp_var_raw (TREE_TYPE (addr), NULL);
addr = build4 (TARGET_EXPR, TREE_TYPE (addr), var, addr, NULL, NULL);
}
- lhs = build_indirect_ref (input_location, addr, NULL);
+ lhs = build_indirect_ref (loc, addr, NULL);
/* There are lots of warnings, errors, and conversions that need to happen
in the course of interpreting a statement. Use the normal mechanisms
to do this, and then take it apart again. */
- x = build_modify_expr (input_location, lhs, code, rhs);
+ x = build_modify_expr (input_location, lhs, NULL_TREE, code,
+ input_location, rhs, NULL_TREE);
if (x == error_mark_node)
return error_mark_node;
gcc_assert (TREE_CODE (x) == MODIFY_EXPR);
rhs = TREE_OPERAND (x, 1);
/* Punt the actual generation of atomic operations to common code. */
- return build2 (OMP_ATOMIC, void_type_node, addr, rhs);
+ x = build2 (OMP_ATOMIC, void_type_node, addr, rhs);
+ SET_EXPR_LOCATION (x, loc);
+ return x;
}
-/* Complete a #pragma omp flush construct. We don't do anything with the
- variable list that the syntax allows. */
+/* Complete a #pragma omp flush construct. We don't do anything with
+ the variable list that the syntax allows. LOC is the location of
+ the #pragma. */
void
-c_finish_omp_flush (void)
+c_finish_omp_flush (location_t loc)
{
tree x;
x = built_in_decls[BUILT_IN_SYNCHRONIZE];
x = build_call_expr (x, 0);
+ SET_EXPR_LOCATION (x, loc);
add_stmt (x);
}
fail = true;
}
- init = build_modify_expr (elocus, decl, NOP_EXPR, init);
+ init = build_modify_expr (elocus, decl, NULL_TREE, NOP_EXPR,
+ /* FIXME diagnostics: This should
+ be the location of the INIT. */
+ elocus,
+ init,
+ NULL_TREE);
}
gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
gcc_assert (TREE_OPERAND (init, 0) == decl);
if (TREE_CODE (cond) == LT_EXPR
|| TREE_CODE (cond) == LE_EXPR
|| TREE_CODE (cond) == GT_EXPR
- || TREE_CODE (cond) == GE_EXPR)
+ || TREE_CODE (cond) == GE_EXPR
+ || TREE_CODE (cond) == NE_EXPR)
{
tree op0 = TREE_OPERAND (cond, 0);
tree op1 = TREE_OPERAND (cond, 1);
TREE_OPERAND (cond, 0) = decl;
cond_ok = true;
}
+
+ if (TREE_CODE (cond) == NE_EXPR)
+ {
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (decl)))
+ cond_ok = false;
+ else if (operand_equal_p (TREE_OPERAND (cond, 1),
+ TYPE_MIN_VALUE (TREE_TYPE (decl)),
+ 0))
+ TREE_SET_CODE (cond, GT_EXPR);
+ else if (operand_equal_p (TREE_OPERAND (cond, 1),
+ TYPE_MAX_VALUE (TREE_TYPE (decl)),
+ 0))
+ TREE_SET_CODE (cond, LT_EXPR);
+ else
+ cond_ok = false;
+ }
}
if (!cond_ok)
break;
incr_ok = true;
- if (POINTER_TYPE_P (TREE_TYPE (decl)))
+ if (POINTER_TYPE_P (TREE_TYPE (decl))
+ && TREE_OPERAND (incr, 1))
{
tree t = fold_convert (sizetype, TREE_OPERAND (incr, 1));
}
-/* Divide CLAUSES into two lists: those that apply to a parallel construct,
- and those that apply to a work-sharing construct. Place the results in
- *PAR_CLAUSES and *WS_CLAUSES respectively. In addition, add a nowait
- clause to the work-sharing list. */
+/* Divide CLAUSES into two lists: those that apply to a parallel
+ construct, and those that apply to a work-sharing construct. Place
+ the results in *PAR_CLAUSES and *WS_CLAUSES respectively. In
+ addition, add a nowait clause to the work-sharing list. LOC is the
+ location of the OMP_PARALLEL*. */
void
-c_split_parallel_clauses (tree clauses, tree *par_clauses, tree *ws_clauses)
+c_split_parallel_clauses (location_t loc, tree clauses,
+ tree *par_clauses, tree *ws_clauses)
{
tree next;
*par_clauses = NULL;
- *ws_clauses = build_omp_clause (OMP_CLAUSE_NOWAIT);
+ *ws_clauses = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
for (; clauses ; clauses = next)
{