aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/parser.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/parser.cc')
-rw-r--r--gcc/cp/parser.cc101
1 files changed, 60 insertions, 41 deletions
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 7b41635..baa808a 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -2258,7 +2258,7 @@ static vec<tree, va_gc> *cp_parser_parenthesized_expression_list
(cp_parser *, int, bool, bool, bool *, location_t * = NULL,
bool = false);
/* Values for the second parameter of cp_parser_parenthesized_expression_list. */
-enum { non_attr = 0, normal_attr = 1, id_attr = 2 };
+enum { non_attr = 0, normal_attr = 1, id_attr = 2, assume_attr = 3 };
static void cp_parser_pseudo_destructor_name
(cp_parser *, tree, tree *, tree *);
static cp_expr cp_parser_unary_expression
@@ -2287,6 +2287,7 @@ static cp_expr cp_parser_binary_expression
(cp_parser *, bool, bool, enum cp_parser_prec, cp_id_kind *);
static tree cp_parser_question_colon_clause
(cp_parser *, cp_expr);
+static cp_expr cp_parser_conditional_expression (cp_parser *);
static cp_expr cp_parser_assignment_expression
(cp_parser *, cp_id_kind * = NULL, bool = false, bool = false);
static enum tree_code cp_parser_assignment_operator_opt
@@ -8480,7 +8481,6 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
bool wrap_locations_p)
{
vec<tree, va_gc> *expression_list;
- tree identifier = NULL_TREE;
bool saved_greater_than_is_operator_p;
/* Assume all the expressions will be constant. */
@@ -8509,33 +8509,26 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
next token is an identifier. */
if (is_attribute_list == id_attr
&& cp_lexer_peek_token (parser->lexer)->type == CPP_NAME)
- {
- cp_token *token;
-
- /* Consume the identifier. */
- token = cp_lexer_consume_token (parser->lexer);
- /* Save the identifier. */
- identifier = token->u.value;
- }
+ expr = cp_lexer_consume_token (parser->lexer)->u.value;
+ else if (is_attribute_list == assume_attr)
+ expr = cp_parser_conditional_expression (parser);
else
- {
- expr
- = cp_parser_parenthesized_expression_list_elt (parser, cast_p,
- allow_expansion_p,
- non_constant_p);
+ expr
+ = cp_parser_parenthesized_expression_list_elt (parser, cast_p,
+ allow_expansion_p,
+ non_constant_p);
- if (wrap_locations_p)
- expr.maybe_add_location_wrapper ();
+ if (wrap_locations_p)
+ expr.maybe_add_location_wrapper ();
- /* Add it to the list. We add error_mark_node
- expressions to the list, so that we can still tell if
- the correct form for a parenthesized expression-list
- is found. That gives better errors. */
- vec_safe_push (expression_list, expr.get_value ());
+ /* Add it to the list. We add error_mark_node
+ expressions to the list, so that we can still tell if
+ the correct form for a parenthesized expression-list
+ is found. That gives better errors. */
+ vec_safe_push (expression_list, expr.get_value ());
- if (expr == error_mark_node)
- goto skip_comma;
- }
+ if (expr == error_mark_node)
+ goto skip_comma;
/* After the first item, attribute lists look the same as
expression lists. */
@@ -8577,9 +8570,6 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
parser->greater_than_is_operator_p
= saved_greater_than_is_operator_p;
- if (identifier)
- vec_safe_insert (expression_list, 0, identifier);
-
return expression_list;
}
@@ -10310,7 +10300,8 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
logical-or-expression that started the conditional-expression.
Returns a representation of the entire conditional-expression.
- This routine is used by cp_parser_assignment_expression.
+ This routine is used by cp_parser_assignment_expression
+ and cp_parser_conditional_expression.
? expression : assignment-expression
@@ -10377,6 +10368,28 @@ cp_parser_question_colon_clause (cp_parser* parser, cp_expr logical_or_expr)
tf_warning_or_error);
}
+/* Parse a conditional-expression.
+
+ conditional-expression:
+ logical-or-expression
+ logical-or-expression ? expression : assignment-expression
+
+ GNU Extensions:
+
+ logical-or-expression ? : assignment-expression */
+
+static cp_expr
+cp_parser_conditional_expression (cp_parser *parser)
+{
+ cp_expr expr = cp_parser_binary_expression (parser, false, false, false,
+ PREC_NOT_OPERATOR, NULL);
+ /* If the next token is a `?' then we're actually looking at
+ a conditional-expression; otherwise we're done. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_QUERY))
+ return cp_parser_question_colon_clause (parser, expr);
+ return expr;
+}
+
/* Parse an assignment-expression.
assignment-expression:
@@ -10702,15 +10715,7 @@ cp_parser_constant_expression (cp_parser* parser,
determine whether a particular assignment-expression is in fact
constant. */
if (strict_p)
- {
- /* Parse the binary expressions (logical-or-expression). */
- expression = cp_parser_binary_expression (parser, false, false, false,
- PREC_NOT_OPERATOR, NULL);
- /* If the next token is a `?' then we're actually looking at
- a conditional-expression; otherwise we're done. */
- if (cp_lexer_next_token_is (parser->lexer, CPP_QUERY))
- expression = cp_parser_question_colon_clause (parser, expression);
- }
+ expression = cp_parser_conditional_expression (parser);
else
expression = cp_parser_assignment_expression (parser);
/* Restore the old settings. */
@@ -12503,6 +12508,9 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
/* Look for an expression-statement instead. */
statement = cp_parser_expression_statement (parser, in_statement_expr);
+ std_attrs = process_stmt_assume_attribute (std_attrs, statement,
+ attrs_loc);
+
/* Handle [[fallthrough]];. */
if (attribute_fallthrough_p (std_attrs))
{
@@ -12526,7 +12534,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
if (statement && STATEMENT_CODE_P (TREE_CODE (statement)))
SET_EXPR_LOCATION (statement, statement_location);
- /* Allow "[[fallthrough]];", but warn otherwise. */
+ /* Allow "[[fallthrough]];" or "[[assume(cond)]];", but warn otherwise. */
if (std_attrs != NULL_TREE)
warning_at (attrs_loc,
OPT_Wattributes,
@@ -12718,6 +12726,8 @@ cp_parser_expression_statement (cp_parser* parser, tree in_statement_expr)
}
}
+ attr = process_stmt_assume_attribute (attr, statement, loc);
+
/* Handle [[fallthrough]];. */
if (attribute_fallthrough_p (attr))
{
@@ -28876,6 +28886,8 @@ cp_parser_gnu_attribute_list (cp_parser* parser, bool exactly_one /* = false */)
vec<tree, va_gc> *vec;
int attr_flag = (attribute_takes_identifier_p (identifier)
? id_attr : normal_attr);
+ if (is_attribute_p ("assume", identifier))
+ attr_flag = assume_attr;
vec = cp_parser_parenthesized_expression_list
(parser, attr_flag, /*cast_p=*/false,
/*allow_expansion_p=*/false,
@@ -29127,6 +29139,9 @@ cp_parser_std_attribute (cp_parser *parser, tree attr_ns)
/* C++17 fallthrough attribute is equivalent to GNU's. */
else if (is_attribute_p ("fallthrough", attr_id))
TREE_PURPOSE (TREE_PURPOSE (attribute)) = gnu_identifier;
+ /* C++23 assume attribute is equivalent to GNU's. */
+ else if (is_attribute_p ("assume", attr_id))
+ TREE_PURPOSE (TREE_PURPOSE (attribute)) = gnu_identifier;
/* Transactional Memory TS optimize_for_synchronized attribute is
equivalent to GNU transaction_callable. */
else if (is_attribute_p ("optimize_for_synchronized", attr_id))
@@ -29171,8 +29186,12 @@ cp_parser_std_attribute (cp_parser *parser, tree attr_ns)
return error_mark_node;
}
- if (attr_ns == gnu_identifier
- && attribute_takes_identifier_p (attr_id))
+ if (is_attribute_p ("assume", attr_id)
+ && (attr_ns == NULL_TREE || attr_ns == gnu_identifier))
+ /* The assume attribute needs special handling of the argument. */
+ attr_flag = assume_attr;
+ else if (attr_ns == gnu_identifier
+ && attribute_takes_identifier_p (attr_id))
/* A GNU attribute that takes an identifier in parameter. */
attr_flag = id_attr;