diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a8b19aec857..142a8667d44 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2012-07-17 Jason Merrill + + PR c++/53549 + * parser.c (cp_parser_class_head): Call xref_basetypes here. + (cp_parser_class_specifier_1): Not here. + * pt.c (tsubst_decl) [USING_DECL]: Check uses_template_parms + as well as DECL_DEPENDENT_P. + 2012-07-16 Jason Merrill * cp-tree.h (struct deferred_access_check): Add location. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 1428a2616bc..df23299efe2 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -2008,7 +2008,7 @@ static tree cp_parser_class_name static tree cp_parser_class_specifier (cp_parser *); static tree cp_parser_class_head - (cp_parser *, bool *, tree *); + (cp_parser *, bool *); static enum tag_types cp_parser_class_key (cp_parser *); static void cp_parser_member_specification_opt @@ -17961,15 +17961,13 @@ cp_parser_class_specifier_1 (cp_parser* parser) bool saved_in_unbraced_linkage_specification_p; tree old_scope = NULL_TREE; tree scope = NULL_TREE; - tree bases; cp_token *closing_brace; push_deferring_access_checks (dk_no_deferred); /* Parse the class-head. */ type = cp_parser_class_head (parser, - &nested_name_specifier_p, - &bases); + &nested_name_specifier_p); /* If the class-head was a semantic disaster, skip the entire body of the class. */ if (!type) @@ -17986,18 +17984,6 @@ cp_parser_class_specifier_1 (cp_parser* parser) return error_mark_node; } - /* Process the base classes. If they're invalid, skip the - entire class body. */ - if (!xref_basetypes (type, bases)) - { - /* Consuming the closing brace yields better error messages - later on. */ - if (cp_parser_skip_to_closing_brace (parser)) - cp_lexer_consume_token (parser->lexer); - pop_deferring_access_checks (); - return error_mark_node; - } - /* Issue an error message if type-definitions are forbidden here. */ cp_parser_check_type_definition (parser); /* Remember that we are defining one more class. */ @@ -18283,14 +18269,14 @@ cp_parser_class_specifier (cp_parser* parser) static tree cp_parser_class_head (cp_parser* parser, - bool* nested_name_specifier_p, - tree *bases) + bool* nested_name_specifier_p) { tree nested_name_specifier; enum tag_types class_key; tree id = NULL_TREE; tree type = NULL_TREE; tree attributes; + tree bases; cp_virt_specifiers virt_specifiers = VIRT_SPEC_UNSPECIFIED; bool template_id_p = false; bool qualified_p = false; @@ -18307,8 +18293,6 @@ cp_parser_class_head (cp_parser* parser, num_templates = 0; parser->colon_corrects_to_scope_p = false; - *bases = NULL_TREE; - /* Look for the class-key. */ class_key = cp_parser_class_key (parser); if (class_key == none_type) @@ -18671,7 +18655,15 @@ cp_parser_class_head (cp_parser* parser, /* Get the list of base-classes, if there is one. */ if (cp_lexer_next_token_is (parser->lexer, CPP_COLON)) - *bases = cp_parser_base_clause (parser); + bases = cp_parser_base_clause (parser); + else + bases = NULL_TREE; + + /* If we're really defining a class, process the base classes. + If they're invalid, fail. */ + if (type && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE) + && !xref_basetypes (type, bases)) + type = NULL_TREE; done: /* Leave the scope given by the nested-name-specifier. We will diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 95c6464e61b..542f57a30a0 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -10235,8 +10235,12 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) break; case USING_DECL: - /* We reach here only for member using decls. */ - if (DECL_DEPENDENT_P (t)) + /* We reach here only for member using decls. We also need to check + uses_template_parms because DECL_DEPENDENT_P is not set for a + using-declaration that designates a member of the current + instantiation (c++/53549). */ + if (DECL_DEPENDENT_P (t) + || uses_template_parms (USING_DECL_SCOPE (t))) { r = do_class_using_decl (tsubst_copy (USING_DECL_SCOPE (t), args, complain, in_decl), diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 56743bd137b..f4e7ff58b0d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2012-07-17 Jason Merrill + + PR c++/53549 + * g++.dg/template/current-inst1.C: New. + * g++.dg/parse/crash35.C: Adjust. + 2012-07-17 Tobias Burnus PR fortran/52101 diff --git a/gcc/testsuite/g++.dg/parse/crash35.C b/gcc/testsuite/g++.dg/parse/crash35.C index 4937cdc66e7..161edad32a2 100644 --- a/gcc/testsuite/g++.dg/parse/crash35.C +++ b/gcc/testsuite/g++.dg/parse/crash35.C @@ -3,5 +3,5 @@ struct a {}; -class foo : public a, a -{ /* { dg-error "duplicate base type|at end of input" } */ +class foo : public a, a // { dg-error "duplicate base" } +{ /* { dg-error "at end of input" } */ diff --git a/gcc/testsuite/g++.dg/template/current-inst1.C b/gcc/testsuite/g++.dg/template/current-inst1.C new file mode 100644 index 00000000000..8f42ef84440 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/current-inst1.C @@ -0,0 +1,19 @@ +// PR c++/53549 + +template +struct C2 +{ + int operator()(); + + template struct F2; +}; + + +template +template +struct C2::F2 : C2 +{ + using C2::operator(); +}; + +C2::F2<42> f;