diff options
Diffstat (limited to 'libcpp')
-rw-r--r-- | libcpp/ChangeLog | 238 | ||||
-rw-r--r-- | libcpp/charset.c | 3 | ||||
-rw-r--r-- | libcpp/directives.c | 71 | ||||
-rw-r--r-- | libcpp/expr.c | 32 | ||||
-rw-r--r-- | libcpp/files.c | 215 | ||||
-rw-r--r-- | libcpp/generated_cpp_wcwidth.h | 188 | ||||
-rw-r--r-- | libcpp/include/cpplib.h | 97 | ||||
-rw-r--r-- | libcpp/include/line-map.h | 51 | ||||
-rw-r--r-- | libcpp/include/mkdeps.h | 13 | ||||
-rw-r--r-- | libcpp/init.c | 73 | ||||
-rw-r--r-- | libcpp/internal.h | 72 | ||||
-rw-r--r-- | libcpp/lex.c | 447 | ||||
-rw-r--r-- | libcpp/line-map.c | 116 | ||||
-rw-r--r-- | libcpp/macro.c | 284 | ||||
-rw-r--r-- | libcpp/mkdeps.c | 119 | ||||
-rw-r--r-- | libcpp/traditional.c | 1 |
16 files changed, 1664 insertions, 356 deletions
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index 61bfe81..c071469 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,3 +1,241 @@ +2020-12-14 Nathan Sidwell <nathan@acm.org> + + * include/cpplib.h (struct cpp_macro): Add imported_p field. + (struct cpp_hashnode): Tweak deferred field documentation. + * macro.c (_cpp_new_macro): Clear new field. + (cpp_get_deferred_macro, get_deferred_or_lazy_macro): Assert + more. + +2020-12-10 Jason Merrill <jason@redhat.com> + + * init.c (cpp_init_builtins): Update __cplusplus for C++20. + +2020-12-01 JeanHeyd Meneide <phdofthehouse@gmail.com> + + * charset.c (init_iconv_desc): Initialize "to" and "from" fields. + * directives.c (cpp_get_narrow_charset_name): New function. + (cpp_get_wide_charset_name): Likewise. + * include/cpplib.h (cpp_get_narrow_charset_name): Prototype. + (cpp_get_wide_charset_name): Likewise. + * internal.h (cset_converter): Add "to" and "from" fields. + +2020-11-27 Joseph Myers <joseph@codesourcery.com> + + PR preprocessor/97602 + * directives.c (strtolinenum): Check for overflow before it + occurs. Correct comment. + +2020-11-24 Nathan Sidwell <nathan@acm.org> + + * include/cpplib.h (struct cpp_hashnode): Add deferred field. + (cpp_set_deferred_macro): Define. + (cpp_get_deferred_macro): Declare. + (cpp_macro_definition): Reformat, add overload. + (cpp_macro_definition_location): Deal with deferred macro. + (cpp_alloc_token_string, cpp_compare_macro): Declare. + * internal.h (_cpp_notify_macro_use): Return bool + (_cpp_maybe_notify_macro_use): Likewise. + * directives.c (do_undef): Check macro is not undef before + warning. + (do_ifdef, do_ifndef): Deal with deferred macro. + * expr.c (parse_defined): Likewise. + * lex.c (cpp_allocate_token_string): Break out of ... + (create_literal): ... here. Call it. + (cpp_maybe_module_directive): Deal with deferred macro. + * macro.c (cpp_get_token_1): Deal with deferred macro. + (warn_of_redefinition): Deal with deferred macro. + (compare_macros): Rename to ... + (cpp_compare_macro): ... here. Make extern. + (cpp_get_deferred_macro): New. + (_cpp_notify_macro_use): Deal with deferred macro, return bool + indicating definedness. + (cpp_macro_definition): Deal with deferred macro. + +2020-11-19 Nathan Sidwell <nathan@acm.org> + + * include/cpplib.h (enum cpp_main_search): New. + (struct cpp_options): Add main_search field. + (cpp_main_loc): Declare. + (cpp_retrofit_as_include): Declare. + * internal.h (struct cpp_reader): Add main_loc field. + (_cpp_in_main_source_file): Not main if main is a header. + * init.c (cpp_read_main_file): Use main_search option to locate + main file. Set main_loc + * files.c (cpp_retrofit_as_include): New. + +2020-11-19 Nathan Sidwell <nathan@acm.org> + + * internal.h (cpp_in_system_header): Rename to ... + (_cpp_in_system_header): ... here. + (cpp_in_primary_file): Rename to ... + (_cpp_in_main_source_file): ... here. Compare main_file equality + and check main_search value. + * lex.c (maybe_va_opt_error, _cpp_lex_direct): Adjust for rename. + * macro.c (_cpp_builtin_macro_text): Likewise. + (replace_args): Likewise. + * directives.c (do_include_next): Likewise. + (do_pragma_once, do_pragma_system_header): Likewise. + * files.c (struct _cpp_file): Delete main_file field. + (pch_open): Check pfile->main_file equality. + (make_cpp_file): Drop cpp_reader parm, don't set main_file. + (_cpp_find_file): Adjust. + (_cpp_stack_file): Check pfile->main_file equality. + (struct report_missing_guard_data): Add cpp_reader field. + (report_missing_guard): Check pfile->main_file equality. + (_cpp_report_missing_guards): Adjust. + +2020-11-18 Nathan Sidwell <nathan@acm.org> + + * include/cpplib.h (struct cpp_options): Add module_directives + option. + (NODE_MODULE): New node flag. + (struct cpp_hashnode): Make rid-code a bitfield, increase bits in + flags and swap with type field. + * init.c (post_options): Create module-directive identifier nodes. + * internal.h (struct lexer_state): Add directive_file_token & + n_modules fields. Add module node enumerator. + * lex.c (cpp_maybe_module_directive): New. + (_cpp_lex_token): Call it. + (cpp_output_token): Add '"' around CPP_HEADER_NAME token. + (do_peek_ident, do_peek_module): New. + (cpp_directives_only): Detect module-directive lines. + * macro.c (cpp_get_token_1): Deal with directive_file_token + triggering. + +2020-11-18 Nathan Sidwell <nathan@acm.org> + + * files.c (struct _cpp_file): Add header_unit field. + (_cpp_stack_file): Add header unit support. + (cpp_find_header_unit): New. + * include/cpplib.h (cpp_find_header_unit): Declare. + +2020-11-18 Nathan Sidwell <nathan@acm.org> + + * include/cpplib.h (struct cpp_options): Add modules to + dep-options. + * include/mkdeps.h (deps_add_module_target): Declare. + (deps_add_module_dep): Declare. + * mkdeps.c (class mkdeps): Add modules, module_name, cmi_name, + is_header_unit fields. Adjust cdtors. + (deps_add_module_target, deps_add_module_dep): New. + (make_write): Write module dependencies, if enabled. + +2020-11-17 Nathan Sidwell <nathan@acm.org> + + * include/cpplib.h (struct cpp_callbacks): Add + user_deferred_macro & translate_include. + +2020-11-17 Nathan Sidwell <nathan@acm.org> + + * include/line-map.h (enum lc_reason): Add LC_MODULE. + (MAP_MODULE_P): New. + (line_map_new_raw): Declare. + (linemap_enter_macro): Move declaration from internal.h + (linemap_module_loc, linemap_module_reparent) + (linemap_module_restore): Declare. + (linemap_lookup_macro_indec): Declare. + * internal.h (linemap_enter_macro): Moved to line-map.h. + * line-map.c (linemap_new_raw): New, broken out of ... + (new_linemap): ... here. Call it. + (LAST_SOURCE_LINE_LOCATION): New. + (liemap_module_loc, linemap_module_reparent) + (linemap_module_restore): New. + (linemap_lookup_macro_index): New, broken out of ... + (linemap_macro_map_lookup): ... here. Call it. + (linemap_dump): Add module dump. + +2020-11-17 Nathan Sidwell <nathan@acm.org> + + PR preprocessor/97858 + * mkdeps.c (munge): Drop varadic args, we only ever use one. + +2020-11-13 Joseph Myers <joseph@codesourcery.com> + + * expr.c (cpp_classify_number): Update diagnostic for binary + constants for C. Also diagnose binary constants for + -Wc11-c2x-compat. + * init.c (lang_defaults): Enable binary constants for GNUC2X and + STDC2X. + +2020-11-13 Piotr H. Dabrowski <phd@phd.re> + + PR c++/91318 + * include/cpplib.h: Added cpp_define_unused(), cpp_define_formatted_unused() + * directives.c: Likewise. + +2020-11-12 Joseph Myers <joseph@codesourcery.com> + + * include/cpplib.h (struct cpp_callbacks): Add bool argument to + has_attribute. + (enum cpp_builtin_type): Add BT_HAS_STD_ATTRIBUTE. + * init.c (builtin_array): Add __has_c_attribute. + (cpp_init_special_builtins): Handle BT_HAS_STD_ATTRIBUTE. + * macro.c (_cpp_builtin_macro_text): Handle BT_HAS_STD_ATTRIBUTE. + Update call to has_attribute for BT_HAS_ATTRIBUTE. + * traditional.c (fun_like_macro): Handle BT_HAS_STD_ATTRIBUTE. + +2020-11-12 Nicholas Guriev <guriev-ns@ya.ru> + + PR pch/86674 + * files.c (_cpp_find_file): Use CPP_DL_NOTE not CPP_DL_ERROR in call to + cpp_error. + +2020-11-07 Lewis Hyatt <lhyatt@gmail.com> + + * generated_cpp_wcwidth.h: Regenerated from Unicode 13.0.0 data. + +2020-11-06 Nathan Sidwell <nathan@acm.org> + + * include/cpplib.h (enum class CPP_time_kind): New. + (cpp_get_date): Declare. + * internal.h (struct cpp_reader): Replace source_date_epoch with + time_stamp and time_stamp_kind. + * init.c (cpp_create_reader): Initialize them. + * macro.c (_cpp_builtin_macro_text): Use cpp_get_date. + (cpp_get_date): Broken out from _cpp_builtin_macro_text and + genericized. + +2020-11-03 Nathan Sidwell <nathan@acm.org> + + * lex.c (cpp_peek_token): Do not peek past CPP_PRAGMA. + (_cpp_lex_direct): Handle EOF in pragma when setting need_line, + not when needing a line. + +2020-11-03 Nathan Sidwell <nathan@acm.org> + + * lex.c (_cpp_clean_line): Fix DOS off-by-one error. + +2020-11-03 Nathan Sidwell <nathan@acm.org> + + * init.c (cpp_read_main_file): Use cpp_get_deps result. + +2020-11-03 Nathan Sidwell <nathan@acm.org> + + * include/mkdeps.h: Include cpplib.h + (deps_write): Adjust first parm type. + * mkdeps.c: Include internal.h + (make_write): Adjust first parm type. Check phony option + directly. + (deps_write): Adjust first parm type. + * init.c (cpp_read_main_file): Use get_deps. + * directives.c (cpp_get_deps): Check option before initializing. + +2020-11-02 Nathan Sidwell <nathan@acm.org> + + * internal.h (_cpp_notify_macro_use): Add location parm. + (_cpp_maybe_notify_macro_use): Likewise. + * directives.c (_cpp_do_file_change): Check we've not changed file + when optimizing a rewind. + (do_ifdef): Pass location to _cpp_maybe_notify_macro_use. + (do_ifndef): Likewise. Delete obsolete comment about powerpc. + * expr.c (parse_defined): Pass location to + _cpp_maybe_notify_macro_use. + * macro.c (enter_macro_context): Likewise. + (warn_of_redefinition): Break out helper function. Call it. + (compare_macros): New function broken out of warn_of_redefinition. + (_cpp_new_macro): Zero all fields. + (_cpp_notify_macro_use): Add location parameter. + 2020-10-20 Nathan Sidwell <nathan@acm.org> * lex.c (_cpp_lex_direct): Do not complete EOF processing when diff --git a/libcpp/charset.c b/libcpp/charset.c index 28b81c9c..3e5578b 100644 --- a/libcpp/charset.c +++ b/libcpp/charset.c @@ -638,6 +638,9 @@ init_iconv_desc (cpp_reader *pfile, const char *to, const char *from) char *pair; size_t i; + ret.to = to; + ret.from = from; + if (!strcasecmp (to, from)) { ret.func = convert_no_conversion; diff --git a/libcpp/directives.c b/libcpp/directives.c index f597187..0d09da7 100644 --- a/libcpp/directives.c +++ b/libcpp/directives.c @@ -667,7 +667,8 @@ do_undef (cpp_reader *pfile) pfile->directive_line, 0, "undefining \"%s\"", NODE_NAME (node)); - if (CPP_OPTION (pfile, warn_unused_macros)) + if (node->value.macro + && CPP_OPTION (pfile, warn_unused_macros)) _cpp_warn_if_unused_macro (pfile, node, NULL); _cpp_free_definition (node); @@ -877,7 +878,7 @@ do_include_next (cpp_reader *pfile) /* If this is the primary source file, warn and use the normal search logic. */ - if (cpp_in_primary_file (pfile)) + if (_cpp_in_main_source_file (pfile)) { cpp_error (pfile, CPP_DL_WARNING, "#include_next in primary source file"); @@ -914,12 +915,11 @@ read_flag (cpp_reader *pfile, unsigned int last) /* Subroutine of do_line and do_linemarker. Convert a number in STR, of length LEN, to binary; store it in NUMP, and return false if the number was well-formed, true if not. WRAPPED is set to true if the - number did not fit into 'unsigned long'. */ + number did not fit into 'linenum_type'. */ static bool strtolinenum (const uchar *str, size_t len, linenum_type *nump, bool *wrapped) { linenum_type reg = 0; - linenum_type reg_prev = 0; uchar c; *wrapped = false; @@ -928,11 +928,12 @@ strtolinenum (const uchar *str, size_t len, linenum_type *nump, bool *wrapped) c = *str++; if (!ISDIGIT (c)) return true; + if (reg > ((linenum_type) -1) / 10) + *wrapped = true; reg *= 10; - reg += c - '0'; - if (reg < reg_prev) + if (reg > ((linenum_type) -1) - (c - '0')) *wrapped = true; - reg_prev = reg; + reg += c - '0'; } *nump = reg; return false; @@ -1134,6 +1135,7 @@ _cpp_do_file_change (cpp_reader *pfile, enum lc_reason reason, preprocessed source. */ line_map_ordinary *last = LINEMAPS_LAST_ORDINARY_MAP (pfile->line_table); if (!ORDINARY_MAP_STARTING_LINE_NUMBER (last) + && 0 == filename_cmp (to_file, ORDINARY_MAP_FILE_NAME (last)) && SOURCE_LINE (last, pfile->line_table->highest_line) == 2) { ord_map = last; @@ -1545,7 +1547,7 @@ do_pragma (cpp_reader *pfile) static void do_pragma_once (cpp_reader *pfile) { - if (cpp_in_primary_file (pfile)) + if (_cpp_in_main_source_file (pfile)) cpp_error (pfile, CPP_DL_WARNING, "#pragma once in main file"); check_eol (pfile, false); @@ -1707,7 +1709,7 @@ do_pragma_poison (cpp_reader *pfile) static void do_pragma_system_header (cpp_reader *pfile) { - if (cpp_in_primary_file (pfile)) + if (_cpp_in_main_source_file (pfile)) cpp_error (pfile, CPP_DL_WARNING, "#pragma system_header ignored outside include file"); else @@ -1980,8 +1982,10 @@ do_ifdef (cpp_reader *pfile) if (node) { skip = !_cpp_defined_macro_p (node); + if (!_cpp_maybe_notify_macro_use (pfile, node, pfile->directive_line)) + /* It wasn't a macro after all. */ + skip = true; _cpp_mark_macro_used (node); - _cpp_maybe_notify_macro_use (pfile, node); if (pfile->cb.used) pfile->cb.used (pfile, pfile->directive_line, node); check_eol (pfile, false); @@ -2004,13 +2008,11 @@ do_ifndef (cpp_reader *pfile) if (node) { - /* Do not treat conditional macros as being defined. This is due to - the powerpc port using conditional macros for 'vector', 'bool', - and 'pixel' to act as conditional keywords. This messes up tests - like #ifndef bool. */ skip = _cpp_defined_macro_p (node); + if (!_cpp_maybe_notify_macro_use (pfile, node, pfile->directive_line)) + /* It wasn't a macro after all. */ + skip = false; _cpp_mark_macro_used (node); - _cpp_maybe_notify_macro_use (pfile, node); if (pfile->cb.used) pfile->cb.used (pfile, pfile->directive_line, node); check_eol (pfile, false); @@ -2415,6 +2417,15 @@ cpp_define (cpp_reader *pfile, const char *str) run_directive (pfile, T_DEFINE, buf, count); } +/* Like cpp_define, but does not warn about unused macro. */ +void +cpp_define_unused (cpp_reader *pfile, const char *str) +{ + unsigned char warn_unused_macros = CPP_OPTION (pfile, warn_unused_macros); + CPP_OPTION (pfile, warn_unused_macros) = 0; + cpp_define (pfile, str); + CPP_OPTION (pfile, warn_unused_macros) = warn_unused_macros; +} /* Use to build macros to be run through cpp_define() as described above. @@ -2434,6 +2445,20 @@ cpp_define_formatted (cpp_reader *pfile, const char *fmt, ...) free (ptr); } +/* Like cpp_define_formatted, but does not warn about unused macro. */ +void +cpp_define_formatted_unused (cpp_reader *pfile, const char *fmt, ...) +{ + char *ptr; + + va_list ap; + va_start (ap, fmt); + ptr = xvasprintf (fmt, ap); + va_end (ap); + + cpp_define_unused (pfile, ptr); + free (ptr); +} /* Slight variant of the above for use by initialize_builtins. */ void @@ -2571,11 +2596,25 @@ cpp_set_callbacks (cpp_reader *pfile, cpp_callbacks *cb) pfile->cb = *cb; } +/* The narrow character set identifier. */ +const char * +cpp_get_narrow_charset_name (cpp_reader *pfile) +{ + return pfile->narrow_cset_desc.to; +} + +/* The wide character set identifier. */ +const char * +cpp_get_wide_charset_name (cpp_reader *pfile) +{ + return pfile->wide_cset_desc.to; +} + /* The dependencies structure. (Creates one if it hasn't already been.) */ class mkdeps * cpp_get_deps (cpp_reader *pfile) { - if (!pfile->deps) + if (!pfile->deps && CPP_OPTION (pfile, deps.style) != DEPS_NONE) pfile->deps = deps_init (); return pfile->deps; } diff --git a/libcpp/expr.c b/libcpp/expr.c index 2ae9be0..2ba7726 100644 --- a/libcpp/expr.c +++ b/libcpp/expr.c @@ -812,14 +812,21 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token, if ((result & CPP_N_IMAGINARY) && CPP_PEDANTIC (pfile)) cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0, "imaginary constants are a GCC extension"); - if (radix == 2 - && !CPP_OPTION (pfile, binary_constants) - && CPP_PEDANTIC (pfile)) - cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0, - CPP_OPTION (pfile, cplusplus) - ? N_("binary constants are a C++14 feature " - "or GCC extension") - : N_("binary constants are a GCC extension")); + if (radix == 2) + { + if (!CPP_OPTION (pfile, binary_constants) + && CPP_PEDANTIC (pfile)) + cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0, + CPP_OPTION (pfile, cplusplus) + ? N_("binary constants are a C++14 feature " + "or GCC extension") + : N_("binary constants are a C2X feature " + "or GCC extension")); + else if (CPP_OPTION (pfile, cpp_warn_c11_c2x_compat) > 0) + cpp_warning_with_line (pfile, CPP_W_C11_C2X_COMPAT, + virtual_location, 0, + "binary constants are a C2X feature"); + } if (radix == 10) result |= CPP_N_DECIMAL; @@ -1061,6 +1068,7 @@ parse_defined (cpp_reader *pfile) } } + bool is_defined = false; if (node) { if ((pfile->context != initial_context @@ -1068,9 +1076,11 @@ parse_defined (cpp_reader *pfile) && CPP_OPTION (pfile, warn_expansion_to_defined)) cpp_pedwarning (pfile, CPP_W_EXPANSION_TO_DEFINED, "this use of \"defined\" may not be portable"); - + is_defined = _cpp_defined_macro_p (node); + if (!_cpp_maybe_notify_macro_use (pfile, node, token->src_loc)) + /* It wasn't a macro after all. */ + is_defined = false; _cpp_mark_macro_used (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. */ @@ -1086,7 +1096,7 @@ parse_defined (cpp_reader *pfile) result.unsignedp = false; result.high = 0; result.overflow = false; - result.low = node && _cpp_defined_macro_p (node); + result.low = is_defined; return result; } diff --git a/libcpp/files.c b/libcpp/files.c index 5af4136..301b237 100644 --- a/libcpp/files.c +++ b/libcpp/files.c @@ -103,14 +103,14 @@ struct _cpp_file /* If read() failed before. */ bool dont_read : 1; - /* If this file is the main file. */ - bool main_file : 1; - /* If BUFFER above contains the true contents of the file. */ bool buffer_valid : 1; /* If this file is implicitly preincluded. */ bool implicit_preinclude : 1; + + /* > 0: Known C++ Module header unit, <0: known not. ==0, unknown */ + int header_unit : 2; }; /* A singly-linked list for all searches for a given file name, with @@ -183,7 +183,7 @@ static void open_file_failed (cpp_reader *pfile, _cpp_file *file, int, location_t); static struct cpp_file_hash_entry *search_cache (struct cpp_file_hash_entry *head, const cpp_dir *start_dir); -static _cpp_file *make_cpp_file (cpp_reader *, cpp_dir *, const char *fname); +static _cpp_file *make_cpp_file (cpp_dir *, const char *fname); static void destroy_cpp_file (_cpp_file *); static cpp_dir *make_cpp_dir (cpp_reader *, const char *dir_name, int sysp); static void allocate_file_hash_entries (cpp_reader *pfile); @@ -296,7 +296,7 @@ pch_open_file (cpp_reader *pfile, _cpp_file *file, bool *invalid_pch) for (_cpp_file *f = pfile->all_files; f; f = f->next_file) if (f->implicit_preinclude) continue; - else if (f->main_file) + else if (pfile->main_file == f) break; else return false; @@ -525,7 +525,7 @@ _cpp_find_file (cpp_reader *pfile, const char *fname, cpp_dir *start_dir, if (entry) return entry->u.file; - _cpp_file *file = make_cpp_file (pfile, start_dir, fname); + _cpp_file *file = make_cpp_file (start_dir, fname); file->implicit_preinclude = (kind == _cpp_FFK_PRE_INCLUDE || (pfile->buffer && pfile->buffer->file->implicit_preinclude)); @@ -571,7 +571,7 @@ _cpp_find_file (cpp_reader *pfile, const char *fname, cpp_dir *start_dir, "one or more PCH files were found," " but they were invalid"); if (!cpp_get_options (pfile)->warn_invalid_pch) - cpp_error (pfile, CPP_DL_ERROR, + cpp_error (pfile, CPP_DL_NOTE, "use -Winvalid-pch for more information"); } @@ -862,7 +862,7 @@ has_unique_contents (cpp_reader *pfile, _cpp_file *file, bool import, { /* We already have a buffer but it is not valid, because the file is still stacked. Make a new one. */ - ref_file = make_cpp_file (pfile, f->dir, f->name); + ref_file = make_cpp_file (f->dir, f->name); ref_file->path = f->path; } else @@ -891,9 +891,9 @@ has_unique_contents (cpp_reader *pfile, _cpp_file *file, bool import, } /* Place the file referenced by FILE into a new buffer on the buffer - stack if possible. IMPORT is true if this stacking attempt is - because of a #import directive. Returns true if a buffer is - stacked. Use LOC for any diagnostics. */ + stack if possible. Returns true if a buffer is stacked. Use LOC + for any diagnostics. */ + bool _cpp_stack_file (cpp_reader *pfile, _cpp_file *file, include_type type, location_t loc) @@ -901,39 +901,74 @@ _cpp_stack_file (cpp_reader *pfile, _cpp_file *file, include_type type, if (is_known_idempotent_file (pfile, file, type == IT_IMPORT)) return false; - if (!read_file (pfile, file, loc)) - return false; - - if (!has_unique_contents (pfile, file, type == IT_IMPORT, loc)) - return false; - int sysp = 0; - if (pfile->buffer && file->dir) - sysp = MAX (pfile->buffer->sysp, file->dir->sysp); - - /* Add the file to the dependencies on its first inclusion. */ - if (CPP_OPTION (pfile, deps.style) > (sysp != 0) - && !file->stack_count - && file->path[0] - && !(file->main_file && CPP_OPTION (pfile, deps.ignore_main_file))) - deps_add_dep (pfile->deps, file->path); - - /* Clear buffer_valid since _cpp_clean_line messes it up. */ - file->buffer_valid = false; - file->stack_count++; - - /* Stack the buffer. */ - cpp_buffer *buffer - = cpp_push_buffer (pfile, file->buffer, file->st.st_size, - CPP_OPTION (pfile, preprocessed) - && !CPP_OPTION (pfile, directives_only)); - buffer->file = file; - buffer->sysp = sysp; - buffer->to_free = file->buffer_start; + char *buf = nullptr; - /* Initialize controlling macro state. */ - pfile->mi_valid = true; - pfile->mi_cmacro = 0; + /* Check C++ module include translation. */ + if (!file->header_unit && type < IT_HEADER_HWM + /* Do not include translate include-next. */ + && type != IT_INCLUDE_NEXT + && pfile->cb.translate_include) + buf = (pfile->cb.translate_include + (pfile, pfile->line_table, loc, file->path)); + + if (buf) + { + /* We don't increment the line number at the end of a buffer, + because we don't usually need that location (we're popping an + include file). However in this case we do want to do the + increment. So push a writable buffer of two newlines to acheive + that. */ + static uchar newlines[] = "\n\n"; + cpp_push_buffer (pfile, newlines, 2, true); + + cpp_buffer *buffer + = cpp_push_buffer (pfile, reinterpret_cast<unsigned char *> (buf), + strlen (buf), true); + buffer->to_free = buffer->buf; + + file->header_unit = +1; + _cpp_mark_file_once_only (pfile, file); + } + else + { + /* Not a header unit, and we know it. */ + file->header_unit = -1; + + if (!read_file (pfile, file, loc)) + return false; + + if (!has_unique_contents (pfile, file, type == IT_IMPORT, loc)) + return false; + + if (pfile->buffer && file->dir) + sysp = MAX (pfile->buffer->sysp, file->dir->sysp); + + /* Add the file to the dependencies on its first inclusion. */ + if (CPP_OPTION (pfile, deps.style) > (sysp != 0) + && !file->stack_count + && file->path[0] + && !(pfile->main_file == file + && CPP_OPTION (pfile, deps.ignore_main_file))) + deps_add_dep (pfile->deps, file->path); + + /* Clear buffer_valid since _cpp_clean_line messes it up. */ + file->buffer_valid = false; + file->stack_count++; + + /* Stack the buffer. */ + cpp_buffer *buffer + = cpp_push_buffer (pfile, file->buffer, file->st.st_size, + CPP_OPTION (pfile, preprocessed) + && !CPP_OPTION (pfile, directives_only)); + buffer->file = file; + buffer->sysp = sysp; + buffer->to_free = file->buffer_start; + + /* Initialize controlling macro state. */ + pfile->mi_valid = true; + pfile->mi_cmacro = 0; + } /* In the case of a normal #include, we're now at the start of the line *following* the #include. A separate location_t for this @@ -941,19 +976,30 @@ _cpp_stack_file (cpp_reader *pfile, _cpp_file *file, include_type type, This does not apply if we found a PCH file, we're not a regular include, or we ran out of locations. */ - if (file->pchname == NULL - && type < IT_DIRECTIVE_HWM - && pfile->line_table->highest_location != LINE_MAP_MAX_LOCATION - 1) + bool decrement = (file->pchname == NULL + && type < IT_DIRECTIVE_HWM + && (pfile->line_table->highest_location + != LINE_MAP_MAX_LOCATION - 1)); + if (decrement) pfile->line_table->highest_location--; - /* Add line map and do callbacks. */ - _cpp_do_file_change (pfile, LC_ENTER, file->path, + if (file->header_unit <= 0) + /* Add line map and do callbacks. */ + _cpp_do_file_change (pfile, LC_ENTER, file->path, /* With preamble injection, start on line zero, so the preamble doesn't appear to have been included from line 1. Likewise when starting preprocessed, we expect an initial locating line. */ - type == IT_PRE_MAIN ? 0 : 1, sysp); + type == IT_PRE_MAIN ? 0 : 1, sysp); + else if (decrement) + { + /* Adjust the line back one so we appear on the #include line itself. */ + const line_map_ordinary *map + = LINEMAPS_LAST_ORDINARY_MAP (pfile->line_table); + linenum_type line = SOURCE_LINE (map, pfile->line_table->highest_line); + linemap_line_start (pfile->line_table, line - 1, 0); + } return true; } @@ -1058,6 +1104,64 @@ _cpp_stack_include (cpp_reader *pfile, const char *fname, int angle_brackets, return _cpp_stack_file (pfile, file, type, loc); } +/* NAME is a header file name, find the path we'll use to open it. */ + +const char * +cpp_find_header_unit (cpp_reader *pfile, const char *name, bool angle, + location_t loc) +{ + cpp_dir *dir = search_path_head (pfile, name, angle, IT_INCLUDE); + if (!dir) + return NULL; + + _cpp_file *file = _cpp_find_file (pfile, name, dir, angle, + _cpp_FFK_NORMAL, loc); + if (!file) + return NULL; + + if (file->fd > 0) + { + /* Don't leave it open. */ + close (file->fd); + file->fd = 0; + } + + file->header_unit = +1; + _cpp_mark_file_once_only (pfile, file); + return file->path; +} + +/* Retrofit the just-entered main file asif it was an include. This + will permit correct include_next use, and mark it as a system + header if that's where it resides. We use filesystem-appropriate + prefix matching of the include path to locate the main file. */ +void +cpp_retrofit_as_include (cpp_reader *pfile) +{ + /* We should be the outermost. */ + gcc_assert (!pfile->buffer->prev); + + if (const char *name = pfile->main_file->name) + { + /* Locate name on the include dir path, using a prefix match. */ + size_t name_len = strlen (name); + for (cpp_dir *dir = pfile->quote_include; dir; dir = dir->next) + if (dir->len < name_len + && IS_DIR_SEPARATOR (name[dir->len]) + && !filename_ncmp (name, dir->name, dir->len)) + { + pfile->main_file->dir = dir; + if (dir->sysp) + cpp_make_system_header (pfile, 1, 0); + break; + } + } + + /* Initialize controlling macro state. */ + pfile->mi_valid = true; + pfile->mi_cmacro = 0; +} + /* Could not open FILE. The complication is dependency output. */ static void open_file_failed (cpp_reader *pfile, _cpp_file *file, int angle_brackets, @@ -1112,12 +1216,9 @@ search_cache (struct cpp_file_hash_entry *head, const cpp_dir *start_dir) /* Allocate a new _cpp_file structure. */ static _cpp_file * -make_cpp_file (cpp_reader *pfile, cpp_dir *dir, const char *fname) +make_cpp_file (cpp_dir *dir, const char *fname) { - _cpp_file *file; - - file = XCNEW (_cpp_file); - file->main_file = !pfile->buffer; + _cpp_file *file = XCNEW (_cpp_file); file->fd = -1; file->dir = dir; file->name = xstrdup (fname); @@ -1377,6 +1478,7 @@ cpp_change_file (cpp_reader *pfile, enum lc_reason reason, struct report_missing_guard_data { + cpp_reader *pfile; const char **paths; size_t count; }; @@ -1395,8 +1497,10 @@ report_missing_guard (void **slot, void *d) _cpp_file *file = entry->u.file; /* We don't want MI guard advice for the main file. */ - if (!file->once_only && file->cmacro == NULL - && file->stack_count == 1 && !file->main_file) + if (!file->once_only + && file->cmacro == NULL + && file->stack_count == 1 + && data->pfile->main_file != file) { if (data->paths == NULL) { @@ -1426,6 +1530,7 @@ _cpp_report_missing_guards (cpp_reader *pfile) { struct report_missing_guard_data data; + data.pfile = pfile; data.paths = NULL; data.count = htab_elements (pfile->file_hash); htab_traverse (pfile->file_hash, report_missing_guard, &data); diff --git a/libcpp/generated_cpp_wcwidth.h b/libcpp/generated_cpp_wcwidth.h index ec8b73d..abe1be3 100644 --- a/libcpp/generated_cpp_wcwidth.h +++ b/libcpp/generated_cpp_wcwidth.h @@ -1,5 +1,5 @@ /* Generated by contrib/unicode/gen_wcwidth.py, with the help of glibc's - utf8_gen.py, using version 12.1.0 of the Unicode standard. */ + utf8_gen.py, using version 13.0.0 of the Unicode standard. */ static const cppchar_t wcwidth_range_ends[] = { 0x2ff, 0x36f, 0x482, 0x489, 0x590, 0x5bd, 0x5be, 0x5bf, @@ -16,50 +16,50 @@ static const cppchar_t wcwidth_range_ends[] = { 0xa50, 0xa51, 0xa6f, 0xa71, 0xa74, 0xa75, 0xa80, 0xa82, 0xabb, 0xabc, 0xac0, 0xac5, 0xac6, 0xac8, 0xacc, 0xacd, 0xae1, 0xae3, 0xaf9, 0xaff, 0xb00, 0xb01, 0xb3b, 0xb3c, - 0xb3e, 0xb3f, 0xb40, 0xb44, 0xb4c, 0xb4d, 0xb55, 0xb56, + 0xb3e, 0xb3f, 0xb40, 0xb44, 0xb4c, 0xb4d, 0xb54, 0xb56, 0xb61, 0xb63, 0xb81, 0xb82, 0xbbf, 0xbc0, 0xbcc, 0xbcd, 0xbff, 0xc00, 0xc03, 0xc04, 0xc3d, 0xc40, 0xc45, 0xc48, 0xc49, 0xc4d, 0xc54, 0xc56, 0xc61, 0xc63, 0xc80, 0xc81, 0xcbb, 0xcbc, 0xcbe, 0xcbf, 0xcc5, 0xcc6, 0xccb, 0xccd, 0xce1, 0xce3, 0xcff, 0xd01, 0xd3a, 0xd3c, 0xd40, 0xd44, - 0xd4c, 0xd4d, 0xd61, 0xd63, 0xdc9, 0xdca, 0xdd1, 0xdd4, - 0xdd5, 0xdd6, 0xe30, 0xe31, 0xe33, 0xe3a, 0xe46, 0xe4e, - 0xeb0, 0xeb1, 0xeb3, 0xebc, 0xec7, 0xecd, 0xf17, 0xf19, - 0xf34, 0xf35, 0xf36, 0xf37, 0xf38, 0xf39, 0xf70, 0xf7e, - 0xf7f, 0xf84, 0xf85, 0xf87, 0xf8c, 0xf97, 0xf98, 0xfbc, - 0xfc5, 0xfc6, 0x102c, 0x1030, 0x1031, 0x1037, 0x1038, 0x103a, - 0x103c, 0x103e, 0x1057, 0x1059, 0x105d, 0x1060, 0x1070, 0x1074, - 0x1081, 0x1082, 0x1084, 0x1086, 0x108c, 0x108d, 0x109c, 0x109d, - 0x10ff, 0x115f, 0x11ff, 0x135c, 0x135f, 0x1711, 0x1714, 0x1731, - 0x1734, 0x1751, 0x1753, 0x1771, 0x1773, 0x17b3, 0x17b5, 0x17b6, - 0x17bd, 0x17c5, 0x17c6, 0x17c8, 0x17d3, 0x17dc, 0x17dd, 0x180a, - 0x180e, 0x1884, 0x1886, 0x18a8, 0x18a9, 0x191f, 0x1922, 0x1926, - 0x1928, 0x1931, 0x1932, 0x1938, 0x193b, 0x1a16, 0x1a18, 0x1a1a, - 0x1a1b, 0x1a55, 0x1a56, 0x1a57, 0x1a5e, 0x1a5f, 0x1a60, 0x1a61, - 0x1a62, 0x1a64, 0x1a6c, 0x1a72, 0x1a7c, 0x1a7e, 0x1a7f, 0x1aaf, - 0x1abe, 0x1aff, 0x1b03, 0x1b33, 0x1b34, 0x1b35, 0x1b3a, 0x1b3b, - 0x1b3c, 0x1b41, 0x1b42, 0x1b6a, 0x1b73, 0x1b7f, 0x1b81, 0x1ba1, - 0x1ba5, 0x1ba7, 0x1ba9, 0x1baa, 0x1bad, 0x1be5, 0x1be6, 0x1be7, - 0x1be9, 0x1bec, 0x1bed, 0x1bee, 0x1bf1, 0x1c2b, 0x1c33, 0x1c35, - 0x1c37, 0x1ccf, 0x1cd2, 0x1cd3, 0x1ce0, 0x1ce1, 0x1ce8, 0x1cec, - 0x1ced, 0x1cf3, 0x1cf4, 0x1cf7, 0x1cf9, 0x1dbf, 0x1df9, 0x1dfa, - 0x1dff, 0x200a, 0x200f, 0x2029, 0x202e, 0x205f, 0x2064, 0x2065, - 0x206f, 0x20cf, 0x20f0, 0x2319, 0x231b, 0x2328, 0x232a, 0x23e8, - 0x23ec, 0x23ef, 0x23f0, 0x23f2, 0x23f3, 0x25fc, 0x25fe, 0x2613, - 0x2615, 0x2647, 0x2653, 0x267e, 0x267f, 0x2692, 0x2693, 0x26a0, - 0x26a1, 0x26a9, 0x26ab, 0x26bc, 0x26be, 0x26c3, 0x26c5, 0x26cd, - 0x26ce, 0x26d3, 0x26d4, 0x26e9, 0x26ea, 0x26f1, 0x26f3, 0x26f4, - 0x26f5, 0x26f9, 0x26fa, 0x26fc, 0x26fd, 0x2704, 0x2705, 0x2709, - 0x270b, 0x2727, 0x2728, 0x274b, 0x274c, 0x274d, 0x274e, 0x2752, - 0x2755, 0x2756, 0x2757, 0x2794, 0x2797, 0x27af, 0x27b0, 0x27be, - 0x27bf, 0x2b1a, 0x2b1c, 0x2b4f, 0x2b50, 0x2b54, 0x2b55, 0x2cee, - 0x2cf1, 0x2d7e, 0x2d7f, 0x2ddf, 0x2dff, 0x2e7f, 0x2e99, 0x2e9a, - 0x2ef3, 0x2eff, 0x2fd5, 0x2fef, 0x2ffb, 0x2fff, 0x3029, 0x302d, - 0x303e, 0x3040, 0x3096, 0x3098, 0x309a, 0x30ff, 0x3104, 0x312f, - 0x3130, 0x318e, 0x318f, 0x31ba, 0x31bf, 0x31e3, 0x31ef, 0x321e, - 0x321f, 0x4db5, 0x4dbf, 0x9fef, 0x9fff, 0xa48c, 0xa48f, 0xa4c6, - 0xa66e, 0xa672, 0xa673, 0xa67d, 0xa69d, 0xa69f, 0xa6ef, 0xa6f1, - 0xa801, 0xa802, 0xa805, 0xa806, 0xa80a, 0xa80b, 0xa824, 0xa826, + 0xd4c, 0xd4d, 0xd61, 0xd63, 0xd80, 0xd81, 0xdc9, 0xdca, + 0xdd1, 0xdd4, 0xdd5, 0xdd6, 0xe30, 0xe31, 0xe33, 0xe3a, + 0xe46, 0xe4e, 0xeb0, 0xeb1, 0xeb3, 0xebc, 0xec7, 0xecd, + 0xf17, 0xf19, 0xf34, 0xf35, 0xf36, 0xf37, 0xf38, 0xf39, + 0xf70, 0xf7e, 0xf7f, 0xf84, 0xf85, 0xf87, 0xf8c, 0xf97, + 0xf98, 0xfbc, 0xfc5, 0xfc6, 0x102c, 0x1030, 0x1031, 0x1037, + 0x1038, 0x103a, 0x103c, 0x103e, 0x1057, 0x1059, 0x105d, 0x1060, + 0x1070, 0x1074, 0x1081, 0x1082, 0x1084, 0x1086, 0x108c, 0x108d, + 0x109c, 0x109d, 0x10ff, 0x115f, 0x11ff, 0x135c, 0x135f, 0x1711, + 0x1714, 0x1731, 0x1734, 0x1751, 0x1753, 0x1771, 0x1773, 0x17b3, + 0x17b5, 0x17b6, 0x17bd, 0x17c5, 0x17c6, 0x17c8, 0x17d3, 0x17dc, + 0x17dd, 0x180a, 0x180e, 0x1884, 0x1886, 0x18a8, 0x18a9, 0x191f, + 0x1922, 0x1926, 0x1928, 0x1931, 0x1932, 0x1938, 0x193b, 0x1a16, + 0x1a18, 0x1a1a, 0x1a1b, 0x1a55, 0x1a56, 0x1a57, 0x1a5e, 0x1a5f, + 0x1a60, 0x1a61, 0x1a62, 0x1a64, 0x1a6c, 0x1a72, 0x1a7c, 0x1a7e, + 0x1a7f, 0x1aaf, 0x1ac0, 0x1aff, 0x1b03, 0x1b33, 0x1b34, 0x1b35, + 0x1b3a, 0x1b3b, 0x1b3c, 0x1b41, 0x1b42, 0x1b6a, 0x1b73, 0x1b7f, + 0x1b81, 0x1ba1, 0x1ba5, 0x1ba7, 0x1ba9, 0x1baa, 0x1bad, 0x1be5, + 0x1be6, 0x1be7, 0x1be9, 0x1bec, 0x1bed, 0x1bee, 0x1bf1, 0x1c2b, + 0x1c33, 0x1c35, 0x1c37, 0x1ccf, 0x1cd2, 0x1cd3, 0x1ce0, 0x1ce1, + 0x1ce8, 0x1cec, 0x1ced, 0x1cf3, 0x1cf4, 0x1cf7, 0x1cf9, 0x1dbf, + 0x1df9, 0x1dfa, 0x1dff, 0x200a, 0x200f, 0x2029, 0x202e, 0x205f, + 0x2064, 0x2065, 0x206f, 0x20cf, 0x20f0, 0x2319, 0x231b, 0x2328, + 0x232a, 0x23e8, 0x23ec, 0x23ef, 0x23f0, 0x23f2, 0x23f3, 0x25fc, + 0x25fe, 0x2613, 0x2615, 0x2647, 0x2653, 0x267e, 0x267f, 0x2692, + 0x2693, 0x26a0, 0x26a1, 0x26a9, 0x26ab, 0x26bc, 0x26be, 0x26c3, + 0x26c5, 0x26cd, 0x26ce, 0x26d3, 0x26d4, 0x26e9, 0x26ea, 0x26f1, + 0x26f3, 0x26f4, 0x26f5, 0x26f9, 0x26fa, 0x26fc, 0x26fd, 0x2704, + 0x2705, 0x2709, 0x270b, 0x2727, 0x2728, 0x274b, 0x274c, 0x274d, + 0x274e, 0x2752, 0x2755, 0x2756, 0x2757, 0x2794, 0x2797, 0x27af, + 0x27b0, 0x27be, 0x27bf, 0x2b1a, 0x2b1c, 0x2b4f, 0x2b50, 0x2b54, + 0x2b55, 0x2cee, 0x2cf1, 0x2d7e, 0x2d7f, 0x2ddf, 0x2dff, 0x2e7f, + 0x2e99, 0x2e9a, 0x2ef3, 0x2eff, 0x2fd5, 0x2fef, 0x2ffb, 0x2fff, + 0x3029, 0x302d, 0x303e, 0x3040, 0x3096, 0x3098, 0x309a, 0x30ff, + 0x3104, 0x312f, 0x3130, 0x318e, 0x318f, 0x31e3, 0x31ef, 0x321e, + 0x321f, 0x9ffc, 0x9fff, 0xa48c, 0xa48f, 0xa4c6, 0xa66e, 0xa672, + 0xa673, 0xa67d, 0xa69d, 0xa69f, 0xa6ef, 0xa6f1, 0xa801, 0xa802, + 0xa805, 0xa806, 0xa80a, 0xa80b, 0xa824, 0xa826, 0xa82b, 0xa82c, 0xa8c3, 0xa8c5, 0xa8df, 0xa8f1, 0xa8fe, 0xa8ff, 0xa925, 0xa92d, 0xa946, 0xa951, 0xa95f, 0xa97c, 0xa97f, 0xa982, 0xa9b2, 0xa9b3, 0xa9b5, 0xa9b9, 0xa9bb, 0xa9bd, 0xa9e4, 0xa9e5, 0xaa28, 0xaa2e, @@ -67,15 +67,16 @@ static const cppchar_t wcwidth_range_ends[] = { 0xaa7b, 0xaa7c, 0xaaaf, 0xaab0, 0xaab1, 0xaab4, 0xaab6, 0xaab8, 0xaabd, 0xaabf, 0xaac0, 0xaac1, 0xaaeb, 0xaaed, 0xaaf5, 0xaaf6, 0xabe4, 0xabe5, 0xabe7, 0xabe8, 0xabec, 0xabed, 0xabff, 0xd7a3, - 0xf8ff, 0xfa6d, 0xfa6f, 0xfad9, 0xfb1d, 0xfb1e, 0xfdff, 0xfe0f, - 0xfe19, 0xfe1f, 0xfe2f, 0xfe52, 0xfe53, 0xfe66, 0xfe67, 0xfe6b, - 0xfefe, 0xfeff, 0xff00, 0xff60, 0xffdf, 0xffe6, 0xfff8, 0xfffb, - 0x101fc, 0x101fd, 0x102df, 0x102e0, 0x10375, 0x1037a, 0x10a00, 0x10a03, - 0x10a04, 0x10a06, 0x10a0b, 0x10a0f, 0x10a37, 0x10a3a, 0x10a3e, 0x10a3f, - 0x10ae4, 0x10ae6, 0x10d23, 0x10d27, 0x10f45, 0x10f50, 0x11000, 0x11001, - 0x11037, 0x11046, 0x1107e, 0x11081, 0x110b2, 0x110b6, 0x110b8, 0x110ba, - 0x110ff, 0x11102, 0x11126, 0x1112b, 0x1112c, 0x11134, 0x11172, 0x11173, - 0x1117f, 0x11181, 0x111b5, 0x111be, 0x111c8, 0x111cc, 0x1122e, 0x11231, + 0xd7af, 0xd7c6, 0xd7ca, 0xd7fb, 0xf8ff, 0xfa6d, 0xfa6f, 0xfad9, + 0xfb1d, 0xfb1e, 0xfdff, 0xfe0f, 0xfe19, 0xfe1f, 0xfe2f, 0xfe52, + 0xfe53, 0xfe66, 0xfe67, 0xfe6b, 0xfefe, 0xfeff, 0xff00, 0xff60, + 0xffdf, 0xffe6, 0xfff8, 0xfffb, 0x101fc, 0x101fd, 0x102df, 0x102e0, + 0x10375, 0x1037a, 0x10a00, 0x10a03, 0x10a04, 0x10a06, 0x10a0b, 0x10a0f, + 0x10a37, 0x10a3a, 0x10a3e, 0x10a3f, 0x10ae4, 0x10ae6, 0x10d23, 0x10d27, + 0x10eaa, 0x10eac, 0x10f45, 0x10f50, 0x11000, 0x11001, 0x11037, 0x11046, + 0x1107e, 0x11081, 0x110b2, 0x110b6, 0x110b8, 0x110ba, 0x110ff, 0x11102, + 0x11126, 0x1112b, 0x1112c, 0x11134, 0x11172, 0x11173, 0x1117f, 0x11181, + 0x111b5, 0x111be, 0x111c8, 0x111cc, 0x111ce, 0x111cf, 0x1122e, 0x11231, 0x11233, 0x11234, 0x11235, 0x11237, 0x1123d, 0x1123e, 0x112de, 0x112df, 0x112e2, 0x112ea, 0x112ff, 0x11301, 0x1133a, 0x1133c, 0x1133f, 0x11340, 0x11365, 0x1136c, 0x1136f, 0x11374, 0x11437, 0x1143f, 0x11441, 0x11444, @@ -84,35 +85,38 @@ static const cppchar_t wcwidth_range_ends[] = { 0x115be, 0x115c0, 0x115db, 0x115dd, 0x11632, 0x1163a, 0x1163c, 0x1163d, 0x1163e, 0x11640, 0x116aa, 0x116ab, 0x116ac, 0x116ad, 0x116af, 0x116b5, 0x116b6, 0x116b7, 0x1171c, 0x1171f, 0x11721, 0x11725, 0x11726, 0x1172b, - 0x1182e, 0x11837, 0x11838, 0x1183a, 0x119d3, 0x119d7, 0x119d9, 0x119db, - 0x119df, 0x119e0, 0x11a00, 0x11a0a, 0x11a32, 0x11a38, 0x11a3a, 0x11a3e, - 0x11a46, 0x11a47, 0x11a50, 0x11a56, 0x11a58, 0x11a5b, 0x11a89, 0x11a96, - 0x11a97, 0x11a99, 0x11c2f, 0x11c36, 0x11c37, 0x11c3d, 0x11c3e, 0x11c3f, - 0x11c91, 0x11ca7, 0x11ca9, 0x11cb0, 0x11cb1, 0x11cb3, 0x11cb4, 0x11cb6, - 0x11d30, 0x11d36, 0x11d39, 0x11d3a, 0x11d3b, 0x11d3d, 0x11d3e, 0x11d45, - 0x11d46, 0x11d47, 0x11d8f, 0x11d91, 0x11d94, 0x11d95, 0x11d96, 0x11d97, - 0x11ef2, 0x11ef4, 0x1342f, 0x13438, 0x16aef, 0x16af4, 0x16b2f, 0x16b36, - 0x16f4e, 0x16f4f, 0x16f8e, 0x16f92, 0x16fdf, 0x16fe3, 0x16fff, 0x187f7, - 0x187ff, 0x18af2, 0x1afff, 0x1b11e, 0x1b14f, 0x1b152, 0x1b163, 0x1b167, - 0x1b16f, 0x1b2fb, 0x1bc9c, 0x1bc9e, 0x1bc9f, 0x1bca3, 0x1d166, 0x1d169, - 0x1d172, 0x1d182, 0x1d184, 0x1d18b, 0x1d1a9, 0x1d1ad, 0x1d241, 0x1d244, - 0x1d9ff, 0x1da36, 0x1da3a, 0x1da6c, 0x1da74, 0x1da75, 0x1da83, 0x1da84, - 0x1da9a, 0x1da9f, 0x1daa0, 0x1daaf, 0x1dfff, 0x1e006, 0x1e007, 0x1e018, - 0x1e01a, 0x1e021, 0x1e022, 0x1e024, 0x1e025, 0x1e02a, 0x1e12f, 0x1e136, - 0x1e2eb, 0x1e2ef, 0x1e8cf, 0x1e8d6, 0x1e943, 0x1e94a, 0x1f003, 0x1f004, - 0x1f0ce, 0x1f0cf, 0x1f18d, 0x1f18e, 0x1f190, 0x1f19a, 0x1f1ff, 0x1f202, - 0x1f20f, 0x1f23b, 0x1f23f, 0x1f248, 0x1f24f, 0x1f251, 0x1f25f, 0x1f265, - 0x1f2ff, 0x1f320, 0x1f32c, 0x1f335, 0x1f336, 0x1f37c, 0x1f37d, 0x1f393, - 0x1f39f, 0x1f3ca, 0x1f3ce, 0x1f3d3, 0x1f3df, 0x1f3f0, 0x1f3f3, 0x1f3f4, - 0x1f3f7, 0x1f43e, 0x1f43f, 0x1f440, 0x1f441, 0x1f4fc, 0x1f4fe, 0x1f53d, - 0x1f54a, 0x1f54e, 0x1f54f, 0x1f567, 0x1f579, 0x1f57a, 0x1f594, 0x1f596, - 0x1f5a3, 0x1f5a4, 0x1f5fa, 0x1f64f, 0x1f67f, 0x1f6c5, 0x1f6cb, 0x1f6cc, - 0x1f6cf, 0x1f6d2, 0x1f6d4, 0x1f6d5, 0x1f6ea, 0x1f6ec, 0x1f6f3, 0x1f6fa, - 0x1f7df, 0x1f7eb, 0x1f90c, 0x1f971, 0x1f972, 0x1f976, 0x1f979, 0x1f9a2, - 0x1f9a4, 0x1f9aa, 0x1f9ad, 0x1f9ca, 0x1f9cc, 0x1f9ff, 0x1fa6f, 0x1fa73, - 0x1fa77, 0x1fa7a, 0x1fa7f, 0x1fa82, 0x1fa8f, 0x1fa95, 0x1ffff, 0x2a6d6, - 0x2a6ff, 0x2b734, 0x2b73f, 0x2b81d, 0x2b81f, 0x2cea1, 0x2ceaf, 0x2ebe0, - 0x2f7ff, 0x2fa1d, 0xe0000, 0xe0001, 0xe001f, 0xe007f, 0xe00ff, 0xe01ef, + 0x1182e, 0x11837, 0x11838, 0x1183a, 0x1193a, 0x1193c, 0x1193d, 0x1193e, + 0x11942, 0x11943, 0x119d3, 0x119d7, 0x119d9, 0x119db, 0x119df, 0x119e0, + 0x11a00, 0x11a0a, 0x11a32, 0x11a38, 0x11a3a, 0x11a3e, 0x11a46, 0x11a47, + 0x11a50, 0x11a56, 0x11a58, 0x11a5b, 0x11a89, 0x11a96, 0x11a97, 0x11a99, + 0x11c2f, 0x11c36, 0x11c37, 0x11c3d, 0x11c3e, 0x11c3f, 0x11c91, 0x11ca7, + 0x11ca9, 0x11cb0, 0x11cb1, 0x11cb3, 0x11cb4, 0x11cb6, 0x11d30, 0x11d36, + 0x11d39, 0x11d3a, 0x11d3b, 0x11d3d, 0x11d3e, 0x11d45, 0x11d46, 0x11d47, + 0x11d8f, 0x11d91, 0x11d94, 0x11d95, 0x11d96, 0x11d97, 0x11ef2, 0x11ef4, + 0x1342f, 0x13438, 0x16aef, 0x16af4, 0x16b2f, 0x16b36, 0x16f4e, 0x16f4f, + 0x16f8e, 0x16f92, 0x16fdf, 0x16fe3, 0x16fe4, 0x16fef, 0x16ff1, 0x16fff, + 0x187f7, 0x187ff, 0x18cd5, 0x18cff, 0x18d08, 0x1afff, 0x1b11e, 0x1b14f, + 0x1b152, 0x1b163, 0x1b167, 0x1b16f, 0x1b2fb, 0x1bc9c, 0x1bc9e, 0x1bc9f, + 0x1bca3, 0x1d166, 0x1d169, 0x1d172, 0x1d182, 0x1d184, 0x1d18b, 0x1d1a9, + 0x1d1ad, 0x1d241, 0x1d244, 0x1d9ff, 0x1da36, 0x1da3a, 0x1da6c, 0x1da74, + 0x1da75, 0x1da83, 0x1da84, 0x1da9a, 0x1da9f, 0x1daa0, 0x1daaf, 0x1dfff, + 0x1e006, 0x1e007, 0x1e018, 0x1e01a, 0x1e021, 0x1e022, 0x1e024, 0x1e025, + 0x1e02a, 0x1e12f, 0x1e136, 0x1e2eb, 0x1e2ef, 0x1e8cf, 0x1e8d6, 0x1e943, + 0x1e94a, 0x1f003, 0x1f004, 0x1f0ce, 0x1f0cf, 0x1f18d, 0x1f18e, 0x1f190, + 0x1f19a, 0x1f1ff, 0x1f202, 0x1f20f, 0x1f23b, 0x1f23f, 0x1f248, 0x1f24f, + 0x1f251, 0x1f25f, 0x1f265, 0x1f2ff, 0x1f320, 0x1f32c, 0x1f335, 0x1f336, + 0x1f37c, 0x1f37d, 0x1f393, 0x1f39f, 0x1f3ca, 0x1f3ce, 0x1f3d3, 0x1f3df, + 0x1f3f0, 0x1f3f3, 0x1f3f4, 0x1f3f7, 0x1f43e, 0x1f43f, 0x1f440, 0x1f441, + 0x1f4fc, 0x1f4fe, 0x1f53d, 0x1f54a, 0x1f54e, 0x1f54f, 0x1f567, 0x1f579, + 0x1f57a, 0x1f594, 0x1f596, 0x1f5a3, 0x1f5a4, 0x1f5fa, 0x1f64f, 0x1f67f, + 0x1f6c5, 0x1f6cb, 0x1f6cc, 0x1f6cf, 0x1f6d2, 0x1f6d4, 0x1f6d7, 0x1f6ea, + 0x1f6ec, 0x1f6f3, 0x1f6fc, 0x1f7df, 0x1f7eb, 0x1f90b, 0x1f93a, 0x1f93b, + 0x1f945, 0x1f946, 0x1f978, 0x1f979, 0x1f9cb, 0x1f9cc, 0x1f9ff, 0x1fa6f, + 0x1fa74, 0x1fa77, 0x1fa7a, 0x1fa7f, 0x1fa86, 0x1fa8f, 0x1faa8, 0x1faaf, + 0x1fab6, 0x1fabf, 0x1fac2, 0x1facf, 0x1fad6, 0x1ffff, 0x2a6dd, 0x2a6ff, + 0x2b734, 0x2b73f, 0x2b81d, 0x2b81f, 0x2cea1, 0x2ceaf, 0x2ebe0, 0x2f7ff, + 0x2fa1d, 0x2ffff, 0x3134a, 0xe0000, 0xe0001, 0xe001f, 0xe007f, 0xe00ff, + 0xe01ef, }; static const unsigned char wcwidth_widths[] = { @@ -125,20 +129,20 @@ static const unsigned char wcwidth_widths[] = { 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, - 0, 1, 0, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, + 0, 1, 0, 1, 0, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, - 0, 1, 0, 1, 0, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 0, 2, 1, 2, 1, 0, 2, 1, 2, - 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 0, 1, 0, 1, 0, 1, 0, + 2, 1, 0, 1, 0, 1, 0, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 0, 2, 1, 2, 1, 0, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 1, 2, 1, 2, 1, 0, 1, 0, - 2, 1, 0, 2, 1, 2, 1, 2, 1, 0, 1, 2, 1, 2, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 1, 0, 1, 0, 1, 2, 1, 2, + 1, 0, 1, 0, 2, 1, 0, 2, 1, 2, 1, 2, 1, 0, 1, 2, 1, 2, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, @@ -146,11 +150,13 @@ static const unsigned char wcwidth_widths[] = { 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, - 1, 0, 1, 0, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 0, 1, 0, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, - 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, - 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, - 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, - 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 0, 1, 2, 1, + 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, + 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, + 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, + 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, + 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 0, 1, 0, 1, + 0, }; diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h index 8e39886..50d28dc 100644 --- a/libcpp/include/cpplib.h +++ b/libcpp/include/cpplib.h @@ -308,6 +308,15 @@ enum cpp_normalize_level { normalized_none }; +enum cpp_main_search +{ + CMS_none, /* A regular source file. */ + CMS_header, /* Is a directly-specified header file (eg PCH or + header-unit). */ + CMS_user, /* Search the user INCLUDE path. */ + CMS_system, /* Search the system INCLUDE path. */ +}; + /* This structure is nested inside struct cpp_reader, and carries all the options visible to the command line. */ struct cpp_options @@ -487,6 +496,9 @@ struct cpp_options /* Nonzero for the '::' token. */ unsigned char scope; + /* Nonzero means tokenize C++20 module directives. */ + unsigned char module_directives; + /* Holds the name of the target (execution) character set. */ const char *narrow_charset; @@ -528,6 +540,9 @@ struct cpp_options one. */ bool phony_targets; + /* Generate dependency info for modules. */ + bool modules; + /* If true, no dependency is generated on the main file. */ bool ignore_main_file; @@ -560,6 +575,8 @@ struct cpp_options /* The maximum depth of the nested #include. */ unsigned int max_include_depth; + + cpp_main_search main_search : 8; }; /* Diagnostic levels. To get a diagnostic without associating a @@ -672,7 +689,7 @@ struct cpp_callbacks void (*used) (cpp_reader *, location_t, cpp_hashnode *); /* Callback to identify whether an attribute exists. */ - int (*has_attribute) (cpp_reader *); + int (*has_attribute) (cpp_reader *, bool); /* Callback to determine whether a built-in function is recognized. */ int (*has_builtin) (cpp_reader *); @@ -680,6 +697,9 @@ struct cpp_callbacks /* Callback that can change a user lazy into normal macro. */ void (*user_lazy_macro) (cpp_reader *, cpp_macro *, unsigned); + /* Callback to handle deferred cpp_macros. */ + cpp_macro *(*user_deferred_macro) (cpp_reader *, location_t, cpp_hashnode *); + /* Callback to parse SOURCE_DATE_EPOCH from environment. */ time_t (*get_source_date_epoch) (cpp_reader *); @@ -698,6 +718,11 @@ struct cpp_callbacks /* Callback for filename remapping in __FILE__ and __BASE_FILE__ macro expansions. */ const char *(*remap_filename) (const char*); + + /* Maybe translate a #include into something else. Return a + cpp_buffer containing the translation if translating. */ + char *(*translate_include) (cpp_reader *, line_maps *, location_t, + const char *path); }; #ifdef VMS @@ -801,7 +826,10 @@ struct GTY(()) cpp_macro { tokens. */ unsigned int extra_tokens : 1; - /* 1 bits spare (32-bit). 33 on 64-bit target. */ + /* Imported C++20 macro (from a header unit). */ + unsigned int imported_p : 1; + + /* 0 bits spare (32-bit). 32 on 64-bit target. */ union cpp_exp_u { @@ -831,6 +859,7 @@ struct GTY(()) cpp_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. */ +#define NODE_MODULE (1 << 8) /* C++-20 module-related name. */ /* Different flavors of hash node. */ enum node_type @@ -857,6 +886,7 @@ enum cpp_builtin_type BT_TIMESTAMP, /* `__TIMESTAMP__' */ BT_COUNTER, /* `__COUNTER__' */ BT_HAS_ATTRIBUTE, /* `__has_attribute(x)' */ + BT_HAS_STD_ATTRIBUTE, /* `__has_c_attribute(x)' */ BT_HAS_BUILTIN, /* `__has_builtin(x)' */ BT_HAS_INCLUDE, /* `__has_include(x)' */ BT_HAS_INCLUDE_NEXT /* `__has_include_next(x)' */ @@ -874,7 +904,7 @@ enum cpp_builtin_type union GTY(()) _cpp_hashnode_value { /* Assert (maybe NULL) */ cpp_macro * GTY((tag ("NT_VOID"))) answers; - /* Macro (never NULL) */ + /* Macro (maybe NULL) */ cpp_macro * GTY((tag ("NT_USER_MACRO"))) macro; /* Code for a builtin macro. */ enum cpp_builtin_type GTY ((tag ("NT_BUILTIN_MACRO"))) builtin; @@ -888,11 +918,17 @@ struct GTY(()) cpp_hashnode { unsigned int directive_index : 7; /* If is_directive, then index into directive table. Otherwise, a NODE_OPERATOR. */ - unsigned char rid_code; /* Rid code - for front ends. */ + unsigned int rid_code : 8; /* Rid code - for front ends. */ + unsigned int flags : 9; /* 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). */ + /* 5 bits spare. */ + + /* The deferred cookie is applicable to NT_USER_MACRO or NT_VOID. + The latter for when a macro had a prevailing undef. + On a 64-bit system there would be 32-bits of padding to the value + field. So placing the deferred index here is not costly. */ + unsigned deferred; /* Deferred cookie */ union _cpp_hashnode_value GTY ((desc ("%1.type"))) value; }; @@ -971,6 +1007,14 @@ extern cpp_callbacks *cpp_get_callbacks (cpp_reader *) ATTRIBUTE_PURE; extern void cpp_set_callbacks (cpp_reader *, cpp_callbacks *); extern class mkdeps *cpp_get_deps (cpp_reader *) ATTRIBUTE_PURE; +extern const char *cpp_find_header_unit (cpp_reader *, const char *file, + bool angle_p, location_t); + +/* Call these to get name data about the various compile-time + charsets. */ +extern const char *cpp_get_narrow_charset_name (cpp_reader *) ATTRIBUTE_PURE; +extern const char *cpp_get_wide_charset_name (cpp_reader *) ATTRIBUTE_PURE; + /* This function reads the file, but does not start preprocessing. It returns the name of the original file; this is the same as the input file, except for preprocessed input. This will generate at @@ -978,6 +1022,10 @@ extern class mkdeps *cpp_get_deps (cpp_reader *) ATTRIBUTE_PURE; too. If there was an error opening the file, it returns NULL. */ extern const char *cpp_read_main_file (cpp_reader *, const char *, bool injecting = false); +extern location_t cpp_main_loc (const cpp_reader *); + +/* Adjust for the main file to be an include. */ +extern void cpp_retrofit_as_include (cpp_reader *); /* Set up built-ins with special behavior. Use cpp_init_builtins() instead unless your know what you are doing. */ @@ -1027,6 +1075,18 @@ inline bool cpp_macro_p (const cpp_hashnode *node) { return node->type & NT_MACRO_MASK; } +inline cpp_macro *cpp_set_deferred_macro (cpp_hashnode *node, + cpp_macro *forced = NULL) +{ + cpp_macro *old = node->value.macro; + + node->value.macro = forced; + node->type = NT_USER_MACRO; + node->flags &= ~NODE_USED; + + return old; +} +cpp_macro *cpp_get_deferred_macro (cpp_reader *, cpp_hashnode *, location_t); /* Returns true if NODE is a function-like user macro. */ inline bool cpp_fun_like_macro_p (cpp_hashnode *node) @@ -1034,12 +1094,23 @@ 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 *); +extern const unsigned char *cpp_macro_definition (cpp_reader *, cpp_hashnode *); +extern const unsigned char *cpp_macro_definition (cpp_reader *, cpp_hashnode *, + const cpp_macro *); inline location_t cpp_macro_definition_location (cpp_hashnode *node) { - return node->value.macro->line; + const cpp_macro *macro = node->value.macro; + return macro ? macro->line : 0; } +/* Return an idempotent time stamp (possibly from SOURCE_DATE_EPOCH). */ +enum class CPP_time_kind +{ + FIXED = -1, /* Fixed time via source epoch. */ + DYNAMIC = -2, /* Dynamic via time(2). */ + UNKNOWN = -3 /* Wibbly wobbly, timey wimey. */ +}; +extern CPP_time_kind cpp_get_date (cpp_reader *, time_t *); + extern void _cpp_backup_tokens (cpp_reader *, unsigned int); extern const cpp_token *cpp_peek_token (cpp_reader *, int); @@ -1066,8 +1137,12 @@ extern cppchar_t cpp_host_to_exec_charset (cpp_reader *, cppchar_t); /* Used to register macros and assertions, perhaps from the command line. The text is the same as the command line argument. */ extern void cpp_define (cpp_reader *, const char *); +extern void cpp_define_unused (cpp_reader *, const char *); extern void cpp_define_formatted (cpp_reader *pfile, const char *fmt, ...) ATTRIBUTE_PRINTF_2; +extern void cpp_define_formatted_unused (cpp_reader *pfile, + const char *fmt, + ...) ATTRIBUTE_PRINTF_2; extern void cpp_assert (cpp_reader *, const char *); extern void cpp_undef (cpp_reader *, const char *); extern void cpp_unassert (cpp_reader *, const char *); @@ -1219,6 +1294,8 @@ extern int cpp_ideq (const cpp_token *, const char *); extern void cpp_output_line (cpp_reader *, FILE *); extern unsigned char *cpp_output_line_to_string (cpp_reader *, const unsigned char *); +extern const unsigned char *cpp_alloc_token_string + (cpp_reader *, const unsigned char *, unsigned); extern void cpp_output_token (const cpp_token *, FILE *); extern const char *cpp_type2name (enum cpp_ttype, unsigned char flags); /* Returns the value of an escape sequence, truncated to the correct @@ -1274,6 +1351,8 @@ extern void cpp_scan_nooutput (cpp_reader *); extern int cpp_sys_macro_p (cpp_reader *); extern unsigned char *cpp_quote_string (unsigned char *, const unsigned char *, unsigned int); +extern bool cpp_compare_macros (const cpp_macro *macro1, + const cpp_macro *macro2); /* In files.c */ extern bool cpp_included (cpp_reader *, const char *); diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h index 44008be..50b2e4f 100644 --- a/libcpp/include/line-map.h +++ b/libcpp/include/line-map.h @@ -72,6 +72,7 @@ enum lc_reason LC_RENAME, /* Other reason for name change. */ LC_RENAME_VERBATIM, /* Likewise, but "" != stdin. */ LC_ENTER_MACRO, /* Begin macro expansion. */ + LC_MODULE, /* A (C++) Module. */ /* FIXME: add support for stringize and paste. */ LC_HWM /* High Water Mark. */ }; @@ -439,7 +440,8 @@ struct GTY((tag ("1"))) line_map_ordinary : public line_map { /* 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. */ + outermost file, this is 0. For modules it could be anywhere + within a map. */ location_t included_from; /* Size is 20 or 24 bytes, no padding */ @@ -662,6 +664,15 @@ ORDINARY_MAP_IN_SYSTEM_HEADER_P (const line_map_ordinary *ord_map) return ord_map->sysp; } +/* TRUE if this line map is for a module (not a source file). */ + +inline bool +MAP_MODULE_P (const line_map *map) +{ + return (MAP_ORDINARY_P (map) + && linemap_check_ordinary (map)->reason == LC_MODULE); +} + /* Get the filename of ordinary map MAP. */ inline const char * @@ -1076,6 +1087,9 @@ extern void linemap_check_files_exited (class line_maps *); extern location_t linemap_line_start (class line_maps *set, linenum_type to_line, unsigned int max_column_hint); +/* Allocate a raw block of line maps, zero initialized. */ +extern line_map *line_map_new_raw (line_maps *, bool, unsigned); + /* Add a mapping of logical source line to physical source file and line number. This function creates an "ordinary map", which is a map that records locations of tokens that are not part of macro @@ -1093,6 +1107,39 @@ extern const line_map *linemap_add (class line_maps *, enum lc_reason, unsigned int sysp, const char *to_file, linenum_type to_line); +/* Create a macro map. A macro map encodes source locations of tokens + that are part of a macro replacement-list, at a macro expansion + point. See the extensive comments of struct line_map and struct + line_map_macro, in line-map.h. + + This map shall be created when the macro is expanded. The map + encodes the source location of the expansion point of the macro as + well as the "original" source location of each token that is part + of the macro replacement-list. If a macro is defined but never + expanded, it has no macro map. SET is the set of maps the macro + map should be part of. MACRO_NODE is the macro which the new macro + map should encode source locations for. EXPANSION is the location + of the expansion point of MACRO. For function-like macros + invocations, it's best to make it point to the closing parenthesis + of the macro, rather than the the location of the first character + of the macro. NUM_TOKENS is the number of tokens that are part of + the replacement-list of MACRO. */ +const line_map_macro *linemap_enter_macro (line_maps *, cpp_hashnode *, + location_t, unsigned int); + +/* Create a source location for a module. The creator must either do + this after the TU is tokenized, or deal with saving and restoring + map state. */ + +extern location_t linemap_module_loc + (line_maps *, location_t from, const char *name); +extern void linemap_module_reparent + (line_maps *, location_t loc, location_t new_parent); + +/* Restore the linemap state such that the map at LWM-1 continues. */ +extern void linemap_module_restore + (line_maps *, unsigned lwm); + /* Given a logical source location, returns the map which the corresponding (source file, line, column) triplet can be deduced from. Since the set is built chronologically, the logical lines are @@ -1102,6 +1149,8 @@ extern const line_map *linemap_add extern const line_map *linemap_lookup (const line_maps *, location_t); +unsigned linemap_lookup_macro_index (const line_maps *, location_t); + /* Returns TRUE if the line table set tracks token locations across macro expansion, FALSE otherwise. */ bool linemap_tracks_macro_expansion_locs_p (class line_maps *); diff --git a/libcpp/include/mkdeps.h b/libcpp/include/mkdeps.h index 6d05351..9f10327 100644 --- a/libcpp/include/mkdeps.h +++ b/libcpp/include/mkdeps.h @@ -23,6 +23,8 @@ along with this program; see the file COPYING3. If not see #ifndef LIBCPP_MKDEPS_H #define LIBCPP_MKDEPS_H +#include "cpplib.h" + /* This is the data structure used by all the functions in mkdeps.c. It's quite straightforward, but should be treated as opaque. */ @@ -49,15 +51,22 @@ extern void deps_add_target (class mkdeps *, const char *, int); string as the default target is interpreted as stdin. */ extern void deps_add_default_target (class mkdeps *, const char *); +/* Adds a module target. The module name and cmi name are copied. */ +extern void deps_add_module_target (struct mkdeps *, const char *module, + const char *cmi, bool is_header); + +/* Adds a module dependency. The module name is copied. */ +extern void deps_add_module_dep (struct mkdeps *, const char *module); + /* Add a dependency (appears on the right side of the colon) to the deps list. Dependencies will be printed in the order that they were entered with this function. By convention, the first dependency entered should be the primary source file. */ extern void deps_add_dep (class mkdeps *, const char *); -/* Write out a deps buffer to a specified file. The third argument +/* Write out a deps buffer to a specified file. The last argument is the number of columns to word-wrap at (0 means don't wrap). */ -extern void deps_write (const class mkdeps *, FILE *, bool, unsigned int); +extern void deps_write (const cpp_reader *, FILE *, unsigned int); /* Write out a deps buffer to a file, in a form that can be read back with deps_restore. Returns nonzero on error, in which case the diff --git a/libcpp/init.c b/libcpp/init.c index 454a183..7987798 100644 --- a/libcpp/init.c +++ b/libcpp/init.c @@ -102,13 +102,13 @@ static const struct lang_flags lang_defaults[] = /* GNUC99 */ { 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0 }, /* GNUC11 */ { 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0 }, /* GNUC17 */ { 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0 }, - /* GNUC2X */ { 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1 }, + /* GNUC2X */ { 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1 }, /* STDC89 */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 }, /* STDC94 */ { 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 }, /* STDC99 */ { 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 }, /* STDC11 */ { 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0 }, /* STDC17 */ { 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0 }, - /* STDC2X */ { 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1 }, + /* STDC2X */ { 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1 }, /* GNUCXX */ { 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0 }, /* CXX98 */ { 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0 }, /* GNUCXX11 */ { 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0 }, @@ -273,8 +273,9 @@ cpp_create_reader (enum c_lang lang, cpp_hash_table *table, /* Do not force token locations by default. */ pfile->forced_token_location = 0; - /* Initialize source_date_epoch to -2 (not yet set). */ - pfile->source_date_epoch = (time_t) -2; + /* Note the timestamp is unset. */ + pfile->time_stamp = time_t (-1); + pfile->time_stamp_kind = 0; /* The expression parser stack. */ _cpp_expand_op_stack (pfile); @@ -406,6 +407,7 @@ static const struct builtin_macro builtin_array[] = function-like macros in traditional.c: fun_like_macro() when adding more following */ B("__has_attribute", BT_HAS_ATTRIBUTE, true), + B("__has_c_attribute", BT_HAS_STD_ATTRIBUTE, true), B("__has_cpp_attribute", BT_HAS_ATTRIBUTE, true), B("__has_builtin", BT_HAS_BUILTIN, true), B("__has_include", BT_HAS_INCLUDE, true), @@ -491,6 +493,7 @@ cpp_init_special_builtins (cpp_reader *pfile) for (b = builtin_array; b < builtin_array + n; b++) { if ((b->value == BT_HAS_ATTRIBUTE + || b->value == BT_HAS_STD_ATTRIBUTE || b->value == BT_HAS_BUILTIN) && (CPP_OPTION (pfile, lang) == CLK_ASM || pfile->cb.has_attribute == NULL)) @@ -539,7 +542,7 @@ cpp_init_builtins (cpp_reader *pfile, int hosted) { if (CPP_OPTION (pfile, lang) == CLK_CXX20 || CPP_OPTION (pfile, lang) == CLK_GNUCXX20) - _cpp_define_builtin (pfile, "__cplusplus 201709L"); + _cpp_define_builtin (pfile, "__cplusplus 202002L"); else if (CPP_OPTION (pfile, lang) == CLK_CXX17 || CPP_OPTION (pfile, lang) == CLK_GNUCXX17) _cpp_define_builtin (pfile, "__cplusplus 201703L"); @@ -667,18 +670,19 @@ cpp_post_options (cpp_reader *pfile) const char * cpp_read_main_file (cpp_reader *pfile, const char *fname, bool injecting) { - if (CPP_OPTION (pfile, deps.style) != DEPS_NONE) - { - if (!pfile->deps) - pfile->deps = deps_init (); - - /* Set the default target (if there is none already). */ - deps_add_default_target (pfile->deps, fname); - } + if (mkdeps *deps = cpp_get_deps (pfile)) + /* Set the default target (if there is none already). */ + deps_add_default_target (deps, fname); pfile->main_file - = _cpp_find_file (pfile, fname, &pfile->no_search_path, /*angle=*/0, - _cpp_FFK_NORMAL, 0); + = _cpp_find_file (pfile, fname, + CPP_OPTION (pfile, preprocessed) ? &pfile->no_search_path + : CPP_OPTION (pfile, main_search) == CMS_user + ? pfile->quote_include + : CPP_OPTION (pfile, main_search) == CMS_system + ? pfile->bracket_include : &pfile->no_search_path, + /*angle=*/0, _cpp_FFK_NORMAL, 0); + if (_cpp_find_failed (pfile->main_file)) return NULL; @@ -700,7 +704,16 @@ cpp_read_main_file (cpp_reader *pfile, const char *fname, bool injecting) LINEMAP_LINE (last), LINEMAP_SYSP (last)); } - return ORDINARY_MAP_FILE_NAME (LINEMAPS_LAST_ORDINARY_MAP (pfile->line_table)); + auto *map = LINEMAPS_LAST_ORDINARY_MAP (pfile->line_table); + pfile->main_loc = MAP_START_LOCATION (map); + + return ORDINARY_MAP_FILE_NAME (map); +} + +location_t +cpp_main_loc (const cpp_reader *pfile) +{ + return pfile->main_loc; } /* For preprocessed files, if the very first characters are @@ -813,9 +826,8 @@ cpp_finish (cpp_reader *pfile, FILE *deps_stream) while (pfile->buffer) _cpp_pop_buffer (pfile); - if (CPP_OPTION (pfile, deps.style) != DEPS_NONE && deps_stream) - deps_write (pfile->deps, deps_stream, - CPP_OPTION (pfile, deps.phony_targets), 72); + if (deps_stream) + deps_write (pfile, deps_stream, 72); /* Report on headers that could use multiple include guards. */ if (CPP_OPTION (pfile, print_include_names)) @@ -846,4 +858,27 @@ post_options (cpp_reader *pfile) CPP_OPTION (pfile, trigraphs) = 0; CPP_OPTION (pfile, warn_trigraphs) = 0; } + + if (CPP_OPTION (pfile, module_directives)) + { + /* These unspellable tokens have a leading space. */ + const char *const inits[spec_nodes::M_HWM] + = {"export ", "module ", "import ", "__import"}; + + for (int ix = 0; ix != spec_nodes::M_HWM; ix++) + { + cpp_hashnode *node = cpp_lookup (pfile, UC (inits[ix]), + strlen (inits[ix])); + + /* Token we pass to the compiler. */ + pfile->spec_nodes.n_modules[ix][1] = node; + + if (ix != spec_nodes::M__IMPORT) + /* Token we recognize when lexing, drop the trailing ' '. */ + node = cpp_lookup (pfile, NODE_NAME (node), NODE_LEN (node) - 1); + + node->flags |= NODE_MODULE; + pfile->spec_nodes.n_modules[ix][0] = node; + } + } } diff --git a/libcpp/internal.h b/libcpp/internal.h index b1a2a99..4010af8 100644 --- a/libcpp/internal.h +++ b/libcpp/internal.h @@ -48,6 +48,8 @@ struct cset_converter convert_f func; iconv_t cd; int width; + const char* from; + const char* to; }; #define BITS_PER_CPPCHAR_T (CHAR_BIT * sizeof (cppchar_t)) @@ -280,6 +282,9 @@ struct lexer_state /* Nonzero when tokenizing a deferred pragma. */ unsigned char in_deferred_pragma; + /* Count to token that is a header-name. */ + unsigned char directive_file_token; + /* Nonzero if the deferred pragma being handled allows macro expansion. */ unsigned char pragma_allow_expansion; }; @@ -292,6 +297,12 @@ struct spec_nodes cpp_hashnode *n_false; /* C++ keyword false */ cpp_hashnode *n__VA_ARGS__; /* C99 vararg macros */ cpp_hashnode *n__VA_OPT__; /* C++ vararg macros */ + + enum {M_EXPORT, M_MODULE, M_IMPORT, M__IMPORT, M_HWM}; + + /* C++20 modules, only set when module_directives is in effect. + incoming variants [0], outgoing ones [1] */ + cpp_hashnode *n_modules[M_HWM][2]; }; typedef struct _cpp_line_note _cpp_line_note; @@ -512,10 +523,9 @@ struct cpp_reader const unsigned char *date; const unsigned char *time; - /* Externally set timestamp to replace current date and time useful for - reproducibility. It should be initialized to -2 (not yet set) and - set to -1 to disable it or to a non-negative value to enable it. */ - time_t source_date_epoch; + /* Time stamp, set idempotently lazily. */ + time_t time_stamp; + int time_stamp_kind; /* Or errno. */ /* A token forcing paste avoidance, and one demarking macro arguments. */ cpp_token avoid_paste; @@ -583,6 +593,10 @@ struct cpp_reader /* If non-zero, the lexer will use this location for the next token instead of getting a location from the linemap. */ location_t forced_token_location; + + /* Location identifying the main source file -- intended to be line + zero of said file. */ + location_t main_loc; }; /* Character classes. Based on the more primitive macros in safe-ctype.h. @@ -620,22 +634,23 @@ typedef unsigned char uchar; #define UC (const uchar *) /* Intended use: UC"string" */ -/* Macros. */ +/* Accessors. */ -static inline int cpp_in_system_header (cpp_reader *); -static inline int -cpp_in_system_header (cpp_reader *pfile) +inline int +_cpp_in_system_header (cpp_reader *pfile) { return pfile->buffer ? pfile->buffer->sysp : 0; } #define CPP_PEDANTIC(PF) CPP_OPTION (PF, cpp_pedantic) #define CPP_WTRADITIONAL(PF) CPP_OPTION (PF, cpp_warn_traditional) -static inline int cpp_in_primary_file (cpp_reader *); -static inline int -cpp_in_primary_file (cpp_reader *pfile) +/* Return true if we're in the main file (unless it's considered to be + an include file in its own right. */ +inline int +_cpp_in_main_source_file (cpp_reader *pfile) { - return pfile->line_table->depth == 1; + return (!CPP_OPTION (pfile, main_search) + && pfile->buffer->file == pfile->main_file); } /* True if NODE is a macro for the purposes of ifdef, defined etc. */ @@ -649,11 +664,14 @@ inline bool _cpp_defined_macro_p (cpp_hashnode *node) } /* 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) +extern bool _cpp_notify_macro_use (cpp_reader *pfile, cpp_hashnode *node, + location_t); +inline bool _cpp_maybe_notify_macro_use (cpp_reader *pfile, cpp_hashnode *node, + location_t loc) { if (!(node->flags & NODE_USED)) - _cpp_notify_macro_use (pfile, node); + return _cpp_notify_macro_use (pfile, node, loc); + return true; } extern cpp_macro *_cpp_new_macro (cpp_reader *, cpp_macro_kind, void *); extern void _cpp_free_definition (cpp_hashnode *); @@ -867,29 +885,7 @@ ufputs (const unsigned char *s, FILE *f) return fputs ((const char *)s, f); } - /* In line-map.c. */ - -/* Create a macro map. A macro map encodes source locations of tokens - that are part of a macro replacement-list, at a macro expansion - point. See the extensive comments of struct line_map and struct - line_map_macro, in line-map.h. - - This map shall be created when the macro is expanded. The map - encodes the source location of the expansion point of the macro as - well as the "original" source location of each token that is part - of the macro replacement-list. If a macro is defined but never - expanded, it has no macro map. SET is the set of maps the macro - map should be part of. MACRO_NODE is the macro which the new macro - map should encode source locations for. EXPANSION is the location - of the expansion point of MACRO. For function-like macros - invocations, it's best to make it point to the closing parenthesis - of the macro, rather than the the location of the first character - of the macro. NUM_TOKENS is the number of tokens that are part of - the replacement-list of MACRO. */ -const line_map_macro *linemap_enter_macro (class line_maps *, - struct cpp_hashnode*, - location_t, - unsigned int); +/* In line-map.c. */ /* Create and return a virtual location for a token that is part of a macro expansion-list at a macro expansion point. See the comment diff --git a/libcpp/lex.c b/libcpp/lex.c index fb22292..07d5a4f 100644 --- a/libcpp/lex.c +++ b/libcpp/lex.c @@ -1062,7 +1062,7 @@ _cpp_clean_line (cpp_reader *pfile) d = (uchar *) s; /* Handle DOS line endings. */ - if (*s == '\r' && s != buffer->rlimit && s[1] == '\n') + if (*s == '\r' && s + 1 != buffer->rlimit && s[1] == '\n') s++; } @@ -1370,7 +1370,7 @@ maybe_va_opt_error (cpp_reader *pfile) { /* __VA_OPT__ should not be accepted at all, but allow it in system headers. */ - if (!cpp_in_system_header (pfile)) + if (!_cpp_in_system_header (pfile)) cpp_error (pfile, CPP_DL_PEDWARN, "__VA_OPT__ is not available until C++20"); } @@ -1577,13 +1577,20 @@ static void create_literal (cpp_reader *pfile, cpp_token *token, const uchar *base, unsigned int len, enum cpp_ttype type) { - uchar *dest = _cpp_unaligned_alloc (pfile, len + 1); - - memcpy (dest, base, len); - dest[len] = '\0'; token->type = type; token->val.str.len = len; - token->val.str.text = dest; + token->val.str.text = cpp_alloc_token_string (pfile, base, len); +} + +const uchar * +cpp_alloc_token_string (cpp_reader *pfile, + const unsigned char *ptr, unsigned len) +{ + uchar *dest = _cpp_unaligned_alloc (pfile, len + 1); + + dest[len] = 0; + memcpy (dest, ptr, len); + return dest; } /* A pair of raw buffer pointers. The currently open one is [1], the @@ -2554,6 +2561,15 @@ cpp_peek_token (cpp_reader *pfile, int index) index--; break; } + else if (peektok->type == CPP_PRAGMA) + { + /* Don't peek past a pragma. */ + if (peektok == &pfile->directive_result) + /* Save the pragma in the buffer. */ + *pfile->cur_token++ = *peektok; + index--; + break; + } } while (index--); @@ -2606,6 +2622,151 @@ _cpp_temp_token (cpp_reader *pfile) return result; } +/* We're at the beginning of a logical line (so not in + directives-mode) and RESULT is a CPP_NAME with NODE_MODULE set. See + if we should enter deferred_pragma mode to tokenize the rest of the + line as a module control-line. */ + +static void +cpp_maybe_module_directive (cpp_reader *pfile, cpp_token *result) +{ + unsigned backup = 0; /* Tokens we peeked. */ + cpp_hashnode *node = result->val.node.node; + cpp_token *peek = result; + cpp_token *keyword = peek; + cpp_hashnode *(&n_modules)[spec_nodes::M_HWM][2] = pfile->spec_nodes.n_modules; + int header_count = 0; + + /* Make sure the incoming state is as we expect it. This way we + can restore it using constants. */ + gcc_checking_assert (!pfile->state.in_deferred_pragma + && !pfile->state.skipping + && !pfile->state.parsing_args + && !pfile->state.angled_headers + && (pfile->state.save_comments + == !CPP_OPTION (pfile, discard_comments))); + + /* Enter directives mode sufficiently for peeking. We don't have + to actually set in_directive. */ + pfile->state.in_deferred_pragma = true; + + /* These two fields are needed to process tokenization in deferred + pragma mode. They are not used outside deferred pragma mode or + directives mode. */ + pfile->state.pragma_allow_expansion = true; + pfile->directive_line = result->src_loc; + + /* Saving comments is incompatible with directives mode. */ + pfile->state.save_comments = 0; + + if (node == n_modules[spec_nodes::M_EXPORT][0]) + { + peek = _cpp_lex_direct (pfile); + keyword = peek; + backup++; + if (keyword->type != CPP_NAME) + goto not_module; + node = keyword->val.node.node; + if (!(node->flags & NODE_MODULE)) + goto not_module; + } + + if (node == n_modules[spec_nodes::M__IMPORT][0]) + /* __import */ + header_count = backup + 2 + 16; + else if (node == n_modules[spec_nodes::M_IMPORT][0]) + /* import */ + header_count = backup + 2 + (CPP_OPTION (pfile, preprocessed) ? 16 : 0); + else if (node == n_modules[spec_nodes::M_MODULE][0]) + ; /* module */ + else + goto not_module; + + /* We've seen [export] {module|import|__import}. Check the next token. */ + if (header_count) + /* After '{,__}import' a header name may appear. */ + pfile->state.angled_headers = true; + peek = _cpp_lex_direct (pfile); + backup++; + + /* ... import followed by identifier, ':', '<' or + header-name preprocessing tokens, or module + followed by cpp-identifier, ':' or ';' preprocessing + tokens. C++ keywords are not yet relevant. */ + if (peek->type == CPP_NAME + || peek->type == CPP_COLON + || (header_count + ? (peek->type == CPP_LESS + || (peek->type == CPP_STRING && peek->val.str.text[0] != 'R') + || peek->type == CPP_HEADER_NAME) + : peek->type == CPP_SEMICOLON)) + { + pfile->state.pragma_allow_expansion = !CPP_OPTION (pfile, preprocessed); + if (!pfile->state.pragma_allow_expansion) + pfile->state.prevent_expansion++; + + if (!header_count && linemap_included_from + (LINEMAPS_LAST_ORDINARY_MAP (pfile->line_table))) + cpp_error_with_line (pfile, CPP_DL_ERROR, keyword->src_loc, 0, + "module control-line cannot be in included file"); + + /* The first one or two tokens cannot be macro names. */ + for (int ix = backup; ix--;) + { + cpp_token *tok = ix ? keyword : result; + cpp_hashnode *node = tok->val.node.node; + + /* Don't attempt to expand the token. */ + tok->flags |= NO_EXPAND; + if (_cpp_defined_macro_p (node) + && _cpp_maybe_notify_macro_use (pfile, node, tok->src_loc) + && !cpp_fun_like_macro_p (node)) + cpp_error_with_line (pfile, CPP_DL_ERROR, tok->src_loc, 0, + "module control-line \"%s\" cannot be" + " an object-like macro", + NODE_NAME (node)); + } + + /* Map to underbar variants. */ + keyword->val.node.node = n_modules[header_count + ? spec_nodes::M_IMPORT + : spec_nodes::M_MODULE][1]; + if (backup != 1) + result->val.node.node = n_modules[spec_nodes::M_EXPORT][1]; + + /* Maybe tell the tokenizer we expect a header-name down the + road. */ + pfile->state.directive_file_token = header_count; + } + else + { + not_module: + /* Drop out of directive mode. */ + /* We aaserted save_comments had this value upon entry. */ + pfile->state.save_comments + = !CPP_OPTION (pfile, discard_comments); + pfile->state.in_deferred_pragma = false; + /* Do not let this remain on. */ + pfile->state.angled_headers = false; + } + + /* In either case we want to backup the peeked tokens. */ + if (backup) + { + /* If we saw EOL, we should drop it, because this isn't a module + control-line after all. */ + bool eol = peek->type == CPP_PRAGMA_EOL; + if (!eol || backup > 1) + { + /* Put put the peeked tokens back */ + _cpp_backup_tokens_direct (pfile, backup); + /* But if the last one was an EOL, forget it. */ + if (eol) + pfile->lookaheads--; + } + } +} + /* Lex a token into RESULT (external interface). Takes care of issues like directive handling, token lookahead, multiple include optimization and skipping. */ @@ -2654,6 +2815,21 @@ _cpp_lex_token (cpp_reader *pfile) } else if (pfile->state.in_deferred_pragma) result = &pfile->directive_result; + else if (result->type == CPP_NAME + && (result->val.node.node->flags & NODE_MODULE) + && !pfile->state.skipping + /* Unlike regular directives, we do not deal with + tokenizing module directives as macro arguments. + That's not permitted. */ + && !pfile->state.parsing_args) + { + /* P1857. Before macro expansion, At start of logical + line ... */ + /* We don't have to consider lookaheads at this point. */ + gcc_checking_assert (!pfile->lookaheads); + + cpp_maybe_module_directive (pfile, result); + } if (pfile->cb.line_change && !pfile->state.skipping) pfile->cb.line_change (pfile, result, pfile->state.parsing_args); @@ -2757,14 +2933,7 @@ _cpp_lex_direct (cpp_reader *pfile) buffer = pfile->buffer; if (buffer->need_line) { - if (pfile->state.in_deferred_pragma) - { - result->type = CPP_PRAGMA_EOL; - pfile->state.in_deferred_pragma = false; - if (!pfile->state.pragma_allow_expansion) - pfile->state.prevent_expansion--; - return result; - } + gcc_assert (!pfile->state.in_deferred_pragma); if (!_cpp_get_fresh_line (pfile)) { result->type = CPP_EOF; @@ -2829,6 +2998,19 @@ _cpp_lex_direct (cpp_reader *pfile) && !CPP_OPTION (pfile, traditional))) CPP_INCREMENT_LINE (pfile, 0); buffer->need_line = true; + if (pfile->state.in_deferred_pragma) + { + /* Produce the PRAGMA_EOL on this line. File reading + ensures there is always a \n at end of the buffer, thus + in a deferred pragma we always see CPP_PRAGMA_EOL before + any CPP_EOF. */ + result->type = CPP_PRAGMA_EOL; + result->flags &= ~PREV_WHITE; + pfile->state.in_deferred_pragma = false; + if (!pfile->state.pragma_allow_expansion) + pfile->state.prevent_expansion--; + return result; + } goto fresh_line; case '0': case '1': case '2': case '3': case '4': @@ -2919,7 +3101,7 @@ _cpp_lex_direct (cpp_reader *pfile) else if (c == '/' && ! CPP_OPTION (pfile, traditional)) { /* Don't warn for system headers. */ - if (cpp_in_system_header (pfile)) + if (_cpp_in_system_header (pfile)) ; /* Warn about comments if pedantically GNUC89, and not in system headers. */ @@ -3446,7 +3628,11 @@ cpp_output_token (const cpp_token *token, FILE *fp) break; case SPELL_LITERAL: + if (token->type == CPP_HEADER_NAME) + fputc ('"', fp); fwrite (token->val.str.text, 1, token->val.str.len, fp); + if (token->type == CPP_HEADER_NAME) + fputc ('"', fp); break; case SPELL_NONE: @@ -3932,6 +4118,188 @@ do_peek_prev (const unsigned char *peek, const unsigned char *bound) return peek; } +/* If PEEK[-1] is identifier MATCH, scan past it and trailing white + space. Otherwise return NULL. */ + +static const unsigned char * +do_peek_ident (const char *match, const unsigned char *peek, + const unsigned char *limit) +{ + for (; *++match; peek++) + if (*peek != *match) + { + peek = do_peek_next (peek, limit); + if (*peek != *match) + return NULL; + } + + /* Must now not be looking at an identifier char. */ + peek = do_peek_next (peek, limit); + if (ISIDNUM (*peek)) + return NULL; + + /* Skip control-line whitespace. */ + ws: + while (*peek == ' ' || *peek == '\t') + peek++; + if (__builtin_expect (*peek == '\\', false)) + { + peek = do_peek_backslash (peek, limit); + if (*peek != '\\') + goto ws; + } + + return peek; +} + +/* Are we looking at a module control line starting as PEEK - 1? */ + +static bool +do_peek_module (cpp_reader *pfile, unsigned char c, + const unsigned char *peek, const unsigned char *limit) +{ + bool import = false; + + if (__builtin_expect (c == 'e', false)) + { + if (!((peek[0] == 'x' || peek[0] == '\\') + && (peek = do_peek_ident ("export", peek, limit)))) + return false; + + /* export, peek for import or module. No need to peek __import + here. */ + if (peek[0] == 'i') + { + if (!((peek[1] == 'm' || peek[1] == '\\') + && (peek = do_peek_ident ("import", peek + 1, limit)))) + return false; + import = true; + } + else if (peek[0] == 'm') + { + if (!((peek[1] == 'o' || peek[1] == '\\') + && (peek = do_peek_ident ("module", peek + 1, limit)))) + return false; + } + else + return false; + } + else if (__builtin_expect (c == 'i', false)) + { + if (!((peek[0] == 'm' || peek[0] == '\\') + && (peek = do_peek_ident ("import", peek, limit)))) + return false; + import = true; + } + else if (__builtin_expect (c == '_', false)) + { + /* Needed for translated includes. */ + if (!((peek[0] == '_' || peek[0] == '\\') + && (peek = do_peek_ident ("__import", peek, limit)))) + return false; + import = true; + } + else if (__builtin_expect (c == 'm', false)) + { + if (!((peek[0] == 'o' || peek[0] == '\\') + && (peek = do_peek_ident ("module", peek, limit)))) + return false; + } + else + return false; + + /* Peek the next character to see if it's good enough. We'll be at + the first non-whitespace char, including skipping an escaped + newline. */ + /* ... import followed by identifier, ':', '<' or header-name + preprocessing tokens, or module followed by identifier, ':' or + ';' preprocessing tokens. */ + unsigned char p = *peek++; + + /* A character literal is ... single quotes, ... optionally preceded + by u8, u, U, or L */ + /* A string-literal is a ... double quotes, optionally prefixed by + R, u8, u8R, u, uR, U, UR, L, or LR */ + if (p == 'u') + { + peek = do_peek_next (peek, limit); + if (*peek == '8') + { + peek++; + goto peek_u8; + } + goto peek_u; + } + else if (p == 'U' || p == 'L') + { + peek_u8: + peek = do_peek_next (peek, limit); + peek_u: + if (*peek == '\"' || *peek == '\'') + return false; + + if (*peek == 'R') + goto peek_R; + /* Identifier. Ok. */ + } + else if (p == 'R') + { + peek_R: + if (CPP_OPTION (pfile, rliterals)) + { + peek = do_peek_next (peek, limit); + if (*peek == '\"') + return false; + } + /* Identifier. Ok. */ + } + else if ('Z' - 'A' == 25 + ? ((p >= 'A' && p <= 'Z') || (p >= 'a' && p <= 'z') || p == '_') + : ISIDST (p)) + { + /* Identifier. Ok. */ + } + else if (p == '<') + { + /* Maybe angle header, ok for import. Reject + '<=', '<<' digraph:'<:'. */ + if (!import) + return false; + peek = do_peek_next (peek, limit); + if (*peek == '=' || *peek == '<' + || (*peek == ':' && CPP_OPTION (pfile, digraphs))) + return false; + } + else if (p == ';') + { + /* SEMICOLON, ok for module. */ + if (import) + return false; + } + else if (p == '"') + { + /* STRING, ok for import. */ + if (!import) + return false; + } + else if (p == ':') + { + /* Maybe COLON, ok. Reject '::', digraph:':>'. */ + peek = do_peek_next (peek, limit); + if (*peek == ':' || (*peek == '>' && CPP_OPTION (pfile, digraphs))) + return false; + } + else + /* FIXME: Detect a unicode character, excluding those not + permitted as the initial character. [lex.name]/1. I presume + we need to check the \[uU] spellings, and directly using + Unicode in say UTF8 form? Or perhaps we do the phase-1 + conversion of UTF8 to universal-character-names? */ + return false; + + return true; +} + /* Directives-only scanning. Somewhat more relaxed than correct parsing -- some ill-formed programs will not be rejected. */ @@ -3940,6 +4308,8 @@ cpp_directive_only_process (cpp_reader *pfile, void *data, void (*cb) (cpp_reader *, CPP_DO_task, void *, ...)) { + bool module_p = CPP_OPTION (pfile, module_directives); + do { restart: @@ -4332,6 +4702,51 @@ cpp_directive_only_process (cpp_reader *pfile, } goto dflt; + case '_': + case 'e': + case 'i': + case 'm': + if (bol && module_p && !pfile->state.skipping + && do_peek_module (pfile, c, pos, limit)) + { + /* We've seen the start of a module control line. + Start up the tokenizer. */ + pos--; /* Backup over the first character. */ + + /* Backup over whitespace to start of line. */ + while (pos > line_start + && (pos[-1] == ' ' || pos[-1] == '\t')) + pos--; + + if (pos > base) + cb (pfile, CPP_DO_print, data, line_count, base, pos - base); + + /* Prep things for directive handling. */ + buffer->next_line = pos; + buffer->need_line = true; + + /* Now get tokens until the PRAGMA_EOL. */ + do + { + location_t spelling; + const cpp_token *tok + = cpp_get_token_with_location (pfile, &spelling); + + gcc_assert (pfile->state.in_deferred_pragma + || tok->type == CPP_PRAGMA_EOL); + cb (pfile, CPP_DO_token, data, tok, spelling); + } + while (pfile->state.in_deferred_pragma); + + if (pfile->buffer->next_line < pfile->buffer->rlimit) + cb (pfile, CPP_DO_location, data, + pfile->line_table->highest_line); + + pfile->mi_valid = false; + goto restart; + } + goto dflt; + default: dflt: bol = false; diff --git a/libcpp/line-map.c b/libcpp/line-map.c index 5a74174..bbb6963 100644 --- a/libcpp/line-map.c +++ b/libcpp/line-map.c @@ -378,23 +378,21 @@ linemap_check_files_exited (line_maps *set) ORDINARY_MAP_FILE_NAME (map)); } -/* Create a new line map in the line map set SET, and return it. - REASON is the reason of creating the map. It determines the type - of map created (ordinary or macro map). Note that ordinary maps and - macro maps are allocated in different memory location. */ +/* Create NUM zero-initialized maps of type MACRO_P. */ -static struct line_map * -new_linemap (line_maps *set, location_t start_location) +line_map * +line_map_new_raw (line_maps *set, bool macro_p, unsigned num) { - 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 (num_maps_used == num_maps_allocated) + + if (num > num_maps_allocated - num_maps_used) { /* We need more space! */ if (!num_maps_allocated) num_maps_allocated = 128; + if (num_maps_allocated < num_maps_used + num) + num_maps_allocated = num_maps_used + num; num_maps_allocated *= 2; size_t size_of_a_map; @@ -436,13 +434,39 @@ new_linemap (line_maps *set, location_t 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_p) += num; + + return result; +} + +/* Create a new line map in the line map set SET, and return it. + REASON is the reason of creating the map. It determines the type + of map created (ordinary or macro map). Note that ordinary maps and + macro maps are allocated in different memory location. */ + +static struct line_map * +new_linemap (line_maps *set, location_t start_location) +{ + line_map *result = line_map_new_raw (set, + start_location >= LINE_MAP_MAX_LOCATION, + 1); result->start_location = start_location; return result; } +/* Return the location of the last source line within an ordinary + map. */ +inline location_t +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); +} + /* Add a mapping of logical source line to physical source file and line number. @@ -570,6 +594,56 @@ linemap_add (line_maps *set, enum lc_reason reason, return map; } +/* Create a location for a module NAME imported at FROM. */ + +location_t +linemap_module_loc (line_maps *set, location_t from, const char *name) +{ + const line_map_ordinary *map + = linemap_check_ordinary (linemap_add (set, LC_MODULE, false, name, 0)); + const_cast <line_map_ordinary *> (map)->included_from = from; + + location_t loc = linemap_line_start (set, 0, 0); + + return loc; +} + +/* The linemap containing LOC is being reparented to be + imported/included from ADOPTOR. This can happen when an + indirectly imported module is then directly imported, or when + partitions are involved. */ + +void +linemap_module_reparent (line_maps *set, location_t loc, location_t adoptor) +{ + const line_map_ordinary *map = linemap_ordinary_map_lookup (set, loc); + const_cast<line_map_ordinary *> (map)->included_from = adoptor; +} + +/* A linemap at LWM-1 was interrupted to insert module locations & imports. + Append a new map, continuing the interrupted one. */ + +void +linemap_module_restore (line_maps *set, unsigned lwm) +{ + if (lwm && lwm != LINEMAPS_USED (set, false)) + { + const line_map_ordinary *pre_map + = linemap_check_ordinary (LINEMAPS_MAP_AT (set, false, lwm - 1)); + unsigned src_line = SOURCE_LINE (pre_map, + LAST_SOURCE_LINE_LOCATION (pre_map)); + location_t inc_at = pre_map->included_from; + if (const line_map_ordinary *post_map + = (linemap_check_ordinary + (linemap_add (set, LC_RENAME_VERBATIM, + ORDINARY_MAP_IN_SYSTEM_HEADER_P (pre_map), + ORDINARY_MAP_FILE_NAME (pre_map), src_line)))) + /* linemap_add will think we were included from the same as + the preceeding map. */ + const_cast <line_map_ordinary *> (post_map)->included_from = inc_at; + } +} + /* Returns TRUE if the line table set tracks token locations across macro expansion, FALSE otherwise. */ @@ -1003,14 +1077,25 @@ linemap_macro_map_lookup (const line_maps *set, location_t line) if (set == NULL) return NULL; + unsigned ix = linemap_lookup_macro_index (set, line); + const struct line_map_macro *result = LINEMAPS_MACRO_MAP_AT (set, ix); + linemap_assert (MAP_START_LOCATION (result) <= line); + + return result; +} + +unsigned +linemap_lookup_macro_index (const line_maps *set, location_t line) +{ unsigned mn = LINEMAPS_MACRO_CACHE (set); unsigned mx = LINEMAPS_MACRO_USED (set); const struct line_map_macro *cached = LINEMAPS_MACRO_MAP_AT (set, mn); if (line >= MAP_START_LOCATION (cached)) { - if (mn == 0 || line < MAP_START_LOCATION (&cached[-1])) - return cached; + if (line < (MAP_START_LOCATION (cached) + + MACRO_MAP_NUM_MACRO_TOKENS (cached))) + return mn; mx = mn - 1; mn = 0; } @@ -1025,10 +1110,7 @@ linemap_macro_map_lookup (const line_maps *set, location_t line) } LINEMAPS_MACRO_CACHE (set) = mx; - const struct line_map_macro *result = LINEMAPS_MACRO_MAP_AT (set, mx); - linemap_assert (MAP_START_LOCATION (result) <= line); - - return result; + return mx; } /* Return TRUE if MAP encodes locations coming from a macro @@ -1747,7 +1829,7 @@ linemap_dump (FILE *stream, class line_maps *set, unsigned ix, bool is_macro) { const char *const lc_reasons_v[LC_HWM] = { "LC_ENTER", "LC_LEAVE", "LC_RENAME", "LC_RENAME_VERBATIM", - "LC_ENTER_MACRO" }; + "LC_ENTER_MACRO", "LC_MODULE" }; const line_map *map; unsigned reason; diff --git a/libcpp/macro.c b/libcpp/macro.c index 0874028..cdb1821 100644 --- a/libcpp/macro.c +++ b/libcpp/macro.c @@ -268,6 +268,8 @@ class vaopt_state { /* Macro expansion. */ +static cpp_macro *get_deferred_or_lazy_macro (cpp_reader *, cpp_hashnode *, + location_t); static int enter_macro_context (cpp_reader *, cpp_hashnode *, const cpp_token *, location_t); static int builtin_macro (cpp_reader *, cpp_hashnode *, @@ -338,8 +340,6 @@ static cpp_macro *create_iso_definition (cpp_reader *); /* #define directive parsing and handling. */ 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 *); static void check_trad_stringification (cpp_reader *, const cpp_macro *, const cpp_string *); @@ -351,8 +351,6 @@ static const cpp_token* cpp_get_token_1 (cpp_reader *, location_t *); static cpp_hashnode* macro_of_context (cpp_context *context); -static bool in_macro_expansion_p (cpp_reader *pfile); - /* Statistical counter tracking the number of macros that got expanded. */ unsigned num_expanded_macros_counter = 0; @@ -586,7 +584,7 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node, (c) we are not in strictly conforming mode, then it has the value 0. (b) and (c) are already checked in cpp_init_builtins. */ case BT_STDC: - if (cpp_in_system_header (pfile)) + if (_cpp_in_system_header (pfile)) number = 0; else number = 1; @@ -604,29 +602,21 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node, at init time, because time() and localtime() are very slow on some systems. */ time_t tt; - struct tm *tb = NULL; - - /* Set a reproducible timestamp for __DATE__ and __TIME__ macro - if SOURCE_DATE_EPOCH is defined. */ - if (pfile->source_date_epoch == (time_t) -2 - && pfile->cb.get_source_date_epoch != NULL) - pfile->source_date_epoch = pfile->cb.get_source_date_epoch (pfile); + auto kind = cpp_get_date (pfile, &tt); - if (pfile->source_date_epoch >= (time_t) 0) - tb = gmtime (&pfile->source_date_epoch); - else + if (kind == CPP_time_kind::UNKNOWN) { - /* (time_t) -1 is a legitimate value for "number of seconds - since the Epoch", so we have to do a little dance to - distinguish that from a genuine error. */ - errno = 0; - tt = time (NULL); - if (tt != (time_t)-1 || errno == 0) - tb = localtime (&tt); + cpp_errno (pfile, CPP_DL_WARNING, + "could not determine date and time"); + + pfile->date = UC"\"??? ?? ????\""; + pfile->time = UC"\"??:??:??\""; } - - if (tb) + else { + struct tm *tb = (kind == CPP_time_kind::FIXED + ? gmtime : localtime) (&tt); + pfile->date = _cpp_unaligned_alloc (pfile, sizeof ("\"Oct 11 1347\"")); sprintf ((char *) pfile->date, "\"%s %2d %4d\"", @@ -638,14 +628,6 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node, sprintf ((char *) pfile->time, "\"%02d:%02d:%02d\"", tb->tm_hour, tb->tm_min, tb->tm_sec); } - else - { - cpp_errno (pfile, CPP_DL_WARNING, - "could not determine date and time"); - - pfile->date = UC"\"??? ?? ????\""; - pfile->time = UC"\"??:??:??\""; - } } if (node->value.builtin == BT_DATE) @@ -662,7 +644,11 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node, break; case BT_HAS_ATTRIBUTE: - number = pfile->cb.has_attribute (pfile); + number = pfile->cb.has_attribute (pfile, false); + break; + + case BT_HAS_STD_ATTRIBUTE: + number = pfile->cb.has_attribute (pfile, true); break; case BT_HAS_BUILTIN: @@ -686,6 +672,51 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node, return result; } +/* Get an idempotent date. Either the cached value, the value from + source epoch, or failing that, the value from time(2). Use this + during compilation so that every time stamp is the same. */ +CPP_time_kind +cpp_get_date (cpp_reader *pfile, time_t *result) +{ + if (!pfile->time_stamp_kind) + { + int kind = 0; + if (pfile->cb.get_source_date_epoch) + { + /* Try reading the fixed epoch. */ + pfile->time_stamp = pfile->cb.get_source_date_epoch (pfile); + if (pfile->time_stamp != time_t (-1)) + kind = int (CPP_time_kind::FIXED); + } + + if (!kind) + { + /* Pedantically time_t (-1) is a legitimate value for + "number of seconds since the Epoch". It is a silly + time. */ + errno = 0; + pfile->time_stamp = time (nullptr); + /* Annoyingly a library could legally set errno and return a + valid time! Bad library! */ + if (pfile->time_stamp == time_t (-1) && errno) + kind = errno; + else + kind = int (CPP_time_kind::DYNAMIC); + } + + pfile->time_stamp_kind = kind; + } + + *result = pfile->time_stamp; + if (pfile->time_stamp_kind >= 0) + { + errno = pfile->time_stamp_kind; + return CPP_time_kind::UNKNOWN; + } + + return CPP_time_kind (pfile->time_stamp_kind); +} + /* Convert builtin macros like __FILE__ to a token and push it on the context stack. Also handles _Pragma, for which a new token may not be created. Returns 1 if it generates a new token context, 0 to @@ -1433,7 +1464,7 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode *node, /* Laziness can only affect the expansion tokens of the macro, not its fun-likeness or parameters. */ - _cpp_maybe_notify_macro_use (pfile, node); + _cpp_maybe_notify_macro_use (pfile, node, location); if (pfile->cb.used) pfile->cb.used (pfile, location, node); @@ -2182,7 +2213,7 @@ replace_args (cpp_reader *pfile, cpp_hashnode *node, cpp_macro *macro, = (const cpp_token **) tokens_buff_last_token_ptr (buff); } else if (CPP_PEDANTIC (pfile) && ! CPP_OPTION (pfile, c99) - && ! macro->syshdr && ! cpp_in_system_header (pfile)) + && ! macro->syshdr && ! _cpp_in_system_header (pfile)) { if (CPP_OPTION (pfile, cplusplus)) cpp_pedwarning (pfile, CPP_W_PEDANTIC, @@ -2201,7 +2232,7 @@ replace_args (cpp_reader *pfile, cpp_hashnode *node, cpp_macro *macro, } else if (CPP_OPTION (pfile, cpp_warn_c90_c99_compat) > 0 && ! CPP_OPTION (pfile, cplusplus) - && ! macro->syshdr && ! cpp_in_system_header (pfile)) + && ! macro->syshdr && ! _cpp_in_system_header (pfile)) cpp_warning (pfile, CPP_W_C90_C99_COMPAT, "invoking macro %s argument %d: " "empty macro arguments are undefined" @@ -2843,6 +2874,12 @@ cpp_get_token_1 (cpp_reader *pfile, location_t *location) if (node->type == NT_VOID || (result->flags & NO_EXPAND)) break; + if (!(node->flags & NODE_USED) + && node->type == NT_USER_MACRO + && !node->value.macro + && !cpp_get_deferred_macro (pfile, node, result->src_loc)) + break; + if (!(node->flags & NODE_DISABLED)) { int ret = 0; @@ -2928,6 +2965,85 @@ cpp_get_token_1 (cpp_reader *pfile, location_t *location) } pfile->about_to_expand_macro_p = saved_about_to_expand_macro; + + if (pfile->state.directive_file_token + && !pfile->state.parsing_args + && !(result->type == CPP_PADDING || result->type == CPP_COMMENT) + && !(15 & --pfile->state.directive_file_token)) + { + /* Do header-name frobbery. Concatenate < ... > as approprate. + Do header search if needed, and finally drop the outer <> or + "". */ + pfile->state.angled_headers = false; + + /* Do angle-header reconstitution. Then do include searching. + We'll always end up with a ""-quoted header-name in that + case. If searching finds nothing, we emit a diagnostic and + an empty string. */ + size_t len = 0; + char *fname = NULL; + + cpp_token *tmp = _cpp_temp_token (pfile); + *tmp = *result; + + tmp->type = CPP_HEADER_NAME; + bool need_search = !pfile->state.directive_file_token; + pfile->state.directive_file_token = 0; + + bool angle = result->type != CPP_STRING; + if (result->type == CPP_HEADER_NAME + || (result->type == CPP_STRING && result->val.str.text[0] != 'R')) + { + len = result->val.str.len - 2; + fname = XNEWVEC (char, len + 1); + memcpy (fname, result->val.str.text + 1, len); + fname[len] = 0; + } + else if (result->type == CPP_LESS) + fname = _cpp_bracket_include (pfile); + + if (fname) + { + /* We have a header-name. Look it up. This will emit an + unfound diagnostic. Canonicalize the found name. */ + const char *found = fname; + + if (need_search) + { + found = cpp_find_header_unit (pfile, fname, angle, tmp->src_loc); + if (!found) + found = ""; + len = strlen (found); + } + /* Force a leading './' if it's not absolute. */ + bool dotme = (found[0] == '.' ? !IS_DIR_SEPARATOR (found[1]) + : found[0] && !IS_ABSOLUTE_PATH (found)); + + if (BUFF_ROOM (pfile->u_buff) < len + 1 + dotme * 2) + _cpp_extend_buff (pfile, &pfile->u_buff, len + 1 + dotme * 2); + unsigned char *buf = BUFF_FRONT (pfile->u_buff); + size_t pos = 0; + + if (dotme) + { + buf[pos++] = '.'; + /* Apparently '/' is unconditional. */ + buf[pos++] = '/'; + } + memcpy (&buf[pos], found, len); + pos += len; + buf[pos] = 0; + + tmp->val.str.len = pos; + tmp->val.str.text = buf; + + tmp->type = CPP_HEADER_NAME; + XDELETEVEC (fname); + + result = tmp; + } + } + return result; } @@ -3102,15 +3218,16 @@ 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; - } + if (cpp_macro *macro1 = get_deferred_or_lazy_macro (pfile, node, macro2->line)) + return cpp_compare_macros (macro1, macro2); + return false; +} + +/* Return TRUE if MACRO1 and MACRO2 differ. */ +bool +cpp_compare_macros (const cpp_macro *macro1, const cpp_macro *macro2) +{ /* Redefinition of a macro is allowed if and only if the old and new definitions are the same. (6.10.3 paragraph 2). */ @@ -3579,6 +3696,10 @@ _cpp_new_macro (cpp_reader *pfile, cpp_macro_kind kind, void *placement) { cpp_macro *macro = (cpp_macro *) placement; + /* Zero init all the fields. This'll tell the compiler know all the + following inits are writing a virgin object. */ + memset (macro, 0, offsetof (cpp_macro, exp)); + macro->line = pfile->directive_line; macro->parm.params = 0; macro->lazy = 0; @@ -3587,6 +3708,7 @@ _cpp_new_macro (cpp_reader *pfile, cpp_macro_kind kind, void *placement) macro->used = !CPP_OPTION (pfile, warn_unused_macros); macro->count = 0; macro->fun_like = 0; + macro->imported_p = false; macro->extra_tokens = 0; /* To suppress some diagnostics. */ macro->syshdr = pfile->buffer && pfile->buffer->sysp != 0; @@ -3664,39 +3786,72 @@ cpp_define_lazily (cpp_reader *pfile, cpp_hashnode *node, unsigned num) macro->lazy = num + 1; } +/* NODE is a deferred macro, resolve it, returning the definition + (which may be NULL). */ +cpp_macro * +cpp_get_deferred_macro (cpp_reader *pfile, cpp_hashnode *node, + location_t loc) +{ + gcc_checking_assert (node->type == NT_USER_MACRO); + + node->value.macro = pfile->cb.user_deferred_macro (pfile, loc, node); + + if (!node->value.macro) + node->type = NT_VOID; + + return node->value.macro; +} + +static cpp_macro * +get_deferred_or_lazy_macro (cpp_reader *pfile, cpp_hashnode *node, + location_t loc) +{ + cpp_macro *macro = node->value.macro; + if (!macro) + { + macro = cpp_get_deferred_macro (pfile, node, loc); + gcc_checking_assert (!macro || !macro->lazy); + } + else if (macro->lazy) + { + pfile->cb.user_lazy_macro (pfile, macro, macro->lazy - 1); + macro->lazy = 0; + } + + return macro; +} + /* Notify the use of NODE in a macro-aware context (i.e. expanding it, - or testing its existance). Also applies any lazy definition. */ + or testing its existance). Also applies any lazy definition. + Return FALSE if the macro isn't really there. */ -extern void -_cpp_notify_macro_use (cpp_reader *pfile, cpp_hashnode *node) +extern bool +_cpp_notify_macro_use (cpp_reader *pfile, cpp_hashnode *node, + location_t loc) { node->flags |= NODE_USED; switch (node->type) { 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; - } - } + if (!get_deferred_or_lazy_macro (pfile, node, loc)) + return false; /* FALLTHROUGH. */ case NT_BUILTIN_MACRO: if (pfile->cb.used_define) - pfile->cb.used_define (pfile, pfile->directive_line, node); + pfile->cb.used_define (pfile, loc, node); break; case NT_VOID: if (pfile->cb.used_undef) - pfile->cb.used_undef (pfile, pfile->directive_line, node); + pfile->cb.used_undef (pfile, loc, node); break; default: abort (); } + + return true; } /* Warn if a token in STRING matches one of a function-like MACRO's @@ -3749,12 +3904,19 @@ check_trad_stringification (cpp_reader *pfile, const cpp_macro *macro, const unsigned char * cpp_macro_definition (cpp_reader *pfile, cpp_hashnode *node) { - unsigned int i, len; - unsigned char *buffer; - gcc_checking_assert (cpp_user_macro_p (node)); - const cpp_macro *macro = node->value.macro; + if (const cpp_macro *macro = get_deferred_or_lazy_macro (pfile, node, 0)) + return cpp_macro_definition (pfile, node, macro); + return NULL; +} + +const unsigned char * +cpp_macro_definition (cpp_reader *pfile, cpp_hashnode *node, + const cpp_macro *macro) +{ + unsigned int i, len; + unsigned char *buffer; /* Calculate length. */ len = NODE_LEN (node) * 10 + 2; /* ' ' and NUL. */ diff --git a/libcpp/mkdeps.c b/libcpp/mkdeps.c index 09a111f..4a8e101 100644 --- a/libcpp/mkdeps.c +++ b/libcpp/mkdeps.c @@ -23,6 +23,7 @@ along with this program; see the file COPYING3. If not see #include "config.h" #include "system.h" #include "mkdeps.h" +#include "internal.h" /* Not set up to just include std::vector et al, here's a simple implementation. */ @@ -80,7 +81,7 @@ public: }; mkdeps () - : quote_lwm (0) + : module_name (NULL), cmi_name (NULL), is_header_unit (false), quote_lwm (0) { } ~mkdeps () @@ -93,34 +94,39 @@ public: free (const_cast <char *> (deps[i])); for (i = vpath.size (); i--;) XDELETEVEC (vpath[i].str); + for (i = modules.size (); i--;) + XDELETEVEC (modules[i]); + XDELETEVEC (module_name); + free (const_cast <char *> (cmi_name)); } public: vec<const char *> targets; vec<const char *> deps; vec<velt> vpath; + vec<const char *> modules; public: + const char *module_name; + const char *cmi_name; + bool is_header_unit; unsigned short quote_lwm; }; -/* Apply Make quoting to STR, TRAIL etc. Note that it's not possible - to quote all such characters - e.g. \n, %, *, ?, [, \ (in some +/* Apply Make quoting to STR, TRAIL. Note that it's not possible to + quote all such characters - e.g. \n, %, *, ?, [, \ (in some contexts), and ~ are not properly handled. It isn't possible to get this right in any current version of Make. (??? Still true? Old comment referred to 3.76.1.) */ static const char * -munge (const char *str, const char *trail = NULL, ...) +munge (const char *str, const char *trail = nullptr) { static unsigned alloc; static char *buf; unsigned dst = 0; - va_list args; - if (trail) - va_start (args, trail); - for (bool first = true; str; first = false) + for (; str; str = trail, trail = nullptr) { unsigned slashes = 0; char c; @@ -168,14 +174,7 @@ munge (const char *str, const char *trail = NULL, ...) buf[dst++] = c; } - - if (first) - str = trail; - else - str = va_arg (args, const char *); } - if (trail) - va_end (args); buf[dst] = 0; return buf; @@ -322,6 +321,28 @@ deps_add_vpath (class mkdeps *d, const char *vpath) } } +/* Add a new module target (there can only be one). M is the module + name. */ + +void +deps_add_module_target (struct mkdeps *d, const char *m, + const char *cmi, bool is_header_unit) +{ + gcc_assert (!d->module_name); + + d->module_name = xstrdup (m); + d->is_header_unit = is_header_unit; + d->cmi_name = xstrdup (cmi); +} + +/* Add a new module dependency. M is the module name. */ + +void +deps_add_module_dep (struct mkdeps *d, const char *m) +{ + d->modules.push (xstrdup (m)); +} + /* Write NAME, with a leading space to FP, a Makefile. Advance COL as appropriate, wrap at COLMAX, returning new column number. Iff QUOTE apply quoting. Append TRAIL. */ @@ -331,7 +352,7 @@ make_write_name (const char *name, FILE *fp, unsigned col, unsigned colmax, bool quote = true, const char *trail = NULL) { if (quote) - name = munge (name, trail, NULL); + name = munge (name, trail); unsigned size = strlen (name); if (col) @@ -367,8 +388,10 @@ make_write_vec (const mkdeps::vec<const char *> &vec, FILE *fp, .PHONY targets for all the dependencies too. */ static void -make_write (const class mkdeps *d, FILE *fp, bool phony, unsigned int colmax) +make_write (const cpp_reader *pfile, FILE *fp, unsigned int colmax) { + const mkdeps *d = pfile->deps; + unsigned column = 0; if (colmax && colmax < 34) colmax = 34; @@ -376,23 +399,79 @@ make_write (const class mkdeps *d, FILE *fp, bool phony, unsigned int colmax) if (d->deps.size ()) { column = make_write_vec (d->targets, fp, 0, colmax, d->quote_lwm); + if (CPP_OPTION (pfile, deps.modules) && d->cmi_name) + column = make_write_name (d->cmi_name, fp, column, colmax); fputs (":", fp); column++; make_write_vec (d->deps, fp, column, colmax); fputs ("\n", fp); - if (phony) + if (CPP_OPTION (pfile, deps.phony_targets)) for (unsigned i = 1; i < d->deps.size (); i++) fprintf (fp, "%s:\n", munge (d->deps[i])); } + + if (!CPP_OPTION (pfile, deps.modules)) + return; + + if (d->modules.size ()) + { + column = make_write_vec (d->targets, fp, 0, colmax, d->quote_lwm); + if (d->cmi_name) + column = make_write_name (d->cmi_name, fp, column, colmax); + fputs (":", fp); + column++; + column = make_write_vec (d->modules, fp, column, colmax, 0, ".c++m"); + fputs ("\n", fp); + } + + if (d->module_name) + { + if (d->cmi_name) + { + /* module-name : cmi-name */ + column = make_write_name (d->module_name, fp, 0, colmax, + true, ".c++m"); + fputs (":", fp); + column++; + column = make_write_name (d->cmi_name, fp, column, colmax); + fputs ("\n", fp); + + column = fprintf (fp, ".PHONY:"); + column = make_write_name (d->module_name, fp, column, colmax, + true, ".c++m"); + fputs ("\n", fp); + } + + if (d->cmi_name && !d->is_header_unit) + { + /* An order-only dependency. + cmi-name :| first-target + We can probably drop this this in favour of Make-4.3's grouped + targets '&:' */ + column = make_write_name (d->cmi_name, fp, 0, colmax); + fputs (":|", fp); + column++; + column = make_write_name (d->targets[0], fp, column, colmax); + fputs ("\n", fp); + } + } + + if (d->modules.size ()) + { + column = fprintf (fp, "CXX_IMPORTS +="); + make_write_vec (d->modules, fp, column, colmax, 0, ".c++m"); + fputs ("\n", fp); + } } /* Write out dependencies according to the selected format (which is only Make at the moment). */ +/* Really we should be opening fp here. */ void -deps_write (const class mkdeps *d, FILE *fp, bool phony, unsigned int colmax) +deps_write (const cpp_reader *pfile, FILE *fp, unsigned int colmax) { - make_write (d, fp, phony, colmax); + make_write (pfile, fp, colmax); } /* Write out a deps buffer to a file, in a form that can be read back diff --git a/libcpp/traditional.c b/libcpp/traditional.c index b087072..225e3c2 100644 --- a/libcpp/traditional.c +++ b/libcpp/traditional.c @@ -330,6 +330,7 @@ fun_like_macro (cpp_hashnode *node) { if (cpp_builtin_macro_p (node)) return (node->value.builtin == BT_HAS_ATTRIBUTE + || node->value.builtin == BT_HAS_STD_ATTRIBUTE || node->value.builtin == BT_HAS_BUILTIN || node->value.builtin == BT_HAS_INCLUDE || node->value.builtin == BT_HAS_INCLUDE_NEXT); |