aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Palka <ppalka@redhat.com>2021-02-11 10:59:54 -0500
committerPatrick Palka <ppalka@redhat.com>2021-02-11 10:59:54 -0500
commitcb168f779c87c1e0c37d22ea82dfb93ff8c873bc (patch)
tree16f4421193ce9ad7b934fa31438a98757cd4d93f
parent38c5703449c0638618ba6896f0d039c3868ad4e0 (diff)
downloadgcc-cb168f779c87c1e0c37d22ea82dfb93ff8c873bc.zip
gcc-cb168f779c87c1e0c37d22ea82dfb93ff8c873bc.tar.gz
gcc-cb168f779c87c1e0c37d22ea82dfb93ff8c873bc.tar.bz2
c++: Fix ICE from op_unqualified_lookup [PR97582]
In this testcase, we're crashing because the lookup of operator+ from within the generic lambda via lookup_name finds multiple bindings (C1::operator+ and C2::operator+) and returns a TREE_LIST thereof, something which op_unqualified_lookup (and push_operator_bindings) isn't prepared to handle. This patch extends op_unqualified_lookup and push_operator_bindings to handle such an ambiguous lookup result in the natural way. gcc/cp/ChangeLog: PR c++/97582 * name-lookup.c (op_unqualified_lookup): Handle an ambiguous lookup result by discarding it if the first element is a class-scope declaration, otherwise return it. (push_operator_bindings): Handle an ambiguous lookup result by doing push_local_binding on each element in the list. gcc/testsuite/ChangeLog: PR c++/97582 * g++.dg/cpp0x/lambda/lambda-template17.C: New test.
-rw-r--r--gcc/cp/name-lookup.c14
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template17.C12
2 files changed, 23 insertions, 3 deletions
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 1f4a7ac..1cd4f67 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -9219,11 +9219,15 @@ op_unqualified_lookup (tree fnname)
/* Remember we found nothing! */
return error_mark_node;
- tree d = is_overloaded_fn (fns) ? get_first_fn (fns) : fns;
+ tree d = fns;
+ if (TREE_CODE (d) == TREE_LIST)
+ d = TREE_VALUE (d);
+ if (is_overloaded_fn (d))
+ d = get_first_fn (d);
if (DECL_CLASS_SCOPE_P (d))
/* We don't need to remember class-scope functions or declarations,
normal unqualified lookup will find them again. */
- fns = NULL_TREE;
+ return NULL_TREE;
return fns;
}
@@ -9302,7 +9306,11 @@ push_operator_bindings ()
if (tree val = TREE_VALUE (binds))
{
tree name = TREE_PURPOSE (binds);
- push_local_binding (name, val, /*using*/true);
+ if (TREE_CODE (val) == TREE_LIST)
+ for (tree v = val; v; v = TREE_CHAIN (v))
+ push_local_binding (name, TREE_VALUE (v), /*using*/true);
+ else
+ push_local_binding (name, val, /*using*/true);
}
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template17.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template17.C
new file mode 100644
index 0000000..ac6c2e2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template17.C
@@ -0,0 +1,12 @@
+// PR c++/97582
+// { dg-do compile { target c++11 } }
+
+struct C1 { void operator+(); };
+struct C2 { void operator+(); };
+struct C3 : C1, C2 {
+ template <class T> void get() { [] (T x) { +x; }; } // { dg-error "ambiguous" }
+};
+
+template void C3::get<C1>(); // { dg-bogus "" }
+template void C3::get<C2>(); // { dg-bogus "" }
+template void C3::get<C3>(); // { dg-message "required from here" }