public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Lewis Hyatt <lhyatt@gmail.com>
To: gcc-patches@gcc.gnu.org
Cc: David Malcolm <dmalcolm@redhat.com>, Lewis Hyatt <lhyatt@gmail.com>
Subject: [PATCH v4 5/8] diagnostics: Support testing generated data in input.cc selftests
Date: Wed,  9 Aug 2023 18:14:11 -0400	[thread overview]
Message-ID: <20230809221414.2849878-6-lhyatt@gmail.com> (raw)
In-Reply-To: <20230809221414.2849878-1-lhyatt@gmail.com>

Add selftests for the new capabilities in input.cc related to source code
locations that are stored in memory rather than ordinary files.

gcc/ChangeLog:

	* input.cc (temp_source_file::do_linemap_add): New function.
	(line_table_case::line_table_case): Add GENERATED_DATA argument.
	(line_table_test::line_table_test): Implement new M_GENERATED_DATA
	argument.
	(for_each_line_table_case): Optionally include generated data
	locations in the set of cases.
	(test_accessing_ordinary_linemaps): Test generated data locations.
	(test_make_location_nonpure_range_endpoints): Likewise.
	(test_line_offset_overflow): Likewise.
	(input_cc_tests): Likewise.
	* selftest.cc (named_temp_file::named_temp_file): Interpret a null
	SUFFIX argument as a request to use in-memory data.
	(named_temp_file::~named_temp_file): Support in-memory data.
	(temp_source_file::temp_source_file): Likewise.
	(temp_source_file::~temp_source_file): Likewise.
	* selftest.h (struct line_map_ordinary): Foward declare.
	(class named_temp_file): Add missing explicit to the constructor.
	(class temp_source_file): Add new members to support in-memory data.
	(class line_table_test): Likewise.
	(for_each_line_table_case): Adjust prototype.
---
 gcc/input.cc    | 81 +++++++++++++++++++++++++++++++++----------------
 gcc/selftest.cc | 53 +++++++++++++++++++++++++-------
 gcc/selftest.h  | 19 ++++++++++--
 3 files changed, 113 insertions(+), 40 deletions(-)

diff --git a/gcc/input.cc b/gcc/input.cc
index 790279d4273..8c4e40aaf23 100644
--- a/gcc/input.cc
+++ b/gcc/input.cc
@@ -2066,6 +2066,20 @@ get_num_source_ranges_for_substring (cpp_reader *pfile,
 
 /* Selftests of location handling.  */
 
+/* Wrapper around linemap_add to handle transparently adding either a tmp file,
+   or in-memory generated content.  */
+const line_map_ordinary *
+temp_source_file::do_linemap_add (int line)
+{
+  const line_map *map;
+  if (content_buf)
+    map = linemap_add (line_table, LC_GEN, false, content_buf,
+		       line, content_len);
+  else
+    map = linemap_add (line_table, LC_ENTER, false, get_filename (), line);
+  return linemap_check_ordinary (map);
+}
+
 /* Verify that compare() on linenum_type handles comparisons over the full
    range of the type.  */
 
@@ -2144,13 +2158,16 @@ assert_loceq (const char *exp_filename, int exp_linenum, int exp_colnum,
 class line_table_case
 {
 public:
-  line_table_case (int default_range_bits, int base_location)
+  line_table_case (int default_range_bits, int base_location,
+		   bool generated_data)
   : m_default_range_bits (default_range_bits),
-    m_base_location (base_location)
+    m_base_location (base_location),
+    m_generated_data (generated_data)
   {}
 
   int m_default_range_bits;
   int m_base_location;
+  bool m_generated_data;
 };
 
 /* Constructor.  Store the old value of line_table, and create a new
@@ -2167,6 +2184,7 @@ line_table_test::line_table_test ()
   gcc_assert (saved_line_table->round_alloc_size);
   line_table->round_alloc_size = saved_line_table->round_alloc_size;
   line_table->default_range_bits = 0;
+  m_generated_data = false;
 }
 
 /* Constructor.  Store the old value of line_table, and create a new
@@ -2188,6 +2206,7 @@ line_table_test::line_table_test (const line_table_case &case_)
       line_table->highest_location = case_.m_base_location;
       line_table->highest_line = case_.m_base_location;
     }
+  m_generated_data = case_.m_generated_data;
 }
 
 /* Destructor.  Restore the old value of line_table.  */
@@ -2207,7 +2226,10 @@ test_accessing_ordinary_linemaps (const line_table_case &case_)
   line_table_test ltt (case_);
 
   /* Build a simple linemap describing some locations. */
-  linemap_add (line_table, LC_ENTER, false, "foo.c", 0);
+  if (ltt.m_generated_data)
+    linemap_add (line_table, LC_GEN, false, "some data", 0, 10);
+  else
+    linemap_add (line_table, LC_ENTER, false, "foo.c", 0);
 
   linemap_line_start (line_table, 1, 100);
   location_t loc_a = linemap_position_for_column (line_table, 1);
@@ -2257,21 +2279,23 @@ test_accessing_ordinary_linemaps (const line_table_case &case_)
   linemap_add (line_table, LC_LEAVE, false, NULL, 0);
 
   /* Verify that we can recover the location info.  */
-  assert_loceq ("foo.c", 1, 1, loc_a);
-  assert_loceq ("foo.c", 1, 23, loc_b);
-  assert_loceq ("foo.c", 2, 1, loc_c);
-  assert_loceq ("foo.c", 2, 17, loc_d);
-  assert_loceq ("foo.c", 3, 700, loc_e);
-  assert_loceq ("foo.c", 4, 100, loc_back_to_short);
+  const auto fname
+    = (ltt.m_generated_data ? special_fname_generated () : "foo.c");
+  assert_loceq (fname, 1, 1, loc_a);
+  assert_loceq (fname, 1, 23, loc_b);
+  assert_loceq (fname, 2, 1, loc_c);
+  assert_loceq (fname, 2, 17, loc_d);
+  assert_loceq (fname, 3, 700, loc_e);
+  assert_loceq (fname, 4, 100, loc_back_to_short);
 
   /* In the very wide line, the initial location should be fully tracked.  */
-  assert_loceq ("foo.c", 5, 2000, loc_start_of_very_long_line);
+  assert_loceq (fname, 5, 2000, loc_start_of_very_long_line);
   /* ...but once we exceed LINE_MAP_MAX_COLUMN_NUMBER column-tracking should
      be disabled.  */
-  assert_loceq ("foo.c", 5, 0, loc_too_wide);
-  assert_loceq ("foo.c", 5, 0, loc_too_wide_2);
+  assert_loceq (fname, 5, 0, loc_too_wide);
+  assert_loceq (fname, 5, 0, loc_too_wide_2);
   /*...and column-tracking should be re-enabled for subsequent lines.  */
-  assert_loceq ("foo.c", 6, 10, loc_sane_again);
+  assert_loceq (fname, 6, 10, loc_sane_again);
 
   assert_loceq ("bar.c", 1, 150, loc_f);
 
@@ -2318,10 +2342,11 @@ test_make_location_nonpure_range_endpoints (const line_table_case &case_)
      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 char *content = "     r += !aaa == bbb;\n";
+  temp_source_file tmp (SELFTEST_LOCATION, ".C", content, strlen (content),
+			ltt.m_generated_data);
+  tmp.do_linemap_add (1);
 
   const location_t c11 = linemap_position_for_column (line_table, 11);
   const location_t c12 = linemap_position_for_column (line_table, 12);
@@ -3978,7 +4003,8 @@ static const location_t boundary_locations[] = {
 /* Run TESTCASE multiple times, once for each case in our test matrix.  */
 
 void
-for_each_line_table_case (void (*testcase) (const line_table_case &))
+for_each_line_table_case (void (*testcase) (const line_table_case &),
+			  bool test_generated_data)
 {
   /* As noted above in the description of struct line_table_case,
      we want to explore a test matrix of interesting line_table
@@ -3997,16 +4023,19 @@ for_each_line_table_case (void (*testcase) (const line_table_case &))
       const int num_boundary_locations = ARRAY_SIZE (boundary_locations);
       for (int loc_idx = 0; loc_idx < num_boundary_locations; loc_idx++)
 	{
-	  line_table_case c (default_range_bits, boundary_locations[loc_idx]);
-
-	  testcase (c);
-
-	  num_cases_tested++;
+	  /* ...and try both normal files, and internally generated data.  */
+	  for (int gen = 0; gen != 1+test_generated_data; ++gen)
+	    {
+	      line_table_case c (default_range_bits,
+				 boundary_locations[loc_idx], gen);
+	      testcase (c);
+	      num_cases_tested++;
+	    }
 	}
     }
 
   /* Verify that we fully covered the test matrix.  */
-  ASSERT_EQ (num_cases_tested, 2 * 12);
+  ASSERT_EQ (num_cases_tested, 2 * 12 * (1+test_generated_data));
 }
 
 /* Verify that when presented with a consecutive pair of locations with
@@ -4017,7 +4046,7 @@ for_each_line_table_case (void (*testcase) (const line_table_case &))
 static void
 test_line_offset_overflow ()
 {
-  line_table_test ltt (line_table_case (5, 0));
+  line_table_test ltt (line_table_case (5, 0, false));
 
   linemap_add (line_table, LC_ENTER, false, "foo.c", 0);
   linemap_line_start (line_table, 1, 100);
@@ -4257,9 +4286,9 @@ input_cc_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_make_location_nonpure_range_endpoints, true);
 
-  for_each_line_table_case (test_accessing_ordinary_linemaps);
+  for_each_line_table_case (test_accessing_ordinary_linemaps, true);
   for_each_line_table_case (test_lexer);
   for_each_line_table_case (test_lexer_string_locations_simple);
   for_each_line_table_case (test_lexer_string_locations_ebcdic);
diff --git a/gcc/selftest.cc b/gcc/selftest.cc
index 20c10bbd055..7126b9901dd 100644
--- a/gcc/selftest.cc
+++ b/gcc/selftest.cc
@@ -163,14 +163,21 @@ assert_str_startswith (const location &loc,
 
 named_temp_file::named_temp_file (const char *suffix)
 {
-  m_filename = make_temp_file (suffix);
-  ASSERT_NE (m_filename, NULL);
+  if (suffix)
+    {
+      m_filename = make_temp_file (suffix);
+      ASSERT_NE (m_filename, NULL);
+    }
+  else
+    m_filename = nullptr;
 }
 
 /* Destructor.  Delete the tempfile.  */
 
 named_temp_file::~named_temp_file ()
 {
+  if (!m_filename)
+    return;
   unlink (m_filename);
   diagnostics_file_cache_forcibly_evict_file (m_filename);
   free (m_filename);
@@ -183,7 +190,9 @@ named_temp_file::~named_temp_file ()
 temp_source_file::temp_source_file (const location &loc,
 				    const char *suffix,
 				    const char *content)
-: named_temp_file (suffix)
+: named_temp_file (suffix),
+  content_buf (nullptr),
+  content_len (0)
 {
   FILE *out = fopen (get_filename (), "w");
   if (!out)
@@ -192,19 +201,41 @@ temp_source_file::temp_source_file (const location &loc,
   fclose (out);
 }
 
-/* As above, but with a size, to allow for NUL bytes in CONTENT.  */
+/* As above, but with a size, to allow for NUL bytes in CONTENT.  When
+   IS_GENERATED==true, the data is kept in memory instead, for testing LC_GEN
+   maps.  */
 
 temp_source_file::temp_source_file (const location &loc,
 				    const char *suffix,
 				    const char *content,
-				    size_t sz)
-: named_temp_file (suffix)
+				    size_t sz,
+				    bool is_generated)
+: named_temp_file (is_generated ? nullptr : suffix),
+  content_buf (is_generated ? XNEWVEC (char, sz) : nullptr),
+  content_len (is_generated ? sz : 0)
 {
-  FILE *out = fopen (get_filename (), "w");
-  if (!out)
-    fail_formatted (loc, "unable to open tempfile: %s", get_filename ());
-  fwrite (content, sz, 1, out);
-  fclose (out);
+  if (is_generated)
+    {
+      gcc_assert (sz); /* Empty generated content is not supported.  */
+      memcpy (content_buf, content, sz);
+    }
+  else
+    {
+      FILE *out = fopen (get_filename (), "w");
+      if (!out)
+	fail_formatted (loc, "unable to open tempfile: %s", get_filename ());
+      fwrite (content, sz, 1, out);
+      fclose (out);
+    }
+}
+
+temp_source_file::~temp_source_file ()
+{
+  if (content_buf)
+    {
+      diagnostics_file_cache_forcibly_evict_data (content_buf, content_len);
+      XDELETEVEC (content_buf);
+    }
 }
 
 /* Avoid introducing locale-specific differences in the results
diff --git a/gcc/selftest.h b/gcc/selftest.h
index 20d522afda4..ede3b008145 100644
--- a/gcc/selftest.h
+++ b/gcc/selftest.h
@@ -25,6 +25,8 @@ along with GCC; see the file COPYING3.  If not see
 
 #if CHECKING_P
 
+struct line_map_ordinary;
+
 namespace selftest {
 
 /* A struct describing the source-location of a selftest, to make it
@@ -96,7 +98,7 @@ extern void assert_str_startswith (const location &loc,
 class named_temp_file
 {
  public:
-  named_temp_file (const char *suffix);
+  explicit named_temp_file (const char *suffix);
   ~named_temp_file ();
   const char *get_filename () const { return m_filename; }
 
@@ -113,7 +115,13 @@ class temp_source_file : public named_temp_file
   temp_source_file (const location &loc, const char *suffix,
 		    const char *content);
   temp_source_file (const location &loc, const char *suffix,
-		    const char *content, size_t sz);
+		    const char *content, size_t sz,
+		    bool is_generated = false);
+  ~temp_source_file ();
+
+  char *const content_buf;
+  const size_t content_len;
+  const line_map_ordinary *do_linemap_add (int line); /* In input.cc */
 };
 
 /* RAII-style class for avoiding introducing locale-specific differences
@@ -171,6 +179,10 @@ class line_table_test
 
   /* Destructor.  Restore the saved line_table.  */
   ~line_table_test ();
+
+  /* When this is enabled in the line_table_case, test storing all the data
+     in memory rather than a file.  */
+  bool m_generated_data;
 };
 
 /* Helper function for selftests that need a function decl.  */
@@ -183,7 +195,8 @@ extern tree make_fndecl (tree return_type,
 /* Run TESTCASE multiple times, once for each case in our test matrix.  */
 
 extern void
-for_each_line_table_case (void (*testcase) (const line_table_case &));
+for_each_line_table_case (void (*testcase) (const line_table_case &),
+			  bool test_generated_data = false);
 
 /* Read the contents of PATH into memory, returning a 0-terminated buffer
    that must be freed by the caller.

  parent reply	other threads:[~2023-08-09 22:14 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-07-21 23:08 [PATCH v3 0/4] diagnostics: libcpp: Overhaul locations for _Pragma tokens Lewis Hyatt
2023-07-21 23:08 ` [PATCH v3 1/4] diagnostics: libcpp: Add LC_GEN linemaps to support in-memory buffers Lewis Hyatt
2023-07-28 22:58   ` David Malcolm
2023-07-31 22:39     ` Lewis Hyatt
2023-08-09 22:14       ` [PATCH v4 0/8] diagnostics: libcpp: Overhaul locations for _Pragma tokens Lewis Hyatt
2023-08-09 22:14         ` [PATCH v4 1/8] libcpp: Add LC_GEN linemaps to support in-memory buffers Lewis Hyatt
2023-08-11 22:45           ` David Malcolm
2023-08-13 20:18             ` Lewis Hyatt
2023-08-09 22:14         ` [PATCH v4 2/8] libcpp: diagnostics: Support generated data in expanded locations Lewis Hyatt
2023-08-11 23:02           ` David Malcolm
2023-08-14 21:41             ` Lewis Hyatt
2023-08-09 22:14         ` [PATCH v4 3/8] diagnostics: Refactor class file_cache_slot Lewis Hyatt
2023-08-15 15:43           ` David Malcolm
2023-08-15 17:58             ` Lewis Hyatt
2023-08-15 19:39               ` David Malcolm
2023-08-23 21:22                 ` Lewis Hyatt
2023-08-09 22:14         ` [PATCH v4 4/8] diagnostics: Support obtaining source code lines from generated data buffers Lewis Hyatt
2023-08-15 16:15           ` David Malcolm
2023-08-15 18:15             ` Lewis Hyatt
2023-08-15 19:46               ` David Malcolm
2023-08-15 20:08                 ` Lewis Hyatt
2023-08-23 19:41                   ` Lewis Hyatt
2023-08-09 22:14         ` Lewis Hyatt [this message]
2023-08-15 16:27           ` [PATCH v4 5/8] diagnostics: Support testing generated data in input.cc selftests David Malcolm
2023-08-09 22:14         ` [PATCH v4 6/8] diagnostics: Full support for generated data locations Lewis Hyatt
2023-08-15 16:39           ` David Malcolm
2023-08-09 22:14         ` [PATCH v4 7/8] diagnostics: libcpp: Assign real locations to the tokens inside _Pragma strings Lewis Hyatt
2023-08-09 22:14         ` [PATCH v4 8/8] diagnostics: Support generated data locations in SARIF output Lewis Hyatt
2023-08-15 17:04           ` David Malcolm
2023-08-15 17:51             ` Lewis Hyatt
2023-07-21 23:08 ` [PATCH v3 2/4] diagnostics: Handle generated data locations in edit_context Lewis Hyatt
2023-07-21 23:08 ` [PATCH v3 3/4] diagnostics: libcpp: Assign real locations to the tokens inside _Pragma strings Lewis Hyatt
2023-07-21 23:08 ` [PATCH v3 4/4] diagnostics: Support generated data locations in SARIF output Lewis Hyatt
2023-07-28 22:22 ` [PATCH v3 0/4] diagnostics: libcpp: Overhaul locations for _Pragma tokens David Malcolm
2023-07-29 14:27   ` Lewis Hyatt
2023-07-29 16:03     ` David Malcolm

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230809221414.2849878-6-lhyatt@gmail.com \
    --to=lhyatt@gmail.com \
    --cc=dmalcolm@redhat.com \
    --cc=gcc-patches@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).