From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-qt1-x82d.google.com (mail-qt1-x82d.google.com [IPv6:2607:f8b0:4864:20::82d]) by sourceware.org (Postfix) with ESMTPS id 21B143858027 for ; Fri, 4 Nov 2022 13:44:46 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 21B143858027 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-qt1-x82d.google.com with SMTP id h24so3018701qta.7 for ; Fri, 04 Nov 2022 06:44:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=vlPio+AUfrWMNTOhD/ZRU+3HukWXzkDvW6qrokDtx1E=; b=QTH2H/ioa6gaDqEOhMzKn0+oaiyBqtHMT6aeAw1OREgfzUKx5OBauU+AbrwsyIys2g c0bmt50rStJwOKHFJybvFLZGAvjZcZjYHKmr4VqukNj+/ww5gWrBJ86eTu99STVYCUNc owbFIuNGDsCGI01Y8ADubToxxmRtaDmR8I4qBIQfD4No0Pn1O31Nqcwllw03ZncJDVV4 Mi1w/VRRFK+1g2IAuriEvqbd6S4WCS8fRmuBwb1rJT8RqM46OCg15lPO8KvV6El4Q3w3 66Vv+4misnrkCucxm3S+xcNG0RiafzyEy6o8ojOfyQOnQyZDhV0PDMitKGNAewcdcELW 7aUA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=vlPio+AUfrWMNTOhD/ZRU+3HukWXzkDvW6qrokDtx1E=; b=k0VsJu8sPZFxJCU+5FGU2Il9IgPsOKuLXDSdfs5Q9zHe29LlwvV1koyWwKHO7oV3TE ERXDZJGkguxp+A2eFHGHNsPQkJv3vqdWpk8UcTxyGoM/JRoYTv+RjqQ3+2qIsUVt6lHp oLZrf0lIIDoPDArxQ5DbsNXnNdSZbf3pkBf78jPQID6Nmkf4QGbgJkP58R8ETrwwKkOL Z35ZrvMMYTjYRfRwKHkBuYcV6Cgv+0V17OPOkwjbiDyD2uG6B158NpMZXl8f/m+ZV90u lXSkV8hORn/EXXoKMcg7Z1PkqHRIFEmqWQ5CdQNtJgmYsEY5z0qSO8U7epwiurpOEJD/ T8rw== X-Gm-Message-State: ACrzQf17Qjlqwy7oUp8y7OJqLIlBdmcZDQBmGRgUTV9uipLMBEBhnqi3 DB7YNt2QXnN1YUav8+F/GSt4yXwdrns= X-Google-Smtp-Source: AMsMyM7guPmniSQpzQsk2IshGYDfdhHsFQ+SiaFsMoVO+kx19agldNApXnuUe93v7VWFBu0bM1+xYA== X-Received: by 2002:ac8:604b:0:b0:3a5:456d:8bae with SMTP id k11-20020ac8604b000000b003a5456d8baemr11652503qtm.416.1667569484449; Fri, 04 Nov 2022 06:44:44 -0700 (PDT) Received: from localhost.localdomain (96-67-140-173-static.hfc.comcastbusiness.net. [96.67.140.173]) by smtp.gmail.com with ESMTPSA id ey21-20020a05622a4c1500b003988b3d5280sm2470577qtb.70.2022.11.04.06.44.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Nov 2022 06:44:43 -0700 (PDT) From: Lewis Hyatt To: gcc-patches@gcc.gnu.org Cc: Lewis Hyatt Subject: [PATCH 4/6] diagnostics: libcpp: Add LC_GEN linemaps to support in-memory buffers Date: Fri, 4 Nov 2022 09:44:12 -0400 Message-Id: X-Mailer: git-send-email 2.25.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-3038.8 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,GIT_PATCH_0,KAM_LOTSOFHASH,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,TXREP,T_FILL_THIS_FORM_SHORT autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: Add a new linemap reason LC_GEN which enables encoding the location of data that was generated during compilation and does not appear in any source file. There could be many use cases, such as, for instance, referring to the content of builtin macros (not yet implemented, but an easy lift after this one.) The first intended application is to create a place to store the input to a _Pragma directive, so that proper locations can be assigned to those tokens. This will be done in a subsequent commit. The actual change needed to the line-maps API in libcpp is very minimal and requires no space overhead in the line map data structures (on 64-bit systems that is; one newly added data member to class line_map_ordinary sits inside former padding bytes.) An LC_GEN map is just an ordinary map like any other, but the TO_FILE member that normally points to the file name points instead to the actual data. This works automatically with PCH as well, for the same reason that the file name makes its way into a PCH. Outside libcpp, there are many small changes but most of them are to selftests, which are necessarily more sensitive to implementation details. From the perspective of the user (the "user", here, being a frontend using line maps or else the diagnostics infrastructure), the chief visible change is that the function location_get_source_line() should be passed an expanded_location object instead of a separate filename and line number. This is not a big change because in most cases, this information came anyway from a call to expand_location and the needed expanded_location object is readily available. The new overload of location_get_source_line() uses the extra information in the expanded_location object to obtain the data from the in-memory buffer when it originated from an LC_GEN map. Until the subsequent patch that starts using LC_GEN maps, none are yet generated within GCC, hence nothing is added to the testsuite here; but all relevant selftests have been extended to cover generated data maps in addition to normal files. libcpp/ChangeLog: * include/line-map.h (enum lc_reason): Add LC_GEN. (struct line_map_ordinary): Add new member to_file_len and update the GTY markup on to_file to support embedded null bytes. (class expanded_location): Add new members to store generated content. * line-map.cc (linemap_add): Add new argument to_file_len to support generated content. Implement LC_GEN maps. (linemap_line_start): Pass new to_file_len argument to linemap_add. (linemap_expand_location): Support LC_GEN locations. (linemap_dump): Likewise. gcc/ChangeLog: * diagnostic-show-locus.cc (make_range): Initialize new fields in expanded_location. (layout::calculate_x_offset_display): Use the new expanded_location overload of location_get_source_line(), so as to support LC_GEN maps. (layout::print_line): Likewise. (source_line::source_line): Likewise. (line_corrections::add_hint): Likewise. (class line_corrections): Store the location as an exploc rather than individual filename, so as to support LC_GEN maps. (layout::print_trailing_fixits): Use the new exploc constructor for class line_corrections. (test_layout_x_offset_display_utf8): Test LC_GEN maps as well as normal. (test_layout_x_offset_display_tab): Likewise. (test_diagnostic_show_locus_one_liner): Likewise. (test_diagnostic_show_locus_one_liner_utf8): Likewise. (test_add_location_if_nearby): Likewise. (test_diagnostic_show_locus_fixit_lines): Likewise. (test_fixit_consolidation): Likewise. (test_overlapped_fixit_printing): Likewise. (test_overlapped_fixit_printing_utf8): Likewise. (test_overlapped_fixit_printing_2): Likewise. (test_fixit_insert_containing_newline): Likewise. (test_fixit_insert_containing_newline_2): Likewise. (test_fixit_replace_containing_newline): Likewise. (test_fixit_deletion_affecting_newline): Likewise. (test_tab_expansion): Likewise. (test_escaping_bytes_1): Likewise. (test_escaping_bytes_2): Likewise. (test_line_numbers_multiline_range): Likewise. (diagnostic_show_locus_cc_tests): Likewise. * diagnostic.cc (diagnostic_report_current_module): Support LC_GEN maps when outputting include trace. (assert_location_text): Zero-initialize the expanded_location so as to cover all fields, including the newly added ones. * gcc-rich-location.cc (blank_line_before_p): Use the new expanded_location overload of location_get_source_line(). * input.cc (class file_cache_slot): Add new member m_data_active. (file_cache_slot::file_cache_slot): Initialize new member. (special_fname_generated): New function. (expand_location_1): Recognize LC_GEN locations and output the special filename for them. (file_cache::add_file): Support generated data that is already in memory and does not need to be read from a file. (file_cache_slot::create): Likewise. (file_cache::lookup_or_add_file): Likewise. (file_cache_slot::maybe_grow): Add assert that we are not in generated data mode. (file_cache_slot::read_data): Likewise. (find_end_of_line): Add missing const. (file_cache_slot::goto_next_line): Likewise. (file_cache_slot::read_line_num): Likewise. (file_cache_slot::get_next_line): Add missing const. Adapt to use of new m_data_active member. (location_get_source_line): Change to take an expanded_location argument instead of a filename. Support generated data. Add another overload taking a filename that delegates to this one. (location_compute_display_column): Use the new overload of location_get_source_line. (dump_location_info): Likewise. (get_substring_ranges_for_loc): Likewise. (location_missing_trailing_newline): Pass new argument to lookup_or_add_file (). (temp_source_file::do_linemap_add): New function. (class line_table_case): Add new m_generated_data member. (line_table_test::line_table_test): Initialize the new member. (test_accessing_ordinary_linemaps): Test generated data too. (test_make_location_nonpure_range_endpoints): Likewise. (test_line_offset_overflow): Likewise. (for_each_line_table_case): Add new argument requesting to test generated data as well as regular. (input_cc_tests): Enable testing generated data in the selftests. * input.h (special_fname_generated): Declare. (location_get_source_line): Declare new overloads. (class file_cache): Update prototypes for new arguments. * selftest.cc (named_temp_file::named_temp_file): Support nullptr argument to disable creating any file. (named_temp_file::~named_temp_file): Likewise. (temp_source_file::temp_source_file): Add a new constructor argument to enable creating generated data instead of a file. (temp_source_file::~temp_source_file): Handle freeing generated data buffer. * selftest.h (struct line_map_ordinary): Forward declare. (class named_temp_file): Add missing explicit on constructor. (class temp_source_file): Add new members to store generated content. (class line_table_test): Add new m_generated_data member. (for_each_line_table_case): Update prototype for new argument. gcc/c-family/ChangeLog: * c-common.cc (try_to_locate_new_include_insertion_point): Add awareness of LC_GEN maps. * c-format.cc (get_corrected_substring): Use the new expanded_location overload of location_get_source_line(), so as to support LC_GEN maps. * c-indentation.cc (get_visual_column): Likewise. (get_first_nws_vis_column): Likewise. (detect_intervening_unindent): Likewise. (should_warn_for_misleading_indentation): Likewise. (assert_get_visual_column_succeeds): Zero-initialize the exploc to cover all fields including those newly added. (assert_get_visual_column_fails): Likewise. gcc/testsuite/ChangeLog: * gcc.dg/plugin/diagnostic_plugin_test_show_locus.c: Use the new overload of location_get_source_line. --- gcc/c-family/c-common.cc | 5 +- gcc/c-family/c-format.cc | 2 +- gcc/c-family/c-indentation.cc | 28 +- gcc/diagnostic-show-locus.cc | 237 +++++++++-------- gcc/diagnostic.cc | 15 +- gcc/gcc-rich-location.cc | 2 +- gcc/input.cc | 240 ++++++++++++------ gcc/input.h | 11 +- gcc/selftest.cc | 49 +++- gcc/selftest.h | 20 +- .../diagnostic_plugin_test_show_locus.c | 4 +- libcpp/include/line-map.h | 21 +- libcpp/line-map.cc | 51 +++- 13 files changed, 443 insertions(+), 242 deletions(-) diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc index 5890c18bdc3..2935d7fb236 100644 --- a/gcc/c-family/c-common.cc +++ b/gcc/c-family/c-common.cc @@ -9183,11 +9183,14 @@ try_to_locate_new_include_insertion_point (const char *file, location_t loc) const line_map_ordinary *ord_map = LINEMAPS_ORDINARY_MAP_AT (line_table, i); + if (ord_map->reason == LC_GEN) + continue; + if (const line_map_ordinary *from = linemap_included_from_linemap (line_table, ord_map)) /* We cannot use pointer equality, because with preprocessed input all filename strings are unique. */ - if (0 == strcmp (from->to_file, file)) + if (from->reason != LC_GEN && 0 == strcmp (from->to_file, file)) { last_include_ord_map = from; last_ord_map_after_include = NULL; diff --git a/gcc/c-family/c-format.cc b/gcc/c-family/c-format.cc index 01adea4ff41..87ad3e74b72 100644 --- a/gcc/c-family/c-format.cc +++ b/gcc/c-family/c-format.cc @@ -4538,7 +4538,7 @@ get_corrected_substring (const substring_loc &fmt_loc, if (caret.column > finish.column) return NULL; - char_span line = location_get_source_line (start.file, start.line); + char_span line = location_get_source_line (start); if (!line) return NULL; diff --git a/gcc/c-family/c-indentation.cc b/gcc/c-family/c-indentation.cc index 85a3ae1b303..42738dd4d13 100644 --- a/gcc/c-family/c-indentation.cc +++ b/gcc/c-family/c-indentation.cc @@ -50,7 +50,7 @@ get_visual_column (expanded_location exploc, unsigned int *first_nws, unsigned int tab_width) { - char_span line = location_get_source_line (exploc.file, exploc.line); + char_span line = location_get_source_line (exploc); if (!line) return false; if ((size_t)exploc.column > line.length ()) @@ -87,13 +87,13 @@ get_visual_column (expanded_location exploc, Otherwise, return false, leaving *FIRST_NWS untouched. */ static bool -get_first_nws_vis_column (const char *file, int line_num, +get_first_nws_vis_column (expanded_location exploc, unsigned int *first_nws, unsigned int tab_width) { gcc_assert (first_nws); - char_span line = location_get_source_line (file, line_num); + char_span line = location_get_source_line (exploc); if (!line) return false; unsigned int vis_column = 0; @@ -158,19 +158,18 @@ get_first_nws_vis_column (const char *file, int line_num, Return true if such an unindent/outdent is detected. */ static bool -detect_intervening_unindent (const char *file, - int body_line, +detect_intervening_unindent (expanded_location exploc, int next_stmt_line, unsigned int vis_column, unsigned int tab_width) { - gcc_assert (file); - gcc_assert (next_stmt_line > body_line); + gcc_assert (exploc.file); + gcc_assert (next_stmt_line > exploc.line); - for (int line = body_line + 1; line < next_stmt_line; line++) + while (++exploc.line < next_stmt_line) { unsigned int line_vis_column; - if (get_first_nws_vis_column (file, line, &line_vis_column, tab_width)) + if (get_first_nws_vis_column (exploc, &line_vis_column, tab_width)) if (line_vis_column < vis_column) return true; } @@ -528,8 +527,7 @@ should_warn_for_misleading_indentation (const token_indent_info &guard_tinfo, /* Don't warn if there is an unindent between the two statements. */ int vis_column = MIN (next_stmt_vis_column, body_vis_column); - if (detect_intervening_unindent (body_exploc.file, body_exploc.line, - next_stmt_exploc.line, + if (detect_intervening_unindent (body_exploc, next_stmt_exploc.line, vis_column, tab_width)) return false; @@ -691,12 +689,10 @@ assert_get_visual_column_succeeds (const location &loc, unsigned int expected_visual_column, unsigned int expected_first_nws) { - expanded_location exploc; + expanded_location exploc = {}; exploc.file = file; exploc.line = line; exploc.column = column; - exploc.data = NULL; - exploc.sysp = false; unsigned int actual_visual_column; unsigned int actual_first_nws; bool result = get_visual_column (exploc, @@ -729,12 +725,10 @@ assert_get_visual_column_fails (const location &loc, const char *file, int line, int column, const unsigned int tab_width) { - expanded_location exploc; + expanded_location exploc = {}; exploc.file = file; exploc.line = line; exploc.column = column; - exploc.data = NULL; - exploc.sysp = false; unsigned int actual_visual_column; unsigned int actual_first_nws; bool result = get_visual_column (exploc, diff --git a/gcc/diagnostic-show-locus.cc b/gcc/diagnostic-show-locus.cc index 9d430b5189c..442744f5e0b 100644 --- a/gcc/diagnostic-show-locus.cc +++ b/gcc/diagnostic-show-locus.cc @@ -709,9 +709,9 @@ static layout_range make_range (int start_line, int start_col, int end_line, int end_col) { const expanded_location start_exploc - = {"", start_line, start_col, NULL, false}; + = {"", start_line, start_col, NULL, false, 0, NULL}; const expanded_location finish_exploc - = {"", end_line, end_col, NULL, false}; + = {"", end_line, end_col, NULL, false, 0, NULL}; return layout_range (exploc_with_display_col (start_exploc, def_policy (), LOCATION_ASPECT_START), exploc_with_display_col (finish_exploc, def_policy (), @@ -1614,8 +1614,7 @@ layout::calculate_x_offset_display () return; } - const char_span line = location_get_source_line (m_exploc.file, - m_exploc.line); + const char_span line = location_get_source_line (m_exploc); if (!line) { /* Nothing to do, we couldn't find the source line. */ @@ -2398,17 +2397,18 @@ class line_corrections { public: line_corrections (const char_display_policy &policy, - const char *filename, - linenum_type row) - : m_policy (policy), m_filename (filename), m_row (row) - {} + expanded_location exploc, linenum_type row = 0) + : m_policy (policy), m_exploc (exploc) + { + if (row) + m_exploc.line = row; + } ~line_corrections (); void add_hint (const fixit_hint *hint); const char_display_policy &m_policy; - const char *m_filename; - linenum_type m_row; + expanded_location m_exploc; auto_vec m_corrections; }; @@ -2428,7 +2428,7 @@ line_corrections::~line_corrections () class source_line { public: - source_line (const char *filename, int line); + explicit source_line (expanded_location xloc); char_span as_span () { return char_span (chars, width); } @@ -2438,9 +2438,9 @@ public: /* source_line's ctor. */ -source_line::source_line (const char *filename, int line) +source_line::source_line (expanded_location exploc) { - char_span span = location_get_source_line (filename, line); + char_span span = location_get_source_line (exploc); chars = span.get_buffer (); width = span.length (); } @@ -2482,7 +2482,7 @@ line_corrections::add_hint (const fixit_hint *hint) affected_bytes.start - 1); /* Try to read the source. */ - source_line line (m_filename, m_row); + source_line line (m_exploc); if (line.chars && between.finish < line.width) { /* Consolidate into the last correction: @@ -2538,7 +2538,7 @@ layout::print_trailing_fixits (linenum_type row) { /* Build a list of correction instances for the line, potentially consolidating hints (for the sake of readability). */ - line_corrections corrections (m_policy, m_exploc.file, row); + line_corrections corrections (m_policy, m_exploc, row); for (unsigned int i = 0; i < m_fixit_hints.length (); i++) { const fixit_hint *hint = m_fixit_hints[i]; @@ -2776,7 +2776,7 @@ layout::show_ruler (int max_column) const void layout::print_line (linenum_type row) { - char_span line = location_get_source_line (m_exploc.file, row); + char_span line = location_get_source_line (m_exploc, row); if (!line) return; @@ -2985,10 +2985,10 @@ test_layout_x_offset_display_utf8 (const line_table_case &case_) no multibyte characters earlier on the line. */ const int emoji_col = 102; - temp_source_file tmp (SELFTEST_LOCATION, ".c", content); line_table_test ltt (case_); - - linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 1); + temp_source_file tmp (SELFTEST_LOCATION, ".c", content, 1 + line_bytes, + ltt.m_generated_data); + tmp.do_linemap_add (1); location_t line_end = linemap_position_for_column (line_table, line_bytes); @@ -2996,17 +2996,23 @@ test_layout_x_offset_display_utf8 (const line_table_case &case_) if (line_end > LINE_MAP_MAX_LOCATION_WITH_COLS) return; - ASSERT_STREQ (tmp.get_filename (), LOCATION_FILE (line_end)); + if (ltt.m_generated_data) + { + ASSERT_EQ (nullptr, tmp.get_filename ()); + ASSERT_STREQ (special_fname_generated (), LOCATION_FILE (line_end)); + } + else + ASSERT_STREQ (tmp.get_filename (), LOCATION_FILE (line_end)); ASSERT_EQ (1, LOCATION_LINE (line_end)); ASSERT_EQ (line_bytes, LOCATION_COLUMN (line_end)); - char_span lspan = location_get_source_line (tmp.get_filename (), 1); + const expanded_location xloc = expand_location (line_end); + char_span lspan = location_get_source_line (xloc); ASSERT_EQ (line_display_cols, cpp_display_width (lspan.get_buffer (), lspan.length (), def_policy ())); ASSERT_EQ (line_display_cols, - location_compute_display_column (expand_location (line_end), - def_policy ())); + location_compute_display_column (xloc, def_policy ())); ASSERT_EQ (0, memcmp (lspan.get_buffer () + (emoji_col - 1), "\xf0\x9f\x98\x82\xf0\x9f\x98\x82", 8)); @@ -3138,10 +3144,10 @@ test_layout_x_offset_display_tab (const line_table_case &case_) a space would have taken up. */ ASSERT_EQ (7, extra_width[10]); - temp_source_file tmp (SELFTEST_LOCATION, ".c", content); line_table_test ltt (case_); - - linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 1); + temp_source_file tmp (SELFTEST_LOCATION, ".c", content, line_bytes + 1, + ltt.m_generated_data); + tmp.do_linemap_add (1); location_t line_end = linemap_position_for_column (line_table, line_bytes); @@ -3150,7 +3156,8 @@ test_layout_x_offset_display_tab (const line_table_case &case_) return; /* Check that cpp_display_width handles the tabs as expected. */ - char_span lspan = location_get_source_line (tmp.get_filename (), 1); + const expanded_location xloc = expand_location (line_end); + char_span lspan = location_get_source_line (xloc); ASSERT_EQ ('\t', *(lspan.get_buffer () + (tab_col - 1))); for (int tabstop = 1; tabstop != num_tabstops; ++tabstop) { @@ -3159,8 +3166,7 @@ test_layout_x_offset_display_tab (const line_table_case &case_) cpp_display_width (lspan.get_buffer (), lspan.length (), policy)); ASSERT_EQ (line_bytes + extra_width[tabstop], - location_compute_display_column (expand_location (line_end), - policy)); + location_compute_display_column (xloc, policy)); } /* Check that the tab is expanded to the expected number of spaces. */ @@ -3784,10 +3790,10 @@ test_diagnostic_show_locus_one_liner (const line_table_case &case_) ....................0000000001111111. ....................1234567890123456. */ const char *content = "foo = bar.field;\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); + temp_source_file tmp (SELFTEST_LOCATION, ".c", content, strlen (content), + ltt.m_generated_data); + tmp.do_linemap_add (1); location_t line_end = linemap_position_for_column (line_table, 16); @@ -3795,7 +3801,14 @@ test_diagnostic_show_locus_one_liner (const line_table_case &case_) if (line_end > LINE_MAP_MAX_LOCATION_WITH_COLS) return; - ASSERT_STREQ (tmp.get_filename (), LOCATION_FILE (line_end)); + if (ltt.m_generated_data) + { + ASSERT_EQ (nullptr, tmp.get_filename ()); + ASSERT_STREQ (special_fname_generated (), LOCATION_FILE (line_end)); + } + else + ASSERT_STREQ (tmp.get_filename (), LOCATION_FILE (line_end)); + ASSERT_EQ (1, LOCATION_LINE (line_end)); ASSERT_EQ (16, LOCATION_COLUMN (line_end)); @@ -4366,10 +4379,10 @@ test_diagnostic_show_locus_one_liner_utf8 (const line_table_case &case_) /* 0000000000000000000001111111111111111111222222222222222222222233333 1111222233334444567890122223333456789999000011112222345678999900001 Byte columns. */ - temp_source_file tmp (SELFTEST_LOCATION, ".c", content); line_table_test ltt (case_); - - linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 1); + temp_source_file tmp (SELFTEST_LOCATION, ".c", content, strlen (content), + ltt.m_generated_data); + tmp.do_linemap_add (1); location_t line_end = linemap_position_for_column (line_table, 31); @@ -4377,11 +4390,18 @@ test_diagnostic_show_locus_one_liner_utf8 (const line_table_case &case_) if (line_end > LINE_MAP_MAX_LOCATION_WITH_COLS) return; - ASSERT_STREQ (tmp.get_filename (), LOCATION_FILE (line_end)); + if (ltt.m_generated_data) + { + ASSERT_EQ (nullptr, tmp.get_filename ()); + ASSERT_STREQ (special_fname_generated (), LOCATION_FILE (line_end)); + } + else + ASSERT_STREQ (tmp.get_filename (), LOCATION_FILE (line_end)); + ASSERT_EQ (1, LOCATION_LINE (line_end)); ASSERT_EQ (31, LOCATION_COLUMN (line_end)); - char_span lspan = location_get_source_line (tmp.get_filename (), 1); + char_span lspan = location_get_source_line (expand_location (line_end)); ASSERT_EQ (25, cpp_display_width (lspan.get_buffer (), lspan.length (), def_policy ())); ASSERT_EQ (25, location_compute_display_column (expand_location (line_end), @@ -4418,12 +4438,10 @@ test_add_location_if_nearby (const line_table_case &case_) " double x;\n" /* line 4. */ " double y;\n" /* line 5. */ ";\n"); /* line 6. */ - temp_source_file tmp (SELFTEST_LOCATION, ".c", content); line_table_test ltt (case_); - - const line_map_ordinary *ord_map - = linemap_check_ordinary (linemap_add (line_table, LC_ENTER, false, - tmp.get_filename (), 0)); + temp_source_file tmp (SELFTEST_LOCATION, ".c", content, strlen (content), + ltt.m_generated_data); + const line_map_ordinary *ord_map = tmp.do_linemap_add (0); linemap_line_start (line_table, 1, 100); @@ -4482,12 +4500,10 @@ test_diagnostic_show_locus_fixit_lines (const line_table_case &case_) "\n" /* line 4. */ "\n" /* line 5. */ " : 0.0};\n"); /* line 6. */ - temp_source_file tmp (SELFTEST_LOCATION, ".c", content); line_table_test ltt (case_); - - const line_map_ordinary *ord_map - = linemap_check_ordinary (linemap_add (line_table, LC_ENTER, false, - tmp.get_filename (), 0)); + temp_source_file tmp (SELFTEST_LOCATION, ".c", content, strlen (content), + ltt.m_generated_data); + const line_map_ordinary *ord_map = tmp.do_linemap_add (0); linemap_line_start (line_table, 1, 100); @@ -4578,8 +4594,10 @@ static void test_fixit_consolidation (const line_table_case &case_) { line_table_test ltt (case_); - - linemap_add (line_table, LC_ENTER, false, "test.c", 1); + if (ltt.m_generated_data) + linemap_add (line_table, LC_GEN, false, "some content", 1, 13); + else + linemap_add (line_table, LC_ENTER, false, "test.c", 1); const location_t c10 = linemap_position_for_column (line_table, 10); const location_t c15 = linemap_position_for_column (line_table, 15); @@ -4725,13 +4743,11 @@ test_overlapped_fixit_printing (const line_table_case &case_) ...123456789012345678901234567890123456789. */ const char *content = (" foo *f = (foo *)ptr->field;\n"); - temp_source_file tmp (SELFTEST_LOCATION, ".C", content); line_table_test ltt (case_); + temp_source_file tmp (SELFTEST_LOCATION, ".C", content, strlen (content), + ltt.m_generated_data); - const line_map_ordinary *ord_map - = linemap_check_ordinary (linemap_add (line_table, LC_ENTER, false, - tmp.get_filename (), 0)); - + const line_map_ordinary *ord_map = tmp.do_linemap_add (0); linemap_line_start (line_table, 1, 100); const location_t final_line_end @@ -4752,6 +4768,8 @@ test_overlapped_fixit_printing (const line_table_case &case_) = linemap_position_for_line_and_column (line_table, ord_map, 1, 28); const location_t expr = make_location (expr_start, expr_start, expr_finish); + const expanded_location xloc = expand_location (expr); + /* Various examples of fix-it hints that aren't themselves consolidated, but for which the *printing* may need consolidation. */ @@ -4795,7 +4813,7 @@ test_overlapped_fixit_printing (const line_table_case &case_) /* Add each hint in turn to a line_corrections instance, and verify that they are consolidated into one correction instance as expected. */ - line_corrections lc (policy, tmp.get_filename (), 1); + line_corrections lc (policy, xloc); /* The first replace hint by itself. */ lc.add_hint (hint_0); @@ -4936,13 +4954,10 @@ test_overlapped_fixit_printing_utf8 (const line_table_case &case_) 12344445555666677778901234566667777888899990123456789012333344445 Byte columns. */ - temp_source_file tmp (SELFTEST_LOCATION, ".C", content); line_table_test ltt (case_); - - const line_map_ordinary *ord_map - = linemap_check_ordinary (linemap_add (line_table, LC_ENTER, false, - tmp.get_filename (), 0)); - + temp_source_file tmp (SELFTEST_LOCATION, ".C", content, strlen (content), + ltt.m_generated_data); + const line_map_ordinary *ord_map = tmp.do_linemap_add (0); linemap_line_start (line_table, 1, 100); const location_t final_line_end @@ -4963,6 +4978,8 @@ test_overlapped_fixit_printing_utf8 (const line_table_case &case_) = linemap_position_for_line_and_column (line_table, ord_map, 1, 34); const location_t expr = make_location (expr_start, expr_start, expr_finish); + const expanded_location xloc = expand_location (expr); + /* Various examples of fix-it hints that aren't themselves consolidated, but for which the *printing* may need consolidation. */ @@ -5011,7 +5028,7 @@ test_overlapped_fixit_printing_utf8 (const line_table_case &case_) /* Add each hint in turn to a line_corrections instance, and verify that they are consolidated into one correction instance as expected. */ - line_corrections lc (policy, tmp.get_filename (), 1); + line_corrections lc (policy, xloc); /* The first replace hint by itself. */ lc.add_hint (hint_0); @@ -5169,13 +5186,11 @@ test_overlapped_fixit_printing_2 (const line_table_case &case_) ...123456789012345678901234567890123456789. */ const char *content = ("int a5[][0][0] = { 1, 2 };\n"); - temp_source_file tmp (SELFTEST_LOCATION, ".c", content); - line_table_test ltt (case_); - - const line_map_ordinary *ord_map - = linemap_check_ordinary (linemap_add (line_table, LC_ENTER, false, - tmp.get_filename (), 0)); + line_table_test ltt (case_); + temp_source_file tmp (SELFTEST_LOCATION, ".c", content, strlen (content), + ltt.m_generated_data); + const line_map_ordinary *ord_map = tmp.do_linemap_add (0); linemap_line_start (line_table, 1, 100); const location_t final_line_end @@ -5260,10 +5275,10 @@ test_fixit_insert_containing_newline (const line_table_case &case_) " x = a;\n" /* line 2. */ " case 'b':\n" /* line 3. */ " x = b;\n");/* line 4. */ - - temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content); line_table_test ltt (case_); - linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 3); + temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content, + strlen (old_content), false); + tmp.do_linemap_add (3); location_t case_start = linemap_position_for_column (line_table, 5); location_t case_finish = linemap_position_for_column (line_table, 13); @@ -5331,12 +5346,11 @@ test_fixit_insert_containing_newline_2 (const line_table_case &case_) "{\n" /* line 2. */ " putchar (ch);\n" /* line 3. */ "}\n"); /* line 4. */ - - temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content); line_table_test ltt (case_); + temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content, + strlen (old_content), ltt.m_generated_data); - const line_map_ordinary *ord_map = linemap_check_ordinary - (linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 0)); + const line_map_ordinary *ord_map = tmp.do_linemap_add (0); linemap_line_start (line_table, 1, 100); /* The primary range is the "putchar" token. */ @@ -5395,9 +5409,10 @@ test_fixit_replace_containing_newline (const line_table_case &case_) .........................1234567890123. */ const char *old_content = "foo = bar ();\n"; - temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content); line_table_test ltt (case_); - linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 1); + temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content, + strlen (old_content), ltt.m_generated_data); + tmp.do_linemap_add (1); /* Replace the " = " with "\n = ", as if we were reformatting an overly long line. */ @@ -5435,10 +5450,10 @@ test_fixit_deletion_affecting_newline (const line_table_case &case_) const char *old_content = ("foo = bar (\n" " );\n"); - temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content); line_table_test ltt (case_); - const line_map_ordinary *ord_map = linemap_check_ordinary - (linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 0)); + temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content, + strlen (old_content), ltt.m_generated_data); + const line_map_ordinary *ord_map = tmp.do_linemap_add (0); linemap_line_start (line_table, 1, 100); /* Attempt to delete the " (\n...)". */ @@ -5487,9 +5502,10 @@ test_tab_expansion (const line_table_case &case_) const int last_byte_col = 25; ASSERT_EQ (35, cpp_display_width (content, last_byte_col, policy)); - temp_source_file tmp (SELFTEST_LOCATION, ".c", content); line_table_test ltt (case_); - linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 1); + temp_source_file tmp (SELFTEST_LOCATION, ".c", content, strlen (content), + ltt.m_generated_data); + tmp.do_linemap_add (1); /* Don't attempt to run the tests if column data might be unavailable. */ location_t line_end = linemap_position_for_column (line_table, last_byte_col); @@ -5536,15 +5552,14 @@ test_escaping_bytes_1 (const line_table_case &case_) { const char content[] = "before\0\1\2\3\v\x80\xff""after\n"; const size_t sz = sizeof (content); - temp_source_file tmp (SELFTEST_LOCATION, ".c", content, sz); line_table_test ltt (case_); - const line_map_ordinary *ord_map = linemap_check_ordinary - (linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 0)); + temp_source_file tmp (SELFTEST_LOCATION, ".c", content, sz, + ltt.m_generated_data); + const line_map_ordinary *ord_map = tmp.do_linemap_add (0); linemap_line_start (line_table, 1, 100); location_t finish - = linemap_position_for_line_and_column (line_table, ord_map, 1, - strlen (content)); + = linemap_position_for_line_and_column (line_table, ord_map, 1, sz); if (finish > LINE_MAP_MAX_LOCATION_WITH_COLS) return; @@ -5592,15 +5607,14 @@ test_escaping_bytes_2 (const line_table_case &case_) { const char content[] = "\0after\n"; const size_t sz = sizeof (content); - temp_source_file tmp (SELFTEST_LOCATION, ".c", content, sz); line_table_test ltt (case_); - const line_map_ordinary *ord_map = linemap_check_ordinary - (linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 0)); + temp_source_file tmp (SELFTEST_LOCATION, ".c", content, sz, + ltt.m_generated_data); + const line_map_ordinary *ord_map = tmp.do_linemap_add (0); linemap_line_start (line_table, 1, 100); location_t finish - = linemap_position_for_line_and_column (line_table, ord_map, 1, - strlen (content)); + = linemap_position_for_line_and_column (line_table, ord_map, 1, sz); if (finish > LINE_MAP_MAX_LOCATION_WITH_COLS) return; @@ -5652,8 +5666,7 @@ test_line_numbers_multiline_range () temp_source_file tmp (SELFTEST_LOCATION, ".txt", pp_formatted_text (&pp)); line_table_test ltt; - const line_map_ordinary *ord_map = linemap_check_ordinary - (linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 0)); + const line_map_ordinary *ord_map = tmp.do_linemap_add (0); linemap_line_start (line_table, 1, 100); /* Create a multi-line location, starting at the "line" of line 9, with @@ -5694,28 +5707,28 @@ diagnostic_show_locus_cc_tests () test_display_widths (); - for_each_line_table_case (test_layout_x_offset_display_utf8); - for_each_line_table_case (test_layout_x_offset_display_tab); + for_each_line_table_case (test_layout_x_offset_display_utf8, true); + for_each_line_table_case (test_layout_x_offset_display_tab, true); test_get_line_bytes_without_trailing_whitespace (); test_diagnostic_show_locus_unknown_location (); - for_each_line_table_case (test_diagnostic_show_locus_one_liner); - for_each_line_table_case (test_diagnostic_show_locus_one_liner_utf8); - for_each_line_table_case (test_add_location_if_nearby); - for_each_line_table_case (test_diagnostic_show_locus_fixit_lines); - for_each_line_table_case (test_fixit_consolidation); - for_each_line_table_case (test_overlapped_fixit_printing); - for_each_line_table_case (test_overlapped_fixit_printing_utf8); - for_each_line_table_case (test_overlapped_fixit_printing_2); - for_each_line_table_case (test_fixit_insert_containing_newline); - for_each_line_table_case (test_fixit_insert_containing_newline_2); - for_each_line_table_case (test_fixit_replace_containing_newline); - for_each_line_table_case (test_fixit_deletion_affecting_newline); - for_each_line_table_case (test_tab_expansion); - for_each_line_table_case (test_escaping_bytes_1); - for_each_line_table_case (test_escaping_bytes_2); + for_each_line_table_case (test_diagnostic_show_locus_one_liner, true); + for_each_line_table_case (test_diagnostic_show_locus_one_liner_utf8, true); + for_each_line_table_case (test_add_location_if_nearby, true); + for_each_line_table_case (test_diagnostic_show_locus_fixit_lines, true); + for_each_line_table_case (test_fixit_consolidation, true); + for_each_line_table_case (test_overlapped_fixit_printing, true); + for_each_line_table_case (test_overlapped_fixit_printing_utf8, true); + for_each_line_table_case (test_overlapped_fixit_printing_2, true); + for_each_line_table_case (test_fixit_insert_containing_newline, true); + for_each_line_table_case (test_fixit_insert_containing_newline_2, true); + for_each_line_table_case (test_fixit_replace_containing_newline, true); + for_each_line_table_case (test_fixit_deletion_affecting_newline, true); + for_each_line_table_case (test_tab_expansion, true); + for_each_line_table_case (test_escaping_bytes_1, true); + for_each_line_table_case (test_escaping_bytes_2, true); test_line_numbers_multiline_range (); } diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc index 7c7ee6da746..164b4206b41 100644 --- a/gcc/diagnostic.cc +++ b/gcc/diagnostic.cc @@ -771,13 +771,15 @@ diagnostic_report_current_module (diagnostic_context *context, location_t where) if (!includes_seen (context, map)) { bool first = true, need_inc = true, was_module = MAP_MODULE_P (map); + const bool was_gen = (map->reason == LC_GEN); expanded_location s = {}; do { where = linemap_included_from (map); map = linemap_included_from_linemap (line_table, map); bool is_module = MAP_MODULE_P (map); - s.file = LINEMAP_FILE (map); + s.file = (map->reason == LC_GEN + ? special_fname_generated () : LINEMAP_FILE (map)); s.line = SOURCE_LINE (map, where); int col = -1; if (first && context->show_column) @@ -796,10 +798,13 @@ diagnostic_report_current_module (diagnostic_context *context, location_t where) N_("of module"), N_("In module imported at"), /* 6 */ N_("imported at"), + N_("In buffer generated from"), /* 8 */ }; - unsigned index = (was_module ? 6 : is_module ? 4 - : need_inc ? 2 : 0) + !first; + const unsigned index + = was_gen ? 8 + : ((was_module ? 6 : is_module ? 4 : need_inc ? 2 : 0) + + !first); pp_verbatim (context->printer, "%s%s %r%s%s%R", first ? "" : was_module ? ", " : ",\n", @@ -2573,12 +2578,10 @@ assert_location_text (const char *expected_loc_text, dc.column_unit = column_unit; dc.column_origin = origin; - expanded_location xloc; + expanded_location xloc = {}; xloc.file = filename; xloc.line = line; xloc.column = column; - xloc.data = NULL; - xloc.sysp = false; char *actual_loc_text = diagnostic_get_location_text (&dc, xloc); ASSERT_STREQ (expected_loc_text, actual_loc_text); diff --git a/gcc/gcc-rich-location.cc b/gcc/gcc-rich-location.cc index 0fa4239bd29..4836624f03c 100644 --- a/gcc/gcc-rich-location.cc +++ b/gcc/gcc-rich-location.cc @@ -78,7 +78,7 @@ static bool blank_line_before_p (location_t loc) { expanded_location exploc = expand_location (loc); - char_span line = location_get_source_line (exploc.file, exploc.line); + char_span line = location_get_source_line (exploc); if (!line) return false; if (line.length () < (size_t)exploc.column) diff --git a/gcc/input.cc b/gcc/input.cc index 483cb6e940d..3cf5480551d 100644 --- a/gcc/input.cc +++ b/gcc/input.cc @@ -35,6 +35,12 @@ special_fname_builtin () return _(""); } +const char * +special_fname_generated () +{ + return _(""); +} + /* Input charset configuration. */ static const char *default_charset_callback (const char *) { @@ -58,7 +64,7 @@ public: ~file_cache_slot (); bool read_line_num (size_t line_num, - char ** line, ssize_t *line_len); + const char **line, ssize_t *line_len); /* Accessors. */ const char *get_file_path () const { return m_file_path; } @@ -71,7 +77,8 @@ public: void inc_use_count () { m_use_count++; } bool create (const file_cache::input_context &in_context, - const char *file_path, FILE *fp, unsigned highest_use_count); + const char *file_path, FILE *fp, unsigned highest_use_count, + unsigned int generated_data_len); void evict (); private: @@ -106,8 +113,8 @@ public: void maybe_grow (); bool read_data (); bool maybe_read_data (); - bool get_next_line (char **line, ssize_t *line_len); - bool read_next_line (char ** line, ssize_t *line_len); + bool get_next_line (const char **line, ssize_t *line_len); + bool read_next_line (const char **line, ssize_t *line_len); bool goto_next_line (); static const size_t buffer_size = 4 * 1024; @@ -126,10 +133,16 @@ public: FILE *m_fp; - /* This points to the content of the file that we've read so - far. */ + /* This is a buffer owned by this object, holding the content of the file + that we've read so far. */ char *m_data; + /* This is the current buffer from which to obtain data. It is usually + equal to m_data, except when we are handling internally generated + content that already lives in memory and does not require a separate + buffer here. */ + const char *m_data_active; + /* The allocated buffer to be freed may start a little earlier than DATA, e.g. if a UTF8 BOM was skipped at the beginning. */ int m_alloc_offset; @@ -179,6 +192,7 @@ public: gcc_assert (m_data); m_alloc_offset += offset; m_data += offset; + m_data_active = m_data; m_size -= offset; } @@ -282,6 +296,8 @@ expand_location_1 (location_t loc, xloc.data = block; if (loc <= BUILTINS_LOCATION) xloc.file = loc == UNKNOWN_LOCATION ? NULL : special_fname_builtin (); + else if (xloc.generated_data_len) + xloc.file = special_fname_generated (); return xloc; } @@ -445,16 +461,23 @@ file_cache::evicted_cache_tab_entry (unsigned *highest_use_count) num_file_slots files are cached. */ file_cache_slot* -file_cache::add_file (const char *file_path) +file_cache::add_file (const char *file_path, unsigned int generated_data_len) { - FILE *fp = fopen (file_path, "r"); - if (fp == NULL) - return NULL; + FILE *fp; + if (generated_data_len) + fp = NULL; + else + { + fp = fopen (file_path, "r"); + if (fp == NULL) + return NULL; + } unsigned highest_use_count = 0; file_cache_slot *r = evicted_cache_tab_entry (&highest_use_count); - if (!r->create (in_context, file_path, fp, highest_use_count)) + if (!r->create (in_context, file_path, fp, highest_use_count, + generated_data_len)) return NULL; return r; } @@ -465,14 +488,13 @@ file_cache::add_file (const char *file_path) bool file_cache_slot::create (const file_cache::input_context &in_context, const char *file_path, FILE *fp, - unsigned highest_use_count) + unsigned highest_use_count, + unsigned int generated_data_len) { m_file_path = file_path; if (m_fp) fclose (m_fp); m_fp = fp; - if (m_alloc_offset) - offset_buffer (-m_alloc_offset); m_nb_read = 0; m_line_start_idx = 0; m_line_num = 0; @@ -480,9 +502,23 @@ file_cache_slot::create (const file_cache::input_context &in_context, /* Ensure that this cache entry doesn't get evicted next time add_file_to_cache_tab is called. */ m_use_count = ++highest_use_count; - m_total_lines = total_lines_num (file_path); m_missing_trailing_newline = true; + /* If this is generated data, then file_path points to it and we temporarily + source from there rather than from our own m_data buffer. */ + if (!m_fp) + { + gcc_assert (generated_data_len); + m_data_active = file_path; + m_nb_read = generated_data_len; + m_total_lines = 0; + return true; + } + + m_data_active = m_data; + m_total_lines = total_lines_num (file_path); + if (m_alloc_offset) + offset_buffer (-m_alloc_offset); /* Check the input configuration to determine if we need to do any transformations, such as charset conversion or BOM skipping. */ @@ -497,7 +533,7 @@ file_cache_slot::create (const file_cache::input_context &in_context, return false; if (m_data) XDELETEVEC (m_data); - m_data = cs.data; + m_data_active = m_data = cs.data; m_nb_read = m_size = cs.len; m_alloc_offset = cs.data - cs.to_free; } @@ -535,11 +571,12 @@ file_cache::~file_cache () it. */ file_cache_slot* -file_cache::lookup_or_add_file (const char *file_path) +file_cache::lookup_or_add_file (const char *file_path, + unsigned int generated_data_len) { file_cache_slot *r = lookup_file (file_path); if (r == NULL) - r = add_file (file_path); + r = add_file (file_path, generated_data_len); return r; } @@ -547,7 +584,8 @@ file_cache::lookup_or_add_file (const char *file_path) diagnostic. */ file_cache_slot::file_cache_slot () -: m_use_count (0), m_file_path (NULL), m_fp (NULL), m_data (0), +: m_use_count (0), m_file_path (NULL), m_fp (NULL), + m_data (0), m_data_active (0), m_alloc_offset (0), m_size (0), m_nb_read (0), m_line_start_idx (0), m_line_num (0), m_total_lines (0), m_missing_trailing_newline (true) { @@ -599,6 +637,8 @@ file_cache_slot::needs_grow_p () const void file_cache_slot::maybe_grow () { + gcc_checking_assert (m_data_active == m_data); + if (!needs_grow_p ()) return; @@ -616,6 +656,8 @@ file_cache_slot::maybe_grow () m_data = XRESIZEVEC (char, m_data, m_size); offset_buffer (offset); } + + m_data_active = m_data; } /* Read more data into the cache. Extends the cache if need be. @@ -624,6 +666,8 @@ file_cache_slot::maybe_grow () bool file_cache_slot::read_data () { + gcc_checking_assert (m_data_active == m_data); + if (feof (m_fp) || ferror (m_fp)) return false; @@ -657,8 +701,8 @@ file_cache_slot::maybe_read_data () terminator was not found. We need to determine line endings in the same manner that libcpp does: any of \n, \r\n, or \r is a line ending. */ -static char * -find_end_of_line (char *s, size_t len) +static const char * +find_end_of_line (const char *s, size_t len) { for (const auto end = s + len; s != end; ++s) { @@ -694,7 +738,7 @@ find_end_of_line (char *s, size_t len) make the content of *LINE invalid. */ bool -file_cache_slot::get_next_line (char **line, ssize_t *line_len) +file_cache_slot::get_next_line (const char **line, ssize_t *line_len) { /* Fill the cache with data to process. */ maybe_read_data (); @@ -704,18 +748,18 @@ file_cache_slot::get_next_line (char **line, ssize_t *line_len) /* There is no more data to process. */ return false; - char *line_start = m_data + m_line_start_idx; + const char *line_start = m_data_active + m_line_start_idx; - char *next_line_start = NULL; + const char *next_line_start = NULL; size_t len = 0; - char *line_end = find_end_of_line (line_start, remaining_size); + const char *line_end = find_end_of_line (line_start, remaining_size); if (line_end == NULL) { /* We haven't found an end-of-line delimiter in the cache. Fill the cache with more data from the file and look again. */ while (maybe_read_data ()) { - line_start = m_data + m_line_start_idx; + line_start = m_data_active + m_line_start_idx; remaining_size = m_nb_read - m_line_start_idx; line_end = find_end_of_line (line_start, remaining_size); if (line_end != NULL) @@ -734,7 +778,7 @@ file_cache_slot::get_next_line (char **line, ssize_t *line_len) If the file ends in a \r, we didn't identify it as a line terminator above, so do that now instead. */ - line_end = m_data + m_nb_read; + line_end = m_data_active + m_nb_read; if (m_nb_read && line_end[-1] == '\r') { --line_end; @@ -785,7 +829,7 @@ file_cache_slot::get_next_line (char **line, ssize_t *line_len) m_line_record.safe_push (file_cache_slot::line_info (m_line_num, m_line_start_idx, - line_end - m_data)); + line_end - m_data_active)); else if (m_total_lines > line_record_size) { /* ... otherwise, we just scale total_lines down to @@ -796,14 +840,14 @@ file_cache_slot::get_next_line (char **line, ssize_t *line_len) m_line_record.safe_push (file_cache_slot::line_info (m_line_num, m_line_start_idx, - line_end - m_data)); + line_end - m_data_active)); } } /* Update m_line_start_idx so that it points to the next line to be read. */ if (next_line_start) - m_line_start_idx = next_line_start - m_data; + m_line_start_idx = next_line_start - m_data_active; else /* We didn't find any terminal '\n'. Let's consider that the end of line is the end of the data in the cache. The next @@ -826,7 +870,7 @@ file_cache_slot::get_next_line (char **line, ssize_t *line_len) bool file_cache_slot::goto_next_line () { - char *l; + const char *l; ssize_t len; return get_next_line (&l, &len); @@ -841,7 +885,7 @@ file_cache_slot::goto_next_line () bool file_cache_slot::read_line_num (size_t line_num, - char ** line, ssize_t *line_len) + const char **line, ssize_t *line_len) { gcc_assert (line_num > 0); @@ -894,7 +938,7 @@ file_cache_slot::read_line_num (size_t line_num, if (i && i->line_num == line_num) { /* We have the start/end of the line. */ - *line = m_data + i->start_pos; + *line = m_data_active + i->start_pos; *line_len = i->end_pos - i->start_pos; return true; } @@ -931,30 +975,49 @@ file_cache_slot::read_line_num (size_t line_num, If the function fails, a NULL char_span is returned. */ char_span -location_get_source_line (const char *file_path, int line) +location_get_source_line (expanded_location xloc, int line) { - char *buffer = NULL; - ssize_t len; + xloc.line = line; - if (line == 0) + if (xloc.line == 0) return char_span (NULL, 0); - if (file_path == NULL) + if (xloc.file == NULL) return char_span (NULL, 0); diagnostic_file_cache_init (); - file_cache_slot *c = global_dc->m_file_cache->lookup_or_add_file (file_path); + file_cache_slot *c = global_dc->m_file_cache->lookup_or_add_file + (xloc.generated_data ? xloc.generated_data : xloc.file, + xloc.generated_data_len); + if (c == NULL) return char_span (NULL, 0); - bool read = c->read_line_num (line, &buffer, &len); + const char *buffer = NULL; + ssize_t len; + bool read = c->read_line_num (xloc.line, &buffer, &len); if (!read) return char_span (NULL, 0); return char_span (buffer, len); } +char_span +location_get_source_line (expanded_location xloc) +{ + return location_get_source_line (xloc, xloc.line); +} + +char_span +location_get_source_line (const char *file_path, int line) +{ + expanded_location xloc = {}; + xloc.file = file_path; + xloc.line = line; + return location_get_source_line (xloc); +} + /* Determine if FILE_PATH missing a trailing newline on its final line. Only valid to call once all of the file has been loaded, by requesting a line number beyond the end of the file. */ @@ -964,7 +1027,8 @@ location_missing_trailing_newline (const char *file_path) { diagnostic_file_cache_init (); - file_cache_slot *c = global_dc->m_file_cache->lookup_or_add_file (file_path); + file_cache_slot *c + = global_dc->m_file_cache->lookup_or_add_file (file_path, 0); if (c == NULL) return false; @@ -1110,9 +1174,10 @@ int location_compute_display_column (expanded_location exploc, const cpp_char_column_policy &policy) { - if (!(exploc.file && *exploc.file && exploc.line && exploc.column)) + if (!(exploc.file && (exploc.generated_data_len || *exploc.file) + && exploc.line && exploc.column)) return exploc.column; - char_span line = location_get_source_line (exploc.file, exploc.line); + char_span line = location_get_source_line (exploc); /* If line is NULL, this function returns exploc.column which is the desired fallback. */ return cpp_byte_column_to_display_column (line.get_buffer (), line.length (), @@ -1298,6 +1363,9 @@ dump_location_info (FILE *stream) case LC_ENTER_MACRO: reason = "LC_RENAME_MACRO"; break; + case LC_GEN: + reason = "LC_GEN"; + break; default: reason = "Unknown"; } @@ -1327,8 +1395,7 @@ dump_location_info (FILE *stream) { /* Beginning of a new source line: draw the line. */ - char_span line_text = location_get_source_line (exploc.file, - exploc.line); + char_span line_text = location_get_source_line (exploc); if (!line_text) break; fprintf (stream, @@ -1655,7 +1722,7 @@ get_substring_ranges_for_loc (cpp_reader *pfile, if (start.column > finish.column) return "range endpoints are reversed"; - char_span line = location_get_source_line (start.file, start.line); + char_span line = location_get_source_line (start); if (!line) return "unable to read source line"; @@ -1871,6 +1938,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. */ @@ -1949,13 +2030,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 @@ -1972,6 +2056,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 @@ -1993,6 +2078,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. */ @@ -2012,7 +2098,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); @@ -2062,21 +2151,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); @@ -2123,10 +2214,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); @@ -3783,7 +3875,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 @@ -3802,16 +3895,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 @@ -3822,7 +3918,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); @@ -3965,9 +4061,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/input.h b/gcc/input.h index 0b23e66e53b..c5a7b69400f 100644 --- a/gcc/input.h +++ b/gcc/input.h @@ -34,6 +34,7 @@ extern GTY(()) class line_maps *saved_line_table; /* Returns the translated string referring to the special location. */ const char *special_fname_builtin (); +const char *special_fname_generated (); /* line-map.cc reserves RESERVED_LOCATION_COUNT to the user. Ensure both UNKNOWN_LOCATION and BUILTINS_LOCATION fit into that. */ @@ -114,6 +115,10 @@ class char_span }; extern char_span location_get_source_line (const char *file_path, int line); +/* The version taking an exploc handles generated source too, and should be used + whenever possible. */ +extern char_span location_get_source_line (expanded_location exploc); +extern char_span location_get_source_line (expanded_location exploc, int line); extern bool location_missing_trailing_newline (const char *file_path); @@ -136,7 +141,8 @@ class file_cache file_cache (); ~file_cache (); - file_cache_slot *lookup_or_add_file (const char *file_path); + file_cache_slot *lookup_or_add_file (const char *file_path, + unsigned int generated_data_len); void forcibly_evict_file (const char *file_path); /* See comments in diagnostic.h about the input conversion context. */ @@ -150,7 +156,8 @@ class file_cache private: file_cache_slot *evicted_cache_tab_entry (unsigned *highest_use_count); - file_cache_slot *add_file (const char *file_path); + file_cache_slot *add_file (const char *file_path, + unsigned int generated_data_len); file_cache_slot *lookup_file (const char *file_path); private: diff --git a/gcc/selftest.cc b/gcc/selftest.cc index 89abfba5e80..179a41bde1c 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,37 @@ 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 () +{ + XDELETEVEC (content_buf); } /* Avoid introducing locale-specific differences in the results diff --git a/gcc/selftest.h b/gcc/selftest.h index 7568a6d24d4..ab1c9025349 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,10 +98,9 @@ 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; } - private: char *m_filename; }; @@ -113,7 +114,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 +178,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 +194,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. diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c index baa6b629b83..29e653625f8 100644 --- a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c +++ b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c @@ -430,7 +430,7 @@ test_show_locus (function *fun) to upper case. Give all of the ranges labels (sharing one label). */ if (0 == strcmp (fnname, "test_many_nested_locations")) { - const char *file = LOCATION_FILE (fnstart); + const expanded_location xloc = expand_location (fnstart); const int start_line = fnstart_line + 2; const int finish_line = start_line + 7; location_t loc = get_loc (start_line - 1, 2); @@ -438,7 +438,7 @@ test_show_locus (function *fun) rich_location richloc (line_table, loc); for (int line = start_line; line <= finish_line; line++) { - char_span content = location_get_source_line (file, line); + char_span content = location_get_source_line (xloc, line); gcc_assert (content); /* Split line up into words. */ for (int idx = 0; idx < content.length (); idx++) diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h index 50207cacc12..eb281809cbd 100644 --- a/libcpp/include/line-map.h +++ b/libcpp/include/line-map.h @@ -75,6 +75,8 @@ enum lc_reason LC_RENAME_VERBATIM, /* Likewise, but "" != stdin. */ LC_ENTER_MACRO, /* Begin macro expansion. */ LC_MODULE, /* A (C++) Module. */ + LC_GEN, /* Internally generated source. */ + /* FIXME: add support for stringize and paste. */ LC_HWM /* High Water Mark. */ }; @@ -437,7 +439,11 @@ struct GTY((tag ("1"))) line_map_ordinary : public line_map { /* Pointer alignment boundary on both 32 and 64-bit systems. */ - const char *to_file; + /* This GTY markup is in case this is an LC_GEN map, in which case + to_file actually points to the generated data, which we do not + want to require to be free of null bytes. */ + const char * GTY((string_length ("%h.to_file_len"))) to_file; + unsigned int to_file_len; linenum_type to_line; /* Location from whence this line map was included. For regular @@ -1101,13 +1107,15 @@ extern line_map *line_map_new_raw (line_maps *, bool, unsigned); at least as long as the lifetime of SET. An empty TO_FILE means standard input. If reason is LC_LEAVE, and TO_FILE is NULL, then TO_FILE, TO_LINE and SYSP are given their - natural values considering the file we are returning to. + natural values considering the file we are returning to. If reason + is LC_GEN, then TO_FILE is not a file name, but rather the actual + content, and TO_FILE_LEN>0 is the length of it. A call to this function can relocate the previous set of maps, so any stored line_map pointers should not be used. */ extern const line_map *linemap_add (class line_maps *, enum lc_reason, unsigned int sysp, - const char *to_file, linenum_type to_line); + const char *to_file, linenum_type to_line, unsigned int to_file_len = 0); /* Create a macro map. A macro map encodes source locations of tokens that are part of a macro replacement-list, at a macro expansion @@ -1304,7 +1312,8 @@ linemap_location_before_p (class line_maps *set, typedef struct { - /* The name of the source file involved. */ + /* The name of the source file involved, or NULL if + generated_data is non-NULL. */ const char *file; /* The line-location in the source file. */ @@ -1316,6 +1325,10 @@ typedef struct /* In a system header?. */ bool sysp; + + /* If generated data, the data and its length. */ + unsigned int generated_data_len; + const char *generated_data; } expanded_location; class range_label; diff --git a/libcpp/line-map.cc b/libcpp/line-map.cc index 50e8043255e..2838d1103b0 100644 --- a/libcpp/line-map.cc +++ b/libcpp/line-map.cc @@ -513,13 +513,18 @@ LAST_SOURCE_LINE_LOCATION (const line_map_ordinary *map) TO_FILE is NULL, then TO_FILE, TO_LINE and SYSP are given their natural values considering the file we are returning to. + If reason is LC_GEN, then to_file is not a file name, but is + rather the actual generated content, and TO_FILE_LEN > 0 is the number + of bytes it contains. Otherwise TO_FILE_LEN should be set to 0. + FROM_LINE should be monotonic increasing across calls to this function. A call to this function can relocate the previous set of maps, so any stored line_map pointers should not be used. */ const struct line_map * linemap_add (line_maps *set, enum lc_reason reason, - unsigned int sysp, const char *to_file, linenum_type to_line) + unsigned int sysp, const char *to_file, linenum_type to_line, + unsigned int to_file_len) { /* Generate a start_location above the current highest_location. If possible, make the low range bits be zero. */ @@ -535,8 +540,20 @@ linemap_add (line_maps *set, enum lc_reason reason, >= MAP_START_LOCATION (LINEMAPS_LAST_ORDINARY_MAP (set)))); /* When we enter the file for the first time reason cannot be - LC_RENAME. */ - linemap_assert (!(set->depth == 0 && reason == LC_RENAME)); + LC_RENAME. To keep things simple, don't track LC_RENAME for + LC_GEN maps, but just keep their reason as always LC_GEN. */ + if (reason == LC_RENAME) + { + linemap_assert (set->depth != 0); + const auto prev = LINEMAPS_LAST_ORDINARY_MAP (set); + linemap_assert (prev); + if (prev->reason == LC_GEN) + { + reason = LC_GEN; + to_file = prev->to_file; + to_file_len = prev->to_file_len; + } + } /* If we are leaving the main file, return a NULL map. */ if (reason == LC_LEAVE @@ -557,7 +574,8 @@ linemap_add (line_maps *set, enum lc_reason reason, = linemap_check_ordinary (new_linemap (set, start_location)); map->reason = reason; - if (to_file && *to_file == '\0' && reason != LC_RENAME_VERBATIM) + if (to_file && *to_file == '\0' && reason != LC_RENAME_VERBATIM + && reason != LC_GEN) to_file = ""; if (reason == LC_RENAME_VERBATIM) @@ -591,6 +609,15 @@ linemap_add (line_maps *set, enum lc_reason reason, map->sysp = sysp; map->to_file = to_file; + + if (reason == LC_GEN) + { + gcc_assert (to_file_len); + map->to_file_len = to_file_len; + } + else + map->to_file_len = (to_file_len ? to_file_len : strlen (to_file) + 1); + map->to_line = to_line; LINEMAPS_ORDINARY_CACHE (set) = LINEMAPS_ORDINARY_USED (set) - 1; /* Do not store range_bits here. That's readjusted in @@ -606,7 +633,7 @@ linemap_add (line_maps *set, enum lc_reason reason, pure_location_p. */ linemap_assert (pure_location_p (set, start_location)); - if (reason == LC_ENTER) + if (reason == LC_ENTER || reason == LC_GEN) { if (set->depth == 0) map->included_from = 0; @@ -617,7 +644,7 @@ linemap_add (line_maps *set, enum lc_reason reason, & ~((1 << map[-1].m_column_and_range_bits) - 1)) + map[-1].start_location); set->depth++; - if (set->trace_includes) + if (set->trace_includes && reason == LC_ENTER) trace_include (set, map); } else if (reason == LC_RENAME) @@ -864,7 +891,7 @@ linemap_line_start (line_maps *set, linenum_type to_line, (linemap_add (set, LC_RENAME, ORDINARY_MAP_IN_SYSTEM_HEADER_P (map), ORDINARY_MAP_FILE_NAME (map), - to_line))); + to_line, map->to_file_len))); map->m_column_and_range_bits = column_bits; map->m_range_bits = range_bits; r = (MAP_START_LOCATION (map) @@ -1853,8 +1880,14 @@ linemap_expand_location (line_maps *set, abort (); const line_map_ordinary *ord_map = linemap_check_ordinary (map); + if (ord_map->reason == LC_GEN) + { + xloc.generated_data = ord_map->to_file; + xloc.generated_data_len = ord_map->to_file_len; + } + else + xloc.file = LINEMAP_FILE (ord_map); - xloc.file = LINEMAP_FILE (ord_map); xloc.line = SOURCE_LINE (ord_map, loc); xloc.column = SOURCE_COLUMN (ord_map, loc); xloc.sysp = LINEMAP_SYSP (ord_map) != 0; @@ -1873,7 +1906,7 @@ linemap_dump (FILE *stream, class line_maps *set, unsigned ix, bool is_macro) { const char *const lc_reasons_v[LC_HWM] = { "LC_ENTER", "LC_LEAVE", "LC_RENAME", "LC_RENAME_VERBATIM", - "LC_ENTER_MACRO", "LC_MODULE" }; + "LC_ENTER_MACRO", "LC_MODULE", "LC_GEN" }; const line_map *map; unsigned reason;