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.
Crazy.
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.
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.
I have a patchlet which works for the testcase and passes testing. Let's fix this insanity, one way or another.
Fixed.
Patch reverted. For some reason, it only worked on Linux.
GCC 4.9.0 has been released
GCC 4.9.1 has been released.
GCC 4.9.2 has been released.
GCC 4.9.3 has been released.
(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.