On Wed, 10 Feb 2021, Jason Merrill wrote: > On 2/10/21 12:32 PM, Patrick Palka wrote: > > On Wed, 10 Feb 2021, Jason Merrill wrote: > > > > > On 2/9/21 5:12 PM, Patrick Palka wrote: > > > > On Tue, 2 Feb 2021, Jason Merrill wrote: > > > > > > > > > On 2/2/21 12:19 AM, Patrick Palka wrote: > > > > > > In this testcase, we're crashing because the lookup of operator+ > > > > > > from > > > > > > within the generic lambda via lookup_name finds multiple bindings > > > > > > (namely C1::operator+ and C2::operator+) and returns a TREE_LIST > > > > > > thereof, something which maybe_save_operator_binding isn't prepared > > > > > > to > > > > > > handle. > > > > > > > > > > > > Since we already discard the result of lookup_name when it returns a > > > > > > class-scope binding here, it seems cleaner (and equivalent) to > > > > > > instead > > > > > > communicate to lookup_name that we don't want such bindings in the > > > > > > first > > > > > > place. While this change seems like an improvement on its own, it > > > > > > also > > > > > > fixes the mentioned PR, because the call to lookup_name now returns > > > > > > NULL_TREE rather than a TREE_LIST of (unwanted) class-scope > > > > > > bindings. > > > > > > > > > > > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK > > > > > > for > > > > > > trunk/9/10? > > > > > > > > > > > > gcc/cp/ChangeLog: > > > > > > > > > > > > PR c++/97582 > > > > > > * name-lookup.c (op_unqualified_lookup): Pass BLOCK_NAMESPACE > > > > > > to > > > > > > lookup_name in order to ignore class-scope bindings, rather > > > > > > than discarding them after the fact. > > > > > > > > > > > > gcc/testsuite/ChangeLog: > > > > > > > > > > > > PR c++/97582 > > > > > > * g++.dg/cpp0x/lambda/lambda-template17.C: New test. > > > > > > --- > > > > > > gcc/cp/name-lookup.c | 11 > > > > > > +++-------- > > > > > > gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template17.C | 8 > > > > > > ++++++++ > > > > > > 2 files changed, 11 insertions(+), 8 deletions(-) > > > > > > create mode 100644 > > > > > > gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template17.C > > > > > > > > > > > > diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c > > > > > > index 52e4a630e25..46d6cc0dfa4 100644 > > > > > > --- a/gcc/cp/name-lookup.c > > > > > > +++ b/gcc/cp/name-lookup.c > > > > > > @@ -9213,17 +9213,12 @@ op_unqualified_lookup (tree fnname) > > > > > > return NULL_TREE; > > > > > > } > > > > > > - tree fns = lookup_name (fnname); > > > > > > + /* We don't need to remember class-scope functions or > > > > > > declarations, > > > > > > + normal unqualified lookup will find them again. */ > > > > > > + tree fns = lookup_name (fnname, LOOK_where::BLOCK_NAMESPACE); > > > > > > > > > > Hmm, I'd expect this to look past class-scope declarations to find > > > > > namespace-scope declarations, but we want class decls to hide decls in > > > > > an > > > > > outer scope. > > > > > > > > D'oh, good point. But IIUC, even if we did return (and later inject at > > > > instantiation time) namespace-scope declarations that were hidden by > > > > class-scope declarations, wouldn't the lookup at instantiation time > > > > still find and prefer the class-scope bindings (as desired)? It seems > > > > to me that the end result might be the same, but I'm not sure. > > > > > > The injection happens in the function parameter binding level, so I'd > > > expect > > > it to be found before class bindings. > > > > Oops, I didn't look at push_operator_bindings closely enough. Never > > mind about that idea then. > > > > > > > > > Alternatively, would it be safe to assume that if lookup_name returns an > > > > ambiguous result, then the result must consist of class-scope > > > > declarations and so we can discard it? > > > > > > That isn't true in general: > > > > > > inline namespace A { int i; } > > > inline namespace B { int i; } > > > int main() { return i; } // ambiguous lookup > > > > > > though I think it is true for functions. But if the result is ambiguous, > > > you > > > can look at the first element to see if it's from class scope. > > > > I see, that's good to know. So something like this? > > > > -- >8 -- > > > > Subject: [PATCH] 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 > > (namely 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 makes op_unqualified_lookup and push_operator_bindings handle > > an ambiguous lookup result appropriately. > > > > 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. > > --- > > gcc/cp/name-lookup.c | 16 ++++++++++++---- > > .../g++.dg/cpp0x/lambda/lambda-template17.C | 8 ++++++++ > > 2 files changed, 20 insertions(+), 4 deletions(-) > > create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template17.C > > > > diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c > > index 1f4a7ac1d0c..27af21d9ac9 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; > > - if (DECL_CLASS_SCOPE_P (d)) > > + tree fn = fns; > > + if (TREE_CODE (fn) == TREE_LIST) > > + fn = TREE_VALUE (fn); > > + if (is_overloaded_fn (fn)) > > + fn = get_first_fn (fn); > > + if (DECL_CLASS_SCOPE_P (fn)) > > /* 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 00000000000..6cafbab8cb0 > > --- /dev/null > > +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template17.C > > @@ -0,0 +1,8 @@ > > +// 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; }; } > > +}; > > The testcase should instantiate get() and check that we get the appropriate > error. Done in the patch below: -- >8 -- Subject: [PATCH] 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 (namely 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 makes op_unqualified_lookup and push_operator_bindings handle an ambiguous lookup result appropriately. 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. --- gcc/cp/name-lookup.c | 16 ++++++++++++---- .../g++.dg/cpp0x/lambda/lambda-template17.C | 10 ++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template17.C diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 1f4a7ac1d0c..27af21d9ac9 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; - if (DECL_CLASS_SCOPE_P (d)) + tree fn = fns; + if (TREE_CODE (fn) == TREE_LIST) + fn = TREE_VALUE (fn); + if (is_overloaded_fn (fn)) + fn = get_first_fn (fn); + if (DECL_CLASS_SCOPE_P (fn)) /* 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 00000000000..34dd07c983d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template17.C @@ -0,0 +1,10 @@ +// 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<C3>(); -- 2.30.0.452.gfb7fa4a1fd
Re: [PATCH] c++: Fix ICE from op_unqualified_lookup [PR97582]
Patrick Palka via Gcc-patches Wed, 10 Feb 2021 14:25:39 -0800
- [PATCH] c++: Fix ICE from op_unqualified_loo... Patrick Palka via Gcc-patches
- Re: [PATCH] c++: Fix ICE from op_unqual... Jason Merrill via Gcc-patches
- Re: [PATCH] c++: Fix ICE from op_un... Patrick Palka via Gcc-patches
- Re: [PATCH] c++: Fix ICE from o... Jason Merrill via Gcc-patches
- Re: [PATCH] c++: Fix ICE fr... Patrick Palka via Gcc-patches
- Re: [PATCH] c++: Fix I... Jason Merrill via Gcc-patches
- Re: [PATCH] c++: F... Patrick Palka via Gcc-patches
- Re: [PATCH] c+... Jason Merrill via Gcc-patches