From e81c3c4dc14a3a927f643ab15fcb8ecbcfc088f5 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Tue, 7 Aug 2018 21:28:51 +0000 Subject: [PATCH] Line map table allocation https://gcc.gnu.org/ml/gcc-patches/2018-08/msg00434.html * line-map.c: (linemap_init): Set default allocator here. (new_linemap): Rather than here. Refactor allocation logic. From-SVN: r263366 --- libcpp/ChangeLog | 5 +++ libcpp/line-map.c | 100 ++++++++++++++++++++++-------------------------------- 2 files changed, 45 insertions(+), 60 deletions(-) (limited to 'libcpp') diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index c72804f..50fa253 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,3 +1,8 @@ +2018-08-07 Nathan Sidwell + + * line-map.c: (linemap_init): Set default allocator here. + (new_linemap): Rather than here. Refactor allocation logic. + 2018-07-20 David Malcolm * include/line-map.h (rich_location::set_range): Remove redundant diff --git a/libcpp/line-map.c b/libcpp/line-map.c index a1a765f..a5dc485 100644 --- a/libcpp/line-map.c +++ b/libcpp/line-map.c @@ -346,6 +346,8 @@ linemap_init (struct line_maps *set, #else new (set) line_maps(); #endif + /* Set default reallocator (used for initial alloc too). */ + set->reallocator = xrealloc; set->highest_location = RESERVED_LOCATION_COUNT - 1; set->highest_line = RESERVED_LOCATION_COUNT - 1; set->location_adhoc_data_map.htab = @@ -376,81 +378,59 @@ linemap_check_files_exited (struct line_maps *set) static struct line_map * new_linemap (struct line_maps *set, source_location start_location) { - struct line_map *result; - bool macro_map_p = start_location >= LINE_MAP_MAX_LOCATION; + bool macro_p = start_location >= LINE_MAP_MAX_LOCATION; + unsigned num_maps_allocated = LINEMAPS_ALLOCATED (set, macro_p); + unsigned num_maps_used = LINEMAPS_USED (set, macro_p); - if (LINEMAPS_USED (set, macro_map_p) == LINEMAPS_ALLOCATED (set, macro_map_p)) + if (num_maps_used == num_maps_allocated) { - /* We ran out of allocated line maps. Let's allocate more. */ - size_t alloc_size; - - /* Cast away extern "C" from the type of xrealloc. */ - line_map_realloc reallocator = (set->reallocator - ? set->reallocator - : (line_map_realloc) xrealloc); - line_map_round_alloc_size_func round_alloc_size = - set->round_alloc_size; - - size_t map_size = (macro_map_p - ? sizeof (line_map_macro) - : sizeof (line_map_ordinary)); + /* We need more space! */ + if (!num_maps_allocated) + num_maps_allocated = 128; + num_maps_allocated *= 2; + + size_t size_of_a_map; + void *buffer; + if (macro_p) + { + size_of_a_map = sizeof (line_map_macro); + buffer = set->info_macro.maps; + } + else + { + size_of_a_map = sizeof (line_map_ordinary); + buffer = set->info_ordinary.maps; + } /* We are going to execute some dance to try to reduce the overhead of the memory allocator, in case we are using the ggc-page.c one. The actual size of memory we are going to get back from the - allocator is the smallest power of 2 that is greater than the - size we requested. So let's consider that size then. */ - - alloc_size = - (2 * LINEMAPS_ALLOCATED (set, macro_map_p) + 256) - * map_size; - - /* Get the actual size of memory that is going to be allocated - by the allocator. */ - alloc_size = round_alloc_size (alloc_size); + allocator may well be larger than what we ask for. Use this + hook to find what that size is. */ + size_t alloc_size + = set->round_alloc_size (num_maps_allocated * size_of_a_map); /* Now alloc_size contains the exact memory size we would get if we have asked for the initial alloc_size amount of memory. - Let's get back to the number of macro map that amounts - to. */ - LINEMAPS_ALLOCATED (set, macro_map_p) = - alloc_size / map_size; - - /* And now let's really do the re-allocation. */ - if (macro_map_p) - { - set->info_macro.maps - = (line_map_macro *) (*reallocator) (set->info_macro.maps, - (LINEMAPS_ALLOCATED (set, macro_map_p) - * map_size)); - result = &set->info_macro.maps[LINEMAPS_USED (set, macro_map_p)]; - } - else - { - set->info_ordinary.maps = - (line_map_ordinary *) (*reallocator) (set->info_ordinary.maps, - (LINEMAPS_ALLOCATED (set, macro_map_p) - * map_size)); - result = &set->info_ordinary.maps[LINEMAPS_USED (set, macro_map_p)]; - } - memset (result, 0, - ((LINEMAPS_ALLOCATED (set, macro_map_p) - - LINEMAPS_USED (set, macro_map_p)) - * map_size)); - } - else - { - if (macro_map_p) - result = &set->info_macro.maps[LINEMAPS_USED (set, macro_map_p)]; + Let's get back to the number of map that amounts to. */ + unsigned num_maps = alloc_size / size_of_a_map; + buffer = set->reallocator (buffer, num_maps * size_of_a_map); + memset ((char *)buffer + num_maps_used * size_of_a_map, 0, + (num_maps - num_maps_used) * size_of_a_map); + if (macro_p) + set->info_macro.maps = (line_map_macro *)buffer; else - result = &set->info_ordinary.maps[LINEMAPS_USED (set, macro_map_p)]; + set->info_ordinary.maps = (line_map_ordinary *)buffer; + LINEMAPS_ALLOCATED (set, macro_p) = num_maps; } - result->start_location = start_location; + line_map *result = (macro_p ? (line_map *)&set->info_macro.maps[num_maps_used] + : (line_map *)&set->info_ordinary.maps[num_maps_used]); + LINEMAPS_USED (set, macro_p)++; - LINEMAPS_USED (set, macro_map_p)++; + result->start_location = start_location; return result; } -- cgit v1.1 From f10a91352f83232394646df5a67bdb8f4366a067 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Wed, 8 Aug 2018 18:13:00 +0000 Subject: [PATCH] line-map include-from representation https://gcc.gnu.org/ml/gcc-patches/2018-08/msg00554.html Make linemap::included_from a location libcpp/ * include/line-map.h (struct line_map_ordinary): Replace included_from map index with included_at source_location. (ORDINARY_MAP_INCLUDER_FILE_INDEX): Delete. (LAST_SOURCE_LINE_LOCATION): Delete. (LAST_SOURCE_LINE, LAST_SOURCE_COLUMN): Delete. (linemap_included_from): New. (linemap_included_from_linemap): Declare. (MAIN_FILE_P): Adjust. * line-map.c (linemap_included_from_linemap): New. (lonemap_check_files_exited): Use linemap_included_at. (linemap_add): Adjust inclusion setting. (linemap_dump, linemap_dump_location): Adjust. * directives.c (do_linemarker): Use linemap_included_at. gcc/ * diagnostic.c (diagnostic_report_current_module): Use linemap_included_from & linemap_included_from_linemap. gcc/c-family/ * c-common.c (try_to_locate_new_include_inertion_point): Use linemap_included_from_linemap. * c-lex.c (fe_file_change): Use linemap_included_from. * c-ppoutput.c (pp_file_change): Likewise. gcc/fortran/ * cpp.c (cb_file_change): Use linemap_included_from. gcc/testsuite/ * c-c++-common/inc-from-1a.h, c-c++-common/inc-from-1b.h, c-c++-common/inc-from-1.c: New From-SVN: r263429 --- libcpp/ChangeLog | 18 ++++++++++++++ libcpp/directives.c | 6 ++--- libcpp/include/line-map.h | 61 +++++++++-------------------------------------- libcpp/line-map.c | 53 ++++++++++++++++++++++++---------------- 4 files changed, 64 insertions(+), 74 deletions(-) (limited to 'libcpp') diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index 50fa253..3eaebfd 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,3 +1,21 @@ +2018-08-08 Nathan Sidwell + + Make linemap::included_from a location + libcpp/ + * include/line-map.h (struct line_map_ordinary): Replace + included_from map index with included_at source_location. + (ORDINARY_MAP_INCLUDER_FILE_INDEX): Delete. + (LAST_SOURCE_LINE_LOCATION): Delete. + (LAST_SOURCE_LINE, LAST_SOURCE_COLUMN): Delete. + (linemap_included_from): New. + (linemap_included_from_linemap): Declare. + (MAIN_FILE_P): Adjust. + * line-map.c (linemap_included_from_linemap): New. + (lonemap_check_files_exited): Use linemap_included_at. + (linemap_add): Adjust inclusion setting. + (linemap_dump, linemap_dump_location): Adjust. + * directives.c (do_linemarker): Use linemap_included_at. + 2018-08-07 Nathan Sidwell * line-map.c: (linemap_init): Set default allocator here. diff --git a/libcpp/directives.c b/libcpp/directives.c index bf13ada..352c591 100644 --- a/libcpp/directives.c +++ b/libcpp/directives.c @@ -1088,10 +1088,10 @@ do_linemarker (cpp_reader *pfile) /* Reread map since cpp_get_token can invalidate it with a reallocation. */ map = LINEMAPS_LAST_ORDINARY_MAP (line_table); - const line_map_ordinary *from; + const line_map_ordinary *from + = linemap_included_from_linemap (line_table, map); if (MAIN_FILE_P (map) - || (new_file - && (from = INCLUDED_FROM (pfile->line_table, map)) != NULL + || (from && filename_cmp (ORDINARY_MAP_FILE_NAME (from), new_file) != 0)) { cpp_warning (pfile, CPP_W_NONE, diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h index a4baa49..1061d20 100644 --- a/libcpp/include/line-map.h +++ b/libcpp/include/line-map.h @@ -440,10 +440,10 @@ struct GTY((tag ("1"))) line_map_ordinary : public line_map { const char *to_file; linenum_type to_line; - /* 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; + /* Location from whence this line map was included. For regular + #includes, this location will be the last location of a map. For + outermost file, this is 0. */ + source_location included_from; /* Size is 20 or 24 bytes, no padding */ }; @@ -634,17 +634,6 @@ ORDINARY_MAP_STARTING_LINE_NUMBER (const line_map_ordinary *ord_map) return ord_map->to_line; } -/* Get the index of the ordinary map at whose end - ordinary map MAP was included. - - File(s) at the bottom of the include stack have this set. */ - -inline int -ORDINARY_MAP_INCLUDER_FILE_INDEX (const line_map_ordinary *ord_map) -{ - return ord_map->included_from; -} - /* Return a positive value if map encodes locations from a system header, 0 otherwise. Returns 1 if ordinary map MAP encodes locations in a system header and 2 if it encodes locations in a C system header @@ -1192,51 +1181,23 @@ SOURCE_COLUMN (const line_map_ordinary *ord_map, source_location loc) & ((1 << ord_map->m_column_and_range_bits) - 1)) >> ord_map->m_range_bits; } -/* Return the location of the last source line within an ordinary - map. */ -inline source_location -LAST_SOURCE_LINE_LOCATION (const line_map_ordinary *map) -{ - return (((map[1].start_location - 1 - - map->start_location) - & ~((1 << map->m_column_and_range_bits) - 1)) - + map->start_location); -} - -/* 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. */ -inline linenum_type -LAST_SOURCE_LINE (const line_map_ordinary *map) -{ - return SOURCE_LINE (map, LAST_SOURCE_LINE_LOCATION (map)); -} -/* Return the last column number within an ordinary map. */ - -inline linenum_type -LAST_SOURCE_COLUMN (const line_map_ordinary *map) +inline source_location +linemap_included_from (const line_map_ordinary *ord_map) { - return SOURCE_COLUMN (map, LAST_SOURCE_LINE_LOCATION (map)); + return ord_map->included_from; } -/* 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. */ -inline line_map_ordinary * -INCLUDED_FROM (struct line_maps *set, const line_map_ordinary *ord_map) -{ - return ((ord_map->included_from == -1) - ? NULL - : LINEMAPS_ORDINARY_MAP_AT (set, ord_map->included_from)); -} +/* The linemap containing the included-from location of MAP. */ +const line_map_ordinary *linemap_included_from_linemap + (line_maps *set, const line_map_ordinary *map); /* True if the map is at the bottom of the include stack. */ inline bool MAIN_FILE_P (const line_map_ordinary *ord_map) { - return ord_map->included_from < 0; + return ord_map->included_from == 0; } /* Encode and return a source_location from a column number. The diff --git a/libcpp/line-map.c b/libcpp/line-map.c index a5dc485..555cd12 100644 --- a/libcpp/line-map.c +++ b/libcpp/line-map.c @@ -355,17 +355,25 @@ linemap_init (struct line_maps *set, set->builtin_location = builtin_location; } +/* Return the ordinary line map from whence MAP was included. Returns + NULL if MAP was not an include. */ + +const line_map_ordinary * +linemap_included_from_linemap (line_maps *set, const line_map_ordinary *map) +{ + return linemap_ordinary_map_lookup (set, linemap_included_from (map)); +} + /* Check for and warn about line_maps entered but not exited. */ void linemap_check_files_exited (struct line_maps *set) { - const line_map_ordinary *map; /* Depending upon whether we are handling preprocessed input or not, this can be a user error or an ICE. */ - for (map = LINEMAPS_LAST_ORDINARY_MAP (set); + for (const line_map_ordinary *map = LINEMAPS_LAST_ORDINARY_MAP (set); ! MAIN_FILE_P (map); - map = INCLUDED_FROM (set, map)) + map = linemap_included_from_linemap (set, map)) fprintf (stderr, "line-map.c: file \"%s\" entered but not left\n", ORDINARY_MAP_FILE_NAME (map)); } @@ -494,19 +502,19 @@ linemap_add (struct line_maps *set, enum lc_reason reason, if (reason == LC_RENAME_VERBATIM) reason = LC_RENAME; + const line_map_ordinary *from = NULL; 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. */ - line_map_ordinary *from; linemap_assert (!MAIN_FILE_P (map - 1)); /* (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); + from = linemap_included_from_linemap (set, map - 1); /* A TO_FILE of NULL is special - we use the natural values. */ if (to_file == NULL) @@ -538,19 +546,24 @@ linemap_add (struct line_maps *set, enum lc_reason reason, if (reason == LC_ENTER) { - map->included_from = - set->depth == 0 ? -1 : (int) (LINEMAPS_ORDINARY_USED (set) - 2); + if (set->depth == 0) + map->included_from = 0; + else + /* The location of the end of the just-closed map. */ + map->included_from + = (((map[0].start_location - 1 - map[-1].start_location) + & ~((1 << map[-1].m_column_and_range_bits) - 1)) + + map[-1].start_location); set->depth++; if (set->trace_includes) trace_include (set, map); } else if (reason == LC_RENAME) - map->included_from = ORDINARY_MAP_INCLUDER_FILE_INDEX (&map[-1]); + map->included_from = linemap_included_from (&map[-1]); else if (reason == LC_LEAVE) { set->depth--; - map->included_from = - ORDINARY_MAP_INCLUDER_FILE_INDEX (INCLUDED_FROM (set, map - 1)); + map->included_from = linemap_included_from (from); } return map; @@ -1761,17 +1774,13 @@ linemap_dump (FILE *stream, struct line_maps *set, unsigned ix, bool is_macro) if (!is_macro) { const line_map_ordinary *ord_map = linemap_check_ordinary (map); - unsigned includer_ix; - const line_map_ordinary *includer_map; - - includer_ix = ORDINARY_MAP_INCLUDER_FILE_INDEX (ord_map); - includer_map = includer_ix < LINEMAPS_ORDINARY_USED (set) - ? LINEMAPS_ORDINARY_MAP_AT (set, includer_ix) - : NULL; + const line_map_ordinary *includer_map + = linemap_included_from_linemap (set, ord_map); fprintf (stream, "File: %s:%d\n", ORDINARY_MAP_FILE_NAME (ord_map), ORDINARY_MAP_STARTING_LINE_NUMBER (ord_map)); - fprintf (stream, "Included from: [%d] %s\n", includer_ix, + fprintf (stream, "Included from: [%d] %s\n", + includer_map ? int (includer_map - set->info_ordinary.maps) : -1, includer_map ? ORDINARY_MAP_FILE_NAME (includer_map) : "None"); } else @@ -1821,9 +1830,11 @@ linemap_dump_location (struct line_maps *set, if (e) from = "N/A"; else - from = (INCLUDED_FROM (set, map)) - ? LINEMAP_FILE (INCLUDED_FROM (set, map)) - : ""; + { + const line_map_ordinary *from_map + = linemap_included_from_linemap (set, map); + from = from_map ? LINEMAP_FILE (from_map) : ""; + } } /* P: path, L: line, C: column, S: in-system-header, M: map address, -- cgit v1.1 From 96e6ae576c48cd8efc26670b0d0bbb9e961393bf Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Wed, 15 Aug 2018 18:09:35 +0000 Subject: diagnostics: add labeling of source ranges This patch adds the ability to label source ranges within a rich_location, to be printed by diagnostic_show_locus. For example: pr69554-1.c:11:18: error: invalid operands to binary + (have 'const char *' and 'const char *') 11 | return (p + 1) + (q + 1); | ~~~~~~~ ^ ~~~~~~~ | | | | | const char * | const char * The patch implements labels for various type mismatch errors in the C and C++ frontends, and in -Wformat. I implemented it wherever accurate location information was guaranteed (there are other places that could benefit, but we need better location information in those places). The labels can be disabled via -fno-diagnostics-show-labels. Similarly: param-type-mismatch.C: In function 'int test_1(int, int, float)': param-type-mismatch.C:11:27: error: invalid conversion from 'int' to 'const char*' [-fpermissive] 11 | return callee_1 (first, second, third); | ^~~~~~ | | | int param-type-mismatch.C:7:43: note: initializing argument 2 of 'int callee_1(int, const char*, float)' 7 | extern int callee_1 (int one, const char *two, float three); | ~~~~~~~~~~~~^~~ where the first "error" describing the bad argument gets a label describing the type inline (since it's non-obvious from "second"). The "note" describing the type of the param of the callee *doesn't* get a label, since that information is explicit there in the source ("const char *two"). The idea is that in any diagnostic where two aspects of the source aren't in sync it ought to be easier for the user if we directly show them the mismatching aspects inline (e.g. types). As well as type mismatch errors, perhaps labels could also be used for buffer overflow warnings, for describing the capacity of the destination buffer vs the size of what's being written: sprintf (buf, "filename: %s\n", file); ^~~ ~~~~~~~~~~~^~~ | | capacity: 32 10 + strlen(file) + 2 or somesuch. Another idea might be for macro expansion warnings: warning: repeated side effects in macro expansion... x = MIN (p++, q++); ~~~~^~~~~~~~~~ note: ...expanded here as #define MIN(X,Y) (Xm_label when constructing layout_range instances. (struct line_label): New struct. (layout::print_any_labels): New member function. (layout::print_line): Call it if label-printing is enabled. (selftest::test_one_liner_labels): New test. (selftest::test_diagnostic_show_locus_one_liner): Call it. * diagnostic.c (diagnostic_initialize): Initialize context->show_labels_p. * diagnostic.h (struct diagnostic_context): Add field "show_labels_p". * doc/invoke.texi (Diagnostic Message Formatting Options): Add -fno-diagnostics-show-labels. * dwarf2out.c (gen_producer_string): Add OPT_fdiagnostics_show_labels to the ignored options. * gcc-rich-location.c (gcc_rich_location::add_expr): Add "label" param. (gcc_rich_location::maybe_add_expr): Likewise. * gcc-rich-location.h (gcc_rich_location::gcc_rich_location): Add label" param, defaulting to NULL. (gcc_rich_location::add_expr): Add "label" param. (gcc_rich_location::maybe_add_expr): Likewise. (class text_range_label): New class. (class range_label_for_type_mismatch): New class. * gimple-ssa-sprintf.c (fmtwarn): Pass NULL for new label params of format_warning_va. (fmtwarn_n): Likewise for new params of format_warning_n_va. * lto-wrapper.c (merge_and_complain): Add OPT_fdiagnostics_show_labels to the "pick one setting" options. (append_compiler_options): Likewise to the dropped options. (append_diag_options): Likewise to the passed-on options. * opts.c (common_handle_option): Handle the new option. * selftest-diagnostic.c (test_diagnostic_context::test_diagnostic_context): Enable show_labels_p. * substring-locations.c: Include "gcc-rich-location.h". (format_warning_n_va): Add "fmt_label" and "param_label" params and use them as appropriate. (format_warning_va): Add "fmt_label" and "param_label" params, passing them on to format_warning_n_va. (format_warning_at_substring): Likewise. (format_warning_at_substring_n): Likewise. * substring-locations.h (format_warning_va): Add "fmt_label" and "param_label" params. (format_warning_n_va): Likewise. (format_warning_at_substring): Likewise. (format_warning_at_substring_n): Likewise. * toplev.c (general_init): Initialize global_dc->show_labels_p. gcc/testsuite/ChangeLog: * g++.dg/diagnostic/aka3.C: New test. * g++.dg/diagnostic/param-type-mismatch-2.C: Update expected output to show range labels. * g++.dg/diagnostic/param-type-mismatch.C: Likewise. * g++.dg/plugin/plugin.exp (plugin_test_list): Add... * g++.dg/plugin/show-template-tree-color-labels.C: New test. * gcc.dg/bad-binary-ops.c: Update expected output to show range labels. Add an "aka" example. * gcc.dg/cpp/pr66415-1.c: Update expected output to show range labels. * gcc.dg/format/diagnostic-ranges.c: Likewise. * gcc.dg/format/pr72858.c: Likewise. * gcc.dg/format/pr78498.c: Likewise. * gcc.dg/param-type-mismatch.c: Add "-Wpointer-sign" to options. Update expected output to show range labels. Add examples of -Wincompatible-pointer-types and -Wpointer-sign for parameters. * gcc.dg/plugin/diagnostic-test-show-locus-bw-line-numbers.c: Update expected output to show range labels. * gcc.dg/plugin/diagnostic-test-show-locus-bw.c: Likewise. (test_very_wide_line): Adjust so that label is at left-clipping boundary. (test_very_wide_line_2): New test. * gcc.dg/plugin/diagnostic-test-show-locus-color-line-numbers.c: Update expected output to show range labels. * gcc.dg/plugin/diagnostic-test-show-locus-color.c: Likewise. * gcc.dg/plugin/diagnostic-test-show-locus-no-labels.c: New test. * gcc.dg/plugin/diagnostic_plugin_show_trees.c (show_tree): Update for new param to gcc_rich_location::add_expr. * gcc.dg/plugin/diagnostic_plugin_test_show_locus.c (add_range): Add "label" param. (test_show_locus): Add examples of labels to various tests. Tweak the "very wide_line" test case and duplicate it, to cover the boundary values for clipping of labels against the left-margin. * gcc.dg/plugin/plugin.exp (plugin_test_list): Add diagnostic-test-show-locus-no-labels.c. * gcc.dg/pr69554-1.c: Update expected output to show range labels. Update line numbers of dg-locus directives. * gcc.dg/pr69627.c: Update expected output to show range labels. * lib/multiline.exp (proc _build_multiline_regex): Remove special-case handling of lines with trailing '|'. libcpp/ChangeLog: * include/line-map.h (struct location_range): Add "m_label" field. (class rich_location): Add description of labels to leading comment. (rich_location::rich_location): Add "label" param, defaulting to NULL. (rich_location::add_range): Likewise. (struct label_text): New struct. (class range_label): New abstract base class. * line-map.c (rich_location::rich_location): Add "label" param; use it. (rich_location::add_range): Likewise. From-SVN: r263564 --- libcpp/ChangeLog | 14 +++++++++ libcpp/include/line-map.h | 78 ++++++++++++++++++++++++++++++++++++++++++----- libcpp/line-map.c | 9 ++++-- 3 files changed, 90 insertions(+), 11 deletions(-) (limited to 'libcpp') diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index 3eaebfd..a39144c 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,3 +1,17 @@ +2018-08-15 David Malcolm + + * include/line-map.h (struct location_range): Add "m_label" field. + (class rich_location): Add description of labels to leading + comment. + (rich_location::rich_location): Add "label" param, defaulting to + NULL. + (rich_location::add_range): Likewise. + (struct label_text): New struct. + (class range_label): New abstract base class. + * line-map.c (rich_location::rich_location): Add "label" param; + use it. + (rich_location::add_range): Likewise. + 2018-08-08 Nathan Sidwell Make linemap::included_from a location diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h index 1061d20..4f0ff87 100644 --- a/libcpp/include/line-map.h +++ b/libcpp/include/line-map.h @@ -1281,8 +1281,11 @@ typedef struct bool sysp; } expanded_location; +class range_label; + /* A location within a rich_location: a caret&range, with - the caret potentially flagged for display. */ + the caret potentially flagged for display, and an optional + label. */ struct location_range { @@ -1298,6 +1301,9 @@ struct location_range where "1" and "2" are notionally carets. */ bool m_show_caret_p; + + /* If non-NULL, the label for this range. */ + const range_label *m_label; }; /* A partially-embedded vec for use within rich_location for storing @@ -1439,6 +1445,8 @@ class fixit_hint; Additional ranges may be added to help the user identify other pertinent clauses in a diagnostic. + Ranges can (optionally) be given labels via class range_label. + rich_location instances are intended to be allocated on the stack when generating diagnostics, and to be short-lived. @@ -1484,18 +1492,22 @@ class fixit_hint; equal to their caret point. The frontend overrides the diagnostic context's default caret character for these ranges. - Example E - ********* + Example E (range labels) + ************************ printf ("arg0: %i arg1: %s arg2: %i", ^~ + | + const char * 100, 101, 102); ~~~ + | + int This rich location has two ranges: - range 0 is at the "%s" with start = caret = "%" and finish at - the "s". + the "s". It has a range_label ("const char *"). - range 1 has start/finish covering the "101" and is not flagged for - caret printing; it is perhaps at the start of "101". - + caret printing. The caret is at the start of "101", where its + range_label is printed ("int"). Fix-it hints ------------ @@ -1587,7 +1599,8 @@ class rich_location /* Constructors. */ /* Constructing from a location. */ - rich_location (line_maps *set, source_location loc); + rich_location (line_maps *set, source_location loc, + const range_label *label = NULL); /* Destructor. */ ~rich_location (); @@ -1597,7 +1610,8 @@ class rich_location source_location get_loc (unsigned int idx) const; void - add_range (source_location loc, bool show_caret_p); + add_range (source_location loc, bool show_caret_p, + const range_label *label = NULL); void set_range (unsigned int idx, source_location loc, bool show_caret_p); @@ -1721,6 +1735,54 @@ protected: bool m_fixits_cannot_be_auto_applied; }; +/* A struct for the result of range_label::get_text: a NUL-terminated buffer + of localized text, and a flag to determine if the caller should "free" the + buffer. */ + +struct label_text +{ + label_text () + : m_buffer (NULL), m_caller_owned (false) + {} + + label_text (char *buffer, bool caller_owned) + : m_buffer (buffer), m_caller_owned (caller_owned) + {} + + void maybe_free () + { + if (m_caller_owned) + free (m_buffer); + } + + char *m_buffer; + bool m_caller_owned; +}; + +/* Abstract base class for labelling a range within a rich_location + (e.g. for labelling expressions with their type). + + Generating the text could require non-trivial work, so this work + is delayed (via the "get_text" virtual function) until the diagnostic + printing code "knows" it needs it, thus avoiding doing it e.g. for + warnings that are filtered by command-line flags. This virtual + function also isolates libcpp and the diagnostics subsystem from + the front-end and middle-end-specific code for generating the text + for the labels. + + Like the rich_location instances they annotate, range_label instances + are intended to be allocated on the stack when generating diagnostics, + and to be short-lived. */ + +class range_label +{ + public: + virtual ~range_label () {} + + /* Get localized text for the label. */ + virtual label_text get_text () const = 0; +}; + /* A fix-it hint: a suggested insertion, replacement, or deletion of text. We handle these three types of edit with one class, by representing them as replacement of a half-open range: diff --git a/libcpp/line-map.c b/libcpp/line-map.c index 555cd12..f0e6318 100644 --- a/libcpp/line-map.c +++ b/libcpp/line-map.c @@ -1988,7 +1988,8 @@ line_table_dump (FILE *stream, struct line_maps *set, unsigned int num_ordinary, /* Construct a rich_location with location LOC as its initial range. */ -rich_location::rich_location (line_maps *set, source_location loc) : +rich_location::rich_location (line_maps *set, source_location loc, + const range_label *label) : m_line_table (set), m_ranges (), m_column_override (0), @@ -1997,7 +1998,7 @@ rich_location::rich_location (line_maps *set, source_location loc) : m_seen_impossible_fixit (false), m_fixits_cannot_be_auto_applied (false) { - add_range (loc, true); + add_range (loc, true, label); } /* The destructor for class rich_location. */ @@ -2073,11 +2074,13 @@ rich_location::override_column (int column) /* Add the given range. */ void -rich_location::add_range (source_location loc, bool show_caret_p) +rich_location::add_range (source_location loc, bool show_caret_p, + const range_label *label) { location_range range; range.m_loc = loc; range.m_show_caret_p = show_caret_p; + range.m_label = label; m_ranges.push (range); } -- cgit v1.1 From 3f6677f418564e634e3b77b0fc385891d1fdf1da Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Thu, 16 Aug 2018 13:51:38 +0000 Subject: [PATCH] CPP Macro predicates https://gcc.gnu.org/ml/gcc-patches/2018-08/msg00897.html libcpp/ * include/cpplib.h (cpp_user_macro_p, cpp_builtin_macro_p) (cpp_macro_p): New inlines. * directives.c (do_pragma_poison): Use cpp_macro_p. (do_ifdef, do_ifndef): Likewise. Use _cpp_maybe_notify_macro_use. (cpp_pop_definition): Use cpp_macro_p. Move _cpp_free_definition earlier. Don't zap node directly. * expr.c (parse_defined): Use _cpp_maybe_notify_macro_use & cpp_macro_p. * files.c (should_stack_file): Use cpp_macro_p. * identifiers.c (cpp_defined): Likewise. * internal.h (_cpp_mark_macro): Use cpp_user_macro_p. (_cpp_notify_macro_use): Declare. (_cpp_maybe_notify_macro_use): New inline. * lex.c (is_macro): Use cpp_macro_p. * macro.c (_cpp_warn_if_unused_macro): Use cpp_user_macro_p. (enter_macro_context): Likewise. (_cpp_create_definition): Use cpp_builtin_macro_p, cpp_user_macro_p. Move _cpp_free_definition earlier. (_cpp_notify_macro_use): New, broken out of multiple call sites. * traditional.c (fun_like_macro_p): Use cpp_builtin_macro_p. (maybe_start_funlike, _cpp_scan_out_logical_line) (push_replacement_text): Likewise. gcc/c-family/ * c-ada-spec.c (count_ada_macro): Use cpp_user_macro_p. (store_ada_macro): Likewise. * c-ppoutput.c (cb_used_define, dump_macro): Likewise. * c-spellcheck.cc (should-suggest_as_macro_p): Likewise, gcc/ * config/rs6000/rs6000-c.c (rs6000_macro_to_expend): Use cpp_macro_p. * config/powerpcspc/powerpcspe-c.c (rs6000_macro_to_expend): Likewise. gcc/cp/ * name-lookup.c (lookup_name_fuzzy): Likewise. gcc/fortran/ * cpp.c (dump_macro): Use cpp_user_macro_p. From-SVN: r263587 --- libcpp/ChangeLog | 26 ++++++++++++++++++++++++ libcpp/directives.c | 53 +++++++++---------------------------------------- libcpp/expr.c | 22 +++----------------- libcpp/files.c | 2 +- libcpp/identifiers.c | 4 ++-- libcpp/include/cpplib.h | 16 ++++++++++++++- libcpp/internal.h | 11 +++++++--- libcpp/lex.c | 2 +- libcpp/macro.c | 51 ++++++++++++++++++++++++++++++++++------------- libcpp/traditional.c | 10 +++++----- 10 files changed, 107 insertions(+), 90 deletions(-) (limited to 'libcpp') diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index a39144c..2bab8a7 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,3 +1,29 @@ +2018-08-16 Nathan Sidwell + + libcpp/ + * include/cpplib.h (cpp_user_macro_p, cpp_builtin_macro_p) + (cpp_macro_p): New inlines. + * directives.c (do_pragma_poison): Use cpp_macro_p. + (do_ifdef, do_ifndef): Likewise. Use _cpp_maybe_notify_macro_use. + (cpp_pop_definition): Use cpp_macro_p. Move _cpp_free_definition + earlier. Don't zap node directly. + * expr.c (parse_defined): Use _cpp_maybe_notify_macro_use & + cpp_macro_p. + * files.c (should_stack_file): Use cpp_macro_p. + * identifiers.c (cpp_defined): Likewise. + * internal.h (_cpp_mark_macro): Use cpp_user_macro_p. + (_cpp_notify_macro_use): Declare. + (_cpp_maybe_notify_macro_use): New inline. + * lex.c (is_macro): Use cpp_macro_p. + * macro.c (_cpp_warn_if_unused_macro): Use cpp_user_macro_p. + (enter_macro_context): Likewise. + (_cpp_create_definition): Use cpp_builtin_macro_p, + cpp_user_macro_p. Move _cpp_free_definition earlier. + (_cpp_notify_macro_use): New, broken out of multiple call sites. + * traditional.c (fun_like_macro_p): Use cpp_builtin_macro_p. + (maybe_start_funlike, _cpp_scan_out_logical_line) + (push_replacement_text): Likewise. + 2018-08-15 David Malcolm * include/line-map.h (struct location_range): Add "m_label" field. diff --git a/libcpp/directives.c b/libcpp/directives.c index 352c591..6ddfce6 100644 --- a/libcpp/directives.c +++ b/libcpp/directives.c @@ -1666,7 +1666,7 @@ do_pragma_poison (cpp_reader *pfile) if (hp->flags & NODE_POISONED) continue; - if (hp->type == NT_MACRO) + if (cpp_macro_p (hp)) cpp_error (pfile, CPP_DL_WARNING, "poisoning existing macro \"%s\"", NODE_NAME (hp)); _cpp_free_definition (hp); @@ -1960,26 +1960,9 @@ do_ifdef (cpp_reader *pfile) the powerpc and spu ports using conditional macros for 'vector', 'bool', and 'pixel' to act as conditional keywords. This messes up tests like #ifndef bool. */ - skip = (node->type != NT_MACRO - || ((node->flags & NODE_CONDITIONAL) != 0)); + skip = !cpp_macro_p (node) || (node->flags & NODE_CONDITIONAL); _cpp_mark_macro_used (node); - if (!(node->flags & NODE_USED)) - { - node->flags |= NODE_USED; - if (node->type == NT_MACRO) - { - if ((node->flags & NODE_BUILTIN) - && pfile->cb.user_builtin_macro) - pfile->cb.user_builtin_macro (pfile, node); - if (pfile->cb.used_define) - pfile->cb.used_define (pfile, pfile->directive_line, node); - } - else - { - if (pfile->cb.used_undef) - pfile->cb.used_undef (pfile, pfile->directive_line, node); - } - } + _cpp_maybe_notify_macro_use (pfile, node); if (pfile->cb.used) pfile->cb.used (pfile, pfile->directive_line, node); check_eol (pfile, false); @@ -2006,26 +1989,10 @@ do_ifndef (cpp_reader *pfile) the powerpc and spu ports using conditional macros for 'vector', 'bool', and 'pixel' to act as conditional keywords. This messes up tests like #ifndef bool. */ - skip = (node->type == NT_MACRO - && ((node->flags & NODE_CONDITIONAL) == 0)); + skip = (cpp_macro_p (node) + && !(node->flags & NODE_CONDITIONAL)); _cpp_mark_macro_used (node); - if (!(node->flags & NODE_USED)) - { - node->flags |= NODE_USED; - if (node->type == NT_MACRO) - { - if ((node->flags & NODE_BUILTIN) - && pfile->cb.user_builtin_macro) - pfile->cb.user_builtin_macro (pfile, node); - if (pfile->cb.used_define) - pfile->cb.used_define (pfile, pfile->directive_line, node); - } - else - { - if (pfile->cb.used_undef) - pfile->cb.used_undef (pfile, pfile->directive_line, node); - } - } + _cpp_maybe_notify_macro_use (pfile, node); if (pfile->cb.used) pfile->cb.used (pfile, pfile->directive_line, node); check_eol (pfile, false); @@ -2508,18 +2475,18 @@ cpp_pop_definition (cpp_reader *pfile, struct def_pragma_macro *c) if (pfile->cb.before_define) pfile->cb.before_define (pfile); - if (node->type == NT_MACRO) + if (cpp_macro_p (node)) { if (pfile->cb.undef) pfile->cb.undef (pfile, pfile->directive_line, node); if (CPP_OPTION (pfile, warn_unused_macros)) _cpp_warn_if_unused_macro (pfile, node, NULL); + _cpp_free_definition (node); } - if (node->type != NT_VOID) - _cpp_free_definition (node); if (c->is_undef) return; + { size_t namelen; const uchar *dn; @@ -2530,8 +2497,6 @@ cpp_pop_definition (cpp_reader *pfile, struct def_pragma_macro *c) h = cpp_lookup (pfile, c->definition, namelen); dn = c->definition + namelen; - h->type = NT_VOID; - h->flags &= ~(NODE_POISONED|NODE_BUILTIN|NODE_DISABLED|NODE_USED); nbuf = cpp_push_buffer (pfile, dn, ustrchr (dn, '\n') - dn, true); if (nbuf != NULL) { diff --git a/libcpp/expr.c b/libcpp/expr.c index 36c3fc4..201a619 100644 --- a/libcpp/expr.c +++ b/libcpp/expr.c @@ -1065,23 +1065,7 @@ parse_defined (cpp_reader *pfile) "this use of \"defined\" may not be portable"); _cpp_mark_macro_used (node); - if (!(node->flags & NODE_USED)) - { - node->flags |= NODE_USED; - if (node->type == NT_MACRO) - { - if ((node->flags & NODE_BUILTIN) - && pfile->cb.user_builtin_macro) - pfile->cb.user_builtin_macro (pfile, node); - if (pfile->cb.used_define) - pfile->cb.used_define (pfile, pfile->directive_line, node); - } - else - { - if (pfile->cb.used_undef) - pfile->cb.used_undef (pfile, pfile->directive_line, node); - } - } + _cpp_maybe_notify_macro_use (pfile, node); /* A possible controlling macro of the form #if !defined (). _cpp_parse_expr checks there was no other junk on the line. */ @@ -1097,8 +1081,8 @@ parse_defined (cpp_reader *pfile) result.unsignedp = false; result.high = 0; result.overflow = false; - result.low = (node && node->type == NT_MACRO - && (node->flags & NODE_CONDITIONAL) == 0); + result.low = (node && cpp_macro_p (node) + && !(node->flags & NODE_CONDITIONAL)); return result; } diff --git a/libcpp/files.c b/libcpp/files.c index e8d21b2..08b7c64 100644 --- a/libcpp/files.c +++ b/libcpp/files.c @@ -805,7 +805,7 @@ should_stack_file (cpp_reader *pfile, _cpp_file *file, bool import, /* Skip if the file had a header guard and the macro is defined. PCH relies on this appearing before the PCH handler below. */ - if (file->cmacro && file->cmacro->type == NT_MACRO) + if (file->cmacro && cpp_macro_p (file->cmacro)) return false; /* Handle PCH files immediately; don't stack them. */ diff --git a/libcpp/identifiers.c b/libcpp/identifiers.c index 16584a6..3d42d1a 100644 --- a/libcpp/identifiers.c +++ b/libcpp/identifiers.c @@ -104,8 +104,8 @@ cpp_defined (cpp_reader *pfile, const unsigned char *str, int len) node = CPP_HASHNODE (ht_lookup (pfile->hash_table, str, len, HT_NO_INSERT)); - /* If it's of type NT_MACRO, it cannot be poisoned. */ - return node && node->type == NT_MACRO; + /* If it's a macro, it cannot have been poisoned. */ + return node && cpp_macro_p (node); } /* We don't need a proxy since the hash table's identifier comes first diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h index 3ad52d5..99992a2 100644 --- a/libcpp/include/cpplib.h +++ b/libcpp/include/cpplib.h @@ -890,7 +890,21 @@ extern int cpp_avoid_paste (cpp_reader *, const cpp_token *, extern const cpp_token *cpp_get_token (cpp_reader *); extern const cpp_token *cpp_get_token_with_location (cpp_reader *, source_location *); -extern bool cpp_fun_like_macro_p (cpp_hashnode *); +inline bool cpp_user_macro_p (const cpp_hashnode *node) +{ + return node->type == NT_MACRO && !(node->flags & NODE_BUILTIN); +} +inline bool cpp_builtin_macro_p (const cpp_hashnode *node) +{ + return node->flags & NODE_BUILTIN; +} +inline bool cpp_macro_p (const cpp_hashnode *node) +{ + return node->type == NT_MACRO; +} +/* Returns true if NODE is a function-like user macro. */ +extern bool cpp_fun_like_macro_p (cpp_hashnode *node); + extern const unsigned char *cpp_macro_definition (cpp_reader *, cpp_hashnode *); extern source_location cpp_macro_definition_location (cpp_hashnode *); diff --git a/libcpp/internal.h b/libcpp/internal.h index 782d8e6..dd145ab 100644 --- a/libcpp/internal.h +++ b/libcpp/internal.h @@ -93,9 +93,8 @@ struct dummy #define CPP_ALIGN2(size, align) (((size) + ((align) - 1)) & ~((align) - 1)) #define CPP_ALIGN(size) CPP_ALIGN2 (size, DEFAULT_ALIGNMENT) -#define _cpp_mark_macro_used(NODE) do { \ - if ((NODE)->type == NT_MACRO && !((NODE)->flags & NODE_BUILTIN)) \ - (NODE)->value.macro->used = 1; } while (0) +#define _cpp_mark_macro_used(NODE) \ + (cpp_user_macro_p (NODE) ? (NODE)->value.macro->used = 1 : 0) /* A generic memory buffer, and operations on it. */ typedef struct _cpp_buff _cpp_buff; @@ -622,6 +621,12 @@ cpp_in_primary_file (cpp_reader *pfile) } /* In macro.c */ +extern void _cpp_notify_macro_use (cpp_reader *pfile, cpp_hashnode *node); +inline void _cpp_maybe_notify_macro_use (cpp_reader *pfile, cpp_hashnode *node) +{ + if (!(node->flags & NODE_USED)) + _cpp_notify_macro_use (pfile, node); +} extern void _cpp_free_definition (cpp_hashnode *); extern bool _cpp_create_definition (cpp_reader *, cpp_hashnode *); extern void _cpp_pop_context (cpp_reader *); diff --git a/libcpp/lex.c b/libcpp/lex.c index a2592e0..fa465be 100644 --- a/libcpp/lex.c +++ b/libcpp/lex.c @@ -1627,7 +1627,7 @@ is_macro(cpp_reader *pfile, const uchar *base) cpp_hashnode *result = CPP_HASHNODE (ht_lookup_with_hash (pfile->hash_table, base, cur - base, hash, HT_NO_INSERT)); - return !result ? false : (result->type == NT_MACRO); + return result && cpp_macro_p (result); } /* Returns true if a literal suffix does not have the expected form diff --git a/libcpp/macro.c b/libcpp/macro.c index 683f918..5d4cd78 100644 --- a/libcpp/macro.c +++ b/libcpp/macro.c @@ -342,7 +342,7 @@ int _cpp_warn_if_unused_macro (cpp_reader *pfile, cpp_hashnode *node, void *v ATTRIBUTE_UNUSED) { - if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN)) + if (cpp_user_macro_p (node)) { cpp_macro *macro = node->value.macro; @@ -1282,8 +1282,7 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode *node, pfile->cb.used_define (pfile, pfile->directive_line, node); } - /* Handle standard macros. */ - if (! (node->flags & NODE_BUILTIN)) + if (cpp_user_macro_p (node)) { cpp_macro *macro = node->value.macro; _cpp_buff *pragma_buff = NULL; @@ -1413,10 +1412,8 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode *node, source_location expand_loc; if (/* The top-level macro invocation that triggered the expansion - we are looking at is with a standard macro ... */ - !(pfile->top_most_macro_node->flags & NODE_BUILTIN) - /* ... and it's a function-like macro invocation, */ - && pfile->top_most_macro_node->value.macro->fun_like + we are looking at is with a function-like user macro ... */ + cpp_fun_like_macro_p (pfile->top_most_macro_node) /* ... and we are tracking the macro expansion. */ && CPP_OPTION (pfile, track_macro_expansion)) /* Then the location of the end of the macro invocation is the @@ -3505,25 +3502,23 @@ _cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node) if (warn_of_redefinition (pfile, node, macro)) { - const int reason = ((node->flags & NODE_BUILTIN) - && !(node->flags & NODE_WARN)) - ? CPP_W_BUILTIN_MACRO_REDEFINED : CPP_W_NONE; + const int reason + = (cpp_builtin_macro_p (node) && !(node->flags & NODE_WARN)) + ? CPP_W_BUILTIN_MACRO_REDEFINED : CPP_W_NONE; bool warned = cpp_pedwarning_with_line (pfile, reason, pfile->directive_line, 0, "\"%s\" redefined", NODE_NAME (node)); - if (warned && node->type == NT_MACRO && !(node->flags & NODE_BUILTIN)) + if (warned && cpp_user_macro_p (node)) cpp_error_with_line (pfile, CPP_DL_NOTE, node->value.macro->line, 0, "this is the location of the previous definition"); } + _cpp_free_definition (node); } - if (node->type != NT_VOID) - _cpp_free_definition (node); - /* Enter definition in hash table. */ node->type = NT_MACRO; node->value.macro = macro; @@ -3544,6 +3539,34 @@ _cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node) return ok; } +/* Notify the use of NODE in a macro-aware context (i.e. expanding it, + or testing its existance). Also applies any lazy definition. */ + +extern void +_cpp_notify_macro_use (cpp_reader *pfile, cpp_hashnode *node) +{ + node->flags |= NODE_USED; + switch (node->type) + { + case NT_MACRO: + if ((node->flags & NODE_BUILTIN) + && pfile->cb.user_builtin_macro) + pfile->cb.user_builtin_macro (pfile, node); + + if (pfile->cb.used_define) + pfile->cb.used_define (pfile, pfile->directive_line, node); + break; + + case NT_VOID: + if (pfile->cb.used_undef) + pfile->cb.used_undef (pfile, pfile->directive_line, node); + break; + + default: + abort (); + } +} + /* Warn if a token in STRING matches one of a function-like MACRO's parameters. */ static void diff --git a/libcpp/traditional.c b/libcpp/traditional.c index b25d522..aa38ea4 100644 --- a/libcpp/traditional.c +++ b/libcpp/traditional.c @@ -325,7 +325,7 @@ _cpp_read_logical_line_trad (cpp_reader *pfile) static inline bool fun_like_macro (cpp_hashnode *node) { - if (node->flags & NODE_BUILTIN) + if (cpp_builtin_macro_p (node)) return node->value.builtin == BT_HAS_ATTRIBUTE; else return node->value.macro->fun_like; @@ -338,7 +338,7 @@ maybe_start_funlike (cpp_reader *pfile, cpp_hashnode *node, const uchar *start, struct fun_macro *macro) { unsigned int n; - if (node->flags & NODE_BUILTIN) + if (cpp_builtin_macro_p (node)) n = 1; else n = node->value.macro->paramc; @@ -521,7 +521,7 @@ _cpp_scan_out_logical_line (cpp_reader *pfile, cpp_macro *macro, out = pfile->out.cur; cur = CUR (context); - if (node->type == NT_MACRO + if (cpp_macro_p (node) /* Should we expand for ls_answer? */ && (lex_state == ls_none || lex_state == ls_fun_open) && !pfile->state.prevent_expansion) @@ -610,7 +610,7 @@ _cpp_scan_out_logical_line (cpp_reader *pfile, cpp_macro *macro, paren_depth--; if (lex_state == ls_fun_close && paren_depth == 0) { - if (fmacro.node->flags & NODE_BUILTIN) + if (cpp_builtin_macro_p (fmacro.node)) { /* Handle builtin function-like macros like __has_attribute. The already parsed arguments @@ -839,7 +839,7 @@ push_replacement_text (cpp_reader *pfile, cpp_hashnode *node) const uchar *text; uchar *buf; - if (node->flags & NODE_BUILTIN) + if (cpp_builtin_macro_p (node)) { text = _cpp_builtin_macro_text (pfile, node); len = ustrlen (text); -- cgit v1.1 From 729a01f72ca6c1bd106cb2285187191c3568201b Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Thu, 16 Aug 2018 19:18:42 +0000 Subject: [PATCH] Macro definition parameter parsing https://gcc.gnu.org/ml/gcc-patches/2018-08/msg00977.html libcpp/ * internal.h (_cpp_save_parameter): Take parmno, not macro. (_cpp_unsave_parameters): Declare. * macro.c (_cpp_save_parameter): Take parm number, not macro. Return true on success. (_cpp_unsave_parameters): New. (parse_params): Take parm_no and variadic pointers, not macro. Reimplement parsing logic. (create_iso_definition): Adjust parse_params changes. Call _cpp_unsave_parameters here. (_cpp_create_definition): Don't unsave params here. * traditional.c (scan_parameters): Take n_param pointer, adjust. (_cpp_create_trad_definition): Ajust scan_parameters change. Call _cpp_unsave_parameters. gcc/testsuite/ * gcc.dg/cpp/macsyntx.c: Adjust expected errors. * gcc.dg/cpp/macsyntx2.c: likewise. From-SVN: r263600 --- libcpp/ChangeLog | 15 ++- libcpp/internal.h | 3 +- libcpp/macro.c | 280 +++++++++++++++++++++++++++------------------------ libcpp/traditional.c | 18 +++- 4 files changed, 177 insertions(+), 139 deletions(-) (limited to 'libcpp') diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index 2bab8a7..5f087ec 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,6 +1,19 @@ 2018-08-16 Nathan Sidwell - libcpp/ + * internal.h (_cpp_save_parameter): Take parmno, not macro. + (_cpp_unsave_parameters): Declare. + * macro.c (_cpp_save_parameter): Take parm number, not macro. + Return true on success. + (_cpp_unsave_parameters): New. + (parse_params): Take parm_no and variadic pointers, not macro. + Reimplement parsing logic. + (create_iso_definition): Adjust parse_params changes. Call + _cpp_unsave_parameters here. + (_cpp_create_definition): Don't unsave params here. + * traditional.c (scan_parameters): Take n_param pointer, adjust. + (_cpp_create_trad_definition): Ajust scan_parameters change. Call + _cpp_unsave_parameters. + * include/cpplib.h (cpp_user_macro_p, cpp_builtin_macro_p) (cpp_macro_p): New inlines. * directives.c (do_pragma_poison): Use cpp_macro_p. diff --git a/libcpp/internal.h b/libcpp/internal.h index dd145ab..0012520 100644 --- a/libcpp/internal.h +++ b/libcpp/internal.h @@ -632,8 +632,9 @@ extern bool _cpp_create_definition (cpp_reader *, cpp_hashnode *); extern void _cpp_pop_context (cpp_reader *); extern void _cpp_push_text_context (cpp_reader *, cpp_hashnode *, const unsigned char *, size_t); -extern bool _cpp_save_parameter (cpp_reader *, cpp_macro *, cpp_hashnode *, +extern bool _cpp_save_parameter (cpp_reader *, unsigned, cpp_hashnode *, cpp_hashnode *); +extern void _cpp_unsave_parameters (cpp_reader *, unsigned); extern bool _cpp_arguments_ok (cpp_reader *, cpp_macro *, const cpp_hashnode *, unsigned int); extern const unsigned char *_cpp_builtin_macro_text (cpp_reader *, diff --git a/libcpp/macro.c b/libcpp/macro.c index 5d4cd78..52098ef 100644 --- a/libcpp/macro.c +++ b/libcpp/macro.c @@ -316,7 +316,7 @@ static cpp_token *alloc_expansion_token (cpp_reader *, cpp_macro *); static cpp_token *lex_expansion_token (cpp_reader *, cpp_macro *); static bool warn_of_redefinition (cpp_reader *, cpp_hashnode *, const cpp_macro *); -static bool parse_params (cpp_reader *, cpp_macro *); +static bool parse_params (cpp_reader *, unsigned *, bool *); static void check_trad_stringification (cpp_reader *, const cpp_macro *, const cpp_string *); static bool reached_end_of_context (cpp_context *); @@ -3053,119 +3053,158 @@ _cpp_free_definition (cpp_hashnode *h) } /* Save parameter NODE (spelling SPELLING) to the parameter list of - macro MACRO. Returns zero on success, nonzero if the parameter is - a duplicate. */ + macro MACRO. Returns true on success, false on failure. */ bool -_cpp_save_parameter (cpp_reader *pfile, cpp_macro *macro, cpp_hashnode *node, +_cpp_save_parameter (cpp_reader *pfile, unsigned n, cpp_hashnode *node, cpp_hashnode *spelling) { - unsigned int len; /* Constraint 6.10.3.6 - duplicate parameter names. */ if (node->flags & NODE_MACRO_ARG) { cpp_error (pfile, CPP_DL_ERROR, "duplicate macro parameter \"%s\"", NODE_NAME (node)); - return true; + return false; } - if (BUFF_ROOM (pfile->a_buff) - < (macro->paramc + 1) * sizeof (cpp_hashnode *)) - _cpp_extend_buff (pfile, &pfile->a_buff, sizeof (cpp_hashnode *)); - - ((cpp_hashnode **) BUFF_FRONT (pfile->a_buff))[macro->paramc++] = spelling; - node->flags |= NODE_MACRO_ARG; - len = macro->paramc * sizeof (struct macro_arg_saved_data); + unsigned len = (n + 1) * sizeof (struct macro_arg_saved_data); if (len > pfile->macro_buffer_len) { - pfile->macro_buffer = XRESIZEVEC (unsigned char, pfile->macro_buffer, - len); + pfile->macro_buffer + = XRESIZEVEC (unsigned char, pfile->macro_buffer, len); pfile->macro_buffer_len = len; } - struct macro_arg_saved_data save; - save.value = node->value; - save.canonical_node = node; - ((struct macro_arg_saved_data *) pfile->macro_buffer)[macro->paramc - 1] - = save; - node->value.arg_index = macro->paramc; - return false; + macro_arg_saved_data *saved = (macro_arg_saved_data *)pfile->macro_buffer; + saved[n].canonical_node = node; + saved[n].value = node->value; + + if (BUFF_ROOM (pfile->a_buff) < (n + 1) * sizeof (cpp_hashnode *)) + _cpp_extend_buff (pfile, &pfile->a_buff, sizeof (cpp_hashnode *)); + + ((cpp_hashnode **) BUFF_FRONT (pfile->a_buff))[n] = spelling; + + /* Morph into a macro arg. */ + node->flags |= NODE_MACRO_ARG; + /* Index is 1 based. */ + node->value.arg_index = n + 1; + + return true; } -/* Check the syntax of the parameters in a MACRO definition. Returns - false if an error occurs. */ +/* Restore the parameters to their previous state. */ +void +_cpp_unsave_parameters (cpp_reader *pfile, unsigned n) +{ + /* Clear the fast argument lookup indices. */ + while (n--) + { + struct macro_arg_saved_data *save = + &((struct macro_arg_saved_data *) pfile->macro_buffer)[n]; + + struct cpp_hashnode *node = save->canonical_node; + node->value = save->value; + node->flags &= ~NODE_MACRO_ARG; + } +} + +/* Check the syntax of the parameters in a MACRO definition. Return + false on failure. Set *N_PTR and *VARADIC_PTR as appropriate. + '(' ')' + '(' parm-list ',' last-parm ')' + '(' last-parm ')' + parm-list: name + | parm-list, name + last-parm: name + | name '...' + | '...' +*/ static bool -parse_params (cpp_reader *pfile, cpp_macro *macro) +parse_params (cpp_reader *pfile, unsigned *n_ptr, bool *varadic_ptr) { - unsigned int prev_ident = 0; + unsigned nparms = 0; + bool ok = false; - for (;;) + for (bool prev_ident = false;;) { const cpp_token *token = _cpp_lex_token (pfile); switch (token->type) { - default: + case CPP_COMMENT: /* Allow/ignore comments in parameter lists if we are preserving comments in macro expansions. */ - if (token->type == CPP_COMMENT - && ! CPP_OPTION (pfile, discard_comments_in_macro_exp)) - continue; + if (!CPP_OPTION (pfile, discard_comments_in_macro_exp)) + break; - cpp_error (pfile, CPP_DL_ERROR, - "\"%s\" may not appear in macro parameter list", - cpp_token_as_text (pfile, token)); - return false; + /* FALLTHRU */ + default: + bad: + { + const char *const msgs[5] = + { + N_("expected parameter name, found \"%s\""), + N_("expected ',' or ')', found \"%s\""), + N_("expected parameter name before end of line"), + N_("expected ')' before end of line"), + N_("expected ')' after \"...\"") + }; + unsigned ix = prev_ident; + const unsigned char *as_text = NULL; + if (*varadic_ptr) + ix = 4; + else if (token->type == CPP_EOF) + ix += 2; + else + as_text = cpp_token_as_text (pfile, token); + cpp_error (pfile, CPP_DL_ERROR, msgs[ix], as_text); + } + goto out; case CPP_NAME: - if (prev_ident) - { - cpp_error (pfile, CPP_DL_ERROR, - "macro parameters must be comma-separated"); - return false; - } - prev_ident = 1; - - if (_cpp_save_parameter (pfile, macro, token->val.node.node, - token->val.node.spelling)) - return false; - continue; + if (prev_ident || *varadic_ptr) + goto bad; + prev_ident = true; + + if (!_cpp_save_parameter (pfile, nparms, token->val.node.node, + token->val.node.spelling)) + goto out; + nparms++; + break; case CPP_CLOSE_PAREN: - if (prev_ident || macro->paramc == 0) - return true; + if (prev_ident || !nparms || *varadic_ptr) + { + ok = true; + goto out; + } - /* Fall through to pick up the error. */ /* FALLTHRU */ case CPP_COMMA: - if (!prev_ident) - { - cpp_error (pfile, CPP_DL_ERROR, "parameter name missing"); - return false; - } - prev_ident = 0; - continue; + if (!prev_ident || *varadic_ptr) + goto bad; + prev_ident = false; + break; case CPP_ELLIPSIS: - macro->variadic = 1; + if (*varadic_ptr) + goto bad; + *varadic_ptr = true; if (!prev_ident) { - _cpp_save_parameter (pfile, macro, + /* An ISO bare ellipsis. */ + _cpp_save_parameter (pfile, nparms, pfile->spec_nodes.n__VA_ARGS__, pfile->spec_nodes.n__VA_ARGS__); + nparms++; pfile->state.va_args_ok = 1; if (! CPP_OPTION (pfile, c99) && CPP_OPTION (pfile, cpp_pedantic) && CPP_OPTION (pfile, warn_variadic_macros)) - { - if (CPP_OPTION (pfile, cplusplus)) - cpp_pedwarning - (pfile, CPP_W_VARIADIC_MACROS, - "anonymous variadic macros were introduced in C++11"); - else - cpp_pedwarning - (pfile, CPP_W_VARIADIC_MACROS, - "anonymous variadic macros were introduced in C99"); - } + cpp_pedwarning + (pfile, CPP_W_VARIADIC_MACROS, + CPP_OPTION (pfile, cplusplus) + ? N_("anonymous variadic macros were introduced in C++11") + : N_("anonymous variadic macros were introduced in C99")); else if (CPP_OPTION (pfile, cpp_warn_c90_c99_compat) > 0 && ! CPP_OPTION (pfile, cplusplus)) cpp_error (pfile, CPP_DL_WARNING, @@ -3173,26 +3212,18 @@ parse_params (cpp_reader *pfile, cpp_macro *macro) } else if (CPP_OPTION (pfile, cpp_pedantic) && CPP_OPTION (pfile, warn_variadic_macros)) - { - if (CPP_OPTION (pfile, cplusplus)) - cpp_pedwarning (pfile, CPP_W_VARIADIC_MACROS, - "ISO C++ does not permit named variadic macros"); - else - cpp_pedwarning (pfile, CPP_W_VARIADIC_MACROS, - "ISO C does not permit named variadic macros"); - } - - /* We're at the end, and just expect a closing parenthesis. */ - token = _cpp_lex_token (pfile); - if (token->type == CPP_CLOSE_PAREN) - return true; - /* Fall through. */ - - case CPP_EOF: - cpp_error (pfile, CPP_DL_ERROR, "missing ')' in macro parameter list"); - return false; + cpp_pedwarning (pfile, CPP_W_VARIADIC_MACROS, + CPP_OPTION (pfile, cplusplus) + ? N_("ISO C++ does not permit named variadic macros") + : N_("ISO C does not permit named variadic macros")); + break; } } + + out: + *n_ptr = nparms; + + return ok; } /* Allocate room for a token from a macro's replacement list. */ @@ -3242,17 +3273,24 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro) const char *paste_op_error_msg = N_("'##' cannot appear at either end of a macro expansion"); unsigned int num_extra_tokens = 0; + unsigned nparms = 0; + bool varadic = false; + bool ok = false; /* Get the first token of the expansion (or the '(' of a function-like macro). */ ctoken = _cpp_lex_token (pfile); - if (ctoken->type == CPP_OPEN_PAREN && !(ctoken->flags & PREV_WHITE)) + if (ctoken->flags & PREV_WHITE) + /* Preceeded by space, must be part of expansion. */; + else if (ctoken->type == CPP_OPEN_PAREN) { - bool ok = parse_params (pfile, macro); + /* An open-paren, get a parameter list. */ + if (!parse_params (pfile, &nparms, &varadic)) + goto out; + macro->variadic = varadic; + macro->paramc = nparms; macro->params = (cpp_hashnode **) BUFF_FRONT (pfile->a_buff); - if (!ok) - return false; /* Success. Commit or allocate the parameter array. */ if (pfile->hash_table->alloc_subobject) @@ -3274,14 +3312,10 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro) in a macro definition, ISO C90 with TC1 allows characters from the basic source character set there. */ if (CPP_OPTION (pfile, c99)) - { - if (CPP_OPTION (pfile, cplusplus)) - cpp_error (pfile, CPP_DL_PEDWARN, - "ISO C++11 requires whitespace after the macro name"); - else - cpp_error (pfile, CPP_DL_PEDWARN, - "ISO C99 requires whitespace after the macro name"); - } + cpp_error (pfile, CPP_DL_PEDWARN, + CPP_OPTION (pfile, cplusplus) + ? N_("ISO C++11 requires whitespace after the macro name") + : N_("ISO C99 requires whitespace after the macro name")); else { int warntype = CPP_DL_WARNING; @@ -3317,10 +3351,7 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro) *token = *ctoken; } - /* The argument doesn't matter here. */ - vaopt_state vaopt_tracker (pfile, macro->variadic, true); - - for (;;) + for ( vaopt_state vaopt_tracker (pfile, macro->variadic, true);;) { /* Check the stringifying # constraint 6.10.3.2.1 of function-like macros when lexing the subsequent token. */ @@ -3343,7 +3374,7 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro) { cpp_error (pfile, CPP_DL_ERROR, "'#' is not followed by a macro parameter"); - return false; + goto out; } } @@ -3355,8 +3386,10 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro) if (following_paste_op) { cpp_error (pfile, CPP_DL_ERROR, paste_op_error_msg); - return false; + goto out; } + if (!vaopt_tracker.completed ()) + goto out; break; } @@ -3368,7 +3401,7 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro) if (macro->count == 1) { cpp_error (pfile, CPP_DL_ERROR, paste_op_error_msg); - return false; + goto out; } if (token[-1].flags & PASTE_LEFT) @@ -3389,14 +3422,14 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro) } if (vaopt_tracker.update (token) == vaopt_state::ERROR) - return false; + goto out; following_paste_op = (token->type == CPP_PASTE); token = lex_expansion_token (pfile, macro); } - if (!vaopt_tracker.completed ()) - return false; + /* We're committed to winning now. */ + ok = true; macro->exp.tokens = (cpp_token *) BUFF_FRONT (pfile->a_buff); macro->traditional = 0; @@ -3440,7 +3473,11 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro) else BUFF_FRONT (pfile->a_buff) = (uchar *) ¯o->exp.tokens[macro->count]; - return true; + out: + pfile->state.va_args_ok = 0; + _cpp_unsave_parameters (pfile, nparms); + + return ok; } /* Parse a macro and save its expansion. Returns nonzero on success. */ @@ -3448,7 +3485,6 @@ bool _cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node) { cpp_macro *macro; - unsigned int i; bool ok; if (pfile->hash_table->alloc_subobject) @@ -3470,27 +3506,7 @@ _cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node) if (CPP_OPTION (pfile, traditional)) ok = _cpp_create_trad_definition (pfile, macro); else - { - ok = create_iso_definition (pfile, macro); - - /* We set the type for SEEN_EOL() in directives.c. - - Longer term we should lex the whole line before coming here, - and just copy the expansion. */ - - /* Stop the lexer accepting __VA_ARGS__. */ - pfile->state.va_args_ok = 0; - } - - /* Clear the fast argument lookup indices. */ - for (i = macro->paramc; i-- > 0; ) - { - struct macro_arg_saved_data *save = - &((struct macro_arg_saved_data *) pfile->macro_buffer)[i]; - struct cpp_hashnode *node = save->canonical_node; - node->flags &= ~ NODE_MACRO_ARG; - node->value = save->value; - } + ok = create_iso_definition (pfile, macro); if (!ok) return ok; diff --git a/libcpp/traditional.c b/libcpp/traditional.c index aa38ea4..f484236 100644 --- a/libcpp/traditional.c +++ b/libcpp/traditional.c @@ -89,7 +89,7 @@ static cpp_hashnode *lex_identifier (cpp_reader *, const uchar *); static const uchar *copy_comment (cpp_reader *, const uchar *, int); static void check_output_buffer (cpp_reader *, size_t); static void push_replacement_text (cpp_reader *, cpp_hashnode *); -static bool scan_parameters (cpp_reader *, cpp_macro *); +static bool scan_parameters (cpp_reader *, unsigned *); static bool recursive_macro (cpp_reader *, cpp_hashnode *); static void save_replacement_text (cpp_reader *, cpp_macro *, unsigned int); static void maybe_start_funlike (cpp_reader *, cpp_hashnode *, const uchar *, @@ -1082,11 +1082,12 @@ replace_args_and_push (cpp_reader *pfile, struct fun_macro *fmacro) duplicate parameter). On success, CUR (pfile->context) is just past the closing parenthesis. */ static bool -scan_parameters (cpp_reader *pfile, cpp_macro *macro) +scan_parameters (cpp_reader *pfile, unsigned *n_ptr) { const uchar *cur = CUR (pfile->context) + 1; bool ok; + unsigned nparms = 0; for (;;) { cur = skip_whitespace (pfile, cur, true /* skip_comments */); @@ -1095,8 +1096,9 @@ scan_parameters (cpp_reader *pfile, cpp_macro *macro) { struct cpp_hashnode *id = lex_identifier (pfile, cur); ok = false; - if (_cpp_save_parameter (pfile, macro, id, id)) + if (!_cpp_save_parameter (pfile, nparms, id, id)) break; + nparms++; cur = skip_whitespace (pfile, CUR (pfile->context), true /* skip_comments */); if (*cur == ',') @@ -1108,10 +1110,12 @@ scan_parameters (cpp_reader *pfile, cpp_macro *macro) break; } - ok = (*cur == ')' && macro->paramc == 0); + ok = (*cur == ')' && !nparms); break; } + *n_ptr = nparms; + if (!ok) cpp_error (pfile, CPP_DL_ERROR, "syntax error in macro parameter list"); @@ -1181,6 +1185,7 @@ _cpp_create_trad_definition (cpp_reader *pfile, cpp_macro *macro) const uchar *cur; uchar *limit; cpp_context *context = pfile->context; + unsigned nparms = 0; /* The context has not been set up for command line defines, and CUR has not been updated for the macro name for in-file defines. */ @@ -1192,7 +1197,8 @@ _cpp_create_trad_definition (cpp_reader *pfile, cpp_macro *macro) /* Is this a function-like macro? */ if (* CUR (context) == '(') { - bool ok = scan_parameters (pfile, macro); + bool ok = scan_parameters (pfile, &nparms); + macro->paramc = nparms; /* Remember the params so we can clear NODE_MACRO_ARG flags. */ macro->params = (cpp_hashnode **) BUFF_FRONT (pfile->a_buff); @@ -1217,6 +1223,8 @@ _cpp_create_trad_definition (cpp_reader *pfile, cpp_macro *macro) _cpp_scan_out_logical_line (pfile, macro, false); pfile->state.prevent_expansion--; + _cpp_unsave_parameters (pfile, nparms); + if (!macro) return false; -- cgit v1.1 From c5d725c0a8da3b2227d119871e881d8a6e1bf600 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Fri, 17 Aug 2018 12:04:13 +0000 Subject: [PATCH] Move cpp_macro to cpplib.h https://gcc.gnu.org/ml/gcc-patches/2018-08/msg01016.html libcpp/ * cpp-id-data.h (uchar, UC): Move to internal.h (struct cpp_macro): Move to cpplib.h. * internal.h (uchar, UC): From cpp-id-data.h. * include/cpplib.h (struct cpp_macro): From cpp-id-data.h. gcc/c-family/ * c-ada-spec.c: Don't #include "cpp-id-data.h" * c-cppbuiltin.c: Likewise. gcc/ * cppbuiltin.c: Include "cpplib.h", not "cpp-id-data.h". From-SVN: r263618 --- libcpp/ChangeLog | 7 ++++++ libcpp/include/cpp-id-data.h | 56 -------------------------------------------- libcpp/include/cpplib.h | 51 ++++++++++++++++++++++++++++++++++++++++ libcpp/internal.h | 6 +++++ 4 files changed, 64 insertions(+), 56 deletions(-) (limited to 'libcpp') diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index 5f087ec..978b32e 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,3 +1,10 @@ +2018-08-17 Nathan Sidwell + + * cpp-id-data.h (uchar, UC): Move to internal.h + (struct cpp_macro): Move to cpplib.h. + * internal.h (uchar, UC): From cpp-id-data.h. + * include/cpplib.h (struct cpp_macro): From cpp-id-data.h. + 2018-08-16 Nathan Sidwell * internal.h (_cpp_save_parameter): Take parmno, not macro. diff --git a/libcpp/include/cpp-id-data.h b/libcpp/include/cpp-id-data.h index 0299984..fb073fa 100644 --- a/libcpp/include/cpp-id-data.h +++ b/libcpp/include/cpp-id-data.h @@ -17,12 +17,6 @@ along with this program; see the file COPYING3. If not see #include "cpplib.h" -#if !defined (HAVE_UCHAR) && !defined (IN_GCC) -typedef unsigned char uchar; -#endif - -#define UC (const unsigned char *) /* Intended use: UC"string" */ - /* Chained list of answers to an assertion. */ struct GTY(()) answer { struct answer *next; @@ -30,53 +24,3 @@ struct GTY(()) answer { cpp_token GTY ((length ("%h.count"))) first[1]; }; -/* Each macro definition is recorded in a cpp_macro structure. - Variadic macros cannot occur with traditional cpp. */ -struct GTY(()) cpp_macro { - /* Parameters, if any. If parameter names use extended identifiers, - the original spelling of those identifiers, not the canonical - UTF-8 spelling, goes here. */ - 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"), - length ("%h.paramc"))) - params; - - /* Replacement tokens (ISO) or replacement text (traditional). See - comment at top of cpptrad.c for how traditional function-like - macros are encoded. */ - union cpp_macro_u - { - cpp_token * GTY ((tag ("0"), length ("%0.count"))) tokens; - const unsigned char * GTY ((tag ("1"))) text; - } GTY ((desc ("%1.traditional"))) exp; - - /* Definition line number. */ - source_location line; - - /* Number of tokens in expansion, or bytes for traditional macros. */ - unsigned int count; - - /* Number of parameters. */ - unsigned short paramc; - - /* If a function-like macro. */ - unsigned int fun_like : 1; - - /* If a variadic macro. */ - unsigned int variadic : 1; - - /* If macro defined in system header. */ - unsigned int syshdr : 1; - - /* Nonzero if it has been expanded or had its existence tested. */ - unsigned int used : 1; - - /* Indicate which field of 'exp' is in use. */ - unsigned int traditional : 1; - - /* Indicate whether the tokens include extra CPP_PASTE tokens at the - end to track invalid redefinitions with consecutive CPP_PASTE - tokens. */ - unsigned int extra_tokens : 1; -}; diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h index 99992a2..2b3440d 100644 --- a/libcpp/include/cpplib.h +++ b/libcpp/include/cpplib.h @@ -671,6 +671,57 @@ struct cpp_dir dev_t dev; }; +/* Each macro definition is recorded in a cpp_macro structure. + Variadic macros cannot occur with traditional cpp. */ +struct GTY(()) cpp_macro { + /* Parameters, if any. If parameter names use extended identifiers, + the original spelling of those identifiers, not the canonical + UTF-8 spelling, goes here. */ + 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"), + length ("%h.paramc"))) + params; + + /* Replacement tokens (ISO) or replacement text (traditional). See + comment at top of cpptrad.c for how traditional function-like + macros are encoded. */ + union cpp_macro_u + { + cpp_token * GTY ((tag ("0"), length ("%0.count"))) tokens; + const unsigned char * GTY ((tag ("1"))) text; + } GTY ((desc ("%1.traditional"))) exp; + + /* Definition line number. */ + source_location line; + + /* Number of tokens in expansion, or bytes for traditional macros. */ + unsigned int count; + + /* Number of parameters. */ + unsigned short paramc; + + /* If a function-like macro. */ + unsigned int fun_like : 1; + + /* If a variadic macro. */ + unsigned int variadic : 1; + + /* If macro defined in system header. */ + unsigned int syshdr : 1; + + /* Nonzero if it has been expanded or had its existence tested. */ + unsigned int used : 1; + + /* Indicate which field of 'exp' is in use. */ + unsigned int traditional : 1; + + /* Indicate whether the tokens include extra CPP_PASTE tokens at the + end to track invalid redefinitions with consecutive CPP_PASTE + tokens. */ + unsigned int extra_tokens : 1; +}; + /* The structure of a node in the hash table. The hash table has entries for all identifiers: either macros defined by #define commands (type NT_MACRO), assertions created with #assert diff --git a/libcpp/internal.h b/libcpp/internal.h index 0012520..0c2395a 100644 --- a/libcpp/internal.h +++ b/libcpp/internal.h @@ -602,6 +602,12 @@ extern const unsigned char _cpp_trigraph_map[UCHAR_MAX + 1]; extern unsigned char _cpp_trigraph_map[UCHAR_MAX + 1]; #endif +#if !defined (HAVE_UCHAR) && !defined (IN_GCC) +typedef unsigned char uchar; +#endif + +#define UC (const uchar *) /* Intended use: UC"string" */ + /* Macros. */ static inline int cpp_in_system_header (cpp_reader *); -- cgit v1.1 From 10f04917abbc42e3717d33d9b5079aa4f9eb9ac5 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Fri, 17 Aug 2018 16:07:19 +0000 Subject: [PATCH] Macro body is trailing array https://gcc.gnu.org/ml/gcc-patches/2018-08/msg01037.html * include/cpplib.h (enum cpp_macro_kind): New. (struct cpp_macro): Make body trailing array. Add kind field, delete traditional flag. * internal.h (_cpp_new_macro): Declare. (_cpp_reserve_room): New inline. (_cpp_commit_buf): Declare. (_cpp_create_trad_definition): Return new macro. * lex.c (_cpp_commit_buff): New. * macro.c (macro_real_token_count): Count backwards. (replace_args): Pointer equality not orderedness. (_cpp_save_parameter): Use _cpp_reserve_room. (alloc_expansion_token): Delete. (lex_expansion_token): Return macro pointer. Use _cpp_reserve_room. (create_iso_definition): Allocate macro itself. Adjust for different allocation ordering. (_cpp_new_macro): New. (_cpp_create_definition): Adjust for API changes. * traditional.c (push_replacement_text): Don't set traditional flag. (save_replacement_text): Likewise. (_cpp_create_trad_definition): Allocate macro itself, Adjust for different allocation ordering. From-SVN: r263622 --- libcpp/ChangeLog | 23 +++++ libcpp/include/cpplib.h | 34 ++++--- libcpp/internal.h | 11 ++- libcpp/lex.c | 19 ++++ libcpp/macro.c | 236 ++++++++++++++++++++++++------------------------ libcpp/traditional.c | 59 ++++++------ 6 files changed, 221 insertions(+), 161 deletions(-) (limited to 'libcpp') diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index 978b32e..c79866f 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,5 +1,28 @@ 2018-08-17 Nathan Sidwell + * include/cpplib.h (enum cpp_macro_kind): New. + (struct cpp_macro): Make body trailing array. Add kind field, + delete traditional flag. + * internal.h (_cpp_new_macro): Declare. + (_cpp_reserve_room): New inline. + (_cpp_commit_buf): Declare. + (_cpp_create_trad_definition): Return new macro. + * lex.c (_cpp_commit_buff): New. + * macro.c (macro_real_token_count): Count backwards. + (replace_args): Pointer equality not orderedness. + (_cpp_save_parameter): Use _cpp_reserve_room. + (alloc_expansion_token): Delete. + (lex_expansion_token): Return macro pointer. Use _cpp_reserve_room. + (create_iso_definition): Allocate macro itself. Adjust for + different allocation ordering. + (_cpp_new_macro): New. + (_cpp_create_definition): Adjust for API changes. + * traditional.c (push_replacement_text): Don't set traditional + flag. + (save_replacement_text): Likewise. + (_cpp_create_trad_definition): Allocate macro itself, Adjust for + different allocation ordering. + * cpp-id-data.h (uchar, UC): Move to internal.h (struct cpp_macro): Move to cpplib.h. * internal.h (uchar, UC): From cpp-id-data.h. diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h index 2b3440d..a0d0c53 100644 --- a/libcpp/include/cpplib.h +++ b/libcpp/include/cpplib.h @@ -671,6 +671,12 @@ struct cpp_dir dev_t dev; }; +/* The kind of the cpp_macro. */ +enum cpp_macro_kind { + cmk_macro, /* An ISO macro (token expansion). */ + cmk_traditional, /* A traditional macro (text expansion). */ +}; + /* Each macro definition is recorded in a cpp_macro structure. Variadic macros cannot occur with traditional cpp. */ struct GTY(()) cpp_macro { @@ -683,15 +689,6 @@ struct GTY(()) cpp_macro { length ("%h.paramc"))) params; - /* Replacement tokens (ISO) or replacement text (traditional). See - comment at top of cpptrad.c for how traditional function-like - macros are encoded. */ - union cpp_macro_u - { - cpp_token * GTY ((tag ("0"), length ("%0.count"))) tokens; - const unsigned char * GTY ((tag ("1"))) text; - } GTY ((desc ("%1.traditional"))) exp; - /* Definition line number. */ source_location line; @@ -701,6 +698,9 @@ struct GTY(()) cpp_macro { /* Number of parameters. */ unsigned short paramc; + /* The kind of this macro (ISO, trad or assert) */ + unsigned kind : 2; + /* If a function-like macro. */ unsigned int fun_like : 1; @@ -713,13 +713,23 @@ struct GTY(()) cpp_macro { /* Nonzero if it has been expanded or had its existence tested. */ unsigned int used : 1; - /* Indicate which field of 'exp' is in use. */ - unsigned int traditional : 1; - /* Indicate whether the tokens include extra CPP_PASTE tokens at the end to track invalid redefinitions with consecutive CPP_PASTE tokens. */ unsigned int extra_tokens : 1; + + /* 1 bits spare (32-bit). 33 on 64-bit target. */ + + union cpp_exp_u + { + /* Trailing array of replacement tokens (ISO), or assertion body value. */ + cpp_token GTY ((tag ("false"), length ("%1.count"))) tokens[1]; + + /* Pointer to replacement text (traditional). See comment at top + of cpptrad.c for how traditional function-like macros are + encoded. */ + const unsigned char *GTY ((tag ("true"))) text; + } GTY ((desc ("%1.kind == cmk_traditional"))) exp; }; /* The structure of a node in the hash table. The hash table has diff --git a/libcpp/internal.h b/libcpp/internal.h index 0c2395a..e40b20f 100644 --- a/libcpp/internal.h +++ b/libcpp/internal.h @@ -633,6 +633,7 @@ inline void _cpp_maybe_notify_macro_use (cpp_reader *pfile, cpp_hashnode *node) if (!(node->flags & NODE_USED)) _cpp_notify_macro_use (pfile, node); } +extern cpp_macro *_cpp_new_macro (cpp_reader *, cpp_macro_kind, void *); extern void _cpp_free_definition (cpp_hashnode *); extern bool _cpp_create_definition (cpp_reader *, cpp_hashnode *); extern void _cpp_pop_context (cpp_reader *); @@ -697,6 +698,14 @@ extern void _cpp_init_tokenrun (tokenrun *, unsigned int); extern cpp_hashnode *_cpp_lex_identifier (cpp_reader *, const char *); extern int _cpp_remaining_tokens_num_in_context (cpp_context *); extern void _cpp_init_lexer (void); +static inline void *_cpp_reserve_room (cpp_reader *pfile, size_t have, + size_t extra) +{ + if (BUFF_ROOM (pfile->a_buff) < (have + extra)) + _cpp_extend_buff (pfile, &pfile->a_buff, extra); + return BUFF_FRONT (pfile->a_buff); +} +extern void *_cpp_commit_buff (cpp_reader *pfile, size_t size); /* In init.c. */ extern void _cpp_maybe_push_include_file (cpp_reader *); @@ -733,7 +742,7 @@ extern bool _cpp_read_logical_line_trad (cpp_reader *); extern void _cpp_overlay_buffer (cpp_reader *pfile, const unsigned char *, size_t); extern void _cpp_remove_overlay (cpp_reader *); -extern bool _cpp_create_trad_definition (cpp_reader *, cpp_macro *); +extern cpp_macro *_cpp_create_trad_definition (cpp_reader *); extern bool _cpp_expansions_different_trad (const cpp_macro *, const cpp_macro *); extern unsigned char *_cpp_copy_replacement_text (const cpp_macro *, diff --git a/libcpp/lex.c b/libcpp/lex.c index fa465be..892cfc4 100644 --- a/libcpp/lex.c +++ b/libcpp/lex.c @@ -3725,6 +3725,25 @@ _cpp_aligned_alloc (cpp_reader *pfile, size_t len) return result; } +/* Commit or allocate storage from a buffer. */ + +void * +_cpp_commit_buff (cpp_reader *pfile, size_t size) +{ + void *ptr = BUFF_FRONT (pfile->a_buff); + + if (pfile->hash_table->alloc_subobject) + { + void *copy = pfile->hash_table->alloc_subobject (size); + memcpy (copy, ptr, size); + ptr = copy; + } + else + BUFF_FRONT (pfile->a_buff) += size; + + return ptr; +} + /* Say which field of TOK is in use. */ enum cpp_token_fld_kind diff --git a/libcpp/macro.c b/libcpp/macro.c index 52098ef..25f4a36 100644 --- a/libcpp/macro.c +++ b/libcpp/macro.c @@ -308,12 +308,11 @@ static void replace_args (cpp_reader *, cpp_hashnode *, cpp_macro *, macro_arg *, source_location); static _cpp_buff *funlike_invocation_p (cpp_reader *, cpp_hashnode *, _cpp_buff **, unsigned *); -static bool create_iso_definition (cpp_reader *, cpp_macro *); +static cpp_macro *create_iso_definition (cpp_reader *); /* #define directive parsing and handling. */ -static cpp_token *alloc_expansion_token (cpp_reader *, cpp_macro *); -static cpp_token *lex_expansion_token (cpp_reader *, cpp_macro *); +static cpp_macro *lex_expansion_token (cpp_reader *, cpp_macro *); static bool warn_of_redefinition (cpp_reader *, cpp_hashnode *, const cpp_macro *); static bool parse_params (cpp_reader *, unsigned *, bool *); @@ -1235,13 +1234,14 @@ funlike_invocation_p (cpp_reader *pfile, cpp_hashnode *node, static inline unsigned int macro_real_token_count (const cpp_macro *macro) { - unsigned int i; if (__builtin_expect (!macro->extra_tokens, true)) return macro->count; - for (i = 0; i < macro->count; i++) - if (macro->exp.tokens[i].type == CPP_PASTE) - return i; - abort (); + + for (unsigned i = macro->count; i--;) + if (macro->exp.tokens[i].type != CPP_PASTE) + return i + 1; + + return 0; } /* Push the context of a macro with hash entry NODE onto the context @@ -1773,7 +1773,7 @@ replace_args (cpp_reader *pfile, cpp_hashnode *node, cpp_macro *macro, arg->stringified = stringify_arg (pfile, arg); } else if ((src->flags & PASTE_LEFT) - || (src > macro->exp.tokens && (src[-1].flags & PASTE_LEFT))) + || (src != macro->exp.tokens && (src[-1].flags & PASTE_LEFT))) total += arg->count - 1; else { @@ -3078,10 +3078,9 @@ _cpp_save_parameter (cpp_reader *pfile, unsigned n, cpp_hashnode *node, saved[n].canonical_node = node; saved[n].value = node->value; - if (BUFF_ROOM (pfile->a_buff) < (n + 1) * sizeof (cpp_hashnode *)) - _cpp_extend_buff (pfile, &pfile->a_buff, sizeof (cpp_hashnode *)); - - ((cpp_hashnode **) BUFF_FRONT (pfile->a_buff))[n] = spelling; + void *base = _cpp_reserve_room (pfile, n * sizeof (cpp_hashnode *), + sizeof (cpp_hashnode *)); + ((cpp_hashnode **)base)[n] = spelling; /* Morph into a macro arg. */ node->flags |= NODE_MACRO_ARG; @@ -3226,26 +3225,18 @@ parse_params (cpp_reader *pfile, unsigned *n_ptr, bool *varadic_ptr) return ok; } -/* Allocate room for a token from a macro's replacement list. */ -static cpp_token * -alloc_expansion_token (cpp_reader *pfile, cpp_macro *macro) -{ - if (BUFF_ROOM (pfile->a_buff) < (macro->count + 1) * sizeof (cpp_token)) - _cpp_extend_buff (pfile, &pfile->a_buff, sizeof (cpp_token)); - - return &((cpp_token *) BUFF_FRONT (pfile->a_buff))[macro->count++]; -} - /* Lex a token from the expansion of MACRO, but mark parameters as we find them and warn of traditional stringification. */ -static cpp_token * +static cpp_macro * lex_expansion_token (cpp_reader *pfile, cpp_macro *macro) { - cpp_token *token, *saved_cur_token; - - saved_cur_token = pfile->cur_token; - pfile->cur_token = alloc_expansion_token (pfile, macro); - token = _cpp_lex_direct (pfile); + macro = (cpp_macro *)_cpp_reserve_room (pfile, + sizeof (cpp_macro) - sizeof (cpp_token) + + macro->count * sizeof (cpp_token), + sizeof (cpp_token)); + cpp_token *saved_cur_token = pfile->cur_token; + pfile->cur_token = ¯o->exp.tokens[macro->count]; + cpp_token *token = _cpp_lex_direct (pfile); pfile->cur_token = saved_cur_token; /* Is this a parameter? */ @@ -3261,52 +3252,45 @@ lex_expansion_token (cpp_reader *pfile, cpp_macro *macro) && (token->type == CPP_STRING || token->type == CPP_CHAR)) check_trad_stringification (pfile, macro, &token->val.str); - return token; + return macro; } -static bool -create_iso_definition (cpp_reader *pfile, cpp_macro *macro) +static cpp_macro * +create_iso_definition (cpp_reader *pfile) { - cpp_token *token; - const cpp_token *ctoken; bool following_paste_op = false; const char *paste_op_error_msg = N_("'##' cannot appear at either end of a macro expansion"); unsigned int num_extra_tokens = 0; unsigned nparms = 0; + cpp_hashnode **params = NULL; bool varadic = false; bool ok = false; + cpp_macro *macro = NULL; - /* Get the first token of the expansion (or the '(' of a - function-like macro). */ - ctoken = _cpp_lex_token (pfile); + /* Look at the first token, to see if this is a function-like + macro. */ + cpp_token first; + cpp_token *saved_cur_token = pfile->cur_token; + pfile->cur_token = &first; + cpp_token *token = _cpp_lex_direct (pfile); + pfile->cur_token = saved_cur_token; - if (ctoken->flags & PREV_WHITE) + if (token->flags & PREV_WHITE) /* Preceeded by space, must be part of expansion. */; - else if (ctoken->type == CPP_OPEN_PAREN) + else if (token->type == CPP_OPEN_PAREN) { /* An open-paren, get a parameter list. */ if (!parse_params (pfile, &nparms, &varadic)) goto out; - macro->variadic = varadic; - macro->paramc = nparms; - macro->params = (cpp_hashnode **) BUFF_FRONT (pfile->a_buff); - /* Success. Commit or allocate the parameter array. */ - if (pfile->hash_table->alloc_subobject) - { - cpp_hashnode **params = - (cpp_hashnode **) pfile->hash_table->alloc_subobject - (sizeof (cpp_hashnode *) * macro->paramc); - memcpy (params, macro->params, - sizeof (cpp_hashnode *) * macro->paramc); - macro->params = params; - } - else - BUFF_FRONT (pfile->a_buff) = (uchar *) ¯o->params[macro->paramc]; - macro->fun_like = 1; + params = (cpp_hashnode **)_cpp_commit_buff + (pfile, sizeof (cpp_hashnode *) * nparms); + token = NULL; } - else if (ctoken->type != CPP_EOF && !(ctoken->flags & PREV_WHITE)) + else if (token->type != CPP_EOF + && !(token->type == CPP_COMMENT + && ! CPP_OPTION (pfile, discard_comments_in_macro_exp))) { /* While ISO C99 requires whitespace before replacement text in a macro definition, ISO C90 with TC1 allows characters @@ -3319,7 +3303,7 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro) else { int warntype = CPP_DL_WARNING; - switch (ctoken->type) + switch (token->type) { case CPP_ATSIGN: case CPP_AT_NAME: @@ -3330,7 +3314,7 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro) case CPP_OTHER: /* Basic character set sans letters, digits and _. */ if (strchr ("!\"#%&'()*+,-./:;<=>?[\\]^{|}~", - ctoken->val.str.text[0]) == NULL) + token->val.str.text[0]) == NULL) warntype = CPP_DL_PEDWARN; break; default: @@ -3343,16 +3327,32 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro) } } - if (macro->fun_like) - token = lex_expansion_token (pfile, macro); + macro = _cpp_new_macro (pfile, cmk_macro, + _cpp_reserve_room (pfile, 0, sizeof (cpp_macro))); + + if (!token) + { + macro->variadic = varadic; + macro->paramc = nparms; + macro->params = params; + macro->fun_like = true; + } else { - token = alloc_expansion_token (pfile, macro); - *token = *ctoken; + /* Preserve the token we peeked, there is already a single slot for it. */ + macro->exp.tokens[0] = *token; + token = ¯o->exp.tokens[0]; + macro->count = 1; } - for ( vaopt_state vaopt_tracker (pfile, macro->variadic, true);;) + for (vaopt_state vaopt_tracker (pfile, macro->variadic, true);; token = NULL) { + if (!token) + { + macro = lex_expansion_token (pfile, macro); + token = ¯o->exp.tokens[macro->count++]; + } + /* Check the stringifying # constraint 6.10.3.2.1 of function-like macros when lexing the subsequent token. */ if (macro->count > 1 && token[-1].type == CPP_HASH && macro->fun_like) @@ -3404,14 +3404,16 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro) goto out; } - if (token[-1].flags & PASTE_LEFT) + if (following_paste_op) { - macro->extra_tokens = 1; + /* Consecutive paste operators. This one will be moved + to the end. */ num_extra_tokens++; token->val.token_no = macro->count - 1; } else { + /* Drop the paste operator. */ --macro->count; token[-1].flags |= PASTE_LEFT; if (token->flags & DIGRAPH) @@ -3419,79 +3421,64 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro) if (token->flags & PREV_WHITE) token[-1].flags |= SP_PREV_WHITE; } + following_paste_op = true; } + else + following_paste_op = false; if (vaopt_tracker.update (token) == vaopt_state::ERROR) goto out; - - following_paste_op = (token->type == CPP_PASTE); - token = lex_expansion_token (pfile, macro); } /* We're committed to winning now. */ ok = true; - macro->exp.tokens = (cpp_token *) BUFF_FRONT (pfile->a_buff); - macro->traditional = 0; - /* Don't count the CPP_EOF. */ macro->count--; + macro = (cpp_macro *)_cpp_commit_buff + (pfile, sizeof (cpp_macro) - sizeof (cpp_token) + + sizeof (cpp_token) * macro->count); + /* Clear whitespace on first token for warn_of_redefinition(). */ if (macro->count) macro->exp.tokens[0].flags &= ~PREV_WHITE; - /* Commit or allocate the memory. */ - if (pfile->hash_table->alloc_subobject) + if (num_extra_tokens) { - cpp_token *tokns = - (cpp_token *) pfile->hash_table->alloc_subobject (sizeof (cpp_token) - * macro->count); - if (num_extra_tokens) - { - /* Place second and subsequent ## or %:%: tokens in - sequences of consecutive such tokens at the end of the - list to preserve information about where they appear, how - they are spelt and whether they are preceded by - whitespace without otherwise interfering with macro - expansion. */ - cpp_token *normal_dest = tokns; - cpp_token *extra_dest = tokns + macro->count - num_extra_tokens; - unsigned int i; - for (i = 0; i < macro->count; i++) - { - if (macro->exp.tokens[i].type == CPP_PASTE) - *extra_dest++ = macro->exp.tokens[i]; - else - *normal_dest++ = macro->exp.tokens[i]; - } - } - else - memcpy (tokns, macro->exp.tokens, sizeof (cpp_token) * macro->count); - macro->exp.tokens = tokns; + /* Place second and subsequent ## or %:%: tokens in sequences of + consecutive such tokens at the end of the list to preserve + information about where they appear, how they are spelt and + whether they are preceded by whitespace without otherwise + interfering with macro expansion. Remember, this is + extremely rare, so efficiency is not a priority. */ + cpp_token *temp = (cpp_token *)_cpp_reserve_room + (pfile, 0, num_extra_tokens * sizeof (cpp_token)); + unsigned extra_ix = 0, norm_ix = 0; + cpp_token *exp = macro->exp.tokens; + for (unsigned ix = 0; ix != macro->count; ix++) + if (exp[ix].type == CPP_PASTE) + temp[extra_ix++] = exp[ix]; + else + exp[norm_ix++] = exp[ix]; + memcpy (&exp[norm_ix], temp, num_extra_tokens * sizeof (cpp_token)); + + /* Record there are extra tokens. */ + macro->extra_tokens = 1; } - else - BUFF_FRONT (pfile->a_buff) = (uchar *) ¯o->exp.tokens[macro->count]; out: pfile->state.va_args_ok = 0; _cpp_unsave_parameters (pfile, nparms); - return ok; + return ok ? macro : NULL; } -/* Parse a macro and save its expansion. Returns nonzero on success. */ -bool -_cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node) +cpp_macro * +_cpp_new_macro (cpp_reader *pfile, cpp_macro_kind kind, void *placement) { - cpp_macro *macro; - bool ok; + cpp_macro *macro = (cpp_macro *) placement; - if (pfile->hash_table->alloc_subobject) - macro = (cpp_macro *) pfile->hash_table->alloc_subobject - (sizeof (cpp_macro)); - else - macro = (cpp_macro *) _cpp_aligned_alloc (pfile, sizeof (cpp_macro)); macro->line = pfile->directive_line; macro->params = 0; macro->paramc = 0; @@ -3503,15 +3490,26 @@ _cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node) /* To suppress some diagnostics. */ macro->syshdr = pfile->buffer && pfile->buffer->sysp != 0; + macro->kind = kind; + + return macro; +} + +/* Parse a macro and save its expansion. Returns nonzero on success. */ +bool +_cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node) +{ + cpp_macro *macro; + if (CPP_OPTION (pfile, traditional)) - ok = _cpp_create_trad_definition (pfile, macro); + macro = _cpp_create_trad_definition (pfile); else - ok = create_iso_definition (pfile, macro); + macro = create_iso_definition (pfile); - if (!ok) - return ok; + if (!macro) + return false; - if (node->type == NT_MACRO) + if (cpp_macro_p (node)) { if (CPP_OPTION (pfile, warn_unused_macros)) _cpp_warn_if_unused_macro (pfile, node, NULL); @@ -3552,7 +3550,7 @@ _cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node) conditional flag */ node->flags &= ~NODE_CONDITIONAL; - return ok; + return true; } /* Notify the use of NODE in a macro-aware context (i.e. expanding it, @@ -3678,7 +3676,7 @@ cpp_macro_definition (cpp_reader *pfile, cpp_hashnode *node) unsigned int count = macro_real_token_count (macro); for (i = 0; i < count; i++) { - cpp_token *token = ¯o->exp.tokens[i]; + const cpp_token *token = ¯o->exp.tokens[i]; if (token->type == CPP_MACRO_ARG) len += NODE_LEN (token->val.macro_arg.spelling); @@ -3742,7 +3740,7 @@ cpp_macro_definition (cpp_reader *pfile, cpp_hashnode *node) unsigned int count = macro_real_token_count (macro); for (i = 0; i < count; i++) { - cpp_token *token = ¯o->exp.tokens[i]; + const cpp_token *token = ¯o->exp.tokens[i]; if (token->flags & PREV_WHITE) *buffer++ = ' '; diff --git a/libcpp/traditional.c b/libcpp/traditional.c index f484236..3c3b8ac 100644 --- a/libcpp/traditional.c +++ b/libcpp/traditional.c @@ -853,7 +853,6 @@ push_replacement_text (cpp_reader *pfile, cpp_hashnode *node) cpp_macro *macro = node->value.macro; macro->used = 1; text = macro->exp.text; - macro->traditional = 1; len = macro->count; } @@ -1143,7 +1142,6 @@ save_replacement_text (cpp_reader *pfile, cpp_macro *macro, memcpy (exp, pfile->out.base, len); exp[len] = '\n'; macro->exp.text = exp; - macro->traditional = 1; macro->count = len; } else @@ -1159,7 +1157,6 @@ save_replacement_text (cpp_reader *pfile, cpp_macro *macro, exp = BUFF_FRONT (pfile->a_buff); block = (struct block *) (exp + macro->count); macro->exp.text = exp; - macro->traditional = 1; /* Write out the block information. */ block->text_len = len; @@ -1179,13 +1176,15 @@ save_replacement_text (cpp_reader *pfile, cpp_macro *macro, /* Analyze and save the replacement text of a macro. Returns true on success. */ -bool -_cpp_create_trad_definition (cpp_reader *pfile, cpp_macro *macro) +cpp_macro * +_cpp_create_trad_definition (cpp_reader *pfile) { const uchar *cur; uchar *limit; cpp_context *context = pfile->context; unsigned nparms = 0; + int fun_like = 0; + cpp_hashnode **params = NULL; /* The context has not been set up for command line defines, and CUR has not been updated for the macro name for in-file defines. */ @@ -1197,21 +1196,23 @@ _cpp_create_trad_definition (cpp_reader *pfile, cpp_macro *macro) /* Is this a function-like macro? */ if (* CUR (context) == '(') { - bool ok = scan_parameters (pfile, &nparms); - macro->paramc = nparms; + fun_like = +1; + if (scan_parameters (pfile, &nparms)) + params = (cpp_hashnode **)_cpp_commit_buff + (pfile, sizeof (cpp_hashnode *) * nparms); + else + fun_like = -1; + } - /* Remember the params so we can clear NODE_MACRO_ARG flags. */ - macro->params = (cpp_hashnode **) BUFF_FRONT (pfile->a_buff); + cpp_macro *macro = NULL; - /* Setting macro to NULL indicates an error occurred, and - prevents unnecessary work in _cpp_scan_out_logical_line. */ - if (!ok) - macro = NULL; - else - { - BUFF_FRONT (pfile->a_buff) = (uchar *) ¯o->params[macro->paramc]; - macro->fun_like = 1; - } + if (fun_like >= 0) + { + macro = _cpp_new_macro (pfile, cmk_traditional, + _cpp_aligned_alloc (pfile, sizeof (cpp_macro))); + macro->params = params; + macro->paramc = nparms; + macro->fun_like = fun_like != 0; } /* Skip leading whitespace in the replacement text. */ @@ -1225,18 +1226,18 @@ _cpp_create_trad_definition (cpp_reader *pfile, cpp_macro *macro) _cpp_unsave_parameters (pfile, nparms); - if (!macro) - return false; - - /* Skip trailing white space. */ - cur = pfile->out.base; - limit = pfile->out.cur; - while (limit > cur && is_space (limit[-1])) - limit--; - pfile->out.cur = limit; - save_replacement_text (pfile, macro, 0); + if (macro) + { + /* Skip trailing white space. */ + cur = pfile->out.base; + limit = pfile->out.cur; + while (limit > cur && is_space (limit[-1])) + limit--; + pfile->out.cur = limit; + save_replacement_text (pfile, macro, 0); + } - return true; + return macro; } /* Copy SRC of length LEN to DEST, but convert all contiguous -- cgit v1.1 From 800c0e9877f2adce864fd3e0c0ee5906bd32736f Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Fri, 17 Aug 2018 23:18:11 +0000 Subject: [PATCH] Adjust lazy macro definition https://gcc.gnu.org/ml/gcc-patches/2018-08/msg01072.html libcpp/ * include/cpplib.h (struct cpp_callbacks): Replace user_builtin_macro with user_lazy_macro. (struct cpp_macro): add lazy field. (enum cpp_builtin_type): Remove BT_FIRST_USER, BT_LAST_USER. (cpp_define_lazily): Declare. * macro.c (enter_macro_context) Use _cpp_maybe_notify_macro_use. (warn_of_redefinition): Use cpp_builtin_macro_p, directly call user_lazy_macro hook. (_cpp_new_macro): Clear lazy field. (cpp_define_lazily): Define. (_cpp_notify_macro_use): Adjust lazy definition code. (cpp_macro_definition): No need to do lazy definition here. * pch.c (write_macdef, save_macros): Likewise. gcc/c-family/ * c-cppbuiltin.c (struct lazy_hex_fp_value_struct): Remove macro field. (laxy_hex_fp_value_count): Make unsigned. (lazy_hex_fp_value): Provided with macro & lazy number. Directly manipulate the macro. (builtin_defin_with_hex_fp_value): Adjust callback name, use cpp_define_lazily. From-SVN: r263640 --- libcpp/ChangeLog | 14 ++++++++++ libcpp/include/cpplib.h | 14 ++++++---- libcpp/macro.c | 74 ++++++++++++++++++++++++------------------------- libcpp/pch.c | 9 +----- 4 files changed, 60 insertions(+), 51 deletions(-) (limited to 'libcpp') diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index c79866f..994d424 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,5 +1,19 @@ 2018-08-17 Nathan Sidwell + * include/cpplib.h (struct cpp_callbacks): Replace + user_builtin_macro with user_lazy_macro. + (struct cpp_macro): add lazy field. + (enum cpp_builtin_type): Remove BT_FIRST_USER, BT_LAST_USER. + (cpp_define_lazily): Declare. + * macro.c (enter_macro_context) Use _cpp_maybe_notify_macro_use. + (warn_of_redefinition): Use cpp_builtin_macro_p, directly call + user_lazy_macro hook. + (_cpp_new_macro): Clear lazy field. + (cpp_define_lazily): Define. + (_cpp_notify_macro_use): Adjust lazy definition code. + (cpp_macro_definition): No need to do lazy definition here. + * pch.c (write_macdef, save_macros): Likewise. + * include/cpplib.h (enum cpp_macro_kind): New. (struct cpp_macro): Make body trailing array. Add kind field, delete traditional flag. diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h index a0d0c53..e0be2dc 100644 --- a/libcpp/include/cpplib.h +++ b/libcpp/include/cpplib.h @@ -605,8 +605,8 @@ struct cpp_callbacks /* Callback to identify whether an attribute exists. */ int (*has_attribute) (cpp_reader *); - /* Callback that can change a user builtin into normal macro. */ - bool (*user_builtin_macro) (cpp_reader *, cpp_hashnode *); + /* Callback that can change a user lazy into normal macro. */ + void (*user_lazy_macro) (cpp_reader *, cpp_macro *, unsigned); /* Callback to parse SOURCE_DATE_EPOCH from environment. */ time_t (*get_source_date_epoch) (cpp_reader *); @@ -698,6 +698,9 @@ struct GTY(()) cpp_macro { /* Number of parameters. */ unsigned short paramc; + /* Non-zero if this is a user-lazy macro, value provided by user. */ + unsigned char lazy; + /* The kind of this macro (ISO, trad or assert) */ unsigned kind : 2; @@ -778,9 +781,7 @@ enum cpp_builtin_type BT_PRAGMA, /* `_Pragma' operator */ BT_TIMESTAMP, /* `__TIMESTAMP__' */ BT_COUNTER, /* `__COUNTER__' */ - BT_HAS_ATTRIBUTE, /* `__has_attribute__(x)' */ - BT_FIRST_USER, /* User defined builtin macros. */ - BT_LAST_USER = BT_FIRST_USER + 63 + BT_HAS_ATTRIBUTE /* `__has_attribute__(x)' */ }; #define CPP_HASHNODE(HNODE) ((cpp_hashnode *) (HNODE)) @@ -1001,6 +1002,9 @@ extern void cpp_assert (cpp_reader *, const char *); extern void cpp_undef (cpp_reader *, const char *); extern void cpp_unassert (cpp_reader *, const char *); +/* Mark a node as a lazily defined macro. */ +extern void cpp_define_lazily (cpp_reader *, cpp_hashnode *node, unsigned N); + /* Undefine all macros and assertions. */ extern void cpp_undef_all (cpp_reader *); diff --git a/libcpp/macro.c b/libcpp/macro.c index 25f4a36..369a461 100644 --- a/libcpp/macro.c +++ b/libcpp/macro.c @@ -1273,15 +1273,6 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode *node, function where set this flag to FALSE. */ pfile->about_to_expand_macro_p = true; - if ((node->flags & NODE_BUILTIN) && !(node->flags & NODE_USED)) - { - node->flags |= NODE_USED; - if ((!pfile->cb.user_builtin_macro - || !pfile->cb.user_builtin_macro (pfile, node)) - && pfile->cb.used_define) - pfile->cb.used_define (pfile, pfile->directive_line, node); - } - if (cpp_user_macro_p (node)) { cpp_macro *macro = node->value.macro; @@ -1328,13 +1319,9 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode *node, /* Disable the macro within its expansion. */ node->flags |= NODE_DISABLED; - if (!(node->flags & NODE_USED)) - { - node->flags |= NODE_USED; - if (pfile->cb.used_define) - pfile->cb.used_define (pfile, pfile->directive_line, node); - } - + /* Laziness can only affect the expansion tokens of the macro, + not its fun-likeness or parameters. */ + _cpp_maybe_notify_macro_use (pfile, node); if (pfile->cb.used) pfile->cb.used (pfile, location, node); @@ -2993,7 +2980,6 @@ static bool warn_of_redefinition (cpp_reader *pfile, cpp_hashnode *node, const cpp_macro *macro2) { - const cpp_macro *macro1; unsigned int i; /* Some redefinitions need to be warned about regardless. */ @@ -3002,9 +2988,7 @@ warn_of_redefinition (cpp_reader *pfile, cpp_hashnode *node, /* Suppress warnings for builtins that lack the NODE_WARN flag, unless Wbuiltin-macro-redefined. */ - if (node->flags & NODE_BUILTIN - && (!pfile->cb.user_builtin_macro - || !pfile->cb.user_builtin_macro (pfile, node))) + if (cpp_builtin_macro_p (node)) return CPP_OPTION (pfile, warn_builtin_macro_redefined); /* Redefinitions of conditional (context-sensitive) macros, on @@ -3012,9 +2996,17 @@ warn_of_redefinition (cpp_reader *pfile, cpp_hashnode *node, if (node->flags & NODE_CONDITIONAL) return false; + cpp_macro *macro1 = node->value.macro; + if (macro1->lazy) + { + /* We don't want to mark MACRO as used, but do need to finalize + its laziness. */ + pfile->cb.user_lazy_macro (pfile, macro1, macro1->lazy - 1); + macro1->lazy = 0; + } + /* Redefinition of a macro is allowed if and only if the old and new definitions are the same. (6.10.3 paragraph 2). */ - macro1 = node->value.macro; /* Don't check count here as it can be different in valid traditional redefinitions with just whitespace differences. */ @@ -3481,6 +3473,7 @@ _cpp_new_macro (cpp_reader *pfile, cpp_macro_kind kind, void *placement) macro->line = pfile->directive_line; macro->params = 0; + macro->lazy = 0; macro->paramc = 0; macro->variadic = 0; macro->used = !CPP_OPTION (pfile, warn_unused_macros); @@ -3553,6 +3546,16 @@ _cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node) return true; } +extern void +cpp_define_lazily (cpp_reader *pfile, cpp_hashnode *node, unsigned num) +{ + cpp_macro *macro = node->value.macro; + + gcc_checking_assert (pfile->cb.user_lazy_macro && macro && num < 255); + + macro->lazy = num + 1; +} + /* Notify the use of NODE in a macro-aware context (i.e. expanding it, or testing its existance). Also applies any lazy definition. */ @@ -3563,9 +3566,15 @@ _cpp_notify_macro_use (cpp_reader *pfile, cpp_hashnode *node) switch (node->type) { case NT_MACRO: - if ((node->flags & NODE_BUILTIN) - && pfile->cb.user_builtin_macro) - pfile->cb.user_builtin_macro (pfile, node); + if (!(node->flags & NODE_BUILTIN)) + { + cpp_macro *macro = node->value.macro; + if (macro->lazy) + { + pfile->cb.user_lazy_macro (pfile, macro, macro->lazy - 1); + macro->lazy = 0; + } + } if (pfile->cb.used_define) pfile->cb.used_define (pfile, pfile->directive_line, node); @@ -3641,23 +3650,12 @@ const unsigned char * cpp_macro_definition (cpp_reader *pfile, cpp_hashnode *node) { unsigned int i, len; - const cpp_macro *macro; unsigned char *buffer; - if (node->type != NT_MACRO || (node->flags & NODE_BUILTIN)) - { - if (node->type != NT_MACRO - || !pfile->cb.user_builtin_macro - || !pfile->cb.user_builtin_macro (pfile, node)) - { - cpp_error (pfile, CPP_DL_ICE, - "invalid hash type %d in cpp_macro_definition", - node->type); - return 0; - } - } + gcc_checking_assert (cpp_user_macro_p (node)); + + const cpp_macro *macro = node->value.macro; - macro = node->value.macro; /* Calculate length. */ len = NODE_LEN (node) * 10 + 2; /* ' ' and NUL. */ if (macro->fun_like) diff --git a/libcpp/pch.c b/libcpp/pch.c index 997c4da..47b99c1 100644 --- a/libcpp/pch.c +++ b/libcpp/pch.c @@ -59,9 +59,7 @@ write_macdef (cpp_reader *pfile, cpp_hashnode *hn, void *file_p) /* FALLTHRU */ case NT_MACRO: - if ((hn->flags & NODE_BUILTIN) - && (!pfile->cb.user_builtin_macro - || !pfile->cb.user_builtin_macro (pfile, hn))) + if (hn->flags & NODE_BUILTIN) return 1; { @@ -760,11 +758,6 @@ save_macros (cpp_reader *r, cpp_hashnode *h, void *data_p) { struct save_macro_data *data = (struct save_macro_data *)data_p; - if ((h->flags & NODE_BUILTIN) - && h->type == NT_MACRO - && r->cb.user_builtin_macro) - r->cb.user_builtin_macro (r, h); - if (h->type != NT_VOID && (h->flags & NODE_BUILTIN) == 0) { -- cgit v1.1 From 3fb558b154f795983ae6a9dd6478e18a2c846584 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Mon, 20 Aug 2018 12:39:36 +0000 Subject: [PATCH] #assert becomes macro-like https://gcc.gnu.org/ml/gcc-patches/2018-08/msg01140.html libcpp/ * include/cpp-id-data.h (struct answer): Delete. * include/cpplib.h (struct answer): Don't forward-declare. (enum cpp_macro_kind): Add cmk_assert. (struct cpp_macro): Union parms and next assert chain. (union _cpp_hashnode_value): 'answer' field is cpp_macro. * directives.c (parse_answer): Convert to use cpp_macro. Return true on success. (parse_assertion, find_answer, _cpp_test_assertion, cpp_do_assert) (cpp_do_unassert): Convert to use cpp_macro. * macro.c (warn_of_redefinition, _cpp_new_macro) (check_trad_stringification, cpp_macro_definition): Adjust macro parm access. * traditional.c (_cpp_replacement_text_len) (_cpp_copy_replacement_text, _cpp_create_trad_definition): Likewise. gcc/c-family/ * c-ada-spec.c (macro_length, dump_ada_macros): Adjust macro parm access. From-SVN: r263658 --- libcpp/ChangeLog | 17 +++++ libcpp/directives.c | 170 +++++++++++++++++++------------------------ libcpp/include/cpp-id-data.h | 7 -- libcpp/include/cpplib.h | 29 +++++--- libcpp/macro.c | 12 +-- libcpp/traditional.c | 6 +- 6 files changed, 120 insertions(+), 121 deletions(-) (limited to 'libcpp') diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index 994d424..2e347db 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,3 +1,20 @@ +2018-08-20 Nathan Sidwell + + * include/cpp-id-data.h (struct answer): Delete. + * include/cpplib.h (struct answer): Don't forward-declare. + (enum cpp_macro_kind): Add cmk_assert. + (struct cpp_macro): Union parms and next assert chain. + (union _cpp_hashnode_value): 'answer' field is cpp_macro. + * directives.c (parse_answer): Convert to use cpp_macro. Return + true on success. + (parse_assertion, find_answer, _cpp_test_assertion, cpp_do_assert) + (cpp_do_unassert): Convert to use cpp_macro. + * macro.c (warn_of_redefinition, _cpp_new_macro) + (check_trad_stringification, cpp_macro_definition): Adjust macro + parm access. + * traditional.c (_cpp_replacement_text_len) + (_cpp_copy_replacement_text, _cpp_create_trad_definition): Likewise. + 2018-08-17 Nathan Sidwell * include/cpplib.h (struct cpp_callbacks): Replace diff --git a/libcpp/directives.c b/libcpp/directives.c index 6ddfce6..e75462f 100644 --- a/libcpp/directives.c +++ b/libcpp/directives.c @@ -124,9 +124,9 @@ static const cpp_token *get_token_no_padding (cpp_reader *); static const cpp_token *get__Pragma_string (cpp_reader *); static void destringize_and_run (cpp_reader *, const cpp_string *, source_location); -static int parse_answer (cpp_reader *, struct answer **, int, source_location); -static cpp_hashnode *parse_assertion (cpp_reader *, struct answer **, int); -static struct answer ** find_answer (cpp_hashnode *, const struct answer *); +static bool parse_answer (cpp_reader *, int, source_location, cpp_macro **); +static cpp_hashnode *parse_assertion (cpp_reader *, int, cpp_macro **); +static cpp_macro **find_answer (cpp_hashnode *, const cpp_macro *); static void handle_assertion (cpp_reader *, const char *, int); static void do_pragma_push_macro (cpp_reader *); static void do_pragma_pop_macro (cpp_reader *); @@ -2149,17 +2149,13 @@ push_conditional (cpp_reader *pfile, int skip, int type, storage, i.e. the #assert case. Returns 0 on success, and sets ANSWERP to point to the answer. PRED_LOC is the location of the predicate. */ -static int -parse_answer (cpp_reader *pfile, struct answer **answerp, int type, - source_location pred_loc) +static bool +parse_answer (cpp_reader *pfile, int type, source_location pred_loc, + cpp_macro **answer_ptr) { - const cpp_token *paren; - struct answer *answer; - unsigned int acount; - /* In a conditional, it is legal to not have an open paren. We should save the following token in this case. */ - paren = cpp_get_token (pfile); + const cpp_token *paren = cpp_get_token (pfile); /* If not a paren, see if we're OK. */ if (paren->type != CPP_OPEN_PAREN) @@ -2169,23 +2165,26 @@ parse_answer (cpp_reader *pfile, struct answer **answerp, int type, if (type == T_IF) { _cpp_backup_tokens (pfile, 1); - return 0; + return true; } /* #unassert with no answer is valid - it removes all answers. */ if (type == T_UNASSERT && paren->type == CPP_EOF) - return 0; + return true; cpp_error_with_line (pfile, CPP_DL_ERROR, pred_loc, 0, "missing '(' after predicate"); - return 1; + return false; } - for (acount = 0;; acount++) + cpp_macro *answer = _cpp_new_macro (pfile, cmk_assert, + _cpp_reserve_room (pfile, 0, + sizeof (cpp_macro))); + answer->parm.next = NULL; + unsigned count = 0; + for (;;) { - size_t room_needed; const cpp_token *token = cpp_get_token (pfile); - cpp_token *dest; if (token->type == CPP_CLOSE_PAREN) break; @@ -2193,57 +2192,51 @@ parse_answer (cpp_reader *pfile, struct answer **answerp, int type, if (token->type == CPP_EOF) { cpp_error (pfile, CPP_DL_ERROR, "missing ')' to complete answer"); - return 1; + return false; } - /* struct answer includes the space for one token. */ - room_needed = (sizeof (struct answer) + acount * sizeof (cpp_token)); - - if (BUFF_ROOM (pfile->a_buff) < room_needed) - _cpp_extend_buff (pfile, &pfile->a_buff, sizeof (struct answer)); - - dest = &((struct answer *) BUFF_FRONT (pfile->a_buff))->first[acount]; - *dest = *token; - - /* Drop whitespace at start, for answer equivalence purposes. */ - if (acount == 0) - dest->flags &= ~PREV_WHITE; + answer = (cpp_macro *)_cpp_reserve_room + (pfile, sizeof (cpp_macro) + count * sizeof (cpp_token), + sizeof (cpp_token)); + answer->exp.tokens[count++] = *token; } - if (acount == 0) + if (!count) { cpp_error (pfile, CPP_DL_ERROR, "predicate's answer is empty"); - return 1; + return false; } - answer = (struct answer *) BUFF_FRONT (pfile->a_buff); - answer->count = acount; - answer->next = NULL; - *answerp = answer; + /* Drop whitespace at start, for answer equivalence purposes. */ + answer->exp.tokens[0].flags &= ~PREV_WHITE; - return 0; + answer->count = count; + *answer_ptr = answer; + + return true; } /* Parses an assertion directive of type TYPE, returning a pointer to the hash node of the predicate, or 0 on error. If an answer was - supplied, it is placed in ANSWERP, otherwise it is set to 0. */ + supplied, it is placed in EXP_PTR & EXP_COUNT, which is otherwise + set to 0. */ static cpp_hashnode * -parse_assertion (cpp_reader *pfile, struct answer **answerp, int type) +parse_assertion (cpp_reader *pfile, int type, cpp_macro **answer_ptr) { cpp_hashnode *result = 0; - const cpp_token *predicate; /* We don't expand predicates or answers. */ pfile->state.prevent_expansion++; - *answerp = 0; - predicate = cpp_get_token (pfile); + *answer_ptr = NULL; + + const cpp_token *predicate = cpp_get_token (pfile); if (predicate->type == CPP_EOF) cpp_error (pfile, CPP_DL_ERROR, "assertion without predicate"); else if (predicate->type != CPP_NAME) cpp_error_with_line (pfile, CPP_DL_ERROR, predicate->src_loc, 0, "predicate must be an identifier"); - else if (parse_answer (pfile, answerp, type, predicate->src_loc) == 0) + else if (parse_answer (pfile, type, predicate->src_loc, answer_ptr)) { unsigned int len = NODE_LEN (predicate->val.node.node); unsigned char *sym = (unsigned char *) alloca (len + 1); @@ -2255,25 +2248,27 @@ parse_assertion (cpp_reader *pfile, struct answer **answerp, int type) } pfile->state.prevent_expansion--; + return result; } /* Returns a pointer to the pointer to CANDIDATE in the answer chain, or a pointer to NULL if the answer is not in the chain. */ -static struct answer ** -find_answer (cpp_hashnode *node, const struct answer *candidate) +static cpp_macro ** +find_answer (cpp_hashnode *node, const cpp_macro *candidate) { unsigned int i; - struct answer **result; + cpp_macro **result = NULL; - for (result = &node->value.answers; *result; result = &(*result)->next) + for (result = &node->value.answers; *result; result = &(*result)->parm.next) { - struct answer *answer = *result; + cpp_macro *answer = *result; if (answer->count == candidate->count) { for (i = 0; i < answer->count; i++) - if (! _cpp_equiv_tokens (&answer->first[i], &candidate->first[i])) + if (!_cpp_equiv_tokens (&answer->exp.tokens[i], + &candidate->exp.tokens[i])) break; if (i == answer->count) @@ -2290,18 +2285,18 @@ find_answer (cpp_hashnode *node, const struct answer *candidate) int _cpp_test_assertion (cpp_reader *pfile, unsigned int *value) { - struct answer *answer; - cpp_hashnode *node; - - node = parse_assertion (pfile, &answer, T_IF); + cpp_macro *answer; + cpp_hashnode *node = parse_assertion (pfile, T_IF, &answer); /* For recovery, an erroneous assertion expression is handled as a failing assertion. */ *value = 0; if (node) - *value = (node->type == NT_ASSERTION && - (answer == 0 || *find_answer (node, answer) != 0)); + { + if (node->type == NT_ASSERTION) + *value = !answer || *find_answer (node, answer); + } else if (pfile->cur_token[-1].type == CPP_EOF) _cpp_backup_tokens (pfile, 1); @@ -2313,43 +2308,31 @@ _cpp_test_assertion (cpp_reader *pfile, unsigned int *value) static void do_assert (cpp_reader *pfile) { - struct answer *new_answer; - cpp_hashnode *node; + cpp_macro *answer; + cpp_hashnode *node = parse_assertion (pfile, T_ASSERT, &answer); - node = parse_assertion (pfile, &new_answer, T_ASSERT); if (node) { - size_t answer_size; - /* Place the new answer in the answer list. First check there is not a duplicate. */ - new_answer->next = 0; - if (node->type == NT_ASSERTION) + if (node->type == NT_ASSERTION && *find_answer (node, answer)) { - if (*find_answer (node, new_answer)) - { - cpp_error (pfile, CPP_DL_WARNING, "\"%s\" re-asserted", - NODE_NAME (node) + 1); - return; - } - new_answer->next = node->value.answers; + cpp_error (pfile, CPP_DL_WARNING, "\"%s\" re-asserted", + NODE_NAME (node) + 1); + return; } - answer_size = sizeof (struct answer) + ((new_answer->count - 1) - * sizeof (cpp_token)); - /* Commit or allocate storage for the object. */ - if (pfile->hash_table->alloc_subobject) - { - struct answer *temp_answer = new_answer; - new_answer = (struct answer *) pfile->hash_table->alloc_subobject - (answer_size); - memcpy (new_answer, temp_answer, answer_size); - } - else - BUFF_FRONT (pfile->a_buff) += answer_size; + /* Commit or allocate storage for the answer. */ + answer = (cpp_macro *)_cpp_commit_buff + (pfile, sizeof (cpp_macro) - sizeof (cpp_token) + + sizeof (cpp_token) * answer->count); + + if (node->type == NT_ASSERTION) + answer->parm.next = node->value.answers; node->type = NT_ASSERTION; - node->value.answers = new_answer; + node->value.answers = answer; + check_eol (pfile, false); } } @@ -2358,25 +2341,24 @@ do_assert (cpp_reader *pfile) static void do_unassert (cpp_reader *pfile) { - cpp_hashnode *node; - struct answer *answer; + cpp_macro *answer; + cpp_hashnode *node = parse_assertion (pfile, T_UNASSERT, &answer); - node = parse_assertion (pfile, &answer, T_UNASSERT); /* It isn't an error to #unassert something that isn't asserted. */ if (node && node->type == NT_ASSERTION) { if (answer) { - struct answer **p = find_answer (node, answer), *temp; - - /* Remove the answer from the list. */ - temp = *p; - if (temp) - *p = temp->next; + cpp_macro **p = find_answer (node, answer); - /* Did we free the last answer? */ - if (node->value.answers == 0) - node->type = NT_VOID; + /* Remove the assert from the list. */ + if (cpp_macro *temp = *p) + { + *p = temp->parm.next; + /* Did we free the last answer? */ + if (!*p) + node->type = NT_VOID; + } check_eol (pfile, false); } diff --git a/libcpp/include/cpp-id-data.h b/libcpp/include/cpp-id-data.h index fb073fa..909f828 100644 --- a/libcpp/include/cpp-id-data.h +++ b/libcpp/include/cpp-id-data.h @@ -17,10 +17,3 @@ along with this program; see the file COPYING3. If not see #include "cpplib.h" -/* Chained list of answers to an assertion. */ -struct GTY(()) answer { - struct answer *next; - unsigned int count; - cpp_token GTY ((length ("%h.count"))) first[1]; -}; - diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h index e0be2dc..d446fb1 100644 --- a/libcpp/include/cpplib.h +++ b/libcpp/include/cpplib.h @@ -36,7 +36,6 @@ typedef struct cpp_macro cpp_macro; typedef struct cpp_callbacks cpp_callbacks; typedef struct cpp_dir cpp_dir; -struct answer; struct _cpp_file; /* The first three groups, apart from '=', can appear in preprocessor @@ -674,25 +673,33 @@ struct cpp_dir /* The kind of the cpp_macro. */ enum cpp_macro_kind { cmk_macro, /* An ISO macro (token expansion). */ + cmk_assert, /* An assertion. */ cmk_traditional, /* A traditional macro (text expansion). */ }; /* Each macro definition is recorded in a cpp_macro structure. Variadic macros cannot occur with traditional cpp. */ struct GTY(()) cpp_macro { - /* Parameters, if any. If parameter names use extended identifiers, - the original spelling of those identifiers, not the canonical - UTF-8 spelling, goes here. */ - 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"), - length ("%h.paramc"))) - params; + union cpp_parm_u + { + /* Parameters, if any. If parameter names use extended identifiers, + the original spelling of those identifiers, not the canonical + UTF-8 spelling, goes here. */ + cpp_hashnode ** GTY ((tag ("false"), + 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"), + length ("%1.paramc"))) params; + + /* If this is an assertion, the next one in the chain. */ + cpp_macro *GTY ((tag ("true"))) next; + } GTY ((desc ("%1.kind == cmk_assert"))) parm; /* Definition line number. */ source_location line; - /* Number of tokens in expansion, or bytes for traditional macros. */ + /* Number of tokens in body, or bytes for traditional macros. */ + /* Do we really need 2^32-1 range here? */ unsigned int count; /* Number of parameters. */ @@ -814,7 +821,7 @@ union GTY(()) _cpp_hashnode_value { /* If a macro. */ cpp_macro * GTY((tag ("NTV_MACRO"))) macro; /* Answers to an assertion. */ - struct answer * GTY ((tag ("NTV_ANSWER"))) answers; + cpp_macro * GTY ((tag ("NTV_ANSWER"))) answers; /* Code for a builtin macro. */ enum cpp_builtin_type GTY ((tag ("NTV_BUILTIN"))) builtin; /* Macro argument index. */ diff --git a/libcpp/macro.c b/libcpp/macro.c index 369a461..0f9e25d 100644 --- a/libcpp/macro.c +++ b/libcpp/macro.c @@ -3017,7 +3017,7 @@ warn_of_redefinition (cpp_reader *pfile, cpp_hashnode *node, /* Check parameter spellings. */ for (i = 0; i < macro1->paramc; i++) - if (macro1->params[i] != macro2->params[i]) + if (macro1->parm.params[i] != macro2->parm.params[i]) return true; /* Check the replacement text or tokens. */ @@ -3326,7 +3326,7 @@ create_iso_definition (cpp_reader *pfile) { macro->variadic = varadic; macro->paramc = nparms; - macro->params = params; + macro->parm.params = params; macro->fun_like = true; } else @@ -3472,7 +3472,7 @@ _cpp_new_macro (cpp_reader *pfile, cpp_macro_kind kind, void *placement) cpp_macro *macro = (cpp_macro *) placement; macro->line = pfile->directive_line; - macro->params = 0; + macro->parm.params = 0; macro->lazy = 0; macro->paramc = 0; macro->variadic = 0; @@ -3618,7 +3618,7 @@ check_trad_stringification (cpp_reader *pfile, const cpp_macro *macro, identifier inside the string matches one of them. */ for (i = 0; i < macro->paramc; i++) { - const cpp_hashnode *node = macro->params[i]; + const cpp_hashnode *node = macro->parm.params[i]; if (NODE_LEN (node) == len && !memcmp (p, NODE_NAME (node), len)) @@ -3663,7 +3663,7 @@ cpp_macro_definition (cpp_reader *pfile, cpp_hashnode *node) len += 4; /* "()" plus possible final ".." of named varargs (we have + 1 below). */ for (i = 0; i < macro->paramc; i++) - len += NODE_LEN (macro->params[i]) + 1; /* "," */ + len += NODE_LEN (macro->parm.params[i]) + 1; /* "," */ } /* This should match below where we fill in the buffer. */ @@ -3707,7 +3707,7 @@ cpp_macro_definition (cpp_reader *pfile, cpp_hashnode *node) *buffer++ = '('; for (i = 0; i < macro->paramc; i++) { - cpp_hashnode *param = macro->params[i]; + cpp_hashnode *param = macro->parm.params[i]; if (param != pfile->spec_nodes.n__VA_ARGS__) { diff --git a/libcpp/traditional.c b/libcpp/traditional.c index 3c3b8ac..0c42b25 100644 --- a/libcpp/traditional.c +++ b/libcpp/traditional.c @@ -918,7 +918,7 @@ _cpp_replacement_text_len (const cpp_macro *macro) len += b->text_len; if (b->arg_index == 0) break; - len += NODE_LEN (macro->params[b->arg_index - 1]); + len += NODE_LEN (macro->parm.params[b->arg_index - 1]); exp += BLOCK_LEN (b->text_len); } } @@ -947,7 +947,7 @@ _cpp_copy_replacement_text (const cpp_macro *macro, uchar *dest) dest += b->text_len; if (b->arg_index == 0) break; - param = macro->params[b->arg_index - 1]; + param = macro->parm.params[b->arg_index - 1]; memcpy (dest, NODE_NAME (param), NODE_LEN (param)); dest += NODE_LEN (param); exp += BLOCK_LEN (b->text_len); @@ -1210,7 +1210,7 @@ _cpp_create_trad_definition (cpp_reader *pfile) { macro = _cpp_new_macro (pfile, cmk_traditional, _cpp_aligned_alloc (pfile, sizeof (cpp_macro))); - macro->params = params; + macro->parm.params = params; macro->paramc = nparms; macro->fun_like = fun_like != 0; } -- cgit v1.1 From abcd1775e067600918da69330f8ff3f1f6734b4c Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Mon, 20 Aug 2018 14:20:04 +0000 Subject: [PATCH] Kill cpp-id-data.h https://gcc.gnu.org/ml/gcc-patches/2018-08/msg01149.html libcpp/ * Makefile.in (TAGS_SOURCES): Remove cpp-id-data.h. * include/cpp-id-data.h: Delete. * internal.h: Include cpplib.h not cpp-id-data.h. gcc/ * Makefile.in (CPP_ID_DATA_H): Delete. (CPP_INTERNAL_H): Don't add it. (GTFILES): Replace CPP_ID_DATA_H with CPPLIB_H. * gengtype.c (open_base_files): Replace cpp-id-data.h with cpplib.h From-SVN: r263663 --- libcpp/ChangeLog | 4 ++++ libcpp/Makefile.in | 5 ++--- libcpp/include/cpp-id-data.h | 19 ------------------- libcpp/internal.h | 2 +- 4 files changed, 7 insertions(+), 23 deletions(-) delete mode 100644 libcpp/include/cpp-id-data.h (limited to 'libcpp') diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index 2e347db..19d89b1 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,5 +1,9 @@ 2018-08-20 Nathan Sidwell + * Makefile.in (TAGS_SOURCES): Remove cpp-id-data.h. + * include/cpp-id-data.h: Delete. + * internal.h: Include cpplib.h not cpp-id-data.h. + * include/cpp-id-data.h (struct answer): Delete. * include/cpplib.h (struct answer): Don't forward-declare. (enum cpp_macro_kind): Add cmk_assert. diff --git a/libcpp/Makefile.in b/libcpp/Makefile.in index bfd6069..835c835 100644 --- a/libcpp/Makefile.in +++ b/libcpp/Makefile.in @@ -261,9 +261,8 @@ po/$(PACKAGE).pot: $(libcpp_a_SOURCES) sed 's:$(srcdir)/::g' po/$(PACKAGE).pot rm po/$(PACKAGE).pot.tmp -TAGS_SOURCES = $(libcpp_a_SOURCES) internal.h ucnid.h \ - include/line-map.h include/symtab.h include/cpp-id-data.h \ - include/cpplib.h include/mkdeps.h system.h +TAGS_SOURCES = $(libcpp_a_SOURCES) internal.h system.h ucnid.h \ + include/cpplib.h include/line-map.h include/mkdeps.h include/symtab.h TAGS: $(TAGS_SOURCES) cd $(srcdir) && etags $(TAGS_SOURCES) diff --git a/libcpp/include/cpp-id-data.h b/libcpp/include/cpp-id-data.h deleted file mode 100644 index 909f828..0000000 --- a/libcpp/include/cpp-id-data.h +++ /dev/null @@ -1,19 +0,0 @@ -/* Structures that hang off cpp_identifier, for PCH. - Copyright (C) 1986-2018 Free Software Foundation, Inc. - -This program is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 3, or (at your option) any -later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; see the file COPYING3. If not see -. */ - -#include "cpplib.h" - diff --git a/libcpp/internal.h b/libcpp/internal.h index e40b20f..59f830c 100644 --- a/libcpp/internal.h +++ b/libcpp/internal.h @@ -23,7 +23,7 @@ along with this program; see the file COPYING3. If not see #define LIBCPP_INTERNAL_H #include "symtab.h" -#include "cpp-id-data.h" +#include "cpplib.h" #if HAVE_ICONV #include -- cgit v1.1 From 7692e253ee0bdab40fb896991f9208112ebfff61 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Mon, 20 Aug 2018 15:28:15 +0000 Subject: [CPP PATCH] Fix warning & other cleanups. https://gcc.gnu.org/ml/gcc-patches/2018-08/msg01162.html * directives.c (do_undef): Use cpp_macro_p & cpp_builtin_macro_p. * include/cpplib.h (enum cpp_macro_kind): Remove trailing comma. (cpp_fun_like_macro_p): Make inline, define. * macro.c (cpp_define_lazily): Use UCHAR_MAX. (cpp_fun_like_macro_p): Delete. From-SVN: r263666 --- libcpp/ChangeLog | 6 ++++++ libcpp/directives.c | 4 ++-- libcpp/include/cpplib.h | 7 +++++-- libcpp/macro.c | 11 +---------- 4 files changed, 14 insertions(+), 14 deletions(-) (limited to 'libcpp') diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index 19d89b1..01cc250 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,5 +1,11 @@ 2018-08-20 Nathan Sidwell + * directives.c (do_undef): Use cpp_macro_p & cpp_builtin_macro_p. + * include/cpplib.h (enum cpp_macro_kind): Remove trailing comma. + (cpp_fun_like_macro_p): Make inline, define. + * macro.c (cpp_define_lazily): Use UCHAR_MAX. + (cpp_fun_like_macro_p): Delete. + * Makefile.in (TAGS_SOURCES): Remove cpp-id-data.h. * include/cpp-id-data.h: Delete. * internal.h: Include cpplib.h not cpp-id-data.h. diff --git a/libcpp/directives.c b/libcpp/directives.c index e75462f..f04ed7c 100644 --- a/libcpp/directives.c +++ b/libcpp/directives.c @@ -665,12 +665,12 @@ do_undef (cpp_reader *pfile) /* 6.10.3.5 paragraph 2: [#undef] is ignored if the specified identifier is not currently defined as a macro name. */ - if (node->type == NT_MACRO) + if (cpp_macro_p (node)) { if (node->flags & NODE_WARN) cpp_error (pfile, CPP_DL_WARNING, "undefining \"%s\"", NODE_NAME (node)); - else if ((node->flags & NODE_BUILTIN) + else if (cpp_builtin_macro_p (node) && CPP_OPTION (pfile, warn_builtin_macro_redefined)) cpp_warning_with_line (pfile, CPP_W_BUILTIN_MACRO_REDEFINED, pfile->directive_line, 0, diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h index d446fb1..b784e0f 100644 --- a/libcpp/include/cpplib.h +++ b/libcpp/include/cpplib.h @@ -674,7 +674,7 @@ struct cpp_dir enum cpp_macro_kind { cmk_macro, /* An ISO macro (token expansion). */ cmk_assert, /* An assertion. */ - cmk_traditional, /* A traditional macro (text expansion). */ + cmk_traditional /* A traditional macro (text expansion). */ }; /* Each macro definition is recorded in a cpp_macro structure. @@ -972,7 +972,10 @@ inline bool cpp_macro_p (const cpp_hashnode *node) return node->type == NT_MACRO; } /* Returns true if NODE is a function-like user macro. */ -extern bool cpp_fun_like_macro_p (cpp_hashnode *node); +inline bool cpp_fun_like_macro_p (cpp_hashnode *node) +{ + return cpp_user_macro_p (node) && node->value.macro->fun_like; +} extern const unsigned char *cpp_macro_definition (cpp_reader *, cpp_hashnode *); diff --git a/libcpp/macro.c b/libcpp/macro.c index 0f9e25d..123f63d 100644 --- a/libcpp/macro.c +++ b/libcpp/macro.c @@ -3551,7 +3551,7 @@ cpp_define_lazily (cpp_reader *pfile, cpp_hashnode *node, unsigned num) { cpp_macro *macro = node->value.macro; - gcc_checking_assert (pfile->cb.user_lazy_macro && macro && num < 255); + gcc_checking_assert (pfile->cb.user_lazy_macro && macro && num < UCHAR_MAX); macro->lazy = num + 1; } @@ -3632,15 +3632,6 @@ check_trad_stringification (cpp_reader *pfile, const cpp_macro *macro, } } -/* Returns true of NODE is a function-like macro. */ -bool -cpp_fun_like_macro_p (cpp_hashnode *node) -{ - return (node->type == NT_MACRO - && (node->flags & (NODE_BUILTIN | NODE_MACRO_ARG)) == 0 - && node->value.macro->fun_like); -} - /* Returns the name, arguments and expansion of a macro, in a format suitable to be read back in again, and therefore also for DWARF 2 debugging info. e.g. "PASTE(X, Y) X ## Y", or "MACNAME EXPANSION". -- cgit v1.1 From a570d97f5b8612ad2756333e5f21098be64057df Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Mon, 20 Aug 2018 16:32:29 +0000 Subject: [CPP PATCH] node type https://gcc.gnu.org/ml/gcc-patches/2018-08/msg01164.html * include/cpplib.h (NODE_BUILTIN, NODE_MACRO_ARG): Delete. Renumber others. (enum node_type): Replace NT_MACRO with NT_USER_MACRO, NT_BUILTIN_MACRO, NT_MACRO_ARG. Delete NT_ASSERTION. (NTV_MACRO, NTV_ANSWER, NTV_BUILTIN, NTV_ARGUMENT, NTV_NONE): Delete. (CPP_HASHNODE_VALUE_IDX): Delete. (union _cpp_hashnode_value): GTY tag from enum node_type directly. (struct cpp_hashnode): Adjust GTY desc for value field. (cpp_user_macro_p, cpp_builtin_macro_p, cpp_macro_p): Adjust. * directives.c (undefine_macros): Clear value.anwers, adjust flag clearing. (_cpp_test_assertion): No need to check NT_ASSERTION. (do_assert, do_unassert): Likewise. * init.c (cpp_init_special_builtins): Set type not flags. * macro.c (struct macro_arg_saved_data): Add type field. (cpp_get_token_1): Check type not NT_VOID. (_cpp_free_definition): Adjust flag clearing. Nullify value.answers. (_cpp_save_parameter, _cpp_unsave_parameters): Save and restore type. (lex_expansion_token): Check type not flags. (_cpp_create_definition): Set type to NT_USER_MACRO. (_cpp_notify_macro_use): Adjust type checking. * pch.c (write_macdef, count_defs, write_defs, cpp_valid_state) (save_macros): Adjust node type/flag handling. * traditional.c (_cpp_scan_out_logical_line): Check type not flags. From-SVN: r263667 --- libcpp/ChangeLog | 28 ++++++++++++ libcpp/directives.c | 29 +++++------- libcpp/include/cpplib.h | 71 +++++++++++------------------- libcpp/init.c | 3 +- libcpp/macro.c | 44 ++++++++++--------- libcpp/pch.c | 114 ++++++++++++++++++++---------------------------- libcpp/traditional.c | 2 +- 7 files changed, 139 insertions(+), 152 deletions(-) (limited to 'libcpp') diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index 01cc250..8998c0d 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,5 +1,33 @@ 2018-08-20 Nathan Sidwell + * include/cpplib.h (NODE_BUILTIN, NODE_MACRO_ARG): Delete. + Renumber others. + (enum node_type): Replace NT_MACRO with NT_USER_MACRO, + NT_BUILTIN_MACRO, NT_MACRO_ARG. Delete NT_ASSERTION. + (NTV_MACRO, NTV_ANSWER, NTV_BUILTIN, NTV_ARGUMENT, NTV_NONE): + Delete. + (CPP_HASHNODE_VALUE_IDX): Delete. + (union _cpp_hashnode_value): GTY tag from enum node_type directly. + (struct cpp_hashnode): Adjust GTY desc for value field. + (cpp_user_macro_p, cpp_builtin_macro_p, cpp_macro_p): Adjust. + * directives.c (undefine_macros): Clear value.anwers, adjust flag + clearing. + (_cpp_test_assertion): No need to check NT_ASSERTION. + (do_assert, do_unassert): Likewise. + * init.c (cpp_init_special_builtins): Set type not flags. + * macro.c (struct macro_arg_saved_data): Add type field. + (cpp_get_token_1): Check type not NT_VOID. + (_cpp_free_definition): Adjust flag clearing. Nullify + value.answers. + (_cpp_save_parameter, _cpp_unsave_parameters): Save and restore + type. + (lex_expansion_token): Check type not flags. + (_cpp_create_definition): Set type to NT_USER_MACRO. + (_cpp_notify_macro_use): Adjust type checking. + * pch.c (write_macdef, count_defs, write_defs, cpp_valid_state) + (save_macros): Adjust node type/flag handling. + * traditional.c (_cpp_scan_out_logical_line): Check type not flags. + * directives.c (do_undef): Use cpp_macro_p & cpp_builtin_macro_p. * include/cpplib.h (enum cpp_macro_kind): Remove trailing comma. (cpp_fun_like_macro_p): Make inline, define. diff --git a/libcpp/directives.c b/libcpp/directives.c index f04ed7c..f7c460d 100644 --- a/libcpp/directives.c +++ b/libcpp/directives.c @@ -695,7 +695,8 @@ undefine_macros (cpp_reader *pfile ATTRIBUTE_UNUSED, cpp_hashnode *h, /* Body of _cpp_free_definition inlined here for speed. Macros and assertions no longer have anything to free. */ h->type = NT_VOID; - h->flags &= ~(NODE_POISONED|NODE_BUILTIN|NODE_DISABLED|NODE_USED); + h->value.answers = NULL; + h->flags &= ~(NODE_POISONED|NODE_DISABLED|NODE_USED); return 1; } @@ -2217,9 +2218,10 @@ parse_answer (cpp_reader *pfile, int type, source_location pred_loc, } /* Parses an assertion directive of type TYPE, returning a pointer to - the hash node of the predicate, or 0 on error. If an answer was - supplied, it is placed in EXP_PTR & EXP_COUNT, which is otherwise - set to 0. */ + the hash node of the predicate, or 0 on error. The node is + guaranteed to be disjoint from the macro namespace, so can only + have type 'NT_VOID'. If an answer was supplied, it is placed in + *ANSWER_PTR, which is otherwise set to 0. */ static cpp_hashnode * parse_assertion (cpp_reader *pfile, int type, cpp_macro **answer_ptr) { @@ -2294,7 +2296,7 @@ _cpp_test_assertion (cpp_reader *pfile, unsigned int *value) if (node) { - if (node->type == NT_ASSERTION) + if (node->value.answers) *value = !answer || *find_answer (node, answer); } else if (pfile->cur_token[-1].type == CPP_EOF) @@ -2315,7 +2317,7 @@ do_assert (cpp_reader *pfile) { /* Place the new answer in the answer list. First check there is not a duplicate. */ - if (node->type == NT_ASSERTION && *find_answer (node, answer)) + if (*find_answer (node, answer)) { cpp_error (pfile, CPP_DL_WARNING, "\"%s\" re-asserted", NODE_NAME (node) + 1); @@ -2327,10 +2329,8 @@ do_assert (cpp_reader *pfile) (pfile, sizeof (cpp_macro) - sizeof (cpp_token) + sizeof (cpp_token) * answer->count); - if (node->type == NT_ASSERTION) - answer->parm.next = node->value.answers; - - node->type = NT_ASSERTION; + /* Chain into the list. */ + answer->parm.next = node->value.answers; node->value.answers = answer; check_eol (pfile, false); @@ -2345,7 +2345,7 @@ do_unassert (cpp_reader *pfile) cpp_hashnode *node = parse_assertion (pfile, T_UNASSERT, &answer); /* It isn't an error to #unassert something that isn't asserted. */ - if (node && node->type == NT_ASSERTION) + if (node) { if (answer) { @@ -2353,12 +2353,7 @@ do_unassert (cpp_reader *pfile) /* Remove the assert from the list. */ if (cpp_macro *temp = *p) - { - *p = temp->parm.next; - /* Did we free the last answer? */ - if (!*p) - node->type = NT_VOID; - } + *p = temp->parm.next; check_eol (pfile, false); } diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h index b784e0f..e7a933b 100644 --- a/libcpp/include/cpplib.h +++ b/libcpp/include/cpplib.h @@ -742,14 +742,9 @@ struct GTY(()) cpp_macro { } GTY ((desc ("%1.kind == cmk_traditional"))) exp; }; -/* The structure of a node in the hash table. The hash table has - entries for all identifiers: either macros defined by #define - commands (type NT_MACRO), assertions created with #assert - (NT_ASSERTION), or neither of the above (NT_VOID). Builtin macros - like __LINE__ are flagged NODE_BUILTIN. Poisoned identifiers are - flagged NODE_POISONED. NODE_OPERATOR (C++ only) indicates an - identifier that behaves like an operator such as "xor". - NODE_DIAGNOSTIC is for speed in lex_token: it indicates a +/* Poisoned identifiers are flagged NODE_POISONED. NODE_OPERATOR (C++ + only) indicates an identifier that behaves like an operator such as + "xor". NODE_DIAGNOSTIC is for speed in lex_token: it indicates a diagnostic may be required for this node. Currently this only applies to __VA_ARGS__, poisoned identifiers, and -Wc++-compat warnings about NODE_OPERATOR. */ @@ -757,21 +752,21 @@ struct GTY(()) cpp_macro { /* Hash node flags. */ #define NODE_OPERATOR (1 << 0) /* C++ named operator. */ #define NODE_POISONED (1 << 1) /* Poisoned identifier. */ -#define NODE_BUILTIN (1 << 2) /* Builtin macro. */ -#define NODE_DIAGNOSTIC (1 << 3) /* Possible diagnostic when lexed. */ -#define NODE_WARN (1 << 4) /* Warn if redefined or undefined. */ -#define NODE_DISABLED (1 << 5) /* A disabled macro. */ -#define NODE_MACRO_ARG (1 << 6) /* Used during #define processing. */ -#define NODE_USED (1 << 7) /* Dumped with -dU. */ -#define NODE_CONDITIONAL (1 << 8) /* Conditional macro */ -#define NODE_WARN_OPERATOR (1 << 9) /* Warn about C++ named operator. */ +#define NODE_DIAGNOSTIC (1 << 2) /* Possible diagnostic when lexed. */ +#define NODE_WARN (1 << 3) /* Warn if redefined or undefined. */ +#define NODE_DISABLED (1 << 4) /* A disabled macro. */ +#define NODE_USED (1 << 5) /* Dumped with -dU. */ +#define NODE_CONDITIONAL (1 << 6) /* Conditional macro */ +#define NODE_WARN_OPERATOR (1 << 7) /* Warn about C++ named operator. */ /* Different flavors of hash node. */ enum node_type { - NT_VOID = 0, /* No definition yet. */ - NT_MACRO, /* A macro of some form. */ - NT_ASSERTION /* Predicate for #assert. */ + NT_VOID = 0, /* Maybe an assert? */ + NT_MACRO_ARG, /* A macro arg. */ + NT_USER_MACRO, /* A user macro. */ + NT_BUILTIN_MACRO, /* A builtin macro. */ + NT_MACRO_MASK = NT_USER_MACRO /* Mask for either macro kind. */ }; /* Different flavors of builtin macro. _Pragma is an operator, but we @@ -796,36 +791,19 @@ enum cpp_builtin_type #define NODE_LEN(NODE) HT_LEN (&(NODE)->ident) #define NODE_NAME(NODE) HT_STR (&(NODE)->ident) -/* Specify which field, if any, of the union is used. */ - -enum { - NTV_MACRO, - NTV_ANSWER, - NTV_BUILTIN, - NTV_ARGUMENT, - NTV_NONE -}; - -#define CPP_HASHNODE_VALUE_IDX(HNODE) \ - ((HNODE.flags & NODE_MACRO_ARG) ? NTV_ARGUMENT \ - : HNODE.type == NT_MACRO ? ((HNODE.flags & NODE_BUILTIN) \ - ? NTV_BUILTIN : NTV_MACRO) \ - : HNODE.type == NT_ASSERTION ? NTV_ANSWER \ - : NTV_NONE) - /* The common part of an identifier node shared amongst all 3 C front ends. Also used to store CPP identifiers, which are a superset of identifiers in the grammatical sense. */ union GTY(()) _cpp_hashnode_value { - /* If a macro. */ - cpp_macro * GTY((tag ("NTV_MACRO"))) macro; - /* Answers to an assertion. */ - cpp_macro * GTY ((tag ("NTV_ANSWER"))) answers; + /* Assert (maybe NULL) */ + cpp_macro * GTY((tag ("NT_VOID"))) answers; + /* Macro (never NULL) */ + cpp_macro * GTY((tag ("NT_USER_MACRO"))) macro; /* Code for a builtin macro. */ - enum cpp_builtin_type GTY ((tag ("NTV_BUILTIN"))) builtin; + enum cpp_builtin_type GTY ((tag ("NT_BUILTIN_MACRO"))) builtin; /* Macro argument index. */ - unsigned short GTY ((tag ("NTV_ARGUMENT"))) arg_index; + unsigned short GTY ((tag ("NT_MACRO_ARG"))) arg_index; }; struct GTY(()) cpp_hashnode { @@ -838,7 +816,7 @@ struct GTY(()) cpp_hashnode { ENUM_BITFIELD(node_type) type : 6; /* CPP node type. */ unsigned int flags : 10; /* CPP flags. */ - union _cpp_hashnode_value GTY ((desc ("CPP_HASHNODE_VALUE_IDX (%1)"))) value; + union _cpp_hashnode_value GTY ((desc ("%1.type"))) value; }; /* A class for iterating through the source locations within a @@ -961,15 +939,16 @@ extern const cpp_token *cpp_get_token_with_location (cpp_reader *, source_location *); inline bool cpp_user_macro_p (const cpp_hashnode *node) { - return node->type == NT_MACRO && !(node->flags & NODE_BUILTIN); + return node->type == NT_USER_MACRO; + } inline bool cpp_builtin_macro_p (const cpp_hashnode *node) { - return node->flags & NODE_BUILTIN; + return node->type == NT_BUILTIN_MACRO; } inline bool cpp_macro_p (const cpp_hashnode *node) { - return node->type == NT_MACRO; + return node->type & NT_MACRO_MASK; } /* Returns true if NODE is a function-like user macro. */ inline bool cpp_fun_like_macro_p (cpp_hashnode *node) diff --git a/libcpp/init.c b/libcpp/init.c index d1697fd..32a5956 100644 --- a/libcpp/init.c +++ b/libcpp/init.c @@ -480,8 +480,7 @@ cpp_init_special_builtins (cpp_reader *pfile) || pfile->cb.has_attribute == NULL)) continue; cpp_hashnode *hp = cpp_lookup (pfile, b->name, b->len); - hp->type = NT_MACRO; - hp->flags |= NODE_BUILTIN; + hp->type = NT_BUILTIN_MACRO; if (b->always_warn_if_redefined) hp->flags |= NODE_WARN; hp->value.builtin = (enum cpp_builtin_type) b->value; diff --git a/libcpp/macro.c b/libcpp/macro.c index 123f63d..3629e83 100644 --- a/libcpp/macro.c +++ b/libcpp/macro.c @@ -85,8 +85,9 @@ struct macro_arg_token_iter struct macro_arg_saved_data { /* The canonical (UTF-8) spelling of this identifier. */ cpp_hashnode *canonical_node; - /* The previous value of this identifier. */ + /* The previous value & type of this identifier. */ union _cpp_hashnode_value value; + node_type type; }; static const char *vaopt_paste_error = @@ -2730,7 +2731,7 @@ cpp_get_token_1 (cpp_reader *pfile, source_location *location) node = result->val.node.node; - if (node->type != NT_MACRO || (result->flags & NO_EXPAND)) + if (node->type == NT_VOID || (result->flags & NO_EXPAND)) break; if (!(node->flags & NODE_DISABLED)) @@ -3040,8 +3041,8 @@ _cpp_free_definition (cpp_hashnode *h) { /* Macros and assertions no longer have anything to free. */ h->type = NT_VOID; - /* Clear builtin flag in case of redefinition. */ - h->flags &= ~(NODE_BUILTIN | NODE_DISABLED | NODE_USED); + h->value.answers = NULL; + h->flags &= ~(NODE_DISABLED | NODE_USED); } /* Save parameter NODE (spelling SPELLING) to the parameter list of @@ -3051,7 +3052,7 @@ _cpp_save_parameter (cpp_reader *pfile, unsigned n, cpp_hashnode *node, cpp_hashnode *spelling) { /* Constraint 6.10.3.6 - duplicate parameter names. */ - if (node->flags & NODE_MACRO_ARG) + if (node->type == NT_MACRO_ARG) { cpp_error (pfile, CPP_DL_ERROR, "duplicate macro parameter \"%s\"", NODE_NAME (node)); @@ -3069,13 +3070,14 @@ _cpp_save_parameter (cpp_reader *pfile, unsigned n, cpp_hashnode *node, macro_arg_saved_data *saved = (macro_arg_saved_data *)pfile->macro_buffer; saved[n].canonical_node = node; saved[n].value = node->value; + saved[n].type = node->type; void *base = _cpp_reserve_room (pfile, n * sizeof (cpp_hashnode *), sizeof (cpp_hashnode *)); ((cpp_hashnode **)base)[n] = spelling; /* Morph into a macro arg. */ - node->flags |= NODE_MACRO_ARG; + node->type = NT_MACRO_ARG; /* Index is 1 based. */ node->value.arg_index = n + 1; @@ -3093,8 +3095,8 @@ _cpp_unsave_parameters (cpp_reader *pfile, unsigned n) &((struct macro_arg_saved_data *) pfile->macro_buffer)[n]; struct cpp_hashnode *node = save->canonical_node; + node->type = save->type; node->value = save->value; - node->flags &= ~NODE_MACRO_ARG; } } @@ -3109,6 +3111,7 @@ _cpp_unsave_parameters (cpp_reader *pfile, unsigned n) | name '...' | '...' */ + static bool parse_params (cpp_reader *pfile, unsigned *n_ptr, bool *varadic_ptr) { @@ -3232,9 +3235,9 @@ lex_expansion_token (cpp_reader *pfile, cpp_macro *macro) pfile->cur_token = saved_cur_token; /* Is this a parameter? */ - if (token->type == CPP_NAME - && (token->val.node.node->flags & NODE_MACRO_ARG) != 0) + if (token->type == CPP_NAME && token->val.node.node->type == NT_MACRO_ARG) { + /* Morph into a parameter reference. */ cpp_hashnode *spelling = token->val.node.spelling; token->type = CPP_MACRO_ARG; token->val.macro_arg.arg_no = token->val.node.node->value.arg_index; @@ -3527,7 +3530,7 @@ _cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node) } /* Enter definition in hash table. */ - node->type = NT_MACRO; + node->type = NT_USER_MACRO; node->value.macro = macro; if (! ustrncmp (NODE_NAME (node), DSC ("__STDC_")) && ustrcmp (NODE_NAME (node), (const uchar *) "__STDC_FORMAT_MACROS") @@ -3565,17 +3568,18 @@ _cpp_notify_macro_use (cpp_reader *pfile, cpp_hashnode *node) node->flags |= NODE_USED; switch (node->type) { - case NT_MACRO: - if (!(node->flags & NODE_BUILTIN)) - { - cpp_macro *macro = node->value.macro; - if (macro->lazy) - { - pfile->cb.user_lazy_macro (pfile, macro, macro->lazy - 1); - macro->lazy = 0; - } - } + case NT_USER_MACRO: + { + cpp_macro *macro = node->value.macro; + if (macro->lazy) + { + pfile->cb.user_lazy_macro (pfile, macro, macro->lazy - 1); + macro->lazy = 0; + } + } + /* FALLTHROUGH. */ + case NT_BUILTIN_MACRO: if (pfile->cb.used_define) pfile->cb.used_define (pfile, pfile->directive_line, node); break; diff --git a/libcpp/pch.c b/libcpp/pch.c index 47b99c1..04d7094 100644 --- a/libcpp/pch.c +++ b/libcpp/pch.c @@ -50,48 +50,47 @@ static int write_macdef (cpp_reader *pfile, cpp_hashnode *hn, void *file_p) { FILE *f = (FILE *) file_p; + bool is_void = false; switch (hn->type) { case NT_VOID: if (! (hn->flags & NODE_POISONED)) return 1; - /* XXX Really fallthru? */ - /* FALLTHRU */ + is_void = true; + goto poisoned; - case NT_MACRO: - if (hn->flags & NODE_BUILTIN) - return 1; - - { - struct macrodef_struct s; - const unsigned char *defn; + case NT_BUILTIN_MACRO: + return 1; - s.name_length = NODE_LEN (hn); - s.flags = hn->flags & NODE_POISONED; + case NT_USER_MACRO: + if (hn->value.macro->kind != cmk_assert) + { + poisoned: + struct macrodef_struct s; + const unsigned char *defn; - if (hn->type == NT_MACRO) - { - defn = cpp_macro_definition (pfile, hn); - s.definition_length = ustrlen (defn); - } - else - { - defn = NODE_NAME (hn); - s.definition_length = s.name_length; - } + s.name_length = NODE_LEN (hn); + s.flags = hn->flags & NODE_POISONED; - if (fwrite (&s, sizeof (s), 1, f) != 1 - || fwrite (defn, 1, s.definition_length, f) != s.definition_length) - { - cpp_errno (pfile, CPP_DL_ERROR, - "while writing precompiled header"); - return 0; - } - } - return 1; + if (is_void) + { + defn = NODE_NAME (hn); + s.definition_length = s.name_length; + } + else + { + defn = cpp_macro_definition (pfile, hn); + s.definition_length = ustrlen (defn); + } - case NT_ASSERTION: - /* Not currently implemented. */ + if (fwrite (&s, sizeof (s), 1, f) != 1 + || fwrite (defn, 1, s.definition_length, f) != s.definition_length) + { + cpp_errno (pfile, CPP_DL_ERROR, + "while writing precompiled header"); + return 0; + } + } return 1; default: @@ -226,8 +225,11 @@ count_defs (cpp_reader *pfile ATTRIBUTE_UNUSED, cpp_hashnode *hn, void *ss_p) switch (hn->type) { - case NT_MACRO: - if (hn->flags & NODE_BUILTIN) + case NT_BUILTIN_MACRO: + return 1; + + case NT_USER_MACRO: + if (hn->value.macro->kind == cmk_assert) return 1; /* fall through. */ @@ -248,10 +250,6 @@ count_defs (cpp_reader *pfile ATTRIBUTE_UNUSED, cpp_hashnode *hn, void *ss_p) } return 1; - case NT_ASSERTION: - /* Not currently implemented. */ - return 1; - default: abort (); } @@ -265,8 +263,11 @@ write_defs (cpp_reader *pfile ATTRIBUTE_UNUSED, cpp_hashnode *hn, void *ss_p) switch (hn->type) { - case NT_MACRO: - if (hn->flags & NODE_BUILTIN) + case NT_BUILTIN_MACRO: + return 1; + + case NT_USER_MACRO: + if (hn->value.macro->kind == cmk_assert) return 1; /* fall through. */ @@ -287,10 +288,6 @@ write_defs (cpp_reader *pfile ATTRIBUTE_UNUSED, cpp_hashnode *hn, void *ss_p) } return 1; - case NT_ASSERTION: - /* Not currently implemented. */ - return 1; - default: abort (); } @@ -621,7 +618,7 @@ cpp_valid_state (cpp_reader *r, const char *name, int fd) goto fail; } - if (h->type != NT_MACRO) + if (h->type == NT_VOID) { /* It's ok if __GCC_HAVE_DWARF2_CFI_ASM becomes undefined, as in, when the PCH file is created with -g and we're @@ -758,8 +755,7 @@ save_macros (cpp_reader *r, cpp_hashnode *h, void *data_p) { struct save_macro_data *data = (struct save_macro_data *)data_p; - if (h->type != NT_VOID - && (h->flags & NODE_BUILTIN) == 0) + if (cpp_user_macro_p (h)) { if (data->count == data->array_size) { @@ -767,28 +763,14 @@ save_macros (cpp_reader *r, cpp_hashnode *h, void *data_p) data->defns = XRESIZEVEC (uchar *, data->defns, (data->array_size)); } - switch (h->type) - { - case NT_ASSERTION: - /* Not currently implemented. */ - return 1; - - case NT_MACRO: - { - const uchar * defn = cpp_macro_definition (r, h); - size_t defnlen = ustrlen (defn); + const uchar * defn = cpp_macro_definition (r, h); + size_t defnlen = ustrlen (defn); - data->defns[data->count] = (uchar *) xmemdup (defn, defnlen, - defnlen + 2); - data->defns[data->count][defnlen] = '\n'; - } - break; - - default: - abort (); - } + data->defns[data->count] = (uchar *) xmemdup (defn, defnlen, defnlen + 2); + data->defns[data->count][defnlen] = '\n'; data->count++; } + return 1; } diff --git a/libcpp/traditional.c b/libcpp/traditional.c index 0c42b25..51c3e35 100644 --- a/libcpp/traditional.c +++ b/libcpp/traditional.c @@ -545,7 +545,7 @@ _cpp_scan_out_logical_line (cpp_reader *pfile, cpp_macro *macro, goto new_context; } } - else if (macro && (node->flags & NODE_MACRO_ARG) != 0) + else if (macro && node->type == NT_MACRO_ARG) { /* Found a parameter in the replacement text of a #define. Remove its name from the output. */ -- cgit v1.1 From a5a35247177708c5dd2e6c835ae5aa19fe1fb77e Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Mon, 20 Aug 2018 17:45:42 +0000 Subject: [CPP PATCH] node field bits https://gcc.gnu.org/ml/gcc-patches/2018-08/msg01171.html * include/cpplib.h: Fixup some whitespace. (cpp_hashnode): Reduce type to 2 bit & flags to 8. From-SVN: r263669 --- libcpp/ChangeLog | 3 +++ libcpp/include/cpplib.h | 8 +++++--- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'libcpp') diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index 8998c0d..de6f542 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,5 +1,8 @@ 2018-08-20 Nathan Sidwell + * include/cpplib.h: Fixup some whitespace. + (cpp_hashnode): Reduce type to 2 bit & flags to 8. + * include/cpplib.h (NODE_BUILTIN, NODE_MACRO_ARG): Delete. Renumber others. (enum node_type): Replace NT_MACRO with NT_USER_MACRO, diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h index e7a933b..85aa09f 100644 --- a/libcpp/include/cpplib.h +++ b/libcpp/include/cpplib.h @@ -813,8 +813,10 @@ struct GTY(()) cpp_hashnode { then index into directive table. Otherwise, a NODE_OPERATOR. */ unsigned char rid_code; /* Rid code - for front ends. */ - ENUM_BITFIELD(node_type) type : 6; /* CPP node type. */ - unsigned int flags : 10; /* CPP flags. */ + ENUM_BITFIELD(node_type) type : 2; /* CPP node type. */ + unsigned int flags : 8; /* CPP flags. */ + + /* 6 bits spare (plus another 32 on 64-bit hosts). */ union _cpp_hashnode_value GTY ((desc ("%1.type"))) value; }; @@ -940,7 +942,6 @@ extern const cpp_token *cpp_get_token_with_location (cpp_reader *, inline bool cpp_user_macro_p (const cpp_hashnode *node) { return node->type == NT_USER_MACRO; - } inline bool cpp_builtin_macro_p (const cpp_hashnode *node) { @@ -950,6 +951,7 @@ inline bool cpp_macro_p (const cpp_hashnode *node) { return node->type & NT_MACRO_MASK; } + /* Returns true if NODE is a function-like user macro. */ inline bool cpp_fun_like_macro_p (cpp_hashnode *node) { -- cgit v1.1 From cf806c7dc305fe14654b44ed7cfe0a35c7947af1 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Fri, 24 Aug 2018 23:37:53 +0000 Subject: Set start_location to 0 if we ran out of line map space With profiledbootstrap and --with-build-config=bootstrap-lto, linemap_add may create a macro map when we run out of line map space. This patch changes start_location to UNKNOWN_LOCATION (0) in this case. Tested with profiledbootstrap and --with-build-config=bootstrap-lto on Linux/x86-64. PR bootstrap/86872 * line-map.c (pure_location_p): Return true if linemap_lookup returns NULL. (linemap_add): Set start_location to 0 if we run out of line map space. From-SVN: r263845 --- libcpp/ChangeLog | 8 ++++++++ libcpp/line-map.c | 7 +++++++ 2 files changed, 15 insertions(+) (limited to 'libcpp') diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index de6f542..cbf4cbf 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,3 +1,11 @@ +2018-08-24 H.J. Lu + + PR bootstrap/86872 + * line-map.c (pure_location_p): Return true if linemap_lookup + returns NULL. + (linemap_add): Set start_location to 0 if we run out of line map + space. + 2018-08-20 Nathan Sidwell * include/cpplib.h: Fixup some whitespace. diff --git a/libcpp/line-map.c b/libcpp/line-map.c index f0e6318..b5e1f13 100644 --- a/libcpp/line-map.c +++ b/libcpp/line-map.c @@ -304,6 +304,8 @@ pure_location_p (line_maps *set, source_location loc) return false; const line_map *map = linemap_lookup (set, loc); + if (map == NULL) + return true; const line_map_ordinary *ordmap = linemap_check_ordinary (map); if (loc & ((1U << ordmap->m_range_bits) - 1)) @@ -492,6 +494,11 @@ linemap_add (struct line_maps *set, enum lc_reason reason, } linemap_assert (reason != LC_ENTER_MACRO); + + if (start_location >= LINE_MAP_MAX_LOCATION) + /* We ran out of line map space. */ + start_location = 0; + line_map_ordinary *map = linemap_check_ordinary (new_linemap (set, start_location)); map->reason = reason; -- cgit v1.1 From 85204e23e2fed09fc07159ab5607e0b760269561 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Mon, 27 Aug 2018 14:02:05 +0000 Subject: Less verbose fix-it hints for missing header files (PR 87091) This patch tweaks maybe_add_include_fixit so that if we're emitting a note about adding the header file, the note's primary location will be replaced by that of the fix-it hint, to avoid repeating a location we've already emitted (or one close to it). For example, this simplifies: ../x86_64-pc-linux-gnu/libstdc++-v3/include/vector:87:27: error: msg 1 87 | using vector = std::vector<_Tp, polymorphic_allocator<_Tp>>; | ^~~~~~ ../x86_64-pc-linux-gnu/libstdc++-v3/include/vector:87:22: note: msg 2 73 | # include +++ |+#include 74 | #endif .... 87 | using vector = std::vector<_Tp, polymorphic_allocator<_Tp>>; | ^~~ to: ../x86_64-pc-linux-gnu/libstdc++-v3/include/vector:87:27: error: msg 1 87 | using vector = std::vector<_Tp, polymorphic_allocator<_Tp>>; | ^~~~~~ ../x86_64-pc-linux-gnu/libstdc++-v3/include/vector:74:1: note: msg 2 73 | # include +++ |+#include 74 | #endif eliminating the repetition of line 87 in the note. Doing so requires converting show_caret_p to a tri-state, to avoid meaninglessly printing a caret for the first column in the next line (and colorizing it): ../x86_64-pc-linux-gnu/libstdc++-v3/include/vector:74:1: note: msg 2 73 | # include +++ |+#include 74 | #endif | ^ gcc/c-family/ChangeLog: PR 87091 * c-common.c (c_cpp_error): Update for conversion of show_caret_p to a tri-state. (maybe_suggest_missing_token_insertion): Likewise. (maybe_add_include_fixit): Add param "override_location". If set, and source-printing is enabled, then override the rich_location's primary location with that of the insertion point for the fix-it hint, marking it with SHOW_LINES_WITHOUT_RANGE. * c-common.h (extern void maybe_add_include_fixit): Add bool param. * c-format.c (selftest::test_type_mismatch_range_labels): Update for conversion of show_caret_p to a tri-state. * c-warn.c (warn_for_restrict): Likewise. * known-headers.cc (suggest_missing_header::~suggest_missing_header): Update call to maybe_add_include_fixit to suggest overriding the location, as it is for a note. gcc/c/ChangeLog: PR 87091 * c-decl.c (implicitly_declare): Update call to maybe_add_include_fixit to suggest overriding the location, as it is for a note. * c-objc-common.c (c_tree_printer): Update for conversion of show_caret_p to a tri-state. gcc/cp/ChangeLog: PR 87091 * decl.c (grokdeclarator): Update for conversion of show_caret_p to a tri-state. * error.c (cp_printer): Likewise. * name-lookup.c (maybe_suggest_missing_std_header): Update call to maybe_add_include_fixit to suggest overriding the location, as it is for a note. * parser.c (cp_parser_string_literal): Update for conversion of show_caret_p to a tri-state. (cp_parser_elaborated_type_specifier): Likewise. (set_and_check_decl_spec_loc): Likewise. * pt.c (listify): Update call to maybe_add_include_fixit to not override the location, as it is for an error. * rtti.c (typeid_ok_p): Likewise. gcc/ChangeLog: PR 87091 * diagnostic-show-locus.c (class layout_range): Update for conversion of show_caret_p to a tri-state. (layout_range::layout_range): Likewise. (make_range): Likewise. (layout::maybe_add_location_range): Likewise. (layout::should_print_annotation_line_p): Don't show annotation lines for ranges that are SHOW_LINES_WITHOUT_RANGE. (layout::get_state_at_point): Update for conversion of show_caret_p to a tri-state. Bail out early for SHOW_LINES_WITHOUT_RANGE, so that such ranges don't affect underlining or source colorization. (gcc_rich_location::add_location_if_nearby): Update for conversion of show_caret_p to a tri-state. (selftest::test_one_liner_multiple_carets_and_ranges): Likewise. (selftest::test_one_liner_fixit_replace_equal_secondary_range): Likewise. (selftest::test_one_liner_labels): Likewise. * gcc-rich-location.c (gcc_rich_location::add_expr): Update for conversion of show_caret_p to a tri-state. * pretty-print.c (text_info::set_location): Likewise. * pretty-print.h (text_info::set_location): Likewise. * substring-locations.c (format_warning_n_va): Likewise. * tree-diagnostic.c (default_tree_printer): Likewise. * tree-pretty-print.c (newline_and_indent): Likewise. gcc/fortran/ChangeLog: PR 87091 * error.c (gfc_format_decoder): Update for conversion of show_caret_p to a tri-state. gcc/testsuite/ChangeLog: PR 87091 * gcc.dg/empty.h: New file. * gcc.dg/fixits-pr84852-1.c: Update for move of fix-it hint to top of file and removal of redundant second printing of warning location. * gcc.dg/fixits-pr84852-2.c: Likewise. * gcc.dg/missing-header-fixit-3.c: Likewise. * gcc.dg/missing-header-fixit-4.c: New test. * gcc.dg/plugin/diagnostic_plugin_test_show_locus.c: Update for conversion of show_caret_p to a tri-state. libcpp/ChangeLog: PR 87091 * include/line-map.h (enum range_display_kind): New enum. (struct location_range): Replace field "m_show_caret_p" with "m_range_display_kind", converting from bool to the new enum. (class rich_location): Add example of line insertion fix-it hint. (rich_location::add_range): Convert param "show_caret_p" from bool to enum range_display_kind and rename to "range_display_kind", giving it a default of SHOW_RANGE_WITHOUT_CARET. (rich_location::set_range): Likewise, albeit without a default. * line-map.c (rich_location::rich_location): Update for conversion of show_caret_p to tri-state enum. (rich_location::add_range): Likewise. (rich_location::set_range): Likewise. From-SVN: r263885 --- libcpp/ChangeLog | 16 +++++++++++++ libcpp/include/line-map.h | 60 +++++++++++++++++++++++++++++++++++++---------- libcpp/line-map.c | 15 ++++++------ 3 files changed, 72 insertions(+), 19 deletions(-) (limited to 'libcpp') diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index cbf4cbf..7b716cf 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,3 +1,19 @@ +2018-08-27 David Malcolm + + PR 87091 + * include/line-map.h (enum range_display_kind): New enum. + (struct location_range): Replace field "m_show_caret_p" with + "m_range_display_kind", converting from bool to the new enum. + (class rich_location): Add example of line insertion fix-it hint. + (rich_location::add_range): Convert param "show_caret_p" from bool + to enum range_display_kind and rename to "range_display_kind", + giving it a default of SHOW_RANGE_WITHOUT_CARET. + (rich_location::set_range): Likewise, albeit without a default. + * line-map.c (rich_location::rich_location): Update for conversion + of show_caret_p to tri-state enum. + (rich_location::add_range): Likewise. + (rich_location::set_range): Likewise. + 2018-08-24 H.J. Lu PR bootstrap/86872 diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h index 4f0ff87..e74ccbb 100644 --- a/libcpp/include/line-map.h +++ b/libcpp/include/line-map.h @@ -1283,6 +1283,36 @@ typedef struct class range_label; +/* A hint to diagnostic_show_locus on how to print a source range within a + rich_location. + + Typically this is SHOW_RANGE_WITH_CARET for the 0th range, and + SHOW_RANGE_WITHOUT_CARET for subsequent ranges, + but the Fortran frontend uses SHOW_RANGE_WITH_CARET repeatedly for + printing things like: + + x = x + y + 1 2 + Error: Shapes for operands at (1) and (2) are not conformable + + where "1" and "2" are notionally carets. */ + +enum range_display_kind +{ + /* Show the pertinent source line(s), the caret, and underline(s). */ + SHOW_RANGE_WITH_CARET, + + /* Show the pertinent source line(s) and underline(s), but don't + show the caret (just an underline). */ + SHOW_RANGE_WITHOUT_CARET, + + /* Just show the source lines; don't show the range itself. + This is for use when displaying some line-insertion fix-it hints (for + showing the user context on the change, for when it doesn't make sense + to highlight the first column on the next line). */ + SHOW_LINES_WITHOUT_RANGE +}; + /* A location within a rich_location: a caret&range, with the caret potentially flagged for display, and an optional label. */ @@ -1291,16 +1321,7 @@ struct location_range { source_location m_loc; - /* Should a caret be drawn for this range? Typically this is - true for the 0th range, and false for subsequent ranges, - but the Fortran frontend overrides this for rendering things like: - - x = x + y - 1 2 - Error: Shapes for operands at (1) and (2) are not conformable - - where "1" and "2" are notionally carets. */ - bool m_show_caret_p; + enum range_display_kind m_range_display_kind; /* If non-NULL, the label for this range. */ const range_label *m_label; @@ -1567,6 +1588,18 @@ class fixit_hint; added via richloc.add_fixit_replace ("color"); + Example J: fix-it hint: line insertion + ************************************** + + 3 | #include + + |+#include + 4 | int the_next_line; + + This rich location has a single range at line 4 column 1, marked + with SHOW_LINES_WITHOUT_RANGE (to avoid printing a meaningless caret + on the "i" of int). It has a insertion fix-it hint of the string + "#include \n". + Adding a fix-it hint can fail: for example, attempts to insert content at the transition between two line maps may fail due to there being no source_location (aka location_t) value to express the new location. @@ -1610,11 +1643,14 @@ class rich_location source_location get_loc (unsigned int idx) const; void - add_range (source_location loc, bool show_caret_p, + add_range (source_location loc, + enum range_display_kind range_display_kind + = SHOW_RANGE_WITHOUT_CARET, const range_label *label = NULL); void - set_range (unsigned int idx, source_location loc, bool show_caret_p); + set_range (unsigned int idx, source_location loc, + enum range_display_kind range_display_kind); unsigned int get_num_locations () const { return m_ranges.count (); } diff --git a/libcpp/line-map.c b/libcpp/line-map.c index b5e1f13..73d9444 100644 --- a/libcpp/line-map.c +++ b/libcpp/line-map.c @@ -2005,7 +2005,7 @@ rich_location::rich_location (line_maps *set, source_location loc, m_seen_impossible_fixit (false), m_fixits_cannot_be_auto_applied (false) { - add_range (loc, true, label); + add_range (loc, SHOW_RANGE_WITH_CARET, label); } /* The destructor for class rich_location. */ @@ -2081,18 +2081,19 @@ rich_location::override_column (int column) /* Add the given range. */ void -rich_location::add_range (source_location loc, bool show_caret_p, +rich_location::add_range (source_location loc, + enum range_display_kind range_display_kind, const range_label *label) { location_range range; range.m_loc = loc; - range.m_show_caret_p = show_caret_p; + range.m_range_display_kind = range_display_kind; range.m_label = label; m_ranges.push (range); } /* Add or overwrite the location given by IDX, setting its location to LOC, - and setting its "should my caret be printed" flag to SHOW_CARET_P. + and setting its m_range_display_kind to RANGE_DISPLAY_KIND. It must either overwrite an existing location, or add one *exactly* on the end of the array. @@ -2106,19 +2107,19 @@ rich_location::add_range (source_location loc, bool show_caret_p, void rich_location::set_range (unsigned int idx, source_location loc, - bool show_caret_p) + enum range_display_kind range_display_kind) { /* We can either overwrite an existing range, or add one exactly on the end of the array. */ linemap_assert (idx <= m_ranges.count ()); if (idx == m_ranges.count ()) - add_range (loc, show_caret_p); + add_range (loc, range_display_kind); else { location_range *locrange = get_range (idx); locrange->m_loc = loc; - locrange->m_show_caret_p = show_caret_p; + locrange->m_range_display_kind = range_display_kind; } if (idx == 0) -- cgit v1.1 From 92a285c1a7bad310d7223a7aa5d70e6a5fc3e644 Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Mon, 27 Aug 2018 14:04:23 +0000 Subject: Replace 8 spaces with a tabular in ChangeLog files. From-SVN: r263886 --- libcpp/ChangeLog | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'libcpp') diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index 7b716cf..471d6b7 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -296,10 +296,10 @@ 2018-01-18 Boris Kolpackov - PR other/70268 - * include/cpplib.h (cpp_callbacks::remap_filename): New callback. - * macro.c (_cpp_builtin_macro_text): Call remap_filename for - __FILE__ and __BASE_FILE__. + PR other/70268 + * include/cpplib.h (cpp_callbacks::remap_filename): New callback. + * macro.c (_cpp_builtin_macro_text): Call remap_filename for + __FILE__ and __BASE_FILE__. 2018-01-10 Kelvin Nilsen -- cgit v1.1 From 24c35f687a2d1e95c45086f5a13a3624cf21f32a Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Thu, 30 Aug 2018 15:16:21 +0000 Subject: [libcpp] fix some line map comments https://gcc.gnu.org/ml/gcc-patches/2018-08/msg01978.html * include/line-map.h (enum lc_reason): Comment each member separately. (struct line_maps): Fix reallocator comment. From-SVN: r263987 --- libcpp/ChangeLog | 6 ++++++ libcpp/include/line-map.h | 21 +++++++-------------- 2 files changed, 13 insertions(+), 14 deletions(-) (limited to 'libcpp') diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index 471d6b7..59052be 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,3 +1,9 @@ +2018-08-30 Nathan Sidwell + + * include/line-map.h (enum lc_reason): Comment each member + separately. + (struct line_maps): Fix reallocator comment. + 2018-08-27 David Malcolm PR 87091 diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h index e74ccbb..fd06758 100644 --- a/libcpp/include/line-map.h +++ b/libcpp/include/line-map.h @@ -61,20 +61,14 @@ inline int compare (linenum_type lhs, linenum_type rhs) return 0; } -/* 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. LC_ENTER_MACRO is when a macro expansion is about to start. */ +/* Reason for creating a new line map with linemap_add. */ enum lc_reason { - LC_ENTER = 0, - LC_LEAVE, - LC_RENAME, - LC_RENAME_VERBATIM, - LC_ENTER_MACRO, + LC_ENTER = 0, /* Begin #include. */ + LC_LEAVE, /* Return to including file. */ + LC_RENAME, /* Other reason for name change. */ + LC_RENAME_VERBATIM, /* Likewise, but "" != stdin. */ + LC_ENTER_MACRO, /* Begin macro expansion. */ /* FIXME: add support for stringize and paste. */ LC_HWM /* High Water Mark. */ }; @@ -777,8 +771,7 @@ struct GTY(()) line_maps { may require allocating a new line_map. */ unsigned int max_column_hint; - /* If non-null, the allocator to use when resizing 'maps'. If null, - xrealloc is used. */ + /* The allocator to use when resizing 'maps', defaults to xrealloc. */ line_map_realloc reallocator; /* The allocators' function used to know the actual size it -- cgit v1.1 From 9c4a4b3cbd4970447d28963481c04bb7b7d2c4f2 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Mon, 17 Sep 2018 23:32:12 +0000 Subject: Add range_idx param to range_label::get_text This patch updates the pure virtual function range_label::get_text (and its implementations) so that the index of the range is passed in, allowing for one label instance to be shared by multiple ranges. gcc/c-family/ChangeLog: * c-format.c (range_label_for_format_type_mismatch::get_text): Update for new param. gcc/c/ChangeLog: * c-objc-common.c (range_label_for_type_mismatch::get_text): Update for new param. * c-typeck.c (maybe_range_label_for_tree_type_mismatch::get_text): Likewise. gcc/cp/ChangeLog: * error.c (range_label_for_type_mismatch::get_text): Update for new param. gcc/ChangeLog: * diagnostic-show-locus.c (class layout_range): Add field "m_original_idx". (layout_range::layout_range): Add "original_idx" param and use it to initialize new field. (make_range): Use 0 for original_idx. (layout::layout): Pass in index to calls to maybe_add_location_range. (layout::maybe_add_location_range): Add param "original_idx" and pass it on to layout_range. (layout::print_any_labels): Pass on range->m_original_idx to get_text call. (gcc_rich_location::add_location_if_nearby): Use 0 for original_idx. * gcc-rich-location.h (text_range_label::get_text): Update for new param. (range_label_for_type_mismatch::get_text): Likewise. libcpp/ChangeLog: * include/line-map.h (range_label::get_text): Add param "range_idx". From-SVN: r264376 --- libcpp/ChangeLog | 5 +++++ libcpp/include/line-map.h | 6 ++++-- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'libcpp') diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index 59052be..ef96824 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,3 +1,8 @@ +2018-09-17 David Malcolm + + * include/line-map.h (range_label::get_text): Add param + "range_idx". + 2018-08-30 Nathan Sidwell * include/line-map.h (enum lc_reason): Comment each member diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h index fd06758..c479dfa 100644 --- a/libcpp/include/line-map.h +++ b/libcpp/include/line-map.h @@ -1808,8 +1808,10 @@ class range_label public: virtual ~range_label () {} - /* Get localized text for the label. */ - virtual label_text get_text () const = 0; + /* Get localized text for the label. + The RANGE_IDX is provided, allowing for range_label instances to be + shared by multiple ranges if need be (the "flyweight" design pattern). */ + virtual label_text get_text (unsigned range_idx) const = 0; }; /* A fix-it hint: a suggested insertion, replacement, or deletion of text. -- cgit v1.1