/* This file contains routines to construct GNU OpenMP constructs,
called from parsing in the C and C++ front ends.
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2007 Free Software Foundation, Inc.
Contributed by Richard Henderson <rth@redhat.com>,
Diego Novillo <dnovillo@redhat.com>.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
tree x;
x = built_in_decls[BUILT_IN_GOMP_BARRIER];
- x = build_function_call_expr (x, NULL);
+ x = build_call_expr (x, 0);
add_stmt (x);
}
/* Complete a #pragma omp atomic construct. The expression to be
- implemented atomically is LHS code= RHS. */
+ 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. */
-void
+tree
c_finish_omp_atomic (enum tree_code code, tree lhs, tree rhs)
{
tree x, type, addr;
if (lhs == error_mark_node || rhs == error_mark_node)
- return;
+ return error_mark_node;
/* ??? According to one reading of the OpenMP spec, complex type are
supported, but there are no atomic stores for any architecture.
&& !SCALAR_FLOAT_TYPE_P (type))
{
error ("invalid expression type for %<#pragma omp atomic%>");
- return;
+ return error_mark_node;
}
/* ??? Validate that rhs does not overlap lhs. */
via indirection. */
addr = build_unary_op (ADDR_EXPR, lhs, 0);
if (addr == error_mark_node)
- return;
+ return error_mark_node;
addr = save_expr (addr);
+ if (TREE_CODE (addr) != SAVE_EXPR
+ && (TREE_CODE (addr) != ADDR_EXPR
+ || TREE_CODE (TREE_OPERAND (addr, 0)) != VAR_DECL))
+ {
+ /* Make sure LHS is simple enough so that goa_lhs_expr_p can recognize
+ it even after unsharing function body. */
+ 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 (addr, NULL);
/* There are lots of warnings, errors, and conversions that need to happen
to do this, and then take it apart again. */
x = build_modify_expr (lhs, code, rhs);
if (x == error_mark_node)
- return;
+ 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. */
- add_stmt (build2 (OMP_ATOMIC, void_type_node, addr, rhs));
+ return build2 (OMP_ATOMIC, void_type_node, addr, rhs);
}
tree x;
x = built_in_decls[BUILT_IN_SYNCHRONIZE];
- x = build_function_call_expr (x, NULL);
+ x = build_call_expr (x, 0);
add_stmt (x);
}
switch (TREE_CODE (exp))
{
case NOP_EXPR:
+ case CONVERT_EXPR:
t = check_omp_for_incr_expr (TREE_OPERAND (exp, 0), decl);
if (t != error_mark_node)
return fold_convert (TREE_TYPE (exp), t);