aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/parser.c')
-rw-r--r--gcc/cp/parser.c118
1 files changed, 72 insertions, 46 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 07f76e3..52a152d 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -2248,12 +2248,12 @@ static tree cp_parser_trait_expr
static bool cp_parser_declares_only_class_p
(cp_parser *);
static void cp_parser_set_storage_class
- (cp_parser *, cp_decl_specifier_seq *, enum rid, location_t);
+ (cp_parser *, cp_decl_specifier_seq *, enum rid, cp_token *);
static void cp_parser_set_decl_spec_type
- (cp_decl_specifier_seq *, tree, location_t, bool);
+ (cp_decl_specifier_seq *, tree, cp_token *, bool);
static void set_and_check_decl_spec_loc
(cp_decl_specifier_seq *decl_specs,
- cp_decl_spec ds, source_location location);
+ cp_decl_spec ds, cp_token *);
static bool cp_parser_friend_p
(const cp_decl_specifier_seq *);
static void cp_parser_required_error
@@ -10821,7 +10821,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
/* Set the storage class anyway. */
cp_parser_set_storage_class (parser, decl_specs, RID_AUTO,
- token->location);
+ token);
}
else
/* C++0x auto type-specifier. */
@@ -10835,7 +10835,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
/* Consume the token. */
cp_lexer_consume_token (parser->lexer);
cp_parser_set_storage_class (parser, decl_specs, token->keyword,
- token->location);
+ token);
break;
case RID_THREAD:
/* Consume the token. */
@@ -10855,7 +10855,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
error ("decl-specifier invalid in condition");
if (ds != ds_last)
- set_and_check_decl_spec_loc (decl_specs, ds, token->location);
+ set_and_check_decl_spec_loc (decl_specs, ds, token);
/* Constructors are a special case. The `S' in `S()' is not a
decl-specifier; it is the beginning of the declarator. */
@@ -11004,7 +11004,7 @@ cp_parser_function_specifier_opt (cp_parser* parser,
switch (token->keyword)
{
case RID_INLINE:
- set_and_check_decl_spec_loc (decl_specs, ds_inline, token->location);
+ set_and_check_decl_spec_loc (decl_specs, ds_inline, token);
break;
case RID_VIRTUAL:
@@ -11013,11 +11013,11 @@ cp_parser_function_specifier_opt (cp_parser* parser,
A member function template shall not be virtual. */
if (PROCESSING_REAL_TEMPLATE_DECL_P ())
error_at (token->location, "templates may not be %<virtual%>");
- set_and_check_decl_spec_loc (decl_specs, ds_virtual, token->location);
+ set_and_check_decl_spec_loc (decl_specs, ds_virtual, token);
break;
case RID_EXPLICIT:
- set_and_check_decl_spec_loc (decl_specs, ds_explicit, token->location);
+ set_and_check_decl_spec_loc (decl_specs, ds_explicit, token);
break;
default:
@@ -13525,7 +13525,7 @@ cp_parser_type_specifier (cp_parser* parser,
if (decl_specs)
cp_parser_set_decl_spec_type (decl_specs,
type_spec,
- token->location,
+ token,
/*type_definition_p=*/true);
return type_spec;
}
@@ -13554,7 +13554,7 @@ cp_parser_type_specifier (cp_parser* parser,
if (decl_specs)
cp_parser_set_decl_spec_type (decl_specs,
type_spec,
- token->location,
+ token,
/*type_definition_p=*/true);
return type_spec;
}
@@ -13576,7 +13576,7 @@ cp_parser_type_specifier (cp_parser* parser,
if (decl_specs)
cp_parser_set_decl_spec_type (decl_specs,
type_spec,
- token->location,
+ token,
/*type_definition_p=*/false);
return type_spec;
@@ -13612,7 +13612,7 @@ cp_parser_type_specifier (cp_parser* parser,
{
if (decl_specs)
{
- set_and_check_decl_spec_loc (decl_specs, ds, token->location);
+ set_and_check_decl_spec_loc (decl_specs, ds, token);
decl_specs->any_specifiers_p = true;
}
return cp_lexer_consume_token (parser->lexer)->u.value;
@@ -13703,7 +13703,7 @@ cp_parser_simple_type_specifier (cp_parser* parser,
type = boolean_type_node;
break;
case RID_SHORT:
- set_and_check_decl_spec_loc (decl_specs, ds_short, token->location);
+ set_and_check_decl_spec_loc (decl_specs, ds_short, token);
type = short_integer_type_node;
break;
case RID_INT:
@@ -13720,15 +13720,15 @@ cp_parser_simple_type_specifier (cp_parser* parser,
break;
case RID_LONG:
if (decl_specs)
- set_and_check_decl_spec_loc (decl_specs, ds_long, token->location);
+ set_and_check_decl_spec_loc (decl_specs, ds_long, token);
type = long_integer_type_node;
break;
case RID_SIGNED:
- set_and_check_decl_spec_loc (decl_specs, ds_signed, token->location);
+ set_and_check_decl_spec_loc (decl_specs, ds_signed, token);
type = integer_type_node;
break;
case RID_UNSIGNED:
- set_and_check_decl_spec_loc (decl_specs, ds_unsigned, token->location);
+ set_and_check_decl_spec_loc (decl_specs, ds_unsigned, token);
type = unsigned_type_node;
break;
case RID_FLOAT:
@@ -13766,7 +13766,7 @@ cp_parser_simple_type_specifier (cp_parser* parser,
if (decl_specs)
cp_parser_set_decl_spec_type (decl_specs, type,
- token->location,
+ token,
/*type_definition_p=*/false);
return type;
@@ -13775,7 +13775,7 @@ cp_parser_simple_type_specifier (cp_parser* parser,
type = cp_parser_trait_expr (parser, RID_UNDERLYING_TYPE);
if (decl_specs)
cp_parser_set_decl_spec_type (decl_specs, type,
- token->location,
+ token,
/*type_definition_p=*/false);
return type;
@@ -13785,7 +13785,7 @@ cp_parser_simple_type_specifier (cp_parser* parser,
type = cp_parser_trait_expr (parser, token->keyword);
if (decl_specs)
cp_parser_set_decl_spec_type (decl_specs, type,
- token->location,
+ token,
/*type_definition_p=*/false);
return type;
default:
@@ -13800,7 +13800,7 @@ cp_parser_simple_type_specifier (cp_parser* parser,
type = token->u.value;
if (decl_specs)
cp_parser_set_decl_spec_type (decl_specs, type,
- token->location,
+ token,
/*type_definition_p=*/false);
cp_lexer_consume_token (parser->lexer);
return type;
@@ -13817,7 +13817,7 @@ cp_parser_simple_type_specifier (cp_parser* parser,
&& token->keyword != RID_LONG))
cp_parser_set_decl_spec_type (decl_specs,
type,
- token->location,
+ token,
/*type_definition_p=*/false);
if (decl_specs)
decl_specs->any_specifiers_p = true;
@@ -13894,7 +13894,7 @@ cp_parser_simple_type_specifier (cp_parser* parser,
type = NULL_TREE;
if (type && decl_specs)
cp_parser_set_decl_spec_type (decl_specs, type,
- token->location,
+ token,
/*type_definition_p=*/false);
}
@@ -15245,21 +15245,24 @@ static tree
cp_parser_alias_declaration (cp_parser* parser)
{
tree id, type, decl, pushed_scope = NULL_TREE, attributes;
- location_t id_location, using_location, attrs_location = 0;
+ location_t id_location;
cp_declarator *declarator;
cp_decl_specifier_seq decl_specs;
bool member_p;
const char *saved_message = NULL;
/* Look for the `using' keyword. */
- using_location = cp_lexer_peek_token (parser->lexer)->location;
- cp_parser_require_keyword (parser, RID_USING, RT_USING);
+ cp_token *using_token
+ = cp_parser_require_keyword (parser, RID_USING, RT_USING);
+ if (using_token == NULL)
+ return error_mark_node;
+
id_location = cp_lexer_peek_token (parser->lexer)->location;
id = cp_parser_identifier (parser);
if (id == error_mark_node)
return error_mark_node;
- attrs_location = cp_lexer_peek_token (parser->lexer)->location;
+ cp_token *attrs_token = cp_lexer_peek_token (parser->lexer);
attributes = cp_parser_attributes_opt (parser);
if (attributes == error_mark_node)
return error_mark_node;
@@ -15316,14 +15319,14 @@ cp_parser_alias_declaration (cp_parser* parser)
decl_specs.attributes = attributes;
set_and_check_decl_spec_loc (&decl_specs,
ds_attribute,
- attrs_location);
+ attrs_token);
}
set_and_check_decl_spec_loc (&decl_specs,
ds_typedef,
- using_location);
+ using_token);
set_and_check_decl_spec_loc (&decl_specs,
ds_alias,
- using_location);
+ using_token);
declarator = make_id_declarator (NULL_TREE, id, sfk_none);
declarator->id_loc = id_location;
@@ -22585,13 +22588,13 @@ static void
cp_parser_set_storage_class (cp_parser *parser,
cp_decl_specifier_seq *decl_specs,
enum rid keyword,
- location_t location)
+ cp_token *token)
{
cp_storage_class storage_class;
if (parser->in_unbraced_linkage_specification_p)
{
- error_at (location, "invalid use of %qD in linkage specification",
+ error_at (token->location, "invalid use of %qD in linkage specification",
ridpointers[keyword]);
return;
}
@@ -22602,11 +22605,11 @@ cp_parser_set_storage_class (cp_parser *parser,
}
if ((keyword == RID_EXTERN || keyword == RID_STATIC)
- && decl_spec_seq_has_spec_p (decl_specs, ds_thread))
+ && decl_spec_seq_has_spec_p (decl_specs, ds_thread)
+ && decl_specs->gnu_thread_keyword_p)
{
- error_at (decl_specs->locations[ds_thread],
+ pedwarn (decl_specs->locations[ds_thread], 0,
"%<__thread%> before %qD", ridpointers[keyword]);
- decl_specs->locations[ds_thread] = 0;
}
switch (keyword)
@@ -22630,7 +22633,7 @@ cp_parser_set_storage_class (cp_parser *parser,
gcc_unreachable ();
}
decl_specs->storage_class = storage_class;
- set_and_check_decl_spec_loc (decl_specs, ds_storage_class, location);
+ set_and_check_decl_spec_loc (decl_specs, ds_storage_class, token);
/* A storage class specifier cannot be applied alongside a typedef
specifier. If there is a typedef specifier present then set
@@ -22646,7 +22649,7 @@ cp_parser_set_storage_class (cp_parser *parser,
static void
cp_parser_set_decl_spec_type (cp_decl_specifier_seq *decl_specs,
tree type_spec,
- location_t location,
+ cp_token *token,
bool type_definition_p)
{
decl_specs->any_specifiers_p = true;
@@ -22671,12 +22674,12 @@ cp_parser_set_decl_spec_type (cp_decl_specifier_seq *decl_specs,
decl_specs->redefined_builtin_type = type_spec;
set_and_check_decl_spec_loc (decl_specs,
ds_redefined_builtin_type_spec,
- location);
+ token);
if (!decl_specs->type)
{
decl_specs->type = type_spec;
decl_specs->type_definition_p = false;
- set_and_check_decl_spec_loc (decl_specs,ds_type_spec, location);
+ set_and_check_decl_spec_loc (decl_specs,ds_type_spec, token);
}
}
else if (decl_specs->type)
@@ -22686,10 +22689,19 @@ cp_parser_set_decl_spec_type (cp_decl_specifier_seq *decl_specs,
decl_specs->type = type_spec;
decl_specs->type_definition_p = type_definition_p;
decl_specs->redefined_builtin_type = NULL_TREE;
- set_and_check_decl_spec_loc (decl_specs, ds_type_spec, location);
+ set_and_check_decl_spec_loc (decl_specs, ds_type_spec, token);
}
}
+/* True iff TOKEN is the GNU keyword __thread. */
+
+static bool
+token_is__thread (cp_token *token)
+{
+ gcc_assert (token->keyword == RID_THREAD);
+ return !strcmp (IDENTIFIER_POINTER (token->u.value), "__thread");
+}
+
/* Set the location for a declarator specifier and check if it is
duplicated.
@@ -22704,15 +22716,21 @@ cp_parser_set_decl_spec_type (cp_decl_specifier_seq *decl_specs,
static void
set_and_check_decl_spec_loc (cp_decl_specifier_seq *decl_specs,
- cp_decl_spec ds, source_location location)
+ cp_decl_spec ds, cp_token *token)
{
gcc_assert (ds < ds_last);
if (decl_specs == NULL)
return;
+ source_location location = token->location;
+
if (decl_specs->locations[ds] == 0)
- decl_specs->locations[ds] = location;
+ {
+ decl_specs->locations[ds] = location;
+ if (ds == ds_thread)
+ decl_specs->gnu_thread_keyword_p = token_is__thread (token);
+ }
else
{
if (ds == ds_long)
@@ -22728,6 +22746,15 @@ set_and_check_decl_spec_loc (cp_decl_specifier_seq *decl_specs,
"ISO C++ 1998 does not support %<long long%>");
}
}
+ else if (ds == ds_thread)
+ {
+ bool gnu = token_is__thread (token);
+ if (gnu != decl_specs->gnu_thread_keyword_p)
+ error_at (location,
+ "both %<__thread%> and %<thread_local%> specified");
+ else
+ error_at (location, "duplicate %qD", token->u.value);
+ }
else
{
static const char *const decl_spec_names[] = {
@@ -22745,8 +22772,7 @@ set_and_check_decl_spec_loc (cp_decl_specifier_seq *decl_specs,
"typedef",
"using",
"constexpr",
- "__complex",
- "__thread"
+ "__complex"
};
error_at (location,
"duplicate %qs", decl_spec_names[ds]);
@@ -24587,7 +24613,7 @@ cp_parser_objc_class_ivars (cp_parser* parser)
declspecs.storage_class = sc_none;
}
- /* __thread. */
+ /* thread_local. */
if (decl_spec_seq_has_spec_p (&declspecs, ds_thread))
{
cp_parser_error (parser, "invalid type for instance variable");
@@ -25166,7 +25192,7 @@ cp_parser_objc_struct_declaration (cp_parser *parser)
declspecs.storage_class = sc_none;
}
- /* __thread. */
+ /* thread_local. */
if (decl_spec_seq_has_spec_p (&declspecs, ds_thread))
{
cp_parser_error (parser, "invalid type for property");