Esempio n. 1
0
tree
fix_conditional_array_notations (tree stmt)
{
  if (TREE_CODE (stmt) == STATEMENT_LIST)
    {
      tree_stmt_iterator tsi;
      for (tsi = tsi_start (stmt); !tsi_end_p (tsi); tsi_next (&tsi))
	{
	  tree single_stmt = *tsi_stmt_ptr (tsi);
	  *tsi_stmt_ptr (tsi) =
	    fix_conditional_array_notations_1 (single_stmt);
	}
      return stmt;
    }
  else
    return fix_conditional_array_notations_1 (stmt);
}
Esempio n. 2
0
bool
find_rank (location_t loc, tree orig_expr, tree expr, bool ignore_builtin_fn,
	   size_t *rank)
{
  tree ii_tree;
  size_t ii = 0, current_rank = 0;

  if (TREE_CODE (expr) == ARRAY_NOTATION_REF)
    {
      ii_tree = expr;
      while (ii_tree)
	{
	  if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
	    {
	      current_rank++;
	      ii_tree = ARRAY_NOTATION_ARRAY (ii_tree);
	    }
	  else if (handled_component_p (ii_tree)
		   || TREE_CODE (ii_tree) == INDIRECT_REF)
	    ii_tree = TREE_OPERAND (ii_tree, 0);
	  else if (TREE_CODE (ii_tree) == PARM_DECL
		   || TREE_CODE (ii_tree) == VAR_DECL)
	    break;
	  else
	    gcc_unreachable ();
	}
      if (*rank == 0)
	/* In this case, all the expressions this function has encountered thus
	   far have been scalars or expressions with zero rank.  Please see
	   header comment for examples of such expression.  */
	*rank = current_rank;
      else if (*rank != current_rank)
	{
	  /* In this case, find rank is being recursed through a set of 
	     expression of the form A <OPERATION> B, where A and B both have
	     array notations in them and the rank of A is not equal to rank of
	     B.  
	     A simple example of such case is the following: X[:] + Y[:][:] */ 
	  *rank = current_rank;
	  return false;
	}
    }
  else if (TREE_CODE (expr) == STATEMENT_LIST)
    {
      tree_stmt_iterator ii_tsi;
      for (ii_tsi = tsi_start (expr); !tsi_end_p (ii_tsi);
	   tsi_next (&ii_tsi))
	if (!find_rank (loc, orig_expr, *tsi_stmt_ptr (ii_tsi),
			ignore_builtin_fn, rank))
	  return false;
    }
  else
    {
      if (TREE_CODE (expr) == CALL_EXPR)
	{
	  tree func_name = CALL_EXPR_FN (expr);
	  tree prev_arg = NULL_TREE, arg;
	  call_expr_arg_iterator iter;
	  size_t prev_rank = 0;
	  if (TREE_CODE (func_name) == ADDR_EXPR)
	    if (!ignore_builtin_fn)
	      if (is_cilkplus_reduce_builtin (func_name))
		/* 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))
		{
		  if (prev_arg && EXPR_HAS_LOCATION (prev_arg)
		      && prev_rank != *rank)
		    error_at (EXPR_LOCATION (prev_arg),
			      "rank mismatch between %qE and %qE", prev_arg,
			      arg);
		  else if (prev_arg && prev_rank != *rank)
		    /* Here the original expression is printed as a "heads-up"
		       to the programmer.  This is because since there is no 
		       location information for the offending argument, the 
		       error could be in some internally generated code that is
		       not visible for the programmer.  Thus, the correct fix
		       may lie in the original expression.  */
		    error_at (loc, "rank mismatch in expression %qE",
			      orig_expr);
		  return false;
		}
	      prev_arg = arg;
	      prev_rank = *rank;
	    }	
	}
      else
	{
Esempio n. 3
0
tree
expand_array_notation_exprs (tree t)
{
  enum tree_code code;
  bool is_expr;
  location_t loc = UNKNOWN_LOCATION;
  
  if (!t)
    return t;

  loc = EXPR_LOCATION (t);

  code = TREE_CODE (t); 
  is_expr = IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code));
  switch (code)
    {
    case ERROR_MARK:
    case IDENTIFIER_NODE:
    case VOID_CST:
    case INTEGER_CST:
    case REAL_CST:
    case FIXED_CST:
    case STRING_CST:
    case BLOCK:
    case PLACEHOLDER_EXPR:
    case FIELD_DECL:
    case VOID_TYPE:
    case REAL_TYPE:
    case SSA_NAME:
    case LABEL_DECL:
    case RESULT_DECL:
    case VAR_DECL:
    case PARM_DECL:
    case NON_LVALUE_EXPR:
    case NOP_EXPR:
    case ADDR_EXPR:
    case ARRAY_REF:
    case BIT_FIELD_REF:
    case VECTOR_CST:
    case COMPLEX_CST:
      return t;
    case INIT_EXPR:
    case MODIFY_EXPR:
      if (contains_array_notation_expr (t))
	t = expand_an_in_modify_expr (loc, TREE_OPERAND (t, 0), NOP_EXPR, 
					 TREE_OPERAND (t, 1), 
					 tf_warning_or_error);
      return t;
    case MODOP_EXPR:
      if (contains_array_notation_expr (t) && !processing_template_decl)
	t = expand_an_in_modify_expr
	  (loc, TREE_OPERAND (t, 0), TREE_CODE (TREE_OPERAND (t, 1)),
	   TREE_OPERAND (t, 2), tf_warning_or_error);
      return t;
    case CONSTRUCTOR:
      return t;
    case BIND_EXPR:
      {
	BIND_EXPR_BODY (t) =
	  expand_array_notation_exprs  (BIND_EXPR_BODY (t));
	return t;
      }
    case DECL_EXPR:
      if (contains_array_notation_expr (t))
	{
	  tree x = DECL_EXPR_DECL (t);
	  if (DECL_INITIAL (x))
	    {
	      location_t loc = DECL_SOURCE_LOCATION (x);
	      tree lhs = x;
	      tree rhs = DECL_INITIAL (x);
	      DECL_INITIAL (x) = NULL;
	      tree new_modify_expr = build_modify_expr (loc, lhs,
							TREE_TYPE (lhs),
							NOP_EXPR,
							loc, rhs,
							TREE_TYPE(rhs));
	      t = expand_array_notation_exprs (new_modify_expr);
	    }
	}
      return t;
    case STATEMENT_LIST:
      {
	tree_stmt_iterator i;
	for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
	  *tsi_stmt_ptr (i) =
	    expand_array_notation_exprs (*tsi_stmt_ptr (i));
	return t;
      }

    case OMP_PARALLEL:
    case OMP_TASK:
    case OMP_FOR:
    case OMP_SINGLE:
    case OMP_SECTION:
    case OMP_SECTIONS:
    case OMP_MASTER:
    case OMP_TASKGROUP:
    case OMP_ORDERED:
    case OMP_CRITICAL:
    case OMP_ATOMIC:
    case OMP_CLAUSE:
    case TARGET_EXPR:
    case INTEGER_TYPE:
    case ENUMERAL_TYPE:
    case BOOLEAN_TYPE:
    case POINTER_TYPE:
    case ARRAY_TYPE:
    case RECORD_TYPE:
    case METHOD_TYPE:
      return t;
    case RETURN_EXPR:
      if (contains_array_notation_expr (t))
	t = expand_return_expr (t);
      return t;
    case PREDECREMENT_EXPR:
    case PREINCREMENT_EXPR:
    case POSTDECREMENT_EXPR:
    case POSTINCREMENT_EXPR:
    case AGGR_INIT_EXPR:
    case CALL_EXPR:
      t = expand_unary_array_notation_exprs (t);
      return t;
    case CONVERT_EXPR:
    case CLEANUP_POINT_EXPR:
    case EXPR_STMT:
      TREE_OPERAND (t, 0) = expand_array_notation_exprs (TREE_OPERAND (t, 0));
      /* It is not necessary to wrap error_mark_node in EXPR_STMT.  */
      if (TREE_OPERAND (t, 0) == error_mark_node)
	return TREE_OPERAND (t, 0); 
      return t;
    case TRUTH_ANDIF_EXPR:
    case TRUTH_ORIF_EXPR:
    case TRUTH_AND_EXPR:
    case TRUTH_OR_EXPR:
    case TRUTH_XOR_EXPR:
    case TRUTH_NOT_EXPR:
    case COND_EXPR:
      t = cp_expand_cond_array_notations (t);
      if (TREE_CODE (t) == COND_EXPR)
	{
	  COND_EXPR_THEN (t) =
	    expand_array_notation_exprs (COND_EXPR_THEN (t));
	  COND_EXPR_ELSE (t) =
	    expand_array_notation_exprs (COND_EXPR_ELSE (t));
	}
      return t;
    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_EXPR (t) = expand_array_notation_exprs (FOR_EXPR (t));
	}
      else
	t = expand_array_notation_exprs (t);
      return t;
    case IF_STMT:
      t = cp_expand_cond_array_notations (t);
      /* If the above function added some extra instructions above the original
	 if statement, then we can't assume it is still IF_STMT so we have to
	 check again.  */
      if (TREE_CODE (t) == IF_STMT)
	{
	  if (THEN_CLAUSE (t))
	    THEN_CLAUSE (t) = expand_array_notation_exprs (THEN_CLAUSE (t));
	  if (ELSE_CLAUSE (t))
	    ELSE_CLAUSE (t) = expand_array_notation_exprs (ELSE_CLAUSE (t));
	}
      else
	t = expand_array_notation_exprs (t);
      return t;
    case SWITCH_STMT:
      if (contains_array_notation_expr (SWITCH_STMT_COND (t)))
	{
	  error_at (EXPR_LOCATION (SWITCH_STMT_COND (t)),
		    "array notation cannot be used as a condition for "
		    "switch statement");
	  return error_mark_node;
	}
      if (SWITCH_STMT_BODY (t))
	SWITCH_STMT_BODY (t) =
	  expand_array_notation_exprs (SWITCH_STMT_BODY (t));
      return t;
    case WHILE_STMT:
      if (contains_array_notation_expr (WHILE_COND (t)))
	{
	  if (EXPR_LOCATION (WHILE_COND (t)) != UNKNOWN_LOCATION)
	    loc = EXPR_LOCATION (WHILE_COND (t));
	  error_at (loc, "array notation cannot be used as a condition for "
		    "while statement");
	  return error_mark_node;
	}
      if (WHILE_BODY (t))
	WHILE_BODY (t) = expand_array_notation_exprs (WHILE_BODY (t));
      return t;
    case DO_STMT:
      if (contains_array_notation_expr (DO_COND (t)))
	{
	  error_at (EXPR_LOCATION (DO_COND (t)),
		    "array notation cannot be used as a condition for a "
		    "do-while statement");
	  return error_mark_node;
	}
      if (DO_BODY (t))
	DO_BODY (t) = expand_array_notation_exprs (DO_BODY (t));
      return t;
    default:
      if (is_expr)
	{
	  int i, len;

	  /* Walk over all the sub-trees of this operand.  */
	  len = TREE_CODE_LENGTH (code);

	  /* Go through the subtrees.  We need to do this in forward order so
	     that the scope of a FOR_EXPR is handled properly.  */
	  for (i = 0; i < len; ++i)
	    TREE_OPERAND (t, i) =
	      expand_array_notation_exprs (TREE_OPERAND (t, i));
	}
      return t;
    }
  return t;
}