Fix uninitialized src_range values for c_expr
authordmalcolm <dmalcolm@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 17 Nov 2015 20:09:56 +0000 (20:09 +0000)
committerdmalcolm <dmalcolm@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 17 Nov 2015 20:09:56 +0000 (20:09 +0000)
gcc/c/ChangeLog:
* c-parser.c (set_c_expr_source_range): Bulletproof both
overloaded implementations against NULL expr->value.
(c_parser_braced_init): Set src_range for "ret" to a sane pair of
values.
(c_parser_unary_expression): Likewise when handling addresses of
labels.
(c_parser_postfix_expression): Likewise for statement expressions,
for __FUNCTION__, __PRETTY_FUNCTION_ and __func__ keywords, for
__builtin_va_arg, and for __builtin_offset_of.
(c_parser_postfix_expression_after_paren_type): Initialize expr's
src_range using the range of the braced initializer.
(c_parser_transaction_expression): Set src_range for "ret" to a
sane pair of values.

gcc/testsuite/ChangeLog:
* gcc.dg/plugin/diagnostic-test-expressions-1.c (vector): New
macro.
(test_braced_init): New function.
(test_statement_expression): New function.
(test_address_of_label): New function.
(test_transaction_expressions): New function.
(test_keywords): New function.
(test_builtin_va_arg): New function.
(test_builtin_offsetof): New function.
* lib/multiline.exp (_build_multiline_regex): Escape braces.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@230497 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/c/ChangeLog
gcc/c/c-parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/plugin/diagnostic-test-expressions-1.c
gcc/testsuite/lib/multiline.exp

index 3868771..b561fa0 100644 (file)
@@ -1,3 +1,19 @@
+2015-11-17  David Malcolm  <dmalcolm@redhat.com>
+
+       * c-parser.c (set_c_expr_source_range): Bulletproof both
+       overloaded implementations against NULL expr->value.
+       (c_parser_braced_init): Set src_range for "ret" to a sane pair of
+       values.
+       (c_parser_unary_expression): Likewise when handling addresses of
+       labels.
+       (c_parser_postfix_expression): Likewise for statement expressions,
+       for __FUNCTION__, __PRETTY_FUNCTION_ and __func__ keywords, for
+       __builtin_va_arg, and for __builtin_offset_of.
+       (c_parser_postfix_expression_after_paren_type): Initialize expr's
+       src_range using the range of the braced initializer.
+       (c_parser_transaction_expression): Set src_range for "ret" to a
+       sane pair of values.
+
 2015-11-16  Kirill Yukhin  <kirill.yukhin@intel.com>
 
        * c-parser.c (c_finish_omp_declare_simd): Look for
index e63148e..7b10764 100644 (file)
@@ -65,7 +65,8 @@ set_c_expr_source_range (c_expr *expr,
 {
   expr->src_range.m_start = start;
   expr->src_range.m_finish = finish;
-  set_source_range (expr->value, start, finish);
+  if (expr->value)
+    set_source_range (expr->value, start, finish);
 }
 
 void
@@ -73,7 +74,8 @@ set_c_expr_source_range (c_expr *expr,
                         source_range src_range)
 {
   expr->src_range = src_range;
-  set_source_range (expr->value, src_range);
+  if (expr->value)
+    set_source_range (expr->value, src_range);
 }
 
 \f
@@ -4268,7 +4270,8 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p)
            break;
        }
     }
-  if (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
+  c_token *next_tok = c_parser_peek_token (parser);
+  if (next_tok->type != CPP_CLOSE_BRACE)
     {
       ret.value = error_mark_node;
       ret.original_code = ERROR_MARK;
@@ -4278,9 +4281,11 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p)
       obstack_free (&braced_init_obstack, NULL);
       return ret;
     }
+  location_t close_loc = next_tok->location;
   c_parser_consume_token (parser);
   ret = pop_init_level (brace_loc, 0, &braced_init_obstack);
   obstack_free (&braced_init_obstack, NULL);
+  set_c_expr_source_range (&ret, brace_loc, close_loc);
   return ret;
 }
 
@@ -6723,6 +6728,8 @@ c_parser_unary_expression (c_parser *parser)
        {
          ret.value = finish_label_address_expr
            (c_parser_peek_token (parser)->value, op_loc);
+         set_c_expr_source_range (&ret, op_loc,
+                                  c_parser_peek_token (parser)->get_finish ());
          c_parser_consume_token (parser);
        }
       else
@@ -7366,11 +7373,13 @@ c_parser_postfix_expression (c_parser *parser)
            }
          stmt = c_begin_stmt_expr ();
          c_parser_compound_statement_nostart (parser);
+         location_t close_loc = c_parser_peek_token (parser)->location;
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
          pedwarn (loc, OPT_Wpedantic,
                   "ISO C forbids braced-groups within expressions");
          expr.value = c_finish_stmt_expr (brace_loc, stmt);
+         set_c_expr_source_range (&expr, loc, close_loc);
          mark_exp_read (expr.value);
        }
       else if (c_token_starts_typename (c_parser_peek_2nd_token (parser)))
@@ -7421,6 +7430,7 @@ c_parser_postfix_expression (c_parser *parser)
          expr.value = fname_decl (loc,
                                   c_parser_peek_token (parser)->keyword,
                                   c_parser_peek_token (parser)->value);
+         set_c_expr_source_range (&expr, loc, loc);
          c_parser_consume_token (parser);
          break;
        case RID_PRETTY_FUNCTION_NAME:
@@ -7429,6 +7439,7 @@ c_parser_postfix_expression (c_parser *parser)
          expr.value = fname_decl (loc,
                                   c_parser_peek_token (parser)->keyword,
                                   c_parser_peek_token (parser)->value);
+         set_c_expr_source_range (&expr, loc, loc);
          c_parser_consume_token (parser);
          break;
        case RID_C99_FUNCTION_NAME:
@@ -7437,45 +7448,51 @@ c_parser_postfix_expression (c_parser *parser)
          expr.value = fname_decl (loc,
                                   c_parser_peek_token (parser)->keyword,
                                   c_parser_peek_token (parser)->value);
+         set_c_expr_source_range (&expr, loc, loc);
          c_parser_consume_token (parser);
          break;
        case RID_VA_ARG:
-         c_parser_consume_token (parser);
-         if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-           {
-             expr.value = error_mark_node;
-             break;
-           }
-         e1 = c_parser_expr_no_commas (parser, NULL);
-         mark_exp_read (e1.value);
-         e1.value = c_fully_fold (e1.value, false, NULL);
-         if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
-           {
-             c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
-             expr.value = error_mark_node;
-             break;
-           }
-         loc = c_parser_peek_token (parser)->location;
-         t1 = c_parser_type_name (parser);
-         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
-                                    "expected %<)%>");
-         if (t1 == NULL)
-           {
-             expr.value = error_mark_node;
-           }
-         else
-           {
-             tree type_expr = NULL_TREE;
-             expr.value = c_build_va_arg (loc, e1.value,
-                                          groktypename (t1, &type_expr, NULL));
-             if (type_expr)
-               {
-                 expr.value = build2 (C_MAYBE_CONST_EXPR,
-                                      TREE_TYPE (expr.value), type_expr,
-                                      expr.value);
-                 C_MAYBE_CONST_EXPR_NON_CONST (expr.value) = true;
-               }
-           }
+         {
+           location_t start_loc = loc;
+           c_parser_consume_token (parser);
+           if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+             {
+               expr.value = error_mark_node;
+               break;
+             }
+           e1 = c_parser_expr_no_commas (parser, NULL);
+           mark_exp_read (e1.value);
+           e1.value = c_fully_fold (e1.value, false, NULL);
+           if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
+             {
+               c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+               expr.value = error_mark_node;
+               break;
+             }
+           loc = c_parser_peek_token (parser)->location;
+           t1 = c_parser_type_name (parser);
+           location_t end_loc = c_parser_peek_token (parser)->get_finish ();
+           c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+                                      "expected %<)%>");
+           if (t1 == NULL)
+             {
+               expr.value = error_mark_node;
+             }
+           else
+             {
+               tree type_expr = NULL_TREE;
+               expr.value = c_build_va_arg (loc, e1.value,
+                                            groktypename (t1, &type_expr, NULL));
+               if (type_expr)
+                 {
+                   expr.value = build2 (C_MAYBE_CONST_EXPR,
+                                        TREE_TYPE (expr.value), type_expr,
+                                        expr.value);
+                   C_MAYBE_CONST_EXPR_NON_CONST (expr.value) = true;
+                 }
+               set_c_expr_source_range (&expr, start_loc, end_loc);
+             }
+         }
          break;
        case RID_OFFSETOF:
          c_parser_consume_token (parser);
@@ -7561,9 +7578,11 @@ c_parser_postfix_expression (c_parser *parser)
              }
            else
              c_parser_error (parser, "expected identifier");
+           location_t end_loc = c_parser_peek_token (parser)->get_finish ();
            c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                       "expected %<)%>");
            expr.value = fold_offsetof (offsetof_ref);
+           set_c_expr_source_range (&expr, loc, end_loc);
          }
          break;
        case RID_CHOOSE_EXPR:
@@ -7951,6 +7970,7 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser,
               : init.original_code == C_MAYBE_CONST_EXPR);
   non_const |= !type_expr_const;
   expr.value = build_compound_literal (start_loc, type, init.value, non_const);
+  set_c_expr_source_range (&expr, init.src_range);
   expr.original_code = ERROR_MARK;
   expr.original_type = NULL;
   if (type != error_mark_node && type_expr)
@@ -17546,6 +17566,8 @@ c_parser_transaction_expression (c_parser *parser, enum rid keyword)
        : "%<__transaction_relaxed %> "
        "without transactional memory support enabled"));
 
+  set_c_expr_source_range (&ret, loc, loc);
+
   return ret;
 }
 
index 69adb07..a1f1458 100644 (file)
@@ -1,3 +1,16 @@
+2015-11-17  David Malcolm  <dmalcolm@redhat.com>
+
+       * gcc.dg/plugin/diagnostic-test-expressions-1.c (vector): New
+       macro.
+       (test_braced_init): New function.
+       (test_statement_expression): New function.
+       (test_address_of_label): New function.
+       (test_transaction_expressions): New function.
+       (test_keywords): New function.
+       (test_builtin_va_arg): New function.
+       (test_builtin_offsetof): New function.
+       * lib/multiline.exp (_build_multiline_regex): Escape braces.
+
 2015-11-17  Martin Sebor  <msebor@redhat.com>
 
        PR c++/68308
index 5485aaf..0d8c7c5 100644 (file)
@@ -397,6 +397,127 @@ void test_comma_operator (int a, int b)
    { dg-end-multiline-output "" } */
 }
 
+/* Braced initializers.  ***************************************/
+
+/* We can't test the ranges of these directly, since the underlying
+   tree nodes don't retain a location.  However, we can test that they
+   have ranges during parsing by building compound expressions using
+   them, and verifying the ranges of the compound expressions.  */
+
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+void test_braced_init (void)
+{
+  /* Verify start of range.  */
+  __emit_expression_range (0, (vector(4, float)){2., 2., 2., 2.} + 1); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, (vector(4, float)){2., 2., 2., 2.} + 1);
+                                                 ~~~~~~~~~~~~~~~~~^~~
+   { dg-end-multiline-output "" } */
+
+  /* Verify end of range.  */
+  __emit_expression_range (0, &(vector(4, float)){2., 2., 2., 2.}); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, &(vector(4, float)){2., 2., 2., 2.});
+                               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   { dg-end-multiline-output "" } */
+}
+
+/* Statement expressions.  ***************************************/
+
+void test_statement_expression (void)
+{
+  __emit_expression_range (0, ({ static int a; a; }) );  /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, ({ static int a; a; }) );
+                               ~^~~~~~~~~~~~~~~~~~~~~
+   { dg-end-multiline-output "" } */
+}
+
+/* Other expressions.  */
+
+void test_address_of_label (void)
+{
+ label:
+  __emit_expression_range (0, &&label );  /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, &&label );
+                               ^~~~~~~
+   { dg-end-multiline-output "" } */
+}
+
+void test_transaction_expressions (void)
+{
+  int i;
+  i = __transaction_atomic (42); /* { dg-error "without transactional memory support enabled" } */
+/* { dg-begin-multiline-output "" }
+   i = __transaction_atomic (42);
+       ^~~~~~~~~~~~~~~~~~~~
+   { dg-end-multiline-output "" } */
+  i = __transaction_relaxed (42); /* { dg-error "without transactional memory support enabled" } */
+/* { dg-begin-multiline-output "" }
+   i = __transaction_relaxed (42);
+       ^~~~~~~~~~~~~~~~~~~~~
+   { dg-end-multiline-output "" } */
+}
+
+void test_keywords (int i)
+{
+  __emit_expression_range (0, __FUNCTION__[i] );  /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, __FUNCTION__[i] );
+                               ~~~~~~~~~~~~^~~
+   { dg-end-multiline-output "" } */
+
+  __emit_expression_range (0, __PRETTY_FUNCTION__ );  /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, __PRETTY_FUNCTION__ );
+                               ^~~~~~~~~~~~~~~~~~~
+   { dg-end-multiline-output "" } */
+
+  __emit_expression_range (0, __func__ );  /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, __func__ );
+                               ^~~~~~~~
+   { dg-end-multiline-output "" } */
+}
+
+void test_builtin_va_arg (__builtin_va_list v)
+{
+  __emit_expression_range (0,  __builtin_va_arg (v, int) );  /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0,  __builtin_va_arg (v, int) );
+                                ~~~~~~~~~~~~~~~~~~~~~^~~~
+   { dg-end-multiline-output "" } */
+
+  __emit_expression_range (0,  __builtin_va_arg (v, int) + 1 );  /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0,  __builtin_va_arg (v, int) + 1 );
+                                ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~
+   { dg-end-multiline-output "" } */
+}
+
+struct s
+{
+  int f;
+};
+
+void test_builtin_offsetof (int i)
+{
+  __emit_expression_range (0,  i + __builtin_offsetof (struct s, f) );  /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0,  i + __builtin_offsetof (struct s, f) );
+                                ~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   { dg-end-multiline-output "" } */
+
+  __emit_expression_range (0,  __builtin_offsetof (struct s, f) + i );  /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0,  __builtin_offsetof (struct s, f) + i );
+                                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~
+   { dg-end-multiline-output "" } */
+}
+
 /* Examples of non-trivial expressions.  ****************************/
 
 extern double sqrt (double x);
index eb72143..c3d0506 100644 (file)
@@ -181,6 +181,8 @@ proc _build_multiline_regex { multiline index } {
                              ")" "\\)"
                              "[" "\\["
                              "]" "\\]"
+                             "{" "\\{"
+                             "}" "\\}"
                              "." "\\."
                              "\\" "\\\\"
                              "?" "\\?"