parser.c (struct cp_parser_expression_stack_entry): Add location_t field.

/cp
2012-05-12  Paolo Carlini  <paolo.carlini@oracle.com>

	* parser.c (struct cp_parser_expression_stack_entry): Add location_t
	field.
	(cp_parser_binary_expression): Rework to always update at the same
	time tree_type and loc.
	* call.c (print_z_candidate): Add location_t parameter.
	(print_z_candidates, convert_like_real, joust): Adjust.

/testsuite
2012-05-12  Paolo Carlini  <paolo.carlini@oracle.com>

	* g++.dg/parse/error47.C: New.

From-SVN: r187424
This commit is contained in:
Paolo Carlini 2012-05-12 08:41:29 +00:00 committed by Paolo Carlini
parent 819dc46137
commit 498ad15e8c
5 changed files with 88 additions and 61 deletions

View File

@ -1,3 +1,12 @@
2012-05-12 Paolo Carlini <paolo.carlini@oracle.com>
* parser.c (struct cp_parser_expression_stack_entry): Add location_t
field.
(cp_parser_binary_expression): Rework to always update at the same
time tree_type and loc.
* call.c (print_z_candidate): Add location_t parameter.
(print_z_candidates, convert_like_real, joust): Adjust.
2012-05-11 Alexandre Oliva <aoliva@redhat.com>
PR c++/53209

View File

@ -163,7 +163,7 @@ static void op_error (location_t, enum tree_code, enum tree_code, tree,
tree, tree, bool);
static struct z_candidate *build_user_type_conversion_1 (tree, tree, int,
tsubst_flags_t);
static void print_z_candidate (const char *, struct z_candidate *);
static void print_z_candidate (location_t, const char *, struct z_candidate *);
static void print_z_candidates (location_t, struct z_candidate *);
static tree build_this (tree);
static struct z_candidate *splice_viable (struct z_candidate *, bool, bool *);
@ -3159,36 +3159,38 @@ print_arity_information (location_t loc, unsigned int have, unsigned int want)
life simpler in print_z_candidates and for the translators. */
static void
print_z_candidate (const char *msgstr, struct z_candidate *candidate)
print_z_candidate (location_t loc, const char *msgstr,
struct z_candidate *candidate)
{
const char *msg = (msgstr == NULL
? ""
: ACONCAT ((msgstr, " ", NULL)));
location_t loc = location_of (candidate->fn);
location_t cloc = location_of (candidate->fn);
if (TREE_CODE (candidate->fn) == IDENTIFIER_NODE)
{
cloc = loc;
if (candidate->num_convs == 3)
inform (input_location, "%s%D(%T, %T, %T) <built-in>", msg, candidate->fn,
inform (cloc, "%s%D(%T, %T, %T) <built-in>", msg, candidate->fn,
candidate->convs[0]->type,
candidate->convs[1]->type,
candidate->convs[2]->type);
else if (candidate->num_convs == 2)
inform (input_location, "%s%D(%T, %T) <built-in>", msg, candidate->fn,
inform (cloc, "%s%D(%T, %T) <built-in>", msg, candidate->fn,
candidate->convs[0]->type,
candidate->convs[1]->type);
else
inform (input_location, "%s%D(%T) <built-in>", msg, candidate->fn,
inform (cloc, "%s%D(%T) <built-in>", msg, candidate->fn,
candidate->convs[0]->type);
}
else if (TYPE_P (candidate->fn))
inform (loc, "%s%T <conversion>", msg, candidate->fn);
inform (cloc, "%s%T <conversion>", msg, candidate->fn);
else if (candidate->viable == -1)
inform (loc, "%s%#D <near match>", msg, candidate->fn);
inform (cloc, "%s%#D <near match>", msg, candidate->fn);
else if (DECL_DELETED_FN (STRIP_TEMPLATE (candidate->fn)))
inform (loc, "%s%#D <deleted>", msg, candidate->fn);
inform (cloc, "%s%#D <deleted>", msg, candidate->fn);
else
inform (loc, "%s%#D", msg, candidate->fn);
inform (cloc, "%s%#D", msg, candidate->fn);
/* Give the user some information about why this candidate failed. */
if (candidate->reason != NULL)
{
@ -3197,23 +3199,23 @@ print_z_candidate (const char *msgstr, struct z_candidate *candidate)
switch (r->code)
{
case rr_arity:
print_arity_information (loc, r->u.arity.actual,
print_arity_information (cloc, r->u.arity.actual,
r->u.arity.expected);
break;
case rr_arg_conversion:
print_conversion_rejection (loc, &r->u.conversion);
print_conversion_rejection (cloc, &r->u.conversion);
break;
case rr_bad_arg_conversion:
print_conversion_rejection (loc, &r->u.bad_conversion);
print_conversion_rejection (cloc, &r->u.bad_conversion);
break;
case rr_explicit_conversion:
inform (loc, " return type %qT of explicit conversion function "
inform (cloc, " return type %qT of explicit conversion function "
"cannot be converted to %qT with a qualification "
"conversion", r->u.conversion.from_type,
r->u.conversion.to_type);
break;
case rr_template_conversion:
inform (loc, " conversion from return type %qT of template "
inform (cloc, " conversion from return type %qT of template "
"conversion function specialization to %qT is not an "
"exact match", r->u.conversion.from_type,
r->u.conversion.to_type);
@ -3224,12 +3226,12 @@ print_z_candidate (const char *msgstr, struct z_candidate *candidate)
them here. */
if (r->u.template_unification.tmpl == NULL_TREE)
{
inform (loc, " substitution of deduced template arguments "
inform (cloc, " substitution of deduced template arguments "
"resulted in errors seen above");
break;
}
/* Re-run template unification with diagnostics. */
inform (loc, " template argument deduction/substitution failed:");
inform (cloc, " template argument deduction/substitution failed:");
fn_type_unification (r->u.template_unification.tmpl,
r->u.template_unification.explicit_targs,
r->u.template_unification.targs,
@ -3247,7 +3249,7 @@ print_z_candidate (const char *msgstr, struct z_candidate *candidate)
tf_warning_or_error);
break;
case rr_invalid_copy:
inform (loc,
inform (cloc,
" a constructor taking a single argument of its own "
"class type is invalid");
break;
@ -3312,7 +3314,7 @@ print_z_candidates (location_t loc, struct z_candidate *candidates)
inform_n (loc, n_candidates, "candidate is:", "candidates are:");
for (; candidates; candidates = candidates->next)
print_z_candidate (NULL, candidates);
print_z_candidate (loc, NULL, candidates);
}
/* USER_SEQ is a user-defined conversion sequence, beginning with a
@ -5678,7 +5680,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
{
permerror (loc, "invalid user-defined conversion "
"from %qT to %qT", TREE_TYPE (expr), totype);
print_z_candidate ("candidate is:", t->cand);
print_z_candidate (loc, "candidate is:", t->cand);
expr = convert_like_real (t, expr, fn, argnum, 1,
/*issue_conversion_warnings=*/false,
/*c_cast_p=*/false,
@ -8405,8 +8407,8 @@ tweak:
"ISO C++ says that these are ambiguous, even "
"though the worst conversion for the first is better than "
"the worst conversion for the second:");
print_z_candidate (_("candidate 1:"), w);
print_z_candidate (_("candidate 2:"), l);
print_z_candidate (input_location, _("candidate 1:"), w);
print_z_candidate (input_location, _("candidate 2:"), l);
}
else
add_warning (w, l);

View File

@ -1621,6 +1621,8 @@ typedef struct cp_parser_expression_stack_entry
enum tree_code tree_type;
/* Precedence of the binary operation we are parsing. */
enum cp_parser_prec prec;
/* Location of the binary operation we are parsing. */
location_t loc;
} cp_parser_expression_stack_entry;
/* The stack for storing partial expressions. We only need NUM_PREC_VALUES
@ -7275,30 +7277,33 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
{
cp_parser_expression_stack stack;
cp_parser_expression_stack_entry *sp = &stack[0];
tree lhs, rhs;
cp_parser_expression_stack_entry current;
tree rhs;
cp_token *token;
location_t loc;
enum tree_code tree_type, lhs_type, rhs_type;
enum tree_code rhs_type;
enum cp_parser_prec new_prec, lookahead_prec;
tree overload;
/* Parse the first expression. */
lhs = cp_parser_cast_expression (parser, /*address_p=*/false, cast_p, pidk);
lhs_type = ERROR_MARK;
current.lhs = cp_parser_cast_expression (parser, /*address_p=*/false,
cast_p, pidk);
current.lhs_type = ERROR_MARK;
current.prec = prec;
for (;;)
{
/* Get an operator token. */
token = cp_lexer_peek_token (parser->lexer);
loc = token->location;
if (warn_cxx0x_compat
&& token->type == CPP_RSHIFT
&& !parser->greater_than_is_operator_p)
{
if (warning_at (loc, OPT_Wc__0x_compat, "%<>>%> operator is treated"
if (warning_at (token->location, OPT_Wc__0x_compat,
"%<>>%> operator is treated"
" as two right angle brackets in C++11"))
inform (loc, "suggest parentheses around %<>>%> expression");
inform (token->location,
"suggest parentheses around %<>>%> expression");
}
new_prec = TOKEN_PRECEDENCE (token);
@ -7310,7 +7315,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
- 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 (new_prec <= current.prec)
{
if (sp == stack)
break;
@ -7319,17 +7324,18 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
}
get_rhs:
tree_type = binops_by_token[token->type].tree_type;
current.tree_type = binops_by_token[token->type].tree_type;
current.loc = token->location;
/* We used the operator token. */
cp_lexer_consume_token (parser->lexer);
/* For "false && x" or "true || x", x will never be executed;
disable warnings while evaluating it. */
if (tree_type == TRUTH_ANDIF_EXPR)
c_inhibit_evaluation_warnings += lhs == truthvalue_false_node;
else if (tree_type == TRUTH_ORIF_EXPR)
c_inhibit_evaluation_warnings += lhs == truthvalue_true_node;
if (current.tree_type == TRUTH_ANDIF_EXPR)
c_inhibit_evaluation_warnings += current.lhs == truthvalue_false_node;
else if (current.tree_type == TRUTH_ORIF_EXPR)
c_inhibit_evaluation_warnings += current.lhs == truthvalue_true_node;
/* Extract another operand. It may be the RHS of this expression
or the LHS of a new, higher priority expression. */
@ -7347,14 +7353,11 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
expression. Since precedence levels on the stack are
monotonically increasing, we do not have to care about
stack overflows. */
sp->prec = prec;
sp->tree_type = tree_type;
sp->lhs = lhs;
sp->lhs_type = lhs_type;
sp++;
lhs = rhs;
lhs_type = rhs_type;
prec = new_prec;
*sp = current;
++sp;
current.lhs = rhs;
current.lhs_type = rhs_type;
current.prec = new_prec;
new_prec = lookahead_prec;
goto get_rhs;
@ -7367,20 +7370,17 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
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. */
rhs = current.lhs;
rhs_type = current.lhs_type;
--sp;
prec = sp->prec;
tree_type = sp->tree_type;
rhs = lhs;
rhs_type = lhs_type;
lhs = sp->lhs;
lhs_type = sp->lhs_type;
current = *sp;
}
/* Undo the disabling of warnings done above. */
if (tree_type == TRUTH_ANDIF_EXPR)
c_inhibit_evaluation_warnings -= lhs == truthvalue_false_node;
else if (tree_type == TRUTH_ORIF_EXPR)
c_inhibit_evaluation_warnings -= lhs == truthvalue_true_node;
if (current.tree_type == TRUTH_ANDIF_EXPR)
c_inhibit_evaluation_warnings -= current.lhs == truthvalue_false_node;
else if (current.tree_type == TRUTH_ORIF_EXPR)
c_inhibit_evaluation_warnings -= current.lhs == truthvalue_true_node;
overload = NULL;
/* ??? Currently we pass lhs_type == ERROR_MARK and rhs_type ==
@ -7391,14 +7391,17 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
surrounded by parentheses.
*/
if (no_toplevel_fold_p
&& lookahead_prec <= prec
&& lookahead_prec <= current.prec
&& sp == stack
&& TREE_CODE_CLASS (tree_type) == tcc_comparison)
lhs = build2 (tree_type, boolean_type_node, lhs, rhs);
&& TREE_CODE_CLASS (current.tree_type) == tcc_comparison)
current.lhs = build2 (current.tree_type, boolean_type_node,
current.lhs, rhs);
else
lhs = build_x_binary_op (loc, tree_type, lhs, lhs_type, rhs, rhs_type,
&overload, tf_warning_or_error);
lhs_type = tree_type;
current.lhs = build_x_binary_op (current.loc, current.tree_type,
current.lhs, current.lhs_type,
rhs, rhs_type, &overload,
tf_warning_or_error);
current.lhs_type = current.tree_type;
/* If the binary operator required the use of an overloaded operator,
then this expression cannot be an integral constant-expression.
@ -7412,7 +7415,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
return error_mark_node;
}
return lhs;
return current.lhs;
}

View File

@ -1,3 +1,7 @@
2012-05-12 Paolo Carlini <paolo.carlini@oracle.com>
* g++.dg/parse/error47.C: New.
2012-05-11 Thomas Koenig <tkoenig@gcc.gnu.org>
PR fortran/52537

View File

@ -0,0 +1,9 @@
struct T { };
T foo();
void bar(int a, int b)
{
if (foo() && a < b) // { dg-error "13:no match for 'operator&&'" }
;
}