Bug 82193 - incorrectly rejects int x; struct { decltype(x) x; } f = {x};
Summary: incorrectly rejects int x; struct { decltype(x) x; } f = {x};
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 8.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
: 108587 (view as bug list)
Depends on:
Blocks:
 
Reported: 2017-09-12 18:09 UTC by Marc Mutz
Modified: 2023-01-29 07:47 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Marc Mutz 2017-09-12 18:09:47 UTC
This code:

  void fun() {
    constexpr int x = 42;

    constexpr struct {
        decltype(x) x;

        constexpr auto operator()(int a) const { return a * x; }
    } f = {x};
    static_assert(f(0) == 0);
    static_assert(f(2) == 2*42);
  }

(trying to show how a compiler might expand a lambda [x](int a){return a*x;}), fails to compile on all GCCs I tested, incl. trunk as installed on godbold, with the following incomprehensible error message:

6 : <source>:6:21: error: declaration of 'const int fun()::<unnamed struct>::x' [-fpermissive]
         decltype(x) x;
                     ^
3 : <source>:3:19: error: changes meaning of 'x' from 'constexpr const int x' [-fpermissive]
     constexpr int x = 42;
                   ^


Clang 4 and MSVC 2017 both compile this code just fine: https://godbolt.org/g/4L6ULo

The problem is not the constexpr. I only added those to be able to execute the function call operator without having to run the executable.
Comment 1 Andrew Pinski 2017-09-12 18:48:57 UTC
Why do you think this is a bug in GCC?

The "changes meaning of" is a diagnostic which is not required by C++.  That is the C++ language says this is invalid code but a diagnostic is not required.
Comment 2 Marc Mutz 2017-09-12 19:03:52 UTC
Basically: because the other two compilers compile it.
Comment 3 Andrew Pinski 2017-09-12 19:05:33 UTC
(In reply to Marc Mutz from comment #2)
> Basically: because the other two compilers compile it.

Again so ...
Comment 4 Jonathan Wakely 2017-09-12 19:23:55 UTC
[basic.scope.class] p2:

"A name N used in a class S shall refer to the same declaration in its context and when re-evaluated in the completed scope of S. No diagnostic is required for a violation of this rule."

So the code is ill-formed, no diagnostic required.

GCC is allowed to reject it. The other compilers fail to diagnose it (which is also conforming).
Comment 5 Andrew Pinski 2023-01-29 03:04:19 UTC
*** Bug 108587 has been marked as a duplicate of this bug. ***
Comment 6 Andrew Pinski 2023-01-29 07:47:26 UTC
Just a quick note p1787 (https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1787r6.html) moves around the place where it says no diagnostic is required but the effect is the same.


it is now in [class.member.lookup]/7 (note in the draft C++23 standard it is /6).

But GCC is still doing a valid diagnostic because of this. That is the standard didn't change in this area, just changed where the wording was.