From e2f353338584c197e7d62370821fe48f76a52ce8 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Tue, 30 May 2017 14:43:45 +0000 Subject: [PATCH] re PR c++/80913 (Infinite loop in cc1plus with stat hack patch) PR c++/80913 * name-lookup.c (add_decl_to_level): Assert not making a circular chain. (update_binding): Don't prematurely slide artificial decl. * g++.dg/lookup/pr80913.C: New. From-SVN: r248687 --- gcc/cp/ChangeLog | 7 ++++ gcc/cp/name-lookup.c | 79 ++++++++++++++++++----------------- gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/g++.dg/lookup/pr80913.C | 11 +++++ 4 files changed, 64 insertions(+), 38 deletions(-) create mode 100644 gcc/testsuite/g++.dg/lookup/pr80913.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index f4da407..1aa5df8 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2017-05-30 Nathan Sidwell + + PR c++/80913 + * name-lookup.c (add_decl_to_level): Assert not making a circular + chain. + (update_binding): Don't prematurely slide artificial decl. + 2017-05-29 Alexandre Oliva * cp-tree.h (lang_identifier): Drop oracle_looked_up, unused. diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 861580f..3a11d50 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -132,6 +132,11 @@ add_decl_to_level (cp_binding_level *b, tree decl) } else { + /* Make sure we don't create a circular list. xref_tag can end + up pushing the same artificial decl more than once. We + should have already detected that in update_binding. */ + gcc_assert (b->names != decl); + /* We build up the list in reverse order, and reverse it later if necessary. */ TREE_CHAIN (decl) = b->names; @@ -1720,17 +1725,43 @@ update_binding (cp_binding_level *level, cxx_binding *binding, tree *slot, tree old, tree decl, bool is_friend) { tree to_val = decl; - tree to_type = NULL_TREE; + tree old_type = slot ? MAYBE_STAT_TYPE (*slot) : binding->type; + tree to_type = old_type; gcc_assert (level->kind == sk_namespace ? !binding : level->kind != sk_class && !slot); if (old == error_mark_node) old = NULL_TREE; + if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl)) + { + tree other = to_type; + + if (old && TREE_CODE (old) == TYPE_DECL && DECL_ARTIFICIAL (old)) + other = old; + + /* Pushing an artificial typedef. See if this matches either + the type slot or the old value slot. */ + if (!other) + ; + else if (same_type_p (TREE_TYPE (other), TREE_TYPE (decl))) + /* Two artificial decls to same type. Do nothing. */ + return other; + else + goto conflict; + + if (old) + { + /* Slide decl into the type slot, keep old unaltered */ + to_type = decl; + to_val = old; + goto done; + } + } + if (old && TREE_CODE (old) == TYPE_DECL && DECL_ARTIFICIAL (old)) { - /* Slide the tdef out of the way. We'll undo this below, if - we're pushing a matching tdef. */ + /* Slide old into the type slot. */ to_type = old; old = NULL_TREE; } @@ -1767,39 +1798,14 @@ update_binding (cp_binding_level *level, cxx_binding *binding, tree *slot, to_val = ovl_insert (decl, old); } - else if (to_type && TREE_CODE (decl) == TYPE_DECL) - { - /* We thought we wanted to slide an artificial typedef out of - the way, to make way for another typedef. That's not always - what we want to do. */ - if (!DECL_ARTIFICIAL (decl)) - ; /* Slide. */ - else if (same_type_p (TREE_TYPE (to_type), TREE_TYPE (decl))) - /* Two artificial decls to same type. Do nothing. */ - return to_type; - else - goto conflict; - } else if (!old) ; - else if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl)) - { - /* Slide DECL into the type slot. */ - to_type = decl; - to_val = old; - } else if (TREE_CODE (old) != TREE_CODE (decl)) /* Different kinds of decls conflict. */ goto conflict; else if (TREE_CODE (old) == TYPE_DECL) { - if (DECL_ARTIFICIAL (decl)) - { - /* Slide DECL into the type slot instead. */ - to_type = decl; - to_val = old; - } - else if (same_type_p (TREE_TYPE (old), TREE_TYPE (decl))) + if (same_type_p (TREE_TYPE (old), TREE_TYPE (decl))) /* Two type decls to the same type. Do nothing. */ return old; else @@ -1835,6 +1841,7 @@ update_binding (cp_binding_level *level, cxx_binding *binding, tree *slot, to_val = NULL_TREE; } + done: if (to_val) { if (level->kind != sk_namespace @@ -1854,12 +1861,10 @@ update_binding (cp_binding_level *level, cxx_binding *binding, tree *slot, add_decl_to_level (level, to_add); } - if (to_type == (slot ? MAYBE_STAT_TYPE (*slot) : binding->type)) - to_type = NULL_TREE; - - if (to_type) + if (to_type != old_type) { - gcc_checking_assert (TREE_CODE (to_type) == TYPE_DECL + gcc_checking_assert (!old_type + && TREE_CODE (to_type) == TYPE_DECL && DECL_ARTIFICIAL (to_type)); tree type = TREE_TYPE (to_type); @@ -1875,8 +1880,7 @@ update_binding (cp_binding_level *level, cxx_binding *binding, tree *slot, { if (STAT_HACK_P (*slot)) { - if (to_type) - STAT_TYPE (*slot) = to_type; + STAT_TYPE (*slot) = to_type; STAT_DECL (*slot) = to_val; } else if (to_type) @@ -1886,8 +1890,7 @@ update_binding (cp_binding_level *level, cxx_binding *binding, tree *slot, } else { - if (to_type) - binding->type = to_type; + binding->type = to_type; binding->value = to_val; } } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e40a3ed..97b5493 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2017-05-30 Nathan Sidwell + + PR c++/80913 + * g++.dg/lookup/pr80913.C: New. + 2017-05-30 Richard Biener PR middle-end/80901 diff --git a/gcc/testsuite/g++.dg/lookup/pr80913.C b/gcc/testsuite/g++.dg/lookup/pr80913.C new file mode 100644 index 0000000..a7866bc --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/pr80913.C @@ -0,0 +1,11 @@ +// PR 80913 infinite look on spelling corrector caused by incorrectly +// chained decl + +extern int meminfo (); +struct meminfo {}; + +void frob () +{ + meminf (); // { dg-error "not declared" } + // { dg-message "suggested alternative" "" { target *-*-* } .-1 } +} -- 2.7.4