re PR c++/52748 ([C++11] N3276 changes to decltype)
N3276 PR c++/52748 * cp-tree.h (tsubst_flags): Add tf_decltype. * call.c (build_cxx_call): Don't build a temporary if it's set. (build_over_call): Make sure it's only passed to build_cxx_call. * parser.c (cp_parser_primary_expression): Add decltype_p parm. (cp_parser_unary_expression): Likewise. (cp_parser_cast_expression): Likewise. (cp_parser_binary_expression): Likewise. (cp_parser_assignment_expression): Likewise. (cp_parser_postfix_expression): Likewise. Pass tf_decltype. (cp_parser_explicit_instantiation): Add decltype_p. Force a temporary for a call on the LHS of a comma. (cp_parser_decltype): Pass true to decltype_p parms. * pt.c (tsubst) [DECLTYPE_TYPE]: Pass tf_decltype. (tsubst_copy_and_build): Pass tf_decltype down only for CALL_EXPR and the RHS of COMPOUND_EXPR. * tree.c (build_cplus_new): Call complete_type_or_maybe_complain. From-SVN: r196736
This commit is contained in:
parent
2df663cced
commit
57fcd4f4e4
|
@ -1,5 +1,24 @@
|
|||
2013-03-16 Jason Merrill <jason@redhat.com>
|
||||
|
||||
N3276
|
||||
PR c++/52748
|
||||
* cp-tree.h (tsubst_flags): Add tf_decltype.
|
||||
* call.c (build_cxx_call): Don't build a temporary if it's set.
|
||||
(build_over_call): Make sure it's only passed to build_cxx_call.
|
||||
* parser.c (cp_parser_primary_expression): Add decltype_p parm.
|
||||
(cp_parser_unary_expression): Likewise.
|
||||
(cp_parser_cast_expression): Likewise.
|
||||
(cp_parser_binary_expression): Likewise.
|
||||
(cp_parser_assignment_expression): Likewise.
|
||||
(cp_parser_postfix_expression): Likewise. Pass tf_decltype.
|
||||
(cp_parser_explicit_instantiation): Add decltype_p. Force a
|
||||
temporary for a call on the LHS of a comma.
|
||||
(cp_parser_decltype): Pass true to decltype_p parms.
|
||||
* pt.c (tsubst) [DECLTYPE_TYPE]: Pass tf_decltype.
|
||||
(tsubst_copy_and_build): Pass tf_decltype down only for
|
||||
CALL_EXPR and the RHS of COMPOUND_EXPR.
|
||||
* tree.c (build_cplus_new): Call complete_type_or_maybe_complain.
|
||||
|
||||
* cp-tree.h (abstract_class_use): New enum.
|
||||
* typeck2.c (pending_abstract_type): Add use field.
|
||||
(abstract_virtuals_error_sfinae): Add overloads taking
|
||||
|
|
|
@ -6693,6 +6693,10 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
|
|||
/* else continue to get conversion error. */
|
||||
}
|
||||
|
||||
/* N3276 magic doesn't apply to nested calls. */
|
||||
int decltype_flag = (complain & tf_decltype);
|
||||
complain &= ~tf_decltype;
|
||||
|
||||
/* Find maximum size of vector to hold converted arguments. */
|
||||
parmlen = list_length (parm);
|
||||
nargs = vec_safe_length (args) + (first_arg != NULL_TREE ? 1 : 0);
|
||||
|
@ -7064,7 +7068,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
|
|||
return error_mark_node;
|
||||
}
|
||||
|
||||
return build_cxx_call (fn, nargs, argarray, complain);
|
||||
return build_cxx_call (fn, nargs, argarray, complain|decltype_flag);
|
||||
}
|
||||
|
||||
/* Build and return a call to FN, using NARGS arguments in ARGARRAY.
|
||||
|
@ -7106,12 +7110,20 @@ build_cxx_call (tree fn, int nargs, tree *argarray,
|
|||
if (VOID_TYPE_P (TREE_TYPE (fn)))
|
||||
return fn;
|
||||
|
||||
fn = require_complete_type_sfinae (fn, complain);
|
||||
if (fn == error_mark_node)
|
||||
return error_mark_node;
|
||||
/* 5.2.2/11: If a function call is a prvalue of object type: if the
|
||||
function call is either the operand of a decltype-specifier or the
|
||||
right operand of a comma operator that is the operand of a
|
||||
decltype-specifier, a temporary object is not introduced for the
|
||||
prvalue. The type of the prvalue may be incomplete. */
|
||||
if (!(complain & tf_decltype))
|
||||
{
|
||||
fn = require_complete_type_sfinae (fn, complain);
|
||||
if (fn == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
if (MAYBE_CLASS_TYPE_P (TREE_TYPE (fn)))
|
||||
fn = build_cplus_new (TREE_TYPE (fn), fn, complain);
|
||||
if (MAYBE_CLASS_TYPE_P (TREE_TYPE (fn)))
|
||||
fn = build_cplus_new (TREE_TYPE (fn), fn, complain);
|
||||
}
|
||||
return convert_from_reference (fn);
|
||||
}
|
||||
|
||||
|
|
|
@ -4203,6 +4203,9 @@ enum tsubst_flags {
|
|||
conversion might be permissible,
|
||||
not actually performing the
|
||||
conversion. */
|
||||
tf_decltype = 1 << 7, /* We are the operand of decltype.
|
||||
Used to implement the special rules
|
||||
for calls in decltype (5.2.2/11). */
|
||||
tf_partial = 1 << 8, /* Doing initial explicit argument
|
||||
substitution in fn_type_unification. */
|
||||
/* Convenient substitution flags combinations. */
|
||||
|
|
128
gcc/cp/parser.c
128
gcc/cp/parser.c
|
@ -1802,7 +1802,7 @@ static tree cp_parser_nested_name_specifier
|
|||
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
|
||||
|
@ -1832,7 +1832,7 @@ static vec<tree, va_gc> *cp_parser_new_initializer
|
|||
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
|
||||
|
@ -1843,6 +1843,8 @@ static enum tree_code cp_parser_assignment_operator_opt
|
|||
(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
|
||||
|
@ -3900,6 +3902,7 @@ cp_parser_primary_expression (cp_parser *parser,
|
|||
bool address_p,
|
||||
bool cast_p,
|
||||
bool template_arg_p,
|
||||
bool decltype_p,
|
||||
cp_id_kind *idk)
|
||||
{
|
||||
cp_token *token = NULL;
|
||||
|
@ -4051,7 +4054,7 @@ cp_parser_primary_expression (cp_parser *parser,
|
|||
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
|
||||
|
@ -4403,6 +4406,17 @@ cp_parser_primary_expression (cp_parser *parser,
|
|||
}
|
||||
}
|
||||
|
||||
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:
|
||||
|
@ -5364,7 +5378,7 @@ cp_parser_qualifying_entity (cp_parser *parser,
|
|||
|
||||
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;
|
||||
|
@ -5625,11 +5639,17 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
|
|||
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)
|
||||
{
|
||||
|
@ -5668,8 +5688,12 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
|
|||
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
|
||||
|
@ -5726,7 +5750,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
|
|||
postfix_expression
|
||||
= perform_koenig_lookup (postfix_expression, args,
|
||||
/*include_std=*/false,
|
||||
tf_warning_or_error);
|
||||
complain);
|
||||
}
|
||||
else
|
||||
postfix_expression
|
||||
|
@ -5752,7 +5776,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
|
|||
postfix_expression
|
||||
= perform_koenig_lookup (postfix_expression, args,
|
||||
/*include_std=*/false,
|
||||
tf_warning_or_error);
|
||||
complain);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5784,21 +5808,21 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
|
|||
? 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. */
|
||||
|
@ -5806,14 +5830,14 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
|
|||
= 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;
|
||||
|
@ -6414,7 +6438,7 @@ cp_parser_pseudo_destructor_name (cp_parser* parser,
|
|||
|
||||
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;
|
||||
|
@ -6635,7 +6659,9 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p,
|
|||
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)
|
||||
{
|
||||
|
@ -6681,9 +6707,18 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p,
|
|||
|
||||
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. */
|
||||
|
||||
|
@ -7162,7 +7197,7 @@ cp_parser_tokens_start_cast_expression (cp_parser *parser)
|
|||
|
||||
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))
|
||||
|
@ -7236,7 +7271,9 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
|
|||
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
|
||||
|
@ -7262,7 +7299,8 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
|
|||
|
||||
/* 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:
|
||||
|
@ -7347,6 +7385,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
|
|||
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)
|
||||
{
|
||||
|
@ -7361,7 +7400,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
|
|||
|
||||
/* 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;
|
||||
|
||||
|
@ -7498,6 +7537,15 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
|
|||
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
|
||||
|
@ -7567,12 +7615,13 @@ cp_parser_question_colon_clause (cp_parser* parser, tree logical_or_expr)
|
|||
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;
|
||||
|
||||
|
@ -7586,6 +7635,7 @@ cp_parser_assignment_expression (cp_parser* parser, bool cast_p,
|
|||
{
|
||||
/* 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. */
|
||||
|
@ -7631,6 +7681,14 @@ cp_parser_assignment_expression (cp_parser* parser, bool cast_p,
|
|||
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
|
||||
|
@ -7722,11 +7780,14 @@ cp_parser_assignment_operator_opt (cp_parser* parser)
|
|||
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;
|
||||
|
@ -7737,7 +7798,19 @@ cp_parser_expression (cp_parser* parser, bool cast_p, cp_id_kind * pidk)
|
|||
|
||||
/* 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)
|
||||
|
@ -7761,6 +7834,12 @@ cp_parser_expression (cp_parser* parser, bool cast_p, cp_id_kind * pidk)
|
|||
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:
|
||||
|
@ -11287,7 +11366,7 @@ cp_parser_decltype (cp_parser *parser)
|
|||
|
||||
/* 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
|
||||
|
@ -11315,7 +11394,8 @@ cp_parser_decltype (cp_parser *parser)
|
|||
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. */
|
||||
|
@ -22034,7 +22114,7 @@ static tree
|
|||
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
|
||||
|
@ -26831,7 +26911,7 @@ cp_parser_omp_for_incr (cp_parser *parser, tree decl)
|
|||
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);
|
||||
|
|
29
gcc/cp/pt.c
29
gcc/cp/pt.c
|
@ -11781,7 +11781,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
|
|||
++c_inhibit_evaluation_warnings;
|
||||
|
||||
type = tsubst_expr (DECLTYPE_TYPE_EXPR (t), args,
|
||||
complain, in_decl,
|
||||
complain|tf_decltype, in_decl,
|
||||
/*integral_constant_expression_p=*/false);
|
||||
|
||||
--cp_unevaluated_operand;
|
||||
|
@ -13417,6 +13417,12 @@ tsubst_copy_and_build (tree t,
|
|||
if (EXPR_HAS_LOCATION (t))
|
||||
input_location = EXPR_LOCATION (t);
|
||||
|
||||
/* N3276 decltype magic only applies to calls at the top level or on the
|
||||
right side of a comma. */
|
||||
if (TREE_CODE (t) != CALL_EXPR
|
||||
&& TREE_CODE (t) != COMPOUND_EXPR)
|
||||
complain &= ~tf_decltype;
|
||||
|
||||
switch (TREE_CODE (t))
|
||||
{
|
||||
case USING_DECL:
|
||||
|
@ -13848,10 +13854,16 @@ tsubst_copy_and_build (tree t,
|
|||
complain));
|
||||
|
||||
case COMPOUND_EXPR:
|
||||
RETURN (build_x_compound_expr (EXPR_LOCATION (t),
|
||||
RECUR (TREE_OPERAND (t, 0)),
|
||||
RECUR (TREE_OPERAND (t, 1)),
|
||||
complain));
|
||||
{
|
||||
tree op0 = tsubst_copy_and_build (TREE_OPERAND (t, 0), args,
|
||||
complain & ~tf_decltype, in_decl,
|
||||
/*function_p=*/false,
|
||||
integral_constant_expression_p);
|
||||
RETURN (build_x_compound_expr (EXPR_LOCATION (t),
|
||||
op0,
|
||||
RECUR (TREE_OPERAND (t, 1)),
|
||||
complain));
|
||||
}
|
||||
|
||||
case CALL_EXPR:
|
||||
{
|
||||
|
@ -13862,6 +13874,10 @@ tsubst_copy_and_build (tree t,
|
|||
bool koenig_p;
|
||||
tree ret;
|
||||
|
||||
/* Don't pass tf_decltype down to subexpressions. */
|
||||
tsubst_flags_t decltype_flag = (complain & tf_decltype);
|
||||
complain &= ~tf_decltype;
|
||||
|
||||
function = CALL_EXPR_FN (t);
|
||||
/* When we parsed the expression, we determined whether or
|
||||
not Koenig lookup should be performed. */
|
||||
|
@ -14028,6 +14044,9 @@ tsubst_copy_and_build (tree t,
|
|||
if (DECL_P (function))
|
||||
mark_used (function);
|
||||
|
||||
/* Put back tf_decltype for the actual call. */
|
||||
complain |= decltype_flag;
|
||||
|
||||
if (TREE_CODE (function) == OFFSET_REF)
|
||||
ret = build_offset_ref_call_from_tree (function, &call_args,
|
||||
complain);
|
||||
|
|
|
@ -469,6 +469,9 @@ build_cplus_new (tree type, tree init, tsubst_flags_t complain)
|
|||
tree rval = build_aggr_init_expr (type, init);
|
||||
tree slot;
|
||||
|
||||
if (!complete_type_or_maybe_complain (type, init, complain))
|
||||
return error_mark_node;
|
||||
|
||||
/* Make sure that we're not trying to create an instance of an
|
||||
abstract class. */
|
||||
if (abstract_virtuals_error_sfinae (NULL_TREE, type, complain))
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
// PR c++/52748
|
||||
// N3276
|
||||
// { dg-do compile { target c++11 } }
|
||||
|
||||
struct A; // { dg-error "forward declaration" }
|
||||
A f();
|
||||
|
||||
decltype(f()) g1(); // OK
|
||||
decltype(((f()))) g2b(); // OK
|
||||
decltype(42,f()) g3(); // OK
|
||||
decltype(42,45,f()) g3b(); // OK
|
||||
decltype(42,45,(f())) g3c(); // OK
|
||||
decltype(42,((45,(f())))) g3c(); // OK
|
||||
|
||||
decltype(f(),42) g4(); // { dg-error "" }
|
||||
decltype(45,f(),42) g4b(); // { dg-error "" }
|
||||
|
||||
class B
|
||||
{
|
||||
~B(); // { dg-error "private" }
|
||||
public:
|
||||
int i;
|
||||
void operator[](int);
|
||||
};
|
||||
B h();
|
||||
|
||||
void i(const B&);
|
||||
|
||||
decltype(h()) g5a(); // OK
|
||||
decltype(h().i) g5(); // { dg-error "" }
|
||||
decltype(h()[0]) g6(); // { dg-error "" }
|
||||
decltype(i(h())) g7(); // { dg-error "" }
|
Loading…
Reference in New Issue