for  gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	PR debug/46583
	* tree-ssa-live.c (remove_unused_scope_block_p): Keep type decls.

for  gcc/testsuite/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	PR debug/46583
	* g++.dg/debug/pr46583.C: New.

Index: gcc/tree-ssa-live.c
===================================================================
--- gcc/tree-ssa-live.c.orig	2010-11-21 04:57:04.505193778 -0200
+++ gcc/tree-ssa-live.c	2010-11-21 04:53:31.279647303 -0200
@@ -491,11 +491,16 @@ remove_unused_scope_block_p (tree scope)
 	 can be considered dead.  We only want to keep around blocks user can
 	 breakpoint into and ask about value of optimized out variables.
 
-	 Similarly we need to keep around types at least until all variables of
-	 all nested blocks are gone.  We track no information on whether given
-	 type is used or not.  */
+	 Similarly we need to keep around types at least until all
+	 variables of all nested blocks are gone.  We track no
+	 information on whether given type is used or not, so we have
+	 to keep them even when not emitting debug information,
+	 otherwise we may end up remapping variables and their (local)
+	 types in different orders depending on whether debug
+	 information is being generated.  */
 
-      else if (debug_info_level == DINFO_LEVEL_NORMAL
+      else if (TREE_CODE (*t) == TYPE_DECL
+	       || debug_info_level == DINFO_LEVEL_NORMAL
 	       || debug_info_level == DINFO_LEVEL_VERBOSE)
 	;
       else
Index: gcc/testsuite/g++.dg/debug/pr46583.C
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc/testsuite/g++.dg/debug/pr46583.C	2010-11-21 04:56:07.361194389 -0200
@@ -0,0 +1,40 @@
+// PR debug/46583
+// { dg-do compile }
+// { dg-options "-O -fno-inline -fipa-cp -fipa-cp-clone -fcompare-debug" }
+
+template < typename = unsigned long >struct A
+{
+  unsigned long elems[3];
+  unsigned long *begin ()
+  {
+    return 0;
+  }
+};
+
+void
+bar (unsigned long *a1, unsigned long, unsigned long *a3, unsigned const &)
+{
+  *a3 = *a1;
+}
+
+A < >operatorM (A < >a1, unsigned long a2)
+{
+  typedef A < >G;
+  G a3;
+  bar (a1.begin (), a2, a3.begin (), 0);
+  return a3;
+}
+
+struct B
+{
+  B (A < >m):n (operatorM (m, 1))
+  {
+  }
+  A < >n;
+};
+
+void
+foo ()
+{
+  B (A < >());
+}
