summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog15
-rw-r--r--gcc/ada/ChangeLog6
-rw-r--r--gcc/ada/gcc-interface/trans.c10
-rw-r--r--gcc/c-family/ChangeLog9
-rw-r--r--gcc/c-family/c-lex.c6
-rw-r--r--gcc/c-family/c-ppoutput.c43
-rw-r--r--gcc/diagnostic.c11
-rw-r--r--gcc/fortran/ChangeLog6
-rw-r--r--gcc/fortran/cpp.c22
-rw-r--r--gcc/input.c9
-rw-r--r--gcc/input.h18
-rw-r--r--gcc/java/ChangeLog5
-rw-r--r--gcc/java/jcf-parse.c2
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/cpp/pragma-diagnostic-1.c32
-rw-r--r--libcpp/ChangeLog118
-rw-r--r--libcpp/directives.c16
-rw-r--r--libcpp/files.c5
-rw-r--r--libcpp/include/line-map.h585
-rw-r--r--libcpp/init.c4
-rw-r--r--libcpp/internal.h73
-rw-r--r--libcpp/line-map.c946
-rw-r--r--libcpp/macro.c28
23 files changed, 1767 insertions, 207 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 886ba44278f..a6f0e003e90 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,18 @@
+2011-10-15 Tom Tromey <tromey@redhat>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * input.h (struct expanded_location): Move to libcpp/line-map.h.
+ (LOCATION_COLUMN): New accessor
+ (in_system_header_at): Use linemap_location_in_system_header_p.
+ * diagnostic.c (diagnostic_report_current_module): Adjust to avoid
+ touching the internals of struct line_map. Use the public API.
+ instead.
+ (diagnostic_report_diagnostic): Don't use relational operator '<'
+ on virtual locations. Use linemap_location_before_p instead.
+ * input.c (expand_location): Adjust to expand to the tokens'
+ spelling location when macro location tracking is on.
+
+
2011-10-08 Andi Kleen <ak@linux.intel.com>
* ggc-page.c (GGC_QUIRE_SIZE): Increase to 512
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 9c17e0ea826..f839cfb222e 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,9 @@
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * gcc-interface/trans.c (gigi, Sloc_to_locus): Adjust to use the
+ new public ordinary map interface.
+
2011-10-16 Tristan Gingold <gingold@adacore.com>
* link.c (_AIX): Add support for GNU ld.
diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index faf5eb3f3ea..69c66d1b150 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -314,7 +314,7 @@ gigi (Node_Id gnat_root, int max_gnat_node, int number_name ATTRIBUTE_UNUSED,
(Get_Name_String (file_info_ptr[i].File_Name))));
/* We rely on the order isomorphism between files and line maps. */
- gcc_assert ((int) line_table->used == i);
+ gcc_assert ((int) LINEMAPS_ORDINARY_USED (line_table) == i);
/* We create the line map for a source file at once, with a fixed number
of columns chosen to avoid jumping over the next power of 2. */
@@ -8391,12 +8391,10 @@ Sloc_to_locus (Source_Ptr Sloc, location_t *locus)
Source_File_Index file = Get_Source_File_Index (Sloc);
Logical_Line_Number line = Get_Logical_Line_Number (Sloc);
Column_Number column = Get_Column_Number (Sloc);
- struct line_map *map = &line_table->maps[file - 1];
+ struct line_map *map = LINEMAPS_ORDINARY_MAP_AT (line_table, file - 1);
- /* Translate the location according to the line-map.h formula. */
- *locus = map->start_location
- + ((line - map->to_line) << map->column_bits)
- + (column & ((1 << map->column_bits) - 1));
+ /* Translate the location. */
+ *locus = linemap_position_for_line_and_column (map, line, column);
}
ref_filename
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 3a26e170ecc..b6ed818d8ee 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,12 @@
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * c-ppoutput.c (scan_translation_unit, maybe_print_line)
+ (print_line, cb_define, do_line_change): Adjust to avoid touching
+ the internals of struct line_map. Use the public API instead.
+ * c-pch.c (c_common_read_pch): Likewise.
+ * c-lex.c (fe_file_change): Likewise.
+
2011-10-11 Michael Meissner <meissner@linux.vnet.ibm.com>
* c-common.c (def_builtin_1): Delete old interface with two
diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c
index e60dcc53588..be83b61b34c 100644
--- a/gcc/c-family/c-lex.c
+++ b/gcc/c-family/c-lex.c
@@ -207,7 +207,7 @@ fe_file_change (const struct line_map *new_map)
line = SOURCE_LINE (new_map - 1, included_at);
input_location = new_map->start_location;
- (*debug_hooks->start_source_file) (line, new_map->to_file);
+ (*debug_hooks->start_source_file) (line, LINEMAP_FILE (new_map));
#ifndef NO_IMPLICIT_EXTERN_C
if (c_header_level)
++c_header_level;
@@ -231,10 +231,10 @@ fe_file_change (const struct line_map *new_map)
#endif
input_location = new_map->start_location;
- (*debug_hooks->end_source_file) (new_map->to_line);
+ (*debug_hooks->end_source_file) (LINEMAP_LINE (new_map));
}
- update_header_times (new_map->to_file);
+ update_header_times (LINEMAP_FILE (new_map));
input_location = new_map->start_location;
}
diff --git a/gcc/c-family/c-ppoutput.c b/gcc/c-family/c-ppoutput.c
index 16d4f7de994..892f1eaa346 100644
--- a/gcc/c-family/c-ppoutput.c
+++ b/gcc/c-family/c-ppoutput.c
@@ -190,9 +190,7 @@ scan_translation_unit (cpp_reader *pfile)
/* Subtle logic to output a space if and only if necessary. */
if (avoid_paste)
{
- const struct line_map *map
- = linemap_lookup (line_table, loc);
- int src_line = SOURCE_LINE (map, loc);
+ int src_line = LOCATION_LINE (loc);
if (print.source == NULL)
print.source = token;
@@ -212,9 +210,7 @@ scan_translation_unit (cpp_reader *pfile)
}
else if (token->flags & PREV_WHITE)
{
- const struct line_map *map
- = linemap_lookup (line_table, loc);
- int src_line = SOURCE_LINE (map, loc);
+ int src_line = LOCATION_LINE (loc);
if (src_line != print.src_line
&& do_line_adjustments
@@ -304,8 +300,9 @@ scan_translation_unit_trad (cpp_reader *pfile)
static void
maybe_print_line (source_location src_loc)
{
- const struct line_map *map = linemap_lookup (line_table, src_loc);
- int src_line = SOURCE_LINE (map, src_loc);
+ int src_line = LOCATION_LINE (src_loc);
+ const char *src_file = LOCATION_FILE (src_loc);
+
/* End the previous line of text. */
if (print.printed)
{
@@ -317,7 +314,7 @@ maybe_print_line (source_location src_loc)
if (!flag_no_line_commands
&& src_line >= print.src_line
&& src_line < print.src_line + 8
- && strcmp (map->to_file, print.src_file) == 0)
+ && strcmp (src_file, print.src_file) == 0)
{
while (src_line > print.src_line)
{
@@ -341,28 +338,30 @@ print_line (source_location src_loc, const char *special_flags)
if (!flag_no_line_commands)
{
- const struct line_map *map = linemap_lookup (line_table, src_loc);
-
- size_t to_file_len = strlen (map->to_file);
+ const char *file_path = LOCATION_FILE (src_loc);
+ int sysp;
+ size_t to_file_len = strlen (file_path);
unsigned char *to_file_quoted =
(unsigned char *) alloca (to_file_len * 4 + 1);
unsigned char *p;
- print.src_line = SOURCE_LINE (map, src_loc);
- print.src_file = map->to_file;
+ print.src_line = LOCATION_LINE (src_loc);
+ print.src_file = file_path;
/* cpp_quote_string does not nul-terminate, so we have to do it
ourselves. */
p = cpp_quote_string (to_file_quoted,
- (const unsigned char *) map->to_file, to_file_len);
+ (const unsigned char *) file_path,
+ to_file_len);
*p = '\0';
fprintf (print.outf, "# %u \"%s\"%s",
print.src_line == 0 ? 1 : print.src_line,
to_file_quoted, special_flags);
- if (map->sysp == 2)
+ sysp = in_system_header_at (src_loc);
+ if (sysp == 2)
fputs (" 3 4", print.outf);
- else if (map->sysp == 1)
+ else if (sysp == 1)
fputs (" 3", print.outf);
putc ('\n', print.outf);
@@ -391,8 +390,7 @@ do_line_change (cpp_reader *pfile, const cpp_token *token,
ought to care. Some things do care; the fault lies with them. */
if (!CPP_OPTION (pfile, traditional))
{
- const struct line_map *map = linemap_lookup (line_table, src_loc);
- int spaces = SOURCE_COLUMN (map, src_loc) - 2;
+ int spaces = LOCATION_COLUMN (src_loc) - 2;
print.printed = 1;
while (-- spaces >= 0)
@@ -421,6 +419,8 @@ cb_ident (cpp_reader *pfile ATTRIBUTE_UNUSED, source_location line,
static void
cb_define (cpp_reader *pfile, source_location line, cpp_hashnode *node)
{
+ const struct line_map *map;
+
maybe_print_line (line);
fputs ("#define ", print.outf);
@@ -432,7 +432,10 @@ cb_define (cpp_reader *pfile, source_location line, cpp_hashnode *node)
fputs ((const char *) NODE_NAME (node), print.outf);
putc ('\n', print.outf);
- if (linemap_lookup (line_table, line)->to_line != 0)
+ linemap_resolve_location (line_table, line,
+ LRK_MACRO_DEFINITION_LOCATION,
+ &map);
+ if (LINEMAP_LINE (map) != 0)
print.src_line++;
}
diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
index d297cdda0ca..b46eb3570d9 100644
--- a/gcc/diagnostic.c
+++ b/gcc/diagnostic.c
@@ -278,18 +278,18 @@ diagnostic_report_current_module (diagnostic_context *context)
if (context->show_column)
pp_verbatim (context->printer,
"In file included from %s:%d:%d",
- map->to_file,
+ LINEMAP_FILE (map),
LAST_SOURCE_LINE (map), LAST_SOURCE_COLUMN (map));
else
pp_verbatim (context->printer,
"In file included from %s:%d",
- map->to_file, LAST_SOURCE_LINE (map));
+ LINEMAP_FILE (map), LAST_SOURCE_LINE (map));
while (! MAIN_FILE_P (map))
{
map = INCLUDED_FROM (line_table, map);
pp_verbatim (context->printer,
",\n from %s:%d",
- map->to_file, LAST_SOURCE_LINE (map));
+ LINEMAP_FILE (map), LAST_SOURCE_LINE (map));
}
pp_verbatim (context->printer, ":");
pp_newline (context->printer);
@@ -459,7 +459,10 @@ diagnostic_report_diagnostic (diagnostic_context *context,
/* FIXME: Stupid search. Optimize later. */
for (i = context->n_classification_history - 1; i >= 0; i --)
{
- if (context->classification_history[i].location <= location)
+ if (linemap_location_before_p
+ (line_table,
+ context->classification_history[i].location,
+ location))
{
if (context->classification_history[i].kind == (int) DK_POP)
{
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 4866956dd35..8d2f4d6c30e 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,9 @@
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * cpp.c (print_line, cb_define): Adjust to avoid using internals
+ of struct line_map. Use the public API instead.
+
2011-10-17 Janus Weil <janus@gcc.gnu.org>
PR fortran/47023
diff --git a/gcc/fortran/cpp.c b/gcc/fortran/cpp.c
index 9368d890973..2f18893313b 100644
--- a/gcc/fortran/cpp.c
+++ b/gcc/fortran/cpp.c
@@ -818,27 +818,29 @@ print_line (source_location src_loc, const char *special_flags)
if (!gfc_cpp_option.no_line_commands)
{
- const struct line_map *map = linemap_lookup (line_table, src_loc);
-
- size_t to_file_len = strlen (map->to_file);
- unsigned char *to_file_quoted =
- (unsigned char *) alloca (to_file_len * 4 + 1);
+ expanded_location loc;
+ size_t to_file_len;
+ unsigned char *to_file_quoted;
unsigned char *p;
- print.src_line = SOURCE_LINE (map, src_loc);
+ loc = expand_location (src_loc);
+ to_file_len = strlen (loc.file);
+ to_file_quoted = (unsigned char *) alloca (to_file_len * 4 + 1);
+
+ print.src_line = loc.line;
/* cpp_quote_string does not nul-terminate, so we have to do it
ourselves. */
p = cpp_quote_string (to_file_quoted,
- (const unsigned char *) map->to_file, to_file_len);
+ (const unsigned char *) loc.file, to_file_len);
*p = '\0';
fprintf (print.outf, "# %u \"%s\"%s",
print.src_line == 0 ? 1 : print.src_line,
to_file_quoted, special_flags);
- if (map->sysp == 2)
+ if (loc.sysp == 2)
fputs (" 3 4", print.outf);
- else if (map->sysp == 1)
+ else if (loc.sysp == 1)
fputs (" 3", print.outf);
putc ('\n', print.outf);
@@ -935,7 +937,7 @@ cb_define (cpp_reader *pfile ATTRIBUTE_UNUSED, source_location line,
fputs ((const char *) NODE_NAME (node), print.outf);
putc ('\n', print.outf);
- if (linemap_lookup (line_table, line)->to_line != 0)
+ if (LOCATION_LINE (line) != 0)
print.src_line++;
}
diff --git a/gcc/input.c b/gcc/input.c
index e5e051f9eae..83344d79dd9 100644
--- a/gcc/input.c
+++ b/gcc/input.c
@@ -42,12 +42,7 @@ expand_location (source_location loc)
xloc.sysp = 0;
}
else
- {
- const struct line_map *map = linemap_lookup (line_table, loc);
- xloc.file = map->to_file;
- xloc.line = SOURCE_LINE (map, loc);
- xloc.column = SOURCE_COLUMN (map, loc);
- xloc.sysp = map->sysp != 0;
- };
+ xloc = linemap_expand_location_full (line_table, loc,
+ LRK_SPELLING_LOCATION);
return xloc;
}
diff --git a/gcc/input.h b/gcc/input.h
index 59290642090..9fc55f3ac7f 100644
--- a/gcc/input.h
+++ b/gcc/input.h
@@ -37,20 +37,6 @@ extern GTY(()) struct line_maps *line_table;
extern char builtins_location_check[(BUILTINS_LOCATION
< RESERVED_LOCATION_COUNT) ? 1 : -1];
-typedef struct
-{
- /* The name of the source file involved. */
- const char *file;
-
- /* The line-location in the source file. */
- int line;
-
- int column;
-
- /* In a system header?. */
- bool sysp;
-} expanded_location;
-
extern expanded_location expand_location (source_location);
/* Historically GCC used location_t, while cpp used source_location.
@@ -61,10 +47,12 @@ extern location_t input_location;
#define LOCATION_FILE(LOC) ((expand_location (LOC)).file)
#define LOCATION_LINE(LOC) ((expand_location (LOC)).line)
+#define LOCATION_COLUMN(LOC)((expand_location (LOC)).column)
#define input_line LOCATION_LINE (input_location)
#define input_filename LOCATION_FILE (input_location)
-#define in_system_header_at(LOC) ((expand_location (LOC)).sysp != 0)
+#define in_system_header_at(LOC) \
+ ((linemap_location_in_system_header_p (line_table, LOC)))
#define in_system_header (in_system_header_at (input_location))
#endif
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog
index dfb6500541c..ac83a40c50b 100644
--- a/gcc/java/ChangeLog
+++ b/gcc/java/ChangeLog
@@ -1,3 +1,8 @@
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * jcf-parse.c (set_source_filename): Adjust to the new map API.
+
2011-10-11 Michael Meissner <meissner@linux.vnet.ibm.com>
* class.c (build_static_field_ref): Delete old interface with two
diff --git a/gcc/java/jcf-parse.c b/gcc/java/jcf-parse.c
index 37cea2870a8..04c04f575cf 100644
--- a/gcc/java/jcf-parse.c
+++ b/gcc/java/jcf-parse.c
@@ -355,7 +355,7 @@ set_source_filename (JCF *jcf, int index)
}
sfname = find_sourcefile (sfname);
- line_table->maps[line_table->used-1].to_file = sfname;
+ ORDINARY_MAP_FILE_NAME (LINEMAPS_LAST_ORDINARY_MAP (line_table)) = sfname;
if (current_class == main_class) main_input_filename = sfname;
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 11ae542c0f4..e2b4fe1e937 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * gcc.dg/cpp/pragma-diagnostic-1.c: New test.
+
2011-10-17 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/48489
diff --git a/gcc/testsuite/gcc.dg/cpp/pragma-diagnostic-1.c b/gcc/testsuite/gcc.dg/cpp/pragma-diagnostic-1.c
new file mode 100644
index 00000000000..3a2f9da1fce
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/pragma-diagnostic-1.c
@@ -0,0 +1,32 @@
+/*
+ { dg-options "-Wuninitialized" }
+ { dg-do compile }
+*/
+
+void f (unsigned);
+
+#define CODE_WITH_WARNING \
+ int a; \
+ f (a)
+
+#pragma GCC diagnostic ignored "-Wuninitialized"
+
+void
+g (void)
+{
+ CODE_WITH_WARNING;
+}
+
+#pragma GCC diagnostic push
+
+#pragma GCC diagnostic error "-Wuninitialized"
+
+void
+h (void)
+{
+ CODE_WITH_WARNING; /* { dg-error "uninitialized" } */
+}
+
+/*
+ { dg-message "some warnings being treated as errors" "" {target *-*-*} 0 }
+*/
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog
index 4ecda03cfec..b961ef5a810 100644
--- a/libcpp/ChangeLog
+++ b/libcpp/ChangeLog
@@ -1,3 +1,121 @@
+2011-10-15 Tom Tromey <tromey@redhat>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * include/line-map.h (enum lc_reason)<LC_ENTER_MACRO>: New enum
+ member.
+ (MAX_SOURCE_LOCATION): New constant.
+ (struct line_map_ordinary, struct line_map_macro): New structs.
+ (struct line_map): Turn this into a union of the two above. Add
+ comments.
+ (struct maps_info): New struct.
+ (struct line_maps)<info_ordinary, info_macro>: Two new fields.
+ These now carry the map information that was previously scattered
+ in struct line_maps.
+ (struct map_info::allocated): Fix comment.
+ (MAP_START_LOCATION, ORDINARY_MAP_FILE_NAME)
+ (ORDINARY_MAP_STARTING_LINE_NUMBER)
+ (ORDINARY_MAP_INCLUDER_FILE_INDEX)
+ (ORDINARY_MAP_IN_SYSTEM_HEADER_P)
+ (ORDINARY_MAP_NUMBER_OF_COLUMN_BITS, MACRO_MAP_MACRO)
+ (MACRO_MAP_NUM_MACRO_TOKENS MACRO_MAP_LOCATIONS)
+ (MACRO_MAP_EXPANSION_POINT_LOCATION)
+ (LOCATION_POSSIBLY_IN_MACRO_MAP_P, LINEMAPS_MAP_INFO)
+ (LINEMAPS_MAPS, LINEMAPS_ALLOCATE, LINEMAPS_USED, LINEMAPS_CACHE)
+ (LINEMAPS_LAST_MAP, LINEMAPS_LAST_ALLOCATED_MAP)
+ (LINEMAPS_ORDINARY_MAPS, LINEMAPS_ORDINARY_ALLOCATED)
+ (LINEMAPS_ORDINARY_USED, LINEMAPS_ORDINARY_CACHE)
+ (LINEMAPS_LAST_ORDINARY_MAP, LINEMAPS_LAST_ALLOCATED_ORDINARY_MAP)
+ (LINEMAPS_MACRO_MAPS, LINEMAPS_MACRO_ALLOCATED)
+ (LINEMAPS_MACRO_USED, LINEMAPS_MACRO_CACHE)
+ (LINEMAPS_LAST_MACRO_MAP, LINEMAPS_LAST_ALLOCATED_MACRO_MAP)
+ (LINEMAPS_MAP_AT, LINEMAPS_ORDINARY_MAP_AT)
+ (LINEMAPS_MACRO_MAP_AT): New accessors for ordinary and macro map
+ information.
+ (linemap_check_ordinary, linemap_assert)
+ (linemap_location_before_p): New macros.
+ (linemap_position_for_line_and_column)
+ (linemap_tracks_macro_expansion_locs_p, linemap_add_macro_token)
+ (linemap_macro_expansion_map_p)
+ (linemap_macro_map_loc_to_def_point)
+ (linemap_macro_map_loc_unwind_once)
+ (linemap_macro_map_loc_to_exp_point, linemap_step_out_once)
+ (linemap_get_source_line linemap_get_source_column)
+ (linemap_map_get_macro_name, linemap_get_file_path)
+ (linemap_location_in_system_header_p)
+ (linemap_location_from_macro_expansion_p): Declare new functions.
+ (SOURCE_LINE, SOURCE_COLUMN, LAST_SOURCE_LINE_LOCATION)
+ (LINEMAP_FILE, LINEMAP_LINE, LINEMAP_SYSP): Assert that this
+ accessors act on ordinary maps only.
+ (INCLUDED_FROM): Return NULL for main files; use the new
+ accessors.
+ (LINEMAP_POSITION_FOR_COLUMN): Use the new accessors.
+ (struct expanded_location): Move here from gcc/input.h
+ (linemap_resolve_location, linemap_expand_location)
+ (linemap_expand_location_full): Declare new functions.
+ * line-map.c: Include cpplib.h, internal.h
+ (linemap_enter_macro, linemap_add_macro_token)
+ (linemap_get_expansion_line, linemap_get_expansion_filename): New
+ functions that are private to libcpp.
+ (linemap_assert): New macro.
+ (linemap_macro_loc_to_exp_point, linemap_macro_loc_to_exp_point)
+ (linemap_macro_loc_unwind, linemap_macro_map_loc_to_def_point)
+ (linemap_macro_map_loc_unwind_toward_spelling)
+ (linemap_macro_map_loc_to_exp_point)
+ (first_map_in_common_1, first_map_in_common): New static
+ functions.
+ (new_linemap): Define new static functions. Extracted and
+ enhanced from ...
+ (linemap_add): ... here. Use linemap_assert in lieu of abort
+ previously.
+ (linemap_tracks_macro_expansion_locs_p)
+ (linemap_add_macro_token, linemap_macro_expansion_map_p)
+ (linemap_check_ordinary, linemap_macro_map_loc_to_exp_point)
+ (linemap_macro_map_loc_to_def_point)
+ (linemap_macro_map_loc_unwind_once)
+ (linemap_step_out_once, linemap_map_get_index)
+ (linemap_get_source_line,linemap_get_source_column)
+ (linemap_get_file_path, linemap_map_get_macro_name)
+ (linemap_location_in_system_header_p)
+ (linemap_location_originated_from_system_header_p)
+ (linemap_location_from_macro_expansion_p)
+ (linemap_tracks_macro_expansion_locs_p)
+ (linemap_resolve_location, linemap_expand_location)
+ (linemap_expand_location_full)
+ (linemap_tracks_macro_expansion_locs_p)
+ (linemap_position_for_line_and_column, linemap_compare_locations):
+ Define new public functions.
+ (linemap_init): Initialize ordinary and macro maps information in
+ the map set.
+ (linemap_check_files_exited): Use the new accessors.
+ (linemap_free): Remove this dead code.
+ (linemap_line_start): Assert this uses an ordinary map. Adjust to
+ use the new ordinary map accessors and data structures. Don't
+ overflow past the lowest possible macro token's location.
+ (linemap_position_for_column): Assert the ordinary maps of the map
+ set are really ordinary. Use ordinary map accessors.
+ (linemap_lookup): Keep the same logic but generalize to allow
+ lookup of both ordinary and macro maps. Do not crash when called
+ with an empty line table.
+ * directives-only.c (_cpp_preprocess_dir_only): Adjust to use the
+ new API of line-map.h.
+ * directives.c (start_directive, do_line, do_linemarker)
+ (do_linemarker): Likewise.
+ * files.c (_cpp_find_file, _cpp_stack_include, open_file_failed)
+ (make_cpp_dir, cpp_make_system_header): Likewise.
+ * init.c (cpp_read_main_file): Likewise.
+ * internal.h (CPP_INCREMENT_LINE): Likewise.
+ (linemap_enter_macro, linemap_add_macro_token)
+ (linemap_get_expansion_line, linemap_get_expansion_filename): New
+ functions private to libcpp.
+ * lex.c (_cpp_process_line_notes, _cpp_skip_block_comment)
+ (skip_line_comment, skip_whitespace, lex_raw_string)
+ (_cpp_lex_direct): Likewise.
+ * macro.c (_cpp_builtin_macro_text): Likewise.
+ (_cpp_aligned_alloc): Initialize the new name member of the macro.
+ * traditional.c (copy_comment, _cpp_scan_out_logical_line):
+ Likewise.
+ * errors.c (cpp_diagnostic): Adjust to new linemap API.
+
2011-08-28 Dodji Seketeli <dodji@redhat.com>
* line-map.c (linemap_add): Assert that reason must not be
diff --git a/libcpp/directives.c b/libcpp/directives.c
index 83d4a0e8d7f..a62ddeb1672 100644
--- a/libcpp/directives.c
+++ b/libcpp/directives.c
@@ -884,14 +884,14 @@ static void
do_line (cpp_reader *pfile)
{
const struct line_maps *line_table = pfile->line_table;
- const struct line_map *map = &line_table->maps[line_table->used - 1];
+ const struct line_map *map = LINEMAPS_LAST_ORDINARY_MAP (line_table);
/* skip_rest_of_line() may cause line table to be realloc()ed so note down
sysp right now. */
- unsigned char map_sysp = map->sysp;
+ unsigned char map_sysp = ORDINARY_MAP_IN_SYSTEM_HEADER_P (map);
const cpp_token *token;
- const char *new_file = map->to_file;
+ const char *new_file = ORDINARY_MAP_FILE_NAME (map);
linenum_type new_lineno;
/* C99 raised the minimum limit on #line numbers. */
@@ -946,11 +946,11 @@ static void
do_linemarker (cpp_reader *pfile)
{
const struct line_maps *line_table = pfile->line_table;
- const struct line_map *map = &line_table->maps[line_table->used - 1];
+ const struct line_map *map = LINEMAPS_LAST_ORDINARY_MAP (line_table);
const cpp_token *token;
- const char *new_file = map->to_file;
+ const char *new_file = ORDINARY_MAP_FILE_NAME (map);
linenum_type new_lineno;
- unsigned int new_sysp = map->sysp;
+ unsigned int new_sysp = ORDINARY_MAP_IN_SYSTEM_HEADER_P (map);
enum lc_reason reason = LC_RENAME_VERBATIM;
int flag;
bool wrapped;
@@ -1038,7 +1038,9 @@ _cpp_do_file_change (cpp_reader *pfile, enum lc_reason reason,
const struct line_map *map = linemap_add (pfile->line_table, reason, sysp,
to_file, file_line);
if (map != NULL)
- linemap_line_start (pfile->line_table, map->to_line, 127);
+ linemap_line_start (pfile->line_table,
+ ORDINARY_MAP_STARTING_LINE_NUMBER (map),
+ 127);
if (pfile->cb.file_change)
pfile->cb.file_change (pfile, map);
diff --git a/libcpp/files.c b/libcpp/files.c
index d2c6b8bdecf..fad8b75fe57 100644
--- a/libcpp/files.c
+++ b/libcpp/files.c
@@ -1220,13 +1220,12 @@ cpp_make_system_header (cpp_reader *pfile, int syshdr, int externc)
{
int flags = 0;
const struct line_maps *line_table = pfile->line_table;
- const struct line_map *map = &line_table->maps[line_table->used-1];
-
+ const struct line_map *map = LINEMAPS_LAST_ORDINARY_MAP (line_table);
/* 1 = system header, 2 = system header to be treated as C. */
if (syshdr)
flags = 1 + (externc != 0);
pfile->buffer->sysp = flags;
- _cpp_do_file_change (pfile, LC_RENAME, map->to_file,
+ _cpp_do_file_change (pfile, LC_RENAME, ORDINARY_MAP_FILE_NAME (map),
SOURCE_LINE (map, pfile->line_table->highest_line), flags);
}
diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h
index 3c84035e95f..d3c52b241bd 100644
--- a/libcpp/include/line-map.h
+++ b/libcpp/include/line-map.h
@@ -27,13 +27,22 @@ along with this program; see the file COPYING3. If not see
#define GTY(x) /* nothing */
#endif
-/* Reason for adding a line change with add_line_map (). LC_ENTER is
+/* Reason for creating a new line map with linemap_add. LC_ENTER is
when including a new file, e.g. a #include directive in C.
LC_LEAVE is when reaching a file's end. LC_RENAME is when a file
name or line number changes for neither of the above reasons
(e.g. a #line directive in C); LC_RENAME_VERBATIM is like LC_RENAME
- but a filename of "" is not specially interpreted as standard input. */
-enum lc_reason {LC_ENTER = 0, LC_LEAVE, LC_RENAME, LC_RENAME_VERBATIM};
+ but a filename of "" is not specially interpreted as standard
+ input. LC_ENTER_MACRO is when a macro expansion is about to start. */
+enum lc_reason
+{
+ LC_ENTER = 0,
+ LC_LEAVE,
+ LC_RENAME,
+ LC_RENAME_VERBATIM,
+ LC_ENTER_MACRO
+ /* FIXME: add support for stringize and paste. */
+};
/* The type of line numbers. */
typedef unsigned int linenum_type;
@@ -44,37 +53,214 @@ typedef unsigned int source_location;
/* Memory allocation function typedef. Works like xrealloc. */
typedef void *(*line_map_realloc) (void *, size_t);
-/* Physical source file TO_FILE at line TO_LINE at column 0 is represented
+/* An ordinary line map encodes physical source locations. Those
+ physical source locations are called "spelling locations".
+
+ Physical source file TO_FILE at line TO_LINE at column 0 is represented
by the logical START_LOCATION. TO_LINE+L at column C is represented by
START_LOCATION+(L*(1<<column_bits))+C, as long as C<(1<<column_bits),
and the result_location is less than the next line_map's start_location.
(The top line is line 1 and the leftmost column is column 1; line/column 0
means "entire file/line" or "unknown line/column" or "not applicable".)
- INCLUDED_FROM is an index into the set that gives the line mapping
- at whose end the current one was included. File(s) at the bottom
- of the include stack have this set to -1. REASON is the reason for
- creation of this line map, SYSP is one for a system header, two for
- a C system header file that therefore needs to be extern "C"
- protected in C++, and zero otherwise. */
-struct GTY(()) line_map {
+
+ The highest possible source location is MAX_SOURCE_LOCATION. */
+struct GTY(()) line_map_ordinary {
const char *to_file;
linenum_type to_line;
- source_location start_location;
+
+ /* An index into the set that gives the line mapping at whose end
+ the current one was included. File(s) at the bottom of the
+ include stack have this set to -1. */
int included_from;
- ENUM_BITFIELD (lc_reason) reason : CHAR_BIT;
- /* The sysp field isn't really needed now that it's in cpp_buffer. */
+
+ /* SYSP is one for a system header, two for a C system header file
+ that therefore needs to be extern "C" protected in C++, and zero
+ otherwise. This field isn't really needed now that it's in
+ cpp_buffer. */
unsigned char sysp;
+
/* Number of the low-order source_location bits used for a column number. */
unsigned int column_bits : 8;
};
-/* A set of chronological line_map structures. */
-struct GTY(()) line_maps {
+/* This is the highest possible source location encoded within an
+ ordinary or macro map. */
+#define MAX_SOURCE_LOCATION 0xFFFFFFFF
+
+struct cpp_hashnode;
+
+/* A macro line map encodes location of tokens coming from a macro
+ expansion.
+
+ Please note that this struct line_map_macro is a field of struct
+ line_map below, go read the comments of struct line_map below and
+ then come back here.
+
+ The offset from START_LOCATION is used to index into
+ MACRO_LOCATIONS; this holds the original location of the token. */
+struct GTY(()) line_map_macro {
+ /* The cpp macro which expansion gave birth to this macro map. */
+ struct cpp_hashnode * GTY ((nested_ptr (union tree_node,
+ "%h ? CPP_HASHNODE (GCC_IDENT_TO_HT_IDENT (%h)) : NULL",
+ "%h ? HT_IDENT_TO_GCC_IDENT (HT_NODE (%h)) : NULL")))
+ macro;
+
+ /* The number of tokens inside the replacement-list of MACRO. */
+ unsigned int n_tokens;
+
+ /* This array of location is actually an array of pairs of
+ locations. The elements inside it thus look like:
+
+ x0,y0, x1,y1, x2,y2, ...., xn,yn.
+
+ where n == n_tokens;
+
+ Remember that these xI,yI are collected when libcpp is about to
+ expand a given macro.
+
+ yI is the location in the macro definition, either of the token
+ itself or of a macro parameter that it replaces.
+
+ Imagine this:
+
+ #define PLUS(A, B) A + B <--- #1
+
+ int a = PLUS (1,2); <--- #2
+
+ There is a macro map for the expansion of PLUS in #2. PLUS is
+ expanded into its expansion-list. The expansion-list is the
+ replacement-list of PLUS where the macro parameters are replaced
+ with their arguments. So the replacement-list of PLUS is made of
+ the tokens:
+
+ A, +, B
+
+ and the expansion-list is made of the tokens:
+
+ 1, +, 2
+
+ Let's consider the case of token "+". Its y1 [yI for I == 1] is
+ its spelling location in #1.
+
+ y0 (thus for token "1") is the spelling location of A in #1.
+
+ And y2 (of token "2") is the spelling location of B in #1.
+
+ When the token is /not/ an argument for a macro, xI is the same
+ location as yI. Otherwise, xI is the location of the token
+ outside this macro expansion. If this macro was expanded from
+ another macro expansion, xI is a virtual location representing
+ the token in that macro expansion; otherwise, it is the spelling
+ location of the token.
+
+ Note that a virtual location is a location returned by
+ linemap_add_macro_token. It encodes the relevant locations (x,y
+ pairs) of that token accross the macro expansions from which it
+ (the token) might come from.
+
+ In the example above x1 (for token "+") is going to be the same
+ as y1. x0 is the spelling location for the argument token "1",
+ and x2 is the spelling location for the argument token "2". */
+ source_location * GTY((length ("2 * %h.n_tokens"))) macro_locations;
+
+ /* This is the location of the expansion point of the current macro
+ map. It's the location of the macro name. That location is held
+ by the map that was current right before the current one. It
+ could have been either a macro or an ordinary map, depending on
+ if we are in a nested expansion context not. */
+ source_location expansion;
+};
+
+/* A line_map encodes a sequence of locations.
+ There are two kinds of maps. Ordinary maps and macro expansion
+ maps, a.k.a macro maps.
+
+ A macro map encodes source locations of tokens that are part of a
+ macro replacement-list, at a macro expansion point. E.g, in:
+
+ #define PLUS(A,B) A + B
+
+ No macro map is going to be created there, because we are not at a
+ macro expansion point. We are at a macro /definition/ point. So the
+ locations of the tokens of the macro replacement-list (i.e, A + B)
+ will be locations in an ordinary map, not a macro map.
+
+ On the other hand, if we later do:
+
+ int a = PLUS (1,2);
+
+ The invocation of PLUS here is a macro expansion. So we are at a
+ macro expansion point. The preprocessor expands PLUS (1,2) and
+ replaces it with the tokens of its replacement-list: 1 + 2. A macro
+ map is going to be created to hold (or rather to map, haha ...) the
+ locations of the tokens 1, + and 2. The macro map also records the
+ location of the expansion point of PLUS. That location is mapped in
+ the map that is active right before the location of the invocation
+ of PLUS. */
+struct GTY(()) line_map {
+ source_location start_location;
+
+ /* The reason for creation of this line map. */
+ ENUM_BITFIELD (lc_reason) reason : CHAR_BIT;
+
+ union map_u {
+ struct line_map_ordinary GTY((tag ("0"))) ordinary;
+ struct line_map_macro GTY((tag ("1"))) macro;
+ } GTY((desc ("%1.reason == LC_ENTER_MACRO"))) d;
+};
+
+#define MAP_START_LOCATION(MAP) (MAP)->start_location
+
+#define ORDINARY_MAP_FILE_NAME(MAP) \
+ linemap_check_ordinary (MAP)->d.ordinary.to_file
+
+#define ORDINARY_MAP_STARTING_LINE_NUMBER(MAP) \
+ linemap_check_ordinary (MAP)->d.ordinary.to_line
+
+#define ORDINARY_MAP_INCLUDER_FILE_INDEX(MAP) \
+ linemap_check_ordinary (MAP)->d.ordinary.included_from
+
+#define ORDINARY_MAP_IN_SYSTEM_HEADER_P(MAP) \
+ linemap_check_ordinary (MAP)->d.ordinary.sysp
+
+#define ORDINARY_MAP_NUMBER_OF_COLUMN_BITS(MAP) \
+ linemap_check_ordinary (MAP)->d.ordinary.column_bits
+
+#define MACRO_MAP_MACRO(MAP) (MAP)->d.macro.macro
+
+#define MACRO_MAP_NUM_MACRO_TOKENS(MAP) (MAP)->d.macro.n_tokens
+
+#define MACRO_MAP_LOCATIONS(MAP) (MAP)->d.macro.macro_locations
+
+#define MACRO_MAP_EXPANSION_POINT_LOCATION(MAP) (MAP)->d.macro.expansion
+
+/* The abstraction of a set of location maps. There can be several
+ types of location maps. This abstraction contains the attributes
+ that are independent from the type of the map. */
+struct GTY(()) maps_info {
+ /* This array contains the different line maps.
+ A line map is created for the following events:
+ - when a new preprocessing unit start.
+ - when a preprocessing unit ends.
+ - when a macro expansion occurs. */
struct line_map * GTY ((length ("%h.used"))) maps;
+
+ /* The total number of allocated maps. */
unsigned int allocated;
+
+ /* The number of elements used in maps. This number is smaller
+ or equal to ALLOCATED. */
unsigned int used;
unsigned int cache;
+};
+
+/* A set of chronological line_map structures. */
+struct GTY(()) line_maps {
+
+ struct maps_info info_ordinary;
+
+ struct maps_info info_macro;
/* Depth of the include stack, including the current file. */
unsigned int depth;
@@ -97,12 +283,126 @@ struct GTY(()) line_maps {
line_map_realloc reallocator;
};
+/* Returns the pointer to the memory region where information about
+ maps are stored in the line table SET. MACRO_MAP_P is a flag
+ telling if we want macro or ordinary maps. */
+#define LINEMAPS_MAP_INFO(SET, MACRO_MAP_P) \
+ ((MACRO_MAP_P) \
+ ? &((SET)->info_macro) \
+ : &((SET)->info_ordinary))
+
+/* Returns the pointer to the memory region where maps are stored in
+ the line table SET. MAP_KIND shall be TRUE if we are interested in
+ macro maps false otherwise. */
+#define LINEMAPS_MAPS(SET, MAP_KIND) \
+ (LINEMAPS_MAP_INFO (SET, MAP_KIND))->maps
+
+/* Returns the number of allocated maps so far. MAP_KIND shall be TRUE
+ if we are interested in macro maps, FALSE otherwise. */
+#define LINEMAPS_ALLOCATED(SET, MAP_KIND) \
+ (LINEMAPS_MAP_INFO (SET, MAP_KIND))->allocated
+
+/* Returns the number of used maps so far. MAP_KIND shall be TRUE if
+ we are interested in macro maps, FALSE otherwise.*/
+#define LINEMAPS_USED(SET, MAP_KIND) \
+ (LINEMAPS_MAP_INFO (SET, MAP_KIND))->used
+
+/* Returns the index of the last map that was looked up with
+ linemap_lookup. MAP_KIND shall be TRUE if we are interested in
+ macro maps, FALSE otherwise. */
+#define LINEMAPS_CACHE(SET, MAP_KIND) \
+ (LINEMAPS_MAP_INFO (SET, MAP_KIND))->cache
+
+/* Return the map at a given index. */
+#define LINEMAPS_MAP_AT(SET, MAP_KIND, INDEX) \
+ (&((LINEMAPS_MAPS (SET, MAP_KIND))[(INDEX)]))
+
+/* Returns the last map used in the line table SET. MAP_KIND
+ shall be TRUE if we are interested in macro maps, FALSE
+ otherwise.*/
+#define LINEMAPS_LAST_MAP(SET, MAP_KIND) \
+ LINEMAPS_MAP_AT (SET, MAP_KIND, (LINEMAPS_USED (SET, MAP_KIND) - 1))
+
+/* Returns the last map that was allocated in the line table SET.
+ MAP_KIND shall be TRUE if we are interested in macro maps, FALSE
+ otherwise.*/
+#define LINEMAPS_LAST_ALLOCATED_MAP(SET, MAP_KIND) \
+ LINEMAPS_MAP_AT (SET, MAP_KIND, LINEMAPS_ALLOCATED (SET, MAP_KIND) - 1)
+
+/* Returns a pointer to the memory region where ordinary maps are
+ allocated in the line table SET. */
+#define LINEMAPS_ORDINARY_MAPS(SET) \
+ LINEMAPS_MAPS (SET, false)
+
+/* Returns the INDEXth ordinary map. */
+#define LINEMAPS_ORDINARY_MAP_AT(SET, INDEX) \
+ LINEMAPS_MAP_AT (SET, false, INDEX)
+
+/* Return the number of ordinary maps allocated in the line table
+ SET. */
+#define LINEMAPS_ORDINARY_ALLOCATED(SET) \
+ LINEMAPS_ALLOCATED(SET, false)
+
+/* Return the number of ordinary maps used in the line table SET. */
+#define LINEMAPS_ORDINARY_USED(SET) \
+ LINEMAPS_USED(SET, false)
+
+/* Return the index of the last ordinary map that was looked up with
+ linemap_lookup. */
+#define LINEMAPS_ORDINARY_CACHE(SET) \
+ LINEMAPS_CACHE(SET, false)
+
+/* Returns a pointer to the last ordinary map used in the line table
+ SET. */
+#define LINEMAPS_LAST_ORDINARY_MAP(SET) \
+ LINEMAPS_LAST_MAP(SET, false)
+
+/* Returns a pointer to the last ordinary map allocated the line table
+ SET. */
+#define LINEMAPS_LAST_ALLOCATED_ORDINARY_MAP(SET) \
+ LINEMAPS_LAST_ALLOCATED_MAP(SET, false)
+
+/* Returns a pointer to the begining of the region where macro maps
+ are allcoated. */
+#define LINEMAPS_MACRO_MAPS(SET) \
+ LINEMAPS_MAPS(SET, true)
+
+/* Returns the INDEXth macro map. */
+#define LINEMAPS_MACRO_MAP_AT(SET, INDEX) \
+ LINEMAPS_MAP_AT (SET, true, INDEX)
+
+/* Returns the number of macro maps that were allocated in the line
+ table SET. */
+#define LINEMAPS_MACRO_ALLOCATED(SET) \
+ LINEMAPS_ALLOCATED(SET, true)
+
+/* Returns the number of macro maps used in the line table SET. */
+#define LINEMAPS_MACRO_USED(SET) \
+ LINEMAPS_USED(SET, true)
+
+/* Returns the index of the last macro map looked up with
+ linemap_lookup. */
+#define LINEMAPS_MACRO_CACHE(SET) \
+ LINEMAPS_CACHE(SET, true)
+
+/* Returns the lowest location [of a token resulting from macro
+ expansion] encoded in this line table. */
+#define LINEMAPS_MACRO_LOWEST_LOCATION(SET) \
+ (LINEMAPS_MACRO_USED (set) \
+ ? MAP_START_LOCATION (LINEMAPS_LAST_MACRO_MAP (set)) \
+ : MAX_SOURCE_LOCATION)
+
+/* Returns the last macro map used in the line table SET. */
+#define LINEMAPS_LAST_MACRO_MAP(SET) \
+ LINEMAPS_LAST_MAP (SET, true)
+
+/* Returns the last macro map allocated in the line table SET. */
+#define LINEMAPS_LAST_ALLOCATED_MACRO_MAP(SET) \
+ LINEMAPS_LAST_ALLOCATED_MAP (SET, true)
+
/* Initialize a line map set. */
extern void linemap_init (struct line_maps *);
-/* Free a line map set. */
-extern void linemap_free (struct line_maps *);
-
/* Check for and warn about line_maps entered but not exited. */
extern void linemap_check_files_exited (struct line_maps *);
@@ -117,10 +417,12 @@ extern source_location linemap_line_start
(struct line_maps *set, linenum_type to_line, unsigned int max_column_hint);
/* Add a mapping of logical source line to physical source file and
- line number.
+ line number. This function creates an "ordinary map", which is a
+ map that records locations of tokens that are not part of macro
+ replacement-lists present at a macro expansion point.
The text pointed to by TO_FILE must have a lifetime
- at least as long as the final call to lookup_line (). An empty
+ 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.
@@ -131,41 +433,246 @@ extern const struct line_map *linemap_add
(struct line_maps *, enum lc_reason, unsigned int sysp,
const char *to_file, linenum_type to_line);
-/* Given a logical line, returns the map from which the corresponding
- (source file, line) pair can be deduced. */
+/* Given a logical source location, returns the map which the
+ corresponding (source file, line, column) triplet can be deduced
+ from. Since the set is built chronologically, the logical lines are
+ monotonic increasing, and so the list is sorted and we can use a
+ binary search. If no line map have been allocated yet, this
+ function returns NULL. */
extern const struct line_map *linemap_lookup
(struct line_maps *, source_location);
+/* Returns TRUE if the line table set tracks token locations accross
+ macro expansion, FALSE otherwise. */
+bool linemap_tracks_macro_expansion_locs_p (struct line_maps *);
+
+/* Return TRUE if MAP encodes locations coming from a macro
+ replacement-list at macro expansion point. */
+bool linemap_macro_expansion_map_p (const struct line_map *);
+
+/* Return the name of the macro associated to MACRO_MAP. */
+const char* linemap_map_get_macro_name (const struct line_map*);
+
+/* Return a positive value if LOCATION is the locus of a token that is
+ located in a system header, O otherwise. It returns 1 if LOCATION
+ is the locus of a token that is located in a system header, and 2
+ if LOCATION is the locus of a token located in a C system header
+ that therefore needs to be extern "C" protected in C++.
+
+ Note that this function returns 1 if LOCATION belongs to a token
+ that is part of a macro replacement-list defined in a system
+ header, but expanded in a non-system file. */
+int linemap_location_in_system_header_p (struct line_maps *,
+ source_location);
+
+/* Return TRUE if LOCATION is a source code location of a token coming
+ from a macro replacement-list at a macro expansion point, FALSE
+ otherwise. */
+bool linemap_location_from_macro_expansion_p (struct line_maps *,
+ source_location);
+
/* source_location values from 0 to RESERVED_LOCATION_COUNT-1 will
be reserved for libcpp user as special values, no token from libcpp
will contain any of those locations. */
#define RESERVED_LOCATION_COUNT 2
/* Converts a map and a source_location to source line. */
-#define SOURCE_LINE(MAP, LOC) \
- ((((LOC) - (MAP)->start_location) >> (MAP)->column_bits) + (MAP)->to_line)
-
-#define SOURCE_COLUMN(MAP, LOC) \
- (((LOC) - (MAP)->start_location) & ((1 << (MAP)->column_bits) - 1))
-
-/* Returns the last source line within a map. This is the (last) line
- of the #include, or other directive, that caused a map change. */
+#define SOURCE_LINE(MAP, LOC) \
+ (((((LOC) - linemap_check_ordinary (MAP)->start_location) \
+ >> (MAP)->d.ordinary.column_bits) + (MAP)->d.ordinary.to_line))
+
+/* Convert a map and source_location to source column number. */
+#define SOURCE_COLUMN(MAP, LOC) \
+ ((((LOC) - linemap_check_ordinary (MAP)->start_location) \
+ & ((1 << (MAP)->d.ordinary.column_bits) - 1)))
+
+/* Returns the last source line number within an ordinary map. This
+ is the (last) line of the #include, or other directive, that caused
+ a map change. */
#define LAST_SOURCE_LINE(MAP) \
SOURCE_LINE (MAP, LAST_SOURCE_LINE_LOCATION (MAP))
+
+/* Return the last column number within an ordinary map. */
#define LAST_SOURCE_COLUMN(MAP) \
SOURCE_COLUMN (MAP, LAST_SOURCE_LINE_LOCATION (MAP))
-#define LAST_SOURCE_LINE_LOCATION(MAP) \
- ((((MAP)[1].start_location - 1 - (MAP)->start_location) \
- & ~((1 << (MAP)->column_bits) - 1)) \
- + (MAP)->start_location)
-/* Returns the map a given map was included from. */
-#define INCLUDED_FROM(SET, MAP) (&(SET)->maps[(MAP)->included_from])
+/* Return the location of the last source line within an ordinary
+ map. */
+#define LAST_SOURCE_LINE_LOCATION(MAP) \
+ ((((linemap_check_ordinary (MAP)[1].start_location - 1 \
+ - (MAP)->start_location) \
+ & ~((1 << (MAP)->d.ordinary.column_bits) - 1)) \
+ + (MAP)->start_location))
+
+/* Returns the map a given map was included from, or NULL if the map
+ belongs to the main file, i.e, a file that wasn't included by
+ another one. */
+#define INCLUDED_FROM(SET, MAP) \
+ ((linemap_check_ordinary (MAP)->d.ordinary.included_from == -1) \
+ ? NULL \
+ : (&LINEMAPS_ORDINARY_MAPS (SET)[(MAP)->d.ordinary.included_from]))
/* Nonzero if the map is at the bottom of the include stack. */
-#define MAIN_FILE_P(MAP) ((MAP)->included_from < 0)
+#define MAIN_FILE_P(MAP) \
+ ((linemap_check_ordinary (MAP)->d.ordinary.included_from < 0))
+
+#if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
+
+/* Assertion macro to be used in line-map code. */
+#define linemap_assert(EXPR) \
+ do { \
+ if (! (EXPR)) \
+ abort (); \
+ } while (0)
+
+/* Assert that MAP encodes locations of tokens that are not part of
+ the replacement-list of a macro expansion. */
+#define linemap_check_ordinary(LINE_MAP) __extension__ \
+ ({linemap_assert (!linemap_macro_expansion_map_p (LINE_MAP)); \
+ (LINE_MAP);})
+#else
+#define linemap_assert(EXPR)
+#define linemap_check_ordinary(LINE_MAP) (LINE_MAP)
+#endif
+/* Encode and return a source_location from a column number. The
+ source line considered is the last source line used to call
+ linemap_line_start, i.e, the last source line which a location was
+ encoded from. */
extern source_location
-linemap_position_for_column (struct line_maps *set, unsigned int to_column);
+linemap_position_for_column (struct line_maps *, unsigned int);
+
+/* Encode and return a source location from a given line and
+ column. */
+source_location linemap_position_for_line_and_column (struct line_map *,
+ linenum_type,
+ unsigned int);
+/* Return the file this map is for. */
+#define LINEMAP_FILE(MAP) \
+ (linemap_check_ordinary (MAP)->d.ordinary.to_file)
+
+/* Return the line number this map started encoding location from. */
+#define LINEMAP_LINE(MAP) \
+ (linemap_check_ordinary (MAP)->d.ordinary.to_line)
+
+/* Return a positive value if map encodes locations from a system
+ header, 0 otherwise. Returns 1 if MAP encodes locations in a
+ system header and 2 if it encodes locations in a C system header
+ that therefore needs to be extern "C" protected in C++. */
+#define LINEMAP_SYSP(MAP) \
+ (linemap_check_ordinary (MAP)->d.ordinary.sysp)
+
+/* Return a positive value if PRE denotes the location of a token that
+ comes before the token of POST, 0 if PRE denotes the location of
+ the same token as the token for POST, and a negative value
+ otherwise. */
+int linemap_compare_locations (struct line_maps *set,
+ source_location pre,
+ source_location post);
+
+/* Return TRUE if LOC_A denotes the location a token that comes
+ topogically before the token denoted by location LOC_B, or if they
+ are equal. */
+#define linemap_location_before_p(SET, LOC_A, LOC_B) \
+ (linemap_compare_locations ((SET), (LOC_A), (LOC_B)) >= 0)
+
+typedef struct
+{
+ /* The name of the source file involved. */
+ const char *file;
+
+ /* The line-location in the source file. */
+ int line;
+
+ int column;
+
+ /* In a system header?. */
+ bool sysp;
+} expanded_location;
+
+/* This is enum is used by the function linemap_resolve_location
+ below. The meaning of the values is explained in the comment of
+ that function. */
+enum location_resolution_kind
+{
+ LRK_MACRO_EXPANSION_POINT,
+ LRK_SPELLING_LOCATION,
+ LRK_MACRO_DEFINITION_LOCATION
+};
+
+/* Resolve a virtual location into either a spelling location, an
+ expansion point location or a token argument replacement point
+ location. Return the map that encodes the virtual location as well
+ as the resolved location.
+
+ If LOC is *NOT* the location of a token resulting from the
+ expansion of a macro, then the parameter LRK (which stands for
+ Location Resolution Kind) is ignored and the resulting location
+ just equals the one given in argument.
+
+ Now if LOC *IS* the location of a token resulting from the
+ expansion of a macro, this is what happens.
+
+ * If LRK is set to LRK_MACRO_EXPANSION_POINT
+ -------------------------------
+
+ The virtual location is resolved to the first macro expansion point
+ that led to this macro expansion.
+
+ * If LRK is set to LRK_SPELLING_LOCATION
+ -------------------------------------
+
+ The virtual location is resolved to the locus where the token has
+ been spelled in the source. This can follow through all the macro
+ expansions that led to the token.
+
+ * If LRK is set to LRK_MACRO_DEFINITION_LOCATION
+ --------------------------------------
+
+ The virtual location is resolved to the locus of the token in the
+ context of the macro definition.
+
+ If LOC is the locus of a token that is an argument of a
+ function-like macro [replacing a parameter in the replacement list
+ of the macro] the virtual location is resolved to the locus of the
+ parameter that is replaced, in the context of the definition of the
+ macro.
+
+ If LOC is the locus of a token that is not an argument of a
+ function-like macro, then the function behaves as if LRK was set to
+ LRK_SPELLING_LOCATION.
+
+ If LOC_MAP is not NULL, *LOC_MAP is set to the map encoding the
+ returned location. */
+
+source_location linemap_resolve_location (struct line_maps *,
+ source_location loc,
+ enum location_resolution_kind lrk,
+ const struct line_map **loc_map);
+
+/* Suppose that LOC is the virtual location of a token coming from the
+ expansion of a macro M. This function then steps up to get the
+ location L of the point where M got expanded. If L is a spelling
+ location inside a macro expansion M', then this function returns
+ the point where M' was expanded. LOC_MAP is an output parameter.
+ When non-NULL, *LOC_MAP is set the the map of the returned
+ location. */
+source_location linemap_unwind_toward_expansion (struct line_maps *,
+ source_location loc,
+ const struct line_map **loc_map);
+
+/* Expand source code location LOC and return a user readable source
+ code location. LOC must be a spelling (non-virtual) location. */
+
+expanded_location linemap_expand_location (const struct line_map *,
+ source_location loc);
+
+/* Expand source code location LOC and return a user readable source
+ code location. LOC can be a virtual location. The LRK parameter
+ is the same as for linemap_resolve_location. */
+
+expanded_location linemap_expand_location_full (struct line_maps *,
+ source_location loc,
+ enum location_resolution_kind lrk);
#endif /* !LIBCPP_LINE_MAP_H */
diff --git a/libcpp/init.c b/libcpp/init.c
index c5c53256d35..6303868254e 100644
--- a/libcpp/init.c
+++ b/libcpp/init.c
@@ -586,7 +586,9 @@ cpp_read_main_file (cpp_reader *pfile, const char *fname)
if (CPP_OPTION (pfile, preprocessed))
{
read_original_filename (pfile);
- fname = pfile->line_table->maps[pfile->line_table->used-1].to_file;
+ 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 6c423f056bc..65bfa1db0de 100644
--- a/libcpp/internal.h
+++ b/libcpp/internal.h
@@ -67,7 +67,8 @@ struct cset_converter
#define CPP_INCREMENT_LINE(PFILE, COLS_HINT) do { \
const struct line_maps *line_table = PFILE->line_table; \
- const struct line_map *map = &line_table->maps[line_table->used-1]; \
+ const struct line_map *map = \
+ LINEMAPS_LAST_ORDINARY_MAP (line_table); \
linenum_type line = SOURCE_LINE (map, line_table->highest_line); \
linemap_line_start (PFILE->line_table, line + 1, COLS_HINT); \
} while (0)
@@ -739,6 +740,76 @@ ufputs (const unsigned char *s, FILE *f)
return fputs ((const char *)s, f);
}
+ /* In line-map.c. */
+
+/* Create a macro map. A macro map encodes source locations of tokens
+ that are part of a macro replacement-list, at a macro expansion
+ point. See the extensive comments of struct line_map and struct
+ line_map_macro, in line-map.h.
+
+ This map shall be created when the macro is expanded. The map
+ encodes the source location of the expansion point of the macro as
+ well as the "original" source location of each token that is part
+ of the macro replacement-list. If a macro is defined but never
+ expanded, it has no macro map. SET is the set of maps the macro
+ map should be part of. MACRO_NODE is the macro which the new macro
+ map should encode source locations for. EXPANSION is the location
+ of the expansion point of MACRO. For function-like macros
+ invocations, it's best to make it point to the closing parenthesis
+ of the macro, rather than the the location of the first character
+ of the macro. NUM_TOKENS is the number of tokens that are part of
+ the replacement-list of MACRO. */
+const struct line_map *linemap_enter_macro (struct line_maps *,
+ struct cpp_hashnode*,
+ source_location,
+ unsigned int);
+
+/* Create and return a virtual location for a token that is part of a
+ macro expansion-list at a macro expansion point. See the comment
+ inside struct line_map_macro to see what an expansion-list exactly
+ is.
+
+ A call to this function must come after a call to
+ linemap_enter_macro.
+
+ MAP is the map into which the source location is created. TOKEN_NO
+ is the index of the token in the macro replacement-list, starting
+ at number 0.
+
+ ORIG_LOC is the location of the token outside of this macro
+ expansion. If the token comes originally from the macro
+ definition, it is the locus in the macro definition; otherwise it
+ is a location in the context of the caller of this macro expansion
+ (which is a virtual location or a source location if the caller is
+ itself a macro expansion or not).
+
+ MACRO_DEFINITION_LOC is the location in the macro definition,
+ either of the token itself or of a macro parameter that it
+ replaces. */
+source_location linemap_add_macro_token (const struct line_map *,
+ unsigned int,
+ source_location,
+ source_location);
+
+/* Return the source line number corresponding to source location
+ LOCATION. SET is the line map set LOCATION comes from. If
+ LOCATION is the location of token that is part of the
+ expansion-list of a macro expansion return the line number of the
+ macro expansion point. */
+int linemap_get_expansion_line (struct line_maps *,
+ source_location);
+
+/* Return the path of the file corresponding to source code location
+ LOCATION.
+
+ If LOCATION is the location of a token that is part of the
+ replacement-list of a macro expansion return the file path of the
+ macro expansion point.
+
+ SET is the line map set LOCATION comes from. */
+const char* linemap_get_expansion_filename (struct line_maps *,
+ source_location);
+
#ifdef __cplusplus
}
#endif
diff --git a/libcpp/line-map.c b/libcpp/line-map.c
index 2a0749aad2e..49de2449be9 100644
--- a/libcpp/line-map.c
+++ b/libcpp/line-map.c
@@ -23,24 +23,37 @@ along with this program; see the file COPYING3. If not see
#include "config.h"
#include "system.h"
#include "line-map.h"
+#include "cpplib.h"
+#include "internal.h"
static void trace_include (const struct line_maps *, const struct line_map *);
+static const struct line_map * linemap_ordinary_map_lookup (struct line_maps *,
+ source_location);
+static const struct line_map* linemap_macro_map_lookup (struct line_maps *,
+ source_location);
+static source_location linemap_macro_map_loc_to_def_point
+(const struct line_map*, source_location);
+static source_location linemap_macro_map_loc_unwind_toward_spelling
+(const struct line_map*, source_location);
+static source_location linemap_macro_map_loc_to_exp_point
+(const struct line_map*, source_location);
+static source_location linemap_macro_loc_to_spelling_point
+(struct line_maps *, source_location, const struct line_map **);
+static source_location linemap_macro_loc_to_def_point (struct line_maps *,
+ source_location,
+ const struct line_map **);
+static source_location linemap_macro_loc_to_exp_point (struct line_maps *,
+ source_location,
+ const struct line_map **);
/* Initialize a line map set. */
void
linemap_init (struct line_maps *set)
{
- set->maps = NULL;
- set->allocated = 0;
- set->used = 0;
- set->trace_includes = false;
- set->depth = 0;
- set->cache = 0;
+ memset (set, 0, sizeof (struct line_maps));
set->highest_location = RESERVED_LOCATION_COUNT - 1;
set->highest_line = RESERVED_LOCATION_COUNT - 1;
- set->max_column_hint = 0;
- set->reallocator = 0;
}
/* Check for and warn about line_maps entered but not exited. */
@@ -51,23 +64,55 @@ linemap_check_files_exited (struct line_maps *set)
struct line_map *map;
/* Depending upon whether we are handling preprocessed input or
not, this can be a user error or an ICE. */
- for (map = &set->maps[set->used - 1]; ! MAIN_FILE_P (map);
+ for (map = LINEMAPS_LAST_ORDINARY_MAP (set);
+ ! MAIN_FILE_P (map);
map = INCLUDED_FROM (set, map))
fprintf (stderr, "line-map.c: file \"%s\" entered but not left\n",
- map->to_file);
+ ORDINARY_MAP_FILE_NAME (map));
}
-
-/* Free a line map set. */
-void
-linemap_free (struct line_maps *set)
+/* Create a new line map in the line map set SET, and return it.
+ REASON is the reason of creating the map. It determines the type
+ of map created (ordinary or macro map). Note that ordinary maps and
+ macro maps are allocated in different memory location. */
+
+static struct line_map *
+new_linemap (struct line_maps *set,
+ enum lc_reason reason)
{
- if (set->maps)
+ /* Depending on this variable, a macro map would be allocated in a
+ different memory location than an ordinary map. */
+ bool macro_map_p = (reason == LC_ENTER_MACRO);
+ struct line_map *result;
+
+ if (LINEMAPS_USED (set, macro_map_p) == LINEMAPS_ALLOCATED (set, macro_map_p))
{
- linemap_check_files_exited (set);
+ /* We ran out of allocated line maps. Let's allocate more. */
- free (set->maps);
+ line_map_realloc reallocator
+ = set->reallocator ? set->reallocator : xrealloc;
+ LINEMAPS_ALLOCATED (set, macro_map_p) =
+ 2 * LINEMAPS_ALLOCATED (set, macro_map_p) + 256;
+ LINEMAPS_MAPS (set, macro_map_p)
+ = (struct line_map *) (*reallocator) (LINEMAPS_MAPS (set, macro_map_p),
+ LINEMAPS_ALLOCATED (set,
+ macro_map_p)
+ * sizeof (struct line_map));
+ result =
+ &LINEMAPS_MAPS (set, macro_map_p)[LINEMAPS_USED (set, macro_map_p)];
+ memset (result, 0,
+ ((LINEMAPS_ALLOCATED (set, macro_map_p)
+ - LINEMAPS_USED (set, macro_map_p))
+ * sizeof (struct line_map)));
}
+ else
+ result =
+ &LINEMAPS_MAPS (set, macro_map_p)[LINEMAPS_USED (set, macro_map_p)];
+
+ LINEMAPS_USED (set, macro_map_p)++;
+
+ result->reason = reason;
+ return result;
}
/* Add a mapping of logical source line to physical source file and
@@ -90,23 +135,24 @@ linemap_add (struct line_maps *set, enum lc_reason reason,
struct line_map *map;
source_location start_location = set->highest_location + 1;
- if (set->used && start_location < set->maps[set->used - 1].start_location)
- abort ();
+ linemap_assert (!(LINEMAPS_ORDINARY_USED (set)
+ && (start_location
+ < 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));
- if (set->used == set->allocated)
+ /* If we are leaving the main file, return a NULL map. */
+ if (reason == LC_LEAVE
+ && MAIN_FILE_P (LINEMAPS_LAST_ORDINARY_MAP (set))
+ && to_file == NULL)
{
- line_map_realloc reallocator
- = set->reallocator ? set->reallocator : xrealloc;
- set->allocated = 2 * set->allocated + 256;
- set->maps
- = (struct line_map *) (*reallocator) (set->maps,
- set->allocated
- * sizeof (struct line_map));
- memset (&set->maps[set->used], 0, ((set->allocated - set->used)
- * sizeof (struct line_map)));
+ set->depth--;
+ return NULL;
}
- map = &set->maps[set->used];
+ map = new_linemap (set, reason);
if (to_file && *to_file == '\0' && reason != LC_RENAME_VERBATIM)
to_file = "<stdin>";
@@ -114,29 +160,35 @@ linemap_add (struct line_maps *set, enum lc_reason reason,
if (reason == LC_RENAME_VERBATIM)
reason = LC_RENAME;
- if (set->depth == 0 && reason == LC_RENAME)
- abort ();
-
if (reason == LC_LEAVE)
{
+ /* When we are just leaving an "included" file, and jump to the next
+ location inside the "includer" right after the #include
+ "included", this variable points the map in use right before the
+ #include "included", inside the same "includer" file. */
struct line_map *from;
bool error;
if (MAIN_FILE_P (map - 1))
{
- if (to_file == NULL)
- {
- set->depth--;
- return NULL;
- }
+ /* So this _should_ means we are leaving the main file --
+ effectively ending the compilation unit. But to_file not
+ being NULL means the caller thinks we are leaving to
+ another file. This is an erroneous behaviour but we'll
+ try to recover from it. Let's pretend we are not leaving
+ the main file. */
error = true;
reason = LC_RENAME;
from = map - 1;
}
else
{
+ /* (MAP - 1) points to the map we are leaving. The
+ map from which (MAP - 1) got included should be the map
+ that comes right before MAP in the same file. */
from = INCLUDED_FROM (set, map - 1);
- error = to_file && filename_cmp (from->to_file, to_file);
+ error = to_file && filename_cmp (ORDINARY_MAP_FILE_NAME (from),
+ to_file);
}
/* Depending upon whether we are handling preprocessed input or
@@ -148,55 +200,176 @@ linemap_add (struct line_maps *set, enum lc_reason reason,
/* A TO_FILE of NULL is special - we use the natural values. */
if (error || to_file == NULL)
{
- to_file = from->to_file;
+ to_file = ORDINARY_MAP_FILE_NAME (from);
to_line = SOURCE_LINE (from, from[1].start_location);
- sysp = from->sysp;
+ sysp = ORDINARY_MAP_IN_SYSTEM_HEADER_P (from);
}
}
- map->reason = reason;
- map->sysp = sysp;
- map->start_location = start_location;
- map->to_file = to_file;
- map->to_line = to_line;
- set->cache = set->used++;
- map->column_bits = 0;
+ linemap_assert (reason != LC_ENTER_MACRO);
+ ORDINARY_MAP_IN_SYSTEM_HEADER_P (map) = sysp;
+ MAP_START_LOCATION (map) = start_location;
+ ORDINARY_MAP_FILE_NAME (map) = to_file;
+ ORDINARY_MAP_STARTING_LINE_NUMBER (map) = to_line;
+ LINEMAPS_ORDINARY_CACHE (set) = LINEMAPS_ORDINARY_USED (set) - 1;
+ ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map) = 0;
set->highest_location = start_location;
set->highest_line = start_location;
set->max_column_hint = 0;
if (reason == LC_ENTER)
{
- map->included_from = set->depth == 0 ? -1 : (int) (set->used - 2);
+ ORDINARY_MAP_INCLUDER_FILE_INDEX (map) =
+ set->depth == 0 ? -1 : (int) (LINEMAPS_ORDINARY_USED (set) - 2);
set->depth++;
if (set->trace_includes)
trace_include (set, map);
}
else if (reason == LC_RENAME)
- map->included_from = map[-1].included_from;
+ ORDINARY_MAP_INCLUDER_FILE_INDEX (map) =
+ ORDINARY_MAP_INCLUDER_FILE_INDEX (&map[-1]);
else if (reason == LC_LEAVE)
{
set->depth--;
- map->included_from = INCLUDED_FROM (set, map - 1)->included_from;
+ ORDINARY_MAP_INCLUDER_FILE_INDEX (map) =
+ ORDINARY_MAP_INCLUDER_FILE_INDEX (INCLUDED_FROM (set, map - 1));
}
return map;
}
+/* Returns TRUE if the line table set tracks token locations accross
+ macro expansion, FALSE otherwise. */
+
+bool
+linemap_tracks_macro_expansion_locs_p (struct line_maps *set)
+{
+ return LINEMAPS_MACRO_MAPS (set) != NULL;
+}
+
+/* Create a macro map. A macro map encodes source locations of tokens
+ that are part of a macro replacement-list, at a macro expansion
+ point. See the extensive comments of struct line_map and struct
+ line_map_macro, in line-map.h.
+
+ This map shall be created when the macro is expanded. The map
+ encodes the source location of the expansion point of the macro as
+ well as the "original" source location of each token that is part
+ of the macro replacement-list. If a macro is defined but never
+ expanded, it has no macro map. SET is the set of maps the macro
+ map should be part of. MACRO_NODE is the macro which the new macro
+ map should encode source locations for. EXPANSION is the location
+ of the expansion point of MACRO. For function-like macros
+ invocations, it's best to make it point to the closing parenthesis
+ of the macro, rather than the the location of the first character
+ of the macro. NUM_TOKENS is the number of tokens that are part of
+ the replacement-list of MACRO.
+
+ Note that when we run out of the integer space available for source
+ locations, this function returns NULL. In that case, callers of
+ this function cannot encode {line,column} pairs into locations of
+ macro tokens anymore. */
+
+const struct line_map *
+linemap_enter_macro (struct line_maps *set, struct cpp_hashnode *macro_node,
+ source_location expansion, unsigned int num_tokens)
+{
+ struct line_map *map;
+ source_location start_location;
+ line_map_realloc reallocator
+ = set->reallocator ? set->reallocator : xrealloc;
+
+ start_location = LINEMAPS_MACRO_LOWEST_LOCATION (set) - num_tokens;
+
+ if (start_location <= set->highest_line
+ || start_location > LINEMAPS_MACRO_LOWEST_LOCATION (set))
+ /* We ran out of macro map space. */
+ return NULL;
+
+ map = new_linemap (set, LC_ENTER_MACRO);
+
+ MAP_START_LOCATION (map) = start_location;
+ MACRO_MAP_MACRO (map) = macro_node;
+ MACRO_MAP_NUM_MACRO_TOKENS (map) = num_tokens;
+ MACRO_MAP_LOCATIONS (map)
+ = (source_location*) reallocator (NULL,
+ 2 * num_tokens
+ * sizeof (source_location));
+ MACRO_MAP_EXPANSION_POINT_LOCATION (map) = expansion;
+ memset (MACRO_MAP_LOCATIONS (map), 0,
+ num_tokens * sizeof (source_location));
+
+ LINEMAPS_MACRO_CACHE (set) = LINEMAPS_MACRO_USED (set) - 1;
+ set->max_column_hint = 0;
+
+ return map;
+}
+
+/* Create and return a virtual location for a token that is part of a
+ macro expansion-list at a macro expansion point. See the comment
+ inside struct line_map_macro to see what an expansion-list exactly
+ is.
+
+ A call to this function must come after a call to
+ linemap_enter_macro.
+
+ MAP is the map into which the source location is created. TOKEN_NO
+ is the index of the token in the macro replacement-list, starting
+ at number 0.
+
+ ORIG_LOC is the location of the token outside of this macro
+ expansion. If the token comes originally from the macro
+ definition, it is the locus in the macro definition; otherwise it
+ is a location in the context of the caller of this macro expansion
+ (which is a virtual location or a source location if the caller is
+ itself a macro expansion or not).
+
+ MACRO_DEFINITION_LOC is the location in the macro definition,
+ either of the token itself or of a macro parameter that it
+ replaces. */
+
+source_location
+linemap_add_macro_token (const struct line_map *map,
+ unsigned int token_no,
+ source_location orig_loc,
+ source_location orig_parm_replacement_loc)
+{
+ source_location result;
+
+ linemap_assert (linemap_macro_expansion_map_p (map));
+ linemap_assert (token_no < MACRO_MAP_NUM_MACRO_TOKENS (map));
+
+ MACRO_MAP_LOCATIONS (map)[2 * token_no] = orig_loc;
+ MACRO_MAP_LOCATIONS (map)[2 * token_no + 1] = orig_parm_replacement_loc;
+
+ result = MAP_START_LOCATION (map) + token_no;
+ return result;
+}
+
+/* Return a source_location for the start (i.e. column==0) of
+ (physical) line TO_LINE in the current source file (as in the
+ most recent linemap_add). MAX_COLUMN_HINT is the highest column
+ number we expect to use in this line (but it does not change
+ the highest_location). */
+
source_location
linemap_line_start (struct line_maps *set, linenum_type to_line,
unsigned int max_column_hint)
{
- struct line_map *map = &set->maps[set->used - 1];
+ struct line_map *map = LINEMAPS_LAST_ORDINARY_MAP (set);
source_location highest = set->highest_location;
source_location r;
- linenum_type last_line = SOURCE_LINE (map, set->highest_line);
+ linenum_type last_line =
+ SOURCE_LINE (map, set->highest_line);
int line_delta = to_line - last_line;
bool add_map = false;
+
if (line_delta < 0
- || (line_delta > 10 && line_delta * map->column_bits > 1000)
- || (max_column_hint >= (1U << map->column_bits))
- || (max_column_hint <= 80 && map->column_bits >= 10))
+ || (line_delta > 10
+ && line_delta * ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map) > 1000)
+ || (max_column_hint >= (1U << ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map)))
+ || (max_column_hint <= 80
+ && ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map) >= 10))
{
add_map = true;
}
@@ -224,16 +397,27 @@ linemap_line_start (struct line_maps *set, linenum_type to_line,
/* Allocate the new line_map. However, if the current map only has a
single line we can sometimes just increase its column_bits instead. */
if (line_delta < 0
- || last_line != map->to_line
+ || last_line != ORDINARY_MAP_STARTING_LINE_NUMBER (map)
|| SOURCE_COLUMN (map, highest) >= (1U << column_bits))
- map = (struct line_map *) linemap_add (set, LC_RENAME, map->sysp,
- map->to_file, to_line);
- map->column_bits = column_bits;
- r = map->start_location + ((to_line - map->to_line) << column_bits);
+ map = (struct line_map *) linemap_add (set, LC_RENAME,
+ ORDINARY_MAP_IN_SYSTEM_HEADER_P
+ (map),
+ ORDINARY_MAP_FILE_NAME (map),
+ to_line);
+ ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map) = column_bits;
+ r = (MAP_START_LOCATION (map)
+ + ((to_line - ORDINARY_MAP_STARTING_LINE_NUMBER (map))
+ << column_bits));
}
else
r = highest - SOURCE_COLUMN (map, highest)
- + (line_delta << map->column_bits);
+ + (line_delta << ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map));
+
+ /* Locations of ordinary tokens are always lower than locations of
+ macro tokens. */
+ if (r >= LINEMAPS_MACRO_LOWEST_LOCATION (set))
+ return 0;
+
set->highest_line = r;
if (r > set->highest_location)
set->highest_location = r;
@@ -241,10 +425,19 @@ linemap_line_start (struct line_maps *set, linenum_type to_line,
return r;
}
+/* Encode and return a source_location from a column number. The
+ source line considered is the last source line used to call
+ linemap_line_start, i.e, the last source line which a location was
+ encoded from. */
+
source_location
linemap_position_for_column (struct line_maps *set, unsigned int to_column)
{
source_location r = set->highest_line;
+
+ linemap_assert
+ (!linemap_macro_expansion_map_p (LINEMAPS_LAST_ORDINARY_MAP (set)));
+
if (to_column >= set->max_column_hint)
{
if (r >= 0xC000000 || to_column > 100000)
@@ -254,7 +447,7 @@ linemap_position_for_column (struct line_maps *set, unsigned int to_column)
}
else
{
- struct line_map *map = &set->maps[set->used - 1];
+ struct line_map *map = LINEMAPS_LAST_ORDINARY_MAP (set);
r = linemap_line_start (set, SOURCE_LINE (map, r), to_column + 50);
}
}
@@ -264,25 +457,55 @@ linemap_position_for_column (struct line_maps *set, unsigned int to_column)
return r;
}
-/* Given a logical line, returns the map from which the corresponding
- (source file, line) pair can be deduced. Since the set is built
- chronologically, the logical lines are monotonic increasing, and so
- the list is sorted and we can use a binary search. */
+/* Encode and return a source location from a given line and
+ column. */
-const struct line_map *
+source_location
+linemap_position_for_line_and_column (struct line_map *map,
+ linenum_type line,
+ unsigned column)
+{
+ linemap_assert (ORDINARY_MAP_STARTING_LINE_NUMBER (map) <= line);
+
+ return (MAP_START_LOCATION (map)
+ + ((line - ORDINARY_MAP_STARTING_LINE_NUMBER (map))
+ << ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map))
+ + (column & ((1 << ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map)) - 1)));
+}
+
+/* Given a virtual source location yielded by a map (either an
+ ordinary or a macro map), returns that map. */
+
+const struct line_map*
linemap_lookup (struct line_maps *set, source_location line)
{
+ if (linemap_location_from_macro_expansion_p (set, line))
+ return linemap_macro_map_lookup (set, line);
+ return linemap_ordinary_map_lookup (set, line);
+}
+
+/* Given a source location yielded by an ordinary map, returns that
+ map. Since the set is built chronologically, the logical lines are
+ monotonic increasing, and so the list is sorted and we can use a
+ binary search. */
+
+static const struct line_map *
+linemap_ordinary_map_lookup (struct line_maps *set, source_location line)
+{
unsigned int md, mn, mx;
- const struct line_map *cached;
+ const struct line_map *cached, *result;
- mn = set->cache;
- mx = set->used;
+ if (set == NULL || line < RESERVED_LOCATION_COUNT)
+ return NULL;
+
+ mn = LINEMAPS_ORDINARY_CACHE (set);
+ mx = LINEMAPS_ORDINARY_USED (set);
- cached = &set->maps[mn];
+ cached = LINEMAPS_ORDINARY_MAP_AT (set, mn);
/* We should get a segfault if no line_maps have been added yet. */
- if (line >= cached->start_location)
+ if (line >= MAP_START_LOCATION (cached))
{
- if (mn + 1 == mx || line < cached[1].start_location)
+ if (mn + 1 == mx || line < MAP_START_LOCATION (&cached[1]))
return cached;
}
else
@@ -294,14 +517,345 @@ linemap_lookup (struct line_maps *set, source_location line)
while (mx - mn > 1)
{
md = (mn + mx) / 2;
- if (set->maps[md].start_location > line)
+ if (MAP_START_LOCATION (LINEMAPS_ORDINARY_MAP_AT (set, md)) > line)
mx = md;
else
mn = md;
}
- set->cache = mn;
- return &set->maps[mn];
+ LINEMAPS_ORDINARY_CACHE (set) = mn;
+ result = LINEMAPS_ORDINARY_MAP_AT (set, mn);
+ linemap_assert (line >= MAP_START_LOCATION (result));
+ return result;
+}
+
+/* Given a source location yielded by a macro map, returns that map.
+ Since the set is built chronologically, the logical lines are
+ monotonic decreasing, and so the list is sorted and we can use a
+ binary search. */
+
+static const struct line_map*
+linemap_macro_map_lookup (struct line_maps *set, source_location line)
+{
+ unsigned int md, mn, mx;
+ const struct line_map *cached, *result;
+
+ linemap_assert (line >= LINEMAPS_MACRO_LOWEST_LOCATION (set));
+
+ if (set == NULL)
+ return NULL;
+
+ mn = LINEMAPS_MACRO_CACHE (set);
+ mx = LINEMAPS_MACRO_USED (set);
+ cached = LINEMAPS_MACRO_MAP_AT (set, mn);
+
+ if (line >= MAP_START_LOCATION (cached))
+ {
+ if (mn == 0 || line < MAP_START_LOCATION (&cached[-1]))
+ return cached;
+ mx = mn - 1;
+ mn = 0;
+ }
+
+ do
+ {
+ md = (mx + mn) / 2;
+ if (MAP_START_LOCATION (LINEMAPS_MACRO_MAP_AT (set, md)) > line)
+ mn = md;
+ else
+ mx = md;
+ } while (mx - mn > 1);
+
+ LINEMAPS_MACRO_CACHE (set) = mx;
+ result = LINEMAPS_MACRO_MAP_AT (set, LINEMAPS_MACRO_CACHE (set));
+ linemap_assert (MAP_START_LOCATION (result) <= line);
+
+ return result;
+}
+
+/* Return TRUE if MAP encodes locations coming from a macro
+ replacement-list at macro expansion point. */
+
+bool
+linemap_macro_expansion_map_p (const struct line_map *map)
+{
+ if (!map)
+ return false;
+ return (map->reason == LC_ENTER_MACRO);
+}
+
+/* If LOCATION is the locus of a token in a replacement-list of a
+ macro expansion return the location of the macro expansion point.
+
+ Read the comments of struct line_map and struct line_map_macro in
+ line-map.h to understand what a macro expansion point is. */
+
+source_location
+linemap_macro_map_loc_to_exp_point (const struct line_map *map,
+ source_location location)
+{
+ unsigned token_no;
+
+ linemap_assert (linemap_macro_expansion_map_p (map)
+ && location >= MAP_START_LOCATION (map));
+
+ /* Make sure LOCATION is correct. */
+ token_no = location - MAP_START_LOCATION (map);
+ linemap_assert (token_no < MACRO_MAP_NUM_MACRO_TOKENS (map));
+
+ return MACRO_MAP_EXPANSION_POINT_LOCATION (map);
+}
+
+/* If LOCATION is the source location of a token that belongs to a
+ macro replacement-list -- as part of a macro expansion -- then
+ return the location of the token at the definition point of the
+ macro. Otherwise, return LOCATION. SET is the set of maps
+ location come from. ORIGINAL_MAP is an output parm. If non NULL,
+ the function sets *ORIGINAL_MAP to the ordinary (non-macro) map the
+ returned location comes from. */
+
+source_location
+linemap_macro_map_loc_to_def_point (const struct line_map *map,
+ source_location location)
+{
+ unsigned token_no;
+
+ linemap_assert (linemap_macro_expansion_map_p (map)
+ && location >= MAP_START_LOCATION (map));
+ linemap_assert (location >= RESERVED_LOCATION_COUNT);
+
+ token_no = location - MAP_START_LOCATION (map);
+ linemap_assert (token_no < MACRO_MAP_NUM_MACRO_TOKENS (map));
+
+ location = MACRO_MAP_LOCATIONS (map)[2 * token_no + 1];
+
+ return location;
+}
+
+/* If LOCATION is the locus of a token that is an argument of a
+ function-like macro M and appears in the expansion of M, return the
+ locus of that argument in the context of the caller of M.
+
+ In other words, this returns the xI location presented in the
+ comments of line_map_macro above. */
+source_location
+linemap_macro_map_loc_unwind_toward_spelling (const struct line_map* map,
+ source_location location)
+{
+ unsigned token_no;
+
+ linemap_assert (linemap_macro_expansion_map_p (map)
+ && location >= MAP_START_LOCATION (map));
+ linemap_assert (location >= RESERVED_LOCATION_COUNT);
+
+ token_no = location - MAP_START_LOCATION (map);
+ linemap_assert (token_no < MACRO_MAP_NUM_MACRO_TOKENS (map));
+
+ location = MACRO_MAP_LOCATIONS (map)[2 * token_no];
+
+ return location;
+}
+
+/* Return the source line number corresponding to source location
+ LOCATION. SET is the line map set LOCATION comes from. If
+ LOCATION is the source location of token that is part of the
+ replacement-list of a macro expansion return the line number of the
+ macro expansion point. */
+
+int
+linemap_get_expansion_line (struct line_maps *set,
+ source_location location)
+{
+ const struct line_map *map = NULL;
+
+ if (location < RESERVED_LOCATION_COUNT)
+ return 0;
+
+ location =
+ linemap_macro_loc_to_exp_point (set, location, &map);
+
+ return SOURCE_LINE (map, location);
+}
+
+/* Return the path of the file corresponding to source code location
+ LOCATION.
+
+ If LOCATION is the source location of token that is part of the
+ replacement-list of a macro expansion return the file path of the
+ macro expansion point.
+
+ SET is the line map set LOCATION comes from. */
+
+const char*
+linemap_get_expansion_filename (struct line_maps *set,
+ source_location location)
+{
+ const struct line_map *map = NULL;
+
+ if (location < RESERVED_LOCATION_COUNT)
+ return NULL;
+
+ location =
+ linemap_macro_loc_to_exp_point (set, location, &map);
+
+ return LINEMAP_FILE (map);
+}
+
+/* Return the name of the macro associated to MACRO_MAP. */
+
+const char*
+linemap_map_get_macro_name (const struct line_map* macro_map)
+{
+ linemap_assert (macro_map && linemap_macro_expansion_map_p (macro_map));
+ return (const char*) NODE_NAME (MACRO_MAP_MACRO (macro_map));
+}
+
+/* Return a positive value if LOCATION is the locus of a token that is
+ located in a system header, O otherwise. It returns 1 if LOCATION
+ is the locus of a token that is located in a system header, and 2
+ if LOCATION is the locus of a token located in a C system header
+ that therefore needs to be extern "C" protected in C++.
+
+ Note that this function returns 1 if LOCATION belongs to a token
+ that is part of a macro replacement-list defined in a system
+ header, but expanded in a non-system file. */
+
+int
+linemap_location_in_system_header_p (struct line_maps *set,
+ source_location location)
+{
+ const struct line_map *map = NULL;
+
+ if (location < RESERVED_LOCATION_COUNT)
+ return false;
+
+ location =
+ linemap_resolve_location (set, location, LRK_SPELLING_LOCATION, &map);
+
+ return LINEMAP_SYSP (map);
+}
+
+/* Return TRUE if LOCATION is a source code location of a token coming
+ from a macro replacement-list at a macro expansion point, FALSE
+ otherwise. */
+
+bool
+linemap_location_from_macro_expansion_p (struct line_maps *set,
+ source_location location)
+{
+ linemap_assert (location <= MAX_SOURCE_LOCATION
+ && (set->highest_location
+ < LINEMAPS_MACRO_LOWEST_LOCATION (set)));
+ if (set == NULL)
+ return false;
+ return (location > set->highest_location);
+}
+
+/* Given two virtual locations *LOC0 and *LOC1, return the first
+ common macro map in their macro expansion histories. Return NULL
+ if no common macro was found. *LOC0 (resp. *LOC1) is set to the
+ virtual location of the token inside the resulting macro. */
+
+static const struct line_map*
+first_map_in_common_1 (struct line_maps *set,
+ source_location *loc0,
+ source_location *loc1)
+{
+ source_location l0 = *loc0, l1 = *loc1;
+ const struct line_map *map0 = linemap_lookup (set, l0),
+ *map1 = linemap_lookup (set, l1);
+
+ while (linemap_macro_expansion_map_p (map0)
+ && linemap_macro_expansion_map_p (map1)
+ && (map0 != map1))
+ {
+ if (MAP_START_LOCATION (map0) < MAP_START_LOCATION (map1))
+ {
+ l0 = linemap_macro_map_loc_to_exp_point (map0, l0);
+ map0 = linemap_lookup (set, l0);
+ }
+ else
+ {
+ l1 = linemap_macro_map_loc_to_exp_point (map1, l1);
+ map1 = linemap_lookup (set, l1);
+ }
+ }
+
+ if (map0 == map1)
+ {
+ *loc0 = l0;
+ *loc1 = l1;
+ return map0;
+ }
+ return NULL;
+}
+
+/* Given two virtual locations LOC0 and LOC1, return the first common
+ macro map in their macro expansion histories. Return NULL if no
+ common macro was found. *RES_LOC0 (resp. *RES_LOC1) is set to the
+ virtual location of the token inside the resulting macro, upon
+ return of a non-NULL result. */
+
+static const struct line_map*
+first_map_in_common (struct line_maps *set,
+ source_location loc0,
+ source_location loc1,
+ source_location *res_loc0,
+ source_location *res_loc1)
+{
+ *res_loc0 = loc0;
+ *res_loc1 = loc1;
+
+ return first_map_in_common_1 (set, res_loc0, res_loc1);
+}
+
+/* Return a positive value if PRE denotes the location of a token that
+ comes before the token of POST, 0 if PRE denotes the location of
+ the same token as the token for POST, and a negative value
+ otherwise. */
+
+int
+linemap_compare_locations (struct line_maps *set,
+ source_location pre,
+ source_location post)
+{
+ bool pre_virtual_p, post_virtual_p;
+ source_location l0 = pre, l1 = post;
+
+ if (l0 == l1)
+ return 0;
+
+ if ((pre_virtual_p = linemap_location_from_macro_expansion_p (set, l0)))
+ l0 = linemap_resolve_location (set, l0,
+ LRK_MACRO_EXPANSION_POINT,
+ NULL);
+
+ if ((post_virtual_p = linemap_location_from_macro_expansion_p (set, l1)))
+ l1 = linemap_resolve_location (set, l1,
+ LRK_MACRO_EXPANSION_POINT,
+ NULL);
+
+ if (l0 == l1
+ && pre_virtual_p
+ && post_virtual_p)
+ {
+ /* So pre and post represent two tokens that are present in a
+ same macro expansion. Let's see if the token for pre was
+ before the token for post in that expansion. */
+ unsigned i0, i1;
+ const struct line_map *map =
+ first_map_in_common (set, pre, post, &l0, &l1);
+
+ if (map == NULL)
+ /* This should not be possible. */
+ abort ();
+
+ i0 = l0 - MAP_START_LOCATION (map);
+ i1 = l1 - MAP_START_LOCATION (map);
+ return i1 - i0;
+ }
+
+ return l1 - l0;
}
/* Print an include trace, for e.g. the -H option of the preprocessor. */
@@ -313,5 +867,241 @@ trace_include (const struct line_maps *set, const struct line_map *map)
while (--i)
putc ('.', stderr);
- fprintf (stderr, " %s\n", map->to_file);
+
+ fprintf (stderr, " %s\n", ORDINARY_MAP_FILE_NAME (map));
+}
+
+/* Return the spelling location of the token wherever it comes from,
+ whether part of a macro definition or not.
+
+ This is a subroutine for linemap_resolve_location. */
+
+static source_location
+linemap_macro_loc_to_spelling_point (struct line_maps *set,
+ source_location location,
+ const struct line_map **original_map)
+{
+ struct line_map *map;
+
+ linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
+
+ while (true)
+ {
+ map = (struct line_map*) linemap_lookup (set, location);
+ if (!linemap_macro_expansion_map_p (map))
+ break;
+
+ location =
+ linemap_macro_map_loc_unwind_toward_spelling (map, location);
+ }
+
+ if (original_map)
+ *original_map = map;
+ return location;
+}
+
+/* If LOCATION is the source location of a token that belongs to a
+ macro replacement-list -- as part of a macro expansion -- then
+ return the location of the token at the definition point of the
+ macro. Otherwise, return LOCATION. SET is the set of maps
+ location come from. ORIGINAL_MAP is an output parm. If non NULL,
+ the function sets *ORIGINAL_MAP to the ordinary (non-macro) map the
+ returned location comes from.
+
+ This is a subroutine of linemap_resolve_location. */
+
+static source_location
+linemap_macro_loc_to_def_point (struct line_maps *set,
+ source_location location,
+ const struct line_map **original_map)
+{
+ struct line_map *map;
+
+ linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
+
+ while (true)
+ {
+ map = (struct line_map*) linemap_lookup (set, location);
+ if (!linemap_macro_expansion_map_p (map))
+ break;
+
+ location =
+ linemap_macro_map_loc_to_def_point (map, location);
+ }
+
+ if (original_map)
+ *original_map = map;
+ return location;
+}
+
+/* If LOCATION is the source location of a token that belongs to a
+ macro replacement-list -- at a macro expansion point -- then return
+ the location of the topmost expansion point of the macro. We say
+ topmost because if we are in the context of a nested macro
+ expansion, the function returns the source location of the first
+ macro expansion that triggered the nested expansions.
+
+ Otherwise, return LOCATION. SET is the set of maps location come
+ from. ORIGINAL_MAP is an output parm. If non NULL, the function
+ sets *ORIGINAL_MAP to the ordinary (non-macro) map the returned
+ location comes from.
+
+ This is a subroutine of linemap_resolve_location. */
+
+static source_location
+linemap_macro_loc_to_exp_point (struct line_maps *set,
+ source_location location,
+ const struct line_map **original_map)
+{
+ struct line_map *map;
+
+ linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
+
+ while (true)
+ {
+ map = (struct line_map*) linemap_lookup (set, location);
+ if (!linemap_macro_expansion_map_p (map))
+ break;
+ location = linemap_macro_map_loc_to_exp_point (map, location);
+ }
+
+ if (original_map)
+ *original_map = map;
+ return location;
+}
+
+/* Resolve a virtual location into either a spelling location, an
+ expansion point location or a token argument replacement point
+ location. Return the map that encodes the virtual location as well
+ as the resolved location.
+
+ If LOC is *NOT* the location of a token resulting from the
+ expansion of a macro, then the parameter LRK (which stands for
+ Location Resolution Kind) is ignored and the resulting location
+ just equals the one given in argument.
+
+ Now if LOC *IS* the location of a token resulting from the
+ expansion of a macro, this is what happens.
+
+ * If LRK is set to LRK_MACRO_EXPANSION_POINT
+ -------------------------------
+
+ The virtual location is resolved to the location to the locus of
+ the expansion point of the macro.
+
+ * If LRK is set to LRK_SPELLING_LOCATION
+ -------------------------------------
+
+ The virtual location is resolved to the location to the locus where
+ the token has been spelled in the source. This can follow through
+ all the macro expansions that led to the token.
+
+ * If LRK is set to LRK_MACRO_PARM_REPLACEMENT_POINT
+ --------------------------------------
+
+ If LOC is the locus of a token that is an argument of a
+ function-like macro [replacing a parameter in the replacement list
+ of the macro] the virtual location is resolved to the locus of the
+ parameter that is replaced, in the context of the definition of the
+ macro.
+
+ If LOC is the locus of a token that is not an argument of a
+ function-like macro, then the function behaves as if LRK was set to
+ LRK_SPELLING_LOCATION.
+
+ If MAP is non-NULL, *MAP is set to the map of the resolved
+ location. */
+
+source_location
+linemap_resolve_location (struct line_maps *set,
+ source_location loc,
+ enum location_resolution_kind lrk,
+ const struct line_map **map)
+{
+ linemap_assert (set && loc >= RESERVED_LOCATION_COUNT);
+
+ switch (lrk)
+ {
+ case LRK_MACRO_EXPANSION_POINT:
+ loc = linemap_macro_loc_to_exp_point (set, loc, map);
+ break;
+ case LRK_SPELLING_LOCATION:
+ loc = linemap_macro_loc_to_spelling_point (set, loc, map);
+ break;
+ case LRK_MACRO_DEFINITION_LOCATION:
+ loc = linemap_macro_loc_to_def_point (set, loc, map);
+ break;
+ default:
+ abort ();
+ }
+ return loc;
+}
+
+/*
+ Suppose that LOC is the virtual location of a token T coming from
+ the expansion of a macro M. This function then steps up to get the
+ location L of the point where M got expanded. If L is a spelling
+ location inside a macro expansion M', then this function returns
+ the locus of the point where M' was expanded. Said otherwise, this
+ function returns the location of T in the context that triggered
+ the expansion of M.
+
+ *LOC_MAP must be set to the map of LOC. This function then sets it
+ to the map of the returned location. */
+
+source_location
+linemap_unwind_toward_expansion (struct line_maps *set,
+ source_location loc,
+ const struct line_map **map)
+{
+ source_location resolved_location;
+ const struct line_map *resolved_map;
+
+ resolved_location =
+ linemap_macro_map_loc_unwind_toward_spelling (*map, loc);
+ resolved_map = linemap_lookup (set, resolved_location);
+
+ if (!linemap_macro_expansion_map_p (resolved_map))
+ {
+ resolved_location = linemap_macro_map_loc_to_exp_point (*map, loc);
+ resolved_map = linemap_lookup (set, resolved_location);
+ }
+
+ *map = resolved_map;
+ return resolved_location;
+}
+
+/* Expand source code location LOC and return a user readable source
+ code location. LOC must be a spelling (non-virtual) location. */
+
+expanded_location
+linemap_expand_location (const struct line_map *map,
+ source_location loc)
+
+{
+ expanded_location xloc;
+
+ xloc.file = LINEMAP_FILE (map);
+ xloc.line = SOURCE_LINE (map, loc);
+ xloc.column = SOURCE_COLUMN (map, loc);
+ xloc.sysp = LINEMAP_SYSP (map) != 0;
+
+ return xloc;
+}
+
+/* Expand source code location LOC and return a user readable source
+ code location. LOC can be a virtual location. The LRK parameter
+ is the same as for linemap_resolve_location. */
+
+expanded_location
+linemap_expand_location_full (struct line_maps *set,
+ source_location loc,
+ enum location_resolution_kind lrk)
+{
+ const struct line_map *map;
+ expanded_location xloc;
+
+ loc = linemap_resolve_location (set, loc, lrk, &map);
+ xloc = linemap_expand_location (map, loc);
+ return xloc;
}
diff --git a/libcpp/macro.c b/libcpp/macro.c
index eba2349954a..defc4866bd3 100644
--- a/libcpp/macro.c
+++ b/libcpp/macro.c
@@ -171,13 +171,17 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node)
unsigned int len;
const char *name;
uchar *buf;
- map = linemap_lookup (pfile->line_table, pfile->line_table->highest_line);
-
- if (node->value.builtin == BT_BASE_FILE)
- while (! MAIN_FILE_P (map))
- map = INCLUDED_FROM (pfile->line_table, map);
-
- name = map->to_file;
+
+ if (node->value.builtin == BT_FILE)
+ name = linemap_get_expansion_filename (pfile->line_table,
+ pfile->line_table->highest_line);
+ else
+ {
+ map = linemap_lookup (pfile->line_table, pfile->line_table->highest_line);
+ while (! MAIN_FILE_P (map))
+ map = INCLUDED_FROM (pfile->line_table, map);
+ name = ORDINARY_MAP_FILE_NAME (map);
+ }
len = strlen (name);
buf = _cpp_unaligned_alloc (pfile, len * 2 + 3);
result = buf;
@@ -196,14 +200,14 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node)
break;
case BT_SPECLINE:
- map = &pfile->line_table->maps[pfile->line_table->used-1];
+ map = LINEMAPS_LAST_ORDINARY_MAP (pfile->line_table);
/* If __LINE__ is embedded in a macro, it must expand to the
line of the macro's invocation, not its definition.
Otherwise things like assert() will not work properly. */
- number = SOURCE_LINE (map,
- CPP_OPTION (pfile, traditional)
- ? pfile->line_table->highest_line
- : pfile->cur_token[-1].src_loc);
+ number = linemap_get_expansion_line (pfile->line_table,
+ CPP_OPTION (pfile, traditional)
+ ? pfile->line_table->highest_line
+ : pfile->cur_token[-1].src_loc);
break;
/* __STDC__ has the value 1 under normal circumstances.
OpenPOWER on IntegriCloud