+/**
+ * Check if a node is stored.
+ */
+static int is_stored(const ir_node *n)
+{
+ const ir_edge_t *edge;
+ const ir_node *ptr;
+
+ foreach_out_edge(n, edge) {
+ const ir_node *succ = get_edge_src_irn(edge);
+
+ switch (get_irn_opcode(succ)) {
+ case iro_Return:
+ case iro_Load:
+ case iro_Cmp:
+ /* ok */
+ break;
+ case iro_Store:
+ if (get_Store_value(succ) == n)
+ return 1;
+ /* ok if its only the address input */
+ break;
+ case iro_Sel:
+ case iro_Cast:
+ case iro_Confirm:
+ if (is_stored(succ))
+ return 1;
+ break;
+ case iro_Call:
+ ptr = get_Call_ptr(succ);
+ if (is_Global(ptr)) {
+ ir_entity *ent = get_Global_entity(ptr);
+ int i;
+
+ /* we know the called entity */
+ for (i = get_Call_n_params(succ) - 1; i >= 0; --i) {
+ if (get_Call_param(succ, i) == n) {
+ /* n is the i'th param of the call */
+ if (get_method_param_access(ent, i) & ptr_access_store) {
+ /* n is store in ent */
+ return 1;
+ }
+ }
+ }
+ } else {
+ /* unknown call address */
+ return 1;
+ }
+ break;
+ default:
+ /* bad, potential alias */
+ return 1;
+ }
+ }
+ return 0;
+} /* is_stored */
+
+/**
+ * Check that the return value of an irg is not stored anywhere.
+ *
+ * return ~mtp_property_malloc if return values are stored, ~0 else
+ */
+static unsigned check_stored_result(ir_graph *irg)
+{
+ ir_node *end_blk = get_irg_end_block(irg);
+ int i, j;
+ unsigned res = ~0;
+ int old_edges = edges_assure_kind(irg, EDGE_KIND_NORMAL);
+
+ for (i = get_Block_n_cfgpreds(end_blk) - 1; i >= 0; --i) {
+ ir_node *pred = get_Block_cfgpred(end_blk, i);
+
+ if (! is_Return(pred))
+ continue;
+ for (j = get_Return_n_ress(pred) - 1; j >= 0; --j) {
+ const ir_node *irn = get_Return_res(pred, j);
+
+ if (is_stored(irn)) {
+ /* bad, might create an alias */
+ res = ~mtp_property_malloc;
+ goto finish;
+ }
+ }
+ }
+finish:
+ if (! old_edges)
+ edges_deactivate_kind(irg, EDGE_KIND_NORMAL);
+ return res;
+} /* check_stored_result */
+