comparison gcc/input.c @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents 04ced10e8804
children 1830386684a0
comparison
equal deleted inserted replaced
111:04ced10e8804 131:84e7813d76e9
1 /* Data and functions related to line maps and input files. 1 /* Data and functions related to line maps and input files.
2 Copyright (C) 2004-2017 Free Software Foundation, Inc. 2 Copyright (C) 2004-2018 Free Software Foundation, Inc.
3 3
4 This file is part of GCC. 4 This file is part of GCC.
5 5
6 GCC is free software; you can redistribute it and/or modify it under 6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free 7 the terms of the GNU General Public License as published by the Free
739 739
740 /* Return the physical source line that corresponds to FILE_PATH/LINE. 740 /* Return the physical source line that corresponds to FILE_PATH/LINE.
741 The line is not nul-terminated. The returned pointer is only 741 The line is not nul-terminated. The returned pointer is only
742 valid until the next call of location_get_source_line. 742 valid until the next call of location_get_source_line.
743 Note that the line can contain several null characters, 743 Note that the line can contain several null characters,
744 so LINE_LEN, if non-null, points to the actual length of the line. 744 so the returned value's length has the actual length of the line.
745 If the function fails, NULL is returned. */ 745 If the function fails, a NULL char_span is returned. */
746 746
747 const char * 747 char_span
748 location_get_source_line (const char *file_path, int line, 748 location_get_source_line (const char *file_path, int line)
749 int *line_len)
750 { 749 {
751 char *buffer = NULL; 750 char *buffer = NULL;
752 ssize_t len; 751 ssize_t len;
753 752
754 if (line == 0) 753 if (line == 0)
755 return NULL; 754 return char_span (NULL, 0);
756 755
757 fcache *c = lookup_or_add_file_to_cache_tab (file_path); 756 fcache *c = lookup_or_add_file_to_cache_tab (file_path);
758 if (c == NULL) 757 if (c == NULL)
759 return NULL; 758 return char_span (NULL, 0);
760 759
761 bool read = read_line_num (c, line, &buffer, &len); 760 bool read = read_line_num (c, line, &buffer, &len);
762 761 if (!read)
763 if (read && line_len) 762 return char_span (NULL, 0);
764 *line_len = len; 763
765 764 return char_span (buffer, len);
766 return read ? buffer : NULL;
767 } 765 }
768 766
769 /* Determine if FILE_PATH missing a trailing newline on its final line. 767 /* Determine if FILE_PATH missing a trailing newline on its final line.
770 Only valid to call once all of the file has been loaded, by 768 Only valid to call once all of the file has been loaded, by
771 requesting a line number beyond the end of the file. */ 769 requesting a line number beyond the end of the file. */
813 relevant macro. If LOC resolves to a builtin location, the file 811 relevant macro. If LOC resolves to a builtin location, the file
814 name of the readable location is set to the string 812 name of the readable location is set to the string
815 "<built-in>". */ 813 "<built-in>". */
816 814
817 expanded_location 815 expanded_location
818 expand_location_to_spelling_point (source_location loc) 816 expand_location_to_spelling_point (source_location loc,
819 { 817 enum location_aspect aspect)
820 return expand_location_1 (loc, /*expansion_point_p=*/false, 818 {
821 LOCATION_ASPECT_CARET); 819 return expand_location_1 (loc, /*expansion_point_p=*/false, aspect);
822 } 820 }
823 821
824 /* The rich_location class within libcpp requires a way to expand 822 /* The rich_location class within libcpp requires a way to expand
825 source_location instances, and relies on the client code 823 source_location instances, and relies on the client code
826 providing a symbol named 824 providing a symbol named
1115 gcc_assert (pure_location_p (line_table, loc) ); 1113 gcc_assert (pure_location_p (line_table, loc) );
1116 1114
1117 expanded_location exploc 1115 expanded_location exploc
1118 = linemap_expand_location (line_table, map, loc); 1116 = linemap_expand_location (line_table, map, loc);
1119 1117
1120 if (0 == exploc.column) 1118 if (exploc.column == 0)
1121 { 1119 {
1122 /* Beginning of a new source line: draw the line. */ 1120 /* Beginning of a new source line: draw the line. */
1123 1121
1124 int line_size; 1122 char_span line_text = location_get_source_line (exploc.file,
1125 const char *line_text = location_get_source_line (exploc.file, 1123 exploc.line);
1126 exploc.line,
1127 &line_size);
1128 if (!line_text) 1124 if (!line_text)
1129 break; 1125 break;
1130 fprintf (stream, 1126 fprintf (stream,
1131 "%s:%3i|loc:%5i|%.*s\n", 1127 "%s:%3i|loc:%5i|%.*s\n",
1132 exploc.file, exploc.line, 1128 exploc.file, exploc.line,
1133 loc, 1129 loc,
1134 line_size, line_text); 1130 (int)line_text.length (), line_text.get_buffer ());
1135 1131
1136 /* "loc" is at column 0, which means "the whole line". 1132 /* "loc" is at column 0, which means "the whole line".
1137 Render the locations *within* the line, by underlining 1133 Render the locations *within* the line, by underlining
1138 it, showing the source_location numeric values 1134 it, showing the source_location numeric values
1139 at each column. */ 1135 at each column. */
1140 int max_col = (1 << map->m_column_and_range_bits) - 1; 1136 size_t max_col = (1 << map->m_column_and_range_bits) - 1;
1141 if (max_col > line_size) 1137 if (max_col > line_text.length ())
1142 max_col = line_size + 1; 1138 max_col = line_text.length () + 1;
1143 1139
1144 int indent = 14 + strlen (exploc.file); 1140 int indent = 14 + strlen (exploc.file);
1145 1141
1146 /* Thousands. */ 1142 /* Thousands. */
1147 if (end_location > 999) 1143 if (end_location > 999)
1399 /* Get range of strloc. We will use it to locate the start and finish 1395 /* Get range of strloc. We will use it to locate the start and finish
1400 of the literal token within the line. */ 1396 of the literal token within the line. */
1401 source_range src_range = get_range_from_loc (line_table, strlocs[i]); 1397 source_range src_range = get_range_from_loc (line_table, strlocs[i]);
1402 1398
1403 if (src_range.m_start >= LINEMAPS_MACRO_LOWEST_LOCATION (line_table)) 1399 if (src_range.m_start >= LINEMAPS_MACRO_LOWEST_LOCATION (line_table))
1404 /* If the string is within a macro expansion, we can't get at the 1400 {
1405 end location. */ 1401 /* If the string token was within a macro expansion, then we can
1406 return "macro expansion"; 1402 cope with it for the simple case where we have a single token.
1407 1403 Otherwise, bail out. */
1408 if (src_range.m_start >= LINE_MAP_MAX_LOCATION_WITH_COLS) 1404 if (src_range.m_start != src_range.m_finish)
1409 /* If so, we can't reliably determine where the token started within 1405 return "macro expansion";
1410 its line. */ 1406 }
1411 return "range starts after LINE_MAP_MAX_LOCATION_WITH_COLS"; 1407 else
1412 1408 {
1413 if (src_range.m_finish >= LINE_MAP_MAX_LOCATION_WITH_COLS) 1409 if (src_range.m_start >= LINE_MAP_MAX_LOCATION_WITH_COLS)
1414 /* If so, we can't reliably determine where the token finished within 1410 /* If so, we can't reliably determine where the token started within
1415 its line. */ 1411 its line. */
1416 return "range ends after LINE_MAP_MAX_LOCATION_WITH_COLS"; 1412 return "range starts after LINE_MAP_MAX_LOCATION_WITH_COLS";
1413
1414 if (src_range.m_finish >= LINE_MAP_MAX_LOCATION_WITH_COLS)
1415 /* If so, we can't reliably determine where the token finished
1416 within its line. */
1417 return "range ends after LINE_MAP_MAX_LOCATION_WITH_COLS";
1418 }
1417 1419
1418 expanded_location start 1420 expanded_location start
1419 = expand_location_to_spelling_point (src_range.m_start); 1421 = expand_location_to_spelling_point (src_range.m_start,
1422 LOCATION_ASPECT_START);
1420 expanded_location finish 1423 expanded_location finish
1421 = expand_location_to_spelling_point (src_range.m_finish); 1424 = expand_location_to_spelling_point (src_range.m_finish,
1425 LOCATION_ASPECT_FINISH);
1422 if (start.file != finish.file) 1426 if (start.file != finish.file)
1423 return "range endpoints are in different files"; 1427 return "range endpoints are in different files";
1424 if (start.line != finish.line) 1428 if (start.line != finish.line)
1425 return "range endpoints are on different lines"; 1429 return "range endpoints are on different lines";
1426 if (start.column > finish.column) 1430 if (start.column > finish.column)
1427 return "range endpoints are reversed"; 1431 return "range endpoints are reversed";
1428 1432
1429 int line_width; 1433 char_span line = location_get_source_line (start.file, start.line);
1430 const char *line = location_get_source_line (start.file, start.line, 1434 if (!line)
1431 &line_width);
1432 if (line == NULL)
1433 return "unable to read source line"; 1435 return "unable to read source line";
1434 1436
1435 /* Determine the location of the literal (including quotes 1437 /* Determine the location of the literal (including quotes
1436 and leading prefix chars, such as the 'u' in a u"" 1438 and leading prefix chars, such as the 'u' in a u""
1437 token). */ 1439 token). */
1438 const char *literal = line + start.column - 1; 1440 size_t literal_length = finish.column - start.column + 1;
1439 int literal_length = finish.column - start.column + 1;
1440 1441
1441 /* Ensure that we don't crash if we got the wrong location. */ 1442 /* Ensure that we don't crash if we got the wrong location. */
1442 if (line_width < (start.column - 1 + literal_length)) 1443 if (line.length () < (start.column - 1 + literal_length))
1443 return "line is not wide enough"; 1444 return "line is not wide enough";
1445
1446 char_span literal = line.subspan (start.column - 1, literal_length);
1444 1447
1445 cpp_string from; 1448 cpp_string from;
1446 from.len = literal_length; 1449 from.len = literal_length;
1447 /* Make a copy of the literal, to avoid having to rely on 1450 /* Make a copy of the literal, to avoid having to rely on
1448 the lifetime of the copy of the line within the cache. 1451 the lifetime of the copy of the line within the cache.
1449 This will be released by the auto_cpp_string_vec dtor. */ 1452 This will be released by the auto_cpp_string_vec dtor. */
1450 from.text = XDUPVEC (unsigned char, literal, literal_length); 1453 from.text = (unsigned char *)literal.xstrdup ();
1451 strs.safe_push (from); 1454 strs.safe_push (from);
1452 1455
1453 /* For very long lines, a new linemap could have started 1456 /* For very long lines, a new linemap could have started
1454 halfway through the token. 1457 halfway through the token.
1455 Ensure that the loc_reader uses the linemap of the 1458 Ensure that the loc_reader uses the linemap of the
1456 *end* of the token for its start location. */ 1459 *end* of the token for its start location. */
1460 const line_map_ordinary *start_ord_map;
1461 linemap_resolve_location (line_table, src_range.m_start,
1462 LRK_SPELLING_LOCATION, &start_ord_map);
1457 const line_map_ordinary *final_ord_map; 1463 const line_map_ordinary *final_ord_map;
1458 linemap_resolve_location (line_table, src_range.m_finish, 1464 linemap_resolve_location (line_table, src_range.m_finish,
1459 LRK_MACRO_EXPANSION_POINT, &final_ord_map); 1465 LRK_SPELLING_LOCATION, &final_ord_map);
1466 /* Bulletproofing. We ought to only have different ordinary maps
1467 for start vs finish due to line-length jumps. */
1468 if (start_ord_map != final_ord_map
1469 && start_ord_map->to_file != final_ord_map->to_file)
1470 return "start and finish are spelled in different ordinary maps";
1460 location_t start_loc 1471 location_t start_loc
1461 = linemap_position_for_line_and_column (line_table, final_ord_map, 1472 = linemap_position_for_line_and_column (line_table, final_ord_map,
1462 start.line, start.column); 1473 start.line, start.column);
1463 1474
1464 cpp_string_location_reader loc_reader (start_loc, line_table); 1475 cpp_string_location_reader loc_reader (start_loc, line_table);
1592 *out = ranges.get_num_ranges (); 1603 *out = ranges.get_num_ranges ();
1593 return NULL; 1604 return NULL;
1594 } 1605 }
1595 1606
1596 /* Selftests of location handling. */ 1607 /* Selftests of location handling. */
1608
1609 /* Verify that compare() on linenum_type handles comparisons over the full
1610 range of the type. */
1611
1612 static void
1613 test_linenum_comparisons ()
1614 {
1615 linenum_type min_line (0);
1616 linenum_type max_line (0xffffffff);
1617 ASSERT_EQ (0, compare (min_line, min_line));
1618 ASSERT_EQ (0, compare (max_line, max_line));
1619
1620 ASSERT_GT (compare (max_line, min_line), 0);
1621 ASSERT_LT (compare (min_line, max_line), 0);
1622 }
1597 1623
1598 /* Helper function for verifying location data: when location_t 1624 /* Helper function for verifying location data: when location_t
1599 values are > LINE_MAP_MAX_LOCATION_WITH_COLS, they are treated 1625 values are > LINE_MAP_MAX_LOCATION_WITH_COLS, they are treated
1600 as having column 0. */ 1626 as having column 0. */
1601 1627
1891 "01234567890123456789\n" 1917 "01234567890123456789\n"
1892 "This is the test text\n" 1918 "This is the test text\n"
1893 "This is the 3rd line"); 1919 "This is the 3rd line");
1894 1920
1895 /* Read back a specific line from the tempfile. */ 1921 /* Read back a specific line from the tempfile. */
1896 int line_size; 1922 char_span source_line = location_get_source_line (tmp.get_filename (), 3);
1897 const char *source_line = location_get_source_line (tmp.get_filename (), 1923 ASSERT_TRUE (source_line);
1898 3, &line_size); 1924 ASSERT_TRUE (source_line.get_buffer () != NULL);
1899 ASSERT_TRUE (source_line != NULL); 1925 ASSERT_EQ (20, source_line.length ());
1900 ASSERT_EQ (20, line_size);
1901 ASSERT_TRUE (!strncmp ("This is the 3rd line", 1926 ASSERT_TRUE (!strncmp ("This is the 3rd line",
1902 source_line, line_size)); 1927 source_line.get_buffer (), source_line.length ()));
1903 1928
1904 source_line = location_get_source_line (tmp.get_filename (), 1929 source_line = location_get_source_line (tmp.get_filename (), 2);
1905 2, &line_size); 1930 ASSERT_TRUE (source_line);
1906 ASSERT_TRUE (source_line != NULL); 1931 ASSERT_TRUE (source_line.get_buffer () != NULL);
1907 ASSERT_EQ (21, line_size); 1932 ASSERT_EQ (21, source_line.length ());
1908 ASSERT_TRUE (!strncmp ("This is the test text", 1933 ASSERT_TRUE (!strncmp ("This is the test text",
1909 source_line, line_size)); 1934 source_line.get_buffer (), source_line.length ()));
1910 1935
1911 source_line = location_get_source_line (tmp.get_filename (), 1936 source_line = location_get_source_line (tmp.get_filename (), 4);
1912 4, &line_size); 1937 ASSERT_FALSE (source_line);
1913 ASSERT_TRUE (source_line == NULL); 1938 ASSERT_TRUE (source_line.get_buffer () == NULL);
1914 } 1939 }
1915 1940
1916 /* Tests of lexing. */ 1941 /* Tests of lexing. */
1917 1942
1918 /* Verify that token TOK from PARSER has cpp_token_as_text 1943 /* Verify that token TOK from PARSER has cpp_token_as_text
2097 { 2122 {
2098 cpp_options *cpp_opts = cpp_get_options (test.m_parser); 2123 cpp_options *cpp_opts = cpp_get_options (test.m_parser);
2099 cpp_opts->narrow_charset = "IBM1047"; 2124 cpp_opts->narrow_charset = "IBM1047";
2100 2125
2101 cpp_callbacks *callbacks = cpp_get_callbacks (test.m_parser); 2126 cpp_callbacks *callbacks = cpp_get_callbacks (test.m_parser);
2102 callbacks->error = on_error; 2127 callbacks->diagnostic = on_diagnostic;
2103 } 2128 }
2104 2129
2105 static bool on_error (cpp_reader *pfile ATTRIBUTE_UNUSED, 2130 static bool on_diagnostic (cpp_reader *pfile ATTRIBUTE_UNUSED,
2106 int level ATTRIBUTE_UNUSED, 2131 enum cpp_diagnostic_level level ATTRIBUTE_UNUSED,
2107 int reason ATTRIBUTE_UNUSED, 2132 enum cpp_warning_reason reason ATTRIBUTE_UNUSED,
2108 rich_location *richloc ATTRIBUTE_UNUSED, 2133 rich_location *richloc ATTRIBUTE_UNUSED,
2109 const char *msgid, va_list *ap ATTRIBUTE_UNUSED) 2134 const char *msgid, va_list *ap ATTRIBUTE_UNUSED)
2110 ATTRIBUTE_FPTR_PRINTF(5,0) 2135 ATTRIBUTE_FPTR_PRINTF(5,0)
2111 { 2136 {
2112 gcc_assert (s_singleton); 2137 gcc_assert (s_singleton);
2113 /* Avoid exgettext from picking this up, it is translated in libcpp. */ 2138 /* Avoid exgettext from picking this up, it is translated in libcpp. */
2114 const char *msg = "conversion from %s to %s not supported by iconv"; 2139 const char *msg = "conversion from %s to %s not supported by iconv";
2134 int m_num_iconv_errors; 2159 int m_num_iconv_errors;
2135 }; 2160 };
2136 2161
2137 ebcdic_execution_charset *ebcdic_execution_charset::s_singleton; 2162 ebcdic_execution_charset *ebcdic_execution_charset::s_singleton;
2138 2163
2139 /* A lexer_test_options subclass that records a list of error 2164 /* A lexer_test_options subclass that records a list of diagnostic
2140 messages emitted by the lexer. */ 2165 messages emitted by the lexer. */
2141 2166
2142 class lexer_error_sink : public lexer_test_options 2167 class lexer_diagnostic_sink : public lexer_test_options
2143 { 2168 {
2144 public: 2169 public:
2145 lexer_error_sink () 2170 lexer_diagnostic_sink ()
2146 { 2171 {
2147 gcc_assert (s_singleton == NULL); 2172 gcc_assert (s_singleton == NULL);
2148 s_singleton = this; 2173 s_singleton = this;
2149 } 2174 }
2150 ~lexer_error_sink () 2175 ~lexer_diagnostic_sink ()
2151 { 2176 {
2152 gcc_assert (s_singleton == this); 2177 gcc_assert (s_singleton == this);
2153 s_singleton = NULL; 2178 s_singleton = NULL;
2154 2179
2155 int i; 2180 int i;
2156 char *str; 2181 char *str;
2157 FOR_EACH_VEC_ELT (m_errors, i, str) 2182 FOR_EACH_VEC_ELT (m_diagnostics, i, str)
2158 free (str); 2183 free (str);
2159 } 2184 }
2160 2185
2161 void apply (lexer_test &test) FINAL OVERRIDE 2186 void apply (lexer_test &test) FINAL OVERRIDE
2162 { 2187 {
2163 cpp_callbacks *callbacks = cpp_get_callbacks (test.m_parser); 2188 cpp_callbacks *callbacks = cpp_get_callbacks (test.m_parser);
2164 callbacks->error = on_error; 2189 callbacks->diagnostic = on_diagnostic;
2165 } 2190 }
2166 2191
2167 static bool on_error (cpp_reader *pfile ATTRIBUTE_UNUSED, 2192 static bool on_diagnostic (cpp_reader *pfile ATTRIBUTE_UNUSED,
2168 int level ATTRIBUTE_UNUSED, 2193 enum cpp_diagnostic_level level ATTRIBUTE_UNUSED,
2169 int reason ATTRIBUTE_UNUSED, 2194 enum cpp_warning_reason reason ATTRIBUTE_UNUSED,
2170 rich_location *richloc ATTRIBUTE_UNUSED, 2195 rich_location *richloc ATTRIBUTE_UNUSED,
2171 const char *msgid, va_list *ap) 2196 const char *msgid, va_list *ap)
2172 ATTRIBUTE_FPTR_PRINTF(5,0) 2197 ATTRIBUTE_FPTR_PRINTF(5,0)
2173 { 2198 {
2174 char *msg = xvasprintf (msgid, *ap); 2199 char *msg = xvasprintf (msgid, *ap);
2175 s_singleton->m_errors.safe_push (msg); 2200 s_singleton->m_diagnostics.safe_push (msg);
2176 return true; 2201 return true;
2177 } 2202 }
2178 2203
2179 auto_vec<char *> m_errors; 2204 auto_vec<char *> m_diagnostics;
2180 2205
2181 private: 2206 private:
2182 static lexer_error_sink *s_singleton; 2207 static lexer_diagnostic_sink *s_singleton;
2183 }; 2208 };
2184 2209
2185 lexer_error_sink *lexer_error_sink::s_singleton; 2210 lexer_diagnostic_sink *lexer_diagnostic_sink::s_singleton;
2186 2211
2187 /* Constructor. Override line_table with a new instance based on CASE_, 2212 /* Constructor. Override line_table with a new instance based on CASE_,
2188 and write CONTENT to a tempfile. Create a cpp_reader, and use it to 2213 and write CONTENT to a tempfile. Create a cpp_reader, and use it to
2189 start parsing the tempfile. */ 2214 start parsing the tempfile. */
2190 2215
3394 static void 3419 static void
3395 test_lexer_string_locations_raw_string_unterminated (const line_table_case &case_) 3420 test_lexer_string_locations_raw_string_unterminated (const line_table_case &case_)
3396 { 3421 {
3397 const char *content = "R\"ouch()ouCh\" /* etc */"; 3422 const char *content = "R\"ouch()ouCh\" /* etc */";
3398 3423
3399 lexer_error_sink errors; 3424 lexer_diagnostic_sink diagnostics;
3400 lexer_test test (case_, content, &errors); 3425 lexer_test test (case_, content, &diagnostics);
3401 test.m_implicitly_expect_EOF = false; 3426 test.m_implicitly_expect_EOF = false;
3402 3427
3403 /* Attempt to parse the raw string. */ 3428 /* Attempt to parse the raw string. */
3404 const cpp_token *tok = test.get_token (); 3429 const cpp_token *tok = test.get_token ();
3405 ASSERT_EQ (tok->type, CPP_EOF); 3430 ASSERT_EQ (tok->type, CPP_EOF);
3406 3431
3407 ASSERT_EQ (1, errors.m_errors.length ()); 3432 ASSERT_EQ (1, diagnostics.m_diagnostics.length ());
3408 /* We expect the message "unterminated raw string" 3433 /* We expect the message "unterminated raw string"
3409 in the "cpplib" translation domain. 3434 in the "cpplib" translation domain.
3410 It's not clear that dgettext is available on all supported hosts, 3435 It's not clear that dgettext is available on all supported hosts,
3411 so this assertion is commented-out for now. 3436 so this assertion is commented-out for now.
3412 ASSERT_STREQ (dgettext ("cpplib", "unterminated raw string"), 3437 ASSERT_STREQ (dgettext ("cpplib", "unterminated raw string"),
3413 errors.m_errors[0]); 3438 diagnostics.m_diagnostics[0]);
3414 */ 3439 */
3415 } 3440 }
3416 3441
3417 /* Test of lexing char constants. */ 3442 /* Test of lexing char constants. */
3418 3443
3526 /* Run all of the selftests within this file. */ 3551 /* Run all of the selftests within this file. */
3527 3552
3528 void 3553 void
3529 input_c_tests () 3554 input_c_tests ()
3530 { 3555 {
3556 test_linenum_comparisons ();
3531 test_should_have_column_data_p (); 3557 test_should_have_column_data_p ();
3532 test_unknown_location (); 3558 test_unknown_location ();
3533 test_builtins (); 3559 test_builtins ();
3534 for_each_line_table_case (test_make_location_nonpure_range_endpoints); 3560 for_each_line_table_case (test_make_location_nonpure_range_endpoints);
3535 3561