aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@acm.org>2017-05-30 14:43:45 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2017-05-30 14:43:45 +0000
commite2f353338584c197e7d62370821fe48f76a52ce8 (patch)
tree23ae8979361b358e48c6a0849e632d9293aa33ac /gcc
parent064263c11dcac67efa859c8b1896f0a18f5c38dc (diff)
downloadgcc-e2f353338584c197e7d62370821fe48f76a52ce8.zip
gcc-e2f353338584c197e7d62370821fe48f76a52ce8.tar.gz
gcc-e2f353338584c197e7d62370821fe48f76a52ce8.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/name-lookup.c79
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/lookup/pr80913.C11
4 files changed, 64 insertions, 38 deletions
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 <nathan@acm.org>
+
+ 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 <aoliva@redhat.com>
* 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 <nathan@acm.org>
+
+ PR c++/80913
+ * g++.dg/lookup/pr80913.C: New.
+
2017-05-30 Richard Biener <rguenther@suse.de>
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 }
+}