diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 71538ab64f1b..4412994bd571 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2016-04-13 Jakub Jelinek + + 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 PR c++/70615 diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 9260f4c4254f..2ac5c4b1fbf7 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -368,33 +368,61 @@ pop_label (tree label, tree old_value) SET_IDENTIFIER_LABEL_VALUE (DECL_NAME (label), old_value); } +/* Push all named labels into a vector, so that we can sort it on DECL_UID + to avoid code generation differences. */ + +int +note_label (named_label_entry **slot, vec &labels) +{ + labels.quick_push (slot); + return 1; +} + +/* Helper function to sort named label entries in a vector by DECL_UID. */ + +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. */ -int -pop_labels_1 (named_label_entry **slot, tree block) -{ - 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); - - return 1; -} - static void pop_labels (tree block) { if (named_labels) { - named_labels->traverse (block); + auto_vec 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 &, 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; } }