diff mbox

Cilk Plus Array Notation for C++

Message ID BF230D13CA30DD48930C31D4099330003A42E503@FMSMSX101.amr.corp.intel.com
State New
Headers show

Commit Message

Iyer, Balaji V June 12, 2013, 9:32 p.m. UTC
Hi Aldy et al.,
	I am sorry but I forgot to cut and paste the ChangeLog entries in my previous reply.  I am also attaching the patch again, so that they can all be in the same message.

Here you go:

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

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

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

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


Thanks,

Balaji V. Iyer.

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

Patch

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
old mode 100644
new mode 100755
index 2c93982..362f0bc
Binary files a/gcc/cp/ChangeLog and b/gcc/cp/ChangeLog differ
diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
index df8ed3e..6e80bcf 100644
--- a/gcc/cp/Make-lang.in
+++ b/gcc/cp/Make-lang.in
@@ -80,7 +80,7 @@  CXX_AND_OBJCXX_OBJS = cp/call.o cp/decl.o cp/expr.o cp/pt.o cp/typeck2.o \
  cp/typeck.o cp/cvt.o cp/except.o cp/friend.o cp/init.o cp/method.o \
  cp/search.o cp/semantics.o cp/tree.o cp/repo.o cp/dump.o cp/optimize.o \
  cp/mangle.o cp/cp-objcp-common.o cp/name-lookup.o cp/cxx-pretty-print.o \
- cp/cp-gimplify.o $(CXX_C_OBJS)
+ cp/cp-gimplify.o cp/cp-array-notation.o $(CXX_C_OBJS)
 
 # Language-specific object files for C++.
 CXX_OBJS = cp/cp-lang.o c-family/stub-objc.o $(CXX_AND_OBJCXX_OBJS)
@@ -266,6 +266,9 @@  CXX_PRETTY_PRINT_H = cp/cxx-pretty-print.h $(C_PRETTY_PRINT_H)
 cp/lex.o: cp/lex.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) \
   $(C_PRAGMA_H) input.h cp/operators.def $(TM_P_H) \
   c-family/c-objc.h
+cp/cp-array-notation.o: cp/cp-array-notation.c $(CONFIG_H) $(SYSTEM_H) \
+  coretypes.h $(TREE_H) $(CXX_TREE_H) $(DIAGNOSTIC_H) tree-iterator.h vec.h \
+  $(GIMPLE_H) c-family/array-notation-common.o $(C_COMMON_H) 
 cp/cp-lang.o: cp/cp-lang.c $(CXX_TREE_H) $(TM_H) debug.h langhooks.h \
   $(LANGHOOKS_DEF_H) $(C_COMMON_H) gtype-cp.h gt-cp-cp-lang.h \
   cp/cp-objcp-common.h $(EXPR_H) $(TARGET_H) $(CXX_PARSER_H)
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index dfd061a..64be41f 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -5858,9 +5858,15 @@  convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
 	    break;
 	}
 
-      if (permerror (loc, "invalid conversion from %qT to %qT",
-		     TREE_TYPE (expr), totype)
-	  && fn)
+      if (flag_enable_cilkplus
+	  && (contains_array_notation_expr (expr)
+	      || contains_array_notation_expr (fn)))
+	/* If we are using array notations, we fix them up at a later stage
+	   and we will do these checks then.  */
+	;
+      else if (permerror (loc, "invalid conversion from %qT to %qT",
+			  TREE_TYPE (expr), totype)
+	       && fn)
 	inform (DECL_SOURCE_LOCATION (fn),
 		"initializing argument %P of %qD", argnum, fn);
 
@@ -6890,12 +6896,20 @@  build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
 	    }
 	}
 
-      val = convert_like_with_context (conv, arg, fn, i-is_method,
-	                               conversion_warning
-				       ? complain
-				       : complain & (~tf_warning));
+      /* If the function call is builtin array notation function then no need
+	 to do any type conversion.  */
+      if (flag_enable_cilkplus
+	  && is_cilkplus_reduce_builtin (fn) != BUILT_IN_NONE)
+	val = arg;
+      else
+	{
+	  val = convert_like_with_context (conv, arg, fn, i-is_method,
+					   conversion_warning
+					   ? complain
+					   : complain & (~tf_warning));
 
-      val = convert_for_arg_passing (type, val, complain);
+	  val = convert_for_arg_passing (type, val, complain);
+	}
       if (val == error_mark_node)
         return error_mark_node;
       else
diff --git a/gcc/cp/cp-array-notation.c b/gcc/cp/cp-array-notation.c
new file mode 100755
index 0000000..34c73f3
--- /dev/null
+++ b/gcc/cp/cp-array-notation.c
@@ -0,0 +1,2850 @@ 
+/* This file is part of the Intel(R) Cilk(TM) Plus support
+   It contains routines to handle Array Notation expression
+   handling routines in the C++ Compiler.
+   Copyright (C) 2013  Free Software Foundation, Inc.
+   Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com>,
+                  Intel Corporation
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+/* The Array Notation Transformation Technique:
+
+   An array notation expression has 4 major components:
+   1. The array name
+   2. Start Index
+   3. Number of elements we need to acess (we call it length)
+   4. Stride
+
+   So, if we have something like A[0:5:2], we are accessing A[0], A[2], A[4],
+   A[6] and A[8]. The user is responsible to make sure the access length does
+   not step outside the array's size.
+   
+   In this section, I highlight the overall method on how array notations are
+   broken up into C/C++ code.  Almost all the functions follows this step:
+
+   Let's say the user has used the array notation in a statement like this:
+
+   A[St1:Ln:Str1] = B[St2:Ln:Str2] + <NON ARRAY_NOT STMT>
+
+   where St{1,2} = Starting index, Ln = Number of elements we need to access,
+   and Str{1,2} = the stride.
+   Note: The length of both the array notation expressions must be the same.
+   
+   The above expression is broken into the following:
+
+   for (Tmp_Var = 0; Tmp_Var < Ln; Tmp_Var++)
+     A[St1 + Tmp_Var * Str1] = B[St1 + Tmp_Var * Str2] + <NON_ARRAY_NOT_STMT>;
+*/
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "cp-tree.h"
+#include "c-family/c-common.h"
+#include "diagnostic.h"
+#include "tree-iterator.h"
+#include "vec.h"
+#include "gimple.h"
+
+
+/* Creates a FOR_STMT with INIT, COND, INCR and BODY as the initializer,
+   condition, increment expression and the loop-body, respectively.  */
+
+static void
+create_an_loop (tree init, tree cond, tree incr, tree body)
+{
+  tree for_stmt;
+
+  finish_expr_stmt (init);
+  for_stmt = begin_for_stmt (NULL_TREE, NULL_TREE);
+  finish_for_init_stmt (for_stmt);
+  finish_for_cond (cond, for_stmt);
+  finish_for_expr (incr, for_stmt);
+  finish_expr_stmt (body);
+  finish_for_stmt (for_stmt);
+}
+
+/* Replaces all the scalar expressions in *NODE.  Returns a STATEMENT LIST that
+   holds the NODE along with the variables that hold the results of the
+   invariant expressions.  */
+
+static tree
+replace_invariant_exprs (tree *node)
+{
+  size_t ix = 0;
+  tree node_list = NULL_TREE;
+  tree t = NULL_TREE, new_var = NULL_TREE, new_node; 
+  struct inv_list data;
+
+  data.list_values = NULL;
+  data.replacement = NULL;
+  data.additional_tcodes = NULL;
+  cp_walk_tree (node, find_inv_trees, (void *) &data, NULL);
+
+  if (vec_safe_length (data.list_values))
+    {
+      node_list = push_stmt_list ();
+      for (ix = 0; vec_safe_iterate (data.list_values, ix, &t); ix++)
+	{
+	  if (processing_template_decl || !TREE_TYPE (t))
+	    new_var = build_min_nt_loc (EXPR_LOCATION (t), VAR_DECL, NULL_TREE,
+				       	NULL_TREE);
+	  else
+	    new_var = build_decl (EXPR_LOCATION (t), VAR_DECL, NULL_TREE,
+				  TREE_TYPE (t));
+	  gcc_assert (new_var != NULL_TREE && new_var != error_mark_node);
+	  new_node = build_x_modify_expr (EXPR_LOCATION (t), new_var, NOP_EXPR,
+					  t, tf_warning_or_error);
+	  finish_expr_stmt (new_node);
+	  vec_safe_push (data.replacement, new_var);
+	}
+      cp_walk_tree (node, replace_inv_trees, (void *) &data, NULL);
+      node_list = pop_stmt_list (node_list);
+    }
+  return node_list;
+}
+
+/* Returns true if NODE has a call_expression with ARRAY_NOTATION_REF tree.  */
+
+static bool
+has_call_expr_with_array_notation (tree node)
+{
+  int ii = 0;
+  
+  if (!contains_array_notation_expr (node))
+    return false;
+  
+  if (TREE_CODE (node) == ARRAY_NOTATION_REF)
+    return false;
+  else if (TREE_CODE (node) == DECL_EXPR)
+    {
+      tree x = DECL_EXPR_DECL (node);
+      if (x && TREE_CODE (x) != FUNCTION_DECL)
+	if (DECL_INITIAL (x))
+	  return has_call_expr_with_array_notation (DECL_INITIAL (x));
+	
+    }
+  else if (TREE_CODE (node) == STATEMENT_LIST)
+    {
+      tree_stmt_iterator ii_tsi;
+      for (ii_tsi = tsi_start (node); !tsi_end_p (ii_tsi); tsi_next (&ii_tsi))
+	return has_call_expr_with_array_notation (*tsi_stmt_ptr (ii_tsi));
+    }
+  else if (TREE_CODE (node) == CALL_EXPR)
+    {
+      if (is_cilkplus_reduce_builtin (CALL_EXPR_FN (node)) != BUILT_IN_NONE)
+	return true;
+	
+      if (is_sec_implicit_index_fn (CALL_EXPR_FN (node)))
+	return true;
+	 
+      if (TREE_CODE (TREE_OPERAND (node, 0)) == INTEGER_CST)
+	{
+	  int length = TREE_INT_CST_LOW (TREE_OPERAND (node, 0));
+	  bool x = false;
+	  for (ii = 0; ii < length; ii++)
+	    x |= contains_array_notation_expr (TREE_OPERAND (node, ii));
+	  return x;
+	}
+      else
+	gcc_unreachable  ();	  
+    } 
+  else
+    {
+      bool x = false;
+      for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (node)); ii++) 
+	x |= has_call_expr_with_array_notation (TREE_OPERAND (node, ii));
+      return x;
+    }
+  return false;
+}
+
+/* Replace array notation's built-in function passed in AN_BUILTIN_FN with
+   the appropriate loop and computation (all stored in variable LOOP of type
+   tree node).  The output of the function function is always a scalar and that
+   result is returned in *NEW_VAR.  *NEW_VAR is NULL_TREE if the function is
+   __sec_reduce_mutating.  */
+
+static tree
+expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
+{
+  tree new_var_type = NULL_TREE, func_parm, new_expr, new_yes_expr, new_no_expr;
+  tree array_ind_value = NULL_TREE, new_no_ind, new_yes_ind, new_no_list;
+  tree new_yes_list, new_cond_expr; 
+  tree new_var_init = NULL_TREE, new_exp_init = NULL_TREE;
+  vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
+  int s_jj = 0;
+  size_t list_size = 0, rank = 0, ii = 0, jj = 0;
+  tree **array_ops, *array_var, jj_tree;
+  tree **array_value, **array_stride, **array_length, **array_start;
+  tree  body, an_init, loop_with_init = alloc_stmt_list ();
+  tree *compare_expr, array_op0, *expr_incr, *ind_init, comp_node;
+  tree call_fn = NULL_TREE, identity_value = NULL_TREE, new_call_expr;
+  bool **count_down, **array_vector;
+  tree begin_var, lngth_var, strde_var;
+  location_t location = UNKNOWN_LOCATION;
+  tsubst_flags_t complain = tf_warning_or_error;
+
+  enum built_in_function an_type =
+    is_cilkplus_reduce_builtin (CALL_EXPR_FN (an_builtin_fn));
+  
+  if (an_type == BUILT_IN_NONE)
+    return NULL_TREE;
+
+  if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE
+      && an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
+    func_parm = CALL_EXPR_ARG (an_builtin_fn, 0);
+  else
+    {
+      call_fn = CALL_EXPR_ARG (an_builtin_fn, 2);
+
+      /* We need to do this because we are "faking" the builtin function types,
+	 so the compiler does a bunch of typecasts and this will get rid of
+	 all that!  */
+      while (TREE_CODE (call_fn) == CONVERT_EXPR
+	     || TREE_CODE (call_fn) == NOP_EXPR)
+	call_fn = TREE_OPERAND (call_fn, 0);
+
+      if (TREE_CODE (call_fn) != OVERLOAD
+	  && TREE_CODE (call_fn) != FUNCTION_DECL)
+	call_fn = TREE_OPERAND (call_fn, 0);
+      identity_value = CALL_EXPR_ARG (an_builtin_fn, 0);
+      func_parm = CALL_EXPR_ARG (an_builtin_fn, 1);
+
+      /* We need to do this because we are "faking" the builtin function types
+	 so the compiler does a bunch of typecasts and this will get rid of
+	 all that!  */
+      while (TREE_CODE (identity_value) == CONVERT_EXPR
+	     || TREE_CODE (identity_value) == NOP_EXPR)
+	identity_value = TREE_OPERAND (identity_value, 0);
+    }
+
+  while (TREE_CODE (func_parm) == CONVERT_EXPR
+	 || TREE_CODE (func_parm) == NOP_EXPR)
+    func_parm = TREE_OPERAND (func_parm, 0);
+  
+  location = EXPR_LOCATION (an_builtin_fn);
+  if (!find_rank (location, an_builtin_fn, an_builtin_fn, true, &rank))
+      return error_mark_node;
+  if (rank == 0)
+    return an_builtin_fn;
+  else if (rank > 1 
+	   && (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
+	       || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND))
+    { 
+      error_at (location, "__sec_reduce_min_ind or __sec_reduce_max_ind cannot "
+		"have arrays with dimension greater than 1");
+      return error_mark_node;
+    }
+  
+  extract_array_notation_exprs (func_parm, true, &array_list);
+  list_size = vec_safe_length (array_list);
+    switch (an_type)
+    {
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD:
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL:
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX:
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN:
+      new_var_type = TREE_TYPE ((*array_list)[0]);
+      break;
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO:
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO:
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO:
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO:
+      new_var_type = integer_type_node;
+      break;
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
+      new_var_type = size_type_node;
+      break;
+    case BUILT_IN_CILKPLUS_SEC_REDUCE:
+      if (call_fn && identity_value)
+	new_var_type = TREE_TYPE ((*array_list)[0]);
+      break;
+    case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING:
+      new_var_type = NULL_TREE;
+      break;
+    default:
+      gcc_unreachable ();
+    }
+    
+  if (new_var_type && TREE_CODE (new_var_type) == ARRAY_TYPE)
+    new_var_type = TREE_TYPE (new_var_type);
+  
+  array_ops = XNEWVEC (tree *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_ops[ii] = XNEWVEC (tree,  rank);
+  
+  array_vector = XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_vector[ii] = XNEWVEC (bool, rank);
+
+  array_value =  XNEWVEC (tree *, list_size);
+  array_stride =  XNEWVEC (tree *, list_size);
+  array_length =  XNEWVEC (tree *, list_size);
+  array_start =  XNEWVEC (tree *, list_size);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      array_value[ii]  = XNEWVEC (tree, rank);
+      array_stride[ii] = XNEWVEC (tree, rank);
+      array_length[ii] = XNEWVEC (tree, rank);
+      array_start[ii]  = XNEWVEC (tree, rank);
+    }
+
+  compare_expr = XNEWVEC (tree, rank);
+  expr_incr = XNEWVEC (tree, rank);
+  ind_init = XNEWVEC (tree, rank);
+  
+  count_down = XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    count_down[ii] = XNEWVEC (bool, rank);
+  
+  array_var = XNEWVEC (tree, rank);
+  an_init = push_stmt_list ();
+
+    /* Assign the array notation components to variable so that they can satisfy
+       the exec-once rule.  */
+  for (ii = 0; ii < list_size; ii++)
+    {
+      tree array_node = (*array_list)[ii];
+      tree array_begin = ARRAY_NOTATION_START (array_node);
+      tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
+      tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
+      if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF)
+	{
+	  if (TREE_CODE (array_begin) != INTEGER_CST)
+	    {
+	      begin_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, begin_var,
+						     NOP_EXPR, array_begin,
+						     complain));
+	      ARRAY_NOTATION_START (array_node) = begin_var;
+	    }
+	  if (TREE_CODE (array_lngth) != INTEGER_CST)
+	    {
+	      lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, lngth_var,
+						     NOP_EXPR, array_lngth,
+						     complain));
+	      ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
+	    }
+	  if (TREE_CODE (array_strde) != INTEGER_CST)
+	    {
+	      strde_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, strde_var,
+						     NOP_EXPR, array_strde,
+						     complain));
+	      ARRAY_NOTATION_STRIDE (array_node) = strde_var;
+	    }
+	}
+    }
+  for (ii = 0; ii < list_size; ii++)
+    {
+      jj = 0;
+      jj_tree = (*array_list)[ii];
+      while (jj_tree)
+	{
+	  if (TREE_CODE (jj_tree) == ARRAY_NOTATION_REF)
+	    {
+	      array_ops[ii][jj] = jj_tree;
+	      jj++;
+	      jj_tree = ARRAY_NOTATION_ARRAY (jj_tree);
+	    }
+	  else if (TREE_CODE (jj_tree) == ARRAY_REF)
+	    jj_tree = TREE_OPERAND (jj_tree, 0);
+	  else if (TREE_CODE (jj_tree) == VAR_DECL
+		   || TREE_CODE (jj_tree) == PARM_DECL)
+	    break;
+	}
+    }
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      if (TREE_CODE ((*array_list)[ii]) == ARRAY_NOTATION_REF)
+	for (jj = 0; jj < rank; jj++)
+	  {
+	    if (TREE_CODE (array_ops[ii][jj]) == ARRAY_NOTATION_REF)
+	      {
+		array_value[ii][jj] =
+		  ARRAY_NOTATION_ARRAY (array_ops[ii][jj]);
+		array_start[ii][jj] =
+		  ARRAY_NOTATION_START (array_ops[ii][jj]);
+		array_length[ii][jj] =
+		  fold_build1 (CONVERT_EXPR, integer_type_node,
+			       ARRAY_NOTATION_LENGTH (array_ops[ii][jj]));
+		array_stride[ii][jj] =
+		  ARRAY_NOTATION_STRIDE (array_ops[ii][jj]);
+		array_vector[ii][jj] = true;
+
+		if (!TREE_CONSTANT (array_length[ii][jj])
+		    || TREE_CODE (array_length[ii][jj]) != INTEGER_TYPE)
+		  count_down[ii][jj] = false;
+		else if (tree_int_cst_sgn (array_length[ii][jj]) == -1)
+		  count_down[ii][jj] = true;
+		else
+		  count_down[ii][jj] = false;
+	      }
+	    else
+	      array_vector[ii][jj] = false;
+	  }
+    }
+
+  for (ii = 0; ii < rank; ii++)
+    {
+      array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
+				  TREE_TYPE (array_start[0][ii]));
+      ind_init[ii] = build_x_modify_expr
+	(location, array_var[ii], NOP_EXPR, 
+	 build_zero_cst (TREE_TYPE (array_var[ii])), tf_warning_or_error);
+    }
+  for (ii = 0; ii < list_size; ii++)
+    if (array_vector[ii][0])
+      {
+	tree array_opr = array_value[ii][rank - 1];
+	for (s_jj = rank - 1; s_jj >= 0; s_jj--)
+	  {
+	    tree stride = NULL_TREE, var = NULL_TREE, start = NULL_TREE;
+
+	    /* If stride and start are of same type and the induction var
+	       is not, convert induction variable to stride's type.  */
+	    if ((TREE_TYPE (array_start[ii][s_jj]) ==
+		 TREE_TYPE (array_stride[ii][s_jj]))
+		&& (TREE_TYPE (array_stride[ii][s_jj]) !=
+		    TREE_TYPE (array_var[s_jj])))
+	      {
+		start = array_start[ii][s_jj];
+		stride = array_stride[ii][s_jj];
+		var =
+		  build_c_cast (location, TREE_TYPE (array_stride[ii][s_jj]),
+				array_var[s_jj]);
+	      }
+	    else if (TREE_TYPE (array_start[ii][s_jj]) !=
+		     TREE_TYPE (array_stride[ii][s_jj]))
+	      {
+		/* If we reach here, then the stride and start are of
+		   different types, and so it doesn't really matter what
+		   the induction variable type is, convert everything to 
+		   integer.  The reason why we pick an integer
+		   instead of something like size_t is because the stride
+		   and length can be + or -.  */
+		start = build_c_cast (location, integer_type_node,
+				      array_start[ii][s_jj]);
+		stride = build_c_cast (location, integer_type_node,
+				       array_stride[ii][s_jj]);
+		var = build_c_cast (location, integer_type_node,
+				    array_var[s_jj]);
+	      }
+	    else
+	      {
+		start = array_start[ii][s_jj];
+		stride = array_stride[ii][s_jj];
+		var = array_var[s_jj];
+	      }
+	    if (count_down[ii][s_jj])
+	      /* Array[start_index - (induction_var * stride)].  */
+	      array_opr = grok_array_decl
+		(location, array_opr,
+		 build2 (MINUS_EXPR, TREE_TYPE (var), start,
+			 build2 (MULT_EXPR, TREE_TYPE (var), var, stride)),
+		 false);	
+	    else
+	      /* Array[start_index + (induction_var * stride)].  */
+	      array_opr = grok_array_decl
+		(location, array_opr,
+		 build2 (PLUS_EXPR, TREE_TYPE (var), start,
+			 build2 (MULT_EXPR, TREE_TYPE (var), var, stride)),
+		 false);
+	  }
+	vec_safe_push (array_operand, array_opr);
+      }
+    else
+      vec_safe_push (array_operand, integer_one_node);
+    
+  replace_array_notations (&func_parm, true, array_list, array_operand);
+  
+  if (!TREE_TYPE (func_parm))      
+    TREE_TYPE (func_parm) = TREE_TYPE ((*array_list)[0]);
+  
+  for (ii = 0; ii < rank; ii++)
+    if (count_down[0][ii])
+      expr_incr[ii] = build_x_unary_op (location, POSTDECREMENT_EXPR,
+					array_var[ii], tf_warning_or_error);
+    else
+      expr_incr[ii] = build_x_unary_op (location, POSTINCREMENT_EXPR,
+					array_var[ii], tf_warning_or_error);
+  
+  for (jj = 0; jj < rank; jj++)
+    if (rank && expr_incr[jj])
+      {
+	if (count_down[0][jj])
+	  compare_expr[jj] = build_x_binary_op
+	    (location, GT_EXPR, array_var[jj], TREE_CODE (array_var[jj]),
+	     array_length[0][jj], TREE_CODE (array_length[0][jj]), NULL,
+	     tf_warning_or_error);
+	else
+	  compare_expr[jj] = build_x_binary_op
+	    (location, LT_EXPR, array_var[jj], TREE_CODE (array_var[jj]),
+	     array_length[0][jj], TREE_CODE (array_length[0][jj]), NULL,
+	     tf_warning_or_error);
+      } 
+  if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
+    {
+      if (processing_template_decl)
+	*new_var = build_decl (location, VAR_DECL, NULL_TREE, new_var_type);
+      else
+	*new_var = create_tmp_var (new_var_type, NULL);
+    }
+  else
+    /* We do not require a new variable for mutating.  The "identity value"
+       itself is a variable.  */
+    *new_var = NULL_TREE;
+  
+  if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
+      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND)
+    {
+      array_ind_value = create_tmp_var (TREE_TYPE (func_parm), NULL);
+      gcc_assert (array_ind_value && (array_ind_value != error_mark_node));
+      DECL_INITIAL (array_ind_value) = NULL_TREE;
+      pushdecl (array_ind_value);
+    }
+  array_op0 = (*array_operand)[0];
+  if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ADD)
+    {
+      if (ARITHMETIC_TYPE_P (new_var_type))
+	new_var_init = build_x_modify_expr (location, *new_var, 
+					    NOP_EXPR,
+					    build_zero_cst (new_var_type), 1);
+      else
+	new_var_init = build_x_modify_expr (location, *new_var, 
+					    NOP_EXPR,
+					    integer_zero_node, 1);
+      new_expr = build_x_modify_expr (location, *new_var, PLUS_EXPR, 
+				      func_parm, 1);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MUL)
+    {
+      if (ARITHMETIC_TYPE_P (new_var_type))
+	new_var_init = build_x_modify_expr (location, *new_var, 
+					    NOP_EXPR,
+					    build_one_cst (new_var_type), 1);
+      else
+	new_var_init = build_x_modify_expr (location, *new_var, 
+					    NOP_EXPR,
+					    integer_one_node, 1);
+      new_expr = build_x_modify_expr (location, *new_var, MULT_EXPR, 
+				      func_parm, 1);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO)
+    {
+      new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  build_one_cst (new_var_type), 1);
+      /* Initially you assume everything is zero, now if we find a case where
+	 it is NOT true, then we set the result to false. Otherwise we just
+	 keep the previous value.  */
+      new_yes_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  build_zero_cst (new_var_type), 1);
+      new_no_expr = build_x_modify_expr (location, *new_var, NOP_EXPR, 
+					 *new_var, 1);
+      if (ARITHMETIC_TYPE_P (TREE_TYPE (func_parm)))
+	comp_node = build_zero_cst (TREE_TYPE (func_parm));
+      else
+	comp_node = integer_zero_node;
+      new_cond_expr = build_x_binary_op
+	(location, NE_EXPR, func_parm, TREE_CODE (func_parm), comp_node,
+	 TREE_CODE (comp_node), NULL, tf_warning_or_error);
+      new_expr = build_x_conditional_expr (location, new_cond_expr, 
+					   new_yes_expr, new_no_expr, 
+					   tf_warning_or_error);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO)
+    {
+      new_var_init = build_x_modify_expr
+	(location, *new_var, NOP_EXPR, build_one_cst (new_var_type), 1);
+      /* Initially you assume everything is non-zero, now if we find a case
+	 where it is NOT true, then we set the result to false. Otherwise we
+	 just keep the previous value.  */
+      new_yes_expr = build_x_modify_expr
+	(location, *new_var, NOP_EXPR, 
+	 build_zero_cst (TREE_TYPE (*new_var)), 1);
+      new_no_expr = build_x_modify_expr (location, *new_var, NOP_EXPR, 
+					 *new_var, 1);
+      if (ARITHMETIC_TYPE_P (TREE_TYPE (func_parm)))
+	comp_node = build_zero_cst (TREE_TYPE (func_parm));
+      else
+	comp_node = integer_zero_node;
+      new_cond_expr = build_x_binary_op
+	(location, EQ_EXPR, func_parm, TREE_CODE (func_parm), comp_node,
+	 TREE_CODE (comp_node), NULL, tf_warning_or_error);
+      new_expr = build_x_conditional_expr (location, new_cond_expr, 
+					   new_yes_expr, new_no_expr, 
+					   tf_warning_or_error);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO)
+    {
+      new_var_init = build_x_modify_expr
+	(location, *new_var, NOP_EXPR, 
+	 build_zero_cst (new_var_type), 1);
+      /* Initially we assume there are NO zeros in the list. When we find a
+	 non-zero, we keep the previous value. If we find a zero, we set the
+	 value to true.  */
+      new_no_expr = build_x_modify_expr
+	(location, *new_var, NOP_EXPR, 
+	 build_one_cst (TREE_TYPE (*new_var)), 1);
+      new_yes_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  *new_var, 1);
+      if (ARITHMETIC_TYPE_P (TREE_TYPE (func_parm)))
+	comp_node = build_zero_cst (TREE_TYPE (func_parm));
+      else
+	comp_node = integer_zero_node;
+      new_cond_expr = build_x_binary_op
+	(location, EQ_EXPR, func_parm, TREE_CODE (func_parm), comp_node,
+	 TREE_CODE (comp_node), NULL, tf_warning_or_error);
+      new_expr = build_x_conditional_expr (location, new_cond_expr, 
+					   new_yes_expr, new_no_expr, 
+					   tf_warning_or_error);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO)
+    {
+      new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR, 
+					  build_zero_cst (new_var_type), 1);
+      /* Initially we assume there are NO non-zeros in the list. When we find a
+	 zero, we keep the previous value. If we find a zero, we set the value
+	 to true.  */
+      new_no_expr = build_x_modify_expr
+	(location, *new_var, NOP_EXPR, 
+	 build_one_cst (TREE_TYPE (*new_var)), 1);
+      new_yes_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  *new_var, 1);
+      if (ARITHMETIC_TYPE_P (TREE_TYPE (func_parm)))
+	comp_node = build_zero_cst (TREE_TYPE (func_parm));
+      else
+	comp_node = integer_zero_node;
+      new_cond_expr = build_x_binary_op
+	(location, NE_EXPR, func_parm, TREE_CODE (func_parm), comp_node,
+	 TREE_CODE (comp_node), NULL, tf_warning_or_error); 
+      new_expr = build_x_conditional_expr (location, new_cond_expr, 
+					   new_yes_expr, new_no_expr,
+					   tf_warning_or_error);      
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX)
+    {
+      /* If the TYPE_MIN_VALUE is available for the new_var_type, then
+	 set that as the initial value.  */
+      if (TYPE_MIN_VALUE (new_var_type))
+	new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					    TYPE_MIN_VALUE (new_var_type), 1);
+      else
+	/* ... otherwise set initial value as the first element of array.  */
+	new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					    func_parm, 1);
+      new_no_expr  = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  *new_var, 1);
+      new_yes_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  func_parm, 1);
+      new_cond_expr = build_x_binary_op (location, LT_EXPR, *new_var,
+					 TREE_CODE (*new_var), func_parm,
+					 TREE_CODE (func_parm), NULL,
+					 tf_warning_or_error);
+      new_expr = build_x_conditional_expr (location, new_cond_expr, 
+					   new_yes_expr, new_no_expr,
+					   tf_warning_or_error);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN)
+    {
+      /* If the TYPE_MAX_VALUE is available for the new_var_type, then
+	 set that as the initial value.  */
+      if (TYPE_MAX_VALUE (new_var_type))
+	new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					    TYPE_MAX_VALUE (new_var_type), 1);
+      else
+	/* ... otherwise set initial value as the first element of array.  */
+	new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					    func_parm, 1);
+      new_no_expr  = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  *new_var, 1);
+      new_yes_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  func_parm, 1);
+      new_cond_expr = build_x_binary_op (location, GT_EXPR, *new_var,
+					 TREE_CODE (*new_var), func_parm,
+					 TREE_CODE (func_parm), NULL,
+					 tf_warning_or_error);
+      new_expr = build_x_conditional_expr (location, new_cond_expr, 
+					   new_yes_expr, new_no_expr,
+					   tf_warning_or_error);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND)
+    {
+      new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  array_var[0], tf_warning_or_error);
+      new_exp_init = build_x_modify_expr (location, array_ind_value, 
+					  NOP_EXPR, func_parm, 
+					  tf_warning_or_error);
+      new_no_ind   = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  *new_var, tf_warning_or_error);
+      new_no_expr  = build_x_modify_expr (location, array_ind_value, 
+					  NOP_EXPR,
+					  array_ind_value, tf_warning_or_error);
+      if (list_size > 1)
+	new_yes_ind  = build_x_modify_expr (location, *new_var, 
+					    NOP_EXPR, array_var[0],
+					    tf_warning_or_error);
+      else
+	new_yes_ind  = build_x_modify_expr
+	  (location, *new_var, NOP_EXPR, 
+	   TREE_OPERAND (array_op0, 1), tf_warning_or_error);
+      new_yes_expr = build_x_modify_expr (location, array_ind_value, 
+					  NOP_EXPR, func_parm,
+					  tf_warning_or_error);
+      new_yes_list = alloc_stmt_list ();
+      append_to_statement_list (new_yes_ind, &new_yes_list);
+      append_to_statement_list (new_yes_expr, &new_yes_list);
+
+      new_no_list = alloc_stmt_list ();
+      append_to_statement_list (new_no_ind, &new_no_list);
+      append_to_statement_list (new_no_expr, &new_no_list);
+
+      new_cond_expr = build_x_binary_op
+	(location, LT_EXPR, array_ind_value,
+	 TREE_CODE (array_ind_value),
+	 func_parm, TREE_CODE (func_parm), NULL, tf_warning_or_error);
+      new_expr = build_x_conditional_expr (location, new_cond_expr, 
+					   new_yes_list, new_no_list, 
+					   tf_warning_or_error);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND)
+    {
+      new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  array_var[0], 1);
+      new_exp_init = build_x_modify_expr (location, array_ind_value, 
+					  NOP_EXPR, func_parm, 1);
+      new_no_ind   = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  *new_var, 1);
+      new_no_expr  = build_x_modify_expr (location, array_ind_value, 
+					  NOP_EXPR, array_ind_value, 1);
+      if (list_size > 1)
+	new_yes_ind  = build_x_modify_expr (location, *new_var, 
+					    NOP_EXPR, array_var[0], 1);
+      else
+	new_yes_ind  = build_x_modify_expr
+	  (location, *new_var, NOP_EXPR, TREE_OPERAND (array_op0, 1), 1);
+      new_yes_expr = build_x_modify_expr (location, array_ind_value, 
+					  NOP_EXPR, func_parm, 1);
+      new_yes_list = alloc_stmt_list ();
+      append_to_statement_list (new_yes_ind, &new_yes_list);
+      append_to_statement_list (new_yes_expr, &new_yes_list);
+
+      new_no_list = alloc_stmt_list ();
+      append_to_statement_list (new_no_ind, &new_no_list);
+      append_to_statement_list (new_no_expr, &new_no_list);
+      new_cond_expr =
+	build_x_binary_op (location, GT_EXPR, array_ind_value,
+			   TREE_CODE (array_ind_value), func_parm,
+			   TREE_CODE (func_parm), NULL, tf_warning_or_error);
+      new_expr = build_x_conditional_expr (location, new_cond_expr,
+					   new_yes_list, new_no_list, 
+					   tf_warning_or_error);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE)
+    {
+      vec<tree, va_gc> *func_args;
+      func_args = make_tree_vector ();
+      vec_safe_push (func_args, *new_var);
+      vec_safe_push (func_args, func_parm);
+
+      new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
+					  identity_value, tf_warning_or_error);
+      new_call_expr = finish_call_expr (call_fn, &func_args, false, true,
+					tf_warning_or_error);
+      new_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
+				      new_call_expr, tf_warning_or_error);
+    }
+  else if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
+    {
+      vec<tree, va_gc> *func_args;
+
+      func_args = make_tree_vector (); 
+      vec_safe_push (func_args, identity_value); 
+      vec_safe_push (func_args, func_parm);
+      new_expr = finish_call_expr (call_fn, &func_args, false, true,
+				   tf_warning_or_error);
+    }
+  else
+    gcc_unreachable ();
+
+  /* The reason we are putting initial variable twice is because the
+     new exp init below depends on this value being initialized.  */
+  for (ii = 0; ii < rank; ii++)
+    finish_expr_stmt (ind_init[ii]);
+  
+  if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
+    finish_expr_stmt (new_var_init);
+
+  if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
+      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND)
+    finish_expr_stmt (new_exp_init);
+
+  an_init = pop_stmt_list (an_init);
+  append_to_statement_list_force (an_init, &loop_with_init);
+  body = new_expr;
+
+  for (ii = 0; ii < rank; ii++)
+    {
+      tree new_loop = push_stmt_list ();
+      create_an_loop (ind_init[ii], compare_expr[ii], expr_incr[ii], body);
+      body = pop_stmt_list (new_loop);
+    }
+  append_to_statement_list_force (body, &loop_with_init);
+  
+  XDELETEVEC (compare_expr);
+  XDELETEVEC (expr_incr);
+  XDELETEVEC (ind_init);
+  XDELETEVEC (array_var);
+  
+  for (ii = 0; ii < list_size; ii++)
+    {
+      XDELETEVEC (count_down[ii]);
+      XDELETEVEC (array_value[ii]);
+      XDELETEVEC (array_stride[ii]);
+      XDELETEVEC (array_length[ii]);
+      XDELETEVEC (array_start[ii]);
+      XDELETEVEC (array_ops[ii]);
+      XDELETEVEC (array_vector[ii]);
+    }
+  XDELETEVEC (count_down);
+  XDELETEVEC (array_value);
+  XDELETEVEC (array_stride);
+  XDELETEVEC (array_length);
+  XDELETEVEC (array_start);
+  XDELETEVEC (array_ops);
+  XDELETEVEC (array_vector);
+  
+  return loop_with_init;
+}
+
+/* Returns a loop with ARRAY_REF inside it with an appropriate modify expr.
+   The LHS and/or RHS will be array notation expressions that have a
+   MODIFYCODE.  The location of the variable is specified by LOCATION. */
+
+static tree
+expand_an_in_modify_expr (location_t location, tree lhs,
+			     enum tree_code modifycode, tree rhs,
+			     tsubst_flags_t complain)
+{
+  bool **lhs_vector = NULL, **rhs_vector = NULL;
+  tree **lhs_array = NULL, **rhs_array = NULL;
+  tree array_expr_lhs = NULL_TREE, array_expr_rhs = NULL_TREE;
+  tree array_expr = NULL_TREE;
+  tree **lhs_value = NULL, **rhs_value = NULL;
+  tree **lhs_stride = NULL, **lhs_length = NULL, **lhs_start = NULL;
+  tree **rhs_stride = NULL, **rhs_length = NULL, **rhs_start = NULL;
+  tree body = NULL_TREE, *lhs_var = NULL, *rhs_var = NULL;
+  tree  *cond_expr = NULL;
+  tree *lhs_expr_incr = NULL, *rhs_expr_incr = NULL;
+  tree *lhs_ind_init = NULL, *rhs_ind_init = NULL;
+  bool **lhs_count_down = NULL, **rhs_count_down = NULL;
+  tree *lhs_compare = NULL, *rhs_compare = NULL;
+  vec<tree, va_gc> *lhs_array_operand = NULL, *rhs_array_operand = NULL;
+  size_t lhs_rank = 0, rhs_rank = 0, ii = 0, jj = 0;
+  tree ii_tree = NULL_TREE;
+  vec<tree, va_gc> *rhs_list = NULL, *lhs_list = NULL;
+  size_t rhs_list_size = 0, lhs_list_size = 0;
+  tree new_modify_expr, new_var = NULL_TREE, builtin_loop, scalar_mods;
+  bool found_builtin_fn = false;
+  int s_jj = 0;
+  tree lhs_begin_var, lhs_lngth_var, lhs_strde_var, rhs_begin_var;
+  tree rhs_lngth_var, rhs_strde_var;
+  tree an_init, loop_with_init = alloc_stmt_list ();
+  
+  /* Note about using find_rank (): If find_rank returns false, then it must
+     have already reported an error, thus we just return an error_mark_node
+     without any doing any error emission.  */
+  if (!find_rank (location, rhs, rhs, false, &rhs_rank))
+    return error_mark_node;
+ 
+  extract_array_notation_exprs (rhs, false, &rhs_list);
+  rhs_list_size = vec_safe_length (rhs_list);
+  an_init = push_stmt_list ();
+  if (rhs_rank)
+    {
+      scalar_mods = replace_invariant_exprs (&rhs);
+      if (scalar_mods)
+	finish_expr_stmt (scalar_mods);
+    }
+  for (ii = 0; ii < rhs_list_size; ii++)
+    {
+      tree rhs_node = (*rhs_list)[ii];
+      if (TREE_CODE (rhs_node) == CALL_EXPR)
+	{
+	  builtin_loop = expand_sec_reduce_builtin (rhs_node, &new_var);
+	  if (builtin_loop == error_mark_node)
+	    return error_mark_node;
+	  else if (builtin_loop)
+	    {
+	      finish_expr_stmt (builtin_loop);
+	      found_builtin_fn = true;
+	      if (new_var)
+		{
+		  vec <tree, va_gc> *rhs_sub_list = NULL, *new_var_list = NULL;
+		  vec_safe_push (rhs_sub_list, rhs_node);
+		  vec_safe_push (new_var_list, new_var);
+		  replace_array_notations (&rhs, false, rhs_sub_list,
+					   new_var_list);
+		}
+	    }
+	}
+    }
+  
+  lhs_rank = 0;
+  rhs_rank = 0;
+  if (!find_rank (location, lhs, lhs, true, &lhs_rank)
+      || !find_rank (location, rhs, rhs, true, &rhs_rank))
+    {
+      pop_stmt_list (an_init);
+      return error_mark_node;
+    }
+
+  /* If both are scalar, then the only reason why we will get this far is if
+     there is some array notations inside it and was using a builtin array
+     notation functions.  If so, we have already broken those guys up and now 
+     a simple build_x_modify_expr would do.  */
+  if (lhs_rank == 0 && rhs_rank == 0)
+    {
+      if (found_builtin_fn)
+	{
+	  new_modify_expr = build_x_modify_expr (location, lhs,
+						 modifycode, rhs, complain);
+	  finish_expr_stmt (new_modify_expr);
+	  pop_stmt_list (an_init);
+	  return an_init;
+	}
+      else
+	{
+	  pop_stmt_list (an_init);
+	  return NULL_TREE;
+	}
+    }
+
+  /* If for some reason location is not set, then find if LHS or RHS has
+     location info.  If so, then use that so we atleast have an idea.  */
+  if (location == UNKNOWN_LOCATION)
+    {
+      if (EXPR_LOCATION (lhs) != UNKNOWN_LOCATION)
+	location = EXPR_LOCATION (lhs);
+      else if (EXPR_LOCATION (rhs) != UNKNOWN_LOCATION)
+	location = EXPR_LOCATION (rhs);
+    }
+      
+  
+  /* We need this when we have a scatter issue.  */
+  extract_array_notation_exprs (lhs, true, &lhs_list);
+  rhs_list = NULL;
+  extract_array_notation_exprs (rhs, true, &rhs_list);
+  rhs_list_size = vec_safe_length (rhs_list);
+  lhs_list_size = vec_safe_length (lhs_list);
+    
+  if (lhs_rank == 0 && rhs_rank != 0)
+    {
+      tree rhs_base = rhs;
+      if (TREE_CODE (rhs_base) == COMPOUND_EXPR)
+	rhs_base = TREE_OPERAND (rhs_base, 0);
+      if (TREE_CODE (rhs_base) == TARGET_EXPR)
+	rhs_base = TARGET_EXPR_INITIAL (rhs_base);
+      
+      if (TREE_CODE (rhs) != CALL_EXPR
+	  && !has_call_expr_with_array_notation (rhs))
+	{
+	  for (ii = 0; ii < rhs_rank; ii++)
+	    rhs_base = ARRAY_NOTATION_ARRAY (rhs);
+      	  
+	  if (location == UNKNOWN_LOCATION && EXPR_HAS_LOCATION (rhs))
+	    location = EXPR_LOCATION (rhs);
+	  error_at (location, "%qD cannot be scalar when %qD is not", lhs,
+		    rhs_base);
+	  return error_mark_node;
+	}
+    }
+  if (lhs_rank != 0 && rhs_rank != 0 && lhs_rank != rhs_rank)
+    {
+      tree lhs_base = lhs;
+      tree rhs_base = rhs;
+      
+      for (ii = 0; ii < lhs_rank; ii++)
+	lhs_base = ARRAY_NOTATION_ARRAY (lhs_base);
+
+      while (rhs_base && TREE_CODE (rhs_base) != ARRAY_NOTATION_REF)
+	rhs_base = TREE_OPERAND (rhs_base, 0);
+      for (ii = 0; ii < rhs_rank; ii++)
+	rhs_base = ARRAY_NOTATION_ARRAY (rhs_base);
+
+      if (location == UNKNOWN_LOCATION && EXPR_HAS_LOCATION (lhs))
+	location = EXPR_LOCATION (lhs);
+      error_at (location, "rank mismatch between %qD and %qD", lhs_base,
+		rhs_base);
+      return error_mark_node;
+    }
+
+  /* Assign the array notation components to variable so that they can satisfy
+     the exec-once rule.  */
+  for (ii = 0; ii < lhs_list_size; ii++)
+    {
+      tree array_node = (*lhs_list)[ii];
+      tree array_begin = ARRAY_NOTATION_START (array_node);
+      tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
+      tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
+
+      if (TREE_CODE (array_begin) != INTEGER_CST)
+	{
+	  lhs_begin_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	  finish_expr_stmt (build_x_modify_expr (location, lhs_begin_var,
+						 NOP_EXPR, array_begin,
+						 complain));
+	  ARRAY_NOTATION_START (array_node) = lhs_begin_var;
+	}
+      if (TREE_CODE (array_lngth) != INTEGER_CST)
+	{
+	  lhs_lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	  finish_expr_stmt (build_x_modify_expr (location, lhs_lngth_var,
+						 NOP_EXPR, array_lngth,
+						 complain));
+	  ARRAY_NOTATION_LENGTH (array_node) = lhs_lngth_var;
+	}
+      if (TREE_CODE (array_strde) != INTEGER_CST)
+	{
+	  lhs_strde_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	  finish_expr_stmt (build_x_modify_expr (location, lhs_strde_var,
+						 NOP_EXPR, array_strde,
+						 complain));
+	  ARRAY_NOTATION_STRIDE (array_node) = lhs_strde_var;
+	}
+    }
+  for (ii = 0; ii < rhs_list_size; ii++)
+    {
+      tree array_node = (*rhs_list)[ii];
+      if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF)
+	{
+	  tree array_begin = ARRAY_NOTATION_START (array_node);
+	  tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
+	  tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
+
+	  if (TREE_CODE (array_begin) != INTEGER_CST)
+	    {
+	      rhs_begin_var = build_decl (location, VAR_DECL, NULL_TREE,
+					  integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, rhs_begin_var,
+						     NOP_EXPR, array_begin,
+						     complain));
+	      ARRAY_NOTATION_START (array_node) = rhs_begin_var;
+	    }
+	  if (TREE_CODE (array_lngth) != INTEGER_CST)
+	    {
+	      rhs_lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
+					  integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, rhs_lngth_var,
+						     NOP_EXPR, array_lngth,
+						     complain));
+	      ARRAY_NOTATION_LENGTH (array_node) = rhs_lngth_var;
+	    }
+	  if (TREE_CODE (array_strde) != INTEGER_CST)
+	    {
+	      rhs_strde_var = build_decl (location, VAR_DECL, NULL_TREE,
+					  integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, rhs_strde_var,
+						     NOP_EXPR, array_strde,
+						     complain));
+	      ARRAY_NOTATION_STRIDE (array_node) = rhs_strde_var;
+	    }
+	}
+    }  
+  lhs_vector = XNEWVEC (bool *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_vector[ii] = XNEWVEC (bool, lhs_rank);
+  
+  rhs_vector = XNEWVEC (bool *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_vector[ii] = XNEWVEC (bool, rhs_rank);
+
+  lhs_array = XNEWVEC (tree *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_array[ii] = XNEWVEC (tree, lhs_rank);
+  
+  rhs_array = XNEWVEC (tree *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_array[ii] = XNEWVEC (tree, rhs_rank);
+
+  lhs_value = XNEWVEC (tree *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_value[ii] = XNEWVEC (tree, lhs_rank);
+  
+  rhs_value = XNEWVEC (tree *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_value[ii] = XNEWVEC (tree, rhs_rank);
+
+  lhs_stride = XNEWVEC (tree *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_stride[ii] = XNEWVEC (tree, lhs_rank);
+
+  rhs_stride = XNEWVEC (tree *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_stride[ii] = XNEWVEC (tree, rhs_rank);
+
+  lhs_length = XNEWVEC (tree *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_length[ii] = XNEWVEC (tree, lhs_rank);
+  
+  rhs_length = XNEWVEC (tree *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_length[ii] = XNEWVEC (tree, rhs_rank);
+
+  lhs_start = XNEWVEC (tree *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_start[ii] = XNEWVEC (tree, lhs_rank);
+  
+  rhs_start = XNEWVEC (tree *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_start[ii] = XNEWVEC (tree, rhs_rank);
+   
+  lhs_var = XNEWVEC (tree, lhs_rank);
+  rhs_var = XNEWVEC (tree, rhs_rank);
+  
+
+  /* The reason why we are just using lhs_rank for this is because we have then
+     following scenarios:
+     1.  LHS_RANK == RHS_RANK
+     2.  LHS_RANK != RHS_RANK && RHS_RANK = 0
+
+     In both the scenarios, just checking the LHS_RANK is OK.  */
+
+  cond_expr = XNEWVEC (tree, MAX (lhs_rank, rhs_rank));
+  lhs_expr_incr = XNEWVEC (tree, lhs_rank);
+  rhs_expr_incr = XNEWVEC (tree, rhs_rank);
+
+  lhs_ind_init = XNEWVEC (tree, lhs_rank);
+  rhs_ind_init = XNEWVEC (tree, rhs_rank);
+
+  lhs_count_down = XNEWVEC (bool *, lhs_list_size);
+  for (ii = 0; ii < lhs_list_size; ii++)
+    lhs_count_down[ii] = XNEWVEC (bool, lhs_rank);
+  
+  rhs_count_down = XNEWVEC (bool *, rhs_list_size);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    rhs_count_down[ii] = XNEWVEC (bool, rhs_rank);
+
+  lhs_compare = XNEWVEC (tree, lhs_rank);
+  rhs_compare = XNEWVEC (tree, rhs_rank);
+
+  if (lhs_rank)
+    {
+      for (ii = 0; ii < lhs_list_size; ii++)
+	{
+	  jj = 0;
+	  ii_tree = (*lhs_list)[ii];
+	  while (ii_tree)
+	    {
+	      if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
+		{
+		  lhs_array[ii][jj] = ii_tree;
+		  jj++;
+		  ii_tree = ARRAY_NOTATION_ARRAY (ii_tree);
+		}
+	      else if (TREE_CODE (ii_tree) == ARRAY_REF)
+		ii_tree = TREE_OPERAND (ii_tree, 0);
+	      else if (TREE_CODE (ii_tree) == VAR_DECL
+		       || TREE_CODE (ii_tree) == PARM_DECL)
+		break;
+	    }
+	}
+    }
+  else
+    lhs_array[0][0] = NULL_TREE;
+  
+  if (rhs_rank)
+    {
+      for (ii = 0; ii < rhs_list_size; ii++)
+	{
+	  jj = 0;
+	  ii_tree = (*rhs_list)[ii];
+	  while (ii_tree)
+	    {
+	      if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
+		{
+		  rhs_array[ii][jj] = ii_tree;
+		  jj++;
+		  ii_tree = ARRAY_NOTATION_ARRAY (ii_tree);
+		}
+	      else if (TREE_CODE (ii_tree) == ARRAY_REF)
+		ii_tree = TREE_OPERAND (ii_tree, 0);
+	      else if (TREE_CODE (ii_tree) == VAR_DECL
+		       || TREE_CODE (ii_tree) == PARM_DECL
+		       || TREE_CODE (ii_tree) == CALL_EXPR)
+		break;
+	    }
+	}
+    }  
+  for (ii = 0; ii < lhs_list_size; ii++)
+    {
+      if (TREE_CODE ((*lhs_list)[ii]) == ARRAY_NOTATION_REF)
+	{
+	  for (jj = 0; jj < lhs_rank; jj++)
+	    {
+	      if (TREE_CODE (lhs_array[ii][jj]) == ARRAY_NOTATION_REF)
+		{
+		  lhs_value[ii][jj] = ARRAY_NOTATION_ARRAY (lhs_array[ii][jj]);
+		  lhs_start[ii][jj] = ARRAY_NOTATION_START (lhs_array[ii][jj]);
+		  lhs_length[ii][jj] =
+		    fold_build1 (CONVERT_EXPR, integer_type_node,
+				 ARRAY_NOTATION_LENGTH (lhs_array[ii][jj]));
+		  lhs_stride[ii][jj] =
+		    fold_build1 (CONVERT_EXPR, integer_type_node,
+				 ARRAY_NOTATION_STRIDE (lhs_array[ii][jj]));
+		  lhs_vector[ii][jj] = true;
+		  
+		  /* If the stride value is variable (i.e. not constant) then
+		     assume that the length is positive.  */
+		  if (!TREE_CONSTANT (lhs_length[ii][jj]))
+		    lhs_count_down[ii][jj] = false;
+		  else if (tree_int_cst_lt
+			   (lhs_length[ii][jj],
+			    build_zero_cst (TREE_TYPE (lhs_length[ii][jj]))))
+		    lhs_count_down[ii][jj] = true;
+		  else
+		    lhs_count_down[ii][jj] = false;
+		}
+	      else
+		lhs_vector[ii][jj] = false;
+	    }
+	}
+    }
+  for (ii = 0; ii < rhs_list_size; ii++)
+    {
+      if (TREE_CODE ((*rhs_list)[ii]) == ARRAY_NOTATION_REF)
+	{
+	  for (jj = 0; jj < rhs_rank; jj++)
+	    {
+	      if (TREE_CODE (rhs_array[ii][jj]) == ARRAY_NOTATION_REF)
+		{
+		  rhs_value[ii][jj]  = ARRAY_NOTATION_ARRAY (rhs_array[ii][jj]);
+		  rhs_start[ii][jj]  = ARRAY_NOTATION_START (rhs_array[ii][jj]);
+		  rhs_length[ii][jj] =
+		    ARRAY_NOTATION_LENGTH (rhs_array[ii][jj]);
+		  rhs_stride[ii][jj] =
+		    ARRAY_NOTATION_STRIDE (rhs_array[ii][jj]);
+		  rhs_vector[ii][jj] = true;
+		  /* If the stride value is variable (i.e. not constant) then
+		     assume that the length is positive.  */
+		  if (!TREE_CONSTANT (rhs_length[ii][jj]))
+		    rhs_count_down[ii][jj] = false;
+		  else if (tree_int_cst_lt
+			   (rhs_length[ii][jj],
+			    build_zero_cst (TREE_TYPE (rhs_length[ii][jj]))))
+		    rhs_count_down[ii][jj] = true;
+		  else
+		    rhs_count_down[ii][jj] = false;	
+		}
+	      else
+		rhs_vector[ii][jj] = false;
+	    }
+	}
+      else
+	for (jj = 0; jj < rhs_rank; jj++)
+	  {
+	    rhs_vector[ii][jj] = false;
+	    rhs_length[ii][jj] = NULL_TREE;
+	  }
+    }
+
+  if (length_mismatch_in_expr_p (EXPR_LOCATION (lhs), lhs_length,
+				 lhs_list_size, lhs_rank)
+      || length_mismatch_in_expr_p (EXPR_LOCATION (rhs), rhs_length,
+				    rhs_list_size, rhs_rank))
+    {
+      pop_stmt_list (an_init);
+      return error_mark_node;
+    }
+
+  if (lhs_list_size > 0 && rhs_list_size > 0 && lhs_rank > 0 && rhs_rank > 0
+      && TREE_CODE (lhs_length[0][0]) == INTEGER_CST
+      && rhs_length[0][0] && TREE_CODE (rhs_length[0][0]) == INTEGER_CST)
+    {
+      HOST_WIDE_INT l_length = int_cst_value (lhs_length[0][0]);
+      HOST_WIDE_INT r_length = int_cst_value (rhs_length[0][0]);
+      if (absu_hwi (l_length) != absu_hwi (r_length))
+	{
+	  error_at (location, "length mismatch between LHS and RHS");
+	  pop_stmt_list (an_init);
+	  return error_mark_node;
+	}
+    }
+   for (ii = 0; ii < lhs_rank; ii++)
+    if (lhs_start[0][ii] && TREE_TYPE (lhs_start[0][ii]))
+	lhs_var[ii] =  build_decl (location, VAR_DECL, NULL_TREE,
+				   TREE_TYPE (lhs_start[0][ii]));
+    else
+      lhs_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
+				integer_type_node);
+
+  for (ii = 0; ii < rhs_list_size; ii++)
+    {
+      if (TREE_CODE ((*rhs_list)[ii]) == CALL_EXPR)
+	{
+	  int idx_value = 0;
+	  tree func_name = CALL_EXPR_FN ((*rhs_list)[ii]);
+	  if (TREE_CODE (func_name) == ADDR_EXPR)
+	    {
+	      if (is_sec_implicit_index_fn (func_name))
+		{
+		  idx_value = 
+		    extract_sec_implicit_index_arg (location, (*rhs_list)[ii]);
+		  if (idx_value < (int) lhs_rank && idx_value >= 0)
+		    vec_safe_push (rhs_array_operand, lhs_var[idx_value]);
+		  else if (idx_value == -1)
+		    return error_mark_node;
+		  else
+		    {
+		      size_t ee = 0;
+		      tree lhs_base = (*lhs_list)[ii];
+		      for (ee = 0; ee < lhs_rank; ee++)
+			if (lhs_base
+			    && TREE_CODE (lhs_base) == ARRAY_NOTATION_REF)
+			  lhs_base = ARRAY_NOTATION_ARRAY (lhs_base);
+
+		      if (location == UNKNOWN_LOCATION
+			  && EXPR_HAS_LOCATION (lhs))
+			location = EXPR_LOCATION (lhs);
+		      error_at (location, "__sec_implicit_index argument %d "
+				"must be less than the rank of %qD", idx_value,
+				lhs_base);
+		      return error_mark_node;
+		    }
+		}
+	      else
+		vec_safe_push (rhs_array_operand, (*rhs_list)[ii]);
+	    }
+	  else
+	    vec_safe_push (rhs_array_operand, (*rhs_list)[ii]);
+	}
+      else
+	vec_safe_push (rhs_array_operand, (*rhs_list)[ii]);
+    }
+
+  replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
+  rhs_list_size = 0;
+  rhs_list = NULL;
+  extract_array_notation_exprs (rhs, true, &rhs_list);
+  rhs_list_size = vec_safe_length (rhs_list);    
+  
+  for (ii = 0; ii < lhs_rank; ii++)
+    if (lhs_vector[0][ii])
+      {
+	lhs_ind_init[ii] = build_x_modify_expr
+	  (location, lhs_var[ii], NOP_EXPR,
+	   build_zero_cst (TREE_TYPE (lhs_var[ii])), complain);
+      }
+    
+
+  for (ii = 0; ii < rhs_rank; ii++)
+    {
+      /* When we have a polynomial, we assume that the indices are of type
+	 integer.  */
+      rhs_var[ii] =  build_decl (location, VAR_DECL, NULL_TREE,
+				 TREE_TYPE (rhs_start[0][ii]));
+      rhs_ind_init[ii] = build_x_modify_expr
+	(location, rhs_var[ii], NOP_EXPR, 
+	 build_zero_cst (TREE_TYPE (rhs_var[ii])), complain);
+    }
+
+  if (lhs_rank)
+    {
+      for (ii = 0; ii < lhs_list_size; ii++)
+	{
+	  if (lhs_vector[ii][0])
+	    {
+	      /* The last ARRAY_NOTATION element's ARRAY component should be
+		 the array's base value.  */
+	      tree lhs_array_opr = lhs_value[ii][lhs_rank - 1];
+	      for (s_jj = lhs_rank - 1; s_jj >= 0; s_jj--)
+		{
+		  tree stride = NULL_TREE, var = NULL_TREE, start = NULL_TREE;
+		  if ((TREE_TYPE (lhs_start[ii][s_jj]) ==
+		       TREE_TYPE (lhs_stride[ii][s_jj]))
+		      && (TREE_TYPE (lhs_stride[ii][s_jj]) !=
+			  TREE_TYPE (lhs_var[s_jj])))
+		    {
+		      /* If stride and start are of same type and the induction
+			 var is not, convert induction variable to stride's
+			 type.  */
+		      start = lhs_start[ii][s_jj];
+		      stride = lhs_stride[ii][s_jj];
+		      var = build_c_cast (location,
+					  TREE_TYPE (lhs_stride[ii][s_jj]),
+					  lhs_var[s_jj]);
+		    }
+		  else if (TREE_TYPE (lhs_start[ii][s_jj]) !=
+			   TREE_TYPE (lhs_stride[ii][s_jj]))
+		    {
+		      /* If we reach here, then the stride and start are of
+			 different types, and so it doesn't really matter what
+			 the induction variable type is, convert everything to 
+			 integer.  The reason why we pick an integer instead of 
+			 something like size_t is because the stride and 
+			 length can be + or -.  */
+		      start = build_c_cast (location, integer_type_node,
+					    lhs_start[ii][s_jj]);
+		      stride = build_c_cast (location, integer_type_node,
+					     lhs_stride[ii][s_jj]);
+		      var = build_c_cast (location, integer_type_node,
+					  lhs_var[s_jj]);
+		    }
+		  else
+		    {
+		      start = lhs_start[ii][s_jj];
+		      stride = lhs_stride[ii][s_jj];
+		      var = lhs_var[s_jj];
+		    }
+		  if (lhs_count_down[ii][s_jj])
+		    /* Array[start_index - (induction_var * stride)].  */
+		    lhs_array_opr = grok_array_decl
+		      (location, lhs_array_opr,
+		       build2 (MINUS_EXPR, TREE_TYPE (var), start,
+			       build2 (MULT_EXPR, TREE_TYPE (var), var,
+				       stride)), false);	
+		  else
+		    /* Array[start_index + (induction_var * stride)].  */
+		    lhs_array_opr = grok_array_decl
+		      (location, lhs_array_opr,
+		       build2 (PLUS_EXPR, TREE_TYPE (var), start,
+			       build2 (MULT_EXPR, TREE_TYPE (var), var,
+				       stride)), false);
+		}
+	      vec_safe_push (lhs_array_operand, lhs_array_opr);
+	    }
+	  else
+	    vec_safe_push (lhs_array_operand, integer_one_node);
+	}
+      replace_array_notations (&lhs, true, lhs_list, lhs_array_operand);
+      array_expr_lhs = lhs;
+    }
+
+  if (rhs_array_operand)
+    vec_safe_truncate (rhs_array_operand, 0);
+
+  if (rhs_rank)
+    {
+      for (ii = 0; ii < rhs_list_size; ii++)
+	{
+	  if (rhs_vector[ii][0])
+	    {
+	      tree rhs_array_opr = rhs_value[ii][rhs_rank - 1];
+	      for (s_jj = rhs_rank - 1; s_jj >= 0; s_jj--)
+		{
+		  tree stride = NULL_TREE, var = NULL_TREE, start = NULL_TREE;
+		  if ((TREE_TYPE (rhs_start[ii][s_jj]) ==
+		       TREE_TYPE (rhs_stride[ii][s_jj]))
+		      && (TREE_TYPE (rhs_stride[ii][s_jj]) !=
+			  TREE_TYPE (rhs_var[s_jj])))
+		    {
+		      /* If stride and start are of same type and the induction
+			 var is not, convert induction variable to stride's
+			 type.  */
+		      start = rhs_start[ii][s_jj];
+		      stride = rhs_stride[ii][s_jj];
+		      var = build_c_cast (location,
+					  TREE_TYPE (rhs_stride[ii][s_jj]),
+					  rhs_var[s_jj]);
+		    }
+		  else if (TREE_TYPE (rhs_start[ii][s_jj]) !=
+			   TREE_TYPE (rhs_stride[ii][s_jj]))
+		    {
+		      /* If we reach here, then the stride and start are of
+			 different types, and so it doesn't really matter what
+			 the induction variable type is, convert everything to 
+			  integer.  The reason why we pick an integer instead 
+			  of something like size_t is because the stride and 
+			  length can be + or -.  */
+		      start = build_c_cast (location, integer_type_node,
+					    rhs_start[ii][s_jj]);
+		      stride = build_c_cast (location, integer_type_node,
+					     rhs_stride[ii][s_jj]);
+		      var = build_c_cast (location, integer_type_node,
+					  rhs_var[s_jj]);
+		    }
+		  else
+		    {
+		      start = rhs_start[ii][s_jj];
+		      stride = rhs_stride[ii][s_jj];
+		      var = rhs_var[s_jj];
+		    }
+		  if (rhs_count_down[ii][s_jj])
+		    /* Array[start_index - (induction_var * stride)].  */
+		    rhs_array_opr = grok_array_decl
+		      (location, rhs_array_opr,
+		       build2 (MINUS_EXPR, TREE_TYPE (var), start,
+			       build2 (MULT_EXPR, TREE_TYPE (var), var,
+				       stride)), false);	
+		  else
+		    /* Array[start_index + (induction_var * stride)].  */
+		    rhs_array_opr = grok_array_decl
+		      (location, rhs_array_opr,
+		       build2 (PLUS_EXPR, TREE_TYPE (var), start,
+			       build2 (MULT_EXPR, TREE_TYPE (var), var,
+				       stride)), false);
+		}
+	      vec_safe_push (rhs_array_operand, rhs_array_opr);
+	    }
+	  else
+	    /* This is just a dummy node to make sure the list sizes for both
+	       array list and array operand list are the same.  */
+	    vec_safe_push (rhs_array_operand, integer_one_node);
+	}
+      for (ii = 0; ii < rhs_list_size; ii++)
+	{
+	  tree rhs_node = (*rhs_list)[ii];
+	  if (TREE_CODE (rhs_node) == CALL_EXPR)
+	    {
+	      int idx_value = 0;
+	      tree func_name = CALL_EXPR_FN (rhs_node);
+	      if (TREE_CODE (func_name) == ADDR_EXPR)
+		if (is_sec_implicit_index_fn (func_name))
+		  {
+		    idx_value = 
+		      extract_sec_implicit_index_arg (location, rhs_node);
+		    if (idx_value < (int) lhs_rank && idx_value >= 0)
+		      vec_safe_push (rhs_array_operand, rhs_var[idx_value]);
+		    else
+		      {
+			size_t ee = 0;
+			tree rhs_base = (*lhs_list)[ii];
+			for (ee = 0; ee < rhs_rank; ee++)
+			  if (rhs_base
+			      && TREE_CODE (rhs_base) == ARRAY_NOTATION_REF)
+			    rhs_base = ARRAY_NOTATION_ARRAY (rhs_base);
+
+			error_at (location, "__sec_implicit_index argument %d "
+				  "must be less than rank of %qD", idx_value,
+				  rhs_base);
+			return error_mark_node;
+		      }
+		  }
+	    }
+	}	
+      replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
+      array_expr_rhs = rhs;
+    }
+  else
+    {
+      for (ii = 0; ii < rhs_list_size; ii++)
+	{
+	  tree rhs_node = (*rhs_list)[ii];
+	  if (TREE_CODE (rhs_node) == CALL_EXPR)
+	    {
+	      int idx_value = 0;
+	      tree func_name = CALL_EXPR_FN (rhs_node);
+	      if (is_sec_implicit_index_fn (func_name))
+		{
+		  idx_value =  extract_sec_implicit_index_arg (location,
+							       rhs_node);
+		  if (idx_value < (int) lhs_rank && idx_value >= 0)
+		    vec_safe_push (rhs_array_operand, lhs_var[idx_value]);
+		  else
+		    {
+		      size_t ee = 0;
+		      tree lhs_base = (*lhs_list)[ii];
+		      for (ee = 0; ee < lhs_rank; ee++)
+			if (lhs_base
+			    && TREE_CODE (lhs_base) == ARRAY_NOTATION_REF)
+			  lhs_base = ARRAY_NOTATION_ARRAY (lhs_base);
+		      error_at (location, "__sec_implicit_index argument %d "
+				"must be less than the rank of %qD", idx_value,
+				lhs_base);
+		      return error_mark_node;
+		    }
+		}
+	    }
+	}
+      replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
+      array_expr_rhs = rhs;
+      rhs_expr_incr[0] = NULL_TREE;
+    }
+  
+  for (ii = 0; ii < rhs_rank; ii++)
+    if (rhs_count_down[0][ii])
+      rhs_expr_incr[ii] = build_x_unary_op (location, POSTDECREMENT_EXPR,
+					    rhs_var[ii], complain);
+    else
+      rhs_expr_incr[ii] = build_x_unary_op (location, POSTINCREMENT_EXPR,
+					    rhs_var[ii], complain);
+  
+  for (ii = 0; ii < lhs_rank; ii++)
+    if (lhs_count_down[0][ii])
+      lhs_expr_incr[ii] = build_x_unary_op (location, POSTDECREMENT_EXPR,
+					    lhs_var[ii], complain);
+    else
+      lhs_expr_incr[ii] = build_x_unary_op (location, POSTINCREMENT_EXPR,
+					    lhs_var[ii], complain);
+  if (!array_expr_lhs)
+    array_expr_lhs = lhs;
+  
+  array_expr = build_x_modify_expr (location, array_expr_lhs, modifycode,
+				    array_expr_rhs, complain);
+
+  for (jj = 0; jj < MAX (lhs_rank, rhs_rank); jj++)
+    {
+      if (rhs_rank && rhs_expr_incr[jj])
+	{
+	  size_t iii = 0;
+	  if (lhs_rank)
+	    {
+	      if (lhs_count_down[0][jj])
+		lhs_compare[jj] = build_x_binary_op
+		  (location, GT_EXPR, lhs_var[jj], TREE_CODE (lhs_var[jj]),
+		   lhs_length[0][jj], TREE_CODE (lhs_length[0][jj]), NULL,
+		   complain);
+	      else
+		lhs_compare[jj] = build_x_binary_op
+		  (location, LT_EXPR, lhs_var[jj], TREE_CODE (lhs_var[jj]),
+		   lhs_length[0][jj], TREE_CODE (lhs_length[0][jj]), NULL,
+		   complain);
+	    }
+	  else
+	    lhs_compare[jj] = NULL_TREE;
+
+	  for (iii = 0; iii < rhs_list_size; iii++)
+	    if (rhs_vector[iii][jj])
+	      break;
+	  
+	  /* What we are doing here is this:
+	     We always count up, so:
+	       if (length is negative ==> which means we count down)
+	          we multiply length by -1 and count up => ii < -LENGTH
+	       else
+	          we just count up, so we compare for  ii < LENGTH
+	   */
+	  if (rhs_count_down[iii][jj])
+	    {
+	      tree new_rhs = build_x_modify_expr
+		(location, rhs_length[iii][jj], MULT_EXPR,
+		 build_int_cst (TREE_TYPE (rhs_length[iii][jj]), -1), complain);
+	      rhs_compare[jj] = build_x_binary_op
+		(location, GT_EXPR, rhs_var[jj], TREE_CODE (rhs_var[jj]),
+		 new_rhs, TREE_CODE (new_rhs), NULL, complain);
+	    }
+	  else
+	    rhs_compare[jj] = build_x_binary_op
+	      (location, LT_EXPR, rhs_var[jj], TREE_CODE (rhs_var[jj]),
+	       rhs_length[iii][jj], TREE_CODE (rhs_length[0][jj]), NULL,
+	       complain);
+	   
+	  if (lhs_rank)
+	    cond_expr[jj] = build_x_binary_op
+	      (location, TRUTH_ANDIF_EXPR, lhs_compare[jj],
+	       TREE_CODE (lhs_compare[jj]), rhs_compare[jj],
+	       TREE_CODE (rhs_compare[jj]), NULL, complain);
+	  else
+	    cond_expr[jj] = rhs_compare[jj];
+	}
+      else
+	{
+	  if (lhs_count_down[0][jj])
+	    cond_expr[jj] = build_x_binary_op
+	      (location, GT_EXPR, lhs_var[jj], TREE_CODE (lhs_var[jj]),
+	       lhs_length[0][jj], TREE_CODE (lhs_length[0][jj]), NULL,
+	       complain);
+	    else
+	      cond_expr[jj] = build_x_binary_op
+		(location, LT_EXPR, lhs_var[jj], TREE_CODE (lhs_var[jj]),
+		 lhs_length[0][jj], TREE_CODE (lhs_length[0][jj]), NULL,
+		 complain);
+	}
+    }
+  
+  an_init = pop_stmt_list (an_init);
+  append_to_statement_list_force (an_init, &loop_with_init);
+  body = array_expr;
+  for (ii = 0; ii < MAX (lhs_rank, rhs_rank); ii++)
+    {
+      tree incr_list = alloc_stmt_list ();
+      tree init_list = alloc_stmt_list ();
+      tree new_loop = push_stmt_list ();
+
+      if (lhs_rank)
+	{
+	  append_to_statement_list_force (lhs_ind_init[ii], &init_list);
+	  append_to_statement_list_force (lhs_expr_incr[ii], &incr_list);
+	}
+      if (rhs_rank)
+	{
+	  append_to_statement_list_force (rhs_ind_init[ii], &init_list);
+	  append_to_statement_list_force (rhs_expr_incr[ii], &incr_list);
+	}
+      create_an_loop (init_list, cond_expr[ii], incr_list, body);
+      body = pop_stmt_list (new_loop);
+    }
+  append_to_statement_list (body, &loop_with_init);
+  for (ii = 0; ii < rhs_list_size; ii++)
+    {
+      XDELETEVEC (rhs_vector[ii]);
+      XDELETEVEC (rhs_array[ii]);
+      XDELETEVEC (rhs_value[ii]);
+      XDELETEVEC (rhs_length[ii]);
+      XDELETEVEC (rhs_stride[ii]);
+      XDELETEVEC (rhs_start[ii]);
+    }
+    for (ii = 0; ii < lhs_list_size; ii++)
+    {
+      XDELETEVEC (lhs_vector[ii]);
+      XDELETEVEC (lhs_array[ii]);
+      XDELETEVEC (lhs_value[ii]);
+      XDELETEVEC (lhs_length[ii]);
+      XDELETEVEC (lhs_stride[ii]);
+      XDELETEVEC (lhs_start[ii]);
+    }
+  if (rhs_vector)
+    XDELETEVEC (rhs_vector);
+
+  if (rhs_array)
+    XDELETEVEC (rhs_array);
+  if (rhs_value)
+    XDELETEVEC (rhs_value);
+  if (rhs_length)
+    XDELETEVEC (rhs_length);
+  if (rhs_stride)
+    XDELETEVEC (rhs_stride);
+  if (rhs_start)
+    XDELETEVEC (rhs_start);
+  if (rhs_expr_incr)    
+    XDELETEVEC (rhs_expr_incr);
+  if (rhs_ind_init)
+    XDELETEVEC (rhs_ind_init);
+  if (rhs_compare)
+    XDELETEVEC (rhs_compare);
+  if (lhs_compare)
+    XDELETEVEC (lhs_compare);
+  
+  return loop_with_init;
+}
+
+/* Helper function for expand_conditonal_array_notations. Encloses the conditional
+   statement passed in ORIG_STMT with a loop around it and replaces the
+   condition in STMT with a ARRAY_REF tree-node to the array.  The condition
+   must have a ARRAY_NOTATION_REF tree.  */
+
+static tree
+cp_expand_cond_array_notations (tree orig_stmt)
+{
+  vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
+  size_t list_size = 0;
+  size_t rank = 0, ii = 0, jj = 0;
+  tree **array_ops, *array_var, jj_tree, body, stmt = NULL_TREE;
+  tree **array_value, **array_stride, **array_length, **array_start;
+  tree *compare_expr, an_init, *expr_incr, *ind_init;
+  tree builtin_loop, new_var = NULL_TREE;
+  bool **count_down, **array_vector;
+  tree loop_with_init = alloc_stmt_list ();
+  int s_jj = 0;
+  tree begin_var, lngth_var, strde_var;
+  tsubst_flags_t complain = tf_warning_or_error;
+  location_t location = UNKNOWN_LOCATION;
+
+  if (TREE_CODE (orig_stmt) == COND_EXPR)
+    {
+      size_t cond_rank = 0, yes_rank = 0, no_rank = 0;
+      tree yes_expr = COND_EXPR_THEN (orig_stmt);
+      tree no_expr = COND_EXPR_ELSE (orig_stmt);
+      tree cond = COND_EXPR_COND (orig_stmt);
+      if (!find_rank (EXPR_LOCATION (cond), cond, cond, true, &cond_rank)
+	  || !find_rank (EXPR_LOCATION (yes_expr), yes_expr, yes_expr, true,
+			 &yes_rank)
+	  || find_rank (EXPR_LOCATION (no_expr), no_expr, no_expr, true,
+			&no_rank))
+	return error_mark_node;
+      if (cond_rank != 0 && cond_rank != yes_rank && yes_rank != 0)
+	{
+	  error_at (EXPR_LOCATION (yes_expr), "rank mismatch with controlling"
+		    " expression of parent if-statement");
+	  return error_mark_node;
+	}
+      else if (cond_rank != 0 && cond_rank != no_rank && no_rank != 0)
+	{
+	  error_at (EXPR_LOCATION (no_expr), "rank mismatch with controlling "
+		    "expression of parent if-statement");
+	  return error_mark_node;
+	}
+    }
+  else if (TREE_CODE (orig_stmt) == IF_STMT)
+    {
+      size_t cond_rank = 0, yes_rank = 0, no_rank = 0;
+      tree yes_expr = THEN_CLAUSE (orig_stmt);
+      tree no_expr = ELSE_CLAUSE (orig_stmt);
+      tree cond = IF_COND (orig_stmt);
+      if (!find_rank (EXPR_LOCATION (cond), cond, cond, true, &cond_rank)
+	  || (yes_expr
+	      && !find_rank (EXPR_LOCATION (yes_expr), yes_expr, yes_expr, true,
+			     &yes_rank))
+	  || (no_expr
+	      && !find_rank (EXPR_LOCATION (no_expr), no_expr, no_expr, true,
+			     &no_rank)))
+	return error_mark_node;
+      if (cond_rank != 0 && cond_rank != yes_rank && yes_rank != 0)
+	{
+	  error_at (EXPR_LOCATION (yes_expr), "rank mismatch with controlling"
+		    " expression of parent if-statement");
+	  return error_mark_node;
+	}
+      else if (cond_rank != 0 && cond_rank != no_rank && no_rank != 0)
+	{
+	  error_at (EXPR_LOCATION (no_expr), "rank mismatch with controlling "
+		    "expression of parent if-statement");
+	  return error_mark_node;
+	}
+    }
+
+  if (!find_rank (EXPR_LOCATION (orig_stmt), orig_stmt, orig_stmt, true,
+		  &rank))
+    return error_mark_node;
+  if (rank == 0)
+    return orig_stmt;
+
+  extract_array_notation_exprs (orig_stmt, false, &array_list);
+  stmt = alloc_stmt_list ();
+  for (ii = 0; ii < vec_safe_length (array_list); ii++)
+    {
+      tree array_node = (*array_list)[ii];
+      if (TREE_CODE (array_node) == CALL_EXPR
+	  || TREE_CODE (array_node) == AGGR_INIT_EXPR)
+	{
+	  builtin_loop = expand_sec_reduce_builtin (array_node, &new_var);
+	  if (builtin_loop == error_mark_node)
+	    finish_expr_stmt (error_mark_node);
+	  else if (new_var)
+	    {
+	      vec<tree, va_gc> *sub_list = NULL, *new_var_list = NULL;
+	      vec_safe_push (sub_list, array_node);
+	      vec_safe_push (new_var_list, new_var);
+	      replace_array_notations (&orig_stmt, false, sub_list,
+				       new_var_list);
+	      append_to_statement_list_force (builtin_loop, &stmt);
+	    }
+	}
+    }
+  append_to_statement_list_force (orig_stmt, &stmt);
+  rank = 0;
+  array_list = NULL;
+  if (!find_rank (EXPR_LOCATION (stmt), stmt, stmt, true, &rank))
+    return error_mark_node;
+  if (rank == 0)
+    return stmt;
+  
+  extract_array_notation_exprs (stmt, true, &array_list);
+  list_size = vec_safe_length (array_list);
+  if (list_size == 0)
+    return stmt;
+
+  location = EXPR_LOCATION (orig_stmt);
+  array_ops = XNEWVEC (tree *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_ops[ii] = XNEWVEC (tree, rank);
+  
+  array_vector = XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_vector[ii] = XNEWVEC (bool, rank);
+
+  array_value  = XNEWVEC (tree *, list_size);
+  array_stride = XNEWVEC (tree *, list_size);
+  array_length = XNEWVEC (tree *, list_size);
+  array_start  = XNEWVEC (tree *, list_size);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      array_value[ii]  = XNEWVEC (tree, rank);
+      array_stride[ii] = XNEWVEC (tree, rank);
+      array_length[ii] = XNEWVEC (tree, rank);
+      array_start[ii]  = XNEWVEC (tree, rank);
+    }
+
+  compare_expr = XNEWVEC (tree, rank);
+  expr_incr = XNEWVEC (tree, rank);
+  ind_init = XNEWVEC (tree, rank);
+
+  list_size = vec_safe_length (array_list);
+  count_down = XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    count_down[ii] = XNEWVEC (bool, rank);
+  
+  array_var = XNEWVEC (tree, rank);
+  an_init = push_stmt_list ();
+
+    /* Assign the array notation components to variable so that they can satisfy
+     the exec-once rule.  */
+  for (ii = 0; ii < list_size; ii++)
+    {
+      tree array_node = (*array_list)[ii];
+      if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF)
+	{
+	  tree array_begin = ARRAY_NOTATION_START (array_node);
+	  tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
+	  tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
+
+	  if (TREE_CODE (array_begin) != INTEGER_CST)
+	    {
+	      begin_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, begin_var,
+						     NOP_EXPR, array_begin,
+						     complain));
+	      ARRAY_NOTATION_START (array_node) = begin_var;
+	    }
+	  if (TREE_CODE (array_lngth) != INTEGER_CST)
+	    {
+	      lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, lngth_var,
+						     NOP_EXPR, array_lngth,
+						     complain));
+	      ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
+	    }
+	  if (TREE_CODE (array_strde) != INTEGER_CST)
+	    {
+	      strde_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, strde_var,
+						     NOP_EXPR, array_strde,
+						     complain));
+	      ARRAY_NOTATION_STRIDE (array_node) = strde_var;
+	    }
+	}
+    }
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      jj = 0;
+      jj_tree = (*array_list)[ii];
+      while (jj_tree)
+	{
+	  if (TREE_CODE (jj_tree) == ARRAY_NOTATION_REF)
+	    {
+	      array_ops[ii][jj] = jj_tree;
+	      jj++;
+	      jj_tree = ARRAY_NOTATION_ARRAY (jj_tree);
+	    }
+	  else if (TREE_CODE (jj_tree) == ARRAY_REF)
+	    jj_tree = TREE_OPERAND (jj_tree, 0);
+	  else if (TREE_CODE (jj_tree) == VAR_DECL
+		   || TREE_CODE (jj_tree) == PARM_DECL)
+	    break;
+	}
+    }
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      if (TREE_CODE ((*array_list)[ii]) == ARRAY_NOTATION_REF)
+	{
+	  for (jj = 0; jj < rank; jj++)
+	    {
+	      if (TREE_CODE (array_ops[ii][jj]) == ARRAY_NOTATION_REF)
+		{
+		  array_value[ii][jj] =
+		    ARRAY_NOTATION_ARRAY (array_ops[ii][jj]);
+		  array_start[ii][jj] =
+		    ARRAY_NOTATION_START (array_ops[ii][jj]);
+		  array_length[ii][jj] =
+		    ARRAY_NOTATION_LENGTH (array_ops[ii][jj]);
+		  array_stride[ii][jj] =
+		    ARRAY_NOTATION_STRIDE (array_ops[ii][jj]);
+		  array_vector[ii][jj] = true;
+
+		  if (!integer_zerop (array_length[ii][jj])
+		      && !integer_nonzerop (array_length[ii][jj]))
+		    count_down[ii][jj] = false;
+		  else if (tree_int_cst_lt
+			   (array_length[ii][jj],
+			    build_zero_cst (TREE_TYPE (array_length[ii][jj]))))
+		    count_down[ii][jj] = true;
+		  else
+		    count_down[ii][jj] = false;
+		}
+	      else
+		array_vector[ii][jj] = false;
+	    }
+	}
+    }
+  for (ii = 0; ii < rank; ii++)
+    {
+      if (TREE_TYPE (array_start[0][ii])
+	  && TREE_CODE (TREE_TYPE (array_start[0][ii])) != TEMPLATE_TYPE_PARM)
+	{
+	  array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
+				      TREE_TYPE (array_start[0][ii]));
+	  ind_init[ii] = build_x_modify_expr
+	    (location, array_var[ii], NOP_EXPR, 
+	     build_zero_cst (TREE_TYPE (array_var[ii])), tf_warning_or_error);
+	}
+      else
+	{
+	  array_var[ii] = build_min_nt_loc (location, VAR_DECL,
+					    NULL_TREE, NULL_TREE);
+	  ind_init[ii] = build_x_modify_expr (location, array_var[ii], 
+					      NOP_EXPR,
+					      integer_zero_node, 1);
+	}
+    }
+  for (ii = 0; ii < list_size; ii++)
+    {
+      if (array_vector[ii][0])
+	{
+	  tree array_opr = array_value[ii][rank - 1];
+	  for (s_jj = rank - 1; s_jj >= 0; s_jj--)
+	    {
+	      tree stride = NULL_TREE, var = NULL_TREE, start = NULL_TREE;
+
+	      /* If stride and start are of same type and the induction var
+		 is not, convert induction variable to stride's type.  */
+	      if ((TREE_TYPE (array_start[ii][s_jj]) ==
+		   TREE_TYPE (array_stride[ii][s_jj]))
+		  && (TREE_TYPE (array_stride[ii][s_jj]) !=
+		      TREE_TYPE (array_var[s_jj])))
+		{
+		  start = array_start[ii][s_jj];
+		  stride = array_stride[ii][s_jj];
+		  var =
+		    build_c_cast (location, TREE_TYPE (array_stride[ii][s_jj]),
+				  array_var[s_jj]);
+		}
+	      else if (TREE_TYPE (array_start[ii][s_jj]) !=
+			TREE_TYPE (array_stride[ii][s_jj]))
+		{
+		  /* If we reach here, then the stride and start are of
+		     different types, and so it doesn't really matter what
+		     the induction variable type is, we stay safe and convert
+		     everything to integer.  The reason why we pick an integer
+		     instead of something like size_t is because the stride
+		     and length can be + or -.  */
+		  start = build_c_cast (location, integer_type_node,
+					array_start[ii][s_jj]);
+		  stride = build_c_cast (location, integer_type_node,
+					 array_stride[ii][s_jj]);
+		  var = build_c_cast (location, integer_type_node,
+				      array_var[s_jj]);
+		}
+	      else
+		{
+		  start = array_start[ii][s_jj];
+		  stride = array_stride[ii][s_jj];
+		  var = array_var[s_jj];
+		}
+	      if (count_down[ii][s_jj])
+		/* Array[start_index - (induction_var * stride)].  */
+		array_opr = grok_array_decl
+		  (location, array_opr,
+		   build2 (MINUS_EXPR, TREE_TYPE (var), start,
+			   build2 (MULT_EXPR, TREE_TYPE (var), var, stride)),
+		   false);	
+	      else
+		/* Array[start_index + (induction_var * stride)].  */
+		array_opr = grok_array_decl
+		  (location, array_opr,
+		   build2 (PLUS_EXPR, TREE_TYPE (var), start,
+			   build2 (MULT_EXPR, TREE_TYPE (var), var, stride)),
+		   false);
+		
+	    }
+	  vec_safe_push (array_operand, array_opr);
+	}
+      else
+	vec_safe_push (array_operand, integer_one_node);
+    }
+  replace_array_notations (&stmt, true, array_list, array_operand);
+
+  for (ii = 0; ii < rank; ii++)
+    if (count_down[0][ii])
+      expr_incr[ii] = build_x_unary_op (location, POSTDECREMENT_EXPR,
+					array_var[ii], tf_warning_or_error);
+    else
+      expr_incr[ii] = build_x_unary_op (location, POSTINCREMENT_EXPR,
+					array_var[ii], tf_warning_or_error);
+  
+  for (jj = 0; jj < rank; jj++)
+    {
+      if (rank && expr_incr[jj])
+	{
+	  if (count_down[0][jj])
+	    compare_expr[jj] = build_x_binary_op
+	      (location, GT_EXPR, array_var[jj], TREE_CODE (array_var[jj]),
+	       array_length[0][jj], TREE_CODE (array_length[0][jj]), NULL,
+	       tf_warning_or_error);
+	  else
+	    compare_expr[jj] = build_x_binary_op
+	      (location, LT_EXPR, array_var[jj], TREE_CODE (array_var[jj]),
+	       array_length[0][jj], TREE_CODE (array_length[0][jj]), NULL,
+	       tf_warning_or_error);
+	}
+    }
+
+  an_init = pop_stmt_list (an_init);
+  append_to_statement_list_force (an_init, &loop_with_init);
+  body = stmt;
+
+  for (ii = 0; ii < rank; ii++)
+    {
+      tree new_loop = push_stmt_list ();
+      create_an_loop (ind_init[ii], compare_expr[ii], expr_incr[ii], body);
+      body = pop_stmt_list (new_loop);
+    }
+  append_to_statement_list_force (body, &loop_with_init);
+  
+  XDELETEVEC (compare_expr);
+  XDELETEVEC (expr_incr);
+  XDELETEVEC (ind_init);
+  XDELETEVEC (array_var);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      XDELETEVEC (count_down[ii]);
+      XDELETEVEC (array_value[ii]);
+      XDELETEVEC (array_stride[ii]);
+      XDELETEVEC (array_length[ii]);
+      XDELETEVEC (array_start[ii]);
+      XDELETEVEC (array_ops[ii]);
+      XDELETEVEC (array_vector[ii]);
+    }
+
+  XDELETEVEC (count_down);
+  XDELETEVEC (array_value);
+  XDELETEVEC (array_stride);
+  XDELETEVEC (array_length);
+  XDELETEVEC (array_start);
+  XDELETEVEC (array_ops);
+  XDELETEVEC (array_vector);
+
+  return loop_with_init;
+}
+
+/* Transforms array notations inside unary expression ORIG_STMT with an
+   appropriate loop and ARRAY_REF (and returns all this as a super-tree called
+   LOOP).  */
+
+static tree
+expand_unary_array_notation_exprs (tree orig_stmt)
+{
+  vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
+  int s_jj = 0;
+  size_t list_size = 0, rank = 0, ii = 0, jj = 0;
+  tree **array_ops, *array_var, jj_tree, body, array_opr;
+  tree **array_value, **array_stride, **array_length, **array_start;
+  tree *compare_expr, *expr_incr, *ind_init;
+  bool **count_down, **array_vector;
+  tree builtin_loop, stmt = NULL_TREE, new_var = NULL_TREE;
+  tree begin_var, lngth_var, strde_var;
+  location_t location = EXPR_LOCATION (orig_stmt);
+  tree an_init, loop_with_init = alloc_stmt_list ();
+  
+  if (!find_rank (location, orig_stmt, orig_stmt, true, &rank))
+    return error_mark_node;
+  if (rank == 0)
+    return orig_stmt;  
+  
+  extract_array_notation_exprs (orig_stmt, false, &array_list);
+  list_size = vec_safe_length (array_list);
+  location = EXPR_LOCATION (orig_stmt);
+  stmt = NULL_TREE;
+  for (ii = 0; ii < list_size; ii++)
+    {
+      tree list_node = (*array_list)[ii];
+      if (TREE_CODE (list_node) == CALL_EXPR
+	  || TREE_CODE (list_node) == AGGR_INIT_EXPR)
+	{
+	  builtin_loop = expand_sec_reduce_builtin (list_node, &new_var);
+	  if (builtin_loop == error_mark_node)
+	    return error_mark_node;
+	  else if (builtin_loop)
+	    {
+	      vec<tree, va_gc> *sub_list = NULL, *new_var_list = NULL;
+	      stmt = alloc_stmt_list ();
+	      append_to_statement_list_force (builtin_loop, &stmt);
+	      vec_safe_push (sub_list, list_node);
+	      vec_safe_push (new_var_list, new_var);
+	      replace_array_notations (&orig_stmt, false, sub_list,
+				       new_var_list);
+	    }
+	}
+    }
+  if (stmt != NULL_TREE)
+    append_to_statement_list_force (finish_expr_stmt (orig_stmt), &stmt);
+  else
+    stmt = orig_stmt;
+  rank = 0;
+  list_size = 0;
+  array_list = NULL;
+  extract_array_notation_exprs (stmt, true, &array_list);
+  list_size = vec_safe_length (array_list);
+
+  if (!find_rank (EXPR_LOCATION (stmt), stmt, stmt, true, &rank))
+    return error_mark_node;
+  if (rank == 0)
+    return stmt;
+  
+  if (list_size == 0)
+    return stmt;
+
+  array_ops = XNEWVEC (tree *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_ops[ii] = XNEWVEC (tree, rank);
+  
+  array_vector = XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++)
+    array_vector[ii] = XNEWVEC (bool, rank);
+
+  array_value = XNEWVEC (tree *, list_size);
+  array_stride = XNEWVEC (tree *, list_size);
+  array_length = XNEWVEC (tree *, list_size);
+  array_start = XNEWVEC (tree *, list_size);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      array_value[ii]  = XNEWVEC (tree, rank);
+      array_stride[ii] = XNEWVEC (tree, rank);
+      array_length[ii] = XNEWVEC (tree, rank);
+      array_start[ii]  = XNEWVEC (tree, rank);
+    }
+
+  compare_expr = XNEWVEC (tree, rank);
+  expr_incr = XNEWVEC (tree, rank);
+  ind_init = XNEWVEC (tree, rank);
+  array_var = XNEWVEC (tree, rank);
+  
+  count_down = XNEWVEC (bool *, list_size);
+  for (ii = 0; ii < list_size; ii++) 
+    count_down[ii] = XNEWVEC (bool,  rank);
+
+    /* Assign the array notation components to variable so that they can satisfy
+     the exec-once rule.  */
+  for (ii = 0; ii < list_size; ii++)
+    {
+      tree array_node = (*array_list)[ii];
+      tree array_begin = ARRAY_NOTATION_START (array_node);
+      tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
+      tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
+      tsubst_flags_t complain = tf_warning_or_error;
+      if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF)
+	{
+	  if (TREE_CODE (array_begin) != INTEGER_CST)
+	    {
+	      begin_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, begin_var,
+						     NOP_EXPR, array_begin,
+						     complain));
+	      ARRAY_NOTATION_START (array_node) = begin_var;
+	    }
+	  if (TREE_CODE (array_lngth) != INTEGER_CST)
+	    {
+	      lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, lngth_var,
+						     NOP_EXPR, array_lngth,
+						     complain));
+	      ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
+	    }
+	  if (TREE_CODE (array_strde) != INTEGER_CST)
+	    {
+	      strde_var = build_decl (location, VAR_DECL, NULL_TREE,
+				      integer_type_node);
+	      finish_expr_stmt (build_x_modify_expr (location, strde_var,
+						     NOP_EXPR, array_strde,
+						     complain));
+	      ARRAY_NOTATION_STRIDE (array_node) = strde_var;
+	    }
+	}
+    }
+  for (ii = 0; ii < list_size; ii++)
+    {
+      jj = 0;
+      jj_tree = (*array_list)[ii];
+      while (jj_tree)
+	{
+	  if (TREE_CODE (jj_tree) == ARRAY_NOTATION_REF)
+	    {
+	      array_ops[ii][jj] = jj_tree;
+	      jj++;
+	      jj_tree = ARRAY_NOTATION_ARRAY (jj_tree);
+	    }
+	  else if (TREE_CODE (jj_tree) == VAR_DECL
+		   || TREE_CODE (jj_tree) == PARM_DECL)
+	    break;
+	  else
+	    jj_tree = TREE_OPERAND (jj_tree, 0);
+	}
+    }
+  for (ii = 0; ii < list_size; ii++)
+    {
+      if (TREE_CODE ((*array_list)[ii]) == ARRAY_NOTATION_REF)
+	{
+	  for (jj = 0; jj < rank; jj++)
+	    {
+	      if (TREE_CODE (array_ops[ii][jj]) == ARRAY_NOTATION_REF)
+		{
+		  array_value[ii][jj] =
+		    ARRAY_NOTATION_ARRAY (array_ops[ii][jj]);
+		  array_start[ii][jj] =
+		    ARRAY_NOTATION_START (array_ops[ii][jj]);
+		  array_length[ii][jj] =
+		    ARRAY_NOTATION_LENGTH (array_ops[ii][jj]);
+		  array_stride[ii][jj] =
+		    ARRAY_NOTATION_STRIDE (array_ops[ii][jj]);
+		  array_vector[ii][jj] = true;
+
+		  if (!TREE_CONSTANT (array_length[ii][jj])
+		      || TREE_CODE (array_length[ii][jj]) == VAR_DECL)
+		    count_down[ii][jj] = false;
+		  else if (!integer_zerop (array_length[ii][jj])
+		      && !integer_nonzerop (array_length[ii][jj]))
+		      count_down[ii][jj] = false;
+		  else if (tree_int_cst_lt
+			   (array_length[ii][jj],
+			    build_zero_cst (TREE_TYPE (array_length[ii][jj]))))
+		    count_down[ii][jj] = true;
+		  else
+		    count_down[ii][jj] = false;
+		}
+	      else
+		array_vector[ii][jj] = false;
+	    }
+	}
+    }
+
+  an_init = push_stmt_list ();
+  for (ii = 0; ii < rank; ii++)
+    {
+      array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
+				  TREE_TYPE (array_start[0][ii]));
+      ind_init[ii] = build_x_modify_expr
+	(location, array_var[ii], NOP_EXPR, 
+	 build_zero_cst (TREE_TYPE (array_var[ii])), tf_warning_or_error);
+    }
+  for (ii = 0; ii < list_size; ii++)
+    {
+      if (array_vector[ii][0])
+	{
+	  array_opr = array_value[ii][rank - 1];
+	  for (s_jj = rank - 1; s_jj >= 0; s_jj--)
+	    {
+	      tree stride = NULL_TREE, var = NULL_TREE, start = NULL_TREE;
+	      if ((TREE_TYPE (array_start[ii][s_jj]) ==
+		   TREE_TYPE (array_stride[ii][s_jj]))
+		  && (TREE_TYPE (array_stride[ii][s_jj]) !=
+		      TREE_TYPE (array_var[s_jj])))
+		{
+		  /* If stride and start are of same type and the induction var
+		     is not, convert induction variable to stride's type.  */
+		  start = array_start[ii][s_jj];
+		  stride = array_stride[ii][s_jj];
+		  var =
+		    build_c_cast (location, TREE_TYPE (array_stride[ii][s_jj]),
+				  array_var[s_jj]);
+		}
+	      else if (TREE_TYPE (array_start[ii][s_jj]) !=
+			TREE_TYPE (array_stride[ii][s_jj]))
+		{
+		  /* If we reach here, then the stride and start are of
+		     different types, and so it doesn't really matter what
+		     the induction variable type is, convert everything to 
+		     integer.  The reason why we pick an integer
+		     instead of something like size_t is because the stride
+		     and length can be + or -.  */
+		  start = build_c_cast (location, integer_type_node,
+					array_start[ii][s_jj]);
+		  stride = build_c_cast (location, integer_type_node,
+					 array_stride[ii][s_jj]);
+		  var = build_c_cast (location, integer_type_node,
+				      array_var[s_jj]);
+		}
+	      else
+		{
+		  start = array_start[ii][s_jj];
+		  stride = array_stride[ii][s_jj];
+		  var = array_var[s_jj];
+		}
+	      if (count_down[ii][s_jj])
+		/* Array[start_index - (induction_var * stride)].  */
+		array_opr = grok_array_decl
+		  (location, array_opr,
+		   build2 (MINUS_EXPR, TREE_TYPE (var), start,
+			   build2 (MULT_EXPR, TREE_TYPE (var), var, stride)),
+		   false);	
+	      else
+		/* Array[start_index + (induction_var * stride)].  */
+		array_opr = grok_array_decl
+		  (location, array_opr,
+		   build2 (PLUS_EXPR, TREE_TYPE (var), start,
+			   build2 (MULT_EXPR, TREE_TYPE (var), var, stride)),
+		   false);
+	    }
+	  vec_safe_push (array_operand, array_opr);  
+	}
+      else
+	vec_safe_push (array_operand, integer_one_node);
+    }
+  replace_array_notations (&stmt, true, array_list, array_operand);
+
+  for (ii = 0; ii < rank; ii++)
+    if (count_down[0][ii])
+      expr_incr[ii] = build_x_unary_op (location, POSTDECREMENT_EXPR,
+					array_var[ii], tf_warning_or_error);
+    else
+      expr_incr[ii] = build_x_unary_op (location, POSTINCREMENT_EXPR,
+					array_var[ii], tf_warning_or_error);
+
+  for (jj = 0; jj < rank; jj++)
+    {
+      if (rank && expr_incr[jj])
+	{
+	  if (count_down[0][jj])
+	    compare_expr[jj] = build_x_binary_op
+	      (location, GT_EXPR, array_var[jj], TREE_CODE (array_var[jj]),
+	       array_length[0][jj], TREE_CODE (array_length[0][jj]), NULL,
+	       tf_warning_or_error);
+	  else
+	    compare_expr[jj] = build_x_binary_op
+	      (location, LT_EXPR, array_var[jj], TREE_CODE (array_var[jj]),
+	       array_length[0][jj], TREE_CODE (array_length[0][jj]), NULL,
+	       tf_warning_or_error);
+	}
+    }
+
+  an_init = pop_stmt_list (an_init);
+  append_to_statement_list_force (an_init, &loop_with_init);
+  body = stmt;
+  
+  for (ii = 0; ii < rank; ii++)
+    {
+      tree new_loop = push_stmt_list ();
+      create_an_loop (ind_init[ii], compare_expr[ii], expr_incr[ii], body);
+      body = pop_stmt_list (new_loop);
+    }
+  append_to_statement_list_force (body, &loop_with_init);
+
+  XDELETEVEC (compare_expr);
+  XDELETEVEC (expr_incr);
+  XDELETEVEC (ind_init);
+  XDELETEVEC (array_var);
+
+  for (ii = 0; ii < list_size; ii++)
+    {
+      XDELETEVEC (count_down[ii]);
+      XDELETEVEC (array_value[ii]);
+      XDELETEVEC (array_stride[ii]);
+      XDELETEVEC (array_length[ii]);
+      XDELETEVEC (array_start[ii]);
+      XDELETEVEC (array_ops[ii]);
+      XDELETEVEC (array_vector[ii]);
+    }
+    
+  XDELETEVEC (count_down);
+  XDELETEVEC (array_value);
+  XDELETEVEC (array_stride);
+  XDELETEVEC (array_length);
+  XDELETEVEC (array_start);
+  XDELETEVEC (array_ops);
+  XDELETEVEC (array_vector);
+
+  return loop_with_init;
+}
+
+/* Expands the array notation's builtin reduction function in EXPR
+   (of type RETURN_EXPR) and returns a STATEMENT_LIST that contains a loop
+   with the builtin function expansion and a return statement at the end.  */
+
+static tree
+expand_return_expr (tree expr)
+{
+  tree new_mod_list, new_var, new_mod, retval_expr;
+  location_t loc = EXPR_LOCATION (expr);
+
+  if (TREE_CODE (expr) != RETURN_EXPR)
+    return expr;
+
+  new_mod_list = alloc_stmt_list ();
+  retval_expr = TREE_OPERAND (expr, 0);
+  new_var = build_decl (loc, VAR_DECL, NULL_TREE, TREE_TYPE (retval_expr));
+  new_mod = expand_an_in_modify_expr (loc, new_var, NOP_EXPR,
+					 TREE_OPERAND (retval_expr, 1),
+					 tf_warning_or_error);
+  TREE_OPERAND (retval_expr, 1) = new_var;
+  TREE_OPERAND (expr, 0) = retval_expr;
+  append_to_statement_list_force (new_mod, &new_mod_list);
+  append_to_statement_list_force (expr, &new_mod_list);
+  return new_mod_list;
+}
+
+/* Expands ARRAY_NOTATION_REF and builtin functions in a compound statement,
+   STMT. Returns the STMT with expanded array notations.  */
+
+tree
+expand_array_notation_exprs (tree t)
+{
+  enum tree_code code;
+  bool is_expr;
+  location_t loc = UNKNOWN_LOCATION;
+  
+  /* Skip empty subtrees.  */
+  if (!t)
+    return t;
+
+  loc = EXPR_LOCATION (t);
+
+  code = TREE_CODE (t); 
+  is_expr = IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code));
+  switch (code)
+    {
+    case ERROR_MARK:
+    case IDENTIFIER_NODE:
+    case INTEGER_CST:
+    case REAL_CST:
+    case FIXED_CST:
+    case STRING_CST:
+    case BLOCK:
+    case PLACEHOLDER_EXPR:
+    case FIELD_DECL:
+    case VOID_TYPE:
+    case REAL_TYPE:
+    case SSA_NAME:
+    case LABEL_DECL:
+    case RESULT_DECL:
+    case VAR_DECL:
+    case PARM_DECL:
+    case NON_LVALUE_EXPR:
+    case NOP_EXPR:
+    case INIT_EXPR:
+    case ADDR_EXPR:
+    case ARRAY_REF:
+    case BIT_FIELD_REF:
+    case VECTOR_CST:
+    case COMPLEX_CST:
+      return t;
+    case MODIFY_EXPR:
+      if (contains_array_notation_expr (t))
+	t = expand_an_in_modify_expr (loc, TREE_OPERAND (t, 0), NOP_EXPR, 
+					 TREE_OPERAND (t, 1), 
+					 tf_warning_or_error);
+      return t;
+    case MODOP_EXPR:
+      if (contains_array_notation_expr (t) && !processing_template_decl)
+	t = expand_an_in_modify_expr
+	  (loc, TREE_OPERAND (t, 0), TREE_CODE (TREE_OPERAND (t, 1)),
+	   TREE_OPERAND (t, 2), tf_warning_or_error);
+      return t;
+    case CONSTRUCTOR:
+      return t;
+    case BIND_EXPR:
+      {
+	BIND_EXPR_BODY (t) =
+	  expand_array_notation_exprs  (BIND_EXPR_BODY (t));
+	return t;
+      }
+    case DECL_EXPR:
+      {
+	tree x = DECL_EXPR_DECL (t);
+	if (t && TREE_CODE (x) != FUNCTION_DECL)
+	  if (DECL_INITIAL (x))
+	    t = expand_unary_array_notation_exprs (t);
+      return t;
+      }
+    case STATEMENT_LIST:
+      {
+	tree_stmt_iterator i;
+	for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
+	  *tsi_stmt_ptr (i) =
+	    expand_array_notation_exprs (*tsi_stmt_ptr (i));
+	return t;
+      }
+
+    case OMP_PARALLEL:
+    case OMP_TASK:
+    case OMP_FOR:
+    case OMP_SINGLE:
+    case OMP_SECTION:
+    case OMP_SECTIONS:
+    case OMP_MASTER:
+    case OMP_ORDERED:
+    case OMP_CRITICAL:
+    case OMP_ATOMIC:
+    case OMP_CLAUSE:
+    case TARGET_EXPR:
+    case INTEGER_TYPE:
+    case ENUMERAL_TYPE:
+    case BOOLEAN_TYPE:
+    case POINTER_TYPE:
+    case ARRAY_TYPE:
+    case RECORD_TYPE:
+    case METHOD_TYPE:
+      return t;
+    case RETURN_EXPR:
+      if (contains_array_notation_expr (t))
+	t = expand_return_expr (t);
+      return t;
+    case PREDECREMENT_EXPR:
+    case PREINCREMENT_EXPR:
+    case POSTDECREMENT_EXPR:
+    case POSTINCREMENT_EXPR:
+    case AGGR_INIT_EXPR:
+    case CALL_EXPR:
+      t = expand_unary_array_notation_exprs (t);
+      return t;
+    case CONVERT_EXPR:
+    case CLEANUP_POINT_EXPR:
+    case EXPR_STMT:
+      TREE_OPERAND (t, 0) = expand_array_notation_exprs (TREE_OPERAND (t, 0));
+      /* It is not necessary to wrap error_mark_node in EXPR_STMT.  */
+      if (TREE_OPERAND (t, 0) == error_mark_node)
+	return TREE_OPERAND (t, 0); 
+      return t;
+    case COND_EXPR:
+      t = cp_expand_cond_array_notations (t);
+      if (TREE_CODE (t) == COND_EXPR)
+	{
+	  COND_EXPR_THEN (t) =
+	    expand_array_notation_exprs (COND_EXPR_THEN (t));
+	  COND_EXPR_ELSE (t) =
+	    expand_array_notation_exprs (COND_EXPR_ELSE (t));
+	}
+      else
+	t = expand_array_notation_exprs (t);
+      return t;
+
+    case SWITCH_EXPR:
+      t = cp_expand_cond_array_notations (t);
+      if (TREE_CODE (t) == SWITCH_EXPR)
+	SWITCH_BODY (t) = expand_array_notation_exprs (SWITCH_BODY (t));
+      else
+	t = expand_array_notation_exprs (t);
+      return t;
+      
+    case FOR_STMT:
+      
+      /* FIXME: Add a check for CILK_FOR_STMT here when we add Cilk tasking 
+	 keywords.  */
+      if (TREE_CODE (t) == FOR_STMT)
+	FOR_BODY (t) = expand_array_notation_exprs (FOR_BODY (t));
+      else
+	t = expand_array_notation_exprs (t);
+      return t;
+
+    case IF_STMT:
+      t = cp_expand_cond_array_notations (t);
+      /* If the above function added some extra instructions above the original
+	 if statement, then we can't assume it is still IF_STMT so we have to
+	 check again.  */
+      if (TREE_CODE (t) == IF_STMT)
+	{
+	  if (THEN_CLAUSE (t))
+	    THEN_CLAUSE (t) = expand_array_notation_exprs (THEN_CLAUSE (t));
+	  if (ELSE_CLAUSE (t))
+	    ELSE_CLAUSE (t) = expand_array_notation_exprs (ELSE_CLAUSE (t));
+	}
+      else
+	t = expand_array_notation_exprs (t);
+      return t;
+
+    case SWITCH_STMT:
+      t = cp_expand_cond_array_notations (t);
+      /* If the above function added some extra instructions above the original
+	 switch statement, then we can't assume it is still SWITCH_STMT so we
+	 have to check again.  */
+      if (TREE_CODE (t) == SWITCH_STMT)
+	{
+	  if (SWITCH_STMT_BODY (t))
+	    SWITCH_STMT_BODY (t) =
+	      expand_array_notation_exprs (SWITCH_STMT_BODY (t));
+	}
+      else
+	t = expand_array_notation_exprs (t);
+      return t;
+
+    case WHILE_STMT:
+      t = cp_expand_cond_array_notations (t);
+      /* If the above function added some extra instructions above the original
+	 while statement, then we can't assume it is still WHILE_STMTso we
+	 have to check again.  */
+      if (TREE_CODE (t) == WHILE_STMT)
+	{
+	  if (WHILE_BODY (t))
+	    WHILE_BODY (t) = expand_array_notation_exprs (WHILE_BODY (t));
+	}
+      else
+	t = expand_array_notation_exprs (t);
+      return t;
+      
+    case DO_STMT:
+      t = cp_expand_cond_array_notations (t);
+      /* If the above function added some extra instructions above the original
+	 do-while statement, then we can't assume it is still DO_STMT so we
+	 have to check again.  */
+      if (TREE_CODE (t) == DO_STMT)
+	{      
+	  if (DO_BODY (t))
+	    DO_BODY (t) = expand_array_notation_exprs (DO_BODY (t));
+	}
+      else
+	t = expand_array_notation_exprs (t);
+      return t;
+      
+    default:
+      if (is_expr)
+	{
+	  int i, len;
+
+	  /* Walk over all the sub-trees of this operand.  */
+	  len = TREE_CODE_LENGTH (code);
+
+	  /* Go through the subtrees.  We need to do this in forward order so
+	     that the scope of a FOR_EXPR is handled properly.  */
+	  for (i = 0; i < len; ++i)
+	    TREE_OPERAND (t, i) =
+	      expand_array_notation_exprs (TREE_OPERAND (t, i));
+	}
+      return t;
+    }
+  return t;
+}
+
+/* Given the base of an array (ARRAY), the START_INDEX, the number of elements
+   to be accessed (LENGTH) and the STRIDE, construct an ARRAY_NOTATION_REF tree
+   of type TYPE and return it.  Restrictions on START_INDEX, LENGTH and STRIDE 
+   are the same as that of index field passed into ARRAY_REF.  The only
+   additional restriction is that, unlike index in ARRAY_REF, stride, length
+   and start_index cannot contain array notations.  */
+
+tree
+build_array_notation_ref (location_t loc, tree array, tree start_index,
+			  tree length, tree stride, tree type)
+{
+  tree array_ntn_expr = NULL_TREE;
+  
+  /* When dealing with templates, do the type checking at a later time.  */
+  if (processing_template_decl || !type)
+    {
+      if (!type && TREE_TYPE (array))
+	type = TREE_TYPE (array);
+      array_ntn_expr = build_min_nt_loc (loc, ARRAY_NOTATION_REF, array,
+					 start_index, length, stride, type,
+					 NULL_TREE);
+      TREE_TYPE (array_ntn_expr) = type;
+    }
+  if (!stride)
+    {
+      if (TREE_CONSTANT (start_index) && TREE_CONSTANT (length)
+	  && TREE_CODE (start_index) != VAR_DECL
+	  && TREE_CODE (length) != VAR_DECL
+	  && tree_int_cst_lt (length, start_index))
+	stride = build_int_cst (TREE_TYPE (start_index), -1);
+      else
+	stride = build_int_cst (TREE_TYPE (start_index), 1);
+    }
+
+  if (!cilkplus_an_triplet_types_ok_p (loc, start_index, length, stride, type))
+    return error_mark_node;
+
+  if (!processing_template_decl)
+    {
+      array_ntn_expr = build4 (ARRAY_NOTATION_REF, NULL_TREE, NULL_TREE,
+			       NULL_TREE, NULL_TREE, NULL_TREE);
+      ARRAY_NOTATION_ARRAY (array_ntn_expr) = array;
+      ARRAY_NOTATION_START (array_ntn_expr) = start_index;
+      ARRAY_NOTATION_LENGTH (array_ntn_expr) = length;
+      ARRAY_NOTATION_STRIDE (array_ntn_expr) = stride;
+      if (type && (TREE_CODE (type) == ARRAY_TYPE
+		   || TREE_CODE (type) == POINTER_TYPE))
+	TREE_TYPE (array_ntn_expr) = TREE_TYPE (type);
+      else
+	TREE_TYPE (array_ntn_expr) = type;
+    }
+  SET_EXPR_LOCATION (array_ntn_expr, loc);
+
+  return array_ntn_expr;
+}
+
+
+/* Returns false if any of the Array notation triplet values: START_INDEX,
+   LENGTH and STRIDE, are not of integral type and have a rank greater than
+   zero.  */
+
+bool
+cilkplus_an_triplet_types_ok_p (location_t loc, tree start_index, tree length,
+				tree stride, tree type)
+{
+  size_t stride_rank = 0, length_rank = 0, start_rank = 0;
+  if (!TREE_TYPE (start_index) || !INTEGRAL_TYPE_P (TREE_TYPE (start_index)))
+    {
+      error_at (loc, "start-index of array notation triplet is not an integer");
+      return false;
+    }
+  if (!TREE_TYPE (length) || !INTEGRAL_TYPE_P (TREE_TYPE (length)))
+    {
+      error_at (loc, "length of array notation triplet is not an integer");
+      return false;
+    }
+  if (!TREE_TYPE (stride) || !INTEGRAL_TYPE_P (TREE_TYPE (stride)))
+    {
+      error_at (loc, "stride of array notation triplet is not an integer");
+      return false;
+    }
+  if (!TREE_CODE (type) == FUNCTION_TYPE)
+    {
+      error_at (loc, "array notations cannot be used with function type");
+      return false;
+    }
+
+  while (type && (TREE_CODE (type) == POINTER_TYPE
+		  || TREE_CODE (type) == ARRAY_TYPE))
+    {
+      type = TREE_TYPE (type);
+      if (type && TREE_CODE (type) == FUNCTION_TYPE)
+	{
+	  error_at (loc, "array notations cannot be used with function pointer"
+		    " arrays");
+	  return false;
+	}
+    }
+  if (!find_rank (loc, start_index, start_index, false, &start_rank)
+      || !find_rank (loc, length, length, false, &length_rank)
+      || !find_rank (loc, stride, stride, false, &stride_rank))
+    return false;
+
+  if (start_rank != 0)
+    {
+      error_at (loc, "rank of an array notation triplet%'s start-index is not "
+		"zero");
+      return false;
+    }
+  if (length_rank != 0)
+    {
+      error_at (loc, "rank of an array notation triplet%'s length is not zero");
+      return false;
+    }
+  if (stride_rank != 0)
+    {
+      error_at (loc, "rank of array notation triplet%'s stride is not zero");
+      return false;
+    }
+  return true;
+}
diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c
index bccd884..d301db0 100644
--- a/gcc/cp/cp-objcp-common.c
+++ b/gcc/cp/cp-objcp-common.c
@@ -321,6 +321,7 @@  cp_common_init_ts (void)
   MARK_TS_TYPED (USING_STMT);
   MARK_TS_TYPED (LAMBDA_EXPR);
   MARK_TS_TYPED (CTOR_INITIALIZER);
+  MARK_TS_TYPED (ARRAY_NOTATION_REF);
 }
 
 #include "gt-cp-cp-objcp-common.h"
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 9421822..4791a32 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6135,6 +6135,10 @@  extern bool cxx_omp_privatize_by_reference	(const_tree);
 extern void suggest_alternatives_for            (location_t, tree);
 extern tree strip_using_decl                    (tree);
 
+/* In cp/cp-array-notations.c */
+extern tree expand_array_notation_exprs         (tree);
+bool cilkplus_an_triplet_types_ok_p             (location_t, tree, tree, tree,
+						 tree);
 /* -- end of C++ */
 
 #endif /* ! GCC_CP_TREE_H */
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
old mode 100644
new mode 100755
index a75fc4e..a8f52cd
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -1071,6 +1071,17 @@  dump_decl (tree t, int flags)
       pp_cxx_right_bracket (cxx_pp);
       break;
 
+    case ARRAY_NOTATION_REF:
+      dump_decl (ARRAY_NOTATION_ARRAY (t), flags | TFF_EXPR_IN_PARENS);
+      pp_cxx_left_bracket (cxx_pp);
+      dump_decl (ARRAY_NOTATION_START (t), flags | TFF_EXPR_IN_PARENS);
+      pp_string (cxx_pp, ":");
+      dump_decl (ARRAY_NOTATION_LENGTH (t), flags | TFF_EXPR_IN_PARENS);
+      pp_string (cxx_pp, ":");
+      dump_decl (ARRAY_NOTATION_STRIDE (t), flags | TFF_EXPR_IN_PARENS);
+      pp_cxx_right_bracket (cxx_pp);
+      break;
+
       /* So that we can do dump_decl on an aggr type.  */
     case RECORD_TYPE:
     case UNION_TYPE:
@@ -2057,6 +2068,17 @@  dump_expr (tree t, int flags)
       pp_cxx_right_bracket (cxx_pp);
       break;
 
+    case ARRAY_NOTATION_REF:
+      dump_expr (ARRAY_NOTATION_ARRAY (t), flags | TFF_EXPR_IN_PARENS);
+      pp_cxx_left_bracket (cxx_pp);
+      dump_expr (ARRAY_NOTATION_START (t), flags | TFF_EXPR_IN_PARENS);
+      pp_string (cxx_pp, ":");
+      dump_expr (ARRAY_NOTATION_LENGTH (t), flags | TFF_EXPR_IN_PARENS);
+      pp_string (cxx_pp, ":");
+      dump_expr (ARRAY_NOTATION_STRIDE (t), flags | TFF_EXPR_IN_PARENS);
+      pp_cxx_right_bracket (cxx_pp);
+      break;
+
     case UNARY_PLUS_EXPR:
       dump_unary_op ("+", t, flags);
       break;
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
old mode 100644
new mode 100755
index a581e88..523dcf7
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -6060,6 +6060,168 @@  cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
   return error_mark_node;
 }
 
+/* This function parses Cilk Plus array notations.  The starting index is
+   passed in INIT_INDEX and the array name is passed in ARRAY_VALUE.  The 
+   return value of this function is a tree node called VALUE_TREE of type
+   ARRAY_NOTATION_REF.  If some error occurred it returns error_mark_node.  */
+
+static tree
+cp_parser_array_notation (location_t loc, cp_parser *parser, tree init_index,
+			  tree array_value)
+{
+  cp_token *token = NULL;
+  tree start_index = NULL_TREE, length_index = NULL_TREE, stride = NULL_TREE;
+  tree value_tree, type, array_type, array_type_domain;
+  double_int x; 
+  bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
+
+  if (!array_value || array_value == error_mark_node)
+    {
+      cp_parser_skip_to_end_of_statement (parser);
+      return error_mark_node;
+    }
+  
+  if (processing_template_decl)
+    {
+      array_type = TREE_TYPE (array_value);
+      type = TREE_TYPE (array_type);
+    }
+  else
+    {
+      array_type = TREE_TYPE (array_value);
+      gcc_assert (array_type);
+      type = array_type;
+    }
+  token = cp_lexer_peek_token (parser->lexer);
+  if (!token)
+    {
+      cp_parser_error (parser, "expected %<:%> or numeral");
+      return error_mark_node;
+    }
+  else if (token->type == CPP_COLON)
+    {
+      if (!init_index)
+	{
+	  /* If we are here, then we have a case like this A[:].  */
+	  cp_lexer_consume_token (parser->lexer);
+
+	  if (cp_lexer_peek_token (parser->lexer)->type != CPP_CLOSE_SQUARE)
+	    {
+	      cp_parser_error (parser, "expected %<]%>");
+	      cp_parser_skip_to_end_of_statement (parser);
+	      return error_mark_node;
+	    }
+	  if (TREE_CODE (array_type) == RECORD_TYPE
+	      || TREE_CODE (array_type) == POINTER_TYPE)
+	    {
+	      error_at (loc, "start-index and length fields necessary for "
+			"using array notations in pointers or records");
+	      cp_parser_skip_to_end_of_statement (parser);
+	      return error_mark_node;
+	    }
+	  if (TREE_CODE (array_type) == ARRAY_TYPE)
+	    {
+	      tree subtype = TREE_TYPE (array_type);
+	      while (subtype && TREE_CODE (subtype) == POINTER_TYPE)
+		{
+		  /* This could be a function ptr.  If so, then emit error.  */
+		  subtype = TREE_TYPE (subtype);
+		  if (subtype && TREE_CODE (subtype) == FUNCTION_TYPE)
+		    {
+		      error_at (loc, "array notations cannot be used with"
+				" function pointer arrays");
+		      cp_parser_skip_to_end_of_statement (parser);
+		      return error_mark_node;
+		    }
+		}
+	    }
+	  array_type_domain = TYPE_DOMAIN (array_type);
+	  if (!array_type_domain)
+	    {
+	      error_at (loc, "start-index and length fields necessary for "
+			"using array notations in dimensionless arrays");
+	      cp_parser_skip_to_end_of_statement (parser);
+	      return error_mark_node;
+	    }
+	  start_index = TYPE_MINVAL (array_type_domain);
+	  start_index = fold_build1 (CONVERT_EXPR, ptrdiff_type_node,
+				     start_index);
+	  x = TREE_INT_CST (TYPE_MAXVAL (array_type_domain));
+	  x.low++;
+	  length_index = double_int_to_tree (integer_type_node, x);
+	  length_index = fold_build1 (CONVERT_EXPR, ptrdiff_type_node,
+				      length_index);
+	  stride = build_int_cst (integer_type_node, 1);
+	  stride = fold_build1 (CONVERT_EXPR, ptrdiff_type_node, stride);
+	}
+      else if (init_index != error_mark_node)
+	{
+	  /* If we hare here, then there are 2 possibilities:
+	     1. Array [ EXPR : EXPR ]
+	     2. Array [ EXPR : EXPR : EXPR ]
+	  */
+	  start_index = init_index;
+	  cp_lexer_consume_token (parser->lexer);
+
+	  saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
+	   /* The ':' is used in array notation.  Thus compiler cannot do scope 
+	      correction automatically.  */
+	  parser->colon_corrects_to_scope_p = false;
+	  length_index = cp_parser_expression (parser, false, NULL);
+	  parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
+	  if (!length_index || length_index == error_mark_node)
+	    cp_parser_skip_to_end_of_statement (parser);
+	 
+	  if (cp_lexer_peek_token (parser->lexer)->type == CPP_COLON)
+	    {
+	      cp_lexer_consume_token (parser->lexer);
+	      saved_colon_corrects_to_scope_p = 
+		parser->colon_corrects_to_scope_p;
+	      /* Disable correcting single colon correcting to scope.  */
+	      parser->colon_corrects_to_scope_p = false;
+	      stride = cp_parser_expression (parser, false, NULL);
+	      parser->colon_corrects_to_scope_p = 
+		saved_colon_corrects_to_scope_p;
+	      if (!stride || stride == error_mark_node)
+		{
+		  cp_parser_skip_to_end_of_statement (parser);
+		  if (cp_lexer_peek_token (parser->lexer)->type
+		      == CPP_CLOSE_SQUARE)
+		    cp_lexer_consume_token (parser->lexer);
+		}
+	    }
+	  else
+	    stride = build_one_cst (integer_type_node);
+	}
+      else
+	{
+	  cp_parser_skip_to_end_of_statement (parser);
+	  return error_mark_node;
+	}
+    }
+  
+  if (start_index == error_mark_node || length_index == error_mark_node
+      || stride == error_mark_node || !start_index || !length_index
+      || !stride)
+    {
+      if (cp_lexer_peek_token (parser->lexer)->type == CPP_CLOSE_SQUARE)
+	cp_lexer_consume_token (parser->lexer);
+      return error_mark_node;
+    }
+  cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
+  
+  /* We fold all 3 of the values to make things easier when we transform
+     them later.  */
+  start_index = fold (start_index);
+  length_index = fold (length_index);
+  stride = fold (stride);
+
+  value_tree = build_array_notation_ref (input_location, array_value,
+					 start_index, length_index, stride,
+					 type);
+  return value_tree;
+}
+
 /* A subroutine of cp_parser_postfix_expression that also gets hijacked
    by cp_parser_builtin_offsetof.  We're looking for
 
@@ -6081,41 +6243,78 @@  cp_parser_postfix_open_square_expression (cp_parser *parser,
   /* Consume the `[' token.  */
   cp_lexer_consume_token (parser->lexer);
 
-  /* Parse the index expression.  */
-  /* ??? For offsetof, there is a question of what to allow here.  If
-     offsetof is not being used in an integral constant expression context,
-     then we *could* get the right answer by computing the value at runtime.
-     If we are in an integral constant expression context, then we might
-     could accept any constant expression; hard to say without analysis.
-     Rather than open the barn door too wide right away, allow only integer
-     constant expressions here.  */
-  if (for_offsetof)
-    index = cp_parser_constant_expression (parser, false, NULL);
+  if (flag_enable_cilkplus
+      && cp_lexer_peek_token (parser->lexer)->type == CPP_COLON)
+    /* If we are here, then we have something like this:
+       ARRAY[:]
+    */
+    postfix_expression = cp_parser_array_notation (loc, parser, NULL_TREE,
+						   postfix_expression);
   else
     {
-      if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+      /* Here are have these options:
+	 1. ARRAY[EXPR]               -- This is the normal array call.
+	 2. ARRAY[EXPR : EXPR]        -- Array notation expr with default stride
+	 of 1.
+	 3. ARRAY[EXPR : EXPR : EXPR] -- Array Notation with userdefined stride.
+	 4. Array[Braced List]        -- This is handled by braced list.
+      */
+      
+      /* Parse the index expression.  */
+      /* ??? For offsetof, there is a question of what to allow here.  If
+	 offsetof is not being used in an integral constant expression context,
+	 then we *could* get the right answer by computing the value at runtime.
+	 If we are in an integral constant expression context, then we might
+	 could accept any constant expression; hard to say without analysis.
+	 Rather than open the barn door too wide right away, allow only integer
+	 constant expressions here.  */
+      if (for_offsetof)
+	index = cp_parser_constant_expression (parser, false, NULL);
+      else
 	{
-	  bool expr_nonconst_p;
-	  maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
-	  index = cp_parser_braced_list (parser, &expr_nonconst_p);
+	  bool saved_colon_corrects_to_scope_p = 
+	    parser->colon_corrects_to_scope_p;
+	  if (flag_enable_cilkplus)
+	    parser->colon_corrects_to_scope_p = false;
+	  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+	    {
+	      bool expr_nonconst_p;
+	      maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
+	      index = cp_parser_braced_list (parser, &expr_nonconst_p);
+	      if (flag_enable_cilkplus
+		  && cp_lexer_peek_token (parser->lexer)->type == CPP_COLON)
+		{
+		  error_at (cp_lexer_peek_token (parser->lexer)->location,
+			    "braced list index is not allowed with array "
+			    "notations");
+		  index = error_mark_node;
+		}
+	    }
+	  else
+	    index = cp_parser_expression (parser, /*cast_p=*/false, NULL);
+	  parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
 	}
+      if (flag_enable_cilkplus
+	  && cp_lexer_peek_token (parser->lexer)->type == CPP_COLON)
+	postfix_expression = cp_parser_array_notation (loc, parser, index,
+						       postfix_expression);
       else
-	index = cp_parser_expression (parser, /*cast_p=*/false, NULL);
-    }
-
-  /* Look for the closing `]'.  */
-  cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
-
-  /* Build the ARRAY_REF.  */
-  postfix_expression = grok_array_decl (loc, postfix_expression,
-					index, decltype_p);
+	{
+  	  /* Look for the closing `]'.  */
+	  cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
 
-  /* When not doing offsetof, array references are not permitted in
-     constant-expressions.  */
-  if (!for_offsetof
-      && (cp_parser_non_integral_constant_expression (parser, NIC_ARRAY_REF)))
-    postfix_expression = error_mark_node;
+	  /* Build the ARRAY_REF.  */
+	  postfix_expression = grok_array_decl (loc, postfix_expression,
+						index, decltype_p);
 
+	  /* When not doing offsetof, array references are not permitted in
+	     constant-expressions.  */
+	  if (!for_offsetof
+	      && (cp_parser_non_integral_constant_expression (parser,
+							      NIC_ARRAY_REF)))
+	    postfix_expression = error_mark_node;
+	}
+    }
   return postfix_expression;
 }
 
@@ -9342,6 +9541,8 @@  cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr,
   /* Consume the `}'.  */
   cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
 
+  if (flag_enable_cilkplus && contains_array_notation_expr (compound_stmt))
+    compound_stmt = expand_array_notation_exprs (compound_stmt);
   return compound_stmt;
 }
 
@@ -9534,6 +9735,14 @@  cp_parser_selection_statement (cp_parser* parser, bool *if_p)
 
 	    /* Now we're all done with the switch-statement.  */
 	    finish_switch_stmt (statement);
+	    if (flag_enable_cilkplus
+		&& contains_array_notation_expr (condition))
+	      {
+		error_at (EXPR_LOCATION (condition),
+			  "array notations cannot be used as a condition for "
+			  "switch statement");
+		statement = error_mark_node;
+	      }      
 	  }
 
 	return statement;
@@ -10094,6 +10303,12 @@  cp_parser_iteration_statement (cp_parser* parser)
 	parser->in_statement = in_statement;
 	/* We're done with the while-statement.  */
 	finish_while_stmt (statement);
+	if (flag_enable_cilkplus && contains_array_notation_expr (condition))
+	  {
+	    error_at (EXPR_LOCATION (condition), "array notations cannot be "
+		      "used as a condition for while statement");
+	    statement = error_mark_node;
+	  }
       }
       break;
 
@@ -10120,6 +10335,15 @@  cp_parser_iteration_statement (cp_parser* parser)
 	cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
 	/* Look for the `;'.  */
 	cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
+	if (flag_enable_cilkplus
+	    && contains_array_notation_expr (DO_COND (statement)))
+	  {
+	    error_at (EXPR_LOCATION (DO_COND (statement)),
+		      "array notations cannot be used as a condition for a "
+		      "do-while statement");
+	    statement = error_mark_node;
+	  }
+
       }
       break;
 
@@ -10138,8 +10362,17 @@  cp_parser_iteration_statement (cp_parser* parser)
 	cp_parser_already_scoped_statement (parser);
 	parser->in_statement = in_statement;
 
-	/* We're done with the for-statement.  */
-	finish_for_stmt (statement);
+	if (flag_enable_cilkplus
+	    && contains_array_notation_expr (FOR_COND (statement)))
+	  {
+	    error_at (EXPR_LOCATION (FOR_COND (statement)),
+		      "array notations cannot be used in a condition for a "
+		      "for-loop");
+	    statement = error_mark_node;
+	  }
+	else
+	  /* We're done with the for-statement.  */
+	  finish_for_stmt (statement);
       }
       break;
 
@@ -16714,30 +16947,53 @@  cp_parser_direct_declarator (cp_parser* parser,
 	    {
 	      bool non_constant_p;
 
-	      bounds
-		= cp_parser_constant_expression (parser,
-						 /*allow_non_constant=*/true,
-						 &non_constant_p);
-	      if (!non_constant_p)
-		/* OK */;
-	      else if (error_operand_p (bounds))
-		/* Already gave an error.  */;
-	      else if (!parser->in_function_body
-		       || current_binding_level->kind == sk_function_parms)
+	      if (flag_enable_cilkplus
+		  && cp_lexer_next_token_is (parser->lexer, CPP_COLON))
 		{
-		  /* Normally, the array bound must be an integral constant
-		     expression.  However, as an extension, we allow VLAs
-		     in function scopes as long as they aren't part of a
-		     parameter declaration.  */
-		  cp_parser_error (parser,
-				   "array bound is not an integer constant");
 		  bounds = error_mark_node;
+		  error_at (cp_lexer_peek_token (parser->lexer)->location,
+			    "array notations cannot be used in declaration");
+		  cp_lexer_consume_token (parser->lexer);
 		}
-	      else if (processing_template_decl)
+	      else
 		{
-		  /* Remember this wasn't a constant-expression.  */
-		  bounds = build_nop (TREE_TYPE (bounds), bounds);
-		  TREE_SIDE_EFFECTS (bounds) = 1;
+		  bounds
+		    = cp_parser_constant_expression (parser,
+						     /*allow_non_constant=*/true,
+						     &non_constant_p);
+		  if (!non_constant_p)
+		    /* OK */;
+		  else if (error_operand_p (bounds))
+		    /* Already gave an error.  */;
+		  else if (!parser->in_function_body
+			   || current_binding_level->kind == sk_function_parms)
+		    {
+		      /* Normally, the array bound must be an integral constant
+			 expression.  However, as an extension, we allow VLAs
+			 in function scopes as long as they aren't part of a
+			 parameter declaration.  */
+		      cp_parser_error (parser,
+				       "array bound is not an integer constant");
+		      bounds = error_mark_node;
+		    }
+		  else if (processing_template_decl)
+		    {
+		      /* Remember this wasn't a constant-expression.  */
+		      bounds = build_nop (TREE_TYPE (bounds), bounds);
+		      TREE_SIDE_EFFECTS (bounds) = 1;
+		    }
+		  if (flag_enable_cilkplus
+		      && cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+		    {
+		      location_t loc =
+			cp_lexer_peek_token (parser->lexer)->location;
+		      while (cp_lexer_next_token_is_not (parser->lexer,
+							 CPP_CLOSE_SQUARE))
+			cp_lexer_consume_token (parser->lexer);
+		      error_at (loc, "array notations cannot be used in "
+			 	"declaration");
+		      bounds = error_mark_node; 
+		    }
 		}
 	    }
 	  else
@@ -18108,6 +18364,11 @@  cp_parser_ctor_initializer_opt_and_function_body (cp_parser *parser,
   cp_parser_function_body (parser, in_function_try_block);
   if (check_body_p)
     check_constexpr_ctor_body (last, list);
+
+  /* Transform all array notations to the equivalent array refs and loop.  */
+  if (flag_enable_cilkplus && contains_array_notation_expr (body))
+    body = expand_array_notation_exprs (body);
+  
   /* Finish the function body.  */
   finish_function_body (body);
 
@@ -22087,6 +22348,12 @@  cp_parser_function_definition_after_declarator (cp_parser* parser,
 
   finish_lambda_scope ();
 
+  /* Expand all array notation expressions here.  */
+  if (flag_enable_cilkplus && current_function_decl
+      && contains_array_notation_expr (DECL_SAVED_TREE (current_function_decl)))
+    DECL_SAVED_TREE (current_function_decl) =
+      expand_array_notation_exprs (DECL_SAVED_TREE (current_function_decl));
+  
   /* Finish the function.  */
   fn = finish_function ((ctor_initializer_p ? 1 : 0) |
 			(inline_p ? 2 : 0));
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
old mode 100644
new mode 100755
index 3602fcd..0a7d523
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -13740,6 +13740,20 @@  tsubst_copy_and_build (tree t,
 				 RECUR (TREE_OPERAND (t, 1)),
 				 complain|decltype_flag));
 
+    case ARRAY_NOTATION_REF:
+      {
+	tree start_index, length, stride;
+	op1 = tsubst_non_call_postfix_expression (ARRAY_NOTATION_ARRAY (t),
+						  args, complain, in_decl);
+	start_index = RECUR (ARRAY_NOTATION_START (t));
+	length = RECUR (ARRAY_NOTATION_LENGTH (t));
+	stride = RECUR (ARRAY_NOTATION_STRIDE (t));
+	if (!cilkplus_an_triplet_types_ok_p (loc, start_index, length, stride,
+					     TREE_TYPE (op1)))
+	  RETURN (error_mark_node);
+	RETURN (build_array_notation_ref (EXPR_LOCATION (t), op1, start_index,
+					  length, stride, TREE_TYPE (op1)));
+      }
     case SIZEOF_EXPR:
       if (PACK_EXPANSION_P (TREE_OPERAND (t, 0)))
 	RETURN (tsubst_copy (t, args, complain, in_decl));
@@ -15712,6 +15726,9 @@  type_unification_real (tree tparms,
       arg = args[ia];
       ++ia;
 
+      if (flag_enable_cilkplus && TREE_CODE (arg) == ARRAY_NOTATION_REF)
+	return 1;
+
       if (unify_one_argument (tparms, targs, parm, arg, subr, strict,
 			      flags, explain_p))
 	return 1;
@@ -19119,6 +19136,11 @@  instantiate_decl (tree d, int defer_ok,
       pointer_map_destroy (local_specializations);
       local_specializations = saved_local_specializations;
 
+      /* We expand all the array notation expressions here.  */
+      if (flag_enable_cilkplus
+	  && contains_array_notation_expr (DECL_SAVED_TREE (d)))
+	DECL_SAVED_TREE (d) = expand_array_notation_exprs (DECL_SAVED_TREE (d));
+      
       /* Finish the function.  */
       d = finish_function (0);
       expand_or_defer_fn (d);
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index b5c3b0a..656962b 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -779,6 +779,22 @@  finish_return_stmt (tree expr)
   tree r;
   bool no_warning;
 
+  if (flag_enable_cilkplus && contains_array_notation_expr (expr))
+    {
+      size_t rank = 0;
+      
+      if (!find_rank (input_location, expr, expr, false, &rank))
+	return error_mark_node;
+
+      /* If the return expression contains array notatinos, then flag it as
+	 error.  */
+      if (rank >= 1)
+	{
+	  error_at (input_location, "array notation expression cannot be "
+		    "used as a return value");
+	  return error_mark_node;
+	}
+    }
   expr = check_return_expr (expr, &no_warning);
 
   if (flag_openmp && !check_omp_return ())
@@ -8066,6 +8082,7 @@  cxx_eval_constant_expression (const constexpr_call *call, tree t,
 				       non_constant_p, overflow_p);
       break;
 
+    case ARRAY_NOTATION_REF:
     case ARRAY_REF:
       r = cxx_eval_array_reference (call, t, allow_non_constant, addr,
 				    non_constant_p, overflow_p);
@@ -8877,6 +8894,7 @@  potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
       want_rval = true;
       /* Fall through.  */
     case ARRAY_REF:
+    case ARRAY_NOTATION_REF:
     case ARRAY_RANGE_REF:
     case MEMBER_REF:
     case DOTSTAR_EXPR:
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 8524f6c..dd2fda4 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -141,6 +141,7 @@  lvalue_kind (const_tree ref)
     case INDIRECT_REF:
     case ARROW_EXPR:
     case ARRAY_REF:
+    case ARRAY_NOTATION_REF:
     case PARM_DECL:
     case RESULT_DECL:
       return clk_ordinary;
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
old mode 100644
new mode 100755
index 11ac85b..17f19c7
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -3005,6 +3005,22 @@  cp_build_array_ref (location_t loc, tree array, tree idx,
       return error_mark_node;
     }
 
+  /* If an array's index is an array notation, then its rank cannot be
+     greater than one.  */ 
+  if (flag_enable_cilkplus && contains_array_notation_expr (idx))
+    {
+      size_t rank = 0;
+
+      /* If find_rank returns false,  then it should have reported an error,
+	 thus it is unnecessary for repetition.  */
+      if (!find_rank (loc, idx, idx, true, &rank))
+	return error_mark_node;
+      if (rank > 1)
+	{
+	  error_at (loc, "rank of the array%'s index is greater than 1");
+	  return error_mark_node;
+	}
+    }
   if (TREE_TYPE (array) == error_mark_node
       || TREE_TYPE (idx) == error_mark_node)
     return error_mark_node;
@@ -3477,8 +3493,12 @@  cp_build_function_call_vec (tree function, vec<tree, va_gc> **params,
       params = &allocated;
     }
 
-  nargs = convert_arguments (parm_types, params, fndecl, LOOKUP_NORMAL,
-			     complain);
+  if (flag_enable_cilkplus
+      && is_cilkplus_reduce_builtin (fndecl) != BUILT_IN_NONE)
+    nargs = (*params)->length ();
+  else
+    nargs = convert_arguments (parm_types, params, fndecl, LOOKUP_NORMAL,
+			       complain);
   if (nargs < 0)
     return error_mark_node;
 
@@ -3936,8 +3956,15 @@  cp_build_binary_op (location_t location,
 	}
     }
 
-  type0 = TREE_TYPE (op0);
-  type1 = TREE_TYPE (op1);
+  if (flag_enable_cilkplus && contains_array_notation_expr (op0))
+    type0 = find_correct_array_notation_type (op0);
+  else
+    type0 = TREE_TYPE (op0);
+
+  if (flag_enable_cilkplus && contains_array_notation_expr (op1))
+    type1 = find_correct_array_notation_type (op1);
+  else
+    type1 = TREE_TYPE (op1);
 
   /* The expression codes of the data types of the arguments tell us
      whether the arguments are integers, floating, pointers, etc.  */
@@ -5140,6 +5167,13 @@  cp_build_addr_expr_1 (tree arg, bool strict_lvalue, tsubst_flags_t complain)
 
   gcc_assert (!identifier_p (arg) || !IDENTIFIER_OPNAME_P (arg));
 
+  if (flag_enable_cilkplus && TREE_CODE (arg) == ARRAY_NOTATION_REF)
+    {
+      val = build_address (arg);
+      if (TREE_CODE (arg) == OFFSET_REF)
+	PTRMEM_OK_P (val) = PTRMEM_OK_P (arg);
+      return val;
+    }
   if (TREE_CODE (arg) == COMPONENT_REF && type_unknown_p (arg)
       && !really_overloaded_fn (TREE_OPERAND (arg, 1)))
     {
@@ -7818,6 +7852,13 @@  convert_for_assignment (tree type, tree rhs,
   tree rhstype;
   enum tree_code coder;
 
+  /* If we are dealing with built-in array notation function then we don't need
+     to convert them. They will be broken up into modify exprs in future,
+     during which all these checks will be done.  */
+  if (flag_enable_cilkplus
+      && is_cilkplus_reduce_builtin (fndecl) != BUILT_IN_NONE)
+    return rhs;
+  
   /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue.  */
   if (TREE_CODE (rhs) == NON_LVALUE_EXPR)
     rhs = TREE_OPERAND (rhs, 0);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
old mode 100644
new mode 100755
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/array_test1.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/array_test1.c
index e4f1ea8..282a55d 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/array_test1.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/array_test1.c
@@ -1,4 +1,4 @@ 
-/* { dg-do compile } */
+/* { dg-do run } */
 /* { dg-options "-fcilkplus" } */
 
 #include <stdlib.h>
@@ -47,7 +47,7 @@  int main2 (char **argv)
   array[x:y:z] = 505;
   for (ii = x; ii < 10; ii += z)
     if (array[ii] != 505)
-      return 2;
+      return 4;
     
   x = atoi(argv[1]);
   z = (10-atoi(argv[1]))/atoi(argv[1]);
@@ -57,7 +57,7 @@  int main2 (char **argv)
 
   for (ii = x; ii < 10; ii += z)
     if (array[ii] != 25)
-      return 1;
+      return 5;
   x = atoi(argv[1]);
   z = (10-atoi(argv[1]))/atoi(argv[1]);
   y = 10-atoi(argv[1]);
@@ -66,19 +66,19 @@  int main2 (char **argv)
     1400;
   for (ii = x; ii < 10; ii += z)
     if (array[ii] != 1400)
-      return 1;
+      return 6;
   
 
   array[atoi("5"):5:1] = 5555;
   
   for (ii = atoi ("5"); ii < 10; ii++)
     if (array[ii] != 5555)
-      return 2;
+      return 7;
   
 
   array[atoi("5"):atoi("5"):atoi("1")] = 9999;
   for (ii = atoi ("5"); ii < (atoi ("5") + atoi ("5")); ii += atoi ("1"))
     if (array[ii] != 9999)
-      return 3;
+      return 8;
   return 0;
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c
index d17d8cf..579d396 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c
@@ -18,19 +18,19 @@  int main (void)
     array2[:] = 5;
   else
     array2[:] = 10;
-  if (!(array[0:10:1] + array[0:10:1])) /* { dg-error "condition and the then-block" } */
-    array2d[:][:] = 5;
+  if (!(array[0:10:1] + array[0:10:1])) /* { dg-error "condition and the then-block" "" { target c } } */
+    array2d[:][:] = 5; /* { dg-error "rank mismatch with controlling expression of parent" "" { target c++ } } */
   else
     array2[:] = 10;
 
-  if (!(array[0:10:1] + array[0:10:1])) /* { dg-error "condition and the else-block" } */
+  if (!(array[0:10:1] + array[0:10:1])) /* { dg-error "condition and the else-block" "" { target c } } */
     array2[:] = 5;
   else
-    array2d[:][:] = 10;
+    array2d[:][:] = 10; /* { dg-error "rank mismatch with controlling expression of parent" "" { target c++ } } */
 
 
-  if (TwodArray[:][:] != 10) /* { dg-error "condition and the then-block" } */
-    array2[:] = 10; 
+  if (TwodArray[:][:] != 10) /* { dg-error "condition and the then-block" "" { target c } } */
+    array2[:] = 10;  /* { dg-error "rank mismatch with controlling expression of parent" "" { target c++ } } */
   else
     array2[:] = 5;
 
@@ -40,8 +40,8 @@  int main (void)
     array4[32][:][:][:] = 5;
 
   /* atoi(argv[1]) == 10, so it will convert all 10's to 5's */
-  if (FourDArray[42][0:10:1][9:10:-1][0:5:2] != 10) /* { dg-error "condition and the then-block" } */
-    array4[0:10:1][0:5:2][9:10:-1][0:5:2] = 10; 
+  if (FourDArray[42][0:10:1][9:10:-1][0:5:2] != 10) /* { dg-error "condition and the then-block" "" { target c } } */
+    array4[0:10:1][0:5:2][9:10:-1][0:5:2] = 10;  /* { dg-error "rank mismatch with controlling expression of parent" "" { target c++ } } */
   else
     array4[0:10:1][0:5:2][9:10:-1][0:5:2] = 5;
 
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
index 35eb115..14421d9 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
@@ -73,13 +73,13 @@  int main (void)
   while (ii != array2[1:x:3][1:2:1]) /* { dg-error "array notations cannot be used as a condition for while statement"  } */
     x = 2;
 
-  do { /* { dg-error "array notations cannot be used as a condition for a do-while statement" } */
+  do { /* { dg-error "array notations cannot be used as a condition for a do-while statement" "" { target c } } */
     x = 3;
-  } while (ii != array2[:][:]); 
+  } while (ii != array2[:][:]); /* { dg-error "array notations cannot be used as a condition for a do-while statement" "" { target c++ } } */
 
-  do {  /* { dg-error "array notations cannot be used as a condition for a do-while statement" } */
+  do {  /* { dg-error "array notations cannot be used as a condition for a do-while statement" "" { target c } } */
     x = 2;
-  } while (ii != (x + array2[:][1:x:2]) + 2);
+  } while (ii != (x + array2[:][1:x:2]) + 2); /* { dg-error "array notations cannot be used as a condition for a do-while statement" "" { target c++ } } */
   
   do { 
     x += 3;
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c
old mode 100644
new mode 100755
index a0a3742..18816e0
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c
@@ -8,4 +8,4 @@  int main (void)
   array2[:] = array2[: ;  /* { dg-error "expected ']'" } */
 
   return 0;
-} /* { dg-error "expected ';' before" } */
+} /* { dg-error "expected ';' before" "" { target c } } */
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c
index 2e86b4f..4314090 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c
@@ -5,7 +5,8 @@  int main (void)
 {
   int array[10][10], array2[10];
   
-  array2[:] = array2[1:2:] ;  /* { dg-error "expected expression before" } */
+  array2[:] = array2[1:2:] ;  /* { dg-error "expected expression before" "" { target c } } */ 
+  /* { dg-error  "expected primary-expression before" "" { target c++ } 8 } */
 
-  return 0; /* { dg-error "expected ';' before" } */
+  return 0; /* { dg-error "expected ';' before" "" { target c }  } */
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c
index 34dfa16..47b5979 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c
@@ -5,7 +5,8 @@  int main (void)
 {
   int array[10][10], array2[10];
   
-  array2[:] = array2[1::] ;  /* { dg-error "expected expression before" } */
+  array2[:] = array2[1: :] ;  /* { dg-error "expected expression before" "" { target c }  } */ 
+  /* { dg-error "expected primary-expression before" "" { target c++ }  8 } */
 
-  return 0; /* { dg-error "expected ';' before" } */
+  return 0; /* { dg-error "expected ';' before" "" { target c } } */
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c
index eba28a8..a0efc04 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c
@@ -5,7 +5,7 @@  int main (void)
 {
   int array[10][10], array2[10];
   
-  array2[:] = array2[::] ;  /* { dg-error " expected ']' before ':' token" } */
+  array2[:] = array2[ : : ] ;  /* { dg-error " expected ']' before ':' token" }  */
 
   return 0;
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c
index cabdb23..793afb2 100755
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c
@@ -4,11 +4,11 @@ 
 int A[10];
 
 int main () {
-  char c = (char)N; /* { dg-error "undeclared" } */
+  char c = (char)N; /* { dg-error "declared" } */
   short s = (short)N;
   long l = (long)N;
   A[l:s:c];
 }
 
-/* { dg-message "note: each" "defined" { target *-*-* }  7 } */
+/* { dg-message "note: each" "defined" { target c }  7 } */
 
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c
index 843745e..3b0777e 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c
@@ -1,5 +1,5 @@ 
-/* { dg-do compile } */
-/* { dg-options "-fcilkplus -std=c99" } */
+/* { dg-do compile { target c } } */
+/* { dg-options "-fcilkplus -std=c99 -w" } */
 
 int func (int x)
 {
diff --git a/gcc/testsuite/g++.dg/cilk-plus/AN/array_test1_tplt.cc b/gcc/testsuite/g++.dg/cilk-plus/AN/array_test1_tplt.cc
new file mode 100644
index 0000000..e9ee7ec
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/array_test1_tplt.cc
@@ -0,0 +1,118 @@ 
+/* { dg-do run } */
+/* { dg-options "-fcilkplus" } */
+
+#include <cstdlib>
+#include <string.h>
+#if HAVE_IO
+#include <cstdio>
+#endif
+template <class T> int main2 (char **argv);
+
+int main (void)
+{
+  int x = 1, y = 1, z = 1;
+  char *array[2];
+  array[0] = strdup ("a.out");
+  array[1] = strdup ("5");
+  x  = main2<unsigned char> (array);
+  x += main2<char> (array);
+  y  = main2<short> (array);
+  y += main2<unsigned short> (array);
+  y += main2<int> (array);
+  y += main2<unsigned int> (array);
+  z  = main2<long> (array);
+  z += main2<long long> (array);
+  y += main2<float> (array);
+  z += main2<double> (array);
+      
+  return x+y+z;
+}
+template <class T>
+int main2 (char **argv)
+{
+  T array[10];
+  int ii = 0, x = 2, z= 0 , y = 0;
+
+  for (ii = 0; ii < 10; ii++)
+    array[ii] = 10;
+
+  array[0:10:1] = (T)15;
+
+  for (ii = 0; ii < 10; ii++)
+    if (array[ii] != (T)15)
+      return 1;
+  
+
+  array[0:5:2] = (T)20;
+
+  for (ii = 0; ii < 10; ii += 2)
+    if (array[ii] != (T)20)
+      return 2;
+
+
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+
+  array[x:5:z] = (T)50;
+  
+  for (ii = x; ii < 10; ii += z)
+    if (array[ii] != (T)50)
+      return 3;
+
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]); /* (10 - 5) / 5 = 1 */
+  y = 10-atoi(argv[1]);
+  
+  array[x:y:z] = (T)52;
+#if HAVE_IO
+  for (ii = atoi ("5"); ii < (atoi ("5") + atoi ("5")); ii += atoi ("1"))
+    std::printf("%d\t", (int)array[ii]);
+  std::printf("\n");
+#endif
+  for (ii = x; ii < 10; ii += z)
+    if (array[ii] != (T)52)
+      return 4;
+    
+
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  y = 10-atoi(argv[1]);
+  
+  array[x:y:((10-atoi(argv[1]))/atoi(argv[1]))] = (T)25;
+
+  for (ii = x; ii < 10; ii += z)
+    if (array[ii] != (T)25)
+      return 5;
+  
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  y = 10-atoi(argv[1]);
+ 
+  array[atoi(argv[1]):(10-atoi(argv[1])):((10-atoi(argv[1]))/atoi(argv[1]))] =
+    (T)14;
+  for (ii = x; ii < 10; ii += z)
+    if (array[ii] != (T)14)
+      return 6;
+  
+
+  array[atoi("5"):5:1] = (T)65;
+  
+  for (ii = atoi ("5"); ii < 10; ii++)
+    if (array[ii] != (T)65)
+      return 7;
+  
+
+  array[atoi("5"):atoi("5"):atoi("1")] = 99;
+
+#if HAVE_IO
+  for (ii = atoi ("5"); ii < (atoi ("5") + atoi ("5")); ii += atoi ("1"))
+    std::printf("%d\t", (int)array[ii]);
+  std::printf("\n");
+#endif
+
+  for (ii = atoi ("5"); ii < (atoi ("5") + atoi ("5")); ii += atoi ("1"))
+    if (array[ii] != (T)99)
+      return 8;
+
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/AN/array_test2_tplt.cc b/gcc/testsuite/g++.dg/cilk-plus/AN/array_test2_tplt.cc
new file mode 100644
index 0000000..87c37e1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/array_test2_tplt.cc
@@ -0,0 +1,141 @@ 
+/* { dg-do run } */
+/* { dg-options "-fcilkplus" } */
+
+#include <cstdlib>
+#include <string.h>
+template <class T> int main2(char **argv);
+int main(void)
+{
+  int x = 1, y = 1, z = 1, w = 1; 
+  char *array[2]; 
+  array[0] = strdup ("a.out"); 
+  array[1] = strdup ("5");
+  w  = main2<short>(array);
+  w += main2<unsigned short> (array);
+  x  = main2<char> (array);
+  x += main2<unsigned char> (array);
+  y  = main2<int> (array);
+  y += main2<unsigned int> (array);
+  z = main2<long> (array);
+  z += main2<unsigned long> (array);
+  z += main2<long long> (array);
+      
+  return (w+x+y+z);
+}
+
+template<class T>
+int main2(char **argv)
+{
+  T array[10], array2[10]; 
+  int  ii = 0, x = 2, z= 0 , y = 0 ;
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 10;
+      array2[ii] = 5000000;
+    }
+
+  array2[0:10:1] = array[0:10:1];
+
+  for (ii = 0; ii < 10; ii++)
+    if (array2[ii] != array[ii])
+      return 1; 
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 10;
+      array2[ii] = 5000000;
+    }
+  
+  array2[0:5:2] = array[0:5:2];
+
+  for (ii = 0; ii < 10; ii += 2)
+    if (array[ii] != array2[ii])
+      return 2;
+  
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 10;
+      array2[ii] = 5000000;
+    }
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+ 
+  array2[x:5:z] = array[x:5:z];
+
+  for (ii = x; ii < 5; ii += z)
+    if (array2[ii] != array[ii])
+      return 3;
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii] = 500;
+      array2[ii] = 1000000;
+    }
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  y = 10-atoi(argv[1]);
+
+  array2[x:y:z] = array[x:y:z];
+  for (ii = x; ii < 10; ii = ii + z)
+    if (array2[ii] != array[ii])
+      return 4;
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii]  = 500;
+      array2[ii] = 1000000;
+    }
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  y = 10-atoi(argv[1]);
+
+  array[x:y:((10-atoi(argv[1]))/atoi(argv[1]))] = 
+    array2[x:y:((10-atoi(argv[1]))/atoi(argv[1]))];
+
+  for (ii = x; ii < 10; ii += z)
+    if (array[ii] != array2[ii])
+      return 6;
+  
+  
+  x = atoi(argv[1]);
+  z = (10-atoi(argv[1]))/atoi(argv[1]);
+  y = 10-atoi(argv[1]);
+  
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii]  = 500;
+      array2[ii] = 1000000;
+    }
+  
+  array[atoi(argv[1]):(10-atoi(argv[1])):((10-atoi(argv[1]))/atoi(argv[1]))] =
+    array2[atoi(argv[1]):(10-atoi(argv[1])):((10-atoi(argv[1]))/atoi(argv[1]))];
+  for (ii = x; ii < 10; ii += z)
+    if (array[ii] != array2[ii])
+      return 6;
+
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii]  = 4;
+      array2[ii] = 2;
+    }
+
+  array[atoi("5"):5:1] = array2[atoi("5"):5:1];
+
+  for (ii = atoi ("5"); ii < 10; ii++)
+    if (array[ii] != array2[ii])
+      return 7;
+  
+  for (ii = 0; ii < 10; ii++)
+    {
+      array[ii]  = 5;
+      array2[ii] = 1;
+    }
+  array[atoi("5"):atoi("5"):atoi("1")] = array2[atoi("5"):atoi("5"):atoi("1")];
+
+  for (ii = 5; ii < 10; ii++)
+    if (array2[ii] != array[ii])
+      return 8;
+ 
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/AN/array_test_ND_tplt.cc b/gcc/testsuite/g++.dg/cilk-plus/AN/array_test_ND_tplt.cc
new file mode 100644
index 0000000..479ba13
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/array_test_ND_tplt.cc
@@ -0,0 +1,115 @@ 
+/* { dg-do run } */
+/* { dg-options "-fcilkplus" } */
+
+#include <cstdlib>
+#include<string.h>
+template <class T> int main2(char **argv);
+
+int main(void)
+{
+  int x = 1, y=1, z=1, w = 1;
+  char *array[3];
+  array[0] = strdup ("a.out");
+  array[1] = strdup ("10");
+  array[2] = strdup ("15");
+  w  = main2<char> (array);
+  w += main2<unsigned char> (array);
+  x  = main2<int> (array);
+  x += main2<unsigned int> (array);
+  y  = main2<long> (array);
+  y += main2<unsigned long> (array);
+  z  = main2<short> (array);
+  z += main2<unsigned short> (array);
+  return x+y+z;
+}
+
+template <class T>
+int main2(char **argv)
+{  
+  T array[10][15];
+  T array_2[10][15];
+  int ii = 0, jj = 0,x = 0, z= 1 , y = 10 ,argc = 3;
+ 
+
+  for (ii = 0; ii < 10; ii++) {
+    for (jj = 0; jj< 15; jj++) {
+      array[ii][jj] = ii+jj;
+      array_2[ii][jj] = 0;
+    }
+  }
+  array_2[0:5:2][0:5:3] = array[0:5:2][0:5:3] + 1 + 5 + array[0][5] + x;
+
+  for (ii = 0; ii < 10; ii += 2)
+    {
+      for (jj = 0; jj < 15; jj += 3)
+	{
+	  if (array_2[ii][jj] != array[ii][jj] + 1 + 5 + array[0][5] + x)
+	    return 1;
+	}
+    }
+
+
+  for (ii = 0; ii < 10; ii++) {
+    for (jj = 0; jj< 15; jj++) {
+      array[ii][jj] = ii+jj;
+      array_2[ii][jj] = 0;
+    }
+  }
+  x = atoi(argv[1]);
+  y = atoi(argv[2]);
+  array_2[0:x:1][0:y:1] = array[0:x:1][0:y:1] + x + y + array[0:x:1][0:y:1];
+
+  for (ii = 0; ii < x; ii++)
+    {
+      for (jj = 0; jj < y; jj++)
+	{
+	  if (array_2[ii][jj] != array[ii][jj] + x + y + array[ii][jj])
+	    return 2;
+	}
+    }
+
+  for (ii = 0; ii < 10; ii++) {
+    for (jj = 0; jj< 15; jj++) {
+      array[ii][jj] = ii+jj;
+      array_2[ii][jj] = 0;
+    }
+  }
+  x = atoi(argv[1]);
+  y = atoi(argv[2]);
+  z = (20- atoi (argv[1]))/atoi(argv[1]);
+  /* (20-10)/10 evaluates to 1 all the time :-). */
+  array_2[0:x:z][0:y:z] = array[0:x:z][0:y:z] + array[0:x:z][0:y:z] + y + z;
+  
+  for (ii = 0; ii < x; ii += z)
+    {
+      for (jj = 0; jj < y; jj += z)
+	{
+	  if (array_2[ii][jj] != array[ii][jj] + array[ii][jj] + y + z)
+	    return 3;
+	}
+    }
+
+
+ 
+  for (ii = 0; ii < 10; ii++) {
+    for (jj = 0; jj< 15; jj++) {
+      array[ii][jj] = ii+jj;
+      array_2[ii][jj] = 0;
+    }
+  }
+  x = argc-3;
+  y = 20-atoi(argv[1]);
+  z = (20- atoi (argv[1]))/atoi(argv[1]);
+  /* (20-10)/10 evaluates to 1 all the time :-). */
+  array_2[(argc-3):(20-atoi(argv[1])):(20-atoi(argv[1]))/atoi(argv[1])][(argc-3):(30-atoi(argv[2])): ((30-atoi(argv[2]))/atoi(argv[2]))] = array[(argc-3):20-atoi(argv[1]):(20-atoi(argv[1]))/atoi(argv[1])][(argc-3):(30-atoi(argv[2])): (30-atoi(argv[2]))/atoi(argv[2])] + array[(argc-3):20-atoi(argv[1]):(20-atoi(argv[1]))/atoi(argv[1])][(argc-3):(30-atoi(argv[2])): (30-atoi(argv[2]))/atoi(argv[2])] * array[(argc-3):20-atoi(argv[1]):(20-atoi(argv[1]))/atoi(argv[1])][(argc-3):(30-atoi(argv[2])): (30-atoi(argv[2]))/atoi(argv[2])];
+  
+  for (ii = 0; ii < 10; ii++)
+    {
+      for (jj = 0; jj < 15; jj++)
+	{
+	  if (array_2[ii][jj] != array[ii][jj] + array[ii][jj] * array[ii][jj])
+	    return 4;
+	}
+    }
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/AN/braced_list.cc b/gcc/testsuite/g++.dg/cilk-plus/AN/braced_list.cc
new file mode 100755
index 0000000..b91de7a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/braced_list.cc
@@ -0,0 +1,13 @@ 
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus -std=c++11 " } */
+
+int main (void)
+{
+  int Array[100], Array2[100];
+
+  Array[{1,2}:2] = 5; /* { dg-error "braced list index is not allowed" } */
+  Array[1:{1,2}:2] = 5; /* { dg-error "expected primary-expression before" } */
+  Array[1:10:{1,2}] = 5; /* { dg-error "expected primary-expression before" } */
+
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_custom_tplt.cc b/gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_custom_tplt.cc
new file mode 100644
index 0000000..94ffe6e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_custom_tplt.cc
@@ -0,0 +1,126 @@ 
+/* { dg-do run } */
+/* { dg-options "-fcilkplus "} */
+
+#if HAVE_IO 
+#include <cstdio>
+#endif
+
+#include <cstdlib>
+
+template <class T>
+T my_func (T x, T y)
+{
+  if (x > y)
+    return x;
+  else
+    return y;
+}
+
+template <class T>
+T main_func (T  *array, T *array2, T identity_val, int size)
+{
+  T result;
+
+  result = __sec_reduce (identity_val, array[0:size:1] * array2[0:size:1],
+			 my_func); // my_func (identity_val, array[5] * array2[5]);
+  return result;
+}
+int main (void)
+{
+  int    i_index = 0, f_index = 0, d_index = 0, l_index = 0;
+  int    iarray[10], iarray2[10], i_result, i_max;
+  long   larray[10], larray2[10], l_result, l_max;
+  float  farray[10], farray2[10], f_result, f_max;
+  double darray[10], darray2[10], d_result, d_max;
+  for (int ii = 0; ii < 10; ii++)
+    {
+      if (ii%2 && ii)
+	{
+	  darray[ii] = (double)(1.0000/(double)ii);
+	  farray[ii] = (float)(1.00/(float)ii);
+	}
+      else
+	{
+	  darray[ii] = (double) ii + 0.10;
+	  farray[ii] = (float) (1.00/((float)(ii+1.000)));
+	}
+      darray2[ii] = (double) (1.00000/ (double)(ii+1));
+      farray2[ii] = (float) (1.00/ (float)(ii+1));
+    }
+
+  for (int ii = 0; ii < 10; ii++)
+    {
+      iarray[ii] = ii;
+      larray[ii] = (long)ii;
+    }
+
+  for (int ii = 0; ii < 10; ii++)
+    {
+      iarray2[ii] = (ii-5);
+      larray2[ii] = long (ii-5);
+    }
+#if HAVE_IO
+  printf("Int: ");
+  for (int ii=0; ii < 10; ii++)
+    {
+      printf("%2d ", iarray[ii] * iarray2[ii]);
+    }
+  printf("\nfloat: ");
+  for (int ii=0; ii < 10; ii++)
+    {
+      printf("%4.3f ", farray[ii] * farray2[ii]);
+    }
+
+  printf("\nlong: ");
+  for (int ii=0; ii < 10; ii++)
+    {
+      printf("%2d ", larray[ii] * larray2[ii]);
+    }
+
+  printf("\ndouble: ");
+  for (int ii=0; ii < 10; ii++)
+    {
+      printf("%4.3f ", (float) (darray[ii] * darray2[ii]));
+    }
+  printf("\n");
+#endif
+
+  i_result = main_func<int> (iarray, iarray2, iarray[0] * iarray2[0], 10);
+  f_result = main_func<float>(farray, farray2, 0.00, 10);
+  d_result = main_func<double>(darray, darray2, 0.0000, 10);
+  l_result = main_func<long>(larray, larray2, 0, 10);
+
+#if HAVE_IO
+  printf("int result    = %2d\n", i_result);
+  printf ("long result   = %2d\n", l_result);
+  printf("float result  = %4.3f\n", f_result);
+  printf("double result = %4.3lf\n", d_result);
+#endif
+    
+  i_max = iarray[0] * iarray2[0];
+  f_max = farray[0] * farray2[0];
+  d_max = darray[0] * darray2[0];
+  l_max = larray[0] * larray2[0];
+  for (int ii = 0; ii < 10; ii++)
+    {
+      if (i_max < iarray[ii] * iarray2[ii])
+	i_max = iarray[ii] * iarray2[ii];
+      if (f_max < farray[ii] * farray2[ii])
+	f_max = farray[ii] * farray2[ii];
+      if (d_max < darray[ii] * darray2[ii])
+	d_max = darray[ii] * darray2[ii];
+      if (l_max < larray[ii] * larray2[ii])
+	l_max = larray[ii] * larray2[ii];
+    }
+
+  if (i_max != i_result)
+    return 1;
+  if (f_max != f_result)
+    return 2;
+  if (d_max != d_result)
+    return 3;
+  if (l_max != l_result)
+    return 4;
+  return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_mutating_tplt.cc b/gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_mutating_tplt.cc
new file mode 100644
index 0000000..db81912
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_mutating_tplt.cc
@@ -0,0 +1,134 @@ 
+/* { dg-do run } */
+/* { dg-options "-fcilkplus" }  */
+
+#if HAVE_IO 
+#include <cstdio>
+#include<iostream>
+#endif
+
+#include <cstdlib>
+
+template <class T>
+T my_func (T *x, T y)
+{
+  if (*x < y)
+    *x = y;
+  else
+    *x = *x;
+}
+
+template <class T> T my_func (T *x, T y);
+template <class T>
+T main_func (T  *array, T *array2, T identity_val, int size)
+{
+  T result = identity_val;
+  
+  __sec_reduce_mutating (&result, array[0:size] * array2[0:size:1], my_func);
+  
+#if HAVE_IO
+  std::cout << "Result = " << result << std::endl;
+#endif
+  return result;
+}
+
+int main (void)
+{
+  int    iarray[10], iarray2[10], i_result = 0, i_max;
+  long   larray[10], larray2[10], l_result = 0, l_max;
+  float  farray[10], farray2[10], f_result = 0, f_max;
+  double darray[10], darray2[10], d_result = 0, d_max;
+  for (int ii = 0; ii < 10; ii++)
+    {
+      if (ii%2 && ii)
+	{
+	  darray[ii] = (double)(1.0000/(double)(ii));
+	  farray[ii] = (float)(1.00/(float)(ii));
+	}
+      else
+	{
+	  darray[ii] = (double) ii + 0.10;
+	  farray[ii] = (float) (1.00/((float)(ii) + 0.10));
+	}
+      darray2[ii] = (double) (1.00000/ (double)(ii+1));
+      farray2[ii] = (float) (1.00/ (float)(ii+1));
+    }
+
+  for (int ii = 0; ii < 10; ii++)
+    {
+      iarray[ii] = ii;
+      larray[ii] = (long)ii;
+    }
+
+  for (int ii = 0; ii < 10; ii++)
+    {
+      iarray2[ii] = (ii-5);
+      larray2[ii] = (long)ii-5;
+    }
+#if HAVE_IO
+  printf("\nInt: ");
+  for (int ii=0; ii < 10; ii++)
+    {
+      printf("%2d ", iarray[ii] * iarray2[ii]);
+    }
+  printf("\nfloat: ");
+  for (int ii=0; ii < 10; ii++)
+    {
+      printf("%3.2f ", farray[ii] * farray2[ii]);
+    }
+
+  printf("\nlong: ");
+  for (int ii=0; ii < 10; ii++)
+    {
+      printf("%2d ", larray[ii] * larray2[ii]);
+    }
+
+  printf("\ndouble: ");
+  for (int ii=0; ii < 10; ii++)
+    {
+      printf("%4.3lf ", (float) (darray[ii] * darray2[ii]));
+    }
+  printf("\n");
+#endif
+
+  i_result = main_func<int> (iarray, iarray2, 0, 10);
+  l_result = main_func<long>(larray, larray2, 0, 10);
+  f_result = main_func<float>(farray, farray2, 0.00, 10);
+  d_result = main_func<double>(darray, darray2, 0.0000, 10);
+  
+  i_max = iarray[0] * iarray2[0];
+  d_max = darray[0] * darray2[0];
+  f_max = farray[0] * farray2[0];
+  l_max = larray[0] * larray2[0];
+  for (int ii = 0; ii < 10; ii++)
+    {
+      if (iarray[ii] * iarray2[ii] > i_max)
+	i_max = iarray[ii] * iarray2[ii];
+      if (darray[ii] * darray2[ii] > d_max)
+	d_max = darray[ii] * darray2[ii];
+      if (farray[ii] * farray2[ii] > f_max)
+	f_max = farray[ii] * farray2[ii];
+      if (larray[ii] * larray2[ii] > l_max)
+	l_max = larray[ii] * larray2[ii];
+    }
+#if HAVE_IO
+  printf("int result    = %2d\n", i_max);
+  printf("long result   = %2d\n", l_max);
+  printf("float result  = %4.3f\n", f_max);
+  printf("double result = %4.3lf\n", (float)d_max);
+#endif
+  
+ if (i_max != i_result)
+   return 1;
+
+ if (f_max != f_result)
+   return 2;
+
+ if (l_max != l_result)
+   return 3;
+
+ if (d_max != d_result)
+   return 4;
+ 
+  return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/cilk-plus/AN/fp_triplet_values_tplt.c b/gcc/testsuite/g++.dg/cilk-plus/AN/fp_triplet_values_tplt.c
new file mode 100644
index 0000000..1387558
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/fp_triplet_values_tplt.c
@@ -0,0 +1,36 @@ 
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus" } */
+
+float q;
+
+void func (int *x)
+{
+  *x = 5;
+}
+template <class T> int main2 (T x, T y, T z);
+
+int main (void)
+{
+  main2 <float> (1.5, 2.3, 3.443);
+  main2 <double> (1.34393, 2.38383, 4.38383);
+  return 0;
+}
+template <class T> 
+int main2 (T x, T y, T z)
+{
+  int array[10], array2[10];
+  array2[:] = array[x:2]; /* { dg-error "start-index of array notation triplet is not an integer" } */
+  array2[:] = array[1:y]; /* { dg-error "length of array notation triplet is not an integer" } */
+  array2[1:2:z] = array[:]; /* { dg-error "stride of array notation triplet is not an integer" } */
+  func (&array2[1:x:3]); /* { dg-error "length of array notation triplet is not an integer" } */
+  array2[y:9]++; /* { dg-error "start-index of array notation triplet is not an integer" } */
+  array2[1:x]++; /* { dg-error "length of array notation triplet is not an integer" } */
+  array2[1:9:x]++; /* { dg-error "stride of array notation triplet is not an integer" } */
+  
+  ++array2[1:q:3]; /* { dg-error "length of array notation triplet is not an integer" } */
+  array2[:] = array[q:1:3]; /* { dg-error "start-index of array notation triplet is not an integer" } */
+  array2[:] = array[1:q:3]; /* { dg-error "length of array notation triplet is not an integer" } */
+  array2[:] = array[1:3:q]; /* { dg-error "stride of array notation triplet is not an integer" } */
+  func (&array2[1:q:3]); /* { dg-error "length of array notation triplet is not an integer" } */
+  return 0;
+} 
diff --git a/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp b/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp
new file mode 100644
index 0000000..a153529
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp
@@ -0,0 +1,48 @@ 
+#   Copyright (C) 2013 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+# Written by Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+
+load_lib g++-dg.exp
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O0 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O1 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O2 -ftree-vectorize -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O3 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -g -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -g -O0 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -g -O1 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -g -O2 -ftree-vectorize -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -g -O3 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O3 -ftree-vectorize -fcilkplus -g" " "
+dg-finish
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -O0 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -O1 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -O2 -ftree-vectorize -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -O3 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -g -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -g -O0 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -g -O1 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -g -O2 -ftree-vectorize -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -g -O3 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -O3 -ftree-vectorize -fcilkplus -g" " "
+dg-finish
diff --git a/gcc/testsuite/g++.dg/dg.exp b/gcc/testsuite/g++.dg/dg.exp
old mode 100644
new mode 100755
index 7201359..710218e
--- a/gcc/testsuite/g++.dg/dg.exp
+++ b/gcc/testsuite/g++.dg/dg.exp
@@ -33,6 +33,7 @@  dg-init
 set tests [lsort [find $srcdir/$subdir *.C]]
 set tests [prune $tests $srcdir/$subdir/bprob/*]
 set tests [prune $tests $srcdir/$subdir/charset/*]
+set tests [prune $tests $srcdir/$subdir/cilk-plus/AN/*]
 set tests [prune $tests $srcdir/$subdir/compat/*]
 set tests [prune $tests $srcdir/$subdir/debug/*]
 set tests [prune $tests $srcdir/$subdir/dfp/*]