diff mbox

Cilk Plus Array Notation for C++

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

Commit Message

Iyer, Balaji V June 24, 2013, 10:23 p.m. UTC
Hi Jason,
	Please see below for my responses to your questions. I am also attaching a fixed patch (diffed with trunk's head) and Changelog entries.

Thanks,

Balaji V. Iyer.

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

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

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

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

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

Fixed!

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

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

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

Yep, it is done that way.

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

Fixed!

> 
> > +/* This function parses Cilk Plus array notations.  The starting index is
> > +   passed in INIT_INDEX and the array name is passed in ARRAY_VALUE.  If the
> > +   INIT_INDEX is NULL, then we have special case were the entire
> > +array is
> 
> "where"

Fixed!

> 
> > +   accessed (e.g. A[:]).  The return value of this function is a tree node
> > +   called VALUE_TREE of type ARRAY_NOTATION_REF.  If some error
> > + occurred it
> 
> Drop "called VALUE_TREE"; the function comment shouldn't talk about local
> variables.

Fixed!

> 
> > +  cp_token *token = NULL;
> > +  tree start_index = NULL_TREE, length_index = NULL_TREE, stride =
> > + NULL_TREE;  tree value_tree, type, array_type, array_type_domain;
> > + double_int x;  bool saved_colon_corrects_to_scope_p =
> > + parser->colon_corrects_to_scope_p;
> 
> Now that the compiler is built as C++, variables should be defined at the point of
> first use, rather than at the top of the function.
> 

Fixed!

> > +         if (TREE_CODE (array_type) == RECORD_TYPE
> > +             || TREE_CODE (array_type) == POINTER_TYPE)
> > +           {
> > +             error_at (loc, "start-index and length fields necessary for "
> > +                       "using array notations in pointers or
> > + records");
> 
> I think this should handle all non-array types, rather than just pointers and
> classes.
> 
> Let's say "notation" rather than "notations" in all diagnostics.

I think I have fixed them all.

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

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

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

Fixed!

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

Fixed!

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

Fixed!

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

Fixed!
> 
> > +             /* Disable correcting single colon correcting to scope.  */
> > +             parser->colon_corrects_to_scope_p = false;
> > +             stride = cp_parser_expression (parser, false, NULL);
> > +             parser->colon_corrects_to_scope_p =
> > +               saved_colon_corrects_to_scope_p;
> 
> Why do you do this for the stride?  We've already seen both array-notation
> colons at this point.
> 
I removed it.

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

Fixed! We are already folding before transformation.

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

Fixed!

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

OK. 

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

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

> 
> > +  if (flag_enable_cilkplus && contains_array_notation_expr
> (compound_stmt))
> > +    compound_stmt = expand_array_notation_exprs (compound_stmt);
> ...
> > +  /* Transform all array notations to the equivalent array refs and
> > + loop.  */  if (flag_enable_cilkplus && contains_array_notation_expr (body))
> > +    body = expand_array_notation_exprs (body);
> ...
> > +  /* Expand all array notation expressions here.  */  if
> > + (flag_enable_cilkplus && current_function_decl
> > +      && contains_array_notation_expr (DECL_SAVED_TREE
> (current_function_decl)))
> > +    DECL_SAVED_TREE (current_function_decl) =
> > +      expand_array_notation_exprs (DECL_SAVED_TREE
> > + (current_function_decl));
> 
> Let's do the transformation in cp_genericize rather than in these places.
> 
> Perhaps moving the expansion to gimplification time would also help with
> sharing code between C and C++, since you don't have to worry about templates
> at that point.

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

> 
> > +           if (flag_enable_cilkplus
> > +               && contains_array_notation_expr (condition))
> > +             {
> > +               error_at (EXPR_LOCATION (condition),
> > +                         "array notations cannot be used as a condition for "
> > +                         "switch statement");
> > +               statement = error_mark_node;
> > +             }
> [etc]
> 
> I'd prefer to give diagnostics about uses that don't make sense at
> transformation time, rather than parsing time.

Fixed!

> 
> > +             if (flag_enable_cilkplus
> > +                 && cp_lexer_next_token_is (parser->lexer, CPP_COLON))
> > +               {
> > +                 bounds = error_mark_node;
> > +                 error_at (cp_lexer_peek_token (parser->lexer)->location,
> > +                           "array notations cannot be used in declaration");
> > +                 cp_lexer_consume_token (parser->lexer);
> > +               }
> 
> I'm concerned about this causing trouble with tentative parsing, and I think that
> people are unlikely to try to write a declaration using array notation, so let's
> leave out the changes to cp_parser_direct_declarator.

Ok. I have removed it.

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

Yep. This is fixed also.

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

Fixed as you suggested.

> 
> > +  if (flag_enable_cilkplus
> > +      && is_cilkplus_reduce_builtin (fndecl) != BUILT_IN_NONE)
> > +    nargs = (*params)->length ();
> > +  else
> > +    nargs = convert_arguments (parm_types, params, fndecl,
> LOOKUP_NORMAL,
> > +                              complain);
> 
> Another change that should be replaced by addition to magic_varargs_p, though
> it looks like convert_arguments needs to be updated to use magic_varargs_p
> rather than checking specifically for BUILT_IN_CONSTANT_P.

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

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

Is that OK with you?

> 
> > +  for (size_t ii = 0; ii < size; ii++)
> > +    for (size_t jj = 0; jj < rank; jj++)
> > +      {
> > +       (*node)[ii].safe_push (init);
> > +       array_exprs[ii].safe_push (NULL_TREE);
> > +      }
> 
> Why not use safe_grow_cleared for the sub-vecs as well?

Fixed!

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

Fixed!

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

Sorry, it was a mistake as well. The main point of that loop was to allow array refs intermingling with array notations.
 
> > +      if (TREE_CODE ((*list)[ii]) == ARRAY_NOTATION_REF)
> > +       for (size_t jj = 0; jj < rank; jj++)
> > +         if (TREE_CODE (array_exprs[ii][jj]) == ARRAY_NOTATION_REF)
> 
> How could the array_exprs element be anything other than an
> ARRAY_NOTATION_REF?  That's all you put in when you were building it.
> 

Fixed!

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

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

> > +    if (TREE_CODE ((*list)[ii]) == CALL_EXPR
> > +       && TREE_CODE (CALL_EXPR_FN ((*list)[ii])) == ADDR_EXPR
> > +       && is_sec_implicit_index_fn (CALL_EXPR_FN ((*list)[ii])))
> 
> Why check for ADDR_EXPR here?  Better for is_sec_implicit_index_fn to return
> false if its argument isn't what's desired.

Fixed!

> 
> > +       if (idx < (int) rank && idx >= 0)
> > +         vec_safe_push (array_operand, an_loop_info[idx].var);
> > +       else if (idx == -1)
> > +         /* In this case, the returning function would have emitted an
> > +            error thus it is not necessary to do so again.  */
> > +         return NULL;
> 
> Reorder these cases so you don't need to check idx >= 0.

Fixed!

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

Fixed! (Sorry for the stupid mistake).

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

Fixed!

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

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

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

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

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

Fixed! By the way, what is SFINAE?

> 
> > +           /* If stride and start are of same type and the induction var
> > +              is not, convert induction variable to stride's type.  */
> > +           if (TREE_TYPE (start) == TREE_TYPE (stride)
> > +               && TREE_TYPE (stride) != TREE_TYPE (var))
> 
> This seems impossible, since 'var' is created to have the same type as 'start'.

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

> 
> > +               /* If we reach here, then the stride and start are of
> > +                  different types, and so it doesn't really matter what
> > +                  the induction variable type is, convert everything to
> > +                  integer.  The reason why we pick an integer
> > +                  instead of something like size_t is because the stride
> > +                  and length can be + or -.  */
> 
> Maybe the induction variable should always be ptrdiff_type_node.

Yep. Fixed!

> 
> Jason

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

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

Fixed!

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

Fixed!

> 
> > +      /* We need to do this because we are "faking" the builtin function types,
> > +        so the compiler does a bunch of typecasts and this will get rid of
> > +        all that!  */
> 
> Again, magic_varargs_p can avoid any gratuitous type conversions.
> 

Please see my comment above about magic_varargs_p.

> > +    case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO:
> > +    case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO:
> > +    case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO:
> > +    case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO:
> > +      new_var_type = integer_type_node;
> 
> I would expect boolean_type_node.

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

Fixed!

> > +      an_loop_info[ii].ind_init = build_x_modify_expr
> > +       (location, an_loop_info[ii].var, NOP_EXPR,
> > +        build_zero_cst (TREE_TYPE (an_loop_info[ii].var)),
> > +        tf_warning_or_error);
> 
> Here and in other calls to build_x_modify_expr for initialization, use INIT_EXPR
> rather than NOP_EXPR.
> 
Fixed!

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

Removed and replaced it with create_temporary_var.

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

Fixed!

> > +  /* If both are scalar, then the only reason why we will get this far is if
> > +     there is some array notations inside it and was using a builtin array
> > +     notation functions.  If so, we have already broken those guys up and now
> > +     a simple build_x_modify_expr would do.  */  if (lhs_rank == 0 &&
> > + rhs_rank == 0)
> > +    {
> > +      if (found_builtin_fn)
> > +       {
> > +         new_modify_expr = build_x_modify_expr (location, lhs,
> > +                                                modifycode, rhs, complain);
> > +         finish_expr_stmt (new_modify_expr);
> > +         pop_stmt_list (an_init);
> > +         return an_init;
> > +       }
> > +      else
> > +       {
> > +         pop_stmt_list (an_init);
> > +         return NULL_TREE;
> > +       }
> > +    }
> 
> The comment makes it sound like the else should be gcc_unreachable.
> 

Yes, I added gcc_unreachable there.

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

Fixed!

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

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

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

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

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

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

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

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


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

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

Comments

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

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

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

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

Yes, that's OK.

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

Yes.

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

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

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

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

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

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

> Fixed! By the way, what is SFINAE?

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

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

This patch still has ChangeLog entries.

> +  new_var = get_temp_regvar (TREE_TYPE (retval_expr),
> +			     build_zero_cst (TREE_TYPE (retval_expr)));
>    new_mod = expand_an_in_modify_expr (loc, new_var, NOP_EXPR,
> +				      TREE_OPERAND (retval_expr, 1),
> +				      tf_warning_or_error);

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

> -	  parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
>  	  if (!length_index || length_index == error_mark_node)
>  	    cp_parser_skip_to_end_of_statement (parser);
>  	
> @@ -6180,7 +6158,6 @@ cp_parser_array_notation (location_t loc, cp_parser *parser, tree init_index,
>  	      saved_colon_corrects_to_scope_p =
>  		parser->colon_corrects_to_scope_p;
>  	      /* Disable correcting single colon correcting to scope.  */
> -	      parser->colon_corrects_to_scope_p = false;

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

>>> +           /* If stride and start are of same type and the induction var
>>> +              is not, convert induction variable to stride's type.  */
>>> +           if (TREE_TYPE (start) == TREE_TYPE (stride)
>>> +               && TREE_TYPE (stride) != TREE_TYPE (var))
>>
>> This seems impossible, since 'var' is created to have the same type as 'start'.
>
> As you suggested further in the email, I have made var of type ptrdiff_type, so I think I should keep this.

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

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

> +  if (lhs_list_size > 0 && rhs_list_size > 0 && lhs_rank > 0 && rhs_rank > 0
> +      && TREE_CODE (lhs_len) == INTEGER_CST && rhs_len
> +      && TREE_CODE (rhs_len) == INTEGER_CST)
> +    {
> +      HOST_WIDE_INT l_length = int_cst_value (lhs_len);
> +      HOST_WIDE_INT r_length = int_cst_value (rhs_len);
> +      if (absu_hwi (l_length) != absu_hwi (r_length))
> +       {
> +         error_at (location, "length mismatch between LHS and RHS");
> +         pop_stmt_list (an_init);
> +         return error_mark_node;
> +       }
> +    }

Another place that should use tree_int_cst_equal.

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

Too many "cannot"s.

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

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

> +  if (flag_enable_cilkplus && contains_array_notation_expr (expr))
> +    {
> +      size_t rank = 0;
> +
> +      if (!find_rank (input_location, expr, expr, false, &rank))
> +       return error_mark_node;
> +
> +      /* If the return expression contains array notations, then flag it as
> +        error.  */
> +      if (rank >= 1)
> +       {
> +         error_at (input_location, "array notation expression cannot be "
> +                   "used as a return value");
> +         return error_mark_node;
> +       }
> +    }
...
> +  /* If an array's index is an array notation, then its rank cannot be
> +     greater than one.  */
> +  if (flag_enable_cilkplus && contains_array_notation_expr (idx))
> +    {
> +      size_t rank = 0;
> +
> +      /* If find_rank returns false, then it should have reported an error,
> +        thus it is unnecessary for repetition.  */
> +      if (!find_rank (loc, idx, idx, true, &rank))
> +       return error_mark_node;
> +      if (rank > 1)
> +       {
> +         error_at (loc, "rank of the array%'s index is greater than 1");
> +         return error_mark_node;
> +       }
> +    }

More diagnostics that should move to expansion time.

> +  if (flag_enable_cilkplus && contains_array_notation_expr (op0))
> +    type0 = find_correct_array_notation_type (op0);
> +  else
> +    type0 = TREE_TYPE (op0);
...
> +  if (flag_enable_cilkplus && TREE_CODE (arg) == ARRAY_NOTATION_REF)
> +    {
> +      val = build_address (arg);
> +      if (TREE_CODE (arg) == OFFSET_REF)
> +       PTRMEM_OK_P (val) = PTRMEM_OK_P (arg);
> +      return val;
> +    }
...
> +  /* If we are dealing with built-in array notation function then we don't need
> +     to convert them.  They will be broken up into modify exprs in future,
> +     during which all these checks will be done.  */
> +  if (flag_enable_cilkplus
> +      && is_cilkplus_reduce_builtin (fndecl) != BUILT_IN_NONE)
> +    return rhs;

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

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

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


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

This change is implemented.

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

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

> > +  new_var = get_temp_regvar (TREE_TYPE (retval_expr),
> > +			     build_zero_cst (TREE_TYPE (retval_expr)));
> >    new_mod = expand_an_in_modify_expr (loc, new_var, NOP_EXPR,
> > +				      TREE_OPERAND (retval_expr, 1),
> > +				      tf_warning_or_error);
> 
> Why not pass TREE_OPERAND (retval_expr, 1) as the init to get_temp_regvar?
> 


new_var = TREE_OPERAND (retval_expr, 1)

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

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


> > -	  parser->colon_corrects_to_scope_p =
> saved_colon_corrects_to_scope_p;
> >  	  if (!length_index || length_index == error_mark_node)
> >  	    cp_parser_skip_to_end_of_statement (parser);
> >
> > @@ -6180,7 +6158,6 @@ cp_parser_array_notation (location_t loc,
> cp_parser *parser, tree init_index,
> >  	      saved_colon_corrects_to_scope_p =
> >  		parser->colon_corrects_to_scope_p;
> >  	      /* Disable correcting single colon correcting to scope.  */
> > -	      parser->colon_corrects_to_scope_p = false;
> 
> This change looks like now you will only restore
> parser->colon_corrects_to_scope_p if you have a stride.  I would suggest
> putting back the first restore, and removing all the corrects_to_scope_p code
> from the stride block, since there can't be an array-notation colon after the
> stride.

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

> 
> >>> +           /* If stride and start are of same type and the induction var
> >>> +              is not, convert induction variable to stride's type.  */
> >>> +           if (TREE_TYPE (start) == TREE_TYPE (stride)
> >>> +               && TREE_TYPE (stride) != TREE_TYPE (var))
> >>
> >> This seems impossible, since 'var' is created to have the same type as 'start'.
> >
> > As you suggested further in the email, I have made var of type ptrdiff_type, so
> I think I should keep this.
> 
> I think it would be better to convert start/stride to ptrdiff_t.
> 

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

> Incidentally, types should be compared with same_type_p rather than ==.
> 
> > +  if (lhs_list_size > 0 && rhs_list_size > 0 && lhs_rank > 0 && rhs_rank > 0
> > +      && TREE_CODE (lhs_len) == INTEGER_CST && rhs_len
> > +      && TREE_CODE (rhs_len) == INTEGER_CST)
> > +    {
> > +      HOST_WIDE_INT l_length = int_cst_value (lhs_len);
> > +      HOST_WIDE_INT r_length = int_cst_value (rhs_len);
> > +      if (absu_hwi (l_length) != absu_hwi (r_length))
> > +       {
> > +         error_at (location, "length mismatch between LHS and RHS");
> > +         pop_stmt_list (an_init);
> > +         return error_mark_node;
> > +       }
> > +    }
> 
> Another place that should use tree_int_cst_equal.
> 

Fixed!

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

> > +  if (processing_template_decl)
> > +    {
> > +      array_type = TREE_TYPE (array_value);
> > +      type = TREE_TYPE (array_type);
> > +    }
> 
> We should be able to parse array notation in a template even when the array
> expression has unknown type.  In a template, just parse and remember the raw
> expressions without worrying about diagnostics and conversions.
> 
> > +  if (flag_enable_cilkplus && contains_array_notation_expr (expr))
> > +    {
> > +      size_t rank = 0;
> > +
> > +      if (!find_rank (input_location, expr, expr, false, &rank))
> > +       return error_mark_node;
> > +
> > +      /* If the return expression contains array notations, then flag it as
> > +        error.  */
> > +      if (rank >= 1)
> > +       {
> > +         error_at (input_location, "array notation expression cannot be "
> > +                   "used as a return value");
> > +         return error_mark_node;
> > +       }
> > +    }
> ...

Fixed!

> > +  /* If an array's index is an array notation, then its rank cannot be
> > +     greater than one.  */
> > +  if (flag_enable_cilkplus && contains_array_notation_expr (idx))
> > +    {
> > +      size_t rank = 0;
> > +
> > +      /* If find_rank returns false, then it should have reported an error,
> > +        thus it is unnecessary for repetition.  */
> > +      if (!find_rank (loc, idx, idx, true, &rank))
> > +       return error_mark_node;
> > +      if (rank > 1)
> > +       {
> > +         error_at (loc, "rank of the array%'s index is greater than 1");
> > +         return error_mark_node;
> > +       }
> > +    }

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

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


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

Fixed!

> > +  if (flag_enable_cilkplus && TREE_CODE (arg) == ARRAY_NOTATION_REF)
> > +    {
> > +      val = build_address (arg);
> > +      if (TREE_CODE (arg) == OFFSET_REF)
> > +       PTRMEM_OK_P (val) = PTRMEM_OK_P (arg);
> > +      return val;
> > +    }

Fixed!

> ...
> > +  /* If we are dealing with built-in array notation function then we don't need
> > +     to convert them.  They will be broken up into modify exprs in future,
> > +     during which all these checks will be done.  */  if
> > + (flag_enable_cilkplus
> > +      && is_cilkplus_reduce_builtin (fndecl) != BUILT_IN_NONE)
> > +    return rhs;
> 
> More changes that should be unnecessary since ARRAY_NOTATION_REF has a
> normal type.
> 

Fixed!

> What remaining obstacles are there to sharing most of the expansion code
> between C and C++?  That can be a separate patch, of course.
> 
> Jason
Jason Merrill June 25, 2013, 8:55 p.m. UTC | #3
On 06/25/2013 02:27 PM, Iyer, Balaji V wrote:
> This time, I ran the command you gave me. Please tell me how it looks.

No ChangeLog this time, thanks.

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

OK.

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

OK.

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

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

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

It doesn't look like you addressed this comment.

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

Or this one.

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

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

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

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

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

Any thoughts?

Jason
diff mbox

Patch

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 8f45983..d81f7ce 100644
Binary files a/gcc/ChangeLog and b/gcc/ChangeLog differ
diff --git a/gcc/builtins.def b/gcc/builtins.def
index 91879a6..9b55b1f 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -158,9 +158,9 @@  along with GCC; see the file COPYING3.  If not see
 	       (flag_asan || flag_tsan))
 
 #undef DEF_CILKPLUS_BUILTIN
-#define DEF_CILKPLUS_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
-  DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
-  	       false, false, true, ATTRS, false, flag_enable_cilkplus)
+#define DEF_CILKPLUS_BUILTIN(ENUM, NAME, TYPE, ATTRS)  \
+  DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, BT_FN_INT_VAR, BT_LAST, \
+  	       false, false, false, ATTRS, false, flag_enable_cilkplus) 
 
 /* Define an attribute list for math functions that are normally
    "impure" because some of them may write into global memory for
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 03269e9..53f35d4 100644
Binary files a/gcc/c-family/ChangeLog and b/gcc/c-family/ChangeLog differ
diff --git a/gcc/c-family/array-notation-common.c b/gcc/c-family/array-notation-common.c
index 0e2a431..ae96941 100644
--- a/gcc/c-family/array-notation-common.c
+++ b/gcc/c-family/array-notation-common.c
@@ -86,7 +86,6 @@  length_mismatch_in_expr_p (location_t loc, tree **list, size_t x, size_t y)
 {
   size_t ii, jj;
   tree start = NULL_TREE;
-  HOST_WIDE_INT l_start, l_node;
   for (jj = 0; jj < y; jj++)
     {
       start = NULL_TREE;
@@ -99,15 +98,11 @@  length_mismatch_in_expr_p (location_t loc, tree **list, size_t x, size_t y)
 	      /* If start is a INTEGER, and list[ii][jj] is an integer then
 		 check if they are equal.  If they are not equal then return
 		 true.  */
-	      if (TREE_CODE (list[ii][jj]) == INTEGER_CST)
-		{
-		  l_node = int_cst_value (list[ii][jj]);
-		  l_start = int_cst_value (start);
-		  if (absu_hwi (l_start) != absu_hwi (l_node))
-		    {
-		      error_at (loc, "length mismatch in expression");
-		      return true;
-		    }
+	      if (TREE_CODE (list[ii][jj]) == INTEGER_CST
+		  && !tree_int_cst_equal (list[ii][jj], start))
+		{ 
+		  error_at (loc, "length mismatch in expression"); 
+		  return true;
 		}
 	    }
 	  else
@@ -269,6 +264,8 @@  find_rank (location_t loc, tree orig_expr, tree expr, bool ignore_builtin_fn,
 		/* If it is a built-in function, then we know it returns a 
 		   scalar.  */
 		return true;
+	  if (!find_rank (loc, orig_expr, func_name, ignore_builtin_fn, rank))
+	    return false;
 	  FOR_EACH_CALL_EXPR_ARG (arg, iter, expr)
 	    {
 	      if (!find_rank (loc, orig_expr, arg, ignore_builtin_fn, rank))
@@ -356,6 +353,9 @@  extract_array_notation_exprs (tree node, bool ignore_builtin_fn,
 	  vec_safe_push (*array_list, node);
 	  return;
 	}
+      /* This will extract array notations in function pointers.  */
+      extract_array_notation_exprs (CALL_EXPR_FN (node), ignore_builtin_fn,
+				    array_list);
       FOR_EACH_CALL_EXPR_ARG (arg, iter, node)
 	extract_array_notation_exprs (arg, ignore_builtin_fn, array_list);
     } 
@@ -431,6 +431,9 @@  replace_array_notations (tree *orig, bool ignore_builtin_fn,
 	      }
 	  return;
 	}
+      /* Fixes array notations in array notations in function pointers.  */
+      replace_array_notations (&CALL_EXPR_FN (*orig), ignore_builtin_fn, list,
+			       array_operand);
       ii = 0;
       FOR_EACH_CALL_EXPR_ARG (arg, iter, *orig)
 	{
@@ -573,53 +576,49 @@  cilkplus_extract_an_triplets (vec<tree, va_gc> *list, size_t size, size_t rank,
 			      vec<vec<struct cilkplus_an_parts> > *node)
 {
   vec<vec<tree> > array_exprs = vNULL;
-  struct cilkplus_an_parts init = { NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE,
-				    false };
+
   node->safe_grow_cleared (size);
   array_exprs.safe_grow_cleared (size);
-  for (size_t ii = 0; ii < size; ii++)
-    for (size_t jj = 0; jj < rank; jj++)
+
+  if (rank > 0)
+    for (size_t ii = 0; ii < size; ii++)
       {
-	(*node)[ii].safe_push (init);
-	array_exprs[ii].safe_push (NULL_TREE);
+	(*node)[ii].safe_grow_cleared (rank);
+	array_exprs[ii].safe_grow_cleared (rank);
       }
-
   for (size_t ii = 0; ii < size; ii++)
     {
       size_t jj = 0;
       tree ii_tree = (*list)[ii];
       while (ii_tree)
-	if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
-	  {
-	    array_exprs[ii][jj] = ii_tree;
-	    jj++;
-	    ii_tree = ARRAY_NOTATION_ARRAY (ii_tree);
-	  }
-	else if (TREE_CODE (ii_tree) == ARRAY_REF)
-	  ii_tree = TREE_OPERAND (ii_tree, 0);
-	else if (TREE_CODE (ii_tree) == VAR_DECL
-		 || TREE_CODE (ii_tree) == CALL_EXPR
-		 || TREE_CODE (ii_tree) == PARM_DECL)
-	  break;
-	else
-	  gcc_unreachable ();	
+	{
+	  if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
+	    {
+	      array_exprs[ii][jj] = ii_tree;
+	      jj++;
+	      ii_tree = ARRAY_NOTATION_ARRAY (ii_tree);
+	    }
+	  else if (TREE_CODE (ii_tree) == ARRAY_REF)
+	    ii_tree = TREE_OPERAND (ii_tree, 0);
+	  else
+	    break;
+	}
     }
     for (size_t ii = 0; ii < size; ii++)
       if (TREE_CODE ((*list)[ii]) == ARRAY_NOTATION_REF)
 	for (size_t jj = 0; jj < rank; jj++)
-	  if (TREE_CODE (array_exprs[ii][jj]) == ARRAY_NOTATION_REF)
-	    {
-	      tree ii_tree = array_exprs[ii][jj];
-	      (*node)[ii][jj].is_vector = true;
-	      (*node)[ii][jj].value = ARRAY_NOTATION_ARRAY (ii_tree);
-	      (*node)[ii][jj].start = ARRAY_NOTATION_START (ii_tree);
-	      (*node)[ii][jj].length =
-		fold_build1 (CONVERT_EXPR, integer_type_node,
-			     ARRAY_NOTATION_LENGTH (ii_tree));
-	      (*node)[ii][jj].stride =
-		fold_build1 (CONVERT_EXPR, integer_type_node,
-			     ARRAY_NOTATION_STRIDE (ii_tree));
-	    }
+	  {
+	    tree ii_tree = array_exprs[ii][jj];
+	    (*node)[ii][jj].is_vector = true;
+	    (*node)[ii][jj].value = ARRAY_NOTATION_ARRAY (ii_tree);
+	    (*node)[ii][jj].start = ARRAY_NOTATION_START (ii_tree);
+	    (*node)[ii][jj].length =
+	      fold_build1 (CONVERT_EXPR, integer_type_node,
+			   ARRAY_NOTATION_LENGTH (ii_tree));
+	    (*node)[ii][jj].stride =
+	      fold_build1 (CONVERT_EXPR, integer_type_node,
+			   ARRAY_NOTATION_STRIDE (ii_tree));
+	  }
 }
 
 /* Replaces all the __sec_implicit_arg functions in LIST with the induction
@@ -635,16 +634,15 @@  fix_sec_implicit_args (location_t loc, vec <tree, va_gc> *list,
   vec <tree, va_gc> *array_operand = NULL;
   for (size_t ii = 0; ii < vec_safe_length (list); ii++)
     if (TREE_CODE ((*list)[ii]) == CALL_EXPR
-	&& TREE_CODE (CALL_EXPR_FN ((*list)[ii])) == ADDR_EXPR
 	&& is_sec_implicit_index_fn (CALL_EXPR_FN ((*list)[ii])))
       {
 	int idx = extract_sec_implicit_index_arg (loc, (*list)[ii]);
-	if (idx < (int) rank && idx >= 0)
-	  vec_safe_push (array_operand, an_loop_info[idx].var);
-	else if (idx == -1)
+	if (idx < 0)
 	  /* In this case, the returning function would have emitted an
 	     error thus it is not necessary to do so again.  */
 	  return NULL;
+	else if (idx < (int) rank)
+	  vec_safe_push (array_operand, an_loop_info[idx].var);
 	else
 	  {
 	    error_at (loc, "__sec_implicit_index argument %d must be "
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 05766ca..53bfe88 100644
Binary files a/gcc/c/ChangeLog and b/gcc/c/ChangeLog differ
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index d6a500e..c7846ce 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -11053,24 +11053,6 @@  c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
 	      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
 	      return error_mark_node;
 	    }
-	  if (TREE_CODE (array_type) == ARRAY_TYPE)
-	    {
-	      tree subtype = TREE_TYPE (array_type);
-	      while (subtype && TREE_CODE (subtype) == POINTER_TYPE)
-		{
-		  /* Now this could be a function pointer.  Find them and
-		     give out an error.  */
-		  subtype = TREE_TYPE (subtype);
-		  if (subtype && TREE_CODE (subtype) == FUNCTION_TYPE)
-		    {
-		      error_at (loc, "array notations cannot be used with "
-				"function pointer arrays");
-		      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
-						 NULL);
-		      return error_mark_node;
-		    }
-		}
-	    }
 	  array_type_domain = TYPE_DOMAIN (array_type);
 
 	  if (!array_type_domain)
@@ -11114,27 +11096,6 @@  c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
 	      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
 	      return error_mark_node;
 	    }
-	  if (TREE_CODE (array_type) == ARRAY_TYPE
-	      || TREE_CODE (array_type) == POINTER_TYPE)
-	    {
-	      tree subtype = TREE_TYPE (array_type);
-	      while (subtype
-		     && (TREE_CODE (subtype) == POINTER_TYPE
-			 || TREE_CODE (subtype) == ARRAY_TYPE))
-		{
-		  /* Now this could be a function pointer.  Find them and
-		     give out an error.  */
-		  subtype = TREE_TYPE (subtype);
-		  if (subtype && TREE_CODE (subtype) == FUNCTION_TYPE)
-		    {
-		      error_at (loc, "array notations cannot be used with "
-				"function pointer arrays");
-		      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
-						 NULL);
-		      return error_mark_node;
-		    }
-		}
-	    }
 	  c_parser_consume_token (parser); /* consume the ':' */
 	  end_index = c_parser_expression (parser).value;
 	  if (!end_index || end_index == error_mark_node)
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 55ed6a5..9d570b2 100644
Binary files a/gcc/cp/ChangeLog and b/gcc/cp/ChangeLog differ
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 6817bfc..0350da8 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -5857,16 +5857,9 @@  convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
 	  else if (t->kind == ck_identity)
 	    break;
 	}
-
-      if (flag_enable_cilkplus
-	  && (contains_array_notation_expr (expr)
-	      || contains_array_notation_expr (fn)))
-	/* If we are using array notations, we fix them up at a later stage
-	   and we will do these checks then.  */
-	;
-      else if (permerror (loc, "invalid conversion from %qT to %qT",
-			  TREE_TYPE (expr), totype)
-	       && fn)
+       if (permerror (loc, "invalid conversion from %qT to %qT",
+                    TREE_TYPE (expr), totype)
+	   && fn)
 	inform (DECL_SOURCE_LOCATION (fn),
 		"initializing argument %P of %qD", argnum, fn);
 
@@ -6518,6 +6511,9 @@  convert_for_arg_passing (tree type, tree val, tsubst_flags_t complain)
 static bool
 magic_varargs_p (tree fn)
 {
+  if (flag_enable_cilkplus && is_cilkplus_reduce_builtin (fn) != BUILT_IN_NONE)
+    return true;
+
   if (DECL_BUILT_IN (fn))
     switch (DECL_FUNCTION_CODE (fn))
       {
@@ -6895,21 +6891,13 @@  build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
 		       "  (you can disable this with -fno-deduce-init-list)");
 	    }
 	}
+      val = convert_like_with_context (conv, arg, fn, i - is_method,
+				       conversion_warning
+				       ? complain
+				       : complain & (~tf_warning));
 
-      /* If the function call is builtin array notation function then no need
-	 to do any type conversion.  */
-      if (flag_enable_cilkplus
-	  && is_cilkplus_reduce_builtin (fn) != BUILT_IN_NONE)
-	val = arg;
-      else
-	{
-	  val = convert_like_with_context (conv, arg, fn, i - is_method,
-					   conversion_warning
-					   ? complain
-					   : complain & (~tf_warning));
-
-	  val = convert_for_arg_passing (type, val, complain);
-	}
+      val = convert_for_arg_passing (type, val, complain);
+	
       if (val == error_mark_node)
         return error_mark_node;
       else
diff --git a/gcc/cp/cp-array-notation.c b/gcc/cp/cp-array-notation.c
index 92272b3..1209cb3 100644
--- a/gcc/cp/cp-array-notation.c
+++ b/gcc/cp/cp-array-notation.c
@@ -59,7 +59,6 @@ 
 #include "diagnostic.h"
 #include "tree-iterator.h"
 #include "vec.h"
-#include "gimple.h"
 
 /* Creates a FOR_STMT with INIT, COND, INCR and BODY as the initializer,
    condition, increment expression and the loop-body, respectively.  */
@@ -79,7 +78,7 @@  create_an_loop (tree init, tree cond, tree incr, tree body)
 }
 
 /* Returns true if there is a length mismatch among exprssions that are at the
-   same dimension and one the same side of the equal sign.  The Array notation
+   same dimension and on the same side of the equal sign.  The Array notation
    lengths (LIST->LENGTH) is passed in as a 2D vector of trees.  */
 
 static bool
@@ -87,14 +86,13 @@  cp_length_mismatch_in_expr_p (location_t loc, vec<vec<an_parts> >list)
 {
   size_t ii, jj;
   tree length = NULL_TREE;
-  HOST_WIDE_INT l_length, l_node;
   
   size_t x = list.length ();
-  size_t y = list[0].length ();
-  
+  size_t y = list[0].length (); 
+ 
   for (jj = 0; jj < y; jj++)
     {
-      length = NULL_TREE;
+      length = NULL_TREE; 
       for (ii = 0; ii < x; ii++)
 	{
 	  if (!length)
@@ -104,20 +102,16 @@  cp_length_mismatch_in_expr_p (location_t loc, vec<vec<an_parts> >list)
 	      /* If length is a INTEGER, and list[ii][jj] is an integer then
 		 check if they are equal.  If they are not equal then return
 		 true.  */
-	      if (TREE_CODE (list[ii][jj].length) == INTEGER_CST)
-		{
-		  l_node = int_cst_value (list[ii][jj].length);
-		  l_length = int_cst_value (length);
-		  if (absu_hwi (l_length) != absu_hwi (l_node))
-		    {
-		      error_at (loc, "length mismatch in expression");
-		      return true;
-		    }
+	      if (TREE_CODE (list[ii][jj].length) == INTEGER_CST
+		  && !tree_int_cst_equal (list[ii][jj].length, length))
+		{ 
+		  error_at (loc, "length mismatch in expression"); 
+		  return true;
 		}
 	    }
 	  else
-	    /* We set the length node as the current node just in case it turns
-	       out to be an integer.  */
+	    /* We set the list[ii][jj].length as the current node just in case 
+	       it turns out to be an integer.  */
 	    length = list[ii][jj].length;
 	}
     }
@@ -128,17 +122,12 @@  cp_length_mismatch_in_expr_p (location_t loc, vec<vec<an_parts> >list)
    a variable to make it loop invariant for array notations.  */
 
 static inline void
-make_triplet_val_inv (location_t loc, tree *value, tsubst_flags_t cry)
+make_triplet_val_inv (tree *value)
 {
-  tree var;
   if (TREE_CODE (*value) != INTEGER_CST
       && TREE_CODE (*value) != PARM_DECL
       && TREE_CODE (*value) != VAR_DECL)
-    {
-      var = build_decl (loc, VAR_DECL, NULL_TREE, integer_type_node);
-      finish_expr_stmt (build_x_modify_expr (loc, var, NOP_EXPR, *value, cry));
-      *value = var;
-    }
+    *value = get_temp_regvar (integer_type_node, *value);
 }
 
 /* Returns a vector of size RANK that contains an ARRAY_REF.  This vector is
@@ -238,7 +227,7 @@  replace_invariant_exprs (tree *node)
 {
   size_t ix = 0;
   tree node_list = NULL_TREE;
-  tree t = NULL_TREE, new_var = NULL_TREE, new_node; 
+  tree t = NULL_TREE, new_var = NULL_TREE;
   struct inv_list data;
 
   data.list_values = NULL;
@@ -250,17 +239,8 @@  replace_invariant_exprs (tree *node)
     {
       node_list = push_stmt_list ();
       for (ix = 0; vec_safe_iterate (data.list_values, ix, &t); ix++)
-	{
-	  if (processing_template_decl || !TREE_TYPE (t))
-	    new_var = build_min_nt_loc (EXPR_LOCATION (t), VAR_DECL, NULL_TREE,
-				       	NULL_TREE);
-	  else
-	    new_var = build_decl (EXPR_LOCATION (t), VAR_DECL, NULL_TREE,
-				  TREE_TYPE (t));
-	  gcc_assert (new_var != NULL_TREE && new_var != error_mark_node);
-	  new_node = build_x_modify_expr (EXPR_LOCATION (t), new_var, NOP_EXPR,
-					  t, tf_warning_or_error);
-	  finish_expr_stmt (new_node);
+	{ 
+	  new_var = get_temp_regvar (TREE_TYPE (t), t); 
 	  vec_safe_push (data.replacement, new_var);
 	}
       cp_walk_tree (node, replace_inv_trees, (void *) &data, NULL);
@@ -281,7 +261,6 @@  expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
   tree new_var_type = NULL_TREE, func_parm, new_yes_expr, new_no_expr;
   tree array_ind_value = NULL_TREE, new_no_ind, new_yes_ind, new_no_list;
   tree new_yes_list, new_cond_expr, new_expr = NULL_TREE; 
-  tree new_var_init = NULL_TREE, new_exp_init = NULL_TREE;
   vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
   size_t list_size = 0, rank = 0, ii = 0;
   tree  body, an_init, loop_with_init = alloc_stmt_list ();
@@ -351,7 +330,7 @@  expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
     case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO:
     case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO:
     case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO:
-      new_var_type = integer_type_node;
+      new_var_type = boolean_type_node;
       break;
     case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
     case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
@@ -380,24 +359,30 @@  expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
     if (TREE_CODE ((*array_list)[ii]) == ARRAY_NOTATION_REF)
       {
 	tree anode = (*array_list)[ii];
-	make_triplet_val_inv (location, &ARRAY_NOTATION_START (anode),
-			      tf_warning_or_error);
-	make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (anode),
-			      tf_warning_or_error);
-	make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (anode),
-			      tf_warning_or_error);
+	make_triplet_val_inv (&ARRAY_NOTATION_START (anode));
+	make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (anode));
+	make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (anode));
       }
   cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info);
   for (ii = 0; ii < rank; ii++)
     {
-      an_loop_info[ii].var = build_decl (location, VAR_DECL, NULL_TREE,
-				  TREE_TYPE (an_info[0][ii].start));
-      an_loop_info[ii].ind_init = build_x_modify_expr
-	(location, an_loop_info[ii].var, NOP_EXPR, 
-	 build_zero_cst (TREE_TYPE (an_loop_info[ii].var)),
-	 tf_warning_or_error);
+      tree typ = ptrdiff_type_node;
+
+      /* In this place, we are using get_temp_regvar instead of 
+	 create_temporary_var if an_type is SEC_REDUCE_MAX/MIN_IND because
+	 the array_ind_value depends on this value being initalized to 0.  */
+      if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
+	  || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND) 
+	an_loop_info[ii].var = get_temp_regvar (typ, build_zero_cst (typ));
+      else
+	{
+	  an_loop_info[ii].var = create_temporary_var (typ);
+	  add_decl_expr (an_loop_info[ii].var);
+	}
+      an_loop_info[ii].ind_init = 
+	build_x_modify_expr (location, an_loop_info[ii].var, INIT_EXPR,
+			     build_zero_cst (typ), tf_warning_or_error);
     }
-  
   array_operand = create_array_refs (location, an_info, an_loop_info,
 				      list_size, rank);
   replace_array_notations (&func_parm, true, array_list, array_operand);
@@ -406,26 +391,9 @@  expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
     TREE_TYPE (func_parm) = TREE_TYPE ((*array_list)[0]);
   
   create_cmp_incr (location, &an_loop_info, rank, an_info, tf_warning_or_error);
-  if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
-    {
-      if (processing_template_decl)
-	*new_var = build_decl (location, VAR_DECL, NULL_TREE, new_var_type);
-      else
-	*new_var = create_tmp_var (new_var_type, NULL);
-    }
-  else
-    /* We do not require a new variable for mutating.  The "identity value"
-       itself is the variable.  */
-    *new_var = NULL_TREE;
-  
   if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
-      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND)
-    {
-      array_ind_value = create_tmp_var (TREE_TYPE (func_parm), NULL);
-      gcc_assert (array_ind_value && (array_ind_value != error_mark_node));
-      DECL_INITIAL (array_ind_value) = NULL_TREE;
-      pushdecl (array_ind_value);
-    }
+      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND) 
+    array_ind_value = get_temp_regvar (TREE_TYPE (func_parm), func_parm);
 
   array_op0 = (*array_operand)[0];
   switch (an_type)
@@ -440,35 +408,36 @@  expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
       break;
     case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO:
     case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO:
-      code = (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO) ? EQ_EXPR
-	: NE_EXPR;
+      code = ((an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO) ? EQ_EXPR
+	: NE_EXPR);
       init = build_zero_cst (new_var_type);
       cond_init = build_one_cst (new_var_type);
       comp_node = build_zero_cst (TREE_TYPE (func_parm));
       break;
     case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO:
     case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO:
-      code = (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO) ? NE_EXPR
-	: EQ_EXPR;
+      code = ((an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO) ? NE_EXPR
+	: EQ_EXPR);
       init = build_one_cst (new_var_type);
       cond_init = build_zero_cst (new_var_type);
       comp_node = build_zero_cst (TREE_TYPE (func_parm));
       break;
     case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX:
       code = MAX_EXPR;
-      init = TYPE_MIN_VALUE (new_var_type) ? TYPE_MIN_VALUE (new_var_type)
-	: func_parm;
+      init = (TYPE_MIN_VALUE (new_var_type) ? TYPE_MIN_VALUE (new_var_type)
+	: func_parm);
       break;
     case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN:
       code = MIN_EXPR;
-      init = TYPE_MAX_VALUE (new_var_type) ? TYPE_MAX_VALUE (new_var_type)
-	: func_parm;
+      init = (TYPE_MAX_VALUE (new_var_type) ? TYPE_MAX_VALUE (new_var_type)
+	: func_parm);
       break;
     case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
     case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
-      code = an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND ? LE_EXPR
-	: GE_EXPR;
+      code = (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND ? LE_EXPR
+	: GE_EXPR);
       init = an_loop_info[0].var;
+      break;
     case BUILT_IN_CILKPLUS_SEC_REDUCE:
       init = identity_value;
       break;
@@ -479,9 +448,11 @@  expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
       gcc_unreachable ();
     }
 
-  if (init)
-    new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR, init,
-					tf_warning_or_error);
+  if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
+    *new_var = get_temp_regvar (new_var_type, init);
+  else
+    *new_var = NULL_TREE;
+
   switch (an_type)
     {
     case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD:
@@ -516,8 +487,6 @@  expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
       break;
     case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
     case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
-      new_exp_init = build_x_modify_expr (location, array_ind_value, NOP_EXPR,
-					  func_parm, tf_warning_or_error);
       new_yes_expr = build_x_modify_expr (location, array_ind_value, NOP_EXPR,
 					  func_parm, tf_warning_or_error);
       new_no_expr = build_x_modify_expr (location, array_ind_value, NOP_EXPR,
@@ -567,21 +536,8 @@  expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
     default:
       gcc_unreachable ();
     }
-  
-  /* The reason we are putting initial variable twice is because the
-     new exp init below depends on this value being initialized.  */
-  for (ii = 0; ii < rank; ii++)
-    finish_expr_stmt (an_loop_info[ii].ind_init);
- 
-  if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
-    finish_expr_stmt (new_var_init);
-
-  if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
-      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND)
-    finish_expr_stmt (new_exp_init);
-
   an_init = pop_stmt_list (an_init);
-  append_to_statement_list_force (an_init, &loop_with_init);
+  append_to_statement_list (an_init, &loop_with_init);
   body = new_expr;
 
   for (ii = 0; ii < rank; ii++)
@@ -591,7 +547,7 @@  expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
 		      an_loop_info[ii].incr, body);
       body = pop_stmt_list (new_loop);
     }
-  append_to_statement_list_force (body, &loop_with_init);
+  append_to_statement_list (body, &loop_with_init);
 
   an_info.release ();
   an_loop_info.release ();
@@ -680,10 +636,7 @@  expand_an_in_modify_expr (location_t location, tree lhs,
 	  return an_init;
 	}
       else
-	{
-	  pop_stmt_list (an_init);
-	  return NULL_TREE;
-	}
+	gcc_unreachable ();
     }
 
   /* If for some reason location is not set, then find if LHS or RHS has
@@ -705,8 +658,6 @@  expand_an_in_modify_expr (location_t location, tree lhs,
     
   if (lhs_rank == 0 && rhs_rank != 0)
     {
-      if (location == UNKNOWN_LOCATION && EXPR_HAS_LOCATION (rhs))
-	location = EXPR_LOCATION (rhs);
       error_at (location, "%qD cannot be scalar when %qD is not", lhs, rhs);
       return error_mark_node;
     }
@@ -721,17 +672,17 @@  expand_an_in_modify_expr (location_t location, tree lhs,
   for (ii = 0; ii < lhs_list_size; ii++)
     {
       tree anode = (*lhs_list)[ii];
-      make_triplet_val_inv (location, &ARRAY_NOTATION_START (anode), complain);
-      make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (anode), complain);
-      make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (anode), complain);
+      make_triplet_val_inv (&ARRAY_NOTATION_START (anode));
+      make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (anode));
+      make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (anode));
     }
   for (ii = 0; ii < rhs_list_size; ii++)
     if ((*rhs_list)[ii] && TREE_CODE ((*rhs_list)[ii]) == ARRAY_NOTATION_REF)
       {
 	tree aa = (*rhs_list)[ii];
-	make_triplet_val_inv (location, &ARRAY_NOTATION_START (aa), complain);
-	make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (aa), complain);
-	make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (aa), complain);
+	make_triplet_val_inv (&ARRAY_NOTATION_START (aa));
+	make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (aa));
+	make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (aa));
       }
   lhs_an_loop_info.safe_grow_cleared (lhs_rank);
   
@@ -751,10 +702,10 @@  expand_an_in_modify_expr (location_t location, tree lhs,
       pop_stmt_list (an_init);
       return error_mark_node;
     }
-  tree rhs_len = (rhs_list_size > 0 && rhs_rank > 0) ?
-    rhs_an_info[0][0].length : NULL_TREE;
-  tree lhs_len = (lhs_list_size > 0 && lhs_rank > 0) ?
-    lhs_an_info[0][0].length : NULL_TREE;
+  tree rhs_len = ((rhs_list_size > 0 && rhs_rank > 0) ?
+    rhs_an_info[0][0].length : NULL_TREE);
+  tree lhs_len = ((lhs_list_size > 0 && lhs_rank > 0) ?
+    lhs_an_info[0][0].length : NULL_TREE);
   if (lhs_list_size > 0 && rhs_list_size > 0 && lhs_rank > 0 && rhs_rank > 0
       && TREE_CODE (lhs_len) == INTEGER_CST && rhs_len
       && TREE_CODE (rhs_len) == INTEGER_CST)
@@ -768,14 +719,16 @@  expand_an_in_modify_expr (location_t location, tree lhs,
 	  return error_mark_node;
 	}
     }
-   for (ii = 0; ii < lhs_rank; ii++)
-    if (lhs_an_info[0][ii].start && TREE_TYPE (lhs_an_info[0][ii].start))
-      lhs_an_loop_info[ii].var =
-	build_decl (location, VAR_DECL, NULL_TREE,
-		    TREE_TYPE (lhs_an_info[0][ii].start));
-    else
-      lhs_an_loop_info[ii].var = build_decl (location, VAR_DECL, NULL_TREE,
-					     integer_type_node);
+   for (ii = 0; ii < lhs_rank; ii++) 
+     {
+       tree typ = ptrdiff_type_node; 
+       lhs_an_loop_info[ii].var = create_temporary_var (typ);
+       add_decl_expr (lhs_an_loop_info[ii].var);
+       lhs_an_loop_info[ii].ind_init = build_x_modify_expr 
+	 (location, lhs_an_loop_info[ii].var, INIT_EXPR, build_zero_cst (typ), 
+	  complain);
+     }
+   
    if (rhs_list_size > 0)
      {
        rhs_array_operand = fix_sec_implicit_args (location, rhs_list,
@@ -789,24 +742,15 @@  expand_an_in_modify_expr (location_t location, tree lhs,
   rhs_list = NULL;
   extract_array_notation_exprs (rhs, true, &rhs_list);
   rhs_list_size = vec_safe_length (rhs_list);    
-  
-  for (ii = 0; ii < lhs_rank; ii++)
-    if (lhs_an_info[0][ii].is_vector)
-      {
-	lhs_an_loop_info[ii].ind_init = build_x_modify_expr
-	  (location, lhs_an_loop_info[ii].var, NOP_EXPR,
-	   build_zero_cst (TREE_TYPE (lhs_an_loop_info[ii].var)), complain);
-      }
+
   for (ii = 0; ii < rhs_rank; ii++)
     {
-      /* When we have a polynomial, we assume that the indices are of type
-	 integer.  */
-      rhs_an_loop_info[ii].var =
-	build_decl (location, VAR_DECL, NULL_TREE,
-		    TREE_TYPE (rhs_an_info[0][ii].start));
+      tree typ = ptrdiff_type_node;
+      rhs_an_loop_info[ii].var = create_temporary_var (typ);
+      add_decl_expr (rhs_an_loop_info[ii].var);
       rhs_an_loop_info[ii].ind_init = build_x_modify_expr
-	(location, rhs_an_loop_info[ii].var, NOP_EXPR, 
-	 build_zero_cst (TREE_TYPE (rhs_an_loop_info[ii].var)), complain);
+	(location, rhs_an_loop_info[ii].var, INIT_EXPR, build_zero_cst (typ), 
+	 complain);
     }
 
   if (lhs_rank)
@@ -860,7 +804,7 @@  expand_an_in_modify_expr (location_t location, tree lhs,
       gcc_unreachable ();
   
   an_init = pop_stmt_list (an_init);
-  append_to_statement_list_force (an_init, &loop_with_init);
+  append_to_statement_list (an_init, &loop_with_init);
   body = array_expr;
   for (ii = 0; ii < MAX (lhs_rank, rhs_rank); ii++)
     {
@@ -870,17 +814,13 @@  expand_an_in_modify_expr (location_t location, tree lhs,
 
       if (lhs_rank)
 	{
-	  append_to_statement_list_force (lhs_an_loop_info[ii].ind_init,
-					  &init_list);
-	  append_to_statement_list_force (lhs_an_loop_info[ii].incr,
-					  &incr_list);
+	  append_to_statement_list (lhs_an_loop_info[ii].ind_init, &init_list);
+	  append_to_statement_list (lhs_an_loop_info[ii].incr, &incr_list);
 	}
       if (rhs_rank)
 	{
-	  append_to_statement_list_force (rhs_an_loop_info[ii].ind_init,
-					  &init_list);
-	  append_to_statement_list_force (rhs_an_loop_info[ii].incr,
-					  &incr_list);
+	  append_to_statement_list (rhs_an_loop_info[ii].ind_init, &init_list);
+	  append_to_statement_list (rhs_an_loop_info[ii].incr, &incr_list);
 	}
       create_an_loop (init_list, cond_expr[ii], incr_list, body);
       body = pop_stmt_list (new_loop);
@@ -913,7 +853,6 @@  cp_expand_cond_array_notations (tree orig_stmt)
   tree an_init, body, stmt = NULL_TREE;
   tree builtin_loop, new_var = NULL_TREE;
   tree loop_with_init = alloc_stmt_list ();
-  tsubst_flags_t complain = tf_warning_or_error;
   location_t location = UNKNOWN_LOCATION;
   vec<vec<an_parts> > an_info = vNULL;
   vec<an_loop_parts> an_loop_info = vNULL;
@@ -995,11 +934,11 @@  cp_expand_cond_array_notations (tree orig_stmt)
 	      vec_safe_push (new_var_list, new_var);
 	      replace_array_notations (&orig_stmt, false, sub_list,
 				       new_var_list);
-	      append_to_statement_list_force (builtin_loop, &stmt);
+	      append_to_statement_list (builtin_loop, &stmt);
 	    }
 	}
     }
-  append_to_statement_list_force (orig_stmt, &stmt);
+  append_to_statement_list (orig_stmt, &stmt);
   rank = 0;
   array_list = NULL;
   if (!find_rank (EXPR_LOCATION (stmt), stmt, stmt, true, &rank))
@@ -1023,37 +962,28 @@  cp_expand_cond_array_notations (tree orig_stmt)
   for (ii = 0; ii < list_size; ii++)
     {
       tree anode = (*array_list)[ii];
-      make_triplet_val_inv (location, &ARRAY_NOTATION_START (anode), complain);
-      make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (anode), complain);
-      make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (anode), complain);
+      make_triplet_val_inv (&ARRAY_NOTATION_START (anode));
+      make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (anode));
+      make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (anode));
     }
   cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info);
-  for (ii = 0; ii < rank; ii++)
-      if (TREE_TYPE (an_info[0][ii].start)
-	  && TREE_CODE (TREE_TYPE (an_info[0][ii].start)) != TEMPLATE_TYPE_PARM)
-	{
-	  an_loop_info[ii].var = build_decl (location, VAR_DECL, NULL_TREE,
-					     TREE_TYPE (an_info[0][ii].start));
-	  an_loop_info[ii].ind_init = build_x_modify_expr
-	    (location, an_loop_info[ii].var, NOP_EXPR,
-	     build_zero_cst (TREE_TYPE (an_loop_info[ii].var)),
-	     tf_warning_or_error);
-	}
-      else
-	{
-	  an_loop_info[ii].var = build_min_nt_loc (location, VAR_DECL,
-						   NULL_TREE, NULL_TREE);
-	  an_loop_info[ii].ind_init =
-	    build_x_modify_expr (location, an_loop_info[ii].var, NOP_EXPR,
-				 integer_zero_node, tf_warning_or_error);
-	}
+
+  for (ii = 0; ii < rank; ii++) 
+    {
+      tree typ = ptrdiff_type_node;
+      an_loop_info[ii].var = create_temporary_var (typ);
+      add_decl_expr (an_loop_info[ii].var);
+      an_loop_info[ii].ind_init =
+	build_x_modify_expr (location, an_loop_info[ii].var, INIT_EXPR,
+			     build_zero_cst (typ), tf_warning_or_error);
+    }
   array_operand = create_array_refs (location, an_info, an_loop_info,
 				     list_size, rank);
   replace_array_notations (&stmt, true, array_list, array_operand);
   create_cmp_incr (location, &an_loop_info, rank, an_info, tf_warning_or_error);
   
   an_init = pop_stmt_list (an_init);
-  append_to_statement_list_force (an_init, &loop_with_init);
+  append_to_statement_list (an_init, &loop_with_init);
   body = stmt;
 
   for (ii = 0; ii < rank; ii++)
@@ -1063,7 +993,7 @@  cp_expand_cond_array_notations (tree orig_stmt)
 		      an_loop_info[ii].incr, body);
       body = pop_stmt_list (new_loop);
     }
-  append_to_statement_list_force (body, &loop_with_init);
+  append_to_statement_list (body, &loop_with_init);
 
   an_info.release ();
   an_loop_info.release ();
@@ -1108,14 +1038,14 @@  expand_unary_array_notation_exprs (tree orig_stmt)
 	  {
 	    vec<tree, va_gc> *sub_list = NULL, *new_var_list = NULL;
 	    stmt = alloc_stmt_list ();
-	    append_to_statement_list_force (builtin_loop, &stmt);
+	    append_to_statement_list (builtin_loop, &stmt);
 	    vec_safe_push (sub_list, list_node);
 	    vec_safe_push (new_var_list, new_var);
 	    replace_array_notations (&orig_stmt, false, sub_list, new_var_list);
 	  }	
       }
   if (stmt != NULL_TREE)
-    append_to_statement_list_force (finish_expr_stmt (orig_stmt), &stmt);
+    append_to_statement_list (finish_expr_stmt (orig_stmt), &stmt);
   else
     stmt = orig_stmt;
   rank = 0;
@@ -1135,22 +1065,19 @@  expand_unary_array_notation_exprs (tree orig_stmt)
   for (ii = 0; ii < list_size; ii++)
     {
       tree array_node = (*array_list)[ii];
-      make_triplet_val_inv (location, &ARRAY_NOTATION_START (array_node),
-			    tf_warning_or_error);
-      make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (array_node),
-			    tf_warning_or_error);
-      make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (array_node),
-			    tf_warning_or_error);
+      make_triplet_val_inv (&ARRAY_NOTATION_START (array_node));
+      make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (array_node));
+      make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (array_node));
     }
   cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info);
   
   for (ii = 0; ii < rank; ii++)
     {
-      an_loop_info[ii].var = build_decl (location, VAR_DECL, NULL_TREE,
-				  TREE_TYPE (an_info[0][ii].start));
+      tree typ = ptrdiff_type_node;
+      an_loop_info[ii].var = create_temporary_var (typ);
+      add_decl_expr (an_loop_info[ii].var);
       an_loop_info[ii].ind_init = build_x_modify_expr
-	(location, an_loop_info[ii].var, NOP_EXPR, 
-	 build_zero_cst (TREE_TYPE (an_loop_info[ii].var)),
+	(location, an_loop_info[ii].var, INIT_EXPR, build_zero_cst (typ), 
 	 tf_warning_or_error);
     }
   array_operand = create_array_refs (location, an_info, an_loop_info,
@@ -1159,7 +1086,7 @@  expand_unary_array_notation_exprs (tree orig_stmt)
   create_cmp_incr (location, &an_loop_info, rank, an_info, tf_warning_or_error);
   
   an_init = pop_stmt_list (an_init);
-  append_to_statement_list_force (an_init, &loop_with_init);
+  append_to_statement_list (an_init, &loop_with_init);
   body = stmt;
   
   for (ii = 0; ii < rank; ii++)
@@ -1169,7 +1096,7 @@  expand_unary_array_notation_exprs (tree orig_stmt)
 		      an_loop_info[ii].incr, body);
       body = pop_stmt_list (new_loop);
     }
-  append_to_statement_list_force (body, &loop_with_init);
+  append_to_statement_list (body, &loop_with_init);
 
   an_info.release ();
   an_loop_info.release ();
@@ -1190,16 +1117,18 @@  expand_return_expr (tree expr)
     return expr;
 
   location_t loc = EXPR_LOCATION (expr);
-  new_mod_list = alloc_stmt_list ();
+  new_mod_list = push_stmt_list ();
   retval_expr = TREE_OPERAND (expr, 0);
-  new_var = build_decl (loc, VAR_DECL, NULL_TREE, TREE_TYPE (retval_expr));
+  new_var = get_temp_regvar (TREE_TYPE (retval_expr), 
+			     build_zero_cst (TREE_TYPE (retval_expr)));
   new_mod = expand_an_in_modify_expr (loc, new_var, NOP_EXPR,
-					 TREE_OPERAND (retval_expr, 1),
-					 tf_warning_or_error);
+				      TREE_OPERAND (retval_expr, 1),
+				      tf_warning_or_error);
   TREE_OPERAND (retval_expr, 1) = new_var;
   TREE_OPERAND (expr, 0) = retval_expr;
-  append_to_statement_list_force (new_mod, &new_mod_list);
-  append_to_statement_list_force (expr, &new_mod_list);
+  add_stmt (new_mod);
+  add_stmt (expr);
+  new_mod_list = pop_stmt_list (new_mod_list);
   return new_mod_list;
 }
 
@@ -1336,19 +1265,21 @@  expand_array_notation_exprs (tree t)
       else
 	t = expand_array_notation_exprs (t);
       return t;
-
-    case SWITCH_EXPR:
-      t = cp_expand_cond_array_notations (t);
-      if (TREE_CODE (t) == SWITCH_EXPR)
-	SWITCH_BODY (t) = expand_array_notation_exprs (SWITCH_BODY (t));
-      else
-	t = expand_array_notation_exprs (t);
-      return t;
-    case FOR_STMT:      
+    case FOR_STMT:
+      if (contains_array_notation_expr (FOR_COND (t)))
+	{
+	  error_at (EXPR_LOCATION (FOR_COND (t)),
+		    "array notation cannot be used in a condition for "
+		    "a for-loop");
+	  return error_mark_node;
+	}
       /* FIXME: Add a check for CILK_FOR_STMT here when we add Cilk tasking 
 	 keywords.  */
       if (TREE_CODE (t) == FOR_STMT)
-	FOR_BODY (t) = expand_array_notation_exprs (FOR_BODY (t));
+	{ 
+	  FOR_BODY (t) = expand_array_notation_exprs (FOR_BODY (t));
+	  FOR_EXPR (t) = expand_array_notation_exprs (FOR_EXPR (t));
+	}
       else
 	t = expand_array_notation_exprs (t);
       return t;
@@ -1368,6 +1299,13 @@  expand_array_notation_exprs (tree t)
 	t = expand_array_notation_exprs (t);
       return t;
     case SWITCH_STMT:
+      if (contains_array_notation_expr (SWITCH_STMT_COND (t)))
+	{
+	  error_at (EXPR_LOCATION (SWITCH_STMT_COND (t)),
+		    "array notation cannot be used as a condition for "
+		    "switch statement");
+	  return error_mark_node;
+	}
       t = cp_expand_cond_array_notations (t);
       /* If the above function added some extra instructions above the original
 	 switch statement, then we can't assume it is still SWITCH_STMT so we
@@ -1382,6 +1320,14 @@  expand_array_notation_exprs (tree t)
 	t = expand_array_notation_exprs (t);
       return t;
     case WHILE_STMT:
+      if (contains_array_notation_expr (WHILE_COND (t)))
+	{
+	  if (EXPR_LOCATION (WHILE_COND (t)) != UNKNOWN_LOCATION)
+	    loc = EXPR_LOCATION (WHILE_COND (t));
+	  error_at (loc, "array notation cannot be used as a condition for "
+		    "while statement");
+	  return error_mark_node;
+	}
       t = cp_expand_cond_array_notations (t);
       /* If the above function added some extra instructions above the original
 	 while statement, then we can't assume it is still WHILE_STMTso we
@@ -1395,6 +1341,13 @@  expand_array_notation_exprs (tree t)
 	t = expand_array_notation_exprs (t);
       return t;
     case DO_STMT:
+      if (contains_array_notation_expr (DO_COND (t)))
+	{
+	  error_at (EXPR_LOCATION (DO_COND (t)),
+		    "array notation cannot be used as a condition for a "
+		    "do-while statement");
+	  return error_mark_node;
+	}
       t = cp_expand_cond_array_notations (t);
       /* If the above function added some extra instructions above the original
 	 do-while statement, then we can't assume it is still DO_STMT so we
@@ -1508,20 +1461,9 @@  cilkplus_an_triplet_types_ok_p (location_t loc, tree start_index, tree length,
     }
   if (!TREE_CODE (type) == FUNCTION_TYPE)
     {
-      error_at (loc, "array notations cannot be used with function type");
+      error_at (loc, "array notation cannot be used with function type");
       return false;
     }
-  while (type && (TREE_CODE (type) == POINTER_TYPE
-		  || TREE_CODE (type) == ARRAY_TYPE))
-    {
-      type = TREE_TYPE (type);
-      if (type && TREE_CODE (type) == FUNCTION_TYPE)
-	{
-	  error_at (loc, "array notations cannot be used with function pointer"
-		    " arrays");
-	  return false;
-	}
-    }
   if (!find_rank (loc, start_index, start_index, false, &start_rank)
       || !find_rank (loc, length, length, false, &length_rank)
       || !find_rank (loc, stride, stride, false, &stride_rank))
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 38ef878..590d857 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -1207,6 +1207,12 @@  cp_genericize (tree fndecl)
   if (DECL_CLONED_FUNCTION_P (fndecl))
     return;
 
+  /* Expand all the array notations here.  */
+  if (flag_enable_cilkplus 
+      && contains_array_notation_expr (DECL_SAVED_TREE (fndecl)))
+    DECL_SAVED_TREE (fndecl) = 
+      expand_array_notation_exprs (DECL_SAVED_TREE (fndecl));
+
   /* We do want to see every occurrence of the parms, so we can't just use
      walk_tree's hash functionality.  */
   cp_genericize_tree (&DECL_SAVED_TREE (fndecl));
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index f3bc27a..bb5a13d 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -6062,10 +6062,10 @@  cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 
 /* This function parses Cilk Plus array notations.  The starting index is
    passed in INIT_INDEX and the array name is passed in ARRAY_VALUE.  If the
-   INIT_INDEX is NULL, then we have special case were the entire array is
+   INIT_INDEX is NULL, then we have special case where the entire array is
    accessed (e.g. A[:]).  The return value of this function is a tree node
-   called VALUE_TREE of type ARRAY_NOTATION_REF.  If some error occurred it
-   returns error_mark_node.  */
+   of type ARRAY_NOTATION_REF.  If some error occurred it returns 
+   error_mark_node.  */
 
 static tree
 cp_parser_array_notation (location_t loc, cp_parser *parser, tree init_index,
@@ -6074,8 +6074,6 @@  cp_parser_array_notation (location_t loc, cp_parser *parser, tree init_index,
   cp_token *token = NULL;
   tree start_index = NULL_TREE, length_index = NULL_TREE, stride = NULL_TREE;
   tree value_tree, type, array_type, array_type_domain;
-  double_int x; 
-  bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
 
   if (!array_value || array_value == error_mark_node)
     {
@@ -6117,44 +6115,24 @@  cp_parser_array_notation (location_t loc, cp_parser *parser, tree init_index,
 	      || TREE_CODE (array_type) == POINTER_TYPE)
 	    {
 	      error_at (loc, "start-index and length fields necessary for "
-			"using array notations in pointers or records");
+			"using array notation in pointers or records");
 	      cp_parser_skip_to_end_of_statement (parser);
 	      return error_mark_node;
 	    }
-	  if (TREE_CODE (array_type) == ARRAY_TYPE)
-	    {
-	      tree subtype = TREE_TYPE (array_type);
-	      while (subtype && TREE_CODE (subtype) == POINTER_TYPE)
-		{
-		  /* This could be a function ptr.  If so, then emit error.  */
-		  subtype = TREE_TYPE (subtype);
-		  if (subtype && TREE_CODE (subtype) == FUNCTION_TYPE)
-		    {
-		      error_at (loc, "array notations cannot be used with"
-				" function pointer arrays");
-		      cp_parser_skip_to_end_of_statement (parser);
-		      return error_mark_node;
-		    }
-		}
-	    }
 	  array_type_domain = TYPE_DOMAIN (array_type);
 	  if (!array_type_domain)
 	    {
 	      error_at (loc, "start-index and length fields necessary for "
-			"using array notations in dimensionless arrays");
+			"using array notation with array of unknown bound");
 	      cp_parser_skip_to_end_of_statement (parser);
 	      return error_mark_node;
 	    }
 	  start_index = TYPE_MINVAL (array_type_domain);
-	  start_index = fold_build1 (CONVERT_EXPR, ptrdiff_type_node,
-				     start_index);
-	  x = TREE_INT_CST (TYPE_MAXVAL (array_type_domain));
-	  x.low++;
-	  length_index = double_int_to_tree (integer_type_node, x);
-	  length_index = fold_build1 (CONVERT_EXPR, ptrdiff_type_node,
-				      length_index);
-	  stride = build_int_cst (integer_type_node, 1);
-	  stride = fold_build1 (CONVERT_EXPR, ptrdiff_type_node, stride);
+	  start_index = cp_fold_convert (ptrdiff_type_node, start_index);
+	  length_index = size_binop 
+	    (PLUS_EXPR, TYPE_MAXVAL (array_type_domain), size_one_node);
+	  length_index = cp_fold_convert (ptrdiff_type_node, length_index);
+	  stride = build_int_cst (ptrdiff_type_node, 1);
 	}
       else if (init_index != error_mark_node)
 	{
@@ -6165,12 +6143,12 @@  cp_parser_array_notation (location_t loc, cp_parser *parser, tree init_index,
 	  start_index = init_index;
 	  cp_lexer_consume_token (parser->lexer);
 
-	  saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
+	  bool saved_colon_corrects_to_scope_p = 
+	    parser->colon_corrects_to_scope_p;
 	   /* The ':' is used in array notation.  Thus compiler cannot do scope 
 	      correction automatically.  */
 	  parser->colon_corrects_to_scope_p = false;
 	  length_index = cp_parser_expression (parser, false, NULL);
-	  parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
 	  if (!length_index || length_index == error_mark_node)
 	    cp_parser_skip_to_end_of_statement (parser);
 	 
@@ -6180,7 +6158,6 @@  cp_parser_array_notation (location_t loc, cp_parser *parser, tree init_index,
 	      saved_colon_corrects_to_scope_p = 
 		parser->colon_corrects_to_scope_p;
 	      /* Disable correcting single colon correcting to scope.  */
-	      parser->colon_corrects_to_scope_p = false;
 	      stride = cp_parser_expression (parser, false, NULL);
 	      parser->colon_corrects_to_scope_p = 
 		saved_colon_corrects_to_scope_p;
@@ -6211,13 +6188,7 @@  cp_parser_array_notation (location_t loc, cp_parser *parser, tree init_index,
       return error_mark_node;
     }
   cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
-  
-  /* We fold all 3 of the values to make things easier when we transform
-     them later.  */
-  start_index = fold (start_index);
-  length_index = fold (length_index);
-  stride = fold (stride);
-
+ 
   value_tree = build_array_notation_ref (input_location, array_value,
 					 start_index, length_index, stride,
 					 type);
@@ -6248,8 +6219,7 @@  cp_parser_postfix_open_square_expression (cp_parser *parser,
   if (flag_enable_cilkplus
       && cp_lexer_peek_token (parser->lexer)->type == CPP_COLON)
     /* If we are here, then we have something like this:
-       ARRAY[:]
-    */
+       ARRAY[:]   */
     postfix_expression = cp_parser_array_notation (loc, parser, NULL_TREE,
 						   postfix_expression);
   else
@@ -6259,8 +6229,7 @@  cp_parser_postfix_open_square_expression (cp_parser *parser,
 	 2. ARRAY[EXPR : EXPR]        -- Array notation expr with default stride
 	 of 1.
 	 3. ARRAY[EXPR : EXPR : EXPR] -- Array Notation with userdefined stride.
-	 4. Array[Braced List]        -- This is handled by braced list.
-      */
+	 4. Array[Braced List]        -- This is handled by braced list.  */
       
       /* Parse the index expression.  */
       /* ??? For offsetof, there is a question of what to allow here.  If
@@ -6288,7 +6257,7 @@  cp_parser_postfix_open_square_expression (cp_parser *parser,
 		{
 		  error_at (cp_lexer_peek_token (parser->lexer)->location,
 			    "braced list index is not allowed with array "
-			    "notations");
+			    "notation");
 		  index = error_mark_node;
 		}
 	    }
@@ -9550,9 +9519,6 @@  cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr,
   finish_compound_stmt (compound_stmt);
   /* Consume the `}'.  */
   cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
-
-  if (flag_enable_cilkplus && contains_array_notation_expr (compound_stmt))
-    compound_stmt = expand_array_notation_exprs (compound_stmt);
   return compound_stmt;
 }
 
@@ -9745,14 +9711,6 @@  cp_parser_selection_statement (cp_parser* parser, bool *if_p)
 
 	    /* Now we're all done with the switch-statement.  */
 	    finish_switch_stmt (statement);
-	    if (flag_enable_cilkplus
-		&& contains_array_notation_expr (condition))
-	      {
-		error_at (EXPR_LOCATION (condition),
-			  "array notations cannot be used as a condition for "
-			  "switch statement");
-		statement = error_mark_node;
-	      }      
 	  }
 
 	return statement;
@@ -10310,12 +10268,6 @@  cp_parser_iteration_statement (cp_parser* parser)
 	parser->in_statement = in_statement;
 	/* We're done with the while-statement.  */
 	finish_while_stmt (statement);
-	if (flag_enable_cilkplus && contains_array_notation_expr (condition))
-	  {
-	    error_at (EXPR_LOCATION (condition), "array notations cannot be "
-		      "used as a condition for while statement");
-	    statement = error_mark_node;
-	  }
       }
       break;
 
@@ -10342,15 +10294,6 @@  cp_parser_iteration_statement (cp_parser* parser)
 	cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
 	/* Look for the `;'.  */
 	cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
-	if (flag_enable_cilkplus
-	    && contains_array_notation_expr (DO_COND (statement)))
-	  {
-	    error_at (EXPR_LOCATION (DO_COND (statement)),
-		      "array notations cannot be used as a condition for a "
-		      "do-while statement");
-	    statement = error_mark_node;
-	  }
-
       }
       break;
 
@@ -10367,19 +10310,10 @@  cp_parser_iteration_statement (cp_parser* parser)
 	/* Parse the body of the for-statement.  */
 	parser->in_statement = IN_ITERATION_STMT;
 	cp_parser_already_scoped_statement (parser);
-	parser->in_statement = in_statement;
+	parser->in_statement = in_statement; 
 
-	if (flag_enable_cilkplus
-	    && contains_array_notation_expr (FOR_COND (statement)))
-	  {
-	    error_at (EXPR_LOCATION (FOR_COND (statement)),
-		      "array notations cannot be used in a condition for a "
-		      "for-loop");
-	    statement = error_mark_node;
-	  }
-	else
-	  /* We're done with the for-statement.  */
-	  finish_for_stmt (statement);
+	/* We're done with the for-statement.  */ 
+	finish_for_stmt (statement);
       }
       break;
 
@@ -16953,54 +16887,30 @@  cp_parser_direct_declarator (cp_parser* parser,
 	  if (token->type != CPP_CLOSE_SQUARE)
 	    {
 	      bool non_constant_p;
-
-	      if (flag_enable_cilkplus
-		  && cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+	      bounds
+		= cp_parser_constant_expression (parser,
+						 /*allow_non_constant=*/true,
+						 &non_constant_p);
+	      if (!non_constant_p)
+		/* OK */;
+	      else if (error_operand_p (bounds))
+		/* Already gave an error.  */;
+	      else if (!parser->in_function_body
+		       || current_binding_level->kind == sk_function_parms)
 		{
+		  /* Normally, the array bound must be an integral constant
+		     expression.  However, as an extension, we allow VLAs
+		     in function scopes as long as they aren't part of a
+		     parameter declaration.  */
+		  cp_parser_error (parser,
+				   "array bound is not an integer constant");
 		  bounds = error_mark_node;
-		  error_at (cp_lexer_peek_token (parser->lexer)->location,
-			    "array notations cannot be used in declaration");
-		  cp_lexer_consume_token (parser->lexer);
 		}
-	      else
+	      else if (processing_template_decl)
 		{
-		  bounds
-		    = cp_parser_constant_expression (parser,
-						     /*allow_non_constant=*/true,
-						     &non_constant_p);
-		  if (!non_constant_p)
-		    /* OK */;
-		  else if (error_operand_p (bounds))
-		    /* Already gave an error.  */;
-		  else if (!parser->in_function_body
-			   || current_binding_level->kind == sk_function_parms)
-		    {
-		      /* Normally, the array bound must be an integral constant
-			 expression.  However, as an extension, we allow VLAs
-			 in function scopes as long as they aren't part of a
-			 parameter declaration.  */
-		      cp_parser_error (parser,
-				       "array bound is not an integer constant");
-		      bounds = error_mark_node;
-		    }
-		  else if (processing_template_decl)
-		    {
-		      /* Remember this wasn't a constant-expression.  */
-		      bounds = build_nop (TREE_TYPE (bounds), bounds);
-		      TREE_SIDE_EFFECTS (bounds) = 1;
-		    }
-		  if (flag_enable_cilkplus
-		      && cp_lexer_next_token_is (parser->lexer, CPP_COLON))
-		    {
-		      location_t loc =
-			cp_lexer_peek_token (parser->lexer)->location;
-		      while (cp_lexer_next_token_is_not (parser->lexer,
-							 CPP_CLOSE_SQUARE))
-			cp_lexer_consume_token (parser->lexer);
-		      error_at (loc, "array notations cannot be used in "
-			 	"declaration");
-		      bounds = error_mark_node; 
-		    }
+		  /* Remember this wasn't a constant-expression.  */
+		  bounds = build_nop (TREE_TYPE (bounds), bounds);
+		  TREE_SIDE_EFFECTS (bounds) = 1;
 		}
 	    }
 	  else
@@ -18372,10 +18282,6 @@  cp_parser_ctor_initializer_opt_and_function_body (cp_parser *parser,
   if (check_body_p)
     check_constexpr_ctor_body (last, list);
 
-  /* Transform all array notations to the equivalent array refs and loop.  */
-  if (flag_enable_cilkplus && contains_array_notation_expr (body))
-    body = expand_array_notation_exprs (body);
-  
   /* Finish the function body.  */
   finish_function_body (body);
 
@@ -22355,12 +22261,6 @@  cp_parser_function_definition_after_declarator (cp_parser* parser,
 
   finish_lambda_scope ();
 
-  /* Expand all array notation expressions here.  */
-  if (flag_enable_cilkplus && current_function_decl
-      && contains_array_notation_expr (DECL_SAVED_TREE (current_function_decl)))
-    DECL_SAVED_TREE (current_function_decl) =
-      expand_array_notation_exprs (DECL_SAVED_TREE (current_function_decl));
-  
   /* Finish the function.  */
   fn = finish_function ((ctor_initializer_p ? 1 : 0) |
 			(inline_p ? 2 : 0));
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 667e37f..5dafdcd 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -15739,9 +15739,6 @@  type_unification_real (tree tparms,
       arg = args[ia];
       ++ia;
 
-      if (flag_enable_cilkplus && TREE_CODE (arg) == ARRAY_NOTATION_REF)
-	return 1;
-
       if (unify_one_argument (tparms, targs, parm, arg, subr, strict,
 			      flags, explain_p))
 	return 1;
@@ -19143,11 +19140,6 @@  instantiate_decl (tree d, int defer_ok,
       pointer_map_destroy (local_specializations);
       local_specializations = saved_local_specializations;
 
-      /* We expand all the array notation expressions here.  */
-      if (flag_enable_cilkplus
-	  && contains_array_notation_expr (DECL_SAVED_TREE (d)))
-	DECL_SAVED_TREE (d) = expand_array_notation_exprs (DECL_SAVED_TREE (d));
-      
       /* Finish the function.  */
       d = finish_function (0);
       expand_or_defer_fn (d);
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 0a460a4..db81b44 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -8089,7 +8089,6 @@  cxx_eval_constant_expression (const constexpr_call *call, tree t,
 				       non_constant_p, overflow_p);
       break;
 
-    case ARRAY_NOTATION_REF:
     case ARRAY_REF:
       r = cxx_eval_array_reference (call, t, allow_non_constant, addr,
 				    non_constant_p, overflow_p);
@@ -8901,7 +8900,6 @@  potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
       want_rval = true;
       /* Fall through.  */
     case ARRAY_REF:
-    case ARRAY_NOTATION_REF:
     case ARRAY_RANGE_REF:
     case MEMBER_REF:
     case DOTSTAR_EXPR:
@@ -8912,6 +8910,9 @@  potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
 	  return false;
       return true;
 
+    case ARRAY_NOTATION_REF:
+      return false;
+
     case FMA_EXPR:
     case VEC_PERM_EXPR:
      for (i = 0; i < 3; ++i)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 9940868..5594687 100644
Binary files a/gcc/testsuite/ChangeLog and b/gcc/testsuite/ChangeLog differ
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/decl-ptr-colon.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/decl-ptr-colon.c
index 68c8859..4b54f4d 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/decl-ptr-colon.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/decl-ptr-colon.c
@@ -1,3 +1,4 @@ 
+/* { dg-do compile { target c } } */
 /* { dg-options "-fcilkplus" } */
 
 int main(void)
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/dimensionless-arrays.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/dimensionless-arrays.c
index 69aaa52..690e89a 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/dimensionless-arrays.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/dimensionless-arrays.c
@@ -5,6 +5,6 @@  extern int *b;
 
 void foo()
 {
-  a[:] = 5;	// { dg-error "start-index and length fields necessary for using array notations in dimensionless arrays" }
-  b[:] = 5;    // { dg-error "start-index and length fields necessary for using array notations in pointers" }
+  a[:] = 5;	// { dg-error "start-index and length fields necessary for using array notation" }
+  b[:] = 5;    // { dg-error "start-index and length fields necessary for using" }
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/fn_ptr.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/fn_ptr.c
index 024a158..fa6d900 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/fn_ptr.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/fn_ptr.c
@@ -1,3 +1,4 @@ 
+/* { dg-do compile } */
 /* { dg-options "-fcilkplus" } */
 
 typedef int (*foo)(int);
@@ -10,11 +11,11 @@  int main(void)
   foo ***func_array_ptr;
   int argc = 5;
 
-  array[:] =  func_array[:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
-  func_array[0:5](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
-  func_array2[0:5][:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
-  array2[0:5][:] = func_array2[0:5][:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
-  func_array_ptr[0:5][0:4][0:argc:2](argc); /* { dg-error "array notations cannot be used with function pointer arrays" } */
+  array[:] =  func_array[:](10); 
+  func_array[0:5](10); 
+  func_array2[0:5][:](10);
+  array2[0:5][:] = func_array2[0:5][:](10);
+  func_array_ptr[0:5][0:4][0:argc:2](argc); 
 
   return 0;
 }
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
index 14421d9..814786b 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c
@@ -6,7 +6,7 @@  int main (void)
   int array[10], array2[10][10];
   int x, ii, jj ;
 
-  switch (array[:]) {  /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  switch (array[:]) {  /* { dg-error "cannot be used as a condition for switch statement" } */
   case 1:
     x = 5;
     break;
@@ -17,7 +17,7 @@  int main (void)
     x = 9;
   }
 
-  switch (array2[:][:]) { /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  switch (array2[:][:]) { /* { dg-error "cannot be used as a condition for switch statement" } */
   case 1:
     x = 5;
     break;
@@ -28,7 +28,7 @@  int main (void)
     x = 9;
   }
 
-  switch (array[:] + x) { /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  switch (array[:] + x) { /* { dg-error "cannot be used as a condition for switch statement" } */
   case 1:
     x = 5;
     break;
@@ -39,7 +39,7 @@  int main (void)
     x = 9;
   }
   
-  switch (array2[:][1:x:4] + x) { /* { dg-error "array notations cannot be used as a condition for switch statement" } */
+  switch (array2[:][1:x:4] + x) { /* { dg-error "cannot be used as a condition for switch statement" } */
   case 1:
     x = 5;
     break;
@@ -50,36 +50,36 @@  int main (void)
     x = 9;
   }
 
-  for (ii = 0; ii < array[:]; ii++) /* { dg-error "array notations cannot be used in a condition for a for-loop" } */
+  for (ii = 0; ii < array[:]; ii++) /* { dg-error "cannot be used in a condition for a for-loop" } */
     {
       x = 2;
     }
 
-  for (ii = 0; ii < array2[:][:]; ii++) /* { dg-error "array notations cannot be used in a condition for a for-loop" } */
+  for (ii = 0; ii < array2[:][:]; ii++) /* { dg-error "cannot be used in a condition for a for-loop" } */
     {
       x = 3;
     }
 
-  for (; array2[:][:] < 2;) /* { dg-error "array notations cannot be used in a condition for a for-loop" } */
+  for (; array2[:][:] < 2;) /* { dg-error "cannot be used in a condition for a for-loop" } */
     x = 4;
 
 
-  while (array2[:][:]) /* { dg-error "array notations cannot be used as a condition for while statement" } */
+  while (array2[:][:]) /* { dg-error "cannot be used as a condition for while statement" } */
     x = 3;
 
-  while (array[1:1:1]) /* { dg-error "array notations cannot be used as a condition for while statement" } */
+  while (array[1:1:1]) /* { dg-error "cannot be used as a condition for while statement" } */
     x = 1;
 
-  while (ii != array2[1:x:3][1:2:1]) /* { dg-error "array notations cannot be used as a condition for while statement"  } */
+  while (ii != array2[1:x:3][1:2:1]) /* { dg-error "cannot be used as a condition for while statement"  } */
     x = 2;
 
-  do { /* { dg-error "array notations cannot be used as a condition for a do-while statement" "" { target c } } */
+  do { /* { dg-error "cannot be used as a condition for a do-while statement" "" { target c } } */
     x = 3;
-  } while (ii != array2[:][:]); /* { dg-error "array notations cannot be used as a condition for a do-while statement" "" { target c++ } } */
+  } while (ii != array2[:][:]); /* { dg-error "cannot be used as a condition for a do-while statement" "" { target c++ } } */
 
-  do {  /* { dg-error "array notations cannot be used as a condition for a do-while statement" "" { target c } } */
+  do {  /* { dg-error "cannot be used as a condition for a do-while statement" "" { target c } } */
     x = 2;
-  } while (ii != (x + array2[:][1:x:2]) + 2); /* { dg-error "array notations cannot be used as a condition for a do-while statement" "" { target c++ } } */
+  } while (ii != (x + array2[:][1:x:2]) + 2); /* { dg-error "cannot be used as a condition for a do-while statement" "" { target c++ } } */
   
   do { 
     x += 3;
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/rank_mismatch.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/rank_mismatch.c
index b5e37ce..eb3c1f1 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/AN/rank_mismatch.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/rank_mismatch.c
@@ -10,6 +10,7 @@  int main (void)
   int array[10][10], array2[10];
 
   array[:][:] = array[:]; /* { dg-error "rank mismatch between" } */
+  /* { dg-error "invalid conversion" "" { target c++ } 12 } */
 
   x = array2[:]; /* { dg-error "cannot be scalar when" } */