]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Implemented Cilk Plus Array Notation for C++
authorBalaji V. Iyer <balaji.v.iyer@intel.com>
Fri, 21 Jun 2013 19:36:47 +0000 (19:36 +0000)
committerBalaji V. Iyer <bviyer@gcc.gnu.org>
Fri, 21 Jun 2013 19:36:47 +0000 (12:36 -0700)
Implemented Cilk Plus Array Notation for C++
gcc/c-family/ChangeLog
2013-06-21  Balaji V. Iyer  <balaji.v.iyer@intel.com>

        * c-common.h (struct cilkplus_an_parts): New structure.
        (struct cilkplus_an_loop_parts): Likewise.
        (cilkplus_extract_an_triplets): New prototype.
        (fix_sec_implicit_args): Likewise.
        * array-notation-common.c (cilkplus_extract_an_triplets): New function.
        (fix_sec_implicit_args): Likewise.

gcc/cp/ChangeLog
2013-06-21  Balaji V. Iyer  <balaji.v.iyer@intel.com>

        * call.c (convert_like_real): Added a check if array notation is present
        in expression.  If so, then no conversion of arguments is necessary.
        (build_over_call): Likewise.
        * typeck.c (cp_build_function_call_vec): Likewise.
        (convert_for_assignment): Likewise.
        (cp_build_array_ref): Reject array notations with a rank greater than 1
        as an array's index.
        (cp_build_binary_op): If array notations are preent in op, then call
        find_correct_array_notation_type.
        (cp_build_addr_expr_1): Handle ARRAY_NOTATION_REF similar to ARRAY_REF.
        * cp-array-notation.c: New file.
        * cp-objcp-common.c (cp_common_init_ts): Marked ARRAY_NOTATION_REF tree
        as typed.
        * cp-tree.h (fix_array_notation_exprs): New prototype.
        * semantics.c (finish_return_stmt): Reject array notations as
        return value.
        (cxx_eval_constant_expression): Added ARRAY_NOTATION_REF case.
        (potential_constant_expression_1): Likewise.
        * tree.c (lvalue_kind): Likewise.
        * error.c (dump_decl): Likewise.
        (dump_expr): Likewise.
        * pt.c (ARRAY_NOTATION_REF): Likewise.
        (type_unification_real): Do not unify any arguments if array notations
        are found in arg.
        (instantiate_decl): Added a check for array notaitons inside the
        function body.  If so, then expand them.
        * parser.c (cp_parser_array_notation): New function.
        (cp_parser_postfix_open_square_expression): Added a check for colons
        inside square braces.  If found, then handle the array access as an
        array notation access.  Also, disable auto-correction from a single
        colon to scope when Cilk Plus is enabled.
        (cp_parser_compound_statement): Added a check for array notations
        inside the statement.  If found, then expand them.
        (cp_parser_ctor_initializer_opt_and_function_body): Likewise.
        (cp_parser_function_definition_after_declarator): Likewise.
        (cp_parser_selection_statement): Searched for array notations inside
        condition.  If so, then emit an error.
        (cp_parser_iteration_statement): Likewise.
        (cp_parser_direct_declarator): Reject array notations inside a
        variable or array declaration.
        * Make-lang.in (CXX_AND_OBJCXX_OBJS): Added cp/cp-array-notation.o.

gcc/testsuite/ChangeLog
2013-06-21  Balaji V. Iyer  <balaji.v.iyer@intel.com>

        * c-c++-common/cilk-plus/AN/array_test1.c: Make this an execution test.
        Also changed the returns from error as distinct values so that debugging
        can get easier.
        * c-c++-common/cilk-plus/AN/if_test_errors.c (main): Made certain
        errors specific to C, if necessary.  Also added new error hooks for C++.
        * c-c++-common/cilk-plus/AN/misc.c (main): Likewise.
        * c-c++-common/cilk-plus/AN/parser_errors.c (main): Likewise.
        * c-c++-common/cilk-plus/AN/parser_errors2.c (main): Likewise.
        * c-c++-common/cilk-plus/AN/parser_errors3.c (main): Likewise.
        * c-c++-common/cilk-plus/AN/pr57541.c (main): Likewise.
        * c-c++-common/cilk-plus/AN/parser_errors4.c (main): In addition to the
        same changes as parser_errors3.c, spaces were added between colons to
        not confuse C++ compiler with 2 colons as scope.
        * c-c++-common/cilk-plus/AN/vla.c: Make this test C specific.
        * g++.dg/cilk-plus/AN/array_test1_tplt.cc: New test.
        * g++.dg/cilk-plus/AN/array_test2_tplt.cc: Likewise.
        * g++.dg/cilk-plus/AN/array_test_ND_tplt.cc: Likewise.
        * g++.dg/cilk-plus/AN/braced_list.cc: Likewise.
        * g++.dg/cilk-plus/AN/builtin_fn_custom_tplt.cc: Likewise.
        * g++.dg/cilk-plus/AN/builtin_fn_mutating_tplt.cc: Likewise.
        * g++.dg/cilk-plus/AN/fp_triplet_values_tplt.c: Likewise.
        * g++.dg/cilk-plus/AN/preincr_test.cc: Likewise.
        * g++.dg/cilk-plus/AN/postincr_test.cc: Likewise.
        * g++.dg/cilk-plus/cilk-plus.exp: New script.
        * gcc/testsuite/g++.dg/dg.exp: Included Cilk Plus C++ tests in the list.

From-SVN: r200319

35 files changed:
gcc/c-family/ChangeLog
gcc/c-family/array-notation-common.c
gcc/c-family/c-common.h
gcc/cp/ChangeLog
gcc/cp/Make-lang.in
gcc/cp/call.c
gcc/cp/cp-array-notation.c [new file with mode: 0644]
gcc/cp/cp-objcp-common.c
gcc/cp/cp-tree.h
gcc/cp/error.c
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c
gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c
gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c
gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c
gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c
gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c
gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c
gcc/testsuite/g++.dg/cilk-plus/AN/array_test1_tplt.cc [new file with mode: 0644]
gcc/testsuite/g++.dg/cilk-plus/AN/array_test2_tplt.cc [new file with mode: 0644]
gcc/testsuite/g++.dg/cilk-plus/AN/array_test_ND_tplt.cc [new file with mode: 0644]
gcc/testsuite/g++.dg/cilk-plus/AN/braced_list.cc [new file with mode: 0644]
gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_custom_tplt.cc [new file with mode: 0644]
gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_mutating_tplt.cc [new file with mode: 0644]
gcc/testsuite/g++.dg/cilk-plus/AN/fp_triplet_values_tplt.c [new file with mode: 0644]
gcc/testsuite/g++.dg/cilk-plus/AN/postincr_test.cc [new file with mode: 0644]
gcc/testsuite/g++.dg/cilk-plus/AN/preincr_test.cc [new file with mode: 0644]
gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp [new file with mode: 0644]
gcc/testsuite/g++.dg/dg.exp

index a0f195b7a49d3c8e5c84fb59473dcaba5089f454..224e27be67959c763115b442bb84a13826ba62dc 100644 (file)
@@ -1,3 +1,12 @@
+2013-06-21  Balaji V. Iyer  <balaji.v.iyer@intel.com>
+
+       * c-common.h (struct cilkplus_an_parts): New structure.
+       (struct cilkplus_an_loop_parts): Likewise.
+       (cilkplus_extract_an_triplets): New prototype.
+       (fix_sec_implicit_args): Likewise.
+       * array-notation-common.c (cilkplus_extract_an_triplets): New function.
+       (fix_sec_implicit_args): Likewise.
+       
 2013-06-20  Balaji V. Iyer  <balaji.v.iyer@intel.com>
 
        * array-notation-common.c (find_inv_trees): Removed an unwanted
index c82d7dc8b8095423e9f63a94c161b5b7e47febc3..0e2a43132f5c95c10de2a8ed2754eb68c0929acc 100644 (file)
@@ -560,3 +560,100 @@ find_correct_array_notation_type (tree op)
     } 
   return return_type;
 }
+
+/* Extracts all the array notation triplet information from LIST and stores
+   them in the following fields of the 2-D array NODE(size x rank):
+   START, LENGTH and STRIDE, holding the starting index, length, and stride,
+   respectively.  In addition, it also sets two bool fields, IS_VECTOR and
+   COUNT_DOWN, in NODE indicating whether a certain value at a certain field
+   is a vector and if the array is accessed from high to low.  */
+
+void
+cilkplus_extract_an_triplets (vec<tree, va_gc> *list, size_t size, size_t rank,
+                             vec<vec<struct cilkplus_an_parts> > *node)
+{
+  vec<vec<tree> > array_exprs = vNULL;
+  struct cilkplus_an_parts init = { NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE,
+                                   false };
+  node->safe_grow_cleared (size);
+  array_exprs.safe_grow_cleared (size);
+  for (size_t ii = 0; ii < size; ii++)
+    for (size_t jj = 0; jj < rank; jj++)
+      {
+       (*node)[ii].safe_push (init);
+       array_exprs[ii].safe_push (NULL_TREE);
+      }
+
+  for (size_t ii = 0; ii < size; ii++)
+    {
+      size_t jj = 0;
+      tree ii_tree = (*list)[ii];
+      while (ii_tree)
+       if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
+         {
+           array_exprs[ii][jj] = ii_tree;
+           jj++;
+           ii_tree = ARRAY_NOTATION_ARRAY (ii_tree);
+         }
+       else if (TREE_CODE (ii_tree) == ARRAY_REF)
+         ii_tree = TREE_OPERAND (ii_tree, 0);
+       else if (TREE_CODE (ii_tree) == VAR_DECL
+                || TREE_CODE (ii_tree) == CALL_EXPR
+                || TREE_CODE (ii_tree) == PARM_DECL)
+         break;
+       else
+         gcc_unreachable ();   
+    }
+    for (size_t ii = 0; ii < size; ii++)
+      if (TREE_CODE ((*list)[ii]) == ARRAY_NOTATION_REF)
+       for (size_t jj = 0; jj < rank; jj++)
+         if (TREE_CODE (array_exprs[ii][jj]) == ARRAY_NOTATION_REF)
+           {
+             tree ii_tree = array_exprs[ii][jj];
+             (*node)[ii][jj].is_vector = true;
+             (*node)[ii][jj].value = ARRAY_NOTATION_ARRAY (ii_tree);
+             (*node)[ii][jj].start = ARRAY_NOTATION_START (ii_tree);
+             (*node)[ii][jj].length =
+               fold_build1 (CONVERT_EXPR, integer_type_node,
+                            ARRAY_NOTATION_LENGTH (ii_tree));
+             (*node)[ii][jj].stride =
+               fold_build1 (CONVERT_EXPR, integer_type_node,
+                            ARRAY_NOTATION_STRIDE (ii_tree));
+           }
+}
+
+/* Replaces all the __sec_implicit_arg functions in LIST with the induction
+   variable stored in VAR at the appropriate location pointed by the
+   __sec_implicit_arg's first parameter.  Emits an error if the parameter is
+   not between 0 and RANK.  */
+
+vec <tree, va_gc> *
+fix_sec_implicit_args (location_t loc, vec <tree, va_gc> *list,
+                      vec<an_loop_parts> an_loop_info, size_t rank,
+                      tree orig_stmt)
+{
+  vec <tree, va_gc> *array_operand = NULL;
+  for (size_t ii = 0; ii < vec_safe_length (list); ii++)
+    if (TREE_CODE ((*list)[ii]) == CALL_EXPR
+       && TREE_CODE (CALL_EXPR_FN ((*list)[ii])) == ADDR_EXPR
+       && is_sec_implicit_index_fn (CALL_EXPR_FN ((*list)[ii])))
+      {
+       int idx = extract_sec_implicit_index_arg (loc, (*list)[ii]);
+       if (idx < (int) rank && idx >= 0)
+         vec_safe_push (array_operand, an_loop_info[idx].var);
+       else if (idx == -1)
+         /* In this case, the returning function would have emitted an
+            error thus it is not necessary to do so again.  */
+         return NULL;
+       else
+         {
+           error_at (loc, "__sec_implicit_index argument %d must be "
+                     "less than the rank of %qE", idx, orig_stmt);
+           return NULL;
+         }
+      }
+    else
+      /* Save the existing value into the array operand.  */
+      vec_safe_push (array_operand, (*list)[ii]);
+  return array_operand;
+}
index 82625d7f0e414424d0974d39c20ea76219bd8df8..95d3ccfd8456135a49354d08c1dc4931d4d0a941 100644 (file)
@@ -1160,6 +1160,29 @@ struct inv_list
   vec<enum tree_code, va_gc> *additional_tcodes; 
 };
 
+/* This structure holds all the important components that can be extracted
+   from an ARRAY_NOTATION_REF expression.  It is used to pass array notation
+   information between the functions that are responsible for expansion.  */
+typedef struct cilkplus_an_parts
+{
+  tree value;
+  tree start;
+  tree length;
+  tree stride;
+  bool is_vector;
+} an_parts;
+
+/* This structure holds the components necessary to create the loop around
+   the ARRAY_REF that is created using the ARRAY_NOTATION information.  */
+
+typedef struct cilkplus_an_loop_parts
+{
+  tree var;         /* Loop induction variable.  */
+  tree incr;        /* Loop increment/decrement expression.  */
+  tree cmp;         /* Loop condition.  */
+  tree ind_init;    /* Initialization of the loop induction variable.  */
+} an_loop_parts; 
+
 /* In array-notation-common.c.  */
 extern HOST_WIDE_INT extract_sec_implicit_index_arg (location_t, tree);
 extern bool is_sec_implicit_index_fn (tree);
@@ -1179,4 +1202,8 @@ extern void replace_array_notations (tree *, bool, vec<tree, va_gc> *,
 extern tree find_inv_trees (tree *, int *, void *);
 extern tree replace_inv_trees (tree *, int *, void *);
 extern tree find_correct_array_notation_type (tree op);
+extern void cilkplus_extract_an_triplets (vec<tree, va_gc> *, size_t, size_t,
+                                         vec<vec<an_parts> > *);
+extern vec <tree, va_gc> *fix_sec_implicit_args
+  (location_t, vec <tree, va_gc> *, vec<an_loop_parts>, size_t, tree);
 #endif /* ! GCC_C_COMMON_H */
index 7f1168e11ef379f7340592a31f9355570dd8efb3..b4f36b017eb2dc96e629558c594a977942391ae6 100644 (file)
@@ -1,3 +1,47 @@
+2013-06-21  Balaji V. Iyer  <balaji.v.iyer@intel.com>
+
+       * call.c (convert_like_real): Added a check if array notation is present
+       in expression.  If so, then no conversion of arguments is necessary.
+       (build_over_call): Likewise.
+       * typeck.c (cp_build_function_call_vec): Likewise.
+       (convert_for_assignment): Likewise.
+       (cp_build_array_ref): Reject array notations with a rank greater than 1
+       as an array's index.
+       (cp_build_binary_op): If array notations are preent in op, then call
+       find_correct_array_notation_type.
+       (cp_build_addr_expr_1): Handle ARRAY_NOTATION_REF similar to ARRAY_REF.
+       * cp-array-notation.c: New file.
+       * cp-objcp-common.c (cp_common_init_ts): Marked ARRAY_NOTATION_REF tree
+       as typed.
+       * cp-tree.h (fix_array_notation_exprs): New prototype.
+       * semantics.c (finish_return_stmt): Reject array notations as
+       return value.
+       (cxx_eval_constant_expression): Added ARRAY_NOTATION_REF case.
+       (potential_constant_expression_1): Likewise.
+       * tree.c (lvalue_kind): Likewise.
+       * error.c (dump_decl): Likewise.
+       (dump_expr): Likewise.
+       * pt.c (ARRAY_NOTATION_REF): Likewise.
+       (type_unification_real): Do not unify any arguments if array notations
+       are found in arg.
+       (instantiate_decl): Added a check for array notaitons inside the
+       function body.  If so, then expand them.
+       * parser.c (cp_parser_array_notation): New function.
+       (cp_parser_postfix_open_square_expression): Added a check for colons
+       inside square braces.  If found, then handle the array access as an
+       array notation access.  Also, disable auto-correction from a single
+       colon to scope when Cilk Plus is enabled.
+       (cp_parser_compound_statement): Added a check for array notations
+       inside the statement.  If found, then expand them.
+       (cp_parser_ctor_initializer_opt_and_function_body): Likewise.
+       (cp_parser_function_definition_after_declarator): Likewise.
+       (cp_parser_selection_statement): Searched for array notations inside
+       condition.  If so, then emit an error.
+       (cp_parser_iteration_statement): Likewise.
+       (cp_parser_direct_declarator): Reject array notations inside a
+       variable or array declaration.
+       * Make-lang.in (CXX_AND_OBJCXX_OBJS): Added cp/cp-array-notation.o.
+
 2013-06-20  Jason Merrill  <jason@redhat.com>
 
        PR c++/55149
index df8ed3ee0d9de7ff94b18b21c753d342d739a859..6e80bcf8c101cc8463713e670948239ffe7d8e1f 100644 (file)
@@ -80,7 +80,7 @@ CXX_AND_OBJCXX_OBJS = cp/call.o cp/decl.o cp/expr.o cp/pt.o cp/typeck2.o \
  cp/typeck.o cp/cvt.o cp/except.o cp/friend.o cp/init.o cp/method.o \
  cp/search.o cp/semantics.o cp/tree.o cp/repo.o cp/dump.o cp/optimize.o \
  cp/mangle.o cp/cp-objcp-common.o cp/name-lookup.o cp/cxx-pretty-print.o \
- cp/cp-gimplify.o $(CXX_C_OBJS)
+ cp/cp-gimplify.o cp/cp-array-notation.o $(CXX_C_OBJS)
 
 # Language-specific object files for C++.
 CXX_OBJS = cp/cp-lang.o c-family/stub-objc.o $(CXX_AND_OBJCXX_OBJS)
@@ -266,6 +266,9 @@ CXX_PRETTY_PRINT_H = cp/cxx-pretty-print.h $(C_PRETTY_PRINT_H)
 cp/lex.o: cp/lex.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) \
   $(C_PRAGMA_H) input.h cp/operators.def $(TM_P_H) \
   c-family/c-objc.h
+cp/cp-array-notation.o: cp/cp-array-notation.c $(CONFIG_H) $(SYSTEM_H) \
+  coretypes.h $(TREE_H) $(CXX_TREE_H) $(DIAGNOSTIC_H) tree-iterator.h vec.h \
+  $(GIMPLE_H) c-family/array-notation-common.o $(C_COMMON_H) 
 cp/cp-lang.o: cp/cp-lang.c $(CXX_TREE_H) $(TM_H) debug.h langhooks.h \
   $(LANGHOOKS_DEF_H) $(C_COMMON_H) gtype-cp.h gt-cp-cp-lang.h \
   cp/cp-objcp-common.h $(EXPR_H) $(TARGET_H) $(CXX_PARSER_H)
index dfd061aff5c9fd61e219019e38857b13c8479b55..0c729e86626107de847b1fb3fd1b8ce96ce98632 100644 (file)
@@ -5858,9 +5858,15 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
            break;
        }
 
-      if (permerror (loc, "invalid conversion from %qT to %qT",
-                    TREE_TYPE (expr), totype)
-         && fn)
+      if (flag_enable_cilkplus
+         && (contains_array_notation_expr (expr)
+             || contains_array_notation_expr (fn)))
+       /* If we are using array notations, we fix them up at a later stage
+          and we will do these checks then.  */
+       ;
+      else if (permerror (loc, "invalid conversion from %qT to %qT",
+                         TREE_TYPE (expr), totype)
+              && fn)
        inform (DECL_SOURCE_LOCATION (fn),
                "initializing argument %P of %qD", argnum, fn);
 
@@ -6890,12 +6896,20 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
            }
        }
 
-      val = convert_like_with_context (conv, arg, fn, i-is_method,
-                                      conversion_warning
-                                      ? complain
-                                      : complain & (~tf_warning));
+      /* If the function call is builtin array notation function then no need
+        to do any type conversion.  */
+      if (flag_enable_cilkplus
+         && is_cilkplus_reduce_builtin (fn) != BUILT_IN_NONE)
+       val = arg;
+      else
+       {
+         val = convert_like_with_context (conv, arg, fn, i - is_method,
+                                          conversion_warning
+                                          ? complain
+                                          : complain & (~tf_warning));
 
-      val = convert_for_arg_passing (type, val, complain);
+         val = convert_for_arg_passing (type, val, complain);
+       }
       if (val == error_mark_node)
         return error_mark_node;
       else
diff --git a/gcc/cp/cp-array-notation.c b/gcc/cp/cp-array-notation.c
new file mode 100644 (file)
index 0000000..92272b3
--- /dev/null
@@ -0,0 +1,1547 @@
+/* This file is part of the Intel(R) Cilk(TM) Plus support
+   It contains routines to handle Array Notation expression
+   handling routines in the C++ Compiler.
+   Copyright (C) 2013  Free Software Foundation, Inc.
+   Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com>,
+                  Intel Corporation
+
+   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 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or 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 COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+/* The Array Notation Transformation Technique:
+
+   An array notation expression has 4 major components:
+   1. The array name
+   2. Start Index
+   3. Number of elements we need to acess (we call it length)
+   4. Stride
+
+   So, if we have something like A[0:5:2], we are accessing A[0], A[2], A[4],
+   A[6] and A[8]. The user is responsible to make sure the access length does
+   not step outside the array's size.
+   
+   In this section, I highlight the overall method on how array notations are
+   broken up into C/C++ code.  Almost all the functions follows this step:
+
+   Let's say the user has used the array notation in a statement like this:
+
+   A[St1:Ln:Str1] = B[St2:Ln:Str2] + <NON ARRAY_NOT STMT>
+
+   where St{1,2} = Starting index, Ln = Number of elements we need to access,
+   and Str{1,2} = the stride.
+   Note: The length of both the array notation expressions must be the same.
+   
+   The above expression is broken into the following:
+
+   for (Tmp_Var = 0; Tmp_Var < Ln; Tmp_Var++)
+     A[St1 + Tmp_Var * Str1] = B[St1 + Tmp_Var * Str2] + <NON_ARRAY_NOT_STMT>;
+*/
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "cp-tree.h"
+#include "c-family/c-common.h"
+#include "diagnostic.h"
+#include "tree-iterator.h"
+#include "vec.h"
+#include "gimple.h"
+
+/* Creates a FOR_STMT with INIT, COND, INCR and BODY as the initializer,
+   condition, increment expression and the loop-body, respectively.  */
+
+static void
+create_an_loop (tree init, tree cond, tree incr, tree body)
+{
+  tree for_stmt;
+
+  finish_expr_stmt (init);
+  for_stmt = begin_for_stmt (NULL_TREE, NULL_TREE);
+  finish_for_init_stmt (for_stmt);
+  finish_for_cond (cond, for_stmt);
+  finish_for_expr (incr, for_stmt);
+  finish_expr_stmt (body);
+  finish_for_stmt (for_stmt);
+}
+
+/* Returns true if there is a length mismatch among exprssions that are at the
+   same dimension and one the same side of the equal sign.  The Array notation
+   lengths (LIST->LENGTH) is passed in as a 2D vector of trees.  */
+
+static bool
+cp_length_mismatch_in_expr_p (location_t loc, vec<vec<an_parts> >list)
+{
+  size_t ii, jj;
+  tree length = NULL_TREE;
+  HOST_WIDE_INT l_length, l_node;
+  
+  size_t x = list.length ();
+  size_t y = list[0].length ();
+  
+  for (jj = 0; jj < y; jj++)
+    {
+      length = NULL_TREE;
+      for (ii = 0; ii < x; ii++)
+       {
+         if (!length)
+           length = list[ii][jj].length;
+         else if (TREE_CODE (length) == INTEGER_CST)
+           {
+             /* If length is a INTEGER, and list[ii][jj] is an integer then
+                check if they are equal.  If they are not equal then return
+                true.  */
+             if (TREE_CODE (list[ii][jj].length) == INTEGER_CST)
+               {
+                 l_node = int_cst_value (list[ii][jj].length);
+                 l_length = int_cst_value (length);
+                 if (absu_hwi (l_length) != absu_hwi (l_node))
+                   {
+                     error_at (loc, "length mismatch in expression");
+                     return true;
+                   }
+               }
+           }
+         else
+           /* We set the length node as the current node just in case it turns
+              out to be an integer.  */
+           length = list[ii][jj].length;
+       }
+    }
+  return false;
+}
+
+/* If *VALUE is not a constant integer, then this function replaces it with
+   a variable to make it loop invariant for array notations.  */
+
+static inline void
+make_triplet_val_inv (location_t loc, tree *value, tsubst_flags_t cry)
+{
+  tree var;
+  if (TREE_CODE (*value) != INTEGER_CST
+      && TREE_CODE (*value) != PARM_DECL
+      && TREE_CODE (*value) != VAR_DECL)
+    {
+      var = build_decl (loc, VAR_DECL, NULL_TREE, integer_type_node);
+      finish_expr_stmt (build_x_modify_expr (loc, var, NOP_EXPR, *value, cry));
+      *value = var;
+    }
+}
+
+/* Returns a vector of size RANK that contains an ARRAY_REF.  This vector is
+   created using array notation-triplet information stored in AN_INFO. The
+   induction var is taken from AN_LOOP_INFO.
+
+   For example: For an array notation A[5:10:2], the vector start will be
+   of size 1 holding '5', stride of same size as start but holding the value of
+   as 2, and is_vector as true.   Let's assume VAR is 'x'
+   This function returns a vector of size 1 with the following data:
+   A[5 + (x * 2)] .
+*/
+
+static vec<tree, va_gc> *
+create_array_refs (location_t loc, vec<vec<an_parts> > an_info,
+                  vec<an_loop_parts> an_loop_info, size_t size,  size_t rank)
+{
+  tree ind_mult, ind_incr;
+  vec<tree, va_gc> *array_operand = NULL;
+  for (size_t ii = 0; ii < size; ii++)
+    if (an_info[ii][0].is_vector)
+      {
+       tree array_opr = an_info[ii][rank - 1].value;
+       for (int s_jj = rank -1; s_jj >= 0; s_jj--)
+         {
+           tree str = NULL_TREE, v = NULL_TREE, st = NULL_TREE;
+           tree start = an_info[ii][s_jj].start;
+           tree stride = an_info[ii][s_jj].stride;
+           tree var = an_loop_info[s_jj].var;
+
+           /* If stride and start are of same type and the induction var
+              is not, convert induction variable to stride's type.  */
+           if (TREE_TYPE (start) == TREE_TYPE (stride)
+               && TREE_TYPE (stride) != TREE_TYPE (var))
+             {
+               st = start;
+               str = stride;
+               v = build_c_cast (loc, TREE_TYPE (str), var);
+             }
+           else if (TREE_TYPE (start) != TREE_TYPE (stride))
+             {
+               /* If we reach here, then the stride and start are of
+                  different types, and so it doesn't really matter what
+                  the induction variable type is, convert everything to 
+                  integer.  The reason why we pick an integer
+                  instead of something like size_t is because the stride
+                  and length can be + or -.  */
+               st = build_c_cast (loc, integer_type_node, start);
+               str = build_c_cast (loc, integer_type_node, stride);
+               v = build_c_cast (loc, integer_type_node, var);
+             }
+           else
+             {
+               st = start;
+               str = stride;
+               v = var;
+             }
+
+           ind_mult = build2 (MULT_EXPR, TREE_TYPE (v), v, str);
+           ind_incr = build2 (PLUS_EXPR, TREE_TYPE (v), st, ind_mult);
+           /* Array [ start_index + (induction_var * stride)]  */
+           array_opr = grok_array_decl (loc, array_opr, ind_incr, false);
+         }
+       vec_safe_push (array_operand, array_opr);
+      }
+    else
+      vec_safe_push (array_operand, integer_one_node);
+  return array_operand;
+}
+
+/* Populates the INCR and CMP fields in *NODE with the increment
+   (of type POSTINCREMENT) and comparison (of TYPE LT_EXPR) expressions, using 
+   data from AN_INFO.  */
+
+void
+create_cmp_incr (location_t loc, vec <an_loop_parts> *node, size_t rank, 
+                vec<vec<an_parts> > an_info, tsubst_flags_t complain)
+{
+  for (size_t ii = 0; ii < rank; ii++)
+    {
+      (*node)[ii].incr = build_x_unary_op (loc, POSTINCREMENT_EXPR, 
+                                          (*node)[ii].var, complain);
+      (*node)[ii].cmp = build_x_binary_op (loc, LT_EXPR, (*node)[ii].var,
+                                          TREE_CODE ((*node)[ii].var),
+                                          an_info[0][ii].length,
+                                          TREE_CODE (an_info[0][ii].length),
+                                          NULL, complain);
+    }
+}
+
+/* Replaces all the scalar expressions in *NODE.  Returns a STATEMENT LIST that
+   holds the NODE along with the variables that hold the results of the
+   invariant expressions.  */
+
+static tree
+replace_invariant_exprs (tree *node)
+{
+  size_t ix = 0;
+  tree node_list = NULL_TREE;
+  tree t = NULL_TREE, new_var = NULL_TREE, new_node; 
+  struct inv_list data;
+
+  data.list_values = NULL;
+  data.replacement = NULL;
+  data.additional_tcodes = NULL;
+  cp_walk_tree (node, find_inv_trees, (void *) &data, NULL);
+
+  if (vec_safe_length (data.list_values))
+    {
+      node_list = push_stmt_list ();
+      for (ix = 0; vec_safe_iterate (data.list_values, ix, &t); ix++)
+       {
+         if (processing_template_decl || !TREE_TYPE (t))
+           new_var = build_min_nt_loc (EXPR_LOCATION (t), VAR_DECL, NULL_TREE,
+                                       NULL_TREE);
+         else
+           new_var = build_decl (EXPR_LOCATION (t), VAR_DECL, NULL_TREE,
+                                 TREE_TYPE (t));
+         gcc_assert (new_var != NULL_TREE && new_var != error_mark_node);
+         new_node = build_x_modify_expr (EXPR_LOCATION (t), new_var, NOP_EXPR,
+                                         t, tf_warning_or_error);
+         finish_expr_stmt (new_node);
+         vec_safe_push (data.replacement, new_var);
+       }
+      cp_walk_tree (node, replace_inv_trees, (void *) &data, NULL);
+      node_list = pop_stmt_list (node_list);
+    }
+  return node_list;
+}
+
+/* Replace array notation's built-in function passed in AN_BUILTIN_FN with
+   the appropriate loop and computation (all stored in variable LOOP of type
+   tree node).  The output of the function function is always a scalar and that
+   result is returned in *NEW_VAR.  *NEW_VAR is NULL_TREE if the function is
+   __sec_reduce_mutating.  */
+
+static tree
+expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
+{
+  tree new_var_type = NULL_TREE, func_parm, new_yes_expr, new_no_expr;
+  tree array_ind_value = NULL_TREE, new_no_ind, new_yes_ind, new_no_list;
+  tree new_yes_list, new_cond_expr, new_expr = NULL_TREE; 
+  tree new_var_init = NULL_TREE, new_exp_init = NULL_TREE;
+  vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
+  size_t list_size = 0, rank = 0, ii = 0;
+  tree  body, an_init, loop_with_init = alloc_stmt_list ();
+  tree array_op0, comp_node = NULL_TREE;
+  tree call_fn = NULL_TREE, identity_value = NULL_TREE;
+  tree init = NULL_TREE, cond_init = NULL_TREE;
+  enum tree_code code = NOP_EXPR;
+  location_t location = UNKNOWN_LOCATION;
+  vec<vec<an_parts> > an_info = vNULL;
+  vec<an_loop_parts> an_loop_info = vNULL; 
+  enum built_in_function an_type =
+    is_cilkplus_reduce_builtin (CALL_EXPR_FN (an_builtin_fn));
+  vec <tree, va_gc> *func_args;
+  
+  if (an_type == BUILT_IN_NONE)
+    return NULL_TREE;
+
+  if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE
+      && an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
+    func_parm = CALL_EXPR_ARG (an_builtin_fn, 0);
+  else
+    {
+      call_fn = CALL_EXPR_ARG (an_builtin_fn, 2);
+
+      /* We need to do this because we are "faking" the builtin function types,
+        so the compiler does a bunch of typecasts and this will get rid of
+        all that!  */
+      STRIP_NOPS (call_fn);
+      if (TREE_CODE (call_fn) != OVERLOAD
+         && TREE_CODE (call_fn) != FUNCTION_DECL)
+       call_fn = TREE_OPERAND (call_fn, 0);
+      identity_value = CALL_EXPR_ARG (an_builtin_fn, 0);
+      func_parm = CALL_EXPR_ARG (an_builtin_fn, 1);
+      STRIP_NOPS (identity_value);
+    }
+  STRIP_NOPS (func_parm);
+  
+  location = EXPR_LOCATION (an_builtin_fn);
+  
+  /* Note about using find_rank (): If find_rank returns false, then it must
+     have already reported an error, thus we just return an error_mark_node
+     without any doing any error emission.  */  
+  if (!find_rank (location, an_builtin_fn, an_builtin_fn, true, &rank))
+      return error_mark_node;
+  if (rank == 0)
+    return an_builtin_fn;
+  else if (rank > 1 
+          && (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
+              || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND))
+    { 
+      error_at (location, "__sec_reduce_min_ind or __sec_reduce_max_ind cannot "
+               "have arrays with dimension greater than 1");
+      return error_mark_node;
+    }
+  
+  extract_array_notation_exprs (func_parm, true, &array_list);
+  list_size = vec_safe_length (array_list);
+  switch (an_type)
+    {
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD:
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL:
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX:
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN:
+      new_var_type = TREE_TYPE ((*array_list)[0]);
+      break;
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO:
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO:
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO:
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO:
+      new_var_type = integer_type_node;
+      break;
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
+      new_var_type = size_type_node;
+      break;
+    case BUILT_IN_CILKPLUS_SEC_REDUCE:
+      if (call_fn && identity_value)
+       new_var_type = TREE_TYPE ((*array_list)[0]);
+      break;
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING:
+      new_var_type = NULL_TREE;
+      break;
+    default:
+      gcc_unreachable ();
+    }
+    
+  if (new_var_type && TREE_CODE (new_var_type) == ARRAY_TYPE)
+    new_var_type = TREE_TYPE (new_var_type);
+  an_loop_info.safe_grow_cleared (rank);
+
+  an_init = push_stmt_list ();
+
+  /* Assign the array notation components to variable so that they can satisfy
+     the exec-once rule.  */
+  for (ii = 0; ii < list_size; ii++)
+    if (TREE_CODE ((*array_list)[ii]) == ARRAY_NOTATION_REF)
+      {
+       tree anode = (*array_list)[ii];
+       make_triplet_val_inv (location, &ARRAY_NOTATION_START (anode),
+                             tf_warning_or_error);
+       make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (anode),
+                             tf_warning_or_error);
+       make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (anode),
+                             tf_warning_or_error);
+      }
+  cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info);
+  for (ii = 0; ii < rank; ii++)
+    {
+      an_loop_info[ii].var = build_decl (location, VAR_DECL, NULL_TREE,
+                                 TREE_TYPE (an_info[0][ii].start));
+      an_loop_info[ii].ind_init = build_x_modify_expr
+       (location, an_loop_info[ii].var, NOP_EXPR, 
+        build_zero_cst (TREE_TYPE (an_loop_info[ii].var)),
+        tf_warning_or_error);
+    }
+  
+  array_operand = create_array_refs (location, an_info, an_loop_info,
+                                     list_size, rank);
+  replace_array_notations (&func_parm, true, array_list, array_operand);
+  
+  if (!TREE_TYPE (func_parm))      
+    TREE_TYPE (func_parm) = TREE_TYPE ((*array_list)[0]);
+  
+  create_cmp_incr (location, &an_loop_info, rank, an_info, tf_warning_or_error);
+  if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
+    {
+      if (processing_template_decl)
+       *new_var = build_decl (location, VAR_DECL, NULL_TREE, new_var_type);
+      else
+       *new_var = create_tmp_var (new_var_type, NULL);
+    }
+  else
+    /* We do not require a new variable for mutating.  The "identity value"
+       itself is the variable.  */
+    *new_var = NULL_TREE;
+  
+  if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
+      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND)
+    {
+      array_ind_value = create_tmp_var (TREE_TYPE (func_parm), NULL);
+      gcc_assert (array_ind_value && (array_ind_value != error_mark_node));
+      DECL_INITIAL (array_ind_value) = NULL_TREE;
+      pushdecl (array_ind_value);
+    }
+
+  array_op0 = (*array_operand)[0];
+  switch (an_type)
+    {
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD:
+      code = PLUS_EXPR;
+      init = build_zero_cst (new_var_type);
+      break;
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL:
+      code = MULT_EXPR;
+      init = build_one_cst (new_var_type);
+      break;
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO:
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO:
+      code = (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO) ? EQ_EXPR
+       : NE_EXPR;
+      init = build_zero_cst (new_var_type);
+      cond_init = build_one_cst (new_var_type);
+      comp_node = build_zero_cst (TREE_TYPE (func_parm));
+      break;
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO:
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO:
+      code = (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO) ? NE_EXPR
+       : EQ_EXPR;
+      init = build_one_cst (new_var_type);
+      cond_init = build_zero_cst (new_var_type);
+      comp_node = build_zero_cst (TREE_TYPE (func_parm));
+      break;
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX:
+      code = MAX_EXPR;
+      init = TYPE_MIN_VALUE (new_var_type) ? TYPE_MIN_VALUE (new_var_type)
+       : func_parm;
+      break;
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN:
+      code = MIN_EXPR;
+      init = TYPE_MAX_VALUE (new_var_type) ? TYPE_MAX_VALUE (new_var_type)
+       : func_parm;
+      break;
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
+      code = an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND ? LE_EXPR
+       : GE_EXPR;
+      init = an_loop_info[0].var;
+    case BUILT_IN_CILKPLUS_SEC_REDUCE:
+      init = identity_value;
+      break;
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING:
+      init = NULL_TREE;
+      break;
+    default:
+      gcc_unreachable ();
+    }
+
+  if (init)
+    new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR, init,
+                                       tf_warning_or_error);
+  switch (an_type)
+    {
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD:
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL:      
+      new_expr = build_x_modify_expr (location, *new_var, code, func_parm,
+                                     tf_warning_or_error);
+      break;
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO:
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO:
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO:
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO:
+      /* In all these cases, assume the false case is true and as soon as
+        we find a true case,  set the true flag on and latch it in.  */
+      new_yes_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
+                                         cond_init, tf_warning_or_error);
+      new_no_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
+                                        *new_var, tf_warning_or_error);
+      new_cond_expr = build_x_binary_op
+       (location, code, func_parm, TREE_CODE (func_parm), comp_node,
+        TREE_CODE (comp_node), NULL, tf_warning_or_error);
+      new_expr = build_x_conditional_expr (location, new_cond_expr,
+                                          new_yes_expr, new_no_expr,
+                                          tf_warning_or_error);
+      break;
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX:
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN:
+      new_cond_expr = build_x_binary_op
+       (location, code, *new_var, TREE_CODE (*new_var), func_parm,
+        TREE_CODE (func_parm), NULL, tf_warning_or_error);
+      new_expr = build_x_modify_expr (location, *new_var, NOP_EXPR, func_parm,
+                                     tf_warning_or_error);
+      break;
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
+      new_exp_init = build_x_modify_expr (location, array_ind_value, NOP_EXPR,
+                                         func_parm, tf_warning_or_error);
+      new_yes_expr = build_x_modify_expr (location, array_ind_value, NOP_EXPR,
+                                         func_parm, tf_warning_or_error);
+      new_no_expr = build_x_modify_expr (location, array_ind_value, NOP_EXPR,
+                                        array_ind_value, tf_warning_or_error);
+      if (list_size > 1)
+       new_yes_ind = build_x_modify_expr (location, *new_var, NOP_EXPR,
+                                          an_loop_info[0].var,
+                                          tf_warning_or_error);
+      else
+       new_yes_ind = build_x_modify_expr (location, *new_var, NOP_EXPR,
+                                          TREE_OPERAND (array_op0, 1),
+                                          tf_warning_or_error);
+      new_no_ind = build_x_modify_expr (location, *new_var, NOP_EXPR, *new_var,
+                                       tf_warning_or_error);
+      new_yes_list = alloc_stmt_list ();
+      append_to_statement_list (new_yes_ind, &new_yes_list);
+      append_to_statement_list (new_yes_expr, &new_yes_list);
+
+      new_no_list = alloc_stmt_list ();
+      append_to_statement_list (new_no_ind, &new_no_list);
+      append_to_statement_list (new_no_expr, &new_no_list);
+
+      new_cond_expr = build_x_binary_op (location, code, array_ind_value,
+                                        TREE_CODE (array_ind_value), func_parm,
+                                        TREE_CODE (func_parm), NULL,
+                                        tf_warning_or_error);
+      new_expr = build_x_conditional_expr (location, new_cond_expr,
+                                          new_yes_list, new_no_list,
+                                          tf_warning_or_error);
+      break;
+    case BUILT_IN_CILKPLUS_SEC_REDUCE:
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING:
+      func_args = make_tree_vector ();
+      if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE)
+       vec_safe_push (func_args, *new_var);
+      else
+       vec_safe_push (func_args, identity_value);
+      vec_safe_push (func_args, func_parm);
+
+      new_expr = finish_call_expr (call_fn, &func_args, false, true,
+                                  tf_warning_or_error);
+      if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE)
+       new_expr = build_x_modify_expr (location, *new_var, NOP_EXPR, new_expr,
+                                       tf_warning_or_error);
+      release_tree_vector (func_args);
+      break;
+    default:
+      gcc_unreachable ();
+    }
+  
+  /* The reason we are putting initial variable twice is because the
+     new exp init below depends on this value being initialized.  */
+  for (ii = 0; ii < rank; ii++)
+    finish_expr_stmt (an_loop_info[ii].ind_init);
+  if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
+    finish_expr_stmt (new_var_init);
+
+  if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
+      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND)
+    finish_expr_stmt (new_exp_init);
+
+  an_init = pop_stmt_list (an_init);
+  append_to_statement_list_force (an_init, &loop_with_init);
+  body = new_expr;
+
+  for (ii = 0; ii < rank; ii++)
+    {
+      tree new_loop = push_stmt_list ();
+      create_an_loop (an_loop_info[ii].ind_init, an_loop_info[ii].cmp,
+                     an_loop_info[ii].incr, body);
+      body = pop_stmt_list (new_loop);
+    }
+  append_to_statement_list_force (body, &loop_with_init);
+
+  an_info.release ();
+  an_loop_info.release ();
+
+  return loop_with_init;
+}
+
+/* Returns a loop with ARRAY_REF inside it with an appropriate modify expr.
+   The LHS and/or RHS will be array notation expressions that have a
+   MODIFYCODE.  The location of the variable is specified by LOCATION. */
+
+static tree
+expand_an_in_modify_expr (location_t location, tree lhs,
+                         enum tree_code modifycode, tree rhs,
+                         tsubst_flags_t complain)
+{
+  tree array_expr_lhs = NULL_TREE, array_expr_rhs = NULL_TREE;
+  tree array_expr = NULL_TREE;
+  tree body = NULL_TREE;
+  vec<tree> cond_expr = vNULL;
+  vec<tree, va_gc> *lhs_array_operand = NULL, *rhs_array_operand = NULL;
+  size_t lhs_rank = 0, rhs_rank = 0, ii = 0;
+  vec<tree, va_gc> *rhs_list = NULL, *lhs_list = NULL;
+  size_t rhs_list_size = 0, lhs_list_size = 0;
+  tree new_modify_expr, new_var = NULL_TREE, builtin_loop, scalar_mods;
+  bool found_builtin_fn = false;
+  tree an_init, loop_with_init = alloc_stmt_list ();
+  vec<vec<an_parts> > lhs_an_info = vNULL, rhs_an_info = vNULL;
+  vec<an_loop_parts> lhs_an_loop_info = vNULL, rhs_an_loop_info = vNULL;
+
+  if (!find_rank (location, rhs, rhs, false, &rhs_rank))
+    return error_mark_node;
+  extract_array_notation_exprs (rhs, false, &rhs_list);
+  rhs_list_size = vec_safe_length (rhs_list);
+  an_init = push_stmt_list ();
+  if (rhs_rank)
+    {
+      scalar_mods = replace_invariant_exprs (&rhs);
+      if (scalar_mods)
+       finish_expr_stmt (scalar_mods);
+    }
+  for (ii = 0; ii < rhs_list_size; ii++)
+    {
+      tree rhs_node = (*rhs_list)[ii];
+      if (TREE_CODE (rhs_node) == CALL_EXPR)
+       {
+         builtin_loop = expand_sec_reduce_builtin (rhs_node, &new_var);
+         if (builtin_loop == error_mark_node)
+           return error_mark_node;
+         else if (builtin_loop)
+           {
+             finish_expr_stmt (builtin_loop);
+             found_builtin_fn = true;
+             if (new_var)
+               {
+                 vec <tree, va_gc> *rhs_sub_list = NULL, *new_var_list = NULL;
+                 vec_safe_push (rhs_sub_list, rhs_node);
+                 vec_safe_push (new_var_list, new_var);
+                 replace_array_notations (&rhs, false, rhs_sub_list,
+                                          new_var_list);
+               }
+           }
+       }
+    }
+  lhs_rank = 0;
+  rhs_rank = 0;
+  if (!find_rank (location, lhs, lhs, true, &lhs_rank)
+      || !find_rank (location, rhs, rhs, true, &rhs_rank))
+    {
+      pop_stmt_list (an_init);
+      return error_mark_node;
+    }
+
+  /* If both are scalar, then the only reason why we will get this far is if
+     there is some array notations inside it and was using a builtin array
+     notation functions.  If so, we have already broken those guys up and now 
+     a simple build_x_modify_expr would do.  */
+  if (lhs_rank == 0 && rhs_rank == 0)
+    {
+      if (found_builtin_fn)
+       {
+         new_modify_expr = build_x_modify_expr (location, lhs,
+                                                modifycode, rhs, complain);
+         finish_expr_stmt (new_modify_expr);
+         pop_stmt_list (an_init);
+         return an_init;
+       }
+      else
+       {
+         pop_stmt_list (an_init);
+         return NULL_TREE;
+       }
+    }
+
+  /* If for some reason location is not set, then find if LHS or RHS has
+     location info.  If so, then use that so we atleast have an idea.  */
+  if (location == UNKNOWN_LOCATION)
+    {
+      if (EXPR_LOCATION (lhs) != UNKNOWN_LOCATION)
+       location = EXPR_LOCATION (lhs);
+      else if (EXPR_LOCATION (rhs) != UNKNOWN_LOCATION)
+       location = EXPR_LOCATION (rhs);
+    }
+      
+  /* We need this when we have a scatter issue.  */
+  extract_array_notation_exprs (lhs, true, &lhs_list);
+  rhs_list = NULL;
+  extract_array_notation_exprs (rhs, true, &rhs_list);
+  rhs_list_size = vec_safe_length (rhs_list);
+  lhs_list_size = vec_safe_length (lhs_list);
+    
+  if (lhs_rank == 0 && rhs_rank != 0)
+    {
+      if (location == UNKNOWN_LOCATION && EXPR_HAS_LOCATION (rhs))
+       location = EXPR_LOCATION (rhs);
+      error_at (location, "%qD cannot be scalar when %qD is not", lhs, rhs);
+      return error_mark_node;
+    }
+  if (lhs_rank != 0 && rhs_rank != 0 && lhs_rank != rhs_rank)
+    {
+      error_at (location, "rank mismatch between %qE and %qE", lhs, rhs);
+      return error_mark_node;
+    }
+  
+  /* Assign the array notation components to variable so that they can satisfy
+     the execute-once rule.  */
+  for (ii = 0; ii < lhs_list_size; ii++)
+    {
+      tree anode = (*lhs_list)[ii];
+      make_triplet_val_inv (location, &ARRAY_NOTATION_START (anode), complain);
+      make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (anode), complain);
+      make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (anode), complain);
+    }
+  for (ii = 0; ii < rhs_list_size; ii++)
+    if ((*rhs_list)[ii] && TREE_CODE ((*rhs_list)[ii]) == ARRAY_NOTATION_REF)
+      {
+       tree aa = (*rhs_list)[ii];
+       make_triplet_val_inv (location, &ARRAY_NOTATION_START (aa), complain);
+       make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (aa), complain);
+       make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (aa), complain);
+      }
+  lhs_an_loop_info.safe_grow_cleared (lhs_rank);
+  
+  if (rhs_rank)
+    rhs_an_loop_info.safe_grow_cleared (rhs_rank);
+
+  cond_expr.safe_grow_cleared (MAX (lhs_rank, rhs_rank));
+  cilkplus_extract_an_triplets (lhs_list, lhs_list_size, lhs_rank,
+                               &lhs_an_info);
+  if (rhs_list)
+    cilkplus_extract_an_triplets (rhs_list, rhs_list_size, rhs_rank,
+                                 &rhs_an_info);
+  if (cp_length_mismatch_in_expr_p (EXPR_LOCATION (lhs), lhs_an_info)
+      || (rhs_list && cp_length_mismatch_in_expr_p (EXPR_LOCATION (rhs),
+                                                   rhs_an_info)))
+    {
+      pop_stmt_list (an_init);
+      return error_mark_node;
+    }
+  tree rhs_len = (rhs_list_size > 0 && rhs_rank > 0) ?
+    rhs_an_info[0][0].length : NULL_TREE;
+  tree lhs_len = (lhs_list_size > 0 && lhs_rank > 0) ?
+    lhs_an_info[0][0].length : NULL_TREE;
+  if (lhs_list_size > 0 && rhs_list_size > 0 && lhs_rank > 0 && rhs_rank > 0
+      && TREE_CODE (lhs_len) == INTEGER_CST && rhs_len
+      && TREE_CODE (rhs_len) == INTEGER_CST)
+    {
+      HOST_WIDE_INT l_length = int_cst_value (lhs_len);
+      HOST_WIDE_INT r_length = int_cst_value (rhs_len);
+      if (absu_hwi (l_length) != absu_hwi (r_length))
+       {
+         error_at (location, "length mismatch between LHS and RHS");
+         pop_stmt_list (an_init);
+         return error_mark_node;
+       }
+    }
+   for (ii = 0; ii < lhs_rank; ii++)
+    if (lhs_an_info[0][ii].start && TREE_TYPE (lhs_an_info[0][ii].start))
+      lhs_an_loop_info[ii].var =
+       build_decl (location, VAR_DECL, NULL_TREE,
+                   TREE_TYPE (lhs_an_info[0][ii].start));
+    else
+      lhs_an_loop_info[ii].var = build_decl (location, VAR_DECL, NULL_TREE,
+                                            integer_type_node);
+   if (rhs_list_size > 0)
+     {
+       rhs_array_operand = fix_sec_implicit_args (location, rhs_list,
+                                                 lhs_an_loop_info, lhs_rank,
+                                                 lhs); 
+       if (!rhs_array_operand)
+        return error_mark_node;
+     }
+  replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
+  rhs_list_size = 0;
+  rhs_list = NULL;
+  extract_array_notation_exprs (rhs, true, &rhs_list);
+  rhs_list_size = vec_safe_length (rhs_list);    
+  
+  for (ii = 0; ii < lhs_rank; ii++)
+    if (lhs_an_info[0][ii].is_vector)
+      {
+       lhs_an_loop_info[ii].ind_init = build_x_modify_expr
+         (location, lhs_an_loop_info[ii].var, NOP_EXPR,
+          build_zero_cst (TREE_TYPE (lhs_an_loop_info[ii].var)), complain);
+      }
+  for (ii = 0; ii < rhs_rank; ii++)
+    {
+      /* When we have a polynomial, we assume that the indices are of type
+        integer.  */
+      rhs_an_loop_info[ii].var =
+       build_decl (location, VAR_DECL, NULL_TREE,
+                   TREE_TYPE (rhs_an_info[0][ii].start));
+      rhs_an_loop_info[ii].ind_init = build_x_modify_expr
+       (location, rhs_an_loop_info[ii].var, NOP_EXPR, 
+        build_zero_cst (TREE_TYPE (rhs_an_loop_info[ii].var)), complain);
+    }
+
+  if (lhs_rank)
+    {
+      lhs_array_operand =
+       create_array_refs (location, lhs_an_info, lhs_an_loop_info,
+                           lhs_list_size, lhs_rank);
+      replace_array_notations (&lhs, true, lhs_list, lhs_array_operand);
+    }
+  
+  if (rhs_array_operand)
+    vec_safe_truncate (rhs_array_operand, 0);
+  if (rhs_rank)
+    {
+      rhs_array_operand = create_array_refs (location, rhs_an_info,
+                                             rhs_an_loop_info, rhs_list_size,
+                                             rhs_rank);
+      /* Replace all the array refs created by the above function because this
+        variable is blown away by the fix_sec_implicit_args function below.  */
+      replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
+      vec_safe_truncate (rhs_array_operand , 0);
+      rhs_array_operand = fix_sec_implicit_args (location, rhs_list,
+                                                rhs_an_loop_info, rhs_rank,
+                                                rhs);
+      if (!rhs_array_operand)
+       return error_mark_node;
+      replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
+    }
+
+  array_expr_rhs = rhs;
+  array_expr_lhs = lhs;
+  
+  array_expr = build_x_modify_expr (location, array_expr_lhs, modifycode,
+                                   array_expr_rhs, complain);
+  create_cmp_incr (location, &lhs_an_loop_info, lhs_rank, lhs_an_info,
+                  complain);
+  if (rhs_rank) 
+    create_cmp_incr (location, &rhs_an_loop_info, rhs_rank, rhs_an_info, 
+                    complain);
+  for (ii = 0; ii < MAX (rhs_rank, lhs_rank); ii++)
+    if (ii < lhs_rank && ii < rhs_rank)
+      cond_expr[ii] = build_x_binary_op
+       (location, TRUTH_ANDIF_EXPR, lhs_an_loop_info[ii].cmp,
+        TREE_CODE (lhs_an_loop_info[ii].cmp), rhs_an_loop_info[ii].cmp,
+        TREE_CODE (rhs_an_loop_info[ii].cmp), NULL, complain);
+    else if (ii < lhs_rank && ii >= rhs_rank)
+      cond_expr[ii] = lhs_an_loop_info[ii].cmp;
+    else
+      /* No need to compare ii < rhs_rank && ii >= lhs_rank because valid Array
+        notation expression cannot RHS's rank cannot be greater than LHS.  */
+      gcc_unreachable ();
+  
+  an_init = pop_stmt_list (an_init);
+  append_to_statement_list_force (an_init, &loop_with_init);
+  body = array_expr;
+  for (ii = 0; ii < MAX (lhs_rank, rhs_rank); ii++)
+    {
+      tree incr_list = alloc_stmt_list ();
+      tree init_list = alloc_stmt_list ();
+      tree new_loop = push_stmt_list ();
+
+      if (lhs_rank)
+       {
+         append_to_statement_list_force (lhs_an_loop_info[ii].ind_init,
+                                         &init_list);
+         append_to_statement_list_force (lhs_an_loop_info[ii].incr,
+                                         &incr_list);
+       }
+      if (rhs_rank)
+       {
+         append_to_statement_list_force (rhs_an_loop_info[ii].ind_init,
+                                         &init_list);
+         append_to_statement_list_force (rhs_an_loop_info[ii].incr,
+                                         &incr_list);
+       }
+      create_an_loop (init_list, cond_expr[ii], incr_list, body);
+      body = pop_stmt_list (new_loop);
+    }
+  append_to_statement_list (body, &loop_with_init);
+
+  lhs_an_info.release ();
+  lhs_an_loop_info.release ();
+  if (rhs_rank) 
+    { 
+      rhs_an_info.release (); 
+      rhs_an_loop_info.release ();
+    }
+  cond_expr.release ();
+
+  return loop_with_init;
+}
+
+/* Helper function for expand_conditonal_array_notations.  Encloses the
+   conditional statement passed in ORIG_STMT with a loop around it and
+   replaces the condition in STMT with a ARRAY_REF tree-node to the array.  
+   The condition must have a ARRAY_NOTATION_REF tree.  */
+
+static tree
+cp_expand_cond_array_notations (tree orig_stmt)
+{
+  vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
+  size_t list_size = 0;
+  size_t rank = 0, ii = 0;
+  tree an_init, body, stmt = NULL_TREE;
+  tree builtin_loop, new_var = NULL_TREE;
+  tree loop_with_init = alloc_stmt_list ();
+  tsubst_flags_t complain = tf_warning_or_error;
+  location_t location = UNKNOWN_LOCATION;
+  vec<vec<an_parts> > an_info = vNULL;
+  vec<an_loop_parts> an_loop_info = vNULL;
+
+  if (TREE_CODE (orig_stmt) == COND_EXPR)
+    {
+      size_t cond_rank = 0, yes_rank = 0, no_rank = 0;
+      tree yes_expr = COND_EXPR_THEN (orig_stmt);
+      tree no_expr = COND_EXPR_ELSE (orig_stmt);
+      tree cond = COND_EXPR_COND (orig_stmt);
+      if (!find_rank (EXPR_LOCATION (cond), cond, cond, true, &cond_rank)
+         || !find_rank (EXPR_LOCATION (yes_expr), yes_expr, yes_expr, true,
+                        &yes_rank)
+         || find_rank (EXPR_LOCATION (no_expr), no_expr, no_expr, true,
+                       &no_rank))
+       return error_mark_node;
+      if (cond_rank != 0 && cond_rank != yes_rank && yes_rank != 0)
+       {
+         error_at (EXPR_LOCATION (yes_expr), "rank mismatch with controlling"
+                   " expression of parent if-statement");
+         return error_mark_node;
+       }
+      else if (cond_rank != 0 && cond_rank != no_rank && no_rank != 0)
+       {
+         error_at (EXPR_LOCATION (no_expr), "rank mismatch with controlling "
+                   "expression of parent if-statement");
+         return error_mark_node;
+       }
+    }
+  else if (TREE_CODE (orig_stmt) == IF_STMT)
+    {
+      size_t cond_rank = 0, yes_rank = 0, no_rank = 0;
+      tree yes_expr = THEN_CLAUSE (orig_stmt);
+      tree no_expr = ELSE_CLAUSE (orig_stmt);
+      tree cond = IF_COND (orig_stmt);
+      if (!find_rank (EXPR_LOCATION (cond), cond, cond, true, &cond_rank)
+         || (yes_expr
+             && !find_rank (EXPR_LOCATION (yes_expr), yes_expr, yes_expr, true,
+                            &yes_rank))
+         || (no_expr
+             && !find_rank (EXPR_LOCATION (no_expr), no_expr, no_expr, true,
+                            &no_rank)))
+       return error_mark_node;
+      if (cond_rank != 0 && cond_rank != yes_rank && yes_rank != 0)
+       {
+         error_at (EXPR_LOCATION (yes_expr), "rank mismatch with controlling"
+                   " expression of parent if-statement");
+         return error_mark_node;
+       }
+      else if (cond_rank != 0 && cond_rank != no_rank && no_rank != 0)
+       {
+         error_at (EXPR_LOCATION (no_expr), "rank mismatch with controlling "
+                   "expression of parent if-statement");
+         return error_mark_node;
+       }
+    }
+
+  if (!find_rank (EXPR_LOCATION (orig_stmt), orig_stmt, orig_stmt, true,
+                 &rank))
+    return error_mark_node;
+  if (rank == 0)
+    return orig_stmt;
+
+  extract_array_notation_exprs (orig_stmt, false, &array_list);
+  stmt = alloc_stmt_list ();
+  for (ii = 0; ii < vec_safe_length (array_list); ii++)
+    {
+      tree array_node = (*array_list)[ii];
+      if (TREE_CODE (array_node) == CALL_EXPR
+         || TREE_CODE (array_node) == AGGR_INIT_EXPR)
+       {
+         builtin_loop = expand_sec_reduce_builtin (array_node, &new_var);
+         if (builtin_loop == error_mark_node)
+           finish_expr_stmt (error_mark_node);
+         else if (new_var)
+           {
+             vec<tree, va_gc> *sub_list = NULL, *new_var_list = NULL;
+             vec_safe_push (sub_list, array_node);
+             vec_safe_push (new_var_list, new_var);
+             replace_array_notations (&orig_stmt, false, sub_list,
+                                      new_var_list);
+             append_to_statement_list_force (builtin_loop, &stmt);
+           }
+       }
+    }
+  append_to_statement_list_force (orig_stmt, &stmt);
+  rank = 0;
+  array_list = NULL;
+  if (!find_rank (EXPR_LOCATION (stmt), stmt, stmt, true, &rank))
+    return error_mark_node;
+  if (rank == 0)
+    return stmt;
+  
+  extract_array_notation_exprs (stmt, true, &array_list);
+  list_size = vec_safe_length (array_list);
+  if (list_size == 0)
+    return stmt;
+
+  location = EXPR_LOCATION (orig_stmt);
+  list_size = vec_safe_length (array_list);
+  an_loop_info.safe_grow_cleared (rank);
+  
+  an_init = push_stmt_list ();
+
+  /* Assign the array notation components to variable so that they can
+     satisfy the exec-once rule.  */
+  for (ii = 0; ii < list_size; ii++)
+    {
+      tree anode = (*array_list)[ii];
+      make_triplet_val_inv (location, &ARRAY_NOTATION_START (anode), complain);
+      make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (anode), complain);
+      make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (anode), complain);
+    }
+  cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info);
+  for (ii = 0; ii < rank; ii++)
+      if (TREE_TYPE (an_info[0][ii].start)
+         && TREE_CODE (TREE_TYPE (an_info[0][ii].start)) != TEMPLATE_TYPE_PARM)
+       {
+         an_loop_info[ii].var = build_decl (location, VAR_DECL, NULL_TREE,
+                                            TREE_TYPE (an_info[0][ii].start));
+         an_loop_info[ii].ind_init = build_x_modify_expr
+           (location, an_loop_info[ii].var, NOP_EXPR,
+            build_zero_cst (TREE_TYPE (an_loop_info[ii].var)),
+            tf_warning_or_error);
+       }
+      else
+       {
+         an_loop_info[ii].var = build_min_nt_loc (location, VAR_DECL,
+                                                  NULL_TREE, NULL_TREE);
+         an_loop_info[ii].ind_init =
+           build_x_modify_expr (location, an_loop_info[ii].var, NOP_EXPR,
+                                integer_zero_node, tf_warning_or_error);
+       }
+  array_operand = create_array_refs (location, an_info, an_loop_info,
+                                    list_size, rank);
+  replace_array_notations (&stmt, true, array_list, array_operand);
+  create_cmp_incr (location, &an_loop_info, rank, an_info, tf_warning_or_error);
+  
+  an_init = pop_stmt_list (an_init);
+  append_to_statement_list_force (an_init, &loop_with_init);
+  body = stmt;
+
+  for (ii = 0; ii < rank; ii++)
+    {
+      tree new_loop = push_stmt_list ();
+      create_an_loop (an_loop_info[ii].ind_init, an_loop_info[ii].cmp,
+                     an_loop_info[ii].incr, body);
+      body = pop_stmt_list (new_loop);
+    }
+  append_to_statement_list_force (body, &loop_with_init);
+
+  an_info.release ();
+  an_loop_info.release ();
+  
+  return loop_with_init;
+}
+
+/* Transforms array notations inside unary expression ORIG_STMT with an
+   appropriate loop and ARRAY_REF (and returns all this as a super-tree called
+   LOOP).  */
+
+static tree
+expand_unary_array_notation_exprs (tree orig_stmt)
+{
+  vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
+  size_t list_size = 0, rank = 0, ii = 0;
+  tree body;
+  tree builtin_loop, stmt = NULL_TREE, new_var = NULL_TREE;
+  location_t location = EXPR_LOCATION (orig_stmt);
+  tree an_init, loop_with_init = alloc_stmt_list ();
+  vec<vec<an_parts> > an_info = vNULL;
+  vec<an_loop_parts> an_loop_info = vNULL;
+  
+  if (!find_rank (location, orig_stmt, orig_stmt, true, &rank))
+    return error_mark_node;
+  if (rank == 0)
+    return orig_stmt;  
+  
+  extract_array_notation_exprs (orig_stmt, false, &array_list);
+  list_size = vec_safe_length (array_list);
+  location = EXPR_LOCATION (orig_stmt);
+  stmt = NULL_TREE;
+  for (ii = 0; ii < list_size; ii++)
+    if (TREE_CODE ((*array_list)[ii]) == CALL_EXPR
+       || TREE_CODE ((*array_list)[ii]) == AGGR_INIT_EXPR)
+      {
+       tree list_node = (*array_list)[ii];
+       builtin_loop = expand_sec_reduce_builtin (list_node, &new_var);
+       if (builtin_loop == error_mark_node)
+         return error_mark_node;
+       else if (builtin_loop)
+         {
+           vec<tree, va_gc> *sub_list = NULL, *new_var_list = NULL;
+           stmt = alloc_stmt_list ();
+           append_to_statement_list_force (builtin_loop, &stmt);
+           vec_safe_push (sub_list, list_node);
+           vec_safe_push (new_var_list, new_var);
+           replace_array_notations (&orig_stmt, false, sub_list, new_var_list);
+         }     
+      }
+  if (stmt != NULL_TREE)
+    append_to_statement_list_force (finish_expr_stmt (orig_stmt), &stmt);
+  else
+    stmt = orig_stmt;
+  rank = 0;
+  list_size = 0;
+  array_list = NULL;
+  extract_array_notation_exprs (stmt, true, &array_list);
+  list_size = vec_safe_length (array_list);
+
+  if (!find_rank (EXPR_LOCATION (stmt), stmt, stmt, true, &rank))
+    return error_mark_node;
+  if (rank == 0 || list_size == 0)
+    return stmt;
+  an_loop_info.safe_grow_cleared (rank);
+  an_init = push_stmt_list ();  
+    /* Assign the array notation components to variable so that they can satisfy
+     the exec-once rule.  */
+  for (ii = 0; ii < list_size; ii++)
+    {
+      tree array_node = (*array_list)[ii];
+      make_triplet_val_inv (location, &ARRAY_NOTATION_START (array_node),
+                           tf_warning_or_error);
+      make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (array_node),
+                           tf_warning_or_error);
+      make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (array_node),
+                           tf_warning_or_error);
+    }
+  cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info);
+  
+  for (ii = 0; ii < rank; ii++)
+    {
+      an_loop_info[ii].var = build_decl (location, VAR_DECL, NULL_TREE,
+                                 TREE_TYPE (an_info[0][ii].start));
+      an_loop_info[ii].ind_init = build_x_modify_expr
+       (location, an_loop_info[ii].var, NOP_EXPR, 
+        build_zero_cst (TREE_TYPE (an_loop_info[ii].var)),
+        tf_warning_or_error);
+    }
+  array_operand = create_array_refs (location, an_info, an_loop_info,
+                                    list_size, rank);
+  replace_array_notations (&stmt, true, array_list, array_operand);
+  create_cmp_incr (location, &an_loop_info, rank, an_info, tf_warning_or_error);
+  
+  an_init = pop_stmt_list (an_init);
+  append_to_statement_list_force (an_init, &loop_with_init);
+  body = stmt;
+  
+  for (ii = 0; ii < rank; ii++)
+    {
+      tree new_loop = push_stmt_list ();
+      create_an_loop (an_loop_info[ii].ind_init, an_loop_info[ii].cmp,
+                     an_loop_info[ii].incr, body);
+      body = pop_stmt_list (new_loop);
+    }
+  append_to_statement_list_force (body, &loop_with_init);
+
+  an_info.release ();
+  an_loop_info.release ();
+
+  return loop_with_init;
+}
+
+/* Expands the array notation's builtin reduction function in EXPR
+   (of type RETURN_EXPR) and returns a STATEMENT_LIST that contains a loop
+   with the builtin function expansion and a return statement at the end.  */
+
+static tree
+expand_return_expr (tree expr)
+{
+  tree new_mod_list, new_var, new_mod, retval_expr;
+
+  if (TREE_CODE (expr) != RETURN_EXPR)
+    return expr;
+
+  location_t loc = EXPR_LOCATION (expr);
+  new_mod_list = alloc_stmt_list ();
+  retval_expr = TREE_OPERAND (expr, 0);
+  new_var = build_decl (loc, VAR_DECL, NULL_TREE, TREE_TYPE (retval_expr));
+  new_mod = expand_an_in_modify_expr (loc, new_var, NOP_EXPR,
+                                        TREE_OPERAND (retval_expr, 1),
+                                        tf_warning_or_error);
+  TREE_OPERAND (retval_expr, 1) = new_var;
+  TREE_OPERAND (expr, 0) = retval_expr;
+  append_to_statement_list_force (new_mod, &new_mod_list);
+  append_to_statement_list_force (expr, &new_mod_list);
+  return new_mod_list;
+}
+
+/* Expands ARRAY_NOTATION_REF and builtin functions in a compound statement,
+   STMT. Returns the STMT with expanded array notations.  */
+
+tree
+expand_array_notation_exprs (tree t)
+{
+  enum tree_code code;
+  bool is_expr;
+  location_t loc = UNKNOWN_LOCATION;
+  
+  if (!t)
+    return t;
+
+  loc = EXPR_LOCATION (t);
+
+  code = TREE_CODE (t); 
+  is_expr = IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code));
+  switch (code)
+    {
+    case ERROR_MARK:
+    case IDENTIFIER_NODE:
+    case INTEGER_CST:
+    case REAL_CST:
+    case FIXED_CST:
+    case STRING_CST:
+    case BLOCK:
+    case PLACEHOLDER_EXPR:
+    case FIELD_DECL:
+    case VOID_TYPE:
+    case REAL_TYPE:
+    case SSA_NAME:
+    case LABEL_DECL:
+    case RESULT_DECL:
+    case VAR_DECL:
+    case PARM_DECL:
+    case NON_LVALUE_EXPR:
+    case NOP_EXPR:
+    case INIT_EXPR:
+    case ADDR_EXPR:
+    case ARRAY_REF:
+    case BIT_FIELD_REF:
+    case VECTOR_CST:
+    case COMPLEX_CST:
+      return t;
+    case MODIFY_EXPR:
+      if (contains_array_notation_expr (t))
+       t = expand_an_in_modify_expr (loc, TREE_OPERAND (t, 0), NOP_EXPR, 
+                                        TREE_OPERAND (t, 1), 
+                                        tf_warning_or_error);
+      return t;
+    case MODOP_EXPR:
+      if (contains_array_notation_expr (t) && !processing_template_decl)
+       t = expand_an_in_modify_expr
+         (loc, TREE_OPERAND (t, 0), TREE_CODE (TREE_OPERAND (t, 1)),
+          TREE_OPERAND (t, 2), tf_warning_or_error);
+      return t;
+    case CONSTRUCTOR:
+      return t;
+    case BIND_EXPR:
+      {
+       BIND_EXPR_BODY (t) =
+         expand_array_notation_exprs  (BIND_EXPR_BODY (t));
+       return t;
+      }
+    case DECL_EXPR:
+      {
+       tree x = DECL_EXPR_DECL (t);
+       if (t && TREE_CODE (x) != FUNCTION_DECL)
+         if (DECL_INITIAL (x))
+           t = expand_unary_array_notation_exprs (t);
+      return t;
+      }
+    case STATEMENT_LIST:
+      {
+       tree_stmt_iterator i;
+       for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
+         *tsi_stmt_ptr (i) =
+           expand_array_notation_exprs (*tsi_stmt_ptr (i));
+       return t;
+      }
+
+    case OMP_PARALLEL:
+    case OMP_TASK:
+    case OMP_FOR:
+    case OMP_SINGLE:
+    case OMP_SECTION:
+    case OMP_SECTIONS:
+    case OMP_MASTER:
+    case OMP_ORDERED:
+    case OMP_CRITICAL:
+    case OMP_ATOMIC:
+    case OMP_CLAUSE:
+    case TARGET_EXPR:
+    case INTEGER_TYPE:
+    case ENUMERAL_TYPE:
+    case BOOLEAN_TYPE:
+    case POINTER_TYPE:
+    case ARRAY_TYPE:
+    case RECORD_TYPE:
+    case METHOD_TYPE:
+      return t;
+    case RETURN_EXPR:
+      if (contains_array_notation_expr (t))
+       t = expand_return_expr (t);
+      return t;
+    case PREDECREMENT_EXPR:
+    case PREINCREMENT_EXPR:
+    case POSTDECREMENT_EXPR:
+    case POSTINCREMENT_EXPR:
+    case AGGR_INIT_EXPR:
+    case CALL_EXPR:
+      t = expand_unary_array_notation_exprs (t);
+      return t;
+    case CONVERT_EXPR:
+    case CLEANUP_POINT_EXPR:
+    case EXPR_STMT:
+      TREE_OPERAND (t, 0) = expand_array_notation_exprs (TREE_OPERAND (t, 0));
+      /* It is not necessary to wrap error_mark_node in EXPR_STMT.  */
+      if (TREE_OPERAND (t, 0) == error_mark_node)
+       return TREE_OPERAND (t, 0); 
+      return t;
+    case COND_EXPR:
+      t = cp_expand_cond_array_notations (t);
+      if (TREE_CODE (t) == COND_EXPR)
+       {
+         COND_EXPR_THEN (t) =
+           expand_array_notation_exprs (COND_EXPR_THEN (t));
+         COND_EXPR_ELSE (t) =
+           expand_array_notation_exprs (COND_EXPR_ELSE (t));
+       }
+      else
+       t = expand_array_notation_exprs (t);
+      return t;
+
+    case SWITCH_EXPR:
+      t = cp_expand_cond_array_notations (t);
+      if (TREE_CODE (t) == SWITCH_EXPR)
+       SWITCH_BODY (t) = expand_array_notation_exprs (SWITCH_BODY (t));
+      else
+       t = expand_array_notation_exprs (t);
+      return t;
+    case FOR_STMT:      
+      /* FIXME: Add a check for CILK_FOR_STMT here when we add Cilk tasking 
+        keywords.  */
+      if (TREE_CODE (t) == FOR_STMT)
+       FOR_BODY (t) = expand_array_notation_exprs (FOR_BODY (t));
+      else
+       t = expand_array_notation_exprs (t);
+      return t;
+    case IF_STMT:
+      t = cp_expand_cond_array_notations (t);
+      /* If the above function added some extra instructions above the original
+        if statement, then we can't assume it is still IF_STMT so we have to
+        check again.  */
+      if (TREE_CODE (t) == IF_STMT)
+       {
+         if (THEN_CLAUSE (t))
+           THEN_CLAUSE (t) = expand_array_notation_exprs (THEN_CLAUSE (t));
+         if (ELSE_CLAUSE (t))
+           ELSE_CLAUSE (t) = expand_array_notation_exprs (ELSE_CLAUSE (t));
+       }
+      else
+       t = expand_array_notation_exprs (t);
+      return t;
+    case SWITCH_STMT:
+      t = cp_expand_cond_array_notations (t);
+      /* If the above function added some extra instructions above the original
+        switch statement, then we can't assume it is still SWITCH_STMT so we
+        have to check again.  */
+      if (TREE_CODE (t) == SWITCH_STMT)
+       {
+         if (SWITCH_STMT_BODY (t))
+           SWITCH_STMT_BODY (t) =
+             expand_array_notation_exprs (SWITCH_STMT_BODY (t));
+       }
+      else
+       t = expand_array_notation_exprs (t);
+      return t;
+    case WHILE_STMT:
+      t = cp_expand_cond_array_notations (t);
+      /* If the above function added some extra instructions above the original
+        while statement, then we can't assume it is still WHILE_STMTso we
+        have to check again.  */
+      if (TREE_CODE (t) == WHILE_STMT)
+       {
+         if (WHILE_BODY (t))
+           WHILE_BODY (t) = expand_array_notation_exprs (WHILE_BODY (t));
+       }
+      else
+       t = expand_array_notation_exprs (t);
+      return t;
+    case DO_STMT:
+      t = cp_expand_cond_array_notations (t);
+      /* If the above function added some extra instructions above the original
+        do-while statement, then we can't assume it is still DO_STMT so we
+        have to check again.  */
+      if (TREE_CODE (t) == DO_STMT)
+       {      
+         if (DO_BODY (t))
+           DO_BODY (t) = expand_array_notation_exprs (DO_BODY (t));
+       }
+      else
+       t = expand_array_notation_exprs (t);
+      return t;
+    default:
+      if (is_expr)
+       {
+         int i, len;
+
+         /* Walk over all the sub-trees of this operand.  */
+         len = TREE_CODE_LENGTH (code);
+
+         /* Go through the subtrees.  We need to do this in forward order so
+            that the scope of a FOR_EXPR is handled properly.  */
+         for (i = 0; i < len; ++i)
+           TREE_OPERAND (t, i) =
+             expand_array_notation_exprs (TREE_OPERAND (t, i));
+       }
+      return t;
+    }
+  return t;
+}
+
+/* Given the base of an array (ARRAY), the START_INDEX, the number of elements
+   to be accessed (LENGTH) and the STRIDE, construct an ARRAY_NOTATION_REF tree
+   of type TYPE and return it.  Restrictions on START_INDEX, LENGTH and STRIDE 
+   are the same as that of index field passed into ARRAY_REF.  The only
+   additional restriction is that, unlike index in ARRAY_REF, stride, length
+   and start_index cannot contain array notations.  */
+
+tree
+build_array_notation_ref (location_t loc, tree array, tree start_index,
+                         tree length, tree stride, tree type)
+{
+  tree array_ntn_expr = NULL_TREE;
+  
+  /* When dealing with templates, do the type checking at a later time.  */
+  if (processing_template_decl || !type)
+    {
+      if (!type && TREE_TYPE (array))
+       type = TREE_TYPE (array);
+      array_ntn_expr = build_min_nt_loc (loc, ARRAY_NOTATION_REF, array,
+                                        start_index, length, stride, type,
+                                        NULL_TREE);
+      TREE_TYPE (array_ntn_expr) = type;
+    }
+  if (!stride)
+    {
+      if (TREE_CONSTANT (start_index) && TREE_CONSTANT (length)
+         && TREE_CODE (start_index) != VAR_DECL
+         && TREE_CODE (length) != VAR_DECL
+         && tree_int_cst_lt (length, start_index))
+       stride = build_int_cst (TREE_TYPE (start_index), -1);
+      else
+       stride = build_int_cst (TREE_TYPE (start_index), 1);
+    }
+
+  if (!cilkplus_an_triplet_types_ok_p (loc, start_index, length, stride, type))
+    return error_mark_node;
+
+  if (!processing_template_decl)
+    {
+      array_ntn_expr = build4 (ARRAY_NOTATION_REF, NULL_TREE, NULL_TREE,
+                              NULL_TREE, NULL_TREE, NULL_TREE);
+      ARRAY_NOTATION_ARRAY (array_ntn_expr) = array;
+      ARRAY_NOTATION_START (array_ntn_expr) = start_index;
+      ARRAY_NOTATION_LENGTH (array_ntn_expr) = length;
+      ARRAY_NOTATION_STRIDE (array_ntn_expr) = stride;
+      if (type && (TREE_CODE (type) == ARRAY_TYPE
+                  || TREE_CODE (type) == POINTER_TYPE))
+       TREE_TYPE (array_ntn_expr) = TREE_TYPE (type);
+      else
+       TREE_TYPE (array_ntn_expr) = type;
+    }
+  SET_EXPR_LOCATION (array_ntn_expr, loc);
+
+  return array_ntn_expr;
+}
+
+/* Returns false if any of the Array notation triplet values: START_INDEX,
+   LENGTH and STRIDE, are not of integral type and have a rank greater than
+   zero.  */
+
+bool
+cilkplus_an_triplet_types_ok_p (location_t loc, tree start_index, tree length,
+                               tree stride, tree type)
+{
+  size_t stride_rank = 0, length_rank = 0, start_rank = 0;
+  if (!TREE_TYPE (start_index) || !INTEGRAL_TYPE_P (TREE_TYPE (start_index)))
+    {
+      error_at (loc, "start-index of array notation triplet is not an integer");
+      return false;
+    }
+  if (!TREE_TYPE (length) || !INTEGRAL_TYPE_P (TREE_TYPE (length)))
+    {
+      error_at (loc, "length of array notation triplet is not an integer");
+      return false;
+    }
+  if (!TREE_TYPE (stride) || !INTEGRAL_TYPE_P (TREE_TYPE (stride)))
+    {
+      error_at (loc, "stride of array notation triplet is not an integer");
+      return false;
+    }
+  if (!TREE_CODE (type) == FUNCTION_TYPE)
+    {
+      error_at (loc, "array notations cannot be used with function type");
+      return false;
+    }
+  while (type && (TREE_CODE (type) == POINTER_TYPE
+                 || TREE_CODE (type) == ARRAY_TYPE))
+    {
+      type = TREE_TYPE (type);
+      if (type && TREE_CODE (type) == FUNCTION_TYPE)
+       {
+         error_at (loc, "array notations cannot be used with function pointer"
+                   " arrays");
+         return false;
+       }
+    }
+  if (!find_rank (loc, start_index, start_index, false, &start_rank)
+      || !find_rank (loc, length, length, false, &length_rank)
+      || !find_rank (loc, stride, stride, false, &stride_rank))
+    return false;
+
+  if (start_rank != 0)
+    {
+      error_at (loc, "rank of an array notation triplet%'s start-index is not "
+               "zero");
+      return false;
+    }
+  if (length_rank != 0)
+    {
+      error_at (loc, "rank of an array notation triplet%'s length is not zero");
+      return false;
+    }
+  if (stride_rank != 0)
+    {
+      error_at (loc, "rank of array notation triplet%'s stride is not zero");
+      return false;
+    }
+  return true;
+}
index bccd884f5c1e3f8f23b32ea9425d02b26ff307f2..d301db01a78a85dfd0f1d975ce6421975875f507 100644 (file)
@@ -321,6 +321,7 @@ cp_common_init_ts (void)
   MARK_TS_TYPED (USING_STMT);
   MARK_TS_TYPED (LAMBDA_EXPR);
   MARK_TS_TYPED (CTOR_INITIALIZER);
+  MARK_TS_TYPED (ARRAY_NOTATION_REF);
 }
 
 #include "gt-cp-cp-objcp-common.h"
index cf54acf0d683e1d95995635451305bb9b2602eb5..00ee45013b3313f91ab2e82b2b513f4388c46a02 100644 (file)
@@ -6138,6 +6138,10 @@ extern bool cxx_omp_privatize_by_reference       (const_tree);
 extern void suggest_alternatives_for            (location_t, tree);
 extern tree strip_using_decl                    (tree);
 
+/* In cp/cp-array-notations.c */
+extern tree expand_array_notation_exprs         (tree);
+bool cilkplus_an_triplet_types_ok_p             (location_t, tree, tree, tree,
+                                                tree);
 /* -- end of C++ */
 
 #endif /* ! GCC_CP_TREE_H */
index a75fc4e7b33b9dd20aa6e0ab97f2e188235e94c0..a8f52cda0ae9d98c06711d19694b352062efbd8e 100644 (file)
@@ -1071,6 +1071,17 @@ dump_decl (tree t, int flags)
       pp_cxx_right_bracket (cxx_pp);
       break;
 
+    case ARRAY_NOTATION_REF:
+      dump_decl (ARRAY_NOTATION_ARRAY (t), flags | TFF_EXPR_IN_PARENS);
+      pp_cxx_left_bracket (cxx_pp);
+      dump_decl (ARRAY_NOTATION_START (t), flags | TFF_EXPR_IN_PARENS);
+      pp_string (cxx_pp, ":");
+      dump_decl (ARRAY_NOTATION_LENGTH (t), flags | TFF_EXPR_IN_PARENS);
+      pp_string (cxx_pp, ":");
+      dump_decl (ARRAY_NOTATION_STRIDE (t), flags | TFF_EXPR_IN_PARENS);
+      pp_cxx_right_bracket (cxx_pp);
+      break;
+
       /* So that we can do dump_decl on an aggr type.  */
     case RECORD_TYPE:
     case UNION_TYPE:
@@ -2057,6 +2068,17 @@ dump_expr (tree t, int flags)
       pp_cxx_right_bracket (cxx_pp);
       break;
 
+    case ARRAY_NOTATION_REF:
+      dump_expr (ARRAY_NOTATION_ARRAY (t), flags | TFF_EXPR_IN_PARENS);
+      pp_cxx_left_bracket (cxx_pp);
+      dump_expr (ARRAY_NOTATION_START (t), flags | TFF_EXPR_IN_PARENS);
+      pp_string (cxx_pp, ":");
+      dump_expr (ARRAY_NOTATION_LENGTH (t), flags | TFF_EXPR_IN_PARENS);
+      pp_string (cxx_pp, ":");
+      dump_expr (ARRAY_NOTATION_STRIDE (t), flags | TFF_EXPR_IN_PARENS);
+      pp_cxx_right_bracket (cxx_pp);
+      break;
+
     case UNARY_PLUS_EXPR:
       dump_unary_op ("+", t, flags);
       break;
index 904ae0b8003406077f352e989be950e13b95b879..6fc45f30b36d56422931f19f190609456bafb04d 100644 (file)
@@ -6060,6 +6060,170 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
   return error_mark_node;
 }
 
+/* This function parses Cilk Plus array notations.  The starting index is
+   passed in INIT_INDEX and the array name is passed in ARRAY_VALUE.  If the
+   INIT_INDEX is NULL, then we have special case were the entire array is
+   accessed (e.g. A[:]).  The return value of this function is a tree node
+   called VALUE_TREE of type ARRAY_NOTATION_REF.  If some error occurred it
+   returns error_mark_node.  */
+
+static tree
+cp_parser_array_notation (location_t loc, cp_parser *parser, tree init_index,
+                         tree array_value)
+{
+  cp_token *token = NULL;
+  tree start_index = NULL_TREE, length_index = NULL_TREE, stride = NULL_TREE;
+  tree value_tree, type, array_type, array_type_domain;
+  double_int x; 
+  bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
+
+  if (!array_value || array_value == error_mark_node)
+    {
+      cp_parser_skip_to_end_of_statement (parser);
+      return error_mark_node;
+    }
+  
+  if (processing_template_decl)
+    {
+      array_type = TREE_TYPE (array_value);
+      type = TREE_TYPE (array_type);
+    }
+  else
+    {
+      array_type = TREE_TYPE (array_value);
+      gcc_assert (array_type);
+      type = array_type;
+    }
+  token = cp_lexer_peek_token (parser->lexer);
+  if (!token)
+    {
+      cp_parser_error (parser, "expected %<:%> or numeral");
+      return error_mark_node;
+    }
+  else if (token->type == CPP_COLON)
+    {
+      if (!init_index)
+       {
+         /* If we are here, then we have a case like this A[:].  */
+         cp_lexer_consume_token (parser->lexer);
+
+         if (cp_lexer_peek_token (parser->lexer)->type != CPP_CLOSE_SQUARE)
+           {
+             cp_parser_error (parser, "expected %<]%>");
+             cp_parser_skip_to_end_of_statement (parser);
+             return error_mark_node;
+           }
+         if (TREE_CODE (array_type) == RECORD_TYPE
+             || TREE_CODE (array_type) == POINTER_TYPE)
+           {
+             error_at (loc, "start-index and length fields necessary for "
+                       "using array notations in pointers or records");
+             cp_parser_skip_to_end_of_statement (parser);
+             return error_mark_node;
+           }
+         if (TREE_CODE (array_type) == ARRAY_TYPE)
+           {
+             tree subtype = TREE_TYPE (array_type);
+             while (subtype && TREE_CODE (subtype) == POINTER_TYPE)
+               {
+                 /* This could be a function ptr.  If so, then emit error.  */
+                 subtype = TREE_TYPE (subtype);
+                 if (subtype && TREE_CODE (subtype) == FUNCTION_TYPE)
+                   {
+                     error_at (loc, "array notations cannot be used with"
+                               " function pointer arrays");
+                     cp_parser_skip_to_end_of_statement (parser);
+                     return error_mark_node;
+                   }
+               }
+           }
+         array_type_domain = TYPE_DOMAIN (array_type);
+         if (!array_type_domain)
+           {
+             error_at (loc, "start-index and length fields necessary for "
+                       "using array notations in dimensionless arrays");
+             cp_parser_skip_to_end_of_statement (parser);
+             return error_mark_node;
+           }
+         start_index = TYPE_MINVAL (array_type_domain);
+         start_index = fold_build1 (CONVERT_EXPR, ptrdiff_type_node,
+                                    start_index);
+         x = TREE_INT_CST (TYPE_MAXVAL (array_type_domain));
+         x.low++;
+         length_index = double_int_to_tree (integer_type_node, x);
+         length_index = fold_build1 (CONVERT_EXPR, ptrdiff_type_node,
+                                     length_index);
+         stride = build_int_cst (integer_type_node, 1);
+         stride = fold_build1 (CONVERT_EXPR, ptrdiff_type_node, stride);
+       }
+      else if (init_index != error_mark_node)
+       {
+         /* If we hare here, then there are 2 possibilities:
+            1. Array [ EXPR : EXPR ]
+            2. Array [ EXPR : EXPR : EXPR ]
+         */
+         start_index = init_index;
+         cp_lexer_consume_token (parser->lexer);
+
+         saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
+          /* The ':' is used in array notation.  Thus compiler cannot do scope 
+             correction automatically.  */
+         parser->colon_corrects_to_scope_p = false;
+         length_index = cp_parser_expression (parser, false, NULL);
+         parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
+         if (!length_index || length_index == error_mark_node)
+           cp_parser_skip_to_end_of_statement (parser);
+        
+         if (cp_lexer_peek_token (parser->lexer)->type == CPP_COLON)
+           {
+             cp_lexer_consume_token (parser->lexer);
+             saved_colon_corrects_to_scope_p = 
+               parser->colon_corrects_to_scope_p;
+             /* Disable correcting single colon correcting to scope.  */
+             parser->colon_corrects_to_scope_p = false;
+             stride = cp_parser_expression (parser, false, NULL);
+             parser->colon_corrects_to_scope_p = 
+               saved_colon_corrects_to_scope_p;
+             if (!stride || stride == error_mark_node)
+               {
+                 cp_parser_skip_to_end_of_statement (parser);
+                 if (cp_lexer_peek_token (parser->lexer)->type
+                     == CPP_CLOSE_SQUARE)
+                   cp_lexer_consume_token (parser->lexer);
+               }
+           }
+         else
+           stride = build_one_cst (integer_type_node);
+       }
+      else
+       {
+         cp_parser_skip_to_end_of_statement (parser);
+         return error_mark_node;
+       }
+    }
+  
+  if (start_index == error_mark_node || length_index == error_mark_node
+      || stride == error_mark_node || !start_index || !length_index
+      || !stride)
+    {
+      if (cp_lexer_peek_token (parser->lexer)->type == CPP_CLOSE_SQUARE)
+       cp_lexer_consume_token (parser->lexer);
+      return error_mark_node;
+    }
+  cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
+  
+  /* We fold all 3 of the values to make things easier when we transform
+     them later.  */
+  start_index = fold (start_index);
+  length_index = fold (length_index);
+  stride = fold (stride);
+
+  value_tree = build_array_notation_ref (input_location, array_value,
+                                        start_index, length_index, stride,
+                                        type);
+  return value_tree;
+}
+
 /* A subroutine of cp_parser_postfix_expression that also gets hijacked
    by cp_parser_builtin_offsetof.  We're looking for
 
@@ -6081,41 +6245,78 @@ cp_parser_postfix_open_square_expression (cp_parser *parser,
   /* Consume the `[' token.  */
   cp_lexer_consume_token (parser->lexer);
 
-  /* Parse the index expression.  */
-  /* ??? For offsetof, there is a question of what to allow here.  If
-     offsetof is not being used in an integral constant expression context,
-     then we *could* get the right answer by computing the value at runtime.
-     If we are in an integral constant expression context, then we might
-     could accept any constant expression; hard to say without analysis.
-     Rather than open the barn door too wide right away, allow only integer
-     constant expressions here.  */
-  if (for_offsetof)
-    index = cp_parser_constant_expression (parser, false, NULL);
+  if (flag_enable_cilkplus
+      && cp_lexer_peek_token (parser->lexer)->type == CPP_COLON)
+    /* If we are here, then we have something like this:
+       ARRAY[:]
+    */
+    postfix_expression = cp_parser_array_notation (loc, parser, NULL_TREE,
+                                                  postfix_expression);
   else
     {
-      if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+      /* Here are have these options:
+        1. ARRAY[EXPR]               -- This is the normal array call.
+        2. ARRAY[EXPR : EXPR]        -- Array notation expr with default stride
+        of 1.
+        3. ARRAY[EXPR : EXPR : EXPR] -- Array Notation with userdefined stride.
+        4. Array[Braced List]        -- This is handled by braced list.
+      */
+      
+      /* Parse the index expression.  */
+      /* ??? For offsetof, there is a question of what to allow here.  If
+        offsetof is not being used in an integral constant expression context,
+        then we *could* get the right answer by computing the value at runtime.
+        If we are in an integral constant expression context, then we might
+        could accept any constant expression; hard to say without analysis.
+        Rather than open the barn door too wide right away, allow only integer
+        constant expressions here.  */
+      if (for_offsetof)
+       index = cp_parser_constant_expression (parser, false, NULL);
+      else
        {
-         bool expr_nonconst_p;
-         maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
-         index = cp_parser_braced_list (parser, &expr_nonconst_p);
+         bool saved_colon_corrects_to_scope_p = 
+           parser->colon_corrects_to_scope_p;
+         if (flag_enable_cilkplus)
+           parser->colon_corrects_to_scope_p = false;
+         if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+           {
+             bool expr_nonconst_p;
+             maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
+             index = cp_parser_braced_list (parser, &expr_nonconst_p);
+             if (flag_enable_cilkplus
+                 && cp_lexer_peek_token (parser->lexer)->type == CPP_COLON)
+               {
+                 error_at (cp_lexer_peek_token (parser->lexer)->location,
+                           "braced list index is not allowed with array "
+                           "notations");
+                 index = error_mark_node;
+               }
+           }
+         else
+           index = cp_parser_expression (parser, /*cast_p=*/false, NULL);
+         parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
        }
+      if (flag_enable_cilkplus
+         && cp_lexer_peek_token (parser->lexer)->type == CPP_COLON)
+       postfix_expression = cp_parser_array_notation (loc, parser, index,
+                                                      postfix_expression);
       else
-       index = cp_parser_expression (parser, /*cast_p=*/false, NULL);
-    }
-
-  /* Look for the closing `]'.  */
-  cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
-
-  /* Build the ARRAY_REF.  */
-  postfix_expression = grok_array_decl (loc, postfix_expression,
-                                       index, decltype_p);
+       {
+         /* Look for the closing `]'.  */
+         cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
 
-  /* When not doing offsetof, array references are not permitted in
-     constant-expressions.  */
-  if (!for_offsetof
-      && (cp_parser_non_integral_constant_expression (parser, NIC_ARRAY_REF)))
-    postfix_expression = error_mark_node;
+         /* Build the ARRAY_REF.  */
+         postfix_expression = grok_array_decl (loc, postfix_expression,
+                                               index, decltype_p);
 
+         /* When not doing offsetof, array references are not permitted in
+            constant-expressions.  */
+         if (!for_offsetof
+             && (cp_parser_non_integral_constant_expression (parser,
+                                                             NIC_ARRAY_REF)))
+           postfix_expression = error_mark_node;
+       }
+    }
   return postfix_expression;
 }
 
@@ -9350,6 +9551,8 @@ cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr,
   /* Consume the `}'.  */
   cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
 
+  if (flag_enable_cilkplus && contains_array_notation_expr (compound_stmt))
+    compound_stmt = expand_array_notation_exprs (compound_stmt);
   return compound_stmt;
 }
 
@@ -9542,6 +9745,14 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p)
 
            /* Now we're all done with the switch-statement.  */
            finish_switch_stmt (statement);
+           if (flag_enable_cilkplus
+               && contains_array_notation_expr (condition))
+             {
+               error_at (EXPR_LOCATION (condition),
+                         "array notations cannot be used as a condition for "
+                         "switch statement");
+               statement = error_mark_node;
+             }      
          }
 
        return statement;
@@ -10099,6 +10310,12 @@ cp_parser_iteration_statement (cp_parser* parser)
        parser->in_statement = in_statement;
        /* We're done with the while-statement.  */
        finish_while_stmt (statement);
+       if (flag_enable_cilkplus && contains_array_notation_expr (condition))
+         {
+           error_at (EXPR_LOCATION (condition), "array notations cannot be "
+                     "used as a condition for while statement");
+           statement = error_mark_node;
+         }
       }
       break;
 
@@ -10125,6 +10342,15 @@ cp_parser_iteration_statement (cp_parser* parser)
        cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
        /* Look for the `;'.  */
        cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
+       if (flag_enable_cilkplus
+           && contains_array_notation_expr (DO_COND (statement)))
+         {
+           error_at (EXPR_LOCATION (DO_COND (statement)),
+                     "array notations cannot be used as a condition for a "
+                     "do-while statement");
+           statement = error_mark_node;
+         }
+
       }
       break;
 
@@ -10143,8 +10369,17 @@ cp_parser_iteration_statement (cp_parser* parser)
        cp_parser_already_scoped_statement (parser);
        parser->in_statement = in_statement;
 
-       /* We're done with the for-statement.  */
-       finish_for_stmt (statement);
+       if (flag_enable_cilkplus
+           && contains_array_notation_expr (FOR_COND (statement)))
+         {
+           error_at (EXPR_LOCATION (FOR_COND (statement)),
+                     "array notations cannot be used in a condition for a "
+                     "for-loop");
+           statement = error_mark_node;
+         }
+       else
+         /* We're done with the for-statement.  */
+         finish_for_stmt (statement);
       }
       break;
 
@@ -16719,30 +16954,53 @@ cp_parser_direct_declarator (cp_parser* parser,
            {
              bool non_constant_p;
 
-             bounds
-               = cp_parser_constant_expression (parser,
-                                                /*allow_non_constant=*/true,
-                                                &non_constant_p);
-             if (!non_constant_p)
-               /* OK */;
-             else if (error_operand_p (bounds))
-               /* Already gave an error.  */;
-             else if (!parser->in_function_body
-                      || current_binding_level->kind == sk_function_parms)
+             if (flag_enable_cilkplus
+                 && cp_lexer_next_token_is (parser->lexer, CPP_COLON))
                {
-                 /* Normally, the array bound must be an integral constant
-                    expression.  However, as an extension, we allow VLAs
-                    in function scopes as long as they aren't part of a
-                    parameter declaration.  */
-                 cp_parser_error (parser,
-                                  "array bound is not an integer constant");
                  bounds = error_mark_node;
+                 error_at (cp_lexer_peek_token (parser->lexer)->location,
+                           "array notations cannot be used in declaration");
+                 cp_lexer_consume_token (parser->lexer);
                }
-             else if (processing_template_decl)
+             else
                {
-                 /* Remember this wasn't a constant-expression.  */
-                 bounds = build_nop (TREE_TYPE (bounds), bounds);
-                 TREE_SIDE_EFFECTS (bounds) = 1;
+                 bounds
+                   = cp_parser_constant_expression (parser,
+                                                    /*allow_non_constant=*/true,
+                                                    &non_constant_p);
+                 if (!non_constant_p)
+                   /* OK */;
+                 else if (error_operand_p (bounds))
+                   /* Already gave an error.  */;
+                 else if (!parser->in_function_body
+                          || current_binding_level->kind == sk_function_parms)
+                   {
+                     /* Normally, the array bound must be an integral constant
+                        expression.  However, as an extension, we allow VLAs
+                        in function scopes as long as they aren't part of a
+                        parameter declaration.  */
+                     cp_parser_error (parser,
+                                      "array bound is not an integer constant");
+                     bounds = error_mark_node;
+                   }
+                 else if (processing_template_decl)
+                   {
+                     /* Remember this wasn't a constant-expression.  */
+                     bounds = build_nop (TREE_TYPE (bounds), bounds);
+                     TREE_SIDE_EFFECTS (bounds) = 1;
+                   }
+                 if (flag_enable_cilkplus
+                     && cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+                   {
+                     location_t loc =
+                       cp_lexer_peek_token (parser->lexer)->location;
+                     while (cp_lexer_next_token_is_not (parser->lexer,
+                                                        CPP_CLOSE_SQUARE))
+                       cp_lexer_consume_token (parser->lexer);
+                     error_at (loc, "array notations cannot be used in "
+                               "declaration");
+                     bounds = error_mark_node; 
+                   }
                }
            }
          else
@@ -18113,6 +18371,11 @@ cp_parser_ctor_initializer_opt_and_function_body (cp_parser *parser,
   cp_parser_function_body (parser, in_function_try_block);
   if (check_body_p)
     check_constexpr_ctor_body (last, list);
+
+  /* Transform all array notations to the equivalent array refs and loop.  */
+  if (flag_enable_cilkplus && contains_array_notation_expr (body))
+    body = expand_array_notation_exprs (body);
+  
   /* Finish the function body.  */
   finish_function_body (body);
 
@@ -22092,6 +22355,12 @@ cp_parser_function_definition_after_declarator (cp_parser* parser,
 
   finish_lambda_scope ();
 
+  /* Expand all array notation expressions here.  */
+  if (flag_enable_cilkplus && current_function_decl
+      && contains_array_notation_expr (DECL_SAVED_TREE (current_function_decl)))
+    DECL_SAVED_TREE (current_function_decl) =
+      expand_array_notation_exprs (DECL_SAVED_TREE (current_function_decl));
+  
   /* Finish the function.  */
   fn = finish_function ((ctor_initializer_p ? 1 : 0) |
                        (inline_p ? 2 : 0));
index cfabba9e3dd8d63bb7f9063813468712c4d8b33f..c9e376c69c597d5e5096afdbf6203cdfea6be50e 100644 (file)
@@ -13753,6 +13753,20 @@ tsubst_copy_and_build (tree t,
                                 RECUR (TREE_OPERAND (t, 1)),
                                 complain|decltype_flag));
 
+    case ARRAY_NOTATION_REF:
+      {
+       tree start_index, length, stride;
+       op1 = tsubst_non_call_postfix_expression (ARRAY_NOTATION_ARRAY (t),
+                                                 args, complain, in_decl);
+       start_index = RECUR (ARRAY_NOTATION_START (t));
+       length = RECUR (ARRAY_NOTATION_LENGTH (t));
+       stride = RECUR (ARRAY_NOTATION_STRIDE (t));
+       if (!cilkplus_an_triplet_types_ok_p (loc, start_index, length, stride,
+                                            TREE_TYPE (op1)))
+         RETURN (error_mark_node);
+       RETURN (build_array_notation_ref (EXPR_LOCATION (t), op1, start_index,
+                                         length, stride, TREE_TYPE (op1)));
+      }
     case SIZEOF_EXPR:
       if (PACK_EXPANSION_P (TREE_OPERAND (t, 0)))
        RETURN (tsubst_copy (t, args, complain, in_decl));
@@ -15725,6 +15739,9 @@ type_unification_real (tree tparms,
       arg = args[ia];
       ++ia;
 
+      if (flag_enable_cilkplus && TREE_CODE (arg) == ARRAY_NOTATION_REF)
+       return 1;
+
       if (unify_one_argument (tparms, targs, parm, arg, subr, strict,
                              flags, explain_p))
        return 1;
@@ -19126,6 +19143,11 @@ instantiate_decl (tree d, int defer_ok,
       pointer_map_destroy (local_specializations);
       local_specializations = saved_local_specializations;
 
+      /* We expand all the array notation expressions here.  */
+      if (flag_enable_cilkplus
+         && contains_array_notation_expr (DECL_SAVED_TREE (d)))
+       DECL_SAVED_TREE (d) = expand_array_notation_exprs (DECL_SAVED_TREE (d));
+      
       /* Finish the function.  */
       d = finish_function (0);
       expand_or_defer_fn (d);
index 135ef74bec0a9645966961ed332b42ccf6080cf5..3f0faa8081d2b460d72b53c6c35334b4e678e3a1 100644 (file)
@@ -779,6 +779,22 @@ finish_return_stmt (tree expr)
   tree r;
   bool no_warning;
 
+  if (flag_enable_cilkplus && contains_array_notation_expr (expr))
+    {
+      size_t rank = 0;
+      
+      if (!find_rank (input_location, expr, expr, false, &rank))
+       return error_mark_node;
+
+      /* If the return expression contains array notations, then flag it as
+        error.  */
+      if (rank >= 1)
+       {
+         error_at (input_location, "array notation expression cannot be "
+                   "used as a return value");
+         return error_mark_node;
+       }
+    }
   expr = check_return_expr (expr, &no_warning);
 
   if (flag_openmp && !check_omp_return ())
@@ -8073,6 +8089,7 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t,
                                       non_constant_p, overflow_p);
       break;
 
+    case ARRAY_NOTATION_REF:
     case ARRAY_REF:
       r = cxx_eval_array_reference (call, t, allow_non_constant, addr,
                                    non_constant_p, overflow_p);
@@ -8884,6 +8901,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
       want_rval = true;
       /* Fall through.  */
     case ARRAY_REF:
+    case ARRAY_NOTATION_REF:
     case ARRAY_RANGE_REF:
     case MEMBER_REF:
     case DOTSTAR_EXPR:
index d54d46dbb799bb534822be19eecb20f5b9f68b0b..4f71351f8eb83f847016a02cdca3758513f16ad5 100644 (file)
@@ -141,6 +141,7 @@ lvalue_kind (const_tree ref)
     case INDIRECT_REF:
     case ARROW_EXPR:
     case ARRAY_REF:
+    case ARRAY_NOTATION_REF:
     case PARM_DECL:
     case RESULT_DECL:
       return clk_ordinary;
index 11ac85b65cd920c839269772799ee047606a64b5..316a657d924f23ce05d09d23af684a135e560dc5 100644 (file)
@@ -3005,6 +3005,22 @@ cp_build_array_ref (location_t loc, tree array, tree idx,
       return error_mark_node;
     }
 
+  /* If an array's index is an array notation, then its rank cannot be
+     greater than one.  */ 
+  if (flag_enable_cilkplus && contains_array_notation_expr (idx))
+    {
+      size_t rank = 0;
+
+      /* If find_rank returns false, then it should have reported an error,
+        thus it is unnecessary for repetition.  */
+      if (!find_rank (loc, idx, idx, true, &rank))
+       return error_mark_node;
+      if (rank > 1)
+       {
+         error_at (loc, "rank of the array%'s index is greater than 1");
+         return error_mark_node;
+       }
+    }
   if (TREE_TYPE (array) == error_mark_node
       || TREE_TYPE (idx) == error_mark_node)
     return error_mark_node;
@@ -3477,8 +3493,12 @@ cp_build_function_call_vec (tree function, vec<tree, va_gc> **params,
       params = &allocated;
     }
 
-  nargs = convert_arguments (parm_types, params, fndecl, LOOKUP_NORMAL,
-                            complain);
+  if (flag_enable_cilkplus
+      && is_cilkplus_reduce_builtin (fndecl) != BUILT_IN_NONE)
+    nargs = (*params)->length ();
+  else
+    nargs = convert_arguments (parm_types, params, fndecl, LOOKUP_NORMAL,
+                              complain);
   if (nargs < 0)
     return error_mark_node;
 
@@ -3936,8 +3956,15 @@ cp_build_binary_op (location_t location,
        }
     }
 
-  type0 = TREE_TYPE (op0);
-  type1 = TREE_TYPE (op1);
+  if (flag_enable_cilkplus && contains_array_notation_expr (op0))
+    type0 = find_correct_array_notation_type (op0);
+  else
+    type0 = TREE_TYPE (op0);
+
+  if (flag_enable_cilkplus && contains_array_notation_expr (op1))
+    type1 = find_correct_array_notation_type (op1);
+  else
+    type1 = TREE_TYPE (op1);
 
   /* The expression codes of the data types of the arguments tell us
      whether the arguments are integers, floating, pointers, etc.  */
@@ -5140,6 +5167,13 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue, tsubst_flags_t complain)
 
   gcc_assert (!identifier_p (arg) || !IDENTIFIER_OPNAME_P (arg));
 
+  if (flag_enable_cilkplus && TREE_CODE (arg) == ARRAY_NOTATION_REF)
+    {
+      val = build_address (arg);
+      if (TREE_CODE (arg) == OFFSET_REF)
+       PTRMEM_OK_P (val) = PTRMEM_OK_P (arg);
+      return val;
+    }
   if (TREE_CODE (arg) == COMPONENT_REF && type_unknown_p (arg)
       && !really_overloaded_fn (TREE_OPERAND (arg, 1)))
     {
@@ -7818,6 +7852,13 @@ convert_for_assignment (tree type, tree rhs,
   tree rhstype;
   enum tree_code coder;
 
+  /* If we are dealing with built-in array notation function then we don't need
+     to convert them.  They will be broken up into modify exprs in future,
+     during which all these checks will be done.  */
+  if (flag_enable_cilkplus
+      && is_cilkplus_reduce_builtin (fndecl) != BUILT_IN_NONE)
+    return rhs;
+  
   /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue.  */
   if (TREE_CODE (rhs) == NON_LVALUE_EXPR)
     rhs = TREE_OPERAND (rhs, 0);
index b0632ff7df82f0ef7144131f0631b3bf3e99fc4d..9c3fe0efa14c07ffe15c2d886e6393927772566c 100644 (file)
@@ -1,3 +1,31 @@
+2013-06-21  Balaji V. Iyer  <balaji.v.iyer@intel.com>
+
+       * c-c++-common/cilk-plus/AN/array_test1.c: Make this an execution test.
+       Also changed the returns from error as distinct values so that debugging
+       can get easier.
+       * c-c++-common/cilk-plus/AN/if_test_errors.c (main): Made certain
+       errors specific to C, if necessary.  Also added new error hooks for C++.
+       * c-c++-common/cilk-plus/AN/misc.c (main): Likewise.
+       * c-c++-common/cilk-plus/AN/parser_errors.c (main): Likewise.
+       * c-c++-common/cilk-plus/AN/parser_errors2.c (main): Likewise.
+       * c-c++-common/cilk-plus/AN/parser_errors3.c (main): Likewise.
+       * c-c++-common/cilk-plus/AN/pr57541.c (main): Likewise.
+       * c-c++-common/cilk-plus/AN/parser_errors4.c (main): In addition to the
+       same changes as parser_errors3.c, spaces were added between colons to
+       not confuse C++ compiler with 2 colons as scope.
+       * c-c++-common/cilk-plus/AN/vla.c: Make this test C specific.
+       * g++.dg/cilk-plus/AN/array_test1_tplt.cc: New test.
+       * g++.dg/cilk-plus/AN/array_test2_tplt.cc: Likewise.
+       * g++.dg/cilk-plus/AN/array_test_ND_tplt.cc: Likewise.
+       * g++.dg/cilk-plus/AN/braced_list.cc: Likewise.
+       * g++.dg/cilk-plus/AN/builtin_fn_custom_tplt.cc: Likewise.
+       * g++.dg/cilk-plus/AN/builtin_fn_mutating_tplt.cc: Likewise.
+       * g++.dg/cilk-plus/AN/fp_triplet_values_tplt.c: Likewise.
+       * g++.dg/cilk-plus/AN/preincr_test.cc: Likewise.
+       * g++.dg/cilk-plus/AN/postincr_test.cc: Likewise.
+       * g++.dg/cilk-plus/cilk-plus.exp: New script.
+       * gcc/testsuite/g++.dg/dg.exp: Included Cilk Plus C++ tests in the list.
+       
 2013-06-21  Joseph Myers  <joseph@codesourcery.com>
 
        PR other/53317
index d17d8cf5de20fdbddc5e2bb936773f9f916d2f1c..579d396948e7468f443bfeccff0b308c9da74ea3 100644 (file)
@@ -18,19 +18,19 @@ int main (void)
     array2[:] = 5;
   else
     array2[:] = 10;
-  if (!(array[0:10:1] + array[0:10:1])) /* { dg-error "condition and the then-block" } */
-    array2d[:][:] = 5;
+  if (!(array[0:10:1] + array[0:10:1])) /* { dg-error "condition and the then-block" "" { target c } } */
+    array2d[:][:] = 5; /* { dg-error "rank mismatch with controlling expression of parent" "" { target c++ } } */
   else
     array2[:] = 10;
 
-  if (!(array[0:10:1] + array[0:10:1])) /* { dg-error "condition and the else-block" } */
+  if (!(array[0:10:1] + array[0:10:1])) /* { dg-error "condition and the else-block" "" { target c } } */
     array2[:] = 5;
   else
-    array2d[:][:] = 10;
+    array2d[:][:] = 10; /* { dg-error "rank mismatch with controlling expression of parent" "" { target c++ } } */
 
 
-  if (TwodArray[:][:] != 10) /* { dg-error "condition and the then-block" } */
-    array2[:] = 10; 
+  if (TwodArray[:][:] != 10) /* { dg-error "condition and the then-block" "" { target c } } */
+    array2[:] = 10;  /* { dg-error "rank mismatch with controlling expression of parent" "" { target c++ } } */
   else
     array2[:] = 5;
 
@@ -40,8 +40,8 @@ int main (void)
     array4[32][:][:][:] = 5;
 
   /* atoi(argv[1]) == 10, so it will convert all 10's to 5's */
-  if (FourDArray[42][0:10:1][9:10:-1][0:5:2] != 10) /* { dg-error "condition and the then-block" } */
-    array4[0:10:1][0:5:2][9:10:-1][0:5:2] = 10; 
+  if (FourDArray[42][0:10:1][9:10:-1][0:5:2] != 10) /* { dg-error "condition and the then-block" "" { target c } } */
+    array4[0:10:1][0:5:2][9:10:-1][0:5:2] = 10;  /* { dg-error "rank mismatch with controlling expression of parent" "" { target c++ } } */
   else
     array4[0:10:1][0:5:2][9:10:-1][0:5:2] = 5;
 
index 35eb11537d1f38e72a1f9a29033ef037db008d22..14421d94f0cb7d6c0164e9d720bef025316cbe47 100644 (file)
@@ -73,13 +73,13 @@ int main (void)
   while (ii != array2[1:x:3][1:2:1]) /* { dg-error "array notations cannot be used as a condition for while statement"  } */
     x = 2;
 
-  do { /* { dg-error "array notations cannot be used as a condition for a do-while statement" } */
+  do { /* { dg-error "array notations cannot be used as a condition for a do-while statement" "" { target c } } */
     x = 3;
-  } while (ii != array2[:][:]); 
+  } while (ii != array2[:][:]); /* { dg-error "array notations cannot be used as a condition for a do-while statement" "" { target c++ } } */
 
-  do {  /* { dg-error "array notations cannot be used as a condition for a do-while statement" } */
+  do {  /* { dg-error "array notations cannot be used as a condition for a do-while statement" "" { target c } } */
     x = 2;
-  } while (ii != (x + array2[:][1:x:2]) + 2);
+  } while (ii != (x + array2[:][1:x:2]) + 2); /* { dg-error "array notations cannot be used as a condition for a do-while statement" "" { target c++ } } */
   
   do { 
     x += 3;
index a0a3742f5df1d789f827bbc27ca53d0a6e626b09..18816e0ec6f814fbf7fc4b574a3d28d0eb6a3cc8 100644 (file)
@@ -8,4 +8,4 @@ int main (void)
   array2[:] = array2[: ;  /* { dg-error "expected ']'" } */
 
   return 0;
-} /* { dg-error "expected ';' before" } */
+} /* { dg-error "expected ';' before" "" { target c } } */
index 2e86b4f92daaddadc3e49d3ef1d62711e2ac9194..4314090f4269d6e35423164e811da874cdb91dc7 100644 (file)
@@ -5,7 +5,8 @@ int main (void)
 {
   int array[10][10], array2[10];
   
-  array2[:] = array2[1:2:] ;  /* { dg-error "expected expression before" } */
+  array2[:] = array2[1:2:] ;  /* { dg-error "expected expression before" "" { target c } } */ 
+  /* { dg-error  "expected primary-expression before" "" { target c++ } 8 } */
 
-  return 0; /* { dg-error "expected ';' before" } */
+  return 0; /* { dg-error "expected ';' before" "" { target c }  } */
 }
index 34dfa16dd8182b66e04979e2a6077da11901ffa8..47b597986742f15231d40cb1d47a7107d062ffd8 100644 (file)
@@ -5,7 +5,8 @@ int main (void)
 {
   int array[10][10], array2[10];
   
-  array2[:] = array2[1::] ;  /* { dg-error "expected expression before" } */
+  array2[:] = array2[1: :] ;  /* { dg-error "expected expression before" "" { target c }  } */ 
+  /* { dg-error "expected primary-expression before" "" { target c++ }  8 } */
 
-  return 0; /* { dg-error "expected ';' before" } */
+  return 0; /* { dg-error "expected ';' before" "" { target c } } */
 }
index eba28a81ce3840f690fff7fdf9aa56d5cbabe6a1..a0efc04d25e57690fa2ed347fba49e5ba084b6db 100644 (file)
@@ -5,7 +5,7 @@ int main (void)
 {
   int array[10][10], array2[10];
   
-  array2[:] = array2[::] ;  /* { dg-error " expected ']' before ':' token" } */
+  array2[:] = array2[ : : ] ;  /* { dg-error " expected ']' before ':' token" }  */
 
   return 0;
 }
index cabdb2376e61a8d583a78ecfa953d97a25f8de9b..9bff07991a93bcf434343a194cad80afa2ccbf5c 100755 (executable)
@@ -4,11 +4,14 @@
 int A[10];
 
 int main () {
-  char c = (char)N; /* { dg-error "undeclared" } */
+
+  /* C compiler uses the term "undeclared" whereas C++ compiler uses
+    "not declared".  Thus, grepping for declared seem to be the easiest.  */
+  char c = (char)N; /* { dg-error "declared" } */
   short s = (short)N;
   long l = (long)N;
   A[l:s:c];
 }
 
-/* { dg-message "note: each" "defined" { target *-*-* }  7 } */
+/* { dg-message "note: each" "defined" { target c }  10 } */
 
index 843745e384f47f810789a971ee5c822e862d7ea4..3b0777e0f3b25ef2d20fcdf90016c037470f208d 100644 (file)
@@ -1,5 +1,5 @@
-/* { dg-do compile } */
-/* { dg-options "-fcilkplus -std=c99" } */
+/* { dg-do compile { target c } } */
+/* { dg-options "-fcilkplus -std=c99 -w" } */
 
 int func (int x)
 {
diff --git a/gcc/testsuite/g++.dg/cilk-plus/AN/array_test1_tplt.cc b/gcc/testsuite/g++.dg/cilk-plus/AN/array_test1_tplt.cc
new file mode 100644 (file)
index 0000000..e9ee7ec
--- /dev/null
@@ -0,0 +1,118 @@
+/* { dg-do run } */
+/* { dg-options "-fcilkplus" } */
+
+#include <cstdlib>
+#include <string.h>
+#if HAVE_IO
+#include <cstdio>
+#endif
+template <class T> int main2 (char **argv);
+
+int main (void)
+{
+  int x = 1, y = 1, z = 1;
+  char *array[2];
+  array[0] = strdup ("a.out");
+  array[1] = strdup ("5");
+  x  = main2<unsigned char> (array);
+  x += main2<char> (array);
+  y  = main2<short> (array);
+  y += main2<unsigned short> (array);
+  y += main2<int> (array);
+  y += main2<unsigned int> (array);
+  z  = main2<long> (array);
+  z += main2<long long> (array);
+  y += main2<float> (array);
+  z += main2<double> (array);
+      
+  return x+y+z;
+}
+template <class T>
+int main2 (char **argv)
+{
+  T array[10];
+  int ii = 0, x = 2, z= 0 , y = 0;
+
+  for (ii = 0; ii < 10; ii++)
+    array[ii] = 10;
+
+  array[0:10:1] = (T)15;
+
+  for (ii = 0; ii < 10; ii++)
+    if (array[ii] != (T)15)
+      return 1;
+  
+
+  array[0:5:2] = (T)20;
+
+  for (ii = 0; ii < 10; ii += 2)
+    if (array[ii] != (T)20)
+      return 2;
+
+
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+
+  array[x:5:z] = (T)50;
+  
+  for (ii = x; ii < 10; ii += z)
+    if (array[ii] != (T)50)
+      return 3;
+
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]); /* (10 - 5) / 5 = 1 */
+  y = 10-atoi(argv[1]);
+  
+  array[x:y:z] = (T)52;
+#if HAVE_IO
+  for (ii = atoi ("5"); ii < (atoi ("5") + atoi ("5")); ii += atoi ("1"))
+    std::printf("%d\t", (int)array[ii]);
+  std::printf("\n");
+#endif
+  for (ii = x; ii < 10; ii += z)
+    if (array[ii] != (T)52)
+      return 4;
+    
+
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  y = 10-atoi(argv[1]);
+  
+  array[x:y:((10-atoi(argv[1]))/atoi(argv[1]))] = (T)25;
+
+  for (ii = x; ii < 10; ii += z)
+    if (array[ii] != (T)25)
+      return 5;
+  
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  y = 10-atoi(argv[1]);
+  array[atoi(argv[1]):(10-atoi(argv[1])):((10-atoi(argv[1]))/atoi(argv[1]))] =
+    (T)14;
+  for (ii = x; ii < 10; ii += z)
+    if (array[ii] != (T)14)
+      return 6;
+  
+
+  array[atoi("5"):5:1] = (T)65;
+  
+  for (ii = atoi ("5"); ii < 10; ii++)
+    if (array[ii] != (T)65)
+      return 7;
+  
+
+  array[atoi("5"):atoi("5"):atoi("1")] = 99;
+
+#if HAVE_IO
+  for (ii = atoi ("5"); ii < (atoi ("5") + atoi ("5")); ii += atoi ("1"))
+    std::printf("%d\t", (int)array[ii]);
+  std::printf("\n");
+#endif
+
+  for (ii = atoi ("5"); ii < (atoi ("5") + atoi ("5")); ii += atoi ("1"))
+    if (array[ii] != (T)99)
+      return 8;
+
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/AN/array_test2_tplt.cc b/gcc/testsuite/g++.dg/cilk-plus/AN/array_test2_tplt.cc
new file mode 100644 (file)
index 0000000..87c37e1
--- /dev/null
@@ -0,0 +1,141 @@
+/* { dg-do run } */
+/* { dg-options "-fcilkplus" } */
+
+#include <cstdlib>
+#include <string.h>
+template <class T> int main2(char **argv);
+int main(void)
+{
+  int x = 1, y = 1, z = 1, w = 1; 
+  char *array[2]; 
+  array[0] = strdup ("a.out"); 
+  array[1] = strdup ("5");
+  w  = main2<short>(array);
+  w += main2<unsigned short> (array);
+  x  = main2<char> (array);
+  x += main2<unsigned char> (array);
+  y  = main2<int> (array);
+  y += main2<unsigned int> (array);
+  z = main2<long> (array);
+  z += main2<unsigned long> (array);
+  z += main2<long long> (array);
+      
+  return (w+x+y+z);
+}
+
+template<class T>
+int main2(char **argv)
+{
+  T array[10], array2[10]; 
+  int  ii = 0, x = 2, z= 0 , y = 0 ;
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 10;
+      array2[ii] = 5000000;
+    }
+
+  array2[0:10:1] = array[0:10:1];
+
+  for (ii = 0; ii < 10; ii++)
+    if (array2[ii] != array[ii])
+      return 1; 
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 10;
+      array2[ii] = 5000000;
+    }
+  
+  array2[0:5:2] = array[0:5:2];
+
+  for (ii = 0; ii < 10; ii += 2)
+    if (array[ii] != array2[ii])
+      return 2;
+  
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 10;
+      array2[ii] = 5000000;
+    }
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  array2[x:5:z] = array[x:5:z];
+
+  for (ii = x; ii < 5; ii += z)
+    if (array2[ii] != array[ii])
+      return 3;
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 500;
+      array2[ii] = 1000000;
+    }
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  y = 10-atoi(argv[1]);
+
+  array2[x:y:z] = array[x:y:z];
+  for (ii = x; ii < 10; ii = ii + z)
+    if (array2[ii] != array[ii])
+      return 4;
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii]  = 500;
+      array2[ii] = 1000000;
+    }
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  y = 10-atoi(argv[1]);
+
+  array[x:y:((10-atoi(argv[1]))/atoi(argv[1]))] = 
+    array2[x:y:((10-atoi(argv[1]))/atoi(argv[1]))];
+
+  for (ii = x; ii < 10; ii += z)
+    if (array[ii] != array2[ii])
+      return 6;
+  
+  
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  y = 10-atoi(argv[1]);
+  
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii]  = 500;
+      array2[ii] = 1000000;
+    }
+  
+  array[atoi(argv[1]):(10-atoi(argv[1])):((10-atoi(argv[1]))/atoi(argv[1]))] =
+    array2[atoi(argv[1]):(10-atoi(argv[1])):((10-atoi(argv[1]))/atoi(argv[1]))];
+  for (ii = x; ii < 10; ii += z)
+    if (array[ii] != array2[ii])
+      return 6;
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii]  = 4;
+      array2[ii] = 2;
+    }
+
+  array[atoi("5"):5:1] = array2[atoi("5"):5:1];
+
+  for (ii = atoi ("5"); ii < 10; ii++)
+    if (array[ii] != array2[ii])
+      return 7;
+  
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii]  = 5;
+      array2[ii] = 1;
+    }
+  array[atoi("5"):atoi("5"):atoi("1")] = array2[atoi("5"):atoi("5"):atoi("1")];
+
+  for (ii = 5; ii < 10; ii++)
+    if (array2[ii] != array[ii])
+      return 8;
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/AN/array_test_ND_tplt.cc b/gcc/testsuite/g++.dg/cilk-plus/AN/array_test_ND_tplt.cc
new file mode 100644 (file)
index 0000000..479ba13
--- /dev/null
@@ -0,0 +1,115 @@
+/* { dg-do run } */
+/* { dg-options "-fcilkplus" } */
+
+#include <cstdlib>
+#include<string.h>
+template <class T> int main2(char **argv);
+
+int main(void)
+{
+  int x = 1, y=1, z=1, w = 1;
+  char *array[3];
+  array[0] = strdup ("a.out");
+  array[1] = strdup ("10");
+  array[2] = strdup ("15");
+  w  = main2<char> (array);
+  w += main2<unsigned char> (array);
+  x  = main2<int> (array);
+  x += main2<unsigned int> (array);
+  y  = main2<long> (array);
+  y += main2<unsigned long> (array);
+  z  = main2<short> (array);
+  z += main2<unsigned short> (array);
+  return x+y+z;
+}
+
+template <class T>
+int main2(char **argv)
+{  
+  T array[10][15];
+  T array_2[10][15];
+  int ii = 0, jj = 0,x = 0, z= 1 , y = 10 ,argc = 3;
+
+  for (ii = 0; ii < 10; ii++) {
+    for (jj = 0; jj< 15; jj++) {
+      array[ii][jj] = ii+jj;
+      array_2[ii][jj] = 0;
+    }
+  }
+  array_2[0:5:2][0:5:3] = array[0:5:2][0:5:3] + 1 + 5 + array[0][5] + x;
+
+  for (ii = 0; ii < 10; ii += 2)
+    {
+      for (jj = 0; jj < 15; jj += 3)
+       {
+         if (array_2[ii][jj] != array[ii][jj] + 1 + 5 + array[0][5] + x)
+           return 1;
+       }
+    }
+
+
+  for (ii = 0; ii < 10; ii++) {
+    for (jj = 0; jj< 15; jj++) {
+      array[ii][jj] = ii+jj;
+      array_2[ii][jj] = 0;
+    }
+  }
+  x = atoi(argv[1]);
+  y = atoi(argv[2]);
+  array_2[0:x:1][0:y:1] = array[0:x:1][0:y:1] + x + y + array[0:x:1][0:y:1];
+
+  for (ii = 0; ii < x; ii++)
+    {
+      for (jj = 0; jj < y; jj++)
+       {
+         if (array_2[ii][jj] != array[ii][jj] + x + y + array[ii][jj])
+           return 2;
+       }
+    }
+
+  for (ii = 0; ii < 10; ii++) {
+    for (jj = 0; jj< 15; jj++) {
+      array[ii][jj] = ii+jj;
+      array_2[ii][jj] = 0;
+    }
+  }
+  x = atoi(argv[1]);
+  y = atoi(argv[2]);
+  z = (20- atoi (argv[1]))/atoi(argv[1]);
+  /* (20-10)/10 evaluates to 1 all the time :-). */
+  array_2[0:x:z][0:y:z] = array[0:x:z][0:y:z] + array[0:x:z][0:y:z] + y + z;
+  
+  for (ii = 0; ii < x; ii += z)
+    {
+      for (jj = 0; jj < y; jj += z)
+       {
+         if (array_2[ii][jj] != array[ii][jj] + array[ii][jj] + y + z)
+           return 3;
+       }
+    }
+
+
+  for (ii = 0; ii < 10; ii++) {
+    for (jj = 0; jj< 15; jj++) {
+      array[ii][jj] = ii+jj;
+      array_2[ii][jj] = 0;
+    }
+  }
+  x = argc-3;
+  y = 20-atoi(argv[1]);
+  z = (20- atoi (argv[1]))/atoi(argv[1]);
+  /* (20-10)/10 evaluates to 1 all the time :-). */
+  array_2[(argc-3):(20-atoi(argv[1])):(20-atoi(argv[1]))/atoi(argv[1])][(argc-3):(30-atoi(argv[2])): ((30-atoi(argv[2]))/atoi(argv[2]))] = array[(argc-3):20-atoi(argv[1]):(20-atoi(argv[1]))/atoi(argv[1])][(argc-3):(30-atoi(argv[2])): (30-atoi(argv[2]))/atoi(argv[2])] + array[(argc-3):20-atoi(argv[1]):(20-atoi(argv[1]))/atoi(argv[1])][(argc-3):(30-atoi(argv[2])): (30-atoi(argv[2]))/atoi(argv[2])] * array[(argc-3):20-atoi(argv[1]):(20-atoi(argv[1]))/atoi(argv[1])][(argc-3):(30-atoi(argv[2])): (30-atoi(argv[2]))/atoi(argv[2])];
+  
+  for (ii = 0; ii < 10; ii++)
+    {
+      for (jj = 0; jj < 15; jj++)
+       {
+         if (array_2[ii][jj] != array[ii][jj] + array[ii][jj] * array[ii][jj])
+           return 4;
+       }
+    }
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/AN/braced_list.cc b/gcc/testsuite/g++.dg/cilk-plus/AN/braced_list.cc
new file mode 100644 (file)
index 0000000..b91de7a
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus -std=c++11 " } */
+
+int main (void)
+{
+  int Array[100], Array2[100];
+
+  Array[{1,2}:2] = 5; /* { dg-error "braced list index is not allowed" } */
+  Array[1:{1,2}:2] = 5; /* { dg-error "expected primary-expression before" } */
+  Array[1:10:{1,2}] = 5; /* { dg-error "expected primary-expression before" } */
+
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_custom_tplt.cc b/gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_custom_tplt.cc
new file mode 100644 (file)
index 0000000..3d9e87b
--- /dev/null
@@ -0,0 +1,126 @@
+/* { dg-do run } */
+/* { dg-options "-fcilkplus " } */
+
+#if HAVE_IO 
+#include <cstdio>
+#endif
+
+#include <cstdlib>
+
+template <class T>
+T my_func (T x, T y)
+{
+  if (x > y)
+    return x;
+  else
+    return y;
+}
+
+template <class T>
+T main_func (T  *array, T *array2, T identity_val, int size)
+{
+  T result;
+
+  result = __sec_reduce (identity_val, array[0:size:1] * array2[0:size:1],
+                        my_func); // my_func (identity_val, array[5] * array2[5]);
+  return result;
+}
+int main (void)
+{
+  int    i_index = 0, f_index = 0, d_index = 0, l_index = 0;
+  int    iarray[10], iarray2[10], i_result, i_max;
+  long   larray[10], larray2[10], l_result, l_max;
+  float  farray[10], farray2[10], f_result, f_max;
+  double darray[10], darray2[10], d_result, d_max;
+  for (int ii = 0; ii < 10; ii++)
+    {
+      if (ii%2 && ii)
+       {
+         darray[ii] = (double)(1.0000/(double)ii);
+         farray[ii] = (float)(1.00/(float)ii);
+       }
+      else
+       {
+         darray[ii] = (double) ii + 0.10;
+         farray[ii] = (float) (1.00/((float)(ii+1.000)));
+       }
+      darray2[ii] = (double) (1.00000/ (double)(ii+1));
+      farray2[ii] = (float) (1.00/ (float)(ii+1));
+    }
+
+  for (int ii = 0; ii < 10; ii++)
+    {
+      iarray[ii] = ii;
+      larray[ii] = (long)ii;
+    }
+
+  for (int ii = 0; ii < 10; ii++)
+    {
+      iarray2[ii] = (ii-5);
+      larray2[ii] = long (ii-5);
+    }
+#if HAVE_IO
+  printf("Int: ");
+  for (int ii=0; ii < 10; ii++)
+    {
+      printf("%2d ", iarray[ii] * iarray2[ii]);
+    }
+  printf("\nfloat: ");
+  for (int ii=0; ii < 10; ii++)
+    {
+      printf("%4.3f ", farray[ii] * farray2[ii]);
+    }
+
+  printf("\nlong: ");
+  for (int ii=0; ii < 10; ii++)
+    {
+      printf("%2d ", larray[ii] * larray2[ii]);
+    }
+
+  printf("\ndouble: ");
+  for (int ii=0; ii < 10; ii++)
+    {
+      printf("%4.3f ", (float) (darray[ii] * darray2[ii]));
+    }
+  printf("\n");
+#endif
+
+  i_result = main_func<int> (iarray, iarray2, iarray[0] * iarray2[0], 10);
+  f_result = main_func<float>(farray, farray2, 0.00, 10);
+  d_result = main_func<double>(darray, darray2, 0.0000, 10);
+  l_result = main_func<long>(larray, larray2, 0, 10);
+
+#if HAVE_IO
+  printf("int result    = %2d\n", i_result);
+  printf ("long result   = %2d\n", l_result);
+  printf("float result  = %4.3f\n", f_result);
+  printf("double result = %4.3lf\n", d_result);
+#endif
+    
+  i_max = iarray[0] * iarray2[0];
+  f_max = farray[0] * farray2[0];
+  d_max = darray[0] * darray2[0];
+  l_max = larray[0] * larray2[0];
+  for (int ii = 0; ii < 10; ii++)
+    {
+      if (i_max < iarray[ii] * iarray2[ii])
+       i_max = iarray[ii] * iarray2[ii];
+      if (f_max < farray[ii] * farray2[ii])
+       f_max = farray[ii] * farray2[ii];
+      if (d_max < darray[ii] * darray2[ii])
+       d_max = darray[ii] * darray2[ii];
+      if (l_max < larray[ii] * larray2[ii])
+       l_max = larray[ii] * larray2[ii];
+    }
+
+  if (i_max != i_result)
+    return 1;
+  if (f_max != f_result)
+    return 2;
+  if (d_max != d_result)
+    return 3;
+  if (l_max != l_result)
+    return 4;
+  return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_mutating_tplt.cc b/gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_mutating_tplt.cc
new file mode 100644 (file)
index 0000000..db81912
--- /dev/null
@@ -0,0 +1,134 @@
+/* { dg-do run } */
+/* { dg-options "-fcilkplus" }  */
+
+#if HAVE_IO 
+#include <cstdio>
+#include<iostream>
+#endif
+
+#include <cstdlib>
+
+template <class T>
+T my_func (T *x, T y)
+{
+  if (*x < y)
+    *x = y;
+  else
+    *x = *x;
+}
+
+template <class T> T my_func (T *x, T y);
+template <class T>
+T main_func (T  *array, T *array2, T identity_val, int size)
+{
+  T result = identity_val;
+  
+  __sec_reduce_mutating (&result, array[0:size] * array2[0:size:1], my_func);
+  
+#if HAVE_IO
+  std::cout << "Result = " << result << std::endl;
+#endif
+  return result;
+}
+
+int main (void)
+{
+  int    iarray[10], iarray2[10], i_result = 0, i_max;
+  long   larray[10], larray2[10], l_result = 0, l_max;
+  float  farray[10], farray2[10], f_result = 0, f_max;
+  double darray[10], darray2[10], d_result = 0, d_max;
+  for (int ii = 0; ii < 10; ii++)
+    {
+      if (ii%2 && ii)
+       {
+         darray[ii] = (double)(1.0000/(double)(ii));
+         farray[ii] = (float)(1.00/(float)(ii));
+       }
+      else
+       {
+         darray[ii] = (double) ii + 0.10;
+         farray[ii] = (float) (1.00/((float)(ii) + 0.10));
+       }
+      darray2[ii] = (double) (1.00000/ (double)(ii+1));
+      farray2[ii] = (float) (1.00/ (float)(ii+1));
+    }
+
+  for (int ii = 0; ii < 10; ii++)
+    {
+      iarray[ii] = ii;
+      larray[ii] = (long)ii;
+    }
+
+  for (int ii = 0; ii < 10; ii++)
+    {
+      iarray2[ii] = (ii-5);
+      larray2[ii] = (long)ii-5;
+    }
+#if HAVE_IO
+  printf("\nInt: ");
+  for (int ii=0; ii < 10; ii++)
+    {
+      printf("%2d ", iarray[ii] * iarray2[ii]);
+    }
+  printf("\nfloat: ");
+  for (int ii=0; ii < 10; ii++)
+    {
+      printf("%3.2f ", farray[ii] * farray2[ii]);
+    }
+
+  printf("\nlong: ");
+  for (int ii=0; ii < 10; ii++)
+    {
+      printf("%2d ", larray[ii] * larray2[ii]);
+    }
+
+  printf("\ndouble: ");
+  for (int ii=0; ii < 10; ii++)
+    {
+      printf("%4.3lf ", (float) (darray[ii] * darray2[ii]));
+    }
+  printf("\n");
+#endif
+
+  i_result = main_func<int> (iarray, iarray2, 0, 10);
+  l_result = main_func<long>(larray, larray2, 0, 10);
+  f_result = main_func<float>(farray, farray2, 0.00, 10);
+  d_result = main_func<double>(darray, darray2, 0.0000, 10);
+  
+  i_max = iarray[0] * iarray2[0];
+  d_max = darray[0] * darray2[0];
+  f_max = farray[0] * farray2[0];
+  l_max = larray[0] * larray2[0];
+  for (int ii = 0; ii < 10; ii++)
+    {
+      if (iarray[ii] * iarray2[ii] > i_max)
+       i_max = iarray[ii] * iarray2[ii];
+      if (darray[ii] * darray2[ii] > d_max)
+       d_max = darray[ii] * darray2[ii];
+      if (farray[ii] * farray2[ii] > f_max)
+       f_max = farray[ii] * farray2[ii];
+      if (larray[ii] * larray2[ii] > l_max)
+       l_max = larray[ii] * larray2[ii];
+    }
+#if HAVE_IO
+  printf("int result    = %2d\n", i_max);
+  printf("long result   = %2d\n", l_max);
+  printf("float result  = %4.3f\n", f_max);
+  printf("double result = %4.3lf\n", (float)d_max);
+#endif
+  
+ if (i_max != i_result)
+   return 1;
+
+ if (f_max != f_result)
+   return 2;
+
+ if (l_max != l_result)
+   return 3;
+
+ if (d_max != d_result)
+   return 4;
+  return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/cilk-plus/AN/fp_triplet_values_tplt.c b/gcc/testsuite/g++.dg/cilk-plus/AN/fp_triplet_values_tplt.c
new file mode 100644 (file)
index 0000000..1387558
--- /dev/null
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus" } */
+
+float q;
+
+void func (int *x)
+{
+  *x = 5;
+}
+template <class T> int main2 (T x, T y, T z);
+
+int main (void)
+{
+  main2 <float> (1.5, 2.3, 3.443);
+  main2 <double> (1.34393, 2.38383, 4.38383);
+  return 0;
+}
+template <class T> 
+int main2 (T x, T y, T z)
+{
+  int array[10], array2[10];
+  array2[:] = array[x:2]; /* { dg-error "start-index of array notation triplet is not an integer" } */
+  array2[:] = array[1:y]; /* { dg-error "length of array notation triplet is not an integer" } */
+  array2[1:2:z] = array[:]; /* { dg-error "stride of array notation triplet is not an integer" } */
+  func (&array2[1:x:3]); /* { dg-error "length of array notation triplet is not an integer" } */
+  array2[y:9]++; /* { dg-error "start-index of array notation triplet is not an integer" } */
+  array2[1:x]++; /* { dg-error "length of array notation triplet is not an integer" } */
+  array2[1:9:x]++; /* { dg-error "stride of array notation triplet is not an integer" } */
+  
+  ++array2[1:q:3]; /* { dg-error "length of array notation triplet is not an integer" } */
+  array2[:] = array[q:1:3]; /* { dg-error "start-index of array notation triplet is not an integer" } */
+  array2[:] = array[1:q:3]; /* { dg-error "length of array notation triplet is not an integer" } */
+  array2[:] = array[1:3:q]; /* { dg-error "stride of array notation triplet is not an integer" } */
+  func (&array2[1:q:3]); /* { dg-error "length of array notation triplet is not an integer" } */
+  return 0;
+} 
diff --git a/gcc/testsuite/g++.dg/cilk-plus/AN/postincr_test.cc b/gcc/testsuite/g++.dg/cilk-plus/AN/postincr_test.cc
new file mode 100644 (file)
index 0000000..b0952c7
--- /dev/null
@@ -0,0 +1,107 @@
+/* { dg-do run } */
+/* { dg-options "-fcilkplus" } */
+
+#define HAVE_IO 0
+
+#if HAVE_IO
+#include <cstdio>
+#endif
+
+#include <cstdlib>
+template <class T> int main2(int argc);
+
+int main (void)
+{
+    return (main2<int>(1) + main2<long> (1) + main2<long long> (1));
+}
+
+#if HAVE_IO
+template <class T> int print_array (T *array, int size);
+template <class T> int print_array (T *array, int size)
+{
+    for (int ii = 0; ii < size; ii++)
+          printf("%d ", array[ii]);
+      printf("\n");
+        return 0;
+}
+#endif
+
+template <class T>
+int main2(int argc)
+{
+  T array[10], array_serial[10];
+
+  for (int ii = 0; ii < 10; ii++) {
+    array[ii] = 0;
+    array_serial[ii] = 0;
+  }
+
+  array[:] = 19383;
+  for (int ii = 0; ii < 10; ii++)
+    array_serial[ii] = 19383;
+
+  array[:]++;
+  
+  for (int ii = 0; ii < 10; ii++)
+    array_serial[ii]++;
+
+#if HAVE_IO
+  print_array<T>(array, 10);
+  print_array<T>(array_serial, 10);
+#endif
+
+  for (int ii  = 0; ii < 10; ii++)
+    if (array_serial[ii] != array[ii])
+      return 1;
+
+  for (int ii = 0; ii < 10; ii++)
+    array[:]++;
+
+  for (int ii = 0; ii < 10; ii++)
+    for (int jj = 0; jj < 10; jj++)
+      array_serial[jj]++;
+
+#if HAVE_IO
+  print_array<T>(array, 10);
+  print_array<T>(array_serial, 10);
+#endif
+
+  for (int ii  = 0; ii < 10; ii++)
+    if (array_serial[ii] != array[ii])
+      return 2;
+
+  if (argc == 2)
+    array[0:10:1]++; 
+  
+  if (argc == 2)
+    {
+      for (int ii = 0; ii < 10; ii++)
+       array_serial[ii]++;
+    }
+
+#if HAVE_IO
+  print_array<T>(array, 10);
+  print_array<T>(array_serial, 10);
+#endif
+
+  for (int ii  = 0; ii < 10; ii++)
+    if (array_serial[ii] != array[ii])
+      return 3;
+
+  array[0:10/argc:argc]++; 
+  
+  for (int ii = 0; ii < 10; ii += argc) 
+    array_serial[ii]++;
+
+
+  for (int ii  = 0; ii < 10; ii++)
+    if (array_serial[ii] != array[ii])
+      return 4;
+
+#if HAVE_IO
+  print_array<T>(array, 10);
+  print_array<T>(array_serial, 10);
+#endif
+
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/AN/preincr_test.cc b/gcc/testsuite/g++.dg/cilk-plus/AN/preincr_test.cc
new file mode 100644 (file)
index 0000000..f5552c7
--- /dev/null
@@ -0,0 +1,106 @@
+/* { dg-do run } */
+/* { dg-options "-fcilkplus" } */
+
+
+#define HAVE_IO 0
+
+#if HAVE_IO
+#include <cstdio>
+#endif
+
+#include <cstdlib>
+template <class T> int main2(int argc);
+
+int main (void)
+{ 
+  return (main2<int>(1) + main2<long> (1) + main2<long long> (1));
+}
+
+#if HAVE_IO
+template <class T> int print_array (T *array, int size);
+template <class T> int print_array (T *array, int size)
+{
+      for (int ii = 0; ii < size; ii++) 
+       printf("%d ", array[ii]); 
+      printf("\n"); 
+      return 0;
+}
+#endif
+
+template <class T>
+int main2(int argc)
+{
+  int array[10], array_serial[10];
+
+  for (int ii = 0; ii < 10; ii++) {
+    array[ii] = 0;
+    array_serial[ii] = 0;
+  }
+
+  array[:] = 19383;
+  for (int ii = 0; ii < 10; ii++) 
+    array_serial[ii] = 19383;
+
+  ++array[:];
+
+  for (int ii = 0; ii < 10; ii++)
+    ++array_serial[ii];
+
+#if HAVE_IO
+  print_array<T>(array, 10);
+  print_array<T>(array_serial, 10);
+#endif
+  for (int ii = 0; ii < 10; ii++)
+    if (array_serial[ii] != array[ii])
+      return 1;
+
+  for (int ii = 0; ii < 10; ii++)
+    ++array[:];
+
+  for (int ii = 0; ii < 10; ii++)
+    for (int jj = 0; jj < 10; jj++)
+      ++array_serial[jj];
+
+#if HAVE_IO
+  print_array<T>(array, 10);
+  print_array<T>(array_serial, 10);
+#endif
+  for (int ii = 0; ii < 10; ii++)
+    if (array_serial[ii] != array[ii])
+      return 2;
+
+  if (argc == 2)
+    ++array[0:10:1]; 
+
+  if (argc == 2)
+    {
+      for (int ii = 0; ii < 10; ii++)
+       ++array_serial[ii];
+    }
+
+#if HAVE_IO
+  print_array<T>(array, 10);
+  print_array<T>(array_serial, 10);
+#endif
+  for (int ii = 0; ii < 10; ii++)
+    if (array_serial[ii] != array[ii])
+      return 3;
+
+  ++array[0:10/argc:argc]; 
+  
+  for (int ii = 0; ii < 10; ii += argc)
+    {
+      ++array_serial[ii];
+    }
+
+#if HAVE_IO
+  print_array<T>(array, 10);
+  print_array<T>(array_serial, 10);
+#endif
+
+  for (int ii = 0; ii < 10; ii++)
+    if (array_serial[ii] != array[ii])
+      return 4;
+
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp b/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp
new file mode 100644 (file)
index 0000000..a153529
--- /dev/null
@@ -0,0 +1,48 @@
+#   Copyright (C) 2013 Free Software Foundation, Inc.
+
+# This program 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 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or 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 COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+# Written by Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+
+load_lib g++-dg.exp
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O0 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O1 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O2 -ftree-vectorize -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O3 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -g -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -g -O0 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -g -O1 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -g -O2 -ftree-vectorize -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -g -O3 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O3 -ftree-vectorize -fcilkplus -g" " "
+dg-finish
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -O0 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -O1 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -O2 -ftree-vectorize -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -O3 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -g -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -g -O0 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -g -O1 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -g -O2 -ftree-vectorize -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -g -O3 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -O3 -ftree-vectorize -fcilkplus -g" " "
+dg-finish
index 720135942bbf633bd5b356ac67579193147da1eb..710218e67c5f206f8992e9d52650f65099ca1151 100644 (file)
@@ -33,6 +33,7 @@ dg-init
 set tests [lsort [find $srcdir/$subdir *.C]]
 set tests [prune $tests $srcdir/$subdir/bprob/*]
 set tests [prune $tests $srcdir/$subdir/charset/*]
+set tests [prune $tests $srcdir/$subdir/cilk-plus/AN/*]
 set tests [prune $tests $srcdir/$subdir/compat/*]
 set tests [prune $tests $srcdir/$subdir/debug/*]
 set tests [prune $tests $srcdir/$subdir/dfp/*]