OSDN Git Service

PR middle-end/35136
[pf3gnuchains/gcc-fork.git] / gcc / c-omp.c
index ac107e6..f170fbe 100644 (file)
@@ -1,7 +1,7 @@
 /* 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>.
 
@@ -9,7 +9,7 @@ This file is part of GCC.
 
 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
@@ -18,9 +18,8 @@ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 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"
@@ -76,21 +75,24 @@ c_finish_omp_barrier (void)
   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.
@@ -102,7 +104,7 @@ c_finish_omp_atomic (enum tree_code code, tree lhs, tree rhs)
       && !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.  */
@@ -111,8 +113,17 @@ c_finish_omp_atomic (enum tree_code code, tree lhs, tree rhs)
      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
@@ -120,12 +131,12 @@ c_finish_omp_atomic (enum tree_code code, tree lhs, tree rhs)
      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);
 }
 
 
@@ -138,7 +149,7 @@ c_finish_omp_flush (void)
   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);
 }
 
@@ -161,6 +172,7 @@ check_omp_for_incr_expr (tree exp, tree decl)
   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);