This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: PR 26068
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 17 May 2006 10:24:55 -0700
- Subject: C++ PATCH: PR 26068
- Reply-to: mark at codesourcery dot com
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();
+}