make_location: ensure end-points are pure locations
authorDavid Malcolm <dmalcolm@redhat.com>
Mon, 29 Aug 2016 17:10:23 +0000 (17:10 +0000)
committerDavid Malcolm <dmalcolm@gcc.gnu.org>
Mon, 29 Aug 2016 17:10:23 +0000 (17:10 +0000)
gcc/ChangeLog:
* input.c (make_location): Call get_start and get_finish
on the endpoints to avoid storing packed ranges or ad-hoc
ranges in them.
(selftest::test_make_location_nonpure_range_endpoints): New function.
(selftest::input_c_tests): Call it.
* input.h (get_start): New inline function.

From-SVN: r239831

gcc/ChangeLog
gcc/input.c
gcc/input.h

index 55906fea96bd53d83572d28c34a8a218585ab882..fc2ccfc25c9be9d97bb73583f92d7d0dce80e5f0 100644 (file)
@@ -1,3 +1,12 @@
+2016-08-29  David Malcolm  <dmalcolm@redhat.com>
+
+       * input.c (make_location): Call get_start and get_finish
+       on the endpoints to avoid storing packed ranges or ad-hoc
+       ranges in them.
+       (selftest::test_make_location_nonpure_range_endpoints): New function.
+       (selftest::input_c_tests): Call it.
+       * input.h (get_start): New inline function.
+
 2016-08-29  Tom de Vries  <tom@codesourcery.com>
 
        PR c/77398
index 2dcecfb35ba08f289ee772e156f9b308498f8358..4ec218d52a4d8f2e495fc3a54b6992d8382384ac 100644 (file)
@@ -879,8 +879,8 @@ make_location (location_t caret, location_t start, location_t finish)
 {
   location_t pure_loc = get_pure_location (caret);
   source_range src_range;
-  src_range.m_start = start;
-  src_range.m_finish = finish;
+  src_range.m_start = get_start (start);
+  src_range.m_finish = get_finish (finish);
   location_t combined_loc = COMBINE_LOCATION_DATA (line_table,
                                                   pure_loc,
                                                   src_range,
@@ -1741,6 +1741,67 @@ test_builtins ()
   ASSERT_PRED1 (is_location_from_builtin_token, BUILTINS_LOCATION);
 }
 
+/* Regression test for make_location.
+   Ensure that we use the caret locations of the start/finish, rather
+   than storing a packed or ad-hoc range as the start/finish.  */
+
+static void
+test_make_location_nonpure_range_endpoints (const line_table_case &case_)
+{
+  /* Issue seen with testsuite/c-c++-common/Wlogical-not-parentheses-2.c
+     with C++ frontend.
+     ....................0000000001111111111222.
+     ....................1234567890123456789012.  */
+  const char *content = "     r += !aaa == bbb;\n";
+  temp_source_file tmp (SELFTEST_LOCATION, ".C", content);
+  line_table_test ltt (case_);
+  linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 1);
+
+  const location_t c11 = linemap_position_for_column (line_table, 11);
+  const location_t c12 = linemap_position_for_column (line_table, 12);
+  const location_t c13 = linemap_position_for_column (line_table, 13);
+  const location_t c14 = linemap_position_for_column (line_table, 14);
+  const location_t c21 = linemap_position_for_column (line_table, 21);
+
+  if (c21 > LINE_MAP_MAX_LOCATION_WITH_COLS)
+    return;
+
+  /* Use column 13 for the caret location, arbitrarily, to verify that we
+     handle start != caret.  */
+  const location_t aaa = make_location (c13, c12, c14);
+  ASSERT_EQ (c13, get_pure_location (aaa));
+  ASSERT_EQ (c12, get_start (aaa));
+  ASSERT_FALSE (IS_ADHOC_LOC (get_start (aaa)));
+  ASSERT_EQ (c14, get_finish (aaa));
+  ASSERT_FALSE (IS_ADHOC_LOC (get_finish (aaa)));
+
+  /* Make a location using a location with a range as the start-point.  */
+  const location_t not_aaa = make_location (c11, aaa, c14);
+  ASSERT_EQ (c11, get_pure_location (not_aaa));
+  /* It should use the start location of the range, not store the range
+     itself.  */
+  ASSERT_EQ (c12, get_start (not_aaa));
+  ASSERT_FALSE (IS_ADHOC_LOC (get_start (not_aaa)));
+  ASSERT_EQ (c14, get_finish (not_aaa));
+  ASSERT_FALSE (IS_ADHOC_LOC (get_finish (not_aaa)));
+
+  /* Similarly, make a location with a range as the end-point.  */
+  const location_t aaa_eq_bbb = make_location (c12, c12, c21);
+  ASSERT_EQ (c12, get_pure_location (aaa_eq_bbb));
+  ASSERT_EQ (c12, get_start (aaa_eq_bbb));
+  ASSERT_FALSE (IS_ADHOC_LOC (get_start (aaa_eq_bbb)));
+  ASSERT_EQ (c21, get_finish (aaa_eq_bbb));
+  ASSERT_FALSE (IS_ADHOC_LOC (get_finish (aaa_eq_bbb)));
+  const location_t not_aaa_eq_bbb = make_location (c11, c12, aaa_eq_bbb);
+  /* It should use the finish location of the range, not store the range
+     itself.  */
+  ASSERT_EQ (c11, get_pure_location (not_aaa_eq_bbb));
+  ASSERT_EQ (c12, get_start (not_aaa_eq_bbb));
+  ASSERT_FALSE (IS_ADHOC_LOC (get_start (not_aaa_eq_bbb)));
+  ASSERT_EQ (c21, get_finish (not_aaa_eq_bbb));
+  ASSERT_FALSE (IS_ADHOC_LOC (get_finish (not_aaa_eq_bbb)));
+}
+
 /* Verify reading of input files (e.g. for caret-based diagnostics).  */
 
 static void
@@ -3187,6 +3248,7 @@ input_c_tests ()
   test_should_have_column_data_p ();
   test_unknown_location ();
   test_builtins ();
+  for_each_line_table_case (test_make_location_nonpure_range_endpoints);
 
   for_each_line_table_case (test_accessing_ordinary_linemaps);
   for_each_line_table_case (test_lexer);
index c99abfd52927eccec349144375a02a5ddd797036..ecf8db3a7ea58d5e8aa6cdcc3d680daa93bafb97 100644 (file)
@@ -79,6 +79,14 @@ extern location_t input_location;
 
 extern location_t get_pure_location (location_t loc);
 
+/* Get the start of any range encoded within location LOC.  */
+
+static inline location_t
+get_start (location_t loc)
+{
+  return get_range_from_loc (line_table, loc).m_start;
+}
+
 /* Get the endpoint of any range encoded within location LOC.  */
 
 static inline location_t