Bug 46206 - using typedef-name error with typedef name hiding struct name
Summary: using typedef-name error with typedef name hiding struct name
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.1.2
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: rejects-valid
Depends on:
Blocks:
 
Reported: 2010-10-28 01:58 UTC by Nathan Keynes
Modified: 2021-12-18 11:33 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2010-10-28 02:16:05


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Nathan Keynes 2010-10-28 01:58:28 UTC
G++ rejects the following code:

class Foo
{
    bool a, b, c, d;
    typedef struct Bar { } Bar;
    virtual void foo(void) {
        struct Bar bar;
    }
};

example.cc: In member function ‘virtual void Foo::foo()’:
example.cc:6: error: using typedef-name ‘Foo::Bar’ after ‘struct’
example.cc:4: error: ‘Foo::Bar’ has a previous declaration here
example.cc:6: error: invalid type in declaration before ‘;’ token

but accepts many similar examples, including:
class Foo
{
    bool a, b, c;
    typedef struct Bar { } Bar;
    virtual void foo(void) {
        struct Bar bar;
    }
};

This behaviour is reproducible on x86_64-redhat-linux (4.1.2 and 4.4.0) and i386-pc-solaris2.11 (4.2.4, 4.3.4 and 4.5.1)

I'm uncertain if this is strictly legal or not per the standard, but it doesn't seem to make sense to accept one of these cases but not the other.
Comment 1 Paolo Carlini 2010-10-28 02:16:05 UTC
Crazy.
Comment 2 Paolo Carlini 2013-08-05 10:59:41 UTC
The difference is that in the first case the TYPE_DECL Bar is regenerated and the DECL_IMPLICIT_TYPEDEF_P bit is lost, the true value set earlier by create_implicit_typedef is lost.
Comment 3 Paolo Carlini 2013-08-05 13:47:54 UTC
More correctly: it seems that when we parse "typedef struct Bar { } Bar;" we create two TYPE_DECL: first, one marked as DECL_IMPLICIT_TYPEDEF_P in pushtag_1 (via create_implicit_typedef); then a second, real, one in grokdeclarator, via build_lang_decl (TYPE_DECL... ). When we do lookup for "struct Bar bar", it can happen, depending on layout details, that the *second* one is found, thus the check in check_elaborated_type_specifier triggers.
Comment 4 Paolo Carlini 2013-08-05 19:00:42 UTC
I have a patchlet which works for the testcase and passes testing. Let's fix this insanity, one way or another.
Comment 5 Paolo Carlini 2013-08-07 10:11:10 UTC
Fixed.
Comment 6 Paolo Carlini 2013-08-09 12:05:33 UTC
Patch reverted. For some reason, it only worked on Linux.
Comment 7 Jakub Jelinek 2014-04-22 11:36:10 UTC
GCC 4.9.0 has been released
Comment 8 Jakub Jelinek 2014-07-16 13:28:22 UTC
GCC 4.9.1 has been released.
Comment 9 Jakub Jelinek 2014-10-30 10:38:34 UTC
GCC 4.9.2 has been released.
Comment 10 Jakub Jelinek 2015-06-26 19:54:19 UTC
GCC 4.9.3 has been released.
Comment 11 Jonathan Wakely 2020-07-08 15:59:22 UTC
(In reply to Nathan Keynes from comment #0)
> but accepts many similar examples, including:
> class Foo
> {
>     bool a, b, c;
>     typedef struct Bar { } Bar;
>     virtual void foo(void) {
>         struct Bar bar;
>     }
> };

That is no longer accepted, since r252005. So the difference was possibly a bug, which got fixed, and now we consistently reject both, but ...

> I'm uncertain if this is strictly legal or not per the standard, but it
> doesn't seem to make sense to accept one of these cases but not the other.

It was made legal by https://wg21.link/cwg407 (c.f. PR 19538). Both examples should compile.