From: Mark Mitchell Date: Wed, 17 May 2006 17:24:00 +0000 (+0000) Subject: re PR c++/26068 (extern "C" static function should not be allowed) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=bfce0853962267886bd1fc10ac9a579eda2b8f4f;p=gcc.git re PR c++/26068 (extern "C" static function should not be allowed) 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 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b54dfb84742..3c93c355f1a 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2006-05-17 Mark Mitchell + + 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 PR c++/27491 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 28c5007dafc..c6124835599 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -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 %"); - 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 %"); - 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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3fe62f4c58f..b5f5dca0355 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2006-05-17 Mark Mitchell + + 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 PR tree-optimization/27548 diff --git a/gcc/testsuite/g++.dg/opt/pr17697-3.C b/gcc/testsuite/g++.dg/opt/pr17697-3.C index fa7cff0a49f..630441c25f7 100644 --- a/gcc/testsuite/g++.dg/opt/pr17697-3.C +++ b/gcc/testsuite/g++.dg/opt/pr17697-3.C @@ -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 index 00000000000..4a0d8942e52 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/linkage1.C @@ -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(); +}