aboutsummaryrefslogtreecommitdiff
path: root/gcc/c/c-parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/c/c-parser.c')
-rw-r--r--gcc/c/c-parser.c78
1 files changed, 46 insertions, 32 deletions
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 2efa234..03194b4 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -4803,7 +4803,7 @@ c_parser_balanced_token_sequence (c_parser *parser)
*/
static tree
-c_parser_std_attribute (c_parser *parser)
+c_parser_std_attribute (c_parser *parser, bool for_tm)
{
c_token *token = c_parser_peek_token (parser);
tree ns, name, attribute;
@@ -4834,39 +4834,53 @@ c_parser_std_attribute (c_parser *parser)
attribute = build_tree_list (build_tree_list (ns, name), NULL_TREE);
/* Parse the arguments, if any. */
- if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
- return attribute;
- location_t open_loc = c_parser_peek_token (parser)->location;
- matching_parens parens;
- parens.consume_open (parser);
const attribute_spec *as = lookup_attribute_spec (TREE_PURPOSE (attribute));
- if ((as && as->max_length == 0)
- /* Special-case the transactional-memory attribute "outer",
- which is specially handled but not registered as an
- attribute, to avoid allowing arbitrary balanced token
- sequences as arguments. */
- || is_attribute_p ("outer", name))
- {
- error_at (open_loc, "%qE attribute does not take any arguments", name);
- parens.skip_until_found_close (parser);
+ if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
+ goto out;
+ {
+ location_t open_loc = c_parser_peek_token (parser)->location;
+ matching_parens parens;
+ parens.consume_open (parser);
+ if ((as && as->max_length == 0)
+ /* Special-case the transactional-memory attribute "outer",
+ which is specially handled but not registered as an
+ attribute, to avoid allowing arbitrary balanced token
+ sequences as arguments. */
+ || is_attribute_p ("outer", name))
+ {
+ error_at (open_loc, "%qE attribute does not take any arguments", name);
+ parens.skip_until_found_close (parser);
+ return error_mark_node;
+ }
+ if (as)
+ {
+ bool takes_identifier
+ = (ns != NULL_TREE
+ && strcmp (IDENTIFIER_POINTER (ns), "gnu") == 0
+ && attribute_takes_identifier_p (name));
+ bool require_string
+ = (ns == NULL_TREE
+ && strcmp (IDENTIFIER_POINTER (name), "deprecated") == 0);
+ TREE_VALUE (attribute)
+ = c_parser_attribute_arguments (parser, takes_identifier,
+ require_string, false);
+ }
+ else
+ c_parser_balanced_token_sequence (parser);
+ parens.require_close (parser);
+ }
+ out:
+ if (ns == NULL_TREE && !for_tm && !as && !is_attribute_p ("nodiscard", name))
+ {
+ /* An attribute with standard syntax and no namespace specified
+ is a constraint violation if it is not one of the known
+ standard attributes (of which nodiscard is the only one
+ without a handler in GCC). Diagnose it here with a pedwarn
+ and then discard it to prevent a duplicate warning later. */
+ pedwarn (input_location, OPT_Wattributes, "%qE attribute ignored",
+ name);
return error_mark_node;
}
- if (as)
- {
- bool takes_identifier
- = (ns != NULL_TREE
- && strcmp (IDENTIFIER_POINTER (ns), "gnu") == 0
- && attribute_takes_identifier_p (name));
- bool require_string
- = (ns == NULL_TREE
- && strcmp (IDENTIFIER_POINTER (name), "deprecated") == 0);
- TREE_VALUE (attribute)
- = c_parser_attribute_arguments (parser, takes_identifier,
- require_string, false);
- }
- else
- c_parser_balanced_token_sequence (parser);
- parens.require_close (parser);
return attribute;
}
@@ -4898,7 +4912,7 @@ c_parser_std_attribute_specifier (c_parser *parser, bool for_tm)
c_parser_consume_token (parser);
continue;
}
- tree attribute = c_parser_std_attribute (parser);
+ tree attribute = c_parser_std_attribute (parser, for_tm);
if (attribute != error_mark_node)
{
bool duplicate = false;