In the parser, declares_class_or_enum is set to 1 for an elaborated type-specifier, or 2 for a class or enum definition. We only want to complain about a type definition in the latter case.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit 8b366b7f80be1f160bd31501aa436e4d300cd753 Author: Jason Merrill <ja...@redhat.com> Date: Sun Feb 19 14:52:03 2017 -0800 PR c++/79566 - elaborated-type-specifier in range for * parser.c (cp_parser_simple_declaration): Fix check for type definition. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 72597f3..0146596 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -12883,7 +12883,7 @@ cp_parser_simple_declaration (cp_parser* parser, break; else if (maybe_range_for_decl) { - if (declares_class_or_enum && token->type == CPP_COLON) + if ((declares_class_or_enum & 2) && token->type == CPP_COLON) permerror (decl_specifiers.locations[ds_type_spec], "types may not be defined in a for-range-declaration"); break; diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for34.C b/gcc/testsuite/g++.dg/cpp0x/range-for34.C new file mode 100644 index 0000000..2041848 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/range-for34.C @@ -0,0 +1,16 @@ +// PR c++/79566 +// { dg-do compile { target c++11 } } + +struct X { + struct Y { }; + + Y* begin(); + Y* end(); +}; + +void f() +{ + X x; + for (struct X::Y& y : x) + ; +}