diff options
Diffstat (limited to 'gcc/c')
-rw-r--r-- | gcc/c/c-parser.cc | 113 |
1 files changed, 104 insertions, 9 deletions
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index f6a94ba..9b76637 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -1823,6 +1823,46 @@ add_debug_begin_stmt (location_t loc) add_stmt (stmt); } +/* Helper function for c_parser_declaration_or_fndef and + Handle assume attribute(s). */ + +static tree +handle_assume_attribute (location_t here, tree attrs, bool nested) +{ + if (nested) + for (tree attr = lookup_attribute ("gnu", "assume", attrs); attr; + attr = lookup_attribute ("gnu", "assume", TREE_CHAIN (attr))) + { + tree args = TREE_VALUE (attr); + int nargs = list_length (args); + if (nargs != 1) + { + error_at (here, "wrong number of arguments specified " + "for %qE attribute", + get_attribute_name (attr)); + inform (here, "expected %i, found %i", 1, nargs); + } + else + { + tree arg = TREE_VALUE (args); + arg = c_objc_common_truthvalue_conversion (here, arg); + arg = c_fully_fold (arg, false, NULL); + if (arg != error_mark_node) + { + tree fn = build_call_expr_internal_loc (here, IFN_ASSUME, + void_type_node, 1, + arg); + add_stmt (fn); + } + } + } + else + pedwarn (here, OPT_Wattributes, + "%<assume%> attribute at top level"); + + return remove_attribute ("gnu", "assume", attrs); +} + /* Parse a declaration or function definition (C90 6.5, 6.7.1, C99 6.7, 6.9.1, C11 6.7, 6.9.1). If FNDEF_OK is true, a function definition is accepted; otherwise (old-style parameter declarations) only other @@ -2037,6 +2077,14 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool auto_type_p = specs->typespec_word == cts_auto_type; if (c_parser_next_token_is (parser, CPP_SEMICOLON)) { + bool handled_assume = false; + if (specs->typespec_kind == ctsk_none + && lookup_attribute ("gnu", "assume", specs->attrs)) + { + handled_assume = true; + specs->attrs + = handle_assume_attribute (here, specs->attrs, nested); + } if (auto_type_p) error_at (here, "%<__auto_type%> in empty declaration"); else if (specs->typespec_kind == ctsk_none @@ -2054,13 +2102,15 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, pedwarn (here, OPT_Wattributes, "%<fallthrough%> attribute at top level"); } - else if (empty_ok && !(have_attrs - && specs->non_std_attrs_seen_p)) + else if (empty_ok + && !(have_attrs && specs->non_std_attrs_seen_p) + && !handled_assume) shadow_tag (specs); else { shadow_tag_warned (specs, 1); - pedwarn (here, 0, "empty declaration"); + if (!handled_assume) + pedwarn (here, 0, "empty declaration"); } c_parser_consume_token (parser); if (oacc_routine_data) @@ -2160,6 +2210,9 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, else if (attribute_fallthrough_p (specs->attrs)) warning_at (here, OPT_Wattributes, "%<fallthrough%> attribute not followed by %<;%>"); + else if (lookup_attribute ("gnu", "assume", specs->attrs)) + warning_at (here, OPT_Wattributes, + "%<assume%> attribute not followed by %<;%>"); pending_xref_error (); prefix_attrs = specs->attrs; @@ -4598,7 +4651,8 @@ c_parser_gnu_attribute_any_word (c_parser *parser) static tree c_parser_attribute_arguments (c_parser *parser, bool takes_identifier, - bool require_string, bool allow_empty_args) + bool require_string, bool assume_attr, + bool allow_empty_args) { vec<tree, va_gc> *expr_list; tree attr_args; @@ -4617,6 +4671,7 @@ c_parser_attribute_arguments (c_parser *parser, bool takes_identifier, == CPP_CLOSE_PAREN)) && (takes_identifier || (c_dialect_objc () + && !assume_attr && c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME))) { @@ -4653,6 +4708,23 @@ c_parser_attribute_arguments (c_parser *parser, bool takes_identifier, tree string = c_parser_string_literal (parser, false, true).value; attr_args = build_tree_list (NULL_TREE, string); } + else if (assume_attr) + { + tree cond + = c_parser_conditional_expression (parser, NULL, NULL_TREE).value; + if (!c_parser_next_token_is (parser, CPP_COMMA)) + attr_args = build_tree_list (NULL_TREE, cond); + else + { + tree tree_list; + c_parser_consume_token (parser); + expr_list = c_parser_expr_list (parser, false, true, + NULL, NULL, NULL, NULL); + tree_list = build_tree_list_vec (expr_list); + attr_args = tree_cons (NULL_TREE, cond, tree_list); + release_tree_vector (expr_list); + } + } else { expr_list = c_parser_expr_list (parser, false, true, @@ -4736,7 +4808,9 @@ c_parser_gnu_attribute (c_parser *parser, tree attrs, tree attr_args = c_parser_attribute_arguments (parser, attribute_takes_identifier_p (attr_name), - false, true); + false, + is_attribute_p ("assume", attr_name), + true); attr = build_tree_list (attr_name, attr_args); if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) @@ -4982,9 +5056,13 @@ c_parser_std_attribute (c_parser *parser, bool for_tm) = (ns == NULL_TREE && (strcmp (IDENTIFIER_POINTER (name), "deprecated") == 0 || strcmp (IDENTIFIER_POINTER (name), "nodiscard") == 0)); + bool assume_attr + = (ns != NULL_TREE + && strcmp (IDENTIFIER_POINTER (ns), "gnu") == 0 + && strcmp (IDENTIFIER_POINTER (name), "assume") == 0); TREE_VALUE (attribute) = c_parser_attribute_arguments (parser, takes_identifier, - require_string, false); + require_string, assume_attr, false); } else c_parser_balanced_token_sequence (parser); @@ -6264,8 +6342,21 @@ c_parser_statement_after_labels (c_parser *parser, bool *if_p, break; case RID_ATTRIBUTE: { - /* Allow '__attribute__((fallthrough));'. */ + /* Allow '__attribute__((fallthrough));' or + '__attribute__((assume(cond)));'. */ tree attrs = c_parser_gnu_attributes (parser); + bool has_assume = lookup_attribute ("assume", attrs); + if (has_assume) + { + if (c_parser_next_token_is (parser, CPP_SEMICOLON)) + attrs = handle_assume_attribute (loc, attrs, true); + else + { + warning_at (loc, OPT_Wattributes, + "%<assume%> attribute not followed by %<;%>"); + has_assume = false; + } + } if (attribute_fallthrough_p (attrs)) { if (c_parser_next_token_is (parser, CPP_SEMICOLON)) @@ -6282,9 +6373,13 @@ c_parser_statement_after_labels (c_parser *parser, bool *if_p, "%<fallthrough%> attribute not followed " "by %<;%>"); } + else if (has_assume) + /* Eat the ';'. */ + c_parser_consume_token (parser); else if (attrs != NULL_TREE) - warning_at (loc, OPT_Wattributes, "only attribute %<fallthrough%>" - " can be applied to a null statement"); + warning_at (loc, OPT_Wattributes, + "only attribute %<fallthrough%> or %<assume%> can " + "be applied to a null statement"); break; } default: |