Index: icln/gcc/ipa-prop.c
===================================================================
--- icln.orig/gcc/ipa-prop.c	2010-06-20 18:23:13.000000000 +0200
+++ icln/gcc/ipa-prop.c	2010-06-20 18:24:32.000000000 +0200
@@ -212,7 +212,6 @@ visit_store_addr_for_mod_analysis (gimpl
     {
       int index = ipa_get_param_decl_index (info, op);
       gcc_assert (index >= 0);
-      info->params[index].modified = true;
       info->params[index].used = true;
     }
 
@@ -707,6 +706,34 @@ type_like_member_ptr_p (tree type, tree
   return true;
 }
 
+/* Callback of walk_aliased_vdefs.  Flags that it has been invoked to the
+   boolean variable pointed to by DATA.  */
+
+static bool
+mark_modified (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef ATTRIBUTE_UNUSED,
+		     void *data)
+{
+  bool *b = (bool *) data;
+  *b = true;
+  return true;
+}
+
+/* Return true if the formal parameter PARM might have been modified in this
+   function before reaching the statement CALL.  */
+
+static bool
+is_parm_modified_at_call (gimple call, tree parm)
+{
+  bool modified = false;
+  ao_ref refd;
+
+  ao_ref_init (&refd, parm);
+  walk_aliased_vdefs (&refd, gimple_vuse (call), mark_modified,
+		      &modified, NULL);
+
+  return modified;
+}
+
 /* Go through arguments of the CALL and for every one that looks like a member
    pointer, check whether it can be safely declared pass-through and if so,
    mark that to the corresponding item of jump FUNCTIONS.  Return true iff
@@ -733,7 +760,7 @@ compute_pass_through_member_ptrs (struct
 	      int index = ipa_get_param_decl_index (info, arg);
 
 	      gcc_assert (index >=0);
-	      if (!ipa_is_param_modified (info, index))
+	      if (!is_parm_modified_at_call (call, arg))
 		{
 		  functions[num].type = IPA_JF_PASS_THROUGH;
 		  functions[num].value.pass_through.formal_id = index;
@@ -1184,7 +1211,7 @@ ipa_analyze_indirect_call_uses (struct c
     return;
 
   index = ipa_get_param_decl_index (info, rec);
-  if (index >= 0 && !ipa_is_param_modified (info, index))
+  if (index >= 0 && !is_parm_modified_at_call (call, rec))
     ipa_note_param_call (node, index, call, false);
 
   return;
@@ -1854,8 +1881,6 @@ ipa_print_node_params (FILE * f, struct
                  (DECL_NAME (temp)
                   ? (*lang_hooks.decl_printable_name) (temp, 2)
                   : "(unnamed)"));
-      if (ipa_is_param_modified (info, i))
-	fprintf (f, " modified");
       if (ipa_is_param_used (info, i))
 	fprintf (f, " used");
       fprintf (f, "\n");
@@ -2470,10 +2495,7 @@ ipa_write_node_info (struct output_block
   gcc_assert (!info->node_enqueued);
   gcc_assert (!info->ipcp_orig_node);
   for (j = 0; j < ipa_get_param_count (info); j++)
-    {
-      bp_pack_value (&bp, info->params[j].modified, 1);
-      bp_pack_value (&bp, info->params[j].used, 1);
-    }
+    bp_pack_value (&bp, info->params[j].used, 1);
   lto_output_bitpack (&bp);
   for (e = node->callees; e; e = e->next_callee)
     {
@@ -2511,10 +2533,7 @@ ipa_read_node_info (struct lto_input_blo
     }
   info->node_enqueued = false;
   for (k = 0; k < ipa_get_param_count (info); k++)
-    {
-      info->params[k].modified = bp_unpack_value (&bp, 1);
-      info->params[k].used = bp_unpack_value (&bp, 1);
-    }
+    info->params[k].used = bp_unpack_value (&bp, 1);
   for (e = node->callees; e; e = e->next_callee)
     {
       struct ipa_edge_args *args = IPA_EDGE_REF (e);
Index: icln/gcc/ipa-prop.h
===================================================================
--- icln.orig/gcc/ipa-prop.h	2010-06-20 17:56:03.000000000 +0200
+++ icln/gcc/ipa-prop.h	2010-06-20 18:23:16.000000000 +0200
@@ -161,8 +161,6 @@ struct ipa_param_descriptor
   struct ipcp_lattice ipcp_lattice;
   /* PARAM_DECL of this parameter.  */
   tree decl;
-  /* Whether the value parameter has been modified within the function.  */
-  unsigned modified : 1;
   /* The parameter is used.  */
   unsigned used : 1;
 };
@@ -228,17 +226,6 @@ ipa_get_param (struct ipa_node_params *i
   return info->params[i].decl;
 }
 
-/* Return the modification flag corresponding to the Ith formal parameter of
-   the function associated with INFO.  Note that there is no setter method as
-   the goal is to set all flags when building the array in
-   ipa_detect_param_modifications.  */
-
-static inline bool
-ipa_is_param_modified (struct ipa_node_params *info, int i)
-{
-  return info->params[i].modified;
-}
-
 /* Return the used flag corresponding to the Ith formal parameter of
    the function associated with INFO.  */
 
Index: icln/gcc/testsuite/g++.dg/ipa/iinline-2.C
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ icln/gcc/testsuite/g++.dg/ipa/iinline-2.C	2010-06-20 18:23:16.000000000 +0200
@@ -0,0 +1,64 @@
+/* Verify that we do not indirect-inline using member pointer
+   parameters which have been modified.  */
+/* { dg-do run } */
+/* { dg-options "-O3 -fno-early-inlining"  } */
+/* { dg-add-options bind_pic_locally } */
+
+extern "C" void abort (void);
+
+class String
+{
+private:
+  const char *data;
+
+public:
+  String (const char *d) : data(d)
+  {}
+
+  int funcOne (int stuff) const;
+  int funcTwo (int stuff) const;
+};
+
+
+int String::funcOne (int stuff) const
+{
+  return stuff + 1;
+}
+
+int String::funcTwo (int stuff) const
+{
+  return stuff + 100;
+}
+
+int (String::* gmp)(int stuff) const = &String::funcTwo;
+
+int docalling_1 (int (String::* f)(int stuff) const)
+{
+  String S ("muhehehe");
+
+  return (S.*f)(4);
+}
+
+int docalling (int a, int (String::* f)(int stuff) const)
+{
+  if (a < 200)
+    f = gmp;
+
+  return docalling_1 (f);
+}
+
+int __attribute__ ((noinline,noclone)) get_input (void)
+{
+  return 1;
+}
+
+int main (int argc, char *argv[])
+{
+  int i = 0;
+  while (i < 10)
+    i += docalling (get_input (), &String::funcOne);
+
+  if (i != 104)
+    abort();
+  return 0;
+}
