aboutsummaryrefslogtreecommitdiff
path: root/libcpp
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@acm.org>2020-07-07 11:28:59 -0700
committerNathan Sidwell <nathan@acm.org>2020-07-07 11:40:04 -0700
commit6bf2ff0d52a90acdc54f18c75d1978f6b4de4609 (patch)
tree9b411964bcaef7d64711f4ebd372e095be34adca /libcpp
parent6f9c9ea40a1e937ea1b549625cf7762d4a8a2078 (diff)
downloadgcc-6bf2ff0d52a90acdc54f18c75d1978f6b4de4609.zip
gcc-6bf2ff0d52a90acdc54f18c75d1978f6b4de4609.tar.gz
gcc-6bf2ff0d52a90acdc54f18c75d1978f6b4de4609.tar.bz2
preprocessor: Better line info for <builtin> & <command-line>
With C++ module header units it becomes important to distinguish between macros defined in forced headers (& commandline & builtins) from those defined in the header file being processed. We weren't making that easy because we treated the builtins and command-line locations somewhat file-like, with incrementing line numbers, and showing them as included from line 1 of the main file. This patch does 3 things: 0) extend the idiom that 'line 0' of a file means 'the file as a whole' 1) builtins and command-line macros are shown as-if included from line zero. 2) when emitting preprocessed output we keep resetting the line number so that re-reading that preprocessed output will get the same set of locations for the command line etc. For instance the new c-c++-common/cpp/line-2.c test, now emits In file included from <command-line>: ./line-2.h:4:2: error: #error wrong 4 | #error wrong | ^~~~~ line-2.c:3:11: error: macro "bill" passed 1 arguments, but takes just 0 3 | int bill(1); | ^ In file included from <command-line>: ./line-2.h:3: note: macro "bill" defined here 3 | #define bill() 2 | Before it told you about including from <command-line>:31. the preprocessed output looks like: ... (There's a new optimization in do_line_marker to stop each of these line markers causing a new line map. We can simply rewind the location, and keep using the same line map.) libcpp/ * directives.c (do_linemarker): Optimize rewinding to line zero. * files.c (_cpp_stack_file): Start on line zero when about to inject headers. (cpp_push_include, cpp_push_default_include): Use highest_line as the location. * include/cpplib.h (cpp_read_main_file): Add injecting parm. * init.c (cpp_read_main_file): Likewise, inform _cpp_stack_file. * internal.h (enum include_type): Add IT_MAIN_INJECT. gcc/c-family/ * c-opts.c (c_common_post_options): Add 'injecting' arg to cpp_read_main_file. (c_finish_options): Add linemap_line_start calls for builtin and cmd maps. Force token position to line_table's highest line. * c-ppoutput.c (print_line_1): Refactor, print line zero. (cb_define): Always increment source line. gcc/testsuite/ * c-c++-common/cpp/line-2.c: New. * c-c++-common/cpp/line-2.h: New. * c-c++-common/cpp/line-3.c: New. * c-c++-common/cpp/line-4.c: New. * c-c++-common/cpp/line-4.h: New.
Diffstat (limited to 'libcpp')
-rw-r--r--libcpp/directives.c44
-rw-r--r--libcpp/files.c12
-rw-r--r--libcpp/include/cpplib.h3
-rw-r--r--libcpp/init.c15
-rw-r--r--libcpp/internal.h4
5 files changed, 52 insertions, 26 deletions
diff --git a/libcpp/directives.c b/libcpp/directives.c
index bbfdfcd..f597187 100644
--- a/libcpp/directives.c
+++ b/libcpp/directives.c
@@ -940,7 +940,7 @@ strtolinenum (const uchar *str, size_t len, linenum_type *nump, bool *wrapped)
/* Interpret #line command.
Note that the filename string (if any) is a true string constant
- (escapes are interpreted), unlike in #line. */
+ (escapes are interpreted). */
static void
do_line (cpp_reader *pfile)
{
@@ -1115,27 +1115,43 @@ do_linemarker (cpp_reader *pfile)
line_table->seen_line_directive = true;
}
-/* Arrange the file_change callback. pfile->line has changed to
- FILE_LINE of TO_FILE, for reason REASON. SYSP is 1 for a system
- header, 2 for a system header that needs to be extern "C" protected,
- and zero otherwise. */
+/* Arrange the file_change callback. Changing to TO_FILE:TO_LINE for
+ REASON. SYSP is 1 for a system header, 2 for a system header that
+ needs to be extern "C" protected, and zero otherwise. */
void
_cpp_do_file_change (cpp_reader *pfile, enum lc_reason reason,
- const char *to_file, linenum_type file_line,
+ const char *to_file, linenum_type to_line,
unsigned int sysp)
{
linemap_assert (reason != LC_ENTER_MACRO);
- const struct line_map *map = linemap_add (pfile->line_table, reason, sysp,
- to_file, file_line);
+
const line_map_ordinary *ord_map = NULL;
- if (map != NULL)
- {
- ord_map = linemap_check_ordinary (map);
- linemap_line_start (pfile->line_table,
- ORDINARY_MAP_STARTING_LINE_NUMBER (ord_map),
- 127);
+ if (!to_line && reason == LC_RENAME_VERBATIM)
+ {
+ /* A linemarker moving to line zero. If we're on the second
+ line of the current map, and it also starts at zero, just
+ rewind -- we're probably reading the builtins of a
+ preprocessed source. */
+ line_map_ordinary *last = LINEMAPS_LAST_ORDINARY_MAP (pfile->line_table);
+ if (!ORDINARY_MAP_STARTING_LINE_NUMBER (last)
+ && SOURCE_LINE (last, pfile->line_table->highest_line) == 2)
+ {
+ ord_map = last;
+ pfile->line_table->highest_location
+ = pfile->line_table->highest_line = MAP_START_LOCATION (last);
+ }
}
+ if (!ord_map)
+ if (const line_map *map = linemap_add (pfile->line_table, reason, sysp,
+ to_file, to_line))
+ {
+ ord_map = linemap_check_ordinary (map);
+ linemap_line_start (pfile->line_table,
+ ORDINARY_MAP_STARTING_LINE_NUMBER (ord_map),
+ 127);
+ }
+
if (pfile->cb.file_change)
pfile->cb.file_change (pfile, ord_map);
}
diff --git a/libcpp/files.c b/libcpp/files.c
index 85c79a1..3d48c38 100644
--- a/libcpp/files.c
+++ b/libcpp/files.c
@@ -947,7 +947,11 @@ _cpp_stack_file (cpp_reader *pfile, _cpp_file *file, include_type type,
pfile->line_table->highest_location--;
/* Add line map and do callbacks. */
- _cpp_do_file_change (pfile, LC_ENTER, file->path, 1, sysp);
+ _cpp_do_file_change (pfile, LC_ENTER, file->path,
+ /* With preamble injection, start on line zero, so
+ the preamble doesn't appear to have been
+ included from line 1. */
+ type == IT_MAIN_INJECT ? 0 : 1, sysp);
return true;
}
@@ -1475,7 +1479,8 @@ _cpp_compare_file_date (cpp_reader *pfile, const char *fname,
bool
cpp_push_include (cpp_reader *pfile, const char *fname)
{
- return _cpp_stack_include (pfile, fname, false, IT_CMDLINE, 0);
+ return _cpp_stack_include (pfile, fname, false, IT_CMDLINE,
+ pfile->line_table->highest_line);
}
/* Pushes the given file, implicitly included at the start of a
@@ -1484,7 +1489,8 @@ cpp_push_include (cpp_reader *pfile, const char *fname)
bool
cpp_push_default_include (cpp_reader *pfile, const char *fname)
{
- return _cpp_stack_include (pfile, fname, true, IT_DEFAULT, 0);
+ return _cpp_stack_include (pfile, fname, true, IT_DEFAULT,
+ pfile->line_table->highest_line);
}
/* Do appropriate cleanup when a file INC's buffer is popped off the
diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
index 544735a..e8bb15d 100644
--- a/libcpp/include/cpplib.h
+++ b/libcpp/include/cpplib.h
@@ -979,7 +979,8 @@ extern class mkdeps *cpp_get_deps (cpp_reader *) ATTRIBUTE_PURE;
input file, except for preprocessed input. This will generate at
least one file change callback, and possibly a line change callback
too. If there was an error opening the file, it returns NULL. */
-extern const char *cpp_read_main_file (cpp_reader *, const char *);
+extern const char *cpp_read_main_file (cpp_reader *, const char *,
+ bool injecting = false);
/* Set up built-ins with special behavior. Use cpp_init_builtins()
instead unless your know what you are doing. */
diff --git a/libcpp/init.c b/libcpp/init.c
index 63124c8..d641d0a1 100644
--- a/libcpp/init.c
+++ b/libcpp/init.c
@@ -657,10 +657,11 @@ cpp_post_options (cpp_reader *pfile)
}
/* Setup for processing input from the file named FNAME, or stdin if
- it is the empty string. Return the original filename
- on success (e.g. foo.i->foo.c), or NULL on failure. */
+ it is the empty string. Return the original filename on success
+ (e.g. foo.i->foo.c), or NULL on failure. INJECTING is true if
+ there may be injected headers before line 1 of the main file. */
const char *
-cpp_read_main_file (cpp_reader *pfile, const char *fname)
+cpp_read_main_file (cpp_reader *pfile, const char *fname, bool injecting)
{
if (CPP_OPTION (pfile, deps.style) != DEPS_NONE)
{
@@ -677,16 +678,16 @@ cpp_read_main_file (cpp_reader *pfile, const char *fname)
if (_cpp_find_failed (pfile->main_file))
return NULL;
- _cpp_stack_file (pfile, pfile->main_file, IT_MAIN, 0);
+ _cpp_stack_file (pfile, pfile->main_file,
+ injecting ? IT_MAIN_INJECT : IT_MAIN, 0);
/* For foo.i, read the original filename foo.c now, for the benefit
of the front ends. */
if (CPP_OPTION (pfile, preprocessed))
{
read_original_filename (pfile);
- fname =
- ORDINARY_MAP_FILE_NAME
- ((LINEMAPS_LAST_ORDINARY_MAP (pfile->line_table)));
+ fname = (ORDINARY_MAP_FILE_NAME
+ ((LINEMAPS_LAST_ORDINARY_MAP (pfile->line_table))));
}
return fname;
}
diff --git a/libcpp/internal.h b/libcpp/internal.h
index 049ee175..4bafe1c 100644
--- a/libcpp/internal.h
+++ b/libcpp/internal.h
@@ -123,7 +123,9 @@ enum include_type
/* Non-directive including mechanisms. */
IT_CMDLINE, /* -include */
IT_DEFAULT, /* forced header */
- IT_MAIN, /* main */
+ IT_MAIN, /* main, start on line 1 */
+ IT_MAIN_INJECT, /* main, but there will be an injected preamble
+ before line 1 */
IT_DIRECTIVE_HWM = IT_IMPORT + 1, /* Directives below this. */
IT_HEADER_HWM = IT_DEFAULT + 1 /* Header files below this. */