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 26068


This patch fixes PR c++/26068.  We were accepting additional storage
classes within an unbraced linkage-specification.

Tested on x86_64-unknown-linux-gnu, applied on the mainline.  I'll
apply to 4.1 after 4.1.1 is out.

--
Mark Mitchell
CodeSourcery
mark@codesourcery.com
(650) 331-3385 x713
  
2006-05-17  Mark Mitchell  <mark@codesourcery.com>

	PR c++/26068
	* parser.c (cp_parser_set_storage_class): Check for 
	invalid uses of storage classes on unbraced linkage
	specifications.
	(cp_parser_decl_specifier_seq): Pass keywords, not storage classes,
	to cp_parser_set_storage_class.

2006-05-17  Mark Mitchell  <mark@codesourcery.com>

	PR c++/26068
	* g++.dg/opt/pr17697-3.C: Remove invalid extern specifier.
	* g++.dg/parse/linkage1.C: New test.

Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 113819)
+++ gcc/cp/parser.c	(working copy)
@@ -1747,7 +1747,7 @@ static tree cp_parser_sizeof_operand
 static bool cp_parser_declares_only_class_p
   (cp_parser *);
 static void cp_parser_set_storage_class
-  (cp_decl_specifier_seq *, cp_storage_class);
+  (cp_parser *, cp_decl_specifier_seq *, enum rid);
 static void cp_parser_set_decl_spec_type
   (cp_decl_specifier_seq *, tree, bool);
 static bool cp_parser_friend_p
@@ -7463,39 +7463,13 @@ cp_parser_decl_specifier_seq (cp_parser*
 	     GNU Extension:
 	       thread  */
 	case RID_AUTO:
-	  /* Consume the token.  */
-	  cp_lexer_consume_token (parser->lexer);
-	  cp_parser_set_storage_class (decl_specs, sc_auto);
-	  break;
 	case RID_REGISTER:
-	  /* Consume the token.  */
-	  cp_lexer_consume_token (parser->lexer);
-	  cp_parser_set_storage_class (decl_specs, sc_register);
-	  break;
 	case RID_STATIC:
-	  /* Consume the token.  */
-	  cp_lexer_consume_token (parser->lexer);
-	  if (decl_specs->specs[(int) ds_thread])
-	    {
-	      error ("%<__thread%> before %<static%>");
-	      decl_specs->specs[(int) ds_thread] = 0;
-	    }
-	  cp_parser_set_storage_class (decl_specs, sc_static);
-	  break;
 	case RID_EXTERN:
-	  /* Consume the token.  */
-	  cp_lexer_consume_token (parser->lexer);
-	  if (decl_specs->specs[(int) ds_thread])
-	    {
-	      error ("%<__thread%> before %<extern%>");
-	      decl_specs->specs[(int) ds_thread] = 0;
-	    }
-	  cp_parser_set_storage_class (decl_specs, sc_extern);
-	  break;
 	case RID_MUTABLE:
 	  /* Consume the token.  */
 	  cp_lexer_consume_token (parser->lexer);
-	  cp_parser_set_storage_class (decl_specs, sc_mutable);
+	  cp_parser_set_storage_class (parser, decl_specs, token->keyword);
 	  break;
 	case RID_THREAD:
 	  /* Consume the token.  */
@@ -16133,16 +16107,56 @@ cp_parser_declares_only_class_p (cp_pars
 	  || cp_lexer_next_token_is (parser->lexer, CPP_COMMA));
 }
 
-/* Update the DECL_SPECS to reflect the STORAGE_CLASS.  */
+/* Update the DECL_SPECS to reflect the storage class indicated by
+   KEYWORD.  */
 
 static void
-cp_parser_set_storage_class (cp_decl_specifier_seq *decl_specs,
-			     cp_storage_class storage_class)
+cp_parser_set_storage_class (cp_parser *parser,
+			     cp_decl_specifier_seq *decl_specs,
+			     enum rid keyword)
 {
-  if (decl_specs->storage_class != sc_none)
-    decl_specs->multiple_storage_classes_p = true;
-  else
-    decl_specs->storage_class = storage_class;
+  cp_storage_class storage_class;
+
+  if (parser->in_unbraced_linkage_specification_p)
+    {
+      error ("invalid use of %qD in linkage specification",
+	     ridpointers[keyword]);
+      return;
+    }
+  else if (decl_specs->storage_class != sc_none)
+    {
+      decl_specs->multiple_storage_classes_p = true;
+      return;
+    }
+
+  if ((keyword == RID_EXTERN || keyword == RID_STATIC)
+      && decl_specs->specs[(int) ds_thread])
+    {
+      error ("%<__thread%> before %qD", ridpointers[keyword]);
+      decl_specs->specs[(int) ds_thread] = 0;
+    }
+
+  switch (keyword) 
+    {
+    case RID_AUTO:
+      storage_class = sc_auto;
+      break;
+    case RID_REGISTER:
+      storage_class = sc_register;
+      break;
+    case RID_STATIC:
+      storage_class = sc_static;
+      break;
+    case RID_EXTERN:
+      storage_class = sc_extern;
+      break;
+    case RID_MUTABLE:
+      storage_class = sc_mutable;
+      break;
+    default:
+      gcc_unreachable ();
+    }
+  decl_specs->storage_class = storage_class;
 }
 
 /* Update the DECL_SPECS to reflect the TYPE_SPEC.  If USER_DEFINED_P
Index: gcc/testsuite/g++.dg/opt/pr17697-3.C
===================================================================
--- gcc/testsuite/g++.dg/opt/pr17697-3.C	(revision 113765)
+++ gcc/testsuite/g++.dg/opt/pr17697-3.C	(working copy)
@@ -2,7 +2,7 @@
 // { dg-do run }
 // { dg-options "-O2" }
 
-extern "C" extern int strcmp (const char *s, const char *t);
+extern "C" int strcmp (const char *s, const char *t);
 
 namespace A
 {
Index: gcc/testsuite/g++.dg/parse/linkage1.C
===================================================================
--- gcc/testsuite/g++.dg/parse/linkage1.C	(revision 0)
+++ gcc/testsuite/g++.dg/parse/linkage1.C	(revision 0)
@@ -0,0 +1,11 @@
+// PR c++/26068
+
+extern "C" auto int a; // { dg-error "linkage" }
+extern "C" register int b; // { dg-error "linkage" }
+extern "C" static void c(); // { dg-error "linkage" }
+extern "C" extern void d(); // { dg-error "linkage" }
+extern "C" mutable int e; // { dg-error "linkage" }
+
+extern "C" {
+  static void f();
+}


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