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?

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.

+      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.

+       /* 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.

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.

+      /* 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.

+/* 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"

+   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.

+  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.

+         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.

+                     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?

+             error_at (loc, "start-index and length fields necessary for "
+                       "using array notations in dimensionless arrays");

Let's say "...with array of unknown bound"

+         start_index = fold_build1 (CONVERT_EXPR, ptrdiff_type_node,
+                                    start_index);

Use cp_fold_convert rather than fold_build1.

+         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.

+         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.

+             /* 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.

+  /* 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?

+    /* If we are here, then we have something like this:
+       ARRAY[:]
+    */

The */ should go at the end of the last line in all comments.

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

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 (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.

+           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.

+             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.

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

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

+  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.

+  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?

+      while (ii_tree)
+       if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)

Wrap the sub-statement of the 'while' in { }.

+       else if (TREE_CODE (ii_tree) == VAR_DECL
+                || TREE_CODE (ii_tree) == CALL_EXPR
+                || TREE_CODE (ii_tree) == PARM_DECL)
+         break;
+       else
+         gcc_unreachable ();

There are lots of other ways to get an expression of array type, why are only these allowed?

+      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.

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?

+    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.

+       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.

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

"on the same side"

+                 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.

+  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?

+           /* 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.

+      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.

+           /* 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'.

+               /* 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.

Jason

Reply via email to