From: Jakub Jelinek Date: Mon, 25 Jun 2018 17:10:18 +0000 (+0200) Subject: backport: re PR c++/83553 (compiler removes body of the for-loop, although there... X-Git-Tag: releases/gcc-6.5.0~232 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6ab4012d011f2b783dda63385dd2990a0ffa066c;p=thirdparty%2Fgcc.git backport: re PR c++/83553 (compiler removes body of the for-loop, although there is a case label inside) Backported from mainline 2017-12-23 Jakub Jelinek PR c++/83553 * fold-const.c (struct contains_label_data): New type. (contains_label_1): Return non-NULL even for CASE_LABEL_EXPR, unless inside of a SWITCH_BODY seen during the walk. (contains_label_p): Use walk_tree instead of walk_tree_without_duplicates, prepare data for contains_label_1 and provide own pset. * c-c++-common/torture/pr83553.c: New test. From-SVN: r262051 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 072aa51bc4b3..e88bcc28aa12 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,6 +1,16 @@ 2018-06-25 Jakub Jelinek Backported from mainline + 2017-12-23 Jakub Jelinek + + PR c++/83553 + * fold-const.c (struct contains_label_data): New type. + (contains_label_1): Return non-NULL even for CASE_LABEL_EXPR, unless + inside of a SWITCH_BODY seen during the walk. + (contains_label_p): Use walk_tree instead of + walk_tree_without_duplicates, prepare data for contains_label_1 and + provide own pset. + 2017-12-21 Jakub Jelinek PR rtl-optimization/80747 diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 0d575d0548ce..5bb4e2acb470 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -11529,22 +11529,48 @@ fold_binary_loc (location_t loc, } /* switch (code) */ } +/* Used by contains_label_[p1]. */ + +struct contains_label_data +{ + hash_set *pset; + bool inside_switch_p; +}; + /* Callback for walk_tree, looking for LABEL_EXPR. Return *TP if it is - a LABEL_EXPR; otherwise return NULL_TREE. Do not check the subtrees - of GOTO_EXPR. */ + a LABEL_EXPR or CASE_LABEL_EXPR not inside of another SWITCH_EXPR; otherwise + return NULL_TREE. Do not check the subtrees of GOTO_EXPR. */ static tree -contains_label_1 (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED) +contains_label_1 (tree *tp, int *walk_subtrees, void *data) { + contains_label_data *d = (contains_label_data *) data; switch (TREE_CODE (*tp)) { case LABEL_EXPR: return *tp; + case CASE_LABEL_EXPR: + if (!d->inside_switch_p) + return *tp; + return NULL_TREE; + + case SWITCH_EXPR: + if (!d->inside_switch_p) + { + if (walk_tree (&SWITCH_COND (*tp), contains_label_1, data, d->pset)) + return *tp; + d->inside_switch_p = true; + if (walk_tree (&SWITCH_BODY (*tp), contains_label_1, data, d->pset)) + return *tp; + d->inside_switch_p = false; + *walk_subtrees = 0; + } + return NULL_TREE; + case GOTO_EXPR: *walk_subtrees = 0; - - /* ... fall through ... */ + return NULL_TREE; default: return NULL_TREE; @@ -11557,8 +11583,9 @@ contains_label_1 (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED) static bool contains_label_p (tree st) { - return - (walk_tree_without_duplicates (&st, contains_label_1 , NULL) != NULL_TREE); + hash_set pset; + contains_label_data data = { &pset, false }; + return walk_tree (&st, contains_label_1, &data, &pset) != NULL_TREE; } /* Fold a ternary expression of code CODE and type TYPE with operands diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 119a8a13787b..8bc2fb9088cd 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,6 +1,11 @@ 2018-06-25 Jakub Jelinek Backported from mainline + 2017-12-23 Jakub Jelinek + + PR c++/83553 + * c-c++-common/torture/pr83553.c: New test. + 2017-12-22 Jakub Jelinek PR debug/83550 diff --git a/gcc/testsuite/c-c++-common/torture/pr83553.c b/gcc/testsuite/c-c++-common/torture/pr83553.c new file mode 100644 index 000000000000..c12b79b9e770 --- /dev/null +++ b/gcc/testsuite/c-c++-common/torture/pr83553.c @@ -0,0 +1,29 @@ +/* PR c++/83553 */ +/* { dg-do run } */ + +int a[3]; + +int +foo (int n) +{ + switch (n) + { + case 0: + for (n = 7, a[0]++; 0; a[2] = a[1] + 1) + { + case 2: + a[1] = a[0] + 1; + } + } + return n; +} + +int +main () +{ + if (foo (0) != 7 || a[0] != 1 || a[1] || a[2]) + __builtin_abort (); + if (foo (2) != 2 || a[0] != 1 || a[1] != 2 || a[2] != 3) + __builtin_abort (); + return 0; +}