mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-24 22:11:56 +08:00
Objective-C++ : Allow prefix attrs on linkage specs.
For Objective-C++, this combines prefix attributes from before and after top level linkage specs. The "reference implementation" for Objective-C++ allows this, and system headers depend on it. e.g. __attribute__((__deprecated__)) extern "C" __attribute__((__visibility__("default"))) @interface MyClass ... @end Would consider the list of prefix attributes to the interface for MyClass to include both the visibility and deprecated ones. When we are compiling regular C++, this emits a warning and discards any prefix attributes before a linkage spec. gcc/cp/ChangeLog: * parser.c (cp_parser_declaration): Unless we are compiling for Ojective-C++, warn about and discard any attributes that prefix a linkage specification.
This commit is contained in:
parent
b1c9b3c340
commit
9227f81db7
@ -2187,7 +2187,7 @@ static void cp_parser_already_scoped_statement
|
||||
static void cp_parser_declaration_seq_opt
|
||||
(cp_parser *);
|
||||
static void cp_parser_declaration
|
||||
(cp_parser *);
|
||||
(cp_parser *, tree);
|
||||
static void cp_parser_toplevel_declaration
|
||||
(cp_parser *);
|
||||
static void cp_parser_block_declaration
|
||||
@ -2238,7 +2238,7 @@ static tree cp_parser_alias_declaration
|
||||
static void cp_parser_asm_definition
|
||||
(cp_parser *);
|
||||
static void cp_parser_linkage_specification
|
||||
(cp_parser *);
|
||||
(cp_parser *, tree);
|
||||
static void cp_parser_static_assert
|
||||
(cp_parser *, bool);
|
||||
static tree cp_parser_decltype
|
||||
@ -13496,7 +13496,7 @@ cp_parser_declaration_seq_opt (cp_parser* parser)
|
||||
__extension__ declaration */
|
||||
|
||||
static void
|
||||
cp_parser_declaration (cp_parser* parser)
|
||||
cp_parser_declaration (cp_parser* parser, tree prefix_attrs)
|
||||
{
|
||||
int saved_pedantic;
|
||||
|
||||
@ -13504,7 +13504,7 @@ cp_parser_declaration (cp_parser* parser)
|
||||
if (cp_parser_extension_opt (parser, &saved_pedantic))
|
||||
{
|
||||
/* Parse the qualified declaration. */
|
||||
cp_parser_declaration (parser);
|
||||
cp_parser_declaration (parser, prefix_attrs);
|
||||
/* Restore the PEDANTIC flag. */
|
||||
pedantic = saved_pedantic;
|
||||
|
||||
@ -13521,11 +13521,50 @@ cp_parser_declaration (cp_parser* parser)
|
||||
|
||||
tree attributes = NULL_TREE;
|
||||
|
||||
/* Conditionally, allow attributes to precede a linkage specification. */
|
||||
if (token1->keyword == RID_ATTRIBUTE)
|
||||
{
|
||||
cp_lexer_save_tokens (parser->lexer);
|
||||
attributes = cp_parser_attributes_opt (parser);
|
||||
gcc_checking_assert (attributes);
|
||||
cp_token *t1 = cp_lexer_peek_token (parser->lexer);
|
||||
cp_token *t2 = (t1->type == CPP_EOF
|
||||
? t1 : cp_lexer_peek_nth_token (parser->lexer, 2));
|
||||
if (t1->keyword == RID_EXTERN
|
||||
&& cp_parser_is_pure_string_literal (t2))
|
||||
{
|
||||
cp_lexer_commit_tokens (parser->lexer);
|
||||
/* We might have already been here. */
|
||||
if (!c_dialect_objc ())
|
||||
{
|
||||
warning_at (token1->location, OPT_Wattributes, "attributes are"
|
||||
" only permitted in this position for Objective-C++,"
|
||||
" ignored");
|
||||
attributes = NULL_TREE;
|
||||
}
|
||||
token1 = t1;
|
||||
token2 = t2;
|
||||
}
|
||||
else
|
||||
{
|
||||
cp_lexer_rollback_tokens (parser->lexer);
|
||||
attributes = NULL_TREE;
|
||||
}
|
||||
}
|
||||
/* If we already had some attributes, and we've added more, then prepend.
|
||||
Otherwise attributes just contains any that we just read. */
|
||||
if (prefix_attrs)
|
||||
{
|
||||
if (attributes)
|
||||
TREE_CHAIN (prefix_attrs) = attributes;
|
||||
attributes = prefix_attrs;
|
||||
}
|
||||
|
||||
/* If the next token is `extern' and the following token is a string
|
||||
literal, then we have a linkage specification. */
|
||||
if (token1->keyword == RID_EXTERN
|
||||
&& cp_parser_is_pure_string_literal (token2))
|
||||
cp_parser_linkage_specification (parser);
|
||||
cp_parser_linkage_specification (parser, attributes);
|
||||
/* If the next token is `template', then we have either a template
|
||||
declaration, an explicit instantiation, or an explicit
|
||||
specialization. */
|
||||
@ -13575,7 +13614,7 @@ cp_parser_declaration (cp_parser* parser)
|
||||
cp_parser_namespace_definition (parser);
|
||||
/* Objective-C++ declaration/definition. */
|
||||
else if (c_dialect_objc () && OBJC_IS_AT_KEYWORD (token1->keyword))
|
||||
cp_parser_objc_declaration (parser, NULL_TREE);
|
||||
cp_parser_objc_declaration (parser, attributes);
|
||||
else if (c_dialect_objc ()
|
||||
&& token1->keyword == RID_ATTRIBUTE
|
||||
&& cp_parser_objc_valid_prefix_attributes (parser, &attributes))
|
||||
@ -13617,7 +13656,7 @@ cp_parser_toplevel_declaration (cp_parser* parser)
|
||||
}
|
||||
else
|
||||
/* Parse the declaration itself. */
|
||||
cp_parser_declaration (parser);
|
||||
cp_parser_declaration (parser, NULL_TREE);
|
||||
}
|
||||
|
||||
/* Parse a block-declaration.
|
||||
@ -14726,7 +14765,7 @@ cp_parser_function_specifier_opt (cp_parser* parser,
|
||||
extern string-literal declaration */
|
||||
|
||||
static void
|
||||
cp_parser_linkage_specification (cp_parser* parser)
|
||||
cp_parser_linkage_specification (cp_parser* parser, tree prefix_attr)
|
||||
{
|
||||
tree linkage;
|
||||
|
||||
@ -14791,7 +14830,7 @@ cp_parser_linkage_specification (cp_parser* parser)
|
||||
saved_in_unbraced_linkage_specification_p
|
||||
= parser->in_unbraced_linkage_specification_p;
|
||||
parser->in_unbraced_linkage_specification_p = true;
|
||||
cp_parser_declaration (parser);
|
||||
cp_parser_declaration (parser, prefix_attr);
|
||||
parser->in_unbraced_linkage_specification_p
|
||||
= saved_in_unbraced_linkage_specification_p;
|
||||
}
|
||||
@ -33099,7 +33138,7 @@ cp_parser_objc_interstitial_code (cp_parser* parser)
|
||||
if (token->keyword == RID_EXTERN
|
||||
&& cp_parser_is_pure_string_literal
|
||||
(cp_lexer_peek_nth_token (parser->lexer, 2)))
|
||||
cp_parser_linkage_specification (parser);
|
||||
cp_parser_linkage_specification (parser, NULL_TREE);
|
||||
/* Handle #pragma, if any. */
|
||||
else if (token->type == CPP_PRAGMA)
|
||||
cp_parser_pragma (parser, pragma_objc_icode, NULL);
|
||||
@ -33864,11 +33903,15 @@ static bool
|
||||
cp_parser_objc_valid_prefix_attributes (cp_parser* parser, tree *attrib)
|
||||
{
|
||||
cp_lexer_save_tokens (parser->lexer);
|
||||
*attrib = cp_parser_attributes_opt (parser);
|
||||
gcc_assert (*attrib);
|
||||
tree addon = cp_parser_attributes_opt (parser);
|
||||
gcc_checking_assert (addon);
|
||||
if (OBJC_IS_AT_KEYWORD (cp_lexer_peek_token (parser->lexer)->keyword))
|
||||
{
|
||||
cp_lexer_commit_tokens (parser->lexer);
|
||||
if (*attrib)
|
||||
TREE_CHAIN (*attrib) = addon;
|
||||
else
|
||||
*attrib = addon;
|
||||
return true;
|
||||
}
|
||||
cp_lexer_rollback_tokens (parser->lexer);
|
||||
@ -41892,7 +41935,7 @@ cp_parser_omp_declare_simd (cp_parser *parser, cp_token *pragma_tok,
|
||||
switch (context)
|
||||
{
|
||||
case pragma_external:
|
||||
cp_parser_declaration (parser);
|
||||
cp_parser_declaration (parser, NULL_TREE);
|
||||
break;
|
||||
case pragma_member:
|
||||
cp_parser_member_declaration (parser);
|
||||
@ -43449,7 +43492,7 @@ cp_parser_oacc_routine (cp_parser *parser, cp_token *pragma_tok,
|
||||
}
|
||||
|
||||
/* We only have to consider the pragma_external case here. */
|
||||
cp_parser_declaration (parser);
|
||||
cp_parser_declaration (parser, NULL_TREE);
|
||||
if (parser->oacc_routine
|
||||
&& !parser->oacc_routine->fndecl_seen)
|
||||
cp_ensure_no_oacc_routine (parser);
|
||||
|
Loading…
x
Reference in New Issue
Block a user