PR c/71171: Fix uninitialized source_range in c_parser_postfix_expression

A common way for a c_expr to have an uninitialized src_range is in
error-handling, where the "value" field is set to error_mark_node
without touching the src_range, leading to complaints from valgrind.

This patch introduces a new method c_expr::set_error which sets
the value to error_mark_node whilst initializing the src_range to
UNKNOWN_LOCATION.

This fixes the valgrind issue seen in PR c/71171, along with various
other related issues seen when running the testsuite using the
checker patch I posted here:
  https://gcc.gnu.org/ml/gcc-patches/2015-12/msg00887.html
(this checker still doesn't fully work yet, but it seems to be good
for easily detecting these issues without needing Valgrind).

gcc/c/ChangeLog:
	PR c/71171
	* c-parser.c (c_parser_generic_selection): Use c_expr::set_error
	in error-handling.
	(c_parser_postfix_expression): Likewise.
	* c-tree.h (c_expr::set_error): New method.
	* c-typeck.c (parser_build_binary_op): In error-handling, ensure
	that result's range is initialized.

From-SVN: r236488
This commit is contained in:
David Malcolm 2016-05-19 20:29:07 +00:00 committed by David Malcolm
parent 2a5569fad3
commit 8a40fef310
4 changed files with 61 additions and 37 deletions

View File

@ -1,3 +1,13 @@
2016-05-19 David Malcolm <dmalcolm@redhat.com>
PR c/71171
* c-parser.c (c_parser_generic_selection): Use c_expr::set_error
in error-handling.
(c_parser_postfix_expression): Likewise.
* c-tree.h (c_expr::set_error): New method.
* c-typeck.c (parser_build_binary_op): In error-handling, ensure
that result's range is initialized.
2016-05-17 James Greenhalgh <james.greenhalgh@arm.com>
* c-typeck.c (parser_build_unary_op): Fix formatting.

View File

@ -7194,7 +7194,7 @@ c_parser_generic_selection (c_parser *parser)
error_expr.original_code = ERROR_MARK;
error_expr.original_type = NULL;
error_expr.value = error_mark_node;
error_expr.set_error ();
matched_assoc.type_location = UNKNOWN_LOCATION;
matched_assoc.type = NULL_TREE;
matched_assoc.expression = error_expr;
@ -7505,13 +7505,13 @@ c_parser_postfix_expression (c_parser *parser)
gcc_assert (c_dialect_objc ());
if (!c_parser_require (parser, CPP_DOT, "expected %<.%>"))
{
expr.value = error_mark_node;
expr.set_error ();
break;
}
if (c_parser_next_token_is_not (parser, CPP_NAME))
{
c_parser_error (parser, "expected identifier");
expr.value = error_mark_node;
expr.set_error ();
break;
}
c_token *component_tok = c_parser_peek_token (parser);
@ -7525,7 +7525,7 @@ c_parser_postfix_expression (c_parser *parser)
}
default:
c_parser_error (parser, "expected expression");
expr.value = error_mark_node;
expr.set_error ();
break;
}
break;
@ -7547,7 +7547,7 @@ c_parser_postfix_expression (c_parser *parser)
parser->error = true;
c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
expr.value = error_mark_node;
expr.set_error ();
break;
}
stmt = c_begin_stmt_expr ();
@ -7576,7 +7576,7 @@ c_parser_postfix_expression (c_parser *parser)
"expected %<)%>");
if (type_name == NULL)
{
expr.value = error_mark_node;
expr.set_error ();
}
else
expr = c_parser_postfix_expression_after_paren_type (parser,
@ -7636,7 +7636,7 @@ c_parser_postfix_expression (c_parser *parser)
c_parser_consume_token (parser);
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
expr.value = error_mark_node;
expr.set_error ();
break;
}
e1 = c_parser_expr_no_commas (parser, NULL);
@ -7645,7 +7645,7 @@ c_parser_postfix_expression (c_parser *parser)
if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
{
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
expr.value = error_mark_node;
expr.set_error ();
break;
}
loc = c_parser_peek_token (parser)->location;
@ -7655,7 +7655,7 @@ c_parser_postfix_expression (c_parser *parser)
"expected %<)%>");
if (t1 == NULL)
{
expr.value = error_mark_node;
expr.set_error ();
}
else
{
@ -7677,7 +7677,7 @@ c_parser_postfix_expression (c_parser *parser)
c_parser_consume_token (parser);
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
expr.value = error_mark_node;
expr.set_error ();
break;
}
t1 = c_parser_type_name (parser);
@ -7688,7 +7688,7 @@ c_parser_postfix_expression (c_parser *parser)
if (parser->error)
{
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
expr.value = error_mark_node;
expr.set_error ();
break;
}
@ -7777,7 +7777,7 @@ c_parser_postfix_expression (c_parser *parser)
&cexpr_list, true,
&close_paren_loc))
{
expr.value = error_mark_node;
expr.set_error ();
break;
}
@ -7785,7 +7785,7 @@ c_parser_postfix_expression (c_parser *parser)
{
error_at (loc, "wrong number of arguments to "
"%<__builtin_choose_expr%>");
expr.value = error_mark_node;
expr.set_error ();
break;
}
@ -7810,25 +7810,25 @@ c_parser_postfix_expression (c_parser *parser)
c_parser_consume_token (parser);
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
expr.value = error_mark_node;
expr.set_error ();
break;
}
t1 = c_parser_type_name (parser);
if (t1 == NULL)
{
expr.value = error_mark_node;
expr.set_error ();
break;
}
if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
{
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
expr.value = error_mark_node;
expr.set_error ();
break;
}
t2 = c_parser_type_name (parser);
if (t2 == NULL)
{
expr.value = error_mark_node;
expr.set_error ();
break;
}
{
@ -7840,7 +7840,7 @@ c_parser_postfix_expression (c_parser *parser)
e2 = groktypename (t2, NULL, NULL);
if (e1 == error_mark_node || e2 == error_mark_node)
{
expr.value = error_mark_node;
expr.set_error ();
break;
}
@ -7865,14 +7865,14 @@ c_parser_postfix_expression (c_parser *parser)
&cexpr_list, false,
&close_paren_loc))
{
expr.value = error_mark_node;
expr.set_error ();
break;
}
if (vec_safe_length (cexpr_list) != 2)
{
error_at (loc, "wrong number of arguments to "
"%<__builtin_call_with_static_chain%>");
expr.value = error_mark_node;
expr.set_error ();
break;
}
@ -7907,7 +7907,7 @@ c_parser_postfix_expression (c_parser *parser)
&cexpr_list, false,
&close_paren_loc))
{
expr.value = error_mark_node;
expr.set_error ();
break;
}
@ -7915,7 +7915,7 @@ c_parser_postfix_expression (c_parser *parser)
{
error_at (loc, "wrong number of arguments to "
"%<__builtin_complex%>");
expr.value = error_mark_node;
expr.set_error ();
break;
}
@ -7937,7 +7937,7 @@ c_parser_postfix_expression (c_parser *parser)
{
error_at (loc, "%<__builtin_complex%> operand "
"not of real binary floating-point type");
expr.value = error_mark_node;
expr.set_error ();
break;
}
if (TYPE_MAIN_VARIANT (TREE_TYPE (e1_p->value))
@ -7945,7 +7945,7 @@ c_parser_postfix_expression (c_parser *parser)
{
error_at (loc,
"%<__builtin_complex%> operands of different types");
expr.value = error_mark_node;
expr.set_error ();
break;
}
pedwarn_c90 (loc, OPT_Wpedantic,
@ -7971,7 +7971,7 @@ c_parser_postfix_expression (c_parser *parser)
&cexpr_list, false,
&close_paren_loc))
{
expr.value = error_mark_node;
expr.set_error ();
break;
}
@ -7994,7 +7994,7 @@ c_parser_postfix_expression (c_parser *parser)
{
error_at (loc, "wrong number of arguments to "
"%<__builtin_shuffle%>");
expr.value = error_mark_node;
expr.set_error ();
}
set_c_expr_source_range (&expr, loc, close_paren_loc);
break;
@ -8004,7 +8004,7 @@ c_parser_postfix_expression (c_parser *parser)
c_parser_consume_token (parser);
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
expr.value = error_mark_node;
expr.set_error ();
break;
}
{
@ -8021,14 +8021,14 @@ c_parser_postfix_expression (c_parser *parser)
c_parser_consume_token (parser);
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
expr.value = error_mark_node;
expr.set_error ();
break;
}
if (c_parser_next_token_is_not (parser, CPP_NAME))
{
c_parser_error (parser, "expected identifier");
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
expr.value = error_mark_node;
expr.set_error ();
break;
}
{
@ -8047,13 +8047,13 @@ c_parser_postfix_expression (c_parser *parser)
c_parser_consume_token (parser);
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
expr.value = error_mark_node;
expr.set_error ();
break;
}
t1 = c_parser_type_name (parser);
if (t1 == NULL)
{
expr.value = error_mark_node;
expr.set_error ();
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
break;
}
@ -8076,7 +8076,7 @@ c_parser_postfix_expression (c_parser *parser)
error_at (loc, "-fcilkplus must be enabled to use "
"%<_Cilk_spawn%>");
expr = c_parser_cast_expression (parser, NULL);
expr.value = error_mark_node;
expr.set_error ();
}
else if (c_parser_peek_token (parser)->keyword == RID_CILK_SPAWN)
{
@ -8095,7 +8095,7 @@ c_parser_postfix_expression (c_parser *parser)
break;
default:
c_parser_error (parser, "expected expression");
expr.value = error_mark_node;
expr.set_error ();
break;
}
break;
@ -8116,7 +8116,7 @@ c_parser_postfix_expression (c_parser *parser)
/* Else fall through to report error. */
default:
c_parser_error (parser, "expected expression");
expr.value = error_mark_node;
expr.set_error ();
break;
}
return c_parser_postfix_expression_after_primary
@ -8331,7 +8331,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
else
{
c_parser_error (parser, "expected identifier");
expr.value = error_mark_node;
expr.set_error ();
expr.original_code = ERROR_MARK;
expr.original_type = NULL;
return expr;
@ -8363,7 +8363,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
else
{
c_parser_error (parser, "expected identifier");
expr.value = error_mark_node;
expr.set_error ();
expr.original_code = ERROR_MARK;
expr.original_type = NULL;
return expr;

View File

@ -143,6 +143,15 @@ struct c_expr
of this expression. */
location_t get_start () const { return src_range.m_start; }
location_t get_finish () const { return src_range.m_finish; }
/* Set the value to error_mark_node whilst ensuring that src_range
is initialized. */
void set_error ()
{
value = error_mark_node;
src_range.m_start = UNKNOWN_LOCATION;
src_range.m_finish = UNKNOWN_LOCATION;
}
};
/* Type alias for struct c_expr. This allows to use the structure

View File

@ -3533,7 +3533,12 @@ parser_build_binary_op (location_t location, enum tree_code code,
result.original_type = NULL;
if (TREE_CODE (result.value) == ERROR_MARK)
return result;
{
set_c_expr_source_range (&result,
arg1.get_start (),
arg2.get_finish ());
return result;
}
if (location != UNKNOWN_LOCATION)
protected_set_expr_location (result.value, location);