public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Cilk Plus Array Notation for C++
@ 2013-06-10 20:21 Iyer, Balaji V
  2013-06-12 16:34 ` Aldy Hernandez
  0 siblings, 1 reply; 40+ messages in thread
From: Iyer, Balaji V @ 2013-06-10 20:21 UTC (permalink / raw)
  To: gcc-patches
  Cc: Jason Merrill (jason@redhat.com), rth, Aldy Hernandez (aldyh@redhat.com)

[-- Attachment #1: Type: text/plain, Size: 4768 bytes --]

Hello Everyone,
	Attached, please find a patch that will implement Cilk Plus Array Notation for C++. This patch is a follow-up of the Array notation for C patch (i.e. there are several helper functions that are shared between the two). 
I have tested this on x86 and x86_64 and it seem to work OK and pass all the regression tests. The patch does not affect the status (i.e. PASS or FAIL) of any other tests. 

Here are the ChangeLog entries:

gcc/cp/ChangeLog
2013-06-10  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-10  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/sec_implicit_ex.c (main): Removed the usage
        of abort and exit and replaced them with return 1 and return 0.
        * 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/cilk-plus.exp: New script.
        * g++.dg/dg.exp: Included Cilk Plus C++ tests in the list.

Thanks,

Balaji V. Iyer. 

[-- Attachment #2: patch_array_notation_cpp.txt --]
[-- Type: text/plain, Size: 158155 bytes --]

diff --git gcc/cp/ChangeLog gcc/cp/ChangeLog
old mode 100644
new mode 100755
index c0977c3d..4ecae05
Binary files gcc/cp/ChangeLog and gcc/cp/ChangeLog differ
diff --git gcc/cp/Make-lang.in gcc/cp/Make-lang.in
index df8ed3e..6e80bcf 100644
--- gcc/cp/Make-lang.in
+++ gcc/cp/Make-lang.in
@@ -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)
diff --git gcc/cp/call.c gcc/cp/call.c
index dfd061a..a3d7d2d 100644
--- gcc/cp/call.c
+++ gcc/cp/call.c
@@ -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,21 @@ 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 we do not
+	 need to do any type conversion.  */
+      if (flag_enable_cilkplus && fn && TREE_CODE (fn) == FUNCTION_DECL
+	  && DECL_NAME (fn) && IDENTIFIER_POINTER (DECL_NAME (fn))
+	  && !strncmp (IDENTIFIER_POINTER (DECL_NAME (fn)), "__sec_reduce", 12))
+	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 gcc/cp/cp-array-notation.c gcc/cp/cp-array-notation.c
new file mode 100755
index 0000000..e8a5a51
--- /dev/null
+++ gcc/cp/cp-array-notation.c
@@ -0,0 +1,2844 @@
+/* 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);
+}
+
+/* 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;
+}
+
+/* Returns true of NODE has a call_expression with ARRAY_NOTATION_REF tree.  */
+
+static bool
+has_call_expr_with_array_notation (tree node)
+{
+  int ii = 0;
+  
+  if (!contains_array_notation_expr (node))
+    return false;
+  
+  if (TREE_CODE (node) == ARRAY_NOTATION_REF)
+    return false;
+  else if (TREE_CODE (node) == DECL_EXPR)
+    {
+      tree x = DECL_EXPR_DECL (node);
+      if (x && TREE_CODE (x) != FUNCTION_DECL)
+	if (DECL_INITIAL (x))
+	  return has_call_expr_with_array_notation (DECL_INITIAL (x));
+	
+    }
+  else if (TREE_CODE (node) == STATEMENT_LIST)
+    {
+      tree_stmt_iterator ii_tsi;
+      for (ii_tsi = tsi_start (node); !tsi_end_p (ii_tsi); tsi_next (&ii_tsi))
+	return has_call_expr_with_array_notation (*tsi_stmt_ptr (ii_tsi));
+    }
+  else if (TREE_CODE (node) == CALL_EXPR)
+    {
+      if (is_cilkplus_reduce_builtin (CALL_EXPR_FN (node)) != BUILT_IN_NONE)
+	return true;
+	
+      if (is_sec_implicit_index_fn (CALL_EXPR_FN (node)))
+	return true;
+	 
+      if (TREE_CODE (TREE_OPERAND (node, 0)) == INTEGER_CST)
+	{
+	  int length = TREE_INT_CST_LOW (TREE_OPERAND (node, 0));
+	  bool x = false;
+	  for (ii = 0; ii < length; ii++)
+	    x |= contains_array_notation_expr (TREE_OPERAND (node, ii));
+	  return x;
+	}
+      else
+	gcc_unreachable  ();	  
+    } 
+  else
+    {
+      bool x = false;
+      for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (node)); ii++) 
+	x |= has_call_expr_with_array_notation (TREE_OPERAND (node, ii));
+      return x;
+    }
+  return false;
+}
+
+/* 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
+fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
+{
+  tree new_var_type = NULL_TREE, func_parm, new_expr, 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; 
+  tree new_var_init = NULL_TREE, new_exp_init = NULL_TREE;
+  vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
+  int s_jj = 0;
+  size_t list_size = 0, rank = 0, ii = 0, jj = 0;
+  tree **array_ops, *array_var, jj_tree;
+  tree **array_value, **array_stride, **array_length, **array_start;
+  tree  body, an_init, loop_with_init = alloc_stmt_list ();
+  tree *compare_expr, array_op0, *expr_incr, *ind_init, comp_node;
+  tree call_fn = NULL_TREE, identity_value = NULL_TREE, new_call_expr;
+  bool **count_down, **array_vector;
+  tree begin_var, lngth_var, strde_var;
+  location_t location = UNKNOWN_LOCATION;
+  tsubst_flags_t complain = tf_warning_or_error;
+
+  enum built_in_function an_type =
+    is_cilkplus_reduce_builtin (CALL_EXPR_FN (an_builtin_fn));
+  
+  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!  */
+      while (TREE_CODE (call_fn) == CONVERT_EXPR
+	     || TREE_CODE (call_fn) == NOP_EXPR)
+	call_fn = TREE_OPERAND (call_fn, 0);
+
+      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);
+
+      /* 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!  */
+      while (TREE_CODE (identity_value) == CONVERT_EXPR
+	     || TREE_CODE (identity_value) == NOP_EXPR)
+	identity_value = TREE_OPERAND (identity_value, 0);
+    }
+
+  while (TREE_CODE (func_parm) == CONVERT_EXPR
+	 || TREE_CODE (func_parm) == NOP_EXPR)
+    func_parm = TREE_OPERAND (func_parm, 0);
+  
+  location = EXPR_LOCATION (an_builtin_fn);
+  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);
+  
+  array_ops = XNEWVEC (tree *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_ops[ii] = XNEWVEC (tree,  rank);
+  
+  array_vector = XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_vector[ii] = XNEWVEC (bool, rank);
+
+  array_value =  XNEWVEC (tree *, list_size);
+  array_stride =  XNEWVEC (tree *, list_size);
+  array_length =  XNEWVEC (tree *, list_size);
+  array_start =  XNEWVEC (tree *, list_size);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      array_value[ii]  = XNEWVEC (tree, rank);
+      array_stride[ii] = XNEWVEC (tree, rank);
+      array_length[ii] = XNEWVEC (tree, rank);
+      array_start[ii]  = XNEWVEC (tree, rank);
+    }
+
+  compare_expr = XNEWVEC (tree, rank);
+  expr_incr = XNEWVEC (tree, rank);
+  ind_init = XNEWVEC (tree, rank);
+  
+  count_down = XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    count_down[ii] = XNEWVEC (bool, rank);
+  
+  array_var = XNEWVEC (tree, 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];
+      tree array_begin = ARRAY_NOTATION_START (array_node);
+      tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
+      tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
+      if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF)
+	{
+	  if (TREE_CODE (array_begin) != INTEGER_CST)
+	    {
+	      begin_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, begin_var,
+						     NOP_EXPR, array_begin,
+						     complain));
+	      ARRAY_NOTATION_START (array_node) = begin_var;
+	    }
+	  if (TREE_CODE (array_lngth) != INTEGER_CST)
+	    {
+	      lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, lngth_var,
+						     NOP_EXPR, array_lngth,
+						     complain));
+	      ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
+	    }
+	  if (TREE_CODE (array_strde) != INTEGER_CST)
+	    {
+	      strde_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, strde_var,
+						     NOP_EXPR, array_strde,
+						     complain));
+	      ARRAY_NOTATION_STRIDE (array_node) = strde_var;
+	    }
+	}
+    }
+  for (ii = 0; ii < list_size; ii++)
+    {
+      jj = 0;
+      jj_tree = (*array_list)[ii];
+      while (jj_tree)
+	{
+	  if (TREE_CODE (jj_tree) == ARRAY_NOTATION_REF)
+	    {
+	      array_ops[ii][jj] = jj_tree;
+	      jj++;
+	      jj_tree = ARRAY_NOTATION_ARRAY (jj_tree);
+	    }
+	  else if (TREE_CODE (jj_tree) == ARRAY_REF)
+	    jj_tree = TREE_OPERAND (jj_tree, 0);
+	  else if (TREE_CODE (jj_tree) == VAR_DECL
+		   || TREE_CODE (jj_tree) == PARM_DECL)
+	    break;
+	}
+    }
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      if (TREE_CODE ((*array_list)[ii]) == ARRAY_NOTATION_REF)
+	for (jj = 0; jj < rank; jj++)
+	  {
+	    if (TREE_CODE (array_ops[ii][jj]) == ARRAY_NOTATION_REF)
+	      {
+		array_value[ii][jj] =
+		  ARRAY_NOTATION_ARRAY (array_ops[ii][jj]);
+		array_start[ii][jj] =
+		  ARRAY_NOTATION_START (array_ops[ii][jj]);
+		array_length[ii][jj] =
+		  fold_build1 (CONVERT_EXPR, integer_type_node,
+			       ARRAY_NOTATION_LENGTH (array_ops[ii][jj]));
+		array_stride[ii][jj] =
+		  ARRAY_NOTATION_STRIDE (array_ops[ii][jj]);
+		array_vector[ii][jj] = true;
+
+		if (!TREE_CONSTANT (array_length[ii][jj])
+		    || TREE_CODE (array_length[ii][jj]) != INTEGER_TYPE)
+		  count_down[ii][jj] = false;
+		else if (tree_int_cst_sgn (array_length[ii][jj]) == -1)
+		  count_down[ii][jj] = true;
+		else
+		  count_down[ii][jj] = false;
+	      }
+	    else
+	      array_vector[ii][jj] = false;
+	  }
+    }
+
+  for (ii = 0; ii < rank; ii++)
+    {
+      array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
+				  TREE_TYPE (array_start[0][ii]));
+      ind_init[ii] = build_x_modify_expr
+	(location, array_var[ii], NOP_EXPR, 
+	 build_zero_cst (TREE_TYPE (array_var[ii])), tf_warning_or_error);
+    }
+  for (ii = 0; ii < list_size; ii++)
+    if (array_vector[ii][0])
+      {
+	tree array_opr = array_value[ii][rank - 1];
+	for (s_jj = rank - 1; s_jj >= 0; s_jj--)
+	  {
+	    tree stride = NULL_TREE, var = NULL_TREE, start = NULL_TREE;
+
+	    /* If stride and start are of same type and the induction var
+	       is not, we convert induction variable to stride's type.  */
+	    if ((TREE_TYPE (array_start[ii][s_jj]) ==
+		 TREE_TYPE (array_stride[ii][s_jj]))
+		&& (TREE_TYPE (array_stride[ii][s_jj]) !=
+		    TREE_TYPE (array_var[s_jj])))
+	      {
+		start = array_start[ii][s_jj];
+		stride = array_stride[ii][s_jj];
+		var =
+		  build_c_cast (location, TREE_TYPE (array_stride[ii][s_jj]),
+				array_var[s_jj]);
+	      }
+	    else if (TREE_TYPE (array_start[ii][s_jj]) !=
+		     TREE_TYPE (array_stride[ii][s_jj]))
+	      {
+		/* 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, we stay safe and convert
+		   everything to integer.  The reason why we pick integer
+		   instead of something like size_t is because the stride
+		   and length can be + or -.  */
+		start = build_c_cast (location, integer_type_node,
+				      array_start[ii][s_jj]);
+		stride = build_c_cast (location, integer_type_node,
+				       array_stride[ii][s_jj]);
+		var = build_c_cast (location, integer_type_node,
+				    array_var[s_jj]);
+	      }
+	    else
+	      {
+		start = array_start[ii][s_jj];
+		stride = array_stride[ii][s_jj];
+		var = array_var[s_jj];
+	      }
+	    if (count_down[ii][s_jj])
+	      /* Array[start_index - (induction_var * stride)].  */
+	      array_opr = grok_array_decl
+		(location, array_opr,
+		 build2 (MINUS_EXPR, TREE_TYPE (var), start,
+			 build2 (MULT_EXPR, TREE_TYPE (var), var, stride)),
+		 false);	
+	    else
+	      /* Array[start_index + (induction_var * stride)].  */
+	      array_opr = grok_array_decl
+		(location, array_opr,
+		 build2 (PLUS_EXPR, TREE_TYPE (var), start,
+			 build2 (MULT_EXPR, TREE_TYPE (var), var, stride)),
+		 false);
+	  }
+	vec_safe_push (array_operand, array_opr);
+      }
+    else
+      vec_safe_push (array_operand, integer_one_node);
+    
+  replace_array_notations (&func_parm, true, array_list, array_operand);
+  
+  if (!TREE_TYPE (func_parm))      
+    TREE_TYPE (func_parm) = TREE_TYPE ((*array_list)[0]);
+  
+  for (ii = 0; ii < rank; ii++)
+    if (count_down[0][ii])
+      expr_incr[ii] = build_x_unary_op (location, POSTDECREMENT_EXPR,
+					array_var[ii], tf_warning_or_error);
+    else
+      expr_incr[ii] = build_x_unary_op (location, POSTINCREMENT_EXPR,
+					array_var[ii], tf_warning_or_error);
+  
+  for (jj = 0; jj < rank; jj++)
+    if (rank && expr_incr[jj])
+      {
+	if (count_down[0][jj])
+	  compare_expr[jj] = build_x_binary_op
+	    (location, GT_EXPR, array_var[jj], TREE_CODE (array_var[jj]),
+	     array_length[0][jj], TREE_CODE (array_length[0][jj]), NULL,
+	     tf_warning_or_error);
+	else
+	  compare_expr[jj] = build_x_binary_op
+	    (location, LT_EXPR, array_var[jj], TREE_CODE (array_var[jj]),
+	     array_length[0][jj], TREE_CODE (array_length[0][jj]), NULL,
+	     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 a 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];
+  if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ADD)
+    {
+      if (ARITHMETIC_TYPE_P (new_var_type))
+	new_var_init = build_x_modify_expr (location, *new_var, 
+					    NOP_EXPR,
+					    build_zero_cst (new_var_type), 1);
+      else
+	new_var_init = build_x_modify_expr (location, *new_var, 
+					    NOP_EXPR,
+					    integer_zero_node, 1);
+      new_expr = build_x_modify_expr (location, *new_var, PLUS_EXPR, 
+				      func_parm, 1);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MUL)
+    {
+      if (ARITHMETIC_TYPE_P (new_var_type))
+	new_var_init = build_x_modify_expr (location, *new_var, 
+					    NOP_EXPR,
+					    build_one_cst (new_var_type), 1);
+      else
+	new_var_init = build_x_modify_expr (location, *new_var, 
+					    NOP_EXPR,
+					    integer_one_node, 1);
+      new_expr = build_x_modify_expr (location, *new_var, MULT_EXPR, 
+				      func_parm, 1);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO)
+    {
+      new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  build_one_cst (new_var_type), 1);
+      /* Initially you assume everything is zero, now if we find a case where
+	 it is NOT true, then we set the result to false. Otherwise we just
+	 keep the previous value.  */
+      new_yes_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  build_zero_cst (new_var_type), 1);
+      new_no_expr = build_x_modify_expr (location, *new_var, NOP_EXPR, 
+					 *new_var, 1);
+      if (ARITHMETIC_TYPE_P (TREE_TYPE (func_parm)))
+	comp_node = build_zero_cst (TREE_TYPE (func_parm));
+      else
+	comp_node = integer_zero_node;
+      new_cond_expr = build_x_binary_op
+	(location, NE_EXPR, 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);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO)
+    {
+      new_var_init = build_x_modify_expr
+	(location, *new_var, NOP_EXPR, build_one_cst (new_var_type), 1);
+      /* Initially you assume everything is non-zero, now if we find a case
+	 where it is NOT true, then we set the result to false. Otherwise we
+	 just keep the previous value.  */
+      new_yes_expr = build_x_modify_expr
+	(location, *new_var, NOP_EXPR, 
+	 build_zero_cst (TREE_TYPE (*new_var)), 1);
+      new_no_expr = build_x_modify_expr (location, *new_var, NOP_EXPR, 
+					 *new_var, 1);
+      if (ARITHMETIC_TYPE_P (TREE_TYPE (func_parm)))
+	comp_node = build_zero_cst (TREE_TYPE (func_parm));
+      else
+	comp_node = integer_zero_node;
+      new_cond_expr = build_x_binary_op
+	(location, EQ_EXPR, 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);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO)
+    {
+      new_var_init = build_x_modify_expr
+	(location, *new_var, NOP_EXPR, 
+	 build_zero_cst (new_var_type), 1);
+      /* Initially we assume there are NO zeros in the list. When we find a
+	 non-zero, we keep the previous value. If we find a zero, we set the
+	 value to true.  */
+      new_no_expr = build_x_modify_expr
+	(location, *new_var, NOP_EXPR, 
+	 build_one_cst (TREE_TYPE (*new_var)), 1);
+      new_yes_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  *new_var, 1);
+      if (ARITHMETIC_TYPE_P (TREE_TYPE (func_parm)))
+	comp_node = build_zero_cst (TREE_TYPE (func_parm));
+      else
+	comp_node = integer_zero_node;
+      new_cond_expr = build_x_binary_op
+	(location, EQ_EXPR, 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);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO)
+    {
+      new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR, 
+					  build_zero_cst (new_var_type), 1);
+      /* Initially we assume there are NO non-zeros in the list. When we find a
+	 zero, we keep the previous value. If we find a zero, we set the value
+	 to true.  */
+      new_no_expr = build_x_modify_expr
+	(location, *new_var, NOP_EXPR, 
+	 build_one_cst (TREE_TYPE (*new_var)), 1);
+      new_yes_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  *new_var, 1);
+      if (ARITHMETIC_TYPE_P (TREE_TYPE (func_parm)))
+	comp_node = build_zero_cst (TREE_TYPE (func_parm));
+      else
+	comp_node = integer_zero_node;
+      new_cond_expr = build_x_binary_op
+	(location, NE_EXPR, 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);      
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX)
+    {
+      /* If the TYPE_MIN_VALUE is available for the new_var_type, then
+	 set that as the initial value.  */
+      if (TYPE_MIN_VALUE (new_var_type))
+	new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					    TYPE_MIN_VALUE (new_var_type), 1);
+      else
+	/* ... otherwise set initial value as the first element of array.  */
+	new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					    func_parm, 1);
+      new_no_expr  = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  *new_var, 1);
+      new_yes_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  func_parm, 1);
+      new_cond_expr = build_x_binary_op (location, LT_EXPR, *new_var,
+					 TREE_CODE (*new_var), func_parm,
+					 TREE_CODE (func_parm), 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);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN)
+    {
+      /* If the TYPE_MAX_VALUE is available for the new_var_type, then
+	 set that as the initial value.  */
+      if (TYPE_MAX_VALUE (new_var_type))
+	new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					    TYPE_MAX_VALUE (new_var_type), 1);
+      else
+	/* ... otherwise set initial value as the first element of array.  */
+	new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					    func_parm, 1);
+      new_no_expr  = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  *new_var, 1);
+      new_yes_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  func_parm, 1);
+      new_cond_expr = build_x_binary_op (location, GT_EXPR, *new_var,
+					 TREE_CODE (*new_var), func_parm,
+					 TREE_CODE (func_parm), 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);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND)
+    {
+      new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  array_var[0], tf_warning_or_error);
+      new_exp_init = build_x_modify_expr (location, array_ind_value, 
+					  NOP_EXPR, func_parm, 
+					  tf_warning_or_error);
+      new_no_ind   = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  *new_var, 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, array_var[0],
+					    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_yes_expr = build_x_modify_expr (location, array_ind_value, 
+					  NOP_EXPR, func_parm,
+					  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, LT_EXPR, 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);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND)
+    {
+      new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  array_var[0], 1);
+      new_exp_init = build_x_modify_expr (location, array_ind_value, 
+					  NOP_EXPR, func_parm, 1);
+      new_no_ind   = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  *new_var, 1);
+      new_no_expr  = build_x_modify_expr (location, array_ind_value, 
+					  NOP_EXPR, array_ind_value, 1);
+      if (list_size > 1)
+	new_yes_ind  = build_x_modify_expr (location, *new_var, 
+					    NOP_EXPR, array_var[0], 1);
+      else
+	new_yes_ind  = build_x_modify_expr
+	  (location, *new_var, NOP_EXPR, TREE_OPERAND (array_op0, 1), 1);
+      new_yes_expr = build_x_modify_expr (location, array_ind_value, 
+					  NOP_EXPR, func_parm, 1);
+      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, GT_EXPR, 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);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE)
+    {
+      vec<tree, va_gc> *func_args;
+      func_args = make_tree_vector ();
+      vec_safe_push (func_args, *new_var);
+      vec_safe_push (func_args, func_parm);
+
+      new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  identity_value, tf_warning_or_error);
+      new_call_expr = finish_call_expr (call_fn, &func_args, false, true,
+					tf_warning_or_error);
+      new_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
+				      new_call_expr, tf_warning_or_error);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
+    {
+      vec<tree, va_gc> *func_args;
+
+      func_args = make_tree_vector (); 
+      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);
+    }
+  else
+    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 (ind_init[ii]);
+  
+  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 (ind_init[ii], compare_expr[ii], expr_incr[ii], body);
+      body = pop_stmt_list (new_loop);
+    }
+  append_to_statement_list_force (body, &loop_with_init);
+  
+  XDELETEVEC (compare_expr);
+  XDELETEVEC (expr_incr);
+  XDELETEVEC (ind_init);
+  XDELETEVEC (array_var);
+  
+  for (ii = 0; ii < list_size; ii++)
+    {
+      XDELETEVEC (count_down[ii]);
+      XDELETEVEC (array_value[ii]);
+      XDELETEVEC (array_stride[ii]);
+      XDELETEVEC (array_length[ii]);
+      XDELETEVEC (array_start[ii]);
+      XDELETEVEC (array_ops[ii]);
+      XDELETEVEC (array_vector[ii]);
+    }
+  XDELETEVEC (count_down);
+  XDELETEVEC (array_value);
+  XDELETEVEC (array_stride);
+  XDELETEVEC (array_length);
+  XDELETEVEC (array_start);
+  XDELETEVEC (array_ops);
+  XDELETEVEC (array_vector);
+  
+  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
+build_x_array_notation_expr (location_t location, tree lhs,
+			     enum tree_code modifycode, tree rhs,
+			     tsubst_flags_t complain)
+{
+  bool **lhs_vector = NULL, **rhs_vector = NULL;
+  tree **lhs_array = NULL, **rhs_array = NULL;
+  tree array_expr_lhs = NULL_TREE, array_expr_rhs = NULL_TREE;
+  tree array_expr = NULL_TREE;
+  tree **lhs_value = NULL, **rhs_value = NULL;
+  tree **lhs_stride = NULL, **lhs_length = NULL, **lhs_start = NULL;
+  tree **rhs_stride = NULL, **rhs_length = NULL, **rhs_start = NULL;
+  tree body = NULL_TREE, *lhs_var = NULL, *rhs_var = NULL;
+  tree  *cond_expr = NULL;
+  tree *lhs_expr_incr = NULL, *rhs_expr_incr = NULL;
+  tree *lhs_ind_init = NULL, *rhs_ind_init = NULL;
+  bool **lhs_count_down = NULL, **rhs_count_down = NULL;
+  tree *lhs_compare = NULL, *rhs_compare = NULL;
+  vec<tree, va_gc> *lhs_array_operand = NULL, *rhs_array_operand = NULL;
+  size_t lhs_rank = 0, rhs_rank = 0, ii = 0, jj = 0;
+  tree ii_tree = NULL_TREE;
+  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;
+  int s_jj = 0;
+  tree lhs_begin_var, lhs_lngth_var, lhs_strde_var, rhs_begin_var;
+  tree rhs_lngth_var, rhs_strde_var;
+  tree an_init, loop_with_init = alloc_stmt_list ();
+  
+  /* 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, 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 = fix_builtin_array_notation_fn (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)
+    {
+      tree rhs_base = rhs;
+      if (TREE_CODE (rhs_base) == COMPOUND_EXPR)
+	rhs_base = TREE_OPERAND (rhs_base, 0);
+      if (TREE_CODE (rhs_base) == TARGET_EXPR)
+	rhs_base = TARGET_EXPR_INITIAL (rhs_base);
+      
+      if (TREE_CODE (rhs) != CALL_EXPR
+	  && !has_call_expr_with_array_notation (rhs))
+	{
+	  for (ii = 0; ii < rhs_rank; ii++)
+	    rhs_base = ARRAY_NOTATION_ARRAY (rhs);
+      	  
+	  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_base);
+	  return error_mark_node;
+	}
+    }
+  if (lhs_rank != 0 && rhs_rank != 0 && lhs_rank != rhs_rank)
+    {
+      tree lhs_base = lhs;
+      tree rhs_base = rhs;
+      
+      for (ii = 0; ii < lhs_rank; ii++)
+	lhs_base = ARRAY_NOTATION_ARRAY (lhs_base);
+
+      while (rhs_base && TREE_CODE (rhs_base) != ARRAY_NOTATION_REF)
+	rhs_base = TREE_OPERAND (rhs_base, 0);
+      for (ii = 0; ii < rhs_rank; ii++)
+	rhs_base = ARRAY_NOTATION_ARRAY (rhs_base);
+
+      if (location == UNKNOWN_LOCATION && EXPR_HAS_LOCATION (lhs))
+	location = EXPR_LOCATION (lhs);
+      error_at (location, "rank mismatch between %qD and %qD", lhs_base,
+		rhs_base);
+      return error_mark_node;
+    }
+
+  /* Assign the array notation components to variable so that they can satisfy
+     the exec-once rule.  */
+  for (ii = 0; ii < lhs_list_size; ii++)
+    {
+      tree array_node = (*lhs_list)[ii];
+      tree array_begin = ARRAY_NOTATION_START (array_node);
+      tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
+      tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
+
+      if (TREE_CODE (array_begin) != INTEGER_CST)
+	{
+	  lhs_begin_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	  finish_expr_stmt (build_x_modify_expr (location, lhs_begin_var,
+						 NOP_EXPR, array_begin,
+						 complain));
+	  ARRAY_NOTATION_START (array_node) = lhs_begin_var;
+	}
+      if (TREE_CODE (array_lngth) != INTEGER_CST)
+	{
+	  lhs_lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	  finish_expr_stmt (build_x_modify_expr (location, lhs_lngth_var,
+						 NOP_EXPR, array_lngth,
+						 complain));
+	  ARRAY_NOTATION_LENGTH (array_node) = lhs_lngth_var;
+	}
+      if (TREE_CODE (array_strde) != INTEGER_CST)
+	{
+	  lhs_strde_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	  finish_expr_stmt (build_x_modify_expr (location, lhs_strde_var,
+						 NOP_EXPR, array_strde,
+						 complain));
+	  ARRAY_NOTATION_STRIDE (array_node) = lhs_strde_var;
+	}
+    }
+  for (ii = 0; ii < rhs_list_size; ii++)
+    {
+      tree array_node = (*rhs_list)[ii];
+      if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF)
+	{
+	  tree array_begin = ARRAY_NOTATION_START (array_node);
+	  tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
+	  tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
+
+	  if (TREE_CODE (array_begin) != INTEGER_CST)
+	    {
+	      rhs_begin_var = build_decl (location, VAR_DECL, NULL_TREE,
+					  integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, rhs_begin_var,
+						     NOP_EXPR, array_begin,
+						     complain));
+	      ARRAY_NOTATION_START (array_node) = rhs_begin_var;
+	    }
+	  if (TREE_CODE (array_lngth) != INTEGER_CST)
+	    {
+	      rhs_lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
+					  integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, rhs_lngth_var,
+						     NOP_EXPR, array_lngth,
+						     complain));
+	      ARRAY_NOTATION_LENGTH (array_node) = rhs_lngth_var;
+	    }
+	  if (TREE_CODE (array_strde) != INTEGER_CST)
+	    {
+	      rhs_strde_var = build_decl (location, VAR_DECL, NULL_TREE,
+					  integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, rhs_strde_var,
+						     NOP_EXPR, array_strde,
+						     complain));
+	      ARRAY_NOTATION_STRIDE (array_node) = rhs_strde_var;
+	    }
+	}
+    }  
+  lhs_vector = XNEWVEC (bool *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_vector[ii] = XNEWVEC (bool, lhs_rank);
+  
+  rhs_vector = XNEWVEC (bool *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_vector[ii] = XNEWVEC (bool, rhs_rank);
+
+  lhs_array = XNEWVEC (tree *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_array[ii] = XNEWVEC (tree, lhs_rank);
+  
+  rhs_array = XNEWVEC (tree *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_array[ii] = XNEWVEC (tree, rhs_rank);
+
+  lhs_value = XNEWVEC (tree *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_value[ii] = XNEWVEC (tree, lhs_rank);
+  
+  rhs_value = XNEWVEC (tree *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_value[ii] = XNEWVEC (tree, rhs_rank);
+
+  lhs_stride = XNEWVEC (tree *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_stride[ii] = XNEWVEC (tree, lhs_rank);
+
+  rhs_stride = XNEWVEC (tree *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_stride[ii] = XNEWVEC (tree, rhs_rank);
+
+  lhs_length = XNEWVEC (tree *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_length[ii] = XNEWVEC (tree, lhs_rank);
+  
+  rhs_length = XNEWVEC (tree *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_length[ii] = XNEWVEC (tree, rhs_rank);
+
+  lhs_start = XNEWVEC (tree *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_start[ii] = XNEWVEC (tree, lhs_rank);
+  
+  rhs_start = XNEWVEC (tree *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_start[ii] = XNEWVEC (tree, rhs_rank);
+   
+  lhs_var = XNEWVEC (tree, lhs_rank);
+  rhs_var = XNEWVEC (tree, rhs_rank);
+  
+
+  /* The reason why we are just using lhs_rank for this is because we have then
+     following scenarios:
+     1.  LHS_RANK == RHS_RANK
+     2.  LHS_RANK != RHS_RANK && RHS_RANK = 0
+
+     In both the scenarios, just checking the LHS_RANK is OK.  */
+
+  cond_expr = XNEWVEC (tree, MAX (lhs_rank, rhs_rank));
+  lhs_expr_incr = XNEWVEC (tree, lhs_rank);
+  rhs_expr_incr = XNEWVEC (tree, rhs_rank);
+
+  lhs_ind_init = XNEWVEC (tree, lhs_rank);
+  rhs_ind_init = XNEWVEC (tree, rhs_rank);
+
+  lhs_count_down = XNEWVEC (bool *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_count_down[ii] = XNEWVEC (bool, lhs_rank);
+  
+  rhs_count_down = XNEWVEC (bool *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_count_down[ii] = XNEWVEC (bool, rhs_rank);
+
+  lhs_compare = XNEWVEC (tree, lhs_rank);
+  rhs_compare = XNEWVEC (tree, rhs_rank);
+
+  if (lhs_rank)
+    {
+      for (ii = 0; ii < lhs_list_size; ii++)
+	{
+	  jj = 0;
+	  ii_tree = (*lhs_list)[ii];
+	  while (ii_tree)
+	    {
+	      if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
+		{
+		  lhs_array[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) == PARM_DECL)
+		break;
+	    }
+	}
+    }
+  else
+    lhs_array[0][0] = NULL_TREE;
+  
+  if (rhs_rank)
+    {
+      for (ii = 0; ii < rhs_list_size; ii++)
+	{
+	  jj = 0;
+	  ii_tree = (*rhs_list)[ii];
+	  while (ii_tree)
+	    {
+	      if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
+		{
+		  rhs_array[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) == PARM_DECL
+		       || TREE_CODE (ii_tree) == CALL_EXPR)
+		break;
+	    }
+	}
+    }  
+  for (ii = 0; ii < lhs_list_size; ii++)
+    {
+      if (TREE_CODE ((*lhs_list)[ii]) == ARRAY_NOTATION_REF)
+	{
+	  for (jj = 0; jj < lhs_rank; jj++)
+	    {
+	      if (TREE_CODE (lhs_array[ii][jj]) == ARRAY_NOTATION_REF)
+		{
+		  lhs_value[ii][jj] = ARRAY_NOTATION_ARRAY (lhs_array[ii][jj]);
+		  lhs_start[ii][jj] = ARRAY_NOTATION_START (lhs_array[ii][jj]);
+		  lhs_length[ii][jj] =
+		    fold_build1 (CONVERT_EXPR, integer_type_node,
+				 ARRAY_NOTATION_LENGTH (lhs_array[ii][jj]));
+		  lhs_stride[ii][jj] =
+		    fold_build1 (CONVERT_EXPR, integer_type_node,
+				 ARRAY_NOTATION_STRIDE (lhs_array[ii][jj]));
+		  lhs_vector[ii][jj] = true;
+		  
+		  /* If the stride value is variable (i.e. not constant) then
+		     assume that the length is positive.  */
+		  if (!TREE_CONSTANT (lhs_length[ii][jj]))
+		    lhs_count_down[ii][jj] = false;
+		  else if (tree_int_cst_lt
+			   (lhs_length[ii][jj],
+			    build_zero_cst (TREE_TYPE (lhs_length[ii][jj]))))
+		    lhs_count_down[ii][jj] = true;
+		  else
+		    lhs_count_down[ii][jj] = false;
+		}
+	      else
+		lhs_vector[ii][jj] = false;
+	    }
+	}
+    }
+  for (ii = 0; ii < rhs_list_size; ii++)
+    {
+      if (TREE_CODE ((*rhs_list)[ii]) == ARRAY_NOTATION_REF)
+	{
+	  for (jj = 0; jj < rhs_rank; jj++)
+	    {
+	      if (TREE_CODE (rhs_array[ii][jj]) == ARRAY_NOTATION_REF)
+		{
+		  rhs_value[ii][jj]  = ARRAY_NOTATION_ARRAY (rhs_array[ii][jj]);
+		  rhs_start[ii][jj]  = ARRAY_NOTATION_START (rhs_array[ii][jj]);
+		  rhs_length[ii][jj] =
+		    ARRAY_NOTATION_LENGTH (rhs_array[ii][jj]);
+		  rhs_stride[ii][jj] =
+		    ARRAY_NOTATION_STRIDE (rhs_array[ii][jj]);
+		  rhs_vector[ii][jj] = true;
+		  /* If the stride value is variable (i.e. not constant) then
+		     assume that the length is positive.  */
+		  if (!TREE_CONSTANT (rhs_length[ii][jj]))
+		    rhs_count_down[ii][jj] = false;
+		  else if (tree_int_cst_lt
+			   (rhs_length[ii][jj],
+			    build_zero_cst (TREE_TYPE (rhs_length[ii][jj]))))
+		    rhs_count_down[ii][jj] = true;
+		  else
+		    rhs_count_down[ii][jj] = false;	
+		}
+	      else
+		rhs_vector[ii][jj] = false;
+	    }
+	}
+      else
+	for (jj = 0; jj < rhs_rank; jj++)
+	  {
+	    rhs_vector[ii][jj] = false;
+	    rhs_length[ii][jj] = NULL_TREE;
+	  }
+    }
+
+  if (length_mismatch_in_expr_p (EXPR_LOCATION (lhs), lhs_length,
+				 lhs_list_size, lhs_rank)
+      || length_mismatch_in_expr_p (EXPR_LOCATION (rhs), rhs_length,
+				    rhs_list_size, rhs_rank))
+    {
+      pop_stmt_list (an_init);
+      return error_mark_node;
+    }
+
+  if (lhs_list_size > 0 && rhs_list_size > 0 && lhs_rank > 0 && rhs_rank > 0
+      && TREE_CODE (lhs_length[0][0]) == INTEGER_CST
+      && rhs_length[0][0] && TREE_CODE (rhs_length[0][0]) == INTEGER_CST)
+    {
+      HOST_WIDE_INT l_length = int_cst_value (lhs_length[0][0]);
+      HOST_WIDE_INT r_length = int_cst_value (rhs_length[0][0]);
+      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_start[0][ii] && TREE_TYPE (lhs_start[0][ii]))
+	lhs_var[ii] =  build_decl (location, VAR_DECL, NULL_TREE,
+				   TREE_TYPE (lhs_start[0][ii]));
+    else
+      lhs_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
+				integer_type_node);
+
+  for (ii = 0; ii < rhs_list_size; ii++)
+    {
+      if (TREE_CODE ((*rhs_list)[ii]) == CALL_EXPR)
+	{
+	  int idx_value = 0;
+	  tree func_name = CALL_EXPR_FN ((*rhs_list)[ii]);
+	  if (TREE_CODE (func_name) == ADDR_EXPR)
+	    {
+	      if (is_sec_implicit_index_fn (func_name))
+		{
+		  idx_value = 
+		    extract_sec_implicit_index_arg (location, (*rhs_list)[ii]);
+		  if (idx_value < (int) lhs_rank && idx_value >= 0)
+		    vec_safe_push (rhs_array_operand, lhs_var[idx_value]);
+		  else if (idx_value == -1)
+		    return error_mark_node;
+		  else
+		    {
+		      size_t ee = 0;
+		      tree lhs_base = (*lhs_list)[ii];
+		      for (ee = 0; ee < lhs_rank; ee++)
+			if (lhs_base
+			    && TREE_CODE (lhs_base) == ARRAY_NOTATION_REF)
+			  lhs_base = ARRAY_NOTATION_ARRAY (lhs_base);
+
+		      if (location == UNKNOWN_LOCATION
+			  && EXPR_HAS_LOCATION (lhs))
+			location = EXPR_LOCATION (lhs);
+		      error_at (location, "__sec_implicit_index argument %d "
+				"must be less than the rank of %qD", idx_value,
+				lhs_base);
+		      return error_mark_node;
+		    }
+		}
+	      else
+		vec_safe_push (rhs_array_operand, (*rhs_list)[ii]);
+	    }
+	  else
+	    vec_safe_push (rhs_array_operand, (*rhs_list)[ii]);
+	}
+      else
+	vec_safe_push (rhs_array_operand, (*rhs_list)[ii]);
+    }
+
+  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_vector[0][ii])
+      {
+	lhs_ind_init[ii] = build_x_modify_expr
+	  (location, lhs_var[ii], NOP_EXPR,
+	   build_zero_cst (TREE_TYPE (lhs_var[ii])), complain);
+      }
+    
+
+  for (ii = 0; ii < rhs_rank; ii++)
+    {
+      /* When we have a polynomial, we assume that the indices are of type
+	 integer.  */
+      rhs_var[ii] =  build_decl (location, VAR_DECL, NULL_TREE,
+				 TREE_TYPE (rhs_start[0][ii]));
+      rhs_ind_init[ii] = build_x_modify_expr
+	(location, rhs_var[ii], NOP_EXPR, 
+	 build_zero_cst (TREE_TYPE (rhs_var[ii])), complain);
+    }
+
+  if (lhs_rank)
+    {
+      for (ii = 0; ii < lhs_list_size; ii++)
+	{
+	  if (lhs_vector[ii][0])
+	    {
+	      /* The last ARRAY_NOTATION element's ARRAY component should be
+		 the array's base value.  */
+	      tree lhs_array_opr = lhs_value[ii][lhs_rank - 1];
+	      for (s_jj = lhs_rank - 1; s_jj >= 0; s_jj--)
+		{
+		  tree stride = NULL_TREE, var = NULL_TREE, start = NULL_TREE;
+		  if ((TREE_TYPE (lhs_start[ii][s_jj]) ==
+		       TREE_TYPE (lhs_stride[ii][s_jj]))
+		      && (TREE_TYPE (lhs_stride[ii][s_jj]) !=
+			  TREE_TYPE (lhs_var[s_jj])))
+		    {
+		      /* If stride and start are of same type and the induction
+			 var is not, we convert induction variable to stride's
+			 type.  */
+		      start = lhs_start[ii][s_jj];
+		      stride = lhs_stride[ii][s_jj];
+		      var = build_c_cast (location,
+					  TREE_TYPE (lhs_stride[ii][s_jj]),
+					  lhs_var[s_jj]);
+		    }
+		  else if (TREE_TYPE (lhs_start[ii][s_jj]) !=
+			   TREE_TYPE (lhs_stride[ii][s_jj]))
+		    {
+		      /* 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, we stay safe and
+			 convert everything to integer.  The reason why we
+			 pick integer instead of something like size_t is
+			 because the stride and length can be + or -.  */
+		      start = build_c_cast (location, integer_type_node,
+					    lhs_start[ii][s_jj]);
+		      stride = build_c_cast (location, integer_type_node,
+					     lhs_stride[ii][s_jj]);
+		      var = build_c_cast (location, integer_type_node,
+					  lhs_var[s_jj]);
+		    }
+		  else
+		    {
+		      start = lhs_start[ii][s_jj];
+		      stride = lhs_stride[ii][s_jj];
+		      var = lhs_var[s_jj];
+		    }
+		  if (lhs_count_down[ii][s_jj])
+		    /* Array[start_index - (induction_var * stride)].  */
+		    lhs_array_opr = grok_array_decl
+		      (location, lhs_array_opr,
+		       build2 (MINUS_EXPR, TREE_TYPE (var), start,
+			       build2 (MULT_EXPR, TREE_TYPE (var), var,
+				       stride)), false);	
+		  else
+		    /* Array[start_index + (induction_var * stride)].  */
+		    lhs_array_opr = grok_array_decl
+		      (location, lhs_array_opr,
+		       build2 (PLUS_EXPR, TREE_TYPE (var), start,
+			       build2 (MULT_EXPR, TREE_TYPE (var), var,
+				       stride)), false);
+		}
+	      vec_safe_push (lhs_array_operand, lhs_array_opr);
+	    }
+	  else
+	    vec_safe_push (lhs_array_operand, integer_one_node);
+	}
+      replace_array_notations (&lhs, true, lhs_list, lhs_array_operand);
+      array_expr_lhs = lhs;
+    }
+
+  if (rhs_array_operand)
+    vec_safe_truncate (rhs_array_operand, 0);
+
+  if (rhs_rank)
+    {
+      for (ii = 0; ii < rhs_list_size; ii++)
+	{
+	  if (rhs_vector[ii][0])
+	    {
+	      tree rhs_array_opr = rhs_value[ii][rhs_rank - 1];
+	      for (s_jj = rhs_rank - 1; s_jj >= 0; s_jj--)
+		{
+		  tree stride = NULL_TREE, var = NULL_TREE, start = NULL_TREE;
+		  if ((TREE_TYPE (rhs_start[ii][s_jj]) ==
+		       TREE_TYPE (rhs_stride[ii][s_jj]))
+		      && (TREE_TYPE (rhs_stride[ii][s_jj]) !=
+			  TREE_TYPE (rhs_var[s_jj])))
+		    {
+		      /* If stride and start are of same type and the induction
+			 var is not, we convert induction variable to stride's
+			 type.  */
+		      start = rhs_start[ii][s_jj];
+		      stride = rhs_stride[ii][s_jj];
+		      var = build_c_cast (location,
+					  TREE_TYPE (rhs_stride[ii][s_jj]),
+					  rhs_var[s_jj]);
+		    }
+		  else if (TREE_TYPE (rhs_start[ii][s_jj]) !=
+			   TREE_TYPE (rhs_stride[ii][s_jj]))
+		    {
+		      /* 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, we stay safe and
+			 convert everything to integer.  The reason why we
+			 pick integer instead of something like size_t is
+			 because the stride and length can be + or -.  */
+		      start = build_c_cast (location, integer_type_node,
+					    rhs_start[ii][s_jj]);
+		      stride = build_c_cast (location, integer_type_node,
+					     rhs_stride[ii][s_jj]);
+		      var = build_c_cast (location, integer_type_node,
+					  rhs_var[s_jj]);
+		    }
+		  else
+		    {
+		      start = rhs_start[ii][s_jj];
+		      stride = rhs_stride[ii][s_jj];
+		      var = rhs_var[s_jj];
+		    }
+		  if (rhs_count_down[ii][s_jj])
+		    /* Array[start_index - (induction_var * stride)].  */
+		    rhs_array_opr = grok_array_decl
+		      (location, rhs_array_opr,
+		       build2 (MINUS_EXPR, TREE_TYPE (var), start,
+			       build2 (MULT_EXPR, TREE_TYPE (var), var,
+				       stride)), false);	
+		  else
+		    /* Array[start_index + (induction_var * stride)].  */
+		    rhs_array_opr = grok_array_decl
+		      (location, rhs_array_opr,
+		       build2 (PLUS_EXPR, TREE_TYPE (var), start,
+			       build2 (MULT_EXPR, TREE_TYPE (var), var,
+				       stride)), false);
+		}
+	      vec_safe_push (rhs_array_operand, rhs_array_opr);
+	    }
+	  else
+	    /* This is just a dummy node to make sure the list sizes for both
+	       array list and array operand list are the same.  */
+	    vec_safe_push (rhs_array_operand, integer_one_node);
+	}
+      for (ii = 0; ii < rhs_list_size; ii++)
+	{
+	  tree rhs_node = (*rhs_list)[ii];
+	  if (TREE_CODE (rhs_node) == CALL_EXPR)
+	    {
+	      int idx_value = 0;
+	      tree func_name = CALL_EXPR_FN (rhs_node);
+	      if (TREE_CODE (func_name) == ADDR_EXPR)
+		if (is_sec_implicit_index_fn (func_name))
+		  {
+		    idx_value = 
+		      extract_sec_implicit_index_arg (location, rhs_node);
+		    if (idx_value < (int) lhs_rank && idx_value >= 0)
+		      vec_safe_push (rhs_array_operand, rhs_var[idx_value]);
+		    else
+		      {
+			size_t ee = 0;
+			tree rhs_base = (*lhs_list)[ii];
+			for (ee = 0; ee < rhs_rank; ee++)
+			  if (rhs_base
+			      && TREE_CODE (rhs_base) == ARRAY_NOTATION_REF)
+			    rhs_base = ARRAY_NOTATION_ARRAY (rhs_base);
+
+			error_at (location, "__sec_implicit_index argument %d "
+				  "must be less than rank of %qD", idx_value,
+				  rhs_base);
+			return error_mark_node;
+		      }
+		  }
+	    }
+	}	
+      replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
+      array_expr_rhs = rhs;
+    }
+  else
+    {
+      for (ii = 0; ii < rhs_list_size; ii++)
+	{
+	  tree rhs_node = (*rhs_list)[ii];
+	  if (TREE_CODE (rhs_node) == CALL_EXPR)
+	    {
+	      int idx_value = 0;
+	      tree func_name = CALL_EXPR_FN (rhs_node);
+	      if (is_sec_implicit_index_fn (func_name))
+		{
+		  idx_value =  extract_sec_implicit_index_arg (location,
+							       rhs_node);
+		  if (idx_value < (int) lhs_rank && idx_value >= 0)
+		    vec_safe_push (rhs_array_operand, lhs_var[idx_value]);
+		  else
+		    {
+		      size_t ee = 0;
+		      tree lhs_base = (*lhs_list)[ii];
+		      for (ee = 0; ee < lhs_rank; ee++)
+			if (lhs_base
+			    && TREE_CODE (lhs_base) == ARRAY_NOTATION_REF)
+			  lhs_base = ARRAY_NOTATION_ARRAY (lhs_base);
+		      error_at (location, "__sec_implicit_index argument %d "
+				"must be less than the rank of %qD", idx_value,
+				lhs_base);
+		      return error_mark_node;
+		    }
+		}
+	    }
+	}
+      replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
+      array_expr_rhs = rhs;
+      rhs_expr_incr[0] = NULL_TREE;
+    }
+  
+  for (ii = 0; ii < rhs_rank; ii++)
+    if (rhs_count_down[0][ii])
+      rhs_expr_incr[ii] = build_x_unary_op (location, POSTDECREMENT_EXPR,
+					    rhs_var[ii], complain);
+    else
+      rhs_expr_incr[ii] = build_x_unary_op (location, POSTINCREMENT_EXPR,
+					    rhs_var[ii], complain);
+  
+  for (ii = 0; ii < lhs_rank; ii++)
+    if (lhs_count_down[0][ii])
+      lhs_expr_incr[ii] = build_x_unary_op (location, POSTDECREMENT_EXPR,
+					    lhs_var[ii], complain);
+    else
+      lhs_expr_incr[ii] = build_x_unary_op (location, POSTINCREMENT_EXPR,
+					    lhs_var[ii], complain);
+  if (!array_expr_lhs)
+    array_expr_lhs = lhs;
+  
+  array_expr = build_x_modify_expr (location, array_expr_lhs, modifycode,
+				    array_expr_rhs, complain);
+
+  for (jj = 0; jj < MAX (lhs_rank, rhs_rank); jj++)
+    {
+      if (rhs_rank && rhs_expr_incr[jj])
+	{
+	  size_t iii = 0;
+	  if (lhs_rank)
+	    {
+	      if (lhs_count_down[0][jj])
+		lhs_compare[jj] = build_x_binary_op
+		  (location, GT_EXPR, lhs_var[jj], TREE_CODE (lhs_var[jj]),
+		   lhs_length[0][jj], TREE_CODE (lhs_length[0][jj]), NULL,
+		   complain);
+	      else
+		lhs_compare[jj] = build_x_binary_op
+		  (location, LT_EXPR, lhs_var[jj], TREE_CODE (lhs_var[jj]),
+		   lhs_length[0][jj], TREE_CODE (lhs_length[0][jj]), NULL,
+		   complain);
+	    }
+	  else
+	    lhs_compare[jj] = NULL_TREE;
+
+	  for (iii = 0; iii < rhs_list_size; iii++)
+	    if (rhs_vector[iii][jj])
+	      break;
+	  
+	  /* What we are doing here is this:
+	     We always count up, so:
+	       if (length is negative ==> which means we count down)
+	          we multiply length by -1 and count up => ii < -LENGTH
+	       else
+	          we just count up, so we compare for  ii < LENGTH
+	   */
+	  if (rhs_count_down[iii][jj])
+	    {
+	      tree new_rhs = build_x_modify_expr
+		(location, rhs_length[iii][jj], MULT_EXPR,
+		 build_int_cst (TREE_TYPE (rhs_length[iii][jj]), -1), complain);
+	      rhs_compare[jj] = build_x_binary_op
+		(location, GT_EXPR, rhs_var[jj], TREE_CODE (rhs_var[jj]),
+		 new_rhs, TREE_CODE (new_rhs), NULL, complain);
+	    }
+	  else
+	    rhs_compare[jj] = build_x_binary_op
+	      (location, LT_EXPR, rhs_var[jj], TREE_CODE (rhs_var[jj]),
+	       rhs_length[iii][jj], TREE_CODE (rhs_length[0][jj]), NULL,
+	       complain);
+	   
+	  if (lhs_rank)
+	    cond_expr[jj] = build_x_binary_op
+	      (location, TRUTH_ANDIF_EXPR, lhs_compare[jj],
+	       TREE_CODE (lhs_compare[jj]), rhs_compare[jj],
+	       TREE_CODE (rhs_compare[jj]), NULL, complain);
+	  else
+	    cond_expr[jj] = rhs_compare[jj];
+	}
+      else
+	{
+	  if (lhs_count_down[0][jj])
+	    cond_expr[jj] = build_x_binary_op
+	      (location, GT_EXPR, lhs_var[jj], TREE_CODE (lhs_var[jj]),
+	       lhs_length[0][jj], TREE_CODE (lhs_length[0][jj]), NULL,
+	       complain);
+	    else
+	      cond_expr[jj] = build_x_binary_op
+		(location, LT_EXPR, lhs_var[jj], TREE_CODE (lhs_var[jj]),
+		 lhs_length[0][jj], TREE_CODE (lhs_length[0][jj]), NULL,
+		 complain);
+	}
+    }
+  
+  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_ind_init[ii], &init_list);
+	  append_to_statement_list_force (lhs_expr_incr[ii], &incr_list);
+	}
+      if (rhs_rank)
+	{
+	  append_to_statement_list_force (rhs_ind_init[ii], &init_list);
+	  append_to_statement_list_force (rhs_expr_incr[ii], &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);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    {
+      XDELETEVEC (rhs_vector[ii]);
+      XDELETEVEC (rhs_array[ii]);
+      XDELETEVEC (rhs_value[ii]);
+      XDELETEVEC (rhs_length[ii]);
+      XDELETEVEC (rhs_stride[ii]);
+      XDELETEVEC (rhs_start[ii]);
+    }
+    for (ii = 0; ii < lhs_list_size; ii++)
+    {
+      XDELETEVEC (lhs_vector[ii]);
+      XDELETEVEC (lhs_array[ii]);
+      XDELETEVEC (lhs_value[ii]);
+      XDELETEVEC (lhs_length[ii]);
+      XDELETEVEC (lhs_stride[ii]);
+      XDELETEVEC (lhs_start[ii]);
+    }
+  if (rhs_vector)
+    XDELETEVEC (rhs_vector);
+
+  if (rhs_array)
+    XDELETEVEC (rhs_array);
+  if (rhs_value)
+    XDELETEVEC (rhs_value);
+  if (rhs_length)
+    XDELETEVEC (rhs_length);
+  if (rhs_stride)
+    XDELETEVEC (rhs_stride);
+  if (rhs_start)
+    XDELETEVEC (rhs_start);
+  if (rhs_expr_incr)    
+    XDELETEVEC (rhs_expr_incr);
+  if (rhs_ind_init)
+    XDELETEVEC (rhs_ind_init);
+  if (rhs_compare)
+    XDELETEVEC (rhs_compare);
+  if (lhs_compare)
+    XDELETEVEC (lhs_compare);
+  
+  return loop_with_init;
+}
+
+/* Helper function for fix_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_fix_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, jj = 0;
+  tree **array_ops, *array_var, jj_tree, body, stmt = NULL_TREE;
+  tree **array_value, **array_stride, **array_length, **array_start;
+  tree *compare_expr, an_init, *expr_incr, *ind_init;
+  tree builtin_loop, new_var = NULL_TREE;
+  bool **count_down, **array_vector;
+  tree loop_with_init = alloc_stmt_list ();
+  int s_jj = 0;
+  tree begin_var, lngth_var, strde_var;
+  tsubst_flags_t complain = tf_warning_or_error;
+  location_t location = UNKNOWN_LOCATION;
+
+  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 = fix_builtin_array_notation_fn (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);
+  array_ops = XNEWVEC (tree *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_ops[ii] = XNEWVEC (tree, rank);
+  
+  array_vector = XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_vector[ii] = XNEWVEC (bool, rank);
+
+  array_value  = XNEWVEC (tree *, list_size);
+  array_stride = XNEWVEC (tree *, list_size);
+  array_length = XNEWVEC (tree *, list_size);
+  array_start  = XNEWVEC (tree *, list_size);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      array_value[ii]  = XNEWVEC (tree, rank);
+      array_stride[ii] = XNEWVEC (tree, rank);
+      array_length[ii] = XNEWVEC (tree, rank);
+      array_start[ii]  = XNEWVEC (tree, rank);
+    }
+
+  compare_expr = XNEWVEC (tree, rank);
+  expr_incr = XNEWVEC (tree, rank);
+  ind_init = XNEWVEC (tree, rank);
+
+  list_size = vec_safe_length (array_list);
+  count_down = XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    count_down[ii] = XNEWVEC (bool, rank);
+  
+  array_var = XNEWVEC (tree, 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];
+      if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF)
+	{
+	  tree array_begin = ARRAY_NOTATION_START (array_node);
+	  tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
+	  tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
+
+	  if (TREE_CODE (array_begin) != INTEGER_CST)
+	    {
+	      begin_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, begin_var,
+						     NOP_EXPR, array_begin,
+						     complain));
+	      ARRAY_NOTATION_START (array_node) = begin_var;
+	    }
+	  if (TREE_CODE (array_lngth) != INTEGER_CST)
+	    {
+	      lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, lngth_var,
+						     NOP_EXPR, array_lngth,
+						     complain));
+	      ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
+	    }
+	  if (TREE_CODE (array_strde) != INTEGER_CST)
+	    {
+	      strde_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, strde_var,
+						     NOP_EXPR, array_strde,
+						     complain));
+	      ARRAY_NOTATION_STRIDE (array_node) = strde_var;
+	    }
+	}
+    }
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      jj = 0;
+      jj_tree = (*array_list)[ii];
+      while (jj_tree)
+	{
+	  if (TREE_CODE (jj_tree) == ARRAY_NOTATION_REF)
+	    {
+	      array_ops[ii][jj] = jj_tree;
+	      jj++;
+	      jj_tree = ARRAY_NOTATION_ARRAY (jj_tree);
+	    }
+	  else if (TREE_CODE (jj_tree) == ARRAY_REF)
+	    jj_tree = TREE_OPERAND (jj_tree, 0);
+	  else if (TREE_CODE (jj_tree) == VAR_DECL
+		   || TREE_CODE (jj_tree) == PARM_DECL)
+	    break;
+	}
+    }
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      if (TREE_CODE ((*array_list)[ii]) == ARRAY_NOTATION_REF)
+	{
+	  for (jj = 0; jj < rank; jj++)
+	    {
+	      if (TREE_CODE (array_ops[ii][jj]) == ARRAY_NOTATION_REF)
+		{
+		  array_value[ii][jj] =
+		    ARRAY_NOTATION_ARRAY (array_ops[ii][jj]);
+		  array_start[ii][jj] =
+		    ARRAY_NOTATION_START (array_ops[ii][jj]);
+		  array_length[ii][jj] =
+		    ARRAY_NOTATION_LENGTH (array_ops[ii][jj]);
+		  array_stride[ii][jj] =
+		    ARRAY_NOTATION_STRIDE (array_ops[ii][jj]);
+		  array_vector[ii][jj] = true;
+
+		  if (!integer_zerop (array_length[ii][jj])
+		      && !integer_nonzerop (array_length[ii][jj]))
+		    count_down[ii][jj] = false;
+		  else if (tree_int_cst_lt
+			   (array_length[ii][jj],
+			    build_zero_cst (TREE_TYPE (array_length[ii][jj]))))
+		    count_down[ii][jj] = true;
+		  else
+		    count_down[ii][jj] = false;
+		}
+	      else
+		array_vector[ii][jj] = false;
+	    }
+	}
+    }
+  for (ii = 0; ii < rank; ii++)
+    {
+      if (TREE_TYPE (array_start[0][ii])
+	  && TREE_CODE (TREE_TYPE (array_start[0][ii])) != TEMPLATE_TYPE_PARM)
+	{
+	  array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
+				      TREE_TYPE (array_start[0][ii]));
+	  ind_init[ii] = build_x_modify_expr
+	    (location, array_var[ii], NOP_EXPR, 
+	     build_zero_cst (TREE_TYPE (array_var[ii])), tf_warning_or_error);
+	}
+      else
+	{
+	  array_var[ii] = build_min_nt_loc (location, VAR_DECL,
+					    NULL_TREE, NULL_TREE);
+	  ind_init[ii] = build_x_modify_expr (location, array_var[ii], 
+					      NOP_EXPR,
+					      integer_zero_node, 1);
+	}
+    }
+  for (ii = 0; ii < list_size; ii++)
+    {
+      if (array_vector[ii][0])
+	{
+	  tree array_opr = array_value[ii][rank - 1];
+	  for (s_jj = rank - 1; s_jj >= 0; s_jj--)
+	    {
+	      tree stride = NULL_TREE, var = NULL_TREE, start = NULL_TREE;
+
+	      /* If stride and start are of same type and the induction var
+		 is not, we convert induction variable to stride's type.  */
+	      if ((TREE_TYPE (array_start[ii][s_jj]) ==
+		   TREE_TYPE (array_stride[ii][s_jj]))
+		  && (TREE_TYPE (array_stride[ii][s_jj]) !=
+		      TREE_TYPE (array_var[s_jj])))
+		{
+		  start = array_start[ii][s_jj];
+		  stride = array_stride[ii][s_jj];
+		  var =
+		    build_c_cast (location, TREE_TYPE (array_stride[ii][s_jj]),
+				  array_var[s_jj]);
+		}
+	      else if (TREE_TYPE (array_start[ii][s_jj]) !=
+			TREE_TYPE (array_stride[ii][s_jj]))
+		{
+		  /* 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, we stay safe and convert
+		     everything to integer.  The reason why we pick integer
+		     instead of something like size_t is because the stride
+		     and length can be + or -.  */
+		  start = build_c_cast (location, integer_type_node,
+					array_start[ii][s_jj]);
+		  stride = build_c_cast (location, integer_type_node,
+					 array_stride[ii][s_jj]);
+		  var = build_c_cast (location, integer_type_node,
+				      array_var[s_jj]);
+		}
+	      else
+		{
+		  start = array_start[ii][s_jj];
+		  stride = array_stride[ii][s_jj];
+		  var = array_var[s_jj];
+		}
+	      if (count_down[ii][s_jj])
+		/* Array[start_index - (induction_var * stride)].  */
+		array_opr = grok_array_decl
+		  (location, array_opr,
+		   build2 (MINUS_EXPR, TREE_TYPE (var), start,
+			   build2 (MULT_EXPR, TREE_TYPE (var), var, stride)),
+		   false);	
+	      else
+		/* Array[start_index + (induction_var * stride)].  */
+		array_opr = grok_array_decl
+		  (location, array_opr,
+		   build2 (PLUS_EXPR, TREE_TYPE (var), start,
+			   build2 (MULT_EXPR, TREE_TYPE (var), var, stride)),
+		   false);
+		
+	    }
+	  vec_safe_push (array_operand, array_opr);
+	}
+      else
+	vec_safe_push (array_operand, integer_one_node);
+    }
+  replace_array_notations (&stmt, true, array_list, array_operand);
+
+  for (ii = 0; ii < rank; ii++)
+    if (count_down[0][ii])
+      expr_incr[ii] = build_x_unary_op (location, POSTDECREMENT_EXPR,
+					array_var[ii], tf_warning_or_error);
+    else
+      expr_incr[ii] = build_x_unary_op (location, POSTINCREMENT_EXPR,
+					array_var[ii], tf_warning_or_error);
+  
+  for (jj = 0; jj < rank; jj++)
+    {
+      if (rank && expr_incr[jj])
+	{
+	  if (count_down[0][jj])
+	    compare_expr[jj] = build_x_binary_op
+	      (location, GT_EXPR, array_var[jj], TREE_CODE (array_var[jj]),
+	       array_length[0][jj], TREE_CODE (array_length[0][jj]), NULL,
+	       tf_warning_or_error);
+	  else
+	    compare_expr[jj] = build_x_binary_op
+	      (location, LT_EXPR, array_var[jj], TREE_CODE (array_var[jj]),
+	       array_length[0][jj], TREE_CODE (array_length[0][jj]), NULL,
+	       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 (ind_init[ii], compare_expr[ii], expr_incr[ii], body);
+      body = pop_stmt_list (new_loop);
+    }
+  append_to_statement_list_force (body, &loop_with_init);
+  
+  XDELETEVEC (compare_expr);
+  XDELETEVEC (expr_incr);
+  XDELETEVEC (ind_init);
+  XDELETEVEC (array_var);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      XDELETEVEC (count_down[ii]);
+      XDELETEVEC (array_value[ii]);
+      XDELETEVEC (array_stride[ii]);
+      XDELETEVEC (array_length[ii]);
+      XDELETEVEC (array_start[ii]);
+      XDELETEVEC (array_ops[ii]);
+      XDELETEVEC (array_vector[ii]);
+    }
+
+  XDELETEVEC (count_down);
+  XDELETEVEC (array_value);
+  XDELETEVEC (array_stride);
+  XDELETEVEC (array_length);
+  XDELETEVEC (array_start);
+  XDELETEVEC (array_ops);
+  XDELETEVEC (array_vector);
+
+  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
+fix_unary_array_notation_exprs (tree orig_stmt)
+{
+  vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
+  int s_jj = 0;
+  size_t list_size = 0, rank = 0, ii = 0, jj = 0;
+  tree **array_ops, *array_var, jj_tree, body, array_opr;
+  tree **array_value, **array_stride, **array_length, **array_start;
+  tree *compare_expr, *expr_incr, *ind_init;
+  bool **count_down, **array_vector;
+  tree builtin_loop, stmt = NULL_TREE, new_var = NULL_TREE;
+  tree begin_var, lngth_var, strde_var;
+  location_t location = EXPR_LOCATION (orig_stmt);
+  tree an_init, loop_with_init = alloc_stmt_list ();
+  
+  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++)
+    {
+      tree list_node = (*array_list)[ii];
+      if (TREE_CODE (list_node) == CALL_EXPR
+	  || TREE_CODE (list_node) == AGGR_INIT_EXPR)
+	{
+	  builtin_loop =
+	    fix_builtin_array_notation_fn (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)
+    return stmt;
+  
+  if (list_size == 0)
+    return stmt;
+
+  array_ops = XNEWVEC (tree *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_ops[ii] = XNEWVEC (tree, rank);
+  
+  array_vector = XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_vector[ii] = XNEWVEC (bool, rank);
+
+  array_value = XNEWVEC (tree *, list_size);
+  array_stride = XNEWVEC (tree *, list_size);
+  array_length = XNEWVEC (tree *, list_size);
+  array_start = XNEWVEC (tree *, list_size);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      array_value[ii]  = XNEWVEC (tree, rank);
+      array_stride[ii] = XNEWVEC (tree, rank);
+      array_length[ii] = XNEWVEC (tree, rank);
+      array_start[ii]  = XNEWVEC (tree, rank);
+    }
+
+  compare_expr = XNEWVEC (tree, rank);
+  expr_incr = XNEWVEC (tree, rank);
+  ind_init = XNEWVEC (tree, rank);
+  array_var = XNEWVEC (tree, rank);
+  
+  count_down = XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++) 
+    count_down[ii] = XNEWVEC (bool,  rank);
+
+    /* 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];
+      tree array_begin = ARRAY_NOTATION_START (array_node);
+      tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
+      tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
+      tsubst_flags_t complain = tf_warning_or_error;
+      if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF)
+	{
+	  if (TREE_CODE (array_begin) != INTEGER_CST)
+	    {
+	      begin_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, begin_var,
+						     NOP_EXPR, array_begin,
+						     complain));
+	      ARRAY_NOTATION_START (array_node) = begin_var;
+	    }
+	  if (TREE_CODE (array_lngth) != INTEGER_CST)
+	    {
+	      lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, lngth_var,
+						     NOP_EXPR, array_lngth,
+						     complain));
+	      ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
+	    }
+	  if (TREE_CODE (array_strde) != INTEGER_CST)
+	    {
+	      strde_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, strde_var,
+						     NOP_EXPR, array_strde,
+						     complain));
+	      ARRAY_NOTATION_STRIDE (array_node) = strde_var;
+	    }
+	}
+    }
+  for (ii = 0; ii < list_size; ii++)
+    {
+      jj = 0;
+      jj_tree = (*array_list)[ii];
+      while (jj_tree)
+	{
+	  if (TREE_CODE (jj_tree) == ARRAY_NOTATION_REF)
+	    {
+	      array_ops[ii][jj] = jj_tree;
+	      jj++;
+	      jj_tree = ARRAY_NOTATION_ARRAY (jj_tree);
+	    }
+	  else if (TREE_CODE (jj_tree) == VAR_DECL
+		   || TREE_CODE (jj_tree) == PARM_DECL)
+	    break;
+	  else
+	    jj_tree = TREE_OPERAND (jj_tree, 0);
+	}
+    }
+  for (ii = 0; ii < list_size; ii++)
+    {
+      if (TREE_CODE ((*array_list)[ii]) == ARRAY_NOTATION_REF)
+	{
+	  for (jj = 0; jj < rank; jj++)
+	    {
+	      if (TREE_CODE (array_ops[ii][jj]) == ARRAY_NOTATION_REF)
+		{
+		  array_value[ii][jj] =
+		    ARRAY_NOTATION_ARRAY (array_ops[ii][jj]);
+		  array_start[ii][jj] =
+		    ARRAY_NOTATION_START (array_ops[ii][jj]);
+		  array_length[ii][jj] =
+		    ARRAY_NOTATION_LENGTH (array_ops[ii][jj]);
+		  array_stride[ii][jj] =
+		    ARRAY_NOTATION_STRIDE (array_ops[ii][jj]);
+		  array_vector[ii][jj] = true;
+
+		  if (!TREE_CONSTANT (array_length[ii][jj])
+		      || TREE_CODE (array_length[ii][jj]) == VAR_DECL)
+		    count_down[ii][jj] = false;
+		  else if (!integer_zerop (array_length[ii][jj])
+		      && !integer_nonzerop (array_length[ii][jj]))
+		      count_down[ii][jj] = false;
+		  else if (tree_int_cst_lt
+			   (array_length[ii][jj],
+			    build_zero_cst (TREE_TYPE (array_length[ii][jj]))))
+		    count_down[ii][jj] = true;
+		  else
+		    count_down[ii][jj] = false;
+		}
+	      else
+		array_vector[ii][jj] = false;
+	    }
+	}
+    }
+
+  an_init = push_stmt_list ();
+  for (ii = 0; ii < rank; ii++)
+    {
+      array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
+				  TREE_TYPE (array_start[0][ii]));
+      ind_init[ii] = build_x_modify_expr
+	(location, array_var[ii], NOP_EXPR, 
+	 build_zero_cst (TREE_TYPE (array_var[ii])), tf_warning_or_error);
+    }
+  for (ii = 0; ii < list_size; ii++)
+    {
+      if (array_vector[ii][0])
+	{
+	  array_opr = array_value[ii][rank - 1];
+	  for (s_jj = rank - 1; s_jj >= 0; s_jj--)
+	    {
+	      tree stride = NULL_TREE, var = NULL_TREE, start = NULL_TREE;
+	      if ((TREE_TYPE (array_start[ii][s_jj]) ==
+		   TREE_TYPE (array_stride[ii][s_jj]))
+		  && (TREE_TYPE (array_stride[ii][s_jj]) !=
+		      TREE_TYPE (array_var[s_jj])))
+		{
+		  /* If stride and start are of same type and the induction var
+		     is not, we convert induction variable to stride's
+		     type.  */
+		  start = array_start[ii][s_jj];
+		  stride = array_stride[ii][s_jj];
+		  var =
+		    build_c_cast (location, TREE_TYPE (array_stride[ii][s_jj]),
+				  array_var[s_jj]);
+		}
+	      else if (TREE_TYPE (array_start[ii][s_jj]) !=
+			TREE_TYPE (array_stride[ii][s_jj]))
+		{
+		  /* 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, we stay safe and convert
+		     everything to integer.  The reason why we pick integer
+		     instead of something like size_t is because the stride
+		     and length can be + or -.  */
+		  start = build_c_cast (location, integer_type_node,
+					array_start[ii][s_jj]);
+		  stride = build_c_cast (location, integer_type_node,
+					 array_stride[ii][s_jj]);
+		  var = build_c_cast (location, integer_type_node,
+				      array_var[s_jj]);
+		}
+	      else
+		{
+		  start = array_start[ii][s_jj];
+		  stride = array_stride[ii][s_jj];
+		  var = array_var[s_jj];
+		}
+	      if (count_down[ii][s_jj])
+		/* Array[start_index - (induction_var * stride)].  */
+		array_opr = grok_array_decl
+		  (location, array_opr,
+		   build2 (MINUS_EXPR, TREE_TYPE (var), start,
+			   build2 (MULT_EXPR, TREE_TYPE (var), var, stride)),
+		   false);	
+	      else
+		/* Array[start_index + (induction_var * stride)].  */
+		array_opr = grok_array_decl
+		  (location, array_opr,
+		   build2 (PLUS_EXPR, TREE_TYPE (var), start,
+			   build2 (MULT_EXPR, TREE_TYPE (var), var, stride)),
+		   false);
+	    }
+	  vec_safe_push (array_operand, array_opr);  
+	}
+      else
+	vec_safe_push (array_operand, integer_one_node);
+    }
+  replace_array_notations (&stmt, true, array_list, array_operand);
+
+  for (ii = 0; ii < rank; ii++)
+    if (count_down[0][ii])
+      expr_incr[ii] = build_x_unary_op (location, POSTDECREMENT_EXPR,
+					array_var[ii], tf_warning_or_error);
+    else
+      expr_incr[ii] = build_x_unary_op (location, POSTINCREMENT_EXPR,
+					array_var[ii], tf_warning_or_error);
+
+  for (jj = 0; jj < rank; jj++)
+    {
+      if (rank && expr_incr[jj])
+	{
+	  if (count_down[0][jj])
+	    compare_expr[jj] = build_x_binary_op
+	      (location, GT_EXPR, array_var[jj], TREE_CODE (array_var[jj]),
+	       array_length[0][jj], TREE_CODE (array_length[0][jj]), NULL,
+	       tf_warning_or_error);
+	  else
+	    compare_expr[jj] = build_x_binary_op
+	      (location, LT_EXPR, array_var[jj], TREE_CODE (array_var[jj]),
+	       array_length[0][jj], TREE_CODE (array_length[0][jj]), NULL,
+	       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 (ind_init[ii], compare_expr[ii], expr_incr[ii], body);
+      body = pop_stmt_list (new_loop);
+    }
+  append_to_statement_list_force (body, &loop_with_init);
+
+  XDELETEVEC (compare_expr);
+  XDELETEVEC (expr_incr);
+  XDELETEVEC (ind_init);
+  XDELETEVEC (array_var);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      XDELETEVEC (count_down[ii]);
+      XDELETEVEC (array_value[ii]);
+      XDELETEVEC (array_stride[ii]);
+      XDELETEVEC (array_length[ii]);
+      XDELETEVEC (array_start[ii]);
+      XDELETEVEC (array_ops[ii]);
+      XDELETEVEC (array_vector[ii]);
+    }
+    
+  XDELETEVEC (count_down);
+  XDELETEVEC (array_value);
+  XDELETEVEC (array_stride);
+  XDELETEVEC (array_length);
+  XDELETEVEC (array_start);
+  XDELETEVEC (array_ops);
+  XDELETEVEC (array_vector);
+
+  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
+fix_return_expr (tree expr)
+{
+  tree new_mod_list, new_var, new_mod, retval_expr;
+  location_t loc = EXPR_LOCATION (expr);
+
+  if (TREE_CODE (expr) != RETURN_EXPR)
+    return 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 = build_x_array_notation_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
+fix_array_notation_exprs (tree t)
+{
+  enum tree_code code;
+  bool is_expr;
+  location_t loc = UNKNOWN_LOCATION;
+  
+  /* Skip empty subtrees.  */
+  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 = build_x_array_notation_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 = build_x_array_notation_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) =
+	  fix_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 = fix_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) =
+	    fix_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 = fix_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 = fix_unary_array_notation_exprs (t);
+      return t;
+    case CONVERT_EXPR:
+    case CLEANUP_POINT_EXPR:
+    case EXPR_STMT:
+      TREE_OPERAND (t, 0) = fix_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_fix_cond_array_notations (t);
+      if (TREE_CODE (t) == COND_EXPR)
+	{
+	  COND_EXPR_THEN (t) =
+	    fix_array_notation_exprs (COND_EXPR_THEN (t));
+	  COND_EXPR_ELSE (t) =
+	    fix_array_notation_exprs (COND_EXPR_ELSE (t));
+	}
+      else
+	t = fix_array_notation_exprs (t);
+      return t;
+
+    case SWITCH_EXPR:
+      t = cp_fix_cond_array_notations (t);
+      if (TREE_CODE (t) == SWITCH_EXPR)
+	SWITCH_BODY (t) = fix_array_notation_exprs (SWITCH_BODY (t));
+      else
+	t = fix_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) = fix_array_notation_exprs (FOR_BODY (t));
+      else
+	t = fix_array_notation_exprs (t);
+      return t;
+
+    case IF_STMT:
+      t = cp_fix_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) = fix_array_notation_exprs (THEN_CLAUSE (t));
+	  if (ELSE_CLAUSE (t))
+	    ELSE_CLAUSE (t) = fix_array_notation_exprs (ELSE_CLAUSE (t));
+	}
+      else
+	t = fix_array_notation_exprs (t);
+      return t;
+
+    case SWITCH_STMT:
+      t = cp_fix_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) =
+	      fix_array_notation_exprs (SWITCH_STMT_BODY (t));
+	}
+      else
+	t = fix_array_notation_exprs (t);
+      return t;
+
+    case WHILE_STMT:
+      t = cp_fix_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) = fix_array_notation_exprs (WHILE_BODY (t));
+	}
+      else
+	t = fix_array_notation_exprs (t);
+      return t;
+      
+    case DO_STMT:
+      t = cp_fix_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) = fix_array_notation_exprs (DO_BODY (t));
+	}
+      else
+	t = fix_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) =
+	      fix_array_notation_exprs (TREE_OPERAND (t, i));
+	}
+      return t;
+    }
+  return t;
+}
+
+/* Handles expression of the form "a[i:j:k]" or "a[:]" or "a[i:j]," which
+   denotes an array notation expression.  If a is a variable or a member, then
+   we generate a ARRAY_NOTATION_REF front-end tree and return it.
+   This tree is broken down to ARRAY_REF toward the end of parsing.
+   ARRAY_NOTATION_REF tree holds the START_INDEX, LENGTH, STRIDE and the TYPE
+   of ARRAY_REF.  Restrictions on START_INDEX, LENGTH and STRIDE is same as that
+   of the 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;
+  size_t stride_rank = 0, length_rank = 0, start_rank = 0;
+  tree subtype = type;
+  
+  /* If we are dealing with templates, then we will resolve 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 (!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 error_mark_node;
+    }
+  if (!TREE_TYPE (length) || !INTEGRAL_TYPE_P (TREE_TYPE (length)))
+    {
+      error_at (loc, "length of array notation triplet is not an integer");
+      return error_mark_node;
+    }
+  if (!TREE_TYPE (stride) || !INTEGRAL_TYPE_P (TREE_TYPE (stride)))
+    {
+      error_at (loc, "stride of array notation triplet is not an integer");
+      return error_mark_node;
+    }
+  if (TREE_CODE (type) == FUNCTION_TYPE)
+    {
+      error_at (loc, "array notations cannot be used with function type");
+      return error_mark_node;
+    }
+    
+  while (subtype && (TREE_CODE (subtype) == POINTER_TYPE
+		     || TREE_CODE (subtype) == ARRAY_TYPE))
+    {
+      subtype = TREE_TYPE (subtype);
+      if (subtype && TREE_CODE (subtype) == FUNCTION_TYPE)
+	{
+	  error_at (loc, "array notations cannot be used with function pointer "
+		    "arrays");
+	  return error_mark_node;
+	}
+    }
+
+  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 (!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 error_mark_node;
+
+  if (start_rank != 0)
+    {
+      error_at (loc, "rank of an array notation triplet's start-index is not "
+		"zero");
+      return error_mark_node;
+    }
+  if (length_rank != 0)
+    {
+      error_at (loc, "rank of array notation triplet's length is not zero");
+      return error_mark_node;
+    }
+  if (stride_rank != 0)
+    {
+      error_at (loc, "rank of array notation triplet's stride is not zero");
+      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;
+}
diff --git gcc/cp/cp-objcp-common.c gcc/cp/cp-objcp-common.c
index bccd884..d301db0 100644
--- gcc/cp/cp-objcp-common.c
+++ gcc/cp/cp-objcp-common.c
@@ -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"
diff --git gcc/cp/cp-tree.h gcc/cp/cp-tree.h
index 9421822..94037a3 100644
--- gcc/cp/cp-tree.h
+++ gcc/cp/cp-tree.h
@@ -6135,6 +6135,8 @@ 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 fix_array_notation_exprs            (tree);
 /* -- end of C++ */
 
 #endif /* ! GCC_CP_TREE_H */
diff --git gcc/cp/error.c gcc/cp/error.c
old mode 100644
new mode 100755
index a75fc4e..a8f52cd
--- gcc/cp/error.c
+++ gcc/cp/error.c
@@ -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;
diff --git gcc/cp/parser.c gcc/cp/parser.c
old mode 100644
new mode 100755
index 319da21..05cb9a5
--- gcc/cp/parser.c
+++ gcc/cp/parser.c
@@ -6054,6 +6054,168 @@ 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.  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
 
@@ -6075,41 +6237,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;
 }
 
@@ -9336,6 +9535,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 = fix_array_notation_exprs (compound_stmt);
   return compound_stmt;
 }
 
@@ -9528,6 +9729,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;
@@ -10088,6 +10297,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;
 
@@ -10114,6 +10329,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;
 
@@ -10132,8 +10356,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;
 
@@ -16708,30 +16941,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
@@ -18102,6 +18358,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 = fix_array_notation_exprs (body);
+  
   /* Finish the function body.  */
   finish_function_body (body);
 
@@ -22081,6 +22342,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) =
+      fix_array_notation_exprs (DECL_SAVED_TREE (current_function_decl));
+  
   /* Finish the function.  */
   fn = finish_function ((ctor_initializer_p ? 1 : 0) |
 			(inline_p ? 2 : 0));
diff --git gcc/cp/pt.c gcc/cp/pt.c
old mode 100644
new mode 100755
index 5d83cc6..485b718
--- gcc/cp/pt.c
+++ gcc/cp/pt.c
@@ -13740,6 +13740,43 @@ 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));
+
+	/* We do type-checking here for templatized array notation triplets.  */
+	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 (error_mark_node);
+	  }
+	if (!TREE_TYPE (length) || !INTEGRAL_TYPE_P (TREE_TYPE (length)))
+	  {
+	    error_at (loc, "length of array notation triplet is not an "
+		      "integer");
+	    RETURN (error_mark_node);
+	  }
+	if (!TREE_TYPE (stride) || !INTEGRAL_TYPE_P (TREE_TYPE (stride)))
+	  {
+	    error_at (loc, "stride of array notation triplet is not an "
+		      "integer");
+	    RETURN (error_mark_node);
+	  }
+	if (TREE_CODE (TREE_TYPE (op1)) == FUNCTION_TYPE)
+	  {
+	    error_at (loc, "array notations cannot be used with function type");
+	    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));
@@ -15712,6 +15749,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;
@@ -19112,6 +19152,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) = fix_array_notation_exprs (DECL_SAVED_TREE (d));
+      
       /* Finish the function.  */
       d = finish_function (0);
       expand_or_defer_fn (d);
diff --git gcc/cp/semantics.c gcc/cp/semantics.c
index b5c3b0a..77467bf 100644
--- gcc/cp/semantics.c
+++ gcc/cp/semantics.c
@@ -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 expr. has a builtin array notation function, then its
+	 OK.  */
+      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 ())
@@ -8066,6 +8082,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);
@@ -8877,6 +8894,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:
diff --git gcc/cp/tree.c gcc/cp/tree.c
index 8524f6c..dd2fda4 100644
--- gcc/cp/tree.c
+++ gcc/cp/tree.c
@@ -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;
diff --git gcc/cp/typeck.c gcc/cp/typeck.c
old mode 100644
new mode 100755
index 11ac85b..06979f9
--- gcc/cp/typeck.c
+++ gcc/cp/typeck.c
@@ -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
+      && fndecl && is_cilkplus_reduce_builtin (fndecl))
+    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);
diff --git gcc/testsuite/ChangeLog gcc/testsuite/ChangeLog
old mode 100644
new mode 100755
diff --git gcc/testsuite/c-c++-common/cilk-plus/AN/array_test1.c gcc/testsuite/c-c++-common/cilk-plus/AN/array_test1.c
index e4f1ea8..282a55d 100644
--- gcc/testsuite/c-c++-common/cilk-plus/AN/array_test1.c
+++ gcc/testsuite/c-c++-common/cilk-plus/AN/array_test1.c
@@ -1,4 +1,4 @@
-/* { dg-do compile } */
+/* { dg-do run } */
 /* { dg-options "-fcilkplus" } */
 
 #include <stdlib.h>
@@ -47,7 +47,7 @@ int main2 (char **argv)
   array[x:y:z] = 505;
   for (ii = x; ii < 10; ii += z)
     if (array[ii] != 505)
-      return 2;
+      return 4;
     
   x = atoi(argv[1]);
   z = (10-atoi(argv[1]))/atoi(argv[1]);
@@ -57,7 +57,7 @@ int main2 (char **argv)
 
   for (ii = x; ii < 10; ii += z)
     if (array[ii] != 25)
-      return 1;
+      return 5;
   x = atoi(argv[1]);
   z = (10-atoi(argv[1]))/atoi(argv[1]);
   y = 10-atoi(argv[1]);
@@ -66,19 +66,19 @@ int main2 (char **argv)
     1400;
   for (ii = x; ii < 10; ii += z)
     if (array[ii] != 1400)
-      return 1;
+      return 6;
   
 
   array[atoi("5"):5:1] = 5555;
   
   for (ii = atoi ("5"); ii < 10; ii++)
     if (array[ii] != 5555)
-      return 2;
+      return 7;
   
 
   array[atoi("5"):atoi("5"):atoi("1")] = 9999;
   for (ii = atoi ("5"); ii < (atoi ("5") + atoi ("5")); ii += atoi ("1"))
     if (array[ii] != 9999)
-      return 3;
+      return 8;
   return 0;
 }
diff --git gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c
index d17d8cf..579d396 100644
--- gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c
+++ gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c
@@ -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;
 
diff --git gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
index 35eb115..14421d9 100644
--- gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
+++ gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
@@ -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;
diff --git gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c
old mode 100644
new mode 100755
index a0a3742..18816e0
--- gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c
+++ gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c
@@ -8,4 +8,4 @@ int main (void)
   array2[:] = array2[: ;  /* { dg-error "expected ']'" } */
 
   return 0;
-} /* { dg-error "expected ';' before" } */
+} /* { dg-error "expected ';' before" "" { target c } } */
diff --git gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c
index 2e86b4f..4314090 100644
--- gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c
+++ gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c
@@ -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 }  } */
 }
diff --git gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c
index 34dfa16..47b5979 100644
--- gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c
+++ gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c
@@ -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 } } */
 }
diff --git gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c
index eba28a8..a0efc04 100644
--- gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c
+++ gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c
@@ -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;
 }
diff --git gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c
index cabdb23..793afb2 100755
--- gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c
+++ gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c
@@ -4,11 +4,11 @@
 int A[10];
 
 int main () {
-  char c = (char)N; /* { dg-error "undeclared" } */
+  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 }  7 } */
 
diff --git gcc/testsuite/c-c++-common/cilk-plus/AN/sec_implicit_ex.c gcc/testsuite/c-c++-common/cilk-plus/AN/sec_implicit_ex.c
index c22b818..b863276 100644
--- gcc/testsuite/c-c++-common/cilk-plus/AN/sec_implicit_ex.c
+++ gcc/testsuite/c-c++-common/cilk-plus/AN/sec_implicit_ex.c
@@ -1,9 +1,6 @@
 /* { dg-do run } */
 /* { dg-options "-fcilkplus" } */
 
-void abort (void);
-void exit  (int);
-
 
 int main(void)
 {
@@ -24,10 +21,7 @@ int main(void)
     for (jj = 0; jj < 10; jj++)
       for (kk = 0; kk < 10; kk++)
 	if (array_3[ii][jj][kk] != array_3C[ii][jj][kk])
-	  abort ();
+	  return 1;
 	
-
-  exit (0);
-  
   return 0;
 }
diff --git gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c
index 843745e..3b0777e 100644
--- gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c
+++ gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c
@@ -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 gcc/testsuite/g++.dg/cilk-plus/AN/array_test1_tplt.cc gcc/testsuite/g++.dg/cilk-plus/AN/array_test1_tplt.cc
new file mode 100644
index 0000000..e9ee7ec
--- /dev/null
+++ gcc/testsuite/g++.dg/cilk-plus/AN/array_test1_tplt.cc
@@ -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 gcc/testsuite/g++.dg/cilk-plus/AN/array_test2_tplt.cc gcc/testsuite/g++.dg/cilk-plus/AN/array_test2_tplt.cc
new file mode 100644
index 0000000..87c37e1
--- /dev/null
+++ gcc/testsuite/g++.dg/cilk-plus/AN/array_test2_tplt.cc
@@ -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 gcc/testsuite/g++.dg/cilk-plus/AN/array_test_ND_tplt.cc gcc/testsuite/g++.dg/cilk-plus/AN/array_test_ND_tplt.cc
new file mode 100644
index 0000000..479ba13
--- /dev/null
+++ gcc/testsuite/g++.dg/cilk-plus/AN/array_test_ND_tplt.cc
@@ -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 gcc/testsuite/g++.dg/cilk-plus/AN/braced_list.cc gcc/testsuite/g++.dg/cilk-plus/AN/braced_list.cc
new file mode 100755
index 0000000..b91de7a
--- /dev/null
+++ gcc/testsuite/g++.dg/cilk-plus/AN/braced_list.cc
@@ -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 gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_custom_tplt.cc gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_custom_tplt.cc
new file mode 100644
index 0000000..fd60063
--- /dev/null
+++ gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_custom_tplt.cc
@@ -0,0 +1,128 @@
+/* { 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;
+#if 1
+  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);
+    }
+#endif 
+#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 gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_mutating_tplt.cc gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_mutating_tplt.cc
new file mode 100644
index 0000000..d4267c5
--- /dev/null
+++ gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_mutating_tplt.cc
@@ -0,0 +1,136 @@
+/* { 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;
+#if 1
+  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;
+    }
+#endif
+#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 gcc/testsuite/g++.dg/cilk-plus/AN/fp_triplet_values_tplt.c gcc/testsuite/g++.dg/cilk-plus/AN/fp_triplet_values_tplt.c
new file mode 100644
index 0000000..1387558
--- /dev/null
+++ gcc/testsuite/g++.dg/cilk-plus/AN/fp_triplet_values_tplt.c
@@ -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 gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp
new file mode 100644
index 0000000..a153529
--- /dev/null
+++ gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp
@@ -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
diff --git gcc/testsuite/g++.dg/dg.exp gcc/testsuite/g++.dg/dg.exp
old mode 100644
new mode 100755
index 7201359..710218e
--- gcc/testsuite/g++.dg/dg.exp
+++ gcc/testsuite/g++.dg/dg.exp
@@ -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/*]

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH] Cilk Plus Array Notation for C++
  2013-06-10 20:21 [PATCH] Cilk Plus Array Notation for C++ Iyer, Balaji V
@ 2013-06-12 16:34 ` Aldy Hernandez
  2013-06-12 17:20   ` Iyer, Balaji V
                     ` (2 more replies)
  0 siblings, 3 replies; 40+ messages in thread
From: Aldy Hernandez @ 2013-06-12 16:34 UTC (permalink / raw)
  To: Iyer, Balaji V; +Cc: gcc-patches, Jason Merrill (jason@redhat.com), rth

[Jason/Richard: there are some things below I could use your feedback on.]

Hi Balaji.

Overall, a lot of the stuff in cp-array-notation.c looks familiar from 
the C front-end changes.  Can't you reuse a lot of it?

Otherwise, here are some minor nits...

> +      /* If the function call is builtin array notation function then we do not
> +	 need to do any type conversion.  */
> +      if (flag_enable_cilkplus && fn && TREE_CODE (fn) == FUNCTION_DECL
> +	  && DECL_NAME (fn) && IDENTIFIER_POINTER (DECL_NAME (fn))
> +	  && !strncmp (IDENTIFIER_POINTER (DECL_NAME (fn)), "__sec_reduce", 12))
> +	val = arg;

Don't we have BUILT_IN_CILKPLUS_SEC_REDUCE* now?  So you shouldn't need 
to poke at the actual identifier.  And even so, won't the above strncmp 
match __sec_reducegarbage?

> +/* This function parses Cilk Plus array notations.  The starting index is
> +   passed in INIT_INDEX and the array name is passed in ARRAY_VALUE.  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.  */
> +

It looks like a NULL in INIT_INDEX is a specially handled case.  Perhaps 
you should document that INIT_INDEX can be null and what it means. 
Also, you don't need to document what internal variable name you are 
using as a return value (VALUE_TREE).  Perhaps instead of "The return 
value..." you could write "This function returns the ARRAY_NOTATION_REF 
node." or something like it.

> +    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));
> +
> +	/* We do type-checking here for templatized array notation triplets.  */
> +	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 (error_mark_node);
> +	  }
> +	if (!TREE_TYPE (length) || !INTEGRAL_TYPE_P (TREE_TYPE (length)))
> +	  {
> +	    error_at (loc, "length of array notation triplet is not an "
> +		      "integer");
> +	    RETURN (error_mark_node);
> +	  }
> +	if (!TREE_TYPE (stride) || !INTEGRAL_TYPE_P (TREE_TYPE (stride)))
> +	  {
> +	    error_at (loc, "stride of array notation triplet is not an "
> +		      "integer");
> +	    RETURN (error_mark_node);
> +	  }
> +	if (TREE_CODE (TREE_TYPE (op1)) == FUNCTION_TYPE)
> +	  {
> +	    error_at (loc, "array notations cannot be used with function type");
> +	    RETURN (error_mark_node);
> +	  }
> +	RETURN (build_array_notation_ref (EXPR_LOCATION (t), op1, start_index,
> +					  length, stride, TREE_TYPE (op1)));
> +      }


You do all this type checking here, but aren't you doing the same type 
checking in build_array_notation_ref() which you're going to call 
anyway?  It looks like there is some code duplication going on.

Also, I see you have a build_array_notation_ref() in 
cp/cp-array-notation.c and also in c/c-array-notation.c.  Can you not 
implement one function that handles both C and C++, or at the very least 
reuse some of the common things?

You are missing a ChangeLog entry for the above snippet.

> +      /* If the return expr. has a builtin array notation function, then its
> +	 OK.  */
> +      if (rank >= 1)
> +	{
> +	  error_at (input_location, "array notation expression cannot be "
> +		    "used as a return value");
> +	  return error_mark_node;
> +	}

The comment doesn't seem to match the code, or am I missing something?

> +      /* If find_rank returns false,  then it should have reported an error,

Extra whitespace.

> +      if (rank > 1)
> +	{
> +	  error_at (loc, "rank of the array%'s index is greater than 1");
> +	  return error_mark_node;
> +	}

No corresponding test.

> +  /* 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.  */

Line too long, please wrap.

There are various lines throughout your patch that are pretty long (both 
in code and in ChangeLog entries).  I don't know what the official GNU 
guidelines say, but what I usually see as prior art in the GCC code base 
is something along the lines of wrapping around column 72.  Perhaps 
someone can pontificate on this, but lines reaching the 78-80 columns 
look pretty darn long to me.

> diff --git gcc/testsuite/c-c++-common/cilk-plus/AN/sec_implicit_ex.c gcc/testsuite/c-c++-common/cilk-plus/AN/sec_implicit_ex.c
> index c22b818..b863276 100644
> --- gcc/testsuite/c-c++-common/cilk-plus/AN/sec_implicit_ex.c
> +++ gcc/testsuite/c-c++-common/cilk-plus/AN/sec_implicit_ex.c
> @@ -1,9 +1,6 @@
>  /* { dg-do run } */
>  /* { dg-options "-fcilkplus" } */
>
> -void abort (void);
> -void exit  (int);
> -
>
>  int main(void)
>  {
> @@ -24,10 +21,7 @@ int main(void)
>      for (jj = 0; jj < 10; jj++)
>        for (kk = 0; kk < 10; kk++)
>  	if (array_3[ii][jj][kk] != array_3C[ii][jj][kk])
> -	  abort ();
> +	  return 1;
>  	
> -
> -  exit (0);
> -
 >   return 0;

Changes to existing tests should be submitted as a separate patch, since 
this doesn't seem to be C++ specific.  And BTW, this particular test 
change can be committed as obvious.

> +  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;
> +#if 1
> +  for (int ii = 0; ii < 10; ii++)
> +    {
> +      if (ii%2 && ii)

Remove this redundant #if 1/#endif pair.  Similarly in other tests.

> +	    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");

No corresponding test, or is this handled by the existing 
c-c++-common/cilk-plus tests?

> +		  /* 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");

No need to document the obvious.  The error message can be used in lieu 
of the comment :).  Also, no corresponding test.  I didn't see one 
matching in c-c++-common/cilkplus either.

> +	      /* Disable correcting single colon correcting to scope.  */
> +	      parser->colon_corrects_to_scope_p = false;

No need to document the obvious.

I suggest a different name for fix_array_notation_exprs() to avoid 
confusion with the C function fix_array_notation_expr() (no final "s"). 
  Perhaps cpp_fix_array_notation_expr, or something similar?

> +/* Handles expression of the form "a[i:j:k]" or "a[:]" or "a[i:j]," which
> +   denotes an array notation expression.  If a is a variable or a member, then

Do you mean "ARRAY" instead of "a"?

> +   we generate a ARRAY_NOTATION_REF front-end tree and return it.

s/a ARRAY/an ARRAY/

> +   This tree is broken down to ARRAY_REF toward the end of parsing.
> +   ARRAY_NOTATION_REF tree holds the START_INDEX, LENGTH, STRIDE and the TYPE
> +   of ARRAY_REF.  Restrictions on START_INDEX, LENGTH and STRIDE is same as that
> +   of the 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)

Overall this function comment needs to be reworded.  From reading the 
comment, I still don't know what the function actually does and what it 
returns.  "Handles expression..." is rather ambiguous.  Perhaps 
something like "Given a blah blah blah in ARRAY, construct an 
ARRAY_NOTATION_REF and return it.  START_INDEX is blah, LENGTH is blah, 
etc etc".

Again, you can probably reuse a lot of the C counterpart.  It looks like 
a lot of the same code.

> +  XDELETEVEC (compare_expr);
> +  XDELETEVEC (expr_incr);
> +  XDELETEVEC (ind_init);
> +  XDELETEVEC (array_var);
> +
> +  for (ii = 0; ii < list_size; ii++)
> +    {
> +      XDELETEVEC (count_down[ii]);
> +      XDELETEVEC (array_value[ii]);
> +      XDELETEVEC (array_stride[ii]);
> +      XDELETEVEC (array_length[ii]);
> +      XDELETEVEC (array_start[ii]);
> +      XDELETEVEC (array_ops[ii]);
> +      XDELETEVEC (array_vector[ii]);
> +    }
> +
> +  XDELETEVEC (count_down);
> +  XDELETEVEC (array_value);
> +  XDELETEVEC (array_stride);
> +  XDELETEVEC (array_length);
> +  XDELETEVEC (array_start);
> +  XDELETEVEC (array_ops);
> +  XDELETEVEC (array_vector);

I see a lot of this business going on.  Perhaps one of the core 
maintainers can comment, but I would rather use an obstack, and avoid 
having to keep track of all these little buckets-- which seems rather 
error prone, and then free the obstack all in one swoop.  But I'll defer 
to Richard or Jason.


> +		     is not, we convert induction variable to stride's

Rephrase as "is not, convert the induction variable to the stride's"
Similarly in a few other places.  It looks like you used the same comment.

> +		  /* 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, we stay safe and convert

s/type is, we stay safe/type is.  We stay safe/.
Similarly in a few other places.  It looks like you used the same comment.

> +		     everything to integer.  The reason why we pick integer

s/pick integer/pick an integer
Similarly in a few other places.

> +/* 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
> +build_x_array_notation_expr (location_t location, tree lhs,
> +			     enum tree_code modifycode, tree rhs,
> +			     tsubst_flags_t complain)

This is called "build_x_array_notation_expr", but it doesn't look like 
we build any ARRAY_NOTATION_EXPRs in here.  Perhaps a better name would 
be "expand_array_notation_expr" (or something to that effect)?

> +static tree
> +fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)

It looks like this function expands the __sec_reduce* builtins.  Perhaps 
it would be cleaner to rename it as such?  Maybe... 
"expand_sec_reduce_builtin" or something?

The fact that you are sometimes using "build_*" and sometimes "fix_*" to 
denote expansion is confusing.

> +/* Returns true of NODE has a call_expression with ARRAY_NOTATION_REF tree.  */
> +
> +static bool
> +has_call_expr_with_array_notation (tree node)

s/of NODE/if NODE

Thanks.
Aldy

^ permalink raw reply	[flat|nested] 40+ messages in thread

* RE: [PATCH] Cilk Plus Array Notation for C++
  2013-06-12 16:34 ` Aldy Hernandez
@ 2013-06-12 17:20   ` Iyer, Balaji V
  2013-06-12 17:40     ` Aldy Hernandez
  2013-06-12 20:50   ` Iyer, Balaji V
  2013-06-12 21:32   ` Iyer, Balaji V
  2 siblings, 1 reply; 40+ messages in thread
From: Iyer, Balaji V @ 2013-06-12 17:20 UTC (permalink / raw)
  To: Aldy Hernandez; +Cc: gcc-patches, Jason Merrill (jason@redhat.com), rth

Hi Aldy,
	Below are my responses to a couple of the things you pointed out.

Thanks,

Balaji V. Iyer.

> -----Original Message-----
> From: Aldy Hernandez [mailto:aldyh@redhat.com]
> Sent: Wednesday, June 12, 2013 12:34 PM
> To: Iyer, Balaji V
> Cc: gcc-patches@gcc.gnu.org; Jason Merrill (jason@redhat.com);
> rth@redhat.com
> Subject: Re: [PATCH] Cilk Plus Array Notation for C++
> 
> [Jason/Richard: there are some things below I could use your feedback on.]
> 
> Hi Balaji.
> 
> Overall, a lot of the stuff in cp-array-notation.c looks familiar from the C front-
> end changes.  Can't you reuse a lot of it?

I looked into trying to combine many functionality. The issue that prohibited me was templates and extra trees. For example, IF_STMT, FOR_STMT, MODOP_EXPR, etc are not available in C but are in C++. So, I had to add this additional check for those. Also, if we are processing templates we have to create different kind of trees (e.g MODOP_EXPR intead of MODIFY_EXPR).

One way to do it is to break up the places where I am using C++ specific code and add a language hook to handle those. I tried doing that a while back and the whole thing looked a lot messy and I would imagine it would be hard to debug them in future (...atleast for me). This looked organized for me, even though a few code looks repeated. Also, the function names are repeated because they do similar things in C and C++ only thing is that the body of the function is different. 

> 
> > +    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));
> > +
> > +	/* We do type-checking here for templatized array notation triplets.  */
> > +	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 (error_mark_node);
> > +	  }
> > +	if (!TREE_TYPE (length) || !INTEGRAL_TYPE_P (TREE_TYPE (length)))
> > +	  {
> > +	    error_at (loc, "length of array notation triplet is not an "
> > +		      "integer");
> > +	    RETURN (error_mark_node);
> > +	  }
> > +	if (!TREE_TYPE (stride) || !INTEGRAL_TYPE_P (TREE_TYPE (stride)))
> > +	  {
> > +	    error_at (loc, "stride of array notation triplet is not an "
> > +		      "integer");
> > +	    RETURN (error_mark_node);
> > +	  }
> > +	if (TREE_CODE (TREE_TYPE (op1)) == FUNCTION_TYPE)
> > +	  {
> > +	    error_at (loc, "array notations cannot be used with function type");
> > +	    RETURN (error_mark_node);
> > +	  }
> > +	RETURN (build_array_notation_ref (EXPR_LOCATION (t), op1,
> start_index,
> > +					  length, stride, TREE_TYPE (op1)));
> > +      }
> 
> 
> You do all this type checking here, but aren't you doing the same type checking
> in build_array_notation_ref() which you're going to call anyway?  It looks like
> there is some code duplication going on.

The reason why we do this second type checking here is because we don't know what they could be when we are parsing it. For example, in:

T x,y,z
A[x:y:z]

x, y, z could be floats and that should be flagged as error, but if x, y z are ints, then its ok. We don't know this information until we hit this spot in pt.c

> 
> Also, I see you have a build_array_notation_ref() in cp/cp-array-notation.c and
> also in c/c-array-notation.c.  Can you not implement one function that handles
> both C and C++, or at the very least reuse some of the common things?

I looked into that also, but templates got in the way.

> 
> You are missing a ChangeLog entry for the above snippet.

That I will put in.


> 
> > +  XDELETEVEC (compare_expr);
> > +  XDELETEVEC (expr_incr);
> > +  XDELETEVEC (ind_init);
> > +  XDELETEVEC (array_var);
> > +
> > +  for (ii = 0; ii < list_size; ii++)
> > +    {
> > +      XDELETEVEC (count_down[ii]);
> > +      XDELETEVEC (array_value[ii]);
> > +      XDELETEVEC (array_stride[ii]);
> > +      XDELETEVEC (array_length[ii]);
> > +      XDELETEVEC (array_start[ii]);
> > +      XDELETEVEC (array_ops[ii]);
> > +      XDELETEVEC (array_vector[ii]);
> > +    }
> > +
> > +  XDELETEVEC (count_down);
> > +  XDELETEVEC (array_value);
> > +  XDELETEVEC (array_stride);
> > +  XDELETEVEC (array_length);
> > +  XDELETEVEC (array_start);
> > +  XDELETEVEC (array_ops);
> > +  XDELETEVEC (array_vector);
> 
> I see a lot of this business going on.  Perhaps one of the core
> maintainers can comment, but I would rather use an obstack, and avoid
> having to keep track of all these little buckets-- which seems rather
> error prone, and then free the obstack all in one swoop.  But I'll defer
> to Richard or Jason.
>

They are temporary variables that are used to store information necessary for expansion. To me, dynamic arrays seem to be the most straight-forward way to do it. Changing them would involve pretty much rewriting the whole thing and thus maybe breaking the stability. So, if it is not a huge issue, I would like to keep the dynamic arrays. They are not being used anywhere else just inside the function. 

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH] Cilk Plus Array Notation for C++
  2013-06-12 17:20   ` Iyer, Balaji V
@ 2013-06-12 17:40     ` Aldy Hernandez
  2013-06-12 18:02       ` Iyer, Balaji V
  0 siblings, 1 reply; 40+ messages in thread
From: Aldy Hernandez @ 2013-06-12 17:40 UTC (permalink / raw)
  To: Iyer, Balaji V; +Cc: gcc-patches, Jason Merrill (jason@redhat.com), rth


>> Overall, a lot of the stuff in cp-array-notation.c looks familiar
>> from the C front- end changes.  Can't you reuse a lot of it?
>
> I looked into trying to combine many functionality. The issue that
> prohibited me was templates and extra trees. For example, IF_STMT,
> FOR_STMT, MODOP_EXPR, etc are not available in C but are in C++. So,
> I had to add this additional check for those. Also, if we are
> processing templates we have to create different kind of trees (e.g
> MODOP_EXPR intead of MODIFY_EXPR).

I see.

>
> One way to do it is to break up the places where I am using C++
> specific code and add a language hook to handle those. I tried doing
> that a while back and the whole thing looked a lot messy and I would
> imagine it would be hard to debug them in future (...atleast for me).
> This looked organized for me, even though a few code looks repeated.

That's what I had in mind, but if you tried it and it looks worse, I 
guess I can live with it.

>> You do all this type checking here, but aren't you doing the same
>> type checking in build_array_notation_ref() which you're going to
>> call anyway?  It looks like there is some code duplication going
>> on.
>
> The reason why we do this second type checking here is because we
> don't know what they could be when we are parsing it. For example,
> in:

Couldn't you abstract the type checking out into a helper function 
shared by both routines?

>> Also, I see you have a build_array_notation_ref() in
>> cp/cp-array-notation.c and also in c/c-array-notation.c.  Can you
>> not implement one function that handles both C and C++, or at the
>> very least reuse some of the common things?
>
> I looked into that also, but templates got in the way.

Ughh... ok, I'll let Jason deal with this then.

>>> +  XDELETEVEC (compare_expr); +  XDELETEVEC (expr_incr); +
>>> XDELETEVEC (ind_init); +  XDELETEVEC (array_var); + +  for (ii =
>>> 0; ii < list_size; ii++) +    { +      XDELETEVEC
>>> (count_down[ii]); +      XDELETEVEC (array_value[ii]); +
>>> XDELETEVEC (array_stride[ii]); +      XDELETEVEC
>>> (array_length[ii]); +      XDELETEVEC (array_start[ii]); +
>>> XDELETEVEC (array_ops[ii]); +      XDELETEVEC
>>> (array_vector[ii]); +    } + +  XDELETEVEC (count_down); +
>>> XDELETEVEC (array_value); +  XDELETEVEC (array_stride); +
>>> XDELETEVEC (array_length); +  XDELETEVEC (array_start); +
>>> XDELETEVEC (array_ops); +  XDELETEVEC (array_vector);
>>
>> I see a lot of this business going on.  Perhaps one of the core
>> maintainers can comment, but I would rather use an obstack, and
>> avoid having to keep track of all these little buckets-- which
>> seems rather error prone, and then free the obstack all in one
>> swoop.  But I'll defer to Richard or Jason.
>>
>
> They are temporary variables that are used to store information
> necessary for expansion. To me, dynamic arrays seem to be the most
> straight-forward way to do it. Changing them would involve pretty
> much rewriting the whole thing and thus maybe breaking the stability.
> So, if it is not a huge issue, I would like to keep the dynamic
> arrays. They are not being used anywhere else just inside the
> function.
>

This is not huge, so don't worry, but XNEWVEC is just a wrapper to 
xmalloc (see include/libiberty.h).  You could do the exact thing with 
XOBNEWVEC and save yourself all the XDELETEVECs, with one obstack_free().

^ permalink raw reply	[flat|nested] 40+ messages in thread

* RE: [PATCH] Cilk Plus Array Notation for C++
  2013-06-12 17:40     ` Aldy Hernandez
@ 2013-06-12 18:02       ` Iyer, Balaji V
  0 siblings, 0 replies; 40+ messages in thread
From: Iyer, Balaji V @ 2013-06-12 18:02 UTC (permalink / raw)
  To: Aldy Hernandez; +Cc: gcc-patches, Jason Merrill (jason@redhat.com), rth



> -----Original Message-----
> From: Aldy Hernandez [mailto:aldyh@redhat.com]
> Sent: Wednesday, June 12, 2013 1:40 PM
> To: Iyer, Balaji V
> Cc: gcc-patches@gcc.gnu.org; Jason Merrill (jason@redhat.com);
> rth@redhat.com
> Subject: Re: [PATCH] Cilk Plus Array Notation for C++
> 
> 
> >> Overall, a lot of the stuff in cp-array-notation.c looks familiar
> >> from the C front- end changes.  Can't you reuse a lot of it?
> >
> > I looked into trying to combine many functionality. The issue that
> > prohibited me was templates and extra trees. For example, IF_STMT,
> > FOR_STMT, MODOP_EXPR, etc are not available in C but are in C++. So, I
> > had to add this additional check for those. Also, if we are processing
> > templates we have to create different kind of trees (e.g MODOP_EXPR
> > intead of MODIFY_EXPR).
> 
> I see.
> 
> >
> > One way to do it is to break up the places where I am using C++
> > specific code and add a language hook to handle those. I tried doing
> > that a while back and the whole thing looked a lot messy and I would
> > imagine it would be hard to debug them in future (...atleast for me).
> > This looked organized for me, even though a few code looks repeated.
> 
> That's what I had in mind, but if you tried it and it looks worse, I guess I can live
> with it.
> 
> >> You do all this type checking here, but aren't you doing the same
> >> type checking in build_array_notation_ref() which you're going to
> >> call anyway?  It looks like there is some code duplication going on.
> >
> > The reason why we do this second type checking here is because we
> > don't know what they could be when we are parsing it. For example,
> > in:
> 
> Couldn't you abstract the type checking out into a helper function shared by
> both routines?


Yes, that I could do. I will fix it in the new  upcoming Array Notation for C++ patch.

Thanks,

Balaji V. Iyer.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* RE: [PATCH] Cilk Plus Array Notation for C++
  2013-06-12 16:34 ` Aldy Hernandez
  2013-06-12 17:20   ` Iyer, Balaji V
@ 2013-06-12 20:50   ` Iyer, Balaji V
  2013-06-13 16:11     ` Aldy Hernandez
  2013-06-12 21:32   ` Iyer, Balaji V
  2 siblings, 1 reply; 40+ messages in thread
From: Iyer, Balaji V @ 2013-06-12 20:50 UTC (permalink / raw)
  To: Aldy Hernandez; +Cc: gcc-patches, Jason Merrill (jason@redhat.com), rth

[-- Attachment #1: Type: text/plain, Size: 13691 bytes --]

Hi Aldy,
	Please see my comments below with the fixed patch.

Thanks,

Balaji V. Iyer.

> -----Original Message-----
> From: Aldy Hernandez [mailto:aldyh@redhat.com]
> Sent: Wednesday, June 12, 2013 12:34 PM
> To: Iyer, Balaji V
> Cc: gcc-patches@gcc.gnu.org; Jason Merrill (jason@redhat.com);
> rth@redhat.com
> Subject: Re: [PATCH] Cilk Plus Array Notation for C++
> 
> [Jason/Richard: there are some things below I could use your feedback on.]
> 
> Hi Balaji.
> 
> Overall, a lot of the stuff in cp-array-notation.c looks familiar from the C front-
> end changes.  Can't you reuse a lot of it?
> 
> Otherwise, here are some minor nits...
> 
> > +      /* If the function call is builtin array notation function then we do not
> > +	 need to do any type conversion.  */
> > +      if (flag_enable_cilkplus && fn && TREE_CODE (fn) == FUNCTION_DECL
> > +	  && DECL_NAME (fn) && IDENTIFIER_POINTER (DECL_NAME (fn))
> > +	  && !strncmp (IDENTIFIER_POINTER (DECL_NAME (fn)),
> "__sec_reduce", 12))
> > +	val = arg;
> 
> Don't we have BUILT_IN_CILKPLUS_SEC_REDUCE* now?  So you shouldn't need
> to poke at the actual identifier.  And even so, won't the above strncmp match
> __sec_reducegarbage?

FIXED!

> 
> > +/* This function parses Cilk Plus array notations.  The starting index is
> > +   passed in INIT_INDEX and the array name is passed in ARRAY_VALUE.  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.  */
> > +
> 
> It looks like a NULL in INIT_INDEX is a specially handled case.  Perhaps you
> should document that INIT_INDEX can be null and what it means.
> Also, you don't need to document what internal variable name you are using as
> a return value (VALUE_TREE).  Perhaps instead of "The return value..." you could
> write "This function returns the ARRAY_NOTATION_REF node." or something
> like it.

It is documented inside the function, right before checking for !init_index. Is that enough?

> 
> > +    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));
> > +
> > +	/* We do type-checking here for templatized array notation triplets.  */
> > +	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 (error_mark_node);
> > +	  }
> > +	if (!TREE_TYPE (length) || !INTEGRAL_TYPE_P (TREE_TYPE (length)))
> > +	  {
> > +	    error_at (loc, "length of array notation triplet is not an "
> > +		      "integer");
> > +	    RETURN (error_mark_node);
> > +	  }
> > +	if (!TREE_TYPE (stride) || !INTEGRAL_TYPE_P (TREE_TYPE (stride)))
> > +	  {
> > +	    error_at (loc, "stride of array notation triplet is not an "
> > +		      "integer");
> > +	    RETURN (error_mark_node);
> > +	  }
> > +	if (TREE_CODE (TREE_TYPE (op1)) == FUNCTION_TYPE)
> > +	  {
> > +	    error_at (loc, "array notations cannot be used with function type");
> > +	    RETURN (error_mark_node);
> > +	  }
> > +	RETURN (build_array_notation_ref (EXPR_LOCATION (t), op1,
> start_index,
> > +					  length, stride, TREE_TYPE (op1)));
> > +      }
> 
> 
> You do all this type checking here, but aren't you doing the same type checking
> in build_array_notation_ref() which you're going to call anyway?  It looks like
> there is some code duplication going on.
> 
> Also, I see you have a build_array_notation_ref() in cp/cp-array-notation.c and
> also in c/c-array-notation.c.  Can you not implement one function that handles
> both C and C++, or at the very least reuse some of the common things?

As we discussed in the previous email-exchange, I have created a new function called cilkplus_an_triplet_types_ok_p (). The reason why I prefixed "cilkplus_an" is because it is not a static function and I want to make sure this is unique and descriptive and does not cause any interference with anything present or future. 

> 
> You are missing a ChangeLog entry for the above snippet.

I have put it in now.

> 
> > +      /* If the return expr. has a builtin array notation function, then its
> > +	 OK.  */
> > +      if (rank >= 1)
> > +	{
> > +	  error_at (input_location, "array notation expression cannot be "
> > +		    "used as a return value");
> > +	  return error_mark_node;
> > +	}
> 
> The comment doesn't seem to match the code, or am I missing something?
> 
> > +      /* If find_rank returns false,  then it should have reported an
> > + error,

FIXED

> 
> Extra whitespace.
> 
> > +      if (rank > 1)
> > +	{
> > +	  error_at (loc, "rank of the array%'s index is greater than 1");
> > +	  return error_mark_node;
> > +	}
> 
> No corresponding test.

This is being tested in the file "testsuite/c-c++-common/cilk-plus/AN/gather-scatter-errors.c"

> 
> > +  /* 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.  */
> 
> Line too long, please wrap.
> 
> There are various lines throughout your patch that are pretty long (both in code
> and in ChangeLog entries).  I don't know what the official GNU guidelines say,
> but what I usually see as prior art in the GCC code base is something along the
> lines of wrapping around column 72.  Perhaps someone can pontificate on this,
> but lines reaching the 78-80 columns look pretty darn long to me.

The line length is specified to be at most 80 characters (http://gcc.gnu.org/codingconventions.html#Line). I have followed it everywhere except in the cases of dg-error since I can't fit them all in one line.
> 
> > diff --git gcc/testsuite/c-c++-common/cilk-plus/AN/sec_implicit_ex.c
> > gcc/testsuite/c-c++-common/cilk-plus/AN/sec_implicit_ex.c
> > index c22b818..b863276 100644
> > --- gcc/testsuite/c-c++-common/cilk-plus/AN/sec_implicit_ex.c
> > +++ gcc/testsuite/c-c++-common/cilk-plus/AN/sec_implicit_ex.c
> > @@ -1,9 +1,6 @@
> >  /* { dg-do run } */
> >  /* { dg-options "-fcilkplus" } */
> >
> > -void abort (void);
> > -void exit  (int);
> > -
> >
> >  int main(void)
> >  {
> > @@ -24,10 +21,7 @@ int main(void)
> >      for (jj = 0; jj < 10; jj++)
> >        for (kk = 0; kk < 10; kk++)
> >  	if (array_3[ii][jj][kk] != array_3C[ii][jj][kk])
> > -	  abort ();
> > +	  return 1;
> >
> > -
> > -  exit (0);
> > -
>  >   return 0;
> 
> Changes to existing tests should be submitted as a separate patch, since this
> doesn't seem to be C++ specific.  And BTW, this particular test change can be
> committed as obvious.

OK will do.  What about adding {target c} and {target c++} for test cases. Can that be submitted with the patch?

> 
> > +  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; #if 1
> > +  for (int ii = 0; ii < 10; ii++)
> > +    {
> > +      if (ii%2 && ii)
> 
> Remove this redundant #if 1/#endif pair.  Similarly in other tests.

FIXED!

> 
> > +	    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");
> 
> No corresponding test, or is this handled by the existing
> c-c++-common/cilk-plus tests?

Please see c-c++-common/cilk-plus/AN/misc.c

> 
> > +		  /* 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");
> 
> No need to document the obvious.  The error message can be used in lieu of the
> comment :).  Also, no corresponding test.  I didn't see one matching in c-c++-
> common/cilkplus either.

OK. This testcase (testsuite/c-c++-common/cilk-plus/AN/fn_ptr.c) checks this error.

> 
> > +	      /* Disable correcting single colon correcting to scope.  */
> > +	      parser->colon_corrects_to_scope_p = false;
> 
> No need to document the obvious.

FIXED!

> 
> I suggest a different name for fix_array_notation_exprs() to avoid confusion
> with the C function fix_array_notation_expr() (no final "s").
>   Perhaps cpp_fix_array_notation_expr, or something similar?
> 
> > +/* Handles expression of the form "a[i:j:k]" or "a[:]" or "a[i:j]," which
> > +   denotes an array notation expression.  If a is a variable or a
> > +member, then
> 
> Do you mean "ARRAY" instead of "a"?
> 
> > +   we generate a ARRAY_NOTATION_REF front-end tree and return it.
> 
> s/a ARRAY/an ARRAY/
> 
> > +   This tree is broken down to ARRAY_REF toward the end of parsing.
> > +   ARRAY_NOTATION_REF tree holds the START_INDEX, LENGTH, STRIDE and
> the TYPE
> > +   of ARRAY_REF.  Restrictions on START_INDEX, LENGTH and STRIDE is same
> as that
> > +   of the 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)
> 
> Overall this function comment needs to be reworded.  From reading the
> comment, I still don't know what the function actually does and what it returns.
> "Handles expression..." is rather ambiguous.  Perhaps something like "Given a
> blah blah blah in ARRAY, construct an ARRAY_NOTATION_REF and return it.
> START_INDEX is blah, LENGTH is blah, etc etc".

Reworded it. Please let me know if it is OK.

> 
> Again, you can probably reuse a lot of the C counterpart.  It looks like a lot of
> the same code.
> 
> > +  XDELETEVEC (compare_expr);
> > +  XDELETEVEC (expr_incr);
> > +  XDELETEVEC (ind_init);
> > +  XDELETEVEC (array_var);
> > +
> > +  for (ii = 0; ii < list_size; ii++)
> > +    {
> > +      XDELETEVEC (count_down[ii]);
> > +      XDELETEVEC (array_value[ii]);
> > +      XDELETEVEC (array_stride[ii]);
> > +      XDELETEVEC (array_length[ii]);
> > +      XDELETEVEC (array_start[ii]);
> > +      XDELETEVEC (array_ops[ii]);
> > +      XDELETEVEC (array_vector[ii]);
> > +    }
> > +
> > +  XDELETEVEC (count_down);
> > +  XDELETEVEC (array_value);
> > +  XDELETEVEC (array_stride);
> > +  XDELETEVEC (array_length);
> > +  XDELETEVEC (array_start);
> > +  XDELETEVEC (array_ops);
> > +  XDELETEVEC (array_vector);
> 
> I see a lot of this business going on.  Perhaps one of the core maintainers can
> comment, but I would rather use an obstack, and avoid having to keep track of
> all these little buckets-- which seems rather error prone, and then free the
> obstack all in one swoop.  But I'll defer to Richard or Jason.
> 
> 
> > +		     is not, we convert induction variable to stride's
> 
> Rephrase as "is not, convert the induction variable to the stride's"
> Similarly in a few other places.  It looks like you used the same comment.

FIXED!

> 
> > +		  /* 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, we stay safe and convert
> 
> s/type is, we stay safe/type is.  We stay safe/.
> Similarly in a few other places.  It looks like you used the same comment.

FIXED!

> 
> > +		     everything to integer.  The reason why we pick integer
> 
> s/pick integer/pick an integer
> Similarly in a few other places.

FIXED!

> 
> > +/* 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
> > +build_x_array_notation_expr (location_t location, tree lhs,
> > +			     enum tree_code modifycode, tree rhs,
> > +			     tsubst_flags_t complain)
> 
> This is called "build_x_array_notation_expr", but it doesn't look like we build any
> ARRAY_NOTATION_EXPRs in here.  Perhaps a better name would be
> "expand_array_notation_expr" (or something to that effect)?

I renamed this function to "expand_an_in_modify_expr" to indicate that we are expanding array notations in modify expr.

> 
> > +static tree
> > +fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
> 
> It looks like this function expands the __sec_reduce* builtins.  Perhaps it would
> be cleaner to rename it as such?  Maybe...
> "expand_sec_reduce_builtin" or something?

FIXED!

> 
> The fact that you are sometimes using "build_*" and sometimes "fix_*" to
> denote expansion is confusing.

Replaced all the "fix" with "expand"

> 
> > +/* Returns true of NODE has a call_expression with ARRAY_NOTATION_REF
> > +tree.  */
> > +
> > +static bool
> > +has_call_expr_with_array_notation (tree node)
> 
> s/of NODE/if NODE

FIXED!

> 
> Thanks.
> Aldy

[-- Attachment #2: patch_array_notation_cpp.txt --]
[-- Type: text/plain, Size: 157027 bytes --]

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
old mode 100644
new mode 100755
index 2c93982..362f0bc
Binary files a/gcc/cp/ChangeLog and b/gcc/cp/ChangeLog differ
diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
index df8ed3e..6e80bcf 100644
--- a/gcc/cp/Make-lang.in
+++ b/gcc/cp/Make-lang.in
@@ -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)
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index dfd061a..64be41f 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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 100755
index 0000000..34c73f3
--- /dev/null
+++ b/gcc/cp/cp-array-notation.c
@@ -0,0 +1,2850 @@
+/* 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);
+}
+
+/* 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;
+}
+
+/* Returns true if NODE has a call_expression with ARRAY_NOTATION_REF tree.  */
+
+static bool
+has_call_expr_with_array_notation (tree node)
+{
+  int ii = 0;
+  
+  if (!contains_array_notation_expr (node))
+    return false;
+  
+  if (TREE_CODE (node) == ARRAY_NOTATION_REF)
+    return false;
+  else if (TREE_CODE (node) == DECL_EXPR)
+    {
+      tree x = DECL_EXPR_DECL (node);
+      if (x && TREE_CODE (x) != FUNCTION_DECL)
+	if (DECL_INITIAL (x))
+	  return has_call_expr_with_array_notation (DECL_INITIAL (x));
+	
+    }
+  else if (TREE_CODE (node) == STATEMENT_LIST)
+    {
+      tree_stmt_iterator ii_tsi;
+      for (ii_tsi = tsi_start (node); !tsi_end_p (ii_tsi); tsi_next (&ii_tsi))
+	return has_call_expr_with_array_notation (*tsi_stmt_ptr (ii_tsi));
+    }
+  else if (TREE_CODE (node) == CALL_EXPR)
+    {
+      if (is_cilkplus_reduce_builtin (CALL_EXPR_FN (node)) != BUILT_IN_NONE)
+	return true;
+	
+      if (is_sec_implicit_index_fn (CALL_EXPR_FN (node)))
+	return true;
+	 
+      if (TREE_CODE (TREE_OPERAND (node, 0)) == INTEGER_CST)
+	{
+	  int length = TREE_INT_CST_LOW (TREE_OPERAND (node, 0));
+	  bool x = false;
+	  for (ii = 0; ii < length; ii++)
+	    x |= contains_array_notation_expr (TREE_OPERAND (node, ii));
+	  return x;
+	}
+      else
+	gcc_unreachable  ();	  
+    } 
+  else
+    {
+      bool x = false;
+      for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (node)); ii++) 
+	x |= has_call_expr_with_array_notation (TREE_OPERAND (node, ii));
+      return x;
+    }
+  return false;
+}
+
+/* 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_expr, 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; 
+  tree new_var_init = NULL_TREE, new_exp_init = NULL_TREE;
+  vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
+  int s_jj = 0;
+  size_t list_size = 0, rank = 0, ii = 0, jj = 0;
+  tree **array_ops, *array_var, jj_tree;
+  tree **array_value, **array_stride, **array_length, **array_start;
+  tree  body, an_init, loop_with_init = alloc_stmt_list ();
+  tree *compare_expr, array_op0, *expr_incr, *ind_init, comp_node;
+  tree call_fn = NULL_TREE, identity_value = NULL_TREE, new_call_expr;
+  bool **count_down, **array_vector;
+  tree begin_var, lngth_var, strde_var;
+  location_t location = UNKNOWN_LOCATION;
+  tsubst_flags_t complain = tf_warning_or_error;
+
+  enum built_in_function an_type =
+    is_cilkplus_reduce_builtin (CALL_EXPR_FN (an_builtin_fn));
+  
+  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!  */
+      while (TREE_CODE (call_fn) == CONVERT_EXPR
+	     || TREE_CODE (call_fn) == NOP_EXPR)
+	call_fn = TREE_OPERAND (call_fn, 0);
+
+      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);
+
+      /* 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!  */
+      while (TREE_CODE (identity_value) == CONVERT_EXPR
+	     || TREE_CODE (identity_value) == NOP_EXPR)
+	identity_value = TREE_OPERAND (identity_value, 0);
+    }
+
+  while (TREE_CODE (func_parm) == CONVERT_EXPR
+	 || TREE_CODE (func_parm) == NOP_EXPR)
+    func_parm = TREE_OPERAND (func_parm, 0);
+  
+  location = EXPR_LOCATION (an_builtin_fn);
+  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);
+  
+  array_ops = XNEWVEC (tree *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_ops[ii] = XNEWVEC (tree,  rank);
+  
+  array_vector = XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_vector[ii] = XNEWVEC (bool, rank);
+
+  array_value =  XNEWVEC (tree *, list_size);
+  array_stride =  XNEWVEC (tree *, list_size);
+  array_length =  XNEWVEC (tree *, list_size);
+  array_start =  XNEWVEC (tree *, list_size);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      array_value[ii]  = XNEWVEC (tree, rank);
+      array_stride[ii] = XNEWVEC (tree, rank);
+      array_length[ii] = XNEWVEC (tree, rank);
+      array_start[ii]  = XNEWVEC (tree, rank);
+    }
+
+  compare_expr = XNEWVEC (tree, rank);
+  expr_incr = XNEWVEC (tree, rank);
+  ind_init = XNEWVEC (tree, rank);
+  
+  count_down = XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    count_down[ii] = XNEWVEC (bool, rank);
+  
+  array_var = XNEWVEC (tree, 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];
+      tree array_begin = ARRAY_NOTATION_START (array_node);
+      tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
+      tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
+      if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF)
+	{
+	  if (TREE_CODE (array_begin) != INTEGER_CST)
+	    {
+	      begin_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, begin_var,
+						     NOP_EXPR, array_begin,
+						     complain));
+	      ARRAY_NOTATION_START (array_node) = begin_var;
+	    }
+	  if (TREE_CODE (array_lngth) != INTEGER_CST)
+	    {
+	      lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, lngth_var,
+						     NOP_EXPR, array_lngth,
+						     complain));
+	      ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
+	    }
+	  if (TREE_CODE (array_strde) != INTEGER_CST)
+	    {
+	      strde_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, strde_var,
+						     NOP_EXPR, array_strde,
+						     complain));
+	      ARRAY_NOTATION_STRIDE (array_node) = strde_var;
+	    }
+	}
+    }
+  for (ii = 0; ii < list_size; ii++)
+    {
+      jj = 0;
+      jj_tree = (*array_list)[ii];
+      while (jj_tree)
+	{
+	  if (TREE_CODE (jj_tree) == ARRAY_NOTATION_REF)
+	    {
+	      array_ops[ii][jj] = jj_tree;
+	      jj++;
+	      jj_tree = ARRAY_NOTATION_ARRAY (jj_tree);
+	    }
+	  else if (TREE_CODE (jj_tree) == ARRAY_REF)
+	    jj_tree = TREE_OPERAND (jj_tree, 0);
+	  else if (TREE_CODE (jj_tree) == VAR_DECL
+		   || TREE_CODE (jj_tree) == PARM_DECL)
+	    break;
+	}
+    }
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      if (TREE_CODE ((*array_list)[ii]) == ARRAY_NOTATION_REF)
+	for (jj = 0; jj < rank; jj++)
+	  {
+	    if (TREE_CODE (array_ops[ii][jj]) == ARRAY_NOTATION_REF)
+	      {
+		array_value[ii][jj] =
+		  ARRAY_NOTATION_ARRAY (array_ops[ii][jj]);
+		array_start[ii][jj] =
+		  ARRAY_NOTATION_START (array_ops[ii][jj]);
+		array_length[ii][jj] =
+		  fold_build1 (CONVERT_EXPR, integer_type_node,
+			       ARRAY_NOTATION_LENGTH (array_ops[ii][jj]));
+		array_stride[ii][jj] =
+		  ARRAY_NOTATION_STRIDE (array_ops[ii][jj]);
+		array_vector[ii][jj] = true;
+
+		if (!TREE_CONSTANT (array_length[ii][jj])
+		    || TREE_CODE (array_length[ii][jj]) != INTEGER_TYPE)
+		  count_down[ii][jj] = false;
+		else if (tree_int_cst_sgn (array_length[ii][jj]) == -1)
+		  count_down[ii][jj] = true;
+		else
+		  count_down[ii][jj] = false;
+	      }
+	    else
+	      array_vector[ii][jj] = false;
+	  }
+    }
+
+  for (ii = 0; ii < rank; ii++)
+    {
+      array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
+				  TREE_TYPE (array_start[0][ii]));
+      ind_init[ii] = build_x_modify_expr
+	(location, array_var[ii], NOP_EXPR, 
+	 build_zero_cst (TREE_TYPE (array_var[ii])), tf_warning_or_error);
+    }
+  for (ii = 0; ii < list_size; ii++)
+    if (array_vector[ii][0])
+      {
+	tree array_opr = array_value[ii][rank - 1];
+	for (s_jj = rank - 1; s_jj >= 0; s_jj--)
+	  {
+	    tree stride = NULL_TREE, var = NULL_TREE, start = NULL_TREE;
+
+	    /* If stride and start are of same type and the induction var
+	       is not, convert induction variable to stride's type.  */
+	    if ((TREE_TYPE (array_start[ii][s_jj]) ==
+		 TREE_TYPE (array_stride[ii][s_jj]))
+		&& (TREE_TYPE (array_stride[ii][s_jj]) !=
+		    TREE_TYPE (array_var[s_jj])))
+	      {
+		start = array_start[ii][s_jj];
+		stride = array_stride[ii][s_jj];
+		var =
+		  build_c_cast (location, TREE_TYPE (array_stride[ii][s_jj]),
+				array_var[s_jj]);
+	      }
+	    else if (TREE_TYPE (array_start[ii][s_jj]) !=
+		     TREE_TYPE (array_stride[ii][s_jj]))
+	      {
+		/* 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 -.  */
+		start = build_c_cast (location, integer_type_node,
+				      array_start[ii][s_jj]);
+		stride = build_c_cast (location, integer_type_node,
+				       array_stride[ii][s_jj]);
+		var = build_c_cast (location, integer_type_node,
+				    array_var[s_jj]);
+	      }
+	    else
+	      {
+		start = array_start[ii][s_jj];
+		stride = array_stride[ii][s_jj];
+		var = array_var[s_jj];
+	      }
+	    if (count_down[ii][s_jj])
+	      /* Array[start_index - (induction_var * stride)].  */
+	      array_opr = grok_array_decl
+		(location, array_opr,
+		 build2 (MINUS_EXPR, TREE_TYPE (var), start,
+			 build2 (MULT_EXPR, TREE_TYPE (var), var, stride)),
+		 false);	
+	    else
+	      /* Array[start_index + (induction_var * stride)].  */
+	      array_opr = grok_array_decl
+		(location, array_opr,
+		 build2 (PLUS_EXPR, TREE_TYPE (var), start,
+			 build2 (MULT_EXPR, TREE_TYPE (var), var, stride)),
+		 false);
+	  }
+	vec_safe_push (array_operand, array_opr);
+      }
+    else
+      vec_safe_push (array_operand, integer_one_node);
+    
+  replace_array_notations (&func_parm, true, array_list, array_operand);
+  
+  if (!TREE_TYPE (func_parm))      
+    TREE_TYPE (func_parm) = TREE_TYPE ((*array_list)[0]);
+  
+  for (ii = 0; ii < rank; ii++)
+    if (count_down[0][ii])
+      expr_incr[ii] = build_x_unary_op (location, POSTDECREMENT_EXPR,
+					array_var[ii], tf_warning_or_error);
+    else
+      expr_incr[ii] = build_x_unary_op (location, POSTINCREMENT_EXPR,
+					array_var[ii], tf_warning_or_error);
+  
+  for (jj = 0; jj < rank; jj++)
+    if (rank && expr_incr[jj])
+      {
+	if (count_down[0][jj])
+	  compare_expr[jj] = build_x_binary_op
+	    (location, GT_EXPR, array_var[jj], TREE_CODE (array_var[jj]),
+	     array_length[0][jj], TREE_CODE (array_length[0][jj]), NULL,
+	     tf_warning_or_error);
+	else
+	  compare_expr[jj] = build_x_binary_op
+	    (location, LT_EXPR, array_var[jj], TREE_CODE (array_var[jj]),
+	     array_length[0][jj], TREE_CODE (array_length[0][jj]), NULL,
+	     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 a 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];
+  if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ADD)
+    {
+      if (ARITHMETIC_TYPE_P (new_var_type))
+	new_var_init = build_x_modify_expr (location, *new_var, 
+					    NOP_EXPR,
+					    build_zero_cst (new_var_type), 1);
+      else
+	new_var_init = build_x_modify_expr (location, *new_var, 
+					    NOP_EXPR,
+					    integer_zero_node, 1);
+      new_expr = build_x_modify_expr (location, *new_var, PLUS_EXPR, 
+				      func_parm, 1);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MUL)
+    {
+      if (ARITHMETIC_TYPE_P (new_var_type))
+	new_var_init = build_x_modify_expr (location, *new_var, 
+					    NOP_EXPR,
+					    build_one_cst (new_var_type), 1);
+      else
+	new_var_init = build_x_modify_expr (location, *new_var, 
+					    NOP_EXPR,
+					    integer_one_node, 1);
+      new_expr = build_x_modify_expr (location, *new_var, MULT_EXPR, 
+				      func_parm, 1);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO)
+    {
+      new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  build_one_cst (new_var_type), 1);
+      /* Initially you assume everything is zero, now if we find a case where
+	 it is NOT true, then we set the result to false. Otherwise we just
+	 keep the previous value.  */
+      new_yes_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  build_zero_cst (new_var_type), 1);
+      new_no_expr = build_x_modify_expr (location, *new_var, NOP_EXPR, 
+					 *new_var, 1);
+      if (ARITHMETIC_TYPE_P (TREE_TYPE (func_parm)))
+	comp_node = build_zero_cst (TREE_TYPE (func_parm));
+      else
+	comp_node = integer_zero_node;
+      new_cond_expr = build_x_binary_op
+	(location, NE_EXPR, 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);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO)
+    {
+      new_var_init = build_x_modify_expr
+	(location, *new_var, NOP_EXPR, build_one_cst (new_var_type), 1);
+      /* Initially you assume everything is non-zero, now if we find a case
+	 where it is NOT true, then we set the result to false. Otherwise we
+	 just keep the previous value.  */
+      new_yes_expr = build_x_modify_expr
+	(location, *new_var, NOP_EXPR, 
+	 build_zero_cst (TREE_TYPE (*new_var)), 1);
+      new_no_expr = build_x_modify_expr (location, *new_var, NOP_EXPR, 
+					 *new_var, 1);
+      if (ARITHMETIC_TYPE_P (TREE_TYPE (func_parm)))
+	comp_node = build_zero_cst (TREE_TYPE (func_parm));
+      else
+	comp_node = integer_zero_node;
+      new_cond_expr = build_x_binary_op
+	(location, EQ_EXPR, 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);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO)
+    {
+      new_var_init = build_x_modify_expr
+	(location, *new_var, NOP_EXPR, 
+	 build_zero_cst (new_var_type), 1);
+      /* Initially we assume there are NO zeros in the list. When we find a
+	 non-zero, we keep the previous value. If we find a zero, we set the
+	 value to true.  */
+      new_no_expr = build_x_modify_expr
+	(location, *new_var, NOP_EXPR, 
+	 build_one_cst (TREE_TYPE (*new_var)), 1);
+      new_yes_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  *new_var, 1);
+      if (ARITHMETIC_TYPE_P (TREE_TYPE (func_parm)))
+	comp_node = build_zero_cst (TREE_TYPE (func_parm));
+      else
+	comp_node = integer_zero_node;
+      new_cond_expr = build_x_binary_op
+	(location, EQ_EXPR, 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);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO)
+    {
+      new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR, 
+					  build_zero_cst (new_var_type), 1);
+      /* Initially we assume there are NO non-zeros in the list. When we find a
+	 zero, we keep the previous value. If we find a zero, we set the value
+	 to true.  */
+      new_no_expr = build_x_modify_expr
+	(location, *new_var, NOP_EXPR, 
+	 build_one_cst (TREE_TYPE (*new_var)), 1);
+      new_yes_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  *new_var, 1);
+      if (ARITHMETIC_TYPE_P (TREE_TYPE (func_parm)))
+	comp_node = build_zero_cst (TREE_TYPE (func_parm));
+      else
+	comp_node = integer_zero_node;
+      new_cond_expr = build_x_binary_op
+	(location, NE_EXPR, 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);      
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX)
+    {
+      /* If the TYPE_MIN_VALUE is available for the new_var_type, then
+	 set that as the initial value.  */
+      if (TYPE_MIN_VALUE (new_var_type))
+	new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					    TYPE_MIN_VALUE (new_var_type), 1);
+      else
+	/* ... otherwise set initial value as the first element of array.  */
+	new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					    func_parm, 1);
+      new_no_expr  = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  *new_var, 1);
+      new_yes_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  func_parm, 1);
+      new_cond_expr = build_x_binary_op (location, LT_EXPR, *new_var,
+					 TREE_CODE (*new_var), func_parm,
+					 TREE_CODE (func_parm), 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);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN)
+    {
+      /* If the TYPE_MAX_VALUE is available for the new_var_type, then
+	 set that as the initial value.  */
+      if (TYPE_MAX_VALUE (new_var_type))
+	new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					    TYPE_MAX_VALUE (new_var_type), 1);
+      else
+	/* ... otherwise set initial value as the first element of array.  */
+	new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					    func_parm, 1);
+      new_no_expr  = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  *new_var, 1);
+      new_yes_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  func_parm, 1);
+      new_cond_expr = build_x_binary_op (location, GT_EXPR, *new_var,
+					 TREE_CODE (*new_var), func_parm,
+					 TREE_CODE (func_parm), 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);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND)
+    {
+      new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  array_var[0], tf_warning_or_error);
+      new_exp_init = build_x_modify_expr (location, array_ind_value, 
+					  NOP_EXPR, func_parm, 
+					  tf_warning_or_error);
+      new_no_ind   = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  *new_var, 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, array_var[0],
+					    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_yes_expr = build_x_modify_expr (location, array_ind_value, 
+					  NOP_EXPR, func_parm,
+					  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, LT_EXPR, 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);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND)
+    {
+      new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  array_var[0], 1);
+      new_exp_init = build_x_modify_expr (location, array_ind_value, 
+					  NOP_EXPR, func_parm, 1);
+      new_no_ind   = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  *new_var, 1);
+      new_no_expr  = build_x_modify_expr (location, array_ind_value, 
+					  NOP_EXPR, array_ind_value, 1);
+      if (list_size > 1)
+	new_yes_ind  = build_x_modify_expr (location, *new_var, 
+					    NOP_EXPR, array_var[0], 1);
+      else
+	new_yes_ind  = build_x_modify_expr
+	  (location, *new_var, NOP_EXPR, TREE_OPERAND (array_op0, 1), 1);
+      new_yes_expr = build_x_modify_expr (location, array_ind_value, 
+					  NOP_EXPR, func_parm, 1);
+      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, GT_EXPR, 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);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE)
+    {
+      vec<tree, va_gc> *func_args;
+      func_args = make_tree_vector ();
+      vec_safe_push (func_args, *new_var);
+      vec_safe_push (func_args, func_parm);
+
+      new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  identity_value, tf_warning_or_error);
+      new_call_expr = finish_call_expr (call_fn, &func_args, false, true,
+					tf_warning_or_error);
+      new_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
+				      new_call_expr, tf_warning_or_error);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
+    {
+      vec<tree, va_gc> *func_args;
+
+      func_args = make_tree_vector (); 
+      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);
+    }
+  else
+    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 (ind_init[ii]);
+  
+  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 (ind_init[ii], compare_expr[ii], expr_incr[ii], body);
+      body = pop_stmt_list (new_loop);
+    }
+  append_to_statement_list_force (body, &loop_with_init);
+  
+  XDELETEVEC (compare_expr);
+  XDELETEVEC (expr_incr);
+  XDELETEVEC (ind_init);
+  XDELETEVEC (array_var);
+  
+  for (ii = 0; ii < list_size; ii++)
+    {
+      XDELETEVEC (count_down[ii]);
+      XDELETEVEC (array_value[ii]);
+      XDELETEVEC (array_stride[ii]);
+      XDELETEVEC (array_length[ii]);
+      XDELETEVEC (array_start[ii]);
+      XDELETEVEC (array_ops[ii]);
+      XDELETEVEC (array_vector[ii]);
+    }
+  XDELETEVEC (count_down);
+  XDELETEVEC (array_value);
+  XDELETEVEC (array_stride);
+  XDELETEVEC (array_length);
+  XDELETEVEC (array_start);
+  XDELETEVEC (array_ops);
+  XDELETEVEC (array_vector);
+  
+  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)
+{
+  bool **lhs_vector = NULL, **rhs_vector = NULL;
+  tree **lhs_array = NULL, **rhs_array = NULL;
+  tree array_expr_lhs = NULL_TREE, array_expr_rhs = NULL_TREE;
+  tree array_expr = NULL_TREE;
+  tree **lhs_value = NULL, **rhs_value = NULL;
+  tree **lhs_stride = NULL, **lhs_length = NULL, **lhs_start = NULL;
+  tree **rhs_stride = NULL, **rhs_length = NULL, **rhs_start = NULL;
+  tree body = NULL_TREE, *lhs_var = NULL, *rhs_var = NULL;
+  tree  *cond_expr = NULL;
+  tree *lhs_expr_incr = NULL, *rhs_expr_incr = NULL;
+  tree *lhs_ind_init = NULL, *rhs_ind_init = NULL;
+  bool **lhs_count_down = NULL, **rhs_count_down = NULL;
+  tree *lhs_compare = NULL, *rhs_compare = NULL;
+  vec<tree, va_gc> *lhs_array_operand = NULL, *rhs_array_operand = NULL;
+  size_t lhs_rank = 0, rhs_rank = 0, ii = 0, jj = 0;
+  tree ii_tree = NULL_TREE;
+  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;
+  int s_jj = 0;
+  tree lhs_begin_var, lhs_lngth_var, lhs_strde_var, rhs_begin_var;
+  tree rhs_lngth_var, rhs_strde_var;
+  tree an_init, loop_with_init = alloc_stmt_list ();
+  
+  /* 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, 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)
+    {
+      tree rhs_base = rhs;
+      if (TREE_CODE (rhs_base) == COMPOUND_EXPR)
+	rhs_base = TREE_OPERAND (rhs_base, 0);
+      if (TREE_CODE (rhs_base) == TARGET_EXPR)
+	rhs_base = TARGET_EXPR_INITIAL (rhs_base);
+      
+      if (TREE_CODE (rhs) != CALL_EXPR
+	  && !has_call_expr_with_array_notation (rhs))
+	{
+	  for (ii = 0; ii < rhs_rank; ii++)
+	    rhs_base = ARRAY_NOTATION_ARRAY (rhs);
+      	  
+	  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_base);
+	  return error_mark_node;
+	}
+    }
+  if (lhs_rank != 0 && rhs_rank != 0 && lhs_rank != rhs_rank)
+    {
+      tree lhs_base = lhs;
+      tree rhs_base = rhs;
+      
+      for (ii = 0; ii < lhs_rank; ii++)
+	lhs_base = ARRAY_NOTATION_ARRAY (lhs_base);
+
+      while (rhs_base && TREE_CODE (rhs_base) != ARRAY_NOTATION_REF)
+	rhs_base = TREE_OPERAND (rhs_base, 0);
+      for (ii = 0; ii < rhs_rank; ii++)
+	rhs_base = ARRAY_NOTATION_ARRAY (rhs_base);
+
+      if (location == UNKNOWN_LOCATION && EXPR_HAS_LOCATION (lhs))
+	location = EXPR_LOCATION (lhs);
+      error_at (location, "rank mismatch between %qD and %qD", lhs_base,
+		rhs_base);
+      return error_mark_node;
+    }
+
+  /* Assign the array notation components to variable so that they can satisfy
+     the exec-once rule.  */
+  for (ii = 0; ii < lhs_list_size; ii++)
+    {
+      tree array_node = (*lhs_list)[ii];
+      tree array_begin = ARRAY_NOTATION_START (array_node);
+      tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
+      tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
+
+      if (TREE_CODE (array_begin) != INTEGER_CST)
+	{
+	  lhs_begin_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	  finish_expr_stmt (build_x_modify_expr (location, lhs_begin_var,
+						 NOP_EXPR, array_begin,
+						 complain));
+	  ARRAY_NOTATION_START (array_node) = lhs_begin_var;
+	}
+      if (TREE_CODE (array_lngth) != INTEGER_CST)
+	{
+	  lhs_lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	  finish_expr_stmt (build_x_modify_expr (location, lhs_lngth_var,
+						 NOP_EXPR, array_lngth,
+						 complain));
+	  ARRAY_NOTATION_LENGTH (array_node) = lhs_lngth_var;
+	}
+      if (TREE_CODE (array_strde) != INTEGER_CST)
+	{
+	  lhs_strde_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	  finish_expr_stmt (build_x_modify_expr (location, lhs_strde_var,
+						 NOP_EXPR, array_strde,
+						 complain));
+	  ARRAY_NOTATION_STRIDE (array_node) = lhs_strde_var;
+	}
+    }
+  for (ii = 0; ii < rhs_list_size; ii++)
+    {
+      tree array_node = (*rhs_list)[ii];
+      if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF)
+	{
+	  tree array_begin = ARRAY_NOTATION_START (array_node);
+	  tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
+	  tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
+
+	  if (TREE_CODE (array_begin) != INTEGER_CST)
+	    {
+	      rhs_begin_var = build_decl (location, VAR_DECL, NULL_TREE,
+					  integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, rhs_begin_var,
+						     NOP_EXPR, array_begin,
+						     complain));
+	      ARRAY_NOTATION_START (array_node) = rhs_begin_var;
+	    }
+	  if (TREE_CODE (array_lngth) != INTEGER_CST)
+	    {
+	      rhs_lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
+					  integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, rhs_lngth_var,
+						     NOP_EXPR, array_lngth,
+						     complain));
+	      ARRAY_NOTATION_LENGTH (array_node) = rhs_lngth_var;
+	    }
+	  if (TREE_CODE (array_strde) != INTEGER_CST)
+	    {
+	      rhs_strde_var = build_decl (location, VAR_DECL, NULL_TREE,
+					  integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, rhs_strde_var,
+						     NOP_EXPR, array_strde,
+						     complain));
+	      ARRAY_NOTATION_STRIDE (array_node) = rhs_strde_var;
+	    }
+	}
+    }  
+  lhs_vector = XNEWVEC (bool *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_vector[ii] = XNEWVEC (bool, lhs_rank);
+  
+  rhs_vector = XNEWVEC (bool *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_vector[ii] = XNEWVEC (bool, rhs_rank);
+
+  lhs_array = XNEWVEC (tree *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_array[ii] = XNEWVEC (tree, lhs_rank);
+  
+  rhs_array = XNEWVEC (tree *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_array[ii] = XNEWVEC (tree, rhs_rank);
+
+  lhs_value = XNEWVEC (tree *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_value[ii] = XNEWVEC (tree, lhs_rank);
+  
+  rhs_value = XNEWVEC (tree *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_value[ii] = XNEWVEC (tree, rhs_rank);
+
+  lhs_stride = XNEWVEC (tree *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_stride[ii] = XNEWVEC (tree, lhs_rank);
+
+  rhs_stride = XNEWVEC (tree *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_stride[ii] = XNEWVEC (tree, rhs_rank);
+
+  lhs_length = XNEWVEC (tree *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_length[ii] = XNEWVEC (tree, lhs_rank);
+  
+  rhs_length = XNEWVEC (tree *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_length[ii] = XNEWVEC (tree, rhs_rank);
+
+  lhs_start = XNEWVEC (tree *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_start[ii] = XNEWVEC (tree, lhs_rank);
+  
+  rhs_start = XNEWVEC (tree *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_start[ii] = XNEWVEC (tree, rhs_rank);
+   
+  lhs_var = XNEWVEC (tree, lhs_rank);
+  rhs_var = XNEWVEC (tree, rhs_rank);
+  
+
+  /* The reason why we are just using lhs_rank for this is because we have then
+     following scenarios:
+     1.  LHS_RANK == RHS_RANK
+     2.  LHS_RANK != RHS_RANK && RHS_RANK = 0
+
+     In both the scenarios, just checking the LHS_RANK is OK.  */
+
+  cond_expr = XNEWVEC (tree, MAX (lhs_rank, rhs_rank));
+  lhs_expr_incr = XNEWVEC (tree, lhs_rank);
+  rhs_expr_incr = XNEWVEC (tree, rhs_rank);
+
+  lhs_ind_init = XNEWVEC (tree, lhs_rank);
+  rhs_ind_init = XNEWVEC (tree, rhs_rank);
+
+  lhs_count_down = XNEWVEC (bool *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_count_down[ii] = XNEWVEC (bool, lhs_rank);
+  
+  rhs_count_down = XNEWVEC (bool *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_count_down[ii] = XNEWVEC (bool, rhs_rank);
+
+  lhs_compare = XNEWVEC (tree, lhs_rank);
+  rhs_compare = XNEWVEC (tree, rhs_rank);
+
+  if (lhs_rank)
+    {
+      for (ii = 0; ii < lhs_list_size; ii++)
+	{
+	  jj = 0;
+	  ii_tree = (*lhs_list)[ii];
+	  while (ii_tree)
+	    {
+	      if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
+		{
+		  lhs_array[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) == PARM_DECL)
+		break;
+	    }
+	}
+    }
+  else
+    lhs_array[0][0] = NULL_TREE;
+  
+  if (rhs_rank)
+    {
+      for (ii = 0; ii < rhs_list_size; ii++)
+	{
+	  jj = 0;
+	  ii_tree = (*rhs_list)[ii];
+	  while (ii_tree)
+	    {
+	      if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
+		{
+		  rhs_array[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) == PARM_DECL
+		       || TREE_CODE (ii_tree) == CALL_EXPR)
+		break;
+	    }
+	}
+    }  
+  for (ii = 0; ii < lhs_list_size; ii++)
+    {
+      if (TREE_CODE ((*lhs_list)[ii]) == ARRAY_NOTATION_REF)
+	{
+	  for (jj = 0; jj < lhs_rank; jj++)
+	    {
+	      if (TREE_CODE (lhs_array[ii][jj]) == ARRAY_NOTATION_REF)
+		{
+		  lhs_value[ii][jj] = ARRAY_NOTATION_ARRAY (lhs_array[ii][jj]);
+		  lhs_start[ii][jj] = ARRAY_NOTATION_START (lhs_array[ii][jj]);
+		  lhs_length[ii][jj] =
+		    fold_build1 (CONVERT_EXPR, integer_type_node,
+				 ARRAY_NOTATION_LENGTH (lhs_array[ii][jj]));
+		  lhs_stride[ii][jj] =
+		    fold_build1 (CONVERT_EXPR, integer_type_node,
+				 ARRAY_NOTATION_STRIDE (lhs_array[ii][jj]));
+		  lhs_vector[ii][jj] = true;
+		  
+		  /* If the stride value is variable (i.e. not constant) then
+		     assume that the length is positive.  */
+		  if (!TREE_CONSTANT (lhs_length[ii][jj]))
+		    lhs_count_down[ii][jj] = false;
+		  else if (tree_int_cst_lt
+			   (lhs_length[ii][jj],
+			    build_zero_cst (TREE_TYPE (lhs_length[ii][jj]))))
+		    lhs_count_down[ii][jj] = true;
+		  else
+		    lhs_count_down[ii][jj] = false;
+		}
+	      else
+		lhs_vector[ii][jj] = false;
+	    }
+	}
+    }
+  for (ii = 0; ii < rhs_list_size; ii++)
+    {
+      if (TREE_CODE ((*rhs_list)[ii]) == ARRAY_NOTATION_REF)
+	{
+	  for (jj = 0; jj < rhs_rank; jj++)
+	    {
+	      if (TREE_CODE (rhs_array[ii][jj]) == ARRAY_NOTATION_REF)
+		{
+		  rhs_value[ii][jj]  = ARRAY_NOTATION_ARRAY (rhs_array[ii][jj]);
+		  rhs_start[ii][jj]  = ARRAY_NOTATION_START (rhs_array[ii][jj]);
+		  rhs_length[ii][jj] =
+		    ARRAY_NOTATION_LENGTH (rhs_array[ii][jj]);
+		  rhs_stride[ii][jj] =
+		    ARRAY_NOTATION_STRIDE (rhs_array[ii][jj]);
+		  rhs_vector[ii][jj] = true;
+		  /* If the stride value is variable (i.e. not constant) then
+		     assume that the length is positive.  */
+		  if (!TREE_CONSTANT (rhs_length[ii][jj]))
+		    rhs_count_down[ii][jj] = false;
+		  else if (tree_int_cst_lt
+			   (rhs_length[ii][jj],
+			    build_zero_cst (TREE_TYPE (rhs_length[ii][jj]))))
+		    rhs_count_down[ii][jj] = true;
+		  else
+		    rhs_count_down[ii][jj] = false;	
+		}
+	      else
+		rhs_vector[ii][jj] = false;
+	    }
+	}
+      else
+	for (jj = 0; jj < rhs_rank; jj++)
+	  {
+	    rhs_vector[ii][jj] = false;
+	    rhs_length[ii][jj] = NULL_TREE;
+	  }
+    }
+
+  if (length_mismatch_in_expr_p (EXPR_LOCATION (lhs), lhs_length,
+				 lhs_list_size, lhs_rank)
+      || length_mismatch_in_expr_p (EXPR_LOCATION (rhs), rhs_length,
+				    rhs_list_size, rhs_rank))
+    {
+      pop_stmt_list (an_init);
+      return error_mark_node;
+    }
+
+  if (lhs_list_size > 0 && rhs_list_size > 0 && lhs_rank > 0 && rhs_rank > 0
+      && TREE_CODE (lhs_length[0][0]) == INTEGER_CST
+      && rhs_length[0][0] && TREE_CODE (rhs_length[0][0]) == INTEGER_CST)
+    {
+      HOST_WIDE_INT l_length = int_cst_value (lhs_length[0][0]);
+      HOST_WIDE_INT r_length = int_cst_value (rhs_length[0][0]);
+      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_start[0][ii] && TREE_TYPE (lhs_start[0][ii]))
+	lhs_var[ii] =  build_decl (location, VAR_DECL, NULL_TREE,
+				   TREE_TYPE (lhs_start[0][ii]));
+    else
+      lhs_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
+				integer_type_node);
+
+  for (ii = 0; ii < rhs_list_size; ii++)
+    {
+      if (TREE_CODE ((*rhs_list)[ii]) == CALL_EXPR)
+	{
+	  int idx_value = 0;
+	  tree func_name = CALL_EXPR_FN ((*rhs_list)[ii]);
+	  if (TREE_CODE (func_name) == ADDR_EXPR)
+	    {
+	      if (is_sec_implicit_index_fn (func_name))
+		{
+		  idx_value = 
+		    extract_sec_implicit_index_arg (location, (*rhs_list)[ii]);
+		  if (idx_value < (int) lhs_rank && idx_value >= 0)
+		    vec_safe_push (rhs_array_operand, lhs_var[idx_value]);
+		  else if (idx_value == -1)
+		    return error_mark_node;
+		  else
+		    {
+		      size_t ee = 0;
+		      tree lhs_base = (*lhs_list)[ii];
+		      for (ee = 0; ee < lhs_rank; ee++)
+			if (lhs_base
+			    && TREE_CODE (lhs_base) == ARRAY_NOTATION_REF)
+			  lhs_base = ARRAY_NOTATION_ARRAY (lhs_base);
+
+		      if (location == UNKNOWN_LOCATION
+			  && EXPR_HAS_LOCATION (lhs))
+			location = EXPR_LOCATION (lhs);
+		      error_at (location, "__sec_implicit_index argument %d "
+				"must be less than the rank of %qD", idx_value,
+				lhs_base);
+		      return error_mark_node;
+		    }
+		}
+	      else
+		vec_safe_push (rhs_array_operand, (*rhs_list)[ii]);
+	    }
+	  else
+	    vec_safe_push (rhs_array_operand, (*rhs_list)[ii]);
+	}
+      else
+	vec_safe_push (rhs_array_operand, (*rhs_list)[ii]);
+    }
+
+  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_vector[0][ii])
+      {
+	lhs_ind_init[ii] = build_x_modify_expr
+	  (location, lhs_var[ii], NOP_EXPR,
+	   build_zero_cst (TREE_TYPE (lhs_var[ii])), complain);
+      }
+    
+
+  for (ii = 0; ii < rhs_rank; ii++)
+    {
+      /* When we have a polynomial, we assume that the indices are of type
+	 integer.  */
+      rhs_var[ii] =  build_decl (location, VAR_DECL, NULL_TREE,
+				 TREE_TYPE (rhs_start[0][ii]));
+      rhs_ind_init[ii] = build_x_modify_expr
+	(location, rhs_var[ii], NOP_EXPR, 
+	 build_zero_cst (TREE_TYPE (rhs_var[ii])), complain);
+    }
+
+  if (lhs_rank)
+    {
+      for (ii = 0; ii < lhs_list_size; ii++)
+	{
+	  if (lhs_vector[ii][0])
+	    {
+	      /* The last ARRAY_NOTATION element's ARRAY component should be
+		 the array's base value.  */
+	      tree lhs_array_opr = lhs_value[ii][lhs_rank - 1];
+	      for (s_jj = lhs_rank - 1; s_jj >= 0; s_jj--)
+		{
+		  tree stride = NULL_TREE, var = NULL_TREE, start = NULL_TREE;
+		  if ((TREE_TYPE (lhs_start[ii][s_jj]) ==
+		       TREE_TYPE (lhs_stride[ii][s_jj]))
+		      && (TREE_TYPE (lhs_stride[ii][s_jj]) !=
+			  TREE_TYPE (lhs_var[s_jj])))
+		    {
+		      /* If stride and start are of same type and the induction
+			 var is not, convert induction variable to stride's
+			 type.  */
+		      start = lhs_start[ii][s_jj];
+		      stride = lhs_stride[ii][s_jj];
+		      var = build_c_cast (location,
+					  TREE_TYPE (lhs_stride[ii][s_jj]),
+					  lhs_var[s_jj]);
+		    }
+		  else if (TREE_TYPE (lhs_start[ii][s_jj]) !=
+			   TREE_TYPE (lhs_stride[ii][s_jj]))
+		    {
+		      /* 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 -.  */
+		      start = build_c_cast (location, integer_type_node,
+					    lhs_start[ii][s_jj]);
+		      stride = build_c_cast (location, integer_type_node,
+					     lhs_stride[ii][s_jj]);
+		      var = build_c_cast (location, integer_type_node,
+					  lhs_var[s_jj]);
+		    }
+		  else
+		    {
+		      start = lhs_start[ii][s_jj];
+		      stride = lhs_stride[ii][s_jj];
+		      var = lhs_var[s_jj];
+		    }
+		  if (lhs_count_down[ii][s_jj])
+		    /* Array[start_index - (induction_var * stride)].  */
+		    lhs_array_opr = grok_array_decl
+		      (location, lhs_array_opr,
+		       build2 (MINUS_EXPR, TREE_TYPE (var), start,
+			       build2 (MULT_EXPR, TREE_TYPE (var), var,
+				       stride)), false);	
+		  else
+		    /* Array[start_index + (induction_var * stride)].  */
+		    lhs_array_opr = grok_array_decl
+		      (location, lhs_array_opr,
+		       build2 (PLUS_EXPR, TREE_TYPE (var), start,
+			       build2 (MULT_EXPR, TREE_TYPE (var), var,
+				       stride)), false);
+		}
+	      vec_safe_push (lhs_array_operand, lhs_array_opr);
+	    }
+	  else
+	    vec_safe_push (lhs_array_operand, integer_one_node);
+	}
+      replace_array_notations (&lhs, true, lhs_list, lhs_array_operand);
+      array_expr_lhs = lhs;
+    }
+
+  if (rhs_array_operand)
+    vec_safe_truncate (rhs_array_operand, 0);
+
+  if (rhs_rank)
+    {
+      for (ii = 0; ii < rhs_list_size; ii++)
+	{
+	  if (rhs_vector[ii][0])
+	    {
+	      tree rhs_array_opr = rhs_value[ii][rhs_rank - 1];
+	      for (s_jj = rhs_rank - 1; s_jj >= 0; s_jj--)
+		{
+		  tree stride = NULL_TREE, var = NULL_TREE, start = NULL_TREE;
+		  if ((TREE_TYPE (rhs_start[ii][s_jj]) ==
+		       TREE_TYPE (rhs_stride[ii][s_jj]))
+		      && (TREE_TYPE (rhs_stride[ii][s_jj]) !=
+			  TREE_TYPE (rhs_var[s_jj])))
+		    {
+		      /* If stride and start are of same type and the induction
+			 var is not, convert induction variable to stride's
+			 type.  */
+		      start = rhs_start[ii][s_jj];
+		      stride = rhs_stride[ii][s_jj];
+		      var = build_c_cast (location,
+					  TREE_TYPE (rhs_stride[ii][s_jj]),
+					  rhs_var[s_jj]);
+		    }
+		  else if (TREE_TYPE (rhs_start[ii][s_jj]) !=
+			   TREE_TYPE (rhs_stride[ii][s_jj]))
+		    {
+		      /* 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 -.  */
+		      start = build_c_cast (location, integer_type_node,
+					    rhs_start[ii][s_jj]);
+		      stride = build_c_cast (location, integer_type_node,
+					     rhs_stride[ii][s_jj]);
+		      var = build_c_cast (location, integer_type_node,
+					  rhs_var[s_jj]);
+		    }
+		  else
+		    {
+		      start = rhs_start[ii][s_jj];
+		      stride = rhs_stride[ii][s_jj];
+		      var = rhs_var[s_jj];
+		    }
+		  if (rhs_count_down[ii][s_jj])
+		    /* Array[start_index - (induction_var * stride)].  */
+		    rhs_array_opr = grok_array_decl
+		      (location, rhs_array_opr,
+		       build2 (MINUS_EXPR, TREE_TYPE (var), start,
+			       build2 (MULT_EXPR, TREE_TYPE (var), var,
+				       stride)), false);	
+		  else
+		    /* Array[start_index + (induction_var * stride)].  */
+		    rhs_array_opr = grok_array_decl
+		      (location, rhs_array_opr,
+		       build2 (PLUS_EXPR, TREE_TYPE (var), start,
+			       build2 (MULT_EXPR, TREE_TYPE (var), var,
+				       stride)), false);
+		}
+	      vec_safe_push (rhs_array_operand, rhs_array_opr);
+	    }
+	  else
+	    /* This is just a dummy node to make sure the list sizes for both
+	       array list and array operand list are the same.  */
+	    vec_safe_push (rhs_array_operand, integer_one_node);
+	}
+      for (ii = 0; ii < rhs_list_size; ii++)
+	{
+	  tree rhs_node = (*rhs_list)[ii];
+	  if (TREE_CODE (rhs_node) == CALL_EXPR)
+	    {
+	      int idx_value = 0;
+	      tree func_name = CALL_EXPR_FN (rhs_node);
+	      if (TREE_CODE (func_name) == ADDR_EXPR)
+		if (is_sec_implicit_index_fn (func_name))
+		  {
+		    idx_value = 
+		      extract_sec_implicit_index_arg (location, rhs_node);
+		    if (idx_value < (int) lhs_rank && idx_value >= 0)
+		      vec_safe_push (rhs_array_operand, rhs_var[idx_value]);
+		    else
+		      {
+			size_t ee = 0;
+			tree rhs_base = (*lhs_list)[ii];
+			for (ee = 0; ee < rhs_rank; ee++)
+			  if (rhs_base
+			      && TREE_CODE (rhs_base) == ARRAY_NOTATION_REF)
+			    rhs_base = ARRAY_NOTATION_ARRAY (rhs_base);
+
+			error_at (location, "__sec_implicit_index argument %d "
+				  "must be less than rank of %qD", idx_value,
+				  rhs_base);
+			return error_mark_node;
+		      }
+		  }
+	    }
+	}	
+      replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
+      array_expr_rhs = rhs;
+    }
+  else
+    {
+      for (ii = 0; ii < rhs_list_size; ii++)
+	{
+	  tree rhs_node = (*rhs_list)[ii];
+	  if (TREE_CODE (rhs_node) == CALL_EXPR)
+	    {
+	      int idx_value = 0;
+	      tree func_name = CALL_EXPR_FN (rhs_node);
+	      if (is_sec_implicit_index_fn (func_name))
+		{
+		  idx_value =  extract_sec_implicit_index_arg (location,
+							       rhs_node);
+		  if (idx_value < (int) lhs_rank && idx_value >= 0)
+		    vec_safe_push (rhs_array_operand, lhs_var[idx_value]);
+		  else
+		    {
+		      size_t ee = 0;
+		      tree lhs_base = (*lhs_list)[ii];
+		      for (ee = 0; ee < lhs_rank; ee++)
+			if (lhs_base
+			    && TREE_CODE (lhs_base) == ARRAY_NOTATION_REF)
+			  lhs_base = ARRAY_NOTATION_ARRAY (lhs_base);
+		      error_at (location, "__sec_implicit_index argument %d "
+				"must be less than the rank of %qD", idx_value,
+				lhs_base);
+		      return error_mark_node;
+		    }
+		}
+	    }
+	}
+      replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
+      array_expr_rhs = rhs;
+      rhs_expr_incr[0] = NULL_TREE;
+    }
+  
+  for (ii = 0; ii < rhs_rank; ii++)
+    if (rhs_count_down[0][ii])
+      rhs_expr_incr[ii] = build_x_unary_op (location, POSTDECREMENT_EXPR,
+					    rhs_var[ii], complain);
+    else
+      rhs_expr_incr[ii] = build_x_unary_op (location, POSTINCREMENT_EXPR,
+					    rhs_var[ii], complain);
+  
+  for (ii = 0; ii < lhs_rank; ii++)
+    if (lhs_count_down[0][ii])
+      lhs_expr_incr[ii] = build_x_unary_op (location, POSTDECREMENT_EXPR,
+					    lhs_var[ii], complain);
+    else
+      lhs_expr_incr[ii] = build_x_unary_op (location, POSTINCREMENT_EXPR,
+					    lhs_var[ii], complain);
+  if (!array_expr_lhs)
+    array_expr_lhs = lhs;
+  
+  array_expr = build_x_modify_expr (location, array_expr_lhs, modifycode,
+				    array_expr_rhs, complain);
+
+  for (jj = 0; jj < MAX (lhs_rank, rhs_rank); jj++)
+    {
+      if (rhs_rank && rhs_expr_incr[jj])
+	{
+	  size_t iii = 0;
+	  if (lhs_rank)
+	    {
+	      if (lhs_count_down[0][jj])
+		lhs_compare[jj] = build_x_binary_op
+		  (location, GT_EXPR, lhs_var[jj], TREE_CODE (lhs_var[jj]),
+		   lhs_length[0][jj], TREE_CODE (lhs_length[0][jj]), NULL,
+		   complain);
+	      else
+		lhs_compare[jj] = build_x_binary_op
+		  (location, LT_EXPR, lhs_var[jj], TREE_CODE (lhs_var[jj]),
+		   lhs_length[0][jj], TREE_CODE (lhs_length[0][jj]), NULL,
+		   complain);
+	    }
+	  else
+	    lhs_compare[jj] = NULL_TREE;
+
+	  for (iii = 0; iii < rhs_list_size; iii++)
+	    if (rhs_vector[iii][jj])
+	      break;
+	  
+	  /* What we are doing here is this:
+	     We always count up, so:
+	       if (length is negative ==> which means we count down)
+	          we multiply length by -1 and count up => ii < -LENGTH
+	       else
+	          we just count up, so we compare for  ii < LENGTH
+	   */
+	  if (rhs_count_down[iii][jj])
+	    {
+	      tree new_rhs = build_x_modify_expr
+		(location, rhs_length[iii][jj], MULT_EXPR,
+		 build_int_cst (TREE_TYPE (rhs_length[iii][jj]), -1), complain);
+	      rhs_compare[jj] = build_x_binary_op
+		(location, GT_EXPR, rhs_var[jj], TREE_CODE (rhs_var[jj]),
+		 new_rhs, TREE_CODE (new_rhs), NULL, complain);
+	    }
+	  else
+	    rhs_compare[jj] = build_x_binary_op
+	      (location, LT_EXPR, rhs_var[jj], TREE_CODE (rhs_var[jj]),
+	       rhs_length[iii][jj], TREE_CODE (rhs_length[0][jj]), NULL,
+	       complain);
+	   
+	  if (lhs_rank)
+	    cond_expr[jj] = build_x_binary_op
+	      (location, TRUTH_ANDIF_EXPR, lhs_compare[jj],
+	       TREE_CODE (lhs_compare[jj]), rhs_compare[jj],
+	       TREE_CODE (rhs_compare[jj]), NULL, complain);
+	  else
+	    cond_expr[jj] = rhs_compare[jj];
+	}
+      else
+	{
+	  if (lhs_count_down[0][jj])
+	    cond_expr[jj] = build_x_binary_op
+	      (location, GT_EXPR, lhs_var[jj], TREE_CODE (lhs_var[jj]),
+	       lhs_length[0][jj], TREE_CODE (lhs_length[0][jj]), NULL,
+	       complain);
+	    else
+	      cond_expr[jj] = build_x_binary_op
+		(location, LT_EXPR, lhs_var[jj], TREE_CODE (lhs_var[jj]),
+		 lhs_length[0][jj], TREE_CODE (lhs_length[0][jj]), NULL,
+		 complain);
+	}
+    }
+  
+  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_ind_init[ii], &init_list);
+	  append_to_statement_list_force (lhs_expr_incr[ii], &incr_list);
+	}
+      if (rhs_rank)
+	{
+	  append_to_statement_list_force (rhs_ind_init[ii], &init_list);
+	  append_to_statement_list_force (rhs_expr_incr[ii], &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);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    {
+      XDELETEVEC (rhs_vector[ii]);
+      XDELETEVEC (rhs_array[ii]);
+      XDELETEVEC (rhs_value[ii]);
+      XDELETEVEC (rhs_length[ii]);
+      XDELETEVEC (rhs_stride[ii]);
+      XDELETEVEC (rhs_start[ii]);
+    }
+    for (ii = 0; ii < lhs_list_size; ii++)
+    {
+      XDELETEVEC (lhs_vector[ii]);
+      XDELETEVEC (lhs_array[ii]);
+      XDELETEVEC (lhs_value[ii]);
+      XDELETEVEC (lhs_length[ii]);
+      XDELETEVEC (lhs_stride[ii]);
+      XDELETEVEC (lhs_start[ii]);
+    }
+  if (rhs_vector)
+    XDELETEVEC (rhs_vector);
+
+  if (rhs_array)
+    XDELETEVEC (rhs_array);
+  if (rhs_value)
+    XDELETEVEC (rhs_value);
+  if (rhs_length)
+    XDELETEVEC (rhs_length);
+  if (rhs_stride)
+    XDELETEVEC (rhs_stride);
+  if (rhs_start)
+    XDELETEVEC (rhs_start);
+  if (rhs_expr_incr)    
+    XDELETEVEC (rhs_expr_incr);
+  if (rhs_ind_init)
+    XDELETEVEC (rhs_ind_init);
+  if (rhs_compare)
+    XDELETEVEC (rhs_compare);
+  if (lhs_compare)
+    XDELETEVEC (lhs_compare);
+  
+  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, jj = 0;
+  tree **array_ops, *array_var, jj_tree, body, stmt = NULL_TREE;
+  tree **array_value, **array_stride, **array_length, **array_start;
+  tree *compare_expr, an_init, *expr_incr, *ind_init;
+  tree builtin_loop, new_var = NULL_TREE;
+  bool **count_down, **array_vector;
+  tree loop_with_init = alloc_stmt_list ();
+  int s_jj = 0;
+  tree begin_var, lngth_var, strde_var;
+  tsubst_flags_t complain = tf_warning_or_error;
+  location_t location = UNKNOWN_LOCATION;
+
+  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);
+  array_ops = XNEWVEC (tree *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_ops[ii] = XNEWVEC (tree, rank);
+  
+  array_vector = XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_vector[ii] = XNEWVEC (bool, rank);
+
+  array_value  = XNEWVEC (tree *, list_size);
+  array_stride = XNEWVEC (tree *, list_size);
+  array_length = XNEWVEC (tree *, list_size);
+  array_start  = XNEWVEC (tree *, list_size);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      array_value[ii]  = XNEWVEC (tree, rank);
+      array_stride[ii] = XNEWVEC (tree, rank);
+      array_length[ii] = XNEWVEC (tree, rank);
+      array_start[ii]  = XNEWVEC (tree, rank);
+    }
+
+  compare_expr = XNEWVEC (tree, rank);
+  expr_incr = XNEWVEC (tree, rank);
+  ind_init = XNEWVEC (tree, rank);
+
+  list_size = vec_safe_length (array_list);
+  count_down = XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    count_down[ii] = XNEWVEC (bool, rank);
+  
+  array_var = XNEWVEC (tree, 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];
+      if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF)
+	{
+	  tree array_begin = ARRAY_NOTATION_START (array_node);
+	  tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
+	  tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
+
+	  if (TREE_CODE (array_begin) != INTEGER_CST)
+	    {
+	      begin_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, begin_var,
+						     NOP_EXPR, array_begin,
+						     complain));
+	      ARRAY_NOTATION_START (array_node) = begin_var;
+	    }
+	  if (TREE_CODE (array_lngth) != INTEGER_CST)
+	    {
+	      lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, lngth_var,
+						     NOP_EXPR, array_lngth,
+						     complain));
+	      ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
+	    }
+	  if (TREE_CODE (array_strde) != INTEGER_CST)
+	    {
+	      strde_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, strde_var,
+						     NOP_EXPR, array_strde,
+						     complain));
+	      ARRAY_NOTATION_STRIDE (array_node) = strde_var;
+	    }
+	}
+    }
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      jj = 0;
+      jj_tree = (*array_list)[ii];
+      while (jj_tree)
+	{
+	  if (TREE_CODE (jj_tree) == ARRAY_NOTATION_REF)
+	    {
+	      array_ops[ii][jj] = jj_tree;
+	      jj++;
+	      jj_tree = ARRAY_NOTATION_ARRAY (jj_tree);
+	    }
+	  else if (TREE_CODE (jj_tree) == ARRAY_REF)
+	    jj_tree = TREE_OPERAND (jj_tree, 0);
+	  else if (TREE_CODE (jj_tree) == VAR_DECL
+		   || TREE_CODE (jj_tree) == PARM_DECL)
+	    break;
+	}
+    }
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      if (TREE_CODE ((*array_list)[ii]) == ARRAY_NOTATION_REF)
+	{
+	  for (jj = 0; jj < rank; jj++)
+	    {
+	      if (TREE_CODE (array_ops[ii][jj]) == ARRAY_NOTATION_REF)
+		{
+		  array_value[ii][jj] =
+		    ARRAY_NOTATION_ARRAY (array_ops[ii][jj]);
+		  array_start[ii][jj] =
+		    ARRAY_NOTATION_START (array_ops[ii][jj]);
+		  array_length[ii][jj] =
+		    ARRAY_NOTATION_LENGTH (array_ops[ii][jj]);
+		  array_stride[ii][jj] =
+		    ARRAY_NOTATION_STRIDE (array_ops[ii][jj]);
+		  array_vector[ii][jj] = true;
+
+		  if (!integer_zerop (array_length[ii][jj])
+		      && !integer_nonzerop (array_length[ii][jj]))
+		    count_down[ii][jj] = false;
+		  else if (tree_int_cst_lt
+			   (array_length[ii][jj],
+			    build_zero_cst (TREE_TYPE (array_length[ii][jj]))))
+		    count_down[ii][jj] = true;
+		  else
+		    count_down[ii][jj] = false;
+		}
+	      else
+		array_vector[ii][jj] = false;
+	    }
+	}
+    }
+  for (ii = 0; ii < rank; ii++)
+    {
+      if (TREE_TYPE (array_start[0][ii])
+	  && TREE_CODE (TREE_TYPE (array_start[0][ii])) != TEMPLATE_TYPE_PARM)
+	{
+	  array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
+				      TREE_TYPE (array_start[0][ii]));
+	  ind_init[ii] = build_x_modify_expr
+	    (location, array_var[ii], NOP_EXPR, 
+	     build_zero_cst (TREE_TYPE (array_var[ii])), tf_warning_or_error);
+	}
+      else
+	{
+	  array_var[ii] = build_min_nt_loc (location, VAR_DECL,
+					    NULL_TREE, NULL_TREE);
+	  ind_init[ii] = build_x_modify_expr (location, array_var[ii], 
+					      NOP_EXPR,
+					      integer_zero_node, 1);
+	}
+    }
+  for (ii = 0; ii < list_size; ii++)
+    {
+      if (array_vector[ii][0])
+	{
+	  tree array_opr = array_value[ii][rank - 1];
+	  for (s_jj = rank - 1; s_jj >= 0; s_jj--)
+	    {
+	      tree stride = NULL_TREE, var = NULL_TREE, start = NULL_TREE;
+
+	      /* If stride and start are of same type and the induction var
+		 is not, convert induction variable to stride's type.  */
+	      if ((TREE_TYPE (array_start[ii][s_jj]) ==
+		   TREE_TYPE (array_stride[ii][s_jj]))
+		  && (TREE_TYPE (array_stride[ii][s_jj]) !=
+		      TREE_TYPE (array_var[s_jj])))
+		{
+		  start = array_start[ii][s_jj];
+		  stride = array_stride[ii][s_jj];
+		  var =
+		    build_c_cast (location, TREE_TYPE (array_stride[ii][s_jj]),
+				  array_var[s_jj]);
+		}
+	      else if (TREE_TYPE (array_start[ii][s_jj]) !=
+			TREE_TYPE (array_stride[ii][s_jj]))
+		{
+		  /* 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, we stay safe and 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 -.  */
+		  start = build_c_cast (location, integer_type_node,
+					array_start[ii][s_jj]);
+		  stride = build_c_cast (location, integer_type_node,
+					 array_stride[ii][s_jj]);
+		  var = build_c_cast (location, integer_type_node,
+				      array_var[s_jj]);
+		}
+	      else
+		{
+		  start = array_start[ii][s_jj];
+		  stride = array_stride[ii][s_jj];
+		  var = array_var[s_jj];
+		}
+	      if (count_down[ii][s_jj])
+		/* Array[start_index - (induction_var * stride)].  */
+		array_opr = grok_array_decl
+		  (location, array_opr,
+		   build2 (MINUS_EXPR, TREE_TYPE (var), start,
+			   build2 (MULT_EXPR, TREE_TYPE (var), var, stride)),
+		   false);	
+	      else
+		/* Array[start_index + (induction_var * stride)].  */
+		array_opr = grok_array_decl
+		  (location, array_opr,
+		   build2 (PLUS_EXPR, TREE_TYPE (var), start,
+			   build2 (MULT_EXPR, TREE_TYPE (var), var, stride)),
+		   false);
+		
+	    }
+	  vec_safe_push (array_operand, array_opr);
+	}
+      else
+	vec_safe_push (array_operand, integer_one_node);
+    }
+  replace_array_notations (&stmt, true, array_list, array_operand);
+
+  for (ii = 0; ii < rank; ii++)
+    if (count_down[0][ii])
+      expr_incr[ii] = build_x_unary_op (location, POSTDECREMENT_EXPR,
+					array_var[ii], tf_warning_or_error);
+    else
+      expr_incr[ii] = build_x_unary_op (location, POSTINCREMENT_EXPR,
+					array_var[ii], tf_warning_or_error);
+  
+  for (jj = 0; jj < rank; jj++)
+    {
+      if (rank && expr_incr[jj])
+	{
+	  if (count_down[0][jj])
+	    compare_expr[jj] = build_x_binary_op
+	      (location, GT_EXPR, array_var[jj], TREE_CODE (array_var[jj]),
+	       array_length[0][jj], TREE_CODE (array_length[0][jj]), NULL,
+	       tf_warning_or_error);
+	  else
+	    compare_expr[jj] = build_x_binary_op
+	      (location, LT_EXPR, array_var[jj], TREE_CODE (array_var[jj]),
+	       array_length[0][jj], TREE_CODE (array_length[0][jj]), NULL,
+	       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 (ind_init[ii], compare_expr[ii], expr_incr[ii], body);
+      body = pop_stmt_list (new_loop);
+    }
+  append_to_statement_list_force (body, &loop_with_init);
+  
+  XDELETEVEC (compare_expr);
+  XDELETEVEC (expr_incr);
+  XDELETEVEC (ind_init);
+  XDELETEVEC (array_var);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      XDELETEVEC (count_down[ii]);
+      XDELETEVEC (array_value[ii]);
+      XDELETEVEC (array_stride[ii]);
+      XDELETEVEC (array_length[ii]);
+      XDELETEVEC (array_start[ii]);
+      XDELETEVEC (array_ops[ii]);
+      XDELETEVEC (array_vector[ii]);
+    }
+
+  XDELETEVEC (count_down);
+  XDELETEVEC (array_value);
+  XDELETEVEC (array_stride);
+  XDELETEVEC (array_length);
+  XDELETEVEC (array_start);
+  XDELETEVEC (array_ops);
+  XDELETEVEC (array_vector);
+
+  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;
+  int s_jj = 0;
+  size_t list_size = 0, rank = 0, ii = 0, jj = 0;
+  tree **array_ops, *array_var, jj_tree, body, array_opr;
+  tree **array_value, **array_stride, **array_length, **array_start;
+  tree *compare_expr, *expr_incr, *ind_init;
+  bool **count_down, **array_vector;
+  tree builtin_loop, stmt = NULL_TREE, new_var = NULL_TREE;
+  tree begin_var, lngth_var, strde_var;
+  location_t location = EXPR_LOCATION (orig_stmt);
+  tree an_init, loop_with_init = alloc_stmt_list ();
+  
+  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++)
+    {
+      tree list_node = (*array_list)[ii];
+      if (TREE_CODE (list_node) == CALL_EXPR
+	  || TREE_CODE (list_node) == AGGR_INIT_EXPR)
+	{
+	  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)
+    return stmt;
+  
+  if (list_size == 0)
+    return stmt;
+
+  array_ops = XNEWVEC (tree *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_ops[ii] = XNEWVEC (tree, rank);
+  
+  array_vector = XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_vector[ii] = XNEWVEC (bool, rank);
+
+  array_value = XNEWVEC (tree *, list_size);
+  array_stride = XNEWVEC (tree *, list_size);
+  array_length = XNEWVEC (tree *, list_size);
+  array_start = XNEWVEC (tree *, list_size);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      array_value[ii]  = XNEWVEC (tree, rank);
+      array_stride[ii] = XNEWVEC (tree, rank);
+      array_length[ii] = XNEWVEC (tree, rank);
+      array_start[ii]  = XNEWVEC (tree, rank);
+    }
+
+  compare_expr = XNEWVEC (tree, rank);
+  expr_incr = XNEWVEC (tree, rank);
+  ind_init = XNEWVEC (tree, rank);
+  array_var = XNEWVEC (tree, rank);
+  
+  count_down = XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++) 
+    count_down[ii] = XNEWVEC (bool,  rank);
+
+    /* 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];
+      tree array_begin = ARRAY_NOTATION_START (array_node);
+      tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
+      tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
+      tsubst_flags_t complain = tf_warning_or_error;
+      if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF)
+	{
+	  if (TREE_CODE (array_begin) != INTEGER_CST)
+	    {
+	      begin_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, begin_var,
+						     NOP_EXPR, array_begin,
+						     complain));
+	      ARRAY_NOTATION_START (array_node) = begin_var;
+	    }
+	  if (TREE_CODE (array_lngth) != INTEGER_CST)
+	    {
+	      lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, lngth_var,
+						     NOP_EXPR, array_lngth,
+						     complain));
+	      ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
+	    }
+	  if (TREE_CODE (array_strde) != INTEGER_CST)
+	    {
+	      strde_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, strde_var,
+						     NOP_EXPR, array_strde,
+						     complain));
+	      ARRAY_NOTATION_STRIDE (array_node) = strde_var;
+	    }
+	}
+    }
+  for (ii = 0; ii < list_size; ii++)
+    {
+      jj = 0;
+      jj_tree = (*array_list)[ii];
+      while (jj_tree)
+	{
+	  if (TREE_CODE (jj_tree) == ARRAY_NOTATION_REF)
+	    {
+	      array_ops[ii][jj] = jj_tree;
+	      jj++;
+	      jj_tree = ARRAY_NOTATION_ARRAY (jj_tree);
+	    }
+	  else if (TREE_CODE (jj_tree) == VAR_DECL
+		   || TREE_CODE (jj_tree) == PARM_DECL)
+	    break;
+	  else
+	    jj_tree = TREE_OPERAND (jj_tree, 0);
+	}
+    }
+  for (ii = 0; ii < list_size; ii++)
+    {
+      if (TREE_CODE ((*array_list)[ii]) == ARRAY_NOTATION_REF)
+	{
+	  for (jj = 0; jj < rank; jj++)
+	    {
+	      if (TREE_CODE (array_ops[ii][jj]) == ARRAY_NOTATION_REF)
+		{
+		  array_value[ii][jj] =
+		    ARRAY_NOTATION_ARRAY (array_ops[ii][jj]);
+		  array_start[ii][jj] =
+		    ARRAY_NOTATION_START (array_ops[ii][jj]);
+		  array_length[ii][jj] =
+		    ARRAY_NOTATION_LENGTH (array_ops[ii][jj]);
+		  array_stride[ii][jj] =
+		    ARRAY_NOTATION_STRIDE (array_ops[ii][jj]);
+		  array_vector[ii][jj] = true;
+
+		  if (!TREE_CONSTANT (array_length[ii][jj])
+		      || TREE_CODE (array_length[ii][jj]) == VAR_DECL)
+		    count_down[ii][jj] = false;
+		  else if (!integer_zerop (array_length[ii][jj])
+		      && !integer_nonzerop (array_length[ii][jj]))
+		      count_down[ii][jj] = false;
+		  else if (tree_int_cst_lt
+			   (array_length[ii][jj],
+			    build_zero_cst (TREE_TYPE (array_length[ii][jj]))))
+		    count_down[ii][jj] = true;
+		  else
+		    count_down[ii][jj] = false;
+		}
+	      else
+		array_vector[ii][jj] = false;
+	    }
+	}
+    }
+
+  an_init = push_stmt_list ();
+  for (ii = 0; ii < rank; ii++)
+    {
+      array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
+				  TREE_TYPE (array_start[0][ii]));
+      ind_init[ii] = build_x_modify_expr
+	(location, array_var[ii], NOP_EXPR, 
+	 build_zero_cst (TREE_TYPE (array_var[ii])), tf_warning_or_error);
+    }
+  for (ii = 0; ii < list_size; ii++)
+    {
+      if (array_vector[ii][0])
+	{
+	  array_opr = array_value[ii][rank - 1];
+	  for (s_jj = rank - 1; s_jj >= 0; s_jj--)
+	    {
+	      tree stride = NULL_TREE, var = NULL_TREE, start = NULL_TREE;
+	      if ((TREE_TYPE (array_start[ii][s_jj]) ==
+		   TREE_TYPE (array_stride[ii][s_jj]))
+		  && (TREE_TYPE (array_stride[ii][s_jj]) !=
+		      TREE_TYPE (array_var[s_jj])))
+		{
+		  /* If stride and start are of same type and the induction var
+		     is not, convert induction variable to stride's type.  */
+		  start = array_start[ii][s_jj];
+		  stride = array_stride[ii][s_jj];
+		  var =
+		    build_c_cast (location, TREE_TYPE (array_stride[ii][s_jj]),
+				  array_var[s_jj]);
+		}
+	      else if (TREE_TYPE (array_start[ii][s_jj]) !=
+			TREE_TYPE (array_stride[ii][s_jj]))
+		{
+		  /* 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 -.  */
+		  start = build_c_cast (location, integer_type_node,
+					array_start[ii][s_jj]);
+		  stride = build_c_cast (location, integer_type_node,
+					 array_stride[ii][s_jj]);
+		  var = build_c_cast (location, integer_type_node,
+				      array_var[s_jj]);
+		}
+	      else
+		{
+		  start = array_start[ii][s_jj];
+		  stride = array_stride[ii][s_jj];
+		  var = array_var[s_jj];
+		}
+	      if (count_down[ii][s_jj])
+		/* Array[start_index - (induction_var * stride)].  */
+		array_opr = grok_array_decl
+		  (location, array_opr,
+		   build2 (MINUS_EXPR, TREE_TYPE (var), start,
+			   build2 (MULT_EXPR, TREE_TYPE (var), var, stride)),
+		   false);	
+	      else
+		/* Array[start_index + (induction_var * stride)].  */
+		array_opr = grok_array_decl
+		  (location, array_opr,
+		   build2 (PLUS_EXPR, TREE_TYPE (var), start,
+			   build2 (MULT_EXPR, TREE_TYPE (var), var, stride)),
+		   false);
+	    }
+	  vec_safe_push (array_operand, array_opr);  
+	}
+      else
+	vec_safe_push (array_operand, integer_one_node);
+    }
+  replace_array_notations (&stmt, true, array_list, array_operand);
+
+  for (ii = 0; ii < rank; ii++)
+    if (count_down[0][ii])
+      expr_incr[ii] = build_x_unary_op (location, POSTDECREMENT_EXPR,
+					array_var[ii], tf_warning_or_error);
+    else
+      expr_incr[ii] = build_x_unary_op (location, POSTINCREMENT_EXPR,
+					array_var[ii], tf_warning_or_error);
+
+  for (jj = 0; jj < rank; jj++)
+    {
+      if (rank && expr_incr[jj])
+	{
+	  if (count_down[0][jj])
+	    compare_expr[jj] = build_x_binary_op
+	      (location, GT_EXPR, array_var[jj], TREE_CODE (array_var[jj]),
+	       array_length[0][jj], TREE_CODE (array_length[0][jj]), NULL,
+	       tf_warning_or_error);
+	  else
+	    compare_expr[jj] = build_x_binary_op
+	      (location, LT_EXPR, array_var[jj], TREE_CODE (array_var[jj]),
+	       array_length[0][jj], TREE_CODE (array_length[0][jj]), NULL,
+	       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 (ind_init[ii], compare_expr[ii], expr_incr[ii], body);
+      body = pop_stmt_list (new_loop);
+    }
+  append_to_statement_list_force (body, &loop_with_init);
+
+  XDELETEVEC (compare_expr);
+  XDELETEVEC (expr_incr);
+  XDELETEVEC (ind_init);
+  XDELETEVEC (array_var);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      XDELETEVEC (count_down[ii]);
+      XDELETEVEC (array_value[ii]);
+      XDELETEVEC (array_stride[ii]);
+      XDELETEVEC (array_length[ii]);
+      XDELETEVEC (array_start[ii]);
+      XDELETEVEC (array_ops[ii]);
+      XDELETEVEC (array_vector[ii]);
+    }
+    
+  XDELETEVEC (count_down);
+  XDELETEVEC (array_value);
+  XDELETEVEC (array_stride);
+  XDELETEVEC (array_length);
+  XDELETEVEC (array_start);
+  XDELETEVEC (array_ops);
+  XDELETEVEC (array_vector);
+
+  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;
+  location_t loc = EXPR_LOCATION (expr);
+
+  if (TREE_CODE (expr) != RETURN_EXPR)
+    return 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;
+  
+  /* Skip empty subtrees.  */
+  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;
+}
diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c
index bccd884..d301db0 100644
--- a/gcc/cp/cp-objcp-common.c
+++ b/gcc/cp/cp-objcp-common.c
@@ -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"
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 9421822..4791a32 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6135,6 +6135,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 */
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
old mode 100644
new mode 100755
index a75fc4e..a8f52cd
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -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;
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
old mode 100644
new mode 100755
index a581e88..523dcf7
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -6060,6 +6060,168 @@ 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.  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 +6243,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;
 }
 
@@ -9342,6 +9541,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;
 }
 
@@ -9534,6 +9735,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;
@@ -10094,6 +10303,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;
 
@@ -10120,6 +10335,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;
 
@@ -10138,8 +10362,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;
 
@@ -16714,30 +16947,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
@@ -18108,6 +18364,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);
 
@@ -22087,6 +22348,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));
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
old mode 100644
new mode 100755
index 3602fcd..0a7d523
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -13740,6 +13740,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));
@@ -15712,6 +15726,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;
@@ -19119,6 +19136,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);
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index b5c3b0a..656962b 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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 notatinos, 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 ())
@@ -8066,6 +8082,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);
@@ -8877,6 +8894,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:
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 8524f6c..dd2fda4 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -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;
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
old mode 100644
new mode 100755
index 11ac85b..17f19c7
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
old mode 100644
new mode 100755
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/array_test1.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/array_test1.c
index e4f1ea8..282a55d 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/array_test1.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/array_test1.c
@@ -1,4 +1,4 @@
-/* { dg-do compile } */
+/* { dg-do run } */
 /* { dg-options "-fcilkplus" } */
 
 #include <stdlib.h>
@@ -47,7 +47,7 @@ int main2 (char **argv)
   array[x:y:z] = 505;
   for (ii = x; ii < 10; ii += z)
     if (array[ii] != 505)
-      return 2;
+      return 4;
     
   x = atoi(argv[1]);
   z = (10-atoi(argv[1]))/atoi(argv[1]);
@@ -57,7 +57,7 @@ int main2 (char **argv)
 
   for (ii = x; ii < 10; ii += z)
     if (array[ii] != 25)
-      return 1;
+      return 5;
   x = atoi(argv[1]);
   z = (10-atoi(argv[1]))/atoi(argv[1]);
   y = 10-atoi(argv[1]);
@@ -66,19 +66,19 @@ int main2 (char **argv)
     1400;
   for (ii = x; ii < 10; ii += z)
     if (array[ii] != 1400)
-      return 1;
+      return 6;
   
 
   array[atoi("5"):5:1] = 5555;
   
   for (ii = atoi ("5"); ii < 10; ii++)
     if (array[ii] != 5555)
-      return 2;
+      return 7;
   
 
   array[atoi("5"):atoi("5"):atoi("1")] = 9999;
   for (ii = atoi ("5"); ii < (atoi ("5") + atoi ("5")); ii += atoi ("1"))
     if (array[ii] != 9999)
-      return 3;
+      return 8;
   return 0;
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c
index d17d8cf..579d396 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c
@@ -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;
 
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
index 35eb115..14421d9 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
@@ -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;
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c
old mode 100644
new mode 100755
index a0a3742..18816e0
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c
@@ -8,4 +8,4 @@ int main (void)
   array2[:] = array2[: ;  /* { dg-error "expected ']'" } */
 
   return 0;
-} /* { dg-error "expected ';' before" } */
+} /* { dg-error "expected ';' before" "" { target c } } */
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c
index 2e86b4f..4314090 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c
@@ -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 }  } */
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c
index 34dfa16..47b5979 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c
@@ -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 } } */
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c
index eba28a8..a0efc04 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c
@@ -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;
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c
index cabdb23..793afb2 100755
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c
@@ -4,11 +4,11 @@
 int A[10];
 
 int main () {
-  char c = (char)N; /* { dg-error "undeclared" } */
+  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 }  7 } */
 
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c
index 843745e..3b0777e 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c
@@ -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
index 0000000..e9ee7ec
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/array_test1_tplt.cc
@@ -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
index 0000000..87c37e1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/array_test2_tplt.cc
@@ -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
index 0000000..479ba13
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/array_test_ND_tplt.cc
@@ -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 100755
index 0000000..b91de7a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/braced_list.cc
@@ -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
index 0000000..94ffe6e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_custom_tplt.cc
@@ -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
index 0000000..db81912
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_mutating_tplt.cc
@@ -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
index 0000000..1387558
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/fp_triplet_values_tplt.c
@@ -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/cilk-plus.exp b/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp
new file mode 100644
index 0000000..a153529
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp
@@ -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
diff --git a/gcc/testsuite/g++.dg/dg.exp b/gcc/testsuite/g++.dg/dg.exp
old mode 100644
new mode 100755
index 7201359..710218e
--- a/gcc/testsuite/g++.dg/dg.exp
+++ b/gcc/testsuite/g++.dg/dg.exp
@@ -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/*]

^ permalink raw reply	[flat|nested] 40+ messages in thread

* RE: [PATCH] Cilk Plus Array Notation for C++
  2013-06-12 16:34 ` Aldy Hernandez
  2013-06-12 17:20   ` Iyer, Balaji V
  2013-06-12 20:50   ` Iyer, Balaji V
@ 2013-06-12 21:32   ` Iyer, Balaji V
  2 siblings, 0 replies; 40+ messages in thread
From: Iyer, Balaji V @ 2013-06-12 21:32 UTC (permalink / raw)
  To: Aldy Hernandez; +Cc: gcc-patches, Jason Merrill (jason@redhat.com), rth

[-- Attachment #1: Type: text/plain, Size: 19117 bytes --]

Hi Aldy et al.,
	I am sorry but I forgot to cut and paste the ChangeLog entries in my previous reply.  I am also attaching the patch again, so that they can all be in the same message.

Here you go:

gcc/cp/ChangeLog
2013-06-12  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-12  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/cilk-plus.exp: New script.
        * gcc/testsuite/g++.dg/dg.exp: Included Cilk Plus C++ tests in the list.


Thanks,

Balaji V. Iyer.

> -----Original Message-----
> From: Iyer, Balaji V
> Sent: Wednesday, June 12, 2013 4:50 PM
> To: 'Aldy Hernandez'
> Cc: gcc-patches@gcc.gnu.org; Jason Merrill (jason@redhat.com);
> rth@redhat.com
> Subject: RE: [PATCH] Cilk Plus Array Notation for C++
> 
> Hi Aldy,
> 	Please see my comments below with the fixed patch.
> 
> Thanks,
> 
> Balaji V. Iyer.
> 
> > -----Original Message-----
> > From: Aldy Hernandez [mailto:aldyh@redhat.com]
> > Sent: Wednesday, June 12, 2013 12:34 PM
> > To: Iyer, Balaji V
> > Cc: gcc-patches@gcc.gnu.org; Jason Merrill (jason@redhat.com);
> > rth@redhat.com
> > Subject: Re: [PATCH] Cilk Plus Array Notation for C++
> >
> > [Jason/Richard: there are some things below I could use your feedback
> > on.]
> >
> > Hi Balaji.
> >
> > Overall, a lot of the stuff in cp-array-notation.c looks familiar from
> > the C front- end changes.  Can't you reuse a lot of it?
> >
> > Otherwise, here are some minor nits...
> >
> > > +      /* If the function call is builtin array notation function then we do not
> > > +	 need to do any type conversion.  */
> > > +      if (flag_enable_cilkplus && fn && TREE_CODE (fn) == FUNCTION_DECL
> > > +	  && DECL_NAME (fn) && IDENTIFIER_POINTER (DECL_NAME (fn))
> > > +	  && !strncmp (IDENTIFIER_POINTER (DECL_NAME (fn)),
> > "__sec_reduce", 12))
> > > +	val = arg;
> >
> > Don't we have BUILT_IN_CILKPLUS_SEC_REDUCE* now?  So you shouldn't
> > need to poke at the actual identifier.  And even so, won't the above
> > strncmp match __sec_reducegarbage?
> 
> FIXED!
> 
> >
> > > +/* This function parses Cilk Plus array notations.  The starting index is
> > > +   passed in INIT_INDEX and the array name is passed in ARRAY_VALUE.  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.  */
> > > +
> >
> > It looks like a NULL in INIT_INDEX is a specially handled case.
> > Perhaps you should document that INIT_INDEX can be null and what it means.
> > Also, you don't need to document what internal variable name you are
> > using as a return value (VALUE_TREE).  Perhaps instead of "The return
> > value..." you could write "This function returns the
> > ARRAY_NOTATION_REF node." or something like it.
> 
> It is documented inside the function, right before checking for !init_index. Is that
> enough?
> 
> >
> > > +    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));
> > > +
> > > +	/* We do type-checking here for templatized array notation triplets.  */
> > > +	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 (error_mark_node);
> > > +	  }
> > > +	if (!TREE_TYPE (length) || !INTEGRAL_TYPE_P (TREE_TYPE (length)))
> > > +	  {
> > > +	    error_at (loc, "length of array notation triplet is not an "
> > > +		      "integer");
> > > +	    RETURN (error_mark_node);
> > > +	  }
> > > +	if (!TREE_TYPE (stride) || !INTEGRAL_TYPE_P (TREE_TYPE (stride)))
> > > +	  {
> > > +	    error_at (loc, "stride of array notation triplet is not an "
> > > +		      "integer");
> > > +	    RETURN (error_mark_node);
> > > +	  }
> > > +	if (TREE_CODE (TREE_TYPE (op1)) == FUNCTION_TYPE)
> > > +	  {
> > > +	    error_at (loc, "array notations cannot be used with function type");
> > > +	    RETURN (error_mark_node);
> > > +	  }
> > > +	RETURN (build_array_notation_ref (EXPR_LOCATION (t), op1,
> > start_index,
> > > +					  length, stride, TREE_TYPE (op1)));
> > > +      }
> >
> >
> > You do all this type checking here, but aren't you doing the same type
> > checking in build_array_notation_ref() which you're going to call
> > anyway?  It looks like there is some code duplication going on.
> >
> > Also, I see you have a build_array_notation_ref() in
> > cp/cp-array-notation.c and also in c/c-array-notation.c.  Can you not
> > implement one function that handles both C and C++, or at the very least reuse
> some of the common things?
> 
> As we discussed in the previous email-exchange, I have created a new function
> called cilkplus_an_triplet_types_ok_p (). The reason why I prefixed "cilkplus_an"
> is because it is not a static function and I want to make sure this is unique and
> descriptive and does not cause any interference with anything present or future.
> 
> >
> > You are missing a ChangeLog entry for the above snippet.
> 
> I have put it in now.
> 
> >
> > > +      /* If the return expr. has a builtin array notation function, then its
> > > +	 OK.  */
> > > +      if (rank >= 1)
> > > +	{
> > > +	  error_at (input_location, "array notation expression cannot be "
> > > +		    "used as a return value");
> > > +	  return error_mark_node;
> > > +	}
> >
> > The comment doesn't seem to match the code, or am I missing something?
> >
> > > +      /* If find_rank returns false,  then it should have reported
> > > + an error,
> 
> FIXED
> 
> >
> > Extra whitespace.
> >
> > > +      if (rank > 1)
> > > +	{
> > > +	  error_at (loc, "rank of the array%'s index is greater than 1");
> > > +	  return error_mark_node;
> > > +	}
> >
> > No corresponding test.
> 
> This is being tested in the file "testsuite/c-c++-common/cilk-plus/AN/gather-
> scatter-errors.c"
> 
> >
> > > +  /* 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.  */
> >
> > Line too long, please wrap.
> >
> > There are various lines throughout your patch that are pretty long
> > (both in code and in ChangeLog entries).  I don't know what the
> > official GNU guidelines say, but what I usually see as prior art in
> > the GCC code base is something along the lines of wrapping around
> > column 72.  Perhaps someone can pontificate on this, but lines reaching the
> 78-80 columns look pretty darn long to me.
> 
> The line length is specified to be at most 80 characters
> (http://gcc.gnu.org/codingconventions.html#Line). I have followed it
> everywhere except in the cases of dg-error since I can't fit them all in one line.
> >
> > > diff --git gcc/testsuite/c-c++-common/cilk-plus/AN/sec_implicit_ex.c
> > > gcc/testsuite/c-c++-common/cilk-plus/AN/sec_implicit_ex.c
> > > index c22b818..b863276 100644
> > > --- gcc/testsuite/c-c++-common/cilk-plus/AN/sec_implicit_ex.c
> > > +++ gcc/testsuite/c-c++-common/cilk-plus/AN/sec_implicit_ex.c
> > > @@ -1,9 +1,6 @@
> > >  /* { dg-do run } */
> > >  /* { dg-options "-fcilkplus" } */
> > >
> > > -void abort (void);
> > > -void exit  (int);
> > > -
> > >
> > >  int main(void)
> > >  {
> > > @@ -24,10 +21,7 @@ int main(void)
> > >      for (jj = 0; jj < 10; jj++)
> > >        for (kk = 0; kk < 10; kk++)
> > >  	if (array_3[ii][jj][kk] != array_3C[ii][jj][kk])
> > > -	  abort ();
> > > +	  return 1;
> > >
> > > -
> > > -  exit (0);
> > > -
> >  >   return 0;
> >
> > Changes to existing tests should be submitted as a separate patch,
> > since this doesn't seem to be C++ specific.  And BTW, this particular
> > test change can be committed as obvious.
> 
> OK will do.  What about adding {target c} and {target c++} for test cases. Can
> that be submitted with the patch?
> 
> >
> > > +  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; #if 1  for (int ii = 0;
> > > + ii < 10; ii++)
> > > +    {
> > > +      if (ii%2 && ii)
> >
> > Remove this redundant #if 1/#endif pair.  Similarly in other tests.
> 
> FIXED!
> 
> >
> > > +	    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");
> >
> > No corresponding test, or is this handled by the existing
> > c-c++-common/cilk-plus tests?
> 
> Please see c-c++-common/cilk-plus/AN/misc.c
> 
> >
> > > +		  /* 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");
> >
> > No need to document the obvious.  The error message can be used in
> > lieu of the comment :).  Also, no corresponding test.  I didn't see
> > one matching in c-c++- common/cilkplus either.
> 
> OK. This testcase (testsuite/c-c++-common/cilk-plus/AN/fn_ptr.c) checks this
> error.
> 
> >
> > > +	      /* Disable correcting single colon correcting to scope.  */
> > > +	      parser->colon_corrects_to_scope_p = false;
> >
> > No need to document the obvious.
> 
> FIXED!
> 
> >
> > I suggest a different name for fix_array_notation_exprs() to avoid
> > confusion with the C function fix_array_notation_expr() (no final "s").
> >   Perhaps cpp_fix_array_notation_expr, or something similar?
> >
> > > +/* Handles expression of the form "a[i:j:k]" or "a[:]" or "a[i:j]," which
> > > +   denotes an array notation expression.  If a is a variable or a
> > > +member, then
> >
> > Do you mean "ARRAY" instead of "a"?
> >
> > > +   we generate a ARRAY_NOTATION_REF front-end tree and return it.
> >
> > s/a ARRAY/an ARRAY/
> >
> > > +   This tree is broken down to ARRAY_REF toward the end of parsing.
> > > +   ARRAY_NOTATION_REF tree holds the START_INDEX, LENGTH, STRIDE
> > > + and
> > the TYPE
> > > +   of ARRAY_REF.  Restrictions on START_INDEX, LENGTH and STRIDE is
> > > + same
> > as that
> > > +   of the 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)
> >
> > Overall this function comment needs to be reworded.  From reading the
> > comment, I still don't know what the function actually does and what it
> returns.
> > "Handles expression..." is rather ambiguous.  Perhaps something like
> > "Given a blah blah blah in ARRAY, construct an ARRAY_NOTATION_REF and
> return it.
> > START_INDEX is blah, LENGTH is blah, etc etc".
> 
> Reworded it. Please let me know if it is OK.
> 
> >
> > Again, you can probably reuse a lot of the C counterpart.  It looks
> > like a lot of the same code.
> >
> > > +  XDELETEVEC (compare_expr);
> > > +  XDELETEVEC (expr_incr);
> > > +  XDELETEVEC (ind_init);
> > > +  XDELETEVEC (array_var);
> > > +
> > > +  for (ii = 0; ii < list_size; ii++)
> > > +    {
> > > +      XDELETEVEC (count_down[ii]);
> > > +      XDELETEVEC (array_value[ii]);
> > > +      XDELETEVEC (array_stride[ii]);
> > > +      XDELETEVEC (array_length[ii]);
> > > +      XDELETEVEC (array_start[ii]);
> > > +      XDELETEVEC (array_ops[ii]);
> > > +      XDELETEVEC (array_vector[ii]);
> > > +    }
> > > +
> > > +  XDELETEVEC (count_down);
> > > +  XDELETEVEC (array_value);
> > > +  XDELETEVEC (array_stride);
> > > +  XDELETEVEC (array_length);
> > > +  XDELETEVEC (array_start);
> > > +  XDELETEVEC (array_ops);
> > > +  XDELETEVEC (array_vector);
> >
> > I see a lot of this business going on.  Perhaps one of the core
> > maintainers can comment, but I would rather use an obstack, and avoid
> > having to keep track of all these little buckets-- which seems rather
> > error prone, and then free the obstack all in one swoop.  But I'll defer to
> Richard or Jason.
> >
> >
> > > +		     is not, we convert induction variable to stride's
> >
> > Rephrase as "is not, convert the induction variable to the stride's"
> > Similarly in a few other places.  It looks like you used the same comment.
> 
> FIXED!
> 
> >
> > > +		  /* 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, we stay safe and convert
> >
> > s/type is, we stay safe/type is.  We stay safe/.
> > Similarly in a few other places.  It looks like you used the same comment.
> 
> FIXED!
> 
> >
> > > +		     everything to integer.  The reason why we pick integer
> >
> > s/pick integer/pick an integer
> > Similarly in a few other places.
> 
> FIXED!
> 
> >
> > > +/* 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
> > > +build_x_array_notation_expr (location_t location, tree lhs,
> > > +			     enum tree_code modifycode, tree rhs,
> > > +			     tsubst_flags_t complain)
> >
> > This is called "build_x_array_notation_expr", but it doesn't look like
> > we build any ARRAY_NOTATION_EXPRs in here.  Perhaps a better name
> > would be "expand_array_notation_expr" (or something to that effect)?
> 
> I renamed this function to "expand_an_in_modify_expr" to indicate that we are
> expanding array notations in modify expr.
> 
> >
> > > +static tree
> > > +fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
> >
> > It looks like this function expands the __sec_reduce* builtins.
> > Perhaps it would be cleaner to rename it as such?  Maybe...
> > "expand_sec_reduce_builtin" or something?
> 
> FIXED!
> 
> >
> > The fact that you are sometimes using "build_*" and sometimes "fix_*"
> > to denote expansion is confusing.
> 
> Replaced all the "fix" with "expand"
> 
> >
> > > +/* Returns true of NODE has a call_expression with
> > > +ARRAY_NOTATION_REF tree.  */
> > > +
> > > +static bool
> > > +has_call_expr_with_array_notation (tree node)
> >
> > s/of NODE/if NODE
> 
> FIXED!
> 
> >
> > Thanks.
> > Aldy

[-- Attachment #2: patch_array_notation_cpp.txt --]
[-- Type: text/plain, Size: 157027 bytes --]

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
old mode 100644
new mode 100755
index 2c93982..362f0bc
Binary files a/gcc/cp/ChangeLog and b/gcc/cp/ChangeLog differ
diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
index df8ed3e..6e80bcf 100644
--- a/gcc/cp/Make-lang.in
+++ b/gcc/cp/Make-lang.in
@@ -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)
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index dfd061a..64be41f 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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 100755
index 0000000..34c73f3
--- /dev/null
+++ b/gcc/cp/cp-array-notation.c
@@ -0,0 +1,2850 @@
+/* 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);
+}
+
+/* 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;
+}
+
+/* Returns true if NODE has a call_expression with ARRAY_NOTATION_REF tree.  */
+
+static bool
+has_call_expr_with_array_notation (tree node)
+{
+  int ii = 0;
+  
+  if (!contains_array_notation_expr (node))
+    return false;
+  
+  if (TREE_CODE (node) == ARRAY_NOTATION_REF)
+    return false;
+  else if (TREE_CODE (node) == DECL_EXPR)
+    {
+      tree x = DECL_EXPR_DECL (node);
+      if (x && TREE_CODE (x) != FUNCTION_DECL)
+	if (DECL_INITIAL (x))
+	  return has_call_expr_with_array_notation (DECL_INITIAL (x));
+	
+    }
+  else if (TREE_CODE (node) == STATEMENT_LIST)
+    {
+      tree_stmt_iterator ii_tsi;
+      for (ii_tsi = tsi_start (node); !tsi_end_p (ii_tsi); tsi_next (&ii_tsi))
+	return has_call_expr_with_array_notation (*tsi_stmt_ptr (ii_tsi));
+    }
+  else if (TREE_CODE (node) == CALL_EXPR)
+    {
+      if (is_cilkplus_reduce_builtin (CALL_EXPR_FN (node)) != BUILT_IN_NONE)
+	return true;
+	
+      if (is_sec_implicit_index_fn (CALL_EXPR_FN (node)))
+	return true;
+	 
+      if (TREE_CODE (TREE_OPERAND (node, 0)) == INTEGER_CST)
+	{
+	  int length = TREE_INT_CST_LOW (TREE_OPERAND (node, 0));
+	  bool x = false;
+	  for (ii = 0; ii < length; ii++)
+	    x |= contains_array_notation_expr (TREE_OPERAND (node, ii));
+	  return x;
+	}
+      else
+	gcc_unreachable  ();	  
+    } 
+  else
+    {
+      bool x = false;
+      for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (node)); ii++) 
+	x |= has_call_expr_with_array_notation (TREE_OPERAND (node, ii));
+      return x;
+    }
+  return false;
+}
+
+/* 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_expr, 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; 
+  tree new_var_init = NULL_TREE, new_exp_init = NULL_TREE;
+  vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
+  int s_jj = 0;
+  size_t list_size = 0, rank = 0, ii = 0, jj = 0;
+  tree **array_ops, *array_var, jj_tree;
+  tree **array_value, **array_stride, **array_length, **array_start;
+  tree  body, an_init, loop_with_init = alloc_stmt_list ();
+  tree *compare_expr, array_op0, *expr_incr, *ind_init, comp_node;
+  tree call_fn = NULL_TREE, identity_value = NULL_TREE, new_call_expr;
+  bool **count_down, **array_vector;
+  tree begin_var, lngth_var, strde_var;
+  location_t location = UNKNOWN_LOCATION;
+  tsubst_flags_t complain = tf_warning_or_error;
+
+  enum built_in_function an_type =
+    is_cilkplus_reduce_builtin (CALL_EXPR_FN (an_builtin_fn));
+  
+  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!  */
+      while (TREE_CODE (call_fn) == CONVERT_EXPR
+	     || TREE_CODE (call_fn) == NOP_EXPR)
+	call_fn = TREE_OPERAND (call_fn, 0);
+
+      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);
+
+      /* 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!  */
+      while (TREE_CODE (identity_value) == CONVERT_EXPR
+	     || TREE_CODE (identity_value) == NOP_EXPR)
+	identity_value = TREE_OPERAND (identity_value, 0);
+    }
+
+  while (TREE_CODE (func_parm) == CONVERT_EXPR
+	 || TREE_CODE (func_parm) == NOP_EXPR)
+    func_parm = TREE_OPERAND (func_parm, 0);
+  
+  location = EXPR_LOCATION (an_builtin_fn);
+  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);
+  
+  array_ops = XNEWVEC (tree *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_ops[ii] = XNEWVEC (tree,  rank);
+  
+  array_vector = XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_vector[ii] = XNEWVEC (bool, rank);
+
+  array_value =  XNEWVEC (tree *, list_size);
+  array_stride =  XNEWVEC (tree *, list_size);
+  array_length =  XNEWVEC (tree *, list_size);
+  array_start =  XNEWVEC (tree *, list_size);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      array_value[ii]  = XNEWVEC (tree, rank);
+      array_stride[ii] = XNEWVEC (tree, rank);
+      array_length[ii] = XNEWVEC (tree, rank);
+      array_start[ii]  = XNEWVEC (tree, rank);
+    }
+
+  compare_expr = XNEWVEC (tree, rank);
+  expr_incr = XNEWVEC (tree, rank);
+  ind_init = XNEWVEC (tree, rank);
+  
+  count_down = XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    count_down[ii] = XNEWVEC (bool, rank);
+  
+  array_var = XNEWVEC (tree, 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];
+      tree array_begin = ARRAY_NOTATION_START (array_node);
+      tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
+      tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
+      if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF)
+	{
+	  if (TREE_CODE (array_begin) != INTEGER_CST)
+	    {
+	      begin_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, begin_var,
+						     NOP_EXPR, array_begin,
+						     complain));
+	      ARRAY_NOTATION_START (array_node) = begin_var;
+	    }
+	  if (TREE_CODE (array_lngth) != INTEGER_CST)
+	    {
+	      lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, lngth_var,
+						     NOP_EXPR, array_lngth,
+						     complain));
+	      ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
+	    }
+	  if (TREE_CODE (array_strde) != INTEGER_CST)
+	    {
+	      strde_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, strde_var,
+						     NOP_EXPR, array_strde,
+						     complain));
+	      ARRAY_NOTATION_STRIDE (array_node) = strde_var;
+	    }
+	}
+    }
+  for (ii = 0; ii < list_size; ii++)
+    {
+      jj = 0;
+      jj_tree = (*array_list)[ii];
+      while (jj_tree)
+	{
+	  if (TREE_CODE (jj_tree) == ARRAY_NOTATION_REF)
+	    {
+	      array_ops[ii][jj] = jj_tree;
+	      jj++;
+	      jj_tree = ARRAY_NOTATION_ARRAY (jj_tree);
+	    }
+	  else if (TREE_CODE (jj_tree) == ARRAY_REF)
+	    jj_tree = TREE_OPERAND (jj_tree, 0);
+	  else if (TREE_CODE (jj_tree) == VAR_DECL
+		   || TREE_CODE (jj_tree) == PARM_DECL)
+	    break;
+	}
+    }
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      if (TREE_CODE ((*array_list)[ii]) == ARRAY_NOTATION_REF)
+	for (jj = 0; jj < rank; jj++)
+	  {
+	    if (TREE_CODE (array_ops[ii][jj]) == ARRAY_NOTATION_REF)
+	      {
+		array_value[ii][jj] =
+		  ARRAY_NOTATION_ARRAY (array_ops[ii][jj]);
+		array_start[ii][jj] =
+		  ARRAY_NOTATION_START (array_ops[ii][jj]);
+		array_length[ii][jj] =
+		  fold_build1 (CONVERT_EXPR, integer_type_node,
+			       ARRAY_NOTATION_LENGTH (array_ops[ii][jj]));
+		array_stride[ii][jj] =
+		  ARRAY_NOTATION_STRIDE (array_ops[ii][jj]);
+		array_vector[ii][jj] = true;
+
+		if (!TREE_CONSTANT (array_length[ii][jj])
+		    || TREE_CODE (array_length[ii][jj]) != INTEGER_TYPE)
+		  count_down[ii][jj] = false;
+		else if (tree_int_cst_sgn (array_length[ii][jj]) == -1)
+		  count_down[ii][jj] = true;
+		else
+		  count_down[ii][jj] = false;
+	      }
+	    else
+	      array_vector[ii][jj] = false;
+	  }
+    }
+
+  for (ii = 0; ii < rank; ii++)
+    {
+      array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
+				  TREE_TYPE (array_start[0][ii]));
+      ind_init[ii] = build_x_modify_expr
+	(location, array_var[ii], NOP_EXPR, 
+	 build_zero_cst (TREE_TYPE (array_var[ii])), tf_warning_or_error);
+    }
+  for (ii = 0; ii < list_size; ii++)
+    if (array_vector[ii][0])
+      {
+	tree array_opr = array_value[ii][rank - 1];
+	for (s_jj = rank - 1; s_jj >= 0; s_jj--)
+	  {
+	    tree stride = NULL_TREE, var = NULL_TREE, start = NULL_TREE;
+
+	    /* If stride and start are of same type and the induction var
+	       is not, convert induction variable to stride's type.  */
+	    if ((TREE_TYPE (array_start[ii][s_jj]) ==
+		 TREE_TYPE (array_stride[ii][s_jj]))
+		&& (TREE_TYPE (array_stride[ii][s_jj]) !=
+		    TREE_TYPE (array_var[s_jj])))
+	      {
+		start = array_start[ii][s_jj];
+		stride = array_stride[ii][s_jj];
+		var =
+		  build_c_cast (location, TREE_TYPE (array_stride[ii][s_jj]),
+				array_var[s_jj]);
+	      }
+	    else if (TREE_TYPE (array_start[ii][s_jj]) !=
+		     TREE_TYPE (array_stride[ii][s_jj]))
+	      {
+		/* 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 -.  */
+		start = build_c_cast (location, integer_type_node,
+				      array_start[ii][s_jj]);
+		stride = build_c_cast (location, integer_type_node,
+				       array_stride[ii][s_jj]);
+		var = build_c_cast (location, integer_type_node,
+				    array_var[s_jj]);
+	      }
+	    else
+	      {
+		start = array_start[ii][s_jj];
+		stride = array_stride[ii][s_jj];
+		var = array_var[s_jj];
+	      }
+	    if (count_down[ii][s_jj])
+	      /* Array[start_index - (induction_var * stride)].  */
+	      array_opr = grok_array_decl
+		(location, array_opr,
+		 build2 (MINUS_EXPR, TREE_TYPE (var), start,
+			 build2 (MULT_EXPR, TREE_TYPE (var), var, stride)),
+		 false);	
+	    else
+	      /* Array[start_index + (induction_var * stride)].  */
+	      array_opr = grok_array_decl
+		(location, array_opr,
+		 build2 (PLUS_EXPR, TREE_TYPE (var), start,
+			 build2 (MULT_EXPR, TREE_TYPE (var), var, stride)),
+		 false);
+	  }
+	vec_safe_push (array_operand, array_opr);
+      }
+    else
+      vec_safe_push (array_operand, integer_one_node);
+    
+  replace_array_notations (&func_parm, true, array_list, array_operand);
+  
+  if (!TREE_TYPE (func_parm))      
+    TREE_TYPE (func_parm) = TREE_TYPE ((*array_list)[0]);
+  
+  for (ii = 0; ii < rank; ii++)
+    if (count_down[0][ii])
+      expr_incr[ii] = build_x_unary_op (location, POSTDECREMENT_EXPR,
+					array_var[ii], tf_warning_or_error);
+    else
+      expr_incr[ii] = build_x_unary_op (location, POSTINCREMENT_EXPR,
+					array_var[ii], tf_warning_or_error);
+  
+  for (jj = 0; jj < rank; jj++)
+    if (rank && expr_incr[jj])
+      {
+	if (count_down[0][jj])
+	  compare_expr[jj] = build_x_binary_op
+	    (location, GT_EXPR, array_var[jj], TREE_CODE (array_var[jj]),
+	     array_length[0][jj], TREE_CODE (array_length[0][jj]), NULL,
+	     tf_warning_or_error);
+	else
+	  compare_expr[jj] = build_x_binary_op
+	    (location, LT_EXPR, array_var[jj], TREE_CODE (array_var[jj]),
+	     array_length[0][jj], TREE_CODE (array_length[0][jj]), NULL,
+	     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 a 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];
+  if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ADD)
+    {
+      if (ARITHMETIC_TYPE_P (new_var_type))
+	new_var_init = build_x_modify_expr (location, *new_var, 
+					    NOP_EXPR,
+					    build_zero_cst (new_var_type), 1);
+      else
+	new_var_init = build_x_modify_expr (location, *new_var, 
+					    NOP_EXPR,
+					    integer_zero_node, 1);
+      new_expr = build_x_modify_expr (location, *new_var, PLUS_EXPR, 
+				      func_parm, 1);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MUL)
+    {
+      if (ARITHMETIC_TYPE_P (new_var_type))
+	new_var_init = build_x_modify_expr (location, *new_var, 
+					    NOP_EXPR,
+					    build_one_cst (new_var_type), 1);
+      else
+	new_var_init = build_x_modify_expr (location, *new_var, 
+					    NOP_EXPR,
+					    integer_one_node, 1);
+      new_expr = build_x_modify_expr (location, *new_var, MULT_EXPR, 
+				      func_parm, 1);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO)
+    {
+      new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  build_one_cst (new_var_type), 1);
+      /* Initially you assume everything is zero, now if we find a case where
+	 it is NOT true, then we set the result to false. Otherwise we just
+	 keep the previous value.  */
+      new_yes_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  build_zero_cst (new_var_type), 1);
+      new_no_expr = build_x_modify_expr (location, *new_var, NOP_EXPR, 
+					 *new_var, 1);
+      if (ARITHMETIC_TYPE_P (TREE_TYPE (func_parm)))
+	comp_node = build_zero_cst (TREE_TYPE (func_parm));
+      else
+	comp_node = integer_zero_node;
+      new_cond_expr = build_x_binary_op
+	(location, NE_EXPR, 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);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO)
+    {
+      new_var_init = build_x_modify_expr
+	(location, *new_var, NOP_EXPR, build_one_cst (new_var_type), 1);
+      /* Initially you assume everything is non-zero, now if we find a case
+	 where it is NOT true, then we set the result to false. Otherwise we
+	 just keep the previous value.  */
+      new_yes_expr = build_x_modify_expr
+	(location, *new_var, NOP_EXPR, 
+	 build_zero_cst (TREE_TYPE (*new_var)), 1);
+      new_no_expr = build_x_modify_expr (location, *new_var, NOP_EXPR, 
+					 *new_var, 1);
+      if (ARITHMETIC_TYPE_P (TREE_TYPE (func_parm)))
+	comp_node = build_zero_cst (TREE_TYPE (func_parm));
+      else
+	comp_node = integer_zero_node;
+      new_cond_expr = build_x_binary_op
+	(location, EQ_EXPR, 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);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO)
+    {
+      new_var_init = build_x_modify_expr
+	(location, *new_var, NOP_EXPR, 
+	 build_zero_cst (new_var_type), 1);
+      /* Initially we assume there are NO zeros in the list. When we find a
+	 non-zero, we keep the previous value. If we find a zero, we set the
+	 value to true.  */
+      new_no_expr = build_x_modify_expr
+	(location, *new_var, NOP_EXPR, 
+	 build_one_cst (TREE_TYPE (*new_var)), 1);
+      new_yes_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  *new_var, 1);
+      if (ARITHMETIC_TYPE_P (TREE_TYPE (func_parm)))
+	comp_node = build_zero_cst (TREE_TYPE (func_parm));
+      else
+	comp_node = integer_zero_node;
+      new_cond_expr = build_x_binary_op
+	(location, EQ_EXPR, 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);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO)
+    {
+      new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR, 
+					  build_zero_cst (new_var_type), 1);
+      /* Initially we assume there are NO non-zeros in the list. When we find a
+	 zero, we keep the previous value. If we find a zero, we set the value
+	 to true.  */
+      new_no_expr = build_x_modify_expr
+	(location, *new_var, NOP_EXPR, 
+	 build_one_cst (TREE_TYPE (*new_var)), 1);
+      new_yes_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  *new_var, 1);
+      if (ARITHMETIC_TYPE_P (TREE_TYPE (func_parm)))
+	comp_node = build_zero_cst (TREE_TYPE (func_parm));
+      else
+	comp_node = integer_zero_node;
+      new_cond_expr = build_x_binary_op
+	(location, NE_EXPR, 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);      
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX)
+    {
+      /* If the TYPE_MIN_VALUE is available for the new_var_type, then
+	 set that as the initial value.  */
+      if (TYPE_MIN_VALUE (new_var_type))
+	new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					    TYPE_MIN_VALUE (new_var_type), 1);
+      else
+	/* ... otherwise set initial value as the first element of array.  */
+	new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					    func_parm, 1);
+      new_no_expr  = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  *new_var, 1);
+      new_yes_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  func_parm, 1);
+      new_cond_expr = build_x_binary_op (location, LT_EXPR, *new_var,
+					 TREE_CODE (*new_var), func_parm,
+					 TREE_CODE (func_parm), 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);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN)
+    {
+      /* If the TYPE_MAX_VALUE is available for the new_var_type, then
+	 set that as the initial value.  */
+      if (TYPE_MAX_VALUE (new_var_type))
+	new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					    TYPE_MAX_VALUE (new_var_type), 1);
+      else
+	/* ... otherwise set initial value as the first element of array.  */
+	new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					    func_parm, 1);
+      new_no_expr  = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  *new_var, 1);
+      new_yes_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  func_parm, 1);
+      new_cond_expr = build_x_binary_op (location, GT_EXPR, *new_var,
+					 TREE_CODE (*new_var), func_parm,
+					 TREE_CODE (func_parm), 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);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND)
+    {
+      new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  array_var[0], tf_warning_or_error);
+      new_exp_init = build_x_modify_expr (location, array_ind_value, 
+					  NOP_EXPR, func_parm, 
+					  tf_warning_or_error);
+      new_no_ind   = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  *new_var, 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, array_var[0],
+					    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_yes_expr = build_x_modify_expr (location, array_ind_value, 
+					  NOP_EXPR, func_parm,
+					  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, LT_EXPR, 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);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND)
+    {
+      new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  array_var[0], 1);
+      new_exp_init = build_x_modify_expr (location, array_ind_value, 
+					  NOP_EXPR, func_parm, 1);
+      new_no_ind   = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  *new_var, 1);
+      new_no_expr  = build_x_modify_expr (location, array_ind_value, 
+					  NOP_EXPR, array_ind_value, 1);
+      if (list_size > 1)
+	new_yes_ind  = build_x_modify_expr (location, *new_var, 
+					    NOP_EXPR, array_var[0], 1);
+      else
+	new_yes_ind  = build_x_modify_expr
+	  (location, *new_var, NOP_EXPR, TREE_OPERAND (array_op0, 1), 1);
+      new_yes_expr = build_x_modify_expr (location, array_ind_value, 
+					  NOP_EXPR, func_parm, 1);
+      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, GT_EXPR, 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);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE)
+    {
+      vec<tree, va_gc> *func_args;
+      func_args = make_tree_vector ();
+      vec_safe_push (func_args, *new_var);
+      vec_safe_push (func_args, func_parm);
+
+      new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  identity_value, tf_warning_or_error);
+      new_call_expr = finish_call_expr (call_fn, &func_args, false, true,
+					tf_warning_or_error);
+      new_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
+				      new_call_expr, tf_warning_or_error);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
+    {
+      vec<tree, va_gc> *func_args;
+
+      func_args = make_tree_vector (); 
+      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);
+    }
+  else
+    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 (ind_init[ii]);
+  
+  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 (ind_init[ii], compare_expr[ii], expr_incr[ii], body);
+      body = pop_stmt_list (new_loop);
+    }
+  append_to_statement_list_force (body, &loop_with_init);
+  
+  XDELETEVEC (compare_expr);
+  XDELETEVEC (expr_incr);
+  XDELETEVEC (ind_init);
+  XDELETEVEC (array_var);
+  
+  for (ii = 0; ii < list_size; ii++)
+    {
+      XDELETEVEC (count_down[ii]);
+      XDELETEVEC (array_value[ii]);
+      XDELETEVEC (array_stride[ii]);
+      XDELETEVEC (array_length[ii]);
+      XDELETEVEC (array_start[ii]);
+      XDELETEVEC (array_ops[ii]);
+      XDELETEVEC (array_vector[ii]);
+    }
+  XDELETEVEC (count_down);
+  XDELETEVEC (array_value);
+  XDELETEVEC (array_stride);
+  XDELETEVEC (array_length);
+  XDELETEVEC (array_start);
+  XDELETEVEC (array_ops);
+  XDELETEVEC (array_vector);
+  
+  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)
+{
+  bool **lhs_vector = NULL, **rhs_vector = NULL;
+  tree **lhs_array = NULL, **rhs_array = NULL;
+  tree array_expr_lhs = NULL_TREE, array_expr_rhs = NULL_TREE;
+  tree array_expr = NULL_TREE;
+  tree **lhs_value = NULL, **rhs_value = NULL;
+  tree **lhs_stride = NULL, **lhs_length = NULL, **lhs_start = NULL;
+  tree **rhs_stride = NULL, **rhs_length = NULL, **rhs_start = NULL;
+  tree body = NULL_TREE, *lhs_var = NULL, *rhs_var = NULL;
+  tree  *cond_expr = NULL;
+  tree *lhs_expr_incr = NULL, *rhs_expr_incr = NULL;
+  tree *lhs_ind_init = NULL, *rhs_ind_init = NULL;
+  bool **lhs_count_down = NULL, **rhs_count_down = NULL;
+  tree *lhs_compare = NULL, *rhs_compare = NULL;
+  vec<tree, va_gc> *lhs_array_operand = NULL, *rhs_array_operand = NULL;
+  size_t lhs_rank = 0, rhs_rank = 0, ii = 0, jj = 0;
+  tree ii_tree = NULL_TREE;
+  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;
+  int s_jj = 0;
+  tree lhs_begin_var, lhs_lngth_var, lhs_strde_var, rhs_begin_var;
+  tree rhs_lngth_var, rhs_strde_var;
+  tree an_init, loop_with_init = alloc_stmt_list ();
+  
+  /* 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, 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)
+    {
+      tree rhs_base = rhs;
+      if (TREE_CODE (rhs_base) == COMPOUND_EXPR)
+	rhs_base = TREE_OPERAND (rhs_base, 0);
+      if (TREE_CODE (rhs_base) == TARGET_EXPR)
+	rhs_base = TARGET_EXPR_INITIAL (rhs_base);
+      
+      if (TREE_CODE (rhs) != CALL_EXPR
+	  && !has_call_expr_with_array_notation (rhs))
+	{
+	  for (ii = 0; ii < rhs_rank; ii++)
+	    rhs_base = ARRAY_NOTATION_ARRAY (rhs);
+      	  
+	  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_base);
+	  return error_mark_node;
+	}
+    }
+  if (lhs_rank != 0 && rhs_rank != 0 && lhs_rank != rhs_rank)
+    {
+      tree lhs_base = lhs;
+      tree rhs_base = rhs;
+      
+      for (ii = 0; ii < lhs_rank; ii++)
+	lhs_base = ARRAY_NOTATION_ARRAY (lhs_base);
+
+      while (rhs_base && TREE_CODE (rhs_base) != ARRAY_NOTATION_REF)
+	rhs_base = TREE_OPERAND (rhs_base, 0);
+      for (ii = 0; ii < rhs_rank; ii++)
+	rhs_base = ARRAY_NOTATION_ARRAY (rhs_base);
+
+      if (location == UNKNOWN_LOCATION && EXPR_HAS_LOCATION (lhs))
+	location = EXPR_LOCATION (lhs);
+      error_at (location, "rank mismatch between %qD and %qD", lhs_base,
+		rhs_base);
+      return error_mark_node;
+    }
+
+  /* Assign the array notation components to variable so that they can satisfy
+     the exec-once rule.  */
+  for (ii = 0; ii < lhs_list_size; ii++)
+    {
+      tree array_node = (*lhs_list)[ii];
+      tree array_begin = ARRAY_NOTATION_START (array_node);
+      tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
+      tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
+
+      if (TREE_CODE (array_begin) != INTEGER_CST)
+	{
+	  lhs_begin_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	  finish_expr_stmt (build_x_modify_expr (location, lhs_begin_var,
+						 NOP_EXPR, array_begin,
+						 complain));
+	  ARRAY_NOTATION_START (array_node) = lhs_begin_var;
+	}
+      if (TREE_CODE (array_lngth) != INTEGER_CST)
+	{
+	  lhs_lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	  finish_expr_stmt (build_x_modify_expr (location, lhs_lngth_var,
+						 NOP_EXPR, array_lngth,
+						 complain));
+	  ARRAY_NOTATION_LENGTH (array_node) = lhs_lngth_var;
+	}
+      if (TREE_CODE (array_strde) != INTEGER_CST)
+	{
+	  lhs_strde_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	  finish_expr_stmt (build_x_modify_expr (location, lhs_strde_var,
+						 NOP_EXPR, array_strde,
+						 complain));
+	  ARRAY_NOTATION_STRIDE (array_node) = lhs_strde_var;
+	}
+    }
+  for (ii = 0; ii < rhs_list_size; ii++)
+    {
+      tree array_node = (*rhs_list)[ii];
+      if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF)
+	{
+	  tree array_begin = ARRAY_NOTATION_START (array_node);
+	  tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
+	  tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
+
+	  if (TREE_CODE (array_begin) != INTEGER_CST)
+	    {
+	      rhs_begin_var = build_decl (location, VAR_DECL, NULL_TREE,
+					  integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, rhs_begin_var,
+						     NOP_EXPR, array_begin,
+						     complain));
+	      ARRAY_NOTATION_START (array_node) = rhs_begin_var;
+	    }
+	  if (TREE_CODE (array_lngth) != INTEGER_CST)
+	    {
+	      rhs_lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
+					  integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, rhs_lngth_var,
+						     NOP_EXPR, array_lngth,
+						     complain));
+	      ARRAY_NOTATION_LENGTH (array_node) = rhs_lngth_var;
+	    }
+	  if (TREE_CODE (array_strde) != INTEGER_CST)
+	    {
+	      rhs_strde_var = build_decl (location, VAR_DECL, NULL_TREE,
+					  integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, rhs_strde_var,
+						     NOP_EXPR, array_strde,
+						     complain));
+	      ARRAY_NOTATION_STRIDE (array_node) = rhs_strde_var;
+	    }
+	}
+    }  
+  lhs_vector = XNEWVEC (bool *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_vector[ii] = XNEWVEC (bool, lhs_rank);
+  
+  rhs_vector = XNEWVEC (bool *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_vector[ii] = XNEWVEC (bool, rhs_rank);
+
+  lhs_array = XNEWVEC (tree *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_array[ii] = XNEWVEC (tree, lhs_rank);
+  
+  rhs_array = XNEWVEC (tree *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_array[ii] = XNEWVEC (tree, rhs_rank);
+
+  lhs_value = XNEWVEC (tree *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_value[ii] = XNEWVEC (tree, lhs_rank);
+  
+  rhs_value = XNEWVEC (tree *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_value[ii] = XNEWVEC (tree, rhs_rank);
+
+  lhs_stride = XNEWVEC (tree *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_stride[ii] = XNEWVEC (tree, lhs_rank);
+
+  rhs_stride = XNEWVEC (tree *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_stride[ii] = XNEWVEC (tree, rhs_rank);
+
+  lhs_length = XNEWVEC (tree *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_length[ii] = XNEWVEC (tree, lhs_rank);
+  
+  rhs_length = XNEWVEC (tree *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_length[ii] = XNEWVEC (tree, rhs_rank);
+
+  lhs_start = XNEWVEC (tree *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_start[ii] = XNEWVEC (tree, lhs_rank);
+  
+  rhs_start = XNEWVEC (tree *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_start[ii] = XNEWVEC (tree, rhs_rank);
+   
+  lhs_var = XNEWVEC (tree, lhs_rank);
+  rhs_var = XNEWVEC (tree, rhs_rank);
+  
+
+  /* The reason why we are just using lhs_rank for this is because we have then
+     following scenarios:
+     1.  LHS_RANK == RHS_RANK
+     2.  LHS_RANK != RHS_RANK && RHS_RANK = 0
+
+     In both the scenarios, just checking the LHS_RANK is OK.  */
+
+  cond_expr = XNEWVEC (tree, MAX (lhs_rank, rhs_rank));
+  lhs_expr_incr = XNEWVEC (tree, lhs_rank);
+  rhs_expr_incr = XNEWVEC (tree, rhs_rank);
+
+  lhs_ind_init = XNEWVEC (tree, lhs_rank);
+  rhs_ind_init = XNEWVEC (tree, rhs_rank);
+
+  lhs_count_down = XNEWVEC (bool *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_count_down[ii] = XNEWVEC (bool, lhs_rank);
+  
+  rhs_count_down = XNEWVEC (bool *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_count_down[ii] = XNEWVEC (bool, rhs_rank);
+
+  lhs_compare = XNEWVEC (tree, lhs_rank);
+  rhs_compare = XNEWVEC (tree, rhs_rank);
+
+  if (lhs_rank)
+    {
+      for (ii = 0; ii < lhs_list_size; ii++)
+	{
+	  jj = 0;
+	  ii_tree = (*lhs_list)[ii];
+	  while (ii_tree)
+	    {
+	      if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
+		{
+		  lhs_array[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) == PARM_DECL)
+		break;
+	    }
+	}
+    }
+  else
+    lhs_array[0][0] = NULL_TREE;
+  
+  if (rhs_rank)
+    {
+      for (ii = 0; ii < rhs_list_size; ii++)
+	{
+	  jj = 0;
+	  ii_tree = (*rhs_list)[ii];
+	  while (ii_tree)
+	    {
+	      if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
+		{
+		  rhs_array[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) == PARM_DECL
+		       || TREE_CODE (ii_tree) == CALL_EXPR)
+		break;
+	    }
+	}
+    }  
+  for (ii = 0; ii < lhs_list_size; ii++)
+    {
+      if (TREE_CODE ((*lhs_list)[ii]) == ARRAY_NOTATION_REF)
+	{
+	  for (jj = 0; jj < lhs_rank; jj++)
+	    {
+	      if (TREE_CODE (lhs_array[ii][jj]) == ARRAY_NOTATION_REF)
+		{
+		  lhs_value[ii][jj] = ARRAY_NOTATION_ARRAY (lhs_array[ii][jj]);
+		  lhs_start[ii][jj] = ARRAY_NOTATION_START (lhs_array[ii][jj]);
+		  lhs_length[ii][jj] =
+		    fold_build1 (CONVERT_EXPR, integer_type_node,
+				 ARRAY_NOTATION_LENGTH (lhs_array[ii][jj]));
+		  lhs_stride[ii][jj] =
+		    fold_build1 (CONVERT_EXPR, integer_type_node,
+				 ARRAY_NOTATION_STRIDE (lhs_array[ii][jj]));
+		  lhs_vector[ii][jj] = true;
+		  
+		  /* If the stride value is variable (i.e. not constant) then
+		     assume that the length is positive.  */
+		  if (!TREE_CONSTANT (lhs_length[ii][jj]))
+		    lhs_count_down[ii][jj] = false;
+		  else if (tree_int_cst_lt
+			   (lhs_length[ii][jj],
+			    build_zero_cst (TREE_TYPE (lhs_length[ii][jj]))))
+		    lhs_count_down[ii][jj] = true;
+		  else
+		    lhs_count_down[ii][jj] = false;
+		}
+	      else
+		lhs_vector[ii][jj] = false;
+	    }
+	}
+    }
+  for (ii = 0; ii < rhs_list_size; ii++)
+    {
+      if (TREE_CODE ((*rhs_list)[ii]) == ARRAY_NOTATION_REF)
+	{
+	  for (jj = 0; jj < rhs_rank; jj++)
+	    {
+	      if (TREE_CODE (rhs_array[ii][jj]) == ARRAY_NOTATION_REF)
+		{
+		  rhs_value[ii][jj]  = ARRAY_NOTATION_ARRAY (rhs_array[ii][jj]);
+		  rhs_start[ii][jj]  = ARRAY_NOTATION_START (rhs_array[ii][jj]);
+		  rhs_length[ii][jj] =
+		    ARRAY_NOTATION_LENGTH (rhs_array[ii][jj]);
+		  rhs_stride[ii][jj] =
+		    ARRAY_NOTATION_STRIDE (rhs_array[ii][jj]);
+		  rhs_vector[ii][jj] = true;
+		  /* If the stride value is variable (i.e. not constant) then
+		     assume that the length is positive.  */
+		  if (!TREE_CONSTANT (rhs_length[ii][jj]))
+		    rhs_count_down[ii][jj] = false;
+		  else if (tree_int_cst_lt
+			   (rhs_length[ii][jj],
+			    build_zero_cst (TREE_TYPE (rhs_length[ii][jj]))))
+		    rhs_count_down[ii][jj] = true;
+		  else
+		    rhs_count_down[ii][jj] = false;	
+		}
+	      else
+		rhs_vector[ii][jj] = false;
+	    }
+	}
+      else
+	for (jj = 0; jj < rhs_rank; jj++)
+	  {
+	    rhs_vector[ii][jj] = false;
+	    rhs_length[ii][jj] = NULL_TREE;
+	  }
+    }
+
+  if (length_mismatch_in_expr_p (EXPR_LOCATION (lhs), lhs_length,
+				 lhs_list_size, lhs_rank)
+      || length_mismatch_in_expr_p (EXPR_LOCATION (rhs), rhs_length,
+				    rhs_list_size, rhs_rank))
+    {
+      pop_stmt_list (an_init);
+      return error_mark_node;
+    }
+
+  if (lhs_list_size > 0 && rhs_list_size > 0 && lhs_rank > 0 && rhs_rank > 0
+      && TREE_CODE (lhs_length[0][0]) == INTEGER_CST
+      && rhs_length[0][0] && TREE_CODE (rhs_length[0][0]) == INTEGER_CST)
+    {
+      HOST_WIDE_INT l_length = int_cst_value (lhs_length[0][0]);
+      HOST_WIDE_INT r_length = int_cst_value (rhs_length[0][0]);
+      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_start[0][ii] && TREE_TYPE (lhs_start[0][ii]))
+	lhs_var[ii] =  build_decl (location, VAR_DECL, NULL_TREE,
+				   TREE_TYPE (lhs_start[0][ii]));
+    else
+      lhs_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
+				integer_type_node);
+
+  for (ii = 0; ii < rhs_list_size; ii++)
+    {
+      if (TREE_CODE ((*rhs_list)[ii]) == CALL_EXPR)
+	{
+	  int idx_value = 0;
+	  tree func_name = CALL_EXPR_FN ((*rhs_list)[ii]);
+	  if (TREE_CODE (func_name) == ADDR_EXPR)
+	    {
+	      if (is_sec_implicit_index_fn (func_name))
+		{
+		  idx_value = 
+		    extract_sec_implicit_index_arg (location, (*rhs_list)[ii]);
+		  if (idx_value < (int) lhs_rank && idx_value >= 0)
+		    vec_safe_push (rhs_array_operand, lhs_var[idx_value]);
+		  else if (idx_value == -1)
+		    return error_mark_node;
+		  else
+		    {
+		      size_t ee = 0;
+		      tree lhs_base = (*lhs_list)[ii];
+		      for (ee = 0; ee < lhs_rank; ee++)
+			if (lhs_base
+			    && TREE_CODE (lhs_base) == ARRAY_NOTATION_REF)
+			  lhs_base = ARRAY_NOTATION_ARRAY (lhs_base);
+
+		      if (location == UNKNOWN_LOCATION
+			  && EXPR_HAS_LOCATION (lhs))
+			location = EXPR_LOCATION (lhs);
+		      error_at (location, "__sec_implicit_index argument %d "
+				"must be less than the rank of %qD", idx_value,
+				lhs_base);
+		      return error_mark_node;
+		    }
+		}
+	      else
+		vec_safe_push (rhs_array_operand, (*rhs_list)[ii]);
+	    }
+	  else
+	    vec_safe_push (rhs_array_operand, (*rhs_list)[ii]);
+	}
+      else
+	vec_safe_push (rhs_array_operand, (*rhs_list)[ii]);
+    }
+
+  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_vector[0][ii])
+      {
+	lhs_ind_init[ii] = build_x_modify_expr
+	  (location, lhs_var[ii], NOP_EXPR,
+	   build_zero_cst (TREE_TYPE (lhs_var[ii])), complain);
+      }
+    
+
+  for (ii = 0; ii < rhs_rank; ii++)
+    {
+      /* When we have a polynomial, we assume that the indices are of type
+	 integer.  */
+      rhs_var[ii] =  build_decl (location, VAR_DECL, NULL_TREE,
+				 TREE_TYPE (rhs_start[0][ii]));
+      rhs_ind_init[ii] = build_x_modify_expr
+	(location, rhs_var[ii], NOP_EXPR, 
+	 build_zero_cst (TREE_TYPE (rhs_var[ii])), complain);
+    }
+
+  if (lhs_rank)
+    {
+      for (ii = 0; ii < lhs_list_size; ii++)
+	{
+	  if (lhs_vector[ii][0])
+	    {
+	      /* The last ARRAY_NOTATION element's ARRAY component should be
+		 the array's base value.  */
+	      tree lhs_array_opr = lhs_value[ii][lhs_rank - 1];
+	      for (s_jj = lhs_rank - 1; s_jj >= 0; s_jj--)
+		{
+		  tree stride = NULL_TREE, var = NULL_TREE, start = NULL_TREE;
+		  if ((TREE_TYPE (lhs_start[ii][s_jj]) ==
+		       TREE_TYPE (lhs_stride[ii][s_jj]))
+		      && (TREE_TYPE (lhs_stride[ii][s_jj]) !=
+			  TREE_TYPE (lhs_var[s_jj])))
+		    {
+		      /* If stride and start are of same type and the induction
+			 var is not, convert induction variable to stride's
+			 type.  */
+		      start = lhs_start[ii][s_jj];
+		      stride = lhs_stride[ii][s_jj];
+		      var = build_c_cast (location,
+					  TREE_TYPE (lhs_stride[ii][s_jj]),
+					  lhs_var[s_jj]);
+		    }
+		  else if (TREE_TYPE (lhs_start[ii][s_jj]) !=
+			   TREE_TYPE (lhs_stride[ii][s_jj]))
+		    {
+		      /* 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 -.  */
+		      start = build_c_cast (location, integer_type_node,
+					    lhs_start[ii][s_jj]);
+		      stride = build_c_cast (location, integer_type_node,
+					     lhs_stride[ii][s_jj]);
+		      var = build_c_cast (location, integer_type_node,
+					  lhs_var[s_jj]);
+		    }
+		  else
+		    {
+		      start = lhs_start[ii][s_jj];
+		      stride = lhs_stride[ii][s_jj];
+		      var = lhs_var[s_jj];
+		    }
+		  if (lhs_count_down[ii][s_jj])
+		    /* Array[start_index - (induction_var * stride)].  */
+		    lhs_array_opr = grok_array_decl
+		      (location, lhs_array_opr,
+		       build2 (MINUS_EXPR, TREE_TYPE (var), start,
+			       build2 (MULT_EXPR, TREE_TYPE (var), var,
+				       stride)), false);	
+		  else
+		    /* Array[start_index + (induction_var * stride)].  */
+		    lhs_array_opr = grok_array_decl
+		      (location, lhs_array_opr,
+		       build2 (PLUS_EXPR, TREE_TYPE (var), start,
+			       build2 (MULT_EXPR, TREE_TYPE (var), var,
+				       stride)), false);
+		}
+	      vec_safe_push (lhs_array_operand, lhs_array_opr);
+	    }
+	  else
+	    vec_safe_push (lhs_array_operand, integer_one_node);
+	}
+      replace_array_notations (&lhs, true, lhs_list, lhs_array_operand);
+      array_expr_lhs = lhs;
+    }
+
+  if (rhs_array_operand)
+    vec_safe_truncate (rhs_array_operand, 0);
+
+  if (rhs_rank)
+    {
+      for (ii = 0; ii < rhs_list_size; ii++)
+	{
+	  if (rhs_vector[ii][0])
+	    {
+	      tree rhs_array_opr = rhs_value[ii][rhs_rank - 1];
+	      for (s_jj = rhs_rank - 1; s_jj >= 0; s_jj--)
+		{
+		  tree stride = NULL_TREE, var = NULL_TREE, start = NULL_TREE;
+		  if ((TREE_TYPE (rhs_start[ii][s_jj]) ==
+		       TREE_TYPE (rhs_stride[ii][s_jj]))
+		      && (TREE_TYPE (rhs_stride[ii][s_jj]) !=
+			  TREE_TYPE (rhs_var[s_jj])))
+		    {
+		      /* If stride and start are of same type and the induction
+			 var is not, convert induction variable to stride's
+			 type.  */
+		      start = rhs_start[ii][s_jj];
+		      stride = rhs_stride[ii][s_jj];
+		      var = build_c_cast (location,
+					  TREE_TYPE (rhs_stride[ii][s_jj]),
+					  rhs_var[s_jj]);
+		    }
+		  else if (TREE_TYPE (rhs_start[ii][s_jj]) !=
+			   TREE_TYPE (rhs_stride[ii][s_jj]))
+		    {
+		      /* 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 -.  */
+		      start = build_c_cast (location, integer_type_node,
+					    rhs_start[ii][s_jj]);
+		      stride = build_c_cast (location, integer_type_node,
+					     rhs_stride[ii][s_jj]);
+		      var = build_c_cast (location, integer_type_node,
+					  rhs_var[s_jj]);
+		    }
+		  else
+		    {
+		      start = rhs_start[ii][s_jj];
+		      stride = rhs_stride[ii][s_jj];
+		      var = rhs_var[s_jj];
+		    }
+		  if (rhs_count_down[ii][s_jj])
+		    /* Array[start_index - (induction_var * stride)].  */
+		    rhs_array_opr = grok_array_decl
+		      (location, rhs_array_opr,
+		       build2 (MINUS_EXPR, TREE_TYPE (var), start,
+			       build2 (MULT_EXPR, TREE_TYPE (var), var,
+				       stride)), false);	
+		  else
+		    /* Array[start_index + (induction_var * stride)].  */
+		    rhs_array_opr = grok_array_decl
+		      (location, rhs_array_opr,
+		       build2 (PLUS_EXPR, TREE_TYPE (var), start,
+			       build2 (MULT_EXPR, TREE_TYPE (var), var,
+				       stride)), false);
+		}
+	      vec_safe_push (rhs_array_operand, rhs_array_opr);
+	    }
+	  else
+	    /* This is just a dummy node to make sure the list sizes for both
+	       array list and array operand list are the same.  */
+	    vec_safe_push (rhs_array_operand, integer_one_node);
+	}
+      for (ii = 0; ii < rhs_list_size; ii++)
+	{
+	  tree rhs_node = (*rhs_list)[ii];
+	  if (TREE_CODE (rhs_node) == CALL_EXPR)
+	    {
+	      int idx_value = 0;
+	      tree func_name = CALL_EXPR_FN (rhs_node);
+	      if (TREE_CODE (func_name) == ADDR_EXPR)
+		if (is_sec_implicit_index_fn (func_name))
+		  {
+		    idx_value = 
+		      extract_sec_implicit_index_arg (location, rhs_node);
+		    if (idx_value < (int) lhs_rank && idx_value >= 0)
+		      vec_safe_push (rhs_array_operand, rhs_var[idx_value]);
+		    else
+		      {
+			size_t ee = 0;
+			tree rhs_base = (*lhs_list)[ii];
+			for (ee = 0; ee < rhs_rank; ee++)
+			  if (rhs_base
+			      && TREE_CODE (rhs_base) == ARRAY_NOTATION_REF)
+			    rhs_base = ARRAY_NOTATION_ARRAY (rhs_base);
+
+			error_at (location, "__sec_implicit_index argument %d "
+				  "must be less than rank of %qD", idx_value,
+				  rhs_base);
+			return error_mark_node;
+		      }
+		  }
+	    }
+	}	
+      replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
+      array_expr_rhs = rhs;
+    }
+  else
+    {
+      for (ii = 0; ii < rhs_list_size; ii++)
+	{
+	  tree rhs_node = (*rhs_list)[ii];
+	  if (TREE_CODE (rhs_node) == CALL_EXPR)
+	    {
+	      int idx_value = 0;
+	      tree func_name = CALL_EXPR_FN (rhs_node);
+	      if (is_sec_implicit_index_fn (func_name))
+		{
+		  idx_value =  extract_sec_implicit_index_arg (location,
+							       rhs_node);
+		  if (idx_value < (int) lhs_rank && idx_value >= 0)
+		    vec_safe_push (rhs_array_operand, lhs_var[idx_value]);
+		  else
+		    {
+		      size_t ee = 0;
+		      tree lhs_base = (*lhs_list)[ii];
+		      for (ee = 0; ee < lhs_rank; ee++)
+			if (lhs_base
+			    && TREE_CODE (lhs_base) == ARRAY_NOTATION_REF)
+			  lhs_base = ARRAY_NOTATION_ARRAY (lhs_base);
+		      error_at (location, "__sec_implicit_index argument %d "
+				"must be less than the rank of %qD", idx_value,
+				lhs_base);
+		      return error_mark_node;
+		    }
+		}
+	    }
+	}
+      replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
+      array_expr_rhs = rhs;
+      rhs_expr_incr[0] = NULL_TREE;
+    }
+  
+  for (ii = 0; ii < rhs_rank; ii++)
+    if (rhs_count_down[0][ii])
+      rhs_expr_incr[ii] = build_x_unary_op (location, POSTDECREMENT_EXPR,
+					    rhs_var[ii], complain);
+    else
+      rhs_expr_incr[ii] = build_x_unary_op (location, POSTINCREMENT_EXPR,
+					    rhs_var[ii], complain);
+  
+  for (ii = 0; ii < lhs_rank; ii++)
+    if (lhs_count_down[0][ii])
+      lhs_expr_incr[ii] = build_x_unary_op (location, POSTDECREMENT_EXPR,
+					    lhs_var[ii], complain);
+    else
+      lhs_expr_incr[ii] = build_x_unary_op (location, POSTINCREMENT_EXPR,
+					    lhs_var[ii], complain);
+  if (!array_expr_lhs)
+    array_expr_lhs = lhs;
+  
+  array_expr = build_x_modify_expr (location, array_expr_lhs, modifycode,
+				    array_expr_rhs, complain);
+
+  for (jj = 0; jj < MAX (lhs_rank, rhs_rank); jj++)
+    {
+      if (rhs_rank && rhs_expr_incr[jj])
+	{
+	  size_t iii = 0;
+	  if (lhs_rank)
+	    {
+	      if (lhs_count_down[0][jj])
+		lhs_compare[jj] = build_x_binary_op
+		  (location, GT_EXPR, lhs_var[jj], TREE_CODE (lhs_var[jj]),
+		   lhs_length[0][jj], TREE_CODE (lhs_length[0][jj]), NULL,
+		   complain);
+	      else
+		lhs_compare[jj] = build_x_binary_op
+		  (location, LT_EXPR, lhs_var[jj], TREE_CODE (lhs_var[jj]),
+		   lhs_length[0][jj], TREE_CODE (lhs_length[0][jj]), NULL,
+		   complain);
+	    }
+	  else
+	    lhs_compare[jj] = NULL_TREE;
+
+	  for (iii = 0; iii < rhs_list_size; iii++)
+	    if (rhs_vector[iii][jj])
+	      break;
+	  
+	  /* What we are doing here is this:
+	     We always count up, so:
+	       if (length is negative ==> which means we count down)
+	          we multiply length by -1 and count up => ii < -LENGTH
+	       else
+	          we just count up, so we compare for  ii < LENGTH
+	   */
+	  if (rhs_count_down[iii][jj])
+	    {
+	      tree new_rhs = build_x_modify_expr
+		(location, rhs_length[iii][jj], MULT_EXPR,
+		 build_int_cst (TREE_TYPE (rhs_length[iii][jj]), -1), complain);
+	      rhs_compare[jj] = build_x_binary_op
+		(location, GT_EXPR, rhs_var[jj], TREE_CODE (rhs_var[jj]),
+		 new_rhs, TREE_CODE (new_rhs), NULL, complain);
+	    }
+	  else
+	    rhs_compare[jj] = build_x_binary_op
+	      (location, LT_EXPR, rhs_var[jj], TREE_CODE (rhs_var[jj]),
+	       rhs_length[iii][jj], TREE_CODE (rhs_length[0][jj]), NULL,
+	       complain);
+	   
+	  if (lhs_rank)
+	    cond_expr[jj] = build_x_binary_op
+	      (location, TRUTH_ANDIF_EXPR, lhs_compare[jj],
+	       TREE_CODE (lhs_compare[jj]), rhs_compare[jj],
+	       TREE_CODE (rhs_compare[jj]), NULL, complain);
+	  else
+	    cond_expr[jj] = rhs_compare[jj];
+	}
+      else
+	{
+	  if (lhs_count_down[0][jj])
+	    cond_expr[jj] = build_x_binary_op
+	      (location, GT_EXPR, lhs_var[jj], TREE_CODE (lhs_var[jj]),
+	       lhs_length[0][jj], TREE_CODE (lhs_length[0][jj]), NULL,
+	       complain);
+	    else
+	      cond_expr[jj] = build_x_binary_op
+		(location, LT_EXPR, lhs_var[jj], TREE_CODE (lhs_var[jj]),
+		 lhs_length[0][jj], TREE_CODE (lhs_length[0][jj]), NULL,
+		 complain);
+	}
+    }
+  
+  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_ind_init[ii], &init_list);
+	  append_to_statement_list_force (lhs_expr_incr[ii], &incr_list);
+	}
+      if (rhs_rank)
+	{
+	  append_to_statement_list_force (rhs_ind_init[ii], &init_list);
+	  append_to_statement_list_force (rhs_expr_incr[ii], &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);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    {
+      XDELETEVEC (rhs_vector[ii]);
+      XDELETEVEC (rhs_array[ii]);
+      XDELETEVEC (rhs_value[ii]);
+      XDELETEVEC (rhs_length[ii]);
+      XDELETEVEC (rhs_stride[ii]);
+      XDELETEVEC (rhs_start[ii]);
+    }
+    for (ii = 0; ii < lhs_list_size; ii++)
+    {
+      XDELETEVEC (lhs_vector[ii]);
+      XDELETEVEC (lhs_array[ii]);
+      XDELETEVEC (lhs_value[ii]);
+      XDELETEVEC (lhs_length[ii]);
+      XDELETEVEC (lhs_stride[ii]);
+      XDELETEVEC (lhs_start[ii]);
+    }
+  if (rhs_vector)
+    XDELETEVEC (rhs_vector);
+
+  if (rhs_array)
+    XDELETEVEC (rhs_array);
+  if (rhs_value)
+    XDELETEVEC (rhs_value);
+  if (rhs_length)
+    XDELETEVEC (rhs_length);
+  if (rhs_stride)
+    XDELETEVEC (rhs_stride);
+  if (rhs_start)
+    XDELETEVEC (rhs_start);
+  if (rhs_expr_incr)    
+    XDELETEVEC (rhs_expr_incr);
+  if (rhs_ind_init)
+    XDELETEVEC (rhs_ind_init);
+  if (rhs_compare)
+    XDELETEVEC (rhs_compare);
+  if (lhs_compare)
+    XDELETEVEC (lhs_compare);
+  
+  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, jj = 0;
+  tree **array_ops, *array_var, jj_tree, body, stmt = NULL_TREE;
+  tree **array_value, **array_stride, **array_length, **array_start;
+  tree *compare_expr, an_init, *expr_incr, *ind_init;
+  tree builtin_loop, new_var = NULL_TREE;
+  bool **count_down, **array_vector;
+  tree loop_with_init = alloc_stmt_list ();
+  int s_jj = 0;
+  tree begin_var, lngth_var, strde_var;
+  tsubst_flags_t complain = tf_warning_or_error;
+  location_t location = UNKNOWN_LOCATION;
+
+  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);
+  array_ops = XNEWVEC (tree *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_ops[ii] = XNEWVEC (tree, rank);
+  
+  array_vector = XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_vector[ii] = XNEWVEC (bool, rank);
+
+  array_value  = XNEWVEC (tree *, list_size);
+  array_stride = XNEWVEC (tree *, list_size);
+  array_length = XNEWVEC (tree *, list_size);
+  array_start  = XNEWVEC (tree *, list_size);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      array_value[ii]  = XNEWVEC (tree, rank);
+      array_stride[ii] = XNEWVEC (tree, rank);
+      array_length[ii] = XNEWVEC (tree, rank);
+      array_start[ii]  = XNEWVEC (tree, rank);
+    }
+
+  compare_expr = XNEWVEC (tree, rank);
+  expr_incr = XNEWVEC (tree, rank);
+  ind_init = XNEWVEC (tree, rank);
+
+  list_size = vec_safe_length (array_list);
+  count_down = XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    count_down[ii] = XNEWVEC (bool, rank);
+  
+  array_var = XNEWVEC (tree, 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];
+      if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF)
+	{
+	  tree array_begin = ARRAY_NOTATION_START (array_node);
+	  tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
+	  tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
+
+	  if (TREE_CODE (array_begin) != INTEGER_CST)
+	    {
+	      begin_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, begin_var,
+						     NOP_EXPR, array_begin,
+						     complain));
+	      ARRAY_NOTATION_START (array_node) = begin_var;
+	    }
+	  if (TREE_CODE (array_lngth) != INTEGER_CST)
+	    {
+	      lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, lngth_var,
+						     NOP_EXPR, array_lngth,
+						     complain));
+	      ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
+	    }
+	  if (TREE_CODE (array_strde) != INTEGER_CST)
+	    {
+	      strde_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, strde_var,
+						     NOP_EXPR, array_strde,
+						     complain));
+	      ARRAY_NOTATION_STRIDE (array_node) = strde_var;
+	    }
+	}
+    }
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      jj = 0;
+      jj_tree = (*array_list)[ii];
+      while (jj_tree)
+	{
+	  if (TREE_CODE (jj_tree) == ARRAY_NOTATION_REF)
+	    {
+	      array_ops[ii][jj] = jj_tree;
+	      jj++;
+	      jj_tree = ARRAY_NOTATION_ARRAY (jj_tree);
+	    }
+	  else if (TREE_CODE (jj_tree) == ARRAY_REF)
+	    jj_tree = TREE_OPERAND (jj_tree, 0);
+	  else if (TREE_CODE (jj_tree) == VAR_DECL
+		   || TREE_CODE (jj_tree) == PARM_DECL)
+	    break;
+	}
+    }
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      if (TREE_CODE ((*array_list)[ii]) == ARRAY_NOTATION_REF)
+	{
+	  for (jj = 0; jj < rank; jj++)
+	    {
+	      if (TREE_CODE (array_ops[ii][jj]) == ARRAY_NOTATION_REF)
+		{
+		  array_value[ii][jj] =
+		    ARRAY_NOTATION_ARRAY (array_ops[ii][jj]);
+		  array_start[ii][jj] =
+		    ARRAY_NOTATION_START (array_ops[ii][jj]);
+		  array_length[ii][jj] =
+		    ARRAY_NOTATION_LENGTH (array_ops[ii][jj]);
+		  array_stride[ii][jj] =
+		    ARRAY_NOTATION_STRIDE (array_ops[ii][jj]);
+		  array_vector[ii][jj] = true;
+
+		  if (!integer_zerop (array_length[ii][jj])
+		      && !integer_nonzerop (array_length[ii][jj]))
+		    count_down[ii][jj] = false;
+		  else if (tree_int_cst_lt
+			   (array_length[ii][jj],
+			    build_zero_cst (TREE_TYPE (array_length[ii][jj]))))
+		    count_down[ii][jj] = true;
+		  else
+		    count_down[ii][jj] = false;
+		}
+	      else
+		array_vector[ii][jj] = false;
+	    }
+	}
+    }
+  for (ii = 0; ii < rank; ii++)
+    {
+      if (TREE_TYPE (array_start[0][ii])
+	  && TREE_CODE (TREE_TYPE (array_start[0][ii])) != TEMPLATE_TYPE_PARM)
+	{
+	  array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
+				      TREE_TYPE (array_start[0][ii]));
+	  ind_init[ii] = build_x_modify_expr
+	    (location, array_var[ii], NOP_EXPR, 
+	     build_zero_cst (TREE_TYPE (array_var[ii])), tf_warning_or_error);
+	}
+      else
+	{
+	  array_var[ii] = build_min_nt_loc (location, VAR_DECL,
+					    NULL_TREE, NULL_TREE);
+	  ind_init[ii] = build_x_modify_expr (location, array_var[ii], 
+					      NOP_EXPR,
+					      integer_zero_node, 1);
+	}
+    }
+  for (ii = 0; ii < list_size; ii++)
+    {
+      if (array_vector[ii][0])
+	{
+	  tree array_opr = array_value[ii][rank - 1];
+	  for (s_jj = rank - 1; s_jj >= 0; s_jj--)
+	    {
+	      tree stride = NULL_TREE, var = NULL_TREE, start = NULL_TREE;
+
+	      /* If stride and start are of same type and the induction var
+		 is not, convert induction variable to stride's type.  */
+	      if ((TREE_TYPE (array_start[ii][s_jj]) ==
+		   TREE_TYPE (array_stride[ii][s_jj]))
+		  && (TREE_TYPE (array_stride[ii][s_jj]) !=
+		      TREE_TYPE (array_var[s_jj])))
+		{
+		  start = array_start[ii][s_jj];
+		  stride = array_stride[ii][s_jj];
+		  var =
+		    build_c_cast (location, TREE_TYPE (array_stride[ii][s_jj]),
+				  array_var[s_jj]);
+		}
+	      else if (TREE_TYPE (array_start[ii][s_jj]) !=
+			TREE_TYPE (array_stride[ii][s_jj]))
+		{
+		  /* 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, we stay safe and 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 -.  */
+		  start = build_c_cast (location, integer_type_node,
+					array_start[ii][s_jj]);
+		  stride = build_c_cast (location, integer_type_node,
+					 array_stride[ii][s_jj]);
+		  var = build_c_cast (location, integer_type_node,
+				      array_var[s_jj]);
+		}
+	      else
+		{
+		  start = array_start[ii][s_jj];
+		  stride = array_stride[ii][s_jj];
+		  var = array_var[s_jj];
+		}
+	      if (count_down[ii][s_jj])
+		/* Array[start_index - (induction_var * stride)].  */
+		array_opr = grok_array_decl
+		  (location, array_opr,
+		   build2 (MINUS_EXPR, TREE_TYPE (var), start,
+			   build2 (MULT_EXPR, TREE_TYPE (var), var, stride)),
+		   false);	
+	      else
+		/* Array[start_index + (induction_var * stride)].  */
+		array_opr = grok_array_decl
+		  (location, array_opr,
+		   build2 (PLUS_EXPR, TREE_TYPE (var), start,
+			   build2 (MULT_EXPR, TREE_TYPE (var), var, stride)),
+		   false);
+		
+	    }
+	  vec_safe_push (array_operand, array_opr);
+	}
+      else
+	vec_safe_push (array_operand, integer_one_node);
+    }
+  replace_array_notations (&stmt, true, array_list, array_operand);
+
+  for (ii = 0; ii < rank; ii++)
+    if (count_down[0][ii])
+      expr_incr[ii] = build_x_unary_op (location, POSTDECREMENT_EXPR,
+					array_var[ii], tf_warning_or_error);
+    else
+      expr_incr[ii] = build_x_unary_op (location, POSTINCREMENT_EXPR,
+					array_var[ii], tf_warning_or_error);
+  
+  for (jj = 0; jj < rank; jj++)
+    {
+      if (rank && expr_incr[jj])
+	{
+	  if (count_down[0][jj])
+	    compare_expr[jj] = build_x_binary_op
+	      (location, GT_EXPR, array_var[jj], TREE_CODE (array_var[jj]),
+	       array_length[0][jj], TREE_CODE (array_length[0][jj]), NULL,
+	       tf_warning_or_error);
+	  else
+	    compare_expr[jj] = build_x_binary_op
+	      (location, LT_EXPR, array_var[jj], TREE_CODE (array_var[jj]),
+	       array_length[0][jj], TREE_CODE (array_length[0][jj]), NULL,
+	       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 (ind_init[ii], compare_expr[ii], expr_incr[ii], body);
+      body = pop_stmt_list (new_loop);
+    }
+  append_to_statement_list_force (body, &loop_with_init);
+  
+  XDELETEVEC (compare_expr);
+  XDELETEVEC (expr_incr);
+  XDELETEVEC (ind_init);
+  XDELETEVEC (array_var);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      XDELETEVEC (count_down[ii]);
+      XDELETEVEC (array_value[ii]);
+      XDELETEVEC (array_stride[ii]);
+      XDELETEVEC (array_length[ii]);
+      XDELETEVEC (array_start[ii]);
+      XDELETEVEC (array_ops[ii]);
+      XDELETEVEC (array_vector[ii]);
+    }
+
+  XDELETEVEC (count_down);
+  XDELETEVEC (array_value);
+  XDELETEVEC (array_stride);
+  XDELETEVEC (array_length);
+  XDELETEVEC (array_start);
+  XDELETEVEC (array_ops);
+  XDELETEVEC (array_vector);
+
+  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;
+  int s_jj = 0;
+  size_t list_size = 0, rank = 0, ii = 0, jj = 0;
+  tree **array_ops, *array_var, jj_tree, body, array_opr;
+  tree **array_value, **array_stride, **array_length, **array_start;
+  tree *compare_expr, *expr_incr, *ind_init;
+  bool **count_down, **array_vector;
+  tree builtin_loop, stmt = NULL_TREE, new_var = NULL_TREE;
+  tree begin_var, lngth_var, strde_var;
+  location_t location = EXPR_LOCATION (orig_stmt);
+  tree an_init, loop_with_init = alloc_stmt_list ();
+  
+  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++)
+    {
+      tree list_node = (*array_list)[ii];
+      if (TREE_CODE (list_node) == CALL_EXPR
+	  || TREE_CODE (list_node) == AGGR_INIT_EXPR)
+	{
+	  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)
+    return stmt;
+  
+  if (list_size == 0)
+    return stmt;
+
+  array_ops = XNEWVEC (tree *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_ops[ii] = XNEWVEC (tree, rank);
+  
+  array_vector = XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_vector[ii] = XNEWVEC (bool, rank);
+
+  array_value = XNEWVEC (tree *, list_size);
+  array_stride = XNEWVEC (tree *, list_size);
+  array_length = XNEWVEC (tree *, list_size);
+  array_start = XNEWVEC (tree *, list_size);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      array_value[ii]  = XNEWVEC (tree, rank);
+      array_stride[ii] = XNEWVEC (tree, rank);
+      array_length[ii] = XNEWVEC (tree, rank);
+      array_start[ii]  = XNEWVEC (tree, rank);
+    }
+
+  compare_expr = XNEWVEC (tree, rank);
+  expr_incr = XNEWVEC (tree, rank);
+  ind_init = XNEWVEC (tree, rank);
+  array_var = XNEWVEC (tree, rank);
+  
+  count_down = XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++) 
+    count_down[ii] = XNEWVEC (bool,  rank);
+
+    /* 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];
+      tree array_begin = ARRAY_NOTATION_START (array_node);
+      tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
+      tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
+      tsubst_flags_t complain = tf_warning_or_error;
+      if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF)
+	{
+	  if (TREE_CODE (array_begin) != INTEGER_CST)
+	    {
+	      begin_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, begin_var,
+						     NOP_EXPR, array_begin,
+						     complain));
+	      ARRAY_NOTATION_START (array_node) = begin_var;
+	    }
+	  if (TREE_CODE (array_lngth) != INTEGER_CST)
+	    {
+	      lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, lngth_var,
+						     NOP_EXPR, array_lngth,
+						     complain));
+	      ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
+	    }
+	  if (TREE_CODE (array_strde) != INTEGER_CST)
+	    {
+	      strde_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, strde_var,
+						     NOP_EXPR, array_strde,
+						     complain));
+	      ARRAY_NOTATION_STRIDE (array_node) = strde_var;
+	    }
+	}
+    }
+  for (ii = 0; ii < list_size; ii++)
+    {
+      jj = 0;
+      jj_tree = (*array_list)[ii];
+      while (jj_tree)
+	{
+	  if (TREE_CODE (jj_tree) == ARRAY_NOTATION_REF)
+	    {
+	      array_ops[ii][jj] = jj_tree;
+	      jj++;
+	      jj_tree = ARRAY_NOTATION_ARRAY (jj_tree);
+	    }
+	  else if (TREE_CODE (jj_tree) == VAR_DECL
+		   || TREE_CODE (jj_tree) == PARM_DECL)
+	    break;
+	  else
+	    jj_tree = TREE_OPERAND (jj_tree, 0);
+	}
+    }
+  for (ii = 0; ii < list_size; ii++)
+    {
+      if (TREE_CODE ((*array_list)[ii]) == ARRAY_NOTATION_REF)
+	{
+	  for (jj = 0; jj < rank; jj++)
+	    {
+	      if (TREE_CODE (array_ops[ii][jj]) == ARRAY_NOTATION_REF)
+		{
+		  array_value[ii][jj] =
+		    ARRAY_NOTATION_ARRAY (array_ops[ii][jj]);
+		  array_start[ii][jj] =
+		    ARRAY_NOTATION_START (array_ops[ii][jj]);
+		  array_length[ii][jj] =
+		    ARRAY_NOTATION_LENGTH (array_ops[ii][jj]);
+		  array_stride[ii][jj] =
+		    ARRAY_NOTATION_STRIDE (array_ops[ii][jj]);
+		  array_vector[ii][jj] = true;
+
+		  if (!TREE_CONSTANT (array_length[ii][jj])
+		      || TREE_CODE (array_length[ii][jj]) == VAR_DECL)
+		    count_down[ii][jj] = false;
+		  else if (!integer_zerop (array_length[ii][jj])
+		      && !integer_nonzerop (array_length[ii][jj]))
+		      count_down[ii][jj] = false;
+		  else if (tree_int_cst_lt
+			   (array_length[ii][jj],
+			    build_zero_cst (TREE_TYPE (array_length[ii][jj]))))
+		    count_down[ii][jj] = true;
+		  else
+		    count_down[ii][jj] = false;
+		}
+	      else
+		array_vector[ii][jj] = false;
+	    }
+	}
+    }
+
+  an_init = push_stmt_list ();
+  for (ii = 0; ii < rank; ii++)
+    {
+      array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
+				  TREE_TYPE (array_start[0][ii]));
+      ind_init[ii] = build_x_modify_expr
+	(location, array_var[ii], NOP_EXPR, 
+	 build_zero_cst (TREE_TYPE (array_var[ii])), tf_warning_or_error);
+    }
+  for (ii = 0; ii < list_size; ii++)
+    {
+      if (array_vector[ii][0])
+	{
+	  array_opr = array_value[ii][rank - 1];
+	  for (s_jj = rank - 1; s_jj >= 0; s_jj--)
+	    {
+	      tree stride = NULL_TREE, var = NULL_TREE, start = NULL_TREE;
+	      if ((TREE_TYPE (array_start[ii][s_jj]) ==
+		   TREE_TYPE (array_stride[ii][s_jj]))
+		  && (TREE_TYPE (array_stride[ii][s_jj]) !=
+		      TREE_TYPE (array_var[s_jj])))
+		{
+		  /* If stride and start are of same type and the induction var
+		     is not, convert induction variable to stride's type.  */
+		  start = array_start[ii][s_jj];
+		  stride = array_stride[ii][s_jj];
+		  var =
+		    build_c_cast (location, TREE_TYPE (array_stride[ii][s_jj]),
+				  array_var[s_jj]);
+		}
+	      else if (TREE_TYPE (array_start[ii][s_jj]) !=
+			TREE_TYPE (array_stride[ii][s_jj]))
+		{
+		  /* 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 -.  */
+		  start = build_c_cast (location, integer_type_node,
+					array_start[ii][s_jj]);
+		  stride = build_c_cast (location, integer_type_node,
+					 array_stride[ii][s_jj]);
+		  var = build_c_cast (location, integer_type_node,
+				      array_var[s_jj]);
+		}
+	      else
+		{
+		  start = array_start[ii][s_jj];
+		  stride = array_stride[ii][s_jj];
+		  var = array_var[s_jj];
+		}
+	      if (count_down[ii][s_jj])
+		/* Array[start_index - (induction_var * stride)].  */
+		array_opr = grok_array_decl
+		  (location, array_opr,
+		   build2 (MINUS_EXPR, TREE_TYPE (var), start,
+			   build2 (MULT_EXPR, TREE_TYPE (var), var, stride)),
+		   false);	
+	      else
+		/* Array[start_index + (induction_var * stride)].  */
+		array_opr = grok_array_decl
+		  (location, array_opr,
+		   build2 (PLUS_EXPR, TREE_TYPE (var), start,
+			   build2 (MULT_EXPR, TREE_TYPE (var), var, stride)),
+		   false);
+	    }
+	  vec_safe_push (array_operand, array_opr);  
+	}
+      else
+	vec_safe_push (array_operand, integer_one_node);
+    }
+  replace_array_notations (&stmt, true, array_list, array_operand);
+
+  for (ii = 0; ii < rank; ii++)
+    if (count_down[0][ii])
+      expr_incr[ii] = build_x_unary_op (location, POSTDECREMENT_EXPR,
+					array_var[ii], tf_warning_or_error);
+    else
+      expr_incr[ii] = build_x_unary_op (location, POSTINCREMENT_EXPR,
+					array_var[ii], tf_warning_or_error);
+
+  for (jj = 0; jj < rank; jj++)
+    {
+      if (rank && expr_incr[jj])
+	{
+	  if (count_down[0][jj])
+	    compare_expr[jj] = build_x_binary_op
+	      (location, GT_EXPR, array_var[jj], TREE_CODE (array_var[jj]),
+	       array_length[0][jj], TREE_CODE (array_length[0][jj]), NULL,
+	       tf_warning_or_error);
+	  else
+	    compare_expr[jj] = build_x_binary_op
+	      (location, LT_EXPR, array_var[jj], TREE_CODE (array_var[jj]),
+	       array_length[0][jj], TREE_CODE (array_length[0][jj]), NULL,
+	       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 (ind_init[ii], compare_expr[ii], expr_incr[ii], body);
+      body = pop_stmt_list (new_loop);
+    }
+  append_to_statement_list_force (body, &loop_with_init);
+
+  XDELETEVEC (compare_expr);
+  XDELETEVEC (expr_incr);
+  XDELETEVEC (ind_init);
+  XDELETEVEC (array_var);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      XDELETEVEC (count_down[ii]);
+      XDELETEVEC (array_value[ii]);
+      XDELETEVEC (array_stride[ii]);
+      XDELETEVEC (array_length[ii]);
+      XDELETEVEC (array_start[ii]);
+      XDELETEVEC (array_ops[ii]);
+      XDELETEVEC (array_vector[ii]);
+    }
+    
+  XDELETEVEC (count_down);
+  XDELETEVEC (array_value);
+  XDELETEVEC (array_stride);
+  XDELETEVEC (array_length);
+  XDELETEVEC (array_start);
+  XDELETEVEC (array_ops);
+  XDELETEVEC (array_vector);
+
+  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;
+  location_t loc = EXPR_LOCATION (expr);
+
+  if (TREE_CODE (expr) != RETURN_EXPR)
+    return 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;
+  
+  /* Skip empty subtrees.  */
+  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;
+}
diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c
index bccd884..d301db0 100644
--- a/gcc/cp/cp-objcp-common.c
+++ b/gcc/cp/cp-objcp-common.c
@@ -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"
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 9421822..4791a32 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6135,6 +6135,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 */
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
old mode 100644
new mode 100755
index a75fc4e..a8f52cd
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -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;
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
old mode 100644
new mode 100755
index a581e88..523dcf7
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -6060,6 +6060,168 @@ 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.  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 +6243,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;
 }
 
@@ -9342,6 +9541,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;
 }
 
@@ -9534,6 +9735,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;
@@ -10094,6 +10303,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;
 
@@ -10120,6 +10335,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;
 
@@ -10138,8 +10362,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;
 
@@ -16714,30 +16947,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
@@ -18108,6 +18364,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);
 
@@ -22087,6 +22348,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));
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
old mode 100644
new mode 100755
index 3602fcd..0a7d523
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -13740,6 +13740,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));
@@ -15712,6 +15726,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;
@@ -19119,6 +19136,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);
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index b5c3b0a..656962b 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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 notatinos, 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 ())
@@ -8066,6 +8082,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);
@@ -8877,6 +8894,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:
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 8524f6c..dd2fda4 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -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;
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
old mode 100644
new mode 100755
index 11ac85b..17f19c7
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
old mode 100644
new mode 100755
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/array_test1.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/array_test1.c
index e4f1ea8..282a55d 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/array_test1.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/array_test1.c
@@ -1,4 +1,4 @@
-/* { dg-do compile } */
+/* { dg-do run } */
 /* { dg-options "-fcilkplus" } */
 
 #include <stdlib.h>
@@ -47,7 +47,7 @@ int main2 (char **argv)
   array[x:y:z] = 505;
   for (ii = x; ii < 10; ii += z)
     if (array[ii] != 505)
-      return 2;
+      return 4;
     
   x = atoi(argv[1]);
   z = (10-atoi(argv[1]))/atoi(argv[1]);
@@ -57,7 +57,7 @@ int main2 (char **argv)
 
   for (ii = x; ii < 10; ii += z)
     if (array[ii] != 25)
-      return 1;
+      return 5;
   x = atoi(argv[1]);
   z = (10-atoi(argv[1]))/atoi(argv[1]);
   y = 10-atoi(argv[1]);
@@ -66,19 +66,19 @@ int main2 (char **argv)
     1400;
   for (ii = x; ii < 10; ii += z)
     if (array[ii] != 1400)
-      return 1;
+      return 6;
   
 
   array[atoi("5"):5:1] = 5555;
   
   for (ii = atoi ("5"); ii < 10; ii++)
     if (array[ii] != 5555)
-      return 2;
+      return 7;
   
 
   array[atoi("5"):atoi("5"):atoi("1")] = 9999;
   for (ii = atoi ("5"); ii < (atoi ("5") + atoi ("5")); ii += atoi ("1"))
     if (array[ii] != 9999)
-      return 3;
+      return 8;
   return 0;
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c
index d17d8cf..579d396 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c
@@ -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;
 
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
index 35eb115..14421d9 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
@@ -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;
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c
old mode 100644
new mode 100755
index a0a3742..18816e0
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c
@@ -8,4 +8,4 @@ int main (void)
   array2[:] = array2[: ;  /* { dg-error "expected ']'" } */
 
   return 0;
-} /* { dg-error "expected ';' before" } */
+} /* { dg-error "expected ';' before" "" { target c } } */
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c
index 2e86b4f..4314090 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c
@@ -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 }  } */
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c
index 34dfa16..47b5979 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c
@@ -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 } } */
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c
index eba28a8..a0efc04 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c
@@ -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;
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c
index cabdb23..793afb2 100755
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c
@@ -4,11 +4,11 @@
 int A[10];
 
 int main () {
-  char c = (char)N; /* { dg-error "undeclared" } */
+  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 }  7 } */
 
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c
index 843745e..3b0777e 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c
@@ -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
index 0000000..e9ee7ec
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/array_test1_tplt.cc
@@ -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
index 0000000..87c37e1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/array_test2_tplt.cc
@@ -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
index 0000000..479ba13
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/array_test_ND_tplt.cc
@@ -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 100755
index 0000000..b91de7a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/braced_list.cc
@@ -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
index 0000000..94ffe6e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_custom_tplt.cc
@@ -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
index 0000000..db81912
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_mutating_tplt.cc
@@ -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
index 0000000..1387558
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/fp_triplet_values_tplt.c
@@ -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/cilk-plus.exp b/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp
new file mode 100644
index 0000000..a153529
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp
@@ -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
diff --git a/gcc/testsuite/g++.dg/dg.exp b/gcc/testsuite/g++.dg/dg.exp
old mode 100644
new mode 100755
index 7201359..710218e
--- a/gcc/testsuite/g++.dg/dg.exp
+++ b/gcc/testsuite/g++.dg/dg.exp
@@ -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/*]

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH] Cilk Plus Array Notation for C++
  2013-06-12 20:50   ` Iyer, Balaji V
@ 2013-06-13 16:11     ` Aldy Hernandez
  2013-06-13 16:18       ` Richard Henderson
  2013-06-17 16:49       ` Iyer, Balaji V
  0 siblings, 2 replies; 40+ messages in thread
From: Aldy Hernandez @ 2013-06-13 16:11 UTC (permalink / raw)
  To: Iyer, Balaji V; +Cc: gcc-patches, Jason Merrill (jason@redhat.com), rth


>> It looks like a NULL in INIT_INDEX is a specially handled case.  Perhaps you
>> should document that INIT_INDEX can be null and what it means.
>> Also, you don't need to document what internal variable name you are using as
>> a return value (VALUE_TREE).  Perhaps instead of "The return value..." you could
>> write "This function returns the ARRAY_NOTATION_REF node." or something
>> like it.
>
> It is documented inside the function, right before checking for !init_index. Is that enough?

Please put it in the function comment.  As it stands, users would have 
to look through the body to find that init_index==NULL is a special case.


>> Changes to existing tests should be submitted as a separate patch, since this
>> doesn't seem to be C++ specific.  And BTW, this particular test change can be
>> committed as obvious.
>
> OK will do.  What about adding {target c} and {target c++} for test cases. Can that be submitted with the patch?

Yes.

> +  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX)
> +    {
> +      /* If the TYPE_MIN_VALUE is available for the new_var_type, then
> +	 set that as the initial value.  */
> +      if (TYPE_MIN_VALUE (new_var_type))
> +	new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
> +					    TYPE_MIN_VALUE (new_var_type), 1);
> +      else
> +	/* ... otherwise set initial value as the first element of array.  */
> +	new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
> +					    func_parm, 1);
> +      new_no_expr  = build_x_modify_expr (location, *new_var, NOP_EXPR,
> +					  *new_var, 1);
> +      new_yes_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
> +					  func_parm, 1);
> +      new_cond_expr = build_x_binary_op (location, LT_EXPR, *new_var,
> +					 TREE_CODE (*new_var), func_parm,
> +					 TREE_CODE (func_parm), 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);
> +    }
> +  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN)
> +    {
> +      /* If the TYPE_MAX_VALUE is available for the new_var_type, then
> +	 set that as the initial value.  */
> +      if (TYPE_MAX_VALUE (new_var_type))
> +	new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
> +					    TYPE_MAX_VALUE (new_var_type), 1);
> +      else
> +	/* ... otherwise set initial value as the first element of array.  */
> +	new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
> +					    func_parm, 1);
> +      new_no_expr  = build_x_modify_expr (location, *new_var, NOP_EXPR,
> +					  *new_var, 1);
> +      new_yes_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
> +					  func_parm, 1);
> +      new_cond_expr = build_x_binary_op (location, GT_EXPR, *new_var,
> +					 TREE_CODE (*new_var), func_parm,
> +					 TREE_CODE (func_parm), 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);
> +    }

The whole slew of these cases have a lot of duplicated code.  For 
instance, BUILT_IN_CILKPLUS_SEC_REDUCE_MIN is the same as 
BUILT_IN_CILKPLUS_SEC_REDUCE_MAX, the only difference being GT_EXPR vs 
LT_EXPR.  Surely you could do something like:

if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN
     || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX) {
    enum tree_code code;
    if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN)
      code = GT_EXPR;
    else
      code = LT_EXPR;
    // stuff
}

The compiler should be able to optimize the above, but even if it 
couldn't, I am willing to compare twice and save lines and lines of code.

Similarly for SEC_REDUCE_ANY_ZERO/SEC_REDUCE_ANY_NONZERO, 
SEC_REDUCE_ALL_ZERO/SEC_REDUCE_ALL_NONZERO, 
SEC_REDUCE_ADD/SEC_REDUCE_MUL, etc etc etc.

> +  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.  */

Extra whitespace.

> +  if (lhs_rank != 0 && rhs_rank != 0 && lhs_rank != rhs_rank)
> +    {
> +      tree lhs_base = lhs;
> +      tree rhs_base = rhs;
> +
> +      for (ii = 0; ii < lhs_rank; ii++)
> +	lhs_base = ARRAY_NOTATION_ARRAY (lhs_base);
> +
> +      while (rhs_base && TREE_CODE (rhs_base) != ARRAY_NOTATION_REF)
> +	rhs_base = TREE_OPERAND (rhs_base, 0);
> +      for (ii = 0; ii < rhs_rank; ii++)
> +	rhs_base = ARRAY_NOTATION_ARRAY (rhs_base);
> +
> +      if (location == UNKNOWN_LOCATION && EXPR_HAS_LOCATION (lhs))
> +	location = EXPR_LOCATION (lhs);
> +      error_at (location, "rank mismatch between %qD and %qD", lhs_base,
> +		rhs_base);
> +      return error_mark_node;
> +    }

This whole block seems to be indented incorrectly.

> +  /* Assign the array notation components to variable so that they can satisfy
> +     the exec-once rule.  */
> +  for (ii = 0; ii < lhs_list_size; ii++)
> +    {
> +      tree array_node = (*lhs_list)[ii];
> +      tree array_begin = ARRAY_NOTATION_START (array_node);
> +      tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
> +      tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
> +
> +      if (TREE_CODE (array_begin) != INTEGER_CST)
> +	{
> +	  lhs_begin_var = build_decl (location, VAR_DECL, NULL_TREE,
> +				      integer_type_node);
> +	  finish_expr_stmt (build_x_modify_expr (location, lhs_begin_var,
> +						 NOP_EXPR, array_begin,
> +						 complain));
> +	  ARRAY_NOTATION_START (array_node) = lhs_begin_var;
> +	}
> +      if (TREE_CODE (array_lngth) != INTEGER_CST)
> +	{
> +	  lhs_lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
> +				      integer_type_node);
> +	  finish_expr_stmt (build_x_modify_expr (location, lhs_lngth_var,
> +						 NOP_EXPR, array_lngth,
> +						 complain));
> +	  ARRAY_NOTATION_LENGTH (array_node) = lhs_lngth_var;
> +	}

All these exec-one wrappers seem to be doing the same thing over and 
over.  Can you abstract this sequence into a separate helper function? 
Perhaps something like:

for (ii = 0; ii < lhs_list_size; ii++)
   {
     exec_once (&ARRAY_NOTATION_START (array_node));
     exec_once (&ARRAY_NOTATION_LENGTH (array_node));
     exec_once (&ARRAY_NOTATION_STRIDE (array_node));
     ...
     ...
   }

or something to that effect.

> +  if (lhs_rank)
> +    {
> +      for (ii = 0; ii < lhs_list_size; ii++)
> +	{
> +	  jj = 0;
> +	  ii_tree = (*lhs_list)[ii];
> +	  while (ii_tree)
> +	    {
> +	      if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
> +		{
> +		  lhs_array[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) == PARM_DECL)
> +		break;
> +	    }
> +	}
> +    }
> +  else
> +    lhs_array[0][0] = NULL_TREE;
> +
> +  if (rhs_rank)
> +    {
> +      for (ii = 0; ii < rhs_list_size; ii++)
> +	{
> +	  jj = 0;
> +	  ii_tree = (*rhs_list)[ii];
> +	  while (ii_tree)
> +	    {
> +	      if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
> +		{
> +		  rhs_array[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) == PARM_DECL
> +		       || TREE_CODE (ii_tree) == CALL_EXPR)
> +		break;
> +	    }
> +	}
> +    }

Can't you abstract the common idiom into some inline function?

> +  for (ii = 0; ii < lhs_list_size; ii++)
> +    {
> +      if (TREE_CODE ((*lhs_list)[ii]) == ARRAY_NOTATION_REF)
> +	{
> +	  for (jj = 0; jj < lhs_rank; jj++)
> +	    {
> +	      if (TREE_CODE (lhs_array[ii][jj]) == ARRAY_NOTATION_REF)
> +		{
> +		  lhs_value[ii][jj] = ARRAY_NOTATION_ARRAY (lhs_array[ii][jj]);
> +		  lhs_start[ii][jj] = ARRAY_NOTATION_START (lhs_array[ii][jj]);
> +		  lhs_length[ii][jj] =
> +		    fold_build1 (CONVERT_EXPR, integer_type_node,
> +				 ARRAY_NOTATION_LENGTH (lhs_array[ii][jj]));
> +		  lhs_stride[ii][jj] =
> +		    fold_build1 (CONVERT_EXPR, integer_type_node,
> +				 ARRAY_NOTATION_STRIDE (lhs_array[ii][jj]));
> +		  lhs_vector[ii][jj] = true;
> +		
> +		  /* If the stride value is variable (i.e. not constant) then
> +		     assume that the length is positive.  */
> +		  if (!TREE_CONSTANT (lhs_length[ii][jj]))
> +		    lhs_count_down[ii][jj] = false;
> +		  else if (tree_int_cst_lt
> +			   (lhs_length[ii][jj],
> +			    build_zero_cst (TREE_TYPE (lhs_length[ii][jj]))))
> +		    lhs_count_down[ii][jj] = true;
> +		  else
> +		    lhs_count_down[ii][jj] = false;
> +		}
> +	      else
> +		lhs_vector[ii][jj] = false;
> +	    }
> +	}
> +    }
> +  for (ii = 0; ii < rhs_list_size; ii++)
> +    {
> +      if (TREE_CODE ((*rhs_list)[ii]) == ARRAY_NOTATION_REF)
> +	{
> +	  for (jj = 0; jj < rhs_rank; jj++)
> +	    {
> +	      if (TREE_CODE (rhs_array[ii][jj]) == ARRAY_NOTATION_REF)
> +		{
> +		  rhs_value[ii][jj]  = ARRAY_NOTATION_ARRAY (rhs_array[ii][jj]);
> +		  rhs_start[ii][jj]  = ARRAY_NOTATION_START (rhs_array[ii][jj]);
> +		  rhs_length[ii][jj] =
> +		    ARRAY_NOTATION_LENGTH (rhs_array[ii][jj]);
> +		  rhs_stride[ii][jj] =
> +		    ARRAY_NOTATION_STRIDE (rhs_array[ii][jj]);
> +		  rhs_vector[ii][jj] = true;
> +		  /* If the stride value is variable (i.e. not constant) then
> +		     assume that the length is positive.  */
> +		  if (!TREE_CONSTANT (rhs_length[ii][jj]))
> +		    rhs_count_down[ii][jj] = false;
> +		  else if (tree_int_cst_lt
> +			   (rhs_length[ii][jj],
> +			    build_zero_cst (TREE_TYPE (rhs_length[ii][jj]))))
> +		    rhs_count_down[ii][jj] = true;
> +		  else
> +		    rhs_count_down[ii][jj] = false;	
> +		}
> +	      else
> +		rhs_vector[ii][jj] = false;
> +	    }

Similarly here, though I don't know if the CONVERT_EXPR in the first 
case and not in the second case is an oversight.

> +  if (lhs_rank)
> +    {
> +      for (ii = 0; ii < lhs_list_size; ii++)
> +	{
> +	  if (lhs_vector[ii][0])
> +	    {
> +	      /* The last ARRAY_NOTATION element's ARRAY component should be
> +		 the array's base value.  */
> +	      tree lhs_array_opr = lhs_value[ii][lhs_rank - 1];
> +	      for (s_jj = lhs_rank - 1; s_jj >= 0; s_jj--)
> +		{
> +		  tree stride = NULL_TREE, var = NULL_TREE, start = NULL_TREE;
> +		  if ((TREE_TYPE (lhs_start[ii][s_jj]) ==
> +		       TREE_TYPE (lhs_stride[ii][s_jj]))
> +		      && (TREE_TYPE (lhs_stride[ii][s_jj]) !=
> +			  TREE_TYPE (lhs_var[s_jj])))
> +		    {
> +		      /* If stride and start are of same type and the induction
> +			 var is not, convert induction variable to stride's
> +			 type.  */
> +		      start = lhs_start[ii][s_jj];
> +		      stride = lhs_stride[ii][s_jj];
> +		      var = build_c_cast (location,
> +					  TREE_TYPE (lhs_stride[ii][s_jj]),
> +					  lhs_var[s_jj]);
> +		    }
> +		  else if (TREE_TYPE (lhs_start[ii][s_jj]) !=
> +			   TREE_TYPE (lhs_stride[ii][s_jj]))
> +		    {
> +		      /* 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 -.  */
> +		      start = build_c_cast (location, integer_type_node,
> +					    lhs_start[ii][s_jj]);
> +		      stride = build_c_cast (location, integer_type_node,
> +					     lhs_stride[ii][s_jj]);
> +		      var = build_c_cast (location, integer_type_node,
> +					  lhs_var[s_jj]);
> +		    }
> +		  else
> +		    {
> +		      start = lhs_start[ii][s_jj];
> +		      stride = lhs_stride[ii][s_jj];
> +		      var = lhs_var[s_jj];
> +		    }
> +		  if (lhs_count_down[ii][s_jj])
> +		    /* Array[start_index - (induction_var * stride)].  */
> +		    lhs_array_opr = grok_array_decl
> +		      (location, lhs_array_opr,
> +		       build2 (MINUS_EXPR, TREE_TYPE (var), start,
> +			       build2 (MULT_EXPR, TREE_TYPE (var), var,
> +				       stride)), false);	
> +		  else
> +		    /* Array[start_index + (induction_var * stride)].  */
> +		    lhs_array_opr = grok_array_decl
> +		      (location, lhs_array_opr,
> +		       build2 (PLUS_EXPR, TREE_TYPE (var), start,
> +			       build2 (MULT_EXPR, TREE_TYPE (var), var,
> +				       stride)), false);
> +		}
> +	      vec_safe_push (lhs_array_operand, lhs_array_opr);
> +	    }
> +	  else
> +	    vec_safe_push (lhs_array_operand, integer_one_node);
> +	}

99% of this looks exactly like the rhs_rank case, surely you can 
abstract most of this into a separate function.

> +      for (ii = 0; ii < rhs_list_size; ii++)
> +	{
> +	  tree rhs_node = (*rhs_list)[ii];
> +	  if (TREE_CODE (rhs_node) == CALL_EXPR)
> +	    {
> +	      int idx_value = 0;
> +	      tree func_name = CALL_EXPR_FN (rhs_node);
> +	      if (TREE_CODE (func_name) == ADDR_EXPR)
> +		if (is_sec_implicit_index_fn (func_name))
> +		  {
> +		    idx_value =
> +		      extract_sec_implicit_index_arg (location, rhs_node);
> +		    if (idx_value < (int) lhs_rank && idx_value >= 0)
> +		      vec_safe_push (rhs_array_operand, rhs_var[idx_value]);
> +		    else
> +		      {
> +			size_t ee = 0;
> +			tree rhs_base = (*lhs_list)[ii];
> +			for (ee = 0; ee < rhs_rank; ee++)
> +			  if (rhs_base
> +			      && TREE_CODE (rhs_base) == ARRAY_NOTATION_REF)
> +			    rhs_base = ARRAY_NOTATION_ARRAY (rhs_base);
> +
> +			error_at (location, "__sec_implicit_index argument %d "
> +				  "must be less than rank of %qD", idx_value,
> +				  rhs_base);
> +			return error_mark_node;
> +		      }
> +		  }
> +	    }
> +	}	
> +      replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
> +      array_expr_rhs = rhs;
> +    }
> +  else
> +    {
> +      for (ii = 0; ii < rhs_list_size; ii++)
> +	{
> +	  tree rhs_node = (*rhs_list)[ii];
> +	  if (TREE_CODE (rhs_node) == CALL_EXPR)
> +	    {
> +	      int idx_value = 0;
> +	      tree func_name = CALL_EXPR_FN (rhs_node);
> +	      if (is_sec_implicit_index_fn (func_name))
> +		{
> +		  idx_value =  extract_sec_implicit_index_arg (location,
> +							       rhs_node);
> +		  if (idx_value < (int) lhs_rank && idx_value >= 0)
> +		    vec_safe_push (rhs_array_operand, lhs_var[idx_value]);
> +		  else
> +		    {
> +		      size_t ee = 0;
> +		      tree lhs_base = (*lhs_list)[ii];
> +		      for (ee = 0; ee < lhs_rank; ee++)
> +			if (lhs_base
> +			    && TREE_CODE (lhs_base) == ARRAY_NOTATION_REF)
> +			  lhs_base = ARRAY_NOTATION_ARRAY (lhs_base);
> +		      error_at (location, "__sec_implicit_index argument %d "
> +				"must be less than the rank of %qD", idx_value,
> +				lhs_base);
> +		      return error_mark_node;
> +		    }
> +		}
> +	    }

Again, a lot of stuff that looks exactly the same.

Similarly in the rest of expand_an_in_modify_expr().  The function is 
HUGE, and there's a lot of code duplication going on.  Try to abstract 
the things you do more than once into their own helper functions.  This 
will cut down on the maintenance burden.

> +  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;
> +	}
> +    }

And here in cp_expand_cond_array_notations().

> +  for (ii = 0; ii < list_size; ii++)
> +    {
> +      jj = 0;
> +      jj_tree = (*array_list)[ii];
> +      while (jj_tree)
> +	{
> +	  if (TREE_CODE (jj_tree) == ARRAY_NOTATION_REF)
> +	    {
> +	      array_ops[ii][jj] = jj_tree;
> +	      jj++;
> +	      jj_tree = ARRAY_NOTATION_ARRAY (jj_tree);
> +	    }
> +	  else if (TREE_CODE (jj_tree) == ARRAY_REF)
> +	    jj_tree = TREE_OPERAND (jj_tree, 0);
> +	  else if (TREE_CODE (jj_tree) == VAR_DECL
> +		   || TREE_CODE (jj_tree) == PARM_DECL)
> +	    break;
> +	}
> +    }

The above snippet appears in the exact same form in both 
expand_sec_reduce_builtin() and cp_expand_cond_array_notations().  I'm 
not going to mention any more of these duplicated code sequences, but 
you should go through the entire file and abstract what you can into 
separate inlineable functions, no sense maintaining 10 copies of the 
same thing.

Aldy

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH] Cilk Plus Array Notation for C++
  2013-06-13 16:11     ` Aldy Hernandez
@ 2013-06-13 16:18       ` Richard Henderson
  2013-06-17 17:00         ` Iyer, Balaji V
  2013-06-17 16:49       ` Iyer, Balaji V
  1 sibling, 1 reply; 40+ messages in thread
From: Richard Henderson @ 2013-06-13 16:18 UTC (permalink / raw)
  To: Aldy Hernandez
  Cc: Iyer, Balaji V, gcc-patches, Jason Merrill (jason@redhat.com)

On 06/13/2013 09:11 AM, Aldy Hernandez wrote:
> The whole slew of these cases have a lot of duplicated code.  For instance,
> BUILT_IN_CILKPLUS_SEC_REDUCE_MIN is the same as
> BUILT_IN_CILKPLUS_SEC_REDUCE_MAX, the only difference being GT_EXPR vs
> LT_EXPR.  Surely you could do something like:
> 
> if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN
>     || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX) {
>    enum tree_code code;
>    if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN)
>      code = GT_EXPR;
>    else
>      code = LT_EXPR;
>    // stuff
> }
> 
> The compiler should be able to optimize the above, but even if it couldn't, I
> am willing to compare twice and save lines and lines of code.
> 
> Similarly for SEC_REDUCE_ANY_ZERO/SEC_REDUCE_ANY_NONZERO,
> SEC_REDUCE_ALL_ZERO/SEC_REDUCE_ALL_NONZERO, SEC_REDUCE_ADD/SEC_REDUCE_MUL, etc
> etc etc.

Yep.  It's at this point that I normally start using the idiom

	switch (an_type)
	  {
	  case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN:
	    code = GT_EXPR;
	    goto do_min_max;
	  case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX:
	    code = LT_EXPR;
	    goto do_min_max;
	  do_min_max:
	    // stuff

So much the better if you can include the other SEC_* cases in that switch too,
doing one compiler-controlled dispatch.

It also occurs to me to wonder why you're building your own COND_EXPR here,
with the comparison, rather than using MIN/MAX_EXPR...


r~

^ permalink raw reply	[flat|nested] 40+ messages in thread

* RE: [PATCH] Cilk Plus Array Notation for C++
  2013-06-13 16:11     ` Aldy Hernandez
  2013-06-13 16:18       ` Richard Henderson
@ 2013-06-17 16:49       ` Iyer, Balaji V
  1 sibling, 0 replies; 40+ messages in thread
From: Iyer, Balaji V @ 2013-06-17 16:49 UTC (permalink / raw)
  To: Aldy Hernandez; +Cc: gcc-patches, Jason Merrill (jason@redhat.com), rth

[-- Attachment #1: Type: text/plain, Size: 24607 bytes --]

Aldy,
	Please see my responses below. Here is a fixed patch and the ChangeLog entries:

gcc/cp/ChangeLog
2013-06-17  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-17  Balaji V. Iyer  <balaji.v.iyer@intel.com>

        * 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++ parser 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.

Thanks,

Balaji V. Iyer.

> -----Original Message-----
> From: Aldy Hernandez [mailto:aldyh@redhat.com]
> Sent: Thursday, June 13, 2013 12:11 PM
> To: Iyer, Balaji V
> Cc: gcc-patches@gcc.gnu.org; Jason Merrill (jason@redhat.com);
> rth@redhat.com
> Subject: Re: [PATCH] Cilk Plus Array Notation for C++
> 
> 
> >> It looks like a NULL in INIT_INDEX is a specially handled case.
> >> Perhaps you should document that INIT_INDEX can be null and what it
> means.
> >> Also, you don't need to document what internal variable name you are
> >> using as a return value (VALUE_TREE).  Perhaps instead of "The return
> >> value..." you could write "This function returns the
> >> ARRAY_NOTATION_REF node." or something like it.
> >
> > It is documented inside the function, right before checking for !init_index. Is
> that enough?
> 
> Please put it in the function comment.  As it stands, users would have to look
> through the body to find that init_index==NULL is a special case.

DONE!

> 
> 
> >> Changes to existing tests should be submitted as a separate patch, since this
> >> doesn't seem to be C++ specific.  And BTW, this particular test change can be
> >> committed as obvious.
> >
> > OK will do.  What about adding {target c} and {target c++} for test cases. Can
> that be submitted with the patch?
> 
> Yes.
> 
> > +  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX)
> > +    {
> > +      /* If the TYPE_MIN_VALUE is available for the new_var_type, then
> > +	 set that as the initial value.  */
> > +      if (TYPE_MIN_VALUE (new_var_type))
> > +	new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
> > +					    TYPE_MIN_VALUE (new_var_type),
> 1);
> > +      else
> > +	/* ... otherwise set initial value as the first element of array.  */
> > +	new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
> > +					    func_parm, 1);
> > +      new_no_expr  = build_x_modify_expr (location, *new_var, NOP_EXPR,
> > +					  *new_var, 1);
> > +      new_yes_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
> > +					  func_parm, 1);
> > +      new_cond_expr = build_x_binary_op (location, LT_EXPR, *new_var,
> > +					 TREE_CODE (*new_var), func_parm,
> > +					 TREE_CODE (func_parm), 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);
> > +    }
> > +  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN)
> > +    {
> > +      /* If the TYPE_MAX_VALUE is available for the new_var_type, then
> > +	 set that as the initial value.  */
> > +      if (TYPE_MAX_VALUE (new_var_type))
> > +	new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
> > +					    TYPE_MAX_VALUE (new_var_type),
> 1);
> > +      else
> > +	/* ... otherwise set initial value as the first element of array.  */
> > +	new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
> > +					    func_parm, 1);
> > +      new_no_expr  = build_x_modify_expr (location, *new_var, NOP_EXPR,
> > +					  *new_var, 1);
> > +      new_yes_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
> > +					  func_parm, 1);
> > +      new_cond_expr = build_x_binary_op (location, GT_EXPR, *new_var,
> > +					 TREE_CODE (*new_var), func_parm,
> > +					 TREE_CODE (func_parm), 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);
> > +    }
> 
> The whole slew of these cases have a lot of duplicated code.  For
> instance, BUILT_IN_CILKPLUS_SEC_REDUCE_MIN is the same as
> BUILT_IN_CILKPLUS_SEC_REDUCE_MAX, the only difference being GT_EXPR vs
> LT_EXPR.  Surely you could do something like:
> 
> if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN
>      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX) {
>     enum tree_code code;
>     if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN)
>       code = GT_EXPR;
>     else
>       code = LT_EXPR;
>     // stuff
> }
> 
> The compiler should be able to optimize the above, but even if it
> couldn't, I am willing to compare twice and save lines and lines of code.

DONE! The line size went from 261 to ~138

> 
> Similarly for SEC_REDUCE_ANY_ZERO/SEC_REDUCE_ANY_NONZERO,
> SEC_REDUCE_ALL_ZERO/SEC_REDUCE_ALL_NONZERO,
> SEC_REDUCE_ADD/SEC_REDUCE_MUL, etc etc etc.
> 

> > +  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.  */
> 
> Extra whitespace.
> 
> > +  if (lhs_rank != 0 && rhs_rank != 0 && lhs_rank != rhs_rank)
> > +    {
> > +      tree lhs_base = lhs;
> > +      tree rhs_base = rhs;
> > +
> > +      for (ii = 0; ii < lhs_rank; ii++)
> > +	lhs_base = ARRAY_NOTATION_ARRAY (lhs_base);
> > +
> > +      while (rhs_base && TREE_CODE (rhs_base) != ARRAY_NOTATION_REF)
> > +	rhs_base = TREE_OPERAND (rhs_base, 0);
> > +      for (ii = 0; ii < rhs_rank; ii++)
> > +	rhs_base = ARRAY_NOTATION_ARRAY (rhs_base);
> > +
> > +      if (location == UNKNOWN_LOCATION && EXPR_HAS_LOCATION (lhs))
> > +	location = EXPR_LOCATION (lhs);
> > +      error_at (location, "rank mismatch between %qD and %qD", lhs_base,
> > +		rhs_base);
> > +      return error_mark_node;
> > +    }
> 
> This whole block seems to be indented incorrectly.
> 
> > +  /* Assign the array notation components to variable so that they can satisfy
> > +     the exec-once rule.  */
> > +  for (ii = 0; ii < lhs_list_size; ii++)
> > +    {
> > +      tree array_node = (*lhs_list)[ii];
> > +      tree array_begin = ARRAY_NOTATION_START (array_node);
> > +      tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
> > +      tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
> > +
> > +      if (TREE_CODE (array_begin) != INTEGER_CST)
> > +	{
> > +	  lhs_begin_var = build_decl (location, VAR_DECL, NULL_TREE,
> > +				      integer_type_node);
> > +	  finish_expr_stmt (build_x_modify_expr (location, lhs_begin_var,
> > +						 NOP_EXPR, array_begin,
> > +						 complain));
> > +	  ARRAY_NOTATION_START (array_node) = lhs_begin_var;
> > +	}
> > +      if (TREE_CODE (array_lngth) != INTEGER_CST)
> > +	{
> > +	  lhs_lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
> > +				      integer_type_node);
> > +	  finish_expr_stmt (build_x_modify_expr (location, lhs_lngth_var,
> > +						 NOP_EXPR, array_lngth,
> > +						 complain));
> > +	  ARRAY_NOTATION_LENGTH (array_node) = lhs_lngth_var;
> > +	}
> 
> All these exec-one wrappers seem to be doing the same thing over and
> over.  Can you abstract this sequence into a separate helper function?
> Perhaps something like:
> 
> for (ii = 0; ii < lhs_list_size; ii++)
>    {
>      exec_once (&ARRAY_NOTATION_START (array_node));
>      exec_once (&ARRAY_NOTATION_LENGTH (array_node));
>      exec_once (&ARRAY_NOTATION_STRIDE (array_node));
>      ...
>      ...
>    }
> 
> or something to that effect.

DONE!

> 
> > +  if (lhs_rank)
> > +    {
> > +      for (ii = 0; ii < lhs_list_size; ii++)
> > +	{
> > +	  jj = 0;
> > +	  ii_tree = (*lhs_list)[ii];
> > +	  while (ii_tree)
> > +	    {
> > +	      if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
> > +		{
> > +		  lhs_array[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) == PARM_DECL)
> > +		break;
> > +	    }
> > +	}
> > +    }
> > +  else
> > +    lhs_array[0][0] = NULL_TREE;
> > +
> > +  if (rhs_rank)
> > +    {
> > +      for (ii = 0; ii < rhs_list_size; ii++)
> > +	{
> > +	  jj = 0;
> > +	  ii_tree = (*rhs_list)[ii];
> > +	  while (ii_tree)
> > +	    {
> > +	      if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
> > +		{
> > +		  rhs_array[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) == PARM_DECL
> > +		       || TREE_CODE (ii_tree) == CALL_EXPR)
> > +		break;
> > +	    }
> > +	}
> > +    }
> 
> Can't you abstract the common idiom into some inline function?
> 
> > +  for (ii = 0; ii < lhs_list_size; ii++)
> > +    {
> > +      if (TREE_CODE ((*lhs_list)[ii]) == ARRAY_NOTATION_REF)
> > +	{
> > +	  for (jj = 0; jj < lhs_rank; jj++)
> > +	    {
> > +	      if (TREE_CODE (lhs_array[ii][jj]) == ARRAY_NOTATION_REF)
> > +		{
> > +		  lhs_value[ii][jj] = ARRAY_NOTATION_ARRAY (lhs_array[ii][jj]);
> > +		  lhs_start[ii][jj] = ARRAY_NOTATION_START (lhs_array[ii][jj]);
> > +		  lhs_length[ii][jj] =
> > +		    fold_build1 (CONVERT_EXPR, integer_type_node,
> > +				 ARRAY_NOTATION_LENGTH (lhs_array[ii][jj]));
> > +		  lhs_stride[ii][jj] =
> > +		    fold_build1 (CONVERT_EXPR, integer_type_node,
> > +				 ARRAY_NOTATION_STRIDE (lhs_array[ii][jj]));
> > +		  lhs_vector[ii][jj] = true;
> > +
> > +		  /* If the stride value is variable (i.e. not constant) then
> > +		     assume that the length is positive.  */
> > +		  if (!TREE_CONSTANT (lhs_length[ii][jj]))
> > +		    lhs_count_down[ii][jj] = false;
> > +		  else if (tree_int_cst_lt
> > +			   (lhs_length[ii][jj],
> > +			    build_zero_cst (TREE_TYPE (lhs_length[ii][jj]))))
> > +		    lhs_count_down[ii][jj] = true;
> > +		  else
> > +		    lhs_count_down[ii][jj] = false;
> > +		}
> > +	      else
> > +		lhs_vector[ii][jj] = false;
> > +	    }
> > +	}
> > +    }
> > +  for (ii = 0; ii < rhs_list_size; ii++)
> > +    {
> > +      if (TREE_CODE ((*rhs_list)[ii]) == ARRAY_NOTATION_REF)
> > +	{
> > +	  for (jj = 0; jj < rhs_rank; jj++)
> > +	    {
> > +	      if (TREE_CODE (rhs_array[ii][jj]) == ARRAY_NOTATION_REF)
> > +		{
> > +		  rhs_value[ii][jj]  = ARRAY_NOTATION_ARRAY (rhs_array[ii][jj]);
> > +		  rhs_start[ii][jj]  = ARRAY_NOTATION_START (rhs_array[ii][jj]);
> > +		  rhs_length[ii][jj] =
> > +		    ARRAY_NOTATION_LENGTH (rhs_array[ii][jj]);
> > +		  rhs_stride[ii][jj] =
> > +		    ARRAY_NOTATION_STRIDE (rhs_array[ii][jj]);
> > +		  rhs_vector[ii][jj] = true;
> > +		  /* If the stride value is variable (i.e. not constant) then
> > +		     assume that the length is positive.  */
> > +		  if (!TREE_CONSTANT (rhs_length[ii][jj]))
> > +		    rhs_count_down[ii][jj] = false;
> > +		  else if (tree_int_cst_lt
> > +			   (rhs_length[ii][jj],
> > +			    build_zero_cst (TREE_TYPE (rhs_length[ii][jj]))))
> > +		    rhs_count_down[ii][jj] = true;
> > +		  else
> > +		    rhs_count_down[ii][jj] = false;
> > +		}
> > +	      else
> > +		rhs_vector[ii][jj] = false;
> > +	    }
> 
> Similarly here, though I don't know if the CONVERT_EXPR in the first
> case and not in the second case is an oversight.
> 
> > +  if (lhs_rank)
> > +    {
> > +      for (ii = 0; ii < lhs_list_size; ii++)
> > +	{
> > +	  if (lhs_vector[ii][0])
> > +	    {
> > +	      /* The last ARRAY_NOTATION element's ARRAY component should
> be
> > +		 the array's base value.  */
> > +	      tree lhs_array_opr = lhs_value[ii][lhs_rank - 1];
> > +	      for (s_jj = lhs_rank - 1; s_jj >= 0; s_jj--)
> > +		{
> > +		  tree stride = NULL_TREE, var = NULL_TREE, start =
> NULL_TREE;
> > +		  if ((TREE_TYPE (lhs_start[ii][s_jj]) ==
> > +		       TREE_TYPE (lhs_stride[ii][s_jj]))
> > +		      && (TREE_TYPE (lhs_stride[ii][s_jj]) !=
> > +			  TREE_TYPE (lhs_var[s_jj])))
> > +		    {
> > +		      /* If stride and start are of same type and the induction
> > +			 var is not, convert induction variable to stride's
> > +			 type.  */
> > +		      start = lhs_start[ii][s_jj];
> > +		      stride = lhs_stride[ii][s_jj];
> > +		      var = build_c_cast (location,
> > +					  TREE_TYPE (lhs_stride[ii][s_jj]),
> > +					  lhs_var[s_jj]);
> > +		    }
> > +		  else if (TREE_TYPE (lhs_start[ii][s_jj]) !=
> > +			   TREE_TYPE (lhs_stride[ii][s_jj]))
> > +		    {
> > +		      /* 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 -.  */
> > +		      start = build_c_cast (location, integer_type_node,
> > +					    lhs_start[ii][s_jj]);
> > +		      stride = build_c_cast (location, integer_type_node,
> > +					     lhs_stride[ii][s_jj]);
> > +		      var = build_c_cast (location, integer_type_node,
> > +					  lhs_var[s_jj]);
> > +		    }
> > +		  else
> > +		    {
> > +		      start = lhs_start[ii][s_jj];
> > +		      stride = lhs_stride[ii][s_jj];
> > +		      var = lhs_var[s_jj];
> > +		    }
> > +		  if (lhs_count_down[ii][s_jj])
> > +		    /* Array[start_index - (induction_var * stride)].  */
> > +		    lhs_array_opr = grok_array_decl
> > +		      (location, lhs_array_opr,
> > +		       build2 (MINUS_EXPR, TREE_TYPE (var), start,
> > +			       build2 (MULT_EXPR, TREE_TYPE (var), var,
> > +				       stride)), false);
> > +		  else
> > +		    /* Array[start_index + (induction_var * stride)].  */
> > +		    lhs_array_opr = grok_array_decl
> > +		      (location, lhs_array_opr,
> > +		       build2 (PLUS_EXPR, TREE_TYPE (var), start,
> > +			       build2 (MULT_EXPR, TREE_TYPE (var), var,
> > +				       stride)), false);
> > +		}
> > +	      vec_safe_push (lhs_array_operand, lhs_array_opr);
> > +	    }
> > +	  else
> > +	    vec_safe_push (lhs_array_operand, integer_one_node);
> > +	}
> 
> 99% of this looks exactly like the rhs_rank case, surely you can
> abstract most of this into a separate function.
> 
> > +      for (ii = 0; ii < rhs_list_size; ii++)
> > +	{
> > +	  tree rhs_node = (*rhs_list)[ii];
> > +	  if (TREE_CODE (rhs_node) == CALL_EXPR)
> > +	    {
> > +	      int idx_value = 0;
> > +	      tree func_name = CALL_EXPR_FN (rhs_node);
> > +	      if (TREE_CODE (func_name) == ADDR_EXPR)
> > +		if (is_sec_implicit_index_fn (func_name))
> > +		  {
> > +		    idx_value =
> > +		      extract_sec_implicit_index_arg (location, rhs_node);
> > +		    if (idx_value < (int) lhs_rank && idx_value >= 0)
> > +		      vec_safe_push (rhs_array_operand, rhs_var[idx_value]);
> > +		    else
> > +		      {
> > +			size_t ee = 0;
> > +			tree rhs_base = (*lhs_list)[ii];
> > +			for (ee = 0; ee < rhs_rank; ee++)
> > +			  if (rhs_base
> > +			      && TREE_CODE (rhs_base) ==
> ARRAY_NOTATION_REF)
> > +			    rhs_base = ARRAY_NOTATION_ARRAY (rhs_base);
> > +
> > +			error_at (location, "__sec_implicit_index argument %d
> "
> > +				  "must be less than rank of %qD", idx_value,
> > +				  rhs_base);
> > +			return error_mark_node;
> > +		      }
> > +		  }
> > +	    }
> > +	}
> > +      replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
> > +      array_expr_rhs = rhs;
> > +    }
> > +  else
> > +    {
> > +      for (ii = 0; ii < rhs_list_size; ii++)
> > +	{
> > +	  tree rhs_node = (*rhs_list)[ii];
> > +	  if (TREE_CODE (rhs_node) == CALL_EXPR)
> > +	    {
> > +	      int idx_value = 0;
> > +	      tree func_name = CALL_EXPR_FN (rhs_node);
> > +	      if (is_sec_implicit_index_fn (func_name))
> > +		{
> > +		  idx_value =  extract_sec_implicit_index_arg (location,
> > +							       rhs_node);
> > +		  if (idx_value < (int) lhs_rank && idx_value >= 0)
> > +		    vec_safe_push (rhs_array_operand, lhs_var[idx_value]);
> > +		  else
> > +		    {
> > +		      size_t ee = 0;
> > +		      tree lhs_base = (*lhs_list)[ii];
> > +		      for (ee = 0; ee < lhs_rank; ee++)
> > +			if (lhs_base
> > +			    && TREE_CODE (lhs_base) ==
> ARRAY_NOTATION_REF)
> > +			  lhs_base = ARRAY_NOTATION_ARRAY (lhs_base);
> > +		      error_at (location, "__sec_implicit_index argument %d "
> > +				"must be less than the rank of %qD", idx_value,
> > +				lhs_base);
> > +		      return error_mark_node;
> > +		    }
> > +		}
> > +	    }
> 
> Again, a lot of stuff that looks exactly the same.

DONE!

> 
> Similarly in the rest of expand_an_in_modify_expr().  The function is
> HUGE, and there's a lot of code duplication going on.  Try to abstract
> the things you do more than once into their own helper functions.  This
> will cut down on the maintenance burden.
> 
> > +  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;
> > +	}
> > +    }
> 
> And here in cp_expand_cond_array_notations().
> 
> > +  for (ii = 0; ii < list_size; ii++)
> > +    {
> > +      jj = 0;
> > +      jj_tree = (*array_list)[ii];
> > +      while (jj_tree)
> > +	{
> > +	  if (TREE_CODE (jj_tree) == ARRAY_NOTATION_REF)
> > +	    {
> > +	      array_ops[ii][jj] = jj_tree;
> > +	      jj++;
> > +	      jj_tree = ARRAY_NOTATION_ARRAY (jj_tree);
> > +	    }
> > +	  else if (TREE_CODE (jj_tree) == ARRAY_REF)
> > +	    jj_tree = TREE_OPERAND (jj_tree, 0);
> > +	  else if (TREE_CODE (jj_tree) == VAR_DECL
> > +		   || TREE_CODE (jj_tree) == PARM_DECL)
> > +	    break;
> > +	}
> > +    }

DONE!

> 
> The above snippet appears in the exact same form in both
> expand_sec_reduce_builtin() and cp_expand_cond_array_notations().  I'm
> not going to mention any more of these duplicated code sequences, but
> you should go through the entire file and abstract what you can into
> separate inlineable functions, no sense maintaining 10 copies of the
> same thing.

I think I have fixed everything. Also, replaced the mallocs with vec_trees for ease of passing parameters.

So, is this OK for trunk?

> 
> Aldy

[-- Attachment #2: patch_array_notation_cpp.txt --]
[-- Type: text/plain, Size: 126511 bytes --]

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
old mode 100644
new mode 100755
index 1b58ba0..0b11a75
Binary files a/gcc/cp/ChangeLog and b/gcc/cp/ChangeLog differ
diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
index df8ed3e..6e80bcf 100644
--- a/gcc/cp/Make-lang.in
+++ b/gcc/cp/Make-lang.in
@@ -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)
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index dfd061a..64be41f 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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 100755
index 0000000..b51949b
--- /dev/null
+++ b/gcc/cp/cp-array-notation.c
@@ -0,0 +1,1744 @@
+/* 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) is passed in as a 2D vector of trees.  */
+
+static bool
+cp_length_mismatch_in_expr_p (location_t loc, vec<vec<tree> >list)
+{
+  size_t ii, jj;
+  tree start = NULL_TREE;
+  HOST_WIDE_INT l_start, l_node;
+
+  size_t x = list.length ();
+  size_t y = list[0].length ();
+  
+  for (jj = 0; jj < y; jj++)
+    {
+      start = NULL_TREE;
+      for (ii = 0; ii < x; ii++)
+	{
+	  if (!start)
+	    start = list[ii][jj];
+	  else if (TREE_CODE (start) == INTEGER_CST)
+	    {
+	      /* If start 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]) == INTEGER_CST)
+		{
+		  l_node = int_cst_value (list[ii][jj]);
+		  l_start = int_cst_value (start);
+		  if (absu_hwi (l_start) != absu_hwi (l_node))
+		    {
+		      error_at (loc, "length mismatch in expression");
+		      return true;
+		    }
+		}
+	    }
+	  else
+	    /* We set the start node as the current node just in case it turns
+	       out to be an integer.  */
+	    start = list[ii][jj];
+	}
+    }
+  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;
+    }
+}
+
+/* Extracts all the array notation triplet information from LIST and stores them
+   in a 2-D arrays (size x rank) of START, LENGTH and STRIDE, holding the
+   starting index, length, and stride, respectively.  In addition, it also
+   sets two bool arrays IS_VECTOR and COUNT_DOWN indicating whether a certain
+   value at a certain field is a vector or not.  */
+
+static inline void
+extract_an_triplets (vec <tree, va_gc> *list, vec <vec<tree> > *value,
+		     vec <vec<tree> > *start, vec <vec<tree> > *length,
+		     vec <vec<tree> > *stride, vec <vec <bool> > *is_vector,
+		     vec<vec<bool> > *count_down, size_t size, size_t rank)
+{
+  vec<vec<tree> > array_exprs = vNULL;
+
+  start->safe_grow_cleared (size);
+  length->safe_grow_cleared (size);
+  stride->safe_grow_cleared (size);
+  value->safe_grow_cleared (size);
+  array_exprs.safe_grow_cleared (size);
+  is_vector->safe_grow_cleared (size);
+  count_down->safe_grow_cleared (size);
+
+  for (size_t ii = 0; ii < size; ii++)
+    for (size_t jj = 0; jj < rank; jj++)
+      {
+	array_exprs[ii].safe_push (NULL_TREE);
+	(*start)[ii].safe_push (NULL_TREE);
+	(*value)[ii].safe_push (NULL_TREE);
+	(*length)[ii].safe_push (NULL_TREE);
+	(*stride)[ii].safe_push (NULL_TREE);
+	(*is_vector)[ii].safe_push (false);
+	(*count_down)[ii].safe_push (false);
+      }
+  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];
+	    (*is_vector)[ii][jj] = true;
+	    (*value)[ii][jj] = ARRAY_NOTATION_ARRAY (ii_tree);
+	    (*start)[ii][jj] = ARRAY_NOTATION_START (ii_tree);
+	    (*length)[ii][jj] = fold_build1 (CONVERT_EXPR, integer_type_node,
+					     ARRAY_NOTATION_LENGTH (ii_tree));
+	    (*stride)[ii][jj] = fold_build1 (CONVERT_EXPR, integer_type_node,
+					     ARRAY_NOTATION_STRIDE (ii_tree));
+	  }
+}
+
+/* Returns a vector of size RANK that contains an array ref that is derived from
+   array notation triplet parameters stored in VALUE, START, STRIDE.  IS_VECTOR
+   is used to check if the data stored at its corresponding location is an
+   array notation. VAR is the induction variable passed in by the caller.
+
+   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, is_vector as true and count_down as false. 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<tree> > value,
+		   vec <vec<tree> > start, vec <vec<tree> > stride,
+		   vec <vec <bool> > is_vector, vec<tree> var,
+		   vec<vec<bool> > count_down, size_t size, size_t rank)
+{
+  enum tree_code code = PLUS_EXPR;
+  tree ind_mult, ind_incr;
+  vec<tree, va_gc> *array_operand = NULL;
+  for (size_t ii = 0; ii < size; ii++)
+    if (is_vector[ii][0])
+      {
+	tree array_opr = value[ii][rank-1];
+	for (int s_jj = rank -1; s_jj >= 0; s_jj--)
+	  {
+	    tree str = NULL_TREE, v = NULL_TREE, st = NULL_TREE;
+       
+	    /* 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[ii][s_jj]) == TREE_TYPE (stride[ii][s_jj])
+		&& TREE_TYPE (stride[ii][s_jj]) != TREE_TYPE (var[s_jj]))
+	      {
+		st = start[ii][s_jj];
+		str = stride[ii][s_jj];
+		v = build_c_cast (loc, TREE_TYPE (str), var[s_jj]);
+	      }
+	    else if (TREE_TYPE (start[ii][s_jj]) != TREE_TYPE (stride[ii][s_jj]))
+	      {
+		/* 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[ii][s_jj]);
+		str = build_c_cast (loc, integer_type_node, stride[ii][s_jj]);
+		v = build_c_cast (loc, integer_type_node, var[s_jj]);
+	      }
+	    else
+	      {
+		st = start[ii][s_jj];
+		str = stride[ii][s_jj];
+		v = var[s_jj];
+	      }
+
+	    if (count_down[ii][s_jj])
+	      code = MINUS_EXPR;
+	    else
+	      code = PLUS_EXPR;
+
+	    ind_mult = build2 (MULT_EXPR, TREE_TYPE (v), v, str);
+	    ind_incr = build2 (code, 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 vectors with the increment (of type POSTINCREMENT
+   or POSTDECREMENT) and comparison (of TYPE GT_EXPR or LT_EXPR) expressions,
+   using data from LENGTH, COUNT_DOWN, and VAR.  INCR and CMP vectors are of
+   size RANK.  */
+
+static void
+create_cmp_and_incr (location_t loc, vec <tree> var, vec<vec<tree> > length,
+		     vec <tree> *incr, vec <tree> *cmp,
+		     vec<vec<bool> > count_down, size_t rank,
+		     tsubst_flags_t complain)
+{
+  enum tree_code incr_code, comp_code;
+  cmp->safe_grow_cleared (rank);
+  incr->safe_grow_cleared (rank);
+  for (size_t ii = 0; ii < rank; ii++)
+    {
+      if (count_down[0][ii])
+	{
+	  incr_code = POSTDECREMENT_EXPR;
+	  comp_code = GT_EXPR;
+	}
+      else
+	{
+	  incr_code = POSTINCREMENT_EXPR;
+	  comp_code = LT_EXPR;
+	}
+      (*incr)[ii] = build_x_unary_op (loc, incr_code, var[ii], complain);
+      (*cmp)[ii] = build_x_binary_op (loc, comp_code, var[ii],
+				      TREE_CODE (var[ii]), length[0][ii],
+				      TREE_CODE (length[0][ii]), NULL, complain);
+    }
+}
+
+/* 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<tree> var,
+		       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, var[idx]);
+	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;
+}
+
+/* Clear (i.e. deallocate) all the temporary vectors required to expand
+   array notation expressions.  */
+
+static inline void
+clear_all_an_vectors (vec <vec<tree> > *value, vec<vec<tree> > *start,
+		      vec <vec<tree> > *length, vec<vec<tree> > *stride,
+		      vec<vec<bool> > *is_vector, vec<vec<bool> > *count_down,
+		      vec<tree> *incr, vec<tree> *cmp, vec<tree> *ind_init,
+		      vec<tree> *var)
+{
+  value->release ();
+  start->release ();
+  length->release ();
+  stride->release ();
+  is_vector->release ();
+  count_down->release ();
+  incr->release ();
+  cmp->release ();
+  ind_init->release ();
+  var->release ();
+}
+
+/* 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;
+  vec<tree> array_var = vNULL, expr_incr = vNULL, compare_expr = vNULL;
+  vec<tree> ind_init = vNULL;
+  vec<vec<tree> > array_value = vNULL, array_stride = vNULL,
+    array_length = vNULL, array_start = vNULL;
+  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;
+  vec<vec<bool> > count_down = vNULL, array_vector = vNULL;
+  tree init = NULL_TREE, cond_init = NULL_TREE;
+  enum tree_code code = NOP_EXPR;
+  location_t location = UNKNOWN_LOCATION;
+
+  enum built_in_function an_type =
+    is_cilkplus_reduce_builtin (CALL_EXPR_FN (an_builtin_fn));
+  
+  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!  */
+      while (TREE_CODE (call_fn) == CONVERT_EXPR
+	     || TREE_CODE (call_fn) == NOP_EXPR)
+	call_fn = TREE_OPERAND (call_fn, 0);
+
+      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);
+
+      /* 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!  */
+      while (TREE_CODE (identity_value) == CONVERT_EXPR
+	     || TREE_CODE (identity_value) == NOP_EXPR)
+	identity_value = TREE_OPERAND (identity_value, 0);
+    }
+  while (TREE_CODE (func_parm) == CONVERT_EXPR
+	 || TREE_CODE (func_parm) == NOP_EXPR)
+    func_parm = TREE_OPERAND (func_parm, 0);
+  
+  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);
+
+  ind_init.safe_grow_cleared (rank);
+  array_var.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);
+      }
+
+  extract_an_triplets (array_list, &array_value, &array_start, &array_length,
+		       &array_stride, &array_vector, &count_down, list_size,
+		       rank);
+  for (ii = 0; ii < rank; ii++)
+    {
+      array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
+				  TREE_TYPE (array_start[0][ii]));
+      ind_init[ii] = build_x_modify_expr
+	(location, array_var[ii], NOP_EXPR, 
+	 build_zero_cst (TREE_TYPE (array_var[ii])), tf_warning_or_error);
+    }
+  array_operand = create_array_refs (location, array_value, array_start,
+				     array_stride, array_vector, array_var,
+				     count_down, 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_and_incr (location, array_var, array_length, &expr_incr,
+		       &compare_expr, count_down, rank, 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 = ARITHMETIC_TYPE_P (new_var_type) ? build_zero_cst (new_var_type)
+	: integer_zero_node;
+      break;
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL:
+      code = MULT_EXPR;
+      init = ARITHMETIC_TYPE_P (new_var_type) ? build_one_cst (new_var_type)
+	: integer_one_node;
+      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 = !ARITHMETIC_TYPE_P (TREE_TYPE (func_parm)) ? integer_zero_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 = !ARITHMETIC_TYPE_P (TREE_TYPE (func_parm)) ? integer_zero_node
+	: build_zero_cst (TREE_TYPE (func_parm));
+      break;
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX:
+      code = LT_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 = GT_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 = array_var[0];
+    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);
+  if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ADD
+      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MUL)
+    new_expr = build_x_modify_expr (location, *new_var, code, func_parm,
+				    tf_warning_or_error);
+  if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO
+      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO
+      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO
+      || an_type == 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);
+    }
+  if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX
+      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN)
+    {
+      new_yes_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  func_parm, 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, *new_var, TREE_CODE (*new_var), func_parm,
+	 TREE_CODE (func_parm), 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);
+    }
+  if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
+      || an_type == 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,
+					   array_var[0], 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);
+    }
+  if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE
+      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
+    {
+      vec <tree, va_gc> *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);
+    }
+  
+  /* 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 (ind_init[ii]);
+ 
+  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 (ind_init[ii], compare_expr[ii], expr_incr[ii], body);
+      body = pop_stmt_list (new_loop);
+    }
+  append_to_statement_list_force (body, &loop_with_init);
+  clear_all_an_vectors (&array_value, &array_start, &array_length,
+			&array_stride, &array_vector, &count_down, &expr_incr,
+			&compare_expr, &ind_init, &array_var);
+  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> lhs_var = vNULL, rhs_var = vNULL;
+  vec<tree> cond_expr = vNULL;
+  vec<tree> lhs_expr_incr = vNULL, rhs_expr_incr = vNULL;
+  vec<tree> lhs_ind_init = vNULL, rhs_ind_init = vNULL;
+  vec<tree> lhs_compare = vNULL, rhs_compare = 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<tree> > lhs_value = vNULL, lhs_start = vNULL, lhs_length = vNULL;
+  vec <vec<tree> > lhs_stride = vNULL;
+  vec <vec<tree> > rhs_value = vNULL, rhs_start = vNULL, rhs_length = vNULL;
+  vec <vec<tree> > rhs_stride = vNULL;
+  vec <vec<bool> > lhs_count_down = vNULL, rhs_count_down = vNULL;
+  vec <vec<bool> > lhs_vector = vNULL, rhs_vector = 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_var.safe_grow_cleared (lhs_rank);
+  lhs_ind_init.safe_grow_cleared (lhs_rank);
+  if (rhs_rank)
+    {
+      rhs_var.safe_grow_cleared (rhs_rank);
+      rhs_ind_init.safe_grow_cleared (rhs_rank);
+    }
+  
+  cond_expr.safe_grow_cleared (MAX (lhs_rank, rhs_rank));
+
+  extract_an_triplets (lhs_list, &lhs_value, &lhs_start, &lhs_length,
+		       &lhs_stride, &lhs_vector, &lhs_count_down, lhs_list_size,
+		       lhs_rank);
+  if (rhs_list)
+    extract_an_triplets (rhs_list, &rhs_value, &rhs_start, &rhs_length,
+			 &rhs_stride, &rhs_vector, &rhs_count_down,
+			 rhs_list_size, rhs_rank);
+
+  if (cp_length_mismatch_in_expr_p (EXPR_LOCATION (lhs), lhs_length)
+      || (rhs_list && cp_length_mismatch_in_expr_p (EXPR_LOCATION (rhs),
+						    rhs_length)))
+    {
+      pop_stmt_list (an_init);
+      return error_mark_node;
+    }
+  if (lhs_list_size > 0 && rhs_list_size > 0 && lhs_rank > 0 && rhs_rank > 0
+      && TREE_CODE (lhs_length[0][0]) == INTEGER_CST
+      && rhs_length[0][0] && TREE_CODE (rhs_length[0][0]) == INTEGER_CST)
+    {
+      HOST_WIDE_INT l_length = int_cst_value (lhs_length[0][0]);
+      HOST_WIDE_INT r_length = int_cst_value (rhs_length[0][0]);
+      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_start[0][ii] && TREE_TYPE (lhs_start[0][ii]))
+	lhs_var[ii] =  build_decl (location, VAR_DECL, NULL_TREE,
+				   TREE_TYPE (lhs_start[0][ii]));
+    else
+      lhs_var[ii] = 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_var,
+						  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_vector[0][ii])
+      {
+	lhs_ind_init[ii] = build_x_modify_expr
+	  (location, lhs_var[ii], NOP_EXPR,
+	   build_zero_cst (TREE_TYPE (lhs_var[ii])), complain);
+      }
+  for (ii = 0; ii < rhs_rank; ii++)
+    {
+      /* When we have a polynomial, we assume that the indices are of type
+	 integer.  */
+      rhs_var[ii] =  build_decl (location, VAR_DECL, NULL_TREE,
+				 TREE_TYPE (rhs_start[0][ii]));
+      rhs_ind_init[ii] = build_x_modify_expr
+	(location, rhs_var[ii], NOP_EXPR, 
+	 build_zero_cst (TREE_TYPE (rhs_var[ii])), complain);
+    }
+
+  if (lhs_rank)
+    {
+      lhs_array_operand = create_array_refs (location, lhs_value, lhs_start,
+					     lhs_stride, lhs_vector, lhs_var,
+					     lhs_count_down, 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_value, rhs_start,
+					     rhs_stride, rhs_vector, rhs_var,
+					     rhs_count_down, 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_var,
+						 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_and_incr (location, lhs_var, lhs_length, &lhs_expr_incr,
+		       &lhs_compare, lhs_count_down, lhs_rank, complain);
+  if (rhs_rank)
+    create_cmp_and_incr (location, rhs_var, rhs_length, &rhs_expr_incr,
+			 &rhs_compare, rhs_count_down, rhs_rank, 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_compare[ii],
+	 TREE_CODE (lhs_compare[ii]), rhs_compare[ii],
+	 TREE_CODE (rhs_compare[ii]), NULL, complain);
+    else if (ii < lhs_rank && ii >= rhs_rank)
+      cond_expr[ii] = lhs_compare[ii];
+    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_ind_init[ii], &init_list);
+	  append_to_statement_list_force (lhs_expr_incr[ii], &incr_list);
+	}
+      if (rhs_rank)
+	{
+	  append_to_statement_list_force (rhs_ind_init[ii], &init_list);
+	  append_to_statement_list_force (rhs_expr_incr[ii], &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);
+  
+  clear_all_an_vectors (&lhs_value, &lhs_start, &lhs_length, &lhs_stride,
+			&lhs_vector, &lhs_count_down, &lhs_expr_incr,
+			&lhs_compare, &lhs_ind_init, &lhs_var);
+  if (rhs_rank)
+    clear_all_an_vectors (&rhs_value, &rhs_start, &rhs_length, &rhs_stride,
+			  &rhs_vector, &rhs_count_down, &rhs_expr_incr,
+			  &rhs_compare, &rhs_ind_init, &rhs_var);
+  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;
+  vec<vec<tree> > array_value = vNULL, array_stride = vNULL;
+  vec<vec<tree> >  array_length = vNULL, array_start = vNULL;
+  vec<tree> compare_expr = vNULL, array_var = vNULL, expr_incr = vNULL;
+  vec<tree> ind_init = vNULL;
+  tree builtin_loop, new_var = NULL_TREE;
+  vec<vec<bool> > count_down = vNULL, array_vector = vNULL;
+  tree loop_with_init = alloc_stmt_list ();
+  tsubst_flags_t complain = tf_warning_or_error;
+  location_t location = UNKNOWN_LOCATION;
+
+  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);
+
+  compare_expr.safe_grow_cleared (rank);
+  expr_incr.safe_grow_cleared (rank);
+  expr_incr.safe_grow_cleared (rank);
+  array_var.safe_grow_cleared (rank);
+  ind_init.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);
+    }
+
+  extract_an_triplets (array_list, &array_value, &array_start, &array_length,
+		       &array_stride, &array_vector, &count_down, list_size,
+		       rank);
+  for (ii = 0; ii < rank; ii++)
+    {
+      if (TREE_TYPE (array_start[0][ii])
+	  && TREE_CODE (TREE_TYPE (array_start[0][ii])) != TEMPLATE_TYPE_PARM)
+	{
+	  array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
+				      TREE_TYPE (array_start[0][ii]));
+	  ind_init[ii] = build_x_modify_expr
+	    (location, array_var[ii], NOP_EXPR, 
+	     build_zero_cst (TREE_TYPE (array_var[ii])), tf_warning_or_error);
+	}
+      else
+	{
+	  array_var[ii] = build_min_nt_loc (location, VAR_DECL,
+					    NULL_TREE, NULL_TREE);
+	  ind_init[ii] = build_x_modify_expr (location, array_var[ii], 
+					      NOP_EXPR,
+					      integer_zero_node, 1);
+	}
+    }
+  array_operand = create_array_refs (location, array_value, array_start,
+				     array_stride, array_vector, array_var,
+				     count_down, list_size, rank);
+  replace_array_notations (&stmt, true, array_list, array_operand);
+
+  create_cmp_and_incr (location, array_var, array_length, &expr_incr,
+		       &compare_expr, count_down, rank, complain);
+  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 (ind_init[ii], compare_expr[ii], expr_incr[ii], body);
+      body = pop_stmt_list (new_loop);
+    }
+  append_to_statement_list_force (body, &loop_with_init);
+  clear_all_an_vectors (&array_value, &array_start, &array_length,
+			&array_stride, &array_vector, &count_down, &expr_incr,
+			&compare_expr, &ind_init, &array_var);
+  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<tree> > array_value = vNULL, array_stride = vNULL;
+  vec<tree> ind_init = vNULL;
+  vec<vec<tree> >  array_length = vNULL, array_start = vNULL;
+  vec<tree> compare_expr = vNULL, array_var = vNULL, expr_incr = vNULL;
+  vec<vec<bool> > count_down = vNULL, array_vector = 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++)
+    {
+      tree list_node = (*array_list)[ii];
+      if (TREE_CODE (list_node) == CALL_EXPR
+	  || TREE_CODE (list_node) == AGGR_INIT_EXPR)
+	{
+	  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;
+
+  compare_expr.safe_grow_cleared (rank);
+  expr_incr.safe_grow_cleared (rank);
+  expr_incr.safe_grow_cleared (rank);
+  array_var.safe_grow_cleared (rank);
+  ind_init.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);
+    }
+  extract_an_triplets (array_list, &array_value, &array_start, &array_length,
+		       &array_stride, &array_vector, &count_down, list_size,
+		       rank);
+  for (ii = 0; ii < rank; ii++)
+    {
+      array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
+				  TREE_TYPE (array_start[0][ii]));
+      ind_init[ii] = build_x_modify_expr
+	(location, array_var[ii], NOP_EXPR, 
+	 build_zero_cst (TREE_TYPE (array_var[ii])), tf_warning_or_error);
+    }
+  array_operand = create_array_refs (location, array_value, array_start,
+				     array_stride, array_vector, array_var,
+				     count_down, list_size, rank);
+  replace_array_notations (&stmt, true, array_list, array_operand);
+  create_cmp_and_incr (location, array_var, array_length, &expr_incr,
+		       &compare_expr, count_down, rank, 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 (ind_init[ii], compare_expr[ii], expr_incr[ii], body);
+      body = pop_stmt_list (new_loop);
+    }
+  append_to_statement_list_force (body, &loop_with_init);
+  clear_all_an_vectors (&array_value, &array_start, &array_length,
+			&array_stride, &array_vector, &count_down, &expr_incr,
+			&compare_expr, &ind_init, &array_var);
+  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;
+  location_t loc = EXPR_LOCATION (expr);
+
+  if (TREE_CODE (expr) != RETURN_EXPR)
+    return 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;
+  
+  /* Skip empty subtrees.  */
+  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;
+}
diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c
index bccd884..d301db0 100644
--- a/gcc/cp/cp-objcp-common.c
+++ b/gcc/cp/cp-objcp-common.c
@@ -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"
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 2931ac5..76727ad 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6121,6 +6121,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 */
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
old mode 100644
new mode 100755
index a75fc4e..a8f52cd
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -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;
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
old mode 100644
new mode 100755
index d844d15..7bc9334
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -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;
@@ -10102,6 +10313,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;
 
@@ -10128,6 +10345,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;
 
@@ -10146,8 +10372,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;
 
@@ -16722,30 +16957,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
@@ -18116,6 +18374,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);
 
@@ -22095,6 +22358,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));
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
old mode 100644
new mode 100755
index 3602fcd..0a7d523
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -13740,6 +13740,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));
@@ -15712,6 +15726,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;
@@ -19119,6 +19136,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);
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 0a700b7..f27a70d 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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 notatinos, 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:
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 8524f6c..dd2fda4 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -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;
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
old mode 100644
new mode 100755
index 11ac85b..17f19c7
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
old mode 100644
new mode 100755
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c
index d17d8cf..579d396 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c
@@ -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;
 
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
index 35eb115..14421d9 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
@@ -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;
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c
old mode 100644
new mode 100755
index a0a3742..18816e0
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c
@@ -8,4 +8,4 @@ int main (void)
   array2[:] = array2[: ;  /* { dg-error "expected ']'" } */
 
   return 0;
-} /* { dg-error "expected ';' before" } */
+} /* { dg-error "expected ';' before" "" { target c } } */
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c
index 2e86b4f..4314090 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c
@@ -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 }  } */
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c
index 34dfa16..47b5979 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c
@@ -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 } } */
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c
index eba28a8..a0efc04 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c
@@ -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;
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c
index cabdb23..4c80c42 100755
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c
@@ -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 }  7 } */
 
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c
index 843745e..3b0777e 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c
@@ -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
index 0000000..e9ee7ec
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/array_test1_tplt.cc
@@ -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
index 0000000..87c37e1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/array_test2_tplt.cc
@@ -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
index 0000000..479ba13
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/array_test_ND_tplt.cc
@@ -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 100755
index 0000000..b91de7a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/braced_list.cc
@@ -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
index 0000000..3d9e87b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_custom_tplt.cc
@@ -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
index 0000000..db81912
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_mutating_tplt.cc
@@ -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
index 0000000..1387558
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/fp_triplet_values_tplt.c
@@ -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
index 0000000..b0952c7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/postincr_test.cc
@@ -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
index 0000000..f5552c7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/preincr_test.cc
@@ -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
index 0000000..a153529
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp
@@ -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
diff --git a/gcc/testsuite/g++.dg/dg.exp b/gcc/testsuite/g++.dg/dg.exp
old mode 100644
new mode 100755
index 7201359..710218e
--- a/gcc/testsuite/g++.dg/dg.exp
+++ b/gcc/testsuite/g++.dg/dg.exp
@@ -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/*]

^ permalink raw reply	[flat|nested] 40+ messages in thread

* RE: [PATCH] Cilk Plus Array Notation for C++
  2013-06-13 16:18       ` Richard Henderson
@ 2013-06-17 17:00         ` Iyer, Balaji V
  2013-06-17 17:06           ` Richard Henderson
  0 siblings, 1 reply; 40+ messages in thread
From: Iyer, Balaji V @ 2013-06-17 17:00 UTC (permalink / raw)
  To: Richard Henderson, Aldy Hernandez
  Cc: gcc-patches, Jason Merrill (jason@redhat.com)



> -----Original Message-----
> From: gcc-patches-owner@gcc.gnu.org [mailto:gcc-patches-
> owner@gcc.gnu.org] On Behalf Of Richard Henderson
> Sent: Thursday, June 13, 2013 12:19 PM
> To: Aldy Hernandez
> Cc: Iyer, Balaji V; gcc-patches@gcc.gnu.org; Jason Merrill (jason@redhat.com)
> Subject: Re: [PATCH] Cilk Plus Array Notation for C++
> 
> On 06/13/2013 09:11 AM, Aldy Hernandez wrote:
> > The whole slew of these cases have a lot of duplicated code.  For
> > instance, BUILT_IN_CILKPLUS_SEC_REDUCE_MIN is the same as
> > BUILT_IN_CILKPLUS_SEC_REDUCE_MAX, the only difference being GT_EXPR
> vs
> > LT_EXPR.  Surely you could do something like:
> >
> > if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN
> >     || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX) {
> >    enum tree_code code;
> >    if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN)
> >      code = GT_EXPR;
> >    else
> >      code = LT_EXPR;
> >    // stuff
> > }
> >
> > The compiler should be able to optimize the above, but even if it
> > couldn't, I am willing to compare twice and save lines and lines of code.
> >
> > Similarly for SEC_REDUCE_ANY_ZERO/SEC_REDUCE_ANY_NONZERO,
> > SEC_REDUCE_ALL_ZERO/SEC_REDUCE_ALL_NONZERO,
> > SEC_REDUCE_ADD/SEC_REDUCE_MUL, etc etc etc.
> 
> Yep.  It's at this point that I normally start using the idiom
> 
> 	switch (an_type)
> 	  {
> 	  case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN:
> 	    code = GT_EXPR;
> 	    goto do_min_max;
> 	  case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX:
> 	    code = LT_EXPR;
> 	    goto do_min_max;
> 	  do_min_max:
> 	    // stuff
> 
> So much the better if you can include the other SEC_* cases in that switch too,
> doing one compiler-controlled dispatch.

I didn't use goto, but I did try to abstract out the common parts and either tried to lump them together in the same case or  put them outside of the case. The new patch is here: http://gcc.gnu.org/ml/gcc-patches/2013-06/msg00984.html

> 
> It also occurs to me to wonder why you're building your own COND_EXPR here,
> with the comparison, rather than using MIN/MAX_EXPR...

In hindsight, I could have for __sec_reduce_max and __sec_reduce_min. I was more familiar with conditional expression. Out of curiosity, is there a big performance benefit of using max/min expr over conditional?


Thanks,

Balaji V. Iyer.

> 
> 
> r~

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH] Cilk Plus Array Notation for C++
  2013-06-17 17:00         ` Iyer, Balaji V
@ 2013-06-17 17:06           ` Richard Henderson
  2013-06-17 18:29             ` Iyer, Balaji V
  0 siblings, 1 reply; 40+ messages in thread
From: Richard Henderson @ 2013-06-17 17:06 UTC (permalink / raw)
  To: Iyer, Balaji V
  Cc: Aldy Hernandez, gcc-patches, Jason Merrill (jason@redhat.com)

On 06/17/2013 10:00 AM, Iyer, Balaji V wrote:
> In hindsight, I could have for __sec_reduce_max and __sec_reduce_min. I was
> more familiar with conditional expression. Out of curiosity, is there a big
> performance benefit of using max/min expr over conditional?

There can be.  The COND->MIN/MAX transformation is not done without the
-ffinite-math-only component of -ffast-math.  I.e. we don't try the transform
when NaNs are a possibility.

So, yes, you probably should generate MIN/MAX_EXPR right from the start.


r~

^ permalink raw reply	[flat|nested] 40+ messages in thread

* RE: [PATCH] Cilk Plus Array Notation for C++
  2013-06-17 17:06           ` Richard Henderson
@ 2013-06-17 18:29             ` Iyer, Balaji V
  2013-06-18 23:42               ` Aldy Hernandez
  0 siblings, 1 reply; 40+ messages in thread
From: Iyer, Balaji V @ 2013-06-17 18:29 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Aldy Hernandez, gcc-patches, Jason Merrill (jason@redhat.com)

[-- Attachment #1: Type: text/plain, Size: 4831 bytes --]


> > In hindsight, I could have for __sec_reduce_max and __sec_reduce_min.
> > I was more familiar with conditional expression. Out of curiosity, is
> > there a big performance benefit of using max/min expr over conditional?
> 
> There can be.  The COND->MIN/MAX transformation is not done without the -
> ffinite-math-only component of -ffast-math.  I.e. we don't try the transform
> when NaNs are a possibility.
> 
> So, yes, you probably should generate MIN/MAX_EXPR right from the start.

Hi Richard et al.,
	Here is a fixed patch using MIN_EXPR and MAX_EXPR instead of conditionals. Here are the ChangeLog entries (there should be no changes from the previous thread). Is this OK for trunk?

gcc/cp/ChangeLog
2013-06-17  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-17  Balaji V. Iyer  <balaji.v.iyer@intel.com>

        * 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++ parser 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.

Thanks,

Balaji V. Iyer.

> 
> 
> r~

[-- Attachment #2: patch_array_notation_cpp.txt --]
[-- Type: text/plain, Size: 126274 bytes --]

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
old mode 100644
new mode 100755
index 1b58ba0..0b11a75
Binary files a/gcc/cp/ChangeLog and b/gcc/cp/ChangeLog differ
diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
index df8ed3e..6e80bcf 100644
--- a/gcc/cp/Make-lang.in
+++ b/gcc/cp/Make-lang.in
@@ -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)
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index dfd061a..64be41f 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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 100755
index 0000000..da701e7
--- /dev/null
+++ b/gcc/cp/cp-array-notation.c
@@ -0,0 +1,1740 @@
+/* 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) is passed in as a 2D vector of trees.  */
+
+static bool
+cp_length_mismatch_in_expr_p (location_t loc, vec<vec<tree> >list)
+{
+  size_t ii, jj;
+  tree start = NULL_TREE;
+  HOST_WIDE_INT l_start, l_node;
+
+  size_t x = list.length ();
+  size_t y = list[0].length ();
+  
+  for (jj = 0; jj < y; jj++)
+    {
+      start = NULL_TREE;
+      for (ii = 0; ii < x; ii++)
+	{
+	  if (!start)
+	    start = list[ii][jj];
+	  else if (TREE_CODE (start) == INTEGER_CST)
+	    {
+	      /* If start 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]) == INTEGER_CST)
+		{
+		  l_node = int_cst_value (list[ii][jj]);
+		  l_start = int_cst_value (start);
+		  if (absu_hwi (l_start) != absu_hwi (l_node))
+		    {
+		      error_at (loc, "length mismatch in expression");
+		      return true;
+		    }
+		}
+	    }
+	  else
+	    /* We set the start node as the current node just in case it turns
+	       out to be an integer.  */
+	    start = list[ii][jj];
+	}
+    }
+  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;
+    }
+}
+
+/* Extracts all the array notation triplet information from LIST and stores them
+   in a 2-D arrays (size x rank) of START, LENGTH and STRIDE, holding the
+   starting index, length, and stride, respectively.  In addition, it also
+   sets two bool arrays IS_VECTOR and COUNT_DOWN indicating whether a certain
+   value at a certain field is a vector or not.  */
+
+static inline void
+extract_an_triplets (vec <tree, va_gc> *list, vec <vec<tree> > *value,
+		     vec <vec<tree> > *start, vec <vec<tree> > *length,
+		     vec <vec<tree> > *stride, vec <vec <bool> > *is_vector,
+		     vec<vec<bool> > *count_down, size_t size, size_t rank)
+{
+  vec<vec<tree> > array_exprs = vNULL;
+
+  start->safe_grow_cleared (size);
+  length->safe_grow_cleared (size);
+  stride->safe_grow_cleared (size);
+  value->safe_grow_cleared (size);
+  array_exprs.safe_grow_cleared (size);
+  is_vector->safe_grow_cleared (size);
+  count_down->safe_grow_cleared (size);
+
+  for (size_t ii = 0; ii < size; ii++)
+    for (size_t jj = 0; jj < rank; jj++)
+      {
+	array_exprs[ii].safe_push (NULL_TREE);
+	(*start)[ii].safe_push (NULL_TREE);
+	(*value)[ii].safe_push (NULL_TREE);
+	(*length)[ii].safe_push (NULL_TREE);
+	(*stride)[ii].safe_push (NULL_TREE);
+	(*is_vector)[ii].safe_push (false);
+	(*count_down)[ii].safe_push (false);
+      }
+  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];
+	    (*is_vector)[ii][jj] = true;
+	    (*value)[ii][jj] = ARRAY_NOTATION_ARRAY (ii_tree);
+	    (*start)[ii][jj] = ARRAY_NOTATION_START (ii_tree);
+	    (*length)[ii][jj] = fold_build1 (CONVERT_EXPR, integer_type_node,
+					     ARRAY_NOTATION_LENGTH (ii_tree));
+	    (*stride)[ii][jj] = fold_build1 (CONVERT_EXPR, integer_type_node,
+					     ARRAY_NOTATION_STRIDE (ii_tree));
+	  }
+}
+
+/* Returns a vector of size RANK that contains an array ref that is derived from
+   array notation triplet parameters stored in VALUE, START, STRIDE.  IS_VECTOR
+   is used to check if the data stored at its corresponding location is an
+   array notation. VAR is the induction variable passed in by the caller.
+
+   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, is_vector as true and count_down as false. 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<tree> > value,
+		   vec <vec<tree> > start, vec <vec<tree> > stride,
+		   vec <vec <bool> > is_vector, vec<tree> var,
+		   vec<vec<bool> > count_down, size_t size, size_t rank)
+{
+  enum tree_code code = PLUS_EXPR;
+  tree ind_mult, ind_incr;
+  vec<tree, va_gc> *array_operand = NULL;
+  for (size_t ii = 0; ii < size; ii++)
+    if (is_vector[ii][0])
+      {
+	tree array_opr = value[ii][rank-1];
+	for (int s_jj = rank -1; s_jj >= 0; s_jj--)
+	  {
+	    tree str = NULL_TREE, v = NULL_TREE, st = NULL_TREE;
+       
+	    /* 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[ii][s_jj]) == TREE_TYPE (stride[ii][s_jj])
+		&& TREE_TYPE (stride[ii][s_jj]) != TREE_TYPE (var[s_jj]))
+	      {
+		st = start[ii][s_jj];
+		str = stride[ii][s_jj];
+		v = build_c_cast (loc, TREE_TYPE (str), var[s_jj]);
+	      }
+	    else if (TREE_TYPE (start[ii][s_jj]) != TREE_TYPE (stride[ii][s_jj]))
+	      {
+		/* 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[ii][s_jj]);
+		str = build_c_cast (loc, integer_type_node, stride[ii][s_jj]);
+		v = build_c_cast (loc, integer_type_node, var[s_jj]);
+	      }
+	    else
+	      {
+		st = start[ii][s_jj];
+		str = stride[ii][s_jj];
+		v = var[s_jj];
+	      }
+
+	    if (count_down[ii][s_jj])
+	      code = MINUS_EXPR;
+	    else
+	      code = PLUS_EXPR;
+
+	    ind_mult = build2 (MULT_EXPR, TREE_TYPE (v), v, str);
+	    ind_incr = build2 (code, 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 vectors with the increment (of type POSTINCREMENT
+   or POSTDECREMENT) and comparison (of TYPE GT_EXPR or LT_EXPR) expressions,
+   using data from LENGTH, COUNT_DOWN, and VAR.  INCR and CMP vectors are of
+   size RANK.  */
+
+static void
+create_cmp_and_incr (location_t loc, vec <tree> var, vec<vec<tree> > length,
+		     vec <tree> *incr, vec <tree> *cmp,
+		     vec<vec<bool> > count_down, size_t rank,
+		     tsubst_flags_t complain)
+{
+  enum tree_code incr_code, comp_code;
+  cmp->safe_grow_cleared (rank);
+  incr->safe_grow_cleared (rank);
+  for (size_t ii = 0; ii < rank; ii++)
+    {
+      if (count_down[0][ii])
+	{
+	  incr_code = POSTDECREMENT_EXPR;
+	  comp_code = GT_EXPR;
+	}
+      else
+	{
+	  incr_code = POSTINCREMENT_EXPR;
+	  comp_code = LT_EXPR;
+	}
+      (*incr)[ii] = build_x_unary_op (loc, incr_code, var[ii], complain);
+      (*cmp)[ii] = build_x_binary_op (loc, comp_code, var[ii],
+				      TREE_CODE (var[ii]), length[0][ii],
+				      TREE_CODE (length[0][ii]), NULL, complain);
+    }
+}
+
+/* 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<tree> var,
+		       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, var[idx]);
+	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;
+}
+
+/* Clear (i.e. deallocate) all the temporary vectors required to expand
+   array notation expressions.  */
+
+static inline void
+clear_all_an_vectors (vec <vec<tree> > *value, vec<vec<tree> > *start,
+		      vec <vec<tree> > *length, vec<vec<tree> > *stride,
+		      vec<vec<bool> > *is_vector, vec<vec<bool> > *count_down,
+		      vec<tree> *incr, vec<tree> *cmp, vec<tree> *ind_init,
+		      vec<tree> *var)
+{
+  value->release ();
+  start->release ();
+  length->release ();
+  stride->release ();
+  is_vector->release ();
+  count_down->release ();
+  incr->release ();
+  cmp->release ();
+  ind_init->release ();
+  var->release ();
+}
+
+/* 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;
+  vec<tree> array_var = vNULL, expr_incr = vNULL, compare_expr = vNULL;
+  vec<tree> ind_init = vNULL;
+  vec<vec<tree> > array_value = vNULL, array_stride = vNULL,
+    array_length = vNULL, array_start = vNULL;
+  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;
+  vec<vec<bool> > count_down = vNULL, array_vector = vNULL;
+  tree init = NULL_TREE, cond_init = NULL_TREE;
+  enum tree_code code = NOP_EXPR;
+  location_t location = UNKNOWN_LOCATION;
+
+  enum built_in_function an_type =
+    is_cilkplus_reduce_builtin (CALL_EXPR_FN (an_builtin_fn));
+  
+  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!  */
+      while (TREE_CODE (call_fn) == CONVERT_EXPR
+	     || TREE_CODE (call_fn) == NOP_EXPR)
+	call_fn = TREE_OPERAND (call_fn, 0);
+
+      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);
+
+      /* 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!  */
+      while (TREE_CODE (identity_value) == CONVERT_EXPR
+	     || TREE_CODE (identity_value) == NOP_EXPR)
+	identity_value = TREE_OPERAND (identity_value, 0);
+    }
+  while (TREE_CODE (func_parm) == CONVERT_EXPR
+	 || TREE_CODE (func_parm) == NOP_EXPR)
+    func_parm = TREE_OPERAND (func_parm, 0);
+  
+  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);
+
+  ind_init.safe_grow_cleared (rank);
+  array_var.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);
+      }
+
+  extract_an_triplets (array_list, &array_value, &array_start, &array_length,
+		       &array_stride, &array_vector, &count_down, list_size,
+		       rank);
+  for (ii = 0; ii < rank; ii++)
+    {
+      array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
+				  TREE_TYPE (array_start[0][ii]));
+      ind_init[ii] = build_x_modify_expr
+	(location, array_var[ii], NOP_EXPR, 
+	 build_zero_cst (TREE_TYPE (array_var[ii])), tf_warning_or_error);
+    }
+  array_operand = create_array_refs (location, array_value, array_start,
+				     array_stride, array_vector, array_var,
+				     count_down, 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_and_incr (location, array_var, array_length, &expr_incr,
+		       &compare_expr, count_down, rank, 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 = ARITHMETIC_TYPE_P (new_var_type) ? build_zero_cst (new_var_type)
+	: integer_zero_node;
+      break;
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL:
+      code = MULT_EXPR;
+      init = ARITHMETIC_TYPE_P (new_var_type) ? build_one_cst (new_var_type)
+	: integer_one_node;
+      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 = !ARITHMETIC_TYPE_P (TREE_TYPE (func_parm)) ? integer_zero_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 = !ARITHMETIC_TYPE_P (TREE_TYPE (func_parm)) ? integer_zero_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 = array_var[0];
+    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);
+  if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ADD
+      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MUL)
+    new_expr = build_x_modify_expr (location, *new_var, code, func_parm,
+				    tf_warning_or_error);
+  if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO
+      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO
+      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO
+      || an_type == 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);
+    }
+  if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX
+      || an_type == 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);
+    }
+  if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
+      || an_type == 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,
+					   array_var[0], 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);
+    }
+  if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE
+      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
+    {
+      vec <tree, va_gc> *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);
+    }
+  
+  /* 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 (ind_init[ii]);
+ 
+  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 (ind_init[ii], compare_expr[ii], expr_incr[ii], body);
+      body = pop_stmt_list (new_loop);
+    }
+  append_to_statement_list_force (body, &loop_with_init);
+  clear_all_an_vectors (&array_value, &array_start, &array_length,
+			&array_stride, &array_vector, &count_down, &expr_incr,
+			&compare_expr, &ind_init, &array_var);
+  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> lhs_var = vNULL, rhs_var = vNULL;
+  vec<tree> cond_expr = vNULL;
+  vec<tree> lhs_expr_incr = vNULL, rhs_expr_incr = vNULL;
+  vec<tree> lhs_ind_init = vNULL, rhs_ind_init = vNULL;
+  vec<tree> lhs_compare = vNULL, rhs_compare = 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<tree> > lhs_value = vNULL, lhs_start = vNULL, lhs_length = vNULL;
+  vec <vec<tree> > lhs_stride = vNULL;
+  vec <vec<tree> > rhs_value = vNULL, rhs_start = vNULL, rhs_length = vNULL;
+  vec <vec<tree> > rhs_stride = vNULL;
+  vec <vec<bool> > lhs_count_down = vNULL, rhs_count_down = vNULL;
+  vec <vec<bool> > lhs_vector = vNULL, rhs_vector = 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_var.safe_grow_cleared (lhs_rank);
+  lhs_ind_init.safe_grow_cleared (lhs_rank);
+  if (rhs_rank)
+    {
+      rhs_var.safe_grow_cleared (rhs_rank);
+      rhs_ind_init.safe_grow_cleared (rhs_rank);
+    }
+  
+  cond_expr.safe_grow_cleared (MAX (lhs_rank, rhs_rank));
+
+  extract_an_triplets (lhs_list, &lhs_value, &lhs_start, &lhs_length,
+		       &lhs_stride, &lhs_vector, &lhs_count_down, lhs_list_size,
+		       lhs_rank);
+  if (rhs_list)
+    extract_an_triplets (rhs_list, &rhs_value, &rhs_start, &rhs_length,
+			 &rhs_stride, &rhs_vector, &rhs_count_down,
+			 rhs_list_size, rhs_rank);
+
+  if (cp_length_mismatch_in_expr_p (EXPR_LOCATION (lhs), lhs_length)
+      || (rhs_list && cp_length_mismatch_in_expr_p (EXPR_LOCATION (rhs),
+						    rhs_length)))
+    {
+      pop_stmt_list (an_init);
+      return error_mark_node;
+    }
+  if (lhs_list_size > 0 && rhs_list_size > 0 && lhs_rank > 0 && rhs_rank > 0
+      && TREE_CODE (lhs_length[0][0]) == INTEGER_CST
+      && rhs_length[0][0] && TREE_CODE (rhs_length[0][0]) == INTEGER_CST)
+    {
+      HOST_WIDE_INT l_length = int_cst_value (lhs_length[0][0]);
+      HOST_WIDE_INT r_length = int_cst_value (rhs_length[0][0]);
+      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_start[0][ii] && TREE_TYPE (lhs_start[0][ii]))
+	lhs_var[ii] =  build_decl (location, VAR_DECL, NULL_TREE,
+				   TREE_TYPE (lhs_start[0][ii]));
+    else
+      lhs_var[ii] = 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_var,
+						  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_vector[0][ii])
+      {
+	lhs_ind_init[ii] = build_x_modify_expr
+	  (location, lhs_var[ii], NOP_EXPR,
+	   build_zero_cst (TREE_TYPE (lhs_var[ii])), complain);
+      }
+  for (ii = 0; ii < rhs_rank; ii++)
+    {
+      /* When we have a polynomial, we assume that the indices are of type
+	 integer.  */
+      rhs_var[ii] =  build_decl (location, VAR_DECL, NULL_TREE,
+				 TREE_TYPE (rhs_start[0][ii]));
+      rhs_ind_init[ii] = build_x_modify_expr
+	(location, rhs_var[ii], NOP_EXPR, 
+	 build_zero_cst (TREE_TYPE (rhs_var[ii])), complain);
+    }
+
+  if (lhs_rank)
+    {
+      lhs_array_operand = create_array_refs (location, lhs_value, lhs_start,
+					     lhs_stride, lhs_vector, lhs_var,
+					     lhs_count_down, 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_value, rhs_start,
+					     rhs_stride, rhs_vector, rhs_var,
+					     rhs_count_down, 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_var,
+						 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_and_incr (location, lhs_var, lhs_length, &lhs_expr_incr,
+		       &lhs_compare, lhs_count_down, lhs_rank, complain);
+  if (rhs_rank)
+    create_cmp_and_incr (location, rhs_var, rhs_length, &rhs_expr_incr,
+			 &rhs_compare, rhs_count_down, rhs_rank, 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_compare[ii],
+	 TREE_CODE (lhs_compare[ii]), rhs_compare[ii],
+	 TREE_CODE (rhs_compare[ii]), NULL, complain);
+    else if (ii < lhs_rank && ii >= rhs_rank)
+      cond_expr[ii] = lhs_compare[ii];
+    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_ind_init[ii], &init_list);
+	  append_to_statement_list_force (lhs_expr_incr[ii], &incr_list);
+	}
+      if (rhs_rank)
+	{
+	  append_to_statement_list_force (rhs_ind_init[ii], &init_list);
+	  append_to_statement_list_force (rhs_expr_incr[ii], &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);
+  
+  clear_all_an_vectors (&lhs_value, &lhs_start, &lhs_length, &lhs_stride,
+			&lhs_vector, &lhs_count_down, &lhs_expr_incr,
+			&lhs_compare, &lhs_ind_init, &lhs_var);
+  if (rhs_rank)
+    clear_all_an_vectors (&rhs_value, &rhs_start, &rhs_length, &rhs_stride,
+			  &rhs_vector, &rhs_count_down, &rhs_expr_incr,
+			  &rhs_compare, &rhs_ind_init, &rhs_var);
+  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;
+  vec<vec<tree> > array_value = vNULL, array_stride = vNULL;
+  vec<vec<tree> >  array_length = vNULL, array_start = vNULL;
+  vec<tree> compare_expr = vNULL, array_var = vNULL, expr_incr = vNULL;
+  vec<tree> ind_init = vNULL;
+  tree builtin_loop, new_var = NULL_TREE;
+  vec<vec<bool> > count_down = vNULL, array_vector = vNULL;
+  tree loop_with_init = alloc_stmt_list ();
+  tsubst_flags_t complain = tf_warning_or_error;
+  location_t location = UNKNOWN_LOCATION;
+
+  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);
+
+  compare_expr.safe_grow_cleared (rank);
+  expr_incr.safe_grow_cleared (rank);
+  expr_incr.safe_grow_cleared (rank);
+  array_var.safe_grow_cleared (rank);
+  ind_init.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);
+    }
+
+  extract_an_triplets (array_list, &array_value, &array_start, &array_length,
+		       &array_stride, &array_vector, &count_down, list_size,
+		       rank);
+  for (ii = 0; ii < rank; ii++)
+    {
+      if (TREE_TYPE (array_start[0][ii])
+	  && TREE_CODE (TREE_TYPE (array_start[0][ii])) != TEMPLATE_TYPE_PARM)
+	{
+	  array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
+				      TREE_TYPE (array_start[0][ii]));
+	  ind_init[ii] = build_x_modify_expr
+	    (location, array_var[ii], NOP_EXPR, 
+	     build_zero_cst (TREE_TYPE (array_var[ii])), tf_warning_or_error);
+	}
+      else
+	{
+	  array_var[ii] = build_min_nt_loc (location, VAR_DECL,
+					    NULL_TREE, NULL_TREE);
+	  ind_init[ii] = build_x_modify_expr (location, array_var[ii], 
+					      NOP_EXPR,
+					      integer_zero_node, 1);
+	}
+    }
+  array_operand = create_array_refs (location, array_value, array_start,
+				     array_stride, array_vector, array_var,
+				     count_down, list_size, rank);
+  replace_array_notations (&stmt, true, array_list, array_operand);
+
+  create_cmp_and_incr (location, array_var, array_length, &expr_incr,
+		       &compare_expr, count_down, rank, complain);
+  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 (ind_init[ii], compare_expr[ii], expr_incr[ii], body);
+      body = pop_stmt_list (new_loop);
+    }
+  append_to_statement_list_force (body, &loop_with_init);
+  clear_all_an_vectors (&array_value, &array_start, &array_length,
+			&array_stride, &array_vector, &count_down, &expr_incr,
+			&compare_expr, &ind_init, &array_var);
+  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<tree> > array_value = vNULL, array_stride = vNULL;
+  vec<tree> ind_init = vNULL;
+  vec<vec<tree> >  array_length = vNULL, array_start = vNULL;
+  vec<tree> compare_expr = vNULL, array_var = vNULL, expr_incr = vNULL;
+  vec<vec<bool> > count_down = vNULL, array_vector = 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++)
+    {
+      tree list_node = (*array_list)[ii];
+      if (TREE_CODE (list_node) == CALL_EXPR
+	  || TREE_CODE (list_node) == AGGR_INIT_EXPR)
+	{
+	  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;
+
+  compare_expr.safe_grow_cleared (rank);
+  expr_incr.safe_grow_cleared (rank);
+  expr_incr.safe_grow_cleared (rank);
+  array_var.safe_grow_cleared (rank);
+  ind_init.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);
+    }
+  extract_an_triplets (array_list, &array_value, &array_start, &array_length,
+		       &array_stride, &array_vector, &count_down, list_size,
+		       rank);
+  for (ii = 0; ii < rank; ii++)
+    {
+      array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
+				  TREE_TYPE (array_start[0][ii]));
+      ind_init[ii] = build_x_modify_expr
+	(location, array_var[ii], NOP_EXPR, 
+	 build_zero_cst (TREE_TYPE (array_var[ii])), tf_warning_or_error);
+    }
+  array_operand = create_array_refs (location, array_value, array_start,
+				     array_stride, array_vector, array_var,
+				     count_down, list_size, rank);
+  replace_array_notations (&stmt, true, array_list, array_operand);
+  create_cmp_and_incr (location, array_var, array_length, &expr_incr,
+		       &compare_expr, count_down, rank, 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 (ind_init[ii], compare_expr[ii], expr_incr[ii], body);
+      body = pop_stmt_list (new_loop);
+    }
+  append_to_statement_list_force (body, &loop_with_init);
+  clear_all_an_vectors (&array_value, &array_start, &array_length,
+			&array_stride, &array_vector, &count_down, &expr_incr,
+			&compare_expr, &ind_init, &array_var);
+  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;
+  location_t loc = EXPR_LOCATION (expr);
+
+  if (TREE_CODE (expr) != RETURN_EXPR)
+    return 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;
+  
+  /* Skip empty subtrees.  */
+  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;
+}
diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c
index bccd884..d301db0 100644
--- a/gcc/cp/cp-objcp-common.c
+++ b/gcc/cp/cp-objcp-common.c
@@ -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"
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 2931ac5..76727ad 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6121,6 +6121,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 */
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
old mode 100644
new mode 100755
index a75fc4e..a8f52cd
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -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;
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
old mode 100644
new mode 100755
index d844d15..7bc9334
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -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;
@@ -10102,6 +10313,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;
 
@@ -10128,6 +10345,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;
 
@@ -10146,8 +10372,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;
 
@@ -16722,30 +16957,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
@@ -18116,6 +18374,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);
 
@@ -22095,6 +22358,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));
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
old mode 100644
new mode 100755
index 3602fcd..0a7d523
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -13740,6 +13740,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));
@@ -15712,6 +15726,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;
@@ -19119,6 +19136,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);
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 0a700b7..f27a70d 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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 notatinos, 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:
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 8524f6c..dd2fda4 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -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;
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
old mode 100644
new mode 100755
index 11ac85b..17f19c7
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
old mode 100644
new mode 100755
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c
index d17d8cf..579d396 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c
@@ -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;
 
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
index 35eb115..14421d9 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
@@ -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;
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c
old mode 100644
new mode 100755
index a0a3742..18816e0
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c
@@ -8,4 +8,4 @@ int main (void)
   array2[:] = array2[: ;  /* { dg-error "expected ']'" } */
 
   return 0;
-} /* { dg-error "expected ';' before" } */
+} /* { dg-error "expected ';' before" "" { target c } } */
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c
index 2e86b4f..4314090 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c
@@ -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 }  } */
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c
index 34dfa16..47b5979 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c
@@ -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 } } */
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c
index eba28a8..a0efc04 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c
@@ -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;
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c
index cabdb23..4c80c42 100755
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c
@@ -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 }  7 } */
 
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c
index 843745e..3b0777e 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c
@@ -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
index 0000000..e9ee7ec
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/array_test1_tplt.cc
@@ -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
index 0000000..87c37e1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/array_test2_tplt.cc
@@ -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
index 0000000..479ba13
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/array_test_ND_tplt.cc
@@ -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 100755
index 0000000..b91de7a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/braced_list.cc
@@ -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
index 0000000..3d9e87b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_custom_tplt.cc
@@ -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
index 0000000..db81912
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_mutating_tplt.cc
@@ -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
index 0000000..1387558
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/fp_triplet_values_tplt.c
@@ -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
index 0000000..b0952c7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/postincr_test.cc
@@ -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
index 0000000..f5552c7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/preincr_test.cc
@@ -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
index 0000000..a153529
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp
@@ -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
diff --git a/gcc/testsuite/g++.dg/dg.exp b/gcc/testsuite/g++.dg/dg.exp
old mode 100644
new mode 100755
index 7201359..710218e
--- a/gcc/testsuite/g++.dg/dg.exp
+++ b/gcc/testsuite/g++.dg/dg.exp
@@ -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/*]

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH] Cilk Plus Array Notation for C++
  2013-06-17 18:29             ` Iyer, Balaji V
@ 2013-06-18 23:42               ` Aldy Hernandez
  2013-06-19  4:07                 ` Iyer, Balaji V
  0 siblings, 1 reply; 40+ messages in thread
From: Aldy Hernandez @ 2013-06-18 23:42 UTC (permalink / raw)
  To: Iyer, Balaji V
  Cc: Richard Henderson, gcc-patches, Jason Merrill (jason@redhat.com)

Thanks for fixing everything.  This looks much better.

I don't have much, just small typos.  It's up to Jason and Richard to 
take it from here.

Aldy

----

> +      else
> +	{
> +	  val = convert_like_with_context (conv, arg, fn, i-is_method,
> +					   conversion_warning
> +					   ? complain
> +					   : complain & (~tf_warning));

s/i-is_method/i - is_method/

I know this isn't your fault, since the original code had this, but if 
you're going to copy over, might as well fix small formatting errors :).

> +/* Extracts all the array notation triplet information from LIST and stores them
> +   in a 2-D arrays (size x rank) of START, LENGTH and STRIDE, holding the

s/2-D arrays/2-D array/

> +   For example: For an array notation A[5:10:2], the vector start  will be

Extra space after start.

> +      /* 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!  */
> +      while (TREE_CODE (call_fn) == CONVERT_EXPR
> +	     || TREE_CODE (call_fn) == NOP_EXPR)
> +	call_fn = TREE_OPERAND (call_fn, 0);

We already have an automated way of doing this.  Will this work for you?:

/* Given an expression as a tree, strip any conversion that generates
    no instruction.  Accepts both tree and const_tree arguments since
    we are not modifying the tree itself.  */

#define STRIP_NOPS(EXP) \
   (EXP) = tree_strip_nop_conversions (CONST_CAST_TREE (EXP))

Similarly elsewhere.

> +/* Helper function for expand_conditonal_array_notations. Encloses the

Two spaces after "."

> +static tree
> +expand_return_expr (tree expr)
> +{
> +  tree new_mod_list, new_var, new_mod, retval_expr;
> +  location_t loc = EXPR_LOCATION (expr);
> +
> +  if (TREE_CODE (expr) != RETURN_EXPR)
> +    return expr;

Well, since we're using C++, might as well move the comparison with 
RETURN_EXPR earlier, to avoid setting loc.

> +  /* Skip empty subtrees.  */
> +  if (!t)
> +    return t;

No need to document the obvious.

> +    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)));

Indentation of RETURN is wrong.

> +      /* If the return expression contains array notatinos, then flag it as

s/notatinos/notations.  Though I like the sound of "notatinos" :-).

> +      /* If find_rank returns false,  then it should have reported an error,

s/  then/then

> +     to convert them. They will be broken up into modify exprs in future,

Two spaces after period.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* RE: [PATCH] Cilk Plus Array Notation for C++
  2013-06-18 23:42               ` Aldy Hernandez
@ 2013-06-19  4:07                 ` Iyer, Balaji V
  2013-06-20 17:54                   ` Richard Henderson
  0 siblings, 1 reply; 40+ messages in thread
From: Iyer, Balaji V @ 2013-06-19  4:07 UTC (permalink / raw)
  To: Aldy Hernandez
  Cc: Richard Henderson, gcc-patches, Jason Merrill (jason@redhat.com)

[-- Attachment #1: Type: text/plain, Size: 8326 bytes --]

Hi Aldy, Richard, Jason et al.,
	I have fixed all the changes that Aldy suggested. I'm attaching a fixed patch. So, is it OK for trunk now?

Here are the ChangeLog Entries:

gcc/cp/ChangeLog
2013-06-19  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-19  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.

Thanks,

Balaji V. Iyer.

> -----Original Message-----
> From: Aldy Hernandez [mailto:aldyh@redhat.com]
> Sent: Tuesday, June 18, 2013 7:43 PM
> To: Iyer, Balaji V
> Cc: Richard Henderson; gcc-patches@gcc.gnu.org; Jason Merrill
> (jason@redhat.com)
> Subject: Re: [PATCH] Cilk Plus Array Notation for C++
> 
> Thanks for fixing everything.  This looks much better.
> 
> I don't have much, just small typos.  It's up to Jason and Richard to take it from
> here.
> 
> Aldy
> 
> ----
> 
> > +      else
> > +	{
> > +	  val = convert_like_with_context (conv, arg, fn, i-is_method,
> > +					   conversion_warning
> > +					   ? complain
> > +					   : complain & (~tf_warning));
> 
> s/i-is_method/i - is_method/

FIXED!
 
> I know this isn't your fault, since the original code had this, but if you're going to
> copy over, might as well fix small formatting errors :).
> 
> > +/* Extracts all the array notation triplet information from LIST and stores
> them
> > +   in a 2-D arrays (size x rank) of START, LENGTH and STRIDE, holding
> > +the
> 
> s/2-D arrays/2-D array/

FIXED!

> 
> > +   For example: For an array notation A[5:10:2], the vector start
> > + will be
> 
> Extra space after start.

FIXED!

> 
> > +      /* 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!  */
> > +      while (TREE_CODE (call_fn) == CONVERT_EXPR
> > +	     || TREE_CODE (call_fn) == NOP_EXPR)
> > +	call_fn = TREE_OPERAND (call_fn, 0);
> 
> We already have an automated way of doing this.  Will this work for you?:
> 
> /* Given an expression as a tree, strip any conversion that generates
>     no instruction.  Accepts both tree and const_tree arguments since
>     we are not modifying the tree itself.  */
> 
> #define STRIP_NOPS(EXP) \
>    (EXP) = tree_strip_nop_conversions (CONST_CAST_TREE (EXP))
> 
> Similarly elsewhere.

FIXED ALL.

> 
> > +/* Helper function for expand_conditonal_array_notations. Encloses
> > +the
> 
> Two spaces after "."

FIXED!

> 
> > +static tree
> > +expand_return_expr (tree expr)
> > +{
> > +  tree new_mod_list, new_var, new_mod, retval_expr;
> > +  location_t loc = EXPR_LOCATION (expr);
> > +
> > +  if (TREE_CODE (expr) != RETURN_EXPR)
> > +    return expr;
> 
> Well, since we're using C++, might as well move the comparison with
> RETURN_EXPR earlier, to avoid setting loc.

FIXED!

> 
> > +  /* Skip empty subtrees.  */
> > +  if (!t)
> > +    return t;
> 
> No need to document the obvious.

FIXED!

> 
> > +    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)));
> 
> Indentation of RETURN is wrong.

It just looks weird on the patch, on the file it looks OK. I can send you a screen shot if you like.

> 
> > +      /* If the return expression contains array notatinos, then flag
> > + it as
> 
> s/notatinos/notations.  Though I like the sound of "notatinos" :-).

FIXED! 

> 
> > +      /* If find_rank returns false,  then it should have reported an
> > + error,
> 
> s/  then/then

FIXED!

> 
> > +     to convert them. They will be broken up into modify exprs in
> > + future,
> 
> Two spaces after period.

FIXED!

[-- Attachment #2: patch_array_notation_cpp.txt --]
[-- Type: text/plain, Size: 125737 bytes --]

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
old mode 100644
new mode 100755
index 7e25e52..18d3fc3
Binary files a/gcc/cp/ChangeLog and b/gcc/cp/ChangeLog differ
diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
index df8ed3e..6e80bcf 100644
--- a/gcc/cp/Make-lang.in
+++ b/gcc/cp/Make-lang.in
@@ -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)
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index dfd061a..0c729e8 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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 100755
index 0000000..ba92cd7
--- /dev/null
+++ b/gcc/cp/cp-array-notation.c
@@ -0,0 +1,1729 @@
+/* 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) is passed in as a 2D vector of trees.  */
+
+static bool
+cp_length_mismatch_in_expr_p (location_t loc, vec<vec<tree> >list)
+{
+  size_t ii, jj;
+  tree start = NULL_TREE;
+  HOST_WIDE_INT l_start, l_node;
+
+  size_t x = list.length ();
+  size_t y = list[0].length ();
+  
+  for (jj = 0; jj < y; jj++)
+    {
+      start = NULL_TREE;
+      for (ii = 0; ii < x; ii++)
+	{
+	  if (!start)
+	    start = list[ii][jj];
+	  else if (TREE_CODE (start) == INTEGER_CST)
+	    {
+	      /* If start 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]) == INTEGER_CST)
+		{
+		  l_node = int_cst_value (list[ii][jj]);
+		  l_start = int_cst_value (start);
+		  if (absu_hwi (l_start) != absu_hwi (l_node))
+		    {
+		      error_at (loc, "length mismatch in expression");
+		      return true;
+		    }
+		}
+	    }
+	  else
+	    /* We set the start node as the current node just in case it turns
+	       out to be an integer.  */
+	    start = list[ii][jj];
+	}
+    }
+  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;
+    }
+}
+
+/* Extracts all the array notation triplet information from LIST and stores
+   them in a 2-D array (size x rank) of START, LENGTH and STRIDE, holding the
+   starting index, length, and stride, respectively.  In addition, it also
+   sets two bool arrays IS_VECTOR and COUNT_DOWN indicating whether a certain
+   value at a certain field is a vector or not.  */
+
+static inline void
+extract_an_triplets (vec <tree, va_gc> *list, vec <vec<tree> > *value,
+		     vec <vec<tree> > *start, vec <vec<tree> > *length,
+		     vec <vec<tree> > *stride, vec <vec <bool> > *is_vector,
+		     vec<vec<bool> > *count_down, size_t size, size_t rank)
+{
+  vec<vec<tree> > array_exprs = vNULL;
+
+  start->safe_grow_cleared (size);
+  length->safe_grow_cleared (size);
+  stride->safe_grow_cleared (size);
+  value->safe_grow_cleared (size);
+  array_exprs.safe_grow_cleared (size);
+  is_vector->safe_grow_cleared (size);
+  count_down->safe_grow_cleared (size);
+
+  for (size_t ii = 0; ii < size; ii++)
+    for (size_t jj = 0; jj < rank; jj++)
+      {
+	array_exprs[ii].safe_push (NULL_TREE);
+	(*start)[ii].safe_push (NULL_TREE);
+	(*value)[ii].safe_push (NULL_TREE);
+	(*length)[ii].safe_push (NULL_TREE);
+	(*stride)[ii].safe_push (NULL_TREE);
+	(*is_vector)[ii].safe_push (false);
+	(*count_down)[ii].safe_push (false);
+      }
+  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];
+	    (*is_vector)[ii][jj] = true;
+	    (*value)[ii][jj] = ARRAY_NOTATION_ARRAY (ii_tree);
+	    (*start)[ii][jj] = ARRAY_NOTATION_START (ii_tree);
+	    (*length)[ii][jj] = fold_build1 (CONVERT_EXPR, integer_type_node,
+					     ARRAY_NOTATION_LENGTH (ii_tree));
+	    (*stride)[ii][jj] = fold_build1 (CONVERT_EXPR, integer_type_node,
+					     ARRAY_NOTATION_STRIDE (ii_tree));
+	  }
+}
+
+/* Returns a vector of size RANK that contains an array ref that is derived from
+   array notation triplet parameters stored in VALUE, START, STRIDE.  IS_VECTOR
+   is used to check if the data stored at its corresponding location is an
+   array notation. VAR is the induction variable passed in by the caller.
+
+   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, is_vector as true and count_down as false. 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<tree> > value,
+		   vec <vec<tree> > start, vec <vec<tree> > stride,
+		   vec <vec <bool> > is_vector, vec<tree> var,
+		   vec<vec<bool> > count_down, size_t size, size_t rank)
+{
+  enum tree_code code = PLUS_EXPR;
+  tree ind_mult, ind_incr;
+  vec<tree, va_gc> *array_operand = NULL;
+  for (size_t ii = 0; ii < size; ii++)
+    if (is_vector[ii][0])
+      {
+	tree array_opr = value[ii][rank-1];
+	for (int s_jj = rank -1; s_jj >= 0; s_jj--)
+	  {
+	    tree str = NULL_TREE, v = NULL_TREE, st = NULL_TREE;
+       
+	    /* 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[ii][s_jj]) == TREE_TYPE (stride[ii][s_jj])
+		&& TREE_TYPE (stride[ii][s_jj]) != TREE_TYPE (var[s_jj]))
+	      {
+		st = start[ii][s_jj];
+		str = stride[ii][s_jj];
+		v = build_c_cast (loc, TREE_TYPE (str), var[s_jj]);
+	      }
+	    else if (TREE_TYPE (start[ii][s_jj]) != TREE_TYPE (stride[ii][s_jj]))
+	      {
+		/* 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[ii][s_jj]);
+		str = build_c_cast (loc, integer_type_node, stride[ii][s_jj]);
+		v = build_c_cast (loc, integer_type_node, var[s_jj]);
+	      }
+	    else
+	      {
+		st = start[ii][s_jj];
+		str = stride[ii][s_jj];
+		v = var[s_jj];
+	      }
+
+	    if (count_down[ii][s_jj])
+	      code = MINUS_EXPR;
+	    else
+	      code = PLUS_EXPR;
+
+	    ind_mult = build2 (MULT_EXPR, TREE_TYPE (v), v, str);
+	    ind_incr = build2 (code, 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 vectors with the increment (of type POSTINCREMENT
+   or POSTDECREMENT) and comparison (of TYPE GT_EXPR or LT_EXPR) expressions,
+   using data from LENGTH, COUNT_DOWN, and VAR.  INCR and CMP vectors are of
+   size RANK.  */
+
+static void
+create_cmp_and_incr (location_t loc, vec <tree> var, vec<vec<tree> > length,
+		     vec <tree> *incr, vec <tree> *cmp,
+		     vec<vec<bool> > count_down, size_t rank,
+		     tsubst_flags_t complain)
+{
+  enum tree_code incr_code, comp_code;
+  cmp->safe_grow_cleared (rank);
+  incr->safe_grow_cleared (rank);
+  for (size_t ii = 0; ii < rank; ii++)
+    {
+      if (count_down[0][ii])
+	{
+	  incr_code = POSTDECREMENT_EXPR;
+	  comp_code = GT_EXPR;
+	}
+      else
+	{
+	  incr_code = POSTINCREMENT_EXPR;
+	  comp_code = LT_EXPR;
+	}
+      (*incr)[ii] = build_x_unary_op (loc, incr_code, var[ii], complain);
+      (*cmp)[ii] = build_x_binary_op (loc, comp_code, var[ii],
+				      TREE_CODE (var[ii]), length[0][ii],
+				      TREE_CODE (length[0][ii]), NULL, complain);
+    }
+}
+
+/* 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<tree> var,
+		       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, var[idx]);
+	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;
+}
+
+/* Clear (i.e. deallocate) all the temporary vectors required to expand
+   array notation expressions.  */
+
+static inline void
+clear_all_an_vectors (vec <vec<tree> > *value, vec<vec<tree> > *start,
+		      vec <vec<tree> > *length, vec<vec<tree> > *stride,
+		      vec<vec<bool> > *is_vector, vec<vec<bool> > *count_down,
+		      vec<tree> *incr, vec<tree> *cmp, vec<tree> *ind_init,
+		      vec<tree> *var)
+{
+  value->release ();
+  start->release ();
+  length->release ();
+  stride->release ();
+  is_vector->release ();
+  count_down->release ();
+  incr->release ();
+  cmp->release ();
+  ind_init->release ();
+  var->release ();
+}
+
+/* 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;
+  vec<tree> array_var = vNULL, expr_incr = vNULL, compare_expr = vNULL;
+  vec<tree> ind_init = vNULL;
+  vec<vec<tree> > array_value = vNULL, array_stride = vNULL,
+    array_length = vNULL, array_start = vNULL;
+  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;
+  vec<vec<bool> > count_down = vNULL, array_vector = vNULL;
+  tree init = NULL_TREE, cond_init = NULL_TREE;
+  enum tree_code code = NOP_EXPR;
+  location_t location = UNKNOWN_LOCATION;
+
+  enum built_in_function an_type =
+    is_cilkplus_reduce_builtin (CALL_EXPR_FN (an_builtin_fn));
+  
+  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);
+
+  ind_init.safe_grow_cleared (rank);
+  array_var.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);
+      }
+
+  extract_an_triplets (array_list, &array_value, &array_start, &array_length,
+		       &array_stride, &array_vector, &count_down, list_size,
+		       rank);
+  for (ii = 0; ii < rank; ii++)
+    {
+      array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
+				  TREE_TYPE (array_start[0][ii]));
+      ind_init[ii] = build_x_modify_expr
+	(location, array_var[ii], NOP_EXPR, 
+	 build_zero_cst (TREE_TYPE (array_var[ii])), tf_warning_or_error);
+    }
+  array_operand = create_array_refs (location, array_value, array_start,
+				     array_stride, array_vector, array_var,
+				     count_down, 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_and_incr (location, array_var, array_length, &expr_incr,
+		       &compare_expr, count_down, rank, 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 = ARITHMETIC_TYPE_P (new_var_type) ? build_zero_cst (new_var_type)
+	: integer_zero_node;
+      break;
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL:
+      code = MULT_EXPR;
+      init = ARITHMETIC_TYPE_P (new_var_type) ? build_one_cst (new_var_type)
+	: integer_one_node;
+      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 = !ARITHMETIC_TYPE_P (TREE_TYPE (func_parm)) ? integer_zero_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 = !ARITHMETIC_TYPE_P (TREE_TYPE (func_parm)) ? integer_zero_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 = array_var[0];
+    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);
+  if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ADD
+      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MUL)
+    new_expr = build_x_modify_expr (location, *new_var, code, func_parm,
+				    tf_warning_or_error);
+  if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO
+      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO
+      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO
+      || an_type == 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);
+    }
+  if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX
+      || an_type == 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);
+    }
+  if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
+      || an_type == 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,
+					   array_var[0], 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);
+    }
+  if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE
+      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
+    {
+      vec <tree, va_gc> *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);
+    }
+  
+  /* 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 (ind_init[ii]);
+ 
+  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 (ind_init[ii], compare_expr[ii], expr_incr[ii], body);
+      body = pop_stmt_list (new_loop);
+    }
+  append_to_statement_list_force (body, &loop_with_init);
+  clear_all_an_vectors (&array_value, &array_start, &array_length,
+			&array_stride, &array_vector, &count_down, &expr_incr,
+			&compare_expr, &ind_init, &array_var);
+  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> lhs_var = vNULL, rhs_var = vNULL;
+  vec<tree> cond_expr = vNULL;
+  vec<tree> lhs_expr_incr = vNULL, rhs_expr_incr = vNULL;
+  vec<tree> lhs_ind_init = vNULL, rhs_ind_init = vNULL;
+  vec<tree> lhs_compare = vNULL, rhs_compare = 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<tree> > lhs_value = vNULL, lhs_start = vNULL, lhs_length = vNULL;
+  vec <vec<tree> > lhs_stride = vNULL;
+  vec <vec<tree> > rhs_value = vNULL, rhs_start = vNULL, rhs_length = vNULL;
+  vec <vec<tree> > rhs_stride = vNULL;
+  vec <vec<bool> > lhs_count_down = vNULL, rhs_count_down = vNULL;
+  vec <vec<bool> > lhs_vector = vNULL, rhs_vector = 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_var.safe_grow_cleared (lhs_rank);
+  lhs_ind_init.safe_grow_cleared (lhs_rank);
+  if (rhs_rank)
+    {
+      rhs_var.safe_grow_cleared (rhs_rank);
+      rhs_ind_init.safe_grow_cleared (rhs_rank);
+    }
+  
+  cond_expr.safe_grow_cleared (MAX (lhs_rank, rhs_rank));
+
+  extract_an_triplets (lhs_list, &lhs_value, &lhs_start, &lhs_length,
+		       &lhs_stride, &lhs_vector, &lhs_count_down, lhs_list_size,
+		       lhs_rank);
+  if (rhs_list)
+    extract_an_triplets (rhs_list, &rhs_value, &rhs_start, &rhs_length,
+			 &rhs_stride, &rhs_vector, &rhs_count_down,
+			 rhs_list_size, rhs_rank);
+
+  if (cp_length_mismatch_in_expr_p (EXPR_LOCATION (lhs), lhs_length)
+      || (rhs_list && cp_length_mismatch_in_expr_p (EXPR_LOCATION (rhs),
+						    rhs_length)))
+    {
+      pop_stmt_list (an_init);
+      return error_mark_node;
+    }
+  if (lhs_list_size > 0 && rhs_list_size > 0 && lhs_rank > 0 && rhs_rank > 0
+      && TREE_CODE (lhs_length[0][0]) == INTEGER_CST
+      && rhs_length[0][0] && TREE_CODE (rhs_length[0][0]) == INTEGER_CST)
+    {
+      HOST_WIDE_INT l_length = int_cst_value (lhs_length[0][0]);
+      HOST_WIDE_INT r_length = int_cst_value (rhs_length[0][0]);
+      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_start[0][ii] && TREE_TYPE (lhs_start[0][ii]))
+	lhs_var[ii] =  build_decl (location, VAR_DECL, NULL_TREE,
+				   TREE_TYPE (lhs_start[0][ii]));
+    else
+      lhs_var[ii] = 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_var,
+						  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_vector[0][ii])
+      {
+	lhs_ind_init[ii] = build_x_modify_expr
+	  (location, lhs_var[ii], NOP_EXPR,
+	   build_zero_cst (TREE_TYPE (lhs_var[ii])), complain);
+      }
+  for (ii = 0; ii < rhs_rank; ii++)
+    {
+      /* When we have a polynomial, we assume that the indices are of type
+	 integer.  */
+      rhs_var[ii] =  build_decl (location, VAR_DECL, NULL_TREE,
+				 TREE_TYPE (rhs_start[0][ii]));
+      rhs_ind_init[ii] = build_x_modify_expr
+	(location, rhs_var[ii], NOP_EXPR, 
+	 build_zero_cst (TREE_TYPE (rhs_var[ii])), complain);
+    }
+
+  if (lhs_rank)
+    {
+      lhs_array_operand = create_array_refs (location, lhs_value, lhs_start,
+					     lhs_stride, lhs_vector, lhs_var,
+					     lhs_count_down, 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_value, rhs_start,
+					     rhs_stride, rhs_vector, rhs_var,
+					     rhs_count_down, 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_var,
+						 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_and_incr (location, lhs_var, lhs_length, &lhs_expr_incr,
+		       &lhs_compare, lhs_count_down, lhs_rank, complain);
+  if (rhs_rank)
+    create_cmp_and_incr (location, rhs_var, rhs_length, &rhs_expr_incr,
+			 &rhs_compare, rhs_count_down, rhs_rank, 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_compare[ii],
+	 TREE_CODE (lhs_compare[ii]), rhs_compare[ii],
+	 TREE_CODE (rhs_compare[ii]), NULL, complain);
+    else if (ii < lhs_rank && ii >= rhs_rank)
+      cond_expr[ii] = lhs_compare[ii];
+    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_ind_init[ii], &init_list);
+	  append_to_statement_list_force (lhs_expr_incr[ii], &incr_list);
+	}
+      if (rhs_rank)
+	{
+	  append_to_statement_list_force (rhs_ind_init[ii], &init_list);
+	  append_to_statement_list_force (rhs_expr_incr[ii], &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);
+  
+  clear_all_an_vectors (&lhs_value, &lhs_start, &lhs_length, &lhs_stride,
+			&lhs_vector, &lhs_count_down, &lhs_expr_incr,
+			&lhs_compare, &lhs_ind_init, &lhs_var);
+  if (rhs_rank)
+    clear_all_an_vectors (&rhs_value, &rhs_start, &rhs_length, &rhs_stride,
+			  &rhs_vector, &rhs_count_down, &rhs_expr_incr,
+			  &rhs_compare, &rhs_ind_init, &rhs_var);
+  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;
+  vec<vec<tree> > array_value = vNULL, array_stride = vNULL;
+  vec<vec<tree> >  array_length = vNULL, array_start = vNULL;
+  vec<tree> compare_expr = vNULL, array_var = vNULL, expr_incr = vNULL;
+  vec<tree> ind_init = vNULL;
+  tree builtin_loop, new_var = NULL_TREE;
+  vec<vec<bool> > count_down = vNULL, array_vector = vNULL;
+  tree loop_with_init = alloc_stmt_list ();
+  tsubst_flags_t complain = tf_warning_or_error;
+  location_t location = UNKNOWN_LOCATION;
+
+  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);
+
+  compare_expr.safe_grow_cleared (rank);
+  expr_incr.safe_grow_cleared (rank);
+  expr_incr.safe_grow_cleared (rank);
+  array_var.safe_grow_cleared (rank);
+  ind_init.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);
+    }
+
+  extract_an_triplets (array_list, &array_value, &array_start, &array_length,
+		       &array_stride, &array_vector, &count_down, list_size,
+		       rank);
+  for (ii = 0; ii < rank; ii++)
+    {
+      if (TREE_TYPE (array_start[0][ii])
+	  && TREE_CODE (TREE_TYPE (array_start[0][ii])) != TEMPLATE_TYPE_PARM)
+	{
+	  array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
+				      TREE_TYPE (array_start[0][ii]));
+	  ind_init[ii] = build_x_modify_expr
+	    (location, array_var[ii], NOP_EXPR, 
+	     build_zero_cst (TREE_TYPE (array_var[ii])), tf_warning_or_error);
+	}
+      else
+	{
+	  array_var[ii] = build_min_nt_loc (location, VAR_DECL,
+					    NULL_TREE, NULL_TREE);
+	  ind_init[ii] = build_x_modify_expr (location, array_var[ii], 
+					      NOP_EXPR,
+					      integer_zero_node, 1);
+	}
+    }
+  array_operand = create_array_refs (location, array_value, array_start,
+				     array_stride, array_vector, array_var,
+				     count_down, list_size, rank);
+  replace_array_notations (&stmt, true, array_list, array_operand);
+
+  create_cmp_and_incr (location, array_var, array_length, &expr_incr,
+		       &compare_expr, count_down, rank, complain);
+  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 (ind_init[ii], compare_expr[ii], expr_incr[ii], body);
+      body = pop_stmt_list (new_loop);
+    }
+  append_to_statement_list_force (body, &loop_with_init);
+  clear_all_an_vectors (&array_value, &array_start, &array_length,
+			&array_stride, &array_vector, &count_down, &expr_incr,
+			&compare_expr, &ind_init, &array_var);
+  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<tree> > array_value = vNULL, array_stride = vNULL;
+  vec<tree> ind_init = vNULL;
+  vec<vec<tree> >  array_length = vNULL, array_start = vNULL;
+  vec<tree> compare_expr = vNULL, array_var = vNULL, expr_incr = vNULL;
+  vec<vec<bool> > count_down = vNULL, array_vector = 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++)
+    {
+      tree list_node = (*array_list)[ii];
+      if (TREE_CODE (list_node) == CALL_EXPR
+	  || TREE_CODE (list_node) == AGGR_INIT_EXPR)
+	{
+	  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;
+
+  compare_expr.safe_grow_cleared (rank);
+  expr_incr.safe_grow_cleared (rank);
+  expr_incr.safe_grow_cleared (rank);
+  array_var.safe_grow_cleared (rank);
+  ind_init.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);
+    }
+  extract_an_triplets (array_list, &array_value, &array_start, &array_length,
+		       &array_stride, &array_vector, &count_down, list_size,
+		       rank);
+  for (ii = 0; ii < rank; ii++)
+    {
+      array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
+				  TREE_TYPE (array_start[0][ii]));
+      ind_init[ii] = build_x_modify_expr
+	(location, array_var[ii], NOP_EXPR, 
+	 build_zero_cst (TREE_TYPE (array_var[ii])), tf_warning_or_error);
+    }
+  array_operand = create_array_refs (location, array_value, array_start,
+				     array_stride, array_vector, array_var,
+				     count_down, list_size, rank);
+  replace_array_notations (&stmt, true, array_list, array_operand);
+  create_cmp_and_incr (location, array_var, array_length, &expr_incr,
+		       &compare_expr, count_down, rank, 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 (ind_init[ii], compare_expr[ii], expr_incr[ii], body);
+      body = pop_stmt_list (new_loop);
+    }
+  append_to_statement_list_force (body, &loop_with_init);
+  clear_all_an_vectors (&array_value, &array_start, &array_length,
+			&array_stride, &array_vector, &count_down, &expr_incr,
+			&compare_expr, &ind_init, &array_var);
+  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;
+}
diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c
index bccd884..d301db0 100644
--- a/gcc/cp/cp-objcp-common.c
+++ b/gcc/cp/cp-objcp-common.c
@@ -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"
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 2931ac5..76727ad 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6121,6 +6121,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 */
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
old mode 100644
new mode 100755
index a75fc4e..a8f52cd
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -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;
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
old mode 100644
new mode 100755
index 904ae0b..6fc45f3
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -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));
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
old mode 100644
new mode 100755
index 25cbf31..8ff5b57
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -13740,6 +13740,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));
@@ -15712,6 +15726,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;
@@ -19119,6 +19136,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);
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 0a700b7..403a9fa 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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:
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 8524f6c..dd2fda4 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -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;
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
old mode 100644
new mode 100755
index 11ac85b..316a657
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
old mode 100644
new mode 100755
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c
index d17d8cf..579d396 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c
@@ -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;
 
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
index 35eb115..14421d9 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
@@ -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;
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c
old mode 100644
new mode 100755
index a0a3742..18816e0
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c
@@ -8,4 +8,4 @@ int main (void)
   array2[:] = array2[: ;  /* { dg-error "expected ']'" } */
 
   return 0;
-} /* { dg-error "expected ';' before" } */
+} /* { dg-error "expected ';' before" "" { target c } } */
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c
index 2e86b4f..4314090 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c
@@ -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 }  } */
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c
index 34dfa16..47b5979 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c
@@ -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 } } */
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c
index eba28a8..a0efc04 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c
@@ -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;
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c
index cabdb23..9bff079 100755
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c
@@ -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 } */
 
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c
index 843745e..3b0777e 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c
@@ -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
index 0000000..e9ee7ec
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/array_test1_tplt.cc
@@ -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
index 0000000..87c37e1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/array_test2_tplt.cc
@@ -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
index 0000000..479ba13
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/array_test_ND_tplt.cc
@@ -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 100755
index 0000000..b91de7a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/braced_list.cc
@@ -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
index 0000000..3d9e87b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_custom_tplt.cc
@@ -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
index 0000000..db81912
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_mutating_tplt.cc
@@ -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
index 0000000..1387558
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/fp_triplet_values_tplt.c
@@ -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
index 0000000..b0952c7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/postincr_test.cc
@@ -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
index 0000000..f5552c7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/preincr_test.cc
@@ -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
index 0000000..a153529
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp
@@ -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
diff --git a/gcc/testsuite/g++.dg/dg.exp b/gcc/testsuite/g++.dg/dg.exp
old mode 100644
new mode 100755
index 7201359..710218e
--- a/gcc/testsuite/g++.dg/dg.exp
+++ b/gcc/testsuite/g++.dg/dg.exp
@@ -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/*]

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH] Cilk Plus Array Notation for C++
  2013-06-19  4:07                 ` Iyer, Balaji V
@ 2013-06-20 17:54                   ` Richard Henderson
  2013-06-20 23:39                     ` Iyer, Balaji V
  0 siblings, 1 reply; 40+ messages in thread
From: Richard Henderson @ 2013-06-20 17:54 UTC (permalink / raw)
  To: Iyer, Balaji V
  Cc: Aldy Hernandez, gcc-patches, Jason Merrill (jason@redhat.com)

> +/* 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) is passed in as a 2D vector of trees.  */
> +
> +static bool
> +cp_length_mismatch_in_expr_p (location_t loc, vec<vec<tree> >list)

Other than working on a vec<>, how does this differ from the

  length_mismatch_in_expr_p (location_t loc, tree **list, size_t x, size_t y)

in c-family?

> +static inline void
> +clear_all_an_vectors (vec <vec<tree> > *value, vec<vec<tree> > *start,
> +		      vec <vec<tree> > *length, vec<vec<tree> > *stride,
> +		      vec<vec<bool> > *is_vector, vec<vec<bool> > *count_down,
> +		      vec<tree> *incr, vec<tree> *cmp, vec<tree> *ind_init,
> +		      vec<tree> *var)
> +{
> +  value->release ();
> +  start->release ();
> +  length->release ();
> +  stride->release ();
> +  is_vector->release ();
> +  count_down->release ();
> +  incr->release ();
> +  cmp->release ();
> +  ind_init->release ();
> +  var->release ();
> +}

10 arrays kept in sync?  It's at this point that we should realize that there's
a mistake in how we're arranging the data.  This should be one array, with the
element being a structure.

That should significantly improve quite a lot of the functions in this file.

> +      init = ARITHMETIC_TYPE_P (new_var_type) ? build_zero_cst (new_var_type)
> +	: integer_zero_node;

Why the test for ARITHMETIC_TYPE_P?  Surely we always want something of
new_var_type.

> +  if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ADD
> +      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MUL)
> +    new_expr = build_x_modify_expr (location, *new_var, code, func_parm,
> +				    tf_warning_or_error);
> +  if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO
> +      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO
> +      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO
> +      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO)

Why not another switch statement here?


r~

^ permalink raw reply	[flat|nested] 40+ messages in thread

* RE: [PATCH] Cilk Plus Array Notation for C++
  2013-06-20 17:54                   ` Richard Henderson
@ 2013-06-20 23:39                     ` Iyer, Balaji V
  2013-06-21 16:11                       ` Richard Henderson
  2013-06-22 16:20                       ` Jason Merrill
  0 siblings, 2 replies; 40+ messages in thread
From: Iyer, Balaji V @ 2013-06-20 23:39 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Aldy Hernandez, gcc-patches, Jason Merrill (jason@redhat.com)

[-- Attachment #1: Type: text/plain, Size: 7911 bytes --]

Hello Richard,
	Please see my responses below:

Thanks,

Balaji V. Iyer.

> -----Original Message-----
> From: gcc-patches-owner@gcc.gnu.org [mailto:gcc-patches-
> owner@gcc.gnu.org] On Behalf Of Richard Henderson
> Sent: Thursday, June 20, 2013 1:54 PM
> To: Iyer, Balaji V
> Cc: Aldy Hernandez; gcc-patches@gcc.gnu.org; Jason Merrill
> (jason@redhat.com)
> Subject: Re: [PATCH] Cilk Plus Array Notation for C++
> 
> > +/* 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) is passed in as a 2D vector of trees.  */
> > +
> > +static bool
> > +cp_length_mismatch_in_expr_p (location_t loc, vec<vec<tree> >list)
> 
> Other than working on a vec<>, how does this differ from the
> 
>   length_mismatch_in_expr_p (location_t loc, tree **list, size_t x, size_t y)
> 
> in c-family?

There is no difference. After this patch gets approved for trunk,  I will combine them both.

> 
> > +static inline void
> > +clear_all_an_vectors (vec <vec<tree> > *value, vec<vec<tree> > *start,
> > +		      vec <vec<tree> > *length, vec<vec<tree> > *stride,
> > +		      vec<vec<bool> > *is_vector, vec<vec<bool> >
> *count_down,
> > +		      vec<tree> *incr, vec<tree> *cmp, vec<tree> *ind_init,
> > +		      vec<tree> *var)
> > +{
> > +  value->release ();
> > +  start->release ();
> > +  length->release ();
> > +  stride->release ();
> > +  is_vector->release ();
> > +  count_down->release ();
> > +  incr->release ();
> > +  cmp->release ();
> > +  ind_init->release ();
> > +  var->release ();
> > +}
> 
> 10 arrays kept in sync?  It's at this point that we should realize that there's a
> mistake in how we're arranging the data.  This should be one array, with the
> element being a structure.

I couldn't put them into 1 structure, so I made 2 structures holding the following information: array notation triplet information and array notation expansion loop's information. It is fixed in the patch attached.

> 
> That should significantly improve quite a lot of the functions in this file.
> 
> > +      init = ARITHMETIC_TYPE_P (new_var_type) ? build_zero_cst
> (new_var_type)
> > +	: integer_zero_node;
> 
> Why the test for ARITHMETIC_TYPE_P?  Surely we always want something of
> new_var_type.
> 

FIXED!

> > +  if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ADD
> > +      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MUL)
> > +    new_expr = build_x_modify_expr (location, *new_var, code, func_parm,
> > +				    tf_warning_or_error);
> > +  if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO
> > +      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO
> > +      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO
> > +      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO)
> 
> Why not another switch statement here?

No reason really. I changed it to a switch statement now.

It is tested on x86 and x86_64 and is passing all the regression tests it should pass and failing all the ones that it should. So, is this OK for trunk?

Here is the ChangeLog information:

gcc/cp/ChangeLog
2013-06-20  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/c-family/ChangeLog
2013-06-20  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/testsuite/ChangeLog
2013-06-20  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.

> 
> 
> r~

[-- Attachment #2: patch_array_notation_cpp.txt --]
[-- Type: text/plain, Size: 124349 bytes --]

diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
old mode 100644
new mode 100755
index a0f195b..fb70520
Binary files a/gcc/c-family/ChangeLog and b/gcc/c-family/ChangeLog differ
diff --git a/gcc/c-family/array-notation-common.c b/gcc/c-family/array-notation-common.c
old mode 100644
new mode 100755
index c82d7dc..7fa8a69
--- a/gcc/c-family/array-notation-common.c
+++ b/gcc/c-family/array-notation-common.c
@@ -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, 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;
+}
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
old mode 100644
new mode 100755
index 82625d7..71a7580
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1160,6 +1160,30 @@ 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;
+  bool count_down;
+} 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 +1203,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 */
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
old mode 100644
new mode 100755
index a7df33b..70009c6
Binary files a/gcc/cp/ChangeLog and b/gcc/cp/ChangeLog differ
diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
index df8ed3e..6e80bcf 100644
--- a/gcc/cp/Make-lang.in
+++ b/gcc/cp/Make-lang.in
@@ -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)
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index dfd061a..0c729e8 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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 100755
index 0000000..2d97a67
--- /dev/null
+++ b/gcc/cp/cp-array-notation.c
@@ -0,0 +1,1566 @@
+/* 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, is_vector as true and count_down as false.  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)
+{
+  enum tree_code code = PLUS_EXPR;
+  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;
+	    bool count_down = an_info[ii][s_jj].count_down;
+
+	    /* 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;
+	      }
+
+	    if (count_down)
+	      code = MINUS_EXPR;
+	    else
+	      code = PLUS_EXPR;
+
+	    ind_mult = build2 (MULT_EXPR, TREE_TYPE (v), v, str);
+	    ind_incr = build2 (code, 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 or POSTDECREMENT) and comparison
+   (of TYPE GT_EXPR or 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)
+{
+  enum tree_code incr_code, comp_code;
+  
+  for (size_t ii = 0; ii < rank; ii++)
+    {
+      if (an_info[0][ii].count_down)
+	{
+	  incr_code = POSTDECREMENT_EXPR;
+	  comp_code = GT_EXPR;
+	}
+      else
+	{
+	  incr_code = POSTINCREMENT_EXPR;
+	  comp_code = LT_EXPR;
+	}
+      (*node)[ii].incr = build_x_unary_op (loc, incr_code, (*node)[ii].var,
+					   complain);
+      (*node)[ii].cmp = build_x_binary_op (loc, comp_code, (*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;
+}
diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c
index bccd884..d301db0 100644
--- a/gcc/cp/cp-objcp-common.c
+++ b/gcc/cp/cp-objcp-common.c
@@ -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"
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 9fc4aeb..f6a3e58 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6126,6 +6126,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 */
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
old mode 100644
new mode 100755
index a75fc4e..a8f52cd
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -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;
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
old mode 100644
new mode 100755
index 904ae0b..6fc45f3
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -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));
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
old mode 100644
new mode 100755
index 97efdc9..19ac933
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -13751,6 +13751,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));
@@ -15723,6 +15737,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;
@@ -19124,6 +19141,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);
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 0a700b7..403a9fa 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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:
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 8524f6c..dd2fda4 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -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;
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
old mode 100644
new mode 100755
index 11ac85b..316a657
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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);
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c
index d17d8cf..579d396 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c
@@ -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;
 
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
index 35eb115..14421d9 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
@@ -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;
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c
old mode 100644
new mode 100755
index a0a3742..18816e0
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c
@@ -8,4 +8,4 @@ int main (void)
   array2[:] = array2[: ;  /* { dg-error "expected ']'" } */
 
   return 0;
-} /* { dg-error "expected ';' before" } */
+} /* { dg-error "expected ';' before" "" { target c } } */
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c
index 2e86b4f..4314090 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c
@@ -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 }  } */
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c
index 34dfa16..47b5979 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c
@@ -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 } } */
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c
index eba28a8..a0efc04 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c
@@ -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;
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c
index cabdb23..9bff079 100755
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c
@@ -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 } */
 
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c
index 843745e..3b0777e 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c
@@ -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
index 0000000..e9ee7ec
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/array_test1_tplt.cc
@@ -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
index 0000000..87c37e1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/array_test2_tplt.cc
@@ -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
index 0000000..479ba13
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/array_test_ND_tplt.cc
@@ -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 100755
index 0000000..b91de7a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/braced_list.cc
@@ -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
index 0000000..3d9e87b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_custom_tplt.cc
@@ -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
index 0000000..db81912
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_mutating_tplt.cc
@@ -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
index 0000000..1387558
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/fp_triplet_values_tplt.c
@@ -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
index 0000000..b0952c7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/postincr_test.cc
@@ -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
index 0000000..f5552c7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/preincr_test.cc
@@ -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
index 0000000..a153529
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp
@@ -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
diff --git a/gcc/testsuite/g++.dg/dg.exp b/gcc/testsuite/g++.dg/dg.exp
old mode 100644
new mode 100755
index 7201359..710218e
--- a/gcc/testsuite/g++.dg/dg.exp
+++ b/gcc/testsuite/g++.dg/dg.exp
@@ -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/*]

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH] Cilk Plus Array Notation for C++
  2013-06-20 23:39                     ` Iyer, Balaji V
@ 2013-06-21 16:11                       ` Richard Henderson
  2013-06-21 16:59                         ` Iyer, Balaji V
  2013-06-22 16:20                       ` Jason Merrill
  1 sibling, 1 reply; 40+ messages in thread
From: Richard Henderson @ 2013-06-21 16:11 UTC (permalink / raw)
  To: Iyer, Balaji V
  Cc: Aldy Hernandez, gcc-patches, Jason Merrill (jason@redhat.com)

On 06/20/2013 04:39 PM, Iyer, Balaji V wrote:
> I couldn't put them into 1 structure, so I made 2 structures holding the
> following information: array notation triplet information and array notation
> expansion loop's information. It is fixed in the patch attached.

Excellent, thanks.  One thing that seems to be missed in this
conversion is that .count_down is never set, only read.  Mistake
in +cilkplus_extract_an_triplets?

Otherwise this is looking good.


r~

^ permalink raw reply	[flat|nested] 40+ messages in thread

* RE: [PATCH] Cilk Plus Array Notation for C++
  2013-06-21 16:11                       ` Richard Henderson
@ 2013-06-21 16:59                         ` Iyer, Balaji V
  2013-06-21 17:00                           ` Richard Henderson
  0 siblings, 1 reply; 40+ messages in thread
From: Iyer, Balaji V @ 2013-06-21 16:59 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Aldy Hernandez, gcc-patches, Jason Merrill (jason@redhat.com)



> -----Original Message-----
> From: Richard Henderson [mailto:rth@redhat.com]
> Sent: Friday, June 21, 2013 12:11 PM
> To: Iyer, Balaji V
> Cc: Aldy Hernandez; gcc-patches@gcc.gnu.org; Jason Merrill
> (jason@redhat.com)
> Subject: Re: [PATCH] Cilk Plus Array Notation for C++
> 
> On 06/20/2013 04:39 PM, Iyer, Balaji V wrote:
> > I couldn't put them into 1 structure, so I made 2 structures holding
> > the following information: array notation triplet information and
> > array notation expansion loop's information. It is fixed in the patch attached.
> 
> Excellent, thanks.  One thing that seems to be missed in this conversion is that
> .count_down is never set, only read.  Mistake in +cilkplus_extract_an_triplets?

Count down came from an initial implementation were if the stride was negative, I set that bool to true and then we count down. But, the way it stands now, I can remove the count down field. I can remove it.

After I remove that field, will it be OK for trunk?

Thanks,

Balaji V. Iyer.
> 
> Otherwise this is looking good.
> 
> 
> r~

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH] Cilk Plus Array Notation for C++
  2013-06-21 16:59                         ` Iyer, Balaji V
@ 2013-06-21 17:00                           ` Richard Henderson
  2013-06-21 19:35                             ` Iyer, Balaji V
  0 siblings, 1 reply; 40+ messages in thread
From: Richard Henderson @ 2013-06-21 17:00 UTC (permalink / raw)
  To: Iyer, Balaji V
  Cc: Aldy Hernandez, gcc-patches, Jason Merrill (jason@redhat.com)

On 06/21/2013 09:59 AM, Iyer, Balaji V wrote:
> After I remove that field, will it be OK for trunk?

Yes.


r~

^ permalink raw reply	[flat|nested] 40+ messages in thread

* RE: [PATCH] Cilk Plus Array Notation for C++
  2013-06-21 17:00                           ` Richard Henderson
@ 2013-06-21 19:35                             ` Iyer, Balaji V
  0 siblings, 0 replies; 40+ messages in thread
From: Iyer, Balaji V @ 2013-06-21 19:35 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Aldy Hernandez, gcc-patches, Jason Merrill (jason@redhat.com)

[-- Attachment #1: Type: text/plain, Size: 578 bytes --]



> -----Original Message-----
> From: Richard Henderson [mailto:rth@redhat.com]
> Sent: Friday, June 21, 2013 1:00 PM
> To: Iyer, Balaji V
> Cc: Aldy Hernandez; gcc-patches@gcc.gnu.org; Jason Merrill
> (jason@redhat.com)
> Subject: Re: [PATCH] Cilk Plus Array Notation for C++
> 
> On 06/21/2013 09:59 AM, Iyer, Balaji V wrote:
> > After I remove that field, will it be OK for trunk?
> 
> Yes.

Thanks! I have removed the count_down field and have committed the patch. Here is the updated patch for your reference.

Thanks,

Balaji V. Iyer.

> 
> 
> r~

[-- Attachment #2: patch_array_notation_cpp.txt --]
[-- Type: text/plain, Size: 127321 bytes --]

Index: gcc/c-family/ChangeLog
===================================================================
--- gcc/c-family/ChangeLog	(revision 200318)
+++ gcc/c-family/ChangeLog	(working copy)
@@ -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: gcc/c-family/c-common.h
===================================================================
--- gcc/c-family/c-common.h	(revision 200318)
+++ gcc/c-family/c-common.h	(working copy)
@@ -1160,6 +1160,29 @@
   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 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: gcc/c-family/array-notation-common.c
===================================================================
--- gcc/c-family/array-notation-common.c	(revision 200318)
+++ gcc/c-family/array-notation-common.c	(working copy)
@@ -560,3 +560,100 @@
     } 
   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: gcc/testsuite/ChangeLog
===================================================================
--- gcc/testsuite/ChangeLog	(revision 200318)
+++ gcc/testsuite/ChangeLog	(working copy)
@@ -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: gcc/testsuite/g++.dg/dg.exp
===================================================================
--- gcc/testsuite/g++.dg/dg.exp	(revision 200318)
+++ gcc/testsuite/g++.dg/dg.exp	(working copy)
@@ -33,6 +33,7 @@
 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/*]
Index: gcc/testsuite/g++.dg/cilk-plus/AN/braced_list.cc
===================================================================
--- gcc/testsuite/g++.dg/cilk-plus/AN/braced_list.cc	(revision 0)
+++ gcc/testsuite/g++.dg/cilk-plus/AN/braced_list.cc	(revision 0)
@@ -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;
+}
Index: gcc/testsuite/g++.dg/cilk-plus/AN/postincr_test.cc
===================================================================
--- gcc/testsuite/g++.dg/cilk-plus/AN/postincr_test.cc	(revision 0)
+++ gcc/testsuite/g++.dg/cilk-plus/AN/postincr_test.cc	(revision 0)
@@ -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;
+}
Index: gcc/testsuite/g++.dg/cilk-plus/AN/array_test_ND_tplt.cc
===================================================================
--- gcc/testsuite/g++.dg/cilk-plus/AN/array_test_ND_tplt.cc	(revision 0)
+++ gcc/testsuite/g++.dg/cilk-plus/AN/array_test_ND_tplt.cc	(revision 0)
@@ -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;
+}
Index: gcc/testsuite/g++.dg/cilk-plus/AN/array_test1_tplt.cc
===================================================================
--- gcc/testsuite/g++.dg/cilk-plus/AN/array_test1_tplt.cc	(revision 0)
+++ gcc/testsuite/g++.dg/cilk-plus/AN/array_test1_tplt.cc	(revision 0)
@@ -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;
+}
Index: gcc/testsuite/g++.dg/cilk-plus/AN/preincr_test.cc
===================================================================
--- gcc/testsuite/g++.dg/cilk-plus/AN/preincr_test.cc	(revision 0)
+++ gcc/testsuite/g++.dg/cilk-plus/AN/preincr_test.cc	(revision 0)
@@ -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;
+}
Index: gcc/testsuite/g++.dg/cilk-plus/AN/array_test2_tplt.cc
===================================================================
--- gcc/testsuite/g++.dg/cilk-plus/AN/array_test2_tplt.cc	(revision 0)
+++ gcc/testsuite/g++.dg/cilk-plus/AN/array_test2_tplt.cc	(revision 0)
@@ -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;
+}
Index: gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_mutating_tplt.cc
===================================================================
--- gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_mutating_tplt.cc	(revision 0)
+++ gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_mutating_tplt.cc	(revision 0)
@@ -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;
+}
+
Index: gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_custom_tplt.cc
===================================================================
--- gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_custom_tplt.cc	(revision 0)
+++ gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_custom_tplt.cc	(revision 0)
@@ -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;
+}
+
Index: gcc/testsuite/g++.dg/cilk-plus/AN/fp_triplet_values_tplt.c
===================================================================
--- gcc/testsuite/g++.dg/cilk-plus/AN/fp_triplet_values_tplt.c	(revision 0)
+++ gcc/testsuite/g++.dg/cilk-plus/AN/fp_triplet_values_tplt.c	(revision 0)
@@ -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;
+} 
Index: gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp
===================================================================
--- gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp	(revision 0)
+++ gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp	(revision 0)
@@ -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: gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c
===================================================================
--- gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c	(revision 200318)
+++ gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c	(working copy)
@@ -5,7 +5,8 @@
 {
   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: gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c
===================================================================
--- gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c	(revision 200318)
+++ gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c	(working copy)
@@ -5,7 +5,8 @@
 {
   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: gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c
===================================================================
--- gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c	(revision 200318)
+++ gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c	(working copy)
@@ -5,7 +5,7 @@
 {
   int array[10][10], array2[10];
   
-  array2[:] = array2[::] ;  /* { dg-error " expected ']' before ':' token" } */
+  array2[:] = array2[ : : ] ;  /* { dg-error " expected ']' before ':' token" }  */
 
   return 0;
 }
Index: gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c
===================================================================
--- gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c	(revision 200318)
+++ gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c	(working copy)
@@ -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)
 {
Index: gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c
===================================================================
--- gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c	(revision 200318)
+++ gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c	(working copy)
@@ -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: gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c
===================================================================
--- gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c	(revision 200318)
+++ gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c	(working copy)
@@ -8,4 +8,4 @@
   array2[:] = array2[: ;  /* { dg-error "expected ']'" } */
 
   return 0;
-} /* { dg-error "expected ';' before" } */
+} /* { dg-error "expected ';' before" "" { target c } } */
Index: gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c
===================================================================
--- gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c	(revision 200318)
+++ gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c	(working copy)
@@ -18,19 +18,19 @@
     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 @@
     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: gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
===================================================================
--- gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c	(revision 200318)
+++ gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c	(working copy)
@@ -73,13 +73,13 @@
   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: gcc/cp/typeck.c
===================================================================
--- gcc/cp/typeck.c	(revision 200318)
+++ gcc/cp/typeck.c	(working copy)
@@ -3005,6 +3005,22 @@
       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 @@
       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,9 +3956,16 @@
 	}
     }
 
-  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.  */
   code0 = TREE_CODE (type0);
@@ -5140,6 +5167,13 @@
 
   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 @@
   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: gcc/cp/Make-lang.in
===================================================================
--- gcc/cp/Make-lang.in	(revision 200318)
+++ gcc/cp/Make-lang.in	(working copy)
@@ -80,7 +80,7 @@
  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 @@
 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: gcc/cp/error.c
===================================================================
--- gcc/cp/error.c	(revision 200318)
+++ gcc/cp/error.c	(working copy)
@@ -1071,6 +1071,17 @@
       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 @@
       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: gcc/cp/tree.c
===================================================================
--- gcc/cp/tree.c	(revision 200318)
+++ gcc/cp/tree.c	(working copy)
@@ -141,6 +141,7 @@
     case INDIRECT_REF:
     case ARROW_EXPR:
     case ARRAY_REF:
+    case ARRAY_NOTATION_REF:
     case PARM_DECL:
     case RESULT_DECL:
       return clk_ordinary;
Index: gcc/cp/ChangeLog
===================================================================
--- gcc/cp/ChangeLog	(revision 200318)
+++ gcc/cp/ChangeLog	(working copy)
@@ -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: gcc/cp/cp-array-notation.c
===================================================================
--- gcc/cp/cp-array-notation.c	(revision 0)
+++ gcc/cp/cp-array-notation.c	(revision 0)
@@ -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: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c	(revision 200318)
+++ gcc/cp/pt.c	(working copy)
@@ -13753,6 +13753,20 @@
 				 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 @@
       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 @@
       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: gcc/cp/semantics.c
===================================================================
--- gcc/cp/semantics.c	(revision 200318)
+++ gcc/cp/semantics.c	(working copy)
@@ -779,6 +779,22 @@
   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 @@
 				       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 @@
       want_rval = true;
       /* Fall through.  */
     case ARRAY_REF:
+    case ARRAY_NOTATION_REF:
     case ARRAY_RANGE_REF:
     case MEMBER_REF:
     case DOTSTAR_EXPR:
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 200318)
+++ gcc/cp/parser.c	(working copy)
@@ -6060,6 +6060,170 @@
   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 @@
   /* 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);
 
-  /* 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);
 
-  /* 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;
-
+	  /* 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 @@
   /* 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 @@
 
 	    /* 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 @@
 	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_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_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 @@
 	    {
 	      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_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 @@
 
   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: gcc/cp/call.c
===================================================================
--- gcc/cp/call.c	(revision 200318)
+++ gcc/cp/call.c	(working copy)
@@ -5858,9 +5858,15 @@
 	    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 @@
 	    }
 	}
 
-      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
Index: gcc/cp/cp-objcp-common.c
===================================================================
--- gcc/cp/cp-objcp-common.c	(revision 200318)
+++ gcc/cp/cp-objcp-common.c	(working copy)
@@ -321,6 +321,7 @@
   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: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h	(revision 200318)
+++ gcc/cp/cp-tree.h	(working copy)
@@ -6138,6 +6138,10 @@
 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 */

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH] Cilk Plus Array Notation for C++
  2013-06-20 23:39                     ` Iyer, Balaji V
  2013-06-21 16:11                       ` Richard Henderson
@ 2013-06-22 16:20                       ` Jason Merrill
  2013-06-24 15:16                         ` Jason Merrill
  2013-06-24 22:23                         ` Iyer, Balaji V
  1 sibling, 2 replies; 40+ messages in thread
From: Jason Merrill @ 2013-06-22 16:20 UTC (permalink / raw)
  To: Iyer, Balaji V, Richard Henderson; +Cc: Aldy Hernandez, gcc-patches

Hmm, seems like I should have sent this yesterday even though I hadn't 
made it through the whole patch.  But I suppose it doesn't hurt to fix 
it after checkin.

On 06/20/2013 07:39 PM, Iyer, Balaji V wrote:
> diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
> old mode 100644
> new mode 100755
> index a0f195b..fb70520
> Binary files a/gcc/c-family/ChangeLog and b/gcc/c-family/ChangeLog differ

Why are you marking lots of files as executable?

In the future please filter out ChangeLogs entirely from diffs.  I use

   filterdiff -x '*/ChangeLog' | sed -e '/^diff.*ChangeLog/{N;d}'

for my own patches.

> +      if (flag_enable_cilkplus
> +         && (contains_array_notation_expr (expr)
> +             || contains_array_notation_expr (fn)))

Looking at "fn" here doesn't make sense; it's only used for diagnostics.

> +       /* If we are using array notations, we fix them up at a later stage
> +          and we will do these checks then.  */
> +       ;

And please don't mess with the overload resolution code directly to 
handle this case differently.

This seems to be a general problem with the patch; you are 
special-casing array notation all through the compiler rather than 
making it work with the existing mechanisms.

In this case, an ARRAY_NOTATION_REF should have a type that participates 
normally with conversions.

>> +      /* If the function call is builtin array notation function then no need
>> +        to do any type conversion.  */

And here, instead of changing build_over_call, you can use the existing 
magic_varargs_p mechanism.

> +/* 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

"where"

> +   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

Drop "called VALUE_TREE"; the function comment shouldn't talk about 
local variables.

> +  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;

Now that the compiler is built as C++, variables should be defined at 
the point of first use, rather than at the top of the function.

> +         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");

I think this should handle all non-array types, rather than just 
pointers and classes.

Let's say "notation" rather than "notations" in all diagnostics.

> +                     error_at (loc, "array notations cannot be used with"
> +                               " function pointer arrays");

I don't see this restriction in any of the documentation.  What's the 
rationale?

> +             error_at (loc, "start-index and length fields necessary for "
> +                       "using array notations in dimensionless arrays");

Let's say "...with array of unknown bound"

> +         start_index = fold_build1 (CONVERT_EXPR, ptrdiff_type_node,
> +                                    start_index);

Use cp_fold_convert rather than fold_build1.

> +         x = TREE_INT_CST (TYPE_MAXVAL (array_type_domain));
> +         x.low++;
> +         length_index = double_int_to_tree (integer_type_node, x);

This assumes a constant length array.  Use size_binop instead.

> +         stride = build_int_cst (integer_type_node, 1);
> +         stride = fold_build1 (CONVERT_EXPR, ptrdiff_type_node, stride);

Build the constant in ptrdiff_type_node rather than build it in 
integer_type_node and then convert.

> +             /* 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;

Why do you do this for the stride?  We've already seen both 
array-notation colons at this point.

> +  /* We fold all 3 of the values to make things easier when we transform
> +     them later.  */

Why is this better than folding at transformation time?

> +    /* If we are here, then we have something like this:
> +       ARRAY[:]
> +    */

The */ should go at the end of the last line in all comments.

> -  if (for_offsetof)
> -    index = cp_parser_constant_expression (parser, false, NULL);
...
>    else
>      {
> -      if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
...
> +      if (for_offsetof)
> +       index = cp_parser_constant_expression (parser, false, NULL);
> +      else

Please try to avoid re-indenting code when possible, to make history 
annotation simpler.

Actually, to reduce the amount of changes to non-AN code, let's put the 
AN case third, after the offset and {} cases, so you get something like

else if (flag_enable_cilkplus)
   {
     tree an = cp_parser_array_notation (loc, parser, &index,
				        postfix_expression);
     if (an)
       return an;
     /* Otherwise, cp_parser_array_notation set 'index'. */
   }
else
   index = cp_parser_expression (parser, /*cast_p=*/false, NULL);

this way the change is just a few added lines, and everything else is in 
cp_parser_array_notation.

> +  if (flag_enable_cilkplus && contains_array_notation_expr (compound_stmt))
> +    compound_stmt = expand_array_notation_exprs (compound_stmt);
...
> +  /* 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);
...
> +  /* 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));

Let's do the transformation in cp_genericize rather than in these places.

Perhaps moving the expansion to gimplification time would also help with 
sharing code between C and C++, since you don't have to worry about 
templates at that point.

> +           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;
> +             }
[etc]

I'd prefer to give diagnostics about uses that don't make sense at 
transformation time, rather than parsing time.

> +             if (flag_enable_cilkplus
> +                 && cp_lexer_next_token_is (parser->lexer, CPP_COLON))
> +               {
> +                 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);
> +               }

I'm concerned about this causing trouble with tentative parsing, and I 
think that people are unlikely to try to write a declaration using array 
notation, so let's leave out the changes to cp_parser_direct_declarator.

> @@ -15758,6 +15772,9 @@ type_unification_real (tree tparms,
> +      if (flag_enable_cilkplus && TREE_CODE (arg) == ARRAY_NOTATION_REF)
> +       return 1;

Again, an ARRAY_NOTATION_REF should have a type like any other 
expression; we don't need to prevent it from participating in type 
deduction.

> @@ -8073,6 +8089,7 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t,
> +    case ARRAY_NOTATION_REF:
> @@ -8884,6 +8901,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
> +    case ARRAY_NOTATION_REF:

cxx_eval_array_reference doesn't know how to deal with 
ARRAY_NOTATION_REF, so let's not add it to cxx_eval_constant_expression, 
and return false for it from potential_constant_expression_1.

> +  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);

Another change that should be replaced by addition to magic_varargs_p, 
though it looks like convert_arguments needs to be updated to use 
magic_varargs_p rather than checking specifically for BUILT_IN_CONSTANT_P.

> +  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);
> +      }

Why not use safe_grow_cleared for the sub-vecs as well?

> +      while (ii_tree)
> +       if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)

Wrap the sub-statement of the 'while' in { }.

> +       else if (TREE_CODE (ii_tree) == VAR_DECL
> +                || TREE_CODE (ii_tree) == CALL_EXPR
> +                || TREE_CODE (ii_tree) == PARM_DECL)
> +         break;
> +       else
> +         gcc_unreachable ();

There are lots of other ways to get an expression of array type, why are 
only these allowed?

> +      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)

How could the array_exprs element be anything other than an 
ARRAY_NOTATION_REF?  That's all you put in when you were building it.

By the way, why are you breaking out the elements of the 
ARRAY_NOTATION_REF into a cilkplus_an_parts rather than using the _REF 
directly?

> +    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])))

Why check for ADDR_EXPR here?  Better for is_sec_implicit_index_fn to 
return false if its argument isn't what's desired.

> +       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;

Reorder these cases so you don't need to check idx >= 0.

> +   same dimension and one the same side of the equal sign.  The Array notation

"on the same side"

> +                 l_node = int_cst_value (list[ii][jj].length);
> +                 l_length = int_cst_value (length);
> +                 if (absu_hwi (l_length) != absu_hwi (l_node))

Use tree_int_cst_equal instead.

> +  for (jj = 0; jj < y; jj++)
> +    {
> +      length = NULL_TREE;
> +      for (ii = 0; ii < x; ii++)

Why did you switch the outer/inner iteration variables for this loop 
compared to others?

> +           /* We set the length node as the current node just in case it turns
> +              out to be an integer.  */
> +           length = list[ii][jj].length;

How could it "turn out" to be an integer?  We just checked, and it isn't 
one.

> +      var = build_decl (loc, VAR_DECL, NULL_TREE, integer_type_node);
> +      finish_expr_stmt (build_x_modify_expr (loc, var, NOP_EXPR, *value, cry));

This should use get_temp_regvar.

We shouldn't need to pass tsubst_flags_t around, since we will never be 
expanding array notation in SFINAE context.

> +           /* 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))

This seems impossible, since 'var' is created to have the same type as 
'start'.

> +               /* 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 -.  */

Maybe the induction variable should always be ptrdiff_type_node.

Jason

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH] Cilk Plus Array Notation for C++
  2013-06-22 16:20                       ` Jason Merrill
@ 2013-06-24 15:16                         ` Jason Merrill
  2013-06-24 22:23                         ` Iyer, Balaji V
  1 sibling, 0 replies; 40+ messages in thread
From: Jason Merrill @ 2013-06-24 15:16 UTC (permalink / raw)
  To: Iyer, Balaji V, Richard Henderson; +Cc: Aldy Hernandez, gcc-patches

A few more comments:

> +         if (processing_template_decl || !TREE_TYPE (t))
> +           new_var = build_min_nt_loc (EXPR_LOCATION (t), VAR_DECL, NULL_TREE,
> +                                       NULL_TREE);

Again, we shouldn't be trying to expand array notation during template 
parsing.

And replace_invariant_exprs should also use get_temp_regvar, as should 
most of the places you create temporary variables.

> +      /* 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!  */

Again, magic_varargs_p can avoid any gratuitous type conversions.

> +    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;

I would expect boolean_type_node.

> +      an_loop_info[ii].var = build_decl (location, VAR_DECL, NULL_TREE,
> +                                 TREE_TYPE (an_info[0][ii].start));

Here you can use create_temporary_var.

> +      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);

Here and in other calls to build_x_modify_expr for initialization, use 
INIT_EXPR rather than NOP_EXPR.

> +       *new_var = create_tmp_var (new_var_type, NULL);

create_tmp_var is part of gimplification; it might be appropriate to use 
it when you move lowering to happen later in the compilation, but it 
seems wrong in the current code.

> +      code = (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO) ? EQ_EXPR
> +       : NE_EXPR;

A ?: expression split across multiple lines should have parens around it.

> +  /* 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;
> +       }
> +    }

The comment makes it sound like the else should be gcc_unreachable.

> +      if (location == UNKNOWN_LOCATION && EXPR_HAS_LOCATION (rhs))
> +       location = EXPR_LOCATION (rhs);

This is redundant with code a few lines above.

> +         append_to_statement_list_force (lhs_an_loop_info[ii].ind_init,
> +                                         &init_list);

Why do you need _force?

Jason

^ permalink raw reply	[flat|nested] 40+ messages in thread

* RE: [PATCH] Cilk Plus Array Notation for C++
  2013-06-22 16:20                       ` Jason Merrill
  2013-06-24 15:16                         ` Jason Merrill
@ 2013-06-24 22:23                         ` Iyer, Balaji V
  2013-06-25 14:38                           ` Jason Merrill
  1 sibling, 1 reply; 40+ messages in thread
From: Iyer, Balaji V @ 2013-06-24 22:23 UTC (permalink / raw)
  To: Jason Merrill, Richard Henderson; +Cc: Aldy Hernandez, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 20332 bytes --]

Hi Jason,
	Please see below for my responses to your questions. I am also attaching a fixed patch (diffed with trunk's head) and Changelog entries.

Thanks,

Balaji V. Iyer.

> -----Original Message-----
> From: Jason Merrill [mailto:jason@redhat.com]
> Sent: Saturday, June 22, 2013 12:20 PM
> To: Iyer, Balaji V; Richard Henderson
> Cc: Aldy Hernandez; gcc-patches@gcc.gnu.org
> Subject: Re: [PATCH] Cilk Plus Array Notation for C++
> 
> Hmm, seems like I should have sent this yesterday even though I hadn't made it
> through the whole patch.  But I suppose it doesn't hurt to fix it after checkin.
> 
> On 06/20/2013 07:39 PM, Iyer, Balaji V wrote:
> > diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog old mode
> > 100644 new mode 100755 index a0f195b..fb70520 Binary files
> > a/gcc/c-family/ChangeLog and b/gcc/c-family/ChangeLog differ
> 
> Why are you marking lots of files as executable?

I think the reason why this is happening is that I use emacs on my windows machine and it is doing some conversion. Is there a way to tell emacs not to do this?

> 
> In the future please filter out ChangeLogs entirely from diffs.  I use
> 
>    filterdiff -x '*/ChangeLog' | sed -e '/^diff.*ChangeLog/{N;d}'
> 
> for my own patches.

OK. I generally don't include the changelog entries, but the last one was a mistake. I will make sure it doesn't happen again.

> 
> > +      if (flag_enable_cilkplus
> > +         && (contains_array_notation_expr (expr)
> > +             || contains_array_notation_expr (fn)))
> 
> Looking at "fn" here doesn't make sense; it's only used for diagnostics.

Fixed!

> 
> > +       /* If we are using array notations, we fix them up at a later stage
> > +          and we will do these checks then.  */
> > +       ;
> 
> And please don't mess with the overload resolution code directly to handle this
> case differently.

Fixed! Removed the code. It was an artifact of a previous implementation. Things works fine even without it.

> 
> This seems to be a general problem with the patch; you are special-casing array
> notation all through the compiler rather than making it work with the existing
> mechanisms.
> 
> In this case, an ARRAY_NOTATION_REF should have a type that participates
> normally with conversions.

Yep, it is done that way.

> 
> >> +      /* If the function call is builtin array notation function then no need
> >> +        to do any type conversion.  */
> 
> And here, instead of changing build_over_call, you can use the existing
> magic_varargs_p mechanism.

Fixed!

> 
> > +/* 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
> 
> "where"

Fixed!

> 
> > +   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
> 
> Drop "called VALUE_TREE"; the function comment shouldn't talk about local
> variables.

Fixed!

> 
> > +  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;
> 
> Now that the compiler is built as C++, variables should be defined at the point of
> first use, rather than at the top of the function.
> 

Fixed!

> > +         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");
> 
> I think this should handle all non-array types, rather than just pointers and
> classes.
> 
> Let's say "notation" rather than "notations" in all diagnostics.

I think I have fixed them all.

> 
> > +                     error_at (loc, "array notations cannot be used with"
> > +                               " function pointer arrays");
> 
> I don't see this restriction in any of the documentation.  What's the rationale?
> 

Sorry, that was a mistake on my part. I have fixed it.

> > +             error_at (loc, "start-index and length fields necessary for "
> > +                       "using array notations in dimensionless
> > + arrays");
> 
> Let's say "...with array of unknown bound"

Fixed!

> 
> > +         start_index = fold_build1 (CONVERT_EXPR, ptrdiff_type_node,
> > +                                    start_index);
> 
> Use cp_fold_convert rather than fold_build1.

Fixed!

> 
> > +         x = TREE_INT_CST (TYPE_MAXVAL (array_type_domain));
> > +         x.low++;
> > +         length_index = double_int_to_tree (integer_type_node, x);
> 
> This assumes a constant length array.  Use size_binop instead.

Fixed!

> 
> > +         stride = build_int_cst (integer_type_node, 1);
> > +         stride = fold_build1 (CONVERT_EXPR, ptrdiff_type_node,
> > + stride);
> 
> Build the constant in ptrdiff_type_node rather than build it in integer_type_node
> and then convert.

Fixed!
> 
> > +             /* 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;
> 
> Why do you do this for the stride?  We've already seen both array-notation
> colons at this point.
> 
I removed it.

> > +  /* We fold all 3 of the values to make things easier when we transform
> > +     them later.  */
> 
> Why is this better than folding at transformation time?

Fixed! We are already folding before transformation.

> 
> > +    /* If we are here, then we have something like this:
> > +       ARRAY[:]
> > +    */
> 
> The */ should go at the end of the last line in all comments.

Fixed!

> 
> > -  if (for_offsetof)
> > -    index = cp_parser_constant_expression (parser, false, NULL);
> ...
> >    else
> >      {
> > -      if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
> ...
> > +      if (for_offsetof)
> > +       index = cp_parser_constant_expression (parser, false, NULL);
> > +      else
> 
> Please try to avoid re-indenting code when possible, to make history annotation
> simpler.
> 

OK. 

> Actually, to reduce the amount of changes to non-AN code, let's put the AN case
> third, after the offset and {} cases, so you get something like
> 
> else if (flag_enable_cilkplus)
>    {
>      tree an = cp_parser_array_notation (loc, parser, &index,
> 				        postfix_expression);
>      if (an)
>        return an;
>      /* Otherwise, cp_parser_array_notation set 'index'. */
>    }
> else
>    index = cp_parser_expression (parser, /*cast_p=*/false, NULL);
> 
> this way the change is just a few added lines, and everything else is in
> cp_parser_array_notation.

If I do it this way, then I don't think I will be able to handle a normal array reference when cilk plus is enabled. One thing I could do is to assume that people won't use array notations in braced list. I had it like this a while back but I made the change to make sure I have covered more cases. Please let me know if that is OK and I will fix it.

> 
> > +  if (flag_enable_cilkplus && contains_array_notation_expr
> (compound_stmt))
> > +    compound_stmt = expand_array_notation_exprs (compound_stmt);
> ...
> > +  /* 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);
> ...
> > +  /* 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));
> 
> Let's do the transformation in cp_genericize rather than in these places.
> 
> Perhaps moving the expansion to gimplification time would also help with
> sharing code between C and C++, since you don't have to worry about templates
> at that point.

I moved the array notation expansion to cp_generize_tree function. I have also removed the expansion in pt.c

> 
> > +           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;
> > +             }
> [etc]
> 
> I'd prefer to give diagnostics about uses that don't make sense at
> transformation time, rather than parsing time.

Fixed!

> 
> > +             if (flag_enable_cilkplus
> > +                 && cp_lexer_next_token_is (parser->lexer, CPP_COLON))
> > +               {
> > +                 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);
> > +               }
> 
> I'm concerned about this causing trouble with tentative parsing, and I think that
> people are unlikely to try to write a declaration using array notation, so let's
> leave out the changes to cp_parser_direct_declarator.

Ok. I have removed it.

> 
> > @@ -15758,6 +15772,9 @@ type_unification_real (tree tparms,
> > +      if (flag_enable_cilkplus && TREE_CODE (arg) == ARRAY_NOTATION_REF)
> > +       return 1;
> 
> Again, an ARRAY_NOTATION_REF should have a type like any other expression;
> we don't need to prevent it from participating in type deduction.

Yep. This is fixed also.

> 
> > @@ -8073,6 +8089,7 @@ cxx_eval_constant_expression (const
> > constexpr_call *call, tree t,
> > +    case ARRAY_NOTATION_REF:
> > @@ -8884,6 +8901,7 @@ potential_constant_expression_1 (tree t, bool
> > want_rval, tsubst_flags_t flags)
> > +    case ARRAY_NOTATION_REF:
> 
> cxx_eval_array_reference doesn't know how to deal with
> ARRAY_NOTATION_REF, so let's not add it to cxx_eval_constant_expression,
> and return false for it from potential_constant_expression_1.

Fixed as you suggested.

> 
> > +  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);
> 
> Another change that should be replaced by addition to magic_varargs_p, though
> it looks like convert_arguments needs to be updated to use magic_varargs_p
> rather than checking specifically for BUILT_IN_CONSTANT_P.

I looked into this. But, magic_varargs_p is static to call.c. Should I make it non-static? After making it non-static I was planning to do something like this:

if (magic_varargs_p (fndecl)
  Nargs = (*params)->length ();
else
   nargs = convert_arguments (...)

Is that OK with you?

> 
> > +  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);
> > +      }
> 
> Why not use safe_grow_cleared for the sub-vecs as well?

Fixed!

> 
> > +      while (ii_tree)
> > +       if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
> 
> Wrap the sub-statement of the 'while' in { }.
> 

Fixed!

> > +       else if (TREE_CODE (ii_tree) == VAR_DECL
> > +                || TREE_CODE (ii_tree) == CALL_EXPR
> > +                || TREE_CODE (ii_tree) == PARM_DECL)
> > +         break;
> > +       else
> > +         gcc_unreachable ();
> e
> There are lots of other ways to gt an expression of array type, why are only
> these allowed?
>

Sorry, it was a mistake as well. The main point of that loop was to allow array refs intermingling with array notations.
 
> > +      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)
> 
> How could the array_exprs element be anything other than an
> ARRAY_NOTATION_REF?  That's all you put in when you were building it.
> 

Fixed!

> By the way, why are you breaking out the elements of the
> ARRAY_NOTATION_REF into a cilkplus_an_parts rather than using the _REF
> directly?
> 

I use the different parts of array notations for error checking and to create the outer for-loop. Also, to create the ARRAY_REF I need the induction variable.

> > +    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])))
> 
> Why check for ADDR_EXPR here?  Better for is_sec_implicit_index_fn to return
> false if its argument isn't what's desired.

Fixed!

> 
> > +       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;
> 
> Reorder these cases so you don't need to check idx >= 0.

Fixed!

> 
> > +   same dimension and one the same side of the equal sign.  The Array
> > + notation
> 
> "on the same side"

Fixed! (Sorry for the stupid mistake).

> 
> > +                 l_node = int_cst_value (list[ii][jj].length);
> > +                 l_length = int_cst_value (length);
> > +                 if (absu_hwi (l_length) != absu_hwi (l_node))
> 
> Use tree_int_cst_equal instead.

Fixed!

> 
> > +  for (jj = 0; jj < y; jj++)
> > +    {
> > +      length = NULL_TREE;
> > +      for (ii = 0; ii < x; ii++)
> 
> Why did you switch the outer/inner iteration variables for this loop compared to
> others?

The y axis represents the rank and  x-axis represents the expressions in the polynomial. So, for-each rank I go through all the expressions  to make sure the lengths are the same.

> 
> > +           /* We set the length node as the current node just in case it turns
> > +              out to be an integer.  */
> > +           length = list[ii][jj].length;
> 
> How could it "turn out" to be an integer?  We just checked, and it isn't one.
> 

We have not checked list[ii][jj].length is an integer. I agree that I should clarify the comment. I have fixed that.

> > +      var = build_decl (loc, VAR_DECL, NULL_TREE, integer_type_node);
> > +      finish_expr_stmt (build_x_modify_expr (loc, var, NOP_EXPR,
> > + *value, cry));
> 
> This should use get_temp_regvar.
> 
> We shouldn't need to pass tsubst_flags_t around, since we will never be
> expanding array notation in SFINAE context.

Fixed! By the way, what is SFINAE?

> 
> > +           /* 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))
> 
> This seems impossible, since 'var' is created to have the same type as 'start'.

As you suggested further in the email, I have made var of type ptrdiff_type, so I think I should keep this.

> 
> > +               /* 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 -.  */
> 
> Maybe the induction variable should always be ptrdiff_type_node.

Yep. Fixed!

> 
> Jason

COPY- PASTING your  last responde from  thread (http://gcc.gnu.org/ml/gcc-patches/2013-06/msg01385.html) below:

> A few more comments:
> 
> > +         if (processing_template_decl || !TREE_TYPE (t))
> > +           new_var = build_min_nt_loc (EXPR_LOCATION (t), VAR_DECL,
> NULL_TREE,
> > +                                       NULL_TREE);
> 
> Again, we shouldn't be trying to expand array notation during template parsing.

Fixed!

> 
> And replace_invariant_exprs should also use get_temp_regvar, as should most
> of the places you create temporary variables.

Fixed!

> 
> > +      /* 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!  */
> 
> Again, magic_varargs_p can avoid any gratuitous type conversions.
> 

Please see my comment above about magic_varargs_p.

> > +    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;
> 
> I would expect boolean_type_node.

Yep. Fixed!
> 
> > +      an_loop_info[ii].var = build_decl (location, VAR_DECL, NULL_TREE,
> > +                                 TREE_TYPE (an_info[0][ii].start));
> 
> Here you can use create_temporary_var.
> 

Fixed!

> > +      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);
> 
> Here and in other calls to build_x_modify_expr for initialization, use INIT_EXPR
> rather than NOP_EXPR.
> 
Fixed!

> > +       *new_var = create_tmp_var (new_var_type, NULL);
> 
> create_tmp_var is part of gimplification; it might be appropriate to use it when
> you move lowering to happen later in the compilation, but it seems wrong in the
> current code.

Removed and replaced it with create_temporary_var.

> 
> > +      code = (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO) ?
> EQ_EXPR
> > +       : NE_EXPR;
> 
> A ?: expression split across multiple lines should have parens around it.
> 

Fixed!

> > +  /* 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;
> > +       }
> > +    }
> 
> The comment makes it sound like the else should be gcc_unreachable.
> 

Yes, I added gcc_unreachable there.

> > +      if (location == UNKNOWN_LOCATION && EXPR_HAS_LOCATION (rhs))
> > +       location = EXPR_LOCATION (rhs);
> 
> This is redundant with code a few lines above.

Fixed!

> 
> > +         append_to_statement_list_force (lhs_an_loop_info[ii].ind_init,
> > +                                         &init_list);
> 
> Why do you need _force?
> 

No reason. Just wanted to make sure it surely gets in. I have removed it.

> Jason


[-- Attachment #2: CL.txt --]
[-- Type: text/plain, Size: 3968 bytes --]

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

        * builtins.def: Fixed the function type of CILKPLUS_BUILTIN.

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

        * c-parser.c (c_parser_array_notation): Removed rejection of array
        notations in an array of function pointers.

gcc/c-family/ChangeLog
2013-06-24  Balaji V. Iyer  <balaji.v.iyer@intel.com>

        * array-notation-common.c (length_mismatch_in_expr_p): Collapsed two
        if-statements and compared the trees directly using tree_int_cst_equal.
        (find_rank): Checked for array notations in function name to handle
        array notations in function pointers.
        (extract_array_notation_exprs): Likewise.
        (cilkplus_extract_an_triplets): Removed restriction of array notations
        having just VAR, PARM DECL or CALL exprs.
        (replace_array_notations): Likewise.
        (cilkplus_extract_an_triplets): Replaced safe_push with
        safe_grow_cleared.  Also removed an unnecessary check to see if the
        node is of type ARRAY_NOTATION_REF.
        (fix_sec_implicit_args): Removed an unnecessary check for ADDR_EXPR.
        Also switched two if-statements to remove an unnecessary comparison.


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

        * parser.c (cp_parser_array_notation): Removed rejection array notation
        of type function pointers.  Used cp_fold_convert instead of fold_build1.
        Moved variable that saves colon corrects variable into the if-statement.
        (cp_parser_compound_statement): Removed expansion of array notations.
        (cp_parser_ctor_initializer_opt_and_function_body): Likewise.
        (cp_parser_function_definition_after_declarator): Likewise.
        (cp_parser_selection_statement): Removed error reporting.
        (cp_parser_iteration_statement): Likewise.
        (cp_parser_direct_declarator): Removed error checking/reporting if
        array notations are used in the declarator.
        * pt.c (instantiate_decl): Likewise.
        (type_unification_real): Removed a check for ARRAY_NOTATION_REF.
        (cxx_eval_constant_expression): Removed ARRAY_NOTATION_REF case.
        (potential_constant_expression_1): Returned false for ARRAY_NOTATION_REF
        case.
        * cp-gimplify.c (cp_genericize): Added expansion of array notation
        expressions here.
        * cp-array-notation.c (cp_length_mismatch_in_expr_p): Combined two
        if statements into one and compared integers using tree_int_cst_equal.
        (make_triplet_val_inv): Removed loc and cry parameters.  Also, replaced
        build_decls with get_temp_regvar.
        (replace_invariant_var): Replaced build_decl and build_min_nt_loc with
        get_temp_regvar.
        (expand_an_in_modify_expr): Ditto. Replaced body of redundant else with
        gcc_unreachable.  Removed few unwanted checks. Made induction variable
        type as ptrdiff_type.  Removed loc and complain arguments passed into
        make_triplet_val_inv.  Replaced all modify expression's code from NOP
        EXPR to INIT EXPR.  Replaced all forceful appending into stmt. list
        with the non-forceful one.
        (expand_reduce_builtin): All changes mentioned in above function
        expand_an_in_modify_expr.  Made the new variable type of
        SEC_REDUCE_ANY/ALL_{NON}ZERO intrinsic functions as bool.
        (expand_array_notation_exprs): Removed SWITCH_EXPR case.  Moved all
        the error reporting from parser to this function.
        (cilkplus_an_triplet_types_ok_p): Removed rejection of array notation
        in function pointers.
        * call.c (convert_like_real): Removed a check for array notation
        expression in a function.
        (build_over_call): Likewise.
        (magic_varargs_p): Added a check for builtin array notation function.


[-- Attachment #3: diff.txt --]
[-- Type: text/plain, Size: 62902 bytes --]

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 8f45983..d81f7ce 100644
Binary files a/gcc/ChangeLog and b/gcc/ChangeLog differ
diff --git a/gcc/builtins.def b/gcc/builtins.def
index 91879a6..9b55b1f 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -158,9 +158,9 @@ along with GCC; see the file COPYING3.  If not see
 	       (flag_asan || flag_tsan))
 
 #undef DEF_CILKPLUS_BUILTIN
-#define DEF_CILKPLUS_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
-  DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
-  	       false, false, true, ATTRS, false, flag_enable_cilkplus)
+#define DEF_CILKPLUS_BUILTIN(ENUM, NAME, TYPE, ATTRS)  \
+  DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, BT_FN_INT_VAR, BT_LAST, \
+  	       false, false, false, ATTRS, false, flag_enable_cilkplus) 
 
 /* Define an attribute list for math functions that are normally
    "impure" because some of them may write into global memory for
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 03269e9..53f35d4 100644
Binary files a/gcc/c-family/ChangeLog and b/gcc/c-family/ChangeLog differ
diff --git a/gcc/c-family/array-notation-common.c b/gcc/c-family/array-notation-common.c
index 0e2a431..ae96941 100644
--- a/gcc/c-family/array-notation-common.c
+++ b/gcc/c-family/array-notation-common.c
@@ -86,7 +86,6 @@ length_mismatch_in_expr_p (location_t loc, tree **list, size_t x, size_t y)
 {
   size_t ii, jj;
   tree start = NULL_TREE;
-  HOST_WIDE_INT l_start, l_node;
   for (jj = 0; jj < y; jj++)
     {
       start = NULL_TREE;
@@ -99,15 +98,11 @@ length_mismatch_in_expr_p (location_t loc, tree **list, size_t x, size_t y)
 	      /* If start 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]) == INTEGER_CST)
-		{
-		  l_node = int_cst_value (list[ii][jj]);
-		  l_start = int_cst_value (start);
-		  if (absu_hwi (l_start) != absu_hwi (l_node))
-		    {
-		      error_at (loc, "length mismatch in expression");
-		      return true;
-		    }
+	      if (TREE_CODE (list[ii][jj]) == INTEGER_CST
+		  && !tree_int_cst_equal (list[ii][jj], start))
+		{ 
+		  error_at (loc, "length mismatch in expression"); 
+		  return true;
 		}
 	    }
 	  else
@@ -269,6 +264,8 @@ find_rank (location_t loc, tree orig_expr, tree expr, bool ignore_builtin_fn,
 		/* If it is a built-in function, then we know it returns a 
 		   scalar.  */
 		return true;
+	  if (!find_rank (loc, orig_expr, func_name, ignore_builtin_fn, rank))
+	    return false;
 	  FOR_EACH_CALL_EXPR_ARG (arg, iter, expr)
 	    {
 	      if (!find_rank (loc, orig_expr, arg, ignore_builtin_fn, rank))
@@ -356,6 +353,9 @@ extract_array_notation_exprs (tree node, bool ignore_builtin_fn,
 	  vec_safe_push (*array_list, node);
 	  return;
 	}
+      /* This will extract array notations in function pointers.  */
+      extract_array_notation_exprs (CALL_EXPR_FN (node), ignore_builtin_fn,
+				    array_list);
       FOR_EACH_CALL_EXPR_ARG (arg, iter, node)
 	extract_array_notation_exprs (arg, ignore_builtin_fn, array_list);
     } 
@@ -431,6 +431,9 @@ replace_array_notations (tree *orig, bool ignore_builtin_fn,
 	      }
 	  return;
 	}
+      /* Fixes array notations in array notations in function pointers.  */
+      replace_array_notations (&CALL_EXPR_FN (*orig), ignore_builtin_fn, list,
+			       array_operand);
       ii = 0;
       FOR_EACH_CALL_EXPR_ARG (arg, iter, *orig)
 	{
@@ -573,53 +576,49 @@ 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++)
+
+  if (rank > 0)
+    for (size_t ii = 0; ii < size; ii++)
       {
-	(*node)[ii].safe_push (init);
-	array_exprs[ii].safe_push (NULL_TREE);
+	(*node)[ii].safe_grow_cleared (rank);
+	array_exprs[ii].safe_grow_cleared (rank);
       }
-
   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 ();	
+	{
+	  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
+	    break;
+	}
     }
     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));
-	    }
+	  {
+	    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
@@ -635,16 +634,15 @@ fix_sec_implicit_args (location_t loc, vec <tree, va_gc> *list,
   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)
+	if (idx < 0)
 	  /* In this case, the returning function would have emitted an
 	     error thus it is not necessary to do so again.  */
 	  return NULL;
+	else if (idx < (int) rank)
+	  vec_safe_push (array_operand, an_loop_info[idx].var);
 	else
 	  {
 	    error_at (loc, "__sec_implicit_index argument %d must be "
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 05766ca..53bfe88 100644
Binary files a/gcc/c/ChangeLog and b/gcc/c/ChangeLog differ
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index d6a500e..c7846ce 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -11053,24 +11053,6 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
 	      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
 	      return error_mark_node;
 	    }
-	  if (TREE_CODE (array_type) == ARRAY_TYPE)
-	    {
-	      tree subtype = TREE_TYPE (array_type);
-	      while (subtype && TREE_CODE (subtype) == POINTER_TYPE)
-		{
-		  /* Now this could be a function pointer.  Find them and
-		     give out an error.  */
-		  subtype = TREE_TYPE (subtype);
-		  if (subtype && TREE_CODE (subtype) == FUNCTION_TYPE)
-		    {
-		      error_at (loc, "array notations cannot be used with "
-				"function pointer arrays");
-		      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
-						 NULL);
-		      return error_mark_node;
-		    }
-		}
-	    }
 	  array_type_domain = TYPE_DOMAIN (array_type);
 
 	  if (!array_type_domain)
@@ -11114,27 +11096,6 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
 	      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
 	      return error_mark_node;
 	    }
-	  if (TREE_CODE (array_type) == ARRAY_TYPE
-	      || TREE_CODE (array_type) == POINTER_TYPE)
-	    {
-	      tree subtype = TREE_TYPE (array_type);
-	      while (subtype
-		     && (TREE_CODE (subtype) == POINTER_TYPE
-			 || TREE_CODE (subtype) == ARRAY_TYPE))
-		{
-		  /* Now this could be a function pointer.  Find them and
-		     give out an error.  */
-		  subtype = TREE_TYPE (subtype);
-		  if (subtype && TREE_CODE (subtype) == FUNCTION_TYPE)
-		    {
-		      error_at (loc, "array notations cannot be used with "
-				"function pointer arrays");
-		      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
-						 NULL);
-		      return error_mark_node;
-		    }
-		}
-	    }
 	  c_parser_consume_token (parser); /* consume the ':' */
 	  end_index = c_parser_expression (parser).value;
 	  if (!end_index || end_index == error_mark_node)
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 55ed6a5..9d570b2 100644
Binary files a/gcc/cp/ChangeLog and b/gcc/cp/ChangeLog differ
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 6817bfc..0350da8 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -5857,16 +5857,9 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
 	  else if (t->kind == ck_identity)
 	    break;
 	}
-
-      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)
+       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);
 
@@ -6518,6 +6511,9 @@ convert_for_arg_passing (tree type, tree val, tsubst_flags_t complain)
 static bool
 magic_varargs_p (tree fn)
 {
+  if (flag_enable_cilkplus && is_cilkplus_reduce_builtin (fn) != BUILT_IN_NONE)
+    return true;
+
   if (DECL_BUILT_IN (fn))
     switch (DECL_FUNCTION_CODE (fn))
       {
@@ -6895,21 +6891,13 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
 		       "  (you can disable this with -fno-deduce-init-list)");
 	    }
 	}
+      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
index 92272b3..1209cb3 100644
--- a/gcc/cp/cp-array-notation.c
+++ b/gcc/cp/cp-array-notation.c
@@ -59,7 +59,6 @@
 #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.  */
@@ -79,7 +78,7 @@ create_an_loop (tree init, tree cond, tree incr, tree body)
 }
 
 /* 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
+   same dimension and on the same side of the equal sign.  The Array notation
    lengths (LIST->LENGTH) is passed in as a 2D vector of trees.  */
 
 static bool
@@ -87,14 +86,13 @@ 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 ();
-  
+  size_t y = list[0].length (); 
+ 
   for (jj = 0; jj < y; jj++)
     {
-      length = NULL_TREE;
+      length = NULL_TREE; 
       for (ii = 0; ii < x; ii++)
 	{
 	  if (!length)
@@ -104,20 +102,16 @@ cp_length_mismatch_in_expr_p (location_t loc, vec<vec<an_parts> >list)
 	      /* 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;
-		    }
+	      if (TREE_CODE (list[ii][jj].length) == INTEGER_CST
+		  && !tree_int_cst_equal (list[ii][jj].length, length))
+		{ 
+		  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.  */
+	    /* We set the list[ii][jj].length as the current node just in case 
+	       it turns out to be an integer.  */
 	    length = list[ii][jj].length;
 	}
     }
@@ -128,17 +122,12 @@ cp_length_mismatch_in_expr_p (location_t loc, vec<vec<an_parts> >list)
    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)
+make_triplet_val_inv (tree *value)
 {
-  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;
-    }
+    *value = get_temp_regvar (integer_type_node, *value);
 }
 
 /* Returns a vector of size RANK that contains an ARRAY_REF.  This vector is
@@ -238,7 +227,7 @@ replace_invariant_exprs (tree *node)
 {
   size_t ix = 0;
   tree node_list = NULL_TREE;
-  tree t = NULL_TREE, new_var = NULL_TREE, new_node; 
+  tree t = NULL_TREE, new_var = NULL_TREE;
   struct inv_list data;
 
   data.list_values = NULL;
@@ -250,17 +239,8 @@ replace_invariant_exprs (tree *node)
     {
       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);
+	{ 
+	  new_var = get_temp_regvar (TREE_TYPE (t), t); 
 	  vec_safe_push (data.replacement, new_var);
 	}
       cp_walk_tree (node, replace_inv_trees, (void *) &data, NULL);
@@ -281,7 +261,6 @@ 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 ();
@@ -351,7 +330,7 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
     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;
+      new_var_type = boolean_type_node;
       break;
     case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
     case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
@@ -380,24 +359,30 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
     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);
+	make_triplet_val_inv (&ARRAY_NOTATION_START (anode));
+	make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (anode));
+	make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (anode));
       }
   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);
+      tree typ = ptrdiff_type_node;
+
+      /* In this place, we are using get_temp_regvar instead of 
+	 create_temporary_var if an_type is SEC_REDUCE_MAX/MIN_IND because
+	 the array_ind_value depends on this value being initalized to 0.  */
+      if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
+	  || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND) 
+	an_loop_info[ii].var = get_temp_regvar (typ, build_zero_cst (typ));
+      else
+	{
+	  an_loop_info[ii].var = create_temporary_var (typ);
+	  add_decl_expr (an_loop_info[ii].var);
+	}
+      an_loop_info[ii].ind_init = 
+	build_x_modify_expr (location, an_loop_info[ii].var, INIT_EXPR,
+			     build_zero_cst (typ), 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);
@@ -406,26 +391,9 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
     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);
-    }
+      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND) 
+    array_ind_value = get_temp_regvar (TREE_TYPE (func_parm), func_parm);
 
   array_op0 = (*array_operand)[0];
   switch (an_type)
@@ -440,35 +408,36 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
       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;
+      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;
+      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;
+      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;
+      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;
+      code = (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND ? LE_EXPR
+	: GE_EXPR);
       init = an_loop_info[0].var;
+      break;
     case BUILT_IN_CILKPLUS_SEC_REDUCE:
       init = identity_value;
       break;
@@ -479,9 +448,11 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
       gcc_unreachable ();
     }
 
-  if (init)
-    new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR, init,
-					tf_warning_or_error);
+  if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
+    *new_var = get_temp_regvar (new_var_type, init);
+  else
+    *new_var = NULL_TREE;
+
   switch (an_type)
     {
     case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD:
@@ -516,8 +487,6 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
       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,
@@ -567,21 +536,8 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
     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);
+  append_to_statement_list (an_init, &loop_with_init);
   body = new_expr;
 
   for (ii = 0; ii < rank; ii++)
@@ -591,7 +547,7 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
 		      an_loop_info[ii].incr, body);
       body = pop_stmt_list (new_loop);
     }
-  append_to_statement_list_force (body, &loop_with_init);
+  append_to_statement_list (body, &loop_with_init);
 
   an_info.release ();
   an_loop_info.release ();
@@ -680,10 +636,7 @@ expand_an_in_modify_expr (location_t location, tree lhs,
 	  return an_init;
 	}
       else
-	{
-	  pop_stmt_list (an_init);
-	  return NULL_TREE;
-	}
+	gcc_unreachable ();
     }
 
   /* If for some reason location is not set, then find if LHS or RHS has
@@ -705,8 +658,6 @@ expand_an_in_modify_expr (location_t location, tree lhs,
     
   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;
     }
@@ -721,17 +672,17 @@ expand_an_in_modify_expr (location_t location, tree lhs,
   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);
+      make_triplet_val_inv (&ARRAY_NOTATION_START (anode));
+      make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (anode));
+      make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (anode));
     }
   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);
+	make_triplet_val_inv (&ARRAY_NOTATION_START (aa));
+	make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (aa));
+	make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (aa));
       }
   lhs_an_loop_info.safe_grow_cleared (lhs_rank);
   
@@ -751,10 +702,10 @@ expand_an_in_modify_expr (location_t location, tree lhs,
       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;
+  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)
@@ -768,14 +719,16 @@ expand_an_in_modify_expr (location_t location, tree lhs,
 	  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);
+   for (ii = 0; ii < lhs_rank; ii++) 
+     {
+       tree typ = ptrdiff_type_node; 
+       lhs_an_loop_info[ii].var = create_temporary_var (typ);
+       add_decl_expr (lhs_an_loop_info[ii].var);
+       lhs_an_loop_info[ii].ind_init = build_x_modify_expr 
+	 (location, lhs_an_loop_info[ii].var, INIT_EXPR, build_zero_cst (typ), 
+	  complain);
+     }
+   
    if (rhs_list_size > 0)
      {
        rhs_array_operand = fix_sec_implicit_args (location, rhs_list,
@@ -789,24 +742,15 @@ expand_an_in_modify_expr (location_t location, tree lhs,
   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));
+      tree typ = ptrdiff_type_node;
+      rhs_an_loop_info[ii].var = create_temporary_var (typ);
+      add_decl_expr (rhs_an_loop_info[ii].var);
       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);
+	(location, rhs_an_loop_info[ii].var, INIT_EXPR, build_zero_cst (typ), 
+	 complain);
     }
 
   if (lhs_rank)
@@ -860,7 +804,7 @@ expand_an_in_modify_expr (location_t location, tree lhs,
       gcc_unreachable ();
   
   an_init = pop_stmt_list (an_init);
-  append_to_statement_list_force (an_init, &loop_with_init);
+  append_to_statement_list (an_init, &loop_with_init);
   body = array_expr;
   for (ii = 0; ii < MAX (lhs_rank, rhs_rank); ii++)
     {
@@ -870,17 +814,13 @@ expand_an_in_modify_expr (location_t location, tree lhs,
 
       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);
+	  append_to_statement_list (lhs_an_loop_info[ii].ind_init, &init_list);
+	  append_to_statement_list (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);
+	  append_to_statement_list (rhs_an_loop_info[ii].ind_init, &init_list);
+	  append_to_statement_list (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);
@@ -913,7 +853,6 @@ cp_expand_cond_array_notations (tree orig_stmt)
   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;
@@ -995,11 +934,11 @@ cp_expand_cond_array_notations (tree orig_stmt)
 	      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 (builtin_loop, &stmt);
 	    }
 	}
     }
-  append_to_statement_list_force (orig_stmt, &stmt);
+  append_to_statement_list (orig_stmt, &stmt);
   rank = 0;
   array_list = NULL;
   if (!find_rank (EXPR_LOCATION (stmt), stmt, stmt, true, &rank))
@@ -1023,37 +962,28 @@ cp_expand_cond_array_notations (tree orig_stmt)
   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);
+      make_triplet_val_inv (&ARRAY_NOTATION_START (anode));
+      make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (anode));
+      make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (anode));
     }
   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);
-	}
+
+  for (ii = 0; ii < rank; ii++) 
+    {
+      tree typ = ptrdiff_type_node;
+      an_loop_info[ii].var = create_temporary_var (typ);
+      add_decl_expr (an_loop_info[ii].var);
+      an_loop_info[ii].ind_init =
+	build_x_modify_expr (location, an_loop_info[ii].var, INIT_EXPR,
+			     build_zero_cst (typ), 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);
+  append_to_statement_list (an_init, &loop_with_init);
   body = stmt;
 
   for (ii = 0; ii < rank; ii++)
@@ -1063,7 +993,7 @@ cp_expand_cond_array_notations (tree orig_stmt)
 		      an_loop_info[ii].incr, body);
       body = pop_stmt_list (new_loop);
     }
-  append_to_statement_list_force (body, &loop_with_init);
+  append_to_statement_list (body, &loop_with_init);
 
   an_info.release ();
   an_loop_info.release ();
@@ -1108,14 +1038,14 @@ expand_unary_array_notation_exprs (tree orig_stmt)
 	  {
 	    vec<tree, va_gc> *sub_list = NULL, *new_var_list = NULL;
 	    stmt = alloc_stmt_list ();
-	    append_to_statement_list_force (builtin_loop, &stmt);
+	    append_to_statement_list (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);
+    append_to_statement_list (finish_expr_stmt (orig_stmt), &stmt);
   else
     stmt = orig_stmt;
   rank = 0;
@@ -1135,22 +1065,19 @@ expand_unary_array_notation_exprs (tree orig_stmt)
   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);
+      make_triplet_val_inv (&ARRAY_NOTATION_START (array_node));
+      make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (array_node));
+      make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (array_node));
     }
   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));
+      tree typ = ptrdiff_type_node;
+      an_loop_info[ii].var = create_temporary_var (typ);
+      add_decl_expr (an_loop_info[ii].var);
       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)),
+	(location, an_loop_info[ii].var, INIT_EXPR, build_zero_cst (typ), 
 	 tf_warning_or_error);
     }
   array_operand = create_array_refs (location, an_info, an_loop_info,
@@ -1159,7 +1086,7 @@ expand_unary_array_notation_exprs (tree orig_stmt)
   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);
+  append_to_statement_list (an_init, &loop_with_init);
   body = stmt;
   
   for (ii = 0; ii < rank; ii++)
@@ -1169,7 +1096,7 @@ expand_unary_array_notation_exprs (tree orig_stmt)
 		      an_loop_info[ii].incr, body);
       body = pop_stmt_list (new_loop);
     }
-  append_to_statement_list_force (body, &loop_with_init);
+  append_to_statement_list (body, &loop_with_init);
 
   an_info.release ();
   an_loop_info.release ();
@@ -1190,16 +1117,18 @@ expand_return_expr (tree expr)
     return expr;
 
   location_t loc = EXPR_LOCATION (expr);
-  new_mod_list = alloc_stmt_list ();
+  new_mod_list = push_stmt_list ();
   retval_expr = TREE_OPERAND (expr, 0);
-  new_var = build_decl (loc, VAR_DECL, NULL_TREE, TREE_TYPE (retval_expr));
+  new_var = get_temp_regvar (TREE_TYPE (retval_expr), 
+			     build_zero_cst (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),
+				      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);
+  add_stmt (new_mod);
+  add_stmt (expr);
+  new_mod_list = pop_stmt_list (new_mod_list);
   return new_mod_list;
 }
 
@@ -1336,19 +1265,21 @@ expand_array_notation_exprs (tree 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:      
+    case FOR_STMT:
+      if (contains_array_notation_expr (FOR_COND (t)))
+	{
+	  error_at (EXPR_LOCATION (FOR_COND (t)),
+		    "array notation cannot be used in a condition for "
+		    "a for-loop");
+	  return error_mark_node;
+	}
       /* 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));
+	{ 
+	  FOR_BODY (t) = expand_array_notation_exprs (FOR_BODY (t));
+	  FOR_EXPR (t) = expand_array_notation_exprs (FOR_EXPR (t));
+	}
       else
 	t = expand_array_notation_exprs (t);
       return t;
@@ -1368,6 +1299,13 @@ expand_array_notation_exprs (tree t)
 	t = expand_array_notation_exprs (t);
       return t;
     case SWITCH_STMT:
+      if (contains_array_notation_expr (SWITCH_STMT_COND (t)))
+	{
+	  error_at (EXPR_LOCATION (SWITCH_STMT_COND (t)),
+		    "array notation cannot be used as a condition for "
+		    "switch statement");
+	  return error_mark_node;
+	}
       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
@@ -1382,6 +1320,14 @@ expand_array_notation_exprs (tree t)
 	t = expand_array_notation_exprs (t);
       return t;
     case WHILE_STMT:
+      if (contains_array_notation_expr (WHILE_COND (t)))
+	{
+	  if (EXPR_LOCATION (WHILE_COND (t)) != UNKNOWN_LOCATION)
+	    loc = EXPR_LOCATION (WHILE_COND (t));
+	  error_at (loc, "array notation cannot be used as a condition for "
+		    "while statement");
+	  return error_mark_node;
+	}
       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
@@ -1395,6 +1341,13 @@ expand_array_notation_exprs (tree t)
 	t = expand_array_notation_exprs (t);
       return t;
     case DO_STMT:
+      if (contains_array_notation_expr (DO_COND (t)))
+	{
+	  error_at (EXPR_LOCATION (DO_COND (t)),
+		    "array notation cannot be used as a condition for a "
+		    "do-while statement");
+	  return error_mark_node;
+	}
       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
@@ -1508,20 +1461,9 @@ cilkplus_an_triplet_types_ok_p (location_t loc, tree start_index, tree length,
     }
   if (!TREE_CODE (type) == FUNCTION_TYPE)
     {
-      error_at (loc, "array notations cannot be used with function type");
+      error_at (loc, "array notation 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))
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 38ef878..590d857 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -1207,6 +1207,12 @@ cp_genericize (tree fndecl)
   if (DECL_CLONED_FUNCTION_P (fndecl))
     return;
 
+  /* Expand all the array notations here.  */
+  if (flag_enable_cilkplus 
+      && contains_array_notation_expr (DECL_SAVED_TREE (fndecl)))
+    DECL_SAVED_TREE (fndecl) = 
+      expand_array_notation_exprs (DECL_SAVED_TREE (fndecl));
+
   /* We do want to see every occurrence of the parms, so we can't just use
      walk_tree's hash functionality.  */
   cp_genericize_tree (&DECL_SAVED_TREE (fndecl));
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index f3bc27a..bb5a13d 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -6062,10 +6062,10 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 
 /* 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
+   INIT_INDEX is NULL, then we have special case where 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.  */
+   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,
@@ -6074,8 +6074,6 @@ cp_parser_array_notation (location_t loc, cp_parser *parser, tree init_index,
   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)
     {
@@ -6117,44 +6115,24 @@ cp_parser_array_notation (location_t loc, cp_parser *parser, tree init_index,
 	      || TREE_CODE (array_type) == POINTER_TYPE)
 	    {
 	      error_at (loc, "start-index and length fields necessary for "
-			"using array notations in pointers or records");
+			"using array notation 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");
+			"using array notation with array of unknown bound");
 	      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);
+	  start_index = cp_fold_convert (ptrdiff_type_node, start_index);
+	  length_index = size_binop 
+	    (PLUS_EXPR, TYPE_MAXVAL (array_type_domain), size_one_node);
+	  length_index = cp_fold_convert (ptrdiff_type_node, length_index);
+	  stride = build_int_cst (ptrdiff_type_node, 1);
 	}
       else if (init_index != error_mark_node)
 	{
@@ -6165,12 +6143,12 @@ cp_parser_array_notation (location_t loc, cp_parser *parser, tree init_index,
 	  start_index = init_index;
 	  cp_lexer_consume_token (parser->lexer);
 
-	  saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
+	  bool 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);
 	 
@@ -6180,7 +6158,6 @@ cp_parser_array_notation (location_t loc, cp_parser *parser, tree init_index,
 	      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;
@@ -6211,13 +6188,7 @@ cp_parser_array_notation (location_t loc, cp_parser *parser, tree init_index,
       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);
@@ -6248,8 +6219,7 @@ cp_parser_postfix_open_square_expression (cp_parser *parser,
   if (flag_enable_cilkplus
       && cp_lexer_peek_token (parser->lexer)->type == CPP_COLON)
     /* If we are here, then we have something like this:
-       ARRAY[:]
-    */
+       ARRAY[:]   */
     postfix_expression = cp_parser_array_notation (loc, parser, NULL_TREE,
 						   postfix_expression);
   else
@@ -6259,8 +6229,7 @@ cp_parser_postfix_open_square_expression (cp_parser *parser,
 	 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.
-      */
+	 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
@@ -6288,7 +6257,7 @@ cp_parser_postfix_open_square_expression (cp_parser *parser,
 		{
 		  error_at (cp_lexer_peek_token (parser->lexer)->location,
 			    "braced list index is not allowed with array "
-			    "notations");
+			    "notation");
 		  index = error_mark_node;
 		}
 	    }
@@ -9550,9 +9519,6 @@ cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr,
   finish_compound_stmt (compound_stmt);
   /* 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;
 }
 
@@ -9745,14 +9711,6 @@ 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;
@@ -10310,12 +10268,6 @@ 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;
 
@@ -10342,15 +10294,6 @@ 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;
 
@@ -10367,19 +10310,10 @@ cp_parser_iteration_statement (cp_parser* parser)
 	/* Parse the body of the for-statement.  */
 	parser->in_statement = IN_ITERATION_STMT;
 	cp_parser_already_scoped_statement (parser);
-	parser->in_statement = in_statement;
+	parser->in_statement = in_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);
+	/* We're done with the for-statement.  */ 
+	finish_for_stmt (statement);
       }
       break;
 
@@ -16953,54 +16887,30 @@ cp_parser_direct_declarator (cp_parser* parser,
 	  if (token->type != CPP_CLOSE_SQUARE)
 	    {
 	      bool non_constant_p;
-
-	      if (flag_enable_cilkplus
-		  && cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+	      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;
-		  error_at (cp_lexer_peek_token (parser->lexer)->location,
-			    "array notations cannot be used in declaration");
-		  cp_lexer_consume_token (parser->lexer);
 		}
-	      else
+	      else if (processing_template_decl)
 		{
-		  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; 
-		    }
+		  /* Remember this wasn't a constant-expression.  */
+		  bounds = build_nop (TREE_TYPE (bounds), bounds);
+		  TREE_SIDE_EFFECTS (bounds) = 1;
 		}
 	    }
 	  else
@@ -18372,10 +18282,6 @@ cp_parser_ctor_initializer_opt_and_function_body (cp_parser *parser,
   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);
 
@@ -22355,12 +22261,6 @@ 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));
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 667e37f..5dafdcd 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -15739,9 +15739,6 @@ 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;
@@ -19143,11 +19140,6 @@ 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);
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 0a460a4..db81b44 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -8089,7 +8089,6 @@ 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);
@@ -8901,7 +8900,6 @@ 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:
@@ -8912,6 +8910,9 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
 	  return false;
       return true;
 
+    case ARRAY_NOTATION_REF:
+      return false;
+
     case FMA_EXPR:
     case VEC_PERM_EXPR:
      for (i = 0; i < 3; ++i)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 9940868..5594687 100644
Binary files a/gcc/testsuite/ChangeLog and b/gcc/testsuite/ChangeLog differ
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/decl-ptr-colon.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/decl-ptr-colon.c
index 68c8859..4b54f4d 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/decl-ptr-colon.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/decl-ptr-colon.c
@@ -1,3 +1,4 @@
+/* { dg-do compile { target c } } */
 /* { dg-options "-fcilkplus" } */
 
 int main(void)
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/dimensionless-arrays.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/dimensionless-arrays.c
index 69aaa52..690e89a 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/dimensionless-arrays.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/dimensionless-arrays.c
@@ -5,6 +5,6 @@ extern int *b;
 
 void foo()
 {
-  a[:] = 5;	// { dg-error "start-index and length fields necessary for using array notations in dimensionless arrays" }
-  b[:] = 5;    // { dg-error "start-index and length fields necessary for using array notations in pointers" }
+  a[:] = 5;	// { dg-error "start-index and length fields necessary for using array notation" }
+  b[:] = 5;    // { dg-error "start-index and length fields necessary for using" }
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/fn_ptr.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/fn_ptr.c
index 024a158..fa6d900 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/fn_ptr.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/fn_ptr.c
@@ -1,3 +1,4 @@
+/* { dg-do compile } */
 /* { dg-options "-fcilkplus" } */
 
 typedef int (*foo)(int);
@@ -10,11 +11,11 @@ int main(void)
   foo ***func_array_ptr;
   int argc = 5;
 
-  array[:] =  func_array[:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
-  func_array[0:5](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
-  func_array2[0:5][:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
-  array2[0:5][:] = func_array2[0:5][:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
-  func_array_ptr[0:5][0:4][0:argc:2](argc); /* { dg-error "array notations cannot be used with function pointer arrays" } */
+  array[:] =  func_array[:](10); 
+  func_array[0:5](10); 
+  func_array2[0:5][:](10);
+  array2[0:5][:] = func_array2[0:5][:](10);
+  func_array_ptr[0:5][0:4][0:argc:2](argc); 
 
   return 0;
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
index 14421d9..814786b 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
@@ -6,7 +6,7 @@ int main (void)
   int array[10], array2[10][10];
   int x, ii, jj ;
 
-  switch (array[:]) {  /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  switch (array[:]) {  /* { dg-error "cannot be used as a condition for switch statement" } */
   case 1:
     x = 5;
     break;
@@ -17,7 +17,7 @@ int main (void)
     x = 9;
   }
 
-  switch (array2[:][:]) { /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  switch (array2[:][:]) { /* { dg-error "cannot be used as a condition for switch statement" } */
   case 1:
     x = 5;
     break;
@@ -28,7 +28,7 @@ int main (void)
     x = 9;
   }
 
-  switch (array[:] + x) { /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  switch (array[:] + x) { /* { dg-error "cannot be used as a condition for switch statement" } */
   case 1:
     x = 5;
     break;
@@ -39,7 +39,7 @@ int main (void)
     x = 9;
   }
   
-  switch (array2[:][1:x:4] + x) { /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  switch (array2[:][1:x:4] + x) { /* { dg-error "cannot be used as a condition for switch statement" } */
   case 1:
     x = 5;
     break;
@@ -50,36 +50,36 @@ int main (void)
     x = 9;
   }
 
-  for (ii = 0; ii < array[:]; ii++) /* { dg-error "array notations cannot be used in a condition for a for-loop" } */
+  for (ii = 0; ii < array[:]; ii++) /* { dg-error "cannot be used in a condition for a for-loop" } */
     {
       x = 2;
     }
 
-  for (ii = 0; ii < array2[:][:]; ii++) /* { dg-error "array notations cannot be used in a condition for a for-loop" } */
+  for (ii = 0; ii < array2[:][:]; ii++) /* { dg-error "cannot be used in a condition for a for-loop" } */
     {
       x = 3;
     }
 
-  for (; array2[:][:] < 2;) /* { dg-error "array notations cannot be used in a condition for a for-loop" } */
+  for (; array2[:][:] < 2;) /* { dg-error "cannot be used in a condition for a for-loop" } */
     x = 4;
 
 
-  while (array2[:][:]) /* { dg-error "array notations cannot be used as a condition for while statement" } */
+  while (array2[:][:]) /* { dg-error "cannot be used as a condition for while statement" } */
     x = 3;
 
-  while (array[1:1:1]) /* { dg-error "array notations cannot be used as a condition for while statement" } */
+  while (array[1:1:1]) /* { dg-error "cannot be used as a condition for while statement" } */
     x = 1;
 
-  while (ii != array2[1:x:3][1:2:1]) /* { dg-error "array notations cannot be used as a condition for while statement"  } */
+  while (ii != array2[1:x:3][1:2:1]) /* { dg-error "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" "" { target c } } */
+  do { /* { dg-error "cannot be used as a condition for a do-while statement" "" { target c } } */
     x = 3;
-  } while (ii != array2[:][:]); /* { dg-error "array notations cannot be used as a condition for a do-while statement" "" { target c++ } } */
+  } while (ii != array2[:][:]); /* { dg-error "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" "" { target c } } */
+  do {  /* { dg-error "cannot be used as a condition for a do-while statement" "" { target c } } */
     x = 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++ } } */
+  } while (ii != (x + array2[:][1:x:2]) + 2); /* { dg-error "cannot be used as a condition for a do-while statement" "" { target c++ } } */
   
   do { 
     x += 3;
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/rank_mismatch.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/rank_mismatch.c
index b5e37ce..eb3c1f1 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/rank_mismatch.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/rank_mismatch.c
@@ -10,6 +10,7 @@ int main (void)
   int array[10][10], array2[10];
 
   array[:][:] = array[:]; /* { dg-error "rank mismatch between" } */
+  /* { dg-error "invalid conversion" "" { target c++ } 12 } */
 
   x = array2[:]; /* { dg-error "cannot be scalar when" } */
 

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH] Cilk Plus Array Notation for C++
  2013-06-24 22:23                         ` Iyer, Balaji V
@ 2013-06-25 14:38                           ` Jason Merrill
  2013-06-25 18:27                             ` Iyer, Balaji V
  2013-06-25 18:42                             ` Iyer, Balaji V
  0 siblings, 2 replies; 40+ messages in thread
From: Jason Merrill @ 2013-06-25 14:38 UTC (permalink / raw)
  To: Iyer, Balaji V, Richard Henderson; +Cc: Aldy Hernandez, gcc-patches

On 06/24/2013 06:23 PM, Iyer, Balaji V wrote:
>> Actually, to reduce the amount of changes to non-AN code, let's put the AN case
>> third, after the offset and {} cases, so you get something like
>>
>> else if (flag_enable_cilkplus)
>>    {
>>      tree an = cp_parser_array_notation (loc, parser, &index,
>> 				        postfix_expression);
>>      if (an)
>>        return an;
>>      /* Otherwise, cp_parser_array_notation set 'index'. */
>>    }
>> else
>>    index = cp_parser_expression (parser, /*cast_p=*/false, NULL);
>>
>> this way the change is just a few added lines, and everything else is in
>> cp_parser_array_notation.

> If I do it this way, then I don't think I will be able to handle a normal array reference when cilk plus is enabled.

What I had in mind is that in the case of a normal array reference, 
cp_parser_array_notation will update index (which is passed by address) 
and return NULL_TREE, so that it gets back on the normal path.

> One thing I could do is to assume that people won't use array notations in braced list. I had it like this a while back but I made the change to make sure I have covered more cases. Please let me know if that is OK and I will fix it.

Yes, that's OK.

> I looked into this. But, magic_varargs_p is static to call.c. Should I make it non-static?

Yes.

> After making it non-static I was planning to do something like this:
>
> if (magic_varargs_p (fndecl)
>   Nargs = (*params)->length ();
> else
>    nargs = convert_arguments (...)
>
> Is that OK with you?

I was thinking to check magic_varargs_p in convert_arguments, where it 
currently has

>           if (fndecl && DECL_BUILT_IN (fndecl)
>               && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CONSTANT_P)
>             /* Don't do ellipsis conversion for __built_in_constant_p
>                as this will result in spurious errors for non-trivial
>                types.  */

change to "if (fndecl && magic_varargs_p (fndecl))"

>> By the way, why are you breaking out the elements of the
>> ARRAY_NOTATION_REF into a cilkplus_an_parts rather than using the _REF
>> directly?
>
> I use the different parts of array notations for error checking and to create the outer for-loop. Also, to create the ARRAY_REF I need the induction variable.

I understand the need for cilkplus_an_loop_parts, but cilkplus_an_parts 
seems to contain exactly the same information as the ARRAY_NOTATION_REF.

> Fixed! By the way, what is SFINAE?

SFINAE stands for "substitution failure is not an error".  During 
template argument deduction, once we have a full set of template 
arguments we try to substitute them into the template declaration.  In 
that context, things that would normally cause an error just fail and 
return error_mark_node silently.

> diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
> index 55ed6a5..9d570b2 100644
> Binary files a/gcc/cp/ChangeLog and b/gcc/cp/ChangeLog differ

This patch still has ChangeLog entries.

> +  new_var = get_temp_regvar (TREE_TYPE (retval_expr),
> +			     build_zero_cst (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);

Why not pass TREE_OPERAND (retval_expr, 1) as the init to get_temp_regvar?

> -	  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);
>  	
> @@ -6180,7 +6158,6 @@ cp_parser_array_notation (location_t loc, cp_parser *parser, tree init_index,
>  	      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;

This change looks like now you will only restore 
parser->colon_corrects_to_scope_p if you have a stride.  I would suggest 
putting back the first restore, and removing all the corrects_to_scope_p 
code from the stride block, since there can't be an array-notation colon 
after the stride.

>>> +           /* 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))
>>
>> This seems impossible, since 'var' is created to have the same type as 'start'.
>
> As you suggested further in the email, I have made var of type ptrdiff_type, so I think I should keep this.

I think it would be better to convert start/stride to ptrdiff_t.

Incidentally, types should be compared with same_type_p rather than ==.

> +  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;
> +       }
> +    }

Another place that should use tree_int_cst_equal.

> +      /* No need to compare ii < rhs_rank && ii >= lhs_rank because valid Array
> +        notation expression cannot RHS's rank cannot be greater than LHS.  */

Too many "cannot"s.

> +  if (processing_template_decl)
> +    {
> +      array_type = TREE_TYPE (array_value);
> +      type = TREE_TYPE (array_type);
> +    }

We should be able to parse array notation in a template even when the 
array expression has unknown type.  In a template, just parse and 
remember the raw expressions without worrying about diagnostics and 
conversions.

> +  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;
> +       }
> +    }
...
> +  /* 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;
> +       }
> +    }

More diagnostics that should move to expansion time.

> +  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 && 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 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;

More changes that should be unnecessary since ARRAY_NOTATION_REF has a 
normal type.

What remaining obstacles are there to sharing most of the expansion code 
between C and C++?  That can be a separate patch, of course.

Jason

^ permalink raw reply	[flat|nested] 40+ messages in thread

* RE: [PATCH] Cilk Plus Array Notation for C++
  2013-06-25 14:38                           ` Jason Merrill
@ 2013-06-25 18:27                             ` Iyer, Balaji V
  2013-06-25 20:55                               ` Jason Merrill
  2013-06-25 18:42                             ` Iyer, Balaji V
  1 sibling, 1 reply; 40+ messages in thread
From: Iyer, Balaji V @ 2013-06-25 18:27 UTC (permalink / raw)
  To: Jason Merrill, Richard Henderson; +Cc: Aldy Hernandez, gcc-patches



> -----Original Message-----
> From: Jason Merrill [mailto:jason@redhat.com]
> Sent: Tuesday, June 25, 2013 10:39 AM
> To: Iyer, Balaji V; Richard Henderson
> Cc: Aldy Hernandez; gcc-patches@gcc.gnu.org
> Subject: Re: [PATCH] Cilk Plus Array Notation for C++
> 
> On 06/24/2013 06:23 PM, Iyer, Balaji V wrote:
> >> Actually, to reduce the amount of changes to non-AN code, let's put
> >> the AN case third, after the offset and {} cases, so you get
> >> something like
> >>
> >> else if (flag_enable_cilkplus)
> >>    {
> >>      tree an = cp_parser_array_notation (loc, parser, &index,
> >> 				        postfix_expression);
> >>      if (an)
> >>        return an;
> >>      /* Otherwise, cp_parser_array_notation set 'index'. */
> >>    }
> >> else
> >>    index = cp_parser_expression (parser, /*cast_p=*/false, NULL);
> >>
> >> this way the change is just a few added lines, and everything else is
> >> in cp_parser_array_notation.
> 
> > If I do it this way, then I don't think I will be able to handle a normal array
> reference when cilk plus is enabled.
> 
> What I had in mind is that in the case of a normal array reference,
> cp_parser_array_notation will update index (which is passed by address) and
> return NULL_TREE, so that it gets back on the normal path.
> 
> > One thing I could do is to assume that people won't use array notations in
> braced list. I had it like this a while back but I made the change to make sure I
> have covered more cases. Please let me know if that is OK and I will fix it.
> 
> Yes, that's OK.
> 


> > I looked into this. But, magic_varargs_p is static to call.c. Should I make it non-
> static?
> 
> Yes.
> 
> > After making it non-static I was planning to do something like this:
> >
> > if (magic_varargs_p (fndecl)
> >   Nargs = (*params)->length ();
> > else
> >    nargs = convert_arguments (...)
> >
> > Is that OK with you?
> 
> I was thinking to check magic_varargs_p in convert_arguments, where it
> currently has
> 
> >           if (fndecl && DECL_BUILT_IN (fndecl)
> >               && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CONSTANT_P)
> >             /* Don't do ellipsis conversion for __built_in_constant_p
> >                as this will result in spurious errors for non-trivial
> >                types.  */
> 
> change to "if (fndecl && magic_varargs_p (fndecl))"
> 

This change is implemented.

> >> By the way, why are you breaking out the elements of the
> >> ARRAY_NOTATION_REF into a cilkplus_an_parts rather than using the
> >> _REF directly?
> >
> > I use the different parts of array notations for error checking and to create the
> outer for-loop. Also, to create the ARRAY_REF I need the induction variable.
> 
> I understand the need for cilkplus_an_loop_parts, but cilkplus_an_parts seems
> to contain exactly the same information as the ARRAY_NOTATION_REF.
> 
> > Fixed! By the way, what is SFINAE?
> 
> SFINAE stands for "substitution failure is not an error".  During template
> argument deduction, once we have a full set of template arguments we try to
> substitute them into the template declaration.  In that context, things that
> would normally cause an error just fail and return error_mark_node silently.
> 
> > diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index
> > 55ed6a5..9d570b2 100644 Binary files a/gcc/cp/ChangeLog and
> > b/gcc/cp/ChangeLog differ
> 
> This patch still has ChangeLog entries.
> 

This time, I ran the command you gave me. Please tell me how it looks.

> > +  new_var = get_temp_regvar (TREE_TYPE (retval_expr),
> > +			     build_zero_cst (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);
> 
> Why not pass TREE_OPERAND (retval_expr, 1) as the init to get_temp_regvar?
> 


new_var = TREE_OPERAND (retval_expr, 1)

and if TREE_OPERAND (retval_expr, 1) has array notations then it wont get expanded correctly.

Another solution is to replace get_tmp_regvar with get_temporary_var () + add_decl_expr (..). I have implemented this because it looks "more correct"


> > -	  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);
> >
> > @@ -6180,7 +6158,6 @@ cp_parser_array_notation (location_t loc,
> cp_parser *parser, tree init_index,
> >  	      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;
> 
> This change looks like now you will only restore
> parser->colon_corrects_to_scope_p if you have a stride.  I would suggest
> putting back the first restore, and removing all the corrects_to_scope_p code
> from the stride block, since there can't be an array-notation colon after the
> stride.

I am setting the scope correction to false right before I look for length and restore it right after I parse the scope (i.e. outside the if-statement). I think this should fix the issue.

> 
> >>> +           /* 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))
> >>
> >> This seems impossible, since 'var' is created to have the same type as 'start'.
> >
> > As you suggested further in the email, I have made var of type ptrdiff_type, so
> I think I should keep this.
> 
> I think it would be better to convert start/stride to ptrdiff_t.
> 

I don't think I can do that. Stride can be negative and if I am not mistaken, ptrdiff_t is unsigned.

> Incidentally, types should be compared with same_type_p rather than ==.
> 
> > +  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;
> > +       }
> > +    }
> 
> Another place that should use tree_int_cst_equal.
> 

Fixed!

> > +      /* No need to compare ii < rhs_rank && ii >= lhs_rank because valid Array
> > +        notation expression cannot RHS's rank cannot be greater than
> > + LHS.  */
> 
> Too many "cannot"s.
> 
Sorry. Fixed.

> > +  if (processing_template_decl)
> > +    {
> > +      array_type = TREE_TYPE (array_value);
> > +      type = TREE_TYPE (array_type);
> > +    }
> 
> We should be able to parse array notation in a template even when the array
> expression has unknown type.  In a template, just parse and remember the raw
> expressions without worrying about diagnostics and conversions.
> 
> > +  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;
> > +       }
> > +    }
> ...

Fixed!

> > +  /* 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;
> > +       }
> > +    }

This one error is much easier to do it here than anywhere else. An array_ref could be a parameter inside a function, part of a modify expression, unary expression etc. If I move it to transformation stage, I have to do checks in all these places and there is a small chance some will slip through the cracks. This is almost a fool proof way of doing it. Such things have been done before. For example, Open MP does a return expression check in finish_return_stmt (even though this is a different issue we are talking about).

If it is the code lines that is an issue, then I am willing to enclose that in a function or #define.


> > +  if (flag_enable_cilkplus && contains_array_notation_expr (op0))
> > +    type0 = find_correct_array_notation_type (op0);  else
> > +    type0 = TREE_TYPE (op0);
> ...

Fixed!

> > +  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;
> > +    }

Fixed!

> ...
> > +  /* 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;
> 
> More changes that should be unnecessary since ARRAY_NOTATION_REF has a
> normal type.
> 

Fixed!

> What remaining obstacles are there to sharing most of the expansion code
> between C and C++?  That can be a separate patch, of course.
> 
> Jason

^ permalink raw reply	[flat|nested] 40+ messages in thread

* RE: [PATCH] Cilk Plus Array Notation for C++
  2013-06-25 14:38                           ` Jason Merrill
  2013-06-25 18:27                             ` Iyer, Balaji V
@ 2013-06-25 18:42                             ` Iyer, Balaji V
  2013-06-26 13:00                               ` Aldy Hernandez
  1 sibling, 1 reply; 40+ messages in thread
From: Iyer, Balaji V @ 2013-06-25 18:42 UTC (permalink / raw)
  To: Jason Merrill, Richard Henderson; +Cc: Aldy Hernandez, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 11266 bytes --]

Sorry, I accidentally clicked send before attaching the patch. I have attached the patch and the ChangeLogs for this.

Thanks,

Balaji V. Iyer.

> -----Original Message-----
> From: Iyer, Balaji V
> Sent: Tuesday, June 25, 2013 2:28 PM
> To: 'Jason Merrill'; Richard Henderson
> Cc: Aldy Hernandez; gcc-patches@gcc.gnu.org
> Subject: RE: [PATCH] Cilk Plus Array Notation for C++
> 
> 
> 
> > -----Original Message-----
> > From: Jason Merrill [mailto:jason@redhat.com]
> > Sent: Tuesday, June 25, 2013 10:39 AM
> > To: Iyer, Balaji V; Richard Henderson
> > Cc: Aldy Hernandez; gcc-patches@gcc.gnu.org
> > Subject: Re: [PATCH] Cilk Plus Array Notation for C++
> >
> > On 06/24/2013 06:23 PM, Iyer, Balaji V wrote:
> > >> Actually, to reduce the amount of changes to non-AN code, let's put
> > >> the AN case third, after the offset and {} cases, so you get
> > >> something like
> > >>
> > >> else if (flag_enable_cilkplus)
> > >>    {
> > >>      tree an = cp_parser_array_notation (loc, parser, &index,
> > >> 				        postfix_expression);
> > >>      if (an)
> > >>        return an;
> > >>      /* Otherwise, cp_parser_array_notation set 'index'. */
> > >>    }
> > >> else
> > >>    index = cp_parser_expression (parser, /*cast_p=*/false, NULL);
> > >>
> > >> this way the change is just a few added lines, and everything else
> > >> is in cp_parser_array_notation.
> >
> > > If I do it this way, then I don't think I will be able to handle a
> > > normal array
> > reference when cilk plus is enabled.
> >
> > What I had in mind is that in the case of a normal array reference,
> > cp_parser_array_notation will update index (which is passed by
> > address) and return NULL_TREE, so that it gets back on the normal path.
> >
> > > One thing I could do is to assume that people won't use array
> > > notations in
> > braced list. I had it like this a while back but I made the change to
> > make sure I have covered more cases. Please let me know if that is OK and I
> will fix it.
> >
> > Yes, that's OK.
> >
> 
> 
> > > I looked into this. But, magic_varargs_p is static to call.c. Should
> > > I make it non-
> > static?
> >
> > Yes.
> >
> > > After making it non-static I was planning to do something like this:
> > >
> > > if (magic_varargs_p (fndecl)
> > >   Nargs = (*params)->length ();
> > > else
> > >    nargs = convert_arguments (...)
> > >
> > > Is that OK with you?
> >
> > I was thinking to check magic_varargs_p in convert_arguments, where it
> > currently has
> >
> > >           if (fndecl && DECL_BUILT_IN (fndecl)
> > >               && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CONSTANT_P)
> > >             /* Don't do ellipsis conversion for __built_in_constant_p
> > >                as this will result in spurious errors for non-trivial
> > >                types.  */
> >
> > change to "if (fndecl && magic_varargs_p (fndecl))"
> >
> 
> This change is implemented.
> 
> > >> By the way, why are you breaking out the elements of the
> > >> ARRAY_NOTATION_REF into a cilkplus_an_parts rather than using the
> > >> _REF directly?
> > >
> > > I use the different parts of array notations for error checking and
> > > to create the
> > outer for-loop. Also, to create the ARRAY_REF I need the induction variable.
> >
> > I understand the need for cilkplus_an_loop_parts, but
> > cilkplus_an_parts seems to contain exactly the same information as the
> ARRAY_NOTATION_REF.
> >
> > > Fixed! By the way, what is SFINAE?
> >
> > SFINAE stands for "substitution failure is not an error".  During
> > template argument deduction, once we have a full set of template
> > arguments we try to substitute them into the template declaration.  In
> > that context, things that would normally cause an error just fail and return
> error_mark_node silently.
> >
> > > diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index
> > > 55ed6a5..9d570b2 100644 Binary files a/gcc/cp/ChangeLog and
> > > b/gcc/cp/ChangeLog differ
> >
> > This patch still has ChangeLog entries.
> >
> 
> This time, I ran the command you gave me. Please tell me how it looks.
> 
> > > +  new_var = get_temp_regvar (TREE_TYPE (retval_expr),
> > > +			     build_zero_cst (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);
> >
> > Why not pass TREE_OPERAND (retval_expr, 1) as the init to get_temp_regvar?
> >
> 
> 
> new_var = TREE_OPERAND (retval_expr, 1)
> 
> and if TREE_OPERAND (retval_expr, 1) has array notations then it wont get
> expanded correctly.
> 
> Another solution is to replace get_tmp_regvar with get_temporary_var () +
> add_decl_expr (..). I have implemented this because it looks "more correct"
> 
> 
> > > -	  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);
> > >
> > > @@ -6180,7 +6158,6 @@ cp_parser_array_notation (location_t loc,
> > cp_parser *parser, tree init_index,
> > >  	      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;
> >
> > This change looks like now you will only restore
> > parser->colon_corrects_to_scope_p if you have a stride.  I would
> > parser->suggest
> > putting back the first restore, and removing all the
> > corrects_to_scope_p code from the stride block, since there can't be
> > an array-notation colon after the stride.
> 
> I am setting the scope correction to false right before I look for length and
> restore it right after I parse the scope (i.e. outside the if-statement). I think this
> should fix the issue.
> 
> >
> > >>> +           /* 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))
> > >>
> > >> This seems impossible, since 'var' is created to have the same type as 'start'.
> > >
> > > As you suggested further in the email, I have made var of type
> > > ptrdiff_type, so
> > I think I should keep this.
> >
> > I think it would be better to convert start/stride to ptrdiff_t.
> >
> 
> I don't think I can do that. Stride can be negative and if I am not mistaken,
> ptrdiff_t is unsigned.
> 
> > Incidentally, types should be compared with same_type_p rather than ==.
> >
> > > +  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;
> > > +       }
> > > +    }
> >
> > Another place that should use tree_int_cst_equal.
> >
> 
> Fixed!
> 
> > > +      /* No need to compare ii < rhs_rank && ii >= lhs_rank because valid
> Array
> > > +        notation expression cannot RHS's rank cannot be greater
> > > + than LHS.  */
> >
> > Too many "cannot"s.
> >
> Sorry. Fixed.
> 
> > > +  if (processing_template_decl)
> > > +    {
> > > +      array_type = TREE_TYPE (array_value);
> > > +      type = TREE_TYPE (array_type);
> > > +    }
> >
> > We should be able to parse array notation in a template even when the
> > array expression has unknown type.  In a template, just parse and
> > remember the raw expressions without worrying about diagnostics and
> conversions.
> >
> > > +  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;
> > > +       }
> > > +    }
> > ...
> 
> Fixed!
> 
> > > +  /* 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;
> > > +       }
> > > +    }
> 
> This one error is much easier to do it here than anywhere else. An array_ref
> could be a parameter inside a function, part of a modify expression, unary
> expression etc. If I move it to transformation stage, I have to do checks in all
> these places and there is a small chance some will slip through the cracks. This is
> almost a fool proof way of doing it. Such things have been done before. For
> example, Open MP does a return expression check in finish_return_stmt (even
> though this is a different issue we are talking about).
> 
> If it is the code lines that is an issue, then I am willing to enclose that in a
> function or #define.
> 
> 
> > > +  if (flag_enable_cilkplus && contains_array_notation_expr (op0))
> > > +    type0 = find_correct_array_notation_type (op0);  else
> > > +    type0 = TREE_TYPE (op0);
> > ...
> 
> Fixed!
> 
> > > +  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;
> > > +    }
> 
> Fixed!
> 
> > ...
> > > +  /* 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;
> >
> > More changes that should be unnecessary since ARRAY_NOTATION_REF has a
> > normal type.
> >
> 
> Fixed!
> 
> > What remaining obstacles are there to sharing most of the expansion
> > code between C and C++?  That can be a separate patch, of course.
> >
> > Jason


[-- Attachment #2: diff.txt --]
[-- Type: text/plain, Size: 71327 bytes --]

diff --git a/gcc/builtins.def b/gcc/builtins.def
index 91879a6..9b55b1f 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -158,9 +158,9 @@ along with GCC; see the file COPYING3.  If not see
 	       (flag_asan || flag_tsan))
 
 #undef DEF_CILKPLUS_BUILTIN
-#define DEF_CILKPLUS_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
-  DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
-  	       false, false, true, ATTRS, false, flag_enable_cilkplus)
+#define DEF_CILKPLUS_BUILTIN(ENUM, NAME, TYPE, ATTRS)  \
+  DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, BT_FN_INT_VAR, BT_LAST, \
+  	       false, false, false, ATTRS, false, flag_enable_cilkplus) 
 
 /* Define an attribute list for math functions that are normally
    "impure" because some of them may write into global memory for
diff --git a/gcc/c-family/array-notation-common.c b/gcc/c-family/array-notation-common.c
index 0e2a431..ae96941 100644
--- a/gcc/c-family/array-notation-common.c
+++ b/gcc/c-family/array-notation-common.c
@@ -86,7 +86,6 @@ length_mismatch_in_expr_p (location_t loc, tree **list, size_t x, size_t y)
 {
   size_t ii, jj;
   tree start = NULL_TREE;
-  HOST_WIDE_INT l_start, l_node;
   for (jj = 0; jj < y; jj++)
     {
       start = NULL_TREE;
@@ -99,15 +98,11 @@ length_mismatch_in_expr_p (location_t loc, tree **list, size_t x, size_t y)
 	      /* If start 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]) == INTEGER_CST)
-		{
-		  l_node = int_cst_value (list[ii][jj]);
-		  l_start = int_cst_value (start);
-		  if (absu_hwi (l_start) != absu_hwi (l_node))
-		    {
-		      error_at (loc, "length mismatch in expression");
-		      return true;
-		    }
+	      if (TREE_CODE (list[ii][jj]) == INTEGER_CST
+		  && !tree_int_cst_equal (list[ii][jj], start))
+		{ 
+		  error_at (loc, "length mismatch in expression"); 
+		  return true;
 		}
 	    }
 	  else
@@ -269,6 +264,8 @@ find_rank (location_t loc, tree orig_expr, tree expr, bool ignore_builtin_fn,
 		/* If it is a built-in function, then we know it returns a 
 		   scalar.  */
 		return true;
+	  if (!find_rank (loc, orig_expr, func_name, ignore_builtin_fn, rank))
+	    return false;
 	  FOR_EACH_CALL_EXPR_ARG (arg, iter, expr)
 	    {
 	      if (!find_rank (loc, orig_expr, arg, ignore_builtin_fn, rank))
@@ -356,6 +353,9 @@ extract_array_notation_exprs (tree node, bool ignore_builtin_fn,
 	  vec_safe_push (*array_list, node);
 	  return;
 	}
+      /* This will extract array notations in function pointers.  */
+      extract_array_notation_exprs (CALL_EXPR_FN (node), ignore_builtin_fn,
+				    array_list);
       FOR_EACH_CALL_EXPR_ARG (arg, iter, node)
 	extract_array_notation_exprs (arg, ignore_builtin_fn, array_list);
     } 
@@ -431,6 +431,9 @@ replace_array_notations (tree *orig, bool ignore_builtin_fn,
 	      }
 	  return;
 	}
+      /* Fixes array notations in array notations in function pointers.  */
+      replace_array_notations (&CALL_EXPR_FN (*orig), ignore_builtin_fn, list,
+			       array_operand);
       ii = 0;
       FOR_EACH_CALL_EXPR_ARG (arg, iter, *orig)
 	{
@@ -573,53 +576,49 @@ 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++)
+
+  if (rank > 0)
+    for (size_t ii = 0; ii < size; ii++)
       {
-	(*node)[ii].safe_push (init);
-	array_exprs[ii].safe_push (NULL_TREE);
+	(*node)[ii].safe_grow_cleared (rank);
+	array_exprs[ii].safe_grow_cleared (rank);
       }
-
   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 ();	
+	{
+	  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
+	    break;
+	}
     }
     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));
-	    }
+	  {
+	    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
@@ -635,16 +634,15 @@ fix_sec_implicit_args (location_t loc, vec <tree, va_gc> *list,
   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)
+	if (idx < 0)
 	  /* In this case, the returning function would have emitted an
 	     error thus it is not necessary to do so again.  */
 	  return NULL;
+	else if (idx < (int) rank)
+	  vec_safe_push (array_operand, an_loop_info[idx].var);
 	else
 	  {
 	    error_at (loc, "__sec_implicit_index argument %d must be "
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index d6a500e..c7846ce 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -11053,24 +11053,6 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
 	      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
 	      return error_mark_node;
 	    }
-	  if (TREE_CODE (array_type) == ARRAY_TYPE)
-	    {
-	      tree subtype = TREE_TYPE (array_type);
-	      while (subtype && TREE_CODE (subtype) == POINTER_TYPE)
-		{
-		  /* Now this could be a function pointer.  Find them and
-		     give out an error.  */
-		  subtype = TREE_TYPE (subtype);
-		  if (subtype && TREE_CODE (subtype) == FUNCTION_TYPE)
-		    {
-		      error_at (loc, "array notations cannot be used with "
-				"function pointer arrays");
-		      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
-						 NULL);
-		      return error_mark_node;
-		    }
-		}
-	    }
 	  array_type_domain = TYPE_DOMAIN (array_type);
 
 	  if (!array_type_domain)
@@ -11114,27 +11096,6 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
 	      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
 	      return error_mark_node;
 	    }
-	  if (TREE_CODE (array_type) == ARRAY_TYPE
-	      || TREE_CODE (array_type) == POINTER_TYPE)
-	    {
-	      tree subtype = TREE_TYPE (array_type);
-	      while (subtype
-		     && (TREE_CODE (subtype) == POINTER_TYPE
-			 || TREE_CODE (subtype) == ARRAY_TYPE))
-		{
-		  /* Now this could be a function pointer.  Find them and
-		     give out an error.  */
-		  subtype = TREE_TYPE (subtype);
-		  if (subtype && TREE_CODE (subtype) == FUNCTION_TYPE)
-		    {
-		      error_at (loc, "array notations cannot be used with "
-				"function pointer arrays");
-		      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
-						 NULL);
-		      return error_mark_node;
-		    }
-		}
-	    }
 	  c_parser_consume_token (parser); /* consume the ':' */
 	  end_index = c_parser_expression (parser).value;
 	  if (!end_index || end_index == error_mark_node)
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 6817bfc..425ef9b 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -216,7 +216,6 @@ static void add_candidates (tree, tree, const vec<tree, va_gc> *, tree, tree,
 			    bool, tree, tree, int, struct z_candidate **,
 			    tsubst_flags_t);
 static conversion *merge_conversion_sequences (conversion *, conversion *);
-static bool magic_varargs_p (tree);
 static tree build_temp (tree, tree, int, diagnostic_t *, tsubst_flags_t);
 
 /* Returns nonzero iff the destructor name specified in NAME matches BASETYPE.
@@ -5857,16 +5856,9 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
 	  else if (t->kind == ck_identity)
 	    break;
 	}
-
-      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)
+       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);
 
@@ -6515,9 +6507,12 @@ convert_for_arg_passing (tree type, tree val, tsubst_flags_t complain)
    which no conversions at all should be done.  This is true for some
    builtins which don't act like normal functions.  */
 
-static bool
+bool
 magic_varargs_p (tree fn)
 {
+  if (flag_enable_cilkplus && is_cilkplus_reduce_builtin (fn) != BUILT_IN_NONE)
+    return true;
+
   if (DECL_BUILT_IN (fn))
     switch (DECL_FUNCTION_CODE (fn))
       {
@@ -6895,21 +6890,13 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
 		       "  (you can disable this with -fno-deduce-init-list)");
 	    }
 	}
+      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
index 92272b3..a24e672 100644
--- a/gcc/cp/cp-array-notation.c
+++ b/gcc/cp/cp-array-notation.c
@@ -59,7 +59,6 @@
 #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.  */
@@ -79,7 +78,7 @@ create_an_loop (tree init, tree cond, tree incr, tree body)
 }
 
 /* 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
+   same dimension and on the same side of the equal sign.  The Array notation
    lengths (LIST->LENGTH) is passed in as a 2D vector of trees.  */
 
 static bool
@@ -87,14 +86,13 @@ 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 ();
-  
+  size_t y = list[0].length (); 
+ 
   for (jj = 0; jj < y; jj++)
     {
-      length = NULL_TREE;
+      length = NULL_TREE; 
       for (ii = 0; ii < x; ii++)
 	{
 	  if (!length)
@@ -104,20 +102,16 @@ cp_length_mismatch_in_expr_p (location_t loc, vec<vec<an_parts> >list)
 	      /* 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;
-		    }
+	      if (TREE_CODE (list[ii][jj].length) == INTEGER_CST
+		  && !tree_int_cst_equal (list[ii][jj].length, length))
+		{ 
+		  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.  */
+	    /* We set the list[ii][jj].length as the current node just in case 
+	       it turns out to be an integer.  */
 	    length = list[ii][jj].length;
 	}
     }
@@ -128,17 +122,12 @@ cp_length_mismatch_in_expr_p (location_t loc, vec<vec<an_parts> >list)
    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)
+make_triplet_val_inv (tree *value)
 {
-  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;
-    }
+    *value = get_temp_regvar (integer_type_node, *value);
 }
 
 /* Returns a vector of size RANK that contains an ARRAY_REF.  This vector is
@@ -238,7 +227,7 @@ replace_invariant_exprs (tree *node)
 {
   size_t ix = 0;
   tree node_list = NULL_TREE;
-  tree t = NULL_TREE, new_var = NULL_TREE, new_node; 
+  tree t = NULL_TREE, new_var = NULL_TREE;
   struct inv_list data;
 
   data.list_values = NULL;
@@ -250,17 +239,8 @@ replace_invariant_exprs (tree *node)
     {
       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);
+	{ 
+	  new_var = get_temp_regvar (TREE_TYPE (t), t); 
 	  vec_safe_push (data.replacement, new_var);
 	}
       cp_walk_tree (node, replace_inv_trees, (void *) &data, NULL);
@@ -281,7 +261,6 @@ 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 ();
@@ -351,7 +330,7 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
     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;
+      new_var_type = boolean_type_node;
       break;
     case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
     case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
@@ -380,24 +359,30 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
     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);
+	make_triplet_val_inv (&ARRAY_NOTATION_START (anode));
+	make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (anode));
+	make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (anode));
       }
   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);
+      tree typ = ptrdiff_type_node;
+
+      /* In this place, we are using get_temp_regvar instead of 
+	 create_temporary_var if an_type is SEC_REDUCE_MAX/MIN_IND because
+	 the array_ind_value depends on this value being initalized to 0.  */
+      if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
+	  || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND) 
+	an_loop_info[ii].var = get_temp_regvar (typ, build_zero_cst (typ));
+      else
+	{
+	  an_loop_info[ii].var = create_temporary_var (typ);
+	  add_decl_expr (an_loop_info[ii].var);
+	}
+      an_loop_info[ii].ind_init = 
+	build_x_modify_expr (location, an_loop_info[ii].var, INIT_EXPR,
+			     build_zero_cst (typ), 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);
@@ -406,26 +391,9 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
     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);
-    }
+      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND) 
+    array_ind_value = get_temp_regvar (TREE_TYPE (func_parm), func_parm);
 
   array_op0 = (*array_operand)[0];
   switch (an_type)
@@ -440,35 +408,36 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
       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;
+      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;
+      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;
+      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;
+      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;
+      code = (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND ? LE_EXPR
+	: GE_EXPR);
       init = an_loop_info[0].var;
+      break;
     case BUILT_IN_CILKPLUS_SEC_REDUCE:
       init = identity_value;
       break;
@@ -479,9 +448,11 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
       gcc_unreachable ();
     }
 
-  if (init)
-    new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR, init,
-					tf_warning_or_error);
+  if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
+    *new_var = get_temp_regvar (new_var_type, init);
+  else
+    *new_var = NULL_TREE;
+
   switch (an_type)
     {
     case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD:
@@ -516,8 +487,6 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
       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,
@@ -567,21 +536,8 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
     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);
+  append_to_statement_list (an_init, &loop_with_init);
   body = new_expr;
 
   for (ii = 0; ii < rank; ii++)
@@ -591,7 +547,7 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
 		      an_loop_info[ii].incr, body);
       body = pop_stmt_list (new_loop);
     }
-  append_to_statement_list_force (body, &loop_with_init);
+  append_to_statement_list (body, &loop_with_init);
 
   an_info.release ();
   an_loop_info.release ();
@@ -680,10 +636,7 @@ expand_an_in_modify_expr (location_t location, tree lhs,
 	  return an_init;
 	}
       else
-	{
-	  pop_stmt_list (an_init);
-	  return NULL_TREE;
-	}
+	gcc_unreachable ();
     }
 
   /* If for some reason location is not set, then find if LHS or RHS has
@@ -705,8 +658,6 @@ expand_an_in_modify_expr (location_t location, tree lhs,
     
   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;
     }
@@ -721,17 +672,17 @@ expand_an_in_modify_expr (location_t location, tree lhs,
   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);
+      make_triplet_val_inv (&ARRAY_NOTATION_START (anode));
+      make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (anode));
+      make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (anode));
     }
   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);
+	make_triplet_val_inv (&ARRAY_NOTATION_START (aa));
+	make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (aa));
+	make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (aa));
       }
   lhs_an_loop_info.safe_grow_cleared (lhs_rank);
   
@@ -751,31 +702,29 @@ expand_an_in_modify_expr (location_t location, tree lhs,
       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;
+  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;
-	}
+      && TREE_CODE (rhs_len) == INTEGER_CST 
+      && !tree_int_cst_equal (rhs_len, lhs_len))
+    { 
+      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);
+   for (ii = 0; ii < lhs_rank; ii++) 
+     {
+       tree typ = ptrdiff_type_node; 
+       lhs_an_loop_info[ii].var = create_temporary_var (typ);
+       add_decl_expr (lhs_an_loop_info[ii].var);
+       lhs_an_loop_info[ii].ind_init = build_x_modify_expr 
+	 (location, lhs_an_loop_info[ii].var, INIT_EXPR, build_zero_cst (typ), 
+	  complain);
+     }
+   
    if (rhs_list_size > 0)
      {
        rhs_array_operand = fix_sec_implicit_args (location, rhs_list,
@@ -789,24 +738,15 @@ expand_an_in_modify_expr (location_t location, tree lhs,
   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));
+      tree typ = ptrdiff_type_node;
+      rhs_an_loop_info[ii].var = create_temporary_var (typ);
+      add_decl_expr (rhs_an_loop_info[ii].var);
       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);
+	(location, rhs_an_loop_info[ii].var, INIT_EXPR, build_zero_cst (typ), 
+	 complain);
     }
 
   if (lhs_rank)
@@ -855,12 +795,12 @@ expand_an_in_modify_expr (location_t location, tree lhs,
     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.  */
+      /* No need to compare ii < rhs_rank && ii >= lhs_rank because in a valid 
+	 Array notation expression, rank of RHS cannot be greater than LHS.  */
       gcc_unreachable ();
   
   an_init = pop_stmt_list (an_init);
-  append_to_statement_list_force (an_init, &loop_with_init);
+  append_to_statement_list (an_init, &loop_with_init);
   body = array_expr;
   for (ii = 0; ii < MAX (lhs_rank, rhs_rank); ii++)
     {
@@ -870,17 +810,13 @@ expand_an_in_modify_expr (location_t location, tree lhs,
 
       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);
+	  append_to_statement_list (lhs_an_loop_info[ii].ind_init, &init_list);
+	  append_to_statement_list (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);
+	  append_to_statement_list (rhs_an_loop_info[ii].ind_init, &init_list);
+	  append_to_statement_list (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);
@@ -913,7 +849,6 @@ cp_expand_cond_array_notations (tree orig_stmt)
   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;
@@ -930,13 +865,17 @@ cp_expand_cond_array_notations (tree orig_stmt)
 	  || 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)
+      /* If the condition has a zero rank, then handle array notations in body
+	 seperately.  */
+      if (cond_rank == 0)
+	return orig_stmt;
+      if (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)
+      else if (cond_rank != no_rank && no_rank != 0)
 	{
 	  error_at (EXPR_LOCATION (no_expr), "rank mismatch with controlling "
 		    "expression of parent if-statement");
@@ -957,13 +896,17 @@ cp_expand_cond_array_notations (tree orig_stmt)
 	      && !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)
+
+      /* Same reasoning as for COND_EXPR.  */
+      if (cond_rank == 0)
+	return orig_stmt;
+      else if (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)
+      else if (cond_rank != no_rank && no_rank != 0)
 	{
 	  error_at (EXPR_LOCATION (no_expr), "rank mismatch with controlling "
 		    "expression of parent if-statement");
@@ -995,11 +938,11 @@ cp_expand_cond_array_notations (tree orig_stmt)
 	      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 (builtin_loop, &stmt);
 	    }
 	}
     }
-  append_to_statement_list_force (orig_stmt, &stmt);
+  append_to_statement_list (orig_stmt, &stmt);
   rank = 0;
   array_list = NULL;
   if (!find_rank (EXPR_LOCATION (stmt), stmt, stmt, true, &rank))
@@ -1023,37 +966,28 @@ cp_expand_cond_array_notations (tree orig_stmt)
   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);
+      make_triplet_val_inv (&ARRAY_NOTATION_START (anode));
+      make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (anode));
+      make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (anode));
     }
   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);
-	}
+
+  for (ii = 0; ii < rank; ii++) 
+    {
+      tree typ = ptrdiff_type_node;
+      an_loop_info[ii].var = create_temporary_var (typ);
+      add_decl_expr (an_loop_info[ii].var);
+      an_loop_info[ii].ind_init =
+	build_x_modify_expr (location, an_loop_info[ii].var, INIT_EXPR,
+			     build_zero_cst (typ), 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);
+  append_to_statement_list (an_init, &loop_with_init);
   body = stmt;
 
   for (ii = 0; ii < rank; ii++)
@@ -1063,7 +997,7 @@ cp_expand_cond_array_notations (tree orig_stmt)
 		      an_loop_info[ii].incr, body);
       body = pop_stmt_list (new_loop);
     }
-  append_to_statement_list_force (body, &loop_with_init);
+  append_to_statement_list (body, &loop_with_init);
 
   an_info.release ();
   an_loop_info.release ();
@@ -1108,14 +1042,14 @@ expand_unary_array_notation_exprs (tree orig_stmt)
 	  {
 	    vec<tree, va_gc> *sub_list = NULL, *new_var_list = NULL;
 	    stmt = alloc_stmt_list ();
-	    append_to_statement_list_force (builtin_loop, &stmt);
+	    append_to_statement_list (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);
+    append_to_statement_list (finish_expr_stmt (orig_stmt), &stmt);
   else
     stmt = orig_stmt;
   rank = 0;
@@ -1135,22 +1069,19 @@ expand_unary_array_notation_exprs (tree orig_stmt)
   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);
+      make_triplet_val_inv (&ARRAY_NOTATION_START (array_node));
+      make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (array_node));
+      make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (array_node));
     }
   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));
+      tree typ = ptrdiff_type_node;
+      an_loop_info[ii].var = create_temporary_var (typ);
+      add_decl_expr (an_loop_info[ii].var);
       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)),
+	(location, an_loop_info[ii].var, INIT_EXPR, build_zero_cst (typ), 
 	 tf_warning_or_error);
     }
   array_operand = create_array_refs (location, an_info, an_loop_info,
@@ -1159,7 +1090,7 @@ expand_unary_array_notation_exprs (tree orig_stmt)
   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);
+  append_to_statement_list (an_init, &loop_with_init);
   body = stmt;
   
   for (ii = 0; ii < rank; ii++)
@@ -1169,7 +1100,7 @@ expand_unary_array_notation_exprs (tree orig_stmt)
 		      an_loop_info[ii].incr, body);
       body = pop_stmt_list (new_loop);
     }
-  append_to_statement_list_force (body, &loop_with_init);
+  append_to_statement_list (body, &loop_with_init);
 
   an_info.release ();
   an_loop_info.release ();
@@ -1185,21 +1116,35 @@ static tree
 expand_return_expr (tree expr)
 {
   tree new_mod_list, new_var, new_mod, retval_expr;
-
+  size_t rank  = 0;
+  location_t loc = EXPR_LOCATION (expr);
   if (TREE_CODE (expr) != RETURN_EXPR)
     return expr;
+      
+  if (!find_rank (loc, expr, expr, false, &rank))
+    return error_mark_node;
 
-  location_t loc = EXPR_LOCATION (expr);
-  new_mod_list = alloc_stmt_list ();
+  /* If the return expression contains array notations, then flag it as
+     error.  */
+  if (rank >= 1)
+    {
+      error_at (loc, "array notation expression cannot be used as a return "
+		"value");
+      return error_mark_node;
+    }
+  
+  new_mod_list = push_stmt_list ();
   retval_expr = TREE_OPERAND (expr, 0);
-  new_var = build_decl (loc, VAR_DECL, NULL_TREE, TREE_TYPE (retval_expr));
+  new_var = create_temporary_var (TREE_TYPE (retval_expr));
+  add_decl_expr (new_var);
   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),
+				      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);
+  add_stmt (new_mod);
+  add_stmt (expr);
+  new_mod_list = pop_stmt_list (new_mod_list);
   return new_mod_list;
 }
 
@@ -1336,19 +1281,21 @@ expand_array_notation_exprs (tree 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:      
+    case FOR_STMT:
+      if (contains_array_notation_expr (FOR_COND (t)))
+	{
+	  error_at (EXPR_LOCATION (FOR_COND (t)),
+		    "array notation cannot be used in a condition for "
+		    "a for-loop");
+	  return error_mark_node;
+	}
       /* 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));
+	{ 
+	  FOR_BODY (t) = expand_array_notation_exprs (FOR_BODY (t));
+	  FOR_EXPR (t) = expand_array_notation_exprs (FOR_EXPR (t));
+	}
       else
 	t = expand_array_notation_exprs (t);
       return t;
@@ -1368,44 +1315,39 @@ expand_array_notation_exprs (tree t)
 	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 (contains_array_notation_expr (SWITCH_STMT_COND (t)))
 	{
-	  if (SWITCH_STMT_BODY (t))
-	    SWITCH_STMT_BODY (t) =
-	      expand_array_notation_exprs (SWITCH_STMT_BODY (t));
+	  error_at (EXPR_LOCATION (SWITCH_STMT_COND (t)),
+		    "array notation cannot be used as a condition for "
+		    "switch statement");
+	  return error_mark_node;
 	}
-      else
-	t = expand_array_notation_exprs (t);
+      if (SWITCH_STMT_BODY (t))
+	SWITCH_STMT_BODY (t) =
+	  expand_array_notation_exprs (SWITCH_STMT_BODY (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 (contains_array_notation_expr (WHILE_COND (t)))
 	{
-	  if (WHILE_BODY (t))
-	    WHILE_BODY (t) = expand_array_notation_exprs (WHILE_BODY (t));
+	  if (EXPR_LOCATION (WHILE_COND (t)) != UNKNOWN_LOCATION)
+	    loc = EXPR_LOCATION (WHILE_COND (t));
+	  error_at (loc, "array notation cannot be used as a condition for "
+		    "while statement");
+	  return error_mark_node;
 	}
-      else
-	t = expand_array_notation_exprs (t);
+      if (WHILE_BODY (t))
+	WHILE_BODY (t) = expand_array_notation_exprs (WHILE_BODY (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));
+      if (contains_array_notation_expr (DO_COND (t)))
+	{
+	  error_at (EXPR_LOCATION (DO_COND (t)),
+		    "array notation cannot be used as a condition for a "
+		    "do-while statement");
+	  return error_mark_node;
 	}
-      else
-	t = expand_array_notation_exprs (t);
+      if (DO_BODY (t))
+	DO_BODY (t) = expand_array_notation_exprs (DO_BODY (t));
       return t;
     default:
       if (is_expr)
@@ -1508,20 +1450,9 @@ cilkplus_an_triplet_types_ok_p (location_t loc, tree start_index, tree length,
     }
   if (!TREE_CODE (type) == FUNCTION_TYPE)
     {
-      error_at (loc, "array notations cannot be used with function type");
+      error_at (loc, "array notation 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))
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 38ef878..590d857 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -1207,6 +1207,12 @@ cp_genericize (tree fndecl)
   if (DECL_CLONED_FUNCTION_P (fndecl))
     return;
 
+  /* Expand all the array notations here.  */
+  if (flag_enable_cilkplus 
+      && contains_array_notation_expr (DECL_SAVED_TREE (fndecl)))
+    DECL_SAVED_TREE (fndecl) = 
+      expand_array_notation_exprs (DECL_SAVED_TREE (fndecl));
+
   /* We do want to see every occurrence of the parms, so we can't just use
      walk_tree's hash functionality.  */
   cp_genericize_tree (&DECL_SAVED_TREE (fndecl));
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 00ee450..a3438a8 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4974,6 +4974,7 @@ extern bool pragma_java_exceptions;
 
 /* in call.c */
 extern bool check_dtor_name			(tree, tree);
+bool magic_varargs_p                            (tree);
 
 extern tree build_conditional_expr		(location_t, tree, tree, tree, 
                                                  tsubst_flags_t);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index f3bc27a..820a89a 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -6062,10 +6062,10 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 
 /* 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
+   INIT_INDEX is NULL, then we have special case where 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.  */
+   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,
@@ -6074,26 +6074,22 @@ cp_parser_array_notation (location_t loc, cp_parser *parser, tree init_index,
   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);
-    }
+
+  array_type = TREE_TYPE (array_value);
+  if (processing_template_decl) 
+    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)
     {
@@ -6117,44 +6113,24 @@ cp_parser_array_notation (location_t loc, cp_parser *parser, tree init_index,
 	      || TREE_CODE (array_type) == POINTER_TYPE)
 	    {
 	      error_at (loc, "start-index and length fields necessary for "
-			"using array notations in pointers or records");
+			"using array notation 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");
+			"using array notation with array of unknown bound");
 	      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);
+	  start_index = cp_fold_convert (ptrdiff_type_node, start_index);
+	  length_index = size_binop 
+	    (PLUS_EXPR, TYPE_MAXVAL (array_type_domain), size_one_node);
+	  length_index = cp_fold_convert (ptrdiff_type_node, length_index);
+	  stride = build_int_cst (ptrdiff_type_node, 1);
 	}
       else if (init_index != error_mark_node)
 	{
@@ -6165,25 +6141,19 @@ cp_parser_array_notation (location_t loc, cp_parser *parser, tree init_index,
 	  start_index = init_index;
 	  cp_lexer_consume_token (parser->lexer);
 
-	  saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
+	  bool 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);
@@ -6193,7 +6163,9 @@ cp_parser_array_notation (location_t loc, cp_parser *parser, tree init_index,
 		}
 	    }
 	  else
-	    stride = build_one_cst (integer_type_node);
+	    stride = build_one_cst (integer_type_node); 
+	  /* Disable correcting single colon correcting to scope.  */
+	  parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
 	}
       else
 	{
@@ -6211,13 +6183,7 @@ cp_parser_array_notation (location_t loc, cp_parser *parser, tree init_index,
       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);
@@ -6248,8 +6214,7 @@ cp_parser_postfix_open_square_expression (cp_parser *parser,
   if (flag_enable_cilkplus
       && cp_lexer_peek_token (parser->lexer)->type == CPP_COLON)
     /* If we are here, then we have something like this:
-       ARRAY[:]
-    */
+       ARRAY[:]   */
     postfix_expression = cp_parser_array_notation (loc, parser, NULL_TREE,
 						   postfix_expression);
   else
@@ -6259,8 +6224,7 @@ cp_parser_postfix_open_square_expression (cp_parser *parser,
 	 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.
-      */
+	 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
@@ -6288,7 +6252,7 @@ cp_parser_postfix_open_square_expression (cp_parser *parser,
 		{
 		  error_at (cp_lexer_peek_token (parser->lexer)->location,
 			    "braced list index is not allowed with array "
-			    "notations");
+			    "notation");
 		  index = error_mark_node;
 		}
 	    }
@@ -9550,9 +9514,6 @@ cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr,
   finish_compound_stmt (compound_stmt);
   /* 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;
 }
 
@@ -9745,14 +9706,6 @@ 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;
@@ -10310,12 +10263,6 @@ 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;
 
@@ -10342,15 +10289,6 @@ 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;
 
@@ -10367,19 +10305,10 @@ cp_parser_iteration_statement (cp_parser* parser)
 	/* Parse the body of the for-statement.  */
 	parser->in_statement = IN_ITERATION_STMT;
 	cp_parser_already_scoped_statement (parser);
-	parser->in_statement = in_statement;
+	parser->in_statement = in_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);
+	/* We're done with the for-statement.  */ 
+	finish_for_stmt (statement);
       }
       break;
 
@@ -16953,54 +16882,30 @@ cp_parser_direct_declarator (cp_parser* parser,
 	  if (token->type != CPP_CLOSE_SQUARE)
 	    {
 	      bool non_constant_p;
-
-	      if (flag_enable_cilkplus
-		  && cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+	      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;
-		  error_at (cp_lexer_peek_token (parser->lexer)->location,
-			    "array notations cannot be used in declaration");
-		  cp_lexer_consume_token (parser->lexer);
 		}
-	      else
+	      else if (processing_template_decl)
 		{
-		  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; 
-		    }
+		  /* Remember this wasn't a constant-expression.  */
+		  bounds = build_nop (TREE_TYPE (bounds), bounds);
+		  TREE_SIDE_EFFECTS (bounds) = 1;
 		}
 	    }
 	  else
@@ -18372,10 +18277,6 @@ cp_parser_ctor_initializer_opt_and_function_body (cp_parser *parser,
   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);
 
@@ -22355,12 +22256,6 @@ 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));
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 667e37f..5dafdcd 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -15739,9 +15739,6 @@ 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;
@@ -19143,11 +19140,6 @@ 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);
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 0a460a4..87c1560 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -779,22 +779,6 @@ 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 ())
@@ -8089,7 +8073,6 @@ 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);
@@ -8901,7 +8884,6 @@ 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:
@@ -8912,6 +8894,9 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
 	  return false;
       return true;
 
+    case ARRAY_NOTATION_REF:
+      return false;
+
     case FMA_EXPR:
     case VEC_PERM_EXPR:
      for (i = 0; i < 3; ++i)
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 5b321ce..fb9a537 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -3493,10 +3493,6 @@ cp_build_function_call_vec (tree function, vec<tree, va_gc> **params,
       params = &allocated;
     }
 
-  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)
@@ -3660,8 +3656,7 @@ convert_arguments (tree typelist, vec<tree, va_gc> **values, tree fndecl,
 	}
       else
 	{
-	  if (fndecl && DECL_BUILT_IN (fndecl)
-	      && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CONSTANT_P)
+	  if (fndecl && magic_varargs_p (fndecl))
 	    /* Don't do ellipsis conversion for __built_in_constant_p
 	       as this will result in spurious errors for non-trivial
 	       types.  */
@@ -3954,17 +3949,10 @@ cp_build_binary_op (location_t location,
 		       TREE_TYPE (t));
 	  op1 = t;
 	}
-    }
-
-  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);
+  type0 = TREE_TYPE (op0); 
+  type1 = TREE_TYPE (op1);
 
   /* The expression codes of the data types of the arguments tell us
      whether the arguments are integers, floating, pointers, etc.  */
@@ -5167,13 +5155,6 @@ 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)))
     {
@@ -7852,13 +7833,6 @@ 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);
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/decl-ptr-colon.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/decl-ptr-colon.c
index 68c8859..4b54f4d 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/decl-ptr-colon.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/decl-ptr-colon.c
@@ -1,3 +1,4 @@
+/* { dg-do compile { target c } } */
 /* { dg-options "-fcilkplus" } */
 
 int main(void)
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/dimensionless-arrays.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/dimensionless-arrays.c
index 69aaa52..690e89a 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/dimensionless-arrays.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/dimensionless-arrays.c
@@ -5,6 +5,6 @@ extern int *b;
 
 void foo()
 {
-  a[:] = 5;	// { dg-error "start-index and length fields necessary for using array notations in dimensionless arrays" }
-  b[:] = 5;    // { dg-error "start-index and length fields necessary for using array notations in pointers" }
+  a[:] = 5;	// { dg-error "start-index and length fields necessary for using array notation" }
+  b[:] = 5;    // { dg-error "start-index and length fields necessary for using" }
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/fn_ptr.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/fn_ptr.c
index 024a158..fa6d900 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/fn_ptr.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/fn_ptr.c
@@ -1,3 +1,4 @@
+/* { dg-do compile } */
 /* { dg-options "-fcilkplus" } */
 
 typedef int (*foo)(int);
@@ -10,11 +11,11 @@ int main(void)
   foo ***func_array_ptr;
   int argc = 5;
 
-  array[:] =  func_array[:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
-  func_array[0:5](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
-  func_array2[0:5][:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
-  array2[0:5][:] = func_array2[0:5][:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
-  func_array_ptr[0:5][0:4][0:argc:2](argc); /* { dg-error "array notations cannot be used with function pointer arrays" } */
+  array[:] =  func_array[:](10); 
+  func_array[0:5](10); 
+  func_array2[0:5][:](10);
+  array2[0:5][:] = func_array2[0:5][:](10);
+  func_array_ptr[0:5][0:4][0:argc:2](argc); 
 
   return 0;
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
index 14421d9..814786b 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
@@ -6,7 +6,7 @@ int main (void)
   int array[10], array2[10][10];
   int x, ii, jj ;
 
-  switch (array[:]) {  /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  switch (array[:]) {  /* { dg-error "cannot be used as a condition for switch statement" } */
   case 1:
     x = 5;
     break;
@@ -17,7 +17,7 @@ int main (void)
     x = 9;
   }
 
-  switch (array2[:][:]) { /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  switch (array2[:][:]) { /* { dg-error "cannot be used as a condition for switch statement" } */
   case 1:
     x = 5;
     break;
@@ -28,7 +28,7 @@ int main (void)
     x = 9;
   }
 
-  switch (array[:] + x) { /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  switch (array[:] + x) { /* { dg-error "cannot be used as a condition for switch statement" } */
   case 1:
     x = 5;
     break;
@@ -39,7 +39,7 @@ int main (void)
     x = 9;
   }
   
-  switch (array2[:][1:x:4] + x) { /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  switch (array2[:][1:x:4] + x) { /* { dg-error "cannot be used as a condition for switch statement" } */
   case 1:
     x = 5;
     break;
@@ -50,36 +50,36 @@ int main (void)
     x = 9;
   }
 
-  for (ii = 0; ii < array[:]; ii++) /* { dg-error "array notations cannot be used in a condition for a for-loop" } */
+  for (ii = 0; ii < array[:]; ii++) /* { dg-error "cannot be used in a condition for a for-loop" } */
     {
       x = 2;
     }
 
-  for (ii = 0; ii < array2[:][:]; ii++) /* { dg-error "array notations cannot be used in a condition for a for-loop" } */
+  for (ii = 0; ii < array2[:][:]; ii++) /* { dg-error "cannot be used in a condition for a for-loop" } */
     {
       x = 3;
     }
 
-  for (; array2[:][:] < 2;) /* { dg-error "array notations cannot be used in a condition for a for-loop" } */
+  for (; array2[:][:] < 2;) /* { dg-error "cannot be used in a condition for a for-loop" } */
     x = 4;
 
 
-  while (array2[:][:]) /* { dg-error "array notations cannot be used as a condition for while statement" } */
+  while (array2[:][:]) /* { dg-error "cannot be used as a condition for while statement" } */
     x = 3;
 
-  while (array[1:1:1]) /* { dg-error "array notations cannot be used as a condition for while statement" } */
+  while (array[1:1:1]) /* { dg-error "cannot be used as a condition for while statement" } */
     x = 1;
 
-  while (ii != array2[1:x:3][1:2:1]) /* { dg-error "array notations cannot be used as a condition for while statement"  } */
+  while (ii != array2[1:x:3][1:2:1]) /* { dg-error "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" "" { target c } } */
+  do { /* { dg-error "cannot be used as a condition for a do-while statement" "" { target c } } */
     x = 3;
-  } while (ii != array2[:][:]); /* { dg-error "array notations cannot be used as a condition for a do-while statement" "" { target c++ } } */
+  } while (ii != array2[:][:]); /* { dg-error "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" "" { target c } } */
+  do {  /* { dg-error "cannot be used as a condition for a do-while statement" "" { target c } } */
     x = 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++ } } */
+  } while (ii != (x + array2[:][1:x:2]) + 2); /* { dg-error "cannot be used as a condition for a do-while statement" "" { target c++ } } */
   
   do { 
     x += 3;
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/rank_mismatch.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/rank_mismatch.c
index b5e37ce..eb3c1f1 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/rank_mismatch.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/rank_mismatch.c
@@ -10,6 +10,7 @@ int main (void)
   int array[10][10], array2[10];
 
   array[:][:] = array[:]; /* { dg-error "rank mismatch between" } */
+  /* { dg-error "invalid conversion" "" { target c++ } 12 } */
 
   x = array2[:]; /* { dg-error "cannot be scalar when" } */
 

[-- Attachment #3: CL.txt --]
[-- Type: text/plain, Size: 5579 bytes --]

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

        * builtins.def: Fixed the function type of CILKPLUS_BUILTIN.

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

        * c-parser.c (c_parser_array_notation): Removed rejection of array
        notations in an array of function pointers.

gcc/c-family/ChangeLog
2013-06-25  Balaji V. Iyer  <balaji.v.iyer@intel.com>

        * array-notation-common.c (length_mismatch_in_expr_p): Collapsed two
        if-statements and compared the trees directly using tree_int_cst_equal.
        (find_rank): Checked for array notations in function name to handle
        array notations in function pointers.
        (extract_array_notation_exprs): Likewise.
        (replace_array_notations): Likewise.
        (cilkplus_extract_an_triplets): Replaced safe_push with
        safe_grow_cleared.  Also removed an unnecessary check to see if the
        node is of type ARRAY_NOTATION_REF.
        (fix_sec_implicit_args): Removed an unnecessary check for ADDR_EXPR.
        Also switched two if-statements to remove an unnecessary comparison.


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

        * parser.c (cp_parser_array_notation): Removed rejection array notation
        of type function pointers.  Used cp_fold_convert instead of fold_build1.
        Moved variable that saves colon corrects variable into the if-statement.
        (cp_parser_compound_statement): Removed expansion of array notations.
        (cp_parser_ctor_initializer_opt_and_function_body): Likewise.
        (cp_parser_function_definition_after_declarator): Likewise.
        (cp_parser_selection_statement): Removed error reporting.
        (cp_parser_iteration_statement): Likewise.
        (cp_parser_direct_declarator): Removed error checking/reporting if
        array notations are used in the declarator.
        * pt.c (instantiate_decl): Likewise.
        (type_unification_real): Removed a check for ARRAY_NOTATION_REF.
        (cxx_eval_constant_expression): Removed ARRAY_NOTATION_REF case.
        (potential_constant_expression_1): Returned false for ARRAY_NOTATION_REF
        case.
        * cp-gimplify.c (cp_genericize): Added expansion of array notation
        expressions here.
        * cp-array-notation.c (cp_length_mismatch_in_expr_p): Combined two
        if statements into one and compared integers using tree_int_cst_equal.
        (make_triplet_val_inv): Removed loc and cry parameters.  Also, replaced
        build_decls with get_temp_regvar.
        (replace_invariant_var): Replaced build_decl and build_min_nt_loc with
        get_temp_regvar.
        (expand_an_in_modify_expr): Ditto. Replaced body of redundant else with
        gcc_unreachable.  Removed few unwanted checks. Made induction variable
        type as ptrdiff_type.  Removed loc and complain arguments passed into
        make_triplet_val_inv.  Replaced all modify expression's code from NOP
        EXPR to INIT EXPR.  Replaced all forceful appending into stmt. list
        with the non-forceful one.  Replaced some integer conversion and
        checking to using tree_int_cst_equal.
        (expand_reduce_builtin): All changes mentioned in above function
        expand_an_in_modify_expr.  Made the new variable type of
        SEC_REDUCE_ANY/ALL_{NON}ZERO intrinsic functions as bool.
        (expand_array_notation_exprs): Removed SWITCH_EXPR case.  Moved all
        the error reporting from parser to this function.  Removed unwanted
        statements and checks from SWITCH_STMT, WHILE_STMT, and DO_STMT cases.
        (cilkplus_an_triplet_types_ok_p): Removed rejection of array notation
        in function pointers.
        (cp_expand_cond_array_notations): Added a new if statements to check
        if condition has a zero rank.  If so, then just return.
        (expand_return_expr): Added a check for return expressions with a rank.
        Replaced get_tmp_regvar with a create_temporary_var.
        * semantics.c (finish_return_stmt): Removed a check for return exprs.
        with a rank.
        * call.c (convert_like_real): Removed a check for array notation
         expression in a function.
        (build_over_call): Likewise.
        (magic_varargs_p): Added a check for builtin array notation function.
        Made this function non-static and removed its prototype.
        * cp-tree.h (magic_varargs_p): New prototype.
        * typeck.c (cp_build_function_call_vec): Removed automatic setting of
        nargs to the param->length when builtin reduction function is used.
        (convert_arguments): Replaced check for a constant_p function with
        margic_varargs_p function call.
        (cp_build_binary_op): Removed calling of the function
        find_correct_array_notation_type.
        (cp_build_addr_expr_1): Removed an unwanted if-statement.
        (convert_for_assignment): Removed automatic return of rhs when array
        notation builtin function is used.

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

        * c-c++-common/cilk-plus/AN/decl-ptr-colon.c (main): Made this testcase
        c specific.
        * c-c++-common/cilk-plus/AN/decl-ptr-colon.c (main): Changed dg-error
        strings to match the fixed error messages.
        * c-c++-common/cilk-plus/AN/misc.c (main): Likewise.
        * c-c++-common/cilk-plus/AN/rank_mismatch.c (main): Added a new error
        message check.


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH] Cilk Plus Array Notation for C++
  2013-06-25 18:27                             ` Iyer, Balaji V
@ 2013-06-25 20:55                               ` Jason Merrill
  2013-06-26 17:32                                 ` Iyer, Balaji V
  0 siblings, 1 reply; 40+ messages in thread
From: Jason Merrill @ 2013-06-25 20:55 UTC (permalink / raw)
  To: Iyer, Balaji V, Richard Henderson; +Cc: Aldy Hernandez, gcc-patches

On 06/25/2013 02:27 PM, Iyer, Balaji V wrote:
> This time, I ran the command you gave me. Please tell me how it looks.

No ChangeLog this time, thanks.

> Another solution is to replace get_tmp_regvar with get_temporary_var () + add_decl_expr (..). I have implemented this because it looks "more correct"

OK.

> I am setting the scope correction to false right before I look for length and restore it right after I parse the scope (i.e. outside the if-statement). I think this should fix the issue.

OK.

>> I think it would be better to convert start/stride to ptrdiff_t.
>
> I don't think I can do that. Stride can be negative and if I am not mistaken, ptrdiff_t is unsigned.

You are mistaken.  :)
ptrdiff_t is the signed version of size_t.

>> What I had in mind is that in the case of a normal array reference,
>> cp_parser_array_notation will update index (which is passed by address) and
>> return NULL_TREE, so that it gets back on the normal path.

It doesn't look like you addressed this comment.

>>> +  if (processing_template_decl)
>>> +    {
>>> +      array_type = TREE_TYPE (array_value);
>>> +      type = TREE_TYPE (array_type);
>>> +    }
>>
>> We should be able to parse array notation in a template even when the array
>> expression has unknown type.  In a template, just parse and remember the raw
>> expressions without worrying about diagnostics and conversions.

Or this one.

>>> +  /* If an array's index is an array notation, then its rank cannot be
>>> +     greater than one.  */
>
> This one error is much easier to do it here than anywhere else. An array_ref could be a parameter inside a function, part of a modify expression, unary expression etc. If I move it to transformation stage, I have to do checks in all these places and there is a small chance some will slip through the cracks. This is almost a fool proof way of doing it. Such things have been done before. For example, Open MP does a return expression check in finish_return_stmt (even though this is a different issue we are talking about).

What's the failure mode if one is missed?  I would expect it to be 
pretty obvious.

> If it is the code lines that is an issue, then I am willing to enclose that in a function or #define.

But I guess splitting it out into a separate function is OK.

>> What remaining obstacles are there to sharing most of the expansion code
>> between C and C++?  That can be a separate patch, of course.

Any thoughts?

Jason

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH] Cilk Plus Array Notation for C++
  2013-06-25 18:42                             ` Iyer, Balaji V
@ 2013-06-26 13:00                               ` Aldy Hernandez
  0 siblings, 0 replies; 40+ messages in thread
From: Aldy Hernandez @ 2013-06-26 13:00 UTC (permalink / raw)
  To: Iyer, Balaji V; +Cc: Jason Merrill, Richard Henderson, gcc-patches

On 06/25/13 13:42, Iyer, Balaji V wrote:

>>> What remaining obstacles are there to sharing most of the expansion
>>> code between C and C++?  That can be a separate patch, of course.
>>>
>>> Jason
>

??

^ permalink raw reply	[flat|nested] 40+ messages in thread

* RE: [PATCH] Cilk Plus Array Notation for C++
  2013-06-25 20:55                               ` Jason Merrill
@ 2013-06-26 17:32                                 ` Iyer, Balaji V
  2013-06-26 20:12                                   ` Jason Merrill
  0 siblings, 1 reply; 40+ messages in thread
From: Iyer, Balaji V @ 2013-06-26 17:32 UTC (permalink / raw)
  To: Jason Merrill, Richard Henderson; +Cc: Aldy Hernandez, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 3446 bytes --]

Hi Jason et al.,
	Attached, please find a fixed patch and ChangeLog entries:

Thanks,

Balaji V. Iyer.

> -----Original Message-----
> From: Jason Merrill [mailto:jason@redhat.com]
> Sent: Tuesday, June 25, 2013 4:56 PM
> To: Iyer, Balaji V; Richard Henderson
> Cc: Aldy Hernandez; gcc-patches@gcc.gnu.org
> Subject: Re: [PATCH] Cilk Plus Array Notation for C++
> 
> On 06/25/2013 02:27 PM, Iyer, Balaji V wrote:
> > This time, I ran the command you gave me. Please tell me how it looks.
> 
> No ChangeLog this time, thanks.
> 
> > Another solution is to replace get_tmp_regvar with get_temporary_var () +
> add_decl_expr (..). I have implemented this because it looks "more correct"
> 
> OK.
> 
> > I am setting the scope correction to false right before I look for length and
> restore it right after I parse the scope (i.e. outside the if-statement). I think this
> should fix the issue.
> 
> OK.
> 
> >> I think it would be better to convert start/stride to ptrdiff_t.
> >
> > I don't think I can do that. Stride can be negative and if I am not mistaken,
> ptrdiff_t is unsigned.
> 
> You are mistaken.  :)
> ptrdiff_t is the signed version of size_t.
>

Fixed! I have converted them all into ptrdiff_type_node.
 
> >> What I had in mind is that in the case of a normal array reference,
> >> cp_parser_array_notation will update index (which is passed by
> >> address) and return NULL_TREE, so that it gets back on the normal path.
> 
> It doesn't look like you addressed this comment.
> 

Sorry about that, I accidentally missed this one. It is fixed now. I have also added the braced list capability into cp_array_notation.

> >>> +  if (processing_template_decl)
> >>> +    {
> >>> +      array_type = TREE_TYPE (array_value);
> >>> +      type = TREE_TYPE (array_type);
> >>> +    }
> >>
> >> We should be able to parse array notation in a template even when the
> >> array expression has unknown type.  In a template, just parse and
> >> remember the raw expressions without worrying about diagnostics and
> conversions.
> 
> Or this one.

Sorry about this too. This is also fixed.

> 
> >>> +  /* If an array's index is an array notation, then its rank cannot be
> >>> +     greater than one.  */
> >
> > This one error is much easier to do it here than anywhere else. An array_ref
> could be a parameter inside a function, part of a modify expression, unary
> expression etc. If I move it to transformation stage, I have to do checks in all
> these places and there is a small chance some will slip through the cracks. This is
> almost a fool proof way of doing it. Such things have been done before. For
> example, Open MP does a return expression check in finish_return_stmt (even
> though this is a different issue we are talking about).
> 
> What's the failure mode if one is missed?  I would expect it to be pretty obvious.
> 
> > If it is the code lines that is an issue, then I am willing to enclose that in a
> function or #define.
> 
> But I guess splitting it out into a separate function is OK.
> 
> >> What remaining obstacles are there to sharing most of the expansion
> >> code between C and C++?  That can be a separate patch, of course.
> 
> Any thoughts?
> 

After, I have resolved all implementation changes you mentioned, I will be able to come up with a more concrete answer.

So, is this Patch OK for trunk?

> Jason


[-- Attachment #2: diff.txt --]
[-- Type: text/plain, Size: 79430 bytes --]

diff --git a/gcc/builtins.def b/gcc/builtins.def
index 91879a6..9b55b1f 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -158,9 +158,9 @@ along with GCC; see the file COPYING3.  If not see
 	       (flag_asan || flag_tsan))
 
 #undef DEF_CILKPLUS_BUILTIN
-#define DEF_CILKPLUS_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
-  DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
-  	       false, false, true, ATTRS, false, flag_enable_cilkplus)
+#define DEF_CILKPLUS_BUILTIN(ENUM, NAME, TYPE, ATTRS)  \
+  DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, BT_FN_INT_VAR, BT_LAST, \
+  	       false, false, false, ATTRS, false, flag_enable_cilkplus) 
 
 /* Define an attribute list for math functions that are normally
    "impure" because some of them may write into global memory for
diff --git a/gcc/c-family/array-notation-common.c b/gcc/c-family/array-notation-common.c
index 8eab89b..5e17009 100644
--- a/gcc/c-family/array-notation-common.c
+++ b/gcc/c-family/array-notation-common.c
@@ -101,15 +101,11 @@ length_mismatch_in_expr_p (location_t loc, vec<vec<an_parts> >list)
 	      /* 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;
-		    }
+	      if (TREE_CODE (list[ii][jj].length) == INTEGER_CST
+		  && !tree_int_cst_equal (list[ii][jj].length, length))
+		{ 
+		  error_at (loc, "length mismatch in expression"); 
+		  return true;
 		}
 	    }
 	  else
@@ -271,6 +267,8 @@ find_rank (location_t loc, tree orig_expr, tree expr, bool ignore_builtin_fn,
 		/* If it is a built-in function, then we know it returns a 
 		   scalar.  */
 		return true;
+	  if (!find_rank (loc, orig_expr, func_name, ignore_builtin_fn, rank))
+	    return false;
 	  FOR_EACH_CALL_EXPR_ARG (arg, iter, expr)
 	    {
 	      if (!find_rank (loc, orig_expr, arg, ignore_builtin_fn, rank))
@@ -358,6 +356,9 @@ extract_array_notation_exprs (tree node, bool ignore_builtin_fn,
 	  vec_safe_push (*array_list, node);
 	  return;
 	}
+      /* This will extract array notations in function pointers.  */
+      extract_array_notation_exprs (CALL_EXPR_FN (node), ignore_builtin_fn,
+				    array_list);
       FOR_EACH_CALL_EXPR_ARG (arg, iter, node)
 	extract_array_notation_exprs (arg, ignore_builtin_fn, array_list);
     } 
@@ -433,6 +434,9 @@ replace_array_notations (tree *orig, bool ignore_builtin_fn,
 	      }
 	  return;
 	}
+      /* Fixes array notations in array notations in function pointers.  */
+      replace_array_notations (&CALL_EXPR_FN (*orig), ignore_builtin_fn, list,
+			       array_operand);
       ii = 0;
       FOR_EACH_CALL_EXPR_ARG (arg, iter, *orig)
 	{
@@ -575,53 +579,49 @@ 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++)
+
+  if (rank > 0)
+    for (size_t ii = 0; ii < size; ii++)
       {
-	(*node)[ii].safe_push (init);
-	array_exprs[ii].safe_push (NULL_TREE);
+	(*node)[ii].safe_grow_cleared (rank);
+	array_exprs[ii].safe_grow_cleared (rank);
       }
-
   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 ();	
+	{
+	  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
+	    break;
+	}
     }
     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));
-	    }
+	  {
+	    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
@@ -637,16 +637,15 @@ fix_sec_implicit_args (location_t loc, vec <tree, va_gc> *list,
   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)
+	if (idx < 0)
 	  /* In this case, the returning function would have emitted an
 	     error thus it is not necessary to do so again.  */
 	  return NULL;
+	else if (idx < (int) rank)
+	  vec_safe_push (array_operand, an_loop_info[idx].var);
 	else
 	  {
 	    error_at (loc, "__sec_implicit_index argument %d must be "
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index d6a500e..c7846ce 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -11053,24 +11053,6 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
 	      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
 	      return error_mark_node;
 	    }
-	  if (TREE_CODE (array_type) == ARRAY_TYPE)
-	    {
-	      tree subtype = TREE_TYPE (array_type);
-	      while (subtype && TREE_CODE (subtype) == POINTER_TYPE)
-		{
-		  /* Now this could be a function pointer.  Find them and
-		     give out an error.  */
-		  subtype = TREE_TYPE (subtype);
-		  if (subtype && TREE_CODE (subtype) == FUNCTION_TYPE)
-		    {
-		      error_at (loc, "array notations cannot be used with "
-				"function pointer arrays");
-		      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
-						 NULL);
-		      return error_mark_node;
-		    }
-		}
-	    }
 	  array_type_domain = TYPE_DOMAIN (array_type);
 
 	  if (!array_type_domain)
@@ -11114,27 +11096,6 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
 	      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
 	      return error_mark_node;
 	    }
-	  if (TREE_CODE (array_type) == ARRAY_TYPE
-	      || TREE_CODE (array_type) == POINTER_TYPE)
-	    {
-	      tree subtype = TREE_TYPE (array_type);
-	      while (subtype
-		     && (TREE_CODE (subtype) == POINTER_TYPE
-			 || TREE_CODE (subtype) == ARRAY_TYPE))
-		{
-		  /* Now this could be a function pointer.  Find them and
-		     give out an error.  */
-		  subtype = TREE_TYPE (subtype);
-		  if (subtype && TREE_CODE (subtype) == FUNCTION_TYPE)
-		    {
-		      error_at (loc, "array notations cannot be used with "
-				"function pointer arrays");
-		      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
-						 NULL);
-		      return error_mark_node;
-		    }
-		}
-	    }
 	  c_parser_consume_token (parser); /* consume the ':' */
 	  end_index = c_parser_expression (parser).value;
 	  if (!end_index || end_index == error_mark_node)
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 6817bfc..425ef9b 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -216,7 +216,6 @@ static void add_candidates (tree, tree, const vec<tree, va_gc> *, tree, tree,
 			    bool, tree, tree, int, struct z_candidate **,
 			    tsubst_flags_t);
 static conversion *merge_conversion_sequences (conversion *, conversion *);
-static bool magic_varargs_p (tree);
 static tree build_temp (tree, tree, int, diagnostic_t *, tsubst_flags_t);
 
 /* Returns nonzero iff the destructor name specified in NAME matches BASETYPE.
@@ -5857,16 +5856,9 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
 	  else if (t->kind == ck_identity)
 	    break;
 	}
-
-      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)
+       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);
 
@@ -6515,9 +6507,12 @@ convert_for_arg_passing (tree type, tree val, tsubst_flags_t complain)
    which no conversions at all should be done.  This is true for some
    builtins which don't act like normal functions.  */
 
-static bool
+bool
 magic_varargs_p (tree fn)
 {
+  if (flag_enable_cilkplus && is_cilkplus_reduce_builtin (fn) != BUILT_IN_NONE)
+    return true;
+
   if (DECL_BUILT_IN (fn))
     switch (DECL_FUNCTION_CODE (fn))
       {
@@ -6895,21 +6890,13 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
 		       "  (you can disable this with -fno-deduce-init-list)");
 	    }
 	}
+      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
index 491da0f..edde3e0 100644
--- a/gcc/cp/cp-array-notation.c
+++ b/gcc/cp/cp-array-notation.c
@@ -59,7 +59,6 @@
 #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.  */
@@ -82,17 +81,12 @@ create_an_loop (tree init, tree cond, tree incr, tree body)
    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)
+make_triplet_val_inv (tree *value)
 {
-  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;
-    }
+    *value = get_temp_regvar (ptrdiff_type_node, *value);
 }
 
 /* Returns a vector of size RANK that contains an ARRAY_REF.  This vector is
@@ -140,9 +134,9 @@ create_array_refs (location_t loc, vec<vec<an_parts> > an_info,
 		   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);
+		st = build_c_cast (loc, ptrdiff_type_node, start);
+		str = build_c_cast (loc, ptrdiff_type_node, stride);
+		v = build_c_cast (loc, ptrdiff_type_node, var);
 	      }
 	    else
 	      {
@@ -192,7 +186,7 @@ replace_invariant_exprs (tree *node)
 {
   size_t ix = 0;
   tree node_list = NULL_TREE;
-  tree t = NULL_TREE, new_var = NULL_TREE, new_node; 
+  tree t = NULL_TREE, new_var = NULL_TREE;
   struct inv_list data;
 
   data.list_values = NULL;
@@ -204,17 +198,8 @@ replace_invariant_exprs (tree *node)
     {
       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);
+	{ 
+	  new_var = get_temp_regvar (TREE_TYPE (t), t); 
 	  vec_safe_push (data.replacement, new_var);
 	}
       cp_walk_tree (node, replace_inv_trees, (void *) &data, NULL);
@@ -235,7 +220,6 @@ 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 ();
@@ -305,7 +289,7 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
     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;
+      new_var_type = boolean_type_node;
       break;
     case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
     case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
@@ -334,24 +318,30 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
     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);
+	make_triplet_val_inv (&ARRAY_NOTATION_START (anode));
+	make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (anode));
+	make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (anode));
       }
   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);
+      tree typ = ptrdiff_type_node;
+
+      /* In this place, we are using get_temp_regvar instead of 
+	 create_temporary_var if an_type is SEC_REDUCE_MAX/MIN_IND because
+	 the array_ind_value depends on this value being initalized to 0.  */
+      if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
+	  || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND) 
+	an_loop_info[ii].var = get_temp_regvar (typ, build_zero_cst (typ));
+      else
+	{
+	  an_loop_info[ii].var = create_temporary_var (typ);
+	  add_decl_expr (an_loop_info[ii].var);
+	}
+      an_loop_info[ii].ind_init = 
+	build_x_modify_expr (location, an_loop_info[ii].var, INIT_EXPR,
+			     build_zero_cst (typ), 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);
@@ -360,26 +350,9 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
     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);
-    }
+      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND) 
+    array_ind_value = get_temp_regvar (TREE_TYPE (func_parm), func_parm);
 
   array_op0 = (*array_operand)[0];
   switch (an_type)
@@ -394,35 +367,36 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
       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;
+      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;
+      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;
+      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;
+      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;
+      code = (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND ? LE_EXPR
+	: GE_EXPR);
       init = an_loop_info[0].var;
+      break;
     case BUILT_IN_CILKPLUS_SEC_REDUCE:
       init = identity_value;
       break;
@@ -433,9 +407,11 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
       gcc_unreachable ();
     }
 
-  if (init)
-    new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR, init,
-					tf_warning_or_error);
+  if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
+    *new_var = get_temp_regvar (new_var_type, init);
+  else
+    *new_var = NULL_TREE;
+
   switch (an_type)
     {
     case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD:
@@ -470,8 +446,6 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
       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,
@@ -521,21 +495,8 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
     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);
+  append_to_statement_list (an_init, &loop_with_init);
   body = new_expr;
 
   for (ii = 0; ii < rank; ii++)
@@ -545,7 +506,7 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
 		      an_loop_info[ii].incr, body);
       body = pop_stmt_list (new_loop);
     }
-  append_to_statement_list_force (body, &loop_with_init);
+  append_to_statement_list (body, &loop_with_init);
 
   an_info.release ();
   an_loop_info.release ();
@@ -634,10 +595,7 @@ expand_an_in_modify_expr (location_t location, tree lhs,
 	  return an_init;
 	}
       else
-	{
-	  pop_stmt_list (an_init);
-	  return NULL_TREE;
-	}
+	gcc_unreachable ();
     }
 
   /* If for some reason location is not set, then find if LHS or RHS has
@@ -659,8 +617,6 @@ expand_an_in_modify_expr (location_t location, tree lhs,
     
   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;
     }
@@ -675,17 +631,17 @@ expand_an_in_modify_expr (location_t location, tree lhs,
   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);
+      make_triplet_val_inv (&ARRAY_NOTATION_START (anode));
+      make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (anode));
+      make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (anode));
     }
   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);
+	make_triplet_val_inv (&ARRAY_NOTATION_START (aa));
+	make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (aa));
+	make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (aa));
       }
   lhs_an_loop_info.safe_grow_cleared (lhs_rank);
   
@@ -705,31 +661,29 @@ expand_an_in_modify_expr (location_t location, tree lhs,
       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;
+  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;
-	}
+      && TREE_CODE (rhs_len) == INTEGER_CST 
+      && !tree_int_cst_equal (rhs_len, lhs_len))
+    { 
+      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);
+   for (ii = 0; ii < lhs_rank; ii++) 
+     {
+       tree typ = ptrdiff_type_node; 
+       lhs_an_loop_info[ii].var = create_temporary_var (typ);
+       add_decl_expr (lhs_an_loop_info[ii].var);
+       lhs_an_loop_info[ii].ind_init = build_x_modify_expr 
+	 (location, lhs_an_loop_info[ii].var, INIT_EXPR, build_zero_cst (typ), 
+	  complain);
+     }
+   
    if (rhs_list_size > 0)
      {
        rhs_array_operand = fix_sec_implicit_args (location, rhs_list,
@@ -743,24 +697,15 @@ expand_an_in_modify_expr (location_t location, tree lhs,
   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));
+      tree typ = ptrdiff_type_node;
+      rhs_an_loop_info[ii].var = create_temporary_var (typ);
+      add_decl_expr (rhs_an_loop_info[ii].var);
       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);
+	(location, rhs_an_loop_info[ii].var, INIT_EXPR, build_zero_cst (typ), 
+	 complain);
     }
 
   if (lhs_rank)
@@ -809,12 +754,12 @@ expand_an_in_modify_expr (location_t location, tree lhs,
     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.  */
+      /* No need to compare ii < rhs_rank && ii >= lhs_rank because in a valid 
+	 Array notation expression, rank of RHS cannot be greater than LHS.  */
       gcc_unreachable ();
   
   an_init = pop_stmt_list (an_init);
-  append_to_statement_list_force (an_init, &loop_with_init);
+  append_to_statement_list (an_init, &loop_with_init);
   body = array_expr;
   for (ii = 0; ii < MAX (lhs_rank, rhs_rank); ii++)
     {
@@ -824,17 +769,13 @@ expand_an_in_modify_expr (location_t location, tree lhs,
 
       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);
+	  append_to_statement_list (lhs_an_loop_info[ii].ind_init, &init_list);
+	  append_to_statement_list (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);
+	  append_to_statement_list (rhs_an_loop_info[ii].ind_init, &init_list);
+	  append_to_statement_list (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);
@@ -867,7 +808,6 @@ cp_expand_cond_array_notations (tree orig_stmt)
   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;
@@ -884,13 +824,17 @@ cp_expand_cond_array_notations (tree orig_stmt)
 	  || 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)
+      /* If the condition has a zero rank, then handle array notations in body
+	 seperately.  */
+      if (cond_rank == 0)
+	return orig_stmt;
+      if (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)
+      else if (cond_rank != no_rank && no_rank != 0)
 	{
 	  error_at (EXPR_LOCATION (no_expr), "rank mismatch with controlling "
 		    "expression of parent if-statement");
@@ -911,13 +855,17 @@ cp_expand_cond_array_notations (tree orig_stmt)
 	      && !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)
+
+      /* Same reasoning as for COND_EXPR.  */
+      if (cond_rank == 0)
+	return orig_stmt;
+      else if (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)
+      else if (cond_rank != no_rank && no_rank != 0)
 	{
 	  error_at (EXPR_LOCATION (no_expr), "rank mismatch with controlling "
 		    "expression of parent if-statement");
@@ -949,11 +897,11 @@ cp_expand_cond_array_notations (tree orig_stmt)
 	      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 (builtin_loop, &stmt);
 	    }
 	}
     }
-  append_to_statement_list_force (orig_stmt, &stmt);
+  append_to_statement_list (orig_stmt, &stmt);
   rank = 0;
   array_list = NULL;
   if (!find_rank (EXPR_LOCATION (stmt), stmt, stmt, true, &rank))
@@ -977,37 +925,28 @@ cp_expand_cond_array_notations (tree orig_stmt)
   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);
+      make_triplet_val_inv (&ARRAY_NOTATION_START (anode));
+      make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (anode));
+      make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (anode));
     }
   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);
-	}
+
+  for (ii = 0; ii < rank; ii++) 
+    {
+      tree typ = ptrdiff_type_node;
+      an_loop_info[ii].var = create_temporary_var (typ);
+      add_decl_expr (an_loop_info[ii].var);
+      an_loop_info[ii].ind_init =
+	build_x_modify_expr (location, an_loop_info[ii].var, INIT_EXPR,
+			     build_zero_cst (typ), 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);
+  append_to_statement_list (an_init, &loop_with_init);
   body = stmt;
 
   for (ii = 0; ii < rank; ii++)
@@ -1017,7 +956,7 @@ cp_expand_cond_array_notations (tree orig_stmt)
 		      an_loop_info[ii].incr, body);
       body = pop_stmt_list (new_loop);
     }
-  append_to_statement_list_force (body, &loop_with_init);
+  append_to_statement_list (body, &loop_with_init);
 
   an_info.release ();
   an_loop_info.release ();
@@ -1062,14 +1001,14 @@ expand_unary_array_notation_exprs (tree orig_stmt)
 	  {
 	    vec<tree, va_gc> *sub_list = NULL, *new_var_list = NULL;
 	    stmt = alloc_stmt_list ();
-	    append_to_statement_list_force (builtin_loop, &stmt);
+	    append_to_statement_list (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);
+    append_to_statement_list (finish_expr_stmt (orig_stmt), &stmt);
   else
     stmt = orig_stmt;
   rank = 0;
@@ -1089,22 +1028,19 @@ expand_unary_array_notation_exprs (tree orig_stmt)
   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);
+      make_triplet_val_inv (&ARRAY_NOTATION_START (array_node));
+      make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (array_node));
+      make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (array_node));
     }
   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));
+      tree typ = ptrdiff_type_node;
+      an_loop_info[ii].var = create_temporary_var (typ);
+      add_decl_expr (an_loop_info[ii].var);
       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)),
+	(location, an_loop_info[ii].var, INIT_EXPR, build_zero_cst (typ), 
 	 tf_warning_or_error);
     }
   array_operand = create_array_refs (location, an_info, an_loop_info,
@@ -1113,7 +1049,7 @@ expand_unary_array_notation_exprs (tree orig_stmt)
   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);
+  append_to_statement_list (an_init, &loop_with_init);
   body = stmt;
   
   for (ii = 0; ii < rank; ii++)
@@ -1123,7 +1059,7 @@ expand_unary_array_notation_exprs (tree orig_stmt)
 		      an_loop_info[ii].incr, body);
       body = pop_stmt_list (new_loop);
     }
-  append_to_statement_list_force (body, &loop_with_init);
+  append_to_statement_list (body, &loop_with_init);
 
   an_info.release ();
   an_loop_info.release ();
@@ -1139,21 +1075,35 @@ static tree
 expand_return_expr (tree expr)
 {
   tree new_mod_list, new_var, new_mod, retval_expr;
-
+  size_t rank  = 0;
+  location_t loc = EXPR_LOCATION (expr);
   if (TREE_CODE (expr) != RETURN_EXPR)
     return expr;
+      
+  if (!find_rank (loc, expr, expr, false, &rank))
+    return error_mark_node;
 
-  location_t loc = EXPR_LOCATION (expr);
-  new_mod_list = alloc_stmt_list ();
+  /* If the return expression contains array notations, then flag it as
+     error.  */
+  if (rank >= 1)
+    {
+      error_at (loc, "array notation expression cannot be used as a return "
+		"value");
+      return error_mark_node;
+    }
+  
+  new_mod_list = push_stmt_list ();
   retval_expr = TREE_OPERAND (expr, 0);
-  new_var = build_decl (loc, VAR_DECL, NULL_TREE, TREE_TYPE (retval_expr));
+  new_var = create_temporary_var (TREE_TYPE (retval_expr));
+  add_decl_expr (new_var);
   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),
+				      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);
+  add_stmt (new_mod);
+  add_stmt (expr);
+  new_mod_list = pop_stmt_list (new_mod_list);
   return new_mod_list;
 }
 
@@ -1290,19 +1240,21 @@ expand_array_notation_exprs (tree 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:      
+    case FOR_STMT:
+      if (contains_array_notation_expr (FOR_COND (t)))
+	{
+	  error_at (EXPR_LOCATION (FOR_COND (t)),
+		    "array notation cannot be used in a condition for "
+		    "a for-loop");
+	  return error_mark_node;
+	}
       /* 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));
+	{ 
+	  FOR_BODY (t) = expand_array_notation_exprs (FOR_BODY (t));
+	  FOR_EXPR (t) = expand_array_notation_exprs (FOR_EXPR (t));
+	}
       else
 	t = expand_array_notation_exprs (t);
       return t;
@@ -1322,44 +1274,39 @@ expand_array_notation_exprs (tree t)
 	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 (contains_array_notation_expr (SWITCH_STMT_COND (t)))
 	{
-	  if (SWITCH_STMT_BODY (t))
-	    SWITCH_STMT_BODY (t) =
-	      expand_array_notation_exprs (SWITCH_STMT_BODY (t));
+	  error_at (EXPR_LOCATION (SWITCH_STMT_COND (t)),
+		    "array notation cannot be used as a condition for "
+		    "switch statement");
+	  return error_mark_node;
 	}
-      else
-	t = expand_array_notation_exprs (t);
+      if (SWITCH_STMT_BODY (t))
+	SWITCH_STMT_BODY (t) =
+	  expand_array_notation_exprs (SWITCH_STMT_BODY (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 (contains_array_notation_expr (WHILE_COND (t)))
 	{
-	  if (WHILE_BODY (t))
-	    WHILE_BODY (t) = expand_array_notation_exprs (WHILE_BODY (t));
+	  if (EXPR_LOCATION (WHILE_COND (t)) != UNKNOWN_LOCATION)
+	    loc = EXPR_LOCATION (WHILE_COND (t));
+	  error_at (loc, "array notation cannot be used as a condition for "
+		    "while statement");
+	  return error_mark_node;
 	}
-      else
-	t = expand_array_notation_exprs (t);
+      if (WHILE_BODY (t))
+	WHILE_BODY (t) = expand_array_notation_exprs (WHILE_BODY (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));
+      if (contains_array_notation_expr (DO_COND (t)))
+	{
+	  error_at (EXPR_LOCATION (DO_COND (t)),
+		    "array notation cannot be used as a condition for a "
+		    "do-while statement");
+	  return error_mark_node;
 	}
-      else
-	t = expand_array_notation_exprs (t);
+      if (DO_BODY (t))
+	DO_BODY (t) = expand_array_notation_exprs (DO_BODY (t));
       return t;
     default:
       if (is_expr)
@@ -1394,43 +1341,28 @@ build_array_notation_ref (location_t loc, tree array, tree start_index,
   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 = build_min_nt_loc (loc, ARRAY_NOTATION_REF, array, 
+				       start_index, length, stride, NULL_TREE);
+  else
+    { 
+      /* For templatized code, this error checking will be done in pt.c.  */
+      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;
     }
+  if (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;
@@ -1462,20 +1394,9 @@ cilkplus_an_triplet_types_ok_p (location_t loc, tree start_index, tree length,
     }
   if (!TREE_CODE (type) == FUNCTION_TYPE)
     {
-      error_at (loc, "array notations cannot be used with function type");
+      error_at (loc, "array notation 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))
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 38ef878..590d857 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -1207,6 +1207,12 @@ cp_genericize (tree fndecl)
   if (DECL_CLONED_FUNCTION_P (fndecl))
     return;
 
+  /* Expand all the array notations here.  */
+  if (flag_enable_cilkplus 
+      && contains_array_notation_expr (DECL_SAVED_TREE (fndecl)))
+    DECL_SAVED_TREE (fndecl) = 
+      expand_array_notation_exprs (DECL_SAVED_TREE (fndecl));
+
   /* We do want to see every occurrence of the parms, so we can't just use
      walk_tree's hash functionality.  */
   cp_genericize_tree (&DECL_SAVED_TREE (fndecl));
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 00ee450..a3438a8 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4974,6 +4974,7 @@ extern bool pragma_java_exceptions;
 
 /* in call.c */
 extern bool check_dtor_name			(tree, tree);
+bool magic_varargs_p                            (tree);
 
 extern tree build_conditional_expr		(location_t, tree, tree, tree, 
                                                  tsubst_flags_t);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index ec8ad46..7ee9f34 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -6062,38 +6062,26 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 
 /* 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
+   INIT_INDEX is NULL, then we have special case where 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.  */
+   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_parser_array_notation (location_t loc, cp_parser *parser, tree *init_index,
+			  tree array_value, bool for_offsetof)
 {
   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;
+  tree value_tree, array_type, array_type_domain;
 
   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;
-    }
+
+  array_type = TREE_TYPE (array_value);
   token = cp_lexer_peek_token (parser->lexer);
   if (!token)
     {
@@ -6102,106 +6090,99 @@ cp_parser_array_notation (location_t loc, cp_parser *parser, tree init_index,
     }
   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 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)
+      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 notation in pointers or records");
+	  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 notation with array of unknown bound");
+	  cp_parser_skip_to_end_of_statement (parser);
+	  return error_mark_node;
+	}
+      start_index = TYPE_MINVAL (array_type_domain);
+      start_index = cp_fold_convert (ptrdiff_type_node, start_index);
+      length_index = size_binop 
+	(PLUS_EXPR, TYPE_MAXVAL (array_type_domain), size_one_node);
+      length_index = cp_fold_convert (ptrdiff_type_node, length_index);
+      stride = build_int_cst (ptrdiff_type_node, 1);
+    }
+  else
+    {
+      bool 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;
+      if (for_offsetof)
+	*init_index = cp_parser_constant_expression (parser, false, NULL);
+      else
+	{
+	  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
 	    {
-	      tree subtype = TREE_TYPE (array_type);
-	      while (subtype && TREE_CODE (subtype) == POINTER_TYPE)
+	      bool expr_nonconst_p;
+	      maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
+	      *init_index = cp_parser_braced_list (parser, &expr_nonconst_p);
+	      if (cp_lexer_peek_token (parser->lexer)->type == CPP_COLON)
 		{
-		  /* 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;
-		    }
+		  error_at (cp_lexer_peek_token (parser->lexer)->location,
+			    "braced list index is not allowed with array "
+			    "notation");
+		  *init_index = 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);
+	  else
+	    *init_index = cp_parser_expression (parser, /*cast_p=*/false, NULL);
+	}
+      if (cp_lexer_peek_token (parser->lexer)->type != CPP_COLON)
+	{
 	  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);
+	  return NULL_TREE;
+	}
+      else
+	start_index = *init_index;
+
+      /* If we hare here, then there are 2 possibilities:
+	 1. Array [ EXPR : EXPR ]
+	 2. Array [ EXPR : EXPR : EXPR ]  */
+      token = cp_lexer_peek_token (parser->lexer);
+    
+      cp_lexer_consume_token (parser->lexer);
+      length_index = cp_parser_expression (parser, false, NULL);
+      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)
+      if (cp_lexer_peek_token (parser->lexer)->type == CPP_COLON)
+	{
+	  cp_lexer_consume_token (parser->lexer);
+	  stride = cp_parser_expression (parser, false, NULL);
+	  if (!stride || stride == error_mark_node)
 	    {
-	      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);
-		}
+	      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;
-	}
-    }
-  
+	stride = build_one_cst (ptrdiff_type_node);
+      parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
+    }  
   if (start_index == error_mark_node || length_index == error_mark_node
       || stride == error_mark_node || !start_index || !length_index
       || !stride)
@@ -6211,16 +6192,10 @@ cp_parser_array_notation (location_t loc, cp_parser *parser, tree init_index,
       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);
+					 array_type);
   return value_tree;
 }
 
@@ -6245,78 +6220,59 @@ cp_parser_postfix_open_square_expression (cp_parser *parser,
   /* Consume the `[' token.  */
   cp_lexer_consume_token (parser->lexer);
 
-  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);
+  if (flag_enable_cilkplus)
+    {
+      /* Here are have the following options: 
+	 1. ARRAY[:]                  -- Array Notation whose start index is 0, 
+	                                 length is size of the array and stride
+	                                 is 1.
+	 2. ARRAY[EXPR]               -- This is the normal array call.
+	 3. ARRAY[EXPR : EXPR]        -- Array notation expr with default
+	                                 stride of 1.
+	 4. ARRAY[EXPR : EXPR : EXPR] -- Array Notation with userdefined stride.
+	 5. Array[Braced List]        -- This is handled by braced list.  */
+      tree an_expression = cp_parser_array_notation (loc, parser, &index,
+						     postfix_expression,
+						     for_offsetof);
+      if (an_expression)
+	return an_expression;
+    }
+      
+  /* 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.  */
+  else if (for_offsetof)
+    index = cp_parser_constant_expression (parser, false, NULL);
   else
     {
-      /* 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
+      if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
 	{
-	  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;
+	  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)
-	postfix_expression = cp_parser_array_notation (loc, parser, index,
-						       postfix_expression);
       else
-	{
-  	  /* Look for the closing `]'.  */
-	  cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
+	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);
+  /* 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;
-	}
-    }
+  /* 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;
 }
 
@@ -9550,9 +9506,6 @@ cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr,
   finish_compound_stmt (compound_stmt);
   /* 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;
 }
 
@@ -9745,14 +9698,6 @@ 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;
@@ -10310,12 +10255,6 @@ 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;
 
@@ -10342,15 +10281,6 @@ 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;
 
@@ -10367,19 +10297,10 @@ cp_parser_iteration_statement (cp_parser* parser)
 	/* Parse the body of the for-statement.  */
 	parser->in_statement = IN_ITERATION_STMT;
 	cp_parser_already_scoped_statement (parser);
-	parser->in_statement = in_statement;
+	parser->in_statement = in_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);
+	/* We're done with the for-statement.  */ 
+	finish_for_stmt (statement);
       }
       break;
 
@@ -16952,54 +16873,30 @@ cp_parser_direct_declarator (cp_parser* parser,
 	  if (token->type != CPP_CLOSE_SQUARE)
 	    {
 	      bool non_constant_p;
-
-	      if (flag_enable_cilkplus
-		  && cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+	      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;
-		  error_at (cp_lexer_peek_token (parser->lexer)->location,
-			    "array notations cannot be used in declaration");
-		  cp_lexer_consume_token (parser->lexer);
 		}
-	      else
+	      else if (processing_template_decl)
 		{
-		  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; 
-		    }
+		  /* Remember this wasn't a constant-expression.  */
+		  bounds = build_nop (TREE_TYPE (bounds), bounds);
+		  TREE_SIDE_EFFECTS (bounds) = 1;
 		}
 	    }
 	  else
@@ -18371,10 +18268,6 @@ cp_parser_ctor_initializer_opt_and_function_body (cp_parser *parser,
   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);
 
@@ -22354,12 +22247,6 @@ 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));
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 667e37f..5dafdcd 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -15739,9 +15739,6 @@ 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;
@@ -19143,11 +19140,6 @@ 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);
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 0a460a4..87c1560 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -779,22 +779,6 @@ 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 ())
@@ -8089,7 +8073,6 @@ 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);
@@ -8901,7 +8884,6 @@ 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:
@@ -8912,6 +8894,9 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
 	  return false;
       return true;
 
+    case ARRAY_NOTATION_REF:
+      return false;
+
     case FMA_EXPR:
     case VEC_PERM_EXPR:
      for (i = 0; i < 3; ++i)
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 5b321ce..fb9a537 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -3493,10 +3493,6 @@ cp_build_function_call_vec (tree function, vec<tree, va_gc> **params,
       params = &allocated;
     }
 
-  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)
@@ -3660,8 +3656,7 @@ convert_arguments (tree typelist, vec<tree, va_gc> **values, tree fndecl,
 	}
       else
 	{
-	  if (fndecl && DECL_BUILT_IN (fndecl)
-	      && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CONSTANT_P)
+	  if (fndecl && magic_varargs_p (fndecl))
 	    /* Don't do ellipsis conversion for __built_in_constant_p
 	       as this will result in spurious errors for non-trivial
 	       types.  */
@@ -3954,17 +3949,10 @@ cp_build_binary_op (location_t location,
 		       TREE_TYPE (t));
 	  op1 = t;
 	}
-    }
-
-  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);
+  type0 = TREE_TYPE (op0); 
+  type1 = TREE_TYPE (op1);
 
   /* The expression codes of the data types of the arguments tell us
      whether the arguments are integers, floating, pointers, etc.  */
@@ -5167,13 +5155,6 @@ 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)))
     {
@@ -7852,13 +7833,6 @@ 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);
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/decl-ptr-colon.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/decl-ptr-colon.c
index 68c8859..4b54f4d 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/decl-ptr-colon.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/decl-ptr-colon.c
@@ -1,3 +1,4 @@
+/* { dg-do compile { target c } } */
 /* { dg-options "-fcilkplus" } */
 
 int main(void)
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/dimensionless-arrays.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/dimensionless-arrays.c
index 69aaa52..690e89a 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/dimensionless-arrays.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/dimensionless-arrays.c
@@ -5,6 +5,6 @@ extern int *b;
 
 void foo()
 {
-  a[:] = 5;	// { dg-error "start-index and length fields necessary for using array notations in dimensionless arrays" }
-  b[:] = 5;    // { dg-error "start-index and length fields necessary for using array notations in pointers" }
+  a[:] = 5;	// { dg-error "start-index and length fields necessary for using array notation" }
+  b[:] = 5;    // { dg-error "start-index and length fields necessary for using" }
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/fn_ptr.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/fn_ptr.c
index 024a158..fa6d900 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/fn_ptr.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/fn_ptr.c
@@ -1,3 +1,4 @@
+/* { dg-do compile } */
 /* { dg-options "-fcilkplus" } */
 
 typedef int (*foo)(int);
@@ -10,11 +11,11 @@ int main(void)
   foo ***func_array_ptr;
   int argc = 5;
 
-  array[:] =  func_array[:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
-  func_array[0:5](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
-  func_array2[0:5][:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
-  array2[0:5][:] = func_array2[0:5][:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
-  func_array_ptr[0:5][0:4][0:argc:2](argc); /* { dg-error "array notations cannot be used with function pointer arrays" } */
+  array[:] =  func_array[:](10); 
+  func_array[0:5](10); 
+  func_array2[0:5][:](10);
+  array2[0:5][:] = func_array2[0:5][:](10);
+  func_array_ptr[0:5][0:4][0:argc:2](argc); 
 
   return 0;
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
index 14421d9..814786b 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
@@ -6,7 +6,7 @@ int main (void)
   int array[10], array2[10][10];
   int x, ii, jj ;
 
-  switch (array[:]) {  /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  switch (array[:]) {  /* { dg-error "cannot be used as a condition for switch statement" } */
   case 1:
     x = 5;
     break;
@@ -17,7 +17,7 @@ int main (void)
     x = 9;
   }
 
-  switch (array2[:][:]) { /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  switch (array2[:][:]) { /* { dg-error "cannot be used as a condition for switch statement" } */
   case 1:
     x = 5;
     break;
@@ -28,7 +28,7 @@ int main (void)
     x = 9;
   }
 
-  switch (array[:] + x) { /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  switch (array[:] + x) { /* { dg-error "cannot be used as a condition for switch statement" } */
   case 1:
     x = 5;
     break;
@@ -39,7 +39,7 @@ int main (void)
     x = 9;
   }
   
-  switch (array2[:][1:x:4] + x) { /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  switch (array2[:][1:x:4] + x) { /* { dg-error "cannot be used as a condition for switch statement" } */
   case 1:
     x = 5;
     break;
@@ -50,36 +50,36 @@ int main (void)
     x = 9;
   }
 
-  for (ii = 0; ii < array[:]; ii++) /* { dg-error "array notations cannot be used in a condition for a for-loop" } */
+  for (ii = 0; ii < array[:]; ii++) /* { dg-error "cannot be used in a condition for a for-loop" } */
     {
       x = 2;
     }
 
-  for (ii = 0; ii < array2[:][:]; ii++) /* { dg-error "array notations cannot be used in a condition for a for-loop" } */
+  for (ii = 0; ii < array2[:][:]; ii++) /* { dg-error "cannot be used in a condition for a for-loop" } */
     {
       x = 3;
     }
 
-  for (; array2[:][:] < 2;) /* { dg-error "array notations cannot be used in a condition for a for-loop" } */
+  for (; array2[:][:] < 2;) /* { dg-error "cannot be used in a condition for a for-loop" } */
     x = 4;
 
 
-  while (array2[:][:]) /* { dg-error "array notations cannot be used as a condition for while statement" } */
+  while (array2[:][:]) /* { dg-error "cannot be used as a condition for while statement" } */
     x = 3;
 
-  while (array[1:1:1]) /* { dg-error "array notations cannot be used as a condition for while statement" } */
+  while (array[1:1:1]) /* { dg-error "cannot be used as a condition for while statement" } */
     x = 1;
 
-  while (ii != array2[1:x:3][1:2:1]) /* { dg-error "array notations cannot be used as a condition for while statement"  } */
+  while (ii != array2[1:x:3][1:2:1]) /* { dg-error "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" "" { target c } } */
+  do { /* { dg-error "cannot be used as a condition for a do-while statement" "" { target c } } */
     x = 3;
-  } while (ii != array2[:][:]); /* { dg-error "array notations cannot be used as a condition for a do-while statement" "" { target c++ } } */
+  } while (ii != array2[:][:]); /* { dg-error "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" "" { target c } } */
+  do {  /* { dg-error "cannot be used as a condition for a do-while statement" "" { target c } } */
     x = 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++ } } */
+  } while (ii != (x + array2[:][1:x:2]) + 2); /* { dg-error "cannot be used as a condition for a do-while statement" "" { target c++ } } */
   
   do { 
     x += 3;
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/rank_mismatch.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/rank_mismatch.c
index b5e37ce..eb3c1f1 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/rank_mismatch.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/rank_mismatch.c
@@ -10,6 +10,7 @@ int main (void)
   int array[10][10], array2[10];
 
   array[:][:] = array[:]; /* { dg-error "rank mismatch between" } */
+  /* { dg-error "invalid conversion" "" { target c++ } 12 } */
 
   x = array2[:]; /* { dg-error "cannot be scalar when" } */
 

[-- Attachment #3: CL.txt --]
[-- Type: text/plain, Size: 5991 bytes --]

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

        * builtins.def: Fixed the function type of CILKPLUS_BUILTIN.

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

        * c-parser.c (c_parser_array_notation): Removed rejection of array
        notations in an array of function pointers.

gcc/c-family/ChangeLog
2013-06-26  Balaji V. Iyer  <balaji.v.iyer@intel.com>

        * array-notation-common.c (length_mismatch_in_expr_p): Collapsed two
        if-statements and compared the trees directly using tree_int_cst_equal.
        (find_rank): Checked for array notations in function name to handle
        array notations in function pointers.
        (extract_array_notation_exprs): Likewise.
        (replace_array_notations): Likewise.
        (cilkplus_extract_an_triplets): Replaced safe_push with
        safe_grow_cleared.  Also removed an unnecessary check to see if the
        node is of type ARRAY_NOTATION_REF.
        (fix_sec_implicit_args): Removed an unnecessary check for ADDR_EXPR.
        Also switched two if-statements to remove an unnecessary comparison.


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

        * parser.c (cp_parser_array_notation): Removed rejection array notation
        of type function pointers.  Used cp_fold_convert instead of fold_build1.
        Added new parameter "for_offsetof" and moved braced list and constant
        index capturing into this function.
        (cp_parser_postfix_open_square_expression): Folded normal array expr.
        parsing into cp_parser_array_notation when cilkplus is enabled.
        (cp_parser_compound_statement): Removed expansion of array notations.
        (cp_parser_ctor_initializer_opt_and_function_body): Likewise.
        (cp_parser_function_definition_after_declarator): Likewise.
        (cp_parser_selection_statement): Removed error reporting.
        (cp_parser_iteration_statement): Likewise.
        (cp_parser_direct_declarator): Removed error checking/reporting if
        array notations are used in the declarator.
        * pt.c (instantiate_decl): Likewise.
        (type_unification_real): Removed a check for ARRAY_NOTATION_REF.
        (cxx_eval_constant_expression): Removed ARRAY_NOTATION_REF case.
        (potential_constant_expression_1): Returned false for ARRAY_NOTATION_REF
        case.
        * cp-gimplify.c (cp_genericize): Added expansion of array notation
        expressions here.
        * cp-array-notation.c (cp_length_mismatch_in_expr_p): Combined two
        if statements into one and compared integers using tree_int_cst_equal.
        (make_triplet_val_inv): Removed loc and cry parameters.  Replaced
        build_decls with get_temp_regvar with type as ptrdiff.
        (create_array_refs): Made the type-casting to ptrdiff_type.
        (replace_invariant_var): Replaced build_decl and build_min_nt_loc with
        get_temp_regvar.
        (expand_an_in_modify_expr): Ditto. Replaced body of redundant else with
        gcc_unreachable.  Removed few unwanted checks. Made induction variable
        type as ptrdiff_type.  Removed loc and complain arguments passed into
        make_triplet_val_inv.  Replaced all modify expression's code from NOP
        EXPR to INIT EXPR.  Replaced all forceful appending into stmt. list
        with the non-forceful one.  Replaced some integer conversion and
        checking to using tree_int_cst_equal.
        (expand_reduce_builtin): All changes mentioned in above function
        expand_an_in_modify_expr.  Made the new variable type of
        SEC_REDUCE_ANY/ALL_{NON}ZERO intrinsic functions as bool.
        (expand_array_notation_exprs): Removed SWITCH_EXPR case.  Moved all
        the error reporting from parser to this function.  Removed unwanted
        statements and checks from SWITCH_STMT, WHILE_STMT, and DO_STMT cases.
        (cilkplus_an_triplet_types_ok_p): Removed rejection of array notation
        in function pointers.
        (cp_expand_cond_array_notations): Added a new if statements to check
        if condition has a zero rank.  If so, then just return.
        (expand_return_expr): Added a check for return expressions with a rank.
        Replaced get_tmp_regvar with a create_temporary_var.
        (build_array_notation_ref): Simplified and removed unwanted if-stmts.
        Also, moved common code outside if-statements.
        * semantics.c (finish_return_stmt): Removed a check for return exprs.
        with a rank.
        * call.c (convert_like_real): Removed a check for array notation
        expression in a function.
        (build_over_call): Likewise.
        (magic_varargs_p): Added a check for builtin array notation function.
        Made this function non-static and removed its prototype.
        * cp-tree.h (magic_varargs_p): New prototype.
        * typeck.c (cp_build_function_call_vec): Removed automatic setting of
        nargs to the param->length when builtin reduction function is used.
        (convert_arguments): Replaced check for a constant_p function with
        margic_varargs_p function call.
        (cp_build_binary_op): Removed calling of the function
        find_correct_array_notation_type.
        (cp_build_addr_expr_1): Removed an unwanted if-statement.
        (convert_for_assignment): Removed automatic return of rhs when array
        notation builtin function is used.

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

        * c-c++-common/cilk-plus/AN/decl-ptr-colon.c (main): Made this testcase
        c specific.
        * c-c++-common/cilk-plus/AN/decl-ptr-colon.c (main): Changed dg-error
        strings to match the fixed error messages.
        * c-c++-common/cilk-plus/AN/misc.c (main): Likewise.
        * c-c++-common/cilk-plus/AN/rank_mismatch.c (main): Added a new error
        message check.


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH] Cilk Plus Array Notation for C++
  2013-06-26 17:32                                 ` Iyer, Balaji V
@ 2013-06-26 20:12                                   ` Jason Merrill
  2013-06-27 15:52                                     ` Iyer, Balaji V
  0 siblings, 1 reply; 40+ messages in thread
From: Jason Merrill @ 2013-06-26 20:12 UTC (permalink / raw)
  To: Iyer, Balaji V, Richard Henderson; +Cc: Aldy Hernandez, gcc-patches

On 06/26/2013 01:31 PM, Iyer, Balaji V wrote:
> 	Attached, please find a fixed patch and ChangeLog entries:

This patch seems to be missing some hunks that are described in the 
ChangeLog and were present in the previous patch, such as

>         * cp-array-notation.c (cp_length_mismatch_in_expr_p): Combined two
>         if statements into one and compared integers using tree_int_cst_equal.

> Sorry about that, I accidentally missed this one. It is fixed now. I have also added the braced list capability into cp_array_notation.

Hmm, I seem to have been unclear.  I was expecting that the call to 
cp_parser_array_notation could come after the braced list case, so we 
don't need to duplicate the offsetof or braced list code inside 
cp_parser_array_notation.

And then if you'd like we could check for ':' before the ']' and give a 
helpful diagnostic.

> +      /* If we hare here, then there are 2 possibilities:

"are"

> +  if (processing_template_decl)
> +    array_ntn_expr = build_min_nt_loc (loc, ARRAY_NOTATION_REF, array,
> +                                      start_index, length, stride, NULL_TREE);

If we know the type of the array, we should use it, rather than always 
leaving it null in a template.  That is, if !dependent_type_p (type), we 
should give the ARRAY_NOTATION_REF a real type.

> +      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 notation in pointers or records");

In a template, array_type might be NULL_TREE; this diagnostic should 
move into build_array_notation_ref.

> +      array_type_domain = TYPE_DOMAIN (array_type);
> +      if (!array_type_domain)
> +       {
> +         error_at (loc, "start-index and length fields necessary for "
> +                   "using array notation with array of unknown bound");
> +         cp_parser_skip_to_end_of_statement (parser);
> +         return error_mark_node;
> +       }
> +      start_index = TYPE_MINVAL (array_type_domain);
> +      start_index = cp_fold_convert (ptrdiff_type_node, start_index);
> +      length_index = size_binop
> +       (PLUS_EXPR, TYPE_MAXVAL (array_type_domain), size_one_node);
> +      length_index = cp_fold_convert (ptrdiff_type_node, length_index);
> +      stride = build_int_cst (ptrdiff_type_node, 1);

As should all this code.  cp_parser_array_notation should only parse.

> +      else
> +       stride = build_one_cst (ptrdiff_type_node);

I would move this into build_array_notation_ref as well.

Jason

^ permalink raw reply	[flat|nested] 40+ messages in thread

* RE: [PATCH] Cilk Plus Array Notation for C++
  2013-06-26 20:12                                   ` Jason Merrill
@ 2013-06-27 15:52                                     ` Iyer, Balaji V
  2013-06-27 15:54                                       ` Iyer, Balaji V
  0 siblings, 1 reply; 40+ messages in thread
From: Iyer, Balaji V @ 2013-06-27 15:52 UTC (permalink / raw)
  To: Jason Merrill, Richard Henderson; +Cc: Aldy Hernandez, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 3639 bytes --]

Hello Jason et al.,
	Please see my responses to your questions below. I am attaching a fixed patch and ChangeLog. Is this Ok for trunk?

Thanks,

Balaji V. Iyer.

> -----Original Message-----
> From: Jason Merrill [mailto:jason@redhat.com]
> Sent: Wednesday, June 26, 2013 4:13 PM
> To: Iyer, Balaji V; Richard Henderson
> Cc: Aldy Hernandez; gcc-patches@gcc.gnu.org
> Subject: Re: [PATCH] Cilk Plus Array Notation for C++
> 
> On 06/26/2013 01:31 PM, Iyer, Balaji V wrote:
> > 	Attached, please find a fixed patch and ChangeLog entries:
> 
> This patch seems to be missing some hunks that are described in the ChangeLog
> and were present in the previous patch, such as
> 
> >         * cp-array-notation.c (cp_length_mismatch_in_expr_p): Combined two
> >         if statements into one and compared integers using tree_int_cst_equal.
> 

I checked in a patch for C that replaced all dynamic arrays in C with vec_trees. Thus, this function could be replaced with the function in c-family. It was my mistake that I forgot to take this line out of the changelog entry.

> > Sorry about that, I accidentally missed this one. It is fixed now. I have also
> added the braced list capability into cp_array_notation.
> 
> Hmm, I seem to have been unclear.  I was expecting that the call to
> cp_parser_array_notation could come after the braced list case, so we don't
> need to duplicate the offsetof or braced list code inside
> cp_parser_array_notation.
> 
> And then if you'd like we could check for ':' before the ']' and give a helpful
> diagnostic.

I Think I have fixed this as you requested.

> 
> > +      /* If we hare here, then there are 2 possibilities:
> 
> "are"

Fixed!

> 
> > +  if (processing_template_decl)
> > +    array_ntn_expr = build_min_nt_loc (loc, ARRAY_NOTATION_REF, array,
> > +                                      start_index, length, stride,
> > + NULL_TREE);
> 
> If we know the type of the array, we should use it, rather than always leaving it
> null in a template.  That is, if !dependent_type_p (type), we should give the
> ARRAY_NOTATION_REF a real type.
> 

Fixed.

> > +      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 notation in pointers or records");
> 

Moved as you suggested.

> In a template, array_type might be NULL_TREE; this diagnostic should move into
> build_array_notation_ref.
> 
> > +      array_type_domain = TYPE_DOMAIN (array_type);
> > +      if (!array_type_domain)
> > +       {
> > +         error_at (loc, "start-index and length fields necessary for "
> > +                   "using array notation with array of unknown bound");
> > +         cp_parser_skip_to_end_of_statement (parser);
> > +         return error_mark_node;
> > +       }
> > +      start_index = TYPE_MINVAL (array_type_domain);
> > +      start_index = cp_fold_convert (ptrdiff_type_node, start_index);
> > +      length_index = size_binop
> > +       (PLUS_EXPR, TYPE_MAXVAL (array_type_domain), size_one_node);
> > +      length_index = cp_fold_convert (ptrdiff_type_node, length_index);
> > +      stride = build_int_cst (ptrdiff_type_node, 1);
> 
> As should all this code.  cp_parser_array_notation should only parse.
> 

Moved as you suggested.

> > +      else
> > +       stride = build_one_cst (ptrdiff_type_node);
> 
> I would move this into build_array_notation_ref as well.

Moved as you suggested.

> 
> Jason


[-- Attachment #2: CL.txt --]
[-- Type: text/plain, Size: 5853 bytes --]

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

        * builtins.def: Fixed the function type of CILKPLUS_BUILTIN.

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

        * c-parser.c (c_parser_array_notation): Removed rejection of array
        notations in an array of function pointers.

gcc/c-family/ChangeLog
2013-06-26  Balaji V. Iyer  <balaji.v.iyer@intel.com>

        * array-notation-common.c (length_mismatch_in_expr_p): Collapsed two
        if-statements and compared the trees directly using tree_int_cst_equal.
        (find_rank): Checked for array notations in function name to handle
        array notations in function pointers.
        (extract_array_notation_exprs): Likewise.
        (replace_array_notations): Likewise.
        (cilkplus_extract_an_triplets): Replaced safe_push with
        safe_grow_cleared.  Also removed an unnecessary check to see if the
        node is of type ARRAY_NOTATION_REF.
        (fix_sec_implicit_args): Removed an unnecessary check for ADDR_EXPR.
        Also switched two if-statements to remove an unnecessary comparison.


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

        * parser.c (cp_parser_array_notation): Removed rejection array notation
        of type function pointers. Added handling of array expressions when
        Cilk Plus is enabled.  Took out type-checking.
        (cp_parser_postfix_open_square_expression): Moved normal array expr.
        parsing into cp_parser_array_notation when cilkplus is enabled.
        (cp_parser_compound_statement): Removed expansion of array notations.
        (cp_parser_ctor_initializer_opt_and_function_body): Likewise.
        (cp_parser_function_definition_after_declarator): Likewise.
        (cp_parser_selection_statement): Removed error reporting.
        (cp_parser_iteration_statement): Likewise.
        (cp_parser_direct_declarator): Removed error checking/reporting if
        array notations are used in the declarator.
        * pt.c (instantiate_decl): Likewise.
        (type_unification_real): Removed a check for ARRAY_NOTATION_REF.
        (cxx_eval_constant_expression): Removed ARRAY_NOTATION_REF case.
        (potential_constant_expression_1): Returned false for ARRAY_NOTATION_REF
        case.
        * cp-gimplify.c (cp_genericize): Added expansion of array notation
        expressions here.
        * cp-array-notation.c (make_triplet_val_inv): Removed loc and cry 
        parameters.  Replaced build_decls with get_temp_regvar with type as
        ptrdiff.
        (create_array_refs): Made the type-casting to ptrdiff_type.
        (replace_invariant_var): Replaced build_decl and build_min_nt_loc with
        get_temp_regvar.
        (expand_an_in_modify_expr): Ditto.  Replaced body of redundant else with
        gcc_unreachable.  Removed few unwanted checks.  Made induction variable
        type as ptrdiff_type.  Removed loc and complain arguments passed into
        make_triplet_val_inv.  Replaced all modify expression's code from NOP
        EXPR to INIT EXPR.  Replaced all forceful appending into stmt. list
        with the non-forceful one.  Replaced some integer conversion and
        equality-checking to using tree_int_cst_equal.
        (expand_sec_reduce_builtin): All changes mentioned in above function
        expand_an_in_modify_expr.  Made the new variable type of
        SEC_REDUCE_ANY/ALL_{NON}ZERO intrinsic functions as bool.
        (expand_array_notation_exprs): Removed SWITCH_EXPR case.  Moved all
        the error reporting from parser to this function.  Removed unwanted
        statements and checks from SWITCH_STMT, WHILE_STMT, and DO_STMT cases.
        (cilkplus_an_triplet_types_ok_p): Removed rejection of array notation
        in function pointers.
        (cp_expand_cond_array_notations): Added a new if statements to check
        if condition has a zero rank.  If so, then just return.
        (expand_return_expr): Added a check for return expressions with a rank.
        Replaced get_tmp_regvar with a create_temporary_var.
        (build_array_notation_ref): Simplified and removed unwanted if-stmts.
        Moved common code outside if-statements.  Moved type-checking from
        parser to here.
        * semantics.c (finish_return_stmt): Removed a check for return exprs.
        with a rank.
        * call.c (convert_like_real): Removed a check for array notation
        expression in a function.
        (build_over_call): Likewise.
        (magic_varargs_p): Added a check for builtin array notation function.
        Made this function non-static and removed its prototype.
        * cp-tree.h (magic_varargs_p): New prototype.
        * typeck.c (cp_build_function_call_vec): Removed automatic setting of
        nargs to the param->length when builtin reduction function is used.
        (convert_arguments): Replaced check for a constant_p function with
        margic_varargs_p function call.
        (cp_build_binary_op): Removed calling of the function
        find_correct_array_notation_type.
        (cp_build_addr_expr_1): Removed an unwanted if-statement.
        (convert_for_assignment): Removed automatic return of rhs when array
        notation builtin function is used.

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

        * c-c++-common/cilk-plus/AN/decl-ptr-colon.c (main): Made this testcase
        c specific.
        * c-c++-common/cilk-plus/AN/decl-ptr-colon.c (main): Changed dg-error
        strings to match the fixed error messages.
        * c-c++-common/cilk-plus/AN/misc.c (main): Likewise.
        * c-c++-common/cilk-plus/AN/rank_mismatch.c (main): Added a new error
        message check.


[-- Attachment #3: diff.txt --]
[-- Type: text/plain, Size: 81313 bytes --]

diff --git a/gcc/builtins.def b/gcc/builtins.def
index 91879a6..9b55b1f 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -158,9 +158,9 @@ along with GCC; see the file COPYING3.  If not see
 	       (flag_asan || flag_tsan))
 
 #undef DEF_CILKPLUS_BUILTIN
-#define DEF_CILKPLUS_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
-  DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
-  	       false, false, true, ATTRS, false, flag_enable_cilkplus)
+#define DEF_CILKPLUS_BUILTIN(ENUM, NAME, TYPE, ATTRS)  \
+  DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, BT_FN_INT_VAR, BT_LAST, \
+  	       false, false, false, ATTRS, false, flag_enable_cilkplus) 
 
 /* Define an attribute list for math functions that are normally
    "impure" because some of them may write into global memory for
diff --git a/gcc/c-family/array-notation-common.c b/gcc/c-family/array-notation-common.c
index 8eab89b..5e17009 100644
--- a/gcc/c-family/array-notation-common.c
+++ b/gcc/c-family/array-notation-common.c
@@ -101,15 +101,11 @@ length_mismatch_in_expr_p (location_t loc, vec<vec<an_parts> >list)
 	      /* 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;
-		    }
+	      if (TREE_CODE (list[ii][jj].length) == INTEGER_CST
+		  && !tree_int_cst_equal (list[ii][jj].length, length))
+		{ 
+		  error_at (loc, "length mismatch in expression"); 
+		  return true;
 		}
 	    }
 	  else
@@ -271,6 +267,8 @@ find_rank (location_t loc, tree orig_expr, tree expr, bool ignore_builtin_fn,
 		/* If it is a built-in function, then we know it returns a 
 		   scalar.  */
 		return true;
+	  if (!find_rank (loc, orig_expr, func_name, ignore_builtin_fn, rank))
+	    return false;
 	  FOR_EACH_CALL_EXPR_ARG (arg, iter, expr)
 	    {
 	      if (!find_rank (loc, orig_expr, arg, ignore_builtin_fn, rank))
@@ -358,6 +356,9 @@ extract_array_notation_exprs (tree node, bool ignore_builtin_fn,
 	  vec_safe_push (*array_list, node);
 	  return;
 	}
+      /* This will extract array notations in function pointers.  */
+      extract_array_notation_exprs (CALL_EXPR_FN (node), ignore_builtin_fn,
+				    array_list);
       FOR_EACH_CALL_EXPR_ARG (arg, iter, node)
 	extract_array_notation_exprs (arg, ignore_builtin_fn, array_list);
     } 
@@ -433,6 +434,9 @@ replace_array_notations (tree *orig, bool ignore_builtin_fn,
 	      }
 	  return;
 	}
+      /* Fixes array notations in array notations in function pointers.  */
+      replace_array_notations (&CALL_EXPR_FN (*orig), ignore_builtin_fn, list,
+			       array_operand);
       ii = 0;
       FOR_EACH_CALL_EXPR_ARG (arg, iter, *orig)
 	{
@@ -575,53 +579,49 @@ 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++)
+
+  if (rank > 0)
+    for (size_t ii = 0; ii < size; ii++)
       {
-	(*node)[ii].safe_push (init);
-	array_exprs[ii].safe_push (NULL_TREE);
+	(*node)[ii].safe_grow_cleared (rank);
+	array_exprs[ii].safe_grow_cleared (rank);
       }
-
   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 ();	
+	{
+	  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
+	    break;
+	}
     }
     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));
-	    }
+	  {
+	    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
@@ -637,16 +637,15 @@ fix_sec_implicit_args (location_t loc, vec <tree, va_gc> *list,
   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)
+	if (idx < 0)
 	  /* In this case, the returning function would have emitted an
 	     error thus it is not necessary to do so again.  */
 	  return NULL;
+	else if (idx < (int) rank)
+	  vec_safe_push (array_operand, an_loop_info[idx].var);
 	else
 	  {
 	    error_at (loc, "__sec_implicit_index argument %d must be "
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index d6a500e..c7846ce 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -11053,24 +11053,6 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
 	      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
 	      return error_mark_node;
 	    }
-	  if (TREE_CODE (array_type) == ARRAY_TYPE)
-	    {
-	      tree subtype = TREE_TYPE (array_type);
-	      while (subtype && TREE_CODE (subtype) == POINTER_TYPE)
-		{
-		  /* Now this could be a function pointer.  Find them and
-		     give out an error.  */
-		  subtype = TREE_TYPE (subtype);
-		  if (subtype && TREE_CODE (subtype) == FUNCTION_TYPE)
-		    {
-		      error_at (loc, "array notations cannot be used with "
-				"function pointer arrays");
-		      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
-						 NULL);
-		      return error_mark_node;
-		    }
-		}
-	    }
 	  array_type_domain = TYPE_DOMAIN (array_type);
 
 	  if (!array_type_domain)
@@ -11114,27 +11096,6 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
 	      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
 	      return error_mark_node;
 	    }
-	  if (TREE_CODE (array_type) == ARRAY_TYPE
-	      || TREE_CODE (array_type) == POINTER_TYPE)
-	    {
-	      tree subtype = TREE_TYPE (array_type);
-	      while (subtype
-		     && (TREE_CODE (subtype) == POINTER_TYPE
-			 || TREE_CODE (subtype) == ARRAY_TYPE))
-		{
-		  /* Now this could be a function pointer.  Find them and
-		     give out an error.  */
-		  subtype = TREE_TYPE (subtype);
-		  if (subtype && TREE_CODE (subtype) == FUNCTION_TYPE)
-		    {
-		      error_at (loc, "array notations cannot be used with "
-				"function pointer arrays");
-		      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
-						 NULL);
-		      return error_mark_node;
-		    }
-		}
-	    }
 	  c_parser_consume_token (parser); /* consume the ':' */
 	  end_index = c_parser_expression (parser).value;
 	  if (!end_index || end_index == error_mark_node)
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 6817bfc..425ef9b 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -216,7 +216,6 @@ static void add_candidates (tree, tree, const vec<tree, va_gc> *, tree, tree,
 			    bool, tree, tree, int, struct z_candidate **,
 			    tsubst_flags_t);
 static conversion *merge_conversion_sequences (conversion *, conversion *);
-static bool magic_varargs_p (tree);
 static tree build_temp (tree, tree, int, diagnostic_t *, tsubst_flags_t);
 
 /* Returns nonzero iff the destructor name specified in NAME matches BASETYPE.
@@ -5857,16 +5856,9 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
 	  else if (t->kind == ck_identity)
 	    break;
 	}
-
-      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)
+       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);
 
@@ -6515,9 +6507,12 @@ convert_for_arg_passing (tree type, tree val, tsubst_flags_t complain)
    which no conversions at all should be done.  This is true for some
    builtins which don't act like normal functions.  */
 
-static bool
+bool
 magic_varargs_p (tree fn)
 {
+  if (flag_enable_cilkplus && is_cilkplus_reduce_builtin (fn) != BUILT_IN_NONE)
+    return true;
+
   if (DECL_BUILT_IN (fn))
     switch (DECL_FUNCTION_CODE (fn))
       {
@@ -6895,21 +6890,13 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
 		       "  (you can disable this with -fno-deduce-init-list)");
 	    }
 	}
+      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
index 491da0f..b4fada4 100644
--- a/gcc/cp/cp-array-notation.c
+++ b/gcc/cp/cp-array-notation.c
@@ -59,7 +59,6 @@
 #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.  */
@@ -82,17 +81,12 @@ create_an_loop (tree init, tree cond, tree incr, tree body)
    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)
+make_triplet_val_inv (tree *value)
 {
-  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;
-    }
+    *value = get_temp_regvar (ptrdiff_type_node, *value);
 }
 
 /* Returns a vector of size RANK that contains an ARRAY_REF.  This vector is
@@ -140,9 +134,9 @@ create_array_refs (location_t loc, vec<vec<an_parts> > an_info,
 		   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);
+		st = build_c_cast (loc, ptrdiff_type_node, start);
+		str = build_c_cast (loc, ptrdiff_type_node, stride);
+		v = build_c_cast (loc, ptrdiff_type_node, var);
 	      }
 	    else
 	      {
@@ -192,7 +186,7 @@ replace_invariant_exprs (tree *node)
 {
   size_t ix = 0;
   tree node_list = NULL_TREE;
-  tree t = NULL_TREE, new_var = NULL_TREE, new_node; 
+  tree t = NULL_TREE, new_var = NULL_TREE;
   struct inv_list data;
 
   data.list_values = NULL;
@@ -204,17 +198,11 @@ replace_invariant_exprs (tree *node)
     {
       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);
+	{ 
+	  /* Sometimes, it type-casts certain functions to void. Unwrap it.  */
+	  if (VOID_TYPE_P (TREE_TYPE (t)) && TREE_CODE (t) == CONVERT_EXPR)
+	    t = TREE_OPERAND (t, 0);
+	  new_var = get_temp_regvar (TREE_TYPE (t), t); 
 	  vec_safe_push (data.replacement, new_var);
 	}
       cp_walk_tree (node, replace_inv_trees, (void *) &data, NULL);
@@ -235,7 +223,6 @@ 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 ();
@@ -305,7 +292,7 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
     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;
+      new_var_type = boolean_type_node;
       break;
     case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
     case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
@@ -334,24 +321,30 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
     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);
+	make_triplet_val_inv (&ARRAY_NOTATION_START (anode));
+	make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (anode));
+	make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (anode));
       }
   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);
+      tree typ = ptrdiff_type_node;
+
+      /* In this place, we are using get_temp_regvar instead of 
+	 create_temporary_var if an_type is SEC_REDUCE_MAX/MIN_IND because
+	 the array_ind_value depends on this value being initalized to 0.  */
+      if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
+	  || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND) 
+	an_loop_info[ii].var = get_temp_regvar (typ, build_zero_cst (typ));
+      else
+	{
+	  an_loop_info[ii].var = create_temporary_var (typ);
+	  add_decl_expr (an_loop_info[ii].var);
+	}
+      an_loop_info[ii].ind_init = 
+	build_x_modify_expr (location, an_loop_info[ii].var, INIT_EXPR,
+			     build_zero_cst (typ), 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);
@@ -360,26 +353,9 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
     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);
-    }
+      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND) 
+    array_ind_value = get_temp_regvar (TREE_TYPE (func_parm), func_parm);
 
   array_op0 = (*array_operand)[0];
   switch (an_type)
@@ -394,35 +370,36 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
       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;
+      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;
+      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;
+      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;
+      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;
+      code = (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND ? LE_EXPR
+	: GE_EXPR);
       init = an_loop_info[0].var;
+      break;
     case BUILT_IN_CILKPLUS_SEC_REDUCE:
       init = identity_value;
       break;
@@ -433,9 +410,11 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
       gcc_unreachable ();
     }
 
-  if (init)
-    new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR, init,
-					tf_warning_or_error);
+  if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
+    *new_var = get_temp_regvar (new_var_type, init);
+  else
+    *new_var = NULL_TREE;
+
   switch (an_type)
     {
     case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD:
@@ -470,8 +449,6 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
       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,
@@ -521,21 +498,8 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
     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);
+  append_to_statement_list (an_init, &loop_with_init);
   body = new_expr;
 
   for (ii = 0; ii < rank; ii++)
@@ -545,7 +509,7 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
 		      an_loop_info[ii].incr, body);
       body = pop_stmt_list (new_loop);
     }
-  append_to_statement_list_force (body, &loop_with_init);
+  append_to_statement_list (body, &loop_with_init);
 
   an_info.release ();
   an_loop_info.release ();
@@ -634,10 +598,7 @@ expand_an_in_modify_expr (location_t location, tree lhs,
 	  return an_init;
 	}
       else
-	{
-	  pop_stmt_list (an_init);
-	  return NULL_TREE;
-	}
+	gcc_unreachable ();
     }
 
   /* If for some reason location is not set, then find if LHS or RHS has
@@ -659,8 +620,6 @@ expand_an_in_modify_expr (location_t location, tree lhs,
     
   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;
     }
@@ -675,17 +634,17 @@ expand_an_in_modify_expr (location_t location, tree lhs,
   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);
+      make_triplet_val_inv (&ARRAY_NOTATION_START (anode));
+      make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (anode));
+      make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (anode));
     }
   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);
+	make_triplet_val_inv (&ARRAY_NOTATION_START (aa));
+	make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (aa));
+	make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (aa));
       }
   lhs_an_loop_info.safe_grow_cleared (lhs_rank);
   
@@ -705,31 +664,29 @@ expand_an_in_modify_expr (location_t location, tree lhs,
       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;
+  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;
-	}
+      && TREE_CODE (rhs_len) == INTEGER_CST 
+      && !tree_int_cst_equal (rhs_len, lhs_len))
+    { 
+      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);
+   for (ii = 0; ii < lhs_rank; ii++) 
+     {
+       tree typ = ptrdiff_type_node; 
+       lhs_an_loop_info[ii].var = create_temporary_var (typ);
+       add_decl_expr (lhs_an_loop_info[ii].var);
+       lhs_an_loop_info[ii].ind_init = build_x_modify_expr 
+	 (location, lhs_an_loop_info[ii].var, INIT_EXPR, build_zero_cst (typ), 
+	  complain);
+     }
+   
    if (rhs_list_size > 0)
      {
        rhs_array_operand = fix_sec_implicit_args (location, rhs_list,
@@ -743,24 +700,15 @@ expand_an_in_modify_expr (location_t location, tree lhs,
   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));
+      tree typ = ptrdiff_type_node;
+      rhs_an_loop_info[ii].var = create_temporary_var (typ);
+      add_decl_expr (rhs_an_loop_info[ii].var);
       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);
+	(location, rhs_an_loop_info[ii].var, INIT_EXPR, build_zero_cst (typ), 
+	 complain);
     }
 
   if (lhs_rank)
@@ -809,12 +757,12 @@ expand_an_in_modify_expr (location_t location, tree lhs,
     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.  */
+      /* No need to compare ii < rhs_rank && ii >= lhs_rank because in a valid 
+	 Array notation expression, rank of RHS cannot be greater than LHS.  */
       gcc_unreachable ();
   
   an_init = pop_stmt_list (an_init);
-  append_to_statement_list_force (an_init, &loop_with_init);
+  append_to_statement_list (an_init, &loop_with_init);
   body = array_expr;
   for (ii = 0; ii < MAX (lhs_rank, rhs_rank); ii++)
     {
@@ -824,17 +772,13 @@ expand_an_in_modify_expr (location_t location, tree lhs,
 
       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);
+	  append_to_statement_list (lhs_an_loop_info[ii].ind_init, &init_list);
+	  append_to_statement_list (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);
+	  append_to_statement_list (rhs_an_loop_info[ii].ind_init, &init_list);
+	  append_to_statement_list (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);
@@ -867,7 +811,6 @@ cp_expand_cond_array_notations (tree orig_stmt)
   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;
@@ -884,13 +827,17 @@ cp_expand_cond_array_notations (tree orig_stmt)
 	  || 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)
+      /* If the condition has a zero rank, then handle array notations in body
+	 seperately.  */
+      if (cond_rank == 0)
+	return orig_stmt;
+      if (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)
+      else if (cond_rank != no_rank && no_rank != 0)
 	{
 	  error_at (EXPR_LOCATION (no_expr), "rank mismatch with controlling "
 		    "expression of parent if-statement");
@@ -911,13 +858,17 @@ cp_expand_cond_array_notations (tree orig_stmt)
 	      && !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)
+
+      /* Same reasoning as for COND_EXPR.  */
+      if (cond_rank == 0)
+	return orig_stmt;
+      else if (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)
+      else if (cond_rank != no_rank && no_rank != 0)
 	{
 	  error_at (EXPR_LOCATION (no_expr), "rank mismatch with controlling "
 		    "expression of parent if-statement");
@@ -949,11 +900,11 @@ cp_expand_cond_array_notations (tree orig_stmt)
 	      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 (builtin_loop, &stmt);
 	    }
 	}
     }
-  append_to_statement_list_force (orig_stmt, &stmt);
+  append_to_statement_list (orig_stmt, &stmt);
   rank = 0;
   array_list = NULL;
   if (!find_rank (EXPR_LOCATION (stmt), stmt, stmt, true, &rank))
@@ -977,37 +928,28 @@ cp_expand_cond_array_notations (tree orig_stmt)
   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);
+      make_triplet_val_inv (&ARRAY_NOTATION_START (anode));
+      make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (anode));
+      make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (anode));
     }
   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);
-	}
+
+  for (ii = 0; ii < rank; ii++) 
+    {
+      tree typ = ptrdiff_type_node;
+      an_loop_info[ii].var = create_temporary_var (typ);
+      add_decl_expr (an_loop_info[ii].var);
+      an_loop_info[ii].ind_init =
+	build_x_modify_expr (location, an_loop_info[ii].var, INIT_EXPR,
+			     build_zero_cst (typ), 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);
+  append_to_statement_list (an_init, &loop_with_init);
   body = stmt;
 
   for (ii = 0; ii < rank; ii++)
@@ -1017,7 +959,7 @@ cp_expand_cond_array_notations (tree orig_stmt)
 		      an_loop_info[ii].incr, body);
       body = pop_stmt_list (new_loop);
     }
-  append_to_statement_list_force (body, &loop_with_init);
+  append_to_statement_list (body, &loop_with_init);
 
   an_info.release ();
   an_loop_info.release ();
@@ -1062,14 +1004,14 @@ expand_unary_array_notation_exprs (tree orig_stmt)
 	  {
 	    vec<tree, va_gc> *sub_list = NULL, *new_var_list = NULL;
 	    stmt = alloc_stmt_list ();
-	    append_to_statement_list_force (builtin_loop, &stmt);
+	    append_to_statement_list (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);
+    append_to_statement_list (finish_expr_stmt (orig_stmt), &stmt);
   else
     stmt = orig_stmt;
   rank = 0;
@@ -1089,22 +1031,19 @@ expand_unary_array_notation_exprs (tree orig_stmt)
   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);
+      make_triplet_val_inv (&ARRAY_NOTATION_START (array_node));
+      make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (array_node));
+      make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (array_node));
     }
   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));
+      tree typ = ptrdiff_type_node;
+      an_loop_info[ii].var = create_temporary_var (typ);
+      add_decl_expr (an_loop_info[ii].var);
       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)),
+	(location, an_loop_info[ii].var, INIT_EXPR, build_zero_cst (typ), 
 	 tf_warning_or_error);
     }
   array_operand = create_array_refs (location, an_info, an_loop_info,
@@ -1113,7 +1052,7 @@ expand_unary_array_notation_exprs (tree orig_stmt)
   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);
+  append_to_statement_list (an_init, &loop_with_init);
   body = stmt;
   
   for (ii = 0; ii < rank; ii++)
@@ -1123,7 +1062,7 @@ expand_unary_array_notation_exprs (tree orig_stmt)
 		      an_loop_info[ii].incr, body);
       body = pop_stmt_list (new_loop);
     }
-  append_to_statement_list_force (body, &loop_with_init);
+  append_to_statement_list (body, &loop_with_init);
 
   an_info.release ();
   an_loop_info.release ();
@@ -1139,21 +1078,35 @@ static tree
 expand_return_expr (tree expr)
 {
   tree new_mod_list, new_var, new_mod, retval_expr;
-
+  size_t rank  = 0;
+  location_t loc = EXPR_LOCATION (expr);
   if (TREE_CODE (expr) != RETURN_EXPR)
     return expr;
+      
+  if (!find_rank (loc, expr, expr, false, &rank))
+    return error_mark_node;
 
-  location_t loc = EXPR_LOCATION (expr);
-  new_mod_list = alloc_stmt_list ();
+  /* If the return expression contains array notations, then flag it as
+     error.  */
+  if (rank >= 1)
+    {
+      error_at (loc, "array notation expression cannot be used as a return "
+		"value");
+      return error_mark_node;
+    }
+  
+  new_mod_list = push_stmt_list ();
   retval_expr = TREE_OPERAND (expr, 0);
-  new_var = build_decl (loc, VAR_DECL, NULL_TREE, TREE_TYPE (retval_expr));
+  new_var = create_temporary_var (TREE_TYPE (retval_expr));
+  add_decl_expr (new_var);
   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),
+				      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);
+  add_stmt (new_mod);
+  add_stmt (expr);
+  new_mod_list = pop_stmt_list (new_mod_list);
   return new_mod_list;
 }
 
@@ -1290,19 +1243,21 @@ expand_array_notation_exprs (tree 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:      
+    case FOR_STMT:
+      if (contains_array_notation_expr (FOR_COND (t)))
+	{
+	  error_at (EXPR_LOCATION (FOR_COND (t)),
+		    "array notation cannot be used in a condition for "
+		    "a for-loop");
+	  return error_mark_node;
+	}
       /* 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));
+	{ 
+	  FOR_BODY (t) = expand_array_notation_exprs (FOR_BODY (t));
+	  FOR_EXPR (t) = expand_array_notation_exprs (FOR_EXPR (t));
+	}
       else
 	t = expand_array_notation_exprs (t);
       return t;
@@ -1322,44 +1277,39 @@ expand_array_notation_exprs (tree t)
 	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 (contains_array_notation_expr (SWITCH_STMT_COND (t)))
 	{
-	  if (SWITCH_STMT_BODY (t))
-	    SWITCH_STMT_BODY (t) =
-	      expand_array_notation_exprs (SWITCH_STMT_BODY (t));
+	  error_at (EXPR_LOCATION (SWITCH_STMT_COND (t)),
+		    "array notation cannot be used as a condition for "
+		    "switch statement");
+	  return error_mark_node;
 	}
-      else
-	t = expand_array_notation_exprs (t);
+      if (SWITCH_STMT_BODY (t))
+	SWITCH_STMT_BODY (t) =
+	  expand_array_notation_exprs (SWITCH_STMT_BODY (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 (contains_array_notation_expr (WHILE_COND (t)))
 	{
-	  if (WHILE_BODY (t))
-	    WHILE_BODY (t) = expand_array_notation_exprs (WHILE_BODY (t));
+	  if (EXPR_LOCATION (WHILE_COND (t)) != UNKNOWN_LOCATION)
+	    loc = EXPR_LOCATION (WHILE_COND (t));
+	  error_at (loc, "array notation cannot be used as a condition for "
+		    "while statement");
+	  return error_mark_node;
 	}
-      else
-	t = expand_array_notation_exprs (t);
+      if (WHILE_BODY (t))
+	WHILE_BODY (t) = expand_array_notation_exprs (WHILE_BODY (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));
+      if (contains_array_notation_expr (DO_COND (t)))
+	{
+	  error_at (EXPR_LOCATION (DO_COND (t)),
+		    "array notation cannot be used as a condition for a "
+		    "do-while statement");
+	  return error_mark_node;
 	}
-      else
-	t = expand_array_notation_exprs (t);
+      if (DO_BODY (t))
+	DO_BODY (t) = expand_array_notation_exprs (DO_BODY (t));
       return t;
     default:
       if (is_expr)
@@ -1380,57 +1330,64 @@ expand_array_notation_exprs (tree 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.  */
+/* Given the base of an array (ARRAY), the START (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, 
+   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)
+build_array_notation_ref (location_t loc, tree array, tree start, 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)
+  /* If we enter the then-case of the if-statement below, we have hit a case 
+     like this: ARRAY [:].  */
+  if (!start && !length)
     {
-      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;
+      if (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == POINTER_TYPE)
+	{
+	  error_at (loc, "start-index and length fields necessary for "
+		    "using array notation in pointers or records");
+	  return error_mark_node;
+	}
+      tree domain = TYPE_DOMAIN (type);
+      if (!domain)
+	{
+	  error_at (loc, "start-index and length fields necessary for "
+		    "using array notation with array of unknown bound");
+	  return error_mark_node;
+	}
+      start = cp_fold_convert (ptrdiff_type_node, TYPE_MINVAL (domain));
+      length = size_binop (PLUS_EXPR, TYPE_MAXVAL (domain), size_one_node);
+      length = cp_fold_convert (ptrdiff_type_node, length);
     }
+    
+  if (!stride) 
+    stride = build_one_cst (ptrdiff_type_node);
+  
+  /* When dealing with templates, triplet type-checking will be done in pt.c 
+     after type substitution.  */
+  if (processing_template_decl 
+      && (type_dependent_expression_p (array) 
+	  || type_dependent_expression_p (length) 
+	  || type_dependent_expression_p (start) 
+	  || type_dependent_expression_p (stride))) 
+    array_ntn_expr = build_min_nt_loc (loc, ARRAY_NOTATION_REF, array, start, 
+				       length, stride, NULL_TREE);
+  else 
+    { 
+      if (!cilkplus_an_triplet_types_ok_p (loc, start, length, stride, type))
+	return error_mark_node;
+      array_ntn_expr = build4 (ARRAY_NOTATION_REF, NULL_TREE, array, start, 
+			       length, stride);
+    }
+  if (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;
@@ -1462,20 +1419,9 @@ cilkplus_an_triplet_types_ok_p (location_t loc, tree start_index, tree length,
     }
   if (!TREE_CODE (type) == FUNCTION_TYPE)
     {
-      error_at (loc, "array notations cannot be used with function type");
+      error_at (loc, "array notation 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))
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 38ef878..590d857 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -1207,6 +1207,12 @@ cp_genericize (tree fndecl)
   if (DECL_CLONED_FUNCTION_P (fndecl))
     return;
 
+  /* Expand all the array notations here.  */
+  if (flag_enable_cilkplus 
+      && contains_array_notation_expr (DECL_SAVED_TREE (fndecl)))
+    DECL_SAVED_TREE (fndecl) = 
+      expand_array_notation_exprs (DECL_SAVED_TREE (fndecl));
+
   /* We do want to see every occurrence of the parms, so we can't just use
      walk_tree's hash functionality.  */
   cp_genericize_tree (&DECL_SAVED_TREE (fndecl));
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 00ee450..a3438a8 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4974,6 +4974,7 @@ extern bool pragma_java_exceptions;
 
 /* in call.c */
 extern bool check_dtor_name			(tree, tree);
+bool magic_varargs_p                            (tree);
 
 extern tree build_conditional_expr		(location_t, tree, tree, tree, 
                                                  tsubst_flags_t);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index ec8ad46..496d582 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -6062,39 +6062,30 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 
 /* 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
+   INIT_INDEX is NULL, then we have special case where 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.  */
+   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,
+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;
+  tree length_index, stride = NULL_TREE, value_tree, array_type;
+  bool saved_colon_corrects = 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;
-    }
+
+  array_type = TREE_TYPE (array_value);
+
+  parser->colon_corrects_to_scope_p = false;
   token = cp_lexer_peek_token (parser->lexer);
+  
   if (!token)
     {
       cp_parser_error (parser, "expected %<:%> or numeral");
@@ -6102,125 +6093,71 @@ cp_parser_array_notation (location_t loc, cp_parser *parser, tree init_index,
     }
   else if (token->type == CPP_COLON)
     {
-      if (!init_index)
+      /* Consume the ':'.  */
+      cp_lexer_consume_token (parser->lexer);
+      
+      /* If we are here, then we have a case like this A[:].  */
+      if (cp_lexer_peek_token (parser->lexer)->type != CPP_CLOSE_SQUARE)
 	{
-	  /* If we are here, then we have a case like this A[:].  */
-	  cp_lexer_consume_token (parser->lexer);
+	  cp_parser_error (parser, "expected %<]%>");
+	  cp_parser_skip_to_end_of_statement (parser);
+	  return error_mark_node;
+	}
+      *init_index = NULL_TREE;
+      stride = NULL_TREE;
+      length_index = NULL_TREE;
+    }
+  else
+    {
+      /* If we are here, then there are three valid possibilities:
+	 1. ARRAY [ EXP ]
+	 2. ARRAY [ EXP : EXP ]
+	 3. ARRAY [ EXP : EXP : EXP ]  */
 
-	  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);
+      *init_index = cp_parser_expression (parser, false, NULL);
+	
+      if (cp_lexer_peek_token (parser->lexer)->type != CPP_COLON)
+	{  
+	  /* This indicates that we have a normal array expression.  */
+	  parser->colon_corrects_to_scope_p = saved_colon_corrects;
+	  return NULL_TREE;
+	}
+      
+      /* Consume the ':'.  */
+      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)
+      if (!*init_index || *init_index == error_mark_node)
+	cp_parser_skip_to_end_of_statement (parser);
+
+      length_index = cp_parser_expression (parser, false, NULL);
+      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);
+	  stride = cp_parser_expression (parser, false, NULL);
+	  if (stride == error_mark_node)
 	    {
-	      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);
-		}
+	      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)
+  parser->colon_corrects_to_scope_p = saved_colon_corrects;
+
+  if (*init_index == error_mark_node || length_index == error_mark_node
+      || stride == error_mark_node)
     {
       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);
+
+  value_tree = build_array_notation_ref (loc, array_value, *init_index, 
+					 length_index, stride, array_type);
   return value_tree;
 }
 
@@ -6239,84 +6176,84 @@ cp_parser_postfix_open_square_expression (cp_parser *parser,
 					  bool for_offsetof,
 					  bool decltype_p)
 {
-  tree index;
+  tree index = NULL_TREE;
   location_t loc = cp_lexer_peek_token (parser->lexer)->location;
 
   /* Consume the `[' token.  */
   cp_lexer_consume_token (parser->lexer);
 
-  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);
+  if (flag_enable_cilkplus)
+    {
+      bool saved_colon_corrects = parser->colon_corrects_to_scope_p;
+      parser->colon_corrects_to_scope_p = false;
+      if (cp_lexer_peek_token (parser->lexer)->type == CPP_COLON)
+	{
+	  /* If we are here, then we have something like this: ARRAY[:]  */
+	  tree an_exp = cp_parser_array_notation (loc, parser, &index,
+						  postfix_expression);
+	  parser->colon_corrects_to_scope_p = saved_colon_corrects;
+	  return an_exp;
+	}
+    }
+  /* 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
     {
-      /* 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
+      if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
 	{
-	  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);
+	  bool saved_colon_corrects = parser->colon_corrects_to_scope_p;
+	  parser->colon_corrects_to_scope_p = false;
+	  if (flag_enable_cilkplus
+	      && cp_lexer_peek_token (parser->lexer)->type == CPP_COLON)
 	    {
-	      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;
-		}
+	      error_at (cp_lexer_peek_token (parser->lexer)->location,
+			"braced list index is not allowed with array "
+			"notation");
+	      cp_parser_skip_to_end_of_statement (parser);
+	      return 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;
+	  parser->colon_corrects_to_scope_p = saved_colon_corrects;
 	}
-      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
+      else if (flag_enable_cilkplus)
 	{
-  	  /* 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);
-
-	  /* 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;
+	  /* Here are have these two options:
+	     ARRAY[EXP : EXP]        - Array notation expr with default
+	     stride of 1.
+	     ARRAY[EXP : EXP : EXP] - Array Notation with user-defined
+	     stride.  */
+	  tree an_exp = cp_parser_array_notation (loc, parser, &index, 
+						  postfix_expression);
+	  if (an_exp)
+	    return an_exp;
 	}
+      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);
+
+  /* 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;
 }
 
@@ -9551,8 +9488,6 @@ 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;
 }
 
@@ -9745,14 +9680,6 @@ 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;
@@ -10310,12 +10237,6 @@ 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;
 
@@ -10342,15 +10263,6 @@ 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;
 
@@ -10369,17 +10281,8 @@ cp_parser_iteration_statement (cp_parser* parser)
 	cp_parser_already_scoped_statement (parser);
 	parser->in_statement = in_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);
+	/* We're done with the for-statement.  */
+	finish_for_stmt (statement);
       }
       break;
 
@@ -16952,54 +16855,30 @@ cp_parser_direct_declarator (cp_parser* parser,
 	  if (token->type != CPP_CLOSE_SQUARE)
 	    {
 	      bool non_constant_p;
-
-	      if (flag_enable_cilkplus
-		  && cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+	      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;
-		  error_at (cp_lexer_peek_token (parser->lexer)->location,
-			    "array notations cannot be used in declaration");
-		  cp_lexer_consume_token (parser->lexer);
 		}
-	      else
+	      else if (processing_template_decl)
 		{
-		  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; 
-		    }
+		  /* Remember this wasn't a constant-expression.  */
+		  bounds = build_nop (TREE_TYPE (bounds), bounds);
+		  TREE_SIDE_EFFECTS (bounds) = 1;
 		}
 	    }
 	  else
@@ -18370,11 +18249,6 @@ 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);
 
@@ -22354,12 +22228,6 @@ 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));
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 667e37f..5dafdcd 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -15739,9 +15739,6 @@ 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;
@@ -19143,11 +19140,6 @@ 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);
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 0a460a4..87c1560 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -779,22 +779,6 @@ 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 ())
@@ -8089,7 +8073,6 @@ 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);
@@ -8901,7 +8884,6 @@ 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:
@@ -8912,6 +8894,9 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
 	  return false;
       return true;
 
+    case ARRAY_NOTATION_REF:
+      return false;
+
     case FMA_EXPR:
     case VEC_PERM_EXPR:
      for (i = 0; i < 3; ++i)
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 5b321ce..11592b4 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -3493,10 +3493,6 @@ cp_build_function_call_vec (tree function, vec<tree, va_gc> **params,
       params = &allocated;
     }
 
-  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)
@@ -3660,8 +3656,7 @@ convert_arguments (tree typelist, vec<tree, va_gc> **values, tree fndecl,
 	}
       else
 	{
-	  if (fndecl && DECL_BUILT_IN (fndecl)
-	      && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CONSTANT_P)
+	  if (fndecl && magic_varargs_p (fndecl))
 	    /* Don't do ellipsis conversion for __built_in_constant_p
 	       as this will result in spurious errors for non-trivial
 	       types.  */
@@ -3956,15 +3951,8 @@ cp_build_binary_op (location_t location,
 	}
     }
 
-  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);
+  type0 = TREE_TYPE (op0); 
+  type1 = TREE_TYPE (op1);
 
   /* The expression codes of the data types of the arguments tell us
      whether the arguments are integers, floating, pointers, etc.  */
@@ -5167,13 +5155,6 @@ 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)))
     {
@@ -7852,13 +7833,6 @@ 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);
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/decl-ptr-colon.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/decl-ptr-colon.c
index 68c8859..4b54f4d 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/decl-ptr-colon.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/decl-ptr-colon.c
@@ -1,3 +1,4 @@
+/* { dg-do compile { target c } } */
 /* { dg-options "-fcilkplus" } */
 
 int main(void)
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/dimensionless-arrays.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/dimensionless-arrays.c
index 69aaa52..690e89a 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/dimensionless-arrays.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/dimensionless-arrays.c
@@ -5,6 +5,6 @@ extern int *b;
 
 void foo()
 {
-  a[:] = 5;	// { dg-error "start-index and length fields necessary for using array notations in dimensionless arrays" }
-  b[:] = 5;    // { dg-error "start-index and length fields necessary for using array notations in pointers" }
+  a[:] = 5;	// { dg-error "start-index and length fields necessary for using array notation" }
+  b[:] = 5;    // { dg-error "start-index and length fields necessary for using" }
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/fn_ptr.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/fn_ptr.c
index 024a158..fa6d900 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/fn_ptr.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/fn_ptr.c
@@ -1,3 +1,4 @@
+/* { dg-do compile } */
 /* { dg-options "-fcilkplus" } */
 
 typedef int (*foo)(int);
@@ -10,11 +11,11 @@ int main(void)
   foo ***func_array_ptr;
   int argc = 5;
 
-  array[:] =  func_array[:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
-  func_array[0:5](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
-  func_array2[0:5][:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
-  array2[0:5][:] = func_array2[0:5][:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
-  func_array_ptr[0:5][0:4][0:argc:2](argc); /* { dg-error "array notations cannot be used with function pointer arrays" } */
+  array[:] =  func_array[:](10); 
+  func_array[0:5](10); 
+  func_array2[0:5][:](10);
+  array2[0:5][:] = func_array2[0:5][:](10);
+  func_array_ptr[0:5][0:4][0:argc:2](argc); 
 
   return 0;
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
index 14421d9..814786b 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
@@ -6,7 +6,7 @@ int main (void)
   int array[10], array2[10][10];
   int x, ii, jj ;
 
-  switch (array[:]) {  /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  switch (array[:]) {  /* { dg-error "cannot be used as a condition for switch statement" } */
   case 1:
     x = 5;
     break;
@@ -17,7 +17,7 @@ int main (void)
     x = 9;
   }
 
-  switch (array2[:][:]) { /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  switch (array2[:][:]) { /* { dg-error "cannot be used as a condition for switch statement" } */
   case 1:
     x = 5;
     break;
@@ -28,7 +28,7 @@ int main (void)
     x = 9;
   }
 
-  switch (array[:] + x) { /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  switch (array[:] + x) { /* { dg-error "cannot be used as a condition for switch statement" } */
   case 1:
     x = 5;
     break;
@@ -39,7 +39,7 @@ int main (void)
     x = 9;
   }
   
-  switch (array2[:][1:x:4] + x) { /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  switch (array2[:][1:x:4] + x) { /* { dg-error "cannot be used as a condition for switch statement" } */
   case 1:
     x = 5;
     break;
@@ -50,36 +50,36 @@ int main (void)
     x = 9;
   }
 
-  for (ii = 0; ii < array[:]; ii++) /* { dg-error "array notations cannot be used in a condition for a for-loop" } */
+  for (ii = 0; ii < array[:]; ii++) /* { dg-error "cannot be used in a condition for a for-loop" } */
     {
       x = 2;
     }
 
-  for (ii = 0; ii < array2[:][:]; ii++) /* { dg-error "array notations cannot be used in a condition for a for-loop" } */
+  for (ii = 0; ii < array2[:][:]; ii++) /* { dg-error "cannot be used in a condition for a for-loop" } */
     {
       x = 3;
     }
 
-  for (; array2[:][:] < 2;) /* { dg-error "array notations cannot be used in a condition for a for-loop" } */
+  for (; array2[:][:] < 2;) /* { dg-error "cannot be used in a condition for a for-loop" } */
     x = 4;
 
 
-  while (array2[:][:]) /* { dg-error "array notations cannot be used as a condition for while statement" } */
+  while (array2[:][:]) /* { dg-error "cannot be used as a condition for while statement" } */
     x = 3;
 
-  while (array[1:1:1]) /* { dg-error "array notations cannot be used as a condition for while statement" } */
+  while (array[1:1:1]) /* { dg-error "cannot be used as a condition for while statement" } */
     x = 1;
 
-  while (ii != array2[1:x:3][1:2:1]) /* { dg-error "array notations cannot be used as a condition for while statement"  } */
+  while (ii != array2[1:x:3][1:2:1]) /* { dg-error "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" "" { target c } } */
+  do { /* { dg-error "cannot be used as a condition for a do-while statement" "" { target c } } */
     x = 3;
-  } while (ii != array2[:][:]); /* { dg-error "array notations cannot be used as a condition for a do-while statement" "" { target c++ } } */
+  } while (ii != array2[:][:]); /* { dg-error "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" "" { target c } } */
+  do {  /* { dg-error "cannot be used as a condition for a do-while statement" "" { target c } } */
     x = 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++ } } */
+  } while (ii != (x + array2[:][1:x:2]) + 2); /* { dg-error "cannot be used as a condition for a do-while statement" "" { target c++ } } */
   
   do { 
     x += 3;
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/rank_mismatch.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/rank_mismatch.c
index b5e37ce..eb3c1f1 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/rank_mismatch.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/rank_mismatch.c
@@ -10,6 +10,7 @@ int main (void)
   int array[10][10], array2[10];
 
   array[:][:] = array[:]; /* { dg-error "rank mismatch between" } */
+  /* { dg-error "invalid conversion" "" { target c++ } 12 } */
 
   x = array2[:]; /* { dg-error "cannot be scalar when" } */
 

^ permalink raw reply	[flat|nested] 40+ messages in thread

* RE: [PATCH] Cilk Plus Array Notation for C++
  2013-06-27 15:52                                     ` Iyer, Balaji V
@ 2013-06-27 15:54                                       ` Iyer, Balaji V
  2013-06-27 18:39                                         ` Iyer, Balaji V
  0 siblings, 1 reply; 40+ messages in thread
From: Iyer, Balaji V @ 2013-06-27 15:54 UTC (permalink / raw)
  To: Jason Merrill, Richard Henderson; +Cc: Aldy Hernandez, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 4328 bytes --]

Sorry, I forgot to fix an header comment to cp_parser_array_notation (...). Here is the fixed patch and the Changelogs again..

Thanks,

Balaji V. Iyer.

> -----Original Message-----
> From: gcc-patches-owner@gcc.gnu.org [mailto:gcc-patches-
> owner@gcc.gnu.org] On Behalf Of Iyer, Balaji V
> Sent: Thursday, June 27, 2013 11:40 AM
> To: Jason Merrill; Richard Henderson
> Cc: Aldy Hernandez; gcc-patches@gcc.gnu.org
> Subject: RE: [PATCH] Cilk Plus Array Notation for C++
> 
> Hello Jason et al.,
> 	Please see my responses to your questions below. I am attaching a fixed
> patch and ChangeLog. Is this Ok for trunk?
> 
> Thanks,
> 
> Balaji V. Iyer.
> 
> > -----Original Message-----
> > From: Jason Merrill [mailto:jason@redhat.com]
> > Sent: Wednesday, June 26, 2013 4:13 PM
> > To: Iyer, Balaji V; Richard Henderson
> > Cc: Aldy Hernandez; gcc-patches@gcc.gnu.org
> > Subject: Re: [PATCH] Cilk Plus Array Notation for C++
> >
> > On 06/26/2013 01:31 PM, Iyer, Balaji V wrote:
> > > 	Attached, please find a fixed patch and ChangeLog entries:
> >
> > This patch seems to be missing some hunks that are described in the
> > ChangeLog and were present in the previous patch, such as
> >
> > >         * cp-array-notation.c (cp_length_mismatch_in_expr_p): Combined two
> > >         if statements into one and compared integers using tree_int_cst_equal.
> >
> 
> I checked in a patch for C that replaced all dynamic arrays in C with vec_trees.
> Thus, this function could be replaced with the function in c-family. It was my
> mistake that I forgot to take this line out of the changelog entry.
> 
> > > Sorry about that, I accidentally missed this one. It is fixed now. I
> > > have also
> > added the braced list capability into cp_array_notation.
> >
> > Hmm, I seem to have been unclear.  I was expecting that the call to
> > cp_parser_array_notation could come after the braced list case, so we
> > don't need to duplicate the offsetof or braced list code inside
> > cp_parser_array_notation.
> >
> > And then if you'd like we could check for ':' before the ']' and give
> > a helpful diagnostic.
> 
> I Think I have fixed this as you requested.
> 
> >
> > > +      /* If we hare here, then there are 2 possibilities:
> >
> > "are"
> 
> Fixed!
> 
> >
> > > +  if (processing_template_decl)
> > > +    array_ntn_expr = build_min_nt_loc (loc, ARRAY_NOTATION_REF, array,
> > > +                                      start_index, length, stride,
> > > + NULL_TREE);
> >
> > If we know the type of the array, we should use it, rather than always
> > leaving it null in a template.  That is, if !dependent_type_p (type),
> > we should give the ARRAY_NOTATION_REF a real type.
> >
> 
> Fixed.
> 
> > > +      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 notation in pointers or records");
> >
> 
> Moved as you suggested.
> 
> > In a template, array_type might be NULL_TREE; this diagnostic should
> > move into build_array_notation_ref.
> >
> > > +      array_type_domain = TYPE_DOMAIN (array_type);
> > > +      if (!array_type_domain)
> > > +       {
> > > +         error_at (loc, "start-index and length fields necessary for "
> > > +                   "using array notation with array of unknown bound");
> > > +         cp_parser_skip_to_end_of_statement (parser);
> > > +         return error_mark_node;
> > > +       }
> > > +      start_index = TYPE_MINVAL (array_type_domain);
> > > +      start_index = cp_fold_convert (ptrdiff_type_node, start_index);
> > > +      length_index = size_binop
> > > +       (PLUS_EXPR, TYPE_MAXVAL (array_type_domain), size_one_node);
> > > +      length_index = cp_fold_convert (ptrdiff_type_node, length_index);
> > > +      stride = build_int_cst (ptrdiff_type_node, 1);
> >
> > As should all this code.  cp_parser_array_notation should only parse.
> >
> 
> Moved as you suggested.
> 
> > > +      else
> > > +       stride = build_one_cst (ptrdiff_type_node);
> >
> > I would move this into build_array_notation_ref as well.
> 
> Moved as you suggested.
> 
> >
> > Jason


[-- Attachment #2: diff.txt --]
[-- Type: text/plain, Size: 81587 bytes --]

diff --git a/gcc/builtins.def b/gcc/builtins.def
index 91879a6..9b55b1f 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -158,9 +158,9 @@ along with GCC; see the file COPYING3.  If not see
 	       (flag_asan || flag_tsan))
 
 #undef DEF_CILKPLUS_BUILTIN
-#define DEF_CILKPLUS_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
-  DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
-  	       false, false, true, ATTRS, false, flag_enable_cilkplus)
+#define DEF_CILKPLUS_BUILTIN(ENUM, NAME, TYPE, ATTRS)  \
+  DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, BT_FN_INT_VAR, BT_LAST, \
+  	       false, false, false, ATTRS, false, flag_enable_cilkplus) 
 
 /* Define an attribute list for math functions that are normally
    "impure" because some of them may write into global memory for
diff --git a/gcc/c-family/array-notation-common.c b/gcc/c-family/array-notation-common.c
index 8eab89b..5e17009 100644
--- a/gcc/c-family/array-notation-common.c
+++ b/gcc/c-family/array-notation-common.c
@@ -101,15 +101,11 @@ length_mismatch_in_expr_p (location_t loc, vec<vec<an_parts> >list)
 	      /* 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;
-		    }
+	      if (TREE_CODE (list[ii][jj].length) == INTEGER_CST
+		  && !tree_int_cst_equal (list[ii][jj].length, length))
+		{ 
+		  error_at (loc, "length mismatch in expression"); 
+		  return true;
 		}
 	    }
 	  else
@@ -271,6 +267,8 @@ find_rank (location_t loc, tree orig_expr, tree expr, bool ignore_builtin_fn,
 		/* If it is a built-in function, then we know it returns a 
 		   scalar.  */
 		return true;
+	  if (!find_rank (loc, orig_expr, func_name, ignore_builtin_fn, rank))
+	    return false;
 	  FOR_EACH_CALL_EXPR_ARG (arg, iter, expr)
 	    {
 	      if (!find_rank (loc, orig_expr, arg, ignore_builtin_fn, rank))
@@ -358,6 +356,9 @@ extract_array_notation_exprs (tree node, bool ignore_builtin_fn,
 	  vec_safe_push (*array_list, node);
 	  return;
 	}
+      /* This will extract array notations in function pointers.  */
+      extract_array_notation_exprs (CALL_EXPR_FN (node), ignore_builtin_fn,
+				    array_list);
       FOR_EACH_CALL_EXPR_ARG (arg, iter, node)
 	extract_array_notation_exprs (arg, ignore_builtin_fn, array_list);
     } 
@@ -433,6 +434,9 @@ replace_array_notations (tree *orig, bool ignore_builtin_fn,
 	      }
 	  return;
 	}
+      /* Fixes array notations in array notations in function pointers.  */
+      replace_array_notations (&CALL_EXPR_FN (*orig), ignore_builtin_fn, list,
+			       array_operand);
       ii = 0;
       FOR_EACH_CALL_EXPR_ARG (arg, iter, *orig)
 	{
@@ -575,53 +579,49 @@ 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++)
+
+  if (rank > 0)
+    for (size_t ii = 0; ii < size; ii++)
       {
-	(*node)[ii].safe_push (init);
-	array_exprs[ii].safe_push (NULL_TREE);
+	(*node)[ii].safe_grow_cleared (rank);
+	array_exprs[ii].safe_grow_cleared (rank);
       }
-
   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 ();	
+	{
+	  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
+	    break;
+	}
     }
     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));
-	    }
+	  {
+	    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
@@ -637,16 +637,15 @@ fix_sec_implicit_args (location_t loc, vec <tree, va_gc> *list,
   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)
+	if (idx < 0)
 	  /* In this case, the returning function would have emitted an
 	     error thus it is not necessary to do so again.  */
 	  return NULL;
+	else if (idx < (int) rank)
+	  vec_safe_push (array_operand, an_loop_info[idx].var);
 	else
 	  {
 	    error_at (loc, "__sec_implicit_index argument %d must be "
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index d6a500e..c7846ce 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -11053,24 +11053,6 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
 	      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
 	      return error_mark_node;
 	    }
-	  if (TREE_CODE (array_type) == ARRAY_TYPE)
-	    {
-	      tree subtype = TREE_TYPE (array_type);
-	      while (subtype && TREE_CODE (subtype) == POINTER_TYPE)
-		{
-		  /* Now this could be a function pointer.  Find them and
-		     give out an error.  */
-		  subtype = TREE_TYPE (subtype);
-		  if (subtype && TREE_CODE (subtype) == FUNCTION_TYPE)
-		    {
-		      error_at (loc, "array notations cannot be used with "
-				"function pointer arrays");
-		      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
-						 NULL);
-		      return error_mark_node;
-		    }
-		}
-	    }
 	  array_type_domain = TYPE_DOMAIN (array_type);
 
 	  if (!array_type_domain)
@@ -11114,27 +11096,6 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
 	      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
 	      return error_mark_node;
 	    }
-	  if (TREE_CODE (array_type) == ARRAY_TYPE
-	      || TREE_CODE (array_type) == POINTER_TYPE)
-	    {
-	      tree subtype = TREE_TYPE (array_type);
-	      while (subtype
-		     && (TREE_CODE (subtype) == POINTER_TYPE
-			 || TREE_CODE (subtype) == ARRAY_TYPE))
-		{
-		  /* Now this could be a function pointer.  Find them and
-		     give out an error.  */
-		  subtype = TREE_TYPE (subtype);
-		  if (subtype && TREE_CODE (subtype) == FUNCTION_TYPE)
-		    {
-		      error_at (loc, "array notations cannot be used with "
-				"function pointer arrays");
-		      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
-						 NULL);
-		      return error_mark_node;
-		    }
-		}
-	    }
 	  c_parser_consume_token (parser); /* consume the ':' */
 	  end_index = c_parser_expression (parser).value;
 	  if (!end_index || end_index == error_mark_node)
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 6817bfc..425ef9b 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -216,7 +216,6 @@ static void add_candidates (tree, tree, const vec<tree, va_gc> *, tree, tree,
 			    bool, tree, tree, int, struct z_candidate **,
 			    tsubst_flags_t);
 static conversion *merge_conversion_sequences (conversion *, conversion *);
-static bool magic_varargs_p (tree);
 static tree build_temp (tree, tree, int, diagnostic_t *, tsubst_flags_t);
 
 /* Returns nonzero iff the destructor name specified in NAME matches BASETYPE.
@@ -5857,16 +5856,9 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
 	  else if (t->kind == ck_identity)
 	    break;
 	}
-
-      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)
+       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);
 
@@ -6515,9 +6507,12 @@ convert_for_arg_passing (tree type, tree val, tsubst_flags_t complain)
    which no conversions at all should be done.  This is true for some
    builtins which don't act like normal functions.  */
 
-static bool
+bool
 magic_varargs_p (tree fn)
 {
+  if (flag_enable_cilkplus && is_cilkplus_reduce_builtin (fn) != BUILT_IN_NONE)
+    return true;
+
   if (DECL_BUILT_IN (fn))
     switch (DECL_FUNCTION_CODE (fn))
       {
@@ -6895,21 +6890,13 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
 		       "  (you can disable this with -fno-deduce-init-list)");
 	    }
 	}
+      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
index 491da0f..b4fada4 100644
--- a/gcc/cp/cp-array-notation.c
+++ b/gcc/cp/cp-array-notation.c
@@ -59,7 +59,6 @@
 #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.  */
@@ -82,17 +81,12 @@ create_an_loop (tree init, tree cond, tree incr, tree body)
    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)
+make_triplet_val_inv (tree *value)
 {
-  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;
-    }
+    *value = get_temp_regvar (ptrdiff_type_node, *value);
 }
 
 /* Returns a vector of size RANK that contains an ARRAY_REF.  This vector is
@@ -140,9 +134,9 @@ create_array_refs (location_t loc, vec<vec<an_parts> > an_info,
 		   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);
+		st = build_c_cast (loc, ptrdiff_type_node, start);
+		str = build_c_cast (loc, ptrdiff_type_node, stride);
+		v = build_c_cast (loc, ptrdiff_type_node, var);
 	      }
 	    else
 	      {
@@ -192,7 +186,7 @@ replace_invariant_exprs (tree *node)
 {
   size_t ix = 0;
   tree node_list = NULL_TREE;
-  tree t = NULL_TREE, new_var = NULL_TREE, new_node; 
+  tree t = NULL_TREE, new_var = NULL_TREE;
   struct inv_list data;
 
   data.list_values = NULL;
@@ -204,17 +198,11 @@ replace_invariant_exprs (tree *node)
     {
       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);
+	{ 
+	  /* Sometimes, it type-casts certain functions to void. Unwrap it.  */
+	  if (VOID_TYPE_P (TREE_TYPE (t)) && TREE_CODE (t) == CONVERT_EXPR)
+	    t = TREE_OPERAND (t, 0);
+	  new_var = get_temp_regvar (TREE_TYPE (t), t); 
 	  vec_safe_push (data.replacement, new_var);
 	}
       cp_walk_tree (node, replace_inv_trees, (void *) &data, NULL);
@@ -235,7 +223,6 @@ 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 ();
@@ -305,7 +292,7 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
     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;
+      new_var_type = boolean_type_node;
       break;
     case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
     case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
@@ -334,24 +321,30 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
     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);
+	make_triplet_val_inv (&ARRAY_NOTATION_START (anode));
+	make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (anode));
+	make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (anode));
       }
   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);
+      tree typ = ptrdiff_type_node;
+
+      /* In this place, we are using get_temp_regvar instead of 
+	 create_temporary_var if an_type is SEC_REDUCE_MAX/MIN_IND because
+	 the array_ind_value depends on this value being initalized to 0.  */
+      if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
+	  || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND) 
+	an_loop_info[ii].var = get_temp_regvar (typ, build_zero_cst (typ));
+      else
+	{
+	  an_loop_info[ii].var = create_temporary_var (typ);
+	  add_decl_expr (an_loop_info[ii].var);
+	}
+      an_loop_info[ii].ind_init = 
+	build_x_modify_expr (location, an_loop_info[ii].var, INIT_EXPR,
+			     build_zero_cst (typ), 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);
@@ -360,26 +353,9 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
     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);
-    }
+      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND) 
+    array_ind_value = get_temp_regvar (TREE_TYPE (func_parm), func_parm);
 
   array_op0 = (*array_operand)[0];
   switch (an_type)
@@ -394,35 +370,36 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
       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;
+      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;
+      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;
+      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;
+      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;
+      code = (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND ? LE_EXPR
+	: GE_EXPR);
       init = an_loop_info[0].var;
+      break;
     case BUILT_IN_CILKPLUS_SEC_REDUCE:
       init = identity_value;
       break;
@@ -433,9 +410,11 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
       gcc_unreachable ();
     }
 
-  if (init)
-    new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR, init,
-					tf_warning_or_error);
+  if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
+    *new_var = get_temp_regvar (new_var_type, init);
+  else
+    *new_var = NULL_TREE;
+
   switch (an_type)
     {
     case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD:
@@ -470,8 +449,6 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
       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,
@@ -521,21 +498,8 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
     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);
+  append_to_statement_list (an_init, &loop_with_init);
   body = new_expr;
 
   for (ii = 0; ii < rank; ii++)
@@ -545,7 +509,7 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
 		      an_loop_info[ii].incr, body);
       body = pop_stmt_list (new_loop);
     }
-  append_to_statement_list_force (body, &loop_with_init);
+  append_to_statement_list (body, &loop_with_init);
 
   an_info.release ();
   an_loop_info.release ();
@@ -634,10 +598,7 @@ expand_an_in_modify_expr (location_t location, tree lhs,
 	  return an_init;
 	}
       else
-	{
-	  pop_stmt_list (an_init);
-	  return NULL_TREE;
-	}
+	gcc_unreachable ();
     }
 
   /* If for some reason location is not set, then find if LHS or RHS has
@@ -659,8 +620,6 @@ expand_an_in_modify_expr (location_t location, tree lhs,
     
   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;
     }
@@ -675,17 +634,17 @@ expand_an_in_modify_expr (location_t location, tree lhs,
   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);
+      make_triplet_val_inv (&ARRAY_NOTATION_START (anode));
+      make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (anode));
+      make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (anode));
     }
   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);
+	make_triplet_val_inv (&ARRAY_NOTATION_START (aa));
+	make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (aa));
+	make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (aa));
       }
   lhs_an_loop_info.safe_grow_cleared (lhs_rank);
   
@@ -705,31 +664,29 @@ expand_an_in_modify_expr (location_t location, tree lhs,
       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;
+  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;
-	}
+      && TREE_CODE (rhs_len) == INTEGER_CST 
+      && !tree_int_cst_equal (rhs_len, lhs_len))
+    { 
+      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);
+   for (ii = 0; ii < lhs_rank; ii++) 
+     {
+       tree typ = ptrdiff_type_node; 
+       lhs_an_loop_info[ii].var = create_temporary_var (typ);
+       add_decl_expr (lhs_an_loop_info[ii].var);
+       lhs_an_loop_info[ii].ind_init = build_x_modify_expr 
+	 (location, lhs_an_loop_info[ii].var, INIT_EXPR, build_zero_cst (typ), 
+	  complain);
+     }
+   
    if (rhs_list_size > 0)
      {
        rhs_array_operand = fix_sec_implicit_args (location, rhs_list,
@@ -743,24 +700,15 @@ expand_an_in_modify_expr (location_t location, tree lhs,
   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));
+      tree typ = ptrdiff_type_node;
+      rhs_an_loop_info[ii].var = create_temporary_var (typ);
+      add_decl_expr (rhs_an_loop_info[ii].var);
       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);
+	(location, rhs_an_loop_info[ii].var, INIT_EXPR, build_zero_cst (typ), 
+	 complain);
     }
 
   if (lhs_rank)
@@ -809,12 +757,12 @@ expand_an_in_modify_expr (location_t location, tree lhs,
     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.  */
+      /* No need to compare ii < rhs_rank && ii >= lhs_rank because in a valid 
+	 Array notation expression, rank of RHS cannot be greater than LHS.  */
       gcc_unreachable ();
   
   an_init = pop_stmt_list (an_init);
-  append_to_statement_list_force (an_init, &loop_with_init);
+  append_to_statement_list (an_init, &loop_with_init);
   body = array_expr;
   for (ii = 0; ii < MAX (lhs_rank, rhs_rank); ii++)
     {
@@ -824,17 +772,13 @@ expand_an_in_modify_expr (location_t location, tree lhs,
 
       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);
+	  append_to_statement_list (lhs_an_loop_info[ii].ind_init, &init_list);
+	  append_to_statement_list (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);
+	  append_to_statement_list (rhs_an_loop_info[ii].ind_init, &init_list);
+	  append_to_statement_list (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);
@@ -867,7 +811,6 @@ cp_expand_cond_array_notations (tree orig_stmt)
   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;
@@ -884,13 +827,17 @@ cp_expand_cond_array_notations (tree orig_stmt)
 	  || 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)
+      /* If the condition has a zero rank, then handle array notations in body
+	 seperately.  */
+      if (cond_rank == 0)
+	return orig_stmt;
+      if (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)
+      else if (cond_rank != no_rank && no_rank != 0)
 	{
 	  error_at (EXPR_LOCATION (no_expr), "rank mismatch with controlling "
 		    "expression of parent if-statement");
@@ -911,13 +858,17 @@ cp_expand_cond_array_notations (tree orig_stmt)
 	      && !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)
+
+      /* Same reasoning as for COND_EXPR.  */
+      if (cond_rank == 0)
+	return orig_stmt;
+      else if (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)
+      else if (cond_rank != no_rank && no_rank != 0)
 	{
 	  error_at (EXPR_LOCATION (no_expr), "rank mismatch with controlling "
 		    "expression of parent if-statement");
@@ -949,11 +900,11 @@ cp_expand_cond_array_notations (tree orig_stmt)
 	      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 (builtin_loop, &stmt);
 	    }
 	}
     }
-  append_to_statement_list_force (orig_stmt, &stmt);
+  append_to_statement_list (orig_stmt, &stmt);
   rank = 0;
   array_list = NULL;
   if (!find_rank (EXPR_LOCATION (stmt), stmt, stmt, true, &rank))
@@ -977,37 +928,28 @@ cp_expand_cond_array_notations (tree orig_stmt)
   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);
+      make_triplet_val_inv (&ARRAY_NOTATION_START (anode));
+      make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (anode));
+      make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (anode));
     }
   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);
-	}
+
+  for (ii = 0; ii < rank; ii++) 
+    {
+      tree typ = ptrdiff_type_node;
+      an_loop_info[ii].var = create_temporary_var (typ);
+      add_decl_expr (an_loop_info[ii].var);
+      an_loop_info[ii].ind_init =
+	build_x_modify_expr (location, an_loop_info[ii].var, INIT_EXPR,
+			     build_zero_cst (typ), 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);
+  append_to_statement_list (an_init, &loop_with_init);
   body = stmt;
 
   for (ii = 0; ii < rank; ii++)
@@ -1017,7 +959,7 @@ cp_expand_cond_array_notations (tree orig_stmt)
 		      an_loop_info[ii].incr, body);
       body = pop_stmt_list (new_loop);
     }
-  append_to_statement_list_force (body, &loop_with_init);
+  append_to_statement_list (body, &loop_with_init);
 
   an_info.release ();
   an_loop_info.release ();
@@ -1062,14 +1004,14 @@ expand_unary_array_notation_exprs (tree orig_stmt)
 	  {
 	    vec<tree, va_gc> *sub_list = NULL, *new_var_list = NULL;
 	    stmt = alloc_stmt_list ();
-	    append_to_statement_list_force (builtin_loop, &stmt);
+	    append_to_statement_list (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);
+    append_to_statement_list (finish_expr_stmt (orig_stmt), &stmt);
   else
     stmt = orig_stmt;
   rank = 0;
@@ -1089,22 +1031,19 @@ expand_unary_array_notation_exprs (tree orig_stmt)
   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);
+      make_triplet_val_inv (&ARRAY_NOTATION_START (array_node));
+      make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (array_node));
+      make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (array_node));
     }
   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));
+      tree typ = ptrdiff_type_node;
+      an_loop_info[ii].var = create_temporary_var (typ);
+      add_decl_expr (an_loop_info[ii].var);
       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)),
+	(location, an_loop_info[ii].var, INIT_EXPR, build_zero_cst (typ), 
 	 tf_warning_or_error);
     }
   array_operand = create_array_refs (location, an_info, an_loop_info,
@@ -1113,7 +1052,7 @@ expand_unary_array_notation_exprs (tree orig_stmt)
   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);
+  append_to_statement_list (an_init, &loop_with_init);
   body = stmt;
   
   for (ii = 0; ii < rank; ii++)
@@ -1123,7 +1062,7 @@ expand_unary_array_notation_exprs (tree orig_stmt)
 		      an_loop_info[ii].incr, body);
       body = pop_stmt_list (new_loop);
     }
-  append_to_statement_list_force (body, &loop_with_init);
+  append_to_statement_list (body, &loop_with_init);
 
   an_info.release ();
   an_loop_info.release ();
@@ -1139,21 +1078,35 @@ static tree
 expand_return_expr (tree expr)
 {
   tree new_mod_list, new_var, new_mod, retval_expr;
-
+  size_t rank  = 0;
+  location_t loc = EXPR_LOCATION (expr);
   if (TREE_CODE (expr) != RETURN_EXPR)
     return expr;
+      
+  if (!find_rank (loc, expr, expr, false, &rank))
+    return error_mark_node;
 
-  location_t loc = EXPR_LOCATION (expr);
-  new_mod_list = alloc_stmt_list ();
+  /* If the return expression contains array notations, then flag it as
+     error.  */
+  if (rank >= 1)
+    {
+      error_at (loc, "array notation expression cannot be used as a return "
+		"value");
+      return error_mark_node;
+    }
+  
+  new_mod_list = push_stmt_list ();
   retval_expr = TREE_OPERAND (expr, 0);
-  new_var = build_decl (loc, VAR_DECL, NULL_TREE, TREE_TYPE (retval_expr));
+  new_var = create_temporary_var (TREE_TYPE (retval_expr));
+  add_decl_expr (new_var);
   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),
+				      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);
+  add_stmt (new_mod);
+  add_stmt (expr);
+  new_mod_list = pop_stmt_list (new_mod_list);
   return new_mod_list;
 }
 
@@ -1290,19 +1243,21 @@ expand_array_notation_exprs (tree 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:      
+    case FOR_STMT:
+      if (contains_array_notation_expr (FOR_COND (t)))
+	{
+	  error_at (EXPR_LOCATION (FOR_COND (t)),
+		    "array notation cannot be used in a condition for "
+		    "a for-loop");
+	  return error_mark_node;
+	}
       /* 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));
+	{ 
+	  FOR_BODY (t) = expand_array_notation_exprs (FOR_BODY (t));
+	  FOR_EXPR (t) = expand_array_notation_exprs (FOR_EXPR (t));
+	}
       else
 	t = expand_array_notation_exprs (t);
       return t;
@@ -1322,44 +1277,39 @@ expand_array_notation_exprs (tree t)
 	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 (contains_array_notation_expr (SWITCH_STMT_COND (t)))
 	{
-	  if (SWITCH_STMT_BODY (t))
-	    SWITCH_STMT_BODY (t) =
-	      expand_array_notation_exprs (SWITCH_STMT_BODY (t));
+	  error_at (EXPR_LOCATION (SWITCH_STMT_COND (t)),
+		    "array notation cannot be used as a condition for "
+		    "switch statement");
+	  return error_mark_node;
 	}
-      else
-	t = expand_array_notation_exprs (t);
+      if (SWITCH_STMT_BODY (t))
+	SWITCH_STMT_BODY (t) =
+	  expand_array_notation_exprs (SWITCH_STMT_BODY (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 (contains_array_notation_expr (WHILE_COND (t)))
 	{
-	  if (WHILE_BODY (t))
-	    WHILE_BODY (t) = expand_array_notation_exprs (WHILE_BODY (t));
+	  if (EXPR_LOCATION (WHILE_COND (t)) != UNKNOWN_LOCATION)
+	    loc = EXPR_LOCATION (WHILE_COND (t));
+	  error_at (loc, "array notation cannot be used as a condition for "
+		    "while statement");
+	  return error_mark_node;
 	}
-      else
-	t = expand_array_notation_exprs (t);
+      if (WHILE_BODY (t))
+	WHILE_BODY (t) = expand_array_notation_exprs (WHILE_BODY (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));
+      if (contains_array_notation_expr (DO_COND (t)))
+	{
+	  error_at (EXPR_LOCATION (DO_COND (t)),
+		    "array notation cannot be used as a condition for a "
+		    "do-while statement");
+	  return error_mark_node;
 	}
-      else
-	t = expand_array_notation_exprs (t);
+      if (DO_BODY (t))
+	DO_BODY (t) = expand_array_notation_exprs (DO_BODY (t));
       return t;
     default:
       if (is_expr)
@@ -1380,57 +1330,64 @@ expand_array_notation_exprs (tree 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.  */
+/* Given the base of an array (ARRAY), the START (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, 
+   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)
+build_array_notation_ref (location_t loc, tree array, tree start, 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)
+  /* If we enter the then-case of the if-statement below, we have hit a case 
+     like this: ARRAY [:].  */
+  if (!start && !length)
     {
-      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;
+      if (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == POINTER_TYPE)
+	{
+	  error_at (loc, "start-index and length fields necessary for "
+		    "using array notation in pointers or records");
+	  return error_mark_node;
+	}
+      tree domain = TYPE_DOMAIN (type);
+      if (!domain)
+	{
+	  error_at (loc, "start-index and length fields necessary for "
+		    "using array notation with array of unknown bound");
+	  return error_mark_node;
+	}
+      start = cp_fold_convert (ptrdiff_type_node, TYPE_MINVAL (domain));
+      length = size_binop (PLUS_EXPR, TYPE_MAXVAL (domain), size_one_node);
+      length = cp_fold_convert (ptrdiff_type_node, length);
     }
+    
+  if (!stride) 
+    stride = build_one_cst (ptrdiff_type_node);
+  
+  /* When dealing with templates, triplet type-checking will be done in pt.c 
+     after type substitution.  */
+  if (processing_template_decl 
+      && (type_dependent_expression_p (array) 
+	  || type_dependent_expression_p (length) 
+	  || type_dependent_expression_p (start) 
+	  || type_dependent_expression_p (stride))) 
+    array_ntn_expr = build_min_nt_loc (loc, ARRAY_NOTATION_REF, array, start, 
+				       length, stride, NULL_TREE);
+  else 
+    { 
+      if (!cilkplus_an_triplet_types_ok_p (loc, start, length, stride, type))
+	return error_mark_node;
+      array_ntn_expr = build4 (ARRAY_NOTATION_REF, NULL_TREE, array, start, 
+			       length, stride);
+    }
+  if (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;
@@ -1462,20 +1419,9 @@ cilkplus_an_triplet_types_ok_p (location_t loc, tree start_index, tree length,
     }
   if (!TREE_CODE (type) == FUNCTION_TYPE)
     {
-      error_at (loc, "array notations cannot be used with function type");
+      error_at (loc, "array notation 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))
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 38ef878..590d857 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -1207,6 +1207,12 @@ cp_genericize (tree fndecl)
   if (DECL_CLONED_FUNCTION_P (fndecl))
     return;
 
+  /* Expand all the array notations here.  */
+  if (flag_enable_cilkplus 
+      && contains_array_notation_expr (DECL_SAVED_TREE (fndecl)))
+    DECL_SAVED_TREE (fndecl) = 
+      expand_array_notation_exprs (DECL_SAVED_TREE (fndecl));
+
   /* We do want to see every occurrence of the parms, so we can't just use
      walk_tree's hash functionality.  */
   cp_genericize_tree (&DECL_SAVED_TREE (fndecl));
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 00ee450..a3438a8 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4974,6 +4974,7 @@ extern bool pragma_java_exceptions;
 
 /* in call.c */
 extern bool check_dtor_name			(tree, tree);
+bool magic_varargs_p                            (tree);
 
 extern tree build_conditional_expr		(location_t, tree, tree, tree, 
                                                  tsubst_flags_t);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index ec8ad46..67f5a17 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -6060,41 +6060,32 @@ 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.  */
+/* This function parses Cilk Plus array notations.  If a normal array expr. is
+   parsed then the array index is passed back to the caller through *INIT_INDEX 
+   and the function returns a NULL_TREE.  If array notation expr. is parsed, 
+   then *INIT_INDEX is ignored by the caller and the function returns 
+   a 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,
+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;
+  tree length_index, stride = NULL_TREE, value_tree, array_type;
+  bool saved_colon_corrects = 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;
-    }
+
+  array_type = TREE_TYPE (array_value);
+
+  parser->colon_corrects_to_scope_p = false;
   token = cp_lexer_peek_token (parser->lexer);
+  
   if (!token)
     {
       cp_parser_error (parser, "expected %<:%> or numeral");
@@ -6102,125 +6093,71 @@ cp_parser_array_notation (location_t loc, cp_parser *parser, tree init_index,
     }
   else if (token->type == CPP_COLON)
     {
-      if (!init_index)
+      /* Consume the ':'.  */
+      cp_lexer_consume_token (parser->lexer);
+      
+      /* If we are here, then we have a case like this A[:].  */
+      if (cp_lexer_peek_token (parser->lexer)->type != CPP_CLOSE_SQUARE)
 	{
-	  /* If we are here, then we have a case like this A[:].  */
-	  cp_lexer_consume_token (parser->lexer);
+	  cp_parser_error (parser, "expected %<]%>");
+	  cp_parser_skip_to_end_of_statement (parser);
+	  return error_mark_node;
+	}
+      *init_index = NULL_TREE;
+      stride = NULL_TREE;
+      length_index = NULL_TREE;
+    }
+  else
+    {
+      /* If we are here, then there are three valid possibilities:
+	 1. ARRAY [ EXP ]
+	 2. ARRAY [ EXP : EXP ]
+	 3. ARRAY [ EXP : EXP : EXP ]  */
 
-	  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);
+      *init_index = cp_parser_expression (parser, false, NULL);
+	
+      if (cp_lexer_peek_token (parser->lexer)->type != CPP_COLON)
+	{  
+	  /* This indicates that we have a normal array expression.  */
+	  parser->colon_corrects_to_scope_p = saved_colon_corrects;
+	  return NULL_TREE;
+	}
+      
+      /* Consume the ':'.  */
+      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)
+      if (!*init_index || *init_index == error_mark_node)
+	cp_parser_skip_to_end_of_statement (parser);
+
+      length_index = cp_parser_expression (parser, false, NULL);
+      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);
+	  stride = cp_parser_expression (parser, false, NULL);
+	  if (stride == error_mark_node)
 	    {
-	      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);
-		}
+	      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)
+  parser->colon_corrects_to_scope_p = saved_colon_corrects;
+
+  if (*init_index == error_mark_node || length_index == error_mark_node
+      || stride == error_mark_node)
     {
       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);
+
+  value_tree = build_array_notation_ref (loc, array_value, *init_index, 
+					 length_index, stride, array_type);
   return value_tree;
 }
 
@@ -6239,84 +6176,84 @@ cp_parser_postfix_open_square_expression (cp_parser *parser,
 					  bool for_offsetof,
 					  bool decltype_p)
 {
-  tree index;
+  tree index = NULL_TREE;
   location_t loc = cp_lexer_peek_token (parser->lexer)->location;
 
   /* Consume the `[' token.  */
   cp_lexer_consume_token (parser->lexer);
 
-  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);
+  if (flag_enable_cilkplus)
+    {
+      bool saved_colon_corrects = parser->colon_corrects_to_scope_p;
+      parser->colon_corrects_to_scope_p = false;
+      if (cp_lexer_peek_token (parser->lexer)->type == CPP_COLON)
+	{
+	  /* If we are here, then we have something like this: ARRAY[:]  */
+	  tree an_exp = cp_parser_array_notation (loc, parser, &index,
+						  postfix_expression);
+	  parser->colon_corrects_to_scope_p = saved_colon_corrects;
+	  return an_exp;
+	}
+    }
+  /* 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
     {
-      /* 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
+      if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
 	{
-	  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);
+	  bool saved_colon_corrects = parser->colon_corrects_to_scope_p;
+	  parser->colon_corrects_to_scope_p = false;
+	  if (flag_enable_cilkplus
+	      && cp_lexer_peek_token (parser->lexer)->type == CPP_COLON)
 	    {
-	      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;
-		}
+	      error_at (cp_lexer_peek_token (parser->lexer)->location,
+			"braced list index is not allowed with array "
+			"notation");
+	      cp_parser_skip_to_end_of_statement (parser);
+	      return 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;
+	  parser->colon_corrects_to_scope_p = saved_colon_corrects;
 	}
-      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
+      else if (flag_enable_cilkplus)
 	{
-  	  /* 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);
-
-	  /* 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;
+	  /* Here are have these two options:
+	     ARRAY[EXP : EXP]        - Array notation expr with default
+	     stride of 1.
+	     ARRAY[EXP : EXP : EXP] - Array Notation with user-defined
+	     stride.  */
+	  tree an_exp = cp_parser_array_notation (loc, parser, &index, 
+						  postfix_expression);
+	  if (an_exp)
+	    return an_exp;
 	}
+      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);
+
+  /* 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;
 }
 
@@ -9551,8 +9488,6 @@ 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;
 }
 
@@ -9745,14 +9680,6 @@ 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;
@@ -10310,12 +10237,6 @@ 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;
 
@@ -10342,15 +10263,6 @@ 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;
 
@@ -10369,17 +10281,8 @@ cp_parser_iteration_statement (cp_parser* parser)
 	cp_parser_already_scoped_statement (parser);
 	parser->in_statement = in_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);
+	/* We're done with the for-statement.  */
+	finish_for_stmt (statement);
       }
       break;
 
@@ -16952,54 +16855,30 @@ cp_parser_direct_declarator (cp_parser* parser,
 	  if (token->type != CPP_CLOSE_SQUARE)
 	    {
 	      bool non_constant_p;
-
-	      if (flag_enable_cilkplus
-		  && cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+	      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;
-		  error_at (cp_lexer_peek_token (parser->lexer)->location,
-			    "array notations cannot be used in declaration");
-		  cp_lexer_consume_token (parser->lexer);
 		}
-	      else
+	      else if (processing_template_decl)
 		{
-		  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; 
-		    }
+		  /* Remember this wasn't a constant-expression.  */
+		  bounds = build_nop (TREE_TYPE (bounds), bounds);
+		  TREE_SIDE_EFFECTS (bounds) = 1;
 		}
 	    }
 	  else
@@ -18370,11 +18249,6 @@ 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);
 
@@ -22354,12 +22228,6 @@ 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));
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 667e37f..5dafdcd 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -15739,9 +15739,6 @@ 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;
@@ -19143,11 +19140,6 @@ 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);
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 0a460a4..87c1560 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -779,22 +779,6 @@ 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 ())
@@ -8089,7 +8073,6 @@ 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);
@@ -8901,7 +8884,6 @@ 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:
@@ -8912,6 +8894,9 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
 	  return false;
       return true;
 
+    case ARRAY_NOTATION_REF:
+      return false;
+
     case FMA_EXPR:
     case VEC_PERM_EXPR:
      for (i = 0; i < 3; ++i)
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 5b321ce..11592b4 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -3493,10 +3493,6 @@ cp_build_function_call_vec (tree function, vec<tree, va_gc> **params,
       params = &allocated;
     }
 
-  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)
@@ -3660,8 +3656,7 @@ convert_arguments (tree typelist, vec<tree, va_gc> **values, tree fndecl,
 	}
       else
 	{
-	  if (fndecl && DECL_BUILT_IN (fndecl)
-	      && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CONSTANT_P)
+	  if (fndecl && magic_varargs_p (fndecl))
 	    /* Don't do ellipsis conversion for __built_in_constant_p
 	       as this will result in spurious errors for non-trivial
 	       types.  */
@@ -3956,15 +3951,8 @@ cp_build_binary_op (location_t location,
 	}
     }
 
-  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);
+  type0 = TREE_TYPE (op0); 
+  type1 = TREE_TYPE (op1);
 
   /* The expression codes of the data types of the arguments tell us
      whether the arguments are integers, floating, pointers, etc.  */
@@ -5167,13 +5155,6 @@ 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)))
     {
@@ -7852,13 +7833,6 @@ 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);
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/decl-ptr-colon.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/decl-ptr-colon.c
index 68c8859..4b54f4d 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/decl-ptr-colon.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/decl-ptr-colon.c
@@ -1,3 +1,4 @@
+/* { dg-do compile { target c } } */
 /* { dg-options "-fcilkplus" } */
 
 int main(void)
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/dimensionless-arrays.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/dimensionless-arrays.c
index 69aaa52..690e89a 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/dimensionless-arrays.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/dimensionless-arrays.c
@@ -5,6 +5,6 @@ extern int *b;
 
 void foo()
 {
-  a[:] = 5;	// { dg-error "start-index and length fields necessary for using array notations in dimensionless arrays" }
-  b[:] = 5;    // { dg-error "start-index and length fields necessary for using array notations in pointers" }
+  a[:] = 5;	// { dg-error "start-index and length fields necessary for using array notation" }
+  b[:] = 5;    // { dg-error "start-index and length fields necessary for using" }
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/fn_ptr.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/fn_ptr.c
index 024a158..fa6d900 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/fn_ptr.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/fn_ptr.c
@@ -1,3 +1,4 @@
+/* { dg-do compile } */
 /* { dg-options "-fcilkplus" } */
 
 typedef int (*foo)(int);
@@ -10,11 +11,11 @@ int main(void)
   foo ***func_array_ptr;
   int argc = 5;
 
-  array[:] =  func_array[:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
-  func_array[0:5](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
-  func_array2[0:5][:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
-  array2[0:5][:] = func_array2[0:5][:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
-  func_array_ptr[0:5][0:4][0:argc:2](argc); /* { dg-error "array notations cannot be used with function pointer arrays" } */
+  array[:] =  func_array[:](10); 
+  func_array[0:5](10); 
+  func_array2[0:5][:](10);
+  array2[0:5][:] = func_array2[0:5][:](10);
+  func_array_ptr[0:5][0:4][0:argc:2](argc); 
 
   return 0;
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
index 14421d9..814786b 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
@@ -6,7 +6,7 @@ int main (void)
   int array[10], array2[10][10];
   int x, ii, jj ;
 
-  switch (array[:]) {  /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  switch (array[:]) {  /* { dg-error "cannot be used as a condition for switch statement" } */
   case 1:
     x = 5;
     break;
@@ -17,7 +17,7 @@ int main (void)
     x = 9;
   }
 
-  switch (array2[:][:]) { /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  switch (array2[:][:]) { /* { dg-error "cannot be used as a condition for switch statement" } */
   case 1:
     x = 5;
     break;
@@ -28,7 +28,7 @@ int main (void)
     x = 9;
   }
 
-  switch (array[:] + x) { /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  switch (array[:] + x) { /* { dg-error "cannot be used as a condition for switch statement" } */
   case 1:
     x = 5;
     break;
@@ -39,7 +39,7 @@ int main (void)
     x = 9;
   }
   
-  switch (array2[:][1:x:4] + x) { /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  switch (array2[:][1:x:4] + x) { /* { dg-error "cannot be used as a condition for switch statement" } */
   case 1:
     x = 5;
     break;
@@ -50,36 +50,36 @@ int main (void)
     x = 9;
   }
 
-  for (ii = 0; ii < array[:]; ii++) /* { dg-error "array notations cannot be used in a condition for a for-loop" } */
+  for (ii = 0; ii < array[:]; ii++) /* { dg-error "cannot be used in a condition for a for-loop" } */
     {
       x = 2;
     }
 
-  for (ii = 0; ii < array2[:][:]; ii++) /* { dg-error "array notations cannot be used in a condition for a for-loop" } */
+  for (ii = 0; ii < array2[:][:]; ii++) /* { dg-error "cannot be used in a condition for a for-loop" } */
     {
       x = 3;
     }
 
-  for (; array2[:][:] < 2;) /* { dg-error "array notations cannot be used in a condition for a for-loop" } */
+  for (; array2[:][:] < 2;) /* { dg-error "cannot be used in a condition for a for-loop" } */
     x = 4;
 
 
-  while (array2[:][:]) /* { dg-error "array notations cannot be used as a condition for while statement" } */
+  while (array2[:][:]) /* { dg-error "cannot be used as a condition for while statement" } */
     x = 3;
 
-  while (array[1:1:1]) /* { dg-error "array notations cannot be used as a condition for while statement" } */
+  while (array[1:1:1]) /* { dg-error "cannot be used as a condition for while statement" } */
     x = 1;
 
-  while (ii != array2[1:x:3][1:2:1]) /* { dg-error "array notations cannot be used as a condition for while statement"  } */
+  while (ii != array2[1:x:3][1:2:1]) /* { dg-error "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" "" { target c } } */
+  do { /* { dg-error "cannot be used as a condition for a do-while statement" "" { target c } } */
     x = 3;
-  } while (ii != array2[:][:]); /* { dg-error "array notations cannot be used as a condition for a do-while statement" "" { target c++ } } */
+  } while (ii != array2[:][:]); /* { dg-error "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" "" { target c } } */
+  do {  /* { dg-error "cannot be used as a condition for a do-while statement" "" { target c } } */
     x = 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++ } } */
+  } while (ii != (x + array2[:][1:x:2]) + 2); /* { dg-error "cannot be used as a condition for a do-while statement" "" { target c++ } } */
   
   do { 
     x += 3;
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/rank_mismatch.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/rank_mismatch.c
index b5e37ce..eb3c1f1 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/rank_mismatch.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/rank_mismatch.c
@@ -10,6 +10,7 @@ int main (void)
   int array[10][10], array2[10];
 
   array[:][:] = array[:]; /* { dg-error "rank mismatch between" } */
+  /* { dg-error "invalid conversion" "" { target c++ } 12 } */
 
   x = array2[:]; /* { dg-error "cannot be scalar when" } */
 

[-- Attachment #3: CL.txt --]
[-- Type: text/plain, Size: 5853 bytes --]

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

        * builtins.def: Fixed the function type of CILKPLUS_BUILTIN.

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

        * c-parser.c (c_parser_array_notation): Removed rejection of array
        notations in an array of function pointers.

gcc/c-family/ChangeLog
2013-06-26  Balaji V. Iyer  <balaji.v.iyer@intel.com>

        * array-notation-common.c (length_mismatch_in_expr_p): Collapsed two
        if-statements and compared the trees directly using tree_int_cst_equal.
        (find_rank): Checked for array notations in function name to handle
        array notations in function pointers.
        (extract_array_notation_exprs): Likewise.
        (replace_array_notations): Likewise.
        (cilkplus_extract_an_triplets): Replaced safe_push with
        safe_grow_cleared.  Also removed an unnecessary check to see if the
        node is of type ARRAY_NOTATION_REF.
        (fix_sec_implicit_args): Removed an unnecessary check for ADDR_EXPR.
        Also switched two if-statements to remove an unnecessary comparison.


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

        * parser.c (cp_parser_array_notation): Removed rejection array notation
        of type function pointers. Added handling of array expressions when
        Cilk Plus is enabled.  Took out type-checking.
        (cp_parser_postfix_open_square_expression): Moved normal array expr.
        parsing into cp_parser_array_notation when cilkplus is enabled.
        (cp_parser_compound_statement): Removed expansion of array notations.
        (cp_parser_ctor_initializer_opt_and_function_body): Likewise.
        (cp_parser_function_definition_after_declarator): Likewise.
        (cp_parser_selection_statement): Removed error reporting.
        (cp_parser_iteration_statement): Likewise.
        (cp_parser_direct_declarator): Removed error checking/reporting if
        array notations are used in the declarator.
        * pt.c (instantiate_decl): Likewise.
        (type_unification_real): Removed a check for ARRAY_NOTATION_REF.
        (cxx_eval_constant_expression): Removed ARRAY_NOTATION_REF case.
        (potential_constant_expression_1): Returned false for ARRAY_NOTATION_REF
        case.
        * cp-gimplify.c (cp_genericize): Added expansion of array notation
        expressions here.
        * cp-array-notation.c (make_triplet_val_inv): Removed loc and cry 
        parameters.  Replaced build_decls with get_temp_regvar with type as
        ptrdiff.
        (create_array_refs): Made the type-casting to ptrdiff_type.
        (replace_invariant_var): Replaced build_decl and build_min_nt_loc with
        get_temp_regvar.
        (expand_an_in_modify_expr): Ditto.  Replaced body of redundant else with
        gcc_unreachable.  Removed few unwanted checks.  Made induction variable
        type as ptrdiff_type.  Removed loc and complain arguments passed into
        make_triplet_val_inv.  Replaced all modify expression's code from NOP
        EXPR to INIT EXPR.  Replaced all forceful appending into stmt. list
        with the non-forceful one.  Replaced some integer conversion and
        equality-checking to using tree_int_cst_equal.
        (expand_sec_reduce_builtin): All changes mentioned in above function
        expand_an_in_modify_expr.  Made the new variable type of
        SEC_REDUCE_ANY/ALL_{NON}ZERO intrinsic functions as bool.
        (expand_array_notation_exprs): Removed SWITCH_EXPR case.  Moved all
        the error reporting from parser to this function.  Removed unwanted
        statements and checks from SWITCH_STMT, WHILE_STMT, and DO_STMT cases.
        (cilkplus_an_triplet_types_ok_p): Removed rejection of array notation
        in function pointers.
        (cp_expand_cond_array_notations): Added a new if statements to check
        if condition has a zero rank.  If so, then just return.
        (expand_return_expr): Added a check for return expressions with a rank.
        Replaced get_tmp_regvar with a create_temporary_var.
        (build_array_notation_ref): Simplified and removed unwanted if-stmts.
        Moved common code outside if-statements.  Moved type-checking from
        parser to here.
        * semantics.c (finish_return_stmt): Removed a check for return exprs.
        with a rank.
        * call.c (convert_like_real): Removed a check for array notation
        expression in a function.
        (build_over_call): Likewise.
        (magic_varargs_p): Added a check for builtin array notation function.
        Made this function non-static and removed its prototype.
        * cp-tree.h (magic_varargs_p): New prototype.
        * typeck.c (cp_build_function_call_vec): Removed automatic setting of
        nargs to the param->length when builtin reduction function is used.
        (convert_arguments): Replaced check for a constant_p function with
        margic_varargs_p function call.
        (cp_build_binary_op): Removed calling of the function
        find_correct_array_notation_type.
        (cp_build_addr_expr_1): Removed an unwanted if-statement.
        (convert_for_assignment): Removed automatic return of rhs when array
        notation builtin function is used.

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

        * c-c++-common/cilk-plus/AN/decl-ptr-colon.c (main): Made this testcase
        c specific.
        * c-c++-common/cilk-plus/AN/decl-ptr-colon.c (main): Changed dg-error
        strings to match the fixed error messages.
        * c-c++-common/cilk-plus/AN/misc.c (main): Likewise.
        * c-c++-common/cilk-plus/AN/rank_mismatch.c (main): Added a new error
        message check.


^ permalink raw reply	[flat|nested] 40+ messages in thread

* RE: [PATCH] Cilk Plus Array Notation for C++
  2013-06-27 15:54                                       ` Iyer, Balaji V
@ 2013-06-27 18:39                                         ` Iyer, Balaji V
  2013-06-27 23:05                                           ` Jason Merrill
  0 siblings, 1 reply; 40+ messages in thread
From: Iyer, Balaji V @ 2013-06-27 18:39 UTC (permalink / raw)
  To: Jason Merrill, Richard Henderson; +Cc: Aldy Hernandez, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 740 bytes --]

> > > Hmm, I seem to have been unclear.  I was expecting that the call to
> > > cp_parser_array_notation could come after the braced list case, so
> > > we don't need to duplicate the offsetof or braced list code inside
> > > cp_parser_array_notation.
> > >
> > > And then if you'd like we could check for ':' before the ']' and
> > > give a helpful diagnostic.
> >
> > I Think I have fixed this as you requested.
> >

Hi Jason,
	I looked through the patch again. I was able to get rid of the first if-statement in cp_parser_postfix_open_square_expression function. I think now it looks exactly as you requested. 

Here is the fixed patch again. I am very sorry for sending so much regressions.

Thanks,

Balaji V. Iyer.

[-- Attachment #2: diff.txt --]
[-- Type: text/plain, Size: 81103 bytes --]

diff --git a/gcc/builtins.def b/gcc/builtins.def
index 91879a6..9b55b1f 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -158,9 +158,9 @@ along with GCC; see the file COPYING3.  If not see
 	       (flag_asan || flag_tsan))
 
 #undef DEF_CILKPLUS_BUILTIN
-#define DEF_CILKPLUS_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
-  DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
-  	       false, false, true, ATTRS, false, flag_enable_cilkplus)
+#define DEF_CILKPLUS_BUILTIN(ENUM, NAME, TYPE, ATTRS)  \
+  DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, BT_FN_INT_VAR, BT_LAST, \
+  	       false, false, false, ATTRS, false, flag_enable_cilkplus) 
 
 /* Define an attribute list for math functions that are normally
    "impure" because some of them may write into global memory for
diff --git a/gcc/c-family/array-notation-common.c b/gcc/c-family/array-notation-common.c
index 8eab89b..5e17009 100644
--- a/gcc/c-family/array-notation-common.c
+++ b/gcc/c-family/array-notation-common.c
@@ -101,15 +101,11 @@ length_mismatch_in_expr_p (location_t loc, vec<vec<an_parts> >list)
 	      /* 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;
-		    }
+	      if (TREE_CODE (list[ii][jj].length) == INTEGER_CST
+		  && !tree_int_cst_equal (list[ii][jj].length, length))
+		{ 
+		  error_at (loc, "length mismatch in expression"); 
+		  return true;
 		}
 	    }
 	  else
@@ -271,6 +267,8 @@ find_rank (location_t loc, tree orig_expr, tree expr, bool ignore_builtin_fn,
 		/* If it is a built-in function, then we know it returns a 
 		   scalar.  */
 		return true;
+	  if (!find_rank (loc, orig_expr, func_name, ignore_builtin_fn, rank))
+	    return false;
 	  FOR_EACH_CALL_EXPR_ARG (arg, iter, expr)
 	    {
 	      if (!find_rank (loc, orig_expr, arg, ignore_builtin_fn, rank))
@@ -358,6 +356,9 @@ extract_array_notation_exprs (tree node, bool ignore_builtin_fn,
 	  vec_safe_push (*array_list, node);
 	  return;
 	}
+      /* This will extract array notations in function pointers.  */
+      extract_array_notation_exprs (CALL_EXPR_FN (node), ignore_builtin_fn,
+				    array_list);
       FOR_EACH_CALL_EXPR_ARG (arg, iter, node)
 	extract_array_notation_exprs (arg, ignore_builtin_fn, array_list);
     } 
@@ -433,6 +434,9 @@ replace_array_notations (tree *orig, bool ignore_builtin_fn,
 	      }
 	  return;
 	}
+      /* Fixes array notations in array notations in function pointers.  */
+      replace_array_notations (&CALL_EXPR_FN (*orig), ignore_builtin_fn, list,
+			       array_operand);
       ii = 0;
       FOR_EACH_CALL_EXPR_ARG (arg, iter, *orig)
 	{
@@ -575,53 +579,49 @@ 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++)
+
+  if (rank > 0)
+    for (size_t ii = 0; ii < size; ii++)
       {
-	(*node)[ii].safe_push (init);
-	array_exprs[ii].safe_push (NULL_TREE);
+	(*node)[ii].safe_grow_cleared (rank);
+	array_exprs[ii].safe_grow_cleared (rank);
       }
-
   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 ();	
+	{
+	  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
+	    break;
+	}
     }
     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));
-	    }
+	  {
+	    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
@@ -637,16 +637,15 @@ fix_sec_implicit_args (location_t loc, vec <tree, va_gc> *list,
   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)
+	if (idx < 0)
 	  /* In this case, the returning function would have emitted an
 	     error thus it is not necessary to do so again.  */
 	  return NULL;
+	else if (idx < (int) rank)
+	  vec_safe_push (array_operand, an_loop_info[idx].var);
 	else
 	  {
 	    error_at (loc, "__sec_implicit_index argument %d must be "
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index d6a500e..c7846ce 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -11053,24 +11053,6 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
 	      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
 	      return error_mark_node;
 	    }
-	  if (TREE_CODE (array_type) == ARRAY_TYPE)
-	    {
-	      tree subtype = TREE_TYPE (array_type);
-	      while (subtype && TREE_CODE (subtype) == POINTER_TYPE)
-		{
-		  /* Now this could be a function pointer.  Find them and
-		     give out an error.  */
-		  subtype = TREE_TYPE (subtype);
-		  if (subtype && TREE_CODE (subtype) == FUNCTION_TYPE)
-		    {
-		      error_at (loc, "array notations cannot be used with "
-				"function pointer arrays");
-		      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
-						 NULL);
-		      return error_mark_node;
-		    }
-		}
-	    }
 	  array_type_domain = TYPE_DOMAIN (array_type);
 
 	  if (!array_type_domain)
@@ -11114,27 +11096,6 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
 	      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
 	      return error_mark_node;
 	    }
-	  if (TREE_CODE (array_type) == ARRAY_TYPE
-	      || TREE_CODE (array_type) == POINTER_TYPE)
-	    {
-	      tree subtype = TREE_TYPE (array_type);
-	      while (subtype
-		     && (TREE_CODE (subtype) == POINTER_TYPE
-			 || TREE_CODE (subtype) == ARRAY_TYPE))
-		{
-		  /* Now this could be a function pointer.  Find them and
-		     give out an error.  */
-		  subtype = TREE_TYPE (subtype);
-		  if (subtype && TREE_CODE (subtype) == FUNCTION_TYPE)
-		    {
-		      error_at (loc, "array notations cannot be used with "
-				"function pointer arrays");
-		      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
-						 NULL);
-		      return error_mark_node;
-		    }
-		}
-	    }
 	  c_parser_consume_token (parser); /* consume the ':' */
 	  end_index = c_parser_expression (parser).value;
 	  if (!end_index || end_index == error_mark_node)
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 6817bfc..425ef9b 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -216,7 +216,6 @@ static void add_candidates (tree, tree, const vec<tree, va_gc> *, tree, tree,
 			    bool, tree, tree, int, struct z_candidate **,
 			    tsubst_flags_t);
 static conversion *merge_conversion_sequences (conversion *, conversion *);
-static bool magic_varargs_p (tree);
 static tree build_temp (tree, tree, int, diagnostic_t *, tsubst_flags_t);
 
 /* Returns nonzero iff the destructor name specified in NAME matches BASETYPE.
@@ -5857,16 +5856,9 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
 	  else if (t->kind == ck_identity)
 	    break;
 	}
-
-      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)
+       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);
 
@@ -6515,9 +6507,12 @@ convert_for_arg_passing (tree type, tree val, tsubst_flags_t complain)
    which no conversions at all should be done.  This is true for some
    builtins which don't act like normal functions.  */
 
-static bool
+bool
 magic_varargs_p (tree fn)
 {
+  if (flag_enable_cilkplus && is_cilkplus_reduce_builtin (fn) != BUILT_IN_NONE)
+    return true;
+
   if (DECL_BUILT_IN (fn))
     switch (DECL_FUNCTION_CODE (fn))
       {
@@ -6895,21 +6890,13 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
 		       "  (you can disable this with -fno-deduce-init-list)");
 	    }
 	}
+      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
index 491da0f..b4fada4 100644
--- a/gcc/cp/cp-array-notation.c
+++ b/gcc/cp/cp-array-notation.c
@@ -59,7 +59,6 @@
 #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.  */
@@ -82,17 +81,12 @@ create_an_loop (tree init, tree cond, tree incr, tree body)
    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)
+make_triplet_val_inv (tree *value)
 {
-  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;
-    }
+    *value = get_temp_regvar (ptrdiff_type_node, *value);
 }
 
 /* Returns a vector of size RANK that contains an ARRAY_REF.  This vector is
@@ -140,9 +134,9 @@ create_array_refs (location_t loc, vec<vec<an_parts> > an_info,
 		   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);
+		st = build_c_cast (loc, ptrdiff_type_node, start);
+		str = build_c_cast (loc, ptrdiff_type_node, stride);
+		v = build_c_cast (loc, ptrdiff_type_node, var);
 	      }
 	    else
 	      {
@@ -192,7 +186,7 @@ replace_invariant_exprs (tree *node)
 {
   size_t ix = 0;
   tree node_list = NULL_TREE;
-  tree t = NULL_TREE, new_var = NULL_TREE, new_node; 
+  tree t = NULL_TREE, new_var = NULL_TREE;
   struct inv_list data;
 
   data.list_values = NULL;
@@ -204,17 +198,11 @@ replace_invariant_exprs (tree *node)
     {
       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);
+	{ 
+	  /* Sometimes, it type-casts certain functions to void. Unwrap it.  */
+	  if (VOID_TYPE_P (TREE_TYPE (t)) && TREE_CODE (t) == CONVERT_EXPR)
+	    t = TREE_OPERAND (t, 0);
+	  new_var = get_temp_regvar (TREE_TYPE (t), t); 
 	  vec_safe_push (data.replacement, new_var);
 	}
       cp_walk_tree (node, replace_inv_trees, (void *) &data, NULL);
@@ -235,7 +223,6 @@ 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 ();
@@ -305,7 +292,7 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
     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;
+      new_var_type = boolean_type_node;
       break;
     case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
     case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
@@ -334,24 +321,30 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
     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);
+	make_triplet_val_inv (&ARRAY_NOTATION_START (anode));
+	make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (anode));
+	make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (anode));
       }
   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);
+      tree typ = ptrdiff_type_node;
+
+      /* In this place, we are using get_temp_regvar instead of 
+	 create_temporary_var if an_type is SEC_REDUCE_MAX/MIN_IND because
+	 the array_ind_value depends on this value being initalized to 0.  */
+      if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
+	  || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND) 
+	an_loop_info[ii].var = get_temp_regvar (typ, build_zero_cst (typ));
+      else
+	{
+	  an_loop_info[ii].var = create_temporary_var (typ);
+	  add_decl_expr (an_loop_info[ii].var);
+	}
+      an_loop_info[ii].ind_init = 
+	build_x_modify_expr (location, an_loop_info[ii].var, INIT_EXPR,
+			     build_zero_cst (typ), 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);
@@ -360,26 +353,9 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
     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);
-    }
+      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND) 
+    array_ind_value = get_temp_regvar (TREE_TYPE (func_parm), func_parm);
 
   array_op0 = (*array_operand)[0];
   switch (an_type)
@@ -394,35 +370,36 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
       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;
+      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;
+      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;
+      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;
+      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;
+      code = (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND ? LE_EXPR
+	: GE_EXPR);
       init = an_loop_info[0].var;
+      break;
     case BUILT_IN_CILKPLUS_SEC_REDUCE:
       init = identity_value;
       break;
@@ -433,9 +410,11 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
       gcc_unreachable ();
     }
 
-  if (init)
-    new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR, init,
-					tf_warning_or_error);
+  if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
+    *new_var = get_temp_regvar (new_var_type, init);
+  else
+    *new_var = NULL_TREE;
+
   switch (an_type)
     {
     case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD:
@@ -470,8 +449,6 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
       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,
@@ -521,21 +498,8 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
     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);
+  append_to_statement_list (an_init, &loop_with_init);
   body = new_expr;
 
   for (ii = 0; ii < rank; ii++)
@@ -545,7 +509,7 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
 		      an_loop_info[ii].incr, body);
       body = pop_stmt_list (new_loop);
     }
-  append_to_statement_list_force (body, &loop_with_init);
+  append_to_statement_list (body, &loop_with_init);
 
   an_info.release ();
   an_loop_info.release ();
@@ -634,10 +598,7 @@ expand_an_in_modify_expr (location_t location, tree lhs,
 	  return an_init;
 	}
       else
-	{
-	  pop_stmt_list (an_init);
-	  return NULL_TREE;
-	}
+	gcc_unreachable ();
     }
 
   /* If for some reason location is not set, then find if LHS or RHS has
@@ -659,8 +620,6 @@ expand_an_in_modify_expr (location_t location, tree lhs,
     
   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;
     }
@@ -675,17 +634,17 @@ expand_an_in_modify_expr (location_t location, tree lhs,
   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);
+      make_triplet_val_inv (&ARRAY_NOTATION_START (anode));
+      make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (anode));
+      make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (anode));
     }
   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);
+	make_triplet_val_inv (&ARRAY_NOTATION_START (aa));
+	make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (aa));
+	make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (aa));
       }
   lhs_an_loop_info.safe_grow_cleared (lhs_rank);
   
@@ -705,31 +664,29 @@ expand_an_in_modify_expr (location_t location, tree lhs,
       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;
+  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;
-	}
+      && TREE_CODE (rhs_len) == INTEGER_CST 
+      && !tree_int_cst_equal (rhs_len, lhs_len))
+    { 
+      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);
+   for (ii = 0; ii < lhs_rank; ii++) 
+     {
+       tree typ = ptrdiff_type_node; 
+       lhs_an_loop_info[ii].var = create_temporary_var (typ);
+       add_decl_expr (lhs_an_loop_info[ii].var);
+       lhs_an_loop_info[ii].ind_init = build_x_modify_expr 
+	 (location, lhs_an_loop_info[ii].var, INIT_EXPR, build_zero_cst (typ), 
+	  complain);
+     }
+   
    if (rhs_list_size > 0)
      {
        rhs_array_operand = fix_sec_implicit_args (location, rhs_list,
@@ -743,24 +700,15 @@ expand_an_in_modify_expr (location_t location, tree lhs,
   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));
+      tree typ = ptrdiff_type_node;
+      rhs_an_loop_info[ii].var = create_temporary_var (typ);
+      add_decl_expr (rhs_an_loop_info[ii].var);
       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);
+	(location, rhs_an_loop_info[ii].var, INIT_EXPR, build_zero_cst (typ), 
+	 complain);
     }
 
   if (lhs_rank)
@@ -809,12 +757,12 @@ expand_an_in_modify_expr (location_t location, tree lhs,
     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.  */
+      /* No need to compare ii < rhs_rank && ii >= lhs_rank because in a valid 
+	 Array notation expression, rank of RHS cannot be greater than LHS.  */
       gcc_unreachable ();
   
   an_init = pop_stmt_list (an_init);
-  append_to_statement_list_force (an_init, &loop_with_init);
+  append_to_statement_list (an_init, &loop_with_init);
   body = array_expr;
   for (ii = 0; ii < MAX (lhs_rank, rhs_rank); ii++)
     {
@@ -824,17 +772,13 @@ expand_an_in_modify_expr (location_t location, tree lhs,
 
       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);
+	  append_to_statement_list (lhs_an_loop_info[ii].ind_init, &init_list);
+	  append_to_statement_list (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);
+	  append_to_statement_list (rhs_an_loop_info[ii].ind_init, &init_list);
+	  append_to_statement_list (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);
@@ -867,7 +811,6 @@ cp_expand_cond_array_notations (tree orig_stmt)
   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;
@@ -884,13 +827,17 @@ cp_expand_cond_array_notations (tree orig_stmt)
 	  || 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)
+      /* If the condition has a zero rank, then handle array notations in body
+	 seperately.  */
+      if (cond_rank == 0)
+	return orig_stmt;
+      if (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)
+      else if (cond_rank != no_rank && no_rank != 0)
 	{
 	  error_at (EXPR_LOCATION (no_expr), "rank mismatch with controlling "
 		    "expression of parent if-statement");
@@ -911,13 +858,17 @@ cp_expand_cond_array_notations (tree orig_stmt)
 	      && !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)
+
+      /* Same reasoning as for COND_EXPR.  */
+      if (cond_rank == 0)
+	return orig_stmt;
+      else if (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)
+      else if (cond_rank != no_rank && no_rank != 0)
 	{
 	  error_at (EXPR_LOCATION (no_expr), "rank mismatch with controlling "
 		    "expression of parent if-statement");
@@ -949,11 +900,11 @@ cp_expand_cond_array_notations (tree orig_stmt)
 	      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 (builtin_loop, &stmt);
 	    }
 	}
     }
-  append_to_statement_list_force (orig_stmt, &stmt);
+  append_to_statement_list (orig_stmt, &stmt);
   rank = 0;
   array_list = NULL;
   if (!find_rank (EXPR_LOCATION (stmt), stmt, stmt, true, &rank))
@@ -977,37 +928,28 @@ cp_expand_cond_array_notations (tree orig_stmt)
   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);
+      make_triplet_val_inv (&ARRAY_NOTATION_START (anode));
+      make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (anode));
+      make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (anode));
     }
   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);
-	}
+
+  for (ii = 0; ii < rank; ii++) 
+    {
+      tree typ = ptrdiff_type_node;
+      an_loop_info[ii].var = create_temporary_var (typ);
+      add_decl_expr (an_loop_info[ii].var);
+      an_loop_info[ii].ind_init =
+	build_x_modify_expr (location, an_loop_info[ii].var, INIT_EXPR,
+			     build_zero_cst (typ), 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);
+  append_to_statement_list (an_init, &loop_with_init);
   body = stmt;
 
   for (ii = 0; ii < rank; ii++)
@@ -1017,7 +959,7 @@ cp_expand_cond_array_notations (tree orig_stmt)
 		      an_loop_info[ii].incr, body);
       body = pop_stmt_list (new_loop);
     }
-  append_to_statement_list_force (body, &loop_with_init);
+  append_to_statement_list (body, &loop_with_init);
 
   an_info.release ();
   an_loop_info.release ();
@@ -1062,14 +1004,14 @@ expand_unary_array_notation_exprs (tree orig_stmt)
 	  {
 	    vec<tree, va_gc> *sub_list = NULL, *new_var_list = NULL;
 	    stmt = alloc_stmt_list ();
-	    append_to_statement_list_force (builtin_loop, &stmt);
+	    append_to_statement_list (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);
+    append_to_statement_list (finish_expr_stmt (orig_stmt), &stmt);
   else
     stmt = orig_stmt;
   rank = 0;
@@ -1089,22 +1031,19 @@ expand_unary_array_notation_exprs (tree orig_stmt)
   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);
+      make_triplet_val_inv (&ARRAY_NOTATION_START (array_node));
+      make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (array_node));
+      make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (array_node));
     }
   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));
+      tree typ = ptrdiff_type_node;
+      an_loop_info[ii].var = create_temporary_var (typ);
+      add_decl_expr (an_loop_info[ii].var);
       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)),
+	(location, an_loop_info[ii].var, INIT_EXPR, build_zero_cst (typ), 
 	 tf_warning_or_error);
     }
   array_operand = create_array_refs (location, an_info, an_loop_info,
@@ -1113,7 +1052,7 @@ expand_unary_array_notation_exprs (tree orig_stmt)
   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);
+  append_to_statement_list (an_init, &loop_with_init);
   body = stmt;
   
   for (ii = 0; ii < rank; ii++)
@@ -1123,7 +1062,7 @@ expand_unary_array_notation_exprs (tree orig_stmt)
 		      an_loop_info[ii].incr, body);
       body = pop_stmt_list (new_loop);
     }
-  append_to_statement_list_force (body, &loop_with_init);
+  append_to_statement_list (body, &loop_with_init);
 
   an_info.release ();
   an_loop_info.release ();
@@ -1139,21 +1078,35 @@ static tree
 expand_return_expr (tree expr)
 {
   tree new_mod_list, new_var, new_mod, retval_expr;
-
+  size_t rank  = 0;
+  location_t loc = EXPR_LOCATION (expr);
   if (TREE_CODE (expr) != RETURN_EXPR)
     return expr;
+      
+  if (!find_rank (loc, expr, expr, false, &rank))
+    return error_mark_node;
 
-  location_t loc = EXPR_LOCATION (expr);
-  new_mod_list = alloc_stmt_list ();
+  /* If the return expression contains array notations, then flag it as
+     error.  */
+  if (rank >= 1)
+    {
+      error_at (loc, "array notation expression cannot be used as a return "
+		"value");
+      return error_mark_node;
+    }
+  
+  new_mod_list = push_stmt_list ();
   retval_expr = TREE_OPERAND (expr, 0);
-  new_var = build_decl (loc, VAR_DECL, NULL_TREE, TREE_TYPE (retval_expr));
+  new_var = create_temporary_var (TREE_TYPE (retval_expr));
+  add_decl_expr (new_var);
   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),
+				      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);
+  add_stmt (new_mod);
+  add_stmt (expr);
+  new_mod_list = pop_stmt_list (new_mod_list);
   return new_mod_list;
 }
 
@@ -1290,19 +1243,21 @@ expand_array_notation_exprs (tree 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:      
+    case FOR_STMT:
+      if (contains_array_notation_expr (FOR_COND (t)))
+	{
+	  error_at (EXPR_LOCATION (FOR_COND (t)),
+		    "array notation cannot be used in a condition for "
+		    "a for-loop");
+	  return error_mark_node;
+	}
       /* 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));
+	{ 
+	  FOR_BODY (t) = expand_array_notation_exprs (FOR_BODY (t));
+	  FOR_EXPR (t) = expand_array_notation_exprs (FOR_EXPR (t));
+	}
       else
 	t = expand_array_notation_exprs (t);
       return t;
@@ -1322,44 +1277,39 @@ expand_array_notation_exprs (tree t)
 	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 (contains_array_notation_expr (SWITCH_STMT_COND (t)))
 	{
-	  if (SWITCH_STMT_BODY (t))
-	    SWITCH_STMT_BODY (t) =
-	      expand_array_notation_exprs (SWITCH_STMT_BODY (t));
+	  error_at (EXPR_LOCATION (SWITCH_STMT_COND (t)),
+		    "array notation cannot be used as a condition for "
+		    "switch statement");
+	  return error_mark_node;
 	}
-      else
-	t = expand_array_notation_exprs (t);
+      if (SWITCH_STMT_BODY (t))
+	SWITCH_STMT_BODY (t) =
+	  expand_array_notation_exprs (SWITCH_STMT_BODY (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 (contains_array_notation_expr (WHILE_COND (t)))
 	{
-	  if (WHILE_BODY (t))
-	    WHILE_BODY (t) = expand_array_notation_exprs (WHILE_BODY (t));
+	  if (EXPR_LOCATION (WHILE_COND (t)) != UNKNOWN_LOCATION)
+	    loc = EXPR_LOCATION (WHILE_COND (t));
+	  error_at (loc, "array notation cannot be used as a condition for "
+		    "while statement");
+	  return error_mark_node;
 	}
-      else
-	t = expand_array_notation_exprs (t);
+      if (WHILE_BODY (t))
+	WHILE_BODY (t) = expand_array_notation_exprs (WHILE_BODY (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));
+      if (contains_array_notation_expr (DO_COND (t)))
+	{
+	  error_at (EXPR_LOCATION (DO_COND (t)),
+		    "array notation cannot be used as a condition for a "
+		    "do-while statement");
+	  return error_mark_node;
 	}
-      else
-	t = expand_array_notation_exprs (t);
+      if (DO_BODY (t))
+	DO_BODY (t) = expand_array_notation_exprs (DO_BODY (t));
       return t;
     default:
       if (is_expr)
@@ -1380,57 +1330,64 @@ expand_array_notation_exprs (tree 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.  */
+/* Given the base of an array (ARRAY), the START (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, 
+   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)
+build_array_notation_ref (location_t loc, tree array, tree start, 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)
+  /* If we enter the then-case of the if-statement below, we have hit a case 
+     like this: ARRAY [:].  */
+  if (!start && !length)
     {
-      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;
+      if (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == POINTER_TYPE)
+	{
+	  error_at (loc, "start-index and length fields necessary for "
+		    "using array notation in pointers or records");
+	  return error_mark_node;
+	}
+      tree domain = TYPE_DOMAIN (type);
+      if (!domain)
+	{
+	  error_at (loc, "start-index and length fields necessary for "
+		    "using array notation with array of unknown bound");
+	  return error_mark_node;
+	}
+      start = cp_fold_convert (ptrdiff_type_node, TYPE_MINVAL (domain));
+      length = size_binop (PLUS_EXPR, TYPE_MAXVAL (domain), size_one_node);
+      length = cp_fold_convert (ptrdiff_type_node, length);
     }
+    
+  if (!stride) 
+    stride = build_one_cst (ptrdiff_type_node);
+  
+  /* When dealing with templates, triplet type-checking will be done in pt.c 
+     after type substitution.  */
+  if (processing_template_decl 
+      && (type_dependent_expression_p (array) 
+	  || type_dependent_expression_p (length) 
+	  || type_dependent_expression_p (start) 
+	  || type_dependent_expression_p (stride))) 
+    array_ntn_expr = build_min_nt_loc (loc, ARRAY_NOTATION_REF, array, start, 
+				       length, stride, NULL_TREE);
+  else 
+    { 
+      if (!cilkplus_an_triplet_types_ok_p (loc, start, length, stride, type))
+	return error_mark_node;
+      array_ntn_expr = build4 (ARRAY_NOTATION_REF, NULL_TREE, array, start, 
+			       length, stride);
+    }
+  if (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;
@@ -1462,20 +1419,9 @@ cilkplus_an_triplet_types_ok_p (location_t loc, tree start_index, tree length,
     }
   if (!TREE_CODE (type) == FUNCTION_TYPE)
     {
-      error_at (loc, "array notations cannot be used with function type");
+      error_at (loc, "array notation 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))
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 38ef878..590d857 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -1207,6 +1207,12 @@ cp_genericize (tree fndecl)
   if (DECL_CLONED_FUNCTION_P (fndecl))
     return;
 
+  /* Expand all the array notations here.  */
+  if (flag_enable_cilkplus 
+      && contains_array_notation_expr (DECL_SAVED_TREE (fndecl)))
+    DECL_SAVED_TREE (fndecl) = 
+      expand_array_notation_exprs (DECL_SAVED_TREE (fndecl));
+
   /* We do want to see every occurrence of the parms, so we can't just use
      walk_tree's hash functionality.  */
   cp_genericize_tree (&DECL_SAVED_TREE (fndecl));
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 00ee450..a3438a8 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4974,6 +4974,7 @@ extern bool pragma_java_exceptions;
 
 /* in call.c */
 extern bool check_dtor_name			(tree, tree);
+bool magic_varargs_p                            (tree);
 
 extern tree build_conditional_expr		(location_t, tree, tree, tree, 
                                                  tsubst_flags_t);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index ec8ad46..ec8a5a9 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -6060,41 +6060,32 @@ 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.  */
+/* This function parses Cilk Plus array notations.  If a normal array expr. is
+   parsed then the array index is passed back to the caller through *INIT_INDEX 
+   and the function returns a NULL_TREE.  If array notation expr. is parsed, 
+   then *INIT_INDEX is ignored by the caller and the function returns 
+   a 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,
+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;
+  tree length_index, stride = NULL_TREE, value_tree, array_type;
+  bool saved_colon_corrects = 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;
-    }
+
+  array_type = TREE_TYPE (array_value);
+
+  parser->colon_corrects_to_scope_p = false;
   token = cp_lexer_peek_token (parser->lexer);
+  
   if (!token)
     {
       cp_parser_error (parser, "expected %<:%> or numeral");
@@ -6102,125 +6093,71 @@ cp_parser_array_notation (location_t loc, cp_parser *parser, tree init_index,
     }
   else if (token->type == CPP_COLON)
     {
-      if (!init_index)
+      /* Consume the ':'.  */
+      cp_lexer_consume_token (parser->lexer);
+      
+      /* If we are here, then we have a case like this A[:].  */
+      if (cp_lexer_peek_token (parser->lexer)->type != CPP_CLOSE_SQUARE)
 	{
-	  /* If we are here, then we have a case like this A[:].  */
-	  cp_lexer_consume_token (parser->lexer);
+	  cp_parser_error (parser, "expected %<]%>");
+	  cp_parser_skip_to_end_of_statement (parser);
+	  return error_mark_node;
+	}
+      *init_index = NULL_TREE;
+      stride = NULL_TREE;
+      length_index = NULL_TREE;
+    }
+  else
+    {
+      /* If we are here, then there are three valid possibilities:
+	 1. ARRAY [ EXP ]
+	 2. ARRAY [ EXP : EXP ]
+	 3. ARRAY [ EXP : EXP : EXP ]  */
 
-	  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);
+      *init_index = cp_parser_expression (parser, false, NULL);
+	
+      if (cp_lexer_peek_token (parser->lexer)->type != CPP_COLON)
+	{  
+	  /* This indicates that we have a normal array expression.  */
+	  parser->colon_corrects_to_scope_p = saved_colon_corrects;
+	  return NULL_TREE;
+	}
+      
+      /* Consume the ':'.  */
+      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)
+      if (!*init_index || *init_index == error_mark_node)
+	cp_parser_skip_to_end_of_statement (parser);
+
+      length_index = cp_parser_expression (parser, false, NULL);
+      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);
+	  stride = cp_parser_expression (parser, false, NULL);
+	  if (stride == error_mark_node)
 	    {
-	      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);
-		}
+	      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)
+  parser->colon_corrects_to_scope_p = saved_colon_corrects;
+
+  if (*init_index == error_mark_node || length_index == error_mark_node
+      || stride == error_mark_node)
     {
       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);
+
+  value_tree = build_array_notation_ref (loc, array_value, *init_index, 
+					 length_index, stride, array_type);
   return value_tree;
 }
 
@@ -6239,84 +6176,71 @@ cp_parser_postfix_open_square_expression (cp_parser *parser,
 					  bool for_offsetof,
 					  bool decltype_p)
 {
-  tree index;
+  tree index = NULL_TREE;
   location_t loc = cp_lexer_peek_token (parser->lexer)->location;
 
   /* Consume the `[' token.  */
   cp_lexer_consume_token (parser->lexer);
 
-  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);
+  /* 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
     {
-      /* 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
+      if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
 	{
-	  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);
+	  bool saved_colon_corrects = parser->colon_corrects_to_scope_p;
+	  parser->colon_corrects_to_scope_p = false;
+	  if (flag_enable_cilkplus
+	      && cp_lexer_peek_token (parser->lexer)->type == CPP_COLON)
 	    {
-	      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;
-		}
+	      error_at (cp_lexer_peek_token (parser->lexer)->location,
+			"braced list index is not allowed with array "
+			"notation");
+	      cp_parser_skip_to_end_of_statement (parser);
+	      return 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;
+	  parser->colon_corrects_to_scope_p = saved_colon_corrects;
 	}
-      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
+      else if (flag_enable_cilkplus)
 	{
-  	  /* 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);
-
-	  /* 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;
+	  /* Here are have these two options:
+	     ARRAY[EXP : EXP]        - Array notation expr with default
+	     stride of 1.
+	     ARRAY[EXP : EXP : EXP] - Array Notation with user-defined
+	     stride.  */
+	  tree an_exp = cp_parser_array_notation (loc, parser, &index, 
+						  postfix_expression);
+	  if (an_exp)
+	    return an_exp;
 	}
+      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);
+
+  /* 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;
 }
 
@@ -9551,8 +9475,6 @@ 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;
 }
 
@@ -9745,14 +9667,6 @@ 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;
@@ -10310,12 +10224,6 @@ 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;
 
@@ -10342,15 +10250,6 @@ 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;
 
@@ -10369,17 +10268,8 @@ cp_parser_iteration_statement (cp_parser* parser)
 	cp_parser_already_scoped_statement (parser);
 	parser->in_statement = in_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);
+	/* We're done with the for-statement.  */
+	finish_for_stmt (statement);
       }
       break;
 
@@ -16952,54 +16842,30 @@ cp_parser_direct_declarator (cp_parser* parser,
 	  if (token->type != CPP_CLOSE_SQUARE)
 	    {
 	      bool non_constant_p;
-
-	      if (flag_enable_cilkplus
-		  && cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+	      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;
-		  error_at (cp_lexer_peek_token (parser->lexer)->location,
-			    "array notations cannot be used in declaration");
-		  cp_lexer_consume_token (parser->lexer);
 		}
-	      else
+	      else if (processing_template_decl)
 		{
-		  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; 
-		    }
+		  /* Remember this wasn't a constant-expression.  */
+		  bounds = build_nop (TREE_TYPE (bounds), bounds);
+		  TREE_SIDE_EFFECTS (bounds) = 1;
 		}
 	    }
 	  else
@@ -18370,11 +18236,6 @@ 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);
 
@@ -22354,12 +22215,6 @@ 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));
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 667e37f..5dafdcd 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -15739,9 +15739,6 @@ 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;
@@ -19143,11 +19140,6 @@ 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);
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 0a460a4..87c1560 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -779,22 +779,6 @@ 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 ())
@@ -8089,7 +8073,6 @@ 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);
@@ -8901,7 +8884,6 @@ 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:
@@ -8912,6 +8894,9 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
 	  return false;
       return true;
 
+    case ARRAY_NOTATION_REF:
+      return false;
+
     case FMA_EXPR:
     case VEC_PERM_EXPR:
      for (i = 0; i < 3; ++i)
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 5b321ce..11592b4 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -3493,10 +3493,6 @@ cp_build_function_call_vec (tree function, vec<tree, va_gc> **params,
       params = &allocated;
     }
 
-  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)
@@ -3660,8 +3656,7 @@ convert_arguments (tree typelist, vec<tree, va_gc> **values, tree fndecl,
 	}
       else
 	{
-	  if (fndecl && DECL_BUILT_IN (fndecl)
-	      && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CONSTANT_P)
+	  if (fndecl && magic_varargs_p (fndecl))
 	    /* Don't do ellipsis conversion for __built_in_constant_p
 	       as this will result in spurious errors for non-trivial
 	       types.  */
@@ -3956,15 +3951,8 @@ cp_build_binary_op (location_t location,
 	}
     }
 
-  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);
+  type0 = TREE_TYPE (op0); 
+  type1 = TREE_TYPE (op1);
 
   /* The expression codes of the data types of the arguments tell us
      whether the arguments are integers, floating, pointers, etc.  */
@@ -5167,13 +5155,6 @@ 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)))
     {
@@ -7852,13 +7833,6 @@ 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);
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/decl-ptr-colon.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/decl-ptr-colon.c
index 68c8859..4b54f4d 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/decl-ptr-colon.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/decl-ptr-colon.c
@@ -1,3 +1,4 @@
+/* { dg-do compile { target c } } */
 /* { dg-options "-fcilkplus" } */
 
 int main(void)
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/dimensionless-arrays.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/dimensionless-arrays.c
index 69aaa52..690e89a 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/dimensionless-arrays.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/dimensionless-arrays.c
@@ -5,6 +5,6 @@ extern int *b;
 
 void foo()
 {
-  a[:] = 5;	// { dg-error "start-index and length fields necessary for using array notations in dimensionless arrays" }
-  b[:] = 5;    // { dg-error "start-index and length fields necessary for using array notations in pointers" }
+  a[:] = 5;	// { dg-error "start-index and length fields necessary for using array notation" }
+  b[:] = 5;    // { dg-error "start-index and length fields necessary for using" }
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/fn_ptr.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/fn_ptr.c
index 024a158..fa6d900 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/fn_ptr.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/fn_ptr.c
@@ -1,3 +1,4 @@
+/* { dg-do compile } */
 /* { dg-options "-fcilkplus" } */
 
 typedef int (*foo)(int);
@@ -10,11 +11,11 @@ int main(void)
   foo ***func_array_ptr;
   int argc = 5;
 
-  array[:] =  func_array[:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
-  func_array[0:5](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
-  func_array2[0:5][:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
-  array2[0:5][:] = func_array2[0:5][:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
-  func_array_ptr[0:5][0:4][0:argc:2](argc); /* { dg-error "array notations cannot be used with function pointer arrays" } */
+  array[:] =  func_array[:](10); 
+  func_array[0:5](10); 
+  func_array2[0:5][:](10);
+  array2[0:5][:] = func_array2[0:5][:](10);
+  func_array_ptr[0:5][0:4][0:argc:2](argc); 
 
   return 0;
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
index 14421d9..814786b 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
@@ -6,7 +6,7 @@ int main (void)
   int array[10], array2[10][10];
   int x, ii, jj ;
 
-  switch (array[:]) {  /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  switch (array[:]) {  /* { dg-error "cannot be used as a condition for switch statement" } */
   case 1:
     x = 5;
     break;
@@ -17,7 +17,7 @@ int main (void)
     x = 9;
   }
 
-  switch (array2[:][:]) { /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  switch (array2[:][:]) { /* { dg-error "cannot be used as a condition for switch statement" } */
   case 1:
     x = 5;
     break;
@@ -28,7 +28,7 @@ int main (void)
     x = 9;
   }
 
-  switch (array[:] + x) { /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  switch (array[:] + x) { /* { dg-error "cannot be used as a condition for switch statement" } */
   case 1:
     x = 5;
     break;
@@ -39,7 +39,7 @@ int main (void)
     x = 9;
   }
   
-  switch (array2[:][1:x:4] + x) { /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  switch (array2[:][1:x:4] + x) { /* { dg-error "cannot be used as a condition for switch statement" } */
   case 1:
     x = 5;
     break;
@@ -50,36 +50,36 @@ int main (void)
     x = 9;
   }
 
-  for (ii = 0; ii < array[:]; ii++) /* { dg-error "array notations cannot be used in a condition for a for-loop" } */
+  for (ii = 0; ii < array[:]; ii++) /* { dg-error "cannot be used in a condition for a for-loop" } */
     {
       x = 2;
     }
 
-  for (ii = 0; ii < array2[:][:]; ii++) /* { dg-error "array notations cannot be used in a condition for a for-loop" } */
+  for (ii = 0; ii < array2[:][:]; ii++) /* { dg-error "cannot be used in a condition for a for-loop" } */
     {
       x = 3;
     }
 
-  for (; array2[:][:] < 2;) /* { dg-error "array notations cannot be used in a condition for a for-loop" } */
+  for (; array2[:][:] < 2;) /* { dg-error "cannot be used in a condition for a for-loop" } */
     x = 4;
 
 
-  while (array2[:][:]) /* { dg-error "array notations cannot be used as a condition for while statement" } */
+  while (array2[:][:]) /* { dg-error "cannot be used as a condition for while statement" } */
     x = 3;
 
-  while (array[1:1:1]) /* { dg-error "array notations cannot be used as a condition for while statement" } */
+  while (array[1:1:1]) /* { dg-error "cannot be used as a condition for while statement" } */
     x = 1;
 
-  while (ii != array2[1:x:3][1:2:1]) /* { dg-error "array notations cannot be used as a condition for while statement"  } */
+  while (ii != array2[1:x:3][1:2:1]) /* { dg-error "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" "" { target c } } */
+  do { /* { dg-error "cannot be used as a condition for a do-while statement" "" { target c } } */
     x = 3;
-  } while (ii != array2[:][:]); /* { dg-error "array notations cannot be used as a condition for a do-while statement" "" { target c++ } } */
+  } while (ii != array2[:][:]); /* { dg-error "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" "" { target c } } */
+  do {  /* { dg-error "cannot be used as a condition for a do-while statement" "" { target c } } */
     x = 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++ } } */
+  } while (ii != (x + array2[:][1:x:2]) + 2); /* { dg-error "cannot be used as a condition for a do-while statement" "" { target c++ } } */
   
   do { 
     x += 3;
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/rank_mismatch.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/rank_mismatch.c
index b5e37ce..eb3c1f1 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/rank_mismatch.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/rank_mismatch.c
@@ -10,6 +10,7 @@ int main (void)
   int array[10][10], array2[10];
 
   array[:][:] = array[:]; /* { dg-error "rank mismatch between" } */
+  /* { dg-error "invalid conversion" "" { target c++ } 12 } */
 
   x = array2[:]; /* { dg-error "cannot be scalar when" } */
 

[-- Attachment #3: CL.txt --]
[-- Type: text/plain, Size: 5853 bytes --]

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

        * builtins.def: Fixed the function type of CILKPLUS_BUILTIN.

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

        * c-parser.c (c_parser_array_notation): Removed rejection of array
        notations in an array of function pointers.

gcc/c-family/ChangeLog
2013-06-26  Balaji V. Iyer  <balaji.v.iyer@intel.com>

        * array-notation-common.c (length_mismatch_in_expr_p): Collapsed two
        if-statements and compared the trees directly using tree_int_cst_equal.
        (find_rank): Checked for array notations in function name to handle
        array notations in function pointers.
        (extract_array_notation_exprs): Likewise.
        (replace_array_notations): Likewise.
        (cilkplus_extract_an_triplets): Replaced safe_push with
        safe_grow_cleared.  Also removed an unnecessary check to see if the
        node is of type ARRAY_NOTATION_REF.
        (fix_sec_implicit_args): Removed an unnecessary check for ADDR_EXPR.
        Also switched two if-statements to remove an unnecessary comparison.


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

        * parser.c (cp_parser_array_notation): Removed rejection array notation
        of type function pointers. Added handling of array expressions when
        Cilk Plus is enabled.  Took out type-checking.
        (cp_parser_postfix_open_square_expression): Moved normal array expr.
        parsing into cp_parser_array_notation when cilkplus is enabled.
        (cp_parser_compound_statement): Removed expansion of array notations.
        (cp_parser_ctor_initializer_opt_and_function_body): Likewise.
        (cp_parser_function_definition_after_declarator): Likewise.
        (cp_parser_selection_statement): Removed error reporting.
        (cp_parser_iteration_statement): Likewise.
        (cp_parser_direct_declarator): Removed error checking/reporting if
        array notations are used in the declarator.
        * pt.c (instantiate_decl): Likewise.
        (type_unification_real): Removed a check for ARRAY_NOTATION_REF.
        (cxx_eval_constant_expression): Removed ARRAY_NOTATION_REF case.
        (potential_constant_expression_1): Returned false for ARRAY_NOTATION_REF
        case.
        * cp-gimplify.c (cp_genericize): Added expansion of array notation
        expressions here.
        * cp-array-notation.c (make_triplet_val_inv): Removed loc and cry 
        parameters.  Replaced build_decls with get_temp_regvar with type as
        ptrdiff.
        (create_array_refs): Made the type-casting to ptrdiff_type.
        (replace_invariant_var): Replaced build_decl and build_min_nt_loc with
        get_temp_regvar.
        (expand_an_in_modify_expr): Ditto.  Replaced body of redundant else with
        gcc_unreachable.  Removed few unwanted checks.  Made induction variable
        type as ptrdiff_type.  Removed loc and complain arguments passed into
        make_triplet_val_inv.  Replaced all modify expression's code from NOP
        EXPR to INIT EXPR.  Replaced all forceful appending into stmt. list
        with the non-forceful one.  Replaced some integer conversion and
        equality-checking to using tree_int_cst_equal.
        (expand_sec_reduce_builtin): All changes mentioned in above function
        expand_an_in_modify_expr.  Made the new variable type of
        SEC_REDUCE_ANY/ALL_{NON}ZERO intrinsic functions as bool.
        (expand_array_notation_exprs): Removed SWITCH_EXPR case.  Moved all
        the error reporting from parser to this function.  Removed unwanted
        statements and checks from SWITCH_STMT, WHILE_STMT, and DO_STMT cases.
        (cilkplus_an_triplet_types_ok_p): Removed rejection of array notation
        in function pointers.
        (cp_expand_cond_array_notations): Added a new if statements to check
        if condition has a zero rank.  If so, then just return.
        (expand_return_expr): Added a check for return expressions with a rank.
        Replaced get_tmp_regvar with a create_temporary_var.
        (build_array_notation_ref): Simplified and removed unwanted if-stmts.
        Moved common code outside if-statements.  Moved type-checking from
        parser to here.
        * semantics.c (finish_return_stmt): Removed a check for return exprs.
        with a rank.
        * call.c (convert_like_real): Removed a check for array notation
        expression in a function.
        (build_over_call): Likewise.
        (magic_varargs_p): Added a check for builtin array notation function.
        Made this function non-static and removed its prototype.
        * cp-tree.h (magic_varargs_p): New prototype.
        * typeck.c (cp_build_function_call_vec): Removed automatic setting of
        nargs to the param->length when builtin reduction function is used.
        (convert_arguments): Replaced check for a constant_p function with
        margic_varargs_p function call.
        (cp_build_binary_op): Removed calling of the function
        find_correct_array_notation_type.
        (cp_build_addr_expr_1): Removed an unwanted if-statement.
        (convert_for_assignment): Removed automatic return of rhs when array
        notation builtin function is used.

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

        * c-c++-common/cilk-plus/AN/decl-ptr-colon.c (main): Made this testcase
        c specific.
        * c-c++-common/cilk-plus/AN/decl-ptr-colon.c (main): Changed dg-error
        strings to match the fixed error messages.
        * c-c++-common/cilk-plus/AN/misc.c (main): Likewise.
        * c-c++-common/cilk-plus/AN/rank_mismatch.c (main): Added a new error
        message check.


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH] Cilk Plus Array Notation for C++
  2013-06-27 18:39                                         ` Iyer, Balaji V
@ 2013-06-27 23:05                                           ` Jason Merrill
  2013-06-28  6:01                                             ` Iyer, Balaji V
  0 siblings, 1 reply; 40+ messages in thread
From: Jason Merrill @ 2013-06-27 23:05 UTC (permalink / raw)
  To: Iyer, Balaji V, Richard Henderson; +Cc: Aldy Hernandez, gcc-patches

On 06/27/2013 02:36 PM, Iyer, Balaji V wrote:
> 	I looked through the patch again. I was able to get rid of the first if-statement in cp_parser_postfix_open_square_expression function. I think now it looks exactly as you requested.

Much better, thanks.

> +         /* Sometimes, it type-casts certain functions to void. Unwrap it.  */
> +         if (VOID_TYPE_P (TREE_TYPE (t)) && TREE_CODE (t) == CONVERT_EXPR)
> +           t = TREE_OPERAND (t, 0);

If something is typecast to void, we shouldn't need to keep it in a 
temporary; we should be able to just pass it directly to 
finish_expr_stmt and then replace other occurrences with void_zero_node. 
  When are you encountering this?

> +      if (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == POINTER_TYPE)
> +       {
> +         error_at (loc, "start-index and length fields necessary for "
> +                   "using array notation in pointers or records");
> +         return error_mark_node;
> +       }

I'd turn this around and for anything that isn't an array, say that the 
[:] notation can only be used with arrays.  In particular it almost 
never makes sense to check for RECORD_TYPE specifically.

>    if (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;

So the type of an ARRAY_NOTATION_EXPR where the "array" is a class 
object is that same class?  That seems wrong.

> +  bool saved_colon_corrects = parser->colon_corrects_to_scope_p;

Let's declare this just before you change parser->colon_corrects_to_scope_p.

> +      if (!*init_index || *init_index == error_mark_node)
> +       cp_parser_skip_to_end_of_statement (parser);
> +
>        length_index = cp_parser_expression (parser, false, NULL);

It doesn't make sense to skip to the end of the statement and then try 
to keep parsing the stuff you just skipped over.

> +         bool saved_colon_corrects = parser->colon_corrects_to_scope_p;
> +         parser->colon_corrects_to_scope_p = false;
> +         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 "
> +                       "notation");
> +             cp_parser_skip_to_end_of_statement (parser);
> +             return error_mark_node;
> +           }
> +         parser->colon_corrects_to_scope_p = saved_colon_corrects;

You don't need to mess with colon_corrects_to_scope_p here; it doesn't 
affect the peek.

Jason

^ permalink raw reply	[flat|nested] 40+ messages in thread

* RE: [PATCH] Cilk Plus Array Notation for C++
  2013-06-27 23:05                                           ` Jason Merrill
@ 2013-06-28  6:01                                             ` Iyer, Balaji V
  2013-06-28 13:43                                               ` Jason Merrill
  2013-06-28 13:48                                               ` Jason Merrill
  0 siblings, 2 replies; 40+ messages in thread
From: Iyer, Balaji V @ 2013-06-28  6:01 UTC (permalink / raw)
  To: Jason Merrill, Richard Henderson; +Cc: Aldy Hernandez, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 4241 bytes --]

Hi Jason et al,
	Attached, a fixed patch and changelogs.  I have also answered your questions below.

Thanks,

Balaji V. Iyer.

> -----Original Message-----
> From: Jason Merrill [mailto:jason@redhat.com]
> Sent: Thursday, June 27, 2013 5:59 PM
> To: Iyer, Balaji V; Richard Henderson
> Cc: Aldy Hernandez; gcc-patches@gcc.gnu.org
> Subject: Re: [PATCH] Cilk Plus Array Notation for C++
> 
> On 06/27/2013 02:36 PM, Iyer, Balaji V wrote:
> > 	I looked through the patch again. I was able to get rid of the first if-
> statement in cp_parser_postfix_open_square_expression function. I think now it
> looks exactly as you requested.
> 
> Much better, thanks.
> 
> > +         /* Sometimes, it type-casts certain functions to void. Unwrap it.  */
> > +         if (VOID_TYPE_P (TREE_TYPE (t)) && TREE_CODE (t) == CONVERT_EXPR)
> > +           t = TREE_OPERAND (t, 0);
> 
> If something is typecast to void, we shouldn't need to keep it in a temporary; we
> should be able to just pass it directly to finish_expr_stmt and then replace other
> occurrences with void_zero_node.
>   When are you encountering this?
> 

I agree with you and I have fixed it such that if TREE_TYPE is void then don't bother creating a new variable.

This error happens in comma_exp.c testcase in Mac. 
For example, the following expression: 

  array[:]  = (atoi(argv[1]), (array2[0:10]+5));

In Mac, it is converting the above expression to array[:] = ((void) atoi (argv[1]), (array2[0:10]+5)) 

There is a function (replace_invariant_exprs) that will go through all the invariant expressions and replace it with a variable so that the function is only evaluated once. In this case, there is no reason to do so and just ignore it.

> > +      if (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) ==
> POINTER_TYPE)
> > +       {
> > +         error_at (loc, "start-index and length fields necessary for "
> > +                   "using array notation in pointers or records");
> > +         return error_mark_node;
> > +       }
> 
> I'd turn this around and for anything that isn't an array, say that the [:] notation
> can only be used with arrays.  In particular it almost never makes sense to check
> for RECORD_TYPE specifically.
> 

Fixed!

> >    if (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;
> 
> So the type of an ARRAY_NOTATION_EXPR where the "array" is a class object is
> that same class?  That seems wrong.
> 

It was never hitting the else clause.  A while back, I was sometimes passing in TREE_TYPE (array) into type, so in that case, I couldn't get the type. There were other checks around it which got removed. I replaced the else case with gcc_unreachable ().

> > +  bool saved_colon_corrects = parser->colon_corrects_to_scope_p;
> 

Ok. Fixed.

> Let's declare this just before you change parser->colon_corrects_to_scope_p.
> 
> > +      if (!*init_index || *init_index == error_mark_node)
> > +       cp_parser_skip_to_end_of_statement (parser);
> > +
> >        length_index = cp_parser_expression (parser, false, NULL);
> 
> It doesn't make sense to skip to the end of the statement and then try to keep
> parsing the stuff you just skipped over.
> 

Fixed!

> > +         bool saved_colon_corrects = parser->colon_corrects_to_scope_p;
> > +         parser->colon_corrects_to_scope_p = false;
> > +         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 "
> > +                       "notation");
> > +             cp_parser_skip_to_end_of_statement (parser);
> > +             return error_mark_node;
> > +           }
> > +         parser->colon_corrects_to_scope_p = saved_colon_corrects;
> 
> You don't need to mess with colon_corrects_to_scope_p here; it doesn't affect
> the peek.
> 

Fixed!

So, is this patch Ok for trunk?

Thanks,

Balaji V. Iyer.
> Jason


[-- Attachment #2: CL.txt --]
[-- Type: text/plain, Size: 5917 bytes --]

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

        * builtins.def: Fixed the function type of CILKPLUS_BUILTIN.

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

        * c-parser.c (c_parser_array_notation): Removed rejection of array
        notations in an array of function pointers.

gcc/c-family/ChangeLog
2013-06-28  Balaji V. Iyer  <balaji.v.iyer@intel.com>

        * array-notation-common.c (length_mismatch_in_expr_p): Collapsed two
        if-statements and compared the trees directly using tree_int_cst_equal.
        (find_rank): Checked for array notations in function name to handle
        array notations in function pointers.
        (extract_array_notation_exprs): Likewise.
        (replace_array_notations): Likewise.
        (cilkplus_extract_an_triplets): Replaced safe_push with
        safe_grow_cleared.  Also removed an unnecessary check to see if the
        node is of type ARRAY_NOTATION_REF.
        (fix_sec_implicit_args): Removed an unnecessary check for ADDR_EXPR.
        Also switched two if-statements to remove an unnecessary comparison.


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

        * parser.c (cp_parser_array_notation): Removed rejection array notation
        of type function pointers. Added handling of array expressions when
        Cilk Plus is enabled.  Took out type-checking.
        (cp_parser_postfix_open_square_expression): Moved normal array expr.
        parsing into cp_parser_array_notation when cilkplus is enabled.
        (cp_parser_compound_statement): Removed expansion of array notations.
        (cp_parser_ctor_initializer_opt_and_function_body): Likewise.
        (cp_parser_function_definition_after_declarator): Likewise.
        (cp_parser_selection_statement): Removed error reporting.
        (cp_parser_iteration_statement): Likewise.
        (cp_parser_direct_declarator): Removed error checking/reporting if
        array notations are used in the declarator.
        * pt.c (instantiate_decl): Likewise.
        (type_unification_real): Removed a check for ARRAY_NOTATION_REF.
        (cxx_eval_constant_expression): Removed ARRAY_NOTATION_REF case.
        (potential_constant_expression_1): Returned false for ARRAY_NOTATION_REF
        case.
        * cp-gimplify.c (cp_genericize): Added expansion of array notation
        expressions here.
        * cp-array-notation.c (make_triplet_val_inv): Removed loc and cry 
        parameters.  Replaced build_decls with get_temp_regvar with type as
        ptrdiff.
        (create_array_refs): Made the type-casting to ptrdiff_type.
        (replace_invariant_var): Added a check for void return type before 
	creating new var.  Replaced build_decl and build_min_nt_loc with
        get_temp_regvar.
        (expand_an_in_modify_expr): Ditto.  Replaced body of redundant else with
        gcc_unreachable.  Removed few unwanted checks.  Made induction variable
        type as ptrdiff_type.  Removed loc and complain arguments passed into
        make_triplet_val_inv.  Replaced all modify expression's code from NOP
        EXPR to INIT EXPR.  Replaced all forceful appending into stmt. list
        with the non-forceful one.  Replaced some integer conversion and
        equality-checking to using tree_int_cst_equal.
        (expand_sec_reduce_builtin): All changes mentioned in above function
        expand_an_in_modify_expr.  Made the new variable type of
        SEC_REDUCE_ANY/ALL_{NON}ZERO intrinsic functions as bool.
        (expand_array_notation_exprs): Removed SWITCH_EXPR case.  Moved all
        the error reporting from parser to this function.  Removed unwanted
        statements and checks from SWITCH_STMT, WHILE_STMT, and DO_STMT cases.
        (cilkplus_an_triplet_types_ok_p): Removed rejection of array notation
        in function pointers.
        (cp_expand_cond_array_notations): Added a new if statements to check
        if condition has a zero rank.  If so, then just return.
        (expand_return_expr): Added a check for return expressions with a rank.
        Replaced get_tmp_regvar with a create_temporary_var.
        (build_array_notation_ref): Simplified and removed unwanted if-stmts.
        Moved common code outside if-statements.  Moved type-checking from
        parser to here.
        * semantics.c (finish_return_stmt): Removed a check for return exprs.
        with a rank.
        * call.c (convert_like_real): Removed a check for array notation
        expression in a function.
        (build_over_call): Likewise.
        (magic_varargs_p): Added a check for builtin array notation function.
        Made this function non-static and removed its prototype.
        * cp-tree.h (magic_varargs_p): New prototype.
        * typeck.c (cp_build_function_call_vec): Removed automatic setting of
        nargs to the param->length when builtin reduction function is used.
        (convert_arguments): Replaced check for a constant_p function with
        margic_varargs_p function call.
        (cp_build_binary_op): Removed calling of the function
        find_correct_array_notation_type.
        (cp_build_addr_expr_1): Removed an unwanted if-statement.
        (convert_for_assignment): Removed automatic return of rhs when array
        notation builtin function is used.

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

        * c-c++-common/cilk-plus/AN/decl-ptr-colon.c (main): Made this testcase
        c specific.
        * c-c++-common/cilk-plus/AN/decl-ptr-colon.c (main): Changed dg-error
        strings to match the fixed error messages.
        * c-c++-common/cilk-plus/AN/misc.c (main): Likewise.
        * c-c++-common/cilk-plus/AN/rank_mismatch.c (main): Added a new error
        message check.


[-- Attachment #3: diff.txt --]
[-- Type: text/plain, Size: 80567 bytes --]

diff --git a/gcc/builtins.def b/gcc/builtins.def
index 91879a6..9b55b1f 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -158,9 +158,9 @@ along with GCC; see the file COPYING3.  If not see
 	       (flag_asan || flag_tsan))
 
 #undef DEF_CILKPLUS_BUILTIN
-#define DEF_CILKPLUS_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
-  DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
-  	       false, false, true, ATTRS, false, flag_enable_cilkplus)
+#define DEF_CILKPLUS_BUILTIN(ENUM, NAME, TYPE, ATTRS)  \
+  DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, BT_FN_INT_VAR, BT_LAST, \
+  	       false, false, false, ATTRS, false, flag_enable_cilkplus) 
 
 /* Define an attribute list for math functions that are normally
    "impure" because some of them may write into global memory for
diff --git a/gcc/c-family/array-notation-common.c b/gcc/c-family/array-notation-common.c
index 8eab89b..5e17009 100644
--- a/gcc/c-family/array-notation-common.c
+++ b/gcc/c-family/array-notation-common.c
@@ -101,15 +101,11 @@ length_mismatch_in_expr_p (location_t loc, vec<vec<an_parts> >list)
 	      /* 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;
-		    }
+	      if (TREE_CODE (list[ii][jj].length) == INTEGER_CST
+		  && !tree_int_cst_equal (list[ii][jj].length, length))
+		{ 
+		  error_at (loc, "length mismatch in expression"); 
+		  return true;
 		}
 	    }
 	  else
@@ -271,6 +267,8 @@ find_rank (location_t loc, tree orig_expr, tree expr, bool ignore_builtin_fn,
 		/* If it is a built-in function, then we know it returns a 
 		   scalar.  */
 		return true;
+	  if (!find_rank (loc, orig_expr, func_name, ignore_builtin_fn, rank))
+	    return false;
 	  FOR_EACH_CALL_EXPR_ARG (arg, iter, expr)
 	    {
 	      if (!find_rank (loc, orig_expr, arg, ignore_builtin_fn, rank))
@@ -358,6 +356,9 @@ extract_array_notation_exprs (tree node, bool ignore_builtin_fn,
 	  vec_safe_push (*array_list, node);
 	  return;
 	}
+      /* This will extract array notations in function pointers.  */
+      extract_array_notation_exprs (CALL_EXPR_FN (node), ignore_builtin_fn,
+				    array_list);
       FOR_EACH_CALL_EXPR_ARG (arg, iter, node)
 	extract_array_notation_exprs (arg, ignore_builtin_fn, array_list);
     } 
@@ -433,6 +434,9 @@ replace_array_notations (tree *orig, bool ignore_builtin_fn,
 	      }
 	  return;
 	}
+      /* Fixes array notations in array notations in function pointers.  */
+      replace_array_notations (&CALL_EXPR_FN (*orig), ignore_builtin_fn, list,
+			       array_operand);
       ii = 0;
       FOR_EACH_CALL_EXPR_ARG (arg, iter, *orig)
 	{
@@ -575,53 +579,49 @@ 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++)
+
+  if (rank > 0)
+    for (size_t ii = 0; ii < size; ii++)
       {
-	(*node)[ii].safe_push (init);
-	array_exprs[ii].safe_push (NULL_TREE);
+	(*node)[ii].safe_grow_cleared (rank);
+	array_exprs[ii].safe_grow_cleared (rank);
       }
-
   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 ();	
+	{
+	  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
+	    break;
+	}
     }
     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));
-	    }
+	  {
+	    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
@@ -637,16 +637,15 @@ fix_sec_implicit_args (location_t loc, vec <tree, va_gc> *list,
   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)
+	if (idx < 0)
 	  /* In this case, the returning function would have emitted an
 	     error thus it is not necessary to do so again.  */
 	  return NULL;
+	else if (idx < (int) rank)
+	  vec_safe_push (array_operand, an_loop_info[idx].var);
 	else
 	  {
 	    error_at (loc, "__sec_implicit_index argument %d must be "
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index d6a500e..c7846ce 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -11053,24 +11053,6 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
 	      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
 	      return error_mark_node;
 	    }
-	  if (TREE_CODE (array_type) == ARRAY_TYPE)
-	    {
-	      tree subtype = TREE_TYPE (array_type);
-	      while (subtype && TREE_CODE (subtype) == POINTER_TYPE)
-		{
-		  /* Now this could be a function pointer.  Find them and
-		     give out an error.  */
-		  subtype = TREE_TYPE (subtype);
-		  if (subtype && TREE_CODE (subtype) == FUNCTION_TYPE)
-		    {
-		      error_at (loc, "array notations cannot be used with "
-				"function pointer arrays");
-		      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
-						 NULL);
-		      return error_mark_node;
-		    }
-		}
-	    }
 	  array_type_domain = TYPE_DOMAIN (array_type);
 
 	  if (!array_type_domain)
@@ -11114,27 +11096,6 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
 	      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
 	      return error_mark_node;
 	    }
-	  if (TREE_CODE (array_type) == ARRAY_TYPE
-	      || TREE_CODE (array_type) == POINTER_TYPE)
-	    {
-	      tree subtype = TREE_TYPE (array_type);
-	      while (subtype
-		     && (TREE_CODE (subtype) == POINTER_TYPE
-			 || TREE_CODE (subtype) == ARRAY_TYPE))
-		{
-		  /* Now this could be a function pointer.  Find them and
-		     give out an error.  */
-		  subtype = TREE_TYPE (subtype);
-		  if (subtype && TREE_CODE (subtype) == FUNCTION_TYPE)
-		    {
-		      error_at (loc, "array notations cannot be used with "
-				"function pointer arrays");
-		      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
-						 NULL);
-		      return error_mark_node;
-		    }
-		}
-	    }
 	  c_parser_consume_token (parser); /* consume the ':' */
 	  end_index = c_parser_expression (parser).value;
 	  if (!end_index || end_index == error_mark_node)
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 6817bfc..425ef9b 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -216,7 +216,6 @@ static void add_candidates (tree, tree, const vec<tree, va_gc> *, tree, tree,
 			    bool, tree, tree, int, struct z_candidate **,
 			    tsubst_flags_t);
 static conversion *merge_conversion_sequences (conversion *, conversion *);
-static bool magic_varargs_p (tree);
 static tree build_temp (tree, tree, int, diagnostic_t *, tsubst_flags_t);
 
 /* Returns nonzero iff the destructor name specified in NAME matches BASETYPE.
@@ -5857,16 +5856,9 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
 	  else if (t->kind == ck_identity)
 	    break;
 	}
-
-      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)
+       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);
 
@@ -6515,9 +6507,12 @@ convert_for_arg_passing (tree type, tree val, tsubst_flags_t complain)
    which no conversions at all should be done.  This is true for some
    builtins which don't act like normal functions.  */
 
-static bool
+bool
 magic_varargs_p (tree fn)
 {
+  if (flag_enable_cilkplus && is_cilkplus_reduce_builtin (fn) != BUILT_IN_NONE)
+    return true;
+
   if (DECL_BUILT_IN (fn))
     switch (DECL_FUNCTION_CODE (fn))
       {
@@ -6895,21 +6890,13 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
 		       "  (you can disable this with -fno-deduce-init-list)");
 	    }
 	}
+      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
index 491da0f..20bea3e 100644
--- a/gcc/cp/cp-array-notation.c
+++ b/gcc/cp/cp-array-notation.c
@@ -59,7 +59,6 @@
 #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.  */
@@ -82,17 +81,12 @@ create_an_loop (tree init, tree cond, tree incr, tree body)
    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)
+make_triplet_val_inv (tree *value)
 {
-  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;
-    }
+    *value = get_temp_regvar (ptrdiff_type_node, *value);
 }
 
 /* Returns a vector of size RANK that contains an ARRAY_REF.  This vector is
@@ -140,9 +134,9 @@ create_array_refs (location_t loc, vec<vec<an_parts> > an_info,
 		   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);
+		st = build_c_cast (loc, ptrdiff_type_node, start);
+		str = build_c_cast (loc, ptrdiff_type_node, stride);
+		v = build_c_cast (loc, ptrdiff_type_node, var);
 	      }
 	    else
 	      {
@@ -192,7 +186,7 @@ replace_invariant_exprs (tree *node)
 {
   size_t ix = 0;
   tree node_list = NULL_TREE;
-  tree t = NULL_TREE, new_var = NULL_TREE, new_node; 
+  tree t = NULL_TREE, new_var = NULL_TREE;
   struct inv_list data;
 
   data.list_values = NULL;
@@ -204,17 +198,15 @@ replace_invariant_exprs (tree *node)
     {
       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);
+	{ 
+	  /* Sometimes, when comma_expr has a function call in it, it will
+	     typecast it to void.  Find_inv_trees finds those nodes and so
+	     if it void type, then don't bother creating a new var to hold 
+	     the return value.   */
+	  if (VOID_TYPE_P (TREE_TYPE (t)))
+	    new_var = t;
+	  else 
+	    new_var = get_temp_regvar (TREE_TYPE (t), t); 
 	  vec_safe_push (data.replacement, new_var);
 	}
       cp_walk_tree (node, replace_inv_trees, (void *) &data, NULL);
@@ -235,7 +227,6 @@ 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 ();
@@ -305,7 +296,7 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
     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;
+      new_var_type = boolean_type_node;
       break;
     case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
     case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
@@ -334,24 +325,30 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
     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);
+	make_triplet_val_inv (&ARRAY_NOTATION_START (anode));
+	make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (anode));
+	make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (anode));
       }
   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);
+      tree typ = ptrdiff_type_node;
+
+      /* In this place, we are using get_temp_regvar instead of 
+	 create_temporary_var if an_type is SEC_REDUCE_MAX/MIN_IND because
+	 the array_ind_value depends on this value being initalized to 0.  */
+      if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
+	  || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND) 
+	an_loop_info[ii].var = get_temp_regvar (typ, build_zero_cst (typ));
+      else
+	{
+	  an_loop_info[ii].var = create_temporary_var (typ);
+	  add_decl_expr (an_loop_info[ii].var);
+	}
+      an_loop_info[ii].ind_init = 
+	build_x_modify_expr (location, an_loop_info[ii].var, INIT_EXPR,
+			     build_zero_cst (typ), 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);
@@ -360,26 +357,9 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
     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);
-    }
+      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND) 
+    array_ind_value = get_temp_regvar (TREE_TYPE (func_parm), func_parm);
 
   array_op0 = (*array_operand)[0];
   switch (an_type)
@@ -394,35 +374,36 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
       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;
+      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;
+      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;
+      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;
+      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;
+      code = (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND ? LE_EXPR
+	: GE_EXPR);
       init = an_loop_info[0].var;
+      break;
     case BUILT_IN_CILKPLUS_SEC_REDUCE:
       init = identity_value;
       break;
@@ -433,9 +414,11 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
       gcc_unreachable ();
     }
 
-  if (init)
-    new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR, init,
-					tf_warning_or_error);
+  if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
+    *new_var = get_temp_regvar (new_var_type, init);
+  else
+    *new_var = NULL_TREE;
+
   switch (an_type)
     {
     case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD:
@@ -470,8 +453,6 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
       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,
@@ -521,21 +502,8 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
     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);
+  append_to_statement_list (an_init, &loop_with_init);
   body = new_expr;
 
   for (ii = 0; ii < rank; ii++)
@@ -545,7 +513,7 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
 		      an_loop_info[ii].incr, body);
       body = pop_stmt_list (new_loop);
     }
-  append_to_statement_list_force (body, &loop_with_init);
+  append_to_statement_list (body, &loop_with_init);
 
   an_info.release ();
   an_loop_info.release ();
@@ -634,10 +602,7 @@ expand_an_in_modify_expr (location_t location, tree lhs,
 	  return an_init;
 	}
       else
-	{
-	  pop_stmt_list (an_init);
-	  return NULL_TREE;
-	}
+	gcc_unreachable ();
     }
 
   /* If for some reason location is not set, then find if LHS or RHS has
@@ -659,8 +624,6 @@ expand_an_in_modify_expr (location_t location, tree lhs,
     
   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;
     }
@@ -675,17 +638,17 @@ expand_an_in_modify_expr (location_t location, tree lhs,
   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);
+      make_triplet_val_inv (&ARRAY_NOTATION_START (anode));
+      make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (anode));
+      make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (anode));
     }
   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);
+	make_triplet_val_inv (&ARRAY_NOTATION_START (aa));
+	make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (aa));
+	make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (aa));
       }
   lhs_an_loop_info.safe_grow_cleared (lhs_rank);
   
@@ -705,31 +668,29 @@ expand_an_in_modify_expr (location_t location, tree lhs,
       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;
+  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;
-	}
+      && TREE_CODE (rhs_len) == INTEGER_CST 
+      && !tree_int_cst_equal (rhs_len, lhs_len))
+    { 
+      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);
+   for (ii = 0; ii < lhs_rank; ii++) 
+     {
+       tree typ = ptrdiff_type_node; 
+       lhs_an_loop_info[ii].var = create_temporary_var (typ);
+       add_decl_expr (lhs_an_loop_info[ii].var);
+       lhs_an_loop_info[ii].ind_init = build_x_modify_expr 
+	 (location, lhs_an_loop_info[ii].var, INIT_EXPR, build_zero_cst (typ), 
+	  complain);
+     }
+   
    if (rhs_list_size > 0)
      {
        rhs_array_operand = fix_sec_implicit_args (location, rhs_list,
@@ -743,24 +704,15 @@ expand_an_in_modify_expr (location_t location, tree lhs,
   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));
+      tree typ = ptrdiff_type_node;
+      rhs_an_loop_info[ii].var = create_temporary_var (typ);
+      add_decl_expr (rhs_an_loop_info[ii].var);
       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);
+	(location, rhs_an_loop_info[ii].var, INIT_EXPR, build_zero_cst (typ), 
+	 complain);
     }
 
   if (lhs_rank)
@@ -809,12 +761,12 @@ expand_an_in_modify_expr (location_t location, tree lhs,
     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.  */
+      /* No need to compare ii < rhs_rank && ii >= lhs_rank because in a valid 
+	 Array notation expression, rank of RHS cannot be greater than LHS.  */
       gcc_unreachable ();
   
   an_init = pop_stmt_list (an_init);
-  append_to_statement_list_force (an_init, &loop_with_init);
+  append_to_statement_list (an_init, &loop_with_init);
   body = array_expr;
   for (ii = 0; ii < MAX (lhs_rank, rhs_rank); ii++)
     {
@@ -824,17 +776,13 @@ expand_an_in_modify_expr (location_t location, tree lhs,
 
       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);
+	  append_to_statement_list (lhs_an_loop_info[ii].ind_init, &init_list);
+	  append_to_statement_list (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);
+	  append_to_statement_list (rhs_an_loop_info[ii].ind_init, &init_list);
+	  append_to_statement_list (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);
@@ -867,7 +815,6 @@ cp_expand_cond_array_notations (tree orig_stmt)
   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;
@@ -884,13 +831,17 @@ cp_expand_cond_array_notations (tree orig_stmt)
 	  || 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)
+      /* If the condition has a zero rank, then handle array notations in body
+	 seperately.  */
+      if (cond_rank == 0)
+	return orig_stmt;
+      if (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)
+      else if (cond_rank != no_rank && no_rank != 0)
 	{
 	  error_at (EXPR_LOCATION (no_expr), "rank mismatch with controlling "
 		    "expression of parent if-statement");
@@ -911,13 +862,17 @@ cp_expand_cond_array_notations (tree orig_stmt)
 	      && !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)
+
+      /* Same reasoning as for COND_EXPR.  */
+      if (cond_rank == 0)
+	return orig_stmt;
+      else if (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)
+      else if (cond_rank != no_rank && no_rank != 0)
 	{
 	  error_at (EXPR_LOCATION (no_expr), "rank mismatch with controlling "
 		    "expression of parent if-statement");
@@ -949,11 +904,11 @@ cp_expand_cond_array_notations (tree orig_stmt)
 	      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 (builtin_loop, &stmt);
 	    }
 	}
     }
-  append_to_statement_list_force (orig_stmt, &stmt);
+  append_to_statement_list (orig_stmt, &stmt);
   rank = 0;
   array_list = NULL;
   if (!find_rank (EXPR_LOCATION (stmt), stmt, stmt, true, &rank))
@@ -977,37 +932,28 @@ cp_expand_cond_array_notations (tree orig_stmt)
   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);
+      make_triplet_val_inv (&ARRAY_NOTATION_START (anode));
+      make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (anode));
+      make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (anode));
     }
   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);
-	}
+
+  for (ii = 0; ii < rank; ii++) 
+    {
+      tree typ = ptrdiff_type_node;
+      an_loop_info[ii].var = create_temporary_var (typ);
+      add_decl_expr (an_loop_info[ii].var);
+      an_loop_info[ii].ind_init =
+	build_x_modify_expr (location, an_loop_info[ii].var, INIT_EXPR,
+			     build_zero_cst (typ), 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);
+  append_to_statement_list (an_init, &loop_with_init);
   body = stmt;
 
   for (ii = 0; ii < rank; ii++)
@@ -1017,7 +963,7 @@ cp_expand_cond_array_notations (tree orig_stmt)
 		      an_loop_info[ii].incr, body);
       body = pop_stmt_list (new_loop);
     }
-  append_to_statement_list_force (body, &loop_with_init);
+  append_to_statement_list (body, &loop_with_init);
 
   an_info.release ();
   an_loop_info.release ();
@@ -1062,14 +1008,14 @@ expand_unary_array_notation_exprs (tree orig_stmt)
 	  {
 	    vec<tree, va_gc> *sub_list = NULL, *new_var_list = NULL;
 	    stmt = alloc_stmt_list ();
-	    append_to_statement_list_force (builtin_loop, &stmt);
+	    append_to_statement_list (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);
+    append_to_statement_list (finish_expr_stmt (orig_stmt), &stmt);
   else
     stmt = orig_stmt;
   rank = 0;
@@ -1089,22 +1035,19 @@ expand_unary_array_notation_exprs (tree orig_stmt)
   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);
+      make_triplet_val_inv (&ARRAY_NOTATION_START (array_node));
+      make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (array_node));
+      make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (array_node));
     }
   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));
+      tree typ = ptrdiff_type_node;
+      an_loop_info[ii].var = create_temporary_var (typ);
+      add_decl_expr (an_loop_info[ii].var);
       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)),
+	(location, an_loop_info[ii].var, INIT_EXPR, build_zero_cst (typ), 
 	 tf_warning_or_error);
     }
   array_operand = create_array_refs (location, an_info, an_loop_info,
@@ -1113,7 +1056,7 @@ expand_unary_array_notation_exprs (tree orig_stmt)
   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);
+  append_to_statement_list (an_init, &loop_with_init);
   body = stmt;
   
   for (ii = 0; ii < rank; ii++)
@@ -1123,7 +1066,7 @@ expand_unary_array_notation_exprs (tree orig_stmt)
 		      an_loop_info[ii].incr, body);
       body = pop_stmt_list (new_loop);
     }
-  append_to_statement_list_force (body, &loop_with_init);
+  append_to_statement_list (body, &loop_with_init);
 
   an_info.release ();
   an_loop_info.release ();
@@ -1139,21 +1082,35 @@ static tree
 expand_return_expr (tree expr)
 {
   tree new_mod_list, new_var, new_mod, retval_expr;
-
+  size_t rank  = 0;
+  location_t loc = EXPR_LOCATION (expr);
   if (TREE_CODE (expr) != RETURN_EXPR)
     return expr;
+      
+  if (!find_rank (loc, expr, expr, false, &rank))
+    return error_mark_node;
 
-  location_t loc = EXPR_LOCATION (expr);
-  new_mod_list = alloc_stmt_list ();
+  /* If the return expression contains array notations, then flag it as
+     error.  */
+  if (rank >= 1)
+    {
+      error_at (loc, "array notation expression cannot be used as a return "
+		"value");
+      return error_mark_node;
+    }
+  
+  new_mod_list = push_stmt_list ();
   retval_expr = TREE_OPERAND (expr, 0);
-  new_var = build_decl (loc, VAR_DECL, NULL_TREE, TREE_TYPE (retval_expr));
+  new_var = create_temporary_var (TREE_TYPE (retval_expr));
+  add_decl_expr (new_var);
   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),
+				      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);
+  add_stmt (new_mod);
+  add_stmt (expr);
+  new_mod_list = pop_stmt_list (new_mod_list);
   return new_mod_list;
 }
 
@@ -1290,19 +1247,21 @@ expand_array_notation_exprs (tree 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:      
+    case FOR_STMT:
+      if (contains_array_notation_expr (FOR_COND (t)))
+	{
+	  error_at (EXPR_LOCATION (FOR_COND (t)),
+		    "array notation cannot be used in a condition for "
+		    "a for-loop");
+	  return error_mark_node;
+	}
       /* 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));
+	{ 
+	  FOR_BODY (t) = expand_array_notation_exprs (FOR_BODY (t));
+	  FOR_EXPR (t) = expand_array_notation_exprs (FOR_EXPR (t));
+	}
       else
 	t = expand_array_notation_exprs (t);
       return t;
@@ -1322,44 +1281,39 @@ expand_array_notation_exprs (tree t)
 	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 (contains_array_notation_expr (SWITCH_STMT_COND (t)))
 	{
-	  if (SWITCH_STMT_BODY (t))
-	    SWITCH_STMT_BODY (t) =
-	      expand_array_notation_exprs (SWITCH_STMT_BODY (t));
+	  error_at (EXPR_LOCATION (SWITCH_STMT_COND (t)),
+		    "array notation cannot be used as a condition for "
+		    "switch statement");
+	  return error_mark_node;
 	}
-      else
-	t = expand_array_notation_exprs (t);
+      if (SWITCH_STMT_BODY (t))
+	SWITCH_STMT_BODY (t) =
+	  expand_array_notation_exprs (SWITCH_STMT_BODY (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 (contains_array_notation_expr (WHILE_COND (t)))
 	{
-	  if (WHILE_BODY (t))
-	    WHILE_BODY (t) = expand_array_notation_exprs (WHILE_BODY (t));
+	  if (EXPR_LOCATION (WHILE_COND (t)) != UNKNOWN_LOCATION)
+	    loc = EXPR_LOCATION (WHILE_COND (t));
+	  error_at (loc, "array notation cannot be used as a condition for "
+		    "while statement");
+	  return error_mark_node;
 	}
-      else
-	t = expand_array_notation_exprs (t);
+      if (WHILE_BODY (t))
+	WHILE_BODY (t) = expand_array_notation_exprs (WHILE_BODY (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));
+      if (contains_array_notation_expr (DO_COND (t)))
+	{
+	  error_at (EXPR_LOCATION (DO_COND (t)),
+		    "array notation cannot be used as a condition for a "
+		    "do-while statement");
+	  return error_mark_node;
 	}
-      else
-	t = expand_array_notation_exprs (t);
+      if (DO_BODY (t))
+	DO_BODY (t) = expand_array_notation_exprs (DO_BODY (t));
       return t;
     default:
       if (is_expr)
@@ -1380,59 +1334,66 @@ expand_array_notation_exprs (tree 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.  */
+/* Given the base of an array (ARRAY), the START (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, 
+   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)
+build_array_notation_ref (location_t loc, tree array, tree start, 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 we enter the then-case of the if-statement below, we have hit a case 
+     like this: ARRAY [:].  */
+  if (!start && !length)
     {
-      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 (TREE_CODE (type) != ARRAY_TYPE)
+	{
+	  error_at (loc, "start-index and length fields necessary for "
+		    "using array notation in pointers or records");
+	  return error_mark_node;
+	}
+      tree domain = TYPE_DOMAIN (type);
+      if (!domain)
+	{
+	  error_at (loc, "start-index and length fields necessary for "
+		    "using array notation with array of unknown bound");
+	  return error_mark_node;
+	}
+      start = cp_fold_convert (ptrdiff_type_node, TYPE_MINVAL (domain));
+      length = size_binop (PLUS_EXPR, TYPE_MAXVAL (domain), size_one_node);
+      length = cp_fold_convert (ptrdiff_type_node, length);
     }
-  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 (!stride) 
+    stride = build_one_cst (ptrdiff_type_node);
+  
+  /* When dealing with templates, triplet type-checking will be done in pt.c 
+     after type substitution.  */
+  if (processing_template_decl 
+      && (type_dependent_expression_p (array) 
+	  || type_dependent_expression_p (length) 
+	  || type_dependent_expression_p (start) 
+	  || type_dependent_expression_p (stride))) 
+    array_ntn_expr = build_min_nt_loc (loc, ARRAY_NOTATION_REF, array, start, 
+				       length, stride, NULL_TREE);
+  else 
+    { 
+      if (!cilkplus_an_triplet_types_ok_p (loc, start, length, stride, type))
+	return error_mark_node;
+      array_ntn_expr = build4 (ARRAY_NOTATION_REF, NULL_TREE, array, start, 
+			       length, stride);
     }
+  if (TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == POINTER_TYPE)
+    TREE_TYPE (array_ntn_expr) = TREE_TYPE (type);
+  else
+    gcc_unreachable ();
 
-  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;
 }
 
@@ -1462,20 +1423,9 @@ cilkplus_an_triplet_types_ok_p (location_t loc, tree start_index, tree length,
     }
   if (!TREE_CODE (type) == FUNCTION_TYPE)
     {
-      error_at (loc, "array notations cannot be used with function type");
+      error_at (loc, "array notation 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))
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 38ef878..590d857 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -1207,6 +1207,12 @@ cp_genericize (tree fndecl)
   if (DECL_CLONED_FUNCTION_P (fndecl))
     return;
 
+  /* Expand all the array notations here.  */
+  if (flag_enable_cilkplus 
+      && contains_array_notation_expr (DECL_SAVED_TREE (fndecl)))
+    DECL_SAVED_TREE (fndecl) = 
+      expand_array_notation_exprs (DECL_SAVED_TREE (fndecl));
+
   /* We do want to see every occurrence of the parms, so we can't just use
      walk_tree's hash functionality.  */
   cp_genericize_tree (&DECL_SAVED_TREE (fndecl));
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 00ee450..a3438a8 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4974,6 +4974,7 @@ extern bool pragma_java_exceptions;
 
 /* in call.c */
 extern bool check_dtor_name			(tree, tree);
+bool magic_varargs_p                            (tree);
 
 extern tree build_conditional_expr		(location_t, tree, tree, tree, 
                                                  tsubst_flags_t);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index ec8ad46..c2aa159 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -6060,41 +6060,31 @@ 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.  */
+/* This function parses Cilk Plus array notations.  If a normal array expr. is
+   parsed then the array index is passed back to the caller through *INIT_INDEX 
+   and the function returns a NULL_TREE.  If array notation expr. is parsed, 
+   then *INIT_INDEX is ignored by the caller and the function returns 
+   a 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,
+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;
-
+  tree length_index, stride = NULL_TREE, value_tree, array_type;
   if (!array_value || array_value == error_mark_node)
     {
       cp_parser_skip_to_end_of_statement (parser);
       return error_mark_node;
     }
+
+  array_type = TREE_TYPE (array_value);
   
-  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;
-    }
+  bool saved_colon_corrects = parser->colon_corrects_to_scope_p;
+  parser->colon_corrects_to_scope_p = false;
   token = cp_lexer_peek_token (parser->lexer);
+  
   if (!token)
     {
       cp_parser_error (parser, "expected %<:%> or numeral");
@@ -6102,125 +6092,57 @@ cp_parser_array_notation (location_t loc, cp_parser *parser, tree init_index,
     }
   else if (token->type == CPP_COLON)
     {
-      if (!init_index)
+      /* Consume the ':'.  */
+      cp_lexer_consume_token (parser->lexer);
+      
+      /* If we are here, then we have a case like this A[:].  */
+      if (cp_lexer_peek_token (parser->lexer)->type != CPP_CLOSE_SQUARE)
 	{
-	  /* 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);
+	  cp_parser_error (parser, "expected %<]%>");
+	  cp_parser_skip_to_end_of_statement (parser);
+	  return error_mark_node;
+	}
+      *init_index = NULL_TREE;
+      stride = NULL_TREE;
+      length_index = NULL_TREE;
+    }
+  else
+    {
+      /* If we are here, then there are three valid possibilities:
+	 1. ARRAY [ EXP ]
+	 2. ARRAY [ EXP : EXP ]
+	 3. ARRAY [ EXP : EXP : EXP ]  */
 
-	  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);
+      *init_index = cp_parser_expression (parser, false, NULL);	
+      if (cp_lexer_peek_token (parser->lexer)->type != CPP_COLON)
+	{  
+	  /* This indicates that we have a normal array expression.  */
+	  parser->colon_corrects_to_scope_p = saved_colon_corrects;
+	  return NULL_TREE;
 	}
-      else
+      
+      /* Consume the ':'.  */
+      cp_lexer_consume_token (parser->lexer);
+      length_index = cp_parser_expression (parser, false, NULL);
+      if (cp_lexer_peek_token (parser->lexer)->type == CPP_COLON)
 	{
-	  cp_parser_skip_to_end_of_statement (parser);
-	  return error_mark_node;
+	  cp_lexer_consume_token (parser->lexer);
+	  stride = cp_parser_expression (parser, false, NULL);
 	}
     }
-  
-  if (start_index == error_mark_node || length_index == error_mark_node
-      || stride == error_mark_node || !start_index || !length_index
-      || !stride)
+  parser->colon_corrects_to_scope_p = saved_colon_corrects;
+
+  if (*init_index == error_mark_node || length_index == error_mark_node
+      || stride == error_mark_node)
     {
       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);
+
+  value_tree = build_array_notation_ref (loc, array_value, *init_index, 
+					 length_index, stride, array_type);
   return value_tree;
 }
 
@@ -6239,84 +6161,68 @@ cp_parser_postfix_open_square_expression (cp_parser *parser,
 					  bool for_offsetof,
 					  bool decltype_p)
 {
-  tree index;
+  tree index = NULL_TREE;
   location_t loc = cp_lexer_peek_token (parser->lexer)->location;
 
   /* Consume the `[' token.  */
   cp_lexer_consume_token (parser->lexer);
 
-  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);
+  /* 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
     {
-      /* 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
+      if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
 	{
-	  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)
 	    {
-	      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;
-		}
+	      error_at (cp_lexer_peek_token (parser->lexer)->location,
+			"braced list index is not allowed with array "
+			"notation");
+	      cp_parser_skip_to_end_of_statement (parser);
+	      return 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
+      else if (flag_enable_cilkplus)
 	{
-  	  /* 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);
-
-	  /* 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;
+	  /* Here are have these two options:
+	     ARRAY[EXP : EXP]        - Array notation expr with default
+	     stride of 1.
+	     ARRAY[EXP : EXP : EXP] - Array Notation with user-defined
+	     stride.  */
+	  tree an_exp = cp_parser_array_notation (loc, parser, &index, 
+						  postfix_expression);
+	  if (an_exp)
+	    return an_exp;
 	}
+      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);
+
+  /* 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;
 }
 
@@ -9551,8 +9457,6 @@ 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;
 }
 
@@ -9745,14 +9649,6 @@ 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;
@@ -10310,12 +10206,6 @@ 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;
 
@@ -10342,15 +10232,6 @@ 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;
 
@@ -10369,17 +10250,8 @@ cp_parser_iteration_statement (cp_parser* parser)
 	cp_parser_already_scoped_statement (parser);
 	parser->in_statement = in_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);
+	/* We're done with the for-statement.  */
+	finish_for_stmt (statement);
       }
       break;
 
@@ -16952,54 +16824,30 @@ cp_parser_direct_declarator (cp_parser* parser,
 	  if (token->type != CPP_CLOSE_SQUARE)
 	    {
 	      bool non_constant_p;
-
-	      if (flag_enable_cilkplus
-		  && cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+	      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;
-		  error_at (cp_lexer_peek_token (parser->lexer)->location,
-			    "array notations cannot be used in declaration");
-		  cp_lexer_consume_token (parser->lexer);
 		}
-	      else
+	      else if (processing_template_decl)
 		{
-		  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; 
-		    }
+		  /* Remember this wasn't a constant-expression.  */
+		  bounds = build_nop (TREE_TYPE (bounds), bounds);
+		  TREE_SIDE_EFFECTS (bounds) = 1;
 		}
 	    }
 	  else
@@ -18370,11 +18218,6 @@ 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);
 
@@ -22354,12 +22197,6 @@ 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));
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 667e37f..5dafdcd 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -15739,9 +15739,6 @@ 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;
@@ -19143,11 +19140,6 @@ 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);
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 0a460a4..87c1560 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -779,22 +779,6 @@ 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 ())
@@ -8089,7 +8073,6 @@ 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);
@@ -8901,7 +8884,6 @@ 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:
@@ -8912,6 +8894,9 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
 	  return false;
       return true;
 
+    case ARRAY_NOTATION_REF:
+      return false;
+
     case FMA_EXPR:
     case VEC_PERM_EXPR:
      for (i = 0; i < 3; ++i)
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 5b321ce..11592b4 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -3493,10 +3493,6 @@ cp_build_function_call_vec (tree function, vec<tree, va_gc> **params,
       params = &allocated;
     }
 
-  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)
@@ -3660,8 +3656,7 @@ convert_arguments (tree typelist, vec<tree, va_gc> **values, tree fndecl,
 	}
       else
 	{
-	  if (fndecl && DECL_BUILT_IN (fndecl)
-	      && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CONSTANT_P)
+	  if (fndecl && magic_varargs_p (fndecl))
 	    /* Don't do ellipsis conversion for __built_in_constant_p
 	       as this will result in spurious errors for non-trivial
 	       types.  */
@@ -3956,15 +3951,8 @@ cp_build_binary_op (location_t location,
 	}
     }
 
-  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);
+  type0 = TREE_TYPE (op0); 
+  type1 = TREE_TYPE (op1);
 
   /* The expression codes of the data types of the arguments tell us
      whether the arguments are integers, floating, pointers, etc.  */
@@ -5167,13 +5155,6 @@ 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)))
     {
@@ -7852,13 +7833,6 @@ 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);
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/decl-ptr-colon.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/decl-ptr-colon.c
index 68c8859..4b54f4d 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/decl-ptr-colon.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/decl-ptr-colon.c
@@ -1,3 +1,4 @@
+/* { dg-do compile { target c } } */
 /* { dg-options "-fcilkplus" } */
 
 int main(void)
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/dimensionless-arrays.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/dimensionless-arrays.c
index 69aaa52..690e89a 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/dimensionless-arrays.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/dimensionless-arrays.c
@@ -5,6 +5,6 @@ extern int *b;
 
 void foo()
 {
-  a[:] = 5;	// { dg-error "start-index and length fields necessary for using array notations in dimensionless arrays" }
-  b[:] = 5;    // { dg-error "start-index and length fields necessary for using array notations in pointers" }
+  a[:] = 5;	// { dg-error "start-index and length fields necessary for using array notation" }
+  b[:] = 5;    // { dg-error "start-index and length fields necessary for using" }
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/fn_ptr.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/fn_ptr.c
index 024a158..fa6d900 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/fn_ptr.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/fn_ptr.c
@@ -1,3 +1,4 @@
+/* { dg-do compile } */
 /* { dg-options "-fcilkplus" } */
 
 typedef int (*foo)(int);
@@ -10,11 +11,11 @@ int main(void)
   foo ***func_array_ptr;
   int argc = 5;
 
-  array[:] =  func_array[:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
-  func_array[0:5](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
-  func_array2[0:5][:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
-  array2[0:5][:] = func_array2[0:5][:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
-  func_array_ptr[0:5][0:4][0:argc:2](argc); /* { dg-error "array notations cannot be used with function pointer arrays" } */
+  array[:] =  func_array[:](10); 
+  func_array[0:5](10); 
+  func_array2[0:5][:](10);
+  array2[0:5][:] = func_array2[0:5][:](10);
+  func_array_ptr[0:5][0:4][0:argc:2](argc); 
 
   return 0;
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
index 14421d9..814786b 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
@@ -6,7 +6,7 @@ int main (void)
   int array[10], array2[10][10];
   int x, ii, jj ;
 
-  switch (array[:]) {  /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  switch (array[:]) {  /* { dg-error "cannot be used as a condition for switch statement" } */
   case 1:
     x = 5;
     break;
@@ -17,7 +17,7 @@ int main (void)
     x = 9;
   }
 
-  switch (array2[:][:]) { /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  switch (array2[:][:]) { /* { dg-error "cannot be used as a condition for switch statement" } */
   case 1:
     x = 5;
     break;
@@ -28,7 +28,7 @@ int main (void)
     x = 9;
   }
 
-  switch (array[:] + x) { /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  switch (array[:] + x) { /* { dg-error "cannot be used as a condition for switch statement" } */
   case 1:
     x = 5;
     break;
@@ -39,7 +39,7 @@ int main (void)
     x = 9;
   }
   
-  switch (array2[:][1:x:4] + x) { /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  switch (array2[:][1:x:4] + x) { /* { dg-error "cannot be used as a condition for switch statement" } */
   case 1:
     x = 5;
     break;
@@ -50,36 +50,36 @@ int main (void)
     x = 9;
   }
 
-  for (ii = 0; ii < array[:]; ii++) /* { dg-error "array notations cannot be used in a condition for a for-loop" } */
+  for (ii = 0; ii < array[:]; ii++) /* { dg-error "cannot be used in a condition for a for-loop" } */
     {
       x = 2;
     }
 
-  for (ii = 0; ii < array2[:][:]; ii++) /* { dg-error "array notations cannot be used in a condition for a for-loop" } */
+  for (ii = 0; ii < array2[:][:]; ii++) /* { dg-error "cannot be used in a condition for a for-loop" } */
     {
       x = 3;
     }
 
-  for (; array2[:][:] < 2;) /* { dg-error "array notations cannot be used in a condition for a for-loop" } */
+  for (; array2[:][:] < 2;) /* { dg-error "cannot be used in a condition for a for-loop" } */
     x = 4;
 
 
-  while (array2[:][:]) /* { dg-error "array notations cannot be used as a condition for while statement" } */
+  while (array2[:][:]) /* { dg-error "cannot be used as a condition for while statement" } */
     x = 3;
 
-  while (array[1:1:1]) /* { dg-error "array notations cannot be used as a condition for while statement" } */
+  while (array[1:1:1]) /* { dg-error "cannot be used as a condition for while statement" } */
     x = 1;
 
-  while (ii != array2[1:x:3][1:2:1]) /* { dg-error "array notations cannot be used as a condition for while statement"  } */
+  while (ii != array2[1:x:3][1:2:1]) /* { dg-error "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" "" { target c } } */
+  do { /* { dg-error "cannot be used as a condition for a do-while statement" "" { target c } } */
     x = 3;
-  } while (ii != array2[:][:]); /* { dg-error "array notations cannot be used as a condition for a do-while statement" "" { target c++ } } */
+  } while (ii != array2[:][:]); /* { dg-error "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" "" { target c } } */
+  do {  /* { dg-error "cannot be used as a condition for a do-while statement" "" { target c } } */
     x = 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++ } } */
+  } while (ii != (x + array2[:][1:x:2]) + 2); /* { dg-error "cannot be used as a condition for a do-while statement" "" { target c++ } } */
   
   do { 
     x += 3;
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/rank_mismatch.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/rank_mismatch.c
index b5e37ce..eb3c1f1 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/rank_mismatch.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/rank_mismatch.c
@@ -10,6 +10,7 @@ int main (void)
   int array[10][10], array2[10];
 
   array[:][:] = array[:]; /* { dg-error "rank mismatch between" } */
+  /* { dg-error "invalid conversion" "" { target c++ } 12 } */
 
   x = array2[:]; /* { dg-error "cannot be scalar when" } */
 

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH] Cilk Plus Array Notation for C++
  2013-06-28  6:01                                             ` Iyer, Balaji V
@ 2013-06-28 13:43                                               ` Jason Merrill
  2013-06-28 13:48                                               ` Jason Merrill
  1 sibling, 0 replies; 40+ messages in thread
From: Jason Merrill @ 2013-06-28 13:43 UTC (permalink / raw)
  To: Iyer, Balaji V, Richard Henderson; +Cc: Aldy Hernandez, gcc-patches

On 06/28/2013 12:54 AM, Iyer, Balaji V wrote:
> I agree with you and I have fixed it such that if TREE_TYPE is void then don't bother creating a new variable.
>
> This error happens in comma_exp.c testcase in Mac.
> For example, the following expression:
>
>    array[:]  = (atoi(argv[1]), (array2[0:10]+5));
>
> In Mac, it is converting the above expression to array[:] = ((void) atoi (argv[1]), (array2[0:10]+5))
>
> There is a function (replace_invariant_exprs) that will go through all the invariant expressions and replace it with a variable so that the function is only evaluated once. In this case, there is no reason to do so and just ignore it.

We don't need to create a variable, but if the expression has 
side-effects I think we still want to move it out of the loop, right? 
The Cilk+ spec doesn't seem to specify whether subexpressions of rank 0 
are evaluated once per iteration, or just once total.

> +         /* Sometimes, when comma_expr has a function call in it, it will
> +            typecast it to void.  Find_inv_trees finds those nodes and so
> +            if it void type, then don't bother creating a new var to hold
> +            the return value.   */
> +         if (VOID_TYPE_P (TREE_TYPE (t)))
> +           new_var = t;
> +         else
> +           new_var = get_temp_regvar (TREE_TYPE (t), t);

I was suggesting

if (VOID_TYPE_P (TREE_TYPE (t)))
   {
     finish_expr_stmt (t);
     new_var = void_zero_node;
   }

Jason

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH] Cilk Plus Array Notation for C++
  2013-06-28  6:01                                             ` Iyer, Balaji V
  2013-06-28 13:43                                               ` Jason Merrill
@ 2013-06-28 13:48                                               ` Jason Merrill
  2013-06-28 15:03                                                 ` Iyer, Balaji V
  1 sibling, 1 reply; 40+ messages in thread
From: Jason Merrill @ 2013-06-28 13:48 UTC (permalink / raw)
  To: Iyer, Balaji V, Richard Henderson; +Cc: Aldy Hernandez, gcc-patches

On 06/28/2013 12:54 AM, Iyer, Balaji V wrote:
>             /* 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, ptrdiff_type_node, start);
>                 str = build_c_cast (loc, ptrdiff_type_node, stride);
>                 v = build_c_cast (loc, ptrdiff_type_node, var);
>               }
>             else
>               {
>                 st = start;
>                 str = stride;
>                 v = var;
>               }

I still think that what you want is to unconditionally convert start and 
stride to ptrdiff_t, either here or in build_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));

I still don't understand what the purpose of cilkplus_an_parts is; it 
seems to have exactly the same information as the ARRAY_NOTATION_REF, so 
you might as well keep the array of ARRAY_NOTATION_REF instead of 
copying it into an array of cilkplus_an_parts.

> +       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);

You don't need to check the triplet types in tsubst, since you're 
checking them in build_array_notation_ref.

Jason

^ permalink raw reply	[flat|nested] 40+ messages in thread

* RE: [PATCH] Cilk Plus Array Notation for C++
  2013-06-28 13:48                                               ` Jason Merrill
@ 2013-06-28 15:03                                                 ` Iyer, Balaji V
  2013-06-28 18:58                                                   ` Jason Merrill
  0 siblings, 1 reply; 40+ messages in thread
From: Iyer, Balaji V @ 2013-06-28 15:03 UTC (permalink / raw)
  To: Jason Merrill, Richard Henderson; +Cc: Aldy Hernandez, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 5441 bytes --]



> -----Original Message-----
> From: gcc-patches-owner@gcc.gnu.org [mailto:gcc-patches-
> owner@gcc.gnu.org] On Behalf Of Jason Merrill
> Sent: Friday, June 28, 2013 9:43 AM
> To: Iyer, Balaji V; Richard Henderson
> Cc: Aldy Hernandez; gcc-patches@gcc.gnu.org
> Subject: Re: [PATCH] Cilk Plus Array Notation for C++
> 

> > +         /* Sometimes, when comma_expr has a function call in it, it will
> > +            typecast it to void.  Find_inv_trees finds those nodes and so
> > +            if it void type, then don't bother creating a new var to hold
> > +            the return value.   */
> > +         if (VOID_TYPE_P (TREE_TYPE (t)))
> > +           new_var = t;
> > +         else
> > +           new_var = get_temp_regvar (TREE_TYPE (t), t);
> 
> I was suggesting
> 
> if (VOID_TYPE_P (TREE_TYPE (t)))
>    {
>      finish_expr_stmt (t);
>      new_var = void_zero_node;
>    }
>

Fixed! 

> On 06/28/2013 12:54 AM, Iyer, Balaji V wrote:
> >             /* 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 stridje 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, ptrdiff_type_node, start);
> >                 str = build_c_cast (loc, ptrdiff_type_node, stride);
> >                 v = build_c_cast (loc, ptrdiff_type_node, var);
> >               }
> >             else
> >               {
> >                 st = start;
> >                 str = stride;
> >                 v = var;
> >               }
> 
> I still think that what you want is to unconditionally convert start and stride to
> ptrdiff_t, either here or in build_array_notation_ref.
> 

Ok. I made the cast unconditional here. 

> > +           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));
> 
> I still don't understand what the purpose of cilkplus_an_parts is; it seems to have
> exactly the same information as the ARRAY_NOTATION_REF, so you might as
> well keep the array of ARRAY_NOTATION_REF instead of copying it into an array
> of cilkplus_an_parts.
> 

Well, it is mainly for ease of book-keeping. For example, if I have A[0:10][5:12] It is stored in ARRAY_NOTATION_REF like this:

<ARRAY_NOTATION_REF  <ARRAY_NOTATION_REF < 0, 10, 1>, 5, 12, 1>>

Now, if we take a simple polynomial example: A[0:10][5:12] + B[7:10][6:12:2]), we have something like this:

<PLUS_EXPR <ARRAY_NOTATION_REF < ARRAY_NOTATION_REF < 0, 10, 1>, 5, 12, 1>>, <ARRAY_NOTATION_REF<ARRAY_NOTATION_REF < 7, 10, 1>, 6, 12, 2>>>

Now, if we store this  PLUS_EXPR in the cilkplus_an_parts, we get something like this:

Node[0][0].start = 0
Node[0][0].length = 10
Node[0][0].stride = 1

Node[0][1].start = 5
Node[0][1].length = 12
Node[0][1].stride = 1

Node[1][0].start = 7
Node[1][0].length = 10
Node[1][0].stride = 1

Node[1][1].start = 6
Node[1][1].length = 12
Node[1][1].stride = 2

Now, if I have to do checking (e.g. make sure all the lengths are same across the rank), it is much easier for me to go through this set of size X rank arrays, than to recursively walk through the PLUS_EXPR and extract all the length values and check them. Also, if I have to add more features to array notations at a later time, this I feel is a lot more easier and straight-forward. In future, it something needs to be debugged, this table-like approach is a lot more simpler for me. Now, if we add things like a function call into the mix, then things get a bit more complicated for me.

Honestly, I don't think it adds that much memory overhead or dynamic code-footprint, and I free all the memory I allocated at the end of the function call.

> 
> > +       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);
> 
> You don't need to check the triplet types in tsubst, since you're checking them in
> build_array_notation_ref.
> 

Fixed!

So, is this OK for trunk?

> Jason


[-- Attachment #2: diff.txt --]
[-- Type: text/plain, Size: 82724 bytes --]

diff --git a/gcc/builtins.def b/gcc/builtins.def
index 91879a6..9b55b1f 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -158,9 +158,9 @@ along with GCC; see the file COPYING3.  If not see
 	       (flag_asan || flag_tsan))
 
 #undef DEF_CILKPLUS_BUILTIN
-#define DEF_CILKPLUS_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
-  DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
-  	       false, false, true, ATTRS, false, flag_enable_cilkplus)
+#define DEF_CILKPLUS_BUILTIN(ENUM, NAME, TYPE, ATTRS)  \
+  DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, BT_FN_INT_VAR, BT_LAST, \
+  	       false, false, false, ATTRS, false, flag_enable_cilkplus) 
 
 /* Define an attribute list for math functions that are normally
    "impure" because some of them may write into global memory for
diff --git a/gcc/c-family/array-notation-common.c b/gcc/c-family/array-notation-common.c
index 8eab89b..5e17009 100644
--- a/gcc/c-family/array-notation-common.c
+++ b/gcc/c-family/array-notation-common.c
@@ -101,15 +101,11 @@ length_mismatch_in_expr_p (location_t loc, vec<vec<an_parts> >list)
 	      /* 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;
-		    }
+	      if (TREE_CODE (list[ii][jj].length) == INTEGER_CST
+		  && !tree_int_cst_equal (list[ii][jj].length, length))
+		{ 
+		  error_at (loc, "length mismatch in expression"); 
+		  return true;
 		}
 	    }
 	  else
@@ -271,6 +267,8 @@ find_rank (location_t loc, tree orig_expr, tree expr, bool ignore_builtin_fn,
 		/* If it is a built-in function, then we know it returns a 
 		   scalar.  */
 		return true;
+	  if (!find_rank (loc, orig_expr, func_name, ignore_builtin_fn, rank))
+	    return false;
 	  FOR_EACH_CALL_EXPR_ARG (arg, iter, expr)
 	    {
 	      if (!find_rank (loc, orig_expr, arg, ignore_builtin_fn, rank))
@@ -358,6 +356,9 @@ extract_array_notation_exprs (tree node, bool ignore_builtin_fn,
 	  vec_safe_push (*array_list, node);
 	  return;
 	}
+      /* This will extract array notations in function pointers.  */
+      extract_array_notation_exprs (CALL_EXPR_FN (node), ignore_builtin_fn,
+				    array_list);
       FOR_EACH_CALL_EXPR_ARG (arg, iter, node)
 	extract_array_notation_exprs (arg, ignore_builtin_fn, array_list);
     } 
@@ -433,6 +434,9 @@ replace_array_notations (tree *orig, bool ignore_builtin_fn,
 	      }
 	  return;
 	}
+      /* Fixes array notations in array notations in function pointers.  */
+      replace_array_notations (&CALL_EXPR_FN (*orig), ignore_builtin_fn, list,
+			       array_operand);
       ii = 0;
       FOR_EACH_CALL_EXPR_ARG (arg, iter, *orig)
 	{
@@ -575,53 +579,49 @@ 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++)
+
+  if (rank > 0)
+    for (size_t ii = 0; ii < size; ii++)
       {
-	(*node)[ii].safe_push (init);
-	array_exprs[ii].safe_push (NULL_TREE);
+	(*node)[ii].safe_grow_cleared (rank);
+	array_exprs[ii].safe_grow_cleared (rank);
       }
-
   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 ();	
+	{
+	  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
+	    break;
+	}
     }
     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));
-	    }
+	  {
+	    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
@@ -637,16 +637,15 @@ fix_sec_implicit_args (location_t loc, vec <tree, va_gc> *list,
   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)
+	if (idx < 0)
 	  /* In this case, the returning function would have emitted an
 	     error thus it is not necessary to do so again.  */
 	  return NULL;
+	else if (idx < (int) rank)
+	  vec_safe_push (array_operand, an_loop_info[idx].var);
 	else
 	  {
 	    error_at (loc, "__sec_implicit_index argument %d must be "
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index d6a500e..c7846ce 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -11053,24 +11053,6 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
 	      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
 	      return error_mark_node;
 	    }
-	  if (TREE_CODE (array_type) == ARRAY_TYPE)
-	    {
-	      tree subtype = TREE_TYPE (array_type);
-	      while (subtype && TREE_CODE (subtype) == POINTER_TYPE)
-		{
-		  /* Now this could be a function pointer.  Find them and
-		     give out an error.  */
-		  subtype = TREE_TYPE (subtype);
-		  if (subtype && TREE_CODE (subtype) == FUNCTION_TYPE)
-		    {
-		      error_at (loc, "array notations cannot be used with "
-				"function pointer arrays");
-		      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
-						 NULL);
-		      return error_mark_node;
-		    }
-		}
-	    }
 	  array_type_domain = TYPE_DOMAIN (array_type);
 
 	  if (!array_type_domain)
@@ -11114,27 +11096,6 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
 	      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
 	      return error_mark_node;
 	    }
-	  if (TREE_CODE (array_type) == ARRAY_TYPE
-	      || TREE_CODE (array_type) == POINTER_TYPE)
-	    {
-	      tree subtype = TREE_TYPE (array_type);
-	      while (subtype
-		     && (TREE_CODE (subtype) == POINTER_TYPE
-			 || TREE_CODE (subtype) == ARRAY_TYPE))
-		{
-		  /* Now this could be a function pointer.  Find them and
-		     give out an error.  */
-		  subtype = TREE_TYPE (subtype);
-		  if (subtype && TREE_CODE (subtype) == FUNCTION_TYPE)
-		    {
-		      error_at (loc, "array notations cannot be used with "
-				"function pointer arrays");
-		      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
-						 NULL);
-		      return error_mark_node;
-		    }
-		}
-	    }
 	  c_parser_consume_token (parser); /* consume the ':' */
 	  end_index = c_parser_expression (parser).value;
 	  if (!end_index || end_index == error_mark_node)
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 6817bfc..425ef9b 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -216,7 +216,6 @@ static void add_candidates (tree, tree, const vec<tree, va_gc> *, tree, tree,
 			    bool, tree, tree, int, struct z_candidate **,
 			    tsubst_flags_t);
 static conversion *merge_conversion_sequences (conversion *, conversion *);
-static bool magic_varargs_p (tree);
 static tree build_temp (tree, tree, int, diagnostic_t *, tsubst_flags_t);
 
 /* Returns nonzero iff the destructor name specified in NAME matches BASETYPE.
@@ -5857,16 +5856,9 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
 	  else if (t->kind == ck_identity)
 	    break;
 	}
-
-      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)
+       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);
 
@@ -6515,9 +6507,12 @@ convert_for_arg_passing (tree type, tree val, tsubst_flags_t complain)
    which no conversions at all should be done.  This is true for some
    builtins which don't act like normal functions.  */
 
-static bool
+bool
 magic_varargs_p (tree fn)
 {
+  if (flag_enable_cilkplus && is_cilkplus_reduce_builtin (fn) != BUILT_IN_NONE)
+    return true;
+
   if (DECL_BUILT_IN (fn))
     switch (DECL_FUNCTION_CODE (fn))
       {
@@ -6895,21 +6890,13 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
 		       "  (you can disable this with -fno-deduce-init-list)");
 	    }
 	}
+      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
old mode 100644
new mode 100755
index 491da0f..d279ddd
--- a/gcc/cp/cp-array-notation.c
+++ b/gcc/cp/cp-array-notation.c
@@ -59,7 +59,6 @@
 #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.  */
@@ -82,17 +81,12 @@ create_an_loop (tree init, tree cond, tree incr, tree body)
    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)
+make_triplet_val_inv (tree *value)
 {
-  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;
-    }
+    *value = get_temp_regvar (ptrdiff_type_node, *value);
 }
 
 /* Returns a vector of size RANK that contains an ARRAY_REF.  This vector is
@@ -112,47 +106,22 @@ create_array_refs (location_t loc, vec<vec<an_parts> > an_info,
 {
   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);
+	    tree start = cp_fold_convert (ptrdiff_type_node, 
+					  an_info[ii][s_jj].start);
+	    tree stride = cp_fold_convert (ptrdiff_type_node, 
+					   an_info[ii][s_jj].stride);
+	    tree var = cp_fold_convert (ptrdiff_type_node, 
+					an_loop_info[s_jj].var);
+
+	    ind_mult = build2 (MULT_EXPR, TREE_TYPE (var), var, stride);
+	    ind_incr = build2 (PLUS_EXPR, TREE_TYPE (var), start, ind_mult);
 	    /* Array [ start_index + (induction_var * stride)]  */
 	    array_opr = grok_array_decl	(loc, array_opr, ind_incr, false);
 	  }
@@ -192,7 +161,7 @@ replace_invariant_exprs (tree *node)
 {
   size_t ix = 0;
   tree node_list = NULL_TREE;
-  tree t = NULL_TREE, new_var = NULL_TREE, new_node; 
+  tree t = NULL_TREE, new_var = NULL_TREE;
   struct inv_list data;
 
   data.list_values = NULL;
@@ -204,17 +173,18 @@ replace_invariant_exprs (tree *node)
     {
       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);
+	{ 
+	  /* Sometimes, when comma_expr has a function call in it, it will
+	     typecast it to void.  Find_inv_trees finds those nodes and so
+	     if it void type, then don't bother creating a new var to hold 
+	     the return value.   */
+	  if (VOID_TYPE_P (TREE_TYPE (t)))
+	    {
+	      finish_expr_stmt (t);
+	      new_var = void_zero_node;
+	    }
+	  else 
+	    new_var = get_temp_regvar (TREE_TYPE (t), t); 
 	  vec_safe_push (data.replacement, new_var);
 	}
       cp_walk_tree (node, replace_inv_trees, (void *) &data, NULL);
@@ -235,7 +205,6 @@ 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 ();
@@ -305,7 +274,7 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
     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;
+      new_var_type = boolean_type_node;
       break;
     case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
     case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
@@ -334,24 +303,30 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
     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);
+	make_triplet_val_inv (&ARRAY_NOTATION_START (anode));
+	make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (anode));
+	make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (anode));
       }
   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);
+      tree typ = ptrdiff_type_node;
+
+      /* In this place, we are using get_temp_regvar instead of 
+	 create_temporary_var if an_type is SEC_REDUCE_MAX/MIN_IND because
+	 the array_ind_value depends on this value being initalized to 0.  */
+      if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
+	  || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND) 
+	an_loop_info[ii].var = get_temp_regvar (typ, build_zero_cst (typ));
+      else
+	{
+	  an_loop_info[ii].var = create_temporary_var (typ);
+	  add_decl_expr (an_loop_info[ii].var);
+	}
+      an_loop_info[ii].ind_init = 
+	build_x_modify_expr (location, an_loop_info[ii].var, INIT_EXPR,
+			     build_zero_cst (typ), 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);
@@ -360,26 +335,9 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
     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);
-    }
+      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND) 
+    array_ind_value = get_temp_regvar (TREE_TYPE (func_parm), func_parm);
 
   array_op0 = (*array_operand)[0];
   switch (an_type)
@@ -394,35 +352,36 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
       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;
+      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;
+      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;
+      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;
+      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;
+      code = (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND ? LE_EXPR
+	: GE_EXPR);
       init = an_loop_info[0].var;
+      break;
     case BUILT_IN_CILKPLUS_SEC_REDUCE:
       init = identity_value;
       break;
@@ -433,9 +392,11 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
       gcc_unreachable ();
     }
 
-  if (init)
-    new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR, init,
-					tf_warning_or_error);
+  if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
+    *new_var = get_temp_regvar (new_var_type, init);
+  else
+    *new_var = NULL_TREE;
+
   switch (an_type)
     {
     case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD:
@@ -470,8 +431,6 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
       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,
@@ -521,21 +480,8 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
     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);
+  append_to_statement_list (an_init, &loop_with_init);
   body = new_expr;
 
   for (ii = 0; ii < rank; ii++)
@@ -545,7 +491,7 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
 		      an_loop_info[ii].incr, body);
       body = pop_stmt_list (new_loop);
     }
-  append_to_statement_list_force (body, &loop_with_init);
+  append_to_statement_list (body, &loop_with_init);
 
   an_info.release ();
   an_loop_info.release ();
@@ -634,10 +580,7 @@ expand_an_in_modify_expr (location_t location, tree lhs,
 	  return an_init;
 	}
       else
-	{
-	  pop_stmt_list (an_init);
-	  return NULL_TREE;
-	}
+	gcc_unreachable ();
     }
 
   /* If for some reason location is not set, then find if LHS or RHS has
@@ -659,8 +602,6 @@ expand_an_in_modify_expr (location_t location, tree lhs,
     
   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;
     }
@@ -675,17 +616,17 @@ expand_an_in_modify_expr (location_t location, tree lhs,
   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);
+      make_triplet_val_inv (&ARRAY_NOTATION_START (anode));
+      make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (anode));
+      make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (anode));
     }
   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);
+	make_triplet_val_inv (&ARRAY_NOTATION_START (aa));
+	make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (aa));
+	make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (aa));
       }
   lhs_an_loop_info.safe_grow_cleared (lhs_rank);
   
@@ -705,31 +646,29 @@ expand_an_in_modify_expr (location_t location, tree lhs,
       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;
+  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;
-	}
+      && TREE_CODE (rhs_len) == INTEGER_CST 
+      && !tree_int_cst_equal (rhs_len, lhs_len))
+    { 
+      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);
+   for (ii = 0; ii < lhs_rank; ii++) 
+     {
+       tree typ = ptrdiff_type_node; 
+       lhs_an_loop_info[ii].var = create_temporary_var (typ);
+       add_decl_expr (lhs_an_loop_info[ii].var);
+       lhs_an_loop_info[ii].ind_init = build_x_modify_expr 
+	 (location, lhs_an_loop_info[ii].var, INIT_EXPR, build_zero_cst (typ), 
+	  complain);
+     }
+   
    if (rhs_list_size > 0)
      {
        rhs_array_operand = fix_sec_implicit_args (location, rhs_list,
@@ -743,24 +682,15 @@ expand_an_in_modify_expr (location_t location, tree lhs,
   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));
+      tree typ = ptrdiff_type_node;
+      rhs_an_loop_info[ii].var = create_temporary_var (typ);
+      add_decl_expr (rhs_an_loop_info[ii].var);
       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);
+	(location, rhs_an_loop_info[ii].var, INIT_EXPR, build_zero_cst (typ), 
+	 complain);
     }
 
   if (lhs_rank)
@@ -809,12 +739,12 @@ expand_an_in_modify_expr (location_t location, tree lhs,
     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.  */
+      /* No need to compare ii < rhs_rank && ii >= lhs_rank because in a valid 
+	 Array notation expression, rank of RHS cannot be greater than LHS.  */
       gcc_unreachable ();
   
   an_init = pop_stmt_list (an_init);
-  append_to_statement_list_force (an_init, &loop_with_init);
+  append_to_statement_list (an_init, &loop_with_init);
   body = array_expr;
   for (ii = 0; ii < MAX (lhs_rank, rhs_rank); ii++)
     {
@@ -824,17 +754,13 @@ expand_an_in_modify_expr (location_t location, tree lhs,
 
       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);
+	  append_to_statement_list (lhs_an_loop_info[ii].ind_init, &init_list);
+	  append_to_statement_list (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);
+	  append_to_statement_list (rhs_an_loop_info[ii].ind_init, &init_list);
+	  append_to_statement_list (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);
@@ -867,7 +793,6 @@ cp_expand_cond_array_notations (tree orig_stmt)
   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;
@@ -884,13 +809,17 @@ cp_expand_cond_array_notations (tree orig_stmt)
 	  || 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)
+      /* If the condition has a zero rank, then handle array notations in body
+	 seperately.  */
+      if (cond_rank == 0)
+	return orig_stmt;
+      if (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)
+      else if (cond_rank != no_rank && no_rank != 0)
 	{
 	  error_at (EXPR_LOCATION (no_expr), "rank mismatch with controlling "
 		    "expression of parent if-statement");
@@ -911,13 +840,17 @@ cp_expand_cond_array_notations (tree orig_stmt)
 	      && !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)
+
+      /* Same reasoning as for COND_EXPR.  */
+      if (cond_rank == 0)
+	return orig_stmt;
+      else if (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)
+      else if (cond_rank != no_rank && no_rank != 0)
 	{
 	  error_at (EXPR_LOCATION (no_expr), "rank mismatch with controlling "
 		    "expression of parent if-statement");
@@ -949,11 +882,11 @@ cp_expand_cond_array_notations (tree orig_stmt)
 	      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 (builtin_loop, &stmt);
 	    }
 	}
     }
-  append_to_statement_list_force (orig_stmt, &stmt);
+  append_to_statement_list (orig_stmt, &stmt);
   rank = 0;
   array_list = NULL;
   if (!find_rank (EXPR_LOCATION (stmt), stmt, stmt, true, &rank))
@@ -977,37 +910,28 @@ cp_expand_cond_array_notations (tree orig_stmt)
   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);
+      make_triplet_val_inv (&ARRAY_NOTATION_START (anode));
+      make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (anode));
+      make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (anode));
     }
   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);
-	}
+
+  for (ii = 0; ii < rank; ii++) 
+    {
+      tree typ = ptrdiff_type_node;
+      an_loop_info[ii].var = create_temporary_var (typ);
+      add_decl_expr (an_loop_info[ii].var);
+      an_loop_info[ii].ind_init =
+	build_x_modify_expr (location, an_loop_info[ii].var, INIT_EXPR,
+			     build_zero_cst (typ), 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);
+  append_to_statement_list (an_init, &loop_with_init);
   body = stmt;
 
   for (ii = 0; ii < rank; ii++)
@@ -1017,7 +941,7 @@ cp_expand_cond_array_notations (tree orig_stmt)
 		      an_loop_info[ii].incr, body);
       body = pop_stmt_list (new_loop);
     }
-  append_to_statement_list_force (body, &loop_with_init);
+  append_to_statement_list (body, &loop_with_init);
 
   an_info.release ();
   an_loop_info.release ();
@@ -1062,14 +986,14 @@ expand_unary_array_notation_exprs (tree orig_stmt)
 	  {
 	    vec<tree, va_gc> *sub_list = NULL, *new_var_list = NULL;
 	    stmt = alloc_stmt_list ();
-	    append_to_statement_list_force (builtin_loop, &stmt);
+	    append_to_statement_list (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);
+    append_to_statement_list (finish_expr_stmt (orig_stmt), &stmt);
   else
     stmt = orig_stmt;
   rank = 0;
@@ -1089,22 +1013,19 @@ expand_unary_array_notation_exprs (tree orig_stmt)
   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);
+      make_triplet_val_inv (&ARRAY_NOTATION_START (array_node));
+      make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (array_node));
+      make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (array_node));
     }
   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));
+      tree typ = ptrdiff_type_node;
+      an_loop_info[ii].var = create_temporary_var (typ);
+      add_decl_expr (an_loop_info[ii].var);
       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)),
+	(location, an_loop_info[ii].var, INIT_EXPR, build_zero_cst (typ), 
 	 tf_warning_or_error);
     }
   array_operand = create_array_refs (location, an_info, an_loop_info,
@@ -1113,7 +1034,7 @@ expand_unary_array_notation_exprs (tree orig_stmt)
   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);
+  append_to_statement_list (an_init, &loop_with_init);
   body = stmt;
   
   for (ii = 0; ii < rank; ii++)
@@ -1123,7 +1044,7 @@ expand_unary_array_notation_exprs (tree orig_stmt)
 		      an_loop_info[ii].incr, body);
       body = pop_stmt_list (new_loop);
     }
-  append_to_statement_list_force (body, &loop_with_init);
+  append_to_statement_list (body, &loop_with_init);
 
   an_info.release ();
   an_loop_info.release ();
@@ -1139,21 +1060,35 @@ static tree
 expand_return_expr (tree expr)
 {
   tree new_mod_list, new_var, new_mod, retval_expr;
-
+  size_t rank  = 0;
+  location_t loc = EXPR_LOCATION (expr);
   if (TREE_CODE (expr) != RETURN_EXPR)
     return expr;
+      
+  if (!find_rank (loc, expr, expr, false, &rank))
+    return error_mark_node;
 
-  location_t loc = EXPR_LOCATION (expr);
-  new_mod_list = alloc_stmt_list ();
+  /* If the return expression contains array notations, then flag it as
+     error.  */
+  if (rank >= 1)
+    {
+      error_at (loc, "array notation expression cannot be used as a return "
+		"value");
+      return error_mark_node;
+    }
+  
+  new_mod_list = push_stmt_list ();
   retval_expr = TREE_OPERAND (expr, 0);
-  new_var = build_decl (loc, VAR_DECL, NULL_TREE, TREE_TYPE (retval_expr));
+  new_var = create_temporary_var (TREE_TYPE (retval_expr));
+  add_decl_expr (new_var);
   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),
+				      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);
+  add_stmt (new_mod);
+  add_stmt (expr);
+  new_mod_list = pop_stmt_list (new_mod_list);
   return new_mod_list;
 }
 
@@ -1290,19 +1225,21 @@ expand_array_notation_exprs (tree 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:      
+    case FOR_STMT:
+      if (contains_array_notation_expr (FOR_COND (t)))
+	{
+	  error_at (EXPR_LOCATION (FOR_COND (t)),
+		    "array notation cannot be used in a condition for "
+		    "a for-loop");
+	  return error_mark_node;
+	}
       /* 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));
+	{ 
+	  FOR_BODY (t) = expand_array_notation_exprs (FOR_BODY (t));
+	  FOR_EXPR (t) = expand_array_notation_exprs (FOR_EXPR (t));
+	}
       else
 	t = expand_array_notation_exprs (t);
       return t;
@@ -1322,44 +1259,39 @@ expand_array_notation_exprs (tree t)
 	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 (contains_array_notation_expr (SWITCH_STMT_COND (t)))
 	{
-	  if (SWITCH_STMT_BODY (t))
-	    SWITCH_STMT_BODY (t) =
-	      expand_array_notation_exprs (SWITCH_STMT_BODY (t));
+	  error_at (EXPR_LOCATION (SWITCH_STMT_COND (t)),
+		    "array notation cannot be used as a condition for "
+		    "switch statement");
+	  return error_mark_node;
 	}
-      else
-	t = expand_array_notation_exprs (t);
+      if (SWITCH_STMT_BODY (t))
+	SWITCH_STMT_BODY (t) =
+	  expand_array_notation_exprs (SWITCH_STMT_BODY (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 (contains_array_notation_expr (WHILE_COND (t)))
 	{
-	  if (WHILE_BODY (t))
-	    WHILE_BODY (t) = expand_array_notation_exprs (WHILE_BODY (t));
+	  if (EXPR_LOCATION (WHILE_COND (t)) != UNKNOWN_LOCATION)
+	    loc = EXPR_LOCATION (WHILE_COND (t));
+	  error_at (loc, "array notation cannot be used as a condition for "
+		    "while statement");
+	  return error_mark_node;
 	}
-      else
-	t = expand_array_notation_exprs (t);
+      if (WHILE_BODY (t))
+	WHILE_BODY (t) = expand_array_notation_exprs (WHILE_BODY (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));
+      if (contains_array_notation_expr (DO_COND (t)))
+	{
+	  error_at (EXPR_LOCATION (DO_COND (t)),
+		    "array notation cannot be used as a condition for a "
+		    "do-while statement");
+	  return error_mark_node;
 	}
-      else
-	t = expand_array_notation_exprs (t);
+      if (DO_BODY (t))
+	DO_BODY (t) = expand_array_notation_exprs (DO_BODY (t));
       return t;
     default:
       if (is_expr)
@@ -1380,59 +1312,66 @@ expand_array_notation_exprs (tree 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.  */
+/* Given the base of an array (ARRAY), the START (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, 
+   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)
+build_array_notation_ref (location_t loc, tree array, tree start, 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 we enter the then-case of the if-statement below, we have hit a case 
+     like this: ARRAY [:].  */
+  if (!start && !length)
     {
-      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 (TREE_CODE (type) != ARRAY_TYPE)
+	{
+	  error_at (loc, "start-index and length fields necessary for "
+		    "using array notation in pointers or records");
+	  return error_mark_node;
+	}
+      tree domain = TYPE_DOMAIN (type);
+      if (!domain)
+	{
+	  error_at (loc, "start-index and length fields necessary for "
+		    "using array notation with array of unknown bound");
+	  return error_mark_node;
+	}
+      start = cp_fold_convert (ptrdiff_type_node, TYPE_MINVAL (domain));
+      length = size_binop (PLUS_EXPR, TYPE_MAXVAL (domain), size_one_node);
+      length = cp_fold_convert (ptrdiff_type_node, length);
     }
-  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 (!stride) 
+    stride = build_one_cst (ptrdiff_type_node);
+  
+  /* When dealing with templates, triplet type-checking will be done in pt.c 
+     after type substitution.  */
+  if (processing_template_decl 
+      && (type_dependent_expression_p (array) 
+	  || type_dependent_expression_p (length) 
+	  || type_dependent_expression_p (start) 
+	  || type_dependent_expression_p (stride))) 
+    array_ntn_expr = build_min_nt_loc (loc, ARRAY_NOTATION_REF, array, start, 
+				       length, stride, NULL_TREE);
+  else 
+    { 
+      if (!cilkplus_an_triplet_types_ok_p (loc, start, length, stride, type))
+	return error_mark_node;
+      array_ntn_expr = build4 (ARRAY_NOTATION_REF, NULL_TREE, array, start, 
+			       length, stride);
     }
+  if (TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == POINTER_TYPE)
+    TREE_TYPE (array_ntn_expr) = TREE_TYPE (type);
+  else
+    gcc_unreachable ();
 
-  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;
 }
 
@@ -1462,20 +1401,9 @@ cilkplus_an_triplet_types_ok_p (location_t loc, tree start_index, tree length,
     }
   if (!TREE_CODE (type) == FUNCTION_TYPE)
     {
-      error_at (loc, "array notations cannot be used with function type");
+      error_at (loc, "array notation 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))
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 38ef878..590d857 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -1207,6 +1207,12 @@ cp_genericize (tree fndecl)
   if (DECL_CLONED_FUNCTION_P (fndecl))
     return;
 
+  /* Expand all the array notations here.  */
+  if (flag_enable_cilkplus 
+      && contains_array_notation_expr (DECL_SAVED_TREE (fndecl)))
+    DECL_SAVED_TREE (fndecl) = 
+      expand_array_notation_exprs (DECL_SAVED_TREE (fndecl));
+
   /* We do want to see every occurrence of the parms, so we can't just use
      walk_tree's hash functionality.  */
   cp_genericize_tree (&DECL_SAVED_TREE (fndecl));
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 00ee450..a3438a8 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4974,6 +4974,7 @@ extern bool pragma_java_exceptions;
 
 /* in call.c */
 extern bool check_dtor_name			(tree, tree);
+bool magic_varargs_p                            (tree);
 
 extern tree build_conditional_expr		(location_t, tree, tree, tree, 
                                                  tsubst_flags_t);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
old mode 100644
new mode 100755
index ec8ad46..c2aa159
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -6060,41 +6060,31 @@ 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.  */
+/* This function parses Cilk Plus array notations.  If a normal array expr. is
+   parsed then the array index is passed back to the caller through *INIT_INDEX 
+   and the function returns a NULL_TREE.  If array notation expr. is parsed, 
+   then *INIT_INDEX is ignored by the caller and the function returns 
+   a 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,
+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;
-
+  tree length_index, stride = NULL_TREE, value_tree, array_type;
   if (!array_value || array_value == error_mark_node)
     {
       cp_parser_skip_to_end_of_statement (parser);
       return error_mark_node;
     }
+
+  array_type = TREE_TYPE (array_value);
   
-  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;
-    }
+  bool saved_colon_corrects = parser->colon_corrects_to_scope_p;
+  parser->colon_corrects_to_scope_p = false;
   token = cp_lexer_peek_token (parser->lexer);
+  
   if (!token)
     {
       cp_parser_error (parser, "expected %<:%> or numeral");
@@ -6102,125 +6092,57 @@ cp_parser_array_notation (location_t loc, cp_parser *parser, tree init_index,
     }
   else if (token->type == CPP_COLON)
     {
-      if (!init_index)
+      /* Consume the ':'.  */
+      cp_lexer_consume_token (parser->lexer);
+      
+      /* If we are here, then we have a case like this A[:].  */
+      if (cp_lexer_peek_token (parser->lexer)->type != CPP_CLOSE_SQUARE)
 	{
-	  /* 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);
+	  cp_parser_error (parser, "expected %<]%>");
+	  cp_parser_skip_to_end_of_statement (parser);
+	  return error_mark_node;
+	}
+      *init_index = NULL_TREE;
+      stride = NULL_TREE;
+      length_index = NULL_TREE;
+    }
+  else
+    {
+      /* If we are here, then there are three valid possibilities:
+	 1. ARRAY [ EXP ]
+	 2. ARRAY [ EXP : EXP ]
+	 3. ARRAY [ EXP : EXP : EXP ]  */
 
-	  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);
+      *init_index = cp_parser_expression (parser, false, NULL);	
+      if (cp_lexer_peek_token (parser->lexer)->type != CPP_COLON)
+	{  
+	  /* This indicates that we have a normal array expression.  */
+	  parser->colon_corrects_to_scope_p = saved_colon_corrects;
+	  return NULL_TREE;
 	}
-      else
+      
+      /* Consume the ':'.  */
+      cp_lexer_consume_token (parser->lexer);
+      length_index = cp_parser_expression (parser, false, NULL);
+      if (cp_lexer_peek_token (parser->lexer)->type == CPP_COLON)
 	{
-	  cp_parser_skip_to_end_of_statement (parser);
-	  return error_mark_node;
+	  cp_lexer_consume_token (parser->lexer);
+	  stride = cp_parser_expression (parser, false, NULL);
 	}
     }
-  
-  if (start_index == error_mark_node || length_index == error_mark_node
-      || stride == error_mark_node || !start_index || !length_index
-      || !stride)
+  parser->colon_corrects_to_scope_p = saved_colon_corrects;
+
+  if (*init_index == error_mark_node || length_index == error_mark_node
+      || stride == error_mark_node)
     {
       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);
+
+  value_tree = build_array_notation_ref (loc, array_value, *init_index, 
+					 length_index, stride, array_type);
   return value_tree;
 }
 
@@ -6239,84 +6161,68 @@ cp_parser_postfix_open_square_expression (cp_parser *parser,
 					  bool for_offsetof,
 					  bool decltype_p)
 {
-  tree index;
+  tree index = NULL_TREE;
   location_t loc = cp_lexer_peek_token (parser->lexer)->location;
 
   /* Consume the `[' token.  */
   cp_lexer_consume_token (parser->lexer);
 
-  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);
+  /* 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
     {
-      /* 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
+      if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
 	{
-	  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)
 	    {
-	      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;
-		}
+	      error_at (cp_lexer_peek_token (parser->lexer)->location,
+			"braced list index is not allowed with array "
+			"notation");
+	      cp_parser_skip_to_end_of_statement (parser);
+	      return 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
+      else if (flag_enable_cilkplus)
 	{
-  	  /* 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);
-
-	  /* 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;
+	  /* Here are have these two options:
+	     ARRAY[EXP : EXP]        - Array notation expr with default
+	     stride of 1.
+	     ARRAY[EXP : EXP : EXP] - Array Notation with user-defined
+	     stride.  */
+	  tree an_exp = cp_parser_array_notation (loc, parser, &index, 
+						  postfix_expression);
+	  if (an_exp)
+	    return an_exp;
 	}
+      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);
+
+  /* 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;
 }
 
@@ -9551,8 +9457,6 @@ 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;
 }
 
@@ -9745,14 +9649,6 @@ 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;
@@ -10310,12 +10206,6 @@ 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;
 
@@ -10342,15 +10232,6 @@ 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;
 
@@ -10369,17 +10250,8 @@ cp_parser_iteration_statement (cp_parser* parser)
 	cp_parser_already_scoped_statement (parser);
 	parser->in_statement = in_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);
+	/* We're done with the for-statement.  */
+	finish_for_stmt (statement);
       }
       break;
 
@@ -16952,54 +16824,30 @@ cp_parser_direct_declarator (cp_parser* parser,
 	  if (token->type != CPP_CLOSE_SQUARE)
 	    {
 	      bool non_constant_p;
-
-	      if (flag_enable_cilkplus
-		  && cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+	      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;
-		  error_at (cp_lexer_peek_token (parser->lexer)->location,
-			    "array notations cannot be used in declaration");
-		  cp_lexer_consume_token (parser->lexer);
 		}
-	      else
+	      else if (processing_template_decl)
 		{
-		  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; 
-		    }
+		  /* Remember this wasn't a constant-expression.  */
+		  bounds = build_nop (TREE_TYPE (bounds), bounds);
+		  TREE_SIDE_EFFECTS (bounds) = 1;
 		}
 	    }
 	  else
@@ -18370,11 +18218,6 @@ 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);
 
@@ -22354,12 +22197,6 @@ 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));
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 667e37f..4e7a284 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -13761,9 +13761,6 @@ tsubst_copy_and_build (tree t,
 	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)));
       }
@@ -15739,9 +15736,6 @@ 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;
@@ -19143,11 +19137,6 @@ 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);
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 0a460a4..87c1560 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -779,22 +779,6 @@ 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 ())
@@ -8089,7 +8073,6 @@ 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);
@@ -8901,7 +8884,6 @@ 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:
@@ -8912,6 +8894,9 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
 	  return false;
       return true;
 
+    case ARRAY_NOTATION_REF:
+      return false;
+
     case FMA_EXPR:
     case VEC_PERM_EXPR:
      for (i = 0; i < 3; ++i)
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 5b321ce..11592b4 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -3493,10 +3493,6 @@ cp_build_function_call_vec (tree function, vec<tree, va_gc> **params,
       params = &allocated;
     }
 
-  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)
@@ -3660,8 +3656,7 @@ convert_arguments (tree typelist, vec<tree, va_gc> **values, tree fndecl,
 	}
       else
 	{
-	  if (fndecl && DECL_BUILT_IN (fndecl)
-	      && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CONSTANT_P)
+	  if (fndecl && magic_varargs_p (fndecl))
 	    /* Don't do ellipsis conversion for __built_in_constant_p
 	       as this will result in spurious errors for non-trivial
 	       types.  */
@@ -3956,15 +3951,8 @@ cp_build_binary_op (location_t location,
 	}
     }
 
-  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);
+  type0 = TREE_TYPE (op0); 
+  type1 = TREE_TYPE (op1);
 
   /* The expression codes of the data types of the arguments tell us
      whether the arguments are integers, floating, pointers, etc.  */
@@ -5167,13 +5155,6 @@ 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)))
     {
@@ -7852,13 +7833,6 @@ 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);
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/decl-ptr-colon.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/decl-ptr-colon.c
index 68c8859..4b54f4d 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/decl-ptr-colon.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/decl-ptr-colon.c
@@ -1,3 +1,4 @@
+/* { dg-do compile { target c } } */
 /* { dg-options "-fcilkplus" } */
 
 int main(void)
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/dimensionless-arrays.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/dimensionless-arrays.c
index 69aaa52..690e89a 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/dimensionless-arrays.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/dimensionless-arrays.c
@@ -5,6 +5,6 @@ extern int *b;
 
 void foo()
 {
-  a[:] = 5;	// { dg-error "start-index and length fields necessary for using array notations in dimensionless arrays" }
-  b[:] = 5;    // { dg-error "start-index and length fields necessary for using array notations in pointers" }
+  a[:] = 5;	// { dg-error "start-index and length fields necessary for using array notation" }
+  b[:] = 5;    // { dg-error "start-index and length fields necessary for using" }
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/fn_ptr.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/fn_ptr.c
index 024a158..fa6d900 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/fn_ptr.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/fn_ptr.c
@@ -1,3 +1,4 @@
+/* { dg-do compile } */
 /* { dg-options "-fcilkplus" } */
 
 typedef int (*foo)(int);
@@ -10,11 +11,11 @@ int main(void)
   foo ***func_array_ptr;
   int argc = 5;
 
-  array[:] =  func_array[:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
-  func_array[0:5](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
-  func_array2[0:5][:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
-  array2[0:5][:] = func_array2[0:5][:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
-  func_array_ptr[0:5][0:4][0:argc:2](argc); /* { dg-error "array notations cannot be used with function pointer arrays" } */
+  array[:] =  func_array[:](10); 
+  func_array[0:5](10); 
+  func_array2[0:5][:](10);
+  array2[0:5][:] = func_array2[0:5][:](10);
+  func_array_ptr[0:5][0:4][0:argc:2](argc); 
 
   return 0;
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
index 14421d9..814786b 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
@@ -6,7 +6,7 @@ int main (void)
   int array[10], array2[10][10];
   int x, ii, jj ;
 
-  switch (array[:]) {  /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  switch (array[:]) {  /* { dg-error "cannot be used as a condition for switch statement" } */
   case 1:
     x = 5;
     break;
@@ -17,7 +17,7 @@ int main (void)
     x = 9;
   }
 
-  switch (array2[:][:]) { /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  switch (array2[:][:]) { /* { dg-error "cannot be used as a condition for switch statement" } */
   case 1:
     x = 5;
     break;
@@ -28,7 +28,7 @@ int main (void)
     x = 9;
   }
 
-  switch (array[:] + x) { /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  switch (array[:] + x) { /* { dg-error "cannot be used as a condition for switch statement" } */
   case 1:
     x = 5;
     break;
@@ -39,7 +39,7 @@ int main (void)
     x = 9;
   }
   
-  switch (array2[:][1:x:4] + x) { /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  switch (array2[:][1:x:4] + x) { /* { dg-error "cannot be used as a condition for switch statement" } */
   case 1:
     x = 5;
     break;
@@ -50,36 +50,36 @@ int main (void)
     x = 9;
   }
 
-  for (ii = 0; ii < array[:]; ii++) /* { dg-error "array notations cannot be used in a condition for a for-loop" } */
+  for (ii = 0; ii < array[:]; ii++) /* { dg-error "cannot be used in a condition for a for-loop" } */
     {
       x = 2;
     }
 
-  for (ii = 0; ii < array2[:][:]; ii++) /* { dg-error "array notations cannot be used in a condition for a for-loop" } */
+  for (ii = 0; ii < array2[:][:]; ii++) /* { dg-error "cannot be used in a condition for a for-loop" } */
     {
       x = 3;
     }
 
-  for (; array2[:][:] < 2;) /* { dg-error "array notations cannot be used in a condition for a for-loop" } */
+  for (; array2[:][:] < 2;) /* { dg-error "cannot be used in a condition for a for-loop" } */
     x = 4;
 
 
-  while (array2[:][:]) /* { dg-error "array notations cannot be used as a condition for while statement" } */
+  while (array2[:][:]) /* { dg-error "cannot be used as a condition for while statement" } */
     x = 3;
 
-  while (array[1:1:1]) /* { dg-error "array notations cannot be used as a condition for while statement" } */
+  while (array[1:1:1]) /* { dg-error "cannot be used as a condition for while statement" } */
     x = 1;
 
-  while (ii != array2[1:x:3][1:2:1]) /* { dg-error "array notations cannot be used as a condition for while statement"  } */
+  while (ii != array2[1:x:3][1:2:1]) /* { dg-error "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" "" { target c } } */
+  do { /* { dg-error "cannot be used as a condition for a do-while statement" "" { target c } } */
     x = 3;
-  } while (ii != array2[:][:]); /* { dg-error "array notations cannot be used as a condition for a do-while statement" "" { target c++ } } */
+  } while (ii != array2[:][:]); /* { dg-error "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" "" { target c } } */
+  do {  /* { dg-error "cannot be used as a condition for a do-while statement" "" { target c } } */
     x = 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++ } } */
+  } while (ii != (x + array2[:][1:x:2]) + 2); /* { dg-error "cannot be used as a condition for a do-while statement" "" { target c++ } } */
   
   do { 
     x += 3;
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/rank_mismatch.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/rank_mismatch.c
index b5e37ce..eb3c1f1 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/rank_mismatch.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/rank_mismatch.c
@@ -10,6 +10,7 @@ int main (void)
   int array[10][10], array2[10];
 
   array[:][:] = array[:]; /* { dg-error "rank mismatch between" } */
+  /* { dg-error "invalid conversion" "" { target c++ } 12 } */
 
   x = array2[:]; /* { dg-error "cannot be scalar when" } */
 

[-- Attachment #3: CL.txt --]
[-- Type: text/plain, Size: 6008 bytes --]

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

        * builtins.def: Fixed the function type of CILKPLUS_BUILTIN.

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

        * c-parser.c (c_parser_array_notation): Removed rejection of array
        notations in an array of function pointers.

gcc/c-family/ChangeLog
2013-06-28  Balaji V. Iyer  <balaji.v.iyer@intel.com>

        * array-notation-common.c (length_mismatch_in_expr_p): Collapsed two
        if-statements and compared the trees directly using tree_int_cst_equal.
        (find_rank): Checked for array notations in function name to handle
        array notations in function pointers.
        (extract_array_notation_exprs): Likewise.
        (replace_array_notations): Likewise.
        (cilkplus_extract_an_triplets): Replaced safe_push with
        safe_grow_cleared.  Also removed an unnecessary check to see if the
        node is of type ARRAY_NOTATION_REF.
        (fix_sec_implicit_args): Removed an unnecessary check for ADDR_EXPR.
        Also switched two if-statements to remove an unnecessary comparison.


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

        * parser.c (cp_parser_array_notation): Removed rejection array notation
        of type function pointers. Added handling of array expressions when
        Cilk Plus is enabled.  Took out type-checking.
        (cp_parser_postfix_open_square_expression): Moved normal array expr.
        parsing into cp_parser_array_notation when cilkplus is enabled.
        (cp_parser_compound_statement): Removed expansion of array notations.
        (cp_parser_ctor_initializer_opt_and_function_body): Likewise.
        (cp_parser_function_definition_after_declarator): Likewise.
        (cp_parser_selection_statement): Removed error reporting.
        (cp_parser_iteration_statement): Likewise.
        (cp_parser_direct_declarator): Removed error checking/reporting if
        array notations are used in the declarator.
        * pt.c (instantiate_decl): Likewise.
        (type_unification_real): Removed a check for ARRAY_NOTATION_REF.
        (cxx_eval_constant_expression): Removed ARRAY_NOTATION_REF case.
        (potential_constant_expression_1): Returned false for ARRAY_NOTATION_REF
        case.
	(tsubst_copy_and_build): Removed type checking of array notation triplets.
        * cp-gimplify.c (cp_genericize): Added expansion of array notation
        expressions here.
        * cp-array-notation.c (make_triplet_val_inv): Removed loc and cry 
        parameters.  Replaced build_decls with get_temp_regvar with type as
        ptrdiff.
        (create_array_refs): Made the type-casting to ptrdiff_type unconditional.
        (replace_invariant_var): Added a check for void return type before 
	creating new var.  Replaced build_decl and build_min_nt_loc with
        get_temp_regvar.
        (expand_an_in_modify_expr): Ditto.  Replaced body of redundant else with
        gcc_unreachable.  Removed few unwanted checks.  Made induction variable
        type as ptrdiff_type.  Removed loc and complain arguments passed into
        make_triplet_val_inv.  Replaced all modify expression's code from NOP
        EXPR to INIT EXPR.  Replaced all forceful appending into stmt. list
        with the non-forceful one.  Replaced some integer conversion and
        equality-checking to using tree_int_cst_equal.
        (expand_sec_reduce_builtin): All changes mentioned in above function
        expand_an_in_modify_expr.  Made the new variable type of
        SEC_REDUCE_ANY/ALL_{NON}ZERO intrinsic functions as bool.
        (expand_array_notation_exprs): Removed SWITCH_EXPR case.  Moved all
        the error reporting from parser to this function.  Removed unwanted
        statements and checks from SWITCH_STMT, WHILE_STMT, and DO_STMT cases.
        (cilkplus_an_triplet_types_ok_p): Removed rejection of array notation
        in function pointers.
        (cp_expand_cond_array_notations): Added a new if statements to check
        if condition has a zero rank.  If so, then just return.
        (expand_return_expr): Added a check for return expressions with a rank.
        Replaced get_tmp_regvar with a create_temporary_var.
        (build_array_notation_ref): Simplified and removed unwanted if-stmts.
        Moved common code outside if-statements.  Moved type-checking from
        parser to here.
        * semantics.c (finish_return_stmt): Removed a check for return exprs.
        with a rank.
        * call.c (convert_like_real): Removed a check for array notation
        expression in a function.
        (build_over_call): Likewise.
        (magic_varargs_p): Added a check for builtin array notation function.
        Made this function non-static and removed its prototype.
        * cp-tree.h (magic_varargs_p): New prototype.
        * typeck.c (cp_build_function_call_vec): Removed automatic setting of
        nargs to the param->length when builtin reduction function is used.
        (convert_arguments): Replaced check for a constant_p function with
        margic_varargs_p function call.
        (cp_build_binary_op): Removed calling of the function
        find_correct_array_notation_type.
        (cp_build_addr_expr_1): Removed an unwanted if-statement.
        (convert_for_assignment): Removed automatic return of rhs when array
        notation builtin function is used.

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

        * c-c++-common/cilk-plus/AN/decl-ptr-colon.c (main): Made this testcase
        c specific.
        * c-c++-common/cilk-plus/AN/decl-ptr-colon.c (main): Changed dg-error
        strings to match the fixed error messages.
        * c-c++-common/cilk-plus/AN/misc.c (main): Likewise.
        * c-c++-common/cilk-plus/AN/rank_mismatch.c (main): Added a new error
        message check.


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH] Cilk Plus Array Notation for C++
  2013-06-28 15:03                                                 ` Iyer, Balaji V
@ 2013-06-28 18:58                                                   ` Jason Merrill
  0 siblings, 0 replies; 40+ messages in thread
From: Jason Merrill @ 2013-06-28 18:58 UTC (permalink / raw)
  To: Iyer, Balaji V, Richard Henderson; +Cc: Aldy Hernandez, gcc-patches

OK.

Jason

^ permalink raw reply	[flat|nested] 40+ messages in thread

end of thread, other threads:[~2013-06-28 18:56 UTC | newest]

Thread overview: 40+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-06-10 20:21 [PATCH] Cilk Plus Array Notation for C++ Iyer, Balaji V
2013-06-12 16:34 ` Aldy Hernandez
2013-06-12 17:20   ` Iyer, Balaji V
2013-06-12 17:40     ` Aldy Hernandez
2013-06-12 18:02       ` Iyer, Balaji V
2013-06-12 20:50   ` Iyer, Balaji V
2013-06-13 16:11     ` Aldy Hernandez
2013-06-13 16:18       ` Richard Henderson
2013-06-17 17:00         ` Iyer, Balaji V
2013-06-17 17:06           ` Richard Henderson
2013-06-17 18:29             ` Iyer, Balaji V
2013-06-18 23:42               ` Aldy Hernandez
2013-06-19  4:07                 ` Iyer, Balaji V
2013-06-20 17:54                   ` Richard Henderson
2013-06-20 23:39                     ` Iyer, Balaji V
2013-06-21 16:11                       ` Richard Henderson
2013-06-21 16:59                         ` Iyer, Balaji V
2013-06-21 17:00                           ` Richard Henderson
2013-06-21 19:35                             ` Iyer, Balaji V
2013-06-22 16:20                       ` Jason Merrill
2013-06-24 15:16                         ` Jason Merrill
2013-06-24 22:23                         ` Iyer, Balaji V
2013-06-25 14:38                           ` Jason Merrill
2013-06-25 18:27                             ` Iyer, Balaji V
2013-06-25 20:55                               ` Jason Merrill
2013-06-26 17:32                                 ` Iyer, Balaji V
2013-06-26 20:12                                   ` Jason Merrill
2013-06-27 15:52                                     ` Iyer, Balaji V
2013-06-27 15:54                                       ` Iyer, Balaji V
2013-06-27 18:39                                         ` Iyer, Balaji V
2013-06-27 23:05                                           ` Jason Merrill
2013-06-28  6:01                                             ` Iyer, Balaji V
2013-06-28 13:43                                               ` Jason Merrill
2013-06-28 13:48                                               ` Jason Merrill
2013-06-28 15:03                                                 ` Iyer, Balaji V
2013-06-28 18:58                                                   ` Jason Merrill
2013-06-25 18:42                             ` Iyer, Balaji V
2013-06-26 13:00                               ` Aldy Hernandez
2013-06-17 16:49       ` Iyer, Balaji V
2013-06-12 21:32   ` Iyer, Balaji V

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).