PR c/71171 reports yet another instance of the src_range of a
c_expr being used without initialization.  Investigation shows
that this was due to error-handling, where the "value" field of
a c_expr is set to error_mark_node without touching the
src_range, leading to complaints from valgrind.

This seems to be a common mistake, so 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
similar 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).

Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu.

OK for trunk and for gcc-6-branch?

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.
---
 gcc/c/c-parser.c | 72 ++++++++++++++++++++++++++++----------------------------
 gcc/c/c-tree.h   |  9 +++++++
 gcc/c/c-typeck.c |  7 +++++-
 3 files changed, 51 insertions(+), 37 deletions(-)

diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 5703989..5edeb64 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -7200,7 +7200,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;
@@ -7511,13 +7511,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);
@@ -7531,7 +7531,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;
@@ -7553,7 +7553,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 ();
@@ -7582,7 +7582,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,
@@ -7642,7 +7642,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);
@@ -7651,7 +7651,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;
@@ -7661,7 +7661,7 @@ c_parser_postfix_expression (c_parser *parser)
                                       "expected %<)%>");
            if (t1 == NULL)
              {
-               expr.value = error_mark_node;
+               expr.set_error ();
              }
            else
              {
@@ -7683,7 +7683,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);
@@ -7694,7 +7694,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;
            }
 
@@ -7783,7 +7783,7 @@ c_parser_postfix_expression (c_parser *parser)
                                            &cexpr_list, true,
                                            &close_paren_loc))
              {
-               expr.value = error_mark_node;
+               expr.set_error ();
                break;
              }
 
@@ -7791,7 +7791,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;
              }
 
@@ -7816,25 +7816,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;
            }
          {
@@ -7846,7 +7846,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;
              }
 
@@ -7871,14 +7871,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;
              }
 
@@ -7913,7 +7913,7 @@ c_parser_postfix_expression (c_parser *parser)
                                            &cexpr_list, false,
                                            &close_paren_loc))
              {
-               expr.value = error_mark_node;
+               expr.set_error ();
                break;
              }
 
@@ -7921,7 +7921,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;
              }
 
@@ -7943,7 +7943,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))
@@ -7951,7 +7951,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,
@@ -7977,7 +7977,7 @@ c_parser_postfix_expression (c_parser *parser)
                                            &cexpr_list, false,
                                            &close_paren_loc))
              {
-               expr.value = error_mark_node;
+               expr.set_error ();
                break;
              }
 
@@ -8000,7 +8000,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;
@@ -8010,7 +8010,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;
            }
          {
@@ -8027,14 +8027,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;
            }
          {
@@ -8053,13 +8053,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;
            }
@@ -8082,7 +8082,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)
            {
@@ -8101,7 +8101,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;
@@ -8122,7 +8122,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
@@ -8337,7 +8337,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;
@@ -8369,7 +8369,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;
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index d9c4c5d..a00882a 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -169,6 +169,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
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 8405c3d..390959f 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -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);
-- 
1.8.5.3

Reply via email to