diff options
-rw-r--r-- | gcc/cp/ChangeLog | 18 | ||||
-rw-r--r-- | gcc/cp/decl.c | 2 | ||||
-rw-r--r-- | gcc/cp/parser.c | 72 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/friend10.C | 9 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/friend7.C | 8 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/friend9.C | 6 |
7 files changed, 95 insertions, 27 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 35aa7bf..e330f73 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,6 +1,22 @@ +2014-06-11 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/19200 + * parser.c (cp_parser_declarator): Add bool parameter. + (cp_parser_direct_declarator): Likewise, use it. + (cp_parser_member_declaration): Pass friend_p to cp_parser_declarator. + (cp_parser_condition, cp_parser_explicit_instantiation, + cp_parser_init_declarator, cp_parser_type_id_1, + cp_parser_parameter_declaration, cp_parser_exception_declaration, + cp_parser_cache_defarg, cp_parser_objc_class_ivars, + cp_parser_objc_struct_declaration, cp_parser_omp_for_loop_init): + Adjust. + * decl.c (grokdeclarator): Fix handling of friend declared in + namespace scope (g++.dg/parse/friend10.C). + 2014-06-10 Jan Hubicka <hubicka@ucw.cz> - * vtable-class-hierarchy.c: Use symtab_get_node (var_decl)->implicit_section. + * vtable-class-hierarchy.c: Use symtab_get_node (var_decl) + ->implicit_section. * optimize.c (cdtor_comdat_group): Fix handling of aliases. (maybe_clone_body): Move symbol across comdat groups. * method.c (use_thunk): Copy implicit section flag. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 13b5d0b..08f621a 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -9686,7 +9686,7 @@ grokdeclarator (const cp_declarator *declarator, if (ctype == NULL_TREE && decl_context == FIELD && funcdecl_p - && (friendp == 0 || dname == current_class_name)) + && friendp == 0) ctype = current_class_type; if (ctype && (sfk == sfk_constructor diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 7d574d0..22d7ba6 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -2078,9 +2078,9 @@ static tree cp_parser_decltype static tree cp_parser_init_declarator (cp_parser *, cp_decl_specifier_seq *, vec<deferred_access_check, va_gc> *, bool, bool, int, bool *, tree *); static cp_declarator *cp_parser_declarator - (cp_parser *, cp_parser_declarator_kind, int *, bool *, bool); + (cp_parser *, cp_parser_declarator_kind, int *, bool *, bool, bool); static cp_declarator *cp_parser_direct_declarator - (cp_parser *, cp_parser_declarator_kind, int *, bool); + (cp_parser *, cp_parser_declarator_kind, int *, bool, bool); static enum tree_code cp_parser_ptr_operator (cp_parser *, tree *, cp_cv_quals *, tree *); static cp_cv_quals cp_parser_cv_qualifier_seq_opt @@ -10014,7 +10014,8 @@ cp_parser_condition (cp_parser* parser) declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, /*ctor_dtor_or_conv_p=*/NULL, /*parenthesized_p=*/NULL, - /*member_p=*/false); + /*member_p=*/false, + /*friend_p=*/false); /* Parse the attributes. */ attributes = cp_parser_attributes_opt (parser); /* Parse the asm-specification. */ @@ -14160,7 +14161,8 @@ cp_parser_explicit_instantiation (cp_parser* parser) = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, /*ctor_dtor_or_conv_p=*/NULL, /*parenthesized_p=*/NULL, - /*member_p=*/false); + /*member_p=*/false, + /*friend_p=*/false); if (declares_class_or_enum & 2) cp_parser_check_for_definition_in_return_type (declarator, decl_specifiers.type, @@ -16570,7 +16572,7 @@ cp_parser_init_declarator (cp_parser* parser, = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, &ctor_dtor_or_conv_p, /*parenthesized_p=*/NULL, - member_p); + member_p, /*friend_p=*/false); /* Gather up the deferred checks. */ stop_deferring_access_checks (); @@ -16958,14 +16960,16 @@ cp_parser_init_declarator (cp_parser* parser, If PARENTHESIZED_P is non-NULL, *PARENTHESIZED_P is set to true iff the declarator is a direct-declarator of the form "(...)". - MEMBER_P is true iff this declarator is a member-declarator. */ + MEMBER_P is true iff this declarator is a member-declarator. + + FRIEND_P is true iff this declarator is a friend. */ static cp_declarator * cp_parser_declarator (cp_parser* parser, cp_parser_declarator_kind dcl_kind, int* ctor_dtor_or_conv_p, bool* parenthesized_p, - bool member_p) + bool member_p, bool friend_p) { cp_declarator *declarator; enum tree_code code; @@ -17005,7 +17009,8 @@ cp_parser_declarator (cp_parser* parser, declarator = cp_parser_declarator (parser, dcl_kind, /*ctor_dtor_or_conv_p=*/NULL, /*parenthesized_p=*/NULL, - /*member_p=*/false); + /*member_p=*/false, + friend_p); /* If we are parsing an abstract-declarator, we must handle the case where the dependent declarator is absent. */ @@ -17024,7 +17029,7 @@ cp_parser_declarator (cp_parser* parser, CPP_OPEN_PAREN); declarator = cp_parser_direct_declarator (parser, dcl_kind, ctor_dtor_or_conv_p, - member_p); + member_p, friend_p); } if (gnu_attributes && declarator && declarator != cp_error_declarator) @@ -17058,14 +17063,14 @@ cp_parser_declarator (cp_parser* parser, we are parsing a direct-declarator. It is CP_PARSER_DECLARATOR_EITHER, if we can accept either - in the case of ambiguity we prefer an abstract declarator, as per - [dcl.ambig.res]. CTOR_DTOR_OR_CONV_P and MEMBER_P are as for - cp_parser_declarator. */ + [dcl.ambig.res]. CTOR_DTOR_OR_CONV_P, MEMBER_P, and FRIEND_P are + as for cp_parser_declarator. */ static cp_declarator * cp_parser_direct_declarator (cp_parser* parser, cp_parser_declarator_kind dcl_kind, int* ctor_dtor_or_conv_p, - bool member_p) + bool member_p, bool friend_p) { cp_token *token; cp_declarator *declarator = NULL; @@ -17246,7 +17251,7 @@ cp_parser_direct_declarator (cp_parser* parser, declarator = cp_parser_declarator (parser, dcl_kind, ctor_dtor_or_conv_p, /*parenthesized_p=*/NULL, - member_p); + member_p, friend_p); parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p; first = false; /* Expect a `)'. */ @@ -17492,6 +17497,24 @@ cp_parser_direct_declarator (cp_parser* parser, for an anonymous type, even if the type got a name for linkage purposes. */ !TYPE_WAS_ANONYMOUS (class_type) + /* Handle correctly (c++/19200): + + struct S { + struct T{}; + friend void S(T); + }; + + and also: + + namespace N { + void S(); + } + + struct S { + friend void N::S(); + }; */ + && !(friend_p + && class_type != qualifying_scope) && constructor_name_p (unqualified_name, class_type)) { @@ -18035,7 +18058,8 @@ cp_parser_type_id_1 (cp_parser* parser, bool is_template_arg, abstract_declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_ABSTRACT, NULL, /*parenthesized_p=*/NULL, - /*member_p=*/false); + /*member_p=*/false, + /*friend_p=*/false); /* Check to see if there really was a declarator. */ if (!cp_parser_parse_definitely (parser)) abstract_declarator = NULL; @@ -18610,7 +18634,8 @@ cp_parser_parameter_declaration (cp_parser *parser, CP_PARSER_DECLARATOR_EITHER, /*ctor_dtor_or_conv_p=*/NULL, parenthesized_p, - /*member_p=*/false); + /*member_p=*/false, + /*friend_p=*/false); parser->default_arg_ok_p = saved_default_arg_ok_p; /* After the declarator, allow more attributes. */ decl_specifiers.attributes @@ -20446,7 +20471,8 @@ cp_parser_member_declaration (cp_parser* parser) = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, &ctor_dtor_or_conv_p, /*parenthesized_p=*/NULL, - /*member_p=*/true); + /*member_p=*/true, + friend_p); /* If something went wrong parsing the declarator, make sure that we at least consume some tokens. */ @@ -21274,7 +21300,8 @@ cp_parser_exception_declaration (cp_parser* parser) declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_EITHER, /*ctor_dtor_or_conv_p=*/NULL, /*parenthesized_p=*/NULL, - /*member_p=*/false); + /*member_p=*/false, + /*friend_p=*/false); /* Restore the saved message. */ parser->type_definition_forbidden_message = saved_message; @@ -24820,7 +24847,8 @@ cp_parser_cache_defarg (cp_parser *parser, bool nsdmi) cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, &ctor_dtor_or_conv_p, /*parenthesized_p=*/NULL, - /*member_p=*/true); + /*member_p=*/true, + /*friend_p=*/false); } else { @@ -26106,7 +26134,8 @@ cp_parser_objc_class_ivars (cp_parser* parser) = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, &ctor_dtor_or_conv_p, /*parenthesized_p=*/NULL, - /*member_p=*/false); + /*member_p=*/false, + /*friend_p=*/false); } /* Look for attributes that apply to the ivar. */ @@ -26657,7 +26686,7 @@ cp_parser_objc_struct_declaration (cp_parser *parser) /* Parse the declarator. */ declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, - NULL, NULL, false); + NULL, NULL, false, false); /* Look for attributes that apply to the ivar. */ attributes = cp_parser_attributes_opt (parser); @@ -29170,7 +29199,8 @@ cp_parser_omp_for_loop_init (cp_parser *parser, CP_PARSER_DECLARATOR_NAMED, /*ctor_dtor_or_conv_p=*/NULL, /*parenthesized_p=*/NULL, - /*member_p=*/false); + /*member_p=*/false, + /*friend_p=*/false); attributes = cp_parser_attributes_opt (parser); asm_specification = cp_parser_asm_specification_opt (parser); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c586b44..1250218 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2014-06-11 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/19200 + * g++.dg/parse/friend9.C: New. + * g++.dg/parse/friend10.C: Likewise. + * g++.dg/parse/friend7.C: Adjust. + 2014-06-11 Richard Biener <rguenther@suse.de> PR tree-optimization/61452 diff --git a/gcc/testsuite/g++.dg/parse/friend10.C b/gcc/testsuite/g++.dg/parse/friend10.C new file mode 100644 index 0000000..16c2e0a --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/friend10.C @@ -0,0 +1,9 @@ +// PR c++/19200 + +namespace N { + void S(); +} + +struct S { + friend void N::S(); +}; diff --git a/gcc/testsuite/g++.dg/parse/friend7.C b/gcc/testsuite/g++.dg/parse/friend7.C index 668fd35..72ab430 100644 --- a/gcc/testsuite/g++.dg/parse/friend7.C +++ b/gcc/testsuite/g++.dg/parse/friend7.C @@ -17,16 +17,16 @@ struct B struct C { - friend int C (); // { dg-error "return type|in friend decl" } + friend int C (); friend int ~C (); // { dg-error "return type|in friend decl" } - friend int C (const C &); // { dg-error "return type|in friend decl" } + friend int C (const C &); }; struct D { - friend int D () {} // { dg-error "return type|in friend decl" } + friend int D () {} friend int ~D () {} // { dg-error "return type|in friend decl" } - friend int D (const D &) {} // { dg-error "return type|in friend decl" } + friend int D (const D &) {} }; struct E diff --git a/gcc/testsuite/g++.dg/parse/friend9.C b/gcc/testsuite/g++.dg/parse/friend9.C new file mode 100644 index 0000000..dd6729f --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/friend9.C @@ -0,0 +1,6 @@ +// PR c++/19200 + +struct S { + struct T{}; + friend void S(T); +}; |