[Bug c++/51577] dependent name lookup finds operator in global namespace

2023-09-15 Thread ppalka at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51577

Patrick Palka  changed:

   What|Removed |Added

 CC||schuchart at icl dot utk.edu

--- Comment #24 from Patrick Palka  ---
*** Bug 87452 has been marked as a duplicate of this bug. ***

[Bug c++/51577] dependent name lookup finds operator in global namespace

2021-12-16 Thread ppalka at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51577

Patrick Palka  changed:

   What|Removed |Added

 Resolution|--- |FIXED
   Target Milestone|--- |12.0
 Status|ASSIGNED|RESOLVED

--- Comment #23 from Patrick Palka  ---
Fixed for GCC 12.

[Bug c++/51577] dependent name lookup finds operator in global namespace

2021-12-16 Thread cvs-commit at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51577

--- Comment #22 from CVS Commits  ---
The master branch has been updated by Patrick Palka :

https://gcc.gnu.org/g:bb2a7f80a98de3febefbb32b1e4898062bdb6af8

commit r12-6022-gbb2a7f80a98de3febefbb32b1e4898062bdb6af8
Author: Patrick Palka 
Date:   Thu Dec 16 13:40:42 2021 -0500

c++: two-stage name lookup for overloaded operators [PR51577]

In order to properly implement two-stage name lookup for dependent
operator expressions, we need to remember the result of unqualified
lookup of the operator at template definition time, and reuse that
result rather than performing another unqualified lookup at
instantiation time.

Ideally we could just store the lookup in the expression directly, but
as pointed out in r9-6405 this isn't really possible since we use the
standard tree codes to represent most dependent operator expressions.

We could perhaps create a new tree code to represent dependent operator
expressions, with enough operands to store the lookup along with
everything else, but that'd require a lot of careful work to make sure
we handle this new tree code properly across the frontend.

But currently type-dependent operator (and call) expressions are given
an empty TREE_TYPE, which dependent_type_p treats as dependent, so this
field is effectively unused except to signal that the expression is
type-dependent.  It'd be convenient if we could store the lookup there
while preserving the dependent-ness of the expression.

To that end, this patch creates a new kind of type, called
DEPENDENT_OPERATOR_TYPE, which we give to dependent operator expressions
and into which we can store the result of operator lookup at template
definition time (DEPENDENT_OPERATOR_TYPE_SAVED_LOOKUPS).  Since this
type is always dependent (by definition), and since the frontend doesn't
seem to care much about the exact type of a type-dependent expression,
using this type in place of a NULL_TREE type seems to "just work"; only
dependent_type_p and WILDCARD_TYPE_P need to be adjusted to return true
for this new type.

The rest of the patch mostly consists of adding the necessary plumbing
to pass DEPENDENT_OPERATOR_TYPE_SAVED_LOOKUPS to add_operator_candidates,
adjusting all callers of build_x_* appropriately, and removing the now
unnecessary push_operator_bindings mechanism.

In passing, this patch simplifies finish_constraint_binary_op to avoid
using build_x_binary_op for building a binary constraint-expr; we don't
need to consider operator overloads here, as the &&/|| inside a
constraint effectively always has the built-in meaning (since atomic
constraints must have bool type).

This patch also makes FOLD_EXPR_OP yield a tree_code instead of a raw
INTEGER_CST.

Finally, this patch adds the XFAILed test operator-8.C which is about
broken two-stage name lookup for rewritten non-dependent operator
expressions, an existing bug that's otherwise only documented in
build_new_op.

PR c++/51577
PR c++/83035
PR c++/100465

gcc/cp/ChangeLog:

* call.c (add_operator_candidates): Add lookups parameter.
Use it to avoid performing a second unqualified lookup when
instantiating a dependent operator expression.
(build_new_op): Add lookups parameter and pass it appropriately.
* constraint.cc (finish_constraint_binary_op): Use
build_min_nt_loc instead of build_x_binary_op.
* coroutines.cc (build_co_await): Adjust call to build_new_op.
* cp-objcp-common.c (cp_common_init_ts): Mark
DEPENDENT_OPERATOR_TYPE appropriately.
* cp-tree.def (DEPENDENT_OPERATOR_TYPE): Define.
* cp-tree.h (WILDCARD_TYPE_P): Accept DEPENDENT_OPERATOR_TYPE.
(FOLD_EXPR_OP_RAW): New, renamed from ...
(FOLD_EXPR_OP): ... this.  Change this to return the tree_code
directly.
(DEPENDENT_OPERATOR_TYPE_SAVED_LOOKUPS): Define.
(templated_operator_saved_lookups): Define.
(build_new_op): Add lookups parameter.
(build_dependent_operator_type): Declare.
(build_x_indirect_ref): Add lookups parameter.
(build_x_binary_op): Likewise.
(build_x_unary_op): Likewise.
(build_x_compound_expr): Likewise.
(build_x_modify_expr): Likewise.
* cxx-pretty-print.c (get_fold_operator): Adjust after
FOLD_EXPR_OP change.
* decl.c (start_preparsed_function): Don't call
push_operator_bindings.
* decl2.c (grok_array_decl): Adjust calls to build_new_op.
* method.c (do_one_comp): Likewise.
(build_comparison_op): Likewise.
* module.cc (trees_out::type_node): Handle DEPENDENT_OPERATOR_TYPE.

[Bug c++/51577] dependent name lookup finds operator in global namespace

2021-05-20 Thread ppalka at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51577

Patrick Palka  changed:

   What|Removed |Added

 CC||asif_bahrainwala at hotmail 
dot co
   ||m

--- Comment #21 from Patrick Palka  ---
*** Bug 99611 has been marked as a duplicate of this bug. ***

[Bug c++/51577] dependent name lookup finds operator in global namespace

2021-05-10 Thread cvs-commit at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51577

--- Comment #20 from CVS Commits  ---
The master branch has been updated by Patrick Palka :

https://gcc.gnu.org/g:6ab1176667734bd6de20833f8d263c03a418c452

commit r12-702-g6ab1176667734bd6de20833f8d263c03a418c452
Author: Patrick Palka 
Date:   Mon May 10 22:38:34 2021 -0400

c++: dependent operator expression lookup [PR51577]

This unconditionally enables the maybe_save_operator_binding mechanism
for all function templates, so that when resolving a dependent operator
expression from a function template we ignore later-declared
namespace-scope bindings that weren't visible at template definition
time.  This patch additionally makes the mechanism apply to dependent
comma and compound-assignment operator expressions.

Note that this doesn't fix the testcases in PR83035 or PR99692 because
there the dependent operator expressions aren't at function scope.  I'm
not sure how adapt this mechanism for these testcases, since although
we'll in both testcases have a TEMPLATE_DECL to associate the lookup
result with, at instantiation time we won't have an appropriate binding
level to push to.

gcc/cp/ChangeLog:

PR c++/51577
* name-lookup.c (maybe_save_operator_binding): Unconditionally
enable for all function templates, not just generic lambdas.
Handle compound-assignment operator expressions.
* typeck.c (build_x_compound_expr): Call
maybe_save_operator_binding
in the type-dependent case.
(build_x_modify_expr): Likewise.  Move declaration of 'op' closer
to its first use.

gcc/testsuite/ChangeLog:

PR c++/51577
* g++.dg/lookup/operator-3.C: New test.

[Bug c++/51577] dependent name lookup finds operator in global namespace

2021-05-06 Thread ppalka at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51577

Patrick Palka  changed:

   What|Removed |Added

   Assignee|unassigned at gcc dot gnu.org  |ppalka at gcc dot 
gnu.org
 Status|NEW |ASSIGNED

[Bug c++/51577] dependent name lookup finds operator in global namespace

2021-05-06 Thread jason at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51577

--- Comment #19 from Jason Merrill  ---
(In reply to Patrick Palka from comment #18)
> ever since Nathan's r11-2876.  As this commit mentions, should we enable the
> maybe_save_operator_binding / push_operator_binding mechanism for all
> templates?

Let's.

[Bug c++/51577] dependent name lookup finds operator in global namespace

2021-05-06 Thread ppalka at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51577

Patrick Palka  changed:

   What|Removed |Added

 CC||ppalka at gcc dot gnu.org

--- Comment #18 from Patrick Palka  ---
If the dependent operator call is inside a lambda, e.g. when adjusting the
testcase in comment #1 to:

template
void test( T v )
{
[&] { +v; }
}

namespace A
{
struct X { };
}

void operator+(A::X) { }

int main()
{
  test( A::X() );
}

then GCC 11 correctly rejects the testcase:

51577.C: In instantiation of ‘bool test(T, U) [with T = A::X; U = B::Y]’:
51577.C:23:7:   required from here
51577.C:5:14: error: no match for ‘operator==’ (operand types are ‘A::X’ and
‘B::Y’)
5 | [&] { v1 == v2; };
  |   ~~~^

ever since Nathan's r11-2876.  As this commit mentions, should we enable the
maybe_save_operator_binding / push_operator_binding mechanism for all
templates?  Something like

--- a/gcc/cp/name-lookup.c  
+++ b/gcc/cp/name-lookup.c  
@@ -9116,7 +9116,7 @@ static const char *const op_bind_attrname = "operator
bindings";  
 void   
 maybe_save_operator_binding (tree e)   
 {  
-  /* This is only useful in a generic lambda.  */  
+  /* This is only useful in a template.  */
   if (!processing_template_decl)   
 return;

@@ -9124,11 +9124,6 @@ maybe_save_operator_binding (tree e) 
   if (!cfn)
 return;

-  /* Do this for lambdas and code that will emit a CMI.  In a module's 
- GMF we don't yet know whether there will be a CMI.  */
-  if (!module_has_cmi_p () && !global_purview_p () && !current_lambda_expr())  
- return;   
-   
   tree fnname = ovl_op_identifier (false, TREE_CODE (e));  
   if (!fnname) 
 return;

seems to fix all the related testcases I tried.

[Bug c++/51577] dependent name lookup finds operator in global namespace

2020-10-27 Thread nathan at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51577

--- Comment #17 from Nathan Sidwell  ---
ah, the logic to squirrel away lookups on a magic attribute list, records that
nothing is found.  But we don't preserve that negative lookup when injecting
these lookups into the parameter binding.  So we'll end up finding
later-declared namespace-scope entities.

[Bug c++/51577] dependent name lookup finds operator in global namespace

2020-10-27 Thread redi at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51577

Jonathan Wakely  changed:

   What|Removed |Added

 CC||barry.revzin at gmail dot com

--- Comment #15 from Jonathan Wakely  ---
*** Bug 70099 has been marked as a duplicate of this bug. ***

[Bug c++/51577] dependent name lookup finds operator in global namespace

2020-10-27 Thread redi at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51577

Jonathan Wakely  changed:

   What|Removed |Added

 CC||tonvandenheuvel at gmail dot 
com

--- Comment #16 from Jonathan Wakely  ---
*** Bug 83035 has been marked as a duplicate of this bug. ***

[Bug c++/51577] dependent name lookup finds operator in global namespace

2020-10-27 Thread redi at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51577

Jonathan Wakely  changed:

   What|Removed |Added

 CC||zhonghao at pku dot org.cn

--- Comment #14 from Jonathan Wakely  ---
*** Bug 86577 has been marked as a duplicate of this bug. ***

[Bug c++/51577] dependent name lookup finds operator in global namespace

2020-10-27 Thread redi at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51577

Jonathan Wakely  changed:

   What|Removed |Added

 CC||andrea_iob at hotmail dot com

--- Comment #13 from Jonathan Wakely  ---
*** Bug 97584 has been marked as a duplicate of this bug. ***

[Bug c++/51577] dependent name lookup finds operator in global namespace

2020-03-18 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51577

Jonathan Wakely  changed:

   What|Removed |Added

 CC||niklas at nolte dot dev

--- Comment #12 from Jonathan Wakely  ---
*** Bug 94214 has been marked as a duplicate of this bug. ***

[Bug c++/51577] dependent name lookup finds operator in global namespace

2015-03-09 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51577

--- Comment #10 from Jonathan Wakely redi at gcc dot gnu.org ---
Testcase from PR65336:


extern C int puts(const char*);

struct ostream {} cout; 
templatetypename T struct A{ T t; };

struct B{};
struct C : public B{};

ostream operator (ostream out, const B) 
  { puts(right); return out; }

namespace {
templatetypename T
ostream operator (ostream out, const ATv) 
  { return out  v.t; }

ostream operator (ostream out, const C) 
  { puts(wrong); return out; }
}

int main(){
  AC a;
  cout  a;
}


[Bug c++/51577] dependent name lookup finds operator in global namespace

2015-03-09 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51577

--- Comment #11 from Jonathan Wakely redi at gcc dot gnu.org ---
And the testcase from PR 61161:

struct T {
  templatetypename T void f(const T v) {
0  v;
  }
};

namespace N {
  struct X {};
  struct Y : X {};
  void operator(int, const X) {}
}

void operator(int, const N::Y) = delete;

int main() {
  N::Y d;
  T().f(d);
}


[Bug c++/51577] dependent name lookup finds operator in global namespace

2015-03-09 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51577

Jonathan Wakely redi at gcc dot gnu.org changed:

   What|Removed |Added

 CC||thibaut.lutz at googlemail dot 
com

--- Comment #9 from Jonathan Wakely redi at gcc dot gnu.org ---
*** Bug 65336 has been marked as a duplicate of this bug. ***


[Bug c++/51577] dependent name lookup finds operator in global namespace

2014-05-12 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51577

Richard Smith richard-gccbugzilla at metafoo dot co.uk changed:

   What|Removed |Added

 CC||richard-gccbugzilla@metafoo
   ||.co.uk

--- Comment #8 from Richard Smith richard-gccbugzilla at metafoo dot co.uk ---
*** Bug 61161 has been marked as a duplicate of this bug. ***


[Bug c++/51577] dependent name lookup finds operator in global namespace

2013-04-13 Thread redi at gcc dot gnu.org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51577



Jonathan Wakely redi at gcc dot gnu.org changed:



   What|Removed |Added



   Keywords||wrong-code

 Status|UNCONFIRMED |NEW

   Last reconfirmed||2013-04-13

 Ever Confirmed|0   |1



--- Comment #3 from Jonathan Wakely redi at gcc dot gnu.org 2013-04-13 
11:17:55 UTC ---

The example in PR 56943 gives a wrong-code example


[Bug c++/51577] dependent name lookup finds operator in global namespace

2013-04-13 Thread daniel.kruegler at googlemail dot com

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51577

--- Comment #4 from Daniel Krügler daniel.kruegler at googlemail dot com 
2013-04-13 11:26:25 UTC ---
(In reply to comment #3)
 The example in PR 56943 gives a wrong-code example

Could you explain why? It looks valid to me. According to my understanding, the
free operator+ overload in global namespace is no valid candidate, but the
member operator+ of N::A is one.

[Bug c++/51577] dependent name lookup finds operator in global namespace

2013-04-13 Thread redi at gcc dot gnu.org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51577



--- Comment #5 from Jonathan Wakely redi at gcc dot gnu.org 2013-04-13 
11:52:51 UTC ---

(In reply to comment #4)

 (In reply to comment #3)

  The example in PR 56943 gives a wrong-code example

 

 Could you explain why? It looks valid to me. According to my understanding, 
 the

 free operator+ overload in global namespace is no valid candidate, but the

 member operator+ of N::A is one.



and G++ calls the global one, returning the wrong result, so it's wrong-code


[Bug c++/51577] dependent name lookup finds operator in global namespace

2013-04-13 Thread daniel.kruegler at googlemail dot com

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51577

--- Comment #6 from Daniel Krügler daniel.kruegler at googlemail dot com 
2013-04-13 11:55:36 UTC ---
(In reply to comment #5)
 and G++ calls the global one, returning the wrong result, so it's wrong-code
OK, I misunderstood the meaning of wrong-code: I thought that was intended to
mean a code that should not compile. I see now that wrong-code is a specific
keyword here (never used it before).

[Bug c++/51577] dependent name lookup finds operator in global namespace

2013-04-13 Thread paolo.carlini at oracle dot com


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51577



--- Comment #7 from Paolo Carlini paolo.carlini at oracle dot com 2013-04-13 
12:10:58 UTC ---

Essentially in gcc-english at least, wrong code means wrong assembly code, what

the back end emits. Normally for wrong C++ code we say invalid code, hard to

confuse.


[Bug c++/51577] dependent name lookup finds operator in global namespace

2013-04-12 Thread zeratul976 at hotmail dot com


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51577



Nathan Ridge zeratul976 at hotmail dot com changed:



   What|Removed |Added



 CC||zeratul976 at hotmail dot

   ||com



--- Comment #2 from Nathan Ridge zeratul976 at hotmail dot com 2013-04-13 
00:44:58 UTC ---

*** Bug 56943 has been marked as a duplicate of this bug. ***


[Bug c++/51577] dependent name lookup finds operator in global namespace

2012-01-21 Thread redi at gcc dot gnu.org
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51577

Jonathan Wakely redi at gcc dot gnu.org changed:

   What|Removed |Added

 CC||jason at gcc dot gnu.org

--- Comment #1 from Jonathan Wakely redi at gcc dot gnu.org 2012-01-21 
22:53:40 UTC ---
the problem exists for any operator, it's not specific to ==

here's a reduced form using unary operator+

templatetypename T
void test( T v )
{
+v;
}

namespace A
{
struct X { };
}

void operator+(A::X) { }

int main()
{
  test( A::X() );
}