Patchwork [c++] fix PR 46890, parsing regression

login
register
mail settings
Submitter Nathan Froyd
Date Dec. 17, 2010, 5:20 p.m.
Message ID <20101217172046.GK25059@nightcrawler>
Download mbox | patch
Permalink /patch/75926/
State New
Headers show

Comments

Nathan Froyd - Dec. 17, 2010, 5:20 p.m.
The patch below fixes PR 46890, where we were presented with:

struct MdatResource {
const char *mdatAlloc;
} const *_resource;

which is valid, and we incorrectly complained.  This regression was
introduced by a logic error of mine.  If we have a storage class
specifier or a type qualifier after a class definition, then to
determine whether we want a semicolon, the next token must be a keyword
and a known starter for a type specifier.  The previous logic considered
only keywords and names for turning off the semicolon error.

Since I was in the neighborhood, I also took the opportunity to fix the
similar:

struct C { char *p } typedef C_t;

case.  I suppose I could have added RID_TYPEDEF to
keyword_is_storage_class_specifier; I will do so if future uses of said
function prove to require separate checks for RID_TYPEDEF.

Tested on x86_64-unknown-linux-gnu.  OK to commit?

-Nathan

gcc/cp/
	PR c++/46890
	* parser.c (cp_parser_class_specifier): Add RID_TYPEDEF to
	lookahead logic and fix setting of want_semicolon.

gcc/testsuite/
	PR c++/46890
	* g++.dg/pr46890.C: New test.
	* g++.dg/parse/semicolon.C: Add new cases.
Jason Merrill - Jan. 5, 2011, 7:39 p.m.
On 12/17/2010 12:20 PM, Nathan Froyd wrote:
> case.  I suppose I could have added RID_TYPEDEF to
> keyword_is_storage_class_specifier; I will do so if future uses of said
> function prove to require separate checks for RID_TYPEDEF.

How about keyword_is_decl_specifier?

Jason
Nathan Froyd - Jan. 21, 2011, 2:07 p.m.
On Wed, Jan 05, 2011 at 02:39:58PM -0500, Jason Merrill wrote:
> On 12/17/2010 12:20 PM, Nathan Froyd wrote:
>> case.  I suppose I could have added RID_TYPEDEF to
>> keyword_is_storage_class_specifier; I will do so if future uses of said
>> function prove to require separate checks for RID_TYPEDEF.
>
> How about keyword_is_decl_specifier?

That's a bit cryptic.  Do you mean adding keyword_is_decl_specifier to
c-family?

-Nathan
Jason Merrill - Jan. 21, 2011, 4:21 p.m.
On 01/21/2011 09:07 AM, Nathan Froyd wrote:
> On Wed, Jan 05, 2011 at 02:39:58PM -0500, Jason Merrill wrote:
>> On 12/17/2010 12:20 PM, Nathan Froyd wrote:
>>> case.  I suppose I could have added RID_TYPEDEF to
>>> keyword_is_storage_class_specifier; I will do so if future uses of said
>>> function prove to require separate checks for RID_TYPEDEF.
>>
>> How about keyword_is_decl_specifier?
>
> That's a bit cryptic.  Do you mean adding keyword_is_decl_specifier to
> c-family?

Yes, that's what I had in mind.  Let's have a predicate that does the 
test we want with a name that accurately describes it.

Jason

Patch

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 3e6930f..6ab3ec9 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -16959,17 +16959,16 @@  cp_parser_class_specifier (cp_parser* parser)
 	   static const <type> var = ...;  */
       case CPP_KEYWORD:
 	if (keyword_is_storage_class_specifier (token->keyword)
-	    || keyword_is_type_qualifier (token->keyword))
+	    || keyword_is_type_qualifier (token->keyword)
+	    || token->keyword == RID_TYPEDEF)
 	  {
 	    cp_token *lookahead = cp_lexer_peek_nth_token (parser->lexer, 2);
 
-	    if (lookahead->type == CPP_KEYWORD
-		&& !keyword_begins_type_specifier (lookahead->keyword))
-	      want_semicolon = false;
-	    else if (lookahead->type == CPP_NAME)
-	      /* Handling user-defined types here would be nice, but
-		 very tricky.  */
-	      want_semicolon = false;
+	    /* Handling user-defined types here would be nice, but very
+	       tricky.  */
+	    want_semicolon
+	      = (lookahead->type == CPP_KEYWORD
+		 && keyword_begins_type_specifier (lookahead->keyword));
 	  }
 	break;
       default:
diff --git a/gcc/testsuite/g++.dg/parse/semicolon3.C b/gcc/testsuite/g++.dg/parse/semicolon3.C
index a119ef4..bc43b48 100644
--- a/gcc/testsuite/g++.dg/parse/semicolon3.C
+++ b/gcc/testsuite/g++.dg/parse/semicolon3.C
@@ -62,6 +62,48 @@  autotest (void)
   return ok10.a;
 }
 
+struct OK11
+{
+  int a;
+} // no complaints
+  const *ok11_var;
+
+struct OK12
+{
+  int a;
+} // no complaints
+  const &ok12_var = *(new OK12());
+
+struct OK13
+{
+  int a;
+} // no complaints
+  static *ok13_var;
+
+class OK14
+{
+  struct OK14sub
+  {
+    int a;
+  } // no complaints
+    static &ok14_var;
+};
+
+class OK15
+{
+  int a;
+} typedef tOK15;
+
+class OK16
+{
+  int a;
+} typedef *pOK16;
+
+class OK17
+{
+  int a;
+} typedef &rOK16;
+
 struct E1
 {
   int a;
@@ -196,6 +238,13 @@  class E17
     mutable int i;
 } // { dg-error "after class definition" }
 
+class E18
+{
+  int a;
+} // { dg-error "after class definition" }
+
+typedef int E18int;
+
 /* This was the original test from the PR.  */
 
 class C0
diff --git a/gcc/testsuite/g++.dg/pr46890.C b/gcc/testsuite/g++.dg/pr46890.C
new file mode 100644
index 0000000..3ecef5a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr46890.C
@@ -0,0 +1,6 @@ 
+// PR c++/46890
+// { dg-do compile }
+
+struct MdatResource {
+const char *mdatAlloc;
+} const *_resource;