diff options
Diffstat (limited to 'gcc/cp/parser.c')
-rw-r--r-- | gcc/cp/parser.c | 40 |
1 files changed, 38 insertions, 2 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index bba4d25..37df311 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -7330,6 +7330,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser, int* declares_class_or_enum) { bool constructor_possible_p = !parser->in_declarator_p; + cp_decl_spec ds; /* Clear DECL_SPECS. */ clear_decl_specs (decl_specs); @@ -7364,8 +7365,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser, /* decl-specifier: friend */ case RID_FRIEND: - if (decl_specs->specs[(int) ds_friend]++) - error ("duplicate %<friend%>"); + ++decl_specs->specs[(int) ds_friend]; /* Consume the token. */ cp_lexer_consume_token (parser->lexer); break; @@ -7531,6 +7531,42 @@ cp_parser_decl_specifier_seq (cp_parser* parser, flags |= CP_PARSER_FLAGS_OPTIONAL; } + /* Check for repeated decl-specifiers. */ + for (ds = ds_first; ds != ds_last; ++ds) + { + unsigned count = decl_specs->specs[(int)ds]; + if (count < 2) + continue; + /* The "long" specifier is a special case because of "long long". */ + if (ds == ds_long) + { + if (count > 2) + error ("%<long long long%> is too long for GCC"); + else if (pedantic && !in_system_header && warn_long_long) + pedwarn ("ISO C++ does not support %<long long%>"); + } + else if (count > 1) + { + static const char *const decl_spec_names[] = { + "signed", + "unsigned", + "short", + "long", + "const", + "volatile", + "restrict", + "inline", + "virtual", + "explicit", + "friend", + "typedef", + "__complex", + "__thread" + }; + error ("duplicate %qs", decl_spec_names[(int)ds]); + } + } + /* Don't allow a friend specifier with a class definition. */ if (decl_specs->specs[(int) ds_friend] != 0 && (*declares_class_or_enum & 2)) |