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

View File

@ -143,6 +143,15 @@ struct c_expr
of this expression. */ of this expression. */
location_t get_start () const { return src_range.m_start; } location_t get_start () const { return src_range.m_start; }
location_t get_finish () const { return src_range.m_finish; } 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 /* 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; result.original_type = NULL;
if (TREE_CODE (result.value) == ERROR_MARK) 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) if (location != UNKNOWN_LOCATION)
protected_set_expr_location (result.value, location); protected_set_expr_location (result.value, location);