]> git.ipfire.org Git - thirdparty/gcc.git/commit
c++: name lookup for non-dep rewritten != expr [PR121179]
authorPatrick Palka <ppalka@redhat.com>
Wed, 23 Jul 2025 12:38:12 +0000 (08:38 -0400)
committerPatrick Palka <ppalka@redhat.com>
Wed, 23 Jul 2025 12:38:12 +0000 (08:38 -0400)
commit7590c14b53a762ab30f5026148bd1cb9cf142264
tree35cabc496533e09bcd253ee39d1a2d1b3a7c8932
parent04a176a1d84a84c630cfd4d232736c12b105957a
c++: name lookup for non-dep rewritten != expr [PR121179]

Here we're incorrectly rejecting the modules testcase (reduced from a
std module example):

$ cat 121179_a.C
export module foo;

enum class E { x };
bool operator==(E, int);

export
template<class T>
void f() {
  E::x != 0;
}

$ cat 121179_b.C
import foo;

template void f<int>();

$ g++ -fmodules 121179_*.C
In module foo, imported at 121179_b.C:1:
121179_a.C: In instantiation of ‘void f@foo() [with T = int]’:
121179_b.C:3:9:   required from here
121179_a.C:9:8: error: no match for ‘operator!=’ (operand types are ‘E@foo’ and ‘int’)

This is ultimately because our non-dependent rewritten operator expression
handling throws away the result of unqualified lookup at template parse time,
and so we have to repeat the lookup at instantiation time which fails because
the operator== isn't exported.

This is a known deficiency, but it's easy enough to narrowly fix this
for simple != to == rewrites by making build_min_non_dep_op_overload
look through logical negation.

PR c++/121179

gcc/cp/ChangeLog:

* call.cc (build_new_op): Don't clear *overload for a simple
!= to == rewrite.
* tree.cc (build_min_non_dep_op_overload): Handle TRUTH_NOT_EXPR
appearing in a rewritten operator expression.

gcc/testsuite/ChangeLog:

* g++.dg/lookup/operator-8.C: Strengthen test and remove one
XFAIL.

Reviewed-by: Jason Merrill <jason@redhat.com>
gcc/cp/call.cc
gcc/cp/tree.cc
gcc/testsuite/g++.dg/lookup/operator-8.C