On Wed, Feb 27, 2019 at 10:53:16AM -0500, Jason Merrill wrote: > On 2/26/19 5:13 PM, Marek Polacek wrote: > > Here we ICE because the unscoped enum's context is a FUNCTION_DECL, which > > push_using_decl can't handle. > > > > http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_active.html#1742 > > says this is well-formed (but the scoped enum case is ill-formed). > > Nevertheless, the DR hasn't been resolved either way yet, and trying > > to accept a FUNCTION_DECL as a USING_DECL_SCOPE seems like a lot of > > work, and ultimately maybe both cases will be deemed ill-formed. > > > > This patch fixes the ICE by giving the pre-r211479 error while > > simultaneously keeping using-enum-[12].C working. > > > > Bootstrapped/regtested on x86_64-linux, ok for trunk? > > > > 2019-02-26 Marek Polacek <pola...@redhat.com> > > > > PR c++/89511 - ICE with using-declarations and unscoped enumerator. > > * parser.c (cp_parser_using_declaration): For an unscoped enum > > only use its context if it's a namespace declaration. > > > > * g++.dg/cpp0x/using-enum-3.C: New test. > > > > diff --git gcc/cp/parser.c gcc/cp/parser.c > > index e976008e94d..361dc9d065e 100644 > > --- gcc/cp/parser.c > > +++ gcc/cp/parser.c > > @@ -19412,7 +19412,8 @@ cp_parser_using_declaration (cp_parser* parser, > > /*is_declaration=*/true); > > if (!qscope) > > qscope = global_namespace; > > - else if (UNSCOPED_ENUM_P (qscope)) > > + else if (UNSCOPED_ENUM_P (qscope) > > + && TREE_CODE (CP_TYPE_CONTEXT (qscope)) == NAMESPACE_DECL) > > qscope = CP_TYPE_CONTEXT (qscope); > > Hmm, surely we want to handle class scope enums here, too? Maybe > !TYPE_FUNCTION_SCOPE_P instead.
I guess so. It doesn't really make a huge difference, because do_class_using_decl will call error_not_base_type in either case, but it changes the error message from error: type ‘S’ is not a base type for type ‘S’ to error: type ‘S::E’ is not a base type for type ‘S’ and I think we want to keep the former. Thus updated patch, with more testing: Bootstrap/regtest running on x86_64-linux, ok for trunk if it passes? 2019-02-27 Marek Polacek <pola...@redhat.com> PR c++/89511 - ICE with using-declaration and unscoped enumerator. * parser.c (cp_parser_using_declaration): For an unscoped enum only use its context if it's not a function declaration. * g++.dg/cpp0x/using-enum-3.C: New test. diff --git gcc/cp/parser.c gcc/cp/parser.c index d9824e40803..5f694033496 100644 --- gcc/cp/parser.c +++ gcc/cp/parser.c @@ -19412,7 +19412,8 @@ cp_parser_using_declaration (cp_parser* parser, /*is_declaration=*/true); if (!qscope) qscope = global_namespace; - else if (UNSCOPED_ENUM_P (qscope)) + else if (UNSCOPED_ENUM_P (qscope) + && !TYPE_FUNCTION_SCOPE_P (qscope)) qscope = CP_TYPE_CONTEXT (qscope); if (access_declaration_p && cp_parser_error_occurred (parser)) diff --git gcc/testsuite/g++.dg/cpp0x/using-enum-3.C gcc/testsuite/g++.dg/cpp0x/using-enum-3.C new file mode 100644 index 00000000000..edc16890cb1 --- /dev/null +++ gcc/testsuite/g++.dg/cpp0x/using-enum-3.C @@ -0,0 +1,21 @@ +// PR c++/89511 +// { dg-do compile { target c++11 } } + +void f () +{ + enum e { a }; + using e::a; // { dg-error "not a namespace or unscoped enum" } +} + +struct S { + enum E { A }; + using E::A; // { dg-error "type .S. is not a base type for type .S." } +}; + +namespace N { + enum E { B }; +} + +struct T { + using N::E::B; // { dg-error "using-declaration for non-member at class scope" } +};