@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "intl.h"
#include "diagnostic-core.h"
+#include "selftest.h"
/* This is a cache used by get_next_line to store the content of a
file to be searched for file lines. */
@@ -1136,3 +1137,112 @@ dump_location_info (FILE *stream)
dump_labelled_location_range (stream, "AD-HOC LOCATIONS",
MAX_SOURCE_LOCATION + 1, UINT_MAX);
}
+
+#if CHECKING_P
+
+namespace {
+
+/* Fixture for testing location-handling.
+ Creates some pre-canned location_t values. */
+
+class location_test : public ::selftest::test
+{
+ protected:
+ location_test ()
+ {
+ /* Build a simple linemap describing some locations. */
+ linemap_add (line_table, LC_ENTER, false, "foo.c", 0);
+
+ linemap_line_start (line_table, 1, 100);
+ loc_a = linemap_position_for_column (line_table, 1);
+ loc_b = linemap_position_for_column (line_table, 23);
+
+ linemap_line_start (line_table, 2, 100);
+ loc_c = linemap_position_for_column (line_table, 1);
+ loc_d = linemap_position_for_column (line_table, 17);
+
+ /* Example of a very long line. */
+ linemap_line_start (line_table, 3, 2000);
+ loc_e = linemap_position_for_column (line_table, 700);
+
+ linemap_add (line_table, LC_LEAVE, false, NULL, 0);
+
+ /* Multiple files. */
+ linemap_add (line_table, LC_ENTER, false, "bar.c", 0);
+ linemap_line_start (line_table, 1, 200);
+ loc_f = linemap_position_for_column (line_table, 150);
+ linemap_add (line_table, LC_LEAVE, false, NULL, 0);
+ }
+
+ /* Verify the result of LOCATION_FILE/LOCATION_LINE/LOCATION_COLUMN
+ on LOC. */
+ void
+ expect_loceq (const char *exp_filename,
+ int exp_linenum,
+ int exp_colnum,
+ location_t loc)
+ {
+ EXPECT_STREQ (exp_filename, LOCATION_FILE (loc));
+ EXPECT_EQ (exp_linenum, LOCATION_LINE (loc));
+ EXPECT_EQ (exp_colnum, LOCATION_COLUMN (loc));
+ }
+
+ location_t loc_a;
+ location_t loc_b;
+ location_t loc_c;
+ location_t loc_d;
+ location_t loc_e;
+ location_t loc_f;
+};
+
+/* Verify basic operation of ordinary linemaps. */
+
+TEST_F (location_test, accessing_ordinary_linemaps)
+{
+ /* Verify that we can recover the location info. */
+ expect_loceq ("foo.c", 1, 1, loc_a);
+ expect_loceq ("foo.c", 1, 23, loc_b);
+ expect_loceq ("foo.c", 2, 1, loc_c);
+ expect_loceq ("foo.c", 2, 17, loc_d);
+ expect_loceq ("foo.c", 3, 700, loc_e);
+ expect_loceq ("bar.c", 1, 150, loc_f);
+}
+
+TEST_F (location_test, unknown_location)
+{
+ EXPECT_EQ (NULL, LOCATION_FILE (UNKNOWN_LOCATION));
+ EXPECT_EQ (0, LOCATION_LINE (UNKNOWN_LOCATION));
+ EXPECT_EQ (0, LOCATION_COLUMN (UNKNOWN_LOCATION));
+}
+
+TEST_F (location_test, builtins)
+{
+ expect_loceq ("<built-in>", 0, 0, BUILTINS_LOCATION);
+ EXPECT_PRED1 (is_location_from_builtin_token, BUILTINS_LOCATION);
+ EXPECT_FALSE (is_location_from_builtin_token (loc_a));
+}
+
+/* Verify reading of input files (e.g. for caret-based diagnostics. */
+
+TEST_F (location_test, reading_source_line)
+{
+ /* We will read *this* source file, using __FILE__.
+ Here is some specific text to read and test for:
+ The quick brown fox jumps over the lazy dog. */
+ const int linenum_after_test_message = __LINE__;
+ const int linenum = linenum_after_test_message - 1;
+
+ int line_size;
+ const char *source_line = location_get_source_line (__FILE__, linenum, &line_size);
+ EXPECT_TRUE (source_line != NULL);
+ EXPECT_EQ (53, line_size);
+ if (!strncmp (" The quick brown fox jumps over the lazy dog. */",
+ source_line, line_size))
+ pass (__FILE__, __LINE__, "source_line matched expected value");
+ else
+ fail (__FILE__, __LINE__, "source_line did not match expected value");
+}
+
+} /* anon namespace. */
+
+#endif /* CHECKING_P */