re PR c++/26068 (extern "C" static function should not be allowed)
authorMark Mitchell <mark@codesourcery.com>
Wed, 17 May 2006 17:24:00 +0000 (17:24 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Wed, 17 May 2006 17:24:00 +0000 (17:24 +0000)
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.
PR c++/26068
* g++.dg/opt/pr17697-3.C: Remove invalid extern specifier.
* g++.dg/parse/linkage1.C: New test.

From-SVN: r113869

gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/opt/pr17697-3.C
gcc/testsuite/g++.dg/parse/linkage1.C [new file with mode: 0644]

index b54dfb8474254f6f17ba13788e5c3b76e0b6657c..3c93c355f1a4f51f1cacdda402f0ef63d4bc01ed 100644 (file)
@@ -1,3 +1,12 @@
+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  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/27491
index 28c5007dafce60b1bd886092debbf4100ac460ae..c6124835599548949b4be862ddd85098c5c5df10 100644 (file)
@@ -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* 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_parser *parser)
          || 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 3fe62f4c58f748cc0397616cf5d827da006b5195..b5f5dca03557ca525c96e9b544089a2937183e15 100644 (file)
@@ -1,3 +1,9 @@
+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.
+
 2006-05-17  Jakub Jelinek  <jakub@redhat.com>
 
        PR tree-optimization/27548
index fa7cff0a49fdf9a03649b2aca8e8ea78e9d462be..630441c25f78f970f64338ff06ca7db4d2f12b4a 100644 (file)
@@ -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
 {
diff --git a/gcc/testsuite/g++.dg/parse/linkage1.C b/gcc/testsuite/g++.dg/parse/linkage1.C
new file mode 100644 (file)
index 0000000..4a0d894
--- /dev/null
@@ -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();
+}