This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH] Precedence-based parsing
- From: Paolo Bonzini <bonzini at gnu dot org>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 22 Sep 2004 18:02:50 +0200
- Subject: [C++ PATCH] Precedence-based parsing
From PR14179's trail:
> Paolo --
>
> This patch is great. My only comment is that I would like the grammar
> entries that used to be above the various functions (pm-expression:
> ..., etc.) to be preserved above the rewritten binary_expression
> function. Please check in!
I'm finishing regtesting it, then I'll commit it as preapproved.
Paolo
2004-09-20 Paolo Bonzini <bonzini@gnu.org>
* parser.c (cp_parser_token_tree_map_node,
cp_parser_pm_expression, cp_parser_additive_expression,
cp_parser_multiplicative_expression, cp_parser_shift_expression,
cp_parser_relational_expression, cp_parser_equality_expression,
cp_parser_and_expression, cp_parser_exclusive_or_expression,
cp_parser_inclusive_or_expression,
cp_parser_logical_and_expression,
cp_parser_logical_or_expression): Removed.
(enum cp_parser_prec, struct cp_parser_token_tree_map_node,
binops, binops_by_token): New.
(cp_parser_assignment_expression): Use cp_parser_binary_expression.
(cp_parser_new): Initialize binops_by_token.
(cp_parser_binary_expression): Rewritten.
Index: parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.251
diff -u -r1.251 parser.c
*** parser.c 21 Sep 2004 20:46:57 -0000 1.251
--- parser.c 22 Sep 2004 15:52:11 -0000
***************
*** 1038,1055 ****
Future Improvements
-------------------
! The performance of the parser could probably be improved
! substantially. Some possible improvements include:
!
! - The expression parser recurses through the various levels of
! precedence as specified in the grammar, rather than using an
! operator-precedence technique. Therefore, parsing a simple
! identifier requires multiple recursive calls.
!
! - We could often eliminate the need to parse tentatively by
! looking ahead a little bit. In some places, this approach
! might not entirely eliminate the need to parse tentatively, but
! it might still speed up the average case. */
/* Flags that are passed to some parsing functions. These values can
be bitwise-ored together. */
--- 1038,1048 ----
Future Improvements
-------------------
! The performance of the parser could probably be improved substantially.
! We could often eliminate the need to parse tentatively by looking ahead
! a little bit. In some places, this approach might not entirely eliminate
! the need to parse tentatively, but it might still speed up the average
! case. */
/* Flags that are passed to some parsing functions. These values can
be bitwise-ored together. */
***************
*** 1077,1096 ****
CP_PARSER_DECLARATOR_EITHER
} cp_parser_declarator_kind;
! /* A mapping from a token type to a corresponding tree node type. */
! typedef struct cp_parser_token_tree_map_node
{
/* The token type. */
! ENUM_BITFIELD (cpp_ttype) token_type : 8;
/* The corresponding tree code. */
! ENUM_BITFIELD (tree_code) tree_type : 8;
! } cp_parser_token_tree_map_node;
!
! /* A complete map consists of several ordinary entries, followed by a
! terminator. The terminating entry has a token_type of CPP_EOF. */
!
! typedef cp_parser_token_tree_map_node cp_parser_token_tree_map[];
/* The status of a tentative parse. */
--- 1070,1108 ----
CP_PARSER_DECLARATOR_EITHER
} cp_parser_declarator_kind;
! /* The precedence values used to parse binary expressions. The minimum value
! of PREC must be 1, because zero is reserved to quickly discriminate
! binary operators from other tokens. */
!
! enum cp_parser_prec
! {
! PREC_NOT_OPERATOR,
! PREC_LOGICAL_OR_EXPRESSION,
! PREC_LOGICAL_AND_EXPRESSION,
! PREC_INCLUSIVE_OR_EXPRESSION,
! PREC_EXCLUSIVE_OR_EXPRESSION,
! PREC_AND_EXPRESSION,
! PREC_RELATIONAL_EXPRESSION,
! PREC_EQUALITY_EXPRESSION,
! PREC_SHIFT_EXPRESSION,
! PREC_ADDITIVE_EXPRESSION,
! PREC_MULTIPLICATIVE_EXPRESSION,
! PREC_PM_EXPRESSION,
! NUM_PREC_VALUES = PREC_PM_EXPRESSION
! };
!
! /* A mapping from a token type to a corresponding tree node type, with a
! precedence value. */
! typedef struct cp_parser_binary_operations_map_node
{
/* The token type. */
! enum cpp_ttype token_type;
/* The corresponding tree code. */
! enum tree_code tree_type;
! /* The precedence of this operator. */
! enum cp_parser_prec prec;
! } cp_parser_binary_operations_map_node;
/* The status of a tentative parse. */
***************
*** 1105,1112 ****
CP_PARSER_STATUS_KIND_COMMITTED
} cp_parser_status_kind;
! /* Context that is saved and restored when parsing tentatively. */
typedef struct cp_parser_context GTY (())
{
/* If this is a tentative parsing context, the status of the
--- 1117,1133 ----
CP_PARSER_STATUS_KIND_COMMITTED
} cp_parser_status_kind;
! typedef struct cp_parser_expression_stack_entry
! {
! tree lhs;
! enum tree_code tree_type;
! int prec;
! } cp_parser_expression_stack_entry;
!
! typedef struct cp_parser_expression_stack_entry
! cp_parser_expression_stack[NUM_PREC_VALUES];
+ /* Context that is saved and restored when parsing tentatively. */
typedef struct cp_parser_context GTY (())
{
/* If this is a tentative parsing context, the status of the
***************
*** 1132,1137 ****
--- 1154,1203 ----
static GTY((deletable)) cp_parser_context* cp_parser_context_free_list;
+ /* The operator-precedence table used by cp_parser_binary_expression.
+ Transformed into an associative array (binops_by_token) by
+ cp_parser_new. */
+
+ static const cp_parser_binary_operations_map_node binops[] = {
+ { CPP_DEREF_STAR, MEMBER_REF, PREC_PM_EXPRESSION },
+ { CPP_DOT_STAR, DOTSTAR_EXPR, PREC_PM_EXPRESSION },
+
+ { CPP_MULT, MULT_EXPR, PREC_MULTIPLICATIVE_EXPRESSION },
+ { CPP_DIV, TRUNC_DIV_EXPR, PREC_MULTIPLICATIVE_EXPRESSION },
+ { CPP_MOD, TRUNC_MOD_EXPR, PREC_MULTIPLICATIVE_EXPRESSION },
+
+ { CPP_PLUS, PLUS_EXPR, PREC_ADDITIVE_EXPRESSION },
+ { CPP_MINUS, MINUS_EXPR, PREC_ADDITIVE_EXPRESSION },
+
+ { CPP_LSHIFT, LSHIFT_EXPR, PREC_SHIFT_EXPRESSION },
+ { CPP_RSHIFT, RSHIFT_EXPR, PREC_SHIFT_EXPRESSION },
+
+ { CPP_LESS, LT_EXPR, PREC_RELATIONAL_EXPRESSION },
+ { CPP_GREATER, GT_EXPR, PREC_RELATIONAL_EXPRESSION },
+ { CPP_LESS_EQ, LE_EXPR, PREC_RELATIONAL_EXPRESSION },
+ { CPP_GREATER_EQ, GE_EXPR, PREC_RELATIONAL_EXPRESSION },
+ { CPP_MIN, MIN_EXPR, PREC_RELATIONAL_EXPRESSION },
+ { CPP_MAX, MAX_EXPR, PREC_RELATIONAL_EXPRESSION },
+
+ { CPP_EQ_EQ, EQ_EXPR, PREC_EQUALITY_EXPRESSION },
+ { CPP_NOT_EQ, NE_EXPR, PREC_EQUALITY_EXPRESSION },
+
+ { CPP_AND, BIT_AND_EXPR, PREC_AND_EXPRESSION },
+
+ { CPP_XOR, BIT_XOR_EXPR, PREC_EXCLUSIVE_OR_EXPRESSION },
+
+ { CPP_OR, BIT_IOR_EXPR, PREC_INCLUSIVE_OR_EXPRESSION },
+
+ { CPP_AND_AND, TRUTH_ANDIF_EXPR, PREC_LOGICAL_AND_EXPRESSION },
+
+ { CPP_OR_OR, TRUTH_ORIF_EXPR, PREC_LOGICAL_OR_EXPRESSION }
+ };
+
+ /* The same as binops, but initialized by cp_parser_new so that
+ binops_by_token[N].token_type == N. Used in cp_parser_binary_expression
+ for speed. */
+ static cp_parser_binary_operations_map_node binops_by_token[N_TTYPES];
+
/* Constructors and destructors. */
/* Construct a new context. The context below this one on the stack
***************
*** 1152,1157 ****
--- 1218,1224 ----
}
else
context = GGC_CNEW (cp_parser_context);
+
/* No errors have occurred yet in this context. */
context->status = CP_PARSER_STATUS_KIND_NO_ERROR;
/* If this is not the bottomost context, copy information that we
***************
*** 1377,1403 ****
(cp_parser *);
static tree cp_parser_cast_expression
(cp_parser *, bool);
! static tree cp_parser_pm_expression
! (cp_parser *);
! static tree cp_parser_multiplicative_expression
! (cp_parser *);
! static tree cp_parser_additive_expression
! (cp_parser *);
! static tree cp_parser_shift_expression
! (cp_parser *);
! static tree cp_parser_relational_expression
! (cp_parser *);
! static tree cp_parser_equality_expression
! (cp_parser *);
! static tree cp_parser_and_expression
! (cp_parser *);
! static tree cp_parser_exclusive_or_expression
! (cp_parser *);
! static tree cp_parser_inclusive_or_expression
! (cp_parser *);
! static tree cp_parser_logical_and_expression
! (cp_parser *);
! static tree cp_parser_logical_or_expression
(cp_parser *);
static tree cp_parser_question_colon_clause
(cp_parser *, tree);
--- 1444,1450 ----
(cp_parser *);
static tree cp_parser_cast_expression
(cp_parser *, bool);
! static tree cp_parser_binary_expression
(cp_parser *);
static tree cp_parser_question_colon_clause
(cp_parser *, tree);
***************
*** 1651,1658 ****
(cp_parser *, unsigned);
static tree cp_parser_simple_cast_expression
(cp_parser *);
- static tree cp_parser_binary_expression
- (cp_parser *, const cp_parser_token_tree_map, cp_parser_expression_fn);
static tree cp_parser_global_scope_opt
(cp_parser *, bool);
static bool cp_parser_constructor_declarator_p
--- 1698,1703 ----
***************
*** 2340,2350 ****
--- 2385,2401 ----
{
cp_parser *parser;
cp_lexer *lexer;
+ unsigned i;
/* cp_lexer_new_main is called before calling ggc_alloc because
cp_lexer_new_main might load a PCH file. */
lexer = cp_lexer_new_main ();
+ /* Initialize the binops_by_token so that we can get the tree
+ directly from the token. */
+ for (i = 0; i < sizeof (binops) / sizeof (binops[0]); i++)
+ binops_by_token[binops[i].token_type] = binops[i];
+
parser = GGC_CNEW (cp_parser);
parser->lexer = lexer;
parser->context = cp_parser_context_new (NULL);
***************
*** 5161,5261 ****
return cp_parser_unary_expression (parser, address_p);
}
! /* Parse a pm-expression.
pm-expression:
cast-expression
pm-expression .* cast-expression
pm-expression ->* cast-expression
- Returns a representation of the expression. */
-
- static tree
- cp_parser_pm_expression (cp_parser* parser)
- {
- static const cp_parser_token_tree_map map = {
- { CPP_DEREF_STAR, MEMBER_REF },
- { CPP_DOT_STAR, DOTSTAR_EXPR },
- { CPP_EOF, ERROR_MARK }
- };
-
- return cp_parser_binary_expression (parser, map,
- cp_parser_simple_cast_expression);
- }
-
- /* Parse a multiplicative-expression.
-
multiplicative-expression:
pm-expression
multiplicative-expression * pm-expression
multiplicative-expression / pm-expression
multiplicative-expression % pm-expression
- Returns a representation of the expression. */
-
- static tree
- cp_parser_multiplicative_expression (cp_parser* parser)
- {
- static const cp_parser_token_tree_map map = {
- { CPP_MULT, MULT_EXPR },
- { CPP_DIV, TRUNC_DIV_EXPR },
- { CPP_MOD, TRUNC_MOD_EXPR },
- { CPP_EOF, ERROR_MARK }
- };
-
- return cp_parser_binary_expression (parser,
- map,
- cp_parser_pm_expression);
- }
-
- /* Parse an additive-expression.
-
additive-expression:
multiplicative-expression
additive-expression + multiplicative-expression
additive-expression - multiplicative-expression
- Returns a representation of the expression. */
-
- static tree
- cp_parser_additive_expression (cp_parser* parser)
- {
- static const cp_parser_token_tree_map map = {
- { CPP_PLUS, PLUS_EXPR },
- { CPP_MINUS, MINUS_EXPR },
- { CPP_EOF, ERROR_MARK }
- };
-
- return cp_parser_binary_expression (parser,
- map,
- cp_parser_multiplicative_expression);
- }
-
- /* Parse a shift-expression.
-
shift-expression:
additive-expression
shift-expression << additive-expression
shift-expression >> additive-expression
- Returns a representation of the expression. */
-
- static tree
- cp_parser_shift_expression (cp_parser* parser)
- {
- static const cp_parser_token_tree_map map = {
- { CPP_LSHIFT, LSHIFT_EXPR },
- { CPP_RSHIFT, RSHIFT_EXPR },
- { CPP_EOF, ERROR_MARK }
- };
-
- return cp_parser_binary_expression (parser,
- map,
- cp_parser_additive_expression);
- }
-
- /* Parse a relational-expression.
-
relational-expression:
shift-expression
relational-expression < shift-expression
--- 5212,5240 ----
return cp_parser_unary_expression (parser, address_p);
}
! /* Parse a binary expression of the general form:
pm-expression:
cast-expression
pm-expression .* cast-expression
pm-expression ->* cast-expression
multiplicative-expression:
pm-expression
multiplicative-expression * pm-expression
multiplicative-expression / pm-expression
multiplicative-expression % pm-expression
additive-expression:
multiplicative-expression
additive-expression + multiplicative-expression
additive-expression - multiplicative-expression
shift-expression:
additive-expression
shift-expression << additive-expression
shift-expression >> additive-expression
relational-expression:
shift-expression
relational-expression < shift-expression
***************
*** 5263,5423 ****
relational-expression <? shift-expression
relational-expression >? shift-expression
- Returns a representation of the expression. */
-
- static tree
- cp_parser_relational_expression (cp_parser* parser)
- {
- static const cp_parser_token_tree_map map = {
- { CPP_LESS, LT_EXPR },
- { CPP_GREATER, GT_EXPR },
- { CPP_LESS_EQ, LE_EXPR },
- { CPP_GREATER_EQ, GE_EXPR },
- { CPP_MIN, MIN_EXPR },
- { CPP_MAX, MAX_EXPR },
- { CPP_EOF, ERROR_MARK }
- };
-
- return cp_parser_binary_expression (parser,
- map,
- cp_parser_shift_expression);
- }
-
- /* Parse an equality-expression.
-
equality-expression:
relational-expression
equality-expression == relational-expression
equality-expression != relational-expression
- Returns a representation of the expression. */
-
- static tree
- cp_parser_equality_expression (cp_parser* parser)
- {
- static const cp_parser_token_tree_map map = {
- { CPP_EQ_EQ, EQ_EXPR },
- { CPP_NOT_EQ, NE_EXPR },
- { CPP_EOF, ERROR_MARK }
- };
-
- return cp_parser_binary_expression (parser,
- map,
- cp_parser_relational_expression);
- }
-
- /* Parse an and-expression.
-
and-expression:
equality-expression
and-expression & equality-expression
- Returns a representation of the expression. */
-
- static tree
- cp_parser_and_expression (cp_parser* parser)
- {
- static const cp_parser_token_tree_map map = {
- { CPP_AND, BIT_AND_EXPR },
- { CPP_EOF, ERROR_MARK }
- };
-
- return cp_parser_binary_expression (parser,
- map,
- cp_parser_equality_expression);
- }
-
- /* Parse an exclusive-or-expression.
-
exclusive-or-expression:
and-expression
exclusive-or-expression ^ and-expression
! Returns a representation of the expression. */
! static tree
! cp_parser_exclusive_or_expression (cp_parser* parser)
! {
! static const cp_parser_token_tree_map map = {
! { CPP_XOR, BIT_XOR_EXPR },
! { CPP_EOF, ERROR_MARK }
! };
! return cp_parser_binary_expression (parser,
! map,
! cp_parser_and_expression);
! }
! /* Parse an inclusive-or-expression.
! inclusive-or-expression:
! exclusive-or-expression
! inclusive-or-expression | exclusive-or-expression
! Returns a representation of the expression. */
static tree
! cp_parser_inclusive_or_expression (cp_parser* parser)
{
! static const cp_parser_token_tree_map map = {
! { CPP_OR, BIT_IOR_EXPR },
! { CPP_EOF, ERROR_MARK }
! };
! return cp_parser_binary_expression (parser,
! map,
! cp_parser_exclusive_or_expression);
! }
! /* Parse a logical-and-expression.
! logical-and-expression:
! inclusive-or-expression
! logical-and-expression && inclusive-or-expression
! Returns a representation of the expression. */
! static tree
! cp_parser_logical_and_expression (cp_parser* parser)
! {
! static const cp_parser_token_tree_map map = {
! { CPP_AND_AND, TRUTH_ANDIF_EXPR },
! { CPP_EOF, ERROR_MARK }
! };
! return cp_parser_binary_expression (parser,
! map,
! cp_parser_inclusive_or_expression);
! }
! /* Parse a logical-or-expression.
! logical-or-expression:
! logical-and-expression
! logical-or-expression || logical-and-expression
! Returns a representation of the expression. */
! static tree
! cp_parser_logical_or_expression (cp_parser* parser)
! {
! static const cp_parser_token_tree_map map = {
! { CPP_OR_OR, TRUTH_ORIF_EXPR },
! { CPP_EOF, ERROR_MARK }
! };
!
! return cp_parser_binary_expression (parser,
! map,
! cp_parser_logical_and_expression);
}
/* Parse the `? expression : assignment-expression' part of a
conditional-expression. The LOGICAL_OR_EXPR is the
logical-or-expression that started the conditional-expression.
--- 5242,5389 ----
relational-expression <? shift-expression
relational-expression >? shift-expression
equality-expression:
relational-expression
equality-expression == relational-expression
equality-expression != relational-expression
and-expression:
equality-expression
and-expression & equality-expression
exclusive-or-expression:
and-expression
exclusive-or-expression ^ and-expression
! inclusive-or-expression:
! exclusive-or-expression
! inclusive-or-expression | exclusive-or-expression
! logical-and-expression:
! inclusive-or-expression
! logical-and-expression && inclusive-or-expression
! logical-or-expression:
! logical-and-expression
! logical-or-expression || logical-and-expression
+ All these are implemented with a single function like:
! binary-expression:
! simple-cast-expression
! binary-expression <token> binary-expression
! The binops_by_token map is used to get the tree codes for each <token> type.
! binary-expressions are associated according to a precedence table. */
! #define TOKEN_PRECEDENCE(token) \
! ((token->type == CPP_GREATER && !parser->greater_than_is_operator_p) \
! ? PREC_NOT_OPERATOR \
! : binops_by_token[token->type].prec)
static tree
! cp_parser_binary_expression (cp_parser* parser)
{
! cp_parser_expression_stack stack;
! cp_parser_expression_stack_entry *sp = &stack[0];
! tree lhs, rhs;
! cp_token *token;
! enum tree_code tree_type;
! enum cp_parser_prec prec = PREC_NOT_OPERATOR, new_prec, lookahead_prec;
! bool overloaded_p;
! /* Parse the first expression. */
! lhs = cp_parser_simple_cast_expression (parser);
! for (;;)
! {
! /* Get an operator token. */
! token = cp_lexer_peek_token (parser->lexer);
! new_prec = TOKEN_PRECEDENCE (token);
! /* Popping an entry off the stack means we completed a subexpression:
! - either we found a token which is not an operator (`>' where it is not
! an operator, or prec == PREC_NOT_OPERATOR), in which case popping
! will happen repeatedly;
! - or, we found an operator which has lower priority. This is the case
! where the recursive descent *ascends*, as in `3 * 4 + 5' after
! parsing `3 * 4'. */
! if (new_prec <= prec)
! {
! if (sp == stack)
! break;
! else
! goto pop;
! }
! get_rhs:
! tree_type = binops_by_token[token->type].tree_type;
! /* We used the operator token. */
! cp_lexer_consume_token (parser->lexer);
! /* Extract another operand. It may be the RHS of this expression
! or the LHS of a new, higher priority expression. */
! rhs = cp_parser_simple_cast_expression (parser);
! /* Get another operator token. Look up its precedence to avoid
! building a useless (immediately popped) stack entry for common
! cases such as 3 + 4 + 5 or 3 * 4 + 5. */
! token = cp_lexer_peek_token (parser->lexer);
! lookahead_prec = TOKEN_PRECEDENCE (token);
! if (lookahead_prec > new_prec)
! {
! /* ... and prepare to parse the RHS of the new, higher priority
! expression. */
! sp->prec = prec;
! sp->tree_type = tree_type;
! sp->lhs = lhs;
! sp++;
! lhs = rhs;
! prec = new_prec;
! new_prec = lookahead_prec;
! goto get_rhs;
!
! pop:
! /* If the stack is not empty, we have parsed into LHS the right side
! (`4' in the example above) of an expression we had suspended.
! We can use the information on the stack to recover the LHS (`3')
! from the stack together with the tree code (`MULT_EXPR'), and
! the precedence of the higher level subexpression
! (`PREC_ADDITIVE_EXPRESSION'). TOKEN is the CPP_PLUS token,
! which will be used to actually build the additive expression. */
! --sp;
! prec = sp->prec;
! tree_type = sp->tree_type;
! rhs = lhs;
! lhs = sp->lhs;
! }
! overloaded_p = false;
! lhs = build_x_binary_op (tree_type, lhs, rhs, &overloaded_p);
! /* If the binary operator required the use of an overloaded operator,
! then this expression cannot be an integral constant-expression.
! An overloaded operator can be used even if both operands are
! otherwise permissible in an integral constant-expression if at
! least one of the operands is of enumeration type. */
!
! if (overloaded_p
! && (cp_parser_non_integral_constant_expression
! (parser, "calls to overloaded operators")))
! return error_mark_node;
! }
! return lhs;
}
+
/* Parse the `? expression : assignment-expression' part of a
conditional-expression. The LOGICAL_OR_EXPR is the
logical-or-expression that started the conditional-expression.
***************
*** 5480,5487 ****
logical-or-expression. */
else
{
! /* Parse the logical-or-expression. */
! expr = cp_parser_logical_or_expression (parser);
/* If the next token is a `?' then we're actually looking at a
conditional-expression. */
if (cp_lexer_next_token_is (parser->lexer, CPP_QUERY))
--- 5446,5453 ----
logical-or-expression. */
else
{
! /* Parse the binary expressions (logical-or-expression). */
! expr = cp_parser_binary_expression (parser);
/* If the next token is a `?' then we're actually looking at a
conditional-expression. */
if (cp_lexer_next_token_is (parser->lexer, CPP_QUERY))
***************
*** 14411,14489 ****
return false;
}
- /* Parse a binary-expression of the general form:
-
- binary-expression:
- <expr>
- binary-expression <token> <expr>
-
- The TOKEN_TREE_MAP maps <token> types to <expr> codes. FN is used
- to parser the <expr>s. If the first production is used, then the
- value returned by FN is returned directly. Otherwise, a node with
- the indicated EXPR_TYPE is returned, with operands corresponding to
- the two sub-expressions. */
-
- static tree
- cp_parser_binary_expression (cp_parser* parser,
- const cp_parser_token_tree_map token_tree_map,
- cp_parser_expression_fn fn)
- {
- tree lhs;
-
- /* Parse the first expression. */
- lhs = (*fn) (parser);
- /* Now, look for more expressions. */
- while (true)
- {
- cp_token *token;
- const cp_parser_token_tree_map_node *map_node;
- tree rhs;
-
- /* Peek at the next token. */
- token = cp_lexer_peek_token (parser->lexer);
- /* If the token is `>', and that's not an operator at the
- moment, then we're done. */
- if (token->type == CPP_GREATER
- && !parser->greater_than_is_operator_p)
- break;
- /* If we find one of the tokens we want, build the corresponding
- tree representation. */
- for (map_node = token_tree_map;
- map_node->token_type != CPP_EOF;
- ++map_node)
- if (map_node->token_type == token->type)
- {
- /* Assume that an overloaded operator will not be used. */
- bool overloaded_p = false;
-
- /* Consume the operator token. */
- cp_lexer_consume_token (parser->lexer);
- /* Parse the right-hand side of the expression. */
- rhs = (*fn) (parser);
- /* Build the binary tree node. */
- lhs = build_x_binary_op (map_node->tree_type, lhs, rhs,
- &overloaded_p);
- /* If the binary operator required the use of an
- overloaded operator, then this expression cannot be an
- integral constant-expression. An overloaded operator
- can be used even if both operands are otherwise
- permissible in an integral constant-expression if at
- least one of the operands is of enumeration type. */
- if (overloaded_p
- && (cp_parser_non_integral_constant_expression
- (parser, "calls to overloaded operators")))
- lhs = error_mark_node;
- break;
- }
-
- /* If the token wasn't one of the ones we want, we're done. */
- if (map_node->token_type == CPP_EOF)
- break;
- }
-
- return lhs;
- }
-
/* Parse an optional `::' token indicating that the following name is
from the global namespace. If so, PARSER->SCOPE is set to the
GLOBAL_NAMESPACE. Otherwise, PARSER->SCOPE is set to NULL_TREE,
--- 14377,14382 ----