static tree cp_parser_qualifying_entity
(cp_parser *, bool, bool, bool, bool, bool);
static tree cp_parser_postfix_expression
- (cp_parser *, bool, bool, bool, cp_id_kind *);
+ (cp_parser *, bool, bool, bool, bool, cp_id_kind *);
static tree cp_parser_postfix_open_square_expression
(cp_parser *, tree, bool);
static tree cp_parser_postfix_dot_deref_expression
static tree cp_parser_delete_expression
(cp_parser *);
static tree cp_parser_cast_expression
- (cp_parser *, bool, bool, cp_id_kind *);
+ (cp_parser *, bool, bool, bool, cp_id_kind *);
static tree cp_parser_binary_expression
(cp_parser *, bool, bool, enum cp_parser_prec, cp_id_kind *);
static tree cp_parser_question_colon_clause
(cp_parser *);
static tree cp_parser_expression
(cp_parser *, bool, cp_id_kind *);
+static tree cp_parser_expression
+ (cp_parser *, bool, bool, cp_id_kind *);
static tree cp_parser_constant_expression
(cp_parser *, bool, bool *);
static tree cp_parser_builtin_offsetof
bool address_p,
bool cast_p,
bool template_arg_p,
+ bool decltype_p,
cp_id_kind *idk)
{
cp_token *token = NULL;
else
{
/* Parse the parenthesized expression. */
- expr = cp_parser_expression (parser, cast_p, idk);
+ expr = cp_parser_expression (parser, cast_p, decltype_p, idk);
/* Let the front end know that this expression was
enclosed in parentheses. This matters in case, for
example, the expression is of the form `A::B', since
}
}
+static inline tree
+cp_parser_primary_expression (cp_parser *parser,
+ bool address_p,
+ bool cast_p,
+ bool template_arg_p,
+ cp_id_kind *idk)
+{
+ return cp_parser_primary_expression (parser, address_p, cast_p, template_arg_p,
+ /*decltype*/false, idk);
+}
+
/* Parse an id-expression.
id-expression:
static tree
cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
- bool member_access_only_p,
+ bool member_access_only_p, bool decltype_p,
cp_id_kind * pidk_return)
{
cp_token *token;
postfix_expression
= cp_parser_primary_expression (parser, address_p, cast_p,
/*template_arg_p=*/false,
+ decltype_p,
&idk);
}
break;
}
+ /* Note that we don't need to worry about calling build_cplus_new on a
+ class-valued CALL_EXPR in decltype when it isn't the end of the
+ postfix-expression; unary_complex_lvalue will take care of that for
+ all these cases. */
+
/* Keep looping until the postfix-expression is complete. */
while (true)
{
bool is_builtin_constant_p;
bool saved_integral_constant_expression_p = false;
bool saved_non_integral_constant_expression_p = false;
+ int complain = tf_warning_or_error;
vec<tree, va_gc> *args;
+ if (decltype_p)
+ complain |= tf_decltype;
+
is_member_access = false;
is_builtin_constant_p
postfix_expression
= perform_koenig_lookup (postfix_expression, args,
/*include_std=*/false,
- tf_warning_or_error);
+ complain);
}
else
postfix_expression
postfix_expression
= perform_koenig_lookup (postfix_expression, args,
/*include_std=*/false,
- tf_warning_or_error);
+ complain);
}
}
}
? LOOKUP_NORMAL|LOOKUP_NONVIRTUAL
: LOOKUP_NORMAL),
/*fn_p=*/NULL,
- tf_warning_or_error));
+ complain));
}
else
postfix_expression
= finish_call_expr (postfix_expression, &args,
/*disallow_virtual=*/false,
/*koenig_p=*/false,
- tf_warning_or_error);
+ complain);
}
else if (TREE_CODE (postfix_expression) == OFFSET_REF
|| TREE_CODE (postfix_expression) == MEMBER_REF
|| TREE_CODE (postfix_expression) == DOTSTAR_EXPR)
postfix_expression = (build_offset_ref_call_from_tree
(postfix_expression, &args,
- tf_warning_or_error));
+ complain));
else if (idk == CP_ID_KIND_QUALIFIED)
/* A call to a static class member, or a namespace-scope
function. */
= finish_call_expr (postfix_expression, &args,
/*disallow_virtual=*/true,
koenig_p,
- tf_warning_or_error);
+ complain);
else
/* All other function calls. */
postfix_expression
= finish_call_expr (postfix_expression, &args,
/*disallow_virtual=*/false,
koenig_p,
- tf_warning_or_error);
+ complain);
/* The POSTFIX_EXPRESSION is certainly no longer an id. */
idk = CP_ID_KIND_NONE;
static tree
cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p,
- cp_id_kind * pidk)
+ bool decltype_p, cp_id_kind * pidk)
{
cp_token *token;
enum tree_code unary_operator;
cast_expression
= cp_parser_cast_expression (parser,
unary_operator == ADDR_EXPR,
- /*cast_p=*/false, pidk);
+ /*cast_p=*/false,
+ /*decltype*/false,
+ pidk);
/* Now, build an appropriate representation. */
switch (unary_operator)
{
return cp_parser_postfix_expression (parser, address_p, cast_p,
/*member_access_only_p=*/false,
+ decltype_p,
pidk);
}
+static inline tree
+cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p,
+ cp_id_kind * pidk)
+{
+ return cp_parser_unary_expression (parser, address_p, cast_p,
+ /*decltype*/false, pidk);
+}
+
/* Returns ERROR_MARK if TOKEN is not a unary-operator. If TOKEN is a
unary-operator, the corresponding tree code is returned. */
static tree
cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
- cp_id_kind * pidk)
+ bool decltype_p, cp_id_kind * pidk)
{
/* If it's a `(', then we might be looking at a cast. */
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
cp_parser_parse_definitely (parser);
expr = cp_parser_cast_expression (parser,
/*address_p=*/false,
- /*cast_p=*/true, pidk);
+ /*cast_p=*/true,
+ /*decltype_p=*/false,
+ pidk);
/* Warn about old-style casts, if so requested. */
if (warn_old_style_cast
/* If we get here, then it's not a cast, so it must be a
unary-expression. */
- return cp_parser_unary_expression (parser, address_p, cast_p, pidk);
+ return cp_parser_unary_expression (parser, address_p, cast_p,
+ decltype_p, pidk);
}
/* Parse a binary expression of the general form:
static tree
cp_parser_binary_expression (cp_parser* parser, bool cast_p,
bool no_toplevel_fold_p,
+ bool decltype_p,
enum cp_parser_prec prec,
cp_id_kind * pidk)
{
/* Parse the first expression. */
current.lhs = cp_parser_cast_expression (parser, /*address_p=*/false,
- cast_p, pidk);
+ cast_p, decltype_p, pidk);
current.lhs_type = ERROR_MARK;
current.prec = prec;
return current.lhs;
}
+static tree
+cp_parser_binary_expression (cp_parser* parser, bool cast_p,
+ bool no_toplevel_fold_p,
+ enum cp_parser_prec prec,
+ cp_id_kind * pidk)
+{
+ return cp_parser_binary_expression (parser, cast_p, no_toplevel_fold_p,
+ /*decltype*/false, prec, pidk);
+}
/* Parse the `? expression : assignment-expression' part of a
conditional-expression. The LOGICAL_OR_EXPR is the
throw-expression
CAST_P is true if this expression is the target of a cast.
+ DECLTYPE_P is true if this expression is the operand of decltype.
Returns a representation for the expression. */
static tree
cp_parser_assignment_expression (cp_parser* parser, bool cast_p,
- cp_id_kind * pidk)
+ bool decltype_p, cp_id_kind * pidk)
{
tree expr;
{
/* Parse the binary expressions (logical-or-expression). */
expr = cp_parser_binary_expression (parser, cast_p, false,
+ decltype_p,
PREC_NOT_OPERATOR, pidk);
/* If the next token is a `?' then we're actually looking at a
conditional-expression. */
return expr;
}
+static tree
+cp_parser_assignment_expression (cp_parser* parser, bool cast_p,
+ cp_id_kind * pidk)
+{
+ return cp_parser_assignment_expression (parser, cast_p,
+ /*decltype*/false, pidk);
+}
+
/* Parse an (optional) assignment-operator.
assignment-operator: one of
expression , assignment-expression
CAST_P is true if this expression is the target of a cast.
+ DECLTYPE_P is true if this expression is the immediate operand of decltype,
+ except possibly parenthesized or on the RHS of a comma (N3276).
Returns a representation of the expression. */
static tree
-cp_parser_expression (cp_parser* parser, bool cast_p, cp_id_kind * pidk)
+cp_parser_expression (cp_parser* parser, bool cast_p, bool decltype_p,
+ cp_id_kind * pidk)
{
tree expression = NULL_TREE;
location_t loc = UNKNOWN_LOCATION;
/* Parse the next assignment-expression. */
assignment_expression
- = cp_parser_assignment_expression (parser, cast_p, pidk);
+ = cp_parser_assignment_expression (parser, cast_p, decltype_p, pidk);
+
+ /* We don't create a temporary for a call that is the immediate operand
+ of decltype or on the RHS of a comma. But when we see a comma, we
+ need to create a temporary for a call on the LHS. */
+ if (decltype_p && !processing_template_decl
+ && TREE_CODE (assignment_expression) == CALL_EXPR
+ && CLASS_TYPE_P (TREE_TYPE (assignment_expression))
+ && cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+ assignment_expression
+ = build_cplus_new (TREE_TYPE (assignment_expression),
+ assignment_expression, tf_warning_or_error);
+
/* If this is the first assignment-expression, we can just
save it away. */
if (!expression)
return expression;
}
+static inline tree
+cp_parser_expression (cp_parser* parser, bool cast_p, cp_id_kind * pidk)
+{
+ return cp_parser_expression (parser, cast_p, /*decltype*/false, pidk);
+}
+
/* Parse a constant-expression.
constant-expression:
/* Parse a class member access. */
expr = cp_parser_postfix_expression (parser, /*address_p=*/false,
- /*cast_p=*/false,
+ /*cast_p=*/false, /*decltype*/true,
/*member_access_only_p=*/true, NULL);
if (expr
parser->greater_than_is_operator_p = true;
/* Parse a full expression. */
- expr = cp_parser_expression (parser, /*cast_p=*/false, NULL);
+ expr = cp_parser_expression (parser, /*cast_p=*/false,
+ /*decltype*/true, NULL);
/* The `>' token might be the end of a template-id or
template-parameter-list now. */
cp_parser_simple_cast_expression (cp_parser *parser)
{
return cp_parser_cast_expression (parser, /*address_p=*/false,
- /*cast_p=*/false, NULL);
+ /*cast_p=*/false, /*decltype*/false, NULL);
}
/* Parse a functional cast to TYPE. Returns an expression
op = (token->type == CPP_PLUS_PLUS
? PREINCREMENT_EXPR : PREDECREMENT_EXPR);
cp_lexer_consume_token (parser->lexer);
- lhs = cp_parser_cast_expression (parser, false, false, NULL);
+ lhs = cp_parser_simple_cast_expression (parser);
if (lhs != decl)
return error_mark_node;
return build2 (op, TREE_TYPE (decl), decl, NULL_TREE);