re PR c++/19200 (Friend declaration misinterpreted as constructor)
authorPaolo Carlini <paolo@gcc.gnu.org>
Wed, 11 Jun 2014 15:16:45 +0000 (15:16 +0000)
committerPaolo Carlini <paolo@gcc.gnu.org>
Wed, 11 Jun 2014 15:16:45 +0000 (15:16 +0000)
/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

gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/parse/friend10.C [new file with mode: 0644]
gcc/testsuite/g++.dg/parse/friend7.C
gcc/testsuite/g++.dg/parse/friend9.C [new file with mode: 0644]

index 35aa7bf..e330f73 100644 (file)
@@ -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.
index 13b5d0b..08f621a 100644 (file)
@@ -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
index 7d574d0..22d7ba6 100644 (file)
@@ -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);
 
index c586b44..1250218 100644 (file)
@@ -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 (file)
index 0000000..16c2e0a
--- /dev/null
@@ -0,0 +1,9 @@
+// PR c++/19200
+
+namespace N {
+  void S();
+}
+
+struct S {
+  friend void N::S();
+};
index 668fd35..72ab430 100644 (file)
@@ -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 (file)
index 0000000..dd6729f
--- /dev/null
@@ -0,0 +1,6 @@
+// PR c++/19200
+
+struct S {
+  struct T{};
+  friend void S(T);
+};