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