This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH: PR 29138


This patch fixes PR c++/29138, a rejects-valid regression in the C++
front-end.  Old-style "access declarations" didn't work when the
declaration referred to a type, rather than to a data or function
member.  The reason was that the access-declaration code was in
grokfield, and that's not used for types.  This patch fixes the
problem by having the parser detect access declarations as a grammar
rule, thereby handling types and non-types identically.

Tested on x86_64-unknown-linux-gnu, applied on the mainline and on the
4.1 branch.

--
Mark Mitchell
CodeSourcery
mark@codesourcery.com
(650) 331-3385 x713

2006-10-03  Mark Mitchell  <mark@codesourcery.com>

	PR c++/29138
	* decl2.c (grokfield): Don't handle access declarations here.
	* parser.c (cp_parser_using_declaration): Handle access
	declarations too.
	(cp_parser_block_declaration): Adjust calls to
	cp_parser_using_declaration.
	(cp_parser_member_declaration): Likewise.  Use
	cp_parser_using_declaration to look for access_declarations.

2006-10-03  Mark Mitchell  <mark@codesourcery.com>

	PR c++/29138
	* g++.dg/inherit/access8.C: New test.
	* g++.dg/template/dtor4.C: Tweak error messages.

Index: gcc/cp/decl2.c
===================================================================
--- gcc/cp/decl2.c	(revision 117359)
+++ gcc/cp/decl2.c	(working copy)
@@ -769,16 +769,6 @@ grokfield (const cp_declarator *declarat
   const char *asmspec = 0;
   int flags = LOOKUP_ONLYCONVERTING;
 
-  if (!declspecs->any_specifiers_p
-      && declarator->kind == cdk_id
-      && declarator->u.id.qualifying_scope
-      && TYPE_P (declarator->u.id.qualifying_scope)
-      && IS_AGGR_TYPE (declarator->u.id.qualifying_scope)
-      && TREE_CODE (declarator->u.id.unqualified_name) == IDENTIFIER_NODE)
-    /* Access declaration */
-    return do_class_using_decl (declarator->u.id.qualifying_scope,
-				declarator->u.id.unqualified_name);
-
   if (init
       && TREE_CODE (init) == TREE_LIST
       && TREE_VALUE (init) == error_mark_node
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 117360)
+++ gcc/cp/parser.c	(working copy)
@@ -1518,8 +1518,8 @@ static tree cp_parser_qualified_namespac
   (cp_parser *);
 static void cp_parser_namespace_alias_definition
   (cp_parser *);
-static void cp_parser_using_declaration
-  (cp_parser *);
+static bool cp_parser_using_declaration
+  (cp_parser *, bool);
 static void cp_parser_using_directive
   (cp_parser *);
 static void cp_parser_asm_definition
@@ -7184,7 +7184,8 @@ cp_parser_block_declaration (cp_parser *
 	cp_parser_using_directive (parser);
       /* Otherwise, it's a using-declaration.  */
       else
-	cp_parser_using_declaration (parser);
+	cp_parser_using_declaration (parser,
+				     /*access_declaration_p=*/false);
     }
   /* If the next keyword is `__label__' we have a label declaration.  */
   else if (token1->keyword == RID_LABEL)
@@ -10582,14 +10583,21 @@ cp_parser_qualified_namespace_specifier 
   return cp_parser_namespace_name (parser);
 }
 
-/* Parse a using-declaration.
+/* Parse a using-declaration, or, if ACCESS_DECLARATION_P is true, an
+   access declaration.
 
    using-declaration:
      using typename [opt] :: [opt] nested-name-specifier unqualified-id ;
-     using :: unqualified-id ;  */
+     using :: unqualified-id ;  
 
-static void
-cp_parser_using_declaration (cp_parser* parser)
+   access-declaration:
+     qualified-id ;  
+
+   */
+
+static bool
+cp_parser_using_declaration (cp_parser* parser, 
+			     bool access_declaration_p)
 {
   cp_token *token;
   bool typename_p = false;
@@ -10598,18 +10606,23 @@ cp_parser_using_declaration (cp_parser* 
   tree identifier;
   tree qscope;
 
-  /* Look for the `using' keyword.  */
-  cp_parser_require_keyword (parser, RID_USING, "`using'");
-
-  /* Peek at the next token.  */
-  token = cp_lexer_peek_token (parser->lexer);
-  /* See if it's `typename'.  */
-  if (token->keyword == RID_TYPENAME)
+  if (access_declaration_p)
+    cp_parser_parse_tentatively (parser);
+  else
     {
-      /* Remember that we've seen it.  */
-      typename_p = true;
-      /* Consume the `typename' token.  */
-      cp_lexer_consume_token (parser->lexer);
+      /* Look for the `using' keyword.  */
+      cp_parser_require_keyword (parser, RID_USING, "`using'");
+      
+      /* Peek at the next token.  */
+      token = cp_lexer_peek_token (parser->lexer);
+      /* See if it's `typename'.  */
+      if (token->keyword == RID_TYPENAME)
+	{
+	  /* Remember that we've seen it.  */
+	  typename_p = true;
+	  /* Consume the `typename' token.  */
+	  cp_lexer_consume_token (parser->lexer);
+	}
     }
 
   /* Look for the optional global scope qualification.  */
@@ -10643,6 +10656,14 @@ cp_parser_using_declaration (cp_parser* 
 					 /*declarator_p=*/true,
 					 /*optional_p=*/false);
 
+  if (access_declaration_p)
+    {
+      if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+	cp_parser_simulate_error (parser);
+      if (!cp_parser_parse_definitely (parser))
+	return false;
+    }
+
   /* The function we call to handle a using-declaration is different
      depending on what scope we are in.  */
   if (qscope == error_mark_node || identifier == error_mark_node)
@@ -10676,6 +10697,8 @@ cp_parser_using_declaration (cp_parser* 
 
   /* Look for the final `;'.  */
   cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+  
+  return true;
 }
 
 /* Parse a using-directive.
@@ -13551,8 +13574,8 @@ cp_parser_member_declaration (cp_parser*
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_USING))
     {
       /* Parse the using-declaration.  */
-      cp_parser_using_declaration (parser);
-
+      cp_parser_using_declaration (parser,
+				   /*access_declaration_p=*/false);
       return;
     }
 
@@ -13572,6 +13595,9 @@ cp_parser_member_declaration (cp_parser*
       return;
     }
 
+  if (cp_parser_using_declaration (parser, /*access_declaration=*/true))
+    return;
+
   /* Parse the decl-specifier-seq.  */
   cp_parser_decl_specifier_seq (parser,
 				CP_PARSER_FLAGS_OPTIONAL,
Index: gcc/testsuite/g++.dg/inherit/access8.C
===================================================================
--- gcc/testsuite/g++.dg/inherit/access8.C	(revision 0)
+++ gcc/testsuite/g++.dg/inherit/access8.C	(revision 0)
@@ -0,0 +1,25 @@
+// PR c++/29138
+
+class A
+{
+public:
+  int i;
+  class A1
+  {
+    int j;
+  };
+};
+
+class B : private A
+{
+public:
+  A::i;
+  A::A1;
+};
+
+void
+f ()
+{
+  B b;
+  B::A1 a1;
+}
Index: gcc/testsuite/g++.dg/template/dtor4.C
===================================================================
--- gcc/testsuite/g++.dg/template/dtor4.C	(revision 117384)
+++ gcc/testsuite/g++.dg/template/dtor4.C	(working copy)
@@ -5,5 +5,5 @@
 
 template<int> struct A
 {
-  ~A<0>(); // { dg-error "declaration" }
+  ~A<0>(); // { dg-error "parse error|declaration" }
 };


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]