Commit d0ba67dc by Paolo Carlini

re PR c++/19200 (Friend declaration misinterpreted as constructor)

/cp
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).

/testsuite
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.

From-SVN: r211467
parent f8c59c05
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> 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. * optimize.c (cdtor_comdat_group): Fix handling of aliases.
(maybe_clone_body): Move symbol across comdat groups. (maybe_clone_body): Move symbol across comdat groups.
* method.c (use_thunk): Copy implicit section flag. * method.c (use_thunk): Copy implicit section flag.
......
...@@ -9686,7 +9686,7 @@ grokdeclarator (const cp_declarator *declarator, ...@@ -9686,7 +9686,7 @@ grokdeclarator (const cp_declarator *declarator,
if (ctype == NULL_TREE if (ctype == NULL_TREE
&& decl_context == FIELD && decl_context == FIELD
&& funcdecl_p && funcdecl_p
&& (friendp == 0 || dname == current_class_name)) && friendp == 0)
ctype = current_class_type; ctype = current_class_type;
if (ctype && (sfk == sfk_constructor if (ctype && (sfk == sfk_constructor
......
...@@ -2078,9 +2078,9 @@ static tree cp_parser_decltype ...@@ -2078,9 +2078,9 @@ static tree cp_parser_decltype
static tree cp_parser_init_declarator static tree cp_parser_init_declarator
(cp_parser *, cp_decl_specifier_seq *, vec<deferred_access_check, va_gc> *, bool, bool, int, bool *, tree *); (cp_parser *, cp_decl_specifier_seq *, vec<deferred_access_check, va_gc> *, bool, bool, int, bool *, tree *);
static cp_declarator *cp_parser_declarator 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 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 static enum tree_code cp_parser_ptr_operator
(cp_parser *, tree *, cp_cv_quals *, tree *); (cp_parser *, tree *, cp_cv_quals *, tree *);
static cp_cv_quals cp_parser_cv_qualifier_seq_opt static cp_cv_quals cp_parser_cv_qualifier_seq_opt
...@@ -10014,7 +10014,8 @@ cp_parser_condition (cp_parser* parser) ...@@ -10014,7 +10014,8 @@ cp_parser_condition (cp_parser* parser)
declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
/*ctor_dtor_or_conv_p=*/NULL, /*ctor_dtor_or_conv_p=*/NULL,
/*parenthesized_p=*/NULL, /*parenthesized_p=*/NULL,
/*member_p=*/false); /*member_p=*/false,
/*friend_p=*/false);
/* Parse the attributes. */ /* Parse the attributes. */
attributes = cp_parser_attributes_opt (parser); attributes = cp_parser_attributes_opt (parser);
/* Parse the asm-specification. */ /* Parse the asm-specification. */
...@@ -14160,7 +14161,8 @@ cp_parser_explicit_instantiation (cp_parser* parser) ...@@ -14160,7 +14161,8 @@ cp_parser_explicit_instantiation (cp_parser* parser)
= cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
/*ctor_dtor_or_conv_p=*/NULL, /*ctor_dtor_or_conv_p=*/NULL,
/*parenthesized_p=*/NULL, /*parenthesized_p=*/NULL,
/*member_p=*/false); /*member_p=*/false,
/*friend_p=*/false);
if (declares_class_or_enum & 2) if (declares_class_or_enum & 2)
cp_parser_check_for_definition_in_return_type (declarator, cp_parser_check_for_definition_in_return_type (declarator,
decl_specifiers.type, decl_specifiers.type,
...@@ -16570,7 +16572,7 @@ cp_parser_init_declarator (cp_parser* parser, ...@@ -16570,7 +16572,7 @@ cp_parser_init_declarator (cp_parser* parser,
= cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
&ctor_dtor_or_conv_p, &ctor_dtor_or_conv_p,
/*parenthesized_p=*/NULL, /*parenthesized_p=*/NULL,
member_p); member_p, /*friend_p=*/false);
/* Gather up the deferred checks. */ /* Gather up the deferred checks. */
stop_deferring_access_checks (); stop_deferring_access_checks ();
...@@ -16958,14 +16960,16 @@ cp_parser_init_declarator (cp_parser* parser, ...@@ -16958,14 +16960,16 @@ cp_parser_init_declarator (cp_parser* parser,
If PARENTHESIZED_P is non-NULL, *PARENTHESIZED_P is set to true iff If PARENTHESIZED_P is non-NULL, *PARENTHESIZED_P is set to true iff
the declarator is a direct-declarator of the form "(...)". 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 * static cp_declarator *
cp_parser_declarator (cp_parser* parser, cp_parser_declarator (cp_parser* parser,
cp_parser_declarator_kind dcl_kind, cp_parser_declarator_kind dcl_kind,
int* ctor_dtor_or_conv_p, int* ctor_dtor_or_conv_p,
bool* parenthesized_p, bool* parenthesized_p,
bool member_p) bool member_p, bool friend_p)
{ {
cp_declarator *declarator; cp_declarator *declarator;
enum tree_code code; enum tree_code code;
...@@ -17005,7 +17009,8 @@ cp_parser_declarator (cp_parser* parser, ...@@ -17005,7 +17009,8 @@ cp_parser_declarator (cp_parser* parser,
declarator = cp_parser_declarator (parser, dcl_kind, declarator = cp_parser_declarator (parser, dcl_kind,
/*ctor_dtor_or_conv_p=*/NULL, /*ctor_dtor_or_conv_p=*/NULL,
/*parenthesized_p=*/NULL, /*parenthesized_p=*/NULL,
/*member_p=*/false); /*member_p=*/false,
friend_p);
/* If we are parsing an abstract-declarator, we must handle the /* If we are parsing an abstract-declarator, we must handle the
case where the dependent declarator is absent. */ case where the dependent declarator is absent. */
...@@ -17024,7 +17029,7 @@ cp_parser_declarator (cp_parser* parser, ...@@ -17024,7 +17029,7 @@ cp_parser_declarator (cp_parser* parser,
CPP_OPEN_PAREN); CPP_OPEN_PAREN);
declarator = cp_parser_direct_declarator (parser, dcl_kind, declarator = cp_parser_direct_declarator (parser, dcl_kind,
ctor_dtor_or_conv_p, ctor_dtor_or_conv_p,
member_p); member_p, friend_p);
} }
if (gnu_attributes && declarator && declarator != cp_error_declarator) if (gnu_attributes && declarator && declarator != cp_error_declarator)
...@@ -17058,14 +17063,14 @@ cp_parser_declarator (cp_parser* parser, ...@@ -17058,14 +17063,14 @@ cp_parser_declarator (cp_parser* parser,
we are parsing a direct-declarator. It is we are parsing a direct-declarator. It is
CP_PARSER_DECLARATOR_EITHER, if we can accept either - in the case CP_PARSER_DECLARATOR_EITHER, if we can accept either - in the case
of ambiguity we prefer an abstract declarator, as per of ambiguity we prefer an abstract declarator, as per
[dcl.ambig.res]. CTOR_DTOR_OR_CONV_P and MEMBER_P are as for [dcl.ambig.res]. CTOR_DTOR_OR_CONV_P, MEMBER_P, and FRIEND_P are
cp_parser_declarator. */ as for cp_parser_declarator. */
static cp_declarator * static cp_declarator *
cp_parser_direct_declarator (cp_parser* parser, cp_parser_direct_declarator (cp_parser* parser,
cp_parser_declarator_kind dcl_kind, cp_parser_declarator_kind dcl_kind,
int* ctor_dtor_or_conv_p, int* ctor_dtor_or_conv_p,
bool member_p) bool member_p, bool friend_p)
{ {
cp_token *token; cp_token *token;
cp_declarator *declarator = NULL; cp_declarator *declarator = NULL;
...@@ -17246,7 +17251,7 @@ cp_parser_direct_declarator (cp_parser* parser, ...@@ -17246,7 +17251,7 @@ cp_parser_direct_declarator (cp_parser* parser,
declarator declarator
= cp_parser_declarator (parser, dcl_kind, ctor_dtor_or_conv_p, = cp_parser_declarator (parser, dcl_kind, ctor_dtor_or_conv_p,
/*parenthesized_p=*/NULL, /*parenthesized_p=*/NULL,
member_p); member_p, friend_p);
parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p; parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
first = false; first = false;
/* Expect a `)'. */ /* Expect a `)'. */
...@@ -17492,6 +17497,24 @@ cp_parser_direct_declarator (cp_parser* parser, ...@@ -17492,6 +17497,24 @@ cp_parser_direct_declarator (cp_parser* parser,
for an anonymous type, even if the type for an anonymous type, even if the type
got a name for linkage purposes. */ got a name for linkage purposes. */
!TYPE_WAS_ANONYMOUS (class_type) !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, && constructor_name_p (unqualified_name,
class_type)) class_type))
{ {
...@@ -18035,7 +18058,8 @@ cp_parser_type_id_1 (cp_parser* parser, bool is_template_arg, ...@@ -18035,7 +18058,8 @@ cp_parser_type_id_1 (cp_parser* parser, bool is_template_arg,
abstract_declarator abstract_declarator
= cp_parser_declarator (parser, CP_PARSER_DECLARATOR_ABSTRACT, NULL, = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_ABSTRACT, NULL,
/*parenthesized_p=*/NULL, /*parenthesized_p=*/NULL,
/*member_p=*/false); /*member_p=*/false,
/*friend_p=*/false);
/* Check to see if there really was a declarator. */ /* Check to see if there really was a declarator. */
if (!cp_parser_parse_definitely (parser)) if (!cp_parser_parse_definitely (parser))
abstract_declarator = NULL; abstract_declarator = NULL;
...@@ -18610,7 +18634,8 @@ cp_parser_parameter_declaration (cp_parser *parser, ...@@ -18610,7 +18634,8 @@ cp_parser_parameter_declaration (cp_parser *parser,
CP_PARSER_DECLARATOR_EITHER, CP_PARSER_DECLARATOR_EITHER,
/*ctor_dtor_or_conv_p=*/NULL, /*ctor_dtor_or_conv_p=*/NULL,
parenthesized_p, parenthesized_p,
/*member_p=*/false); /*member_p=*/false,
/*friend_p=*/false);
parser->default_arg_ok_p = saved_default_arg_ok_p; parser->default_arg_ok_p = saved_default_arg_ok_p;
/* After the declarator, allow more attributes. */ /* After the declarator, allow more attributes. */
decl_specifiers.attributes decl_specifiers.attributes
...@@ -20446,7 +20471,8 @@ cp_parser_member_declaration (cp_parser* parser) ...@@ -20446,7 +20471,8 @@ cp_parser_member_declaration (cp_parser* parser)
= cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
&ctor_dtor_or_conv_p, &ctor_dtor_or_conv_p,
/*parenthesized_p=*/NULL, /*parenthesized_p=*/NULL,
/*member_p=*/true); /*member_p=*/true,
friend_p);
/* If something went wrong parsing the declarator, make sure /* If something went wrong parsing the declarator, make sure
that we at least consume some tokens. */ that we at least consume some tokens. */
...@@ -21274,7 +21300,8 @@ cp_parser_exception_declaration (cp_parser* parser) ...@@ -21274,7 +21300,8 @@ cp_parser_exception_declaration (cp_parser* parser)
declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_EITHER, declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_EITHER,
/*ctor_dtor_or_conv_p=*/NULL, /*ctor_dtor_or_conv_p=*/NULL,
/*parenthesized_p=*/NULL, /*parenthesized_p=*/NULL,
/*member_p=*/false); /*member_p=*/false,
/*friend_p=*/false);
/* Restore the saved message. */ /* Restore the saved message. */
parser->type_definition_forbidden_message = saved_message; parser->type_definition_forbidden_message = saved_message;
...@@ -24820,7 +24847,8 @@ cp_parser_cache_defarg (cp_parser *parser, bool nsdmi) ...@@ -24820,7 +24847,8 @@ cp_parser_cache_defarg (cp_parser *parser, bool nsdmi)
cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
&ctor_dtor_or_conv_p, &ctor_dtor_or_conv_p,
/*parenthesized_p=*/NULL, /*parenthesized_p=*/NULL,
/*member_p=*/true); /*member_p=*/true,
/*friend_p=*/false);
} }
else else
{ {
...@@ -26106,7 +26134,8 @@ cp_parser_objc_class_ivars (cp_parser* parser) ...@@ -26106,7 +26134,8 @@ cp_parser_objc_class_ivars (cp_parser* parser)
= cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
&ctor_dtor_or_conv_p, &ctor_dtor_or_conv_p,
/*parenthesized_p=*/NULL, /*parenthesized_p=*/NULL,
/*member_p=*/false); /*member_p=*/false,
/*friend_p=*/false);
} }
/* Look for attributes that apply to the ivar. */ /* Look for attributes that apply to the ivar. */
...@@ -26657,7 +26686,7 @@ cp_parser_objc_struct_declaration (cp_parser *parser) ...@@ -26657,7 +26686,7 @@ cp_parser_objc_struct_declaration (cp_parser *parser)
/* Parse the declarator. */ /* Parse the declarator. */
declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
NULL, NULL, false); NULL, NULL, false, false);
/* Look for attributes that apply to the ivar. */ /* Look for attributes that apply to the ivar. */
attributes = cp_parser_attributes_opt (parser); attributes = cp_parser_attributes_opt (parser);
...@@ -29170,7 +29199,8 @@ cp_parser_omp_for_loop_init (cp_parser *parser, ...@@ -29170,7 +29199,8 @@ cp_parser_omp_for_loop_init (cp_parser *parser,
CP_PARSER_DECLARATOR_NAMED, CP_PARSER_DECLARATOR_NAMED,
/*ctor_dtor_or_conv_p=*/NULL, /*ctor_dtor_or_conv_p=*/NULL,
/*parenthesized_p=*/NULL, /*parenthesized_p=*/NULL,
/*member_p=*/false); /*member_p=*/false,
/*friend_p=*/false);
attributes = cp_parser_attributes_opt (parser); attributes = cp_parser_attributes_opt (parser);
asm_specification = cp_parser_asm_specification_opt (parser); asm_specification = cp_parser_asm_specification_opt (parser);
......
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> 2014-06-11 Richard Biener <rguenther@suse.de>
PR tree-optimization/61452 PR tree-optimization/61452
......
// PR c++/19200
namespace N {
void S();
}
struct S {
friend void N::S();
};
...@@ -17,16 +17,16 @@ struct B ...@@ -17,16 +17,16 @@ struct B
struct C 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 (); // { 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 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 () {} // { 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 struct E
......
// PR c++/19200
struct S {
struct T{};
friend void S(T);
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment