Patchwork Cilk Plus Array Notation for C++

login
register
mail settings
Submitter Iyer, Balaji V
Date June 17, 2013, 4:48 p.m.
Message ID <BF230D13CA30DD48930C31D4099330003A43913E@FMSMSX101.amr.corp.intel.com>
Download mbox | patch
Permalink /patch/251930/
State New
Headers show

Comments

Iyer, Balaji V - June 17, 2013, 4:48 p.m.
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

Patch

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