aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/parser.c
diff options
context:
space:
mode:
authorIain Sandoe <iain@sandoe.co.uk>2020-10-26 22:12:22 +0000
committerIain Sandoe <iain@sandoe.co.uk>2020-11-11 20:43:31 +0000
commit9227f81db7a0b38dd14ce4b48ca50c33cf8d5e1c (patch)
tree9e4363f328b7d4facf4a79492cd0569c87f3116a /gcc/cp/parser.c
parentb1c9b3c3408c1ec8043f9b9e1a148f84bb7f3b25 (diff)
downloadgcc-9227f81db7a0b38dd14ce4b48ca50c33cf8d5e1c.zip
gcc-9227f81db7a0b38dd14ce4b48ca50c33cf8d5e1c.tar.gz
gcc-9227f81db7a0b38dd14ce4b48ca50c33cf8d5e1c.tar.bz2
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.
Diffstat (limited to 'gcc/cp/parser.c')
-rw-r--r--gcc/cp/parser.c71
1 files changed, 57 insertions, 14 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 4f59fc4..efcdce0 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -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);