re PR c++/70594 (-fcompare-debug failure)
authorJakub Jelinek <jakub@redhat.com>
Wed, 13 Apr 2016 14:45:46 +0000 (16:45 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 13 Apr 2016 14:45:46 +0000 (16:45 +0200)
PR c++/70594
* decl.c (pop_labels_1): Removed.
(note_label, sort_labels): New functions.
(pop_labels): During named_labels traversal, just push the slot
pointers into a vector, then qsort it by DECL_UID and only then
call pop_label and chain it into BLOCK_VARS.

From-SVN: r234942

gcc/cp/ChangeLog
gcc/cp/decl.c

index 71538ab..4412994 100644 (file)
@@ -1,3 +1,12 @@
+2016-04-13  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/70594
+       * decl.c (pop_labels_1): Removed.
+       (note_label, sort_labels): New functions.
+       (pop_labels): During named_labels traversal, just push the slot
+       pointers into a vector, then qsort it by DECL_UID and only then
+       call pop_label and chain it into BLOCK_VARS.
+
 2016-04-13  Jason Merrill  <jason@redhat.com>
 
        PR c++/70615
index 9260f4c..2ac5c4b 100644 (file)
@@ -368,33 +368,61 @@ pop_label (tree label, tree old_value)
   SET_IDENTIFIER_LABEL_VALUE (DECL_NAME (label), old_value);
 }
 
-/* At the end of a function, all labels declared within the function
-   go out of scope.  BLOCK is the top-level block for the
-   function.  */
+/* Push all named labels into a vector, so that we can sort it on DECL_UID
+   to avoid code generation differences.  */
 
 int
-pop_labels_1 (named_label_entry **slot, tree block)
+note_label (named_label_entry **slot, vec<named_label_entry **> &labels)
 {
-  struct named_label_entry *ent = *slot;
-
-  pop_label (ent->label_decl, NULL_TREE);
-
-  /* Put the labels into the "variables" of the top-level block,
-     so debugger can see them.  */
-  DECL_CHAIN (ent->label_decl) = BLOCK_VARS (block);
-  BLOCK_VARS (block) = ent->label_decl;
+  labels.quick_push (slot);
+  return 1;
+}
 
-  named_labels->clear_slot (slot);
+/* Helper function to sort named label entries in a vector by DECL_UID.  */
 
-  return 1;
+static int
+sort_labels (const void *a, const void *b)
+{
+  named_label_entry **slot1 = *(named_label_entry **const *) a;
+  named_label_entry **slot2 = *(named_label_entry **const *) b;
+  if (DECL_UID ((*slot1)->label_decl) < DECL_UID ((*slot2)->label_decl))
+    return -1;
+  if (DECL_UID ((*slot1)->label_decl) > DECL_UID ((*slot2)->label_decl))
+    return 1;
+  return 0;
 }
 
+/* At the end of a function, all labels declared within the function
+   go out of scope.  BLOCK is the top-level block for the
+   function.  */
+
 static void
 pop_labels (tree block)
 {
   if (named_labels)
     {
-      named_labels->traverse<tree, pop_labels_1> (block);
+      auto_vec<named_label_entry **, 32> labels;
+      named_label_entry **slot;
+      unsigned int i;
+
+      /* Push all the labels into a vector and sort them by DECL_UID,
+        so that gaps between DECL_UIDs don't affect code generation.  */
+      labels.reserve_exact (named_labels->elements ());
+      named_labels->traverse<vec<named_label_entry **> &, note_label> (labels);
+      labels.qsort (sort_labels);
+      FOR_EACH_VEC_ELT (labels, i, slot)
+       {
+         struct named_label_entry *ent = *slot;
+
+         pop_label (ent->label_decl, NULL_TREE);
+
+         /* Put the labels into the "variables" of the top-level block,
+            so debugger can see them.  */
+         DECL_CHAIN (ent->label_decl) = BLOCK_VARS (block);
+         BLOCK_VARS (block) = ent->label_decl;
+
+         named_labels->clear_slot (slot);
+       }
       named_labels = NULL;
     }
 }