OSDN Git Service

* config/rs6000/aix.h (LIBSTDCXX_STATIC): Remove -lstdc++.
[pf3gnuchains/gcc-fork.git] / gcc / c-omp.c
index b06c830..5ec9f94 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, 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>.
 
@@ -35,72 +35,81 @@ along with GCC; see the file COPYING3.  If not see
 
 
 /* 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;
 
@@ -116,7 +125,7 @@ c_finish_omp_atomic (enum tree_code code, tree lhs, tree rhs)
       && !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;
     }
 
@@ -124,7 +133,7 @@ c_finish_omp_atomic (enum tree_code code, tree lhs, tree rhs)
 
   /* 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);
@@ -137,32 +146,37 @@ c_finish_omp_atomic (enum tree_code code, tree lhs, tree rhs)
       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);
 }
 
@@ -260,7 +274,12 @@ c_finish_omp_for (location_t locus, tree declv, tree initv, tree condv,
              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);
@@ -280,7 +299,8 @@ c_finish_omp_for (location_t locus, tree declv, tree initv, tree condv,
          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);
@@ -324,6 +344,22 @@ c_finish_omp_for (location_t locus, tree declv, tree initv, tree condv,
                  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)
@@ -357,7 +393,8 @@ c_finish_omp_for (location_t locus, tree declv, tree initv, tree condv,
                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));
 
@@ -429,18 +466,20 @@ c_finish_omp_for (location_t locus, tree declv, tree initv, tree condv,
 }
 
 
-/* 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)
     {