Implemented Jason Merrill's suggestions on Array Notation C++.

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

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

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

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

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

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


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

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

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

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

From-SVN: r200554
This commit is contained in:
Balaji V. Iyer 2013-06-28 20:04:36 +00:00 committed by Balaji V. Iyer
parent e32e4c4a88
commit 1141ed3f71
20 changed files with 564 additions and 807 deletions

View File

@ -1,3 +1,7 @@
2013-06-28 Balaji V. Iyer <balaji.v.iyer@intel.com>
* builtins.def: Fixed the function type of CILKPLUS_BUILTIN.
2013-06-28 Vladimir Makarov <vmakarov@redhat.com>
* lra-constraints.c (need_for_split_p): Check call used hard regs

View File

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

View File

@ -101,15 +101,11 @@ length_mismatch_in_expr_p (location_t loc, vec<vec<an_parts> >list)
/* If length is a INTEGER, and list[ii][jj] is an integer then
check if they are equal. If they are not equal then return
true. */
if (TREE_CODE (list[ii][jj].length) == INTEGER_CST)
{
l_node = int_cst_value (list[ii][jj].length);
l_length = int_cst_value (length);
if (absu_hwi (l_length) != absu_hwi (l_node))
{
error_at (loc, "length mismatch in expression");
return true;
}
if (TREE_CODE (list[ii][jj].length) == INTEGER_CST
&& !tree_int_cst_equal (list[ii][jj].length, length))
{
error_at (loc, "length mismatch in expression");
return true;
}
}
else
@ -271,6 +267,8 @@ find_rank (location_t loc, tree orig_expr, tree expr, bool ignore_builtin_fn,
/* If it is a built-in function, then we know it returns a
scalar. */
return true;
if (!find_rank (loc, orig_expr, func_name, ignore_builtin_fn, rank))
return false;
FOR_EACH_CALL_EXPR_ARG (arg, iter, expr)
{
if (!find_rank (loc, orig_expr, arg, ignore_builtin_fn, rank))
@ -358,6 +356,9 @@ extract_array_notation_exprs (tree node, bool ignore_builtin_fn,
vec_safe_push (*array_list, node);
return;
}
/* This will extract array notations in function pointers. */
extract_array_notation_exprs (CALL_EXPR_FN (node), ignore_builtin_fn,
array_list);
FOR_EACH_CALL_EXPR_ARG (arg, iter, node)
extract_array_notation_exprs (arg, ignore_builtin_fn, array_list);
}
@ -433,6 +434,9 @@ replace_array_notations (tree *orig, bool ignore_builtin_fn,
}
return;
}
/* Fixes array notations in array notations in function pointers. */
replace_array_notations (&CALL_EXPR_FN (*orig), ignore_builtin_fn, list,
array_operand);
ii = 0;
FOR_EACH_CALL_EXPR_ARG (arg, iter, *orig)
{
@ -575,53 +579,49 @@ cilkplus_extract_an_triplets (vec<tree, va_gc> *list, size_t size, size_t rank,
vec<vec<struct cilkplus_an_parts> > *node)
{
vec<vec<tree> > array_exprs = vNULL;
struct cilkplus_an_parts init = { NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE,
false };
node->safe_grow_cleared (size);
array_exprs.safe_grow_cleared (size);
for (size_t ii = 0; ii < size; ii++)
for (size_t jj = 0; jj < rank; jj++)
{
(*node)[ii].safe_push (init);
array_exprs[ii].safe_push (NULL_TREE);
}
if (rank > 0)
for (size_t ii = 0; ii < size; ii++)
{
(*node)[ii].safe_grow_cleared (rank);
array_exprs[ii].safe_grow_cleared (rank);
}
for (size_t ii = 0; ii < size; ii++)
{
size_t jj = 0;
tree ii_tree = (*list)[ii];
while (ii_tree)
if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
{
array_exprs[ii][jj] = ii_tree;
jj++;
ii_tree = ARRAY_NOTATION_ARRAY (ii_tree);
}
else if (TREE_CODE (ii_tree) == ARRAY_REF)
ii_tree = TREE_OPERAND (ii_tree, 0);
else if (TREE_CODE (ii_tree) == VAR_DECL
|| TREE_CODE (ii_tree) == CALL_EXPR
|| TREE_CODE (ii_tree) == PARM_DECL)
break;
else
gcc_unreachable ();
{
if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
{
array_exprs[ii][jj] = ii_tree;
jj++;
ii_tree = ARRAY_NOTATION_ARRAY (ii_tree);
}
else if (TREE_CODE (ii_tree) == ARRAY_REF)
ii_tree = TREE_OPERAND (ii_tree, 0);
else
break;
}
}
for (size_t ii = 0; ii < size; ii++)
if (TREE_CODE ((*list)[ii]) == ARRAY_NOTATION_REF)
for (size_t jj = 0; jj < rank; jj++)
if (TREE_CODE (array_exprs[ii][jj]) == ARRAY_NOTATION_REF)
{
tree ii_tree = array_exprs[ii][jj];
(*node)[ii][jj].is_vector = true;
(*node)[ii][jj].value = ARRAY_NOTATION_ARRAY (ii_tree);
(*node)[ii][jj].start = ARRAY_NOTATION_START (ii_tree);
(*node)[ii][jj].length =
fold_build1 (CONVERT_EXPR, integer_type_node,
ARRAY_NOTATION_LENGTH (ii_tree));
(*node)[ii][jj].stride =
fold_build1 (CONVERT_EXPR, integer_type_node,
ARRAY_NOTATION_STRIDE (ii_tree));
}
{
tree ii_tree = array_exprs[ii][jj];
(*node)[ii][jj].is_vector = true;
(*node)[ii][jj].value = ARRAY_NOTATION_ARRAY (ii_tree);
(*node)[ii][jj].start = ARRAY_NOTATION_START (ii_tree);
(*node)[ii][jj].length =
fold_build1 (CONVERT_EXPR, integer_type_node,
ARRAY_NOTATION_LENGTH (ii_tree));
(*node)[ii][jj].stride =
fold_build1 (CONVERT_EXPR, integer_type_node,
ARRAY_NOTATION_STRIDE (ii_tree));
}
}
/* Replaces all the __sec_implicit_arg functions in LIST with the induction
@ -637,16 +637,15 @@ fix_sec_implicit_args (location_t loc, vec <tree, va_gc> *list,
vec <tree, va_gc> *array_operand = NULL;
for (size_t ii = 0; ii < vec_safe_length (list); ii++)
if (TREE_CODE ((*list)[ii]) == CALL_EXPR
&& TREE_CODE (CALL_EXPR_FN ((*list)[ii])) == ADDR_EXPR
&& is_sec_implicit_index_fn (CALL_EXPR_FN ((*list)[ii])))
{
int idx = extract_sec_implicit_index_arg (loc, (*list)[ii]);
if (idx < (int) rank && idx >= 0)
vec_safe_push (array_operand, an_loop_info[idx].var);
else if (idx == -1)
if (idx < 0)
/* In this case, the returning function would have emitted an
error thus it is not necessary to do so again. */
return NULL;
else if (idx < (int) rank)
vec_safe_push (array_operand, an_loop_info[idx].var);
else
{
error_at (loc, "__sec_implicit_index argument %d must be "

View File

@ -1,3 +1,8 @@
2013-06-28 Balaji V. Iyer <balaji.v.iyer@intel.com>
* c-parser.c (c_parser_array_notation): Removed rejection of array
notations in an array of function pointers.
2013-06-21 Balaji V. Iyer <balaji.v.iyer@intel.com>
* c-array-notation.c (make_triplet_val_inv): New function.

View File

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

View File

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

View File

@ -216,7 +216,6 @@ static void add_candidates (tree, tree, const vec<tree, va_gc> *, tree, tree,
bool, tree, tree, int, struct z_candidate **,
tsubst_flags_t);
static conversion *merge_conversion_sequences (conversion *, conversion *);
static bool magic_varargs_p (tree);
static tree build_temp (tree, tree, int, diagnostic_t *, tsubst_flags_t);
/* Returns nonzero iff the destructor name specified in NAME matches BASETYPE.
@ -5857,16 +5856,9 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
else if (t->kind == ck_identity)
break;
}
if (flag_enable_cilkplus
&& (contains_array_notation_expr (expr)
|| contains_array_notation_expr (fn)))
/* If we are using array notations, we fix them up at a later stage
and we will do these checks then. */
;
else if (permerror (loc, "invalid conversion from %qT to %qT",
TREE_TYPE (expr), totype)
&& fn)
if (permerror (loc, "invalid conversion from %qT to %qT",
TREE_TYPE (expr), totype)
&& fn)
inform (DECL_SOURCE_LOCATION (fn),
"initializing argument %P of %qD", argnum, fn);
@ -6515,9 +6507,12 @@ convert_for_arg_passing (tree type, tree val, tsubst_flags_t complain)
which no conversions at all should be done. This is true for some
builtins which don't act like normal functions. */
static bool
bool
magic_varargs_p (tree fn)
{
if (flag_enable_cilkplus && is_cilkplus_reduce_builtin (fn) != BUILT_IN_NONE)
return true;
if (DECL_BUILT_IN (fn))
switch (DECL_FUNCTION_CODE (fn))
{
@ -6895,21 +6890,13 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
" (you can disable this with -fno-deduce-init-list)");
}
}
val = convert_like_with_context (conv, arg, fn, i - is_method,
conversion_warning
? complain
: complain & (~tf_warning));
/* If the function call is builtin array notation function then no need
to do any type conversion. */
if (flag_enable_cilkplus
&& is_cilkplus_reduce_builtin (fn) != BUILT_IN_NONE)
val = arg;
else
{
val = convert_like_with_context (conv, arg, fn, i - is_method,
conversion_warning
? complain
: complain & (~tf_warning));
val = convert_for_arg_passing (type, val, complain);
}
val = convert_for_arg_passing (type, val, complain);
if (val == error_mark_node)
return error_mark_node;
else

View File

@ -59,7 +59,6 @@
#include "diagnostic.h"
#include "tree-iterator.h"
#include "vec.h"
#include "gimple.h"
/* Creates a FOR_STMT with INIT, COND, INCR and BODY as the initializer,
condition, increment expression and the loop-body, respectively. */
@ -82,17 +81,12 @@ create_an_loop (tree init, tree cond, tree incr, tree body)
a variable to make it loop invariant for array notations. */
static inline void
make_triplet_val_inv (location_t loc, tree *value, tsubst_flags_t cry)
make_triplet_val_inv (tree *value)
{
tree var;
if (TREE_CODE (*value) != INTEGER_CST
&& TREE_CODE (*value) != PARM_DECL
&& TREE_CODE (*value) != VAR_DECL)
{
var = build_decl (loc, VAR_DECL, NULL_TREE, integer_type_node);
finish_expr_stmt (build_x_modify_expr (loc, var, NOP_EXPR, *value, cry));
*value = var;
}
*value = get_temp_regvar (ptrdiff_type_node, *value);
}
/* Returns a vector of size RANK that contains an ARRAY_REF. This vector is
@ -112,47 +106,22 @@ create_array_refs (location_t loc, vec<vec<an_parts> > an_info,
{
tree ind_mult, ind_incr;
vec<tree, va_gc> *array_operand = NULL;
for (size_t ii = 0; ii < size; ii++)
if (an_info[ii][0].is_vector)
{
tree array_opr = an_info[ii][rank - 1].value;
for (int s_jj = rank -1; s_jj >= 0; s_jj--)
{
tree str = NULL_TREE, v = NULL_TREE, st = NULL_TREE;
tree start = an_info[ii][s_jj].start;
tree stride = an_info[ii][s_jj].stride;
tree var = an_loop_info[s_jj].var;
tree start = cp_fold_convert (ptrdiff_type_node,
an_info[ii][s_jj].start);
tree stride = cp_fold_convert (ptrdiff_type_node,
an_info[ii][s_jj].stride);
tree var = cp_fold_convert (ptrdiff_type_node,
an_loop_info[s_jj].var);
/* If stride and start are of same type and the induction var
is not, convert induction variable to stride's type. */
if (TREE_TYPE (start) == TREE_TYPE (stride)
&& TREE_TYPE (stride) != TREE_TYPE (var))
{
st = start;
str = stride;
v = build_c_cast (loc, TREE_TYPE (str), var);
}
else if (TREE_TYPE (start) != TREE_TYPE (stride))
{
/* If we reach here, then the stride and start are of
different types, and so it doesn't really matter what
the induction variable type is, convert everything to
integer. The reason why we pick an integer
instead of something like size_t is because the stride
and length can be + or -. */
st = build_c_cast (loc, integer_type_node, start);
str = build_c_cast (loc, integer_type_node, stride);
v = build_c_cast (loc, integer_type_node, var);
}
else
{
st = start;
str = stride;
v = var;
}
ind_mult = build2 (MULT_EXPR, TREE_TYPE (v), v, str);
ind_incr = build2 (PLUS_EXPR, TREE_TYPE (v), st, ind_mult);
ind_mult = build2 (MULT_EXPR, TREE_TYPE (var), var, stride);
ind_incr = build2 (PLUS_EXPR, TREE_TYPE (var), start, ind_mult);
/* Array [ start_index + (induction_var * stride)] */
array_opr = grok_array_decl (loc, array_opr, ind_incr, false);
}
@ -192,7 +161,7 @@ replace_invariant_exprs (tree *node)
{
size_t ix = 0;
tree node_list = NULL_TREE;
tree t = NULL_TREE, new_var = NULL_TREE, new_node;
tree t = NULL_TREE, new_var = NULL_TREE;
struct inv_list data;
data.list_values = NULL;
@ -204,17 +173,18 @@ replace_invariant_exprs (tree *node)
{
node_list = push_stmt_list ();
for (ix = 0; vec_safe_iterate (data.list_values, ix, &t); ix++)
{
if (processing_template_decl || !TREE_TYPE (t))
new_var = build_min_nt_loc (EXPR_LOCATION (t), VAR_DECL, NULL_TREE,
NULL_TREE);
else
new_var = build_decl (EXPR_LOCATION (t), VAR_DECL, NULL_TREE,
TREE_TYPE (t));
gcc_assert (new_var != NULL_TREE && new_var != error_mark_node);
new_node = build_x_modify_expr (EXPR_LOCATION (t), new_var, NOP_EXPR,
t, tf_warning_or_error);
finish_expr_stmt (new_node);
{
/* Sometimes, when comma_expr has a function call in it, it will
typecast it to void. Find_inv_trees finds those nodes and so
if it void type, then don't bother creating a new var to hold
the return value. */
if (VOID_TYPE_P (TREE_TYPE (t)))
{
finish_expr_stmt (t);
new_var = void_zero_node;
}
else
new_var = get_temp_regvar (TREE_TYPE (t), t);
vec_safe_push (data.replacement, new_var);
}
cp_walk_tree (node, replace_inv_trees, (void *) &data, NULL);
@ -235,7 +205,6 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
tree new_var_type = NULL_TREE, func_parm, new_yes_expr, new_no_expr;
tree array_ind_value = NULL_TREE, new_no_ind, new_yes_ind, new_no_list;
tree new_yes_list, new_cond_expr, new_expr = NULL_TREE;
tree new_var_init = NULL_TREE, new_exp_init = NULL_TREE;
vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
size_t list_size = 0, rank = 0, ii = 0;
tree body, an_init, loop_with_init = alloc_stmt_list ();
@ -305,7 +274,7 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO:
case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO:
case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO:
new_var_type = integer_type_node;
new_var_type = boolean_type_node;
break;
case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
@ -334,24 +303,30 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
if (TREE_CODE ((*array_list)[ii]) == ARRAY_NOTATION_REF)
{
tree anode = (*array_list)[ii];
make_triplet_val_inv (location, &ARRAY_NOTATION_START (anode),
tf_warning_or_error);
make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (anode),
tf_warning_or_error);
make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (anode),
tf_warning_or_error);
make_triplet_val_inv (&ARRAY_NOTATION_START (anode));
make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (anode));
make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (anode));
}
cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info);
for (ii = 0; ii < rank; ii++)
{
an_loop_info[ii].var = build_decl (location, VAR_DECL, NULL_TREE,
TREE_TYPE (an_info[0][ii].start));
an_loop_info[ii].ind_init = build_x_modify_expr
(location, an_loop_info[ii].var, NOP_EXPR,
build_zero_cst (TREE_TYPE (an_loop_info[ii].var)),
tf_warning_or_error);
tree typ = ptrdiff_type_node;
/* In this place, we are using get_temp_regvar instead of
create_temporary_var if an_type is SEC_REDUCE_MAX/MIN_IND because
the array_ind_value depends on this value being initalized to 0. */
if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
|| an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND)
an_loop_info[ii].var = get_temp_regvar (typ, build_zero_cst (typ));
else
{
an_loop_info[ii].var = create_temporary_var (typ);
add_decl_expr (an_loop_info[ii].var);
}
an_loop_info[ii].ind_init =
build_x_modify_expr (location, an_loop_info[ii].var, INIT_EXPR,
build_zero_cst (typ), tf_warning_or_error);
}
array_operand = create_array_refs (location, an_info, an_loop_info,
list_size, rank);
replace_array_notations (&func_parm, true, array_list, array_operand);
@ -360,26 +335,9 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
TREE_TYPE (func_parm) = TREE_TYPE ((*array_list)[0]);
create_cmp_incr (location, &an_loop_info, rank, an_info, tf_warning_or_error);
if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
{
if (processing_template_decl)
*new_var = build_decl (location, VAR_DECL, NULL_TREE, new_var_type);
else
*new_var = create_tmp_var (new_var_type, NULL);
}
else
/* We do not require a new variable for mutating. The "identity value"
itself is the variable. */
*new_var = NULL_TREE;
if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
|| an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND)
{
array_ind_value = create_tmp_var (TREE_TYPE (func_parm), NULL);
gcc_assert (array_ind_value && (array_ind_value != error_mark_node));
DECL_INITIAL (array_ind_value) = NULL_TREE;
pushdecl (array_ind_value);
}
|| an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND)
array_ind_value = get_temp_regvar (TREE_TYPE (func_parm), func_parm);
array_op0 = (*array_operand)[0];
switch (an_type)
@ -394,35 +352,36 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
break;
case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO:
case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO:
code = (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO) ? EQ_EXPR
: NE_EXPR;
code = ((an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO) ? EQ_EXPR
: NE_EXPR);
init = build_zero_cst (new_var_type);
cond_init = build_one_cst (new_var_type);
comp_node = build_zero_cst (TREE_TYPE (func_parm));
break;
case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO:
case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO:
code = (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO) ? NE_EXPR
: EQ_EXPR;
code = ((an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO) ? NE_EXPR
: EQ_EXPR);
init = build_one_cst (new_var_type);
cond_init = build_zero_cst (new_var_type);
comp_node = build_zero_cst (TREE_TYPE (func_parm));
break;
case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX:
code = MAX_EXPR;
init = TYPE_MIN_VALUE (new_var_type) ? TYPE_MIN_VALUE (new_var_type)
: func_parm;
init = (TYPE_MIN_VALUE (new_var_type) ? TYPE_MIN_VALUE (new_var_type)
: func_parm);
break;
case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN:
code = MIN_EXPR;
init = TYPE_MAX_VALUE (new_var_type) ? TYPE_MAX_VALUE (new_var_type)
: func_parm;
init = (TYPE_MAX_VALUE (new_var_type) ? TYPE_MAX_VALUE (new_var_type)
: func_parm);
break;
case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
code = an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND ? LE_EXPR
: GE_EXPR;
code = (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND ? LE_EXPR
: GE_EXPR);
init = an_loop_info[0].var;
break;
case BUILT_IN_CILKPLUS_SEC_REDUCE:
init = identity_value;
break;
@ -433,9 +392,11 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
gcc_unreachable ();
}
if (init)
new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR, init,
tf_warning_or_error);
if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
*new_var = get_temp_regvar (new_var_type, init);
else
*new_var = NULL_TREE;
switch (an_type)
{
case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD:
@ -470,8 +431,6 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
break;
case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
new_exp_init = build_x_modify_expr (location, array_ind_value, NOP_EXPR,
func_parm, tf_warning_or_error);
new_yes_expr = build_x_modify_expr (location, array_ind_value, NOP_EXPR,
func_parm, tf_warning_or_error);
new_no_expr = build_x_modify_expr (location, array_ind_value, NOP_EXPR,
@ -521,21 +480,8 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
default:
gcc_unreachable ();
}
/* The reason we are putting initial variable twice is because the
new exp init below depends on this value being initialized. */
for (ii = 0; ii < rank; ii++)
finish_expr_stmt (an_loop_info[ii].ind_init);
if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
finish_expr_stmt (new_var_init);
if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
|| an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND)
finish_expr_stmt (new_exp_init);
an_init = pop_stmt_list (an_init);
append_to_statement_list_force (an_init, &loop_with_init);
append_to_statement_list (an_init, &loop_with_init);
body = new_expr;
for (ii = 0; ii < rank; ii++)
@ -545,7 +491,7 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
an_loop_info[ii].incr, body);
body = pop_stmt_list (new_loop);
}
append_to_statement_list_force (body, &loop_with_init);
append_to_statement_list (body, &loop_with_init);
an_info.release ();
an_loop_info.release ();
@ -634,10 +580,7 @@ expand_an_in_modify_expr (location_t location, tree lhs,
return an_init;
}
else
{
pop_stmt_list (an_init);
return NULL_TREE;
}
gcc_unreachable ();
}
/* If for some reason location is not set, then find if LHS or RHS has
@ -659,8 +602,6 @@ expand_an_in_modify_expr (location_t location, tree lhs,
if (lhs_rank == 0 && rhs_rank != 0)
{
if (location == UNKNOWN_LOCATION && EXPR_HAS_LOCATION (rhs))
location = EXPR_LOCATION (rhs);
error_at (location, "%qD cannot be scalar when %qD is not", lhs, rhs);
return error_mark_node;
}
@ -675,17 +616,17 @@ expand_an_in_modify_expr (location_t location, tree lhs,
for (ii = 0; ii < lhs_list_size; ii++)
{
tree anode = (*lhs_list)[ii];
make_triplet_val_inv (location, &ARRAY_NOTATION_START (anode), complain);
make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (anode), complain);
make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (anode), complain);
make_triplet_val_inv (&ARRAY_NOTATION_START (anode));
make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (anode));
make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (anode));
}
for (ii = 0; ii < rhs_list_size; ii++)
if ((*rhs_list)[ii] && TREE_CODE ((*rhs_list)[ii]) == ARRAY_NOTATION_REF)
{
tree aa = (*rhs_list)[ii];
make_triplet_val_inv (location, &ARRAY_NOTATION_START (aa), complain);
make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (aa), complain);
make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (aa), complain);
make_triplet_val_inv (&ARRAY_NOTATION_START (aa));
make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (aa));
make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (aa));
}
lhs_an_loop_info.safe_grow_cleared (lhs_rank);
@ -705,31 +646,29 @@ expand_an_in_modify_expr (location_t location, tree lhs,
pop_stmt_list (an_init);
return error_mark_node;
}
tree rhs_len = (rhs_list_size > 0 && rhs_rank > 0) ?
rhs_an_info[0][0].length : NULL_TREE;
tree lhs_len = (lhs_list_size > 0 && lhs_rank > 0) ?
lhs_an_info[0][0].length : NULL_TREE;
tree rhs_len = ((rhs_list_size > 0 && rhs_rank > 0) ?
rhs_an_info[0][0].length : NULL_TREE);
tree lhs_len = ((lhs_list_size > 0 && lhs_rank > 0) ?
lhs_an_info[0][0].length : NULL_TREE);
if (lhs_list_size > 0 && rhs_list_size > 0 && lhs_rank > 0 && rhs_rank > 0
&& TREE_CODE (lhs_len) == INTEGER_CST && rhs_len
&& TREE_CODE (rhs_len) == INTEGER_CST)
{
HOST_WIDE_INT l_length = int_cst_value (lhs_len);
HOST_WIDE_INT r_length = int_cst_value (rhs_len);
if (absu_hwi (l_length) != absu_hwi (r_length))
{
error_at (location, "length mismatch between LHS and RHS");
pop_stmt_list (an_init);
return error_mark_node;
}
&& TREE_CODE (rhs_len) == INTEGER_CST
&& !tree_int_cst_equal (rhs_len, lhs_len))
{
error_at (location, "length mismatch between LHS and RHS");
pop_stmt_list (an_init);
return error_mark_node;
}
for (ii = 0; ii < lhs_rank; ii++)
if (lhs_an_info[0][ii].start && TREE_TYPE (lhs_an_info[0][ii].start))
lhs_an_loop_info[ii].var =
build_decl (location, VAR_DECL, NULL_TREE,
TREE_TYPE (lhs_an_info[0][ii].start));
else
lhs_an_loop_info[ii].var = build_decl (location, VAR_DECL, NULL_TREE,
integer_type_node);
for (ii = 0; ii < lhs_rank; ii++)
{
tree typ = ptrdiff_type_node;
lhs_an_loop_info[ii].var = create_temporary_var (typ);
add_decl_expr (lhs_an_loop_info[ii].var);
lhs_an_loop_info[ii].ind_init = build_x_modify_expr
(location, lhs_an_loop_info[ii].var, INIT_EXPR, build_zero_cst (typ),
complain);
}
if (rhs_list_size > 0)
{
rhs_array_operand = fix_sec_implicit_args (location, rhs_list,
@ -743,24 +682,15 @@ expand_an_in_modify_expr (location_t location, tree lhs,
rhs_list = NULL;
extract_array_notation_exprs (rhs, true, &rhs_list);
rhs_list_size = vec_safe_length (rhs_list);
for (ii = 0; ii < lhs_rank; ii++)
if (lhs_an_info[0][ii].is_vector)
{
lhs_an_loop_info[ii].ind_init = build_x_modify_expr
(location, lhs_an_loop_info[ii].var, NOP_EXPR,
build_zero_cst (TREE_TYPE (lhs_an_loop_info[ii].var)), complain);
}
for (ii = 0; ii < rhs_rank; ii++)
{
/* When we have a polynomial, we assume that the indices are of type
integer. */
rhs_an_loop_info[ii].var =
build_decl (location, VAR_DECL, NULL_TREE,
TREE_TYPE (rhs_an_info[0][ii].start));
tree typ = ptrdiff_type_node;
rhs_an_loop_info[ii].var = create_temporary_var (typ);
add_decl_expr (rhs_an_loop_info[ii].var);
rhs_an_loop_info[ii].ind_init = build_x_modify_expr
(location, rhs_an_loop_info[ii].var, NOP_EXPR,
build_zero_cst (TREE_TYPE (rhs_an_loop_info[ii].var)), complain);
(location, rhs_an_loop_info[ii].var, INIT_EXPR, build_zero_cst (typ),
complain);
}
if (lhs_rank)
@ -809,12 +739,12 @@ expand_an_in_modify_expr (location_t location, tree lhs,
else if (ii < lhs_rank && ii >= rhs_rank)
cond_expr[ii] = lhs_an_loop_info[ii].cmp;
else
/* No need to compare ii < rhs_rank && ii >= lhs_rank because valid Array
notation expression cannot RHS's rank cannot be greater than LHS. */
/* No need to compare ii < rhs_rank && ii >= lhs_rank because in a valid
Array notation expression, rank of RHS cannot be greater than LHS. */
gcc_unreachable ();
an_init = pop_stmt_list (an_init);
append_to_statement_list_force (an_init, &loop_with_init);
append_to_statement_list (an_init, &loop_with_init);
body = array_expr;
for (ii = 0; ii < MAX (lhs_rank, rhs_rank); ii++)
{
@ -824,17 +754,13 @@ expand_an_in_modify_expr (location_t location, tree lhs,
if (lhs_rank)
{
append_to_statement_list_force (lhs_an_loop_info[ii].ind_init,
&init_list);
append_to_statement_list_force (lhs_an_loop_info[ii].incr,
&incr_list);
append_to_statement_list (lhs_an_loop_info[ii].ind_init, &init_list);
append_to_statement_list (lhs_an_loop_info[ii].incr, &incr_list);
}
if (rhs_rank)
{
append_to_statement_list_force (rhs_an_loop_info[ii].ind_init,
&init_list);
append_to_statement_list_force (rhs_an_loop_info[ii].incr,
&incr_list);
append_to_statement_list (rhs_an_loop_info[ii].ind_init, &init_list);
append_to_statement_list (rhs_an_loop_info[ii].incr, &incr_list);
}
create_an_loop (init_list, cond_expr[ii], incr_list, body);
body = pop_stmt_list (new_loop);
@ -867,7 +793,6 @@ cp_expand_cond_array_notations (tree orig_stmt)
tree an_init, body, stmt = NULL_TREE;
tree builtin_loop, new_var = NULL_TREE;
tree loop_with_init = alloc_stmt_list ();
tsubst_flags_t complain = tf_warning_or_error;
location_t location = UNKNOWN_LOCATION;
vec<vec<an_parts> > an_info = vNULL;
vec<an_loop_parts> an_loop_info = vNULL;
@ -884,13 +809,17 @@ cp_expand_cond_array_notations (tree orig_stmt)
|| find_rank (EXPR_LOCATION (no_expr), no_expr, no_expr, true,
&no_rank))
return error_mark_node;
if (cond_rank != 0 && cond_rank != yes_rank && yes_rank != 0)
/* If the condition has a zero rank, then handle array notations in body
seperately. */
if (cond_rank == 0)
return orig_stmt;
if (cond_rank != yes_rank && yes_rank != 0)
{
error_at (EXPR_LOCATION (yes_expr), "rank mismatch with controlling"
" expression of parent if-statement");
return error_mark_node;
}
else if (cond_rank != 0 && cond_rank != no_rank && no_rank != 0)
else if (cond_rank != no_rank && no_rank != 0)
{
error_at (EXPR_LOCATION (no_expr), "rank mismatch with controlling "
"expression of parent if-statement");
@ -911,13 +840,17 @@ cp_expand_cond_array_notations (tree orig_stmt)
&& !find_rank (EXPR_LOCATION (no_expr), no_expr, no_expr, true,
&no_rank)))
return error_mark_node;
if (cond_rank != 0 && cond_rank != yes_rank && yes_rank != 0)
/* Same reasoning as for COND_EXPR. */
if (cond_rank == 0)
return orig_stmt;
else if (cond_rank != yes_rank && yes_rank != 0)
{
error_at (EXPR_LOCATION (yes_expr), "rank mismatch with controlling"
" expression of parent if-statement");
return error_mark_node;
}
else if (cond_rank != 0 && cond_rank != no_rank && no_rank != 0)
else if (cond_rank != no_rank && no_rank != 0)
{
error_at (EXPR_LOCATION (no_expr), "rank mismatch with controlling "
"expression of parent if-statement");
@ -949,11 +882,11 @@ cp_expand_cond_array_notations (tree orig_stmt)
vec_safe_push (new_var_list, new_var);
replace_array_notations (&orig_stmt, false, sub_list,
new_var_list);
append_to_statement_list_force (builtin_loop, &stmt);
append_to_statement_list (builtin_loop, &stmt);
}
}
}
append_to_statement_list_force (orig_stmt, &stmt);
append_to_statement_list (orig_stmt, &stmt);
rank = 0;
array_list = NULL;
if (!find_rank (EXPR_LOCATION (stmt), stmt, stmt, true, &rank))
@ -977,37 +910,28 @@ cp_expand_cond_array_notations (tree orig_stmt)
for (ii = 0; ii < list_size; ii++)
{
tree anode = (*array_list)[ii];
make_triplet_val_inv (location, &ARRAY_NOTATION_START (anode), complain);
make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (anode), complain);
make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (anode), complain);
make_triplet_val_inv (&ARRAY_NOTATION_START (anode));
make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (anode));
make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (anode));
}
cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info);
for (ii = 0; ii < rank; ii++)
if (TREE_TYPE (an_info[0][ii].start)
&& TREE_CODE (TREE_TYPE (an_info[0][ii].start)) != TEMPLATE_TYPE_PARM)
{
an_loop_info[ii].var = build_decl (location, VAR_DECL, NULL_TREE,
TREE_TYPE (an_info[0][ii].start));
an_loop_info[ii].ind_init = build_x_modify_expr
(location, an_loop_info[ii].var, NOP_EXPR,
build_zero_cst (TREE_TYPE (an_loop_info[ii].var)),
tf_warning_or_error);
}
else
{
an_loop_info[ii].var = build_min_nt_loc (location, VAR_DECL,
NULL_TREE, NULL_TREE);
an_loop_info[ii].ind_init =
build_x_modify_expr (location, an_loop_info[ii].var, NOP_EXPR,
integer_zero_node, tf_warning_or_error);
}
for (ii = 0; ii < rank; ii++)
{
tree typ = ptrdiff_type_node;
an_loop_info[ii].var = create_temporary_var (typ);
add_decl_expr (an_loop_info[ii].var);
an_loop_info[ii].ind_init =
build_x_modify_expr (location, an_loop_info[ii].var, INIT_EXPR,
build_zero_cst (typ), tf_warning_or_error);
}
array_operand = create_array_refs (location, an_info, an_loop_info,
list_size, rank);
replace_array_notations (&stmt, true, array_list, array_operand);
create_cmp_incr (location, &an_loop_info, rank, an_info, tf_warning_or_error);
an_init = pop_stmt_list (an_init);
append_to_statement_list_force (an_init, &loop_with_init);
append_to_statement_list (an_init, &loop_with_init);
body = stmt;
for (ii = 0; ii < rank; ii++)
@ -1017,7 +941,7 @@ cp_expand_cond_array_notations (tree orig_stmt)
an_loop_info[ii].incr, body);
body = pop_stmt_list (new_loop);
}
append_to_statement_list_force (body, &loop_with_init);
append_to_statement_list (body, &loop_with_init);
an_info.release ();
an_loop_info.release ();
@ -1062,14 +986,14 @@ expand_unary_array_notation_exprs (tree orig_stmt)
{
vec<tree, va_gc> *sub_list = NULL, *new_var_list = NULL;
stmt = alloc_stmt_list ();
append_to_statement_list_force (builtin_loop, &stmt);
append_to_statement_list (builtin_loop, &stmt);
vec_safe_push (sub_list, list_node);
vec_safe_push (new_var_list, new_var);
replace_array_notations (&orig_stmt, false, sub_list, new_var_list);
}
}
if (stmt != NULL_TREE)
append_to_statement_list_force (finish_expr_stmt (orig_stmt), &stmt);
append_to_statement_list (finish_expr_stmt (orig_stmt), &stmt);
else
stmt = orig_stmt;
rank = 0;
@ -1089,22 +1013,19 @@ expand_unary_array_notation_exprs (tree orig_stmt)
for (ii = 0; ii < list_size; ii++)
{
tree array_node = (*array_list)[ii];
make_triplet_val_inv (location, &ARRAY_NOTATION_START (array_node),
tf_warning_or_error);
make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (array_node),
tf_warning_or_error);
make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (array_node),
tf_warning_or_error);
make_triplet_val_inv (&ARRAY_NOTATION_START (array_node));
make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (array_node));
make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (array_node));
}
cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info);
for (ii = 0; ii < rank; ii++)
{
an_loop_info[ii].var = build_decl (location, VAR_DECL, NULL_TREE,
TREE_TYPE (an_info[0][ii].start));
tree typ = ptrdiff_type_node;
an_loop_info[ii].var = create_temporary_var (typ);
add_decl_expr (an_loop_info[ii].var);
an_loop_info[ii].ind_init = build_x_modify_expr
(location, an_loop_info[ii].var, NOP_EXPR,
build_zero_cst (TREE_TYPE (an_loop_info[ii].var)),
(location, an_loop_info[ii].var, INIT_EXPR, build_zero_cst (typ),
tf_warning_or_error);
}
array_operand = create_array_refs (location, an_info, an_loop_info,
@ -1113,7 +1034,7 @@ expand_unary_array_notation_exprs (tree orig_stmt)
create_cmp_incr (location, &an_loop_info, rank, an_info, tf_warning_or_error);
an_init = pop_stmt_list (an_init);
append_to_statement_list_force (an_init, &loop_with_init);
append_to_statement_list (an_init, &loop_with_init);
body = stmt;
for (ii = 0; ii < rank; ii++)
@ -1123,7 +1044,7 @@ expand_unary_array_notation_exprs (tree orig_stmt)
an_loop_info[ii].incr, body);
body = pop_stmt_list (new_loop);
}
append_to_statement_list_force (body, &loop_with_init);
append_to_statement_list (body, &loop_with_init);
an_info.release ();
an_loop_info.release ();
@ -1139,21 +1060,35 @@ static tree
expand_return_expr (tree expr)
{
tree new_mod_list, new_var, new_mod, retval_expr;
size_t rank = 0;
location_t loc = EXPR_LOCATION (expr);
if (TREE_CODE (expr) != RETURN_EXPR)
return expr;
if (!find_rank (loc, expr, expr, false, &rank))
return error_mark_node;
location_t loc = EXPR_LOCATION (expr);
new_mod_list = alloc_stmt_list ();
/* If the return expression contains array notations, then flag it as
error. */
if (rank >= 1)
{
error_at (loc, "array notation expression cannot be used as a return "
"value");
return error_mark_node;
}
new_mod_list = push_stmt_list ();
retval_expr = TREE_OPERAND (expr, 0);
new_var = build_decl (loc, VAR_DECL, NULL_TREE, TREE_TYPE (retval_expr));
new_var = create_temporary_var (TREE_TYPE (retval_expr));
add_decl_expr (new_var);
new_mod = expand_an_in_modify_expr (loc, new_var, NOP_EXPR,
TREE_OPERAND (retval_expr, 1),
tf_warning_or_error);
TREE_OPERAND (retval_expr, 1),
tf_warning_or_error);
TREE_OPERAND (retval_expr, 1) = new_var;
TREE_OPERAND (expr, 0) = retval_expr;
append_to_statement_list_force (new_mod, &new_mod_list);
append_to_statement_list_force (expr, &new_mod_list);
add_stmt (new_mod);
add_stmt (expr);
new_mod_list = pop_stmt_list (new_mod_list);
return new_mod_list;
}
@ -1290,19 +1225,21 @@ expand_array_notation_exprs (tree t)
else
t = expand_array_notation_exprs (t);
return t;
case SWITCH_EXPR:
t = cp_expand_cond_array_notations (t);
if (TREE_CODE (t) == SWITCH_EXPR)
SWITCH_BODY (t) = expand_array_notation_exprs (SWITCH_BODY (t));
else
t = expand_array_notation_exprs (t);
return t;
case FOR_STMT:
case FOR_STMT:
if (contains_array_notation_expr (FOR_COND (t)))
{
error_at (EXPR_LOCATION (FOR_COND (t)),
"array notation cannot be used in a condition for "
"a for-loop");
return error_mark_node;
}
/* FIXME: Add a check for CILK_FOR_STMT here when we add Cilk tasking
keywords. */
if (TREE_CODE (t) == FOR_STMT)
FOR_BODY (t) = expand_array_notation_exprs (FOR_BODY (t));
{
FOR_BODY (t) = expand_array_notation_exprs (FOR_BODY (t));
FOR_EXPR (t) = expand_array_notation_exprs (FOR_EXPR (t));
}
else
t = expand_array_notation_exprs (t);
return t;
@ -1322,44 +1259,39 @@ expand_array_notation_exprs (tree t)
t = expand_array_notation_exprs (t);
return t;
case SWITCH_STMT:
t = cp_expand_cond_array_notations (t);
/* If the above function added some extra instructions above the original
switch statement, then we can't assume it is still SWITCH_STMT so we
have to check again. */
if (TREE_CODE (t) == SWITCH_STMT)
if (contains_array_notation_expr (SWITCH_STMT_COND (t)))
{
if (SWITCH_STMT_BODY (t))
SWITCH_STMT_BODY (t) =
expand_array_notation_exprs (SWITCH_STMT_BODY (t));
error_at (EXPR_LOCATION (SWITCH_STMT_COND (t)),
"array notation cannot be used as a condition for "
"switch statement");
return error_mark_node;
}
else
t = expand_array_notation_exprs (t);
if (SWITCH_STMT_BODY (t))
SWITCH_STMT_BODY (t) =
expand_array_notation_exprs (SWITCH_STMT_BODY (t));
return t;
case WHILE_STMT:
t = cp_expand_cond_array_notations (t);
/* If the above function added some extra instructions above the original
while statement, then we can't assume it is still WHILE_STMTso we
have to check again. */
if (TREE_CODE (t) == WHILE_STMT)
if (contains_array_notation_expr (WHILE_COND (t)))
{
if (WHILE_BODY (t))
WHILE_BODY (t) = expand_array_notation_exprs (WHILE_BODY (t));
if (EXPR_LOCATION (WHILE_COND (t)) != UNKNOWN_LOCATION)
loc = EXPR_LOCATION (WHILE_COND (t));
error_at (loc, "array notation cannot be used as a condition for "
"while statement");
return error_mark_node;
}
else
t = expand_array_notation_exprs (t);
if (WHILE_BODY (t))
WHILE_BODY (t) = expand_array_notation_exprs (WHILE_BODY (t));
return t;
case DO_STMT:
t = cp_expand_cond_array_notations (t);
/* If the above function added some extra instructions above the original
do-while statement, then we can't assume it is still DO_STMT so we
have to check again. */
if (TREE_CODE (t) == DO_STMT)
{
if (DO_BODY (t))
DO_BODY (t) = expand_array_notation_exprs (DO_BODY (t));
if (contains_array_notation_expr (DO_COND (t)))
{
error_at (EXPR_LOCATION (DO_COND (t)),
"array notation cannot be used as a condition for a "
"do-while statement");
return error_mark_node;
}
else
t = expand_array_notation_exprs (t);
if (DO_BODY (t))
DO_BODY (t) = expand_array_notation_exprs (DO_BODY (t));
return t;
default:
if (is_expr)
@ -1380,59 +1312,66 @@ expand_array_notation_exprs (tree t)
return t;
}
/* Given the base of an array (ARRAY), the START_INDEX, the number of elements
to be accessed (LENGTH) and the STRIDE, construct an ARRAY_NOTATION_REF tree
of type TYPE and return it. Restrictions on START_INDEX, LENGTH and STRIDE
are the same as that of index field passed into ARRAY_REF. The only
additional restriction is that, unlike index in ARRAY_REF, stride, length
and start_index cannot contain array notations. */
/* Given the base of an array (ARRAY), the START (start_index), the number of
elements to be accessed (LENGTH) and the STRIDE, construct an
ARRAY_NOTATION_REF tree of type TYPE and return it. Restrictions on START,
LENGTH and STRIDE are the same as that of index field passed into ARRAY_REF.
The only additional restriction is that, unlike index in ARRAY_REF, stride,
length and start_index cannot contain array notations. */
tree
build_array_notation_ref (location_t loc, tree array, tree start_index,
tree length, tree stride, tree type)
build_array_notation_ref (location_t loc, tree array, tree start, tree length,
tree stride, tree type)
{
tree array_ntn_expr = NULL_TREE;
/* If we enter the then-case of the if-statement below, we have hit a case
like this: ARRAY [:]. */
if (!start && !length)
{
if (TREE_CODE (type) != ARRAY_TYPE)
{
error_at (loc, "start-index and length fields necessary for "
"using array notation in pointers or records");
return error_mark_node;
}
tree domain = TYPE_DOMAIN (type);
if (!domain)
{
error_at (loc, "start-index and length fields necessary for "
"using array notation with array of unknown bound");
return error_mark_node;
}
start = cp_fold_convert (ptrdiff_type_node, TYPE_MINVAL (domain));
length = size_binop (PLUS_EXPR, TYPE_MAXVAL (domain), size_one_node);
length = cp_fold_convert (ptrdiff_type_node, length);
}
if (!stride)
stride = build_one_cst (ptrdiff_type_node);
/* When dealing with templates, do the type checking at a later time. */
if (processing_template_decl || !type)
{
if (!type && TREE_TYPE (array))
type = TREE_TYPE (array);
array_ntn_expr = build_min_nt_loc (loc, ARRAY_NOTATION_REF, array,
start_index, length, stride, type,
NULL_TREE);
TREE_TYPE (array_ntn_expr) = type;
}
if (!stride)
{
if (TREE_CONSTANT (start_index) && TREE_CONSTANT (length)
&& TREE_CODE (start_index) != VAR_DECL
&& TREE_CODE (length) != VAR_DECL
&& tree_int_cst_lt (length, start_index))
stride = build_int_cst (TREE_TYPE (start_index), -1);
else
stride = build_int_cst (TREE_TYPE (start_index), 1);
/* When dealing with templates, triplet type-checking will be done in pt.c
after type substitution. */
if (processing_template_decl
&& (type_dependent_expression_p (array)
|| type_dependent_expression_p (length)
|| type_dependent_expression_p (start)
|| type_dependent_expression_p (stride)))
array_ntn_expr = build_min_nt_loc (loc, ARRAY_NOTATION_REF, array, start,
length, stride, NULL_TREE);
else
{
if (!cilkplus_an_triplet_types_ok_p (loc, start, length, stride, type))
return error_mark_node;
array_ntn_expr = build4 (ARRAY_NOTATION_REF, NULL_TREE, array, start,
length, stride);
}
if (TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == POINTER_TYPE)
TREE_TYPE (array_ntn_expr) = TREE_TYPE (type);
else
gcc_unreachable ();
if (!cilkplus_an_triplet_types_ok_p (loc, start_index, length, stride, type))
return error_mark_node;
if (!processing_template_decl)
{
array_ntn_expr = build4 (ARRAY_NOTATION_REF, NULL_TREE, NULL_TREE,
NULL_TREE, NULL_TREE, NULL_TREE);
ARRAY_NOTATION_ARRAY (array_ntn_expr) = array;
ARRAY_NOTATION_START (array_ntn_expr) = start_index;
ARRAY_NOTATION_LENGTH (array_ntn_expr) = length;
ARRAY_NOTATION_STRIDE (array_ntn_expr) = stride;
if (type && (TREE_CODE (type) == ARRAY_TYPE
|| TREE_CODE (type) == POINTER_TYPE))
TREE_TYPE (array_ntn_expr) = TREE_TYPE (type);
else
TREE_TYPE (array_ntn_expr) = type;
}
SET_EXPR_LOCATION (array_ntn_expr, loc);
return array_ntn_expr;
}
@ -1462,20 +1401,9 @@ cilkplus_an_triplet_types_ok_p (location_t loc, tree start_index, tree length,
}
if (!TREE_CODE (type) == FUNCTION_TYPE)
{
error_at (loc, "array notations cannot be used with function type");
error_at (loc, "array notation cannot be used with function type");
return false;
}
while (type && (TREE_CODE (type) == POINTER_TYPE
|| TREE_CODE (type) == ARRAY_TYPE))
{
type = TREE_TYPE (type);
if (type && TREE_CODE (type) == FUNCTION_TYPE)
{
error_at (loc, "array notations cannot be used with function pointer"
" arrays");
return false;
}
}
if (!find_rank (loc, start_index, start_index, false, &start_rank)
|| !find_rank (loc, length, length, false, &length_rank)
|| !find_rank (loc, stride, stride, false, &stride_rank))

View File

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

View File

@ -4974,6 +4974,7 @@ extern bool pragma_java_exceptions;
/* in call.c */
extern bool check_dtor_name (tree, tree);
bool magic_varargs_p (tree);
extern tree build_conditional_expr (location_t, tree, tree, tree,
tsubst_flags_t);

View File

@ -6062,41 +6062,31 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
return error_mark_node;
}
/* This function parses Cilk Plus array notations. The starting index is
passed in INIT_INDEX and the array name is passed in ARRAY_VALUE. If the
INIT_INDEX is NULL, then we have special case were the entire array is
accessed (e.g. A[:]). The return value of this function is a tree node
called VALUE_TREE of type ARRAY_NOTATION_REF. If some error occurred it
returns error_mark_node. */
/* This function parses Cilk Plus array notations. If a normal array expr. is
parsed then the array index is passed back to the caller through *INIT_INDEX
and the function returns a NULL_TREE. If array notation expr. is parsed,
then *INIT_INDEX is ignored by the caller and the function returns
a tree of type ARRAY_NOTATION_REF. If some error occurred it returns
error_mark_node. */
static tree
cp_parser_array_notation (location_t loc, cp_parser *parser, tree init_index,
cp_parser_array_notation (location_t loc, cp_parser *parser, tree *init_index,
tree array_value)
{
cp_token *token = NULL;
tree start_index = NULL_TREE, length_index = NULL_TREE, stride = NULL_TREE;
tree value_tree, type, array_type, array_type_domain;
double_int x;
bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
tree length_index, stride = NULL_TREE, value_tree, array_type;
if (!array_value || array_value == error_mark_node)
{
cp_parser_skip_to_end_of_statement (parser);
return error_mark_node;
}
array_type = TREE_TYPE (array_value);
if (processing_template_decl)
{
array_type = TREE_TYPE (array_value);
type = TREE_TYPE (array_type);
}
else
{
array_type = TREE_TYPE (array_value);
gcc_assert (array_type);
type = array_type;
}
bool saved_colon_corrects = parser->colon_corrects_to_scope_p;
parser->colon_corrects_to_scope_p = false;
token = cp_lexer_peek_token (parser->lexer);
if (!token)
{
cp_parser_error (parser, "expected %<:%> or numeral");
@ -6104,125 +6094,57 @@ cp_parser_array_notation (location_t loc, cp_parser *parser, tree init_index,
}
else if (token->type == CPP_COLON)
{
if (!init_index)
{
/* If we are here, then we have a case like this A[:]. */
cp_lexer_consume_token (parser->lexer);
if (cp_lexer_peek_token (parser->lexer)->type != CPP_CLOSE_SQUARE)
{
cp_parser_error (parser, "expected %<]%>");
cp_parser_skip_to_end_of_statement (parser);
return error_mark_node;
}
if (TREE_CODE (array_type) == RECORD_TYPE
|| TREE_CODE (array_type) == POINTER_TYPE)
{
error_at (loc, "start-index and length fields necessary for "
"using array notations in pointers or records");
cp_parser_skip_to_end_of_statement (parser);
return error_mark_node;
}
if (TREE_CODE (array_type) == ARRAY_TYPE)
{
tree subtype = TREE_TYPE (array_type);
while (subtype && TREE_CODE (subtype) == POINTER_TYPE)
{
/* This could be a function ptr. If so, then emit error. */
subtype = TREE_TYPE (subtype);
if (subtype && TREE_CODE (subtype) == FUNCTION_TYPE)
{
error_at (loc, "array notations cannot be used with"
" function pointer arrays");
cp_parser_skip_to_end_of_statement (parser);
return error_mark_node;
}
}
}
array_type_domain = TYPE_DOMAIN (array_type);
if (!array_type_domain)
{
error_at (loc, "start-index and length fields necessary for "
"using array notations in dimensionless arrays");
cp_parser_skip_to_end_of_statement (parser);
return error_mark_node;
}
start_index = TYPE_MINVAL (array_type_domain);
start_index = fold_build1 (CONVERT_EXPR, ptrdiff_type_node,
start_index);
x = TREE_INT_CST (TYPE_MAXVAL (array_type_domain));
x.low++;
length_index = double_int_to_tree (integer_type_node, x);
length_index = fold_build1 (CONVERT_EXPR, ptrdiff_type_node,
length_index);
stride = build_int_cst (integer_type_node, 1);
stride = fold_build1 (CONVERT_EXPR, ptrdiff_type_node, stride);
}
else if (init_index != error_mark_node)
{
/* If we hare here, then there are 2 possibilities:
1. Array [ EXPR : EXPR ]
2. Array [ EXPR : EXPR : EXPR ]
*/
start_index = init_index;
cp_lexer_consume_token (parser->lexer);
saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
/* The ':' is used in array notation. Thus compiler cannot do scope
correction automatically. */
parser->colon_corrects_to_scope_p = false;
length_index = cp_parser_expression (parser, false, NULL);
parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
if (!length_index || length_index == error_mark_node)
cp_parser_skip_to_end_of_statement (parser);
if (cp_lexer_peek_token (parser->lexer)->type == CPP_COLON)
{
cp_lexer_consume_token (parser->lexer);
saved_colon_corrects_to_scope_p =
parser->colon_corrects_to_scope_p;
/* Disable correcting single colon correcting to scope. */
parser->colon_corrects_to_scope_p = false;
stride = cp_parser_expression (parser, false, NULL);
parser->colon_corrects_to_scope_p =
saved_colon_corrects_to_scope_p;
if (!stride || stride == error_mark_node)
{
cp_parser_skip_to_end_of_statement (parser);
if (cp_lexer_peek_token (parser->lexer)->type
== CPP_CLOSE_SQUARE)
cp_lexer_consume_token (parser->lexer);
}
}
else
stride = build_one_cst (integer_type_node);
}
else
/* Consume the ':'. */
cp_lexer_consume_token (parser->lexer);
/* If we are here, then we have a case like this A[:]. */
if (cp_lexer_peek_token (parser->lexer)->type != CPP_CLOSE_SQUARE)
{
cp_parser_error (parser, "expected %<]%>");
cp_parser_skip_to_end_of_statement (parser);
return error_mark_node;
}
*init_index = NULL_TREE;
stride = NULL_TREE;
length_index = NULL_TREE;
}
if (start_index == error_mark_node || length_index == error_mark_node
|| stride == error_mark_node || !start_index || !length_index
|| !stride)
else
{
/* If we are here, then there are three valid possibilities:
1. ARRAY [ EXP ]
2. ARRAY [ EXP : EXP ]
3. ARRAY [ EXP : EXP : EXP ] */
*init_index = cp_parser_expression (parser, false, NULL);
if (cp_lexer_peek_token (parser->lexer)->type != CPP_COLON)
{
/* This indicates that we have a normal array expression. */
parser->colon_corrects_to_scope_p = saved_colon_corrects;
return NULL_TREE;
}
/* Consume the ':'. */
cp_lexer_consume_token (parser->lexer);
length_index = cp_parser_expression (parser, false, NULL);
if (cp_lexer_peek_token (parser->lexer)->type == CPP_COLON)
{
cp_lexer_consume_token (parser->lexer);
stride = cp_parser_expression (parser, false, NULL);
}
}
parser->colon_corrects_to_scope_p = saved_colon_corrects;
if (*init_index == error_mark_node || length_index == error_mark_node
|| stride == error_mark_node)
{
if (cp_lexer_peek_token (parser->lexer)->type == CPP_CLOSE_SQUARE)
cp_lexer_consume_token (parser->lexer);
return error_mark_node;
}
cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
/* We fold all 3 of the values to make things easier when we transform
them later. */
start_index = fold (start_index);
length_index = fold (length_index);
stride = fold (stride);
value_tree = build_array_notation_ref (input_location, array_value,
start_index, length_index, stride,
type);
value_tree = build_array_notation_ref (loc, array_value, *init_index,
length_index, stride, array_type);
return value_tree;
}
@ -6241,84 +6163,68 @@ cp_parser_postfix_open_square_expression (cp_parser *parser,
bool for_offsetof,
bool decltype_p)
{
tree index;
tree index = NULL_TREE;
location_t loc = cp_lexer_peek_token (parser->lexer)->location;
/* Consume the `[' token. */
cp_lexer_consume_token (parser->lexer);
if (flag_enable_cilkplus
&& cp_lexer_peek_token (parser->lexer)->type == CPP_COLON)
/* If we are here, then we have something like this:
ARRAY[:]
*/
postfix_expression = cp_parser_array_notation (loc, parser, NULL_TREE,
postfix_expression);
/* Parse the index expression. */
/* ??? For offsetof, there is a question of what to allow here. If
offsetof is not being used in an integral constant expression context,
then we *could* get the right answer by computing the value at runtime.
If we are in an integral constant expression context, then we might
could accept any constant expression; hard to say without analysis.
Rather than open the barn door too wide right away, allow only integer
constant expressions here. */
if (for_offsetof)
index = cp_parser_constant_expression (parser, false, NULL);
else
{
/* Here are have these options:
1. ARRAY[EXPR] -- This is the normal array call.
2. ARRAY[EXPR : EXPR] -- Array notation expr with default stride
of 1.
3. ARRAY[EXPR : EXPR : EXPR] -- Array Notation with userdefined stride.
4. Array[Braced List] -- This is handled by braced list.
*/
/* Parse the index expression. */
/* ??? For offsetof, there is a question of what to allow here. If
offsetof is not being used in an integral constant expression context,
then we *could* get the right answer by computing the value at runtime.
If we are in an integral constant expression context, then we might
could accept any constant expression; hard to say without analysis.
Rather than open the barn door too wide right away, allow only integer
constant expressions here. */
if (for_offsetof)
index = cp_parser_constant_expression (parser, false, NULL);
else
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
{
bool saved_colon_corrects_to_scope_p =
parser->colon_corrects_to_scope_p;
if (flag_enable_cilkplus)
parser->colon_corrects_to_scope_p = false;
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
bool expr_nonconst_p;
maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
index = cp_parser_braced_list (parser, &expr_nonconst_p);
if (flag_enable_cilkplus
&& cp_lexer_peek_token (parser->lexer)->type == CPP_COLON)
{
bool expr_nonconst_p;
maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
index = cp_parser_braced_list (parser, &expr_nonconst_p);
if (flag_enable_cilkplus
&& cp_lexer_peek_token (parser->lexer)->type == CPP_COLON)
{
error_at (cp_lexer_peek_token (parser->lexer)->location,
"braced list index is not allowed with array "
"notations");
index = error_mark_node;
}
error_at (cp_lexer_peek_token (parser->lexer)->location,
"braced list index is not allowed with array "
"notation");
cp_parser_skip_to_end_of_statement (parser);
return error_mark_node;
}
else
index = cp_parser_expression (parser, /*cast_p=*/false, NULL);
parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
}
if (flag_enable_cilkplus
&& cp_lexer_peek_token (parser->lexer)->type == CPP_COLON)
postfix_expression = cp_parser_array_notation (loc, parser, index,
postfix_expression);
else
else if (flag_enable_cilkplus)
{
/* Look for the closing `]'. */
cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
/* Build the ARRAY_REF. */
postfix_expression = grok_array_decl (loc, postfix_expression,
index, decltype_p);
/* When not doing offsetof, array references are not permitted in
constant-expressions. */
if (!for_offsetof
&& (cp_parser_non_integral_constant_expression (parser,
NIC_ARRAY_REF)))
postfix_expression = error_mark_node;
/* Here are have these two options:
ARRAY[EXP : EXP] - Array notation expr with default
stride of 1.
ARRAY[EXP : EXP : EXP] - Array Notation with user-defined
stride. */
tree an_exp = cp_parser_array_notation (loc, parser, &index,
postfix_expression);
if (an_exp)
return an_exp;
}
else
index = cp_parser_expression (parser, /*cast_p=*/false, NULL);
}
/* Look for the closing `]'. */
cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
/* Build the ARRAY_REF. */
postfix_expression = grok_array_decl (loc, postfix_expression,
index, decltype_p);
/* When not doing offsetof, array references are not permitted in
constant-expressions. */
if (!for_offsetof
&& (cp_parser_non_integral_constant_expression (parser, NIC_ARRAY_REF)))
postfix_expression = error_mark_node;
return postfix_expression;
}
@ -9553,8 +9459,6 @@ cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr,
/* Consume the `}'. */
cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
if (flag_enable_cilkplus && contains_array_notation_expr (compound_stmt))
compound_stmt = expand_array_notation_exprs (compound_stmt);
return compound_stmt;
}
@ -9747,14 +9651,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;
@ -10312,12 +10208,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;
@ -10344,15 +10234,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;
@ -10371,17 +10252,8 @@ cp_parser_iteration_statement (cp_parser* parser)
cp_parser_already_scoped_statement (parser);
parser->in_statement = in_statement;
if (flag_enable_cilkplus
&& contains_array_notation_expr (FOR_COND (statement)))
{
error_at (EXPR_LOCATION (FOR_COND (statement)),
"array notations cannot be used in a condition for a "
"for-loop");
statement = error_mark_node;
}
else
/* We're done with the for-statement. */
finish_for_stmt (statement);
/* We're done with the for-statement. */
finish_for_stmt (statement);
}
break;
@ -16954,54 +16826,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,11 +18220,6 @@ cp_parser_ctor_initializer_opt_and_function_body (cp_parser *parser,
cp_parser_function_body (parser, in_function_try_block);
if (check_body_p)
check_constexpr_ctor_body (last, list);
/* Transform all array notations to the equivalent array refs and loop. */
if (flag_enable_cilkplus && contains_array_notation_expr (body))
body = expand_array_notation_exprs (body);
/* Finish the function body. */
finish_function_body (body);
@ -22356,12 +22199,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));

View File

@ -13762,9 +13762,6 @@ tsubst_copy_and_build (tree t,
start_index = RECUR (ARRAY_NOTATION_START (t));
length = RECUR (ARRAY_NOTATION_LENGTH (t));
stride = RECUR (ARRAY_NOTATION_STRIDE (t));
if (!cilkplus_an_triplet_types_ok_p (loc, start_index, length, stride,
TREE_TYPE (op1)))
RETURN (error_mark_node);
RETURN (build_array_notation_ref (EXPR_LOCATION (t), op1, start_index,
length, stride, TREE_TYPE (op1)));
}
@ -15747,9 +15744,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;
@ -19170,11 +19164,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);

View File

@ -779,22 +779,6 @@ finish_return_stmt (tree expr)
tree r;
bool no_warning;
if (flag_enable_cilkplus && contains_array_notation_expr (expr))
{
size_t rank = 0;
if (!find_rank (input_location, expr, expr, false, &rank))
return error_mark_node;
/* If the return expression contains array notations, then flag it as
error. */
if (rank >= 1)
{
error_at (input_location, "array notation expression cannot be "
"used as a return value");
return error_mark_node;
}
}
expr = check_return_expr (expr, &no_warning);
if (flag_openmp && !check_omp_return ())
@ -8089,7 +8073,6 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t,
non_constant_p, overflow_p);
break;
case ARRAY_NOTATION_REF:
case ARRAY_REF:
r = cxx_eval_array_reference (call, t, allow_non_constant, addr,
non_constant_p, overflow_p);
@ -8901,7 +8884,6 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
want_rval = true;
/* Fall through. */
case ARRAY_REF:
case ARRAY_NOTATION_REF:
case ARRAY_RANGE_REF:
case MEMBER_REF:
case DOTSTAR_EXPR:
@ -8912,6 +8894,9 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
return false;
return true;
case ARRAY_NOTATION_REF:
return false;
case FMA_EXPR:
case VEC_PERM_EXPR:
for (i = 0; i < 3; ++i)

View File

@ -3493,10 +3493,6 @@ cp_build_function_call_vec (tree function, vec<tree, va_gc> **params,
params = &allocated;
}
if (flag_enable_cilkplus
&& is_cilkplus_reduce_builtin (fndecl) != BUILT_IN_NONE)
nargs = (*params)->length ();
else
nargs = convert_arguments (parm_types, params, fndecl, LOOKUP_NORMAL,
complain);
if (nargs < 0)
@ -3660,8 +3656,7 @@ convert_arguments (tree typelist, vec<tree, va_gc> **values, tree fndecl,
}
else
{
if (fndecl && DECL_BUILT_IN (fndecl)
&& DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CONSTANT_P)
if (fndecl && magic_varargs_p (fndecl))
/* Don't do ellipsis conversion for __built_in_constant_p
as this will result in spurious errors for non-trivial
types. */
@ -3956,15 +3951,8 @@ cp_build_binary_op (location_t location,
}
}
if (flag_enable_cilkplus && contains_array_notation_expr (op0))
type0 = find_correct_array_notation_type (op0);
else
type0 = TREE_TYPE (op0);
if (flag_enable_cilkplus && contains_array_notation_expr (op1))
type1 = find_correct_array_notation_type (op1);
else
type1 = TREE_TYPE (op1);
type0 = TREE_TYPE (op0);
type1 = TREE_TYPE (op1);
/* The expression codes of the data types of the arguments tell us
whether the arguments are integers, floating, pointers, etc. */
@ -5182,13 +5170,6 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue, tsubst_flags_t complain)
gcc_assert (!identifier_p (arg) || !IDENTIFIER_OPNAME_P (arg));
if (flag_enable_cilkplus && TREE_CODE (arg) == ARRAY_NOTATION_REF)
{
val = build_address (arg);
if (TREE_CODE (arg) == OFFSET_REF)
PTRMEM_OK_P (val) = PTRMEM_OK_P (arg);
return val;
}
if (TREE_CODE (arg) == COMPONENT_REF && type_unknown_p (arg)
&& !really_overloaded_fn (TREE_OPERAND (arg, 1)))
{
@ -7867,13 +7848,6 @@ convert_for_assignment (tree type, tree rhs,
tree rhstype;
enum tree_code coder;
/* If we are dealing with built-in array notation function then we don't need
to convert them. They will be broken up into modify exprs in future,
during which all these checks will be done. */
if (flag_enable_cilkplus
&& is_cilkplus_reduce_builtin (fndecl) != BUILT_IN_NONE)
return rhs;
/* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */
if (TREE_CODE (rhs) == NON_LVALUE_EXPR)
rhs = TREE_OPERAND (rhs, 0);

View File

@ -1,3 +1,13 @@
2013-06-28 Balaji V. Iyer <balaji.v.iyer@intel.com>
* c-c++-common/cilk-plus/AN/decl-ptr-colon.c (main): Made this testcase
c specific.
* c-c++-common/cilk-plus/AN/decl-ptr-colon.c (main): Changed dg-error
strings to match the fixed error messages.
* c-c++-common/cilk-plus/AN/misc.c (main): Likewise.
* c-c++-common/cilk-plus/AN/rank_mismatch.c (main): Added a new error
message check.
2013-06-28 Michael Meissner <meissner@linux.vnet.ibm.com>
PR target/57744

View File

@ -1,3 +1,4 @@
/* { dg-do compile { target c } } */
/* { dg-options "-fcilkplus" } */
int main(void)

View File

@ -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" }
}

View File

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

View File

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

View File

@ -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" } */