diff options
author | Dodji Seketeli <dodji@redhat.com> | 2012-05-16 10:51:15 +0000 |
---|---|---|
committer | Dodji Seketeli <dodji@gcc.gnu.org> | 2012-05-16 12:51:15 +0200 |
commit | 0b2c4be5fdff70f1babd503c9f6dbabd664c44c7 (patch) | |
tree | 866b6e9e6346cbd21ad2a4974753e1735d1f01b6 /gcc/cp/parser.c | |
parent | 40295cc722ce5ea0b7ba7b3cb91f6accce0db518 (diff) | |
download | gcc-0b2c4be5fdff70f1babd503c9f6dbabd664c44c7.zip gcc-0b2c4be5fdff70f1babd503c9f6dbabd664c44c7.tar.gz gcc-0b2c4be5fdff70f1babd503c9f6dbabd664c44c7.tar.bz2 |
PR preprocessor/7263 - Avoid pedantic warnings on system headers macro tokens
Now that we track token locations accross macro expansions, it would
be cool to be able to fix PR preprocessor/7263 for real. That is,
consider this example where we have a system header named header.h
like this:
#define _Complex __complex__ #define _Complex_I 1.0iF
and then a normal C file like this:
#include "header.h"
static _Complex float c = _Complex_I;
If we compile the file with -pedantic, the usages of _Complex or
_Complex_I should not trigger any warning, even though __complex__ and
the complex literal are extensions to the standard C.
They shouldn't trigger any warning because _Complex and _Complex_I are
defined in a system header (and expanded in normal user code).
To be able to handle this, we must address two separate concerns.
First, warnings about non-standard usage of numerical literals are emitted
directly from within libcpp. So we must teach libcpp's parser for numerical
literals to use virtual locations, instead of the spelling
location it uses today. Once we have that, as the diagnostics machinery
already knows how to avoid emitting errors happening on tokens that come from
system headers, we win.
Second, there is the issue of tracking locations for declaration
specifiers, like the "_Complex" in the declaration:
static _Complex float c;
For that, we need to arrange for each possible declaration specifier
to have its own location, because otherwise, we'd warn on e.g, on:
_Complex float c;
but not on:
static _Complex float c;
So this patch addresses the two concerns above. It's actually a
follow-up on an earlier patch[1] I wrote as part of my initial work on
virtual locations. We then agreed[2] that the second concern was
important to address before the patch could get a chance to go in.
[1]: http://gcc.gnu.org/ml/gcc-patches/2011-09/msg00957.html
[2]: http://gcc.gnu.org/ml/gcc-patches/2011-10/msg00264.html
Bootstrapped and tested on x86_64-unknown-linux-gnu against trunk.
libcpp/
PR preprocessor/7263
* include/cpplib.h (cpp_classify_number): Take a location
parameter.
* expr.c (SYNTAX_ERROR_AT, SYNTAX_ERROR2_AT): New diagnostic
macros that take a location parameter.
(cpp_classify_number): Take a (virtual) location parameter. Use
it for diagnostics. Adjust comments.
(eval_token): Take a location parameter. Pass it to
cpp_classify_number and to diagnostic routines.
(_cpp_parse_expr): Use virtual locations of tokens when parsing
expressions. Pass a virtual location to eval_token and to
diagnostic routines.
gcc/c-family/
PR preprocessor/7263
* c-lex.c (c_lex_with_flags): Pass a virtual location to the call
to cpp_classify_number. For diagnostics, use the precise location
instead of the global input_location.
gcc/
PR preprocessor/7263
* c-tree.h (enum c_declspec_word): Declare new enum.
(struct c_declspecs::locations): New member.
(declspecs_add_qual, declspecs_add_scspec)
(declspecs_add_addrspace, declspecs_add_alignas): Take a new
location parameter.
* c-decl.c (build_null_declspecs): Initialize the new struct
c_declspecs::locations member.
(declspecs_add_addrspace): Take a location parameter for the
address space. Store it onto declaration specifiers.
(declspecs_add_qual): Likewise, take a location parameter for the
qualifier.
(declspecs_add_type): Likewise, take a location parameter for the
type specifier.
(declspecs_add_scspec): Likewise, take a location parameter for
the storage class specifier.
(declspecs_add_attrs): Likewise, take a location parameter for the
first attribute.
(declspecs_add_alignas): Likewise, take a location parameter for
the alignas token.
(finish_declspecs): For diagnostics, use the location of the
relevant declspec, instead of the global input_location.
* c-parser.c (c_parser_parameter_declaration): Pass the precise
virtual location of the declspec to the declspecs-setters.
(c_parser_declspecs): Likewise. Avoid calling c_parser_peek_token
repeatedly.
gcc/cp/
PR preprocessor/7263
* cp-tree.h (enum cp_decl_spec): Add new enumerators to cover all
the possible declarator specifiers so far.
(struct cp_decl_specifier_seq::locations): Declare new member.
(cp_decl_specifier_seq::{specs, type_location}): Remove.
(decl_spec_seq_has_spec_p): Declare new function.
* parser.c (cp_parser_check_decl_spec): Remove.
(set_and_check_decl_spec_loc): Define new static function.
(decl_spec_seq_has_spec_p): Define new public function.
(cp_parser_decl_specifier_seq, cp_parser_function_specifier_opt)
(cp_parser_type_specifier, cp_parser_simple_type_specifier)
(cp_parser_set_storage_class, cp_parser_set_decl_spec_type)
(cp_parser_alias_declaration): Set the locations for each
declspec, using set_and_check_decl_spec_loc.
(cp_parser_explicit_instantiation, cp_parser_init_declarator)
(cp_parser_member_declaration, cp_parser_init_declarator): Use the
new declspec location for specifiers. Use the new
decl_spec_seq_has_spec_p.
(cp_parser_type_specifier_seq): Use the new
set_and_check_decl_spec_loc. Stop using
cp_parser_check_decl_spec. Use the new decl_spec_seq_has_spec_p.
(, cp_parser_init_declarator): Use the new
set_and_check_decl_spec_loc.
(cp_parser_single_declaration, cp_parser_friend_p)
(cp_parser_objc_class_ivars, cp_parser_objc_struct_declaration):
Use the new decl_spec_seq_has_spec_p.
* decl.c (check_tag_decl): Use new decl_spec_seq_has_spec_p. Use
the more precise ds_redefined_builtin_type_spec location for
diagnostics about re-declaring C++ built-in types.
(start_decl, grokvardecl, grokdeclarator): Use the new
decl_spec_seq_has_spec_p.
gcc/testsuite/
PR preprocessor/7263
* gcc.dg/binary-constants-2.c: Run without tracking locations
accross macro expansion.
* gcc.dg/binary-constants-3.c: Likewise.
* gcc.dg/cpp/sysmac2.c: Likewise.
* testsuite/gcc.dg/nofixed-point-2.c: Adjust for more precise
location.
* gcc.dg/cpp/syshdr3.c: New test.
* gcc.dg/cpp/syshdr3.h: New header for the new test above.
* gcc.dg/system-binary-constants-1.c: New test.
* gcc.dg/system-binary-constants-1.h: New header for the new test
above.
* g++.dg/cpp/syshdr3.C: New test.
* g++.dg/cpp/syshdr3.h: New header the new test above.
* g++.dg/system-binary-constants-1.C: New test.
* g++.dg/system-binary-constants-1.h: New header the new test
above.
From-SVN: r187587
Diffstat (limited to 'gcc/cp/parser.c')
-rw-r--r-- | gcc/cp/parser.c | 261 |
1 files changed, 156 insertions, 105 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index dc64fa1..2dc8f56 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -2223,6 +2223,9 @@ static void cp_parser_set_storage_class (cp_parser *, cp_decl_specifier_seq *, enum rid, location_t); static void cp_parser_set_decl_spec_type (cp_decl_specifier_seq *, tree, location_t, bool); +static void set_and_check_decl_spec_loc + (cp_decl_specifier_seq *decl_specs, + cp_decl_spec ds, source_location location); static bool cp_parser_friend_p (const cp_decl_specifier_seq *); static void cp_parser_required_error @@ -2494,53 +2497,6 @@ cp_parser_simulate_error (cp_parser* parser) return false; } -/* Check for repeated decl-specifiers. */ - -static void -cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs, - location_t location) -{ - int ds; - - for (ds = ds_first; ds != ds_last; ++ds) - { - unsigned count = decl_specs->specs[ds]; - if (count < 2) - continue; - /* The "long" specifier is a special case because of "long long". */ - if (ds == ds_long) - { - if (count > 2) - error_at (location, "%<long long long%> is too long for GCC"); - else - pedwarn_cxx98 (location, OPT_Wlong_long, - "ISO C++ 1998 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", - "using", - "constexpr", - "__complex", - "__thread" - }; - error_at (location, "duplicate %qs", decl_spec_names[ds]); - } - } -} - /* This function is called when a type is defined. If type definitions are forbidden at this point, an error message is issued. */ @@ -10555,6 +10511,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser, { bool constructor_possible_p = !parser->in_declarator_p; cp_token *start_token = NULL; + cp_decl_spec ds; /* Clear DECL_SPECS. */ clear_decl_specs (decl_specs); @@ -10568,6 +10525,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser, bool constructor_p; bool found_decl_spec; cp_token *token; + ds = ds_last; /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); @@ -10583,6 +10541,8 @@ cp_parser_decl_specifier_seq (cp_parser* parser, decl_specs->attributes = chainon (decl_specs->attributes, cp_parser_attributes_opt (parser)); + if (decl_specs->locations[ds_attribute] == 0) + decl_specs->locations[ds_attribute] = token->location; continue; } /* Assume we will find a decl-specifier keyword. */ @@ -10602,14 +10562,14 @@ cp_parser_decl_specifier_seq (cp_parser* parser, } else { - ++decl_specs->specs[(int) ds_friend]; + ds = ds_friend; /* Consume the token. */ cp_lexer_consume_token (parser->lexer); } break; case RID_CONSTEXPR: - ++decl_specs->specs[(int) ds_constexpr]; + ds = ds_constexpr; cp_lexer_consume_token (parser->lexer); break; @@ -10626,7 +10586,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser, /* decl-specifier: typedef */ case RID_TYPEDEF: - ++decl_specs->specs[(int) ds_typedef]; + ds = ds_typedef; /* Consume the token. */ cp_lexer_consume_token (parser->lexer); /* A constructor declarator cannot appear in a typedef. */ @@ -10679,8 +10639,8 @@ cp_parser_decl_specifier_seq (cp_parser* parser, break; case RID_THREAD: /* Consume the token. */ + ds = ds_thread; cp_lexer_consume_token (parser->lexer); - ++decl_specs->specs[(int) ds_thread]; break; default: @@ -10694,13 +10654,16 @@ cp_parser_decl_specifier_seq (cp_parser* parser, && token->keyword != RID_CONSTEXPR) error ("decl-specifier invalid in condition"); + if (ds != ds_last) + set_and_check_decl_spec_loc (decl_specs, ds, token->location); + /* Constructors are a special case. The `S' in `S()' is not a decl-specifier; it is the beginning of the declarator. */ constructor_p = (!found_decl_spec && constructor_possible_p && (cp_parser_constructor_declarator_p - (parser, decl_specs->specs[(int) ds_friend] != 0))); + (parser, decl_spec_seq_has_spec_p (decl_specs, ds_friend)))); /* If we don't have a DECL_SPEC yet, then we must be looking at a type-specifier. */ @@ -10777,12 +10740,10 @@ cp_parser_decl_specifier_seq (cp_parser* parser, flags |= CP_PARSER_FLAGS_OPTIONAL; } - cp_parser_check_decl_spec (decl_specs, start_token->location); - /* Don't allow a friend specifier with a class definition. */ - if (decl_specs->specs[(int) ds_friend] != 0 + if (decl_spec_seq_has_spec_p (decl_specs, ds_friend) && (*declares_class_or_enum & 2)) - error_at (start_token->location, + error_at (decl_specs->locations[ds_friend], "class definition may not be declared a friend"); } @@ -10843,8 +10804,7 @@ cp_parser_function_specifier_opt (cp_parser* parser, switch (token->keyword) { case RID_INLINE: - if (decl_specs) - ++decl_specs->specs[(int) ds_inline]; + set_and_check_decl_spec_loc (decl_specs, ds_inline, token->location); break; case RID_VIRTUAL: @@ -10853,13 +10813,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%>"); - else if (decl_specs) - ++decl_specs->specs[(int) ds_virtual]; + set_and_check_decl_spec_loc (decl_specs, ds_virtual, token->location); break; case RID_EXPLICIT: - if (decl_specs) - ++decl_specs->specs[(int) ds_explicit]; + set_and_check_decl_spec_loc (decl_specs, ds_explicit, token->location); break; default: @@ -13170,14 +13128,16 @@ cp_parser_explicit_instantiation (cp_parser* parser) if (declares_class_or_enum & 2) cp_parser_check_for_definition_in_return_type (declarator, decl_specifiers.type, - decl_specifiers.type_location); + decl_specifiers.locations[ds_type_spec]); if (declarator != cp_error_declarator) { - if (decl_specifiers.specs[(int)ds_inline]) - permerror (input_location, "explicit instantiation shall not use" + if (decl_spec_seq_has_spec_p (&decl_specifiers, ds_inline)) + permerror (decl_specifiers.locations[ds_inline], + "explicit instantiation shall not use" " %<inline%> specifier"); - if (decl_specifiers.specs[(int)ds_constexpr]) - permerror (input_location, "explicit instantiation shall not use" + if (decl_spec_seq_has_spec_p (&decl_specifiers, ds_constexpr)) + permerror (decl_specifiers.locations[ds_constexpr], + "explicit instantiation shall not use" " %<constexpr%> specifier"); decl = grokdeclarator (declarator, &decl_specifiers, @@ -13399,7 +13359,7 @@ cp_parser_type_specifier (cp_parser* parser, type_spec = (cp_parser_elaborated_type_specifier (parser, - decl_specs && decl_specs->specs[(int) ds_friend], + decl_spec_seq_has_spec_p (decl_specs, ds_friend), is_declaration)); if (decl_specs) cp_parser_set_decl_spec_type (decl_specs, @@ -13440,7 +13400,7 @@ cp_parser_type_specifier (cp_parser* parser, { if (decl_specs) { - ++decl_specs->specs[(int)ds]; + set_and_check_decl_spec_loc (decl_specs, ds, token->location); decl_specs->any_specifiers_p = true; } return cp_lexer_consume_token (parser->lexer)->u.value; @@ -13531,8 +13491,7 @@ cp_parser_simple_type_specifier (cp_parser* parser, type = boolean_type_node; break; case RID_SHORT: - if (decl_specs) - ++decl_specs->specs[(int) ds_short]; + set_and_check_decl_spec_loc (decl_specs, ds_short, token->location); type = short_integer_type_node; break; case RID_INT: @@ -13549,17 +13508,15 @@ cp_parser_simple_type_specifier (cp_parser* parser, break; case RID_LONG: if (decl_specs) - ++decl_specs->specs[(int) ds_long]; + set_and_check_decl_spec_loc (decl_specs, ds_long, token->location); type = long_integer_type_node; break; case RID_SIGNED: - if (decl_specs) - ++decl_specs->specs[(int) ds_signed]; + set_and_check_decl_spec_loc (decl_specs, ds_signed, token->location); type = integer_type_node; break; case RID_UNSIGNED: - if (decl_specs) - ++decl_specs->specs[(int) ds_unsigned]; + set_and_check_decl_spec_loc (decl_specs, ds_unsigned, token->location); type = unsigned_type_node; break; case RID_FLOAT: @@ -15070,19 +15027,21 @@ static tree cp_parser_alias_declaration (cp_parser* parser) { tree id, type, decl, pushed_scope = NULL_TREE, attributes; - location_t id_location; + location_t id_location, using_location, attrs_location = 0; 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); 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; attributes = cp_parser_attributes_opt (parser); if (attributes == error_mark_node) return error_mark_node; @@ -15131,9 +15090,19 @@ cp_parser_alias_declaration (cp_parser* parser) clear_decl_specs (&decl_specs); decl_specs.type = type; - decl_specs.attributes = attributes; - ++decl_specs.specs[(int) ds_typedef]; - ++decl_specs.specs[(int) ds_alias]; + if (attributes != NULL_TREE) + { + decl_specs.attributes = attributes; + set_and_check_decl_spec_loc (&decl_specs, + ds_attribute, + attrs_location); + } + set_and_check_decl_spec_loc (&decl_specs, + ds_typedef, + using_location); + set_and_check_decl_spec_loc (&decl_specs, + ds_alias, + using_location); declarator = make_id_declarator (NULL_TREE, id, sfk_none); declarator->id_loc = id_location; @@ -15515,7 +15484,7 @@ cp_parser_init_declarator (cp_parser* parser, if (declares_class_or_enum & 2) cp_parser_check_for_definition_in_return_type (declarator, decl_specifiers->type, - decl_specifiers->type_location); + decl_specifiers->locations[ds_type_spec]); /* Figure out what scope the entity declared by the DECLARATOR is located in. `grokdeclarator' sometimes changes the scope, so @@ -16936,8 +16905,6 @@ cp_parser_type_specifier_seq (cp_parser* parser, if (is_declaration && !is_cv_qualifier) flags |= CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES; } - - cp_parser_check_decl_spec (type_specifier_seq, start_token->location); } /* Parse a parameter-declaration-clause. @@ -19042,7 +19009,7 @@ cp_parser_member_declaration (cp_parser* parser) if (declares_class_or_enum & 2) cp_parser_check_for_definition_in_return_type (declarator, decl_specifiers.type, - decl_specifiers.type_location); + decl_specifiers.locations[ds_type_spec]); /* Look for an asm-specification. */ asm_specification = cp_parser_asm_specification_opt (parser); @@ -21301,7 +21268,7 @@ cp_parser_single_declaration (cp_parser* parser, *friend_p = cp_parser_friend_p (&decl_specifiers); /* There are no template typedefs. */ - if (decl_specifiers.specs[(int) ds_typedef]) + if (decl_spec_seq_has_spec_p (&decl_specifiers, ds_typedef)) { error_at (decl_spec_token_start->location, "template declaration of %<typedef%>"); @@ -22049,10 +22016,11 @@ cp_parser_set_storage_class (cp_parser *parser, } if ((keyword == RID_EXTERN || keyword == RID_STATIC) - && decl_specs->specs[(int) ds_thread]) + && decl_spec_seq_has_spec_p (decl_specs, ds_thread)) { - error_at (location, "%<__thread%> before %qD", ridpointers[keyword]); - decl_specs->specs[(int) ds_thread] = 0; + error_at (decl_specs->locations[ds_thread], + "%<__thread%> before %qD", ridpointers[keyword]); + decl_specs->locations[ds_thread] = 0; } switch (keyword) @@ -22076,12 +22044,13 @@ 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); /* A storage class specifier cannot be applied alongside a typedef specifier. If there is a typedef specifier present then set conflicting_specifiers_p which will trigger an error later on in grokdeclarator. */ - if (decl_specs->specs[(int)ds_typedef]) + if (decl_spec_seq_has_spec_p (decl_specs, ds_typedef)) decl_specs->conflicting_specifiers_p = true; } @@ -22101,24 +22070,27 @@ cp_parser_set_decl_spec_type (cp_decl_specifier_seq *decl_specs, this is what happened. In system headers, we ignore these declarations so that G++ can work with system headers that are not C++-safe. */ - if (decl_specs->specs[(int) ds_typedef] + if (decl_spec_seq_has_spec_p (decl_specs, ds_typedef) && !type_definition_p && (type_spec == boolean_type_node || type_spec == char16_type_node || type_spec == char32_type_node || type_spec == wchar_type_node) && (decl_specs->type - || decl_specs->specs[(int) ds_long] - || decl_specs->specs[(int) ds_short] - || decl_specs->specs[(int) ds_unsigned] - || decl_specs->specs[(int) ds_signed])) + || decl_spec_seq_has_spec_p (decl_specs, ds_long) + || decl_spec_seq_has_spec_p (decl_specs, ds_short) + || decl_spec_seq_has_spec_p (decl_specs, ds_unsigned) + || decl_spec_seq_has_spec_p (decl_specs, ds_signed))) { decl_specs->redefined_builtin_type = type_spec; + set_and_check_decl_spec_loc (decl_specs, + ds_redefined_builtin_type_spec, + location); if (!decl_specs->type) { decl_specs->type = type_spec; decl_specs->type_definition_p = false; - decl_specs->type_location = location; + set_and_check_decl_spec_loc (decl_specs,ds_type_spec, location); } } else if (decl_specs->type) @@ -22128,17 +22100,96 @@ 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; - decl_specs->type_location = location; + set_and_check_decl_spec_loc (decl_specs, ds_type_spec, location); + } +} + +/* Set the location for a declarator specifier and check if it is + duplicated. + + DECL_SPECS is the sequence of declarator specifiers onto which to + set the location. + + DS is the single declarator specifier to set which location is to + be set onto the existing sequence of declarators. + + LOCATION is the location for the declarator specifier to + consider. */ + +static void +set_and_check_decl_spec_loc (cp_decl_specifier_seq *decl_specs, + cp_decl_spec ds, source_location location) +{ + gcc_assert (ds < ds_last); + + if (decl_specs == NULL) + return; + + if (decl_specs->locations[ds] == 0) + decl_specs->locations[ds] = location; + else + { + if (ds == ds_long) + { + if (decl_specs->locations[ds_long_long] != 0) + error_at (location, + "%<long long long%> is too long for GCC"); + else + { + decl_specs->locations[ds_long_long] = location; + pedwarn_cxx98 (location, + OPT_Wlong_long, + "ISO C++ 1998 does not support %<long long%>"); + } + } + else + { + static const char *const decl_spec_names[] = { + "signed", + "unsigned", + "short", + "long", + "const", + "volatile", + "restrict", + "inline", + "virtual", + "explicit", + "friend", + "typedef", + "using", + "constexpr", + "__complex", + "__thread" + }; + error_at (location, + "duplicate %qs", decl_spec_names[ds]); + } } } +/* Return true iff the declarator specifier DS is present in the + sequence of declarator specifiers DECL_SPECS. */ + +bool +decl_spec_seq_has_spec_p (const cp_decl_specifier_seq * decl_specs, + cp_decl_spec ds) +{ + gcc_assert (ds < ds_last); + + if (decl_specs == NULL) + return false; + + return decl_specs->locations[ds] != 0; +} + /* DECL_SPECIFIERS is the representation of a decl-specifier-seq. Returns TRUE iff `friend' appears among the DECL_SPECIFIERS. */ static bool cp_parser_friend_p (const cp_decl_specifier_seq *decl_specifiers) { - return decl_specifiers->specs[(int) ds_friend] != 0; + return decl_spec_seq_has_spec_p (decl_specifiers, ds_friend); } /* Issue an error message indicating that TOKEN_DESC was expected. @@ -23951,17 +24002,17 @@ cp_parser_objc_class_ivars (cp_parser* parser) } /* __thread. */ - if (declspecs.specs[(int) ds_thread]) + if (decl_spec_seq_has_spec_p (&declspecs, ds_thread)) { cp_parser_error (parser, "invalid type for instance variable"); - declspecs.specs[(int) ds_thread] = 0; + declspecs.locations[ds_thread] = 0; } /* typedef. */ - if (declspecs.specs[(int) ds_typedef]) + if (decl_spec_seq_has_spec_p (&declspecs, ds_typedef)) { cp_parser_error (parser, "invalid type for instance variable"); - declspecs.specs[(int) ds_typedef] = 0; + declspecs.locations[ds_thread] = 0; } prefix_attributes = declspecs.attributes; @@ -24530,17 +24581,17 @@ cp_parser_objc_struct_declaration (cp_parser *parser) } /* __thread. */ - if (declspecs.specs[(int) ds_thread]) + if (decl_spec_seq_has_spec_p (&declspecs, ds_thread)) { cp_parser_error (parser, "invalid type for property"); - declspecs.specs[(int) ds_thread] = 0; + declspecs.locations[ds_thread] = 0; } /* typedef. */ - if (declspecs.specs[(int) ds_typedef]) + if (decl_spec_seq_has_spec_p (&declspecs, ds_typedef)) { cp_parser_error (parser, "invalid type for property"); - declspecs.specs[(int) ds_typedef] = 0; + declspecs.locations[ds_typedef] = 0; } prefix_attributes = declspecs.attributes; |