+2004-10-18  Diego Novillo  <dnovillo@redhat.com>
+
+       PR tree-optimization/17656
+       * tree-ssa.c (replace_immediate_uses): When replacing a
+       constant, if the call to fold_stmt produced a different
+       statement, get an appropriate statement pointer by scanning
+       STMT's basic block.
+
 2004-10-18  Richard Henderson  <rth@redhat.com>
 
        * pointer-set.c (hash1): Don't use libm functions in fallback case.
 
+2004-10-18  Diego Novillo  <dnovillo@redhat.com>
+
+       PR tree-optimization/17656
+       * testsuite/gcc.c-torture/compile/pr17656.c: New test.
+
 2004-10-18  Nathan Sidwell  <nathan@codesourcery.com>
 
        * g++.dg/eh/shadow1.C: New.
 
--- /dev/null
+int sprintf (char *s, const char *format, ...);
+
+int foo(int i, int j)
+{
+   char *buf, *str;
+
+   if (i)
+     str = "";
+   else if (j)
+     str = "";
+   else
+     return 1;
+
+   /* We were propagating &""[0] here and not calling fold_stmt with a
+      proper statement pointer.  */
+   sprintf(buf, str);
+   return 0;
+}
 
         with a new expression.  Since the current def-use machinery
         does not return pointers to statements, we call fold_stmt
         with the address of a local temporary, if that call changes
-        the temporary then we fall on our swords.
+        the temporary then we fallback on looking for a proper
+        pointer to STMT by scanning STMT's basic block.
 
         Note that all this will become unnecessary soon.  This
         pass is being replaced with a proper copy propagation pass
          tree tmp = stmt;
          fold_stmt (&tmp);
          if (tmp != stmt)
-           abort ();
+           {
+             basic_block bb = bb_for_stmt (stmt);
+             block_stmt_iterator si;
+
+             /* Start iterating at the start of the basic block
+                holding STMT until we reach it.  This is slow, but
+                it's the only way to get a statement pointer
+                reliably.  */
+             for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
+               if (bsi_stmt (si) == stmt)
+                 {
+                   fold_stmt (bsi_stmt_ptr (si));
+                   stmt = bsi_stmt (si);
+                   break;
+                 }
+           }
        }
 
       /* If REPL is a pointer, it may have different memory tags associated