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;
}
Exemple #2
0
void
cp_genericize (tree fndecl)
{
  tree t;

  /* Fix up the types of parms passed by invisible reference.  */
  for (t = DECL_ARGUMENTS (fndecl); t; t = DECL_CHAIN (t))
    if (TREE_ADDRESSABLE (TREE_TYPE (t)))
      {
	/* If a function's arguments are copied to create a thunk,
	   then DECL_BY_REFERENCE will be set -- but the type of the
	   argument will be a pointer type, so we will never get
	   here.  */
	gcc_assert (!DECL_BY_REFERENCE (t));
	gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t));
	TREE_TYPE (t) = DECL_ARG_TYPE (t);
	DECL_BY_REFERENCE (t) = 1;
	TREE_ADDRESSABLE (t) = 0;
	relayout_decl (t);
      }

  /* Do the same for the return value.  */
  if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl))))
    {
      t = DECL_RESULT (fndecl);
      TREE_TYPE (t) = build_reference_type (TREE_TYPE (t));
      DECL_BY_REFERENCE (t) = 1;
      TREE_ADDRESSABLE (t) = 0;
      relayout_decl (t);
      if (DECL_NAME (t))
	{
	  /* Adjust DECL_VALUE_EXPR of the original var.  */
	  tree outer = outer_curly_brace_block (current_function_decl);
	  tree var;

	  if (outer)
	    for (var = BLOCK_VARS (outer); var; var = DECL_CHAIN (var))
	      if (DECL_NAME (t) == DECL_NAME (var)
		  && DECL_HAS_VALUE_EXPR_P (var)
		  && DECL_VALUE_EXPR (var) == t)
		{
		  tree val = convert_from_reference (t);
		  SET_DECL_VALUE_EXPR (var, val);
		  break;
		}
	}
    }

  /* If we're a clone, the body is already GIMPLE.  */
  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));

  if (flag_sanitize & SANITIZE_RETURN)
    cp_ubsan_maybe_instrument_return (fndecl);

  /* Do everything else.  */
  c_genericize (fndecl);

  gcc_assert (bc_label[bc_break] == NULL);
  gcc_assert (bc_label[bc_continue] == NULL);
}