diff mbox

Cilk Plus Array Notation for C++

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

Commit Message

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

Here are the ChangeLog entries:

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

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

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

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

Thanks,

Balaji V. Iyer.

Comments

Aldy Hernandez June 12, 2013, 4:34 p.m. UTC | #1
[Jason/Richard: there are some things below I could use your feedback on.]

Hi Balaji.

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

Otherwise, here are some minor nits...

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

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

> +/* This function parses Cilk Plus array notations.  The starting index is
> +   passed in INIT_INDEX and the array name is passed in ARRAY_VALUE.  The
> +   return value of this function is a tree node called VALUE_TREE of type
> +   ARRAY_NOTATION_REF.  If some error occurred it returns error_mark_node.  */
> +

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

> +    case ARRAY_NOTATION_REF:
> +      {
> +	tree start_index, length, stride;
> +	op1 = tsubst_non_call_postfix_expression (ARRAY_NOTATION_ARRAY (t),
> +						  args, complain, in_decl);
> +	start_index = RECUR (ARRAY_NOTATION_START (t));
> +	length = RECUR (ARRAY_NOTATION_LENGTH (t));
> +	stride = RECUR (ARRAY_NOTATION_STRIDE (t));
> +
> +	/* We do type-checking here for templatized array notation triplets.  */
> +	if (!TREE_TYPE (start_index)
> +	    || !INTEGRAL_TYPE_P (TREE_TYPE (start_index)))
> +	  {
> +	    error_at (loc, "start-index of array notation triplet is not an "
> +		      "integer");
> +	    RETURN (error_mark_node);
> +	  }
> +	if (!TREE_TYPE (length) || !INTEGRAL_TYPE_P (TREE_TYPE (length)))
> +	  {
> +	    error_at (loc, "length of array notation triplet is not an "
> +		      "integer");
> +	    RETURN (error_mark_node);
> +	  }
> +	if (!TREE_TYPE (stride) || !INTEGRAL_TYPE_P (TREE_TYPE (stride)))
> +	  {
> +	    error_at (loc, "stride of array notation triplet is not an "
> +		      "integer");
> +	    RETURN (error_mark_node);
> +	  }
> +	if (TREE_CODE (TREE_TYPE (op1)) == FUNCTION_TYPE)
> +	  {
> +	    error_at (loc, "array notations cannot be used with function type");
> +	    RETURN (error_mark_node);
> +	  }
> +	RETURN (build_array_notation_ref (EXPR_LOCATION (t), op1, start_index,
> +					  length, stride, TREE_TYPE (op1)));
> +      }


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

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

You are missing a ChangeLog entry for the above snippet.

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

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

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

Extra whitespace.

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

No corresponding test.

> +  /* If we are dealing with built-in array notation function then we don't need
> +     to convert them. They will be broken up into modify exprs in future,
> +     during which all these checks will be done.  */

Line too long, please wrap.

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

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

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

> +  int    iarray[10], iarray2[10], i_result, i_max;
> +  long   larray[10], larray2[10], l_result, l_max;
> +  float  farray[10], farray2[10], f_result, f_max;
> +  double darray[10], darray2[10], d_result, d_max;
> +#if 1
> +  for (int ii = 0; ii < 10; ii++)
> +    {
> +      if (ii%2 && ii)

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

> +	    if (flag_enable_cilkplus
> +		&& contains_array_notation_expr (condition))
> +	      {
> +		error_at (EXPR_LOCATION (condition),
> +			  "array notations cannot be used as a condition for "
> +			  "switch statement");

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

> +		  /* This could be a function ptr.  If so, then emit error.  */
> +		  subtype = TREE_TYPE (subtype);
> +		  if (subtype && TREE_CODE (subtype) == FUNCTION_TYPE)
> +		    {
> +		      error_at (loc, "array notations cannot be used with"
> +				" function pointer arrays");

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

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

No need to document the obvious.

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

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

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

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

s/a ARRAY/an ARRAY/

> +   This tree is broken down to ARRAY_REF toward the end of parsing.
> +   ARRAY_NOTATION_REF tree holds the START_INDEX, LENGTH, STRIDE and the TYPE
> +   of ARRAY_REF.  Restrictions on START_INDEX, LENGTH and STRIDE is same as that
> +   of the index field passed into ARRAY_REF.  The only additional restriction
> +   is that, unlike index in ARRAY_REF, stride, length and start_index cannot
> +   contain ARRAY_NOTATIONS.   */
> +
> +tree
> +build_array_notation_ref (location_t loc, tree array, tree start_index,
> +			  tree length, tree stride, tree type)

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

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

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

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


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

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

> +		  /* If we reach here, then the stride and start are of
> +		     different types, and so it doesn't really matter what
> +		     the induction variable type is, we stay safe and convert

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

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

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

> +/* Returns a loop with ARRAY_REF inside it with an appropriate modify expr.
> +   The LHS and/or RHS will be array notation expressions that have a
> +   MODIFYCODE.  The location of the variable is specified by LOCATION. */
> +
> +static tree
> +build_x_array_notation_expr (location_t location, tree lhs,
> +			     enum tree_code modifycode, tree rhs,
> +			     tsubst_flags_t complain)

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

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

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

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

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

s/of NODE/if NODE

Thanks.
Aldy
Iyer, Balaji V June 12, 2013, 5:20 p.m. UTC | #2
Hi Aldy,
	Below are my responses to a couple of the things you pointed out.

Thanks,

Balaji V. Iyer.

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

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

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

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

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

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

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

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

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

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

That I will put in.


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

They are temporary variables that are used to store information necessary for expansion. To me, dynamic arrays seem to be the most straight-forward way to do it. Changing them would involve pretty much rewriting the whole thing and thus maybe breaking the stability. So, if it is not a huge issue, I would like to keep the dynamic arrays. They are not being used anywhere else just inside the function.
Aldy Hernandez June 12, 2013, 5:40 p.m. UTC | #3
>> Overall, a lot of the stuff in cp-array-notation.c looks familiar
>> from the C front- end changes.  Can't you reuse a lot of it?
>
> I looked into trying to combine many functionality. The issue that
> prohibited me was templates and extra trees. For example, IF_STMT,
> FOR_STMT, MODOP_EXPR, etc are not available in C but are in C++. So,
> I had to add this additional check for those. Also, if we are
> processing templates we have to create different kind of trees (e.g
> MODOP_EXPR intead of MODIFY_EXPR).

I see.

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

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

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

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

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

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

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

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


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

Thanks,

Balaji V. Iyer.
diff mbox

Patch

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