public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/106223] New: difference in behaviour between no optimization and -O for specialization of std::forward
@ 2022-07-07  8:37 nimrodcowboy at gmail dot com
  2022-07-07  8:40 ` [Bug c++/106223] " pinskia at gcc dot gnu.org
                   ` (9 more replies)
  0 siblings, 10 replies; 11+ messages in thread
From: nimrodcowboy at gmail dot com @ 2022-07-07  8:37 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106223

            Bug ID: 106223
           Summary: difference in behaviour between no optimization and -O
                    for specialization of std::forward
           Product: gcc
           Version: 12.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: nimrodcowboy at gmail dot com
  Target Milestone: ---

Consider the following C++17 code, I make a specialization of std::forward for
user-defined type A.

#include <iostream>
#include <utility>

struct A{
    constexpr A(int val) : val(val) {}
    int val = 0;
};

namespace std {
template<>
A&& forward(A& a) noexcept {
    a.val += 1;
    return std::move(a);
}

template<>
constexpr A& forward(A& a) noexcept {
    a.val += 1;
    return a;
}
}

void foo(A a) {
    std::cout << a.val << "\n";
}

template <typename T>
void f(T&& arg) {
    foo(std::forward<T>(arg));
}

int main() {
    A a{1};
    f(a);
    f(std::move(a));
}

Output:
no optimization: 
2
3
-O:
1
1

See https://godbolt.org/z/sMKdEj1d5
It seems a regression introduced in GCC 12.
I believe it's not UB, since it's legal to do so in C++17.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [Bug c++/106223] difference in behaviour between no optimization and -O for specialization of std::forward
  2022-07-07  8:37 [Bug c++/106223] New: difference in behaviour between no optimization and -O for specialization of std::forward nimrodcowboy at gmail dot com
@ 2022-07-07  8:40 ` pinskia at gcc dot gnu.org
  2022-07-07  8:51 ` nimrodcowboy at gmail dot com
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: pinskia at gcc dot gnu.org @ 2022-07-07  8:40 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106223

--- Comment #1 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
I really think this is undefined behavior and specialization of std::forward is
not allowed.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [Bug c++/106223] difference in behaviour between no optimization and -O for specialization of std::forward
  2022-07-07  8:37 [Bug c++/106223] New: difference in behaviour between no optimization and -O for specialization of std::forward nimrodcowboy at gmail dot com
  2022-07-07  8:40 ` [Bug c++/106223] " pinskia at gcc dot gnu.org
@ 2022-07-07  8:51 ` nimrodcowboy at gmail dot com
  2022-07-07  8:55 ` pinskia at gcc dot gnu.org
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: nimrodcowboy at gmail dot com @ 2022-07-07  8:51 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106223

--- Comment #2 from Nimrod <nimrodcowboy at gmail dot com> ---
Quoted from https://timsong-cpp.github.io/cppwp/n4659/namespace.std#2

"A program may explicitly instantiate a template defined in the standard
library only if the declaration depends on the name of a user-defined type and
the instantiation meets the standard library requirements for the original
template."

If I understand correctly, at least in C++17, this is allowed. I don't see any
special rules for the specialization of std::forward

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [Bug c++/106223] difference in behaviour between no optimization and -O for specialization of std::forward
  2022-07-07  8:37 [Bug c++/106223] New: difference in behaviour between no optimization and -O for specialization of std::forward nimrodcowboy at gmail dot com
  2022-07-07  8:40 ` [Bug c++/106223] " pinskia at gcc dot gnu.org
  2022-07-07  8:51 ` nimrodcowboy at gmail dot com
@ 2022-07-07  8:55 ` pinskia at gcc dot gnu.org
  2022-07-07  9:25 ` nimrodcowboy at gmail dot com
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: pinskia at gcc dot gnu.org @ 2022-07-07  8:55 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106223

Andrew Pinski <pinskia at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
         Resolution|---                         |INVALID
             Status|UNCONFIRMED                 |RESOLVED

--- Comment #3 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
You missed this part: "meets the standard library requirements for the original
template."
std::forward cannot do anything except for the forwarding part so yes it is
undefined.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [Bug c++/106223] difference in behaviour between no optimization and -O for specialization of std::forward
  2022-07-07  8:37 [Bug c++/106223] New: difference in behaviour between no optimization and -O for specialization of std::forward nimrodcowboy at gmail dot com
                   ` (2 preceding siblings ...)
  2022-07-07  8:55 ` pinskia at gcc dot gnu.org
@ 2022-07-07  9:25 ` nimrodcowboy at gmail dot com
  2022-07-07  9:58 ` redi at gcc dot gnu.org
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: nimrodcowboy at gmail dot com @ 2022-07-07  9:25 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106223

--- Comment #4 from Nimrod <nimrodcowboy at gmail dot com> ---
Ok, that somehow makes sense to me. I agree with the forwarding part, as a
normal case, is doing nothing and keep the type.
But I don't find any wordings about "value" or "internal state" in terms of
"(perfect) forwarding", I believe it's only about the types? (If so, the
example does conforms it.) 



https://timsong-cpp.github.io/cppwp/n4659/forward#1
The standard states std::forward as a helper function to simplify forwarding.
"The library provides templated helper functions to simplify applying move
semantics to an lvalue and to simplify the implementation of forwarding
functions. All functions specified in this subclause are signal-safe
([csignal.syn])."

https://timsong-cpp.github.io/cppwp/n4659/func.require#3
"...A forwarding call wrapper is a call wrapper that can be called with an
arbitrary argument list and delivers the arguments to the wrapped callable
object as references. This forwarding step shall ensure that rvalue arguments
are delivered as rvalue references and lvalue arguments are delivered as lvalue
references...."

https://timsong-cpp.github.io/cppwp/n4659/temp.deduct.call#3
"A forwarding reference is an rvalue reference to a cv-unqualified template
parameter that does not represent a template parameter of a class template
(during class template argument deduction). If P is a forwarding reference and
the argument is an lvalue, the type “lvalue reference to A” is used in place of
A for type deduction."

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [Bug c++/106223] difference in behaviour between no optimization and -O for specialization of std::forward
  2022-07-07  8:37 [Bug c++/106223] New: difference in behaviour between no optimization and -O for specialization of std::forward nimrodcowboy at gmail dot com
                   ` (3 preceding siblings ...)
  2022-07-07  9:25 ` nimrodcowboy at gmail dot com
@ 2022-07-07  9:58 ` redi at gcc dot gnu.org
  2022-07-07 11:01 ` redi at gcc dot gnu.org
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: redi at gcc dot gnu.org @ 2022-07-07  9:58 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106223

--- Comment #5 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Nimrod from comment #2)
> Quoted from https://timsong-cpp.github.io/cppwp/n4659/namespace.std#2
> 
> "A program may explicitly instantiate a template defined in the standard
> library only if the declaration depends on the name of a user-defined type
> and the instantiation meets the standard library requirements for the
> original template."

That paragraph has nothing to do with your case, you are adding a
specialization, not an explicit instantiation.

If the standard allows this nonsense then it needs to be fixed. std::move and
std::forward are effectively built-in language primitives, and you should not
be messing with them.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [Bug c++/106223] difference in behaviour between no optimization and -O for specialization of std::forward
  2022-07-07  8:37 [Bug c++/106223] New: difference in behaviour between no optimization and -O for specialization of std::forward nimrodcowboy at gmail dot com
                   ` (4 preceding siblings ...)
  2022-07-07  9:58 ` redi at gcc dot gnu.org
@ 2022-07-07 11:01 ` redi at gcc dot gnu.org
  2022-07-07 15:53 ` nimrodcowboy at gmail dot com
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: redi at gcc dot gnu.org @ 2022-07-07 11:01 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106223

--- Comment #6 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Nimrod from comment #4)
> https://timsong-cpp.github.io/cppwp/n4659/func.require#3
> "...A forwarding call wrapper is a call wrapper that can be called with an

This is irrelevant, std::forward isn't a call wrapper.

Anyway, specializing any function template from namespace std is explicitly
forbidden since C++20, because it's not necessary or sensible to do it.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [Bug c++/106223] difference in behaviour between no optimization and -O for specialization of std::forward
  2022-07-07  8:37 [Bug c++/106223] New: difference in behaviour between no optimization and -O for specialization of std::forward nimrodcowboy at gmail dot com
                   ` (5 preceding siblings ...)
  2022-07-07 11:01 ` redi at gcc dot gnu.org
@ 2022-07-07 15:53 ` nimrodcowboy at gmail dot com
  2022-07-07 16:02 ` nimrodcowboy at gmail dot com
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: nimrodcowboy at gmail dot com @ 2022-07-07 15:53 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106223

--- Comment #7 from Nimrod <nimrodcowboy at gmail dot com> ---
(In reply to Jonathan Wakely from comment #5)
> That paragraph has nothing to do with your case, you are adding a
> specialization, not an explicit instantiation.

Sorry, I quoted the wrong paragraph. It should be
https://timsong-cpp.github.io/cppwp/n4659/namespace.std#2
"A program may add a template specialization for any standard library template
to namespace std only if the declaration depends on a user-defined type and the
specialization meets the standard library requirements for the original
template and is not explicitly prohibited"

> If the standard allows this nonsense then it needs to be fixed. std::move
> and std::forward are effectively built-in language primitives, and you
> should not be messing with them.

Basically agreed and I think it's fixed in C++20. So I'm talking about C++17
things.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [Bug c++/106223] difference in behaviour between no optimization and -O for specialization of std::forward
  2022-07-07  8:37 [Bug c++/106223] New: difference in behaviour between no optimization and -O for specialization of std::forward nimrodcowboy at gmail dot com
                   ` (6 preceding siblings ...)
  2022-07-07 15:53 ` nimrodcowboy at gmail dot com
@ 2022-07-07 16:02 ` nimrodcowboy at gmail dot com
  2022-07-07 16:03 ` nimrodcowboy at gmail dot com
  2022-07-07 16:59 ` redi at gcc dot gnu.org
  9 siblings, 0 replies; 11+ messages in thread
From: nimrodcowboy at gmail dot com @ 2022-07-07 16:02 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106223

--- Comment #8 from Nimrod <nimrodcowboy at gmail dot com> ---
(In reply to Jonathan Wakely from comment #6)
> (In reply to Nimrod from comment #4)
> > https://timsong-cpp.github.io/cppwp/n4659/func.require#3
> > "...A forwarding call wrapper is a call wrapper that can be called with an
> 
> This is irrelevant, std::forward isn't a call wrapper.
Yes. In which context, what I want to prove is the wording about "forwarding"
in the standard isn't related to the value of the object. I was thinking I can
provide a better example without ruining the std::forward implementation. I
just add a log in the specialization of std::forward and do nothing else. (to
record A is being "forwarded")
like, 

template<>
A&& forward(A& a) noexcept {
    std::cout << "recorded\n";
    return std::move(a);
}

I don't think this example will bring more help in this discussion. I was
trying to reproduce some more cases using std::swap but failed. 

> Anyway, specializing any function template from namespace std is explicitly
> forbidden since C++20, because it's not necessary or sensible to do it.

Ok. It's fair to me. A little off-topic question, what's the GCC's attitude to
features with defects being fixed in newer standards? Will GCC still support
them as the older standard says?

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [Bug c++/106223] difference in behaviour between no optimization and -O for specialization of std::forward
  2022-07-07  8:37 [Bug c++/106223] New: difference in behaviour between no optimization and -O for specialization of std::forward nimrodcowboy at gmail dot com
                   ` (7 preceding siblings ...)
  2022-07-07 16:02 ` nimrodcowboy at gmail dot com
@ 2022-07-07 16:03 ` nimrodcowboy at gmail dot com
  2022-07-07 16:59 ` redi at gcc dot gnu.org
  9 siblings, 0 replies; 11+ messages in thread
From: nimrodcowboy at gmail dot com @ 2022-07-07 16:03 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106223

--- Comment #9 from Nimrod <nimrodcowboy at gmail dot com> ---
(In reply to Nimrod from comment #7)
> Sorry, I quoted the wrong paragraph. It should be
> https://timsong-cpp.github.io/cppwp/n4659/namespace.std#2

https://timsong-cpp.github.io/cppwp/n4659/namespace.std#1

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [Bug c++/106223] difference in behaviour between no optimization and -O for specialization of std::forward
  2022-07-07  8:37 [Bug c++/106223] New: difference in behaviour between no optimization and -O for specialization of std::forward nimrodcowboy at gmail dot com
                   ` (8 preceding siblings ...)
  2022-07-07 16:03 ` nimrodcowboy at gmail dot com
@ 2022-07-07 16:59 ` redi at gcc dot gnu.org
  9 siblings, 0 replies; 11+ messages in thread
From: redi at gcc dot gnu.org @ 2022-07-07 16:59 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106223

--- Comment #10 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Nimrod from comment #8)
> Ok. It's fair to me. A little off-topic question, what's the GCC's attitude
> to features with defects being fixed in newer standards? Will GCC still
> support them as the older standard says?

In general, no. Defects are defects, and if there's a fix available, we fix it.

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2022-07-07 16:59 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-07-07  8:37 [Bug c++/106223] New: difference in behaviour between no optimization and -O for specialization of std::forward nimrodcowboy at gmail dot com
2022-07-07  8:40 ` [Bug c++/106223] " pinskia at gcc dot gnu.org
2022-07-07  8:51 ` nimrodcowboy at gmail dot com
2022-07-07  8:55 ` pinskia at gcc dot gnu.org
2022-07-07  9:25 ` nimrodcowboy at gmail dot com
2022-07-07  9:58 ` redi at gcc dot gnu.org
2022-07-07 11:01 ` redi at gcc dot gnu.org
2022-07-07 15:53 ` nimrodcowboy at gmail dot com
2022-07-07 16:02 ` nimrodcowboy at gmail dot com
2022-07-07 16:03 ` nimrodcowboy at gmail dot com
2022-07-07 16:59 ` redi at gcc dot gnu.org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).