mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-22 15:00:55 +08:00
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
This commit is contained in:
parent
b9cebd5026
commit
bfce085396
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
{
|
||||
|
11
gcc/testsuite/g++.dg/parse/linkage1.C
Normal file
11
gcc/testsuite/g++.dg/parse/linkage1.C
Normal file
@ -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();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user